diff -r beefddde951e -r 26a8b1a14889 src/StreamletAttributeFinder.h --- a/src/StreamletAttributeFinder.h Sun Jan 19 15:44:30 2020 +0100 +++ b/src/StreamletAttributeFinder.h Sun Jan 19 17:05:46 2020 +0100 @@ -45,24 +45,36 @@ std::map> subProcesses; std::map> cachedMetadata; + std::vector splitBySeparator(const string_t& originalString, const wchar_t separator = L':', const wchar_t escape = L'\\') { + std::vector result; + std::wstringstream current; + for (int i = 0, size = originalString.size(); i < size; i++) { + wchar_t ch = originalString[i]; + if (ch == escape) { + if (i + 1 < size) { + ch = originalString[++i]; + if (ch == separator || ch == escape) current.put(ch); + else RelpipeWriterException(L"Invalid escape sequence at position " + std::to_wstring(i) + L" of: " + originalString); + } else { + throw RelpipeWriterException(L"Invalid use of escape character at the end of: " + originalString); + } + } else if (ch == separator || i + 1 == size) { + if (current.str().size()) result.push_back(current.str()); + current.str(L""); + current.clear(); + } else { + current.put(ch); + } + } + return result; + } + string_t getStreamletCommand(const RequestedField& field) { const char* streamletPathChars = getenv("RELPIPE_IN_FILESYSTEM_STREAMLET_PATH"); if (streamletPathChars) { - std::wstringstream current; - string_t streamletPath = convertor.from_bytes(streamletPathChars); - for (int i = 0, streamletPathSize = streamletPath.size(); i < streamletPathSize; i++) { - if (streamletPath[i] == ':' || i == streamletPathSize - 1) { // FIXME: support \: and \\ escaping - current << L"/" << field.name; - fs::path streamletFile(current.str()); - if (fs::exists(streamletFile) && ::access(streamletFile.c_str(), X_OK) == 0) { // n.b. must be set executable using e.g. chmod – files executable through only ACL, are actually not executable - return current.str(); - } else { - current.str(L""); - current.clear(); - } - } else { - current.put(streamletPath[i]); - } + for (string_t path : splitBySeparator(convertor.from_bytes(streamletPathChars))) { + fs::path file = fs::path(path) / fs::path(field.name); + if (fs::exists(file) && ::access(file.c_str(), X_OK) == 0) return file.wstring(); } throw RelpipeWriterException(L"Streamlet „" + field.name + L"“ was not found at $RELPIPE_IN_FILESYSTEM_STREAMLET_PATH"); } else { @@ -99,9 +111,7 @@ public: - static const string_t SCRIPT_PREFIX; - - virtual vector toMetadata(RelationalWriter* writer, const string_t& relationName, const RequestedField& field) override { + virtual vector toMetadata(RelationalWriter* writer, const string_t& relationName, const RequestedField & field) override { if (field.group == RequestedField::GROUP_STREAMLET) { if (cachedMetadata.count(field.id)) { @@ -160,8 +170,6 @@ } }; -const relpipe::writer::string_t StreamletAttributeFinder::SCRIPT_PREFIX = L"__relpipe_in_filesystem_script_"; - } } }