File indexing completed on 2024-04-14 03:53:19

0001 /*
0002     SPDX-FileCopyrightText: 2015 Gregor Mi <codestruct@posteo.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #ifndef URLUTIL_P_H
0008 #define URLUTIL_P_H
0009 
0010 #include <QUrl>
0011 
0012 namespace KIO
0013 {
0014 namespace UrlUtil
0015 {
0016 /**
0017  * Given that @p lastUrl is a child of @p currentUrl
0018  * or put in other words:
0019  * @p currentUrl is a parent in the hierarchy of @p lastUrl,
0020  * then an URL 'currentUrl'/'childitem' is returned where
0021  * 'childitem' is the first item in the hierarchy down to
0022  * @p lastUrl. An example will illustrate this:
0023 
0024    \verbatim
0025    lastUrl    : "/home/test/data/documents/muh/"
0026    currentUrl : "/home/test/"
0027    returns    : "/home/test/data/"
0028    \endverbatim
0029 
0030  * In case @p currentUrl is a child of @p lastUrl, an invalid
0031  * URL is returned:
0032 
0033    \verbatim
0034    lastUrl    : "/home/"
0035    currentUrl : "/home/test/"
0036    returns    : "" (invalid url)
0037    \endverbatim
0038 
0039  * In case both URLs are equal, an invalid URL is returned:
0040 
0041    \verbatim
0042    lastUrl    : "/home/test/"
0043    currentUrl : "/home/test/"
0044    returns    : "" (invalid url)
0045    \endverbatim
0046  */
0047 static QUrl firstChildUrl(const QUrl &lastUrl, const QUrl &currentUrl)
0048 {
0049     const QUrl adjustedLastUrl = lastUrl.adjusted(QUrl::StripTrailingSlash);
0050     const QUrl adjustedCurrentUrl = currentUrl.adjusted(QUrl::StripTrailingSlash);
0051     if (!adjustedCurrentUrl.isParentOf(adjustedLastUrl)) {
0052         return QUrl();
0053     }
0054 
0055     const QString childPath = adjustedLastUrl.path();
0056     const QString parentPath = adjustedCurrentUrl.path();
0057     // if the parent path is root "/"
0058     // one char more is a valid path, otherwise "/" and another char are needed.
0059     const int minIndex = (parentPath == QLatin1String("/")) ? 1 : 2;
0060 
0061     // e.g. this would just be ok:
0062     // childPath  = /a        len=2
0063     // parentPath = /         len=1
0064     // childPath  = /home/a   len=7
0065     // parentPath = /home     len=5
0066 
0067     if (childPath.length() < (parentPath.length() + minIndex)) {
0068         return QUrl();
0069     }
0070 
0071     const int idx2 = childPath.indexOf(QLatin1Char('/'), parentPath.length() + minIndex);
0072     // parentPath = /home
0073     // childPath  = /home/a
0074     //                 idx  = -1
0075     //              => len2 =  7
0076     //
0077     // childPath = /homa/a/b
0078     //                 idx  = 7
0079     //              => len2 = 7
0080     const int len2 = (idx2 < 0) ? childPath.length() : idx2;
0081 
0082     const QString path3 = childPath.left(len2);
0083 
0084     QUrl res = lastUrl; // keeps the scheme (e.g. file://)
0085     res.setPath(path3);
0086     return res;
0087 }
0088 }
0089 }
0090 
0091 #endif