diff --git a/src/utils/conftree.cpp b/src/utils/conftree.cpp index 12eb4b50..09b71b8a 100644 --- a/src/utils/conftree.cpp +++ b/src/utils/conftree.cpp @@ -98,7 +98,11 @@ void ConfSimple::parseinput(istream& input) // Note that we trim whitespace before checking for backslash-eol // This avoids invisible whitespace problems. - trimstring(line); + if (trimvalues) { + trimstring(line); + } else { + ltrimstring(line); + } if (line.empty() || line.at(0) == '#') { if (eof) { break; @@ -119,7 +123,7 @@ void ConfSimple::parseinput(istream& input) appending = false; if (line[0] == '[') { - trimstring(line, "[]"); + trimstring(line, "[] \t"); if (dotildexpand) { submapkey = path_tildexpand(line); } else { @@ -142,7 +146,9 @@ void ConfSimple::parseinput(istream& input) nm = line.substr(0, eqpos); trimstring(nm); val = line.substr(eqpos + 1, string::npos); - trimstring(val); + if (trimvalues) { + trimstring(val); + } if (nm.length() == 0) { m_order.push_back(ConfLine(ConfLine::CFL_COMMENT, line)); @@ -156,8 +162,8 @@ void ConfSimple::parseinput(istream& input) } -ConfSimple::ConfSimple(int readonly, bool tildexp) - : dotildexpand(tildexp), m_fmtime(0), m_holdWrites(false) +ConfSimple::ConfSimple(int readonly, bool tildexp, bool trimv) + : dotildexpand(tildexp), trimvalues(trimv), m_fmtime(0), m_holdWrites(false) { status = readonly ? STATUS_RO : STATUS_RW; } @@ -169,8 +175,8 @@ void ConfSimple::reparse(const string& d) parseinput(input); } -ConfSimple::ConfSimple(const string& d, int readonly, bool tildexp) - : dotildexpand(tildexp), m_fmtime(0), m_holdWrites(false) +ConfSimple::ConfSimple(const string& d, int readonly, bool tildexp, bool trimv) + : dotildexpand(tildexp), trimvalues(trimv), m_fmtime(0), m_holdWrites(false) { status = readonly ? STATUS_RO : STATUS_RW; @@ -178,8 +184,10 @@ ConfSimple::ConfSimple(const string& d, int readonly, bool tildexp) parseinput(input); } -ConfSimple::ConfSimple(const char *fname, int readonly, bool tildexp) - : dotildexpand(tildexp), m_filename(fname), m_fmtime(0), m_holdWrites(false) +ConfSimple::ConfSimple(const char *fname, int readonly, bool tildexp, + bool trimv) + : dotildexpand(tildexp), trimvalues(trimv), m_filename(fname), + m_fmtime(0), m_holdWrites(false) { status = readonly ? STATUS_RO : STATUS_RW; diff --git a/src/utils/conftree.h b/src/utils/conftree.h index f976506c..46065760 100644 --- a/src/utils/conftree.h +++ b/src/utils/conftree.h @@ -121,7 +121,8 @@ public: * @param readonly if true open readonly, else rw * @param tildexp try tilde (home dir) expansion for subkey values */ - ConfSimple(const char *fname, int readonly = 0, bool tildexp = false); + ConfSimple(const char *fname, int readonly = 0, bool tildexp = false, + bool trimvalues = true); /** * Build the object by reading content from a string @@ -129,14 +130,16 @@ public: * @param readonly if true open readonly, else rw * @param tildexp try tilde (home dir) expansion for subsection names */ - ConfSimple(const string& data, int readonly = 0, bool tildexp = false); + ConfSimple(const string& data, int readonly = 0, bool tildexp = false, + bool trimvalues = true); /** * Build an empty object. This will be memory only, with no backing store. * @param readonly if true open read only, else rw * @param tildexp try tilde (home dir) expansion for subsection names */ - ConfSimple(int readonly = 0, bool tildexp = false); + ConfSimple(int readonly = 0, bool tildexp = false, + bool trimvalues = true); virtual ~ConfSimple() {}; @@ -281,6 +284,8 @@ public: */ ConfSimple& operator=(const ConfSimple& rhs) { if (this != &rhs && (status = rhs.status) != STATUS_ERROR) { + dotildexpand = rhs.dotildexpand; + trimvalues = rhs.trimvalues; m_filename = rhs.m_filename; m_submaps = rhs.m_submaps; } @@ -299,6 +304,7 @@ public: protected: bool dotildexpand; + bool trimvalues; StatusCode status; private: // Set if we're working with a file @@ -345,12 +351,12 @@ class ConfTree : public ConfSimple { public: /* The constructors just call ConfSimple's, asking for key tilde * expansion */ - ConfTree(const char *fname, int readonly = 0) - : ConfSimple(fname, readonly, true) {} - ConfTree(const string& data, int readonly = 0) - : ConfSimple(data, readonly, true) {} - ConfTree(int readonly = 0) - : ConfSimple(readonly, true) {} + ConfTree(const char *fname, int readonly = 0, bool trimvalues=true) + : ConfSimple(fname, readonly, true, trimvalues) {} + ConfTree(const string& data, int readonly = 0, bool trimvalues=true) + : ConfSimple(data, readonly, true, trimvalues) {} + ConfTree(int readonly = 0, bool trimvalues=true) + : ConfSimple(readonly, true, trimvalues) {} virtual ~ConfTree() {}; ConfTree(const ConfTree& r) : ConfSimple(r) {}; ConfTree& operator=(const ConfTree& r) { diff --git a/src/utils/execmd.cpp b/src/utils/execmd.cpp index 874cb5de..252112ef 100644 --- a/src/utils/execmd.cpp +++ b/src/utils/execmd.cpp @@ -34,7 +34,9 @@ #include #include #include +#include +#include #include #include #include @@ -493,27 +495,47 @@ int ExecCmd::startExec(const string& cmd, const vector& args, } argv[i] = 0; + // Environment. We first merge our environment and the specified + // variables in a map, overriding existing values, + // then generate an appropriate char*[] Ccharp *envv; - int envsize; - for (envsize = 0; ; envsize++) - if (environ[envsize] == 0) { - break; + map envmap; + for (int i = 0; environ[i] != 0; i++) { + string entry(environ[i]); + string::size_type eqpos = entry.find_first_of("="); + if (eqpos == string::npos) { + continue; } - envv = (Ccharp *)malloc((envsize + m->m_env.size() + 2) * sizeof(char *)); + envmap[entry.substr(0, eqpos)] = entry.substr(eqpos+1); + } + for (const auto& entry : m->m_env) { + string::size_type eqpos = entry.find_first_of("="); + if (eqpos == string::npos) { + continue; + } + envmap[entry.substr(0, eqpos)] = entry.substr(eqpos+1); + } + + // Allocate space for the array + string storage in one block. + unsigned int allocsize = (envmap.size() + 2) * sizeof(char *); + for (const auto& it : envmap) { + allocsize += it.first.size() + 1 + it.second.size() + 1; + } + envv = (Ccharp *)malloc(allocsize); if (envv == 0) { LOGERR("ExecCmd::doexec: malloc() failed. errno " << errno << "\n"); free(argv); return -1; } - int eidx; - for (eidx = 0; eidx < envsize; eidx++) { - envv[eidx] = environ[eidx]; + // Copy to new env array + i = 0; + char *cp = ((char *)envv) + (envmap.size() + 2) * sizeof(char *); + for (const auto& it : envmap) { + strcpy(cp, (it.first + "=" + it.second).c_str()); + envv[i++] = cp; + cp += it.first.size() + 1 + it.second.size() + 1; } - for (vector::const_iterator it = m->m_env.begin(); - it != m->m_env.end(); it++) { - envv[eidx++] = it->c_str(); - } - envv[eidx] = 0; + envv[i++] = 0; // As we are going to use execve, not execvp, do the PATH thing. string exe; diff --git a/src/utils/pathut.cpp b/src/utils/pathut.cpp index b0a518f9..d6c01eba 100644 --- a/src/utils/pathut.cpp +++ b/src/utils/pathut.cpp @@ -15,7 +15,6 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifndef TEST_PATHUT #ifdef BUILDING_RECOLL #include "autoconfig.h" #else @@ -612,6 +611,45 @@ string url_encode(const string& url, string::size_type offs) return out; } +static inline int h2d(int c) { + if ('0' <= c && c <= '9') + return c - '0'; + else if ('A' <= c && c <= 'F') + return 10 + c - 'A'; + else + return -1; +} + +string url_decode(const string &in) +{ + if (in.size() <= 2) + return in; + string out; + out.reserve(in.size()); + const char *cp = in.c_str(); + string::size_type i = 0; + for (; i < in.size() - 2; i++) { + if (cp[i] == '%') { + int d1 = h2d(cp[i+1]); + int d2 = h2d(cp[i+2]); + if (d1 != -1 && d2 != -1) { + out += (d1 << 4) + d2; + } else { + out += '%'; + out += cp[i+1]; + out += cp[i+2]; + } + i += 2; + } else { + out += cp[i]; + } + } + while (i < in.size()) { + out += cp[i++]; + } + return out; +} + string url_gpath(const string& url) { // Remove the access schema part (or whatever it's called) @@ -867,198 +905,3 @@ void pathut_init_mt() { path_home(); } - - -#else // TEST_PATHUT -#include -#include -using namespace std; - -#include "pathut.h" - -void path_to_thumb(const string& _input) -{ - string input(_input); - // Make absolute path if needed - if (input[0] != '/') { - input = path_absolute(input); - } - - input = string("file://") + path_canon(input); - - string path; - //path = url_encode(input, 7); - thumbPathForUrl(input, 7, path); - cout << path << endl; -} - -const char *tstvec[] = {"", "/", "/dir", "/dir/", "/dir1/dir2", - "/dir1/dir2", - "./dir", "./dir1/", "dir", "../dir", "/dir/toto.c", - "/dir/.c", "/dir/toto.txt", "toto.txt1" - }; - -const string ttvec[] = {"/dir", "", "~", "~/sub", "~root", "~root/sub", - "~nosuch", "~nosuch/sub" - }; -int nttvec = sizeof(ttvec) / sizeof(string); - -const char *thisprog; - -int main(int argc, const char **argv) -{ - thisprog = *argv++; - argc--; - - string s; - vector::const_iterator it; -#if 0 - for (unsigned int i = 0; i < sizeof(tstvec) / sizeof(char *); i++) { - cout << tstvec[i] << " Father " << path_getfather(tstvec[i]) << endl; - } - for (unsigned int i = 0; i < sizeof(tstvec) / sizeof(char *); i++) { - cout << tstvec[i] << " Simple " << path_getsimple(tstvec[i]) << endl; - } - for (unsigned int i = 0; i < sizeof(tstvec) / sizeof(char *); i++) { - cout << tstvec[i] << " Basename " << - path_basename(tstvec[i], ".txt") << endl; - } -#endif - -#if 0 - for (int i = 0; i < nttvec; i++) { - cout << "tildexp: '" << ttvec[i] << "' -> '" << - path_tildexpand(ttvec[i]) << "'" << endl; - } -#endif - -#if 0 - const string canontst[] = {"/dir1/../../..", "/////", "", - "/dir1/../../.././/////dir2///////", - "../../", - "../../../../../../../../../../" - }; - unsigned int nttvec = sizeof(canontst) / sizeof(string); - for (unsigned int i = 0; i < nttvec; i++) { - cout << "canon: '" << canontst[i] << "' -> '" << - path_canon(canontst[i]) << "'" << endl; - } -#endif -#if 0 - if (argc != 2) { - cerr << "Usage: trpathut " << endl; - exit(1); - } - string dir = *argv++; - argc--; - string pattern = *argv++; - argc--; - vector matched = path_dirglob(dir, pattern); - for (it = matched.begin(); it != matched.end(); it++) { - cout << *it << endl; - } -#endif - -#if 0 - if (argc != 1) { - fprintf(stderr, "Usage: fsocc: trpathut \n"); - exit(1); - } - string path = *argv++; - argc--; - - int pc; - long long blocks; - if (!fsocc(path, &pc, &blocks)) { - fprintf(stderr, "fsocc failed\n"); - return 1; - } - printf("pc %d, megabytes %ld\n", pc, blocks); -#endif - -#if 0 - Pidfile pidfile("/tmp/pathutpidfile"); - pid_t pid; - if ((pid = pidfile.open()) != 0) { - cerr << "open failed. reason: " << pidfile.getreason() << - " return " << pid << endl; - exit(1); - } - pidfile.write_pid(); - sleep(10); - pidfile.close(); - pidfile.remove(); -#endif - -#if 0 - if (argc > 1) { - cerr << "Usage: thumbpath " << endl; - exit(1); - } - string input; - if (argc == 1) { - input = *argv++; - if (input.empty()) { - cerr << "Usage: thumbpath " << endl; - exit(1); - } - path_to_thumb(input); - } else { - while (getline(cin, input)) { - path_to_thumb(input); - } - } - - - exit(0); -#endif - -#if 0 - if (argc != 1) { - cerr << "Usage: trpathut " << endl; - exit(1); - } - string fn = *argv++; - argc--; - string ext = path_suffix(fn); - cout << "Suffix: [" << ext << "]" << endl; - return 0; -#endif - -#if 0 - if (argc != 1) { - cerr << "Usage: trpathut url" << endl; - exit(1); - } - string url = *argv++; - argc--; - - cout << "File: [" << fileurltolocalpath(url) << "]\n"; - return 0; -#endif - -#if 1 - if (argc != 1) { - cerr << "Usage: trpathut path" << endl; - exit(1); - } - string path = *argv++; - argc--; - - int pc; - long long avmbs; - if (fsocc(path, &pc, &avmbs)) { - cout << "Percent occup " << pc << " avmbs " << avmbs << endl; - return 0; - } else { - cerr << "fsocc failed\n"; - return 1; - } -#endif - - - -} - -#endif // TEST_PATHUT - diff --git a/src/utils/pathut.h b/src/utils/pathut.h index e6b9e0cc..14991f4a 100644 --- a/src/utils/pathut.h +++ b/src/utils/pathut.h @@ -52,6 +52,7 @@ extern std::vector path_dirglob(const std::string& dir, /// Encode according to rfc 1738 extern std::string url_encode(const std::string& url, std::string::size_type offs = 0); +extern std::string url_decode(const std::string& encoded); //// Convert to file path if url is like file://. This modifies the //// input (and returns a copy for convenience) extern std::string fileurltolocalpath(std::string url); diff --git a/src/utils/smallut.cpp b/src/utils/smallut.cpp index e5876f5c..d2218c94 100644 --- a/src/utils/smallut.cpp +++ b/src/utils/smallut.cpp @@ -453,6 +453,20 @@ bool stringToBool(const string& s) } void trimstring(string& s, const char *ws) +{ + rtrimstring(s, ws); + ltrimstring(s, ws); +} + +void rtrimstring(string& s, const char *ws) +{ + string::size_type pos = s.find_last_not_of(ws); + if (pos != string::npos && pos != s.length() - 1) { + s.replace(pos + 1, string::npos, string()); + } +} + +void ltrimstring(string& s, const char *ws) { string::size_type pos = s.find_first_not_of(ws); if (pos == string::npos) { @@ -460,11 +474,6 @@ void trimstring(string& s, const char *ws) return; } s.replace(0, pos, string()); - - pos = s.find_last_not_of(ws); - if (pos != string::npos && pos != s.length() - 1) { - s.replace(pos + 1, string::npos, string()); - } } // Remove some chars and replace them with spaces diff --git a/src/utils/smallut.h b/src/utils/smallut.h index 6a16b529..d159f1f7 100644 --- a/src/utils/smallut.h +++ b/src/utils/smallut.h @@ -142,6 +142,8 @@ extern bool stringToBool(const std::string& s); /** Remove instances of characters belonging to set (default {space, tab}) at beginning and end of input string */ extern void trimstring(std::string& s, const char *ws = " \t"); +extern void rtrimstring(std::string& s, const char *ws = " \t"); +extern void ltrimstring(std::string& s, const char *ws = " \t"); /** Escape things like < or & by turning them into entities */ extern std::string escapeHtml(const std::string& in);