From f571457523d2986687017a8469ce4173fe46ec99 Mon Sep 17 00:00:00 2001
From: goro <qtc-committer@nokia.com>
Date: Fri, 16 Jan 2009 13:31:00 +0100
Subject: [PATCH] Check in qtlibspatcher from change 321515 plus compile fixes

---
 src/tools/qtlibspatcher/binpatch.cpp          | 210 +++++++++++++++++
 src/tools/qtlibspatcher/binpatch.h            |  74 ++++++
 src/tools/qtlibspatcher/qtlibspatcher.pro     |  15 ++
 src/tools/qtlibspatcher/qtlibspatchermain.cpp | 219 ++++++++++++++++++
 4 files changed, 518 insertions(+)
 create mode 100644 src/tools/qtlibspatcher/binpatch.cpp
 create mode 100644 src/tools/qtlibspatcher/binpatch.h
 create mode 100644 src/tools/qtlibspatcher/qtlibspatcher.pro
 create mode 100644 src/tools/qtlibspatcher/qtlibspatchermain.cpp

diff --git a/src/tools/qtlibspatcher/binpatch.cpp b/src/tools/qtlibspatcher/binpatch.cpp
new file mode 100644
index 00000000000..e2fd4cc2f2e
--- /dev/null
+++ b/src/tools/qtlibspatcher/binpatch.cpp
@@ -0,0 +1,210 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact:  Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file.  Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+
+#include <cstdio>
+#include <cstring>
+#include <locale>
+
+#include "binpatch.h"
+
+// returns positive value if it finds a null termination inside the buffer
+long BinPatch::getBufferStringLength(char *data, char *end)
+{
+    long size = 0;
+    while (data < end) {
+        if (*data == '\0')
+            return size;
+        ++data;
+        ++size;
+    }
+
+    return -1;
+}
+
+// returns true if data ends with one of the tokens. (Sep. with ;)
+bool BinPatch::endsWithTokens(const char *data)
+{
+    if(strlen(endTokens) > 0) {
+        char endstmp[1024];
+        ulong tlen = ulong(strlen(data));
+
+        if(strlen(endTokens) >= sizeof(endstmp))
+            return false;
+
+        strcpy(endstmp, endTokens);
+
+        char *token = strtok(endstmp, ";");
+
+        while(token != NULL) {
+            // check if it ends with the token
+            if ((tlen >= strlen(token)) 
+                && (strcasecmp((data+tlen)-strlen(token), token) == 0))
+                return true;
+            token = strtok(NULL, ";");
+        }
+    } else {
+        return true; //true if no tokens
+    }
+
+    return false; //no matching tokens
+}
+
+bool BinPatch::patchHelper(char *inbuffer, const char *oldstr, const char *newstr, size_t len, long *rw)
+{
+    char nc1 = *oldstr;
+    char nc2 = 0;
+    char *inend = inbuffer + len;
+    size_t oldlen = strlen(oldstr);
+    size_t newlen = strlen(newstr);
+    char *instart = inbuffer;
+    *rw = 0;
+    bool write = true;
+
+    isupper(nc1) ? nc2 = tolower(nc1) : nc2 = toupper(nc1);
+
+    while(inbuffer < inend) {
+        if ((*inbuffer == nc1) || (*inbuffer == nc2)) {
+            if (inbuffer > (inend-oldlen) || inbuffer > (inend-newlen)) {
+                *rw = (long)(inend-inbuffer); //rewind, not enough to make a compare
+                break;
+            }
+
+            if (strncasecmp(inbuffer, oldstr, oldlen) == 0) {
+                if (useLength && (instart == inbuffer)) {
+                    *rw = (long)(len+1); //we don't have access to the length byte, rewind all + 1!
+                    write = false;
+                    break;
+                }
+                
+                long oldsize = -1;
+                if (useLength) { //VC60
+                    oldsize = (unsigned char)(*(inbuffer-1));
+
+                    // vc60 pdb files sometimes uses 0A, then it should be null terminated
+                    if (oldsize < (long)oldlen) {
+                        if (oldsize != 0x0A) { //strange case... skip
+                            inbuffer+=oldlen;
+                            continue;
+                        }
+
+                        oldsize = getBufferStringLength(inbuffer, inend);
+                        
+                        if (oldsize < 0) {
+                            *rw = (long)(inend-inbuffer); //rewind, entire string not in buffer
+                            break;
+                        }
+                    }
+
+                    if (inbuffer > (inend-oldsize)) {
+                        *rw = (long)(inend-inbuffer); //rewind, entire string not in buffer
+                        break;
+                    }
+                } else { //VC7x
+                    oldsize = getBufferStringLength(inbuffer, inend);
+                    if (oldsize < 0) {
+                        *rw = (long)(inend-inbuffer); //rewind, entire string not in buffer
+                        break;
+                    }
+                }
+
+                char oldPath[1024];
+                if (oldsize > (long)sizeof(oldPath)) {
+                    //at least don't crash
+                    inbuffer+=oldsize;
+                    continue;
+                }
+                memset(oldPath, '\0', sizeof(oldPath));
+                strncpy(oldPath, newstr, newlen);
+
+                if (insertReplace)
+                    strncat(oldPath, inbuffer+oldlen, oldsize-oldlen);
+
+                // just replace if it ends with a token in endTokens
+                if (endsWithTokens(oldPath)) {
+                    if (oldsize < (long)strlen(oldPath))
+                        oldsize = (long)strlen(oldPath);
+
+                    memcpy(inbuffer, oldPath, oldsize);
+                }
+
+                inbuffer+=oldsize;
+                continue;
+            }
+        }
+        ++inbuffer;
+    }
+
+    return write;
+}
+
+bool BinPatch::patch(const char *oldstr, const char *newstr)
+{
+    size_t oldlen = strlen(oldstr);
+    size_t newlen = strlen(newstr);
+
+    if ((!fileName || strlen(fileName) < 1)
+        || (!oldstr || oldlen < 1)
+        || (!newstr || newlen < 1))
+        return false;
+
+    FILE *input;
+
+    if (!(input = fopen(fileName, "r+b")))
+    {
+        fprintf(stderr, "Cannot open file %s!\n", fileName);
+        return false;
+    }
+
+    char data[60000];
+    long rw = 0;
+    long offset = 0;
+
+    size_t len;
+    len = fread(data, sizeof(char), sizeof(data), input);
+
+    do {
+        if (patchHelper(data, oldstr, newstr, len, &rw)) {
+            fseek(input, offset, SEEK_SET); //overwrite
+            fwrite(data, sizeof(char), len, input);
+        }
+
+        offset += (long)((-rw) + len);
+        if (fseek(input, offset, SEEK_SET) != 0)
+            break;
+        len = fread(data, sizeof(char), sizeof(data), input);
+    } while(!(feof(input) && (len <= oldlen || len <= newlen)));
+    
+    fclose(input);
+    
+    return true;
+}
diff --git a/src/tools/qtlibspatcher/binpatch.h b/src/tools/qtlibspatcher/binpatch.h
new file mode 100644
index 00000000000..a6867d39fbd
--- /dev/null
+++ b/src/tools/qtlibspatcher/binpatch.h
@@ -0,0 +1,74 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact:  Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file.  Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+
+#ifndef BINPATCH_H
+#define BINPATCH_H
+
+#include <string.h>
+
+typedef unsigned long ulong;
+typedef unsigned int uint;
+
+class BinPatch
+{
+public:
+    BinPatch(const char *file)
+        : useLength(false), insertReplace(false)
+    {
+        strcpy(endTokens, "");
+        strcpy(fileName, file);
+    }
+
+    void enableUseLength(bool enabled)
+    { useLength = enabled; }
+    void enableInsertReplace(bool enabled)
+    { insertReplace = enabled; }
+    void setEndTokens(const char *tokens)
+    { strcpy(endTokens, tokens); }
+
+    bool patch(const char *oldstr, const char *newstr);
+
+private:
+    long getBufferStringLength(char *data, char *end);
+    bool endsWithTokens(const char *data);
+
+    bool patchHelper(char *inbuffer, const char *oldstr, 
+        const char *newstr, size_t len, long *rw);
+
+    bool useLength;
+    bool insertReplace;
+    char endTokens[1024];
+    char fileName[1024];
+};
+
+#endif
diff --git a/src/tools/qtlibspatcher/qtlibspatcher.pro b/src/tools/qtlibspatcher/qtlibspatcher.pro
new file mode 100644
index 00000000000..fb0b51c9c9e
--- /dev/null
+++ b/src/tools/qtlibspatcher/qtlibspatcher.pro
@@ -0,0 +1,15 @@
+######################################################################
+# Automatically generated by qmake (2.01a) Di 8. Jul 15:08:13 2008
+######################################################################
+
+CONFIG += console
+QT -= gui
+TEMPLATE = app
+TARGET = 
+DEPENDPATH += .
+INCLUDEPATH += .
+DESTDIR = ./
+
+# Input
+HEADERS += binpatch.h
+SOURCES += binpatch.cpp qtlibspatchermain.cpp
diff --git a/src/tools/qtlibspatcher/qtlibspatchermain.cpp b/src/tools/qtlibspatcher/qtlibspatchermain.cpp
new file mode 100644
index 00000000000..f6b2da18f36
--- /dev/null
+++ b/src/tools/qtlibspatcher/qtlibspatchermain.cpp
@@ -0,0 +1,219 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact:  Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file.  Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception
+** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+
+#include "binpatch.h"
+#include <stdio.h>
+
+#include <QFile>
+#include <QRegExp>
+#include <QTextStream>
+#include <QString>
+#include <QtCore/QDebug>
+
+bool patchBinaryWithQtPathes(const char *fileName, const char *baseQtPath)
+{
+    bool result = true;
+
+    static const struct
+    {
+        const char *variable;
+        const char *subDirectory;
+    } variables[] = {
+        {"qt_prfxpath=", ""},
+        {"qt_docspath=", "/doc"},
+        {"qt_hdrspath=", "/include"},
+        {"qt_libspath=", "/lib"},
+        {"qt_binspath=", "/bin"},
+        {"qt_plugpath=", "/plugins"},
+        {"qt_datapath=", ""},
+        {"qt_trnspath=", "/translations"},
+        {"qt_xmplpath=", "/examples"},
+        {"qt_demopath=", "/demos"}
+    };
+
+    for (int i = 0; i < sizeof(variables)/sizeof(variables[0]); i++) {
+        char newStr[256] = "";
+        strncpy(newStr, variables[i].variable, sizeof(newStr));
+        newStr[sizeof(newStr) - 1] = 0;
+        strncat(newStr, baseQtPath, sizeof(newStr) - strlen(newStr) - 1);
+        newStr[sizeof(newStr) - 1] = 0;
+        strncat(newStr, variables[i].subDirectory, sizeof(newStr) - strlen(newStr) - 1);
+        newStr[sizeof(newStr) - 1] = 0;
+        BinPatch binFile(fileName);
+        if (!binFile.patch(variables[i].variable, newStr)) {
+            result = false;
+            break;
+        }
+    }
+
+    return result;
+}
+
+bool patchBinariesWithQtPathes(const char *baseQtPath)
+{
+    bool result = true;
+
+    static const char *filesToPatch[] = {
+        "/bin/qmake.exe",
+        "/bin/QtCore4.dll",
+        "/bin/QtCored4.dll"
+    };
+
+    for (int i = 0; i < sizeof(filesToPatch)/sizeof(filesToPatch[0]); i++) {
+        char fileName[FILENAME_MAX] = "";
+        strncpy(fileName, baseQtPath, sizeof(fileName));
+        fileName[sizeof(fileName)-1] = '\0';
+        strncat(fileName, filesToPatch[i], sizeof(fileName) - strlen(fileName) - 1);
+        fileName[sizeof(fileName)-1] = '\0';
+        if (!patchBinaryWithQtPathes(fileName, baseQtPath)) {
+            result = false;
+            break;
+        }
+    }
+
+    return result;
+}
+
+bool patchDebugLibrariesWithQtPath(const char *baseQtPath)
+{
+    bool result = true;
+
+    static const struct
+    {
+        const char *fileName;
+        const char *sourceLocation;
+    } libraries[] = {
+        {"/bin/Qt3Supportd4.dll", "/src/qt3support/"},
+        {"/bin/QtCored4.dll", "/src/corelib/"},
+        {"/bin/QtGuid4.dll", "/src/gui/"},
+        {"/bin/QtHelpd4.dll", "/tools/assistant/lib/"},
+        {"/bin/QtNetworkd4.dll", "/src/network/"},
+        {"/bin/QtOpenGLd4.dll", "/src/opengl/"},
+        {"/bin/QtScriptd4.dll", "/src/script/"},
+        {"/bin/QtSqld4.dll", "/src/sql/"},
+        {"/bin/QtSvgd4.dll", "/src/svg/"},
+        {"/bin/QtTestd4.dll", "/src/testlib/"},
+        {"/bin/QtWebKitd4.dll", "/src/3rdparty/webkit/WebCore/"},
+        {"/bin/QtXmld4.dll", "/src/xml/"},
+        {"/bin/QtXmlPatternsd4.dll", "/src/xmlpatterns/"},
+        {"/plugins/accessible/qtaccessiblecompatwidgetsd4.dll", "/src/plugins/accessible/compat/"},
+        {"/plugins/accessible/qtaccessiblewidgetsd4.dll", "/src/plugins/accessible/widgets/"},
+        {"/plugins/codecs/qcncodecsd4.dll", "/src/plugins/codecs/cn/"},
+        {"/plugins/codecs/qjpcodecsd4.dll", "/src/plugins/codecs/jp/"},
+        {"/plugins/codecs/qkrcodecsd4.dll", "/src/plugins/codecs/kr/"},
+        {"/plugins/codecs/qtwcodecsd4.dll", "/src/plugins/codecs/tw/"},
+        {"/plugins/iconengines/qsvgicond4.dll", "/src/plugins/iconengines/svgiconengine/"},
+        {"/plugins/imageformats/qgifd4.dll", "/src/plugins/imageformats/gif/"},
+        {"/plugins/imageformats/qjpegd4.dll", "/src/plugins/imageformats/jpeg/"},
+        {"/plugins/imageformats/qmngd4.dll", "/src/plugins/imageformats/mng/"},
+        {"/plugins/imageformats/qsvgd4.dll", "/src/plugins/imageformats/svg/"},
+        {"/plugins/imageformats/qtiffd4.dll", "/src/plugins/imageformats/tiff/"},
+        {"/plugins/sqldrivers/qsqlited4.dll", "/src/plugins/sqldrivers/sqlite/"},
+//        {"/plugins/sqldrivers/qsqlodbcd4.dll", "/src/plugins/sqldrivers/odbc/"}
+    };
+
+    for (int i = 0; i < sizeof(libraries)/sizeof(libraries[0]); i++) {
+        char fileName[FILENAME_MAX] = "";
+        strncpy(fileName, baseQtPath, sizeof(fileName));
+        fileName[sizeof(fileName)-1] = '\0';
+        strncat(fileName, libraries[i].fileName, sizeof(fileName) - strlen(fileName) - 1);
+        fileName[sizeof(fileName)-1] = '\0';
+
+        char oldSourcePath[FILENAME_MAX] =
+            "C:/qt-greenhouse/Trolltech/Code_less_create_more/Trolltech/Code_less_create_more/Troll/4.4.3";
+        strncat(oldSourcePath, libraries[i].sourceLocation, sizeof(oldSourcePath) - strlen(oldSourcePath) - 1);
+        oldSourcePath[sizeof(oldSourcePath)-1] = '\0';
+
+        char newSourcePath[FILENAME_MAX] = "";
+        strncpy(newSourcePath, baseQtPath, sizeof(newSourcePath));
+        newSourcePath[sizeof(newSourcePath)-1] = '\0';
+        strncat(newSourcePath, libraries[i].sourceLocation, sizeof(newSourcePath) - strlen(newSourcePath) - 1);
+        newSourcePath[sizeof(newSourcePath)-1] = '\0';
+
+        BinPatch binFile(fileName);
+        if (!binFile.patch(oldSourcePath, newSourcePath)) {
+            result = false;
+            break;
+        }
+    }
+
+    return result;
+}
+
+void patchQMakeSpec(const char *path)
+{
+    QString baseQtPath(path);
+    QFile f(baseQtPath + "/mkspecs/default/qmake.conf");
+    f.open(QIODevice::ReadOnly);
+    QTextStream in(&f);
+    QString all = in.readAll();
+    f.close();
+    // Old value is QMAKESPEC_ORIGINAL=C:/somepath/mkspecs/amakespce
+    // New value should be QMAKESPEC_ORIGINAL=baseQtPath/mkspec/amakespec
+    // We don't care to match the line end we simply match to the end of the file
+    QRegExp regExp("(QMAKESPEC_ORIGINAL=).*(/mkspecs/.*)");
+    all.replace(regExp, "\\1"+baseQtPath+"\\2");
+    
+    f.open(QIODevice::WriteOnly);
+    QTextStream out(&f);
+    out << all;
+}
+
+int main(int argc, char *args[])
+{
+    if (argc != 2) {
+        printf("Please provide a QTDIR value as parameter.\n"
+               "This is also the location where the binaries are expected\n"
+               "in the \"/bin\" and \"/plugins\" subdirectories.\n");
+        return 1;
+    }
+
+    char baseQtPath[FILENAME_MAX] = "";
+    strncpy(baseQtPath, args[1], sizeof(baseQtPath));
+    baseQtPath[sizeof(baseQtPath)-1] = '\0';
+
+    // Convert backslash to slash
+    for (char *p = baseQtPath; *p != '\0'; p++)
+        if (*p == '\\')
+            *p = '/';
+
+    // Remove trailing slash(es)
+    for (char *p = baseQtPath + strlen(baseQtPath) - 1; p != baseQtPath; p--)
+        if (*p == '/')
+            *p = '\0';
+        else
+            break;
+
+    patchQMakeSpec(baseQtPath);
+    return patchBinariesWithQtPathes(baseQtPath) && patchDebugLibrariesWithQtPath(baseQtPath)?0:1;
+}
-- 
GitLab