1 /* 2 * PROJECT: ReactOS Automatic Testing Utility 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Various helper functions 5 * COPYRIGHT: Copyright 2008-2015 Colin Finck (colin@reactos.org) 6 */ 7 8 #include "precomp.h" 9 10 #define DBGPRINT_BUFSIZE 511 11 static const char HexCharacters[] = "0123456789ABCDEF"; 12 13 /** 14 * Escapes a string according to RFC 1738. 15 * Required for passing parameters to the web service. 16 * 17 * @param Input 18 * Constant pointer to a char array, which contains the input buffer to escape. 19 * 20 * @return 21 * The escaped string as std::string. 22 */ 23 string 24 EscapeString(const char* Input) 25 { 26 string ReturnedString; 27 28 do 29 { 30 if(strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~", *Input)) 31 { 32 /* It's a character we don't need to escape, just add it to the output string */ 33 ReturnedString += *Input; 34 } 35 else 36 { 37 /* We need to escape this character */ 38 ReturnedString += '%'; 39 ReturnedString += HexCharacters[((UCHAR)*Input >> 4) % 16]; 40 ReturnedString += HexCharacters[(UCHAR)*Input % 16]; 41 } 42 } 43 while(*++Input); 44 45 return ReturnedString; 46 } 47 48 /** 49 * Escapes a string according to RFC 1738. 50 * Required for passing parameters to the web service. 51 * 52 * @param Input 53 * Pointer to a std::string, which contains the input buffer to escape. 54 * 55 * @return 56 * The escaped string as std::string. 57 */ 58 string 59 EscapeString(const string& Input) 60 { 61 return EscapeString(Input.c_str()); 62 } 63 64 /** 65 * Determines whether a string contains entirely numeric values. 66 * 67 * @param Input 68 * Constant pointer to a char array containing the input to check. 69 * 70 * @return 71 * true if the string is entirely numeric, false otherwise. 72 */ 73 bool 74 IsNumber(const char* Input) 75 { 76 do 77 { 78 if(!isdigit(*Input)) 79 return false; 80 81 ++Input; 82 } 83 while(*Input); 84 85 return true; 86 } 87 88 /** 89 * Outputs a string through the standard output and the debug output. 90 * The string may have LF or CRLF line endings. 91 * 92 * @param String 93 * The std::string to output 94 */ 95 string 96 StringOut(const string& String, bool forcePrint) 97 { 98 char DbgString[DBGPRINT_BUFSIZE + 1]; 99 size_t i, start = 0, last_newline = 0, size = 0, curr_pos = 0; 100 string NewString; 101 102 /* Unify the line endings (the piped output of the tests may use CRLF) */ 103 for(i = 0; i < String.size(); i++) 104 { 105 /* If this is a CRLF line-ending, only copy a \n to the new string and skip the next character */ 106 if(String[i] == '\r' && String[i + 1] == '\n') 107 { 108 NewString += '\n'; 109 ++i; 110 } 111 else 112 { 113 /* Otherwise copy the string */ 114 NewString += String[i]; 115 } 116 117 curr_pos = NewString.size(); 118 119 /* Try to print whole lines but obey the 512 bytes chunk size limit*/ 120 if(NewString[curr_pos - 1] == '\n' || (curr_pos - start) == DBGPRINT_BUFSIZE) 121 { 122 if((curr_pos - start) >= DBGPRINT_BUFSIZE) 123 { 124 /* No newlines so far, or the string just fits */ 125 if(last_newline <= start || ((curr_pos - start == DBGPRINT_BUFSIZE) && NewString[curr_pos - 1] == '\n')) 126 { 127 size = curr_pos - start; 128 memcpy(DbgString, NewString.c_str() + start, size); 129 start = curr_pos; 130 } 131 else 132 { 133 size = last_newline - start; 134 memcpy(DbgString, NewString.c_str() + start, size); 135 start = last_newline; 136 } 137 138 DbgString[size] = 0; 139 DbgPrint("%s", DbgString); 140 } 141 142 last_newline = curr_pos; 143 } 144 } 145 146 size = curr_pos - start; 147 148 /* Only print if forced to or if the rest is a whole line */ 149 if(forcePrint == true || NewString[curr_pos - 1] == '\n') 150 { 151 /* Output the whole string */ 152 if(Configuration.DoPrint()) 153 cout << NewString << flush; 154 155 memcpy(DbgString, NewString.c_str() + start, size); 156 DbgString[size] = 0; 157 DbgPrint("%s", DbgString); 158 159 NewString.clear(); 160 return NewString; 161 } 162 163 /* Output full lines only */ 164 if(Configuration.DoPrint()) 165 cout << NewString.substr(0, start) << flush; 166 167 /* Return the remaining chunk */ 168 return NewString.substr(start, size); 169 } 170 171 /** 172 * Gets a value from a specified INI file and returns it converted to ASCII. 173 * 174 * @param AppName 175 * Constant pointer to a WCHAR array with the INI section to look in (lpAppName parameter passed to GetPrivateProfileStringW) 176 * 177 * @param KeyName 178 * Constant pointer to a WCHAR array containing the key to look for in the specified section (lpKeyName parameter passed to GetPrivateProfileStringW) 179 * 180 * @param FileName 181 * Constant pointer to a WCHAR array containing the path to the INI file 182 * 183 * @return 184 * Returns the data of the value as std::string or an empty string if no data could be retrieved. 185 */ 186 string 187 GetINIValue(PCWCH AppName, PCWCH KeyName, PCWCH FileName) 188 { 189 DWORD Length; 190 PCHAR AsciiBuffer; 191 string ReturnedString; 192 WCHAR Buffer[2048]; 193 194 /* Load the value into a temporary Unicode buffer */ 195 Length = GetPrivateProfileStringW(AppName, KeyName, NULL, Buffer, sizeof(Buffer) / sizeof(WCHAR), FileName); 196 197 if(Length) 198 { 199 /* Convert the string to ASCII charset */ 200 AsciiBuffer = new char[Length + 1]; 201 WideCharToMultiByte(CP_ACP, 0, Buffer, Length + 1, AsciiBuffer, Length + 1, NULL, NULL); 202 203 ReturnedString = AsciiBuffer; 204 delete[] AsciiBuffer; 205 } 206 207 return ReturnedString; 208 } 209 210 /** 211 * Converts an ASCII string to a Unicode one. 212 * 213 * @param AsciiString 214 * Constant pointer to a char array containing the ASCII string 215 * 216 * @return 217 * The Unicode string as std::wstring 218 */ 219 wstring 220 AsciiToUnicode(const char* AsciiString) 221 { 222 DWORD Length; 223 PWSTR UnicodeString; 224 wstring ReturnString; 225 226 Length = MultiByteToWideChar(CP_ACP, 0, AsciiString, -1, NULL, 0); 227 228 UnicodeString = new WCHAR[Length]; 229 MultiByteToWideChar(CP_ACP, 0, AsciiString, -1, UnicodeString, Length); 230 ReturnString = UnicodeString; 231 delete UnicodeString; 232 233 return ReturnString; 234 } 235 236 /** 237 * Converts an ASCII string to a Unicode one. 238 * 239 * @param AsciiString 240 * Pointer to a std::string containing the ASCII string 241 * 242 * @return 243 * The Unicode string as std::wstring 244 */ 245 wstring 246 AsciiToUnicode(const string& AsciiString) 247 { 248 return AsciiToUnicode(AsciiString.c_str()); 249 } 250 251 /** 252 * Converts a Unicode string to an ASCII one. 253 * 254 * @param UnicodeString 255 * Constant pointer to a WCHAR array containing the Unicode string 256 * 257 * @return 258 * The ASCII string as std::string 259 */ 260 string 261 UnicodeToAscii(PCWSTR UnicodeString) 262 { 263 DWORD Length; 264 PCHAR AsciiString; 265 string ReturnString; 266 267 Length = WideCharToMultiByte(CP_ACP, 0, UnicodeString, -1, NULL, 0, NULL, NULL); 268 269 AsciiString = new char[Length]; 270 WideCharToMultiByte(CP_ACP, 0, UnicodeString, -1, AsciiString, Length, NULL, NULL); 271 ReturnString = AsciiString; 272 delete AsciiString; 273 274 return ReturnString; 275 } 276 277 /** 278 * Converts a Unicode string to an ASCII one. 279 * 280 * @param UnicodeString 281 * Pointer to a std::wstring containing the Unicode string 282 * 283 * @return 284 * The ASCII string as std::string 285 */ 286 string 287 UnicodeToAscii(const wstring& UnicodeString) 288 { 289 return UnicodeToAscii(UnicodeString.c_str()); 290 } 291