1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
31 **************************************************************************/
42 # define strcasecmp _stricmp
43 # define strncasecmp _strnicmp
46 // returns positive value if it finds a null termination inside the buffer
47 long BinPatch::getBufferStringLength(char *data, char *end)
60 // returns true if data ends with one of the tokens. (Sep. with ;)
61 bool BinPatch::endsWithTokens(const char *data)
63 if(strlen(endTokens) > 0) {
65 ulong tlen = ulong(strlen(data));
67 if(strlen(endTokens) >= sizeof(endstmp))
70 strcpy(endstmp, endTokens);
72 char *token = strtok(endstmp, ";");
74 while(token != NULL) {
75 // check if it ends with the token
76 if ((tlen >= strlen(token))
77 && (strcasecmp((data+tlen)-strlen(token), token) == 0))
79 token = strtok(NULL, ";");
82 return true; //true if no tokens
85 return false; //no matching tokens
88 bool BinPatch::patchHelper(char *inbuffer, const char *oldstr, const char *newstr, size_t len, long *rw)
92 char *inend = inbuffer + len;
93 size_t oldlen = strlen(oldstr);
94 size_t newlen = strlen(newstr);
95 char *instart = inbuffer;
99 isupper(nc1) ? nc2 = tolower(nc1) : nc2 = toupper(nc1);
101 while(inbuffer < inend) {
102 if ((*inbuffer == nc1) || (*inbuffer == nc2)) {
103 if (inbuffer > (inend-oldlen) || inbuffer > (inend-newlen)) {
104 *rw = (long)(inend-inbuffer); //rewind, not enough to make a compare
108 if (strncasecmp(inbuffer, oldstr, oldlen) == 0) {
109 if (useLength && (instart == inbuffer)) {
110 *rw = (long)(len+1); //we don't have access to the length byte, rewind all + 1!
116 if (useLength) { //VC60
117 oldsize = (unsigned char)(*(inbuffer-1));
119 // vc60 pdb files sometimes uses 0A, then it should be null terminated
120 if (oldsize < (long)oldlen) {
121 if (oldsize != 0x0A) { //strange case... skip
126 oldsize = getBufferStringLength(inbuffer, inend);
129 *rw = (long)(inend-inbuffer); //rewind, entire string not in buffer
134 if (inbuffer > (inend-oldsize)) {
135 *rw = (long)(inend-inbuffer); //rewind, entire string not in buffer
139 oldsize = getBufferStringLength(inbuffer, inend);
141 *rw = (long)(inend-inbuffer); //rewind, entire string not in buffer
147 if (oldsize > (long)sizeof(oldPath)) {
148 //at least don't crash
152 memset(oldPath, '\0', sizeof(oldPath));
153 strncpy(oldPath, newstr, newlen);
156 strncat(oldPath, inbuffer+oldlen, oldsize-oldlen);
158 // just replace if it ends with a token in endTokens
159 if (endsWithTokens(oldPath)) {
160 if (oldsize < (long)strlen(oldPath))
161 oldsize = (long)strlen(oldPath);
163 memcpy(inbuffer, oldPath, oldsize);
176 bool BinPatch::patch(const char *oldstr, const char *newstr)
178 size_t oldlen = strlen(oldstr);
179 size_t newlen = strlen(newstr);
181 if ((!fileName || strlen(fileName) < 1)
182 || (!oldstr || oldlen < 1)
183 || (!newstr || newlen < 1))
188 if (!(input = fopen(fileName, "r+b")))
190 fprintf(stderr, "Warning: Could not open file %s\n", fileName);
199 len = fread(data, sizeof(char), sizeof(data), input);
202 if (patchHelper(data, oldstr, newstr, len, &rw)) {
203 fseek(input, offset, SEEK_SET); //overwrite
204 fwrite(data, sizeof(char), len, input);
207 offset += (long)((-rw) + len);
208 if (fseek(input, offset, SEEK_SET) != 0)
210 len = fread(data, sizeof(char), sizeof(data), input);
211 } while(!(feof(input) && (len <= oldlen || len <= newlen)));