1 /********************************************************************************
2 * Nepenthes
3 * - finest collection -
4 *
5 *
6 *
7 * Copyright (C) 2005 Paul Baecher & Markus Koetter
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 *
23 *
24 * contact nepenthesdev@users.sourceforge.net
25 *
26 *******************************************************************************/
27
28 /* $Id: bencoding.c 683 2006-10-27 19:29:58Z common $ */
29
30 #include <string.h>
31 #include <assert.h>
32 #include <ctype.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <unistd.h>
38
39 #include "bencoding.h"
40
41 #define BENCODING_OOM "Out of memory!"
42
43 static int32_t parseBuffer(Bencoding_Context *c, Bencoding_Item *item);
44 void debugItem(Bencoding_Item *item, uint32_t indent);
45 void freeItem(Bencoding_Item *item);
46 static inline uint32_t isEof(Bencoding_Context *c);
47
Bencoding_createContext()48 Bencoding_Context *Bencoding_createContext()
49 {
50 Bencoding_Context *c;
51
52 c = (Bencoding_Context *)malloc(sizeof(Bencoding_Context));
53
54 if ( c != NULL )
55 memset(c, 0, sizeof(Bencoding_Context));
56
57 return c;
58 };
59
Bencoding_destroyContext(Bencoding_Context * c)60 void Bencoding_destroyContext(Bencoding_Context *c)
61 {
62 uint32_t i;
63
64 if ( c->m_items.m_vector )
65 {
66 for ( i = 0; i < c->m_items.m_size; i++ )
67 freeItem(&(c->m_items.m_vector[i]));
68
69 free(c->m_items.m_vector);
70 }
71
72 free(c->m_buffer);
73 free(c);
74 };
75
Bencoding_getErrorMessage(Bencoding_Context * c)76 const char *Bencoding_getErrorMessage(Bencoding_Context *c)
77 {
78 return c->m_errorMessage;
79 }
80
Bencoding_decodeBuffer(Bencoding_Context * c,const void * ptr,size_t len)81 int32_t Bencoding_decodeBuffer(Bencoding_Context *c, const void *ptr, size_t len)
82 {
83 c->m_items.m_vector = 0;
84 c->m_len = len;
85 c->m_buffer = malloc(len);
86
87 if ( c->m_buffer == NULL )
88 {
89 snprintf(c->m_errorMessage, sizeof(c->m_errorMessage), "%s", BENCODING_OOM);
90 return -1;
91 }
92
93 memcpy(c->m_buffer, ptr, len);
94
95 c->m_ptr = (uint8_t *)c->m_buffer;
96 c->m_offset = 0;
97
98 c->m_items.m_size = 0;
99 c->m_items.m_iterator = 0;
100 c->m_items.m_capacity = 4;
101 c->m_items.m_vector = (Bencoding_Item *)malloc(sizeof(Bencoding_Item) * c->m_items.m_capacity);
102 if ( c->m_items.m_vector == NULL )
103 {
104 snprintf(c->m_errorMessage, sizeof(c->m_errorMessage), "%s", BENCODING_OOM);
105 return -1;
106 }
107
108 while ( !isEof(c) )
109 {
110 if ( c->m_items.m_size == c->m_items.m_capacity )
111 {
112 c->m_items.m_capacity *= 2;
113 Bencoding_Item *newvector = (Bencoding_Item *)realloc((void *)c->m_items.m_vector,
114 sizeof(Bencoding_Item) * c->m_items.m_capacity);
115
116 if ( newvector == NULL )
117 {
118 snprintf(c->m_errorMessage, sizeof(c->m_errorMessage), "%s", BENCODING_OOM);
119 return -1;
120 }
121
122 c->m_items.m_vector = newvector;
123 }
124
125 if ( parseBuffer(c, &(c->m_items.m_vector[c->m_items.m_size])) == -1 )
126 return -1;
127
128 c->m_items.m_size++;
129 }
130
131 return 0;
132 }
133
Bencoding_getNext(Bencoding_Context * c)134 Bencoding_Item *Bencoding_getNext(Bencoding_Context *c)
135 {
136 if ( !(c->m_items.m_iterator < c->m_items.m_size) )
137 return NULL;
138
139 return &(c->m_items.m_vector[c->m_items.m_iterator++]);
140 }
141
142 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
143
advance(Bencoding_Context * c)144 static inline void advance(Bencoding_Context *c)
145 {
146 c->m_ptr++;
147 c->m_offset++;
148 }
149
isEof(Bencoding_Context * c)150 static inline uint32_t isEof(Bencoding_Context *c)
151 {
152 return !(c->m_offset < c->m_len);
153 }
154
155 /* look at the next char, don't advance, -1 on error. */
peekChar(Bencoding_Context * c,uint8_t * ch)156 static inline int32_t peekChar(Bencoding_Context *c, uint8_t *ch)
157 {
158 if ( isEof(c) )
159 {
160 snprintf(c->m_errorMessage, sizeof(c->m_errorMessage),
161 "Got premature end of data at position %d",
162 c->m_offset);
163 return -1;
164 }
165
166 *ch = *(c->m_ptr);
167 return 0;
168 }
169
170 /* read one char from the stream, -1 on error.*/
readChar(Bencoding_Context * c,uint8_t * ch)171 static inline int32_t readChar(Bencoding_Context *c, uint8_t *ch)
172 {
173 if ( isEof(c) )
174 {
175 snprintf(c->m_errorMessage, sizeof(c->m_errorMessage),
176 "Got premature end of data at position %d",
177 c->m_offset);
178 return -1;
179 }
180
181 *ch = *(c->m_ptr);
182 advance(c);
183 return 0;
184 }
185
186 /* require the presence of a specific char on the stream, -1 on error. */
consumeChar(Bencoding_Context * c,uint8_t ch)187 inline int32_t consumeChar(Bencoding_Context *c, uint8_t ch)
188 {
189 uint8_t chr;
190
191 if ( readChar(c, &chr) == -1 )
192 {
193 snprintf(c->m_errorMessage, sizeof(c->m_errorMessage),
194 "Expected 0x%02x (`%c'), but got premature end of data at position %d",
195 ch, isprint(ch) ? ch : '.', c->m_offset);
196 return -1;
197 }
198
199 if ( chr != ch )
200 {
201 snprintf(c->m_errorMessage, sizeof(c->m_errorMessage),
202 "Expected 0x%02x (`%c'), but got 0x%02x (`%c') at position %d",
203 ch, isprint(ch) ? ch : '.', chr, isprint(chr) ? chr : '.',
204 c->m_offset);
205 return -1;
206 }
207
208 return 0;
209 }
210
readInt(Bencoding_Context * c,int32_t * value)211 int32_t readInt(Bencoding_Context *c, int32_t *value)
212 {
213 uint8_t premature = 1, neg = 0;
214 *value = 0;
215
216 if ( !isEof(c) && *(c->m_ptr) == '-' )
217 {
218 neg = 1;
219 advance(c);
220 }
221 if ( !isEof(c) && *(c->m_ptr) == '0' )
222 {
223 advance(c);
224 return 0;
225 }
226
227 if ( !isdigit(*(c->m_ptr)) )
228 {
229 snprintf(c->m_errorMessage, sizeof(c->m_errorMessage),
230 "Got non digit character 0x%02x (`%c') for integer value at position %d",
231 *(c->m_ptr), isprint(*(c->m_ptr)) ? *(c->m_ptr) : '.', c->m_offset);
232 return -1;
233 }
234
235 while ( !isEof(c) && isdigit(*(c->m_ptr)) )
236 {
237 premature = 0;
238 *value = *value * 10 + (*(c->m_ptr) - '0');
239 advance(c);
240 }
241
242 if ( neg )
243 *value *= -1;
244
245 if ( premature )
246 {
247 snprintf(c->m_errorMessage, sizeof(c->m_errorMessage),
248 "Expected digit, but got premature end of data at position %d",
249 c->m_offset);
250 return -1;
251 }
252
253 return 0;
254 }
255
readString(Bencoding_Context * c,Bencoding_String * str)256 int32_t readString(Bencoding_Context *c, Bencoding_String *str)
257 {
258 uint32_t len, i;
259
260 if ( readInt(c, (int32_t *)&len) == -1 )
261 return -1;
262
263 if ( consumeChar(c, ':') == -1 )
264 return -1;
265
266 str->m_data = (void *)c->m_ptr;
267 str->m_len = len;
268
269 for ( i = 0; i < len; i++ )
270 {
271 if ( isEof(c) )
272 {
273 snprintf(c->m_errorMessage, sizeof(c->m_errorMessage), "Premature end of encoded string at position %d",
274 c->m_offset);
275 return -1;
276 }
277 advance(c);
278 }
279
280 return 0;
281 }
282
parseBuffer(Bencoding_Context * c,Bencoding_Item * item)283 int32_t parseBuffer(Bencoding_Context *c, Bencoding_Item *item)
284 {
285 assert(!isEof(c));
286
287 uint32_t i;
288 int32_t error;
289 uint8_t ch;
290
291 switch ( *(c->m_ptr) )
292 {
293 case 'i': /* integer */
294 advance(c); /* l */
295 // if( consumeChar(c, ':') == -1 )
296 // return -1;
297
298 if ( readInt(c, (int32_t *)&i) == -1 )
299 return -1;
300
301 if ( consumeChar(c, 'e') == -1 )
302 return -1;
303
304 item->m_type = Bencoding_TypeInt;
305 item->m_int = i;
306 printf("read int\n");
307 break;
308
309 case 'l': /* list */
310 advance(c); /* l */
311 printf("found list\n");
312 item->m_type = Bencoding_TypeList;
313
314 item->m_list.m_size = 0;
315 item->m_list.m_capacity = 4;
316 item->m_list.m_vector = (Bencoding_Item *)malloc(sizeof(Bencoding_Item) * item->m_list.m_capacity);
317 if ( item->m_list.m_vector == NULL )
318 {
319 snprintf(c->m_errorMessage, sizeof(c->m_errorMessage), "%s", BENCODING_OOM);
320 return -1;
321 }
322
323 while ( (error = peekChar(c, &ch)) != -1 && ch != 'e' )
324 {
325 if ( item->m_list.m_size == item->m_list.m_capacity )
326 {
327 item->m_list.m_capacity *= 2;
328 Bencoding_Item *newvec = (Bencoding_Item *)realloc((void *)item->m_list.m_vector,
329 sizeof(Bencoding_Item) * item->m_list.m_capacity);
330 if ( newvec == NULL )
331 {
332 snprintf(c->m_errorMessage, sizeof(c->m_errorMessage), "%s", BENCODING_OOM);
333 return -1;
334 }
335
336 item->m_list.m_vector = newvec;
337 }
338
339 if ( parseBuffer(c, &(item->m_list.m_vector[item->m_list.m_size])) == -1 )
340 {
341 freeItem(item);
342 return -1;
343 }
344
345 item->m_list.m_size++;
346 }
347
348 if ( error == -1 )
349 {
350 freeItem(item);
351 return -1;
352 }
353 else
354 advance(c); /* e */
355
356 printf("read list\n");
357 break;
358
359 case 'd': /* dictionary */
360 advance(c); /* d */
361 printf("found dict\n");
362 item->m_type = Bencoding_TypeDict;
363
364 item->m_dict.m_size = 0;
365 item->m_dict.m_capacity = 2;
366 item->m_dict.m_keys = (Bencoding_String *)malloc(sizeof(Bencoding_String) * item->m_dict.m_capacity);
367 item->m_dict.m_values = (Bencoding_Item *)malloc(sizeof(Bencoding_Item) * item->m_dict.m_capacity);
368
369 if ( item->m_dict.m_keys == NULL || item->m_dict.m_values == NULL )
370 {
371 snprintf(c->m_errorMessage, sizeof(c->m_errorMessage), "%s", BENCODING_OOM);
372 return -1;
373 }
374
375 while ( (error = peekChar(c, &ch)) != -1 && ch != 'e' )
376 {
377 if ( item->m_dict.m_size == item->m_dict.m_capacity )
378 {
379 item->m_dict.m_capacity *= 2;
380 Bencoding_String *newkeys = (Bencoding_String *)realloc((void *)item->m_dict.m_keys,
381 sizeof(Bencoding_String) * item->m_dict.m_capacity);
382 Bencoding_Item *newvalues = (Bencoding_Item *)realloc((void *)item->m_dict.m_values,
383 sizeof(Bencoding_Item) * item->m_dict.m_capacity);
384
385 if ( newkeys == NULL || newvalues == NULL )
386 {
387 snprintf(c->m_errorMessage, sizeof(c->m_errorMessage), "%s", BENCODING_OOM);
388 return -1;
389 }
390
391 item->m_dict.m_keys = newkeys;
392 item->m_dict.m_values = newvalues;
393 }
394
395 /* read key */
396 if ( readString(c, &(item->m_dict.m_keys[item->m_dict.m_size])) == -1 )
397 {
398 freeItem(item);
399 return -1;
400 }
401
402 /* val */
403 if ( parseBuffer(c, &(item->m_dict.m_values[item->m_dict.m_size])) == -1 )
404 {
405 freeItem(item);
406 return -1;
407 }
408
409 item->m_dict.m_size++;
410 }
411
412 if ( error == -1 )
413 {
414 freeItem(item);
415 return -1;
416 }
417 else
418 advance(c); /* e */
419 printf("read dict\n");
420 break;
421
422 case '0': /* string (length-prefixed) */
423 case '1':
424 case '2':
425 case '3':
426 case '4':
427 case '5':
428 case '6':
429 case '7':
430 case '8':
431 case '9':
432 item->m_type = Bencoding_TypeString;
433
434 if ( readString(c, &(item->m_string)) == -1 )
435 return -1;
436
437 printf("read string\n");
438 break;
439
440 default:
441 snprintf(c->m_errorMessage, sizeof(c->m_errorMessage), "Invalid character 0x%02x (`%c') at position %d",
442 *(c->m_ptr), isprint(*(c->m_ptr)) ? *(c->m_ptr) : '.', c->m_offset);
443 return -1;
444 break;
445 }
446
447 return 0;
448 }
449
450
printIndent(uint32_t indent)451 inline void printIndent(uint32_t indent)
452 {
453 while ( indent-- )
454 printf(" ");
455 }
456
debugItem(Bencoding_Item * item,uint32_t indent)457 void debugItem(Bencoding_Item *item, uint32_t indent)
458 {
459 uint32_t i, j;
460 switch ( item->m_type )
461 {
462 case Bencoding_TypeInt:
463 printIndent(indent); printf("(int) %d\n", item->m_int);
464 break;
465
466 case Bencoding_TypeList:
467 printIndent(indent); printf("(list)\n");
468
469 for ( i = 0; i < item->m_list.m_size; i++ )
470 debugItem(&(item->m_list.m_vector[i]), indent + 1);
471 break;
472
473 case Bencoding_TypeString:
474 printIndent(indent); printf("(string) (%i bytes)\n", item->m_string.m_len);
475 printIndent(indent);
476 for ( i = 1; i <= item->m_string.m_len; i++ )
477 {
478 if ( isprint( ( (uint8_t *)item->m_string.m_data )[i-1] ) )
479 printf("%c", ((uint8_t *)item->m_string.m_data)[i-1]);
480 else
481
482 printf("%02x", ((uint8_t *)item->m_string.m_data)[i-1]);
483 if ( i % 20 == 0 && 0 )
484 {
485 printf("\n");
486 printIndent(indent);
487 }
488 }
489 printf("\n");
490 break;
491
492 case Bencoding_TypeDict:
493 printIndent(indent); printf("(dict)\n");
494 for ( i = 0; i < item->m_dict.m_size; i++ )
495 {
496 printIndent(indent + 1);
497 for ( j = 0; j < item->m_dict.m_keys[i].m_len; j++ )
498 printf("%c", ((uint8_t *)item->m_dict.m_keys[i].m_data)[j]);
499 printf(" -->\n");
500 debugItem(&(item->m_dict.m_values[i]), indent + 1);
501 }
502 break;
503
504 default:
505 break;
506 }
507 }
508
freeItem(Bencoding_Item * item)509 void freeItem(Bencoding_Item *item)
510 {
511 uint32_t i;
512
513 switch ( item->m_type )
514 {
515 case Bencoding_TypeList:
516 for ( i = 0; i < item->m_list.m_size; i++ )
517 freeItem(&(item->m_list.m_vector[i]));
518 free(item->m_list.m_vector);
519 break;
520 case Bencoding_TypeDict:
521 for ( i = 0; i < item->m_dict.m_size; i++ )
522 freeItem(&(item->m_dict.m_values[i]));
523 free(item->m_dict.m_keys);
524 free(item->m_dict.m_values);
525 break;
526 default:
527 return;
528 }
529
530 }
531
532
533