1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Copyright (C) 2016 Intel Corporation.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtCore module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #ifndef QURL_H
42 #define QURL_H
43 
44 #include <QtCore/qbytearray.h>
45 #include <QtCore/qobjectdefs.h>
46 #include <QtCore/qstring.h>
47 #include <QtCore/qlist.h>
48 #include <QtCore/qpair.h>
49 #include <QtCore/qglobal.h>
50 
51 #if defined(Q_OS_DARWIN) || defined(Q_QDOC)
52 Q_FORWARD_DECLARE_CF_TYPE(CFURL);
53 Q_FORWARD_DECLARE_OBJC_CLASS(NSURL);
54 #endif
55 
56 QT_BEGIN_NAMESPACE
57 
58 
59 class QUrlQuery;
60 class QUrlPrivate;
61 class QDataStream;
62 
63 template <typename E1, typename E2>
64 class QUrlTwoFlags
65 {
66     int i;
67     typedef int QUrlTwoFlags:: *Zero;
68 public:
QUrlTwoFlags(E1 f)69     Q_DECL_CONSTEXPR inline QUrlTwoFlags(E1 f) : i(f) {}
QUrlTwoFlags(E2 f)70     Q_DECL_CONSTEXPR inline QUrlTwoFlags(E2 f) : i(f) {}
QUrlTwoFlags(QFlag f)71     Q_DECL_CONSTEXPR inline QUrlTwoFlags(QFlag f) : i(f) {}
QUrlTwoFlags(QFlags<E1> f)72     Q_DECL_CONSTEXPR inline QUrlTwoFlags(QFlags<E1> f) : i(f.operator typename QFlags<E1>::Int()) {}
QUrlTwoFlags(QFlags<E2> f)73     Q_DECL_CONSTEXPR inline QUrlTwoFlags(QFlags<E2> f) : i(f.operator typename QFlags<E2>::Int()) {}
74     Q_DECL_CONSTEXPR inline QUrlTwoFlags(Zero = 0) : i(0) {}
75 
76     inline QUrlTwoFlags &operator&=(int mask) { i &= mask; return *this; }
77     inline QUrlTwoFlags &operator&=(uint mask) { i &= mask; return *this; }
78     inline QUrlTwoFlags &operator|=(QUrlTwoFlags f) { i |= f.i; return *this; }
79     inline QUrlTwoFlags &operator|=(E1 f) { i |= f; return *this; }
80     inline QUrlTwoFlags &operator|=(E2 f) { i |= f; return *this; }
81     inline QUrlTwoFlags &operator^=(QUrlTwoFlags f) { i ^= f.i; return *this; }
82     inline QUrlTwoFlags &operator^=(E1 f) { i ^= f; return *this; }
83     inline QUrlTwoFlags &operator^=(E2 f) { i ^= f; return *this; }
84 
85     Q_DECL_CONSTEXPR inline operator QFlags<E1>() const { return QFlag(i); }
86     Q_DECL_CONSTEXPR inline operator QFlags<E2>() const { return QFlag(i); }
87     Q_DECL_CONSTEXPR inline operator int() const { return i; }
88     Q_DECL_CONSTEXPR inline bool operator!() const { return !i; }
89 
90     Q_DECL_CONSTEXPR inline QUrlTwoFlags operator|(QUrlTwoFlags f) const
91     { return QUrlTwoFlags(QFlag(i | f.i)); }
92     Q_DECL_CONSTEXPR inline QUrlTwoFlags operator|(E1 f) const
93     { return QUrlTwoFlags(QFlag(i | f)); }
94     Q_DECL_CONSTEXPR inline QUrlTwoFlags operator|(E2 f) const
95     { return QUrlTwoFlags(QFlag(i | f)); }
96     Q_DECL_CONSTEXPR inline QUrlTwoFlags operator^(QUrlTwoFlags f) const
97     { return QUrlTwoFlags(QFlag(i ^ f.i)); }
98     Q_DECL_CONSTEXPR inline QUrlTwoFlags operator^(E1 f) const
99     { return QUrlTwoFlags(QFlag(i ^ f)); }
100     Q_DECL_CONSTEXPR inline QUrlTwoFlags operator^(E2 f) const
101     { return QUrlTwoFlags(QFlag(i ^ f)); }
102     Q_DECL_CONSTEXPR inline QUrlTwoFlags operator&(int mask) const
103     { return QUrlTwoFlags(QFlag(i & mask)); }
104     Q_DECL_CONSTEXPR inline QUrlTwoFlags operator&(uint mask) const
105     { return QUrlTwoFlags(QFlag(i & mask)); }
106     Q_DECL_CONSTEXPR inline QUrlTwoFlags operator&(E1 f) const
107     { return QUrlTwoFlags(QFlag(i & f)); }
108     Q_DECL_CONSTEXPR inline QUrlTwoFlags operator&(E2 f) const
109     { return QUrlTwoFlags(QFlag(i & f)); }
110     Q_DECL_CONSTEXPR inline QUrlTwoFlags operator~() const
111     { return QUrlTwoFlags(QFlag(~i)); }
112 
testFlag(E1 f)113     Q_DECL_CONSTEXPR inline bool testFlag(E1 f) const { return (i & f) == f && (f != 0 || i == int(f)); }
testFlag(E2 f)114     Q_DECL_CONSTEXPR inline bool testFlag(E2 f) const { return (i & f) == f && (f != 0 || i == int(f)); }
115 };
116 
117 template<typename E1, typename E2>
118 class QTypeInfo<QUrlTwoFlags<E1, E2> > : public QTypeInfoMerger<QUrlTwoFlags<E1, E2>, E1, E2> {};
119 
120 class QUrl;
121 // qHash is a friend, but we can't use default arguments for friends (§8.3.6.4)
122 Q_CORE_EXPORT uint qHash(const QUrl &url, uint seed = 0) noexcept;
123 
124 class Q_CORE_EXPORT QUrl
125 {
126 public:
127     enum ParsingMode {
128         TolerantMode,
129         StrictMode,
130         DecodedMode
131     };
132 
133     // encoding / toString values
134     enum UrlFormattingOption {
135         None = 0x0,
136         RemoveScheme = 0x1,
137         RemovePassword = 0x2,
138         RemoveUserInfo = RemovePassword | 0x4,
139         RemovePort = 0x8,
140         RemoveAuthority = RemoveUserInfo | RemovePort | 0x10,
141         RemovePath = 0x20,
142         RemoveQuery = 0x40,
143         RemoveFragment = 0x80,
144         // 0x100 was a private code in Qt 4, keep unused for a while
145         PreferLocalFile = 0x200,
146         StripTrailingSlash = 0x400,
147         RemoveFilename = 0x800,
148         NormalizePathSegments = 0x1000
149     };
150 
151     enum ComponentFormattingOption {
152         PrettyDecoded = 0x000000,
153         EncodeSpaces = 0x100000,
154         EncodeUnicode = 0x200000,
155         EncodeDelimiters = 0x400000 | 0x800000,
156         EncodeReserved = 0x1000000,
157         DecodeReserved = 0x2000000,
158         // 0x4000000 used to indicate full-decode mode
159 
160         FullyEncoded = EncodeSpaces | EncodeUnicode | EncodeDelimiters | EncodeReserved,
161         FullyDecoded = FullyEncoded | DecodeReserved | 0x4000000
162     };
163     Q_DECLARE_FLAGS(ComponentFormattingOptions, ComponentFormattingOption)
164 #ifdef Q_QDOC
165 private:
166     // We need to let qdoc think that FormattingOptions is a normal QFlags, but
167     // it needs to be a QUrlTwoFlags for compiling default arguments of somme functions.
168     template<typename T> struct QFlags : QUrlTwoFlags<T, ComponentFormattingOption>
169     { using QUrlTwoFlags<T, ComponentFormattingOption>::QUrlTwoFlags; };
170 public:
171     Q_DECLARE_FLAGS(FormattingOptions, UrlFormattingOption)
172 #else
173     typedef QUrlTwoFlags<UrlFormattingOption, ComponentFormattingOption> FormattingOptions;
174 #endif
175 
176     QUrl();
177     QUrl(const QUrl &copy);
178     QUrl &operator =(const QUrl &copy);
179 #ifdef QT_NO_URL_CAST_FROM_STRING
180     explicit QUrl(const QString &url, ParsingMode mode = TolerantMode);
181 #else
182     QUrl(const QString &url, ParsingMode mode = TolerantMode);
183     QUrl &operator=(const QString &url);
184 #endif
QUrl(QUrl && other)185     QUrl(QUrl &&other) noexcept : d(other.d)
186     { other.d = nullptr; }
187     inline QUrl &operator=(QUrl &&other) noexcept
188     { qSwap(d, other.d); return *this; }
189     ~QUrl();
190 
swap(QUrl & other)191     inline void swap(QUrl &other) noexcept { qSwap(d, other.d); }
192 
193     void setUrl(const QString &url, ParsingMode mode = TolerantMode);
194     QString url(FormattingOptions options = FormattingOptions(PrettyDecoded)) const;
195     QString toString(FormattingOptions options = FormattingOptions(PrettyDecoded)) const;
196     QString toDisplayString(FormattingOptions options = FormattingOptions(PrettyDecoded)) const;
197     Q_REQUIRED_RESULT QUrl adjusted(FormattingOptions options) const;
198 
199     QByteArray toEncoded(FormattingOptions options = FullyEncoded) const;
200     static QUrl fromEncoded(const QByteArray &url, ParsingMode mode = TolerantMode);
201 
202     enum UserInputResolutionOption {
203         DefaultResolution,
204         AssumeLocalFile
205     };
206     Q_DECLARE_FLAGS(UserInputResolutionOptions, UserInputResolutionOption)
207 
208     static QUrl fromUserInput(const QString &userInput);
209     // ### Qt6 merge with fromUserInput(QString), by adding = QString()
210     static QUrl fromUserInput(const QString &userInput, const QString &workingDirectory,
211                               UserInputResolutionOptions options = DefaultResolution);
212 
213     bool isValid() const;
214     QString errorString() const;
215 
216     bool isEmpty() const;
217     void clear();
218 
219     void setScheme(const QString &scheme);
220     QString scheme() const;
221 
222     void setAuthority(const QString &authority, ParsingMode mode = TolerantMode);
223     QString authority(ComponentFormattingOptions options = PrettyDecoded) const;
224 
225     void setUserInfo(const QString &userInfo, ParsingMode mode = TolerantMode);
226     QString userInfo(ComponentFormattingOptions options = PrettyDecoded) const;
227 
228     void setUserName(const QString &userName, ParsingMode mode = DecodedMode);
229     QString userName(ComponentFormattingOptions options = FullyDecoded) const;
230 
231     void setPassword(const QString &password, ParsingMode mode = DecodedMode);
232     QString password(ComponentFormattingOptions = FullyDecoded) const;
233 
234     void setHost(const QString &host, ParsingMode mode = DecodedMode);
235     QString host(ComponentFormattingOptions = FullyDecoded) const;
236 #if QT_DEPRECATED_SINCE(5, 15)
237 #if QT_CONFIG(topleveldomain)
238     QT_DEPRECATED QString topLevelDomain(ComponentFormattingOptions options = FullyDecoded) const;
239 #endif
240 #endif // QT_DEPRECATED_SINCE(5, 15)
241 
242     void setPort(int port);
243     int port(int defaultPort = -1) const;
244 
245     void setPath(const QString &path, ParsingMode mode = DecodedMode);
246     QString path(ComponentFormattingOptions options = FullyDecoded) const;
247     QString fileName(ComponentFormattingOptions options = FullyDecoded) const;
248 
249     bool hasQuery() const;
250     void setQuery(const QString &query, ParsingMode mode = TolerantMode);
251     void setQuery(const QUrlQuery &query);
252     QString query(ComponentFormattingOptions = PrettyDecoded) const;
253 
254     bool hasFragment() const;
255     QString fragment(ComponentFormattingOptions options = PrettyDecoded) const;
256     void setFragment(const QString &fragment, ParsingMode mode = TolerantMode);
257 
258     Q_REQUIRED_RESULT QUrl resolved(const QUrl &relative) const;
259 
260     bool isRelative() const;
261     bool isParentOf(const QUrl &url) const;
262 
263     bool isLocalFile() const;
264     static QUrl fromLocalFile(const QString &localfile);
265     QString toLocalFile() const;
266 
267     void detach();
268     bool isDetached() const;
269 
270     bool operator <(const QUrl &url) const;
271     bool operator ==(const QUrl &url) const;
272     bool operator !=(const QUrl &url) const;
273 
274     bool matches(const QUrl &url, FormattingOptions options) const;
275 
276     static QString fromPercentEncoding(const QByteArray &);
277     static QByteArray toPercentEncoding(const QString &,
278                                         const QByteArray &exclude = QByteArray(),
279                                         const QByteArray &include = QByteArray());
280 #if defined(Q_OS_DARWIN) || defined(Q_QDOC)
281     static QUrl fromCFURL(CFURLRef url);
282     CFURLRef toCFURL() const Q_DECL_CF_RETURNS_RETAINED;
283     static QUrl fromNSURL(const NSURL *url);
284     NSURL *toNSURL() const Q_DECL_NS_RETURNS_AUTORELEASED;
285 #endif
286 
287 #if QT_DEPRECATED_SINCE(5,0)
fromPunycode(const QByteArray & punycode)288     QT_DEPRECATED static QString fromPunycode(const QByteArray &punycode)
289     { return fromAce(punycode); }
toPunycode(const QString & string)290     QT_DEPRECATED static QByteArray toPunycode(const QString &string)
291     { return toAce(string); }
292 
293     QT_DEPRECATED inline void setQueryItems(const QList<QPair<QString, QString> > &qry);
294     QT_DEPRECATED inline void addQueryItem(const QString &key, const QString &value);
295     QT_DEPRECATED inline QList<QPair<QString, QString> > queryItems() const;
296     QT_DEPRECATED inline bool hasQueryItem(const QString &key) const;
297     QT_DEPRECATED inline QString queryItemValue(const QString &key) const;
298     QT_DEPRECATED inline QStringList allQueryItemValues(const QString &key) const;
299     QT_DEPRECATED inline void removeQueryItem(const QString &key);
300     QT_DEPRECATED inline void removeAllQueryItems(const QString &key);
301 
302     QT_DEPRECATED inline void setEncodedQueryItems(const QList<QPair<QByteArray, QByteArray> > &query);
303     QT_DEPRECATED inline void addEncodedQueryItem(const QByteArray &key, const QByteArray &value);
304     QT_DEPRECATED inline QList<QPair<QByteArray, QByteArray> > encodedQueryItems() const;
305     QT_DEPRECATED inline bool hasEncodedQueryItem(const QByteArray &key) const;
306     QT_DEPRECATED inline QByteArray encodedQueryItemValue(const QByteArray &key) const;
307     QT_DEPRECATED inline QList<QByteArray> allEncodedQueryItemValues(const QByteArray &key) const;
308     QT_DEPRECATED inline void removeEncodedQueryItem(const QByteArray &key);
309     QT_DEPRECATED inline void removeAllEncodedQueryItems(const QByteArray &key);
310 
311     QT_DEPRECATED void setEncodedUrl(const QByteArray &u, ParsingMode mode = TolerantMode)
312     { setUrl(fromEncodedComponent_helper(u), mode); }
313 
encodedUserName()314     QT_DEPRECATED QByteArray encodedUserName() const
315     { return userName(FullyEncoded).toLatin1(); }
setEncodedUserName(const QByteArray & value)316     QT_DEPRECATED void setEncodedUserName(const QByteArray &value)
317     { setUserName(fromEncodedComponent_helper(value)); }
318 
encodedPassword()319     QT_DEPRECATED QByteArray encodedPassword() const
320     { return password(FullyEncoded).toLatin1(); }
setEncodedPassword(const QByteArray & value)321     QT_DEPRECATED void setEncodedPassword(const QByteArray &value)
322     { setPassword(fromEncodedComponent_helper(value)); }
323 
encodedHost()324     QT_DEPRECATED QByteArray encodedHost() const
325     { return host(FullyEncoded).toLatin1(); }
setEncodedHost(const QByteArray & value)326     QT_DEPRECATED void setEncodedHost(const QByteArray &value)
327     { setHost(fromEncodedComponent_helper(value)); }
328 
encodedPath()329     QT_DEPRECATED QByteArray encodedPath() const
330     { return path(FullyEncoded).toLatin1(); }
setEncodedPath(const QByteArray & value)331     QT_DEPRECATED void setEncodedPath(const QByteArray &value)
332     { setPath(fromEncodedComponent_helper(value)); }
333 
encodedQuery()334     QT_DEPRECATED QByteArray encodedQuery() const
335     { return toLatin1_helper(query(FullyEncoded)); }
setEncodedQuery(const QByteArray & value)336     QT_DEPRECATED void setEncodedQuery(const QByteArray &value)
337     { setQuery(fromEncodedComponent_helper(value)); }
338 
encodedFragment()339     QT_DEPRECATED QByteArray encodedFragment() const
340     { return toLatin1_helper(fragment(FullyEncoded)); }
setEncodedFragment(const QByteArray & value)341     QT_DEPRECATED void setEncodedFragment(const QByteArray &value)
342     { setFragment(fromEncodedComponent_helper(value)); }
343 
344 private:
345     // helper function for the encodedQuery and encodedFragment functions
toLatin1_helper(const QString & string)346     static QByteArray toLatin1_helper(const QString &string)
347     {
348         if (string.isEmpty())
349             return string.isNull() ? QByteArray() : QByteArray("");
350         return string.toLatin1();
351     }
352 #endif
353 private:
354     static QString fromEncodedComponent_helper(const QByteArray &ba);
355 
356 public:
357     static QString fromAce(const QByteArray &);
358     static QByteArray toAce(const QString &);
359     static QStringList idnWhitelist();
360     static QStringList toStringList(const QList<QUrl> &uris, FormattingOptions options = FormattingOptions(PrettyDecoded));
361     static QList<QUrl> fromStringList(const QStringList &uris, ParsingMode mode = TolerantMode);
362 
363     static void setIdnWhitelist(const QStringList &);
364     friend Q_CORE_EXPORT uint qHash(const QUrl &url, uint seed) noexcept;
365 
366 private:
367     QUrlPrivate *d;
368     friend class QUrlQuery;
369 
370 public:
371     typedef QUrlPrivate * DataPtr;
data_ptr()372     inline DataPtr &data_ptr() { return d; }
373 };
374 
375 Q_DECLARE_SHARED(QUrl)
376 Q_DECLARE_OPERATORS_FOR_FLAGS(QUrl::ComponentFormattingOptions)
377 //Q_DECLARE_OPERATORS_FOR_FLAGS(QUrl::FormattingOptions)
378 
379 #ifndef Q_QDOC
380 Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::UrlFormattingOption f1, QUrl::UrlFormattingOption f2)
381 { return QUrl::FormattingOptions(f1) | f2; }
382 Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::UrlFormattingOption f1, QUrl::FormattingOptions f2)
383 { return f2 | f1; }
384 Q_DECL_CONSTEXPR inline QIncompatibleFlag operator|(QUrl::UrlFormattingOption f1, int f2)
385 { return QIncompatibleFlag(int(f1) | f2); }
386 
387 // add operators for OR'ing the two types of flags
388 inline QUrl::FormattingOptions &operator|=(QUrl::FormattingOptions &i, QUrl::ComponentFormattingOptions f)
389 { i |= QUrl::UrlFormattingOption(int(f)); return i; }
390 Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::UrlFormattingOption i, QUrl::ComponentFormattingOption f)
391 { return i | QUrl::UrlFormattingOption(int(f)); }
392 Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::UrlFormattingOption i, QUrl::ComponentFormattingOptions f)
393 { return i | QUrl::UrlFormattingOption(int(f)); }
394 Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::ComponentFormattingOption f, QUrl::UrlFormattingOption i)
395 { return i | QUrl::UrlFormattingOption(int(f)); }
396 Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::ComponentFormattingOptions f, QUrl::UrlFormattingOption i)
397 { return i | QUrl::UrlFormattingOption(int(f)); }
398 Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::FormattingOptions i, QUrl::ComponentFormattingOptions f)
399 { return i | QUrl::UrlFormattingOption(int(f)); }
400 Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::ComponentFormattingOption f, QUrl::FormattingOptions i)
401 { return i | QUrl::UrlFormattingOption(int(f)); }
402 Q_DECL_CONSTEXPR inline QUrl::FormattingOptions operator|(QUrl::ComponentFormattingOptions f, QUrl::FormattingOptions i)
403 { return i | QUrl::UrlFormattingOption(int(f)); }
404 
405 //inline QUrl::UrlFormattingOption &operator=(const QUrl::UrlFormattingOption &i, QUrl::ComponentFormattingOptions f)
406 //{ i = int(f); f; }
407 #endif // Q_QDOC
408 
409 #ifndef QT_NO_DATASTREAM
410 Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QUrl &);
411 Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QUrl &);
412 #endif
413 
414 #ifndef QT_NO_DEBUG_STREAM
415 Q_CORE_EXPORT QDebug operator<<(QDebug, const QUrl &);
416 #endif
417 
418 QT_END_NAMESPACE
419 
420 #if QT_DEPRECATED_SINCE(5,0)
421 # include <QtCore/qurlquery.h>
422 #endif
423 
424 #endif // QURL_H
425