// -*- c-basic-offset: 2 -*- /* This file is part of the KDE libraries * Copyright (C) 1999 Torben Weis * Copyright (C) 2005-2006 David Faure * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KURL_H #define KURL_H #include #include #include #include #include class KUrlPrivate; /** * \class KUrl kurl.h * * Represents and parses a URL. * * A prototypical URL looks like: * \code * protocol://user:password\@hostname:port/path/to/file.ext#reference * \endcode * * KUrl handles escaping of URLs. This means that the specification * of a full URL will differ from the corresponding string that would specify a * local file or directory in file-operations like fopen. This is because an URL * doesn't allow certain characters and escapes them. (e.g. '#'->"%23", space->"%20") * (In a URL the hash-character '#' is used to specify a "reference", i.e. the position * within a document). * * The constructor KUrl(const QString&) expects a string properly escaped, * or at least non-ambiguous. * If you have the absolute path you should use KUrl::fromPath(const QString&). * \code * KUrl kurl = KUrl::fromPath("/bar/#foo#"); * QString url = kurl.url(); // -> "file:///bar/%23foo%23" * \endcode * * If you have the URL of a local file or directory and need the absolute path, * you would use toLocalFile(). * \code * KUrl url( "file:///bar/%23foo%23" ); * ... * if ( url.isLocalFile() ) * QString path = url.toLocalFile(); // -> "/bar/#foo#" * \endcode * * This must also be considered when you have separated directory and file * strings and need to put them together. * While you can simply concatenate normal path strings, you must take care if * the directory-part is already an escaped URL. * (This might be needed if the user specifies a relative path, and your * program supplies the rest from elsewhere.) * * Wrong: * \code * QString dirUrl = "file:///bar/"; * QString fileName = "#foo#"; * QString invalidURL = dirUrl + fileName; // -> "file:///bar/#foo#" won't behave like you would expect. * \endcode * Instead you should use addPath(): * Right: * \code * KUrl url( "file:///bar/" ); * QString fileName = "#foo#"; * url.addPath( fileName ); * QString validURL = url.url(); // -> "file:///bar/%23foo%23" * \endcode * * Also consider that some URLs contain the password, but this shouldn't be * visible. Your program should use prettyUrl() every time it displays a * URL, whether in the GUI or in debug output or... * * \code * KUrl url( "ftp://name:password@ftp.faraway.org/bar/%23foo%23"); * QString visibleURL = url.prettyUrl(); // -> "ftp://name@ftp.faraway.org/bar/%23foo%23" * \endcode * Note that prettyUrl() doesn't change the character escapes (like "%23"). * Otherwise the URL would be invalid and the user wouldn't be able to use it in another * context. * */ class KDECORE_EXPORT KUrl : public QUrl { public: enum MimeDataFlags { DefaultMimeDataFlags = 0, NoTextExport = 1 }; /** * Options to be used in adjustPath */ enum AdjustPathOption { /** * strips a trailing '/', except when the path is already just "/". */ RemoveTrailingSlash, /** * Do not change the path. */ LeaveTrailingSlash, /** * adds a trailing '/' if there is none yet */ AddTrailingSlash }; /** * \class List kurl.h * * KUrl::List is a QList that contains KUrls with a few * convenience methods. * @see KUrl * @see QList */ class KDECORE_EXPORT List : public QList { public: /** * Creates an empty List. */ List() { } /** * Creates a list that contains the given URL as only * item. * @param url the url to add. */ List(const KUrl &url); /** * Creates a list that contains the URLs from the given * list of strings. * @param list the list containing the URLs as strings */ List(const QStringList &list); /** * Creates a list that contains the URLs from the given QList. * @param list the list containing the URLs */ List(const QList &list); /** * Creates a list that contains the URLs from the given QList. * @param list the list containing the URLs * @since 4.7 */ List(const QList &list); /** * Converts the URLs of this list to a list of strings. * @return the list of strings */ QStringList toStringList() const; /** * Converts the URLs of this list to a list of strings. * * @param trailing use to add or remove a trailing slash to/from the path. * * @return the list of strings * * @since 4.6 */ QStringList toStringList(KUrl::AdjustPathOption trailing) const; /** * Converts this KUrl::List to a QVariant, this allows to use KUrl::List * in QVariant() constructor */ operator QVariant() const; /** * Converts this KUrl::List into a list of QUrl instances. * @since 4.7 */ operator QList() const; /** * Adds URLs data into the given QMimeData. * * By default, populateMimeData also exports the URLs as plain text, for e.g. dropping * onto a text editor. * But in some cases this might not be wanted, e.g. if adding other mime data * which provides better plain text data. * * WARNING: do not call this method multiple times on the same mimedata object, * you can add urls only once. But you can add other things, e.g. images, XML... * * @param mimeData the QMimeData instance used to drag or copy this URL * @param flags set NoTextExport to prevent setting plain/text data into @p mimeData */ void populateMimeData(QMimeData *mimeData, MimeDataFlags flags = DefaultMimeDataFlags) const; /** * Adds URLs into the given QMimeData. * * This should add both the KDE-style URLs (eg: desktop:/foo) and * the "most local" version of the URLs (eg: * file:///home/jbloggs/Desktop/foo) to the mimedata. * * This method should be called on the KDE-style URLs. * * @code * QMimeData* mimeData = new QMimeData(); * * KUrl::List kdeUrls; * kdeUrls << "desktop:/foo"; * kdeUrls << "desktop:/bar"; * * KUrl::List normalUrls; * normalUrls << "file:///home/jbloggs/Desktop/foo"; * normalUrls << "file:///home/jbloggs/Desktop/bar"; * * kdeUrls.populateMimeData(normalUrls, mimeData); * @endcode * * @param mostLocalUrls the "most local" urls * @param mimeData the mime data object to populate * @param flags set NoTextExport to prevent setting plain/text * data into @p mimeData. * @since 4.2 */ void populateMimeData(const KUrl::List &mostLocalUrls, QMimeData *mimeData, MimeDataFlags flags = DefaultMimeDataFlags) const; /** * Return true if @p mimeData contains URI data */ static bool canDecode(const QMimeData *mimeData); /** * Return the list of mimeTypes that can be decoded by fromMimeData */ static QStringList mimeDataTypes(); /** * Flags to be used in fromMimeData. * @since 4.2.3 */ enum DecodeOptions { /** * When the mimedata contains both KDE-style URLs (eg: desktop:/foo) and * the "most local" version of the URLs (eg: file:///home/dfaure/Desktop/foo), * decode it as local urls. Useful in paste/drop operations that end up calling KIO, * so that urls from other users work as well. */ PreferLocalUrls, /** * When the mimedata contains both KDE-style URLs (eg: desktop:/foo) and * the "most local" version of the URLs (eg: file:///home/dfaure/Desktop/foo), * decode it as the KDE-style URL. Useful in DnD code e.g. when moving icons, * and the kde-style url is used as identifier for the icons. */ PreferKdeUrls }; /** * Extract a list of KUrls from the contents of @p mimeData. * Decoding will fail if @p mimeData does not contain any URLs, or if at * least one extracted URL is not valid. * @param mimeData the mime data to extract from; cannot be 0 * @param decodeOptions options for decoding * @return the list of urls * @since 4.2.3 */ static KUrl::List fromMimeData(const QMimeData *mimeData, DecodeOptions decodeOptions = PreferKdeUrls); }; /** * Constructs an empty URL. */ KUrl(); /** * Usual constructor, to construct from a string. * @param urlOrPath An encoded URL or a path. */ KUrl(const QString &urlOrPath); /** * Constructor taking a char * @p urlOrPath, which is an _encoded_ representation * of the URL, exactly like the usual constructor. This is useful when * the URL, in its encoded form, is strictly ascii. * @param urlOrPath An encoded URL, or a path. */ explicit KUrl(const char *urlOrPath); /** * Constructor taking a QByteArray @p urlOrPath, which is an _encoded_ representation * of the URL, exactly like the usual constructor. This is useful when * the URL, in its encoded form, is strictly ascii. * @param urlOrPath An encoded URL, or a path. */ explicit KUrl(const QByteArray &urlOrPath); /** * Copy constructor. * @param u the KUrl to copy */ KUrl(const KUrl &u); /** * Converts from a QUrl. * @param u the QUrl */ KUrl(const QUrl &u); /** * Constructor allowing relative URLs. * * @param _baseurl The base url. * @param _rel_url A relative or absolute URL. * If this is an absolute URL then @p _baseurl will be ignored. * If this is a relative URL it will be combined with @p _baseurl. * Note that _rel_url should be encoded too, in any case. * So do NOT pass a path here (use setPath or addPath instead). */ KUrl(const KUrl &_baseurl, const QString &_rel_url); /** * @param trailing use to add or remove a trailing slash to/from the path. see adjustPath * * @return The current decoded path. This does not include the query. Can * be QString() if no path is set. */ QString path(AdjustPathOption trailing = LeaveTrailingSlash) const; /** * @param trailing use to add or remove a trailing slash to/from the local path. see adjustPath * * @return The current local path. Can * be QString() if no path is set. */ QString toLocalFile(AdjustPathOption trailing = LeaveTrailingSlash) const; /// \reimp so that KUrl u; u.setPath(path); implies "file" protocol. void setPath(const QString &path); /** * Resolves "." and ".." components in path. * Some servers seem not to like the removal of extra '/' * even though it is against the specification in RFC 2396. */ void cleanPath(); /** * Add or remove a trailing slash to/from the path. * * If the URL has no path, then no '/' is added * anyway. And on the other side: If the path is "/", then this * character won't be stripped. Reason: "ftp://weis\@host" means something * completely different than "ftp://weis\@host/". So adding or stripping * the '/' would really alter the URL, while "ftp://host/path" and * "ftp://host/path/" mean the same directory. * * @param trailing RemoveTrailingSlash strips any trailing '/' and * AddTrailingSlash adds a trailing '/' if there is none yet */ void adjustPath(AdjustPathOption trailing); /** * Checks whether the file is local. * @return true if the file is a plain local file (i.e. uses the file protocol * and no hostname, or the local hostname). * When isLocalFile returns true, you can use toLocalFile to read the file contents. * Otherwise you need to use KIO (e.g. KIO::get). */ bool isLocalFile() const; /** * Adds to the current path. * Assumes that the current path is a directory. @p txt is appended to the * current path. The function adds '/' if needed while concatenating. * This means it does not matter whether the current path has a trailing * '/' or not. If there is none, it becomes appended. If @p txt * has a leading '/' then this one is stripped. * * @param txt The text to add. It is considered to be decoded. */ void addPath(const QString &txt); /** * Sets the filename of the path. * In comparison to addPath() this function does not assume that the current * path is a directory. This is only assumed if the current path ends with '/'. * * Any reference is reset. * * @param txt The filename to be set. It is considered to be decoded. If the * current path ends with '/' then @p txt is just appended, otherwise * all text behind the last '/' in the current path is erased and * @p txt is appended then. It does not matter whether @p txt starts * with '/' or not. */ void setFileName(const QString &txt); /** * Returns the filename of the path. * @param trailing use to add or remove a trailing slash to/from the path. See adjustPath * @return The filename of the current path. The returned string is decoded. Null * if there is no file (and thus no path). */ QString fileName(AdjustPathOption trailing = RemoveTrailingSlash) const; /** * Returns the directory of the path. * @param trailing use to add or remove a trailing slash to/from the path. See adjustPath * @return The directory part of the current path. Everything between the last and the second last '/' * is returned. For example file:///hallo/torben/ would return "/hallo/torben/" while * file:///hallo/torben would return "hallo/". The returned string is decoded. * QString() is returned when there is no path. */ QString directory(AdjustPathOption trailing = AddTrailingSlash) const; /** * Set the directory to @p dir, leaving the filename empty. */ void setDirectory(const QString &dir); /** * Returns the URL as string, with all escape sequences intact, * encoded in a given charset. * This is used in particular for encoding URLs in UTF-8 before using them * in a drag and drop operation. * Please note that the string returned by url() will include * the password of the URL. If you want to show the URL to the * user, use prettyUrl(). * * @param trailing use to add or remove a trailing slash to/from the path. See adjustPath * @return The complete URL, with all escape sequences intact, encoded * in a given charset. * @see prettyUrl() */ QString url(AdjustPathOption trailing = LeaveTrailingSlash) const; /** * Returns the URL as string in human-friendly format. * Example: * \code * http://localhost:8080/test.cgi?test=hello world&name=fred * \endcode * @param trailing use to add or remove a trailing slash to/from the path. see adjustPath. * * @return A human readable URL, with no non-necessary encodings/escaped * characters. Password will not be shown. * @see url() */ QString prettyUrl(AdjustPathOption trailing = LeaveTrailingSlash) const; /** * Return the URL as a string, which will be either the URL (as prettyUrl * would return) or, when the URL is a local file without query or ref, * the path. * Use this method, to display URLs to the user. * You can give the result of pathOrUrl back to the KUrl constructor, it accepts * both paths and urls. * * @param trailing use to add or remove a trailing slash to/from the path. see adjustPath. * @return the new KUrl * @since 4.2 */ QString pathOrUrl(AdjustPathOption trailing = LeaveTrailingSlash) const; /** * Returns the URL as a string, using the standard conventions for mime data * (drag-n-drop or copy-n-paste). * Internally used by KUrl::List::fromMimeData, which is probably what you want to use instead. */ QString toMimeDataString() const; /** * This function is useful to implement the "Up" button in a file manager for example. * That means that if you are in file:///home/joe/ and hit the up button you expect to see * file:///home. The algorithm tries to go up on the right-most URL. * @return a URL that is a level higher */ KUrl upUrl() const; KUrl& operator=(const KUrl &_u); // Define those, since the constructors are explicit KUrl& operator=(const char *_url) { *this = KUrl(_url); return *this; } KUrl& operator=(const QByteArray &_url) { *this = KUrl(_url); return *this; } KUrl& operator=(const QString &_url) { *this = KUrl(_url); return *this; } bool operator==(const KUrl &_u) const; bool operator==(const QString &_u) const; bool operator!=(const KUrl &_u) const { return !(*this == _u); } bool operator!=(const QString &_u) const { return !(*this == _u); } /** * Converts this KUrl to a QVariant, this allows to use KUrl * in QVariant() constructor */ operator QVariant() const; /** * Compares this url with @p u. * @param u the URL to compare this one with. * @param trailing use to add or remove a trailing slash to/from the path. See adjustPath * @return True if both urls are the same. If at least one of the urls is invalid, * false is returned. * @see operator==. This function should be used if you want to * set additional options, like ignoring trailing '/' characters. */ bool equals(const KUrl &u, AdjustPathOption trailing = LeaveTrailingSlash) const; /** * Checks whether the given URL is parent of this URL. * For instance, ftp://host/dir/ is a parent of ftp://host/dir/subdir/subsubdir/. * @return true if this url is a parent of @p u (or the same URL as @p u) * */ bool isParentOf(const KUrl &u) const; /** * Creates a KUrl object from a QString representing an absolute path. * KUrl url( somePath ) is almost the same, but this method is more explicit, * avoids the path-or-url detection in the KUrl constructor, and parses * "abc:def" as a filename, not as URL. * * @param text the path * @return the new KUrl */ static KUrl fromPath(const QString &text); /** * Adds URL data into the given QMimeData. * * By default, populateMimeData also exports the URL as plain text, for e.g. dropping * onto a text editor. * But in some cases this might not be wanted, e.g. if adding other mime data * which provides better plain text data. * * WARNING: do not call this method multiple times, use KUrl::List::populateMimeData instead. * * @param mimeData the QMimeData instance used to drag or copy this URL * @param flags set NoTextExport to prevent setting plain/text data into @p mimeData */ void populateMimeData(QMimeData* mimeData, MimeDataFlags flags = DefaultMimeDataFlags) const; /** * Convenience function. * * Returns whether '_url' is likely to be a "relative" URL instead of * an "absolute" URL. * * This is mostly meant for KUrl(url, relativeUrl). * * If you are looking for the notion of "relative path" (foo) vs "absolute path" (/foo), * use QUrl::isRelative() instead. * Indeed, isRelativeUrl() returns true for the string "/foo" since it doesn't contain a protocol, * while KUrl("/foo").isRelative() is false since the KUrl constructor turns it into file:///foo. * The two methods basically test the same thing, but this one takes a string (which is faster) * while the class method requires a QUrl/KUrl which gives a more expected result, given * the "magic" in the KUrl constructor. * * @param _url URL to examine * @return true when the URL is likely to be "relative", false otherwise. */ static bool isRelativeUrl(const QString &_url); /** * Convenience function * * Returns a "relative URL" based on @p base_url that points to @p url. * * If no "relative URL" can be created, e.g. because the protocol * and/or hostname differ between @p base_url and @p url an absolute * URL is returned. * Note that if @p base_url represents a directory, it should contain * a trailing slash. * @param base_url the URL to derive from * @param url new URL * @see adjustPath() */ static QString relativeUrl(const KUrl &base_url, const KUrl &url); /** * Convenience function * * Returns a relative path based on @p base_dir that points to @p path. * @param base_dir the base directory to derive from * @param path the new target directory * @param isParent A pointer to a boolean which, if provided, will be set to reflect * whether @p path has @p base_dir is a parent dir. */ static QString relativePath(const QString &base_dir, const QString &path, bool *isParent = nullptr); /** * Compatibility methods, do not use */ inline QString protocol() const { return scheme().toLower(); }; inline bool hasUser() const { return !userName().isEmpty(); }; inline bool hasPass() const { return !password().isEmpty(); }; inline bool hasHost() const { return !host().isEmpty(); }; inline bool hasPath() const { return !path().isEmpty(); }; private: QString toString() const; // forbidden, use url(), prettyUrl(), or pathOrUrl() instead. operator QString() const; // forbidden, use url(), prettyUrl(), or pathOrUrl() instead. }; Q_DECLARE_METATYPE(KUrl) Q_DECLARE_METATYPE(KUrl::List) KDECORE_EXPORT uint qHash(const KUrl& kurl); #endif // KURL_H