xpcom/glue/nsVersionComparator.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #include "nsVersionComparator.h"
michael@0 6
michael@0 7 #include <stdlib.h>
michael@0 8 #include <string.h>
michael@0 9 #include <stdint.h>
michael@0 10 #if defined(XP_WIN) && !defined(UPDATER_NO_STRING_GLUE_STL)
michael@0 11 #include <wchar.h>
michael@0 12 #include "nsStringGlue.h"
michael@0 13 #endif
michael@0 14
michael@0 15 struct VersionPart {
michael@0 16 int32_t numA;
michael@0 17
michael@0 18 const char *strB; // NOT null-terminated, can be a null pointer
michael@0 19 uint32_t strBlen;
michael@0 20
michael@0 21 int32_t numC;
michael@0 22
michael@0 23 char *extraD; // null-terminated
michael@0 24 };
michael@0 25
michael@0 26 #ifdef XP_WIN
michael@0 27 struct VersionPartW {
michael@0 28 int32_t numA;
michael@0 29
michael@0 30 wchar_t *strB; // NOT null-terminated, can be a null pointer
michael@0 31 uint32_t strBlen;
michael@0 32
michael@0 33 int32_t numC;
michael@0 34
michael@0 35 wchar_t *extraD; // null-terminated
michael@0 36
michael@0 37 };
michael@0 38 #endif
michael@0 39
michael@0 40 /**
michael@0 41 * Parse a version part into a number and "extra text".
michael@0 42 *
michael@0 43 * @returns A pointer to the next versionpart, or null if none.
michael@0 44 */
michael@0 45 static char*
michael@0 46 ParseVP(char *part, VersionPart &result)
michael@0 47 {
michael@0 48 char *dot;
michael@0 49
michael@0 50 result.numA = 0;
michael@0 51 result.strB = nullptr;
michael@0 52 result.strBlen = 0;
michael@0 53 result.numC = 0;
michael@0 54 result.extraD = nullptr;
michael@0 55
michael@0 56 if (!part)
michael@0 57 return part;
michael@0 58
michael@0 59 dot = strchr(part, '.');
michael@0 60 if (dot)
michael@0 61 *dot = '\0';
michael@0 62
michael@0 63 if (part[0] == '*' && part[1] == '\0') {
michael@0 64 result.numA = INT32_MAX;
michael@0 65 result.strB = "";
michael@0 66 }
michael@0 67 else {
michael@0 68 result.numA = strtol(part, const_cast<char**>(&result.strB), 10);
michael@0 69 }
michael@0 70
michael@0 71 if (!*result.strB) {
michael@0 72 result.strB = nullptr;
michael@0 73 result.strBlen = 0;
michael@0 74 }
michael@0 75 else {
michael@0 76 if (result.strB[0] == '+') {
michael@0 77 static const char kPre[] = "pre";
michael@0 78
michael@0 79 ++result.numA;
michael@0 80 result.strB = kPre;
michael@0 81 result.strBlen = sizeof(kPre) - 1;
michael@0 82 }
michael@0 83 else {
michael@0 84 const char *numstart = strpbrk(result.strB, "0123456789+-");
michael@0 85 if (!numstart) {
michael@0 86 result.strBlen = strlen(result.strB);
michael@0 87 }
michael@0 88 else {
michael@0 89 result.strBlen = numstart - result.strB;
michael@0 90
michael@0 91 result.numC = strtol(numstart, &result.extraD, 10);
michael@0 92 if (!*result.extraD)
michael@0 93 result.extraD = nullptr;
michael@0 94 }
michael@0 95 }
michael@0 96 }
michael@0 97
michael@0 98 if (dot) {
michael@0 99 ++dot;
michael@0 100
michael@0 101 if (!*dot)
michael@0 102 dot = nullptr;
michael@0 103 }
michael@0 104
michael@0 105 return dot;
michael@0 106 }
michael@0 107
michael@0 108
michael@0 109 /**
michael@0 110 * Parse a version part into a number and "extra text".
michael@0 111 *
michael@0 112 * @returns A pointer to the next versionpart, or null if none.
michael@0 113 */
michael@0 114 #ifdef XP_WIN
michael@0 115 static wchar_t*
michael@0 116 ParseVP(wchar_t *part, VersionPartW &result)
michael@0 117 {
michael@0 118
michael@0 119 wchar_t *dot;
michael@0 120
michael@0 121 result.numA = 0;
michael@0 122 result.strB = nullptr;
michael@0 123 result.strBlen = 0;
michael@0 124 result.numC = 0;
michael@0 125 result.extraD = nullptr;
michael@0 126
michael@0 127 if (!part)
michael@0 128 return part;
michael@0 129
michael@0 130 dot = wcschr(part, '.');
michael@0 131 if (dot)
michael@0 132 *dot = '\0';
michael@0 133
michael@0 134 if (part[0] == '*' && part[1] == '\0') {
michael@0 135 result.numA = INT32_MAX;
michael@0 136 result.strB = L"";
michael@0 137 }
michael@0 138 else {
michael@0 139 result.numA = wcstol(part, const_cast<wchar_t**>(&result.strB), 10);
michael@0 140 }
michael@0 141
michael@0 142 if (!*result.strB) {
michael@0 143 result.strB = nullptr;
michael@0 144 result.strBlen = 0;
michael@0 145 }
michael@0 146 else {
michael@0 147 if (result.strB[0] == '+') {
michael@0 148 static wchar_t kPre[] = L"pre";
michael@0 149
michael@0 150 ++result.numA;
michael@0 151 result.strB = kPre;
michael@0 152 result.strBlen = sizeof(kPre) - 1;
michael@0 153 }
michael@0 154 else {
michael@0 155 const wchar_t *numstart = wcspbrk(result.strB, L"0123456789+-");
michael@0 156 if (!numstart) {
michael@0 157 result.strBlen = wcslen(result.strB);
michael@0 158 }
michael@0 159 else {
michael@0 160 result.strBlen = numstart - result.strB;
michael@0 161
michael@0 162 result.numC = wcstol(numstart, &result.extraD, 10);
michael@0 163 if (!*result.extraD)
michael@0 164 result.extraD = nullptr;
michael@0 165 }
michael@0 166 }
michael@0 167 }
michael@0 168
michael@0 169 if (dot) {
michael@0 170 ++dot;
michael@0 171
michael@0 172 if (!*dot)
michael@0 173 dot = nullptr;
michael@0 174 }
michael@0 175
michael@0 176 return dot;
michael@0 177 }
michael@0 178 #endif
michael@0 179
michael@0 180 // compare two null-terminated strings, which may be null pointers
michael@0 181 static int32_t
michael@0 182 ns_strcmp(const char *str1, const char *str2)
michael@0 183 {
michael@0 184 // any string is *before* no string
michael@0 185 if (!str1)
michael@0 186 return str2 != 0;
michael@0 187
michael@0 188 if (!str2)
michael@0 189 return -1;
michael@0 190
michael@0 191 return strcmp(str1, str2);
michael@0 192 }
michael@0 193
michael@0 194 // compare two length-specified string, which may be null pointers
michael@0 195 static int32_t
michael@0 196 ns_strnncmp(const char *str1, uint32_t len1, const char *str2, uint32_t len2)
michael@0 197 {
michael@0 198 // any string is *before* no string
michael@0 199 if (!str1)
michael@0 200 return str2 != 0;
michael@0 201
michael@0 202 if (!str2)
michael@0 203 return -1;
michael@0 204
michael@0 205 for (; len1 && len2; --len1, --len2, ++str1, ++str2) {
michael@0 206 if (*str1 < *str2)
michael@0 207 return -1;
michael@0 208
michael@0 209 if (*str1 > *str2)
michael@0 210 return 1;
michael@0 211 }
michael@0 212
michael@0 213 if (len1 == 0)
michael@0 214 return len2 == 0 ? 0 : -1;
michael@0 215
michael@0 216 return 1;
michael@0 217 }
michael@0 218
michael@0 219 // compare two int32_t
michael@0 220 static int32_t
michael@0 221 ns_cmp(int32_t n1, int32_t n2)
michael@0 222 {
michael@0 223 if (n1 < n2)
michael@0 224 return -1;
michael@0 225
michael@0 226 return n1 != n2;
michael@0 227 }
michael@0 228
michael@0 229 /**
michael@0 230 * Compares two VersionParts
michael@0 231 */
michael@0 232 static int32_t
michael@0 233 CompareVP(VersionPart &v1, VersionPart &v2)
michael@0 234 {
michael@0 235 int32_t r = ns_cmp(v1.numA, v2.numA);
michael@0 236 if (r)
michael@0 237 return r;
michael@0 238
michael@0 239 r = ns_strnncmp(v1.strB, v1.strBlen, v2.strB, v2.strBlen);
michael@0 240 if (r)
michael@0 241 return r;
michael@0 242
michael@0 243 r = ns_cmp(v1.numC, v2.numC);
michael@0 244 if (r)
michael@0 245 return r;
michael@0 246
michael@0 247 return ns_strcmp(v1.extraD, v2.extraD);
michael@0 248 }
michael@0 249
michael@0 250 /**
michael@0 251 * Compares two VersionParts
michael@0 252 */
michael@0 253 #ifdef XP_WIN
michael@0 254 static int32_t
michael@0 255 CompareVP(VersionPartW &v1, VersionPartW &v2)
michael@0 256 {
michael@0 257 int32_t r = ns_cmp(v1.numA, v2.numA);
michael@0 258 if (r)
michael@0 259 return r;
michael@0 260
michael@0 261 r = wcsncmp(v1.strB, v2.strB, XPCOM_MIN(v1.strBlen,v2.strBlen));
michael@0 262 if (r)
michael@0 263 return r;
michael@0 264
michael@0 265 r = ns_cmp(v1.numC, v2.numC);
michael@0 266 if (r)
michael@0 267 return r;
michael@0 268
michael@0 269 if (!v1.extraD)
michael@0 270 return v2.extraD != 0;
michael@0 271
michael@0 272 if (!v2.extraD)
michael@0 273 return -1;
michael@0 274
michael@0 275 return wcscmp(v1.extraD, v2.extraD);
michael@0 276 }
michael@0 277 #endif
michael@0 278
michael@0 279 namespace mozilla {
michael@0 280
michael@0 281 #ifdef XP_WIN
michael@0 282 int32_t
michael@0 283 CompareVersions(const char16_t *A, const char16_t *B)
michael@0 284 {
michael@0 285 wchar_t *A2 = wcsdup(char16ptr_t(A));
michael@0 286 if (!A2)
michael@0 287 return 1;
michael@0 288
michael@0 289 wchar_t *B2 = wcsdup(char16ptr_t(B));
michael@0 290 if (!B2) {
michael@0 291 free(A2);
michael@0 292 return 1;
michael@0 293 }
michael@0 294
michael@0 295 int32_t result;
michael@0 296 wchar_t *a = A2, *b = B2;
michael@0 297
michael@0 298 do {
michael@0 299 VersionPartW va, vb;
michael@0 300
michael@0 301 a = ParseVP(a, va);
michael@0 302 b = ParseVP(b, vb);
michael@0 303
michael@0 304 result = CompareVP(va, vb);
michael@0 305 if (result)
michael@0 306 break;
michael@0 307
michael@0 308 } while (a || b);
michael@0 309
michael@0 310 free(A2);
michael@0 311 free(B2);
michael@0 312
michael@0 313 return result;
michael@0 314 }
michael@0 315 #endif
michael@0 316
michael@0 317 int32_t
michael@0 318 CompareVersions(const char *A, const char *B)
michael@0 319 {
michael@0 320 char *A2 = strdup(A);
michael@0 321 if (!A2)
michael@0 322 return 1;
michael@0 323
michael@0 324 char *B2 = strdup(B);
michael@0 325 if (!B2) {
michael@0 326 free(A2);
michael@0 327 return 1;
michael@0 328 }
michael@0 329
michael@0 330 int32_t result;
michael@0 331 char *a = A2, *b = B2;
michael@0 332
michael@0 333 do {
michael@0 334 VersionPart va, vb;
michael@0 335
michael@0 336 a = ParseVP(a, va);
michael@0 337 b = ParseVP(b, vb);
michael@0 338
michael@0 339 result = CompareVP(va, vb);
michael@0 340 if (result)
michael@0 341 break;
michael@0 342
michael@0 343 } while (a || b);
michael@0 344
michael@0 345 free(A2);
michael@0 346 free(B2);
michael@0 347
michael@0 348 return result;
michael@0 349 }
michael@0 350
michael@0 351 } // namespace mozilla
michael@0 352

mercurial