15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/mini_installer/mini_string.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if the given two ASCII characters are same (ignoring case). 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EqualASCIICharI(wchar_t a, wchar_t b) { 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (a >= L'A' && a <= L'Z') 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a += (L'a' - L'A'); 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (b >= L'A' && b <= L'Z') 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) b += (L'a' - L'A'); 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (a == b); 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace mini_installer { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Formats a sequence of |bytes| as hex. The |str| buffer must have room for 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// at least 2*|size| + 1. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HexEncode(const void* bytes, size_t size, wchar_t* str, size_t str_size) { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (str_size <= (size * 2)) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const wchar_t kHexChars[] = L"0123456789ABCDEF"; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str[size * 2] = L'\0'; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < size; ++i) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char b = reinterpret_cast<const char*>(bytes)[i]; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str[(i * 2)] = kHexChars[(b >> 4) & 0xf]; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str[(i * 2) + 1] = kHexChars[b & 0xf]; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SafeStrLen(const wchar_t* str, size_t alloc_size) { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!str || !alloc_size) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t len = 0; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (--alloc_size && str[len] != L'\0') 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++len; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return len; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SafeStrCopy(wchar_t* dest, size_t dest_size, const wchar_t* src) { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dest || !dest_size) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t* write = dest; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t remaining = dest_size; remaining != 0; --remaining) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((*write++ = *src++) == L'\0') 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we fail, we do not want to leave the string with partially copied 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // contents. The reason for this is that we use these strings mostly for 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // named objects such as files. If we copy a partial name, then that could 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // match with something we do not want it to match with. 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Furthermore, since SafeStrCopy is called from SafeStrCat, we do not 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // want to mutate the string in case the caller handles the error of a 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // failed concatenation. For example: 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // wchar_t buf[5] = {0}; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if (!SafeStrCat(buf, arraysize(buf), kLongName)) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SafeStrCat(buf, arraysize(buf), kShortName); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we were to return false in the first call to SafeStrCat but still 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mutate the buffer, the buffer will be in an unexpected state. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dest = L'\0'; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Safer replacement for lstrcat function. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SafeStrCat(wchar_t* dest, size_t dest_size, const wchar_t* src) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use SafeStrLen instead of lstrlen just in case the |dest| buffer isn't 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // terminated. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int str_len = SafeStrLen(dest, dest_size); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SafeStrCopy(dest + str_len, dest_size - str_len, src); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool StrEndsWith(const wchar_t* str, const wchar_t* end_str) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (str == NULL || end_str == NULL) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = lstrlen(str) - 1, j = lstrlen(end_str) - 1; j >= 0; --i, --j) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i < 0 || !EqualASCIICharI(str[i], end_str[j])) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool StrStartsWith(const wchar_t* str, const wchar_t* start_str) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (str == NULL || start_str == NULL) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; start_str[i] != L'\0'; ++i) { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!EqualASCIICharI(str[i], start_str[i])) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t* SearchStringI(const wchar_t* source, const wchar_t* find) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!find || find[0] == L'\0') 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return source; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const wchar_t* scan = source; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (*scan) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const wchar_t* s = scan; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const wchar_t* f = find; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (*s && *f && EqualASCIICharI(*s, *f)) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++s, ++f; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!*f) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scan; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++scan; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FindTagInStr(const wchar_t* str, 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const wchar_t* tag, 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const wchar_t** position) { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tag_length = ::lstrlen(tag); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const wchar_t* scan = str; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (const wchar_t* tag_start = SearchStringI(scan, tag); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tag_start != NULL; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tag_start = SearchStringI(scan, tag)) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scan = tag_start + tag_length; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*scan == L'-' || *scan == L'\0') { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (position != NULL) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *position = tag_start; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)wchar_t* GetNameFromPathExt(wchar_t* path, size_t size) { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size <= 1) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t* current = &path[size - 1]; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (current != path && L'\\' != *current) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --current; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (current == path) ? NULL : (current + 1); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace mini_installer 163