Fix QTemporaryFile regressions and new found issues

With this change, the file template is always processed in original
QString format. Trying to generate native paths before adding a missing
placeholder mask could change the meaning of templates, such as "." and
"..", which are now tested to mean "..XXXXXX" and "...XXXXXX",
respectively.

After ensuring the template includes a placeholder mask, the path is
converted to a native *absolute* file path and the mask is sought for
again. On Windows, native paths were already absolute. On Symbian, we'd
need at least a clean path, as "." and ",," are not natively understood.

There is a requirement that the placeholder mask /XXXXXX+/ makes it
through this conversion unaltered, which relaxes prior requirements on
*nix platforms. On Windows and Symbian the conversion is under Qt's
control and not user-configurable.

Reviewed-by: Shane Kearns
(cherry picked from commit 401722ef9e6fe79bd41f9d5f79668f5c4997c8e6)

Conflicts:

	tests/auto/qtemporaryfile/tst_qtemporaryfile.cpp

Change-Id: Iac823881c865adf0931dc4f429c6c1ef135eeb56
Reviewed-by: João Abecasis <joao.abecasis@nokia.com>
This commit is contained in:
João Abecasis 2011-08-16 17:53:41 +02:00 committed by Qt by Nokia
parent c9fde0d590
commit fd61059d35
2 changed files with 36 additions and 50 deletions

View File

@ -44,10 +44,10 @@
#ifndef QT_NO_TEMPORARYFILE
#include "qplatformdefs.h"
#include "qstringbuilder.h"
#include "private/qfile_p.h"
#include "private/qfsfileengine_p.h"
#include "private/qsystemerror_p.h"
#include "private/qfilesystemengine_p.h"
#if defined(Q_OS_SYMBIAN)
#include "private/qcore_symbian_p.h"
@ -102,38 +102,6 @@ typedef char Latin1Char;
typedef int NativeFileHandle;
#endif
struct Placeholder
{
Placeholder(int size)
: size_(size)
{
}
int size() const
{
return size_;
}
private:
int size_;
};
template <>
struct QConcatenable<Placeholder>
{
typedef Placeholder type;
typedef QByteArray ConvertTo;
enum { ExactSize = true };
static int size(const Placeholder &p) { return p.size(); }
template <class CharT>
static inline void appendTo(const Placeholder &p, CharT *&out)
{
// Uninitialized
out += p.size();
}
};
/*
* Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved.
@ -366,43 +334,59 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
if (!filePathIsTemplate)
return QFSFileEngine::open(openMode);
const QFileSystemEntry::NativePath qfilename = d->fileEntry.nativeFilePath();
QString qfilename = d->fileEntry.filePath();
// Find placeholder string.
// Ensure there is a placeholder mask
uint phPos = qfilename.length();
uint phLength = 0;
while (phPos != 0) {
--phPos;
if (qfilename[phPos] == Latin1Char('X')) {
if (qfilename[phPos] == QLatin1Char('X')) {
++phLength;
continue;
}
if (phLength >= 6
|| qfilename[phPos] ==
#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
'/'
#else
QLatin1Char('\\')
#endif
) {
|| qfilename[phPos] == QLatin1Char('/')) {
++phPos;
break;
}
// start over
phLength = 0;
}
QFileSystemEntry::NativePath filename;
if (phLength < 6)
qfilename.append(QLatin1String(".XXXXXX"));
if (phLength < 6) {
phPos = qfilename.length() + 1; // Account for added dot in prefix
phLength = 6;
filename = qfilename % Latin1Char('.') % Placeholder(phLength);
} else
filename = qfilename;
// "Nativify" :-)
QFileSystemEntry::NativePath filename = QFileSystemEngine::absoluteName(
QFileSystemEntry(qfilename, QFileSystemEntry::FromInternalPath()))
.nativeFilePath();
// Find mask in native path
phPos = filename.length();
phLength = 0;
while (phPos != 0) {
--phPos;
if (filename[phPos] == Latin1Char('X')) {
++phLength;
continue;
}
if (phLength >= 6) {
++phPos;
break;
}
// start over
phLength = 0;
}
Q_ASSERT(phLength >= 6);
QSystemError error;
#if defined(Q_OS_WIN)

View File

@ -647,6 +647,8 @@ void tst_QTemporaryFile::QTBUG_4796_data()
QString unicode = QString::fromUtf8("\xc3\xa5\xc3\xa6\xc3\xb8");
QTest::newRow("<empty>") << QString() << QString() << true;
QTest::newRow(".") << QString(".") << QString() << true;
QTest::newRow("..") << QString("..") << QString() << true;
QTest::newRow("blaXXXXXX") << QString("bla") << QString() << true;
QTest::newRow("XXXXXXbla") << QString() << QString("bla") << true;
QTest::newRow("does-not-exist/qt_temp.XXXXXX") << QString("does-not-exist/qt_temp") << QString() << false;