Home | History | Annotate | Download | only in mini_installer
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/installer/mini_installer/mini_string.h"
      6 
      7 #include <windows.h>
      8 
      9 namespace {
     10 
     11 // Returns true if the given two ASCII characters are same (ignoring case).
     12 bool EqualASCIICharI(wchar_t a, wchar_t b) {
     13   if (a >= L'A' && a <= L'Z')
     14     a += (L'a' - L'A');
     15   if (b >= L'A' && b <= L'Z')
     16     b += (L'a' - L'A');
     17   return (a == b);
     18 }
     19 
     20 }  // namespace
     21 
     22 namespace mini_installer {
     23 
     24 // Formats a sequence of |bytes| as hex.  The |str| buffer must have room for
     25 // at least 2*|size| + 1.
     26 bool HexEncode(const void* bytes, size_t size, wchar_t* str, size_t str_size) {
     27   if (str_size <= (size * 2))
     28     return false;
     29 
     30   static const wchar_t kHexChars[] = L"0123456789ABCDEF";
     31 
     32   str[size * 2] = L'\0';
     33 
     34   for (size_t i = 0; i < size; ++i) {
     35     char b = reinterpret_cast<const char*>(bytes)[i];
     36     str[(i * 2)] = kHexChars[(b >> 4) & 0xf];
     37     str[(i * 2) + 1] = kHexChars[b & 0xf];
     38   }
     39 
     40   return true;
     41 }
     42 
     43 size_t SafeStrLen(const wchar_t* str, size_t alloc_size) {
     44   if (!str || !alloc_size)
     45     return 0;
     46   size_t len = 0;
     47   while (--alloc_size && str[len] != L'\0')
     48     ++len;
     49   return len;
     50 }
     51 
     52 bool SafeStrCopy(wchar_t* dest, size_t dest_size, const wchar_t* src) {
     53   if (!dest || !dest_size)
     54     return false;
     55 
     56   wchar_t* write = dest;
     57   for (size_t remaining = dest_size; remaining != 0; --remaining) {
     58     if ((*write++ = *src++) == L'\0')
     59       return true;
     60   }
     61 
     62   // If we fail, we do not want to leave the string with partially copied
     63   // contents.  The reason for this is that we use these strings mostly for
     64   // named objects such as files.  If we copy a partial name, then that could
     65   // match with something we do not want it to match with.
     66   // Furthermore, since SafeStrCopy is called from SafeStrCat, we do not
     67   // want to mutate the string in case the caller handles the error of a
     68   // failed concatenation.  For example:
     69   //
     70   // wchar_t buf[5] = {0};
     71   // if (!SafeStrCat(buf, arraysize(buf), kLongName))
     72   //   SafeStrCat(buf, arraysize(buf), kShortName);
     73   //
     74   // If we were to return false in the first call to SafeStrCat but still
     75   // mutate the buffer, the buffer will be in an unexpected state.
     76   *dest = L'\0';
     77   return false;
     78 }
     79 
     80 // Safer replacement for lstrcat function.
     81 bool SafeStrCat(wchar_t* dest, size_t dest_size, const wchar_t* src) {
     82   // Use SafeStrLen instead of lstrlen just in case the |dest| buffer isn't
     83   // terminated.
     84   int str_len = SafeStrLen(dest, dest_size);
     85   return SafeStrCopy(dest + str_len, dest_size - str_len, src);
     86 }
     87 
     88 bool StrEndsWith(const wchar_t* str, const wchar_t* end_str) {
     89   if (str == NULL || end_str == NULL)
     90     return false;
     91 
     92   for (int i = lstrlen(str) - 1, j = lstrlen(end_str) - 1; j >= 0; --i, --j) {
     93     if (i < 0 || !EqualASCIICharI(str[i], end_str[j]))
     94       return false;
     95   }
     96 
     97   return true;
     98 }
     99 
    100 bool StrStartsWith(const wchar_t* str, const wchar_t* start_str) {
    101   if (str == NULL || start_str == NULL)
    102     return false;
    103 
    104   for (int i = 0; start_str[i] != L'\0'; ++i) {
    105     if (!EqualASCIICharI(str[i], start_str[i]))
    106       return false;
    107   }
    108 
    109   return true;
    110 }
    111 
    112 const wchar_t* SearchStringI(const wchar_t* source, const wchar_t* find) {
    113   if (!find || find[0] == L'\0')
    114     return source;
    115 
    116   const wchar_t* scan = source;
    117   while (*scan) {
    118     const wchar_t* s = scan;
    119     const wchar_t* f = find;
    120 
    121     while (*s && *f && EqualASCIICharI(*s, *f))
    122       ++s, ++f;
    123 
    124     if (!*f)
    125       return scan;
    126 
    127     ++scan;
    128   }
    129 
    130   return NULL;
    131 }
    132 
    133 bool FindTagInStr(const wchar_t* str,
    134                   const wchar_t* tag,
    135                   const wchar_t** position) {
    136   int tag_length = ::lstrlen(tag);
    137   const wchar_t* scan = str;
    138   for (const wchar_t* tag_start = SearchStringI(scan, tag);
    139        tag_start != NULL;
    140        tag_start = SearchStringI(scan, tag)) {
    141     scan = tag_start + tag_length;
    142     if (*scan == L'-' || *scan == L'\0') {
    143       if (position != NULL)
    144         *position = tag_start;
    145       return true;
    146     }
    147   }
    148   return false;
    149 }
    150 
    151 wchar_t* GetNameFromPathExt(wchar_t* path, size_t size) {
    152   if (size <= 1)
    153     return NULL;
    154 
    155   wchar_t* current = &path[size - 1];
    156   while (current != path && L'\\' != *current)
    157     --current;
    158 
    159   return (current == path) ? NULL : (current + 1);
    160 }
    161 
    162 }  // namespace mini_installer
    163