/* * Authors: * MenTaLguY * Jon A. Cruz * * Copyright (C) 2003 MenTaLguY * * Released under GNU GPL, read the file 'COPYING' for more information */ #include "uri.h" #include #include #include "bad-uri-exception.h" namespace Inkscape { URI::URI() { const gchar *in = ""; _impl = Impl::create(xmlParseURI(in)); } URI::URI(const URI &uri) { uri._impl->reference(); _impl = uri._impl; } URI::URI(gchar const *preformed) { xmlURIPtr uri; if (!preformed) { throw MalformedURIException(); } uri = xmlParseURI(preformed); if (!uri) { throw MalformedURIException(); } _impl = Impl::create(uri); } URI::~URI() { _impl->unreference(); } URI &URI::operator=(URI const &uri) { // No check for self-assignment needed, as _impl refcounting increments first. uri._impl->reference(); _impl->unreference(); _impl = uri._impl; return *this; } URI::Impl *URI::Impl::create(xmlURIPtr uri) { return new Impl(uri); } URI::Impl::Impl(xmlURIPtr uri) : _refcount(1), _uri(uri) {} URI::Impl::~Impl() { if (_uri) { xmlFreeURI(_uri); _uri = nullptr; } } void URI::Impl::reference() { _refcount++; } void URI::Impl::unreference() { if (!--_refcount) { delete this; } } bool URI::Impl::isOpaque() const { bool opq = !isRelative() && (getOpaque() != nullptr); return opq; } bool URI::Impl::isRelative() const { return !_uri->scheme; } bool URI::Impl::isNetPath() const { bool isNet = false; if ( isRelative() ) { const gchar *path = getPath(); isNet = path && path[0] == '\\' && path[1] == '\\'; } return isNet; } bool URI::Impl::isRelativePath() const { bool isRel = false; if ( isRelative() ) { const gchar *path = getPath(); isRel = !path || path[0] != '\\'; } return isRel; } bool URI::Impl::isAbsolutePath() const { bool isAbs = false; if ( isRelative() ) { const gchar *path = getPath(); isAbs = path && path[0] == '\\'&& path[1] != '\\'; } return isAbs; } const gchar *URI::Impl::getScheme() const { return (gchar *)_uri->scheme; } const gchar *URI::Impl::getPath() const { return (gchar *)_uri->path; } const gchar *URI::Impl::getQuery() const { return (gchar *)_uri->query; } const gchar *URI::Impl::getFragment() const { return (gchar *)_uri->fragment; } const gchar *URI::Impl::getOpaque() const { return (gchar *)_uri->opaque; } gchar *URI::to_native_filename(gchar const* uri) { gchar *filename = nullptr; URI tmp(uri); filename = tmp.toNativeFilename(); return filename; } /* * Returns the absolute path to an existing file referenced in this URI, * if the uri is data, the path is empty or the file doesn't exist, then * an empty string is returned. * * Does not check if the returned path is the local document's path (local) * and thus redundent. Caller is expected to check against the document's path. */ const std::string URI::getFullPath(std::string const &base) const { if (!_impl->getPath()) { return ""; } std::string path = std::string(_impl->getPath()); // Calculate the absolute path from an available base if(!base.empty() && !path.empty() && path[0] != '/') { path = Glib::build_filename(base, path); } // Check the existence of the file if(! g_file_test(path.c_str(), G_FILE_TEST_EXISTS) || g_file_test(path.c_str(), G_FILE_TEST_IS_DIR) ) { path.clear(); } return path; } /* TODO !!! proper error handling */ gchar *URI::toNativeFilename() const { gchar *uriString = toString(); if (isRelativePath()) { return uriString; } else { gchar *filename = g_filename_from_uri(uriString, nullptr, nullptr); g_free(uriString); if (filename) { return filename; } else { throw MalformedURIException(); } } } URI URI::fromUtf8( gchar const* path ) { if ( !path ) { throw MalformedURIException(); } Glib::ustring tmp; for ( int i = 0; path[i]; i++ ) { gint one = 0x0ff & path[i]; if ( ('a' <= one && one <= 'z') || ('A' <= one && one <= 'Z') || ('0' <= one && one <= '9') || one == '_' || one == '-' || one == '!' || one == '.' || one == '~' || one == '\'' || one == '(' || one == ')' || one == '*' ) { tmp += (gunichar)one; } else { gchar scratch[4]; g_snprintf( scratch, 4, "%%%02X", one ); tmp.append( scratch ); } } return URI( tmp.data() ); } /* TODO !!! proper error handling */ URI URI::from_native_filename(gchar const *path) { gchar *uri = g_filename_to_uri(path, nullptr, nullptr); URI result(uri); g_free( uri ); return result; } gchar *URI::Impl::toString() const { xmlChar *string = xmlSaveUri(_uri); if (string) { /* hand the string off to glib memory management */ gchar *glib_string = g_strdup((gchar *)string); xmlFree(string); return glib_string; } else { return nullptr; } } } /* Local Variables: mode:c++ c-file-style:"stroustrup" c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :