vfs: check userland buffers before reading them.
[haiku.git] / src / servers / registrar / RosterSettingsCharStream.cpp
blob497e13c591e92ca0c672eb7f81dd2e3b017e09e2
1 /*
2 * Copyright 2002-2009, Haiku Inc.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Tyler Dauwalder
7 */
10 #include "RosterSettingsCharStream.h"
12 #include <sniffer/Err.h>
13 #include <StorageDefs.h>
15 #include <stdio.h>
17 #include "Debug.h"
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;
28 using namespace BPrivate::Storage::Sniffer;
31 RosterSettingsCharStream::RosterSettingsCharStream(const std::string &string)
33 CharStream(string)
38 RosterSettingsCharStream::RosterSettingsCharStream()
40 CharStream()
45 RosterSettingsCharStream::~RosterSettingsCharStream()
50 /*! \brief Reads the next string from the stream
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.
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
85 status_t
86 RosterSettingsCharStream::GetString(char *result)
88 status_t error = result ? B_OK : B_BAD_VALUE;
89 if (!error)
90 error = InitCheck();
91 if (error)
92 return error;
94 enum RosterSettingsScannerState {
95 rsssStart,
96 rsssUnquoted,
97 rsssQuoted,
98 rsssEscape,
101 RosterSettingsScannerState state = rsssStart;
102 RosterSettingsScannerState escapedState = rsssStart;
104 bool keepLooping = true;
105 ssize_t resultPos = 0;
106 char quote = '\0';
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;
115 char ch = Get();
116 switch (state) {
117 case rsssStart:
118 switch (ch) {
119 case '#':
120 error = kComment;
121 keepLooping = false;
122 break;
124 case '\t':
125 case ' ':
126 // Acceptable whitespace, so ignore it.
127 break;
129 case '\n':
130 // Premature end of line
131 error = kEndOfLine;
132 keepLooping = false;
133 break;
135 case '\\':
136 // Escape sequence
137 escapedState = rsssUnquoted;
138 state = rsssEscape;
139 break;
141 case '\'':
142 case '"':
143 // Valid quote
144 quote = ch;
145 state = rsssQuoted;
146 break;
148 case 0x3:
149 // End-Of-Text
150 if (IsEmpty()) {
151 error = kEndOfStream;
152 keepLooping = false;
153 break;
155 // else fall through...
157 default:
158 // Valid unquoted character
159 result[resultPos++] = ch;
160 state = rsssUnquoted;
161 break;
163 break;
165 case rsssUnquoted:
166 switch (ch) {
167 case '\t':
168 case ' ':
169 // Terminating whitespace
170 keepLooping = false;
171 break;
173 case '\n':
174 // End of line
175 error = kEndOfLine;
176 keepLooping = false;
177 break;
179 case '\\':
180 // Escape sequence
181 escapedState = state;
182 state = rsssEscape;
183 break;
185 case 0x3:
186 // End-Of-Text
187 if (IsEmpty()) {
188 error = kEndOfStream;
189 keepLooping = false;
190 break;
192 // else fall through...
194 case '#':
195 // comments must begin the string, thus
196 // this char also falls through...
198 default:
199 // Valid unquoted character
200 result[resultPos++] = ch;
201 break;
203 break;
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;
217 case '\\':
218 // Escape sequence
219 escapedState = state;
220 state = rsssEscape;
221 break;
223 case 0x3:
224 // End-Of-Text
225 if (IsEmpty()) {
226 error = kEndOfStream;
227 keepLooping = false;
228 break;
230 // else fall through...
232 default:
233 // Valid quoted character
234 result[resultPos++] = ch;
235 break;
238 break;
240 case rsssEscape:
241 switch (ch) {
242 case '\n':
243 // End of line cannot be escaped
244 error = kInvalidEscape;
245 keepLooping = false;
246 break;
248 case 0x3:
249 // End-Of-Text
250 if (IsEmpty()) {
251 error = kInvalidEscape;
252 keepLooping = false;
253 break;
255 // else fall through...
257 default:
258 // Valid unquoted character
259 result[resultPos++] = ch;
260 state = escapedState;
261 break;
263 break;
265 default:
266 error = kUnexpectedState;
267 keepLooping = false;
268 break;
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;
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;
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;
295 // NULL terminate regardless
296 result[resultPos] = '\0';
298 D(PRINT("error == 0x%" B_PRIx32 ", result == '%s'\n", error, result));
300 return error;
304 /*! \brief Reads past any remaining characters on the current line.
306 If successful, the stream is left positioned at the beginning of
307 the next line.
309 \return
310 - \c B_OK: success
311 - kEndOfStream: The end of the stream was reached.
313 status_t
314 RosterSettingsCharStream::SkipLine()
316 while (true) {
317 char ch = Get();
318 if (ch == '\n')
319 return B_OK;
320 else if (ch == 0x3 && IsEmpty())
321 return kEndOfStream;
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"
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"
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"
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"
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"
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";