• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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).
EqualASCIICharI(wchar_t a,wchar_t b)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.
HexEncode(const void * bytes,size_t size,wchar_t * str,size_t str_size)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 
SafeStrLen(const wchar_t * str,size_t alloc_size)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 
SafeStrCopy(wchar_t * dest,size_t dest_size,const wchar_t * src)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.
SafeStrCat(wchar_t * dest,size_t dest_size,const wchar_t * src)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 
StrEndsWith(const wchar_t * str,const wchar_t * end_str)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 
StrStartsWith(const wchar_t * str,const wchar_t * start_str)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 
SearchStringI(const wchar_t * source,const wchar_t * find)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 
FindTagInStr(const wchar_t * str,const wchar_t * tag,const wchar_t ** position)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 
GetNameFromPathExt(wchar_t * path,size_t size)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