From c728783dc20cc2d4667affdefa19a4162a2ec9ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= Date: Wed, 30 Mar 2011 14:27:00 +0200 Subject: QTemporaryFile: Locate placeholder before re-encoding Previously, the placeholder was identified in unicode-based QString, and the offset was assumed to be correct after conversion to the local 8-bit encoding. This assumption is obviously wrong for variable-sized encoding, such as utf-8. With this change, the placeholder is still identified in the original QString, but conversion to 8-bit encoding is done in a step-wise fashion and offsets recomputed. This allows us to drop the intermediary argument verification in _gettemp. Task-number: QTBUG-4796 Reviewed-by: Robin Burchell --- src/corelib/io/qtemporaryfile.cpp | 71 ++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index 92065cb..34c01a6 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -95,31 +95,6 @@ QT_BEGIN_NAMESPACE * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -static int createFileFromTemplate(char *const path, - char *const placeholderStart, char *const placeholderEnd); - -static int _gettemp(char *path, int slen) -{ - char *trv, *suffp; - - for (trv = path; *trv; ++trv) - ; - trv -= slen; - suffp = trv; - --trv; - if (trv < path) { - errno = EINVAL; - return -1; - } - - while (trv >= path && *trv == 'X') - --trv; - - char *const placeholderStart = trv + 1; - char *const placeholderEnd = suffp; - - return createFileFromTemplate(path, placeholderStart, placeholderEnd); -} /*! \internal @@ -274,15 +249,49 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) return QFSFileEngine::open(openMode); QString qfilename = d->fileEntry.filePath(); - if(!qfilename.contains(QLatin1String("XXXXXX"))) - qfilename += QLatin1String(".XXXXXX"); - int suffixLength = qfilename.length() - (qfilename.lastIndexOf(QLatin1String("XXXXXX"), -1, Qt::CaseSensitive) + 6); - QByteArray filename = qfilename.toLocal8Bit(); + // Find placeholder string. + size_t phPos = size_t(qfilename.length()); + size_t phLength = 0; + + while (phPos != 0) { + --phPos; + + if (qfilename[phPos] == QLatin1Char('X')) { + ++phLength; + continue; + } + + if (qfilename[phPos] == QLatin1Char('/') + || phLength >= 6) { + ++phPos; + break; + } + + phLength = 0; + } + + QStringRef prefix, suffix; + if (phLength < 6) { + qfilename += QLatin1Char('.'); + prefix = QStringRef(&qfilename); + phLength = 6; + } else { + prefix = qfilename.leftRef(phPos); + suffix = qfilename.midRef(phPos + phLength); + } + + QByteArray filename = prefix.toLocal8Bit(); + phPos = filename.length(); + if (suffix.isEmpty()) + filename.resize(phPos + phLength); + else + filename.insert(phPos + phLength, suffix.toLocal8Bit()); + char *path = filename.data(); #ifndef Q_OS_WIN - int fd = _gettemp(path, suffixLength); + int fd = createFileFromTemplate(path, path + phPos, path + phPos + phLength); if (fd != -1) { // First open the fd as an external file descriptor to // initialize the engine properly. @@ -302,7 +311,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode) setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError, qt_error_string(errno)); return false; #else - if (_gettemp(path, suffixLength) == -1) { + if (createFileFromTemplate(path, path + phPos, path + phPos + phLength) == -1) { return false; } -- cgit v0.12