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