X-Git-Url: http://git.home-dn.net/?p=manu%2Fsuphp.git;a=blobdiff_plain;f=src%2FPathMatcher.cpp;fp=src%2FPathMatcher.cpp;h=07bddfd1020c3f2bb1ab256ed0e5c90aa4c040d6;hp=0000000000000000000000000000000000000000;hb=849f4a7977b5780eacae8fad7a078d05f4a615ee;hpb=b0eaa3f1fbf491fdc8a3044cf20754f14254338a diff --git a/src/PathMatcher.cpp b/src/PathMatcher.cpp new file mode 100644 index 0000000..07bddfd --- /dev/null +++ b/src/PathMatcher.cpp @@ -0,0 +1,177 @@ +/* + suPHP - (c)2002-2008 Sebastian Marsching + + This file is part of suPHP. + + suPHP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + suPHP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with suPHP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "PathMatcher.hpp" +#include "Util.hpp" + +using namespace suPHP; + +suPHP::PathMatcher::PathMatcher(const UserInfo& user, const GroupInfo& group) { + this->user = user; + this->group = group; +} + +bool suPHP::PathMatcher::matches(std::string pattern, std::string path) + throw (KeyNotFoundException, ParsingException) { + std::string remainingPath = path; + std::string remainingPattern = pattern; + + while (remainingPath.length() > 0 && remainingPattern.length() > 0) { + bool escapeNext = false; + for (int i = 0; i < remainingPattern.length(); i++) { + char c = remainingPattern.at(i); + if (escapeNext) { + escapeNext = false; + if (c == '\\' || c == '*' || c == '$') { + // Backslash was used as an escape character + if (remainingPath.at(i-1) == c) { + remainingPattern = remainingPattern.substr(i + 1); + remainingPath = remainingPath.substr(i); + break; + } else { + return false; + } + } else { + if (remainingPath.at(i-1) == '\\') { + remainingPattern = remainingPattern.substr(i); + remainingPath = remainingPath.substr(i); + break; + } else { + return false; + } + } + } else { + if (c == '\\') { + escapeNext = true; + } else if (c == '*') { + remainingPattern = remainingPattern.substr(i + 1); + remainingPath = remainingPath.substr(i); + if (matches(remainingPattern, remainingPath)) { + return true; + } + std::string testPrefix; + for (int j = 0; j < remainingPath.length(); j++) { + char c2 = remainingPath.at(j); + if (c2 == '/') { + return false; + } + if (c2 == '\\' || c2 == '*' || c2 == '$') { + testPrefix += "\\"; + } + testPrefix += c2; + if (matches(testPrefix + remainingPattern, + remainingPath)) { + return true; + } + } + } else if (c == '$') { + if (remainingPattern.length() < i + 3) { + throw ParsingException("Incorrect use of $ in pattern \"" + pattern + "\".", __FILE__, __LINE__); + } + if (remainingPattern.at(i + 1) != '{') { + throw ParsingException("Incorrect use of $ in pattern \"" + pattern + "\".", __FILE__, __LINE__); + } + std::string::size_type closingBrace = remainingPattern.find('}', i); + if (closingBrace == std::string::npos) { + throw ParsingException("Incorrect use of $ in pattern \"" + pattern + "\".", __FILE__, __LINE__); + } + std::string varName = remainingPattern.substr(i + 2, closingBrace - i - 2); + remainingPattern = lookupVariable(varName) + remainingPattern.substr(closingBrace + 1); + break; + } else { + if (i >= remainingPath.length() || c != remainingPath.at(i)) { + return false; + } + if (i == remainingPattern.length() - 1) { + if (c == '/' || (i + 1 < remainingPath.length() && remainingPath.at(i + 1) == '/')) { + // Path represents file in subdirectory + return true; + } else if (remainingPath.length() == remainingPattern.length()) { + // Exact match + return true; + } else { + return false; + } + } + } + } + } + } + return false; +} + +std::string suPHP::PathMatcher::lookupVariable(std::string str) + throw (KeyNotFoundException) { + std::string rv; + if (str == "USERNAME") { + rv = user.getUsername(); + } else if (str == "UID") { + rv = Util::intToStr(user.getUid()); + } else if (str == "HOME") { + rv = user.getHomeDirectory(); + } else if (str == "GROUPNAME") { + rv = group.getGroupname(); + } else if (str == "GID") { + rv = Util::intToStr(group.getGid()); + } else { + throw KeyNotFoundException("Key \"" + str + + "\" does not represent a valid variable name", __FILE__, __LINE__); + } + return rv; +} + +std::string suPHP::PathMatcher::resolveVariables(std::string str) throw (KeyNotFoundException, ParsingException) { + std::string out; + bool escapeNext = false; + for (int i = 0; i < str.length(); i++) { + char c = str.at(i); + if (escapeNext) { + escapeNext = false; + if (c == '\\' || c == '$') { + // Backslash was used as an escape character + out += c; + } else { + out += '\\'; + out += c; + } + } else { + if (c == '\\') { + escapeNext = true; + } else if (c == '$') { + if (str.length() < i + 3) { + throw ParsingException("Incorrect use of $ in string \"" + str + "\".", __FILE__, __LINE__); + } + if (str.at(i + 1) != '{') { + throw ParsingException("Incorrect use of $ in string \"" + str + "\".", __FILE__, __LINE__); + } + std::string::size_type closingBrace = str.find('}', i); + if (closingBrace == std::string::npos) { + throw ParsingException("Incorrect use of $ in string \"" + str + "\".", __FILE__, __LINE__); + } + std::string varName = str.substr(i + 2, closingBrace - i - 2); + out += lookupVariable(varName); + i = closingBrace + 1; + } else { + out += c; + } + } + } + return out; +}