1 /*
2 SPDX-FileCopyrightText: 2009 Nokia Corporation and /or its subsidiary(-ies).
3 Contact: Qt Software Information (qt-info@nokia.com)
4
5 This file is part of the QtCore module of the Qt Toolkit.
6
7 $QT_BEGIN_LICENSE:LGPL$
8 Commercial Usage
9 Licensees holding valid Qt Commercial licenses may use this file in
10 accordance with the Qt Commercial License Agreement provided with the
11 Software or, alternatively, in accordance with the terms contained in
12 a written agreement between you and Nokia.
13
14 GNU Lesser General Public License Usage
15 Alternatively, this file may be used under the terms of the GNU Lesser
16 General Public License version 2.1 as published by the Free Software
17 Foundation and appearing in the file LICENSE.LGPL included in the
18 packaging of this file. Please review the following information to
19 ensure the GNU Lesser General Public License version 2.1 requirements
20 will be met: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
21
22 In addition, as a special exception, Nokia gives you certain
23 additional rights. These rights are described in the Nokia Qt LGPL
24 Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
25 package.
26
27 GNU General Public License Usage
28 Alternatively, this file may be used under the terms of the GNU
29 General Public License version 3.0 as published by the Free Software
30 Foundation and appearing in the file LICENSE.GPL included in the
31 packaging of this file. Please review the following information to
32 ensure the GNU General Public License version 3.0 requirements will be
33 met: https://www.gnu.org/licenses/gpl-3.0.html.
34
35 If you are unsure which license is appropriate for your use, please
36 contact the sales department at qt-sales@nokia.com.
37 $QT_END_LICENSE$
38
39 */
40
41 #include "qdebug.h"
42 #include "qfsfileengine_iterator_p.h"
43 #include "qfsfileengine_p.h"
44 #include "qplatformdefs.h"
45
46 #include <qvariant.h>
47 #include <QMutex>
48 #include <private/qmutexpool_p.h>
49
50 QT_BEGIN_NAMESPACE
51
52 class QFSFileEngineIteratorPlatformSpecificData
53 {
54 public:
QFSFileEngineIteratorPlatformSpecificData()55 inline QFSFileEngineIteratorPlatformSpecificData()
56 : uncShareIndex(-1), findFileHandle(INVALID_HANDLE_VALUE),
57 done(false), uncFallback(false)
58 { }
59
60 QFSFileEngineIterator *it;
61
62 QStringList uncShares;
63 int uncShareIndex;
64
65 HANDLE findFileHandle;
66 WIN32_FIND_DATA findData;
67 bool done;
68 bool uncFallback;
69
70 void advance();
71 void saveCurrentFileName();
72 };
73
saveCurrentFileName()74 void QFSFileEngineIteratorPlatformSpecificData::saveCurrentFileName()
75 {
76 if (uncFallback) {
77 // Windows share / UNC path
78 it->currentEntry = uncShares.at(uncShareIndex - 1);
79 } else {
80 // Local directory
81 QT_WA({
82 it->currentEntry = QString::fromUtf16((unsigned short *)findData.cFileName);
83 } , {
84 it->currentEntry = QString::fromLocal8Bit((const char *)findData.cFileName);
85 });
86 }
87 }
88
advance()89 void QFSFileEngineIterator::advance()
90 {
91 platform->saveCurrentFileName();
92
93 if (platform->done)
94 return;
95
96 if (platform->uncFallback) {
97 ++platform->uncShareIndex;
98 } else if (platform->findFileHandle != INVALID_HANDLE_VALUE) {
99 QT_WA({
100 if (!FindNextFile(platform->findFileHandle, &platform->findData)) {
101 platform->done = true;
102 FindClose(platform->findFileHandle);
103 }
104 } , {
105 if (!FindNextFileA(platform->findFileHandle, (WIN32_FIND_DATAA *)&platform->findData)) {
106 platform->done = true;
107 FindClose(platform->findFileHandle);
108 }
109 });
110 }
111 }
112
newPlatformSpecifics()113 void QFSFileEngineIterator::newPlatformSpecifics()
114 {
115 platform = new QFSFileEngineIteratorPlatformSpecificData;
116 platform->it = this;
117 }
118
deletePlatformSpecifics()119 void QFSFileEngineIterator::deletePlatformSpecifics()
120 {
121 delete platform;
122 platform = 0;
123 }
124
hasNext() const125 bool QFSFileEngineIterator::hasNext() const
126 {
127 if (platform->done)
128 return false;
129
130 if (platform->uncFallback)
131 return platform->uncShareIndex > 0 && platform->uncShareIndex <= platform->uncShares.size();
132
133 if (platform->findFileHandle == INVALID_HANDLE_VALUE) {
134 QString path = this->path();
135 // Local directory
136 if (path.endsWith(QLatin1String(".lnk")))
137 path = QFileInfo(path).readLink();
138
139 if (!path.endsWith(QLatin1Char('/')))
140 path.append(QLatin1Char('/'));
141 path.append(QLatin1String("*.*"));
142
143 QT_WA({
144 QString fileName = QFSFileEnginePrivate::longFileName(path);
145 platform->findFileHandle = FindFirstFileW((TCHAR *)fileName.utf16(),
146 &platform->findData);
147 }, {
148 // Cast is safe, since char is at end of WIN32_FIND_DATA
149 platform->findFileHandle = FindFirstFileA(QFSFileEnginePrivate::win95Name(path),
150 (WIN32_FIND_DATAA*)&platform->findData);
151 });
152
153 if (platform->findFileHandle == INVALID_HANDLE_VALUE) {
154 if (path.startsWith(QLatin1String("//"))) {
155 path = this->path();
156 // UNC
157 QStringList parts = QDir::toNativeSeparators(path).split(QLatin1Char('\\'), QString::SkipEmptyParts);
158
159 if (parts.count() == 1 && QFSFileEnginePrivate::uncListSharesOnServer(QLatin1String("\\\\") + parts.at(0),
160 &platform->uncShares)) {
161 if (platform->uncShares.isEmpty()) {
162 platform->done = true;
163 } else {
164 platform->uncShareIndex = 1;
165 }
166 platform->uncFallback = true;
167 } else {
168 platform->done = true;
169 }
170 } else {
171 platform->done = true;
172 }
173 }
174
175 if (!platform->done && (!platform->uncFallback || !platform->uncShares.isEmpty()))
176 platform->saveCurrentFileName();
177 }
178
179 return !platform->done;
180 }
181
182 QT_END_NAMESPACE
183