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