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