//////////////////////////////////////////////////////////////////////////////// // taskwarrior - a command line task list manager. // // Copyright 2010 - 2012, Johannes Schlatow. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // // http://www.opensource.org/licenses/mit-license.php // //////////////////////////////////////////////////////////////////////////////// #define L10N // Localization complete. #include #include #include #include extern Context context; //////////////////////////////////////////////////////////////////////////////// Uri::Uri () { _parsed = false; } //////////////////////////////////////////////////////////////////////////////// Uri::Uri (const Uri& other) { if (this != &other) { _data = other._data; _host = other._host; _path = other._path; _user = other._user; _port = other._port; _protocol = other._protocol; _parsed = other._parsed; } } //////////////////////////////////////////////////////////////////////////////// Uri::Uri (const std::string& in, const std::string& configPrefix) { _data = in; _parsed = false; if (configPrefix != "") expand(configPrefix); } //////////////////////////////////////////////////////////////////////////////// Uri::~Uri () { } //////////////////////////////////////////////////////////////////////////////// Uri& Uri::operator= (const Uri& other) { if (this != &other) { this->_data = other._data; this->_host = other._host; this->_path = other._path; this->_user = other._user; this->_port = other._port; this->_protocol = other._protocol; this->_parsed = other._parsed; } return *this; } //////////////////////////////////////////////////////////////////////////////// Uri::operator std::string () const { return _data; } //////////////////////////////////////////////////////////////////////////////// std::string Uri::name () const { if (_path.length ()) { std::string::size_type slash = _path.rfind ('/'); if (slash != std::string::npos) return _path.substr (slash + 1, std::string::npos); } return _path; } //////////////////////////////////////////////////////////////////////////////// std::string Uri::parent () const { if (_path.length ()) { std::string::size_type slash = _path.rfind ('/'); if (slash != std::string::npos) return _path.substr (0, slash+1); } return ""; } //////////////////////////////////////////////////////////////////////////////// std::string Uri::extension () const { if (_path.length ()) { std::string::size_type dot = _path.rfind ('.'); if (dot != std::string::npos) return _path.substr (dot + 1, std::string::npos); } return ""; } //////////////////////////////////////////////////////////////////////////////// bool Uri::is_directory () const { if (is_local ()) { return Path (this->_data).is_directory (); } else return (_path == ".") || (_path == "") || (_path[_path.length()-1] == '/'); } //////////////////////////////////////////////////////////////////////////////// bool Uri::is_local () const { if (_parsed) return (_protocol == ""); else return ( (_data.find("://") == std::string::npos) && (_data.find(":") == std::string::npos) ); } //////////////////////////////////////////////////////////////////////////////// bool Uri::append (const std::string& path) { if (is_directory ()) { this->_path += path; return true; } else return false; } //////////////////////////////////////////////////////////////////////////////// bool Uri::expand (const std::string& configPrefix ) { std::string tmp; if (_data.length ()) { // try to replace argument with uri from config tmp = context.config.get (configPrefix + "." + _data + ".uri"); } else { // get default target from config tmp = context.config.get (configPrefix + ".default.uri"); } if (tmp != "") { _data = tmp; return true; } return false; } //////////////////////////////////////////////////////////////////////////////// std::string Uri::ToString () { if (!_parsed) return std::string (); if (is_local ()) return _data; std::string result; result = _protocol + "://"; if (_user.length () > 0) { // obscure password in _user std::string::size_type pos = _user.find (":"); if (pos != std::string::npos) { std::string::size_type len = _user.length () - pos - 1; result += _user.replace (pos+1, len, len, '*') + "@"; } else result += _user + "@"; } result += _host; if (_port.length () > 0) result += + ":" + _port; result += "/" + _path; return result; } //////////////////////////////////////////////////////////////////////////////// void Uri::parse () { if (_parsed) return; if (is_local ()) { _path = _data; _parsed = true; return; } std::string::size_type pos; std::string _data = this->_data; std::string pathDelimiter = "/"; _user = ""; _port = ""; // skip ^.*:// if ((pos = _data.find ("://")) != std::string::npos) { _protocol = _data.substr(0, pos); _data = _data.substr (pos+3); // standard syntax: protocol://[user@]host.xz[:port]/path/to/undo.data pathDelimiter = "/"; } else { _protocol = "ssh"; // scp-like syntax: [user@]host.xz:path/to/undo.data pathDelimiter = ":"; } // user delimited by single quotes? if ( _data[0] == '\'' && (pos = _data.find("'", 1)) != std::string::npos ) { if (_data[pos+1] == '@') { // end of user name _user = _data.substr (1, pos-1); _data = _data.substr (pos+2); } else { throw std::string (format (STRING_URI_QUOTES, _data)); } } else { // find user name if ((pos = _data.find ("@")) != std::string::npos) { _user = _data.substr (0, pos); _data = _data.substr (pos+1); } } // get host, port and path if ((pos = _data.find (pathDelimiter)) != std::string::npos) { _host = _data.substr (0, pos); _path = _data.substr (pos+1); } else { throw std::string (format (STRING_URI_BAD_FORMAT, _data)); } // path is absolute for ssh:// syntax if ( (_protocol == "ssh") && (pathDelimiter == "/") && (_path[0] != '~') ) { _path = "/" + _path; } // port specified? // remark: this find() will never be != npos for scp-like syntax // because we found pathDelimiter, which is ":", before if ((pos = _host.find (":")) != std::string::npos) { _port = _host.substr (pos+1); _host = _host.substr (0,pos); } _parsed = true; } //////////////////////////////////////////////////////////////////////////////// // vim: et ts=2 sw=2