1 #include "RosterSettingsCharStream.h" 2 3 #include <sniffer/Err.h> 4 #include <StorageDefs.h> 5 6 #include <stdio.h> 7 8 using namespace BPrivate::Storage::Sniffer; 9 10 //------------------------------------------------------------------------------ 11 // CharStream 12 //------------------------------------------------------------------------------ 13 14 RosterSettingsCharStream::RosterSettingsCharStream(const std::string &string) 15 : CharStream(string) 16 { 17 } 18 19 RosterSettingsCharStream::RosterSettingsCharStream() 20 : CharStream() 21 { 22 } 23 24 RosterSettingsCharStream::~RosterSettingsCharStream() 25 { 26 } 27 28 /*! \brief Reads the next string from the stream 29 30 - Strings are either unquoted or quoted strings on a single line. 31 - Whitespace is either spaces or tabs. 32 - Newlines separate lines and are never included in strings. 33 - Comments extend to the end of the line and must begin the line 34 with #. Technically speaking, any "string" that begins with # 35 will be treated as a comment that extends to the end of the line. 36 However, as all strings of interest are full pathnames, application 37 signatures, integers, or Recent{Doc,Folder,App}, this does not 38 currently pose a problem. 39 - Quotes are " or ' 40 - An unquoted string begins with any character execept whitespace 41 or a quote and continues until a whitespace character, newline, 42 or comment is encountered. Whitespace may be included in the 43 unquoted string if each whitespace character is escaped with a 44 '\' character. Escaped characters are converted to the actual 45 characters they represent before being stored in the result. 46 If the string begins with an unescaped # character, it will be 47 treated as a comment that extends to the end of the line. # 48 characters may appear unescaped anywhere else in the string. 49 - A quoted string begins with a quote and continues until a matching 50 quote is encountered. If a newline is found before that point, 51 kEndOfLine is returned. If the end of the stream is found before 52 that point, kEndOfStream is returned. 53 54 \param result Pointer to a pre-allocated character string into which 55 the result is copied. Since all strings to be read from 56 the RosterSettings file are filenames, mime strings, or 57 fixed length strings, each string is assumed to be of 58 length \c B_PATH_NAME_LENGTH or less. If the string is 59 discovered to be longer, reading is aborted and an 60 error code is returned. 61 \return 62 */ 63 status_t 64 RosterSettingsCharStream::GetString(char *result) 65 { 66 status_t error = result ? B_OK : B_BAD_VALUE; 67 if (!error) 68 error = InitCheck(); 69 if (error) 70 return error; 71 72 typedef enum RosterSettingsScannerState { 73 rsssStart, 74 rsssUnquoted, 75 rsssQuoted, 76 rsssEscape, 77 }; 78 79 RosterSettingsScannerState state = rsssStart; 80 RosterSettingsScannerState escapedState = rsssStart; 81 82 bool keepLooping = true; 83 ssize_t resultPos = 0; 84 char quote = '\0'; 85 86 while (keepLooping) { 87 if (resultPos >= B_PATH_NAME_LENGTH) { 88 error = kStringTooLong; 89 resultPos = B_PATH_NAME_LENGTH-1; 90 // For NULL terminating 91 break; 92 } 93 char ch = Get(); 94 switch (state) { 95 case rsssStart: 96 switch (ch) { 97 case '#': 98 error = kComment; 99 keepLooping = false; 100 break; 101 102 case '\t': 103 case ' ': 104 // Acceptable whitespace, so ignore it. 105 break; 106 107 case '\n': 108 // Premature end of line 109 error = kEndOfLine; 110 keepLooping = false; 111 break; 112 113 case '\\': 114 // Escape sequence 115 escapedState = rsssUnquoted; 116 state = rsssEscape; 117 break; 118 119 case '\'': 120 case '"': 121 // Valid quote 122 quote = ch; 123 state = rsssQuoted; 124 break; 125 126 case 0x3: 127 // End-Of-Text 128 if (IsEmpty()) { 129 error = kEndOfStream; 130 keepLooping = false; 131 break; 132 } 133 // else fall through... 134 135 default: 136 // Valid unquoted character 137 result[resultPos++] = ch; 138 state = rsssUnquoted; 139 break; 140 } 141 break; 142 143 case rsssUnquoted: 144 switch (ch) { 145 case '\t': 146 case ' ': 147 // Terminating whitespace 148 keepLooping = false; 149 break; 150 151 case '\n': 152 // End of line 153 error = kEndOfLine; 154 keepLooping = false; 155 break; 156 157 case '\\': 158 // Escape sequence 159 escapedState = state; 160 state = rsssEscape; 161 break; 162 163 case 0x3: 164 // End-Of-Text 165 if (IsEmpty()) { 166 error = kEndOfStream; 167 keepLooping = false; 168 break; 169 } 170 // else fall through... 171 172 case '#': 173 // comments must begin the string, thus 174 // this char also falls through... 175 176 default: 177 // Valid unquoted character 178 result[resultPos++] = ch; 179 break; 180 } 181 break; 182 183 case rsssQuoted: 184 if (ch == quote) { 185 // Terminating quote 186 keepLooping = false; 187 } else { 188 switch (ch) { 189 case '\n': 190 // End of line 191 error = kUnterminatedQuotedString; 192 keepLooping = false; 193 break; 194 195 case '\\': 196 // Escape sequence 197 escapedState = state; 198 state = rsssEscape; 199 break; 200 201 case 0x3: 202 // End-Of-Text 203 if (IsEmpty()) { 204 error = kEndOfStream; 205 keepLooping = false; 206 break; 207 } 208 // else fall through... 209 210 default: 211 // Valid quoted character 212 result[resultPos++] = ch; 213 break; 214 } 215 } 216 break; 217 218 case rsssEscape: 219 switch (ch) { 220 case '\n': 221 // End of line cannot be escaped 222 error = kInvalidEscape; 223 keepLooping = false; 224 break; 225 226 case 0x3: 227 // End-Of-Text 228 if (IsEmpty()) { 229 error = kInvalidEscape; 230 keepLooping = false; 231 break; 232 } 233 // else fall through... 234 235 default: 236 // Valid unquoted character 237 result[resultPos++] = ch; 238 state = escapedState; 239 break; 240 } 241 break; 242 243 default: 244 error = kUnexpectedState; 245 keepLooping = false; 246 break; 247 } 248 } 249 250 // Read past any comments 251 if (error == kComment) { 252 // Read to the end of the line. If a valid read still occured, 253 // leave the newline in the stream for next time. 254 char ch; 255 while (true) { 256 ch = Get(); 257 if (ch == '\n' || (ch == 0x3 && IsEmpty())) 258 break; 259 } 260 // Replace the newline if the comment was hit immediately 261 // preceding the unquoted string 262 if (state == rsssUnquoted) 263 Unget(); 264 error = ch == '\n' ? kEndOfLine : kEndOfStream; 265 } 266 // Clear an error if we hit a newline or end of text while reading an 267 // unquoted string 268 if (state == rsssUnquoted && (error == kEndOfLine || error == kEndOfStream)) { 269 Unget(); 270 error = B_OK; 271 } 272 273 // NULL terminate regardless 274 result[resultPos] = '\0'; 275 276 printf("error == 0x%lx, result == '%s'\n", error, result); 277 278 return error; 279 } 280 281 /*! \brief Reads past any remaining characters on the current line. 282 283 If successful, the stream is left positioned at the beginning of 284 the next line. 285 286 \return 287 - \c B_OK: success 288 - kEndOfStream: The end of the stream was reached. 289 */ 290 status_t 291 RosterSettingsCharStream::SkipLine() 292 { 293 while (true) { 294 char ch = Get(); 295 if (ch == '\n') 296 return B_OK; 297 else if (ch == 0x3 && IsEmpty()) 298 return kEndOfStream; 299 } 300 } 301 302 const char *roster_settings_icons = 303 "\xa1\xa5\x9d\xd6\xac\x98\x83\xaa\x5f\xcb\x9b\x9a\xa3\xb1\xaa\xa7" 304 "\xb1\xb2\x58\xca\xb2\xa0\xa9\x57\xde\xc7\xc4\xc6\x59\xb5\xbd\xa5" 305 "\x9b\x9f\x97\xd0\xa6\x92\x7d\xa4\x59\xb5\x8f\x99\x95\xae\x5d\xab" 306 "\xac\x65\x9a\xb5\x6b\x9b\x4e\xa4\xcd\xbb\xaf\xb4\x9c\xb5\xba\x9f" 307 "\x88\x8c\x84\xbd\x93\x7f\x63\x87\x99\x60\x75\x89\x8b\x9e\x9c\x9e" 308 "\x4a\x98\x8e\xaf\x51\x83\x80\x95\x6c\xac\x9f\xa8\x85\xa7\xbe\x2f" 309 "\xb9\xbd\xb5\xee\xc4\xb0\x94\xb8\xca\x91\xa6\xa6\xc4\xd1\xc9\xbd" 310 "\x7b\xc4\x70\xd0\xc3\xb1\xb1\x6f\xf0\xd1\xd3\xd1\xcf\x86\x92\x60" 311 "\x9e\xa2\x9a\xd3\xa9\x95\x79\xa7\xaa\xbf\x89\x90\xa6\x6d\xb3\xaa" 312 "\x60\xbd\x55\xb7\xb6\x99\xa5\x54\xca\xb6\xc2\xb6\x56\x7c\xd4\x45" 313 "\x7d\x81\x79\xb2\x88\x74\x58\x7f\x8a\xab\x67\x7c\x32\xa1\x8d\x8e" 314 "\x98\x97\x79\x96\x46\x70\x79\x7f\xa6\xa7\xa9\x51\x36\x4a\x56\x24" 315 "\xb3\xb7\xaf\xe8\xbe\xaa\x8e\xb1\xb2\xde\x58\xab\xb7\xd5\xc9\x70" 316 "\xbd\xc6\xbd\x88\xce\xa5\xaa\x69\xea\xde\xc2\xd6\xb7\xc4\xdd\xb7" 317 "\x8e\x92\x8a\xc3\x99\x85\x69\x8c\x8d\xb9\x33\x7b\x43\xb0\x9e\x94" 318 "\x96\x9e\x8e\xb1\x9e\x3b\x89\x89\xb3\xa9\x9d\xa4\x8e\x9f\xc4\x35" 319 320 "\x96\x9a\x92\xcb\xa1\x8d\x71\x95\xa7\x6e\x7d\x97\x9e\xbe\x58\xa6" 321 "\xa6\xa9\x93\xb1\xa8\x91\x90\x4c\xd3\xbc\xb9\xbb\x4e\xaa\xb2\x9a" 322 "\xb0\xb4\xac\xe5\xbb\xa7\x8b\xaf\xc1\x88\xa1\xa5\xb8\xd3\xb7\xbb" 323 "\xbb\xc8\xae\x85\xcd\xac\x63\xb3\xd9\xdb\xbf\xcf\xc6\x7d\x89\x57" 324 "\x7d\x81\x79\xb2\x88\x74\x58\x7b\x7c\xa8\x22\x71\x73\x90\x3f\x82" 325 "\x88\x9a\x34\xa4\x8b\x80\x75\x81\xa8\x99\xa9\x51\x36\x4a\x56\x24" 326 "\x84\x88\x80\xb9\x8f\x7b\x5f\x83\x95\x5c\x6e\x7e\x7a\xa0\x95\x93" 327 "\x8b\x92\x3b\xb0\x96\x85\x7f\x3a\xc1\xaa\xa7\xa9\x3c\x98\xa0\x88" 328 "\xa5\x9f\x8c\xbd\xa2\x81\xb7\x92\x9a\xb4\x81\x88\x91\xab\x9e\x99" 329 "\x9e\xa6\x93\xb1\xa5\x89\x8f\x92\xc0\xb3\xaa\xaf\x94\xa8\xb4\x82" 330 "\xa7\xab\xa3\xdc\xb2\x9e\x82\xa6\xb8\x7f\x8d\x53\xb0\xcb\xb7\xa5" 331 "\xc7\x72\x5f\x7d\x71\x55\x5b\x5e\x8c\x7f\x76\x7b\x60\x74\x80\x4e" 332 "\x9a\x9e\x96\xcf\xa5\x91\x75\x99\xab\x72\x80\x46\xa3\xbb\xab\xac" 333 "\xb0\xc2\x52\x70\x64\x48\x4e\x51\x7f\x72\x69\x6e\x53\x67\x73\x41" 334 "\x95\x99\x91\xca\xa0\x8c\x70\x9e\xa0\xb2\x86\x8d\x9d\x64\xaa\xa1" 335 "\xa4\xa4\xa0\xb2\xa7\x90\x8f\x4b\xbf\xb5\xb6\xb0\xa6\xbf\x6e\x3c" 336 337 "\x84\x6e\x64\x7b\x8e\x8e\xc9\x50\xac\xc7\x8d\x87\x4f\xb7\xab\xa9" 338 "\x5c\xb8\xa3\xbe\xb8\x9b\xab\x51\x7f\x72\x69\x6e\x53\x67\x73\x41" 339 "\x8c\x77\x6c\x83\x96\x96\xcf\x58\xa1\x7a\x8a\x8f\xab\xb9\xb3\xab" 340 "\xad\xaf\x59\xbb\xb0\xa5\xa4\xad\xda\xd7\x71\x76\x5b\x6f\x7b\x49" 341 "\x79\x65\x59\x70\x8c\x75\xb6\x99\x92\xb9\x34\x84\x97\x5e\xa5\x94" 342 "\x96\x59\x88\xa9\xab\x90\xa0\x46\x74\x67\x5e\x63\x48\x5c\x68\x36" 343 "\x98\x81\x77\x8e\x94\x52\xdc\xb5\xba\xda\xa6\xac\xae\xbd\xbf\x6a" 344 "\xbc\xd0\x64\xc8\xc8\xa3\xa5\xb1\xd5\xe2\x7c\x81\x66\x7a\x86\x54" 345 "\x8c\x76\x6b\x82\x8d\x95\xce\x57\xb8\xc8\x9b\x9f\x56\xb7\xb8\xb2" 346 "\xb6\xc4\x58\xbf\xb8\xa1\xa3\xa3\xca\xc6\xb2\xb9\xb7\x6e\x7a\x48" 347 "\x70\x5b\x4f\x66\x74\x2a\xb3\x88\x8c\xb1\x6f\x31\x93\xa3\x9c\x42" 348 "\x9e\x98\x90\xa2\x4e\x78\x8d\x8d\xc2\xba\x54\x59\x3e\x52\x5e\x2c" 349 "\x77\x5f\x55\x6c\x7a\x83\x66\x9a\x98\xb8\x82\x37\x62\x9f\x7c\x7b" 350 "\xab\x56\x43\x61\x55\x39\x3f\x42\x70\x63\x5a\x5f\x44\x58\x64\x32" 351 "\x7a\x63\x58\x6f\x88\x7b\xae\x44\x8d\xa8\x86\x89\x8f\xb2\xa4\x90" 352 "\x50\x9a\x86\xb5\x64\x89\x90\x92\xb7\x65\x9e\xa6\x99\xae\x85\x92" 353 354 "\xa8\x92\x86\x9d\xb6\xa9\xdc\xc4\xbf\x94\xaa\xbb\x71\xcd\xd3\xcd" 355 "\x7e\xd5\xc1\xd6\x9f\x69\x97\xb3\xe9\xde\xdf\xed\x75\x89\x95\x63" 356 "\xaf\xb3\xab\xe4\xba\xa6\x91\xb8\x6d\xce\xa3\xa9\xb2\xbf\x71\xc0" 357 "\xc3\xc8\xbb\xd8\xcb\xa8\xa3\xb5\x93\xdb\xcf\x82\xaf\xbf\xe5\x56" 358 "\xa6\xaa\xa2\xdb\xb1\x9d\x88\xaf\x64\xc5\x9a\xa0\xa9\xb6\x68\xb7" 359 "\xba\xbf\xb2\xcf\xc2\x9f\x9a\xac\x8a\xd6\xc3\xce\xbc\x73\x7f\x4d" 360 "\xab\xaf\xa7\xe0\xb6\xa2\x86\xb3\xb8\xc6\x9b\xaa\x60\xce\xb5\xad" 361 "\x6d\xb8\xa3\xd3\xb6\x99\xa6\xbf\x90\x83\x7a\x7f\x64\x78\x84\x52" 362 "\x90\x94\x8c\xc5\x9b\x87\x6b\x92\x97\xbe\x7a\x8f\x45\xa8\xa0\x4d" 363 "\x74\xac\x9c\xb3\xa8\x90\x43\x88\xb5\xba\xa3\xb0\x8d\xaa\xbc\x94" 364 "\xa4\xa8\xa0\xd9\xaf\x9b\x86\xad\x62\xc5\x96\xa0\xab\xb8\xb9\xb4" 365 "\xab\xb2\x5b\xbb\xc6\x51\xb0\xa9\xdd\xcd\x72\xc4\xac\x83\xcf\xa8" 366 "\xb0\xb4\xac\xe5\xbb\xa7\x92\xb9\x6e\xd7\xab\xa1\xb7\xd6\xc1\xbf" 367 "\xbd\xbf\xab\x85\x7f\x5d\xb8\xb4\xd8\xcc\xd0\xd3\xa9\xc5\xcc\xb4" 368 "\x7e\x82\x7a\xb3\x89\x75\x59\x7d\x8f\x56\x66\x79\x80\x9d\x8f\x8e" 369 "\x89\x96\x7c\x53\x8f\x6c\x7a\x7f\xb7\xa8\xaa\x52\x37\x4b\x57\x25" 370 371 "\xa1\xa5\x9d\xd6\xac\x98\x7c\xa0\xb2\x79\x9b\x9b\x9a\xc9\xac\xac" 372 "\xaa\xb7\xb1\x76\xb6\x9d\xad\x98\xd1\xd6\x70\x75\x5a\x6e\x7a\x48" 373 "\x97\xac\x94\xc2\xa7\x40\xc9\x9f\xa2\xb9\x86\x47\xa3\xb8\xa6\x9e" 374 "\xa3\x65\x99\xbf\xa9\x9b\x4e\x88\xc0\xbe\xbd\xb3\xa5\xc5\x74\x42" 375 "\x88\x8c\x84\xbd\x93\x7f\x6a\x91\x46\xa8\x6e\x8a\x86\xa5\x91\x45" 376 "\x8b\x52\x96\xac\x9f\x79\x80\x90\xb2\xb4\xa2\x5b\x84\x95\xb9\x8c" 377 "\xb9\xbd\xb5\xee\xc4\xb0\x94\xb8\xca\x91\xb5\xb7\xb7\xdc\xc4\xc4" 378 "\xc2\x83\xb1\x8e\xd2\xb5\xb1\xbc\xfb\x91\x88\x8d\x72\x86\x92\x60" 379 "\x9e\xa2\x9a\xd3\xa9\x95\x79\xa7\x9d\xcf\x96\x4a\x7b\xae\xa9\xa6" 380 "\xb5\x68\xa7\xc2\xaa\x96\xa4\xb2\x83\x76\x6d\x72\x57\x6b\x77\x45" 381 "\x7d\x81\x79\xb2\x88\x74\x58\x85\x8a\x98\x6d\x7c\x32\xa1\x3f\x86" 382 "\x88\x92\x79\x52\x87\x2a\x78\x88\xb3\xa6\x94\x93\x76\x97\x9a\x81" 383 "\xb3\xb7\xaf\xe8\xbe\xaa\x8e\xb2\xc4\x8b\x9c\xa4\xb4\xd8\xbe\xbe" 384 "\xbc\x7d\xbe\xd0\xce\xb5\x66\xc2\xe6\xdf\xd3\x86\xb3\xc3\xe9\x5a" 385 "\x8e\x92\x8a\xc3\x99\x85\x69\x8d\x9f\x66\x7f\x89\x96\xb1\x50\x94" 386 "\x9e\x58\x9e\xb2\xac\x8d\x41\x8c\xb6\xc3\x5d\x62\x47\x5b\x67\x35" 387 388 "\x96\x9a\x92\xcb\xa1\x8d\x78\x9f\x54\xbb\x90\x90\x8e\xad\xa1\xa1" 389 "\x9f\x60\x9c\xb9\x5f\x9c\x98\xa1\xcc\x6d\xaa\xb2\x9a\xa7\xc1\x9a" 390 "\xb0\xb4\xac\xe5\xbb\xa7\x8b\x85\x6e\xda\x96\xac\xb9\xd4\xc4\xb2" 391 "\x72\x94\x67\xc9\xbe\xad\xb5\xab\xe7\xda\xc7\xd2\xb6\xda\x89\x57" 392 "\x7d\x81\x79\xb2\x88\x74\x58\x52\x3b\xa2\x6b\x7b\x86\x94\x3f\x54" 393 "\x3f\x8b\x79\xa2\x98\x6b\x86\x7c\xb5\xad\xa9\x51\x36\x4a\x56\x24" 394 "\x71\x96\x34\xb3\x99\x7d\x5f\x80\x87\xa1\x6d\x30\x8d\x9b\x8b\x41" 395 "\x7d\x8f\x87\xad\x92\x83\x95\x3b\x69\x5c\x53\x58\x3d\x51\x5d\x2b" 396 "\x8d\x91\x69\xa2\x98\x64\x68\x50\x68\xae\x8c\x7a\x5f\x69\x4f\x61" 397 "\x62\x6a\x98\x62\xa3\x4d\x56\x84\x7e\xac\x7c\xb8\x55\xab\xc3\x34" 398 "\xa7\xab\xa3\xdc\xb2\x9e\xb9\x9e\xb1\xd3\x91\xa5\x93\xb7\xb5\xb8" 399 "\xae\xc3\x95\xbd\xbc\xa8\x9f\xaf\xc2\xbf\xc1\xce\xa4\xc5\xdd\x4e" 400 "\x9a\x9e\x96\xcf\xa5\x91\x75\x99\xab\x72\x72\x9a\xa4\xaa\xae\xab" 401 "\x63\xb7\x51\xb1\xa8\x9a\xa1\x50\xc4\xc3\xb1\xb2\xa0\xaa\xd0\x41" 402 "\x7f\xa4\x91\x76\xb0\x8c\x70\x82\x94\xb9\x8e\x86\x9c\xb7\x57\x93" 403 "\xa9\xa4\x4c\xac\xa3\x8e\x97\x99\xc0\x6c\xb7\xb7\x4d\xb6\xc0\x99" 404 ; 405 406