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