~ubuntu-branches/ubuntu/wily/maradns/wily-proposed

« back to all changes in this revision

Viewing changes to deadwood-3.2.07/src/DwStr.c

  • Committer: Package Import Robot
  • Author(s): Dariusz Dwornikowski, Tomasz Buchert, Dariusz Dwornikowski
  • Date: 2015-03-27 18:34:08 UTC
  • mfrom: (1.2.12)
  • Revision ID: package-import@ubuntu.com-20150327183408-wnfachdkdjt96yu6
Tags: 2.0.11-1
[ Tomasz Buchert ]
* Imported Upstream version 2.0.11

[ Dariusz Dwornikowski ]
* d/patches: 
  - refreshed all patches for new deadwood version
  - removed generating of random prime on build (Closes: #785536) 
* d/rules: date taken from changelog (Closes: #785535)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 2007-2014 Sam Trenholme
 
2
 *
 
3
 * TERMS
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 *
 
9
 * 1. Redistributions of source code must retain the above copyright
 
10
 *    notice, this list of conditions and the following disclaimer.
 
11
 * 2. Redistributions in binary form must reproduce the above copyright
 
12
 *    notice, this list of conditions and the following disclaimer in the
 
13
 *    documentation and/or other materials provided with the distribution.
 
14
 *
 
15
 * This software is provided 'as is' with no guarantees of correctness or
 
16
 * fitness for purpose.
 
17
 */
 
18
 
 
19
#include "DwStr.h"
 
20
#include "DwSys.h" /* So we can log errors */
 
21
 
 
22
/* Make sure a dw_str object is sane.
 
23
 * Input: Pointer to dw_str
 
24
 * Output: 0 if sane; -1 if not */
 
25
 
 
26
int dw_assert_sanity(dw_str *object) {
 
27
        if(object == 0) {
 
28
                return -1;
 
29
        }
 
30
        if(object->sane != 114) {
 
31
                return -1;
 
32
        }
 
33
        if(object->str == 0) {
 
34
                return -1;
 
35
        }
 
36
        if(object->len >= object->max) {
 
37
                return -1;
 
38
        }
 
39
        if(object->len > 0x0fffffff) {
 
40
                return -1;
 
41
        }
 
42
        return 0;
 
43
}
 
44
 
 
45
/* Create a new dw_str object.
 
46
 * Input: Maximum length allowed for the string
 
47
 * Output: Pointer to newly created string
 
48
 */
 
49
dw_str *dw_create(uint32_t size) {
 
50
        dw_str *new;
 
51
        new = dw_malloc(sizeof(dw_str));
 
52
        if(new == 0) {
 
53
                return 0; /* We should probably give an "aiee" and
 
54
                           * exit(1) here */
 
55
        }
 
56
        if(size >= 134217728 /* 2 ** 27 */) {
 
57
                free(new);
 
58
                return 0;
 
59
        }
 
60
        /* 2 byte cushion to avoid off-by-one security problems */
 
61
        new->str = dw_malloc(size + 2);
 
62
        if(new->str == 0) {
 
63
                free(new);
 
64
                return 0;
 
65
        }
 
66
        new->len = 0;
 
67
        new->max = size;
 
68
        new->sane = 114;
 
69
        return new;
 
70
}
 
71
 
 
72
/* Destroy a dw_str object.
 
73
 * Input: Pointer to string to destroy
 
74
 * Output: 0 on success; -1 on failure
 
75
 */
 
76
int dw_destroy(dw_str *object) {
 
77
        if(object == 0) {
 
78
                return -1;
 
79
        }
 
80
        /* Make sure we are, in fact, destroying a dw_str object */
 
81
        if(object->sane != 114) {
 
82
                return -1;
 
83
        }
 
84
        if(object->str == 0) {
 
85
                free(object);
 
86
                return -1;
 
87
        }
 
88
        free(object->str);
 
89
        /* Reset values just in case we try and use a freed string */
 
90
        object->str = 0;
 
91
        object->sane = 0;
 
92
        object->len = 0;
 
93
        object->max = 0;
 
94
        free(object);
 
95
        return 0;
 
96
}
 
97
 
 
98
/* Add a single character to the DwStr */
 
99
 
 
100
int dw_addchar(uint8_t add, dw_str *object) {
 
101
        if(dw_assert_sanity(object) == -1) {
 
102
                return -1;
 
103
        }
 
104
        if(object->max > object->len + 1) {
 
105
                *(object->str + object->len) = add;
 
106
                object->len++;
 
107
        } else {
 
108
                return -1;
 
109
        }
 
110
        return 0;
 
111
}
 
112
 
 
113
/* Add a C-string (which may have NULL characters) to a DwStr object.
 
114
 * Input: Pointer to string; number of characters we will add to DwStr
 
115
 * object; pointer to dw_str object.  Output: -1 on error; 0 on success */
 
116
int dw_cstr_append(uint8_t *add, int32_t len, dw_str *obj) {
 
117
        if(dw_assert_sanity(obj) == -1) {
 
118
                return -1;
 
119
        }
 
120
        if(add == 0) {
 
121
                return -1;
 
122
        }
 
123
        if(len < 0) {
 
124
                return -1;
 
125
        }
 
126
        if(obj->len + len >= obj->max) { /* Bounds checking */
 
127
                return -1;
 
128
        }
 
129
        while(len > 0) {
 
130
                *(obj->str + obj->len) = *add;
 
131
                add++;
 
132
                obj->len++;
 
133
                len--;
 
134
        }
 
135
        return 0;
 
136
}
 
137
 
 
138
/* Add a null-terminated string to a DwStr; should the null-terminated string
 
139
 * have the character specified in 'nope', don't append that character and
 
140
 * stop appending to the string. Input: String to append; DwStr to append
 
141
 * to; 'nope' character we're not allowed to add (make this 0 if you want
 
142
 * to allow all non-NULL characters) */
 
143
int dw_qrappend(uint8_t *add, dw_str *object, char nope) {
 
144
        if(dw_assert_sanity(object) == -1) {
 
145
                return -1;
 
146
        }
 
147
        if(add == 0) {
 
148
                return -1;
 
149
        }
 
150
        while(*add != 0 && *add != nope && object->len < object->max) {
 
151
                *(object->str + object->len) = *add;
 
152
                add++;
 
153
                object->len++;
 
154
        }
 
155
        return 0;
 
156
}
 
157
 
 
158
#ifdef OTHER_STUFF
 
159
/* Add an arbitrary null-terminated string of length "len" to a DwStr object */
 
160
int dw_bin_append(uint8_t *add, int len, dw_str *object) {
 
161
        if(dw_assert_sanity(object) == -1) {
 
162
                return -1;
 
163
        }
 
164
        if(add == 0) {
 
165
                return -1;
 
166
        }
 
167
        while(*add != 0 && len > 0 && object->len < object->max) {
 
168
                *(object->str + object->len) = *add;
 
169
                add++;
 
170
                len--;
 
171
                object->len++;
 
172
        }
 
173
        return 0;
 
174
}
 
175
#endif /* OTHER_STUFF */
 
176
 
 
177
#ifdef OTHER_STUFF
 
178
/* Add a null-terminated string to a DwStr; if the DwStr is non-0 length,
 
179
 * first add a comma.  If the null-terminated string has a comma, stop
 
180
 * appending the string.
 
181
 * Input: C string to add; DwStr to add string to
 
182
 * Output: 0 on success; -1 on failure */
 
183
int dw_qspush(uint8_t *add, dw_str *object) {
 
184
        if(dw_assert_sanity(object) == -1) {
 
185
                return -1;
 
186
        }
 
187
        if(add == 0) {
 
188
                return -1;
 
189
        }
 
190
        /* Add a comma to the end if not first element */
 
191
        if(object->len > 0) {
 
192
                if(dw_addchar(',',object) == -1) {
 
193
                        return -1;
 
194
                }
 
195
        }
 
196
        /* Add the string to the end of the string */
 
197
        if(dw_qrappend(add,object,',') == -1) {
 
198
                return -1;
 
199
        }
 
200
        return 0;
 
201
}
 
202
#endif /* OTHER_STUFF */
 
203
 
 
204
#ifdef XTRA_STUFF
 
205
/* For debug purposes: Output a dw_str object on the standard output. */
 
206
void dw_stdout(dw_str *object) {
 
207
        uint8_t *look = 0, q = 0;
 
208
        uint32_t p = 0;
 
209
        if(dw_assert_sanity(object) == -1) {
 
210
                printf("Object at %p does not look kosher.\n",object);
 
211
                return;
 
212
        }
 
213
        /* We don't need this junk; it just makes it harder to debug */
 
214
        /*printf("Object at %p has length %d, max length %d, and string at %p\n"
 
215
               ,object,(int)object->len,(int)object->max,object->str);
 
216
        printf("Object's string is (non-printable-ASCII hex-escaped): ");*/
 
217
        look = object->str;
 
218
        for(p = 0 ; p < object->len; p++) {
 
219
                q = *(look + p);
 
220
                if(q >= 32 && q <= '~' /* Last ASCII char */) {
 
221
                        printf("%c",q);
 
222
                } else {
 
223
                        printf("\\x%02X",q); /* Hex */
 
224
                        /* printf(" %d \\x%02X ",p,q); */ /* Hex w/ offset */
 
225
                        /*printf("\\%03o",q); */ /* Octal */
 
226
                }
 
227
        }
 
228
        printf("\n");
 
229
        return;
 
230
}
 
231
#endif /* XTRA_STUFF */
 
232
 
 
233
/* Take some of, or all, of a dw_str, and copy it in to a new dw_str object.
 
234
 * return 0 (NULL) if there is an error copying the string.  The parameters
 
235
 * are:
 
236
 * 1) The dw_string we want to copy
 
237
 * 2) The first character we starting copying from.  If this value has
 
238
 *    a value of 0, then we start copying from the start of the
 
239
 *    string.  If this has a value of -1, then we start copying at
 
240
 *    the end of the string (meaning, we can only copy the very last
 
241
 *    character). -2 is the second-to-last character in the string; 1 is
 
242
 *    the second character in the string (c indexes, ugh)
 
243
 * 3) The number of characters we copy.  0 means no characters (making
 
244
 *    a zero-length string); 1 means 1 character, etc.  If this is negative
 
245
 *    then we copy relative to the end of the string.  In other words, if
 
246
 *    the length has a value of -1, we copy until the end of the string;
 
247
 *    if length has a value of -2, we copy until the second to last character
 
248
 *    in the string, etc.
 
249
 * 4) The maximum allowed length for the string.  Should this have a positive
 
250
 *    value or 0, the string is allowed to add that many characters to the end
 
251
 *    of the string (0: The string can not grow; 1: the string can grow by
 
252
 *    one character, etc).  If it has a value of -1, then the string has the
 
253
 *    same maximum permitted size as the string we are copying.  Otherwise,
 
254
 *    we return an error.
 
255
 *
 
256
 * Output: We create a new dw_str object, which has the copied substr.
 
257
 *
 
258
 * Some common parameters: dw_substr(str,0,-1,-1): Copies the entire string
 
259
 */
 
260
 
 
261
dw_str *dw_substr(dw_str *obj, int32_t begin, int32_t amount, int32_t max) {
 
262
        dw_str *copy = 0;
 
263
        int c = 0;
 
264
 
 
265
        if(dw_assert_sanity(obj) == -1) {
 
266
                goto catch_dw_substr;
 
267
        }
 
268
 
 
269
        /* Process negative arguments */
 
270
        if(begin < 0) {
 
271
                begin = obj->len + begin;
 
272
        }
 
273
        if(amount < 0) {
 
274
                amount = obj->len - begin + amount + 1;
 
275
        }
 
276
 
 
277
        /* Make the string */
 
278
        if(max >= 0) {
 
279
                copy = dw_create(amount + max + 1);
 
280
        } else if(max == -1) {
 
281
                copy = dw_create(obj->max);
 
282
        } else {
 
283
                goto catch_dw_substr;
 
284
        }
 
285
 
 
286
        if(copy == 0) {
 
287
                goto catch_dw_substr;
 
288
        }
 
289
 
 
290
        /* Do the actual copying */
 
291
        for(c = 0; c < amount; c++) {
 
292
                /* Bounds checking */
 
293
                if(c + begin > obj->len || c >= copy->max) {
 
294
                        break;
 
295
                }
 
296
                *(copy->str + c) = *(obj->str + begin + c);
 
297
        }
 
298
 
 
299
        copy->len = c;
 
300
 
 
301
        return copy;
 
302
 
 
303
        /* Error catcher */
 
304
catch_dw_substr:
 
305
        if(copy != 0) {
 
306
                dw_destroy(copy);
 
307
                copy = 0;
 
308
        }
 
309
        return 0;
 
310
 
 
311
}
 
312
 
 
313
/* Read a 16-bit big-endian string that is in a dw_str as a number.  DNS
 
314
 * commonly has these kinds of numbers (can you say 1983?)
 
315
 * Input: Pointer to dw_str object; offset where we will look for number
 
316
 * (0 is top of string; -1 is last two bytes of string)
 
317
 * Output: The number; -1 on error */
 
318
 
 
319
int32_t dw_fetch_u16(dw_str *object, int32_t offset) {
 
320
        uint8_t *look = 0;
 
321
        if(dw_assert_sanity(object) == -1) {
 
322
                return -1;
 
323
        }
 
324
        if(offset < 0) {
 
325
                offset = offset + object->len - 1;
 
326
        }
 
327
        if(offset + 1 > object->len || offset < 0) {
 
328
                return -1;
 
329
        }
 
330
        look = object->str;
 
331
        look += offset;
 
332
        return (*look << 8) | *(look + 1);
 
333
}
 
334
 
 
335
/* Read a 16-bit big-endian number at the end of a dw_str object, and
 
336
 * remove the string from the string object.  -1 on error */
 
337
int32_t dw_pop_u16(dw_str *object) {
 
338
        uint8_t *look = 0;
 
339
        if(dw_assert_sanity(object) == -1) {
 
340
                return -1;
 
341
        }
 
342
        if(object->len < 2) {
 
343
                return -1;
 
344
        }
 
345
        look = object->str + object->len - 2;
 
346
        object->len -= 2;
 
347
        return (*look << 8) | *(look + 1);
 
348
}
 
349
 
 
350
/* Read an 8-bit number at the end of a dw_str object, and
 
351
 * remove the string from the string object.  -1 on error */
 
352
int32_t dw_pop_u8(dw_str *object) {
 
353
        uint8_t *look = 0;
 
354
        if(dw_assert_sanity(object) == -1) {
 
355
                return -1;
 
356
        }
 
357
        if(object->len < 1) {
 
358
                return -1;
 
359
        }
 
360
        look = object->str + object->len - 1;
 
361
        object->len -= 1;
 
362
        return *look;
 
363
}
 
364
 
 
365
/* Read an 8-bit big-endian string that is in a dw_str as a number.
 
366
 * Input: Pointer to dw_str object; offset where we will look for number
 
367
 * (0 is top of string; negative numbers offsets from end of string [-1
 
368
 * last byte in string, -2 second-to-last byte in string, etc])
 
369
 * Output: The number; -1 on error */
 
370
 
 
371
int32_t dw_fetch_u8(dw_str *object, int32_t offset) {
 
372
        uint8_t *look = 0;
 
373
        if(dw_assert_sanity(object) == -1) {
 
374
                return -1;
 
375
        }
 
376
        if(offset < 0) {
 
377
                offset = object->len + offset;
 
378
        }
 
379
        if(offset > object->len || offset < 0) {
 
380
                return -1;
 
381
        }
 
382
        look = object->str;
 
383
        look += offset;
 
384
        return *look;
 
385
}
 
386
 
 
387
/* Put a 16-bit big-endian number (the argument "value") in a dw_str object.
 
388
 * Offset can be either a positive or negative number; should offset be
 
389
 * a positive number, then we put that byte in that many bytes from
 
390
 * the beginning of the string.  Should offset be a negative number, then
 
391
 * we put the number that many bytes from the end of the string.  This
 
392
 * function will, in certain cases make the string one or two bytes longer.
 
393
 * If offset is -1, then the number is added to the end of the string.
 
394
 * If offset is -2, then the number replaces the last byte of the string,
 
395
 * and adds a byte the the end of the string.  Should offset be 0, the
 
396
 * number replaces the first two numbers in the string (adding numbers
 
397
 * if needed)
 
398
 *
 
399
 * Should this function succeed, it will return a 0.  Otherwise, it
 
400
 * will return a -1 */
 
401
 
 
402
int dw_put_u16(dw_str *obj, uint16_t value, int32_t offset) {
 
403
        uint8_t *look = 0;
 
404
        if(dw_assert_sanity(obj) == -1) {
 
405
                return -1;
 
406
        }
 
407
 
 
408
        /* Process negative offset amount */
 
409
        if(offset < 0) {
 
410
                offset = obj->len + offset + 1;
 
411
        }
 
412
 
 
413
        /* We may need to expand the string to fit the number */
 
414
        if(offset > obj->len || obj->len > 0x0fffffff) {
 
415
                return -1;
 
416
        } else if(offset >= (int32_t)(obj->len & 0x0ffffff) - 1) { /* -Wall */
 
417
                int expand_by;
 
418
                expand_by = obj->len - offset + 2;
 
419
                if(obj->len + expand_by >= obj->max) {
 
420
                        return -1;
 
421
                }
 
422
                obj->len += expand_by;
 
423
                if(obj->len > obj->max) {
 
424
                        obj->len -= expand_by;
 
425
                        return -1;
 
426
                }
 
427
        }
 
428
 
 
429
        look = obj->str + offset;
 
430
        *look = (value >> 8) & 0xff;
 
431
        *(look + 1) = value & 0xff;
 
432
        return 0;
 
433
}
 
434
 
 
435
/* Put an 8-bit (the argument "value") in a dw_str object.
 
436
 * Offset can be either a positive or negative number; should offset be
 
437
 * a positive number, then we put that byte in that many bytes from
 
438
 * the beginning of the string.  Should offset be a negative number, then
 
439
 * we put the number that many bytes from the end of the string.  This
 
440
 * function will, in certain cases make the string one byte longer.
 
441
 * If offset is -1, then the number is added to the end of the string.
 
442
 *
 
443
 * Should offset be 0, the number replaces the first number in the string
 
444
 * (adding numbers if needed)
 
445
 *
 
446
 * Should this function succeed, it will return a 0.  Otherwise, it
 
447
 * will return a -1
 
448
 *
 
449
 * BUG: Does not work correctly with length-1 (1-byte) strings
 
450
 */
 
451
 
 
452
int dw_put_u8(dw_str *obj, uint8_t value, int32_t offset) {
 
453
        uint8_t *look = 0;
 
454
        if(dw_assert_sanity(obj) == -1) {
 
455
                return -1;
 
456
        }
 
457
 
 
458
        /* Process negative offset amount */
 
459
        if(offset < 0) {
 
460
                offset = obj->len + offset + 1;
 
461
        }
 
462
 
 
463
        /* We may need to expand the string to fit the number */
 
464
        if(offset > obj->len || obj->len > 0x0fffffff) {
 
465
                return -1;
 
466
        } else if(offset == (int32_t)(obj->len & 0x0ffffff)) { /* -Wall */
 
467
                obj->len++;
 
468
                if(obj->len > obj->max) {
 
469
                        obj->len--;
 
470
                        return -1;
 
471
                }
 
472
        }
 
473
 
 
474
        look = obj->str + offset;
 
475
        *look = value & 0xff;
 
476
        return 0;
 
477
}
 
478
 
 
479
#ifdef OTHER_STUFF
 
480
/* Read a single bit from a dw_str object.  The way we choose the bit is
 
481
 * to first choose the byte with the desired bit, then to choose the
 
482
 * bit in that byte.  0 is the least significant (rightmost) bit; 7 is the
 
483
 * most significant bit.
 
484
 * We return -1 on error, 0 if the bit is 0, and 1 if the bit is 1 */
 
485
int dw_get_bit(dw_str *obj, int32_t byte, int8_t bit) {
 
486
        int a = 0;
 
487
        uint8_t look;
 
488
        if(dw_assert_sanity(obj) == -1) {
 
489
                return -1;
 
490
        }
 
491
        if(byte >= obj->len || byte < 0) {
 
492
                return -1;
 
493
        }
 
494
        if(bit < 0 || bit > 7) {
 
495
                return -1;
 
496
        }
 
497
        look = *(obj->str + byte);
 
498
        a = 1;
 
499
        a <<= bit;
 
500
        if((look & a) == a) {
 
501
                return 1;
 
502
        } else {
 
503
                return 0;
 
504
        }
 
505
}
 
506
#endif /* OTHER_STUFF */
 
507
 
 
508
/* Compare two dw_string objects to see if they are the same (different max
 
509
 * lengths are allowed).  -1 on error, 0 if not the same, and 1 if they are
 
510
 * the same */
 
511
int dw_issame(dw_str *a, dw_str *b) {
 
512
        int c = 0;
 
513
        if(dw_assert_sanity(a) == -1) {
 
514
                return -1;
 
515
        }
 
516
        if(dw_assert_sanity(b) == -1) {
 
517
                return -1;
 
518
        }
 
519
        if(a->len != b->len) {
 
520
                return 0;
 
521
        }
 
522
        for(c = 0; c < a->len; c++) {
 
523
                if(*(a->str + c) != *(b->str + c)) {
 
524
                        return 0;
 
525
                }
 
526
        }
 
527
        return 1;
 
528
}
 
529
 
 
530
/* Append one dw_string object to another dw_string.
 
531
 * Input: The two dw_string objects
 
532
 * Output: 0 on success, -1 on error */
 
533
int dw_append(dw_str *toappend, dw_str *target) {
 
534
        int c = 0;
 
535
        if(dw_assert_sanity(toappend) == -1) {
 
536
                return -1;
 
537
        }
 
538
        if(dw_assert_sanity(target) == -1) {
 
539
                return -1;
 
540
        }
 
541
        if(target->len + toappend->len >= target->max) {
 
542
                return -1;
 
543
        }
 
544
        for(c = 0; c < toappend->len; c++) {
 
545
                *(target->str + target->len + c) = *(toappend->str + c);
 
546
        }
 
547
        target->len += toappend->len;
 
548
        return 0;
 
549
}
 
550
 
 
551
/* Append a substring of one dw_string object to another dw_string.
 
552
 * Input: String we splice from, where we start cutting from that string,
 
553
 *        how many bytes to cut from said string, the string to append to
 
554
 * Output: 0 on success, -1 on error
 
555
 */
 
556
int dw_substr_append(dw_str *splice, int32_t begin, int32_t amount,
 
557
                dw_str *target) {
 
558
        dw_str *tmp = 0;
 
559
 
 
560
        tmp = dw_substr(splice, begin, amount, 1);
 
561
        if(tmp == 0) {
 
562
                return -1;
 
563
        }
 
564
 
 
565
        if(dw_append(tmp,target) == -1) {
 
566
                dw_destroy(tmp);
 
567
                return -1;
 
568
        }
 
569
 
 
570
        dw_destroy(tmp);
 
571
        return 0;
 
572
}
 
573
 
 
574
/* Copy a dw_string object in to a null-terminated C-string.
 
575
 * Input: The string to convert
 
576
 * Output: A pointer to a newly created C-string; 0 on error */
 
577
 
 
578
uint8_t *dw_to_cstr(dw_str *obj) {
 
579
        uint8_t *out = 0;
 
580
        int a = 0;
 
581
 
 
582
        if(dw_assert_sanity(obj) == -1) {
 
583
                return 0;
 
584
        }
 
585
 
 
586
        out = dw_malloc(obj->len + 3);
 
587
        for(a = 0; a < obj->len; a++) {
 
588
                *(out + a) = *(obj->str + a);
 
589
        }
 
590
        *(out + a) = 0; /* Null-terminated */
 
591
 
 
592
        return out;
 
593
}
 
594
 
 
595
/* Find the last instance of a given character in a DwStr object.
 
596
 * Input: The dw_str object, the character we are seeking
 
597
 * Output: The index in the string with the character in question
 
598
 * -1 on error; -2 on "not found"
 
599
 */
 
600
 
 
601
int32_t dw_rfind(dw_str *obj, uint8_t rx) {
 
602
        int index = 0;
 
603
 
 
604
        if(dw_assert_sanity(obj) == -1) {
 
605
                return -1;
 
606
        }
 
607
 
 
608
        index = obj->len;
 
609
 
 
610
        /* We will never find the char in a 0-length string */
 
611
        if(index == 0) {
 
612
                return -2;
 
613
        }
 
614
 
 
615
        /* C indexes, ugh */
 
616
        index--;
 
617
 
 
618
        while(index >= 0 && *(obj->str + index) != rx) {
 
619
                index--;
 
620
        }
 
621
 
 
622
        if(index == -1) {
 
623
                return -2;
 
624
        }
 
625
 
 
626
        return index;
 
627
 
 
628
}
 
629
 
 
630
/* Take the last element of a comma-separated DwStr object, remove it
 
631
 * from said string, and create a new string with the popped comma-separated
 
632
 * object.  Should the source string not have a comma in it, then we take
 
633
 * the entire source string, blank it (make it 0-length) and copy it over
 
634
 * to the newly created string.  The final comma is removed from the
 
635
 * source string, but is *not* included in the destination string.
 
636
 * Input: The source string
 
637
 * Output: A newly created string with the last comma separated object */
 
638
 
 
639
dw_str *dw_qspop(dw_str *in) {
 
640
        int index = 0;
 
641
        int len = 0;
 
642
        dw_str *out = 0;
 
643
 
 
644
        if(dw_assert_sanity(in) == -1) {
 
645
                goto catch_dw_qspop;
 
646
        }
 
647
 
 
648
        index = dw_rfind(in,',');
 
649
 
 
650
        if(index == -2) { /* Not found */
 
651
                out = dw_copy(in);
 
652
                in->len = 0;
 
653
                return out;
 
654
        } else if(index < 0) { /* Error during seek */
 
655
                goto catch_dw_qspop;
 
656
        }
 
657
 
 
658
        len = in->len;
 
659
        index++; /* We don't include ',' in copied string */
 
660
        len = len - index;
 
661
        if(len < 0) { /* Sanity check */
 
662
                goto catch_dw_qspop;
 
663
        }
 
664
        out = dw_substr(in,index,len,1);
 
665
        in->len -= len + 1;
 
666
        if(in->len >= in->max) {
 
667
                in->len = 0;
 
668
                goto catch_dw_qspop;
 
669
        }
 
670
 
 
671
        return out;
 
672
 
 
673
catch_dw_qspop:
 
674
        if(out != 0) {
 
675
                dw_destroy(out);
 
676
                out = 0;
 
677
        }
 
678
        return 0;
 
679
 
 
680
}
 
681
 
 
682
/* Create a copy of a dw_str object with any leading whitespace in the
 
683
 * original object removed in the copy.  If the original is nothing
 
684
 * but whitespace, the copy will be a 0-length string.
 
685
 * Input: dw_str object we want to remove leading whitespace from
 
686
 * Output: Newly created dw_str object without the leading whitespace */
 
687
 
 
688
dw_str *dw_zap_lws(dw_str *obj) {
 
689
        int index = 0;
 
690
        dw_str *out = 0;
 
691
 
 
692
        if(dw_assert_sanity(obj) == -1) {
 
693
                goto catch_dw_zap_lws;
 
694
        }
 
695
 
 
696
        while(index < obj->len &&
 
697
              (*(obj->str + index) == ' ' || *(obj->str + index) == '\t') ) {
 
698
                index++;
 
699
        }
 
700
 
 
701
        if(index >= obj->len) { /* Obj is nothing but whitespace (or 0-len) */
 
702
                out = dw_create(1);
 
703
                return out;
 
704
        }
 
705
 
 
706
        out = dw_substr(obj,index,-1,1);
 
707
        return out;
 
708
 
 
709
catch_dw_zap_lws:
 
710
        if(out != 0) {
 
711
                dw_destroy(out);
 
712
                out = 0;
 
713
        }
 
714
        return 0;
 
715
}
 
716
 
 
717
/* Convert a dw_str object with a number in to an integer.  Leading
 
718
 * whitespace is ignored; anything that is not a number or letter stops
 
719
 * processing.
 
720
 * Input:
 
721
 *      obj: The dw_str object we convert in to a number
 
722
 *      index: How far in to the string we begin conversion (0 is
 
723
 *              beginning of string)
 
724
 *      base: The base we work in (2 is binary, 10 is decimal, 16 is
 
725
 *            hex; this can be up to 36)
 
726
 * Output:
 
727
 *      The number the string represents; -1 on error
 
728
 */
 
729
 
 
730
int32_t dw_atoi(dw_str *obj, int32_t index, int base) {
 
731
        int32_t out = 0;
 
732
        int num = 0, counter = 0;
 
733
        uint8_t look = 0;
 
734
        if(dw_assert_sanity(obj) == -1) {
 
735
                return -1;
 
736
        }
 
737
        if(base < 2 || base > 36) {
 
738
                return -1;
 
739
        }
 
740
        if(index < 0 || index >= obj->len) {
 
741
                return -1;
 
742
        }
 
743
        look = *(obj->str + index);
 
744
        while(index < obj->len && (look == ' ' || look == '\t')) {
 
745
                index++;
 
746
                look = *(obj->str + index);
 
747
        }
 
748
        for(counter = 0; counter < 100; counter++) {
 
749
                if(index >= obj->len) {
 
750
                        return out;
 
751
                }
 
752
                look = *(obj->str + index);
 
753
                if(look >= '0' && look <= '9') {
 
754
                        num = look - '0';
 
755
                } else if(look >= 'a' && look <= 'z') {
 
756
                        num = look - 'a' + 10;
 
757
                } else if(look >= 'A' && look <= 'Z') {
 
758
                        num = look - 'A' + 10;
 
759
                } else {
 
760
                        return out;
 
761
                }
 
762
                if(num >= base) {
 
763
                        return -1;
 
764
                }
 
765
                out *= base;
 
766
                out += num;
 
767
                index++;
 
768
        }
 
769
        return -1;
 
770
}
 
771
 
 
772
 
 
773
/* This extracts just a DNS DNAME (without TYPE) from a raw c-string (with
 
774
 * ASCII nulls, since DNS packets have those) and puts it in a newly
 
775
 * created string.
 
776
 * Input: Pointer to raw string; offset where we look for DNS DNAME,
 
777
 *        maximum length of raw string
 
778
 * Output: A pointer to a new dw_str with NAME
 
779
 */
 
780
dw_str *dw_get_dname(uint8_t *raw, int offset, int max) {
 
781
        int len = 0, counter = 0;
 
782
        int soffset = 0;
 
783
        dw_str *out = 0;
 
784
 
 
785
        if(max > 260) {
 
786
                out = dw_create(max);
 
787
        } else {
 
788
                out = dw_create(260);
 
789
        }
 
790
 
 
791
        if(out == 0 || raw == 0) {
 
792
                goto catch_dw_get_dname;
 
793
        }
 
794
 
 
795
        for(counter = 0; counter < 400; counter++) {
 
796
                if(offset >= max - 2 || soffset > 255) {
 
797
                        goto catch_dw_get_dname;
 
798
                }
 
799
 
 
800
                len = *(raw + offset);
 
801
                if(len > 63 || len < 0) { /* No compression pointers */
 
802
                        goto catch_dw_get_dname;
 
803
                }
 
804
 
 
805
                *(out->str + soffset) = len;
 
806
                if(len == 0) { /* End of dlabel */
 
807
                        break;
 
808
                }
 
809
                while(len > 0) {
 
810
                        soffset++;
 
811
                        offset++;
 
812
                        len--;
 
813
                        if(offset >= max - 2 || soffset > 255) {
 
814
                                goto catch_dw_get_dname;
 
815
                        }
 
816
                        *(out->str + soffset) = *(raw + offset);
 
817
                        /* No ASCII control characters in DNS names */
 
818
                        if(*(out->str + soffset) < 32) {
 
819
                                goto catch_dw_get_dname;
 
820
                        }
 
821
                }
 
822
                soffset++;
 
823
                offset++;
 
824
        }
 
825
        out->len = soffset + 1;
 
826
        return out;
 
827
 
 
828
catch_dw_get_dname:
 
829
        if(out != 0) {
 
830
                dw_destroy(out);
 
831
        }
 
832
        return 0;
 
833
}
 
834
 
 
835
/* This extracts a DNS DNAME, followed by a two-byte TYPE (the type of RR)
 
836
 * from a raw c-string (with ASCII nulls, since DNS packets have those)
 
837
 * and puts it in a newly created string.
 
838
 * Input: Pointer to raw string; offset where we look for DNS DNAME + TYPE,
 
839
 *        maximum length of raw string
 
840
 * Output: A pointer to a new dw_str with NAME + TYPE
 
841
 */
 
842
dw_str *dw_get_dname_type(uint8_t *raw, int offset, int max) {
 
843
        dw_str *out = 0;
 
844
 
 
845
        out = dw_get_dname(raw,offset,max);
 
846
        if(out == 0) {
 
847
                goto catch_dw_get_dname_class;
 
848
        }
 
849
        offset += out->len;
 
850
 
 
851
        /* Accoring to http://www.iana.org/assignments/dns-parameters,
 
852
         * records 65280 (0xff00) to 65535 (0xfffe) are "private use";
 
853
         * Deadwood uses 65392 - 65407 for internal use and will not
 
854
         * accept queries with these numbers in place; see
 
855
         * doc/internals/RR.Allocation for details on how Deadwood uses
 
856
         * these RR numbers */
 
857
        if(*(raw + offset)==0xff && (*(raw + offset + 1) & 0xf0)==0x70) {
 
858
                goto catch_dw_get_dname_class;
 
859
        }
 
860
        *(out->str + out->len) = *(raw + offset);
 
861
        *(out->str + out->len + 1) = *(raw + offset + 1);
 
862
        out->len += 2;
 
863
        return out;
 
864
 
 
865
catch_dw_get_dname_class:
 
866
        if(out != 0) {
 
867
                dw_destroy(out);
 
868
                out = 0;
 
869
        }
 
870
        return 0;
 
871
}
 
872
 
 
873
/* Determine where the end of a <domain-name> at offset in the string
 
874
 * is (ugh, DNS is ugly); -1 on error */
 
875
int32_t dw_get_dn_end(dw_str *in, int offset) {
 
876
        int len = 0, counter = 0;
 
877
 
 
878
        if(dw_assert_sanity(in) == -1) {
 
879
                return -1;
 
880
        }
 
881
 
 
882
        for(counter = 0; counter < 200; counter++) {
 
883
                if(offset + 1 > in->len) {
 
884
                        return -1;
 
885
                }
 
886
 
 
887
                len = *(in->str + offset);
 
888
                if(len >= 192) { /* Compression pointer */
 
889
                        offset++;
 
890
                        break;
 
891
                } else if(len > 63 || len < 0) { /* Invalid length */
 
892
                        return -1;
 
893
                } else if(len == 0) { /* End of dlabel */
 
894
                        break;
 
895
                }
 
896
                offset += len + 1;
 
897
        }
 
898
 
 
899
        return offset + 1;
 
900
 
 
901
}
 
902
 
 
903
/* Get a TTL that is buried in a DNS string.  We start at the beginning of
 
904
 * the DNS name, figure out how long the name is (ugh), then skip past
 
905
 * type and class to get the TTL; return -1 on error.  We don't support
 
906
 * TTLs longer than 31,536,000: One year (0x01E13380)
 
907
 *
 
908
 * Input: String we will get TTL from; offset from where we will get TTL,
 
909
 *        maximum allowed TTL (which should be 31536000 when called from
 
910
 *        another part of Deadwood), recursion depth (to stop infinite loops)
 
911
 *        Note that depth is a positive number that decrements.
 
912
 */
 
913
int32_t dw_get_a_dnsttl(dw_str *in, int offset, int32_t max, int depth) {
 
914
        int32_t out = 0, type = 0;
 
915
        uint8_t *raw = 0;
 
916
 
 
917
        if(dw_assert_sanity(in) == -1) {
 
918
                return -1;
 
919
        }
 
920
 
 
921
        if(depth <= 0) { /* End of packet/Depth exceeded */
 
922
                return max;
 
923
        }
 
924
 
 
925
        if(max > 31536000) {
 
926
                max = 31536000;
 
927
        }
 
928
 
 
929
        offset = dw_get_dn_end(in,offset);
 
930
 
 
931
        if(offset < 0 || (offset + 8) > in->len) {
 
932
                return -1;
 
933
        }
 
934
 
 
935
        raw = (in->str + offset);
 
936
 
 
937
        /* Get record type (A, CNAME, etc.) */
 
938
        type = ((int32_t)*(raw + 0) << 8) | ((int32_t)*(raw + 1));
 
939
 
 
940
        if(*(raw + 4) > 0x7f) {
 
941
                return 31536000; /* TTL out of bounds */
 
942
        }
 
943
        out = ((int32_t)*(raw + 4)<< 24) |
 
944
              ((int32_t)*(raw + 5) << 16) |
 
945
              ((int32_t)*(raw + 6) << 8) |
 
946
              ((int32_t)*(raw + 7));
 
947
        if(out < 60) {
 
948
                out = 60;
 
949
        } else if(out > max) {
 
950
                out = max;
 
951
        }
 
952
 
 
953
        if(type == 5 /* CNAME */) {
 
954
                offset = dw_get_dn_end(in,offset + 10);
 
955
                if(offset < 0 || offset > in->len) {
 
956
                        return -1;
 
957
                }
 
958
                return dw_get_a_dnsttl(in,offset,out,depth - 1);
 
959
        }
 
960
 
 
961
        return out;
 
962
}
 
963
 
 
964
#ifdef OTHER_STUFF
 
965
/* Given a dw_str object, where the dw_str is a raw DNS packet, determine
 
966
 * the TTL for the packet.  Note that this only looks at the TTL for the
 
967
 * first RR in a reply.  Things like "www.foo.bar. +86400 CNAME www.baz.bar. ~
 
968
 * www.baz.bar. +3600 192.168.42.102" will have the entire record cached
 
969
 * for a day (86400 seconds).
 
970
 *
 
971
 * Note that this routine is currenly not used by any other program.
 
972
 */
 
973
int32_t dw_get_ttl_from_packet(dw_str *in) {
 
974
        int offset = 0;
 
975
 
 
976
        if(dw_assert_sanity(in) == -1) {
 
977
                return -1;
 
978
        }
 
979
 
 
980
        if(in->len < 12) {
 
981
                return -1;
 
982
        }
 
983
 
 
984
        offset = dw_get_dn_end(in,12);
 
985
 
 
986
        if(offset < 0 || offset > in->len) {
 
987
                return -1;
 
988
        }
 
989
 
 
990
        /* BUG: This will not work with packets with only CNAME answers */
 
991
        return dw_get_a_dnsttl(in,offset,31536000,32);
 
992
}
 
993
#endif /* OTHER_STUFF */
 
994
 
 
995
/* Given a packet in the form put in the DNS cache (with things like type,
 
996
 * ancount, nscount, and arcount at the end of the string), tell the user how
 
997
 * many answers are in the packet. */
 
998
int32_t dw_cachepacket_to_ancount(dw_str *packet) {
 
999
        int32_t offset = 0;
 
1000
 
 
1001
        if(dw_assert_sanity(packet) == -1 || packet->len < 7) {
 
1002
                return -1;
 
1003
        }
 
1004
 
 
1005
        /* A cachepacket string is in the format
 
1006
         * <packet><ancount><nscount><arcount><type>, where all numbers
 
1007
         * are 16-bit, except for <type> which is 8-bit */
 
1008
 
 
1009
        offset = packet->len - 7;
 
1010
 
 
1011
        return dw_fetch_u16(packet,offset);
 
1012
}
 
1013
 
 
1014
/* Given a raw pointer to a c-string (which can have NULLs), and a length
 
1015
 * for that string, extract a dw_str object that is a cachable form of
 
1016
 * the packet.  Basically:
 
1017
 *      * Everything after the question is put at the beginning
 
1018
 *        of the packet
 
1019
 *      * This is followed by, in order, ancount, nscount, then
 
1020
 *        arcount, and finally the 8-bit "type"
 
1021
 */
 
1022
 
 
1023
dw_str *dw_packet_to_cache(uint8_t *raw, int len, uint8_t type) {
 
1024
        int32_t ancount = 0, nscount = 0, arcount = 0;
 
1025
        dw_str *hack = 0, *out = 0;
 
1026
        int offset = 0;
 
1027
 
 
1028
        /* A very ugly, but fast, way to make recvfrom()'s str/len pair
 
1029
         * in to a dw_str object.  */
 
1030
        hack = dw_malloc(sizeof(dw_str));
 
1031
        hack->max = len + 1;
 
1032
        hack->len = len;
 
1033
        hack->str = (uint8_t *)raw;
 
1034
        hack->sane = 114;
 
1035
 
 
1036
        ancount = dw_fetch_u16(hack,6);
 
1037
        nscount = dw_fetch_u16(hack,8);
 
1038
        arcount = dw_fetch_u16(hack,10);
 
1039
 
 
1040
        if(ancount < 0 || nscount < 0 || arcount < 0) {
 
1041
                goto catch_dw_packet_to_cache;
 
1042
        }
 
1043
 
 
1044
        /* OK, hunt for the beginning of the packet */
 
1045
        offset = dw_get_dn_end(hack,12);
 
1046
        if(offset < 0) {
 
1047
                goto catch_dw_packet_to_cache;
 
1048
        }
 
1049
        offset += 4;
 
1050
        out = dw_substr(hack,offset,-1,7);
 
1051
        dw_put_u16(out,ancount,-1);
 
1052
        dw_put_u16(out,nscount,-1);
 
1053
        dw_put_u16(out,arcount,-1);
 
1054
        dw_addchar(type,out);
 
1055
        free(hack);
 
1056
        return out;
 
1057
 
 
1058
catch_dw_packet_to_cache:
 
1059
        if(hack != 0) {
 
1060
                free(hack);
 
1061
                hack = 0;
 
1062
        }
 
1063
        if(out != 0) {
 
1064
                dw_destroy(out);
 
1065
                out = 0;
 
1066
        }
 
1067
        return 0;
 
1068
}
 
1069
 
 
1070
/* Make sure a filename is sanitized; only lowercase letters, the '_',
 
1071
 * the '-', and the '/' are allowed in file names; anything else becomes
 
1072
 * a '_' */
 
1073
int dw_filename_sanitize(dw_str *obj) {
 
1074
        int index = 0;
 
1075
        int look = 0;
 
1076
 
 
1077
        if(dw_assert_sanity(obj) == -1) {
 
1078
                return -1;
 
1079
        }
 
1080
 
 
1081
        for(index = 0; index < obj->len; index++) {
 
1082
                look = *(obj->str + index);
 
1083
                if((look < 'a' || look > 'z') && look != '/' &&
 
1084
                   look != '-' && look != '_') {
 
1085
                        *(obj->str + index) = '_';
 
1086
                }
 
1087
        }
 
1088
 
 
1089
        return 1;
 
1090
}
 
1091
 
 
1092
/* See if a given ASCII name ends in a '.'; if it doesn't return -1, if
 
1093
 * there is an unexpected error, return 0, and if it does end with '.', return
 
1094
 * 1 */
 
1095
int dw_ends_in_dot(dw_str *in) {
 
1096
        if(dw_assert_sanity(in) == -1) {
 
1097
                return 0;
 
1098
        }
 
1099
 
 
1100
        if(in->len < 1) {
 
1101
                return -1;
 
1102
        }
 
1103
 
 
1104
        if(*(in->str + in->len - 1) != '.') {
 
1105
                return -1;
 
1106
        }
 
1107
 
 
1108
        return 1;
 
1109
}
 
1110
 
 
1111
/* Used by dw_dnsname_convert, this part of the code converts DNS name
 
1112
 * delimiters in the name (usually dots) into DNS' peculiar length
 
1113
 * names.  It only does things one character at a time.
 
1114
 *
 
1115
 * Input: String to convert, output string to convert to, offset to
 
1116
 *        convert at, place where the last delimiter was, pointer to "count"
 
1117
 *        of characters in this label, character to use as delimiter
 
1118
 *
 
1119
 * Output: New location of delimiter
 
1120
 */
 
1121
 
 
1122
int dw_dnsname_delim_convert(dw_str *in, dw_str *out, int a, int place,
 
1123
        int *count, uint8_t delim) {
 
1124
 
 
1125
        if(*(in->str + a) == delim) {
 
1126
                if(*count <= 0) {
 
1127
                        return -1; /* bad label */
 
1128
                }
 
1129
                if(place < out->max) {
 
1130
                        *(out->str + place) = *count;
 
1131
                }
 
1132
                place = a + 1;
 
1133
                *count = -1;
 
1134
        }
 
1135
        *count += 1;
 
1136
        if(a + 1 < out->max) {
 
1137
                *(out->str + a + 1) = *(in->str + a);
 
1138
        }
 
1139
        if(*count > 63) {
 
1140
                return -1; /* Label too long */
 
1141
        }
 
1142
 
 
1143
        return place;
 
1144
}
 
1145
 
 
1146
 
 
1147
/* Convert an ASCII name, like "www.samiam.org." in to the DNS form of the
 
1148
 * same name (\003www\006samiam\003org\000).  Output, as a new string, the
 
1149
 * newly created DNS string; 0 if there is any error */
 
1150
dw_str *dw_dnsname_convert(dw_str *in) {
 
1151
        dw_str *out = 0;
 
1152
        int c = 0, place = 0, a = 0;
 
1153
 
 
1154
        if(dw_assert_sanity(in) == -1) {
 
1155
                return 0;
 
1156
        }
 
1157
 
 
1158
        if(dw_ends_in_dot(in) != 1) {
 
1159
                return 0;
 
1160
        }
 
1161
 
 
1162
        out = dw_create(in->len + 4); /* Cushion to fit 2-byte qtype */
 
1163
        if(out == 0) {
 
1164
                return 0;
 
1165
        }
 
1166
        out->len = in->len + 1;
 
1167
 
 
1168
        if(*(in->str) == '.') {
 
1169
                if(in->len != 1) {
 
1170
                        goto catch_dw_dnsname_convert; /* bad label */
 
1171
                }
 
1172
                if(out->max > 1) {
 
1173
                        *(out->str) = 0;
 
1174
                }
 
1175
                out->len = 1;
 
1176
                return out;
 
1177
        }
 
1178
 
 
1179
        for(a = 0 ; a < in->len ; a++) {
 
1180
                place = dw_dnsname_delim_convert(in, out, a, place, &c, '.');
 
1181
                if(place == -1) {
 
1182
                        goto catch_dw_dnsname_convert;
 
1183
                }
 
1184
        }
 
1185
 
 
1186
        if(out->len - 1 < out->max) {
 
1187
                *(out->str + out->len - 1) = 0; /* Final "dot" in hostname */
 
1188
        }
 
1189
        return out;
 
1190
 
 
1191
catch_dw_dnsname_convert:
 
1192
        if(out != 0) {
 
1193
                dw_destroy(out);
 
1194
        }
 
1195
        return 0;
 
1196
}
 
1197
 
 
1198
/* Chop off the first label of a DNS name; for example, the raw DNS form
 
1199
 * of www.example.com. (\003www\007example\003com\000) becomes example.com
 
1200
 * (\007example\003com\000).  This will also work with strings having data
 
1201
 * after the end of the DNS name.
 
1202
 *
 
1203
 * This function creates a new string which needs to be freed by its caller
 
1204
 */
 
1205
dw_str *dw_dnslabel_chop(dw_str *in) {
 
1206
        dw_str *out = 0;
 
1207
        int offset = 0, a = 0, b = 0;
 
1208
 
 
1209
        if(dw_assert_sanity(in) == -1) {
 
1210
                return 0;
 
1211
        }
 
1212
 
 
1213
        if(in->len < 2) {
 
1214
                return 0;
 
1215
        }
 
1216
        offset = *(in->str);
 
1217
        if(offset < 1 || offset > 63) {
 
1218
                return 0;
 
1219
        }
 
1220
        if(in->len < offset) {
 
1221
                return 0;
 
1222
        }
 
1223
 
 
1224
        out = dw_create(in->len - offset + 1);
 
1225
        if(out == 0) {
 
1226
                return 0;
 
1227
        }
 
1228
 
 
1229
        a = offset + 1;
 
1230
        b = 0;
 
1231
        while(a < in->len && b < out->max) {
 
1232
                *(out->str + b) = *(in->str + a);
 
1233
                a++;
 
1234
                b++;
 
1235
        }
 
1236
 
 
1237
        out->len = b;
 
1238
        return out;
 
1239
 
 
1240
}
 
1241
 
 
1242
/* Rotate data in a string: Given a start point and a pivot point, take all of
 
1243
 * the string between the pivot point to the end, and put it where the start
 
1244
 * point is.  Take all the data from the start point to the pivot point, and
 
1245
 * put it at the end of the string.
 
1246
 *
 
1247
 * For example, if we have the string "0123456789", and the start is 3, and
 
1248
 * the pivot 5, we would have the string "0125678934" after running
 
1249
 * this function
 
1250
 */
 
1251
 
 
1252
int dw_rotate(dw_str *in, int32_t start, int32_t pivot, int32_t end) {
 
1253
        dw_str *part1 = 0, *part2 = 0, *part3 = 0;
 
1254
 
 
1255
        if(in == 0 || start >= pivot || pivot >= end || end >= in->len) {
 
1256
                return -1;
 
1257
        }
 
1258
 
 
1259
        part1 = dw_substr(in,start,pivot - start,1);
 
1260
        if(part1 == 0) {
 
1261
                return -1;
 
1262
        }
 
1263
        part2 = dw_substr(in,pivot,end - pivot,1);
 
1264
        if(part2 == 0) {
 
1265
                dw_destroy(part1);
 
1266
                return -1;
 
1267
        }
 
1268
        part3 = dw_substr(in,end,-1,1);
 
1269
        if(part3 == 0) {
 
1270
                dw_destroy(part1);
 
1271
                dw_destroy(part2);
 
1272
                return -1;
 
1273
        }
 
1274
        in->len = start;
 
1275
        dw_append(part2,in);
 
1276
        dw_append(part1,in);
 
1277
        dw_append(part3,in);
 
1278
        dw_destroy(part1);
 
1279
        dw_destroy(part2);
 
1280
        dw_destroy(part3);
 
1281
        return 1;
 
1282
}
 
1283