File indexing completed on 2024-12-22 04:35:00

0001 /*
0002     SPDX-FileCopyrightText: 2009 Nokia Corporation and /or its subsidiary(-ies).
0003     Contact: Qt Software Information (qt-info@nokia.com)
0004 
0005     This file is part of the QtCore module of the Qt Toolkit.
0006 
0007     $QT_BEGIN_LICENSE:LGPL$
0008     Commercial Usage
0009     Licensees holding valid Qt Commercial licenses may use this file in
0010     accordance with the Qt Commercial License Agreement provided with the
0011     Software or, alternatively, in accordance with the terms contained in
0012     a written agreement between you and Nokia.
0013 
0014     GNU Lesser General Public License Usage
0015     Alternatively, this file may be used under the terms of the GNU Lesser
0016     General Public License version 2.1 as published by the Free Software
0017     Foundation and appearing in the file LICENSE.LGPL included in the
0018     packaging of this file.  Please review the following information to
0019     ensure the GNU Lesser General Public License version 2.1 requirements
0020     will be met: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
0021 
0022     In addition, as a special exception, Nokia gives you certain
0023     additional rights. These rights are described in the Nokia Qt LGPL
0024     Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
0025     package.
0026 
0027     GNU General Public License Usage
0028     Alternatively, this file may be used under the terms of the GNU
0029     General Public License version 3.0 as published by the Free Software
0030     Foundation and appearing in the file LICENSE.GPL included in the
0031     packaging of this file.  Please review the following information to
0032     ensure the GNU General Public License version 3.0 requirements will be
0033     met: https://www.gnu.org/licenses/gpl-3.0.html.
0034 
0035     If you are unsure which license is appropriate for your use, please
0036     contact the sales department at qt-sales@nokia.com.
0037     $QT_END_LICENSE$
0038 
0039 */
0040 
0041 #include "qdebug.h"
0042 #include "qfsfileengine_iterator_p.h"
0043 #include "qfsfileengine_p.h"
0044 #include "qplatformdefs.h"
0045 
0046 #include <qvariant.h>
0047 #include <QMutex>
0048 #include <private/qmutexpool_p.h>
0049 
0050 QT_BEGIN_NAMESPACE
0051 
0052 class QFSFileEngineIteratorPlatformSpecificData
0053 {
0054 public:
0055     inline QFSFileEngineIteratorPlatformSpecificData()
0056         : uncShareIndex(-1), findFileHandle(INVALID_HANDLE_VALUE),
0057           done(false), uncFallback(false)
0058     { }
0059 
0060     QFSFileEngineIterator *it;
0061 
0062     QStringList uncShares;
0063     int uncShareIndex;
0064 
0065     HANDLE findFileHandle;
0066     WIN32_FIND_DATA findData;
0067     bool done;
0068     bool uncFallback;
0069 
0070     void advance();
0071     void saveCurrentFileName();
0072 };
0073 
0074 void QFSFileEngineIteratorPlatformSpecificData::saveCurrentFileName()
0075 {
0076     if (uncFallback) {
0077         // Windows share / UNC path
0078         it->currentEntry = uncShares.at(uncShareIndex - 1);
0079     } else {
0080         // Local directory
0081         QT_WA({
0082             it->currentEntry = QString::fromUtf16((unsigned short *)findData.cFileName);
0083         } , {
0084             it->currentEntry = QString::fromLocal8Bit((const char *)findData.cFileName);
0085         });
0086     }
0087 }
0088 
0089 void QFSFileEngineIterator::advance()
0090 {
0091     platform->saveCurrentFileName();
0092 
0093     if (platform->done)
0094         return;
0095 
0096     if (platform->uncFallback) {
0097         ++platform->uncShareIndex;
0098     } else if (platform->findFileHandle != INVALID_HANDLE_VALUE) {
0099         QT_WA({
0100             if (!FindNextFile(platform->findFileHandle, &platform->findData)) {
0101                 platform->done = true;        
0102                 FindClose(platform->findFileHandle);
0103             }
0104         } , {
0105             if (!FindNextFileA(platform->findFileHandle, (WIN32_FIND_DATAA *)&platform->findData)) {
0106                 platform->done = true;
0107                 FindClose(platform->findFileHandle);
0108             }
0109         });
0110     }
0111 }
0112 
0113 void QFSFileEngineIterator::newPlatformSpecifics()
0114 {
0115     platform = new QFSFileEngineIteratorPlatformSpecificData;
0116     platform->it = this;
0117 }
0118 
0119 void QFSFileEngineIterator::deletePlatformSpecifics()
0120 {
0121     delete platform;
0122     platform = 0;
0123 }
0124 
0125 bool QFSFileEngineIterator::hasNext() const
0126 {
0127     if (platform->done)
0128         return false;
0129     
0130     if (platform->uncFallback)
0131         return platform->uncShareIndex > 0 && platform->uncShareIndex <= platform->uncShares.size();
0132     
0133     if (platform->findFileHandle == INVALID_HANDLE_VALUE) {
0134         QString path = this->path();
0135         // Local directory
0136         if (path.endsWith(QLatin1String(".lnk")))
0137             path = QFileInfo(path).readLink();
0138 
0139         if (!path.endsWith(QLatin1Char('/')))
0140             path.append(QLatin1Char('/'));
0141         path.append(QLatin1String("*.*"));
0142 
0143         QT_WA({
0144             QString fileName = QFSFileEnginePrivate::longFileName(path);
0145             platform->findFileHandle = FindFirstFileW((TCHAR *)fileName.utf16(),
0146                                                       &platform->findData);
0147         }, {
0148             // Cast is safe, since char is at end of WIN32_FIND_DATA
0149             platform->findFileHandle = FindFirstFileA(QFSFileEnginePrivate::win95Name(path),
0150                                                       (WIN32_FIND_DATAA*)&platform->findData);
0151         });
0152 
0153         if (platform->findFileHandle == INVALID_HANDLE_VALUE) {
0154             if (path.startsWith(QLatin1String("//"))) {
0155                 path = this->path();
0156                 // UNC
0157                 QStringList parts = QDir::toNativeSeparators(path).split(QLatin1Char('\\'), QString::SkipEmptyParts);
0158 
0159                 if (parts.count() == 1 && QFSFileEnginePrivate::uncListSharesOnServer(QLatin1String("\\\\") + parts.at(0),
0160                                                                                       &platform->uncShares)) {
0161                     if (platform->uncShares.isEmpty()) {
0162                         platform->done = true;
0163                     } else {
0164                         platform->uncShareIndex = 1;
0165                     }
0166                     platform->uncFallback = true;
0167                 } else {
0168                     platform->done = true;
0169                 }
0170             } else {
0171                 platform->done = true;        
0172             }
0173         }
0174 
0175         if (!platform->done && (!platform->uncFallback || !platform->uncShares.isEmpty()))
0176             platform->saveCurrentFileName();
0177     }
0178 
0179     return !platform->done;
0180 }
0181 
0182 QT_END_NAMESPACE