comparison archive/patch1 @ 57:de3753c3160a

add archive directory with history of alioth versions that have been merged here
author Carl Byington <carl@five-ten-sg.com>
date Sat, 02 Feb 2008 12:54:07 -0800
parents
children
comparison
equal deleted inserted replaced
56:b504411ad213 57:de3753c3160a
1 diff -Naur ../orig/libpst-0.5.1/define.h libpst64-060926/define.h
2 --- ../orig/libpst-0.5.1/define.h 2004-11-17 07:48:03.000000000 -0700
3 +++ libpst64-060926/define.h 2006-09-26 14:09:55.000000000 -0600
4 @@ -5,7 +5,7 @@
5 * dave.s@earthcorp.com
6 */
7
8 -//#define DEBUG_ALL
9 +#define DEBUG_ALL
10 #ifndef DEFINEH_H
11 #define DEFINEH_H
12
13 diff -Naur ../orig/libpst-0.5.1/generic.c libpst64-060926/generic.c
14 --- ../orig/libpst-0.5.1/generic.c 1969-12-31 17:00:00.000000000 -0700
15 +++ libpst64-060926/generic.c 2006-09-26 14:09:55.000000000 -0600
16 @@ -0,0 +1,110 @@
17 +// {{{ includes
18 +
19 +#include <ctype.h>
20 +#include <errno.h>
21 +#include <malloc.h>
22 +#include <signal.h>
23 +#include <stdarg.h>
24 +#include <stdio.h>
25 +#include <stdlib.h>
26 +#include <string.h>
27 +#include "generic.h"
28 +
29 +#ifdef WITH_DMALLOC
30 +#include <dmalloc.h>
31 +#endif
32 +
33 +// }}}
34 +
35 +// {{{ Macros: ASSERT(), DIE(), F_MALLOC()
36 +void pDIE( char *fmt, ... ) // {{{ Cough...cough
37 +{
38 + va_list ap;
39 + va_start( ap, fmt );
40 + //fprintf( stderr, "Fatal error (will segfault): ");
41 + vfprintf( stderr, fmt, ap );
42 + fprintf( stderr, "\n" );
43 + va_end(ap);
44 + raise( SIGSEGV );
45 +}
46 +// }}}
47 +void pWARN( char *fmt, ... ) // {{{ Cough...cough
48 +{
49 + va_list ap;
50 + va_start( ap, fmt );
51 + fprintf( stderr, "WARNING: ");
52 + vfprintf( stderr, fmt, ap );
53 + fprintf( stderr, "\n" );
54 + va_end(ap);
55 +}
56 +// }}}
57 +void *F_MALLOC( size_t size ) // {{{ malloc() but dumps core when it fails
58 +{
59 + void *result;
60 +
61 + result = malloc( size );
62 + ASSERT( NULL != result, "malloc() failure." );
63 +
64 + return result;
65 +}
66 +// }}}
67 +void *F_REALLOC( void *p, size_t size ) // {{{ realloc() but dumps core when it fails
68 +{
69 + void *result;
70 +
71 + //if( NULL != p ) hexdump((char*)p - 128, 0, 128, 1 );
72 + if(!p) {
73 + ASSERT( NULL != ( result = malloc( size ) ), "malloc() failure." );
74 + }
75 + else {
76 + ASSERT( NULL != ( result = realloc( p, size ) ), "realloc() failure." );
77 + }
78 +
79 + //hexdump((char*)result - 128, 0, 128, 1 );
80 + fflush(stderr);
81 + return result;
82 +}
83 +// }}}
84 +// }}}
85 +// {{{ Program logging/debug output
86 +int DEBUG_LEVEL = DB_INFO;
87 +
88 +void db_default( char *file, int line, int level, char *fmt, ... ) // {{{
89 +{
90 + va_list ap;
91 + if( level <= DEBUG_LEVEL ) {
92 + switch( level ) {
93 + case DB_CRASH:
94 + fprintf(stderr, "CRASH");
95 + break;
96 + case DB_ERR:
97 + fprintf(stderr, "ERROR");
98 + break;
99 + case DB_WARN:
100 + fprintf(stderr, "WARNING");
101 + break;
102 + case DB_INFO:
103 + case DB_VERB:
104 + break;
105 + default:
106 + fprintf(stderr, "DEBUG(%d)", level );
107 + }
108 +
109 + if( level <= DB_WARN )
110 + fprintf(stderr, " (%s:%d)", file, line );
111 +
112 + if( DB_INFO != level && DB_VERB != level )
113 + fprintf(stderr, ": ");
114 +
115 + va_start( ap, fmt );
116 + vfprintf(stderr, fmt, ap );
117 + fprintf(stderr, "\n" );
118 + va_end( ap );
119 + }
120 +} // }}}
121 +
122 +void (*dbfunc)(char *file, int line, int level, char *fmt, ...) = &db_default;
123 +
124 +//#define DEBUG(x) { x; }
125 +//#define DEBUG(x) ;
126 +// }}}
127 diff -Naur ../orig/libpst-0.5.1/generic.h libpst64-060926/generic.h
128 --- ../orig/libpst-0.5.1/generic.h 1969-12-31 17:00:00.000000000 -0700
129 +++ libpst64-060926/generic.h 2006-09-26 14:09:55.000000000 -0600
130 @@ -0,0 +1,48 @@
131 +/* {{{ Generic.h - thigns every program does:
132 + *
133 + * - user output (log, debug, etc)
134 + * - crash and burn
135 + * - allocate memory (or explode)
136 + * }}} */
137 +#ifndef GENERIC_H
138 +#define GENERIC_H
139 +#include <stdlib.h>
140 +#include <stdio.h>
141 +#include <stdarg.h>
142 +/***************************************************/
143 +
144 +#define LOAD_DEBUG 1
145 +
146 +#define DIE(...) { fprintf(stderr, "Fatal Error at %s,%d: ", __FILE__, __LINE__); pDIE(__VA_ARGS__); }
147 +
148 +//#define WARN(...) { fprintf(stderr, "WARN: %s,%d: ", __FILE__, __LINE__); pWARN(__VA_ARGS__); }
149 +void pDIE( char *fmt, ... );
150 +//void pWARN( char *fmt, ... );
151 +
152 +#define WARN(...) DB( DB_WARN, __VA_ARGS__ )
153 +#define ASSERT(x,...) { if( !(x) ) DIE( __VA_ARGS__ ); }
154 +
155 +void *F_MALLOC( size_t size );
156 +void *F_REALLOC( void *p, size_t size );
157 +
158 +#define DO_DEBUG 0
159 +#define DEBUG(x) if( DO_DEBUG ) { x; }
160 +#define STUPID_CR "\r\n"
161 +
162 +#define DB_CRASH 0 // crashing
163 +#define DB_ERR 1 // error
164 +#define DB_WARN 2 // warning
165 +#define DB_INFO 3 // normal, but significant, condition
166 +#define DB_VERB 4 // verbose information
167 +#define DB_0 5 // debug-level message
168 +#define DB_1 6 // debug-level message
169 +#define DB_2 7 // debug-level message
170 +
171 +extern int DEBUG_LEVEL;
172 +extern void (*dbfunc)(char *file, int line, int level, char *fmt, ...);
173 +
174 +#define DB(...) { dbfunc( __FILE__, __LINE__, __VA_ARGS__ ); }
175 +
176 +int set_db_function( void (*func)( char *file, int line, int level, char *fmt, ...) );
177 +
178 +#endif
179 diff -Naur ../orig/libpst-0.5.1/libpst.c libpst64-060926/libpst.c
180 --- ../orig/libpst-0.5.1/libpst.c 2004-11-17 07:48:04.000000000 -0700
181 +++ libpst64-060926/libpst.c 2006-09-26 14:09:55.000000000 -0600
182 @@ -4,6 +4,7 @@
183 * Written by David Smith
184 * dave.s@earthcorp.com
185 */
186 +//{{{
187 #include <stdio.h>
188 #include <stdlib.h>
189 #include <time.h>
190 @@ -12,11 +13,15 @@
191 #include <limits.h>
192 #include <wchar.h>
193
194 +#include <signal.h>
195 #include <errno.h>
196 #include <sys/stat.h> //mkdir
197 #include <fcntl.h> // for Win32 definition of _O_BINARY
198 #include "define.h"
199 #include "libstrfunc.h"
200 +#include "vbuf.h"
201 +
202 +#define ASSERT(x) { if(!(x)) raise( SIGSEGV ); }
203
204 #ifdef _MSC_VER
205 # include <windows.h>
206 @@ -45,30 +50,54 @@
207 //#define LE32_CPU(x) {}
208 //#define LE16_CPU(x) {}
209 //#endif // _MSC_VER
210 -
211 -#define FILE_SIZE_POINTER 0xA8
212 -#define INDEX_POINTER 0xC4
213 -#define SECOND_POINTER 0xBC
214 +// }}}
215 +#define FILE_SIZE_POINTER32 0xA8
216 +#define INDEX_POINTER32 0xC4
217 +#define INDEX_COUNT32 0xC0
218 +#define SECOND_POINTER32 0xBC
219 +#define SECOND_COUNT32 0xB8
220 #define INDEX_DEPTH 0x4C
221 #define SECOND_DEPTH 0x5C
222 // the encryption setting could be at 0x1CC. Will require field testing
223 -#define ENC_OFFSET 0x1CD
224 +#define ENC_OFFSET32 0x1CD
225 // says the type of index we have
226 -#define INDEX_TYPE_OFFSET 0x0A
227 +#define INDEX_TYPE_OFFSET32 0x0A
228 +#define INDEX_TYPE32 0x0E
229 +#define INDEX_TYPE64 0x17 //I think this is wrong
230
231 // for the 64bit 2003 outlook PST we need new file offsets
232 // perhaps someone can figure out the header format for the pst files...
233 -#define FILE_SIZE_POINTER_64 0xB8
234 -#define INDEX_POINTER_64 0xF0
235 -#define SECOND_POINTER_64 0xE0
236 +#define FILE_SIZE_POINTER64 0xB8
237 +#define INDEX_POINTER64 0xF0
238 +#define INDEX_COUNT64 0xE8
239 +#define SECOND_POINTER64 0xE0
240 +#define SECOND_COUNT64 0xD8
241 +#define INDEX_TYPE_OFFSET64 0x0A
242 +#define ENC_OFFSET64 0x201
243 +
244 +#define FILE_SIZE_POINTER ((do_read64)?FILE_SIZE_POINTER64:FILE_SIZE_POINTER32)
245 +#define INDEX_POINTER ((do_read64)?INDEX_POINTER64:INDEX_POINTER32)
246 +#define INDEX_TYPE_OFFSET ((do_read64)?INDEX_TYPE_OFFSET64:INDEX_TYPE_OFFSET32)
247 +#define INDEX_TYPE ((do_read64)?INDEX_TYPE64:INDEX_TYPE32)
248 +#define SECOND_POINTER ((do_read64)?SECOND_POINTER64:SECOND_POINTER32)
249 +#define SECOND_COUNT ((do_read64)?SECOND_COUNT64:SECOND_COUNT32)
250 +#define ENC_OFFSET ((do_read64)?ENC_OFFSET64:ENC_OFFSET32)
251 +#define INDEX_COUNT ((do_read64)?INDEX_COUNT64:INDEX_COUNT32)
252
253 #define PST_SIGNATURE 0x4E444221
254
255 -struct _pst_table_ptr_struct{
256 +int do_read64 = 0; //set this to 1 in order to try and read 64-bit pst files (Outlook 2003)
257 +
258 +struct _pst_table_ptr_struct32{
259 int32_t start;
260 int32_t u1;
261 int32_t offset;
262 };
263 +struct _pst_table_ptr_structn{
264 + int64_t start;
265 + int64_t u1;
266 + int64_t offset;
267 +};
268
269 typedef struct _pst_block_header {
270 int16_t type;
271 @@ -119,6 +148,26 @@
272 0xd4, 0xe1, 0x11, 0xd0, 0x08, 0x8b, 0x2a, 0xf2,
273 0xed, 0x9a, 0x64, 0x3f, 0xc1, 0x6c, 0xf9, 0xec}; /*0xff*/
274
275 +void set_read64() { do_read64 = 1; }
276 +
277 +void dump_desc( off_t off, int depth, int i, pst_descn *desc_rec ) { // {{{
278 +
279 + //desc_rec->d_id = 0x0102030405060708;
280 + DEBUG_INDEX(("%08x [%i] Item(%#x) = [d_id = %#llx, desc_id = %#llx, "
281 + "list_id = %#llx, parent_id = %#x, u1 = %#x] %#x %p %p\n",
282 + off,
283 + depth, i, desc_rec->d_id,
284 + desc_rec->desc_id, desc_rec->list_id, desc_rec->parent_id, desc_rec->u1));
285 + DEBUG_HEXDUMPC( (char*)desc_rec, sizeof( pst_descn ), 0x10 );
286 + DEBUG_INDEX(("WTF? %d %x %x %x %x %x\n",
287 + sizeof( u_int32_t ),
288 + (int)(&desc_rec->d_id) - (int)desc_rec,
289 + (int)(&desc_rec->desc_id) - (int)desc_rec,
290 + (int)(&desc_rec->list_id) - (int)desc_rec,
291 + (int)(&desc_rec->parent_id) - (int)desc_rec,
292 + (int)(&desc_rec->u1) - (int)desc_rec ));
293 +} // }}}
294 +
295 int32_t pst_open(pst_file *pf, char *name, char *mode) {
296 u_int32_t sig;
297 // unsigned char ind_type;
298 @@ -158,9 +207,10 @@
299 DEBUG_RET();
300 return -1;
301 }
302 +
303 _pst_getAtPos(pf->fp, INDEX_TYPE_OFFSET, &(pf->ind_type), sizeof(unsigned char));
304 DEBUG_INFO(("index_type = %i\n", pf->ind_type));
305 - if (pf->ind_type != 0x0E) {
306 + if ( pf->ind_type != INDEX_TYPE) {
307 WARN(("unknown index structure. Could this be a new Outlook 2003 PST file?\n"));
308 DEBUG_RET();
309 return -1;
310 @@ -170,23 +220,18 @@
311 DEBUG_INFO(("encrypt = %i\n", pf->encryption));
312 // pf->encryption = encrypt;
313
314 - _pst_getAtPos(pf->fp, SECOND_POINTER-4, &(pf->index2_count), sizeof(pf->index2_count));
315 - _pst_getAtPos(pf->fp, SECOND_POINTER, &(pf->index2), sizeof(pf->index2));
316 - LE32_CPU(pf->index2_count);
317 - LE32_CPU(pf->index2);
318 + pf->index2_count = _pst_getIntAtPos(pf->fp, SECOND_COUNT);
319 + pf->index2 = _pst_getIntAtPos(pf->fp, SECOND_POINTER );
320
321 - _pst_getAtPos(pf->fp, FILE_SIZE_POINTER, &(pf->size), sizeof(pf->size));
322 - LE32_CPU(pf->size);
323 + pf->size = _pst_getIntAtPos( pf->fp, FILE_SIZE_POINTER );
324
325 // very tempting to leave these values set way too high and let the exploration of the tables set them...
326 pf->index1_depth = pf->index2_depth = 255;
327
328 DEBUG_INFO(("Pointer2 is %#X, count %i[%#x], depth %#x\n",
329 pf->index2, pf->index2_count, pf->index2_count, pf->index2_depth));
330 - _pst_getAtPos(pf->fp, INDEX_POINTER-4, &(pf->index1_count), sizeof(pf->index1_count));
331 - _pst_getAtPos(pf->fp, INDEX_POINTER, &(pf->index1), sizeof(pf->index1));
332 - LE32_CPU(pf->index1_count);
333 - LE32_CPU(pf->index1);
334 + pf->index1_count = _pst_getIntAtPos(pf->fp, INDEX_COUNT);
335 + pf->index1 = _pst_getIntAtPos(pf->fp, INDEX_POINTER);
336
337 DEBUG_INFO(("Pointer1 is %#X, count %i[%#x], depth %#x\n",
338 pf->index1, pf->index1_count, pf->index1_count, pf->index1_depth));
339 @@ -495,18 +540,110 @@
340 }
341
342 #define BLOCK_SIZE 516
343 +int _pst_decode_desc( pst_descn *desc, char *buf ) { // {{{
344 + int r;
345 + if( do_read64 ) {
346 +
347 + DEBUG_INDEX(("Decoding desc64 "));
348 + DEBUG_HEXDUMPC(buf, sizeof( pst_descn ), 0x10);
349 + memcpy(desc, buf, sizeof( pst_descn ));
350 + LE64_CPU(desc->d_id);
351 + LE64_CPU(desc->desc_id);
352 + LE64_CPU(desc->list_id);
353 + LE32_CPU(desc->parent_id);
354 + LE32_CPU(desc->u1);
355 + r = sizeof( pst_descn );
356 + }
357 + else {
358 + pst_desc32 d32;
359 + DEBUG_INDEX(("Decoding desc32 "));
360 + DEBUG_HEXDUMPC(buf, sizeof( d32 ), 0x10);
361 + memcpy(&d32, buf, sizeof(d32));
362 + LE32_CPU(d32.d_id);
363 + LE32_CPU(d32.desc_id);
364 + LE32_CPU(d32.list_id);
365 + LE32_CPU(d32.parent_id);
366 +
367 + desc->d_id = d32.d_id;
368 + desc->desc_id = d32.desc_id;
369 + desc->list_id = d32.list_id;
370 + desc->parent_id = d32.parent_id;
371 + desc->u1 = 0;
372 +
373 + r = sizeof( d32 );
374 + }
375 +
376 + return r;
377 +} // }}}
378 +int _pst_decode_table( struct _pst_table_ptr_structn *table, char *buf ) { // {{{
379 +
380 + if( do_read64 ) {
381 +
382 + DEBUG_INDEX(("Decoding table64"));
383 + DEBUG_HEXDUMPC(buf, sizeof( struct _pst_table_ptr_structn ), 0x10);
384 + memcpy(table, buf, sizeof( struct _pst_table_ptr_structn ) );
385 + LE64_CPU(table->start);
386 + LE64_CPU(table->u1);
387 + LE64_CPU(table->offset);
388 +
389 + return sizeof( struct _pst_table_ptr_structn );
390 + }
391 + else {
392 + struct _pst_table_ptr_struct32 t32;
393 + memcpy(&t32, buf, sizeof(t32));
394 + LE32_CPU(t32.start);
395 + LE32_CPU(t32.u1);
396 + LE32_CPU(t32.offset);
397 + table->start = t32.start;
398 + table->u1 = t32.u1;
399 + table->offset = t32.offset;
400 +
401 + return sizeof( struct _pst_table_ptr_struct32 );
402 + }
403 + return 0;
404 +} // }}}
405 +int _pst_decode_index( pst_index *index, char *buf ) { // {{{
406 + if( do_read64 ) {
407 +
408 + DEBUG_INDEX(("Decoding index64"));
409 + DEBUG_HEXDUMPC(buf, sizeof( pst_index ), 0x10);
410 + memcpy(index, buf, sizeof(pst_index));
411 + LE64_CPU(index->id);
412 + LE64_CPU(index->offset);
413 + LE16_CPU(index->size);
414 + LE16_CPU(index->u0);
415 + LE16_CPU(index->u1);
416 + return sizeof( pst_index );
417 + } else {
418 + pst_index32 index32;
419 + memcpy(&index32, buf, sizeof(pst_index32));
420 + LE32_CPU(index32->id);
421 + LE32_CPU(index32->offset);
422 + LE16_CPU(index32->size);
423 + LE16_CPU(index32->u1);
424 + index->id = index32.id;
425 + index->offset = index32.offset;
426 + index->size = index32.size;
427 + index->u1 = index32.u1;
428 +
429 + return sizeof( pst_index32 );
430 + }
431
432 -int32_t _pst_build_id_ptr(pst_file *pf, int32_t offset, int32_t depth, int32_t start_val, int32_t end_val) {
433 - struct _pst_table_ptr_struct table, table2;
434 + return 0;
435 +} // }}}
436 +
437 +int32_t _pst_build_id_ptr(pst_file *pf, off_t offset, int32_t depth, int32_t start_val, int32_t end_val) {
438 + struct _pst_table_ptr_structn table, table2;
439 pst_index_ll *i_ptr=NULL;
440 pst_index index;
441 // int fpos = ftell(pf->fp);
442 int32_t x, ret;
443 int32_t old = start_val;
444 + off_t roff;
445 char *buf = NULL, *bptr = NULL;
446
447 DEBUG_ENT("_pst_build_id_ptr");
448 - if (pf->index1_depth - depth == 0) {
449 + if (pf->index1_depth - depth == 0) { // {{{ Leaf table, add indexes to linked list
450 // we must be at a leaf table. These are index items
451 DEBUG_INDEX(("Reading Items\n"));
452 // fseek(pf->fp, offset, SEEK_SET);
453 @@ -519,15 +656,14 @@
454 }
455 bptr = buf;
456 // DEBUG_HEXDUMPC(buf, BLOCK_SIZE, 12);
457 - memcpy(&index, bptr, sizeof(index));
458 - LE32_CPU(index.id);
459 - LE32_CPU(index.offset);
460 - LE16_CPU(index.size);
461 - LE16_CPU(index.u1);
462 - bptr += sizeof(index);
463 + roff = offset;
464 + bptr += _pst_decode_index( &index, bptr );
465
466 - while(index.id != 0 && x < 42 && bptr < buf+BLOCK_SIZE && index.id < end_val) {
467 - DEBUG_INDEX(("[%i]%i Item [id = %#x, offset = %#x, u1 = %#x, size = %i(%#x)]\n", depth, ++x, index.id, index.offset, index.u1, index.size, index.size));
468 + while(index.id != 0 && x < 42 && bptr < buf+BLOCK_SIZE && index.id < end_val) { // {{{
469 + DEBUG_INDEX(("%08x [%i]%i Item [ id = %#llx, offset = %#llx, u1 = %#x, size = %i(%#x)] %p %p\n",
470 + roff,
471 + depth, ++x, index.id, index.offset, index.u1,
472 + index.size, index.size, buf, bptr ));
473 if (index.id & 0x02) {
474 DEBUG_INDEX(("two-bit set!!\n"));
475 }
476 @@ -543,7 +679,7 @@
477 pf->id_depth_ok = 1;
478 }
479 // u1 could be a flag. if bit 0x2 is not set, it might be deleted
480 - // if (index.u1 & 0x2 || index.u1 & 0x4) {
481 + // if (index.u1 & 0x2 || index.u1 & 0x4)
482 // ignore the above condition. it doesn't appear to hold
483 if (old > index.id) { // then we have back-slid on the new values
484 DEBUG_INDEX(("Back slider detected - Old value [%#x] greater than new [%#x]. Progressing to next table\n", old, index.id));
485 @@ -551,6 +687,7 @@
486 return 2;
487 }
488 old = index.id;
489 + // {{{ Add index to linked list
490 i_ptr = (pst_index_ll*) xmalloc(sizeof(pst_index_ll));
491 i_ptr->id = index.id;
492 i_ptr->offset = index.offset;
493 @@ -562,15 +699,12 @@
494 if (pf->i_head == NULL)
495 pf->i_head = i_ptr;
496 pf->i_tail = i_ptr;
497 - memcpy(&index, bptr, sizeof(index));
498 - LE32_CPU(index.id);
499 - LE32_CPU(index.offset);
500 - LE16_CPU(index.size);
501 - LE16_CPU(index.u1);
502 - bptr += sizeof(index);
503 - }
504 - // fseek(pf->fp, fpos, SEEK_SET);
505 - if (x < 42) { // we have stopped prematurley. Why?
506 + // }}}
507 +
508 + roff = offset + (bptr - buf);
509 + bptr +=_pst_decode_index( &index, bptr );
510 + } // }}}
511 + if (x < 42) { // {{{ we have stopped prematurley. Why?
512 if (index.id == 0) {
513 DEBUG_INDEX(("Found index.id == 0\n"));
514 } else if (!(bptr < buf+BLOCK_SIZE)) {
515 @@ -581,12 +715,12 @@
516 } else {
517 DEBUG_INDEX(("Stopped for unknown reason\n"));
518 }
519 - }
520 + } // }}}
521 if (buf) free (buf);
522 DEBUG_RET();
523 return 2;
524 - } else {
525 - // this is then probably a table of offsets to more tables.
526 + } // }}}
527 + else { // {{{ probably a table of offsets to tables, recurse
528 DEBUG_INDEX(("Reading Table Items\n"));
529
530 x = 0;
531 @@ -600,15 +734,10 @@
532 bptr = buf;
533 // DEBUG_HEXDUMPC(buf, BLOCK_SIZE, 12);
534
535 - memcpy(&table, bptr, sizeof(table));
536 - LE32_CPU(table.start);
537 - LE32_CPU(table.u1);
538 - LE32_CPU(table.offset);
539 - bptr += sizeof(table);
540 - memcpy(&table2, bptr, sizeof(table));
541 - LE32_CPU(table2.start);
542 - LE32_CPU(table2.u1);
543 - LE32_CPU(table2.offset);
544 +
545 + roff = offset;
546 + bptr += _pst_decode_table( &table, bptr );
547 + _pst_decode_table( &table2, bptr );
548
549 if (start_val != -1 && table.start != start_val) {
550 DEBUG_WARN(("This table isn't right. Must be corruption, or I got it wrong!\n"));
551 @@ -619,7 +748,9 @@
552 }
553
554 while (table.start != 0 && bptr < buf+BLOCK_SIZE && table.start < end_val) {
555 - DEBUG_INDEX(("[%i] %i Table [start id = %#x, u1 = %#x, offset = %#x]\n", depth, ++x, table.start, table.u1, table.offset));
556 + DEBUG_INDEX(("%08x [%i] %i Table [start id = %#x, u1 = %#x, offset = %#x]\n",
557 + roff,
558 + depth, ++x, table.start, table.u1, table.offset));
559
560 if (table2.start <= table.start)
561 // this should only be the case when we come to the end of the table
562 @@ -643,15 +774,9 @@
563 } else {
564 DEBUG_INDEX(("child has returned without a known error [%i]\n", ret));
565 }
566 - memcpy(&table, bptr, sizeof(table));
567 - LE32_CPU(table.start);
568 - LE32_CPU(table.u1);
569 - LE32_CPU(table.offset);
570 - bptr += sizeof(table);
571 - memcpy(&table2, bptr, sizeof(table));
572 - LE32_CPU(table2.start);
573 - LE32_CPU(table2.u1);
574 - LE32_CPU(table2.offset);
575 + bptr += _pst_decode_table( &table, bptr );
576 + roff = offset + ( bptr - buf );
577 + _pst_decode_table( &table2, bptr );
578 }
579
580 if (table.start == 0) {
581 @@ -669,21 +794,23 @@
582 DEBUG_INDEX(("End of table of pointers\n"));
583 DEBUG_RET();
584 return 3;
585 - }
586 + } // }}}
587 DEBUG_WARN(("ERROR ** Shouldn't be here!\n"));
588
589 DEBUG_RET();
590 return 1;
591 }
592
593 +
594 #define DESC_BLOCK_SIZE 520
595 -int32_t _pst_build_desc_ptr (pst_file *pf, int32_t offset, int32_t depth, int32_t *high_id, int32_t start_id,
596 +int32_t _pst_build_desc_ptr (pst_file *pf, off_t offset, int32_t depth, int32_t *high_id, int32_t start_id,
597 int32_t end_val) {
598 - struct _pst_table_ptr_struct table, table2;
599 - pst_desc desc_rec;
600 + struct _pst_table_ptr_structn table, table2;
601 + pst_descn desc_rec;
602 pst_desc_ll *d_ptr=NULL, *d_par=NULL;
603 int32_t i = 0, y, prev_id=-1;
604 char *buf = NULL, *bptr;
605 + off_t roff;
606
607 struct _pst_d_ptr_ll {
608 pst_desc_ll * ptr;
609 @@ -696,8 +823,7 @@
610
611 int32_t d_ptr_count = 0;
612 DEBUG_ENT("_pst_build_desc_ptr");
613 - if (pf->index2_depth-depth == 0) {
614 - // leaf node
615 + if (pf->index2_depth-depth == 0) { // {{{ leaf node, index it
616 if (_pst_read_block_size(pf, offset, DESC_BLOCK_SIZE, &buf, 0, 0) < DESC_BLOCK_SIZE) {
617 DEBUG_WARN(("I didn't get all the index that I wanted. _pst_read_block_size returned less than requested\n"));
618 DEBUG_RET();
619 @@ -707,22 +833,17 @@
620
621 //DEBUG_HEXDUMPC(buf, DESC_BLOCK_SIZE, 16);
622
623 - memcpy(&desc_rec, bptr, sizeof(desc_rec));
624 - LE32_CPU(desc_rec.d_id);
625 - LE32_CPU(desc_rec.desc_id);
626 - LE32_CPU(desc_rec.list_id);
627 - LE32_CPU(desc_rec.parent_id);
628 - bptr+= sizeof(desc_rec);
629 + roff = offset;
630 + bptr += _pst_decode_desc( &desc_rec, bptr );
631
632 if (end_val <= start_id) {
633 DEBUG_WARN(("The end value is BEFORE the start value. This function will quit. Soz. [start:%#x, end:%#x]\n",
634 start_id, end_val));
635 }
636
637 - while (i < 0x1F && desc_rec.d_id < end_val && (prev_id == -1 || desc_rec.d_id > prev_id)) {
638 - DEBUG_INDEX(("[%i] Item(%#x) = [d_id = %#x, desc_id = %#x, "
639 - "list_id = %#x, parent_id = %#x]\n", depth, i, desc_rec.d_id,
640 - desc_rec.desc_id, desc_rec.list_id, desc_rec.parent_id));
641 + while (i < 0x1F && desc_rec.d_id < end_val && (prev_id == -1 || desc_rec.d_id > prev_id)) { // {{{
642 + DEBUG_INDEX(("Bliss %d: %llx %p %p %p ", i, offset, buf, bptr, bptr ));
643 + dump_desc( roff, depth, i, &desc_rec );
644 i++;
645
646 if (start_id != -1 && desc_rec.d_id != start_id) {
647 @@ -737,20 +858,16 @@
648 }
649
650 if (desc_rec.d_id == 0) {
651 - memcpy(&desc_rec, bptr, sizeof(desc_rec));
652 - LE32_CPU(desc_rec.d_id);
653 - LE32_CPU(desc_rec.desc_id);
654 - LE32_CPU(desc_rec.list_id);
655 - LE32_CPU(desc_rec.parent_id);
656 - bptr+=sizeof(desc_rec);
657 - continue;
658 + roff = offset + ( bptr - buf );
659 + bptr+=_pst_decode_desc( &desc_rec, bptr );
660 + continue;
661 }
662 prev_id = desc_rec.d_id;
663
664 // When duplicates found, just update the info.... perhaps this is correct functionality
665 DEBUG_INDEX(("Searching for existing record\n"));
666
667 - if (desc_rec.d_id <= *high_id && (d_ptr = _pst_getDptr(pf, desc_rec.d_id)) != NULL) {
668 + if (desc_rec.d_id <= *high_id && (d_ptr = _pst_getDptr(pf, desc_rec.d_id)) != NULL) { // {{{
669 DEBUG_INDEX(("Updating Existing Values\n"));
670 d_ptr->list_index = _pst_getID(pf, desc_rec.list_id);
671 d_ptr->desc = _pst_getID(pf, desc_rec.desc_id);
672 @@ -802,7 +919,7 @@
673 d_ptr_ptr = d_ptr_ptr->next;
674 }
675
676 - if (d_ptr_ptr == NULL && (d_par = _pst_getDptr(pf, desc_rec.parent_id)) == NULL) {
677 + if (d_ptr_ptr == NULL && (d_par = _pst_getDptr(pf, desc_rec.parent_id)) == NULL) { // {{{
678 // check in the lost/found list
679 lf_ptr = lf_head;
680 while (lf_ptr != NULL && lf_ptr->ptr->id != desc_rec.parent_id) {
681 @@ -820,7 +937,7 @@
682 d_par = lf_ptr->ptr;
683 DEBUG_INDEX(("Found parent (%#x) in Lost and Found\n", d_par->id));
684 }
685 - }
686 + } // }}}
687
688 if (d_ptr_ptr != NULL || d_par != NULL) {
689 if (d_ptr_ptr != NULL)
690 @@ -857,7 +974,8 @@
691 }
692 }
693
694 - } else {
695 + } // }}}
696 + else {
697 if (*high_id < desc_rec.d_id) {
698 DEBUG_INDEX(("Updating New High\n"));
699 *high_id = desc_rec.d_id;
700 @@ -866,8 +984,10 @@
701 d_ptr = (pst_desc_ll*) xmalloc(sizeof(pst_desc_ll));
702 // DEBUG_INDEX(("Item pointer is %p\n", d_ptr));
703 d_ptr->id = desc_rec.d_id;
704 + DEBUG_INDEX(("Weird %llx moo", desc_rec.list_id ));
705 d_ptr->list_index = _pst_getID(pf, desc_rec.list_id);
706 d_ptr->desc = _pst_getID(pf, desc_rec.desc_id);
707 + //ASSERT( d_ptr->desc != NULL );
708 d_ptr->prev = NULL;
709 d_ptr->next = NULL;
710 d_ptr->parent = NULL;
711 @@ -876,7 +996,7 @@
712 d_ptr->no_child = 0;
713
714 DEBUG_INDEX(("Searching for parent\n"));
715 - if (desc_rec.parent_id == 0 || desc_rec.parent_id == desc_rec.d_id) {
716 + if (desc_rec.parent_id == 0 || desc_rec.parent_id == desc_rec.d_id) { // {{{
717 if (desc_rec.parent_id == 0) {
718 DEBUG_INDEX(("No Parent\n"));
719 } else {
720 @@ -888,7 +1008,8 @@
721 pf->d_head = d_ptr;
722 d_ptr->prev = pf->d_tail;
723 pf->d_tail = d_ptr;
724 - } else {
725 + } // }}}
726 + else { // {{{
727 d_ptr_ptr = d_ptr_head;
728 while (d_ptr_ptr != NULL && d_ptr_ptr->ptr->id != desc_rec.parent_id) {
729 d_ptr_ptr = d_ptr_ptr->next;
730 @@ -947,7 +1068,7 @@
731 d_ptr->prev = d_par->child_tail;
732 d_par->child_tail = d_ptr;
733 }
734 - }
735 + } // }}}
736 }
737 // check here to see if d_ptr is the parent of any of the items in the lost / found list
738 lf_ptr = lf_head; lf_shd = NULL;
739 @@ -977,16 +1098,13 @@
740 lf_ptr = lf_ptr->next;
741 }
742 }
743 - memcpy(&desc_rec, bptr, sizeof(desc_rec));
744 - LE32_CPU(desc_rec.d_id);
745 - LE32_CPU(desc_rec.desc_id);
746 - LE32_CPU(desc_rec.list_id);
747 - LE32_CPU(desc_rec.parent_id);
748 - bptr+= sizeof(desc_rec);
749 - }
750 +
751 + roff = offset + ( bptr - buf );
752 + bptr+= _pst_decode_desc( &desc_rec, bptr );
753 + } // }}}
754 // fseek(pf->fp, fpos, SEEK_SET);
755 - } else {
756 - // hopefully a table of offsets to more tables
757 + } // }}}
758 + else { // {{{ table of offsets to more tables, recurse
759 if (_pst_read_block_size(pf, offset, DESC_BLOCK_SIZE, &buf, 0, 0) < DESC_BLOCK_SIZE) {
760 DEBUG_WARN(("didn't read enough desc index. _pst_read_block_size returned less than requested\n"));
761 DEBUG_RET();
762 @@ -995,15 +1113,8 @@
763 bptr = buf;
764 // DEBUG_HEXDUMPC(buf, DESC_BLOCK_SIZE, 12);
765
766 - memcpy(&table, bptr, sizeof(table));
767 - LE32_CPU(table.start);
768 - LE32_CPU(table.u1);
769 - LE32_CPU(table.offset);
770 - bptr+=sizeof(table);
771 - memcpy(&table2, bptr, sizeof(table));
772 - LE32_CPU(table2.start);
773 - LE32_CPU(table2.u1);
774 - LE32_CPU(table2.offset);
775 + bptr+=_pst_decode_table( &table, bptr );
776 + _pst_decode_table( &table2, bptr );
777
778 if (start_id != -1 && table.start != start_id) {
779 DEBUG_WARN(("This table isn't right. Perhaps we are too deep, or corruption\n"));
780 @@ -1034,20 +1145,13 @@
781 _pst_build_desc_ptr(pf, table.offset, depth+1, high_id, table.start, table2.start);
782 }
783
784 - memcpy(&table, bptr, sizeof(table));
785 - LE32_CPU(table.start);
786 - LE32_CPU(table.u1);
787 - LE32_CPU(table.offset);
788 - bptr+=sizeof(table);
789 - memcpy(&table2, bptr, sizeof(table));
790 - LE32_CPU(table2.start);
791 - LE32_CPU(table2.u1);
792 - LE32_CPU(table2.offset);
793 + bptr+=_pst_decode_table( &table, bptr );
794 + _pst_decode_table( &table2, bptr );
795 }
796 if (buf) free(buf);
797 DEBUG_RET();
798 return 3;
799 - }
800 + } // }}}
801 // ok, lets try freeing the d_ptr_head cache here
802 while (d_ptr_head != NULL) {
803 d_ptr_ptr = d_ptr_head->next;
804 @@ -1183,7 +1287,7 @@
805 return item;
806 }
807
808 -pst_num_array * _pst_parse_block(pst_file *pf, u_int32_t block_id, pst_index2_ll *i2_head) {
809 +pst_num_array * _pst_parse_block(pst_file *pf, u_int32_t block_id, pst_index2_ll *i2_head) { // {{{
810 unsigned char *buf = NULL;
811 pst_num_array *na_ptr = NULL, *na_head = NULL;
812 pst_block_offset block_offset;
813 @@ -1194,6 +1298,7 @@
814 size_t read_size=0;
815 pst_x_attrib_ll *mapptr;
816
817 +
818 struct {
819 u_int16_t type;
820 u_int16_t ref_type;
821 @@ -1238,13 +1343,13 @@
822
823 // DEBUG_EMAIL(("About to read %i bytes from offset %#x\n", block->size, block->offset));
824
825 - if ((read_size = _pst_ff_getIDblock_dec(pf, block_id, &buf)) == 0) {
826 - // if (_pst_read_block_size(pf, block->offset, block->size, &buf, PST_ENC, 0) < block->size) {
827 + if ((read_size = _pst_ff_getIDblock_dec(pf, block_id, &buf)) == 0) { // {{{ error
828 + // if (_pst_read_block_size(pf, block->offset, block->size, &buf, PST_ENC, 0) < block->size)
829 WARN(("Error reading block id %#x\n", block_id));
830 if (buf) free (buf);
831 DEBUG_RET();
832 return NULL;
833 - }
834 + } // }}}
835 DEBUG_EMAIL(("pointer to buf is %p\n", buf));
836
837 memcpy(&block_hdr, &(buf[0]), sizeof(block_hdr));
838 @@ -1255,7 +1360,7 @@
839
840 ind_ptr = block_hdr.index_offset;
841
842 - if (block_hdr.type == 0xBCEC) { //type 1
843 + if (block_hdr.type == 0xBCEC) { // {{{ type 1, populate block_offset
844 block_type = 1;
845
846 _pst_getBlockOffset(buf, ind_ptr, block_hdr.offset, &block_offset);
847 @@ -1281,7 +1386,8 @@
848 num_list = (to_ptr - fr_ptr)/sizeof(table_rec);
849 num_recs = 1; // only going to one object in these blocks
850 rec_size = 0; // doesn't matter cause there is only one object
851 - } else if (block_hdr.type == 0x7CEC) { //type 2
852 + } // }}}
853 + else if (block_hdr.type == 0x7CEC) { // {{{ type 2, populate block_offset from seven_c_blk
854 block_type = 2;
855
856 _pst_getBlockOffset(buf, ind_ptr, block_hdr.offset, &block_offset);
857 @@ -1340,16 +1446,17 @@
858
859 _pst_getBlockOffset(buf, ind_ptr, seven_c_blk.ind2_offset, &block_offset);
860 ind2_ptr = block_offset.from;
861 - } else {
862 + } // }}}
863 + else { // {{{ error
864 WARN(("ERROR: Unknown block constant - %#X for id %#x\n", block_hdr.type, block_id));
865 DEBUG_HEXDUMPC(buf, read_size,0x10);
866 if (buf) free(buf);
867 DEBUG_RET();
868 return NULL;
869 - }
870 + } // }}}
871
872 DEBUG_EMAIL(("Mallocing number of items %i\n", num_recs));
873 - while (count_rec < num_recs) {
874 + while (count_rec < num_recs) { // {{{
875 na_ptr = (pst_num_array*) xmalloc(sizeof(pst_num_array));
876 memset(na_ptr, 0, sizeof(pst_num_array));
877 if (na_head == NULL) {
878 @@ -1371,13 +1478,14 @@
879 fr_ptr = list_start; // init fr_ptr to the start of the list.
880 cur_list = 0;
881 stop = 0;
882 - while (!stop && cur_list < num_list) { //we will increase fr_ptr as we progress through index
883 - if (block_type == 1) {
884 + while (!stop && cur_list < num_list) { //{{{ we will increase fr_ptr as we progress through index
885 + if (block_type == 1) { // {{{
886 memcpy(&table_rec, &(buf[fr_ptr]), sizeof(table_rec));
887 LE16_CPU(table_rec.type);
888 LE16_CPU(table_rec.ref_type);
889 fr_ptr += sizeof(table_rec);
890 - } else if (block_type == 2) {
891 + } // }}}
892 + else if (block_type == 2) { // {{{
893 // we will copy the table2_rec values into a table_rec record so that we can keep the rest of the code
894 memcpy(&table2_rec, &(buf[fr_ptr]), sizeof(table2_rec));
895 LE16_CPU(table2_rec.ref_type);
896 @@ -1398,12 +1506,13 @@
897 }
898
899 fr_ptr += sizeof(table2_rec);
900 - } else {
901 + } // }}}
902 + else { // {{{ ERROR
903 WARN(("Missing code for block_type %i\n", block_type));
904 if (buf) free(buf);
905 DEBUG_RET();
906 return NULL;
907 - }
908 + } // }}}
909 cur_list++; // get ready to read next bit from list
910 DEBUG_EMAIL(("reading block %i (type=%#x, ref_type=%#x, value=%#x)\n",
911 x, table_rec.type, table_rec.ref_type, table_rec.value));
912 @@ -1466,10 +1575,10 @@
913 || table_rec.ref_type == 0x001E || table_rec.ref_type == 0x0102
914 || table_rec.ref_type == 0x0040 || table_rec.ref_type == 0x101E
915 || table_rec.ref_type == 0x0048 || table_rec.ref_type == 0x1102
916 - || table_rec.ref_type == 0x1014) {
917 + || table_rec.ref_type == 0x1014 || table_rec.ref_type == 0x001F ) {
918 //contains index_ref to data
919 LE32_CPU(table_rec.value);
920 - if ((table_rec.value & 0x0000000F) == 0xF) {
921 + if ((table_rec.value & 0x0000000F) == 0xF) { // {{{
922 // if value ends in 'F' then this should be an id2 value
923 DEBUG_EMAIL(("Found id2 [%#x] value. Will follow it\n",
924 table_rec.value));
925 @@ -1483,7 +1592,8 @@
926 }
927 DEBUG_EMAIL(("Read %i bytes to a buffer at %p\n",
928 na_ptr->items[x]->size, na_ptr->items[x]->data));
929 - } else if (table_rec.value != 0) {
930 + } // }}}
931 + else if (table_rec.value != 0) {
932 if ((table_rec.value >> 4)+ind_ptr > read_size) {
933 // check that we will not be outside the buffer we have read
934 DEBUG_WARN(("table_rec.value [%#x] is outside of block [%#x]\n",
935 @@ -1507,10 +1617,30 @@
936 }
937
938 // plus one for good luck (and strings) we will null terminate all reads
939 - na_ptr->items[x]->data = (char*) xmalloc(size+1);
940 - memcpy(na_ptr->items[x]->data, &(buf[t_ptr]), size);
941 - na_ptr->items[x]->data[size] = '\0'; // null terminate buffer
942 + if( 0x001F == table_rec.ref_type ) {
943 + VBUF_STATIC( strbuf, 1024 );
944 + VBUF_STATIC( unibuf, 1024 );
945 + //need UTF-16 zero-termination
946 + vbset( strbuf, &(buf[t_ptr]), size );
947 + vbappend( strbuf, "\0\0", 2 );
948 + DEBUG_INDEX(("Iconv in: "));
949 + DEBUG_HEXDUMPC( strbuf->b, strbuf->dlen, 0x10 );
950 + vb_utf16to8( unibuf, strbuf->b, strbuf->dlen );
951 + na_ptr->items[x]->data = (char*) xmalloc(unibuf->dlen);
952 + memcpy(na_ptr->items[x]->data, unibuf->b, unibuf->dlen);
953 + na_ptr->items[x]->size = unibuf->dlen;
954 + DEBUG_INDEX(("Iconv out: "));
955 + DEBUG_HEXDUMPC(na_ptr->items[x]->data, na_ptr->items[x]->size, 0x10 );
956 + }
957 + else {
958 + na_ptr->items[x]->data = (char*) xmalloc(size+1);
959 + memcpy(na_ptr->items[x]->data, &(buf[t_ptr]), size);
960 + na_ptr->items[x]->data[size] = '\0'; // null terminate buffer
961 + }
962
963 + DEBUG_INDEX(("Item Puke: type: %x, ref_type: %x, value: %x\n",
964 + table_rec.type, table_rec.ref_type, table_rec.value ));
965 + DEBUG_HEXDUMPC(na_ptr->items[x]->data, size, 0x10 );
966 if (table_rec.ref_type == 0xd) {
967 // there is still more to do for the type of 0xD
968 type_d_rec = (struct _type_d_rec*) na_ptr->items[x]->data;
969 @@ -1526,7 +1656,6 @@
970 }
971 DEBUG_EMAIL(("Read %i bytes into a buffer at %p\n",
972 na_ptr->items[x]->size, na_ptr->items[x]->data));
973 - // }
974 }
975 } else {
976 DEBUG_EMAIL(("Ignoring 0 value in offset\n"));
977 @@ -1548,18 +1677,18 @@
978 return NULL;
979 }
980 x++;
981 - }
982 + } // }}}
983 DEBUG_EMAIL(("increasing ind2_ptr by %i [%#x] bytes. Was %#x, Now %#x\n",
984 rec_size, rec_size, ind2_ptr,
985 ind2_ptr+rec_size));
986 ind2_ptr += rec_size;
987 count_rec++;
988 - }
989 + } // }}}
990 if (buf != NULL)
991 free(buf);
992 DEBUG_RET();
993 return na_head;
994 -}
995 +} // }}}
996
997 // check if item->email is NULL, and init if so
998 #define MALLOC_EMAIL(x) { if (x->email == NULL) { x->email = (pst_item_email*) xmalloc(sizeof(pst_item_email)); memset (x->email, 0, sizeof(pst_item_email));} }
999 @@ -3384,7 +3513,7 @@
1000 }
1001 if (_pst_read_block_size(pf, list->offset, list->size, &buf, PST_NO_ENC,0) < list->size) {
1002 //an error occured in block read
1003 - WARN(("block read error occured. offset = %#x, size = %#x\n", list->offset, list->size));
1004 + WARN(("block read error occured. offset = %#llx, size = %#llx\n", list->offset, list->size));
1005 DEBUG_RET();
1006 return NULL;
1007 }
1008 @@ -3394,7 +3523,7 @@
1009 LE16_CPU(block_head.count);
1010
1011 if (block_head.type != 0x0002) { // some sort of constant?
1012 - WARN(("Unknown constant [%#x] at start of id2 values [offset %#x].\n", block_head.type, list->offset));
1013 + WARN(("Unknown constant [%#x] at start of id2 values [offset %#llx].\n", block_head.type, list->offset));
1014 DEBUG_RET();
1015 return NULL;
1016 }
1017 @@ -3678,7 +3807,7 @@
1018 return 0;
1019 }
1020
1021 -pst_index_ll * _pst_getID(pst_file* pf, u_int32_t id) {
1022 +pst_index_ll * _pst_getID(pst_file* pf, u_int64_t id) {
1023 // static pst_index_ll *old_val = NULL; //this should make it quicker
1024 pst_index_ll *ptr = NULL;
1025 DEBUG_ENT("_pst_getID");
1026 @@ -3693,9 +3822,10 @@
1027 // Dave: I don't think I should do this. next bit. I really think it doesn't work
1028 // it isn't based on sound principles either.
1029 // update: seems that the last two sig bits are flags. u tell me!
1030 - id &= 0xFFFFFFFE; // remove least sig. bit. seems that it might work if I do this
1031 + //id &= 0xFFFFFFFE; // remove least sig. bit. seems that it might work if I do this
1032 + id -= (id & 1 );
1033
1034 - DEBUG_INDEX(("Trying to find %#x\n", id));
1035 + DEBUG_INDEX(("Trying to find %#llx\n", id));
1036
1037 if (ptr == NULL)
1038 ptr = pf->i_head;
1039 @@ -3927,6 +4057,9 @@
1040 return -1;
1041 }
1042
1043 + DEBUG_INDEX(("_pst_decrypt()"));
1044 + DEBUG_HEXDUMPC(buf, size, 0x10 );
1045 +
1046 if (type == PST_COMP_ENCRYPT) {
1047 x = 0;
1048 while (x < size) {
1049 @@ -3935,6 +4068,9 @@
1050 buf[x] = comp_enc[y]; // transpose from encrypt array
1051 x++;
1052 }
1053 +
1054 + DEBUG_INDEX(("_pst_decrypt() result"));
1055 + DEBUG_HEXDUMPC(buf, size, 0x10 );
1056 } else {
1057 WARN(("Unknown encryption: %i. Cannot decrypt\n", type));
1058 DEBUG_RET();
1059 @@ -3944,7 +4080,23 @@
1060 return 0;
1061 }
1062
1063 -int32_t _pst_getAtPos(FILE *fp, int32_t pos, void* buf, u_int32_t size) {
1064 +int64_t _pst_getIntAtPos(FILE *fp, off_t pos ) {
1065 + int64_t buf64;
1066 + int32_t buf32;
1067 +
1068 + if(do_read64) {
1069 + _pst_getAtPos(fp, pos, &buf64, sizeof( buf64 ) );
1070 + LE64_CPU(buf64);
1071 + return buf64;
1072 + }
1073 + else {
1074 + _pst_getAtPos(fp, pos, &buf32, sizeof( buf32 ) );
1075 + LE32_CPU(buf32);
1076 + return buf32;
1077 + }
1078 +}
1079 +
1080 +int32_t _pst_getAtPos(FILE *fp, off_t pos, void* buf, u_int32_t size) {
1081 DEBUG_ENT("_pst_getAtPos");
1082 if (fseek(fp, pos, SEEK_SET) == -1) {
1083 DEBUG_RET();
1084 diff -Naur ../orig/libpst-0.5.1/libpst.h libpst64-060926/libpst.h
1085 --- ../orig/libpst-0.5.1/libpst.h 2004-11-17 07:48:03.000000000 -0700
1086 +++ libpst64-060926/libpst.h 2006-09-26 14:09:55.000000000 -0600
1087 @@ -117,6 +117,8 @@
1088 #define PST_APP_LABEL_ANNIVERSARY 9 // Anniversary
1089 #define PST_APP_LABEL_PHONE_CALL 10// Phone Call
1090
1091 +extern int do_read64;
1092 +
1093 typedef struct _pst_misc_6_struct {
1094 int32_t i1;
1095 int32_t i2;
1096 @@ -132,26 +134,72 @@
1097 int32_t id;
1098 } pst_entryid;
1099
1100 -typedef struct _pst_desc_struct {
1101 +typedef struct _pst_desc_struct32 {
1102 u_int32_t d_id;
1103 u_int32_t desc_id;
1104 u_int32_t list_id;
1105 u_int32_t parent_id;
1106 -} pst_desc;
1107 +} pst_desc32;
1108
1109 -typedef struct _pst_index_struct{
1110 +typedef struct _pst_desc_structn {
1111 + u_int64_t d_id;
1112 + u_int64_t desc_id;
1113 + u_int64_t list_id;
1114 +// u_int64_t parent_id;
1115 + u_int32_t parent_id;
1116 + u_int32_t u1;
1117 +} pst_descn;
1118 +
1119 +typedef struct _pst_index_struct32{
1120 u_int32_t id;
1121 int32_t offset;
1122 u_int16_t size;
1123 int16_t u1;
1124 +} pst_index32;
1125 +
1126 +/*
1127 +typedef struct _pst_index_struct64{
1128 + u_int64_t id;
1129 + int64_t offset;
1130 + u_int16_t size;
1131 + int16_t u1;
1132 +} pst_index64;
1133 +*/
1134 +
1135 +typedef struct _pst_index_struct{
1136 + u_int64_t id;
1137 + int64_t offset;
1138 + u_int16_t size;
1139 + int16_t u0;
1140 + int32_t u1;
1141 } pst_index;
1142
1143 -typedef struct _pst_index_tree {
1144 +/*
1145 +typedef union _pst_index_struct {
1146 + pst_index32 i32;
1147 + pst_index64 i64;
1148 +} pst_index;
1149 +
1150 +#define INDEX_ID(x) ((do_read64)?x.i64.id:x.i32.id)
1151 +#define INDEX_OFFSET(x) ((do_read64)?x.i64.offset:x.i32.offset)
1152 +#define INDEX_SIZE(x) ((do_read64)?x.i64.size:x.i32.size)
1153 +#define INDEX_U1(x) ((do_read64)?x.i64.u1:x.i32.u1)
1154 +*/
1155 +
1156 +typedef struct _pst_index_tree32 {
1157 u_int32_t id;
1158 int32_t offset;
1159 - size_t size;
1160 + int32_t size;
1161 int32_t u1;
1162 struct _pst_index_tree * next;
1163 +} pst_index_ll32;
1164 +
1165 +typedef struct _pst_index_tree {
1166 + u_int64_t id;
1167 + int64_t offset;
1168 + int64_t size;
1169 + int64_t u1;
1170 + struct _pst_index_tree * next;
1171 } pst_index_ll;
1172
1173 typedef struct _pst_index2_tree {
1174 @@ -421,6 +469,10 @@
1175 int32_t index1_count;
1176 int32_t index2;
1177 int32_t index2_count;
1178 + int64_t index1_64;
1179 + int64_t index1_count_64;
1180 + int64_t index2_64;
1181 + int64_t index2_count_64;
1182 FILE * fp;
1183 size_t size;
1184 unsigned char index1_depth;
1185 @@ -460,6 +512,7 @@
1186 };
1187
1188 // prototypes
1189 +void set_read64();
1190 int32_t pst_open(pst_file *pf, char *name, char *mode);
1191 int32_t pst_close(pst_file *pf);
1192 pst_desc_ll * pst_getTopOfFolders(pst_file *pf, pst_item *root);
1193 @@ -470,8 +523,8 @@
1194 pst_desc_ll* pst_getNextDptr(pst_desc_ll* d);
1195 int32_t pst_load_extended_attributes(pst_file *pf);
1196
1197 -int32_t _pst_build_id_ptr(pst_file *pf, int32_t offset, int32_t depth, int32_t start_val, int32_t end_val);
1198 -int32_t _pst_build_desc_ptr (pst_file *pf, int32_t offset, int32_t depth, int32_t *high_id,
1199 +int32_t _pst_build_id_ptr(pst_file *pf, off_t offset, int32_t depth, int32_t start_val, int32_t end_val);
1200 +int32_t _pst_build_desc_ptr (pst_file *pf, off_t offset, int32_t depth, int32_t *high_id,
1201 int32_t start_id, int32_t end_val);
1202 pst_item* _pst_getItem(pst_file *pf, pst_desc_ll *d_ptr);
1203 void * _pst_parse_item (pst_file *pf, pst_desc_ll *d_ptr);
1204 @@ -485,13 +538,14 @@
1205 int32_t _pst_free_xattrib(pst_x_attrib_ll *x);
1206 int32_t _pst_getBlockOffset(char *buf, int32_t i_offset, int32_t offset, pst_block_offset *p);
1207 pst_index2_ll * _pst_build_id2(pst_file *pf, pst_index_ll* list, pst_index2_ll* head_ptr);
1208 -pst_index_ll * _pst_getID(pst_file* pf, u_int32_t id);
1209 +pst_index_ll * _pst_getID(pst_file* pf, u_int64_t id);
1210 pst_index_ll * _pst_getID2(pst_index2_ll * ptr, u_int32_t id);
1211 pst_desc_ll * _pst_getDptr(pst_file *pf, u_int32_t id);
1212 size_t _pst_read_block_size(pst_file *pf, int32_t offset, size_t size, char ** buf, int32_t do_enc,
1213 unsigned char is_index);
1214 int32_t _pst_decrypt(unsigned char *buf, size_t size, int32_t type);
1215 -int32_t _pst_getAtPos(FILE *fp, int32_t pos, void* buf, u_int32_t size);
1216 +int64_t _pst_getIntAtPos(FILE *fp, off_t pos);
1217 +int32_t _pst_getAtPos(FILE *fp, off_t pos, void* buf, u_int32_t size);
1218 int32_t _pst_get (FILE *fp, void *buf, u_int32_t size);
1219 size_t _pst_ff_getIDblock_dec(pst_file *pf, u_int32_t id, unsigned char **b);
1220 size_t _pst_ff_getIDblock(pst_file *pf, u_int32_t id, unsigned char** b);
1221 diff -Naur ../orig/libpst-0.5.1/libstrfunc.c libpst64-060926/libstrfunc.c
1222 --- ../orig/libpst-0.5.1/libstrfunc.c 2004-11-17 07:48:03.000000000 -0700
1223 +++ libpst64-060926/libstrfunc.c 2006-09-26 14:09:55.000000000 -0600
1224 @@ -67,3 +67,30 @@
1225 return _sf_b64_buf=output;
1226 };
1227
1228 +void hexdump(char *hbuf, int start, int stop, int ascii) /* {{{ HexDump all or a part of some buffer */
1229 +{
1230 + char c;
1231 + int diff,i;
1232 +
1233 + while (start < stop ) {
1234 + diff = stop - start;
1235 + if (diff > 16) diff = 16;
1236 +
1237 + fprintf(stderr, ":%08X ",start);
1238 +
1239 + for (i = 0; i < diff; i++) {
1240 + if( 8 == i ) fprintf( stderr, " " );
1241 + fprintf(stderr, "%02X ",(unsigned char)*(hbuf+start+i));
1242 + }
1243 + if (ascii) {
1244 + for (i = diff; i < 16; i++) fprintf(stderr, " ");
1245 + for (i = 0; i < diff; i++) {
1246 + c = *(hbuf+start+i);
1247 + fprintf(stderr, "%c", isprint(c) ? c : '.');
1248 + }
1249 + }
1250 + fprintf(stderr, "\n");
1251 + start += 16;
1252 + }
1253 +}
1254 +// }}}
1255 diff -Naur ../orig/libpst-0.5.1/libstrfunc.h libpst64-060926/libstrfunc.h
1256 --- ../orig/libpst-0.5.1/libstrfunc.h 2004-11-17 07:48:03.000000000 -0700
1257 +++ libpst64-060926/libstrfunc.h 2006-09-26 14:09:55.000000000 -0600
1258 @@ -1,2 +1,4 @@
1259
1260 char * base64_encode(void *data, size_t size);
1261 +
1262 +void hexdump(char *hbuf, int start, int stop, int ascii);
1263 diff -Naur ../orig/libpst-0.5.1/lspst.c libpst64-060926/lspst.c
1264 --- ../orig/libpst-0.5.1/lspst.c 2004-11-17 07:48:03.000000000 -0700
1265 +++ libpst64-060926/lspst.c 2006-09-26 14:09:55.000000000 -0600
1266 @@ -37,6 +37,7 @@
1267 char *rfc2426_escape(char *str);
1268 char *rfc2445_datetime_format(FILETIME *ft);
1269 // }}}1
1270 +#undef DEBUG_MAIN
1271 #define DEBUG_MAIN(x) debug_print x;
1272 // int main(int argc, char** argv) {{{1
1273 int main(int argc, char** argv) {
1274 diff -Naur ../orig/libpst-0.5.1/Makefile libpst64-060926/Makefile
1275 --- ../orig/libpst-0.5.1/Makefile 2004-11-17 09:16:02.000000000 -0700
1276 +++ libpst64-060926/Makefile 2006-09-26 14:09:55.000000000 -0600
1277 @@ -1,9 +1,12 @@
1278 #!/usr/bin/make -f
1279
1280 -CFLAGS ?= -g -Wall
1281 +CFLAGS ?= -g -Wall
1282 PREFIX ?= /usr/local
1283 INSTALL ?= install
1284
1285 +# You might need this
1286 +#LDLIBS ?= -liconv
1287 +
1288 #---------------- Do not modify below this point ------------------
1289
1290 INSTALL_DIR := $(INSTALL) -p -d -o root -g root -m 0755
1291 @@ -39,9 +42,11 @@
1292 readpstlog.o: XGetopt.h define.h
1293 testdebug.o: define.h
1294 timeconv.o: timeconv.h common.h
1295 +vbuf.o: vbuf.h
1296 +generic.o: generic.h
1297
1298 -readpst: readpst.o libpst.o timeconv.o libstrfunc.o debug.o lzfu.o
1299 -lspst: debug.o libpst.o libstrfunc.o lspst.o timeconv.o
1300 +readpst: readpst.o libpst.o timeconv.o libstrfunc.o debug.o lzfu.o vbuf.o generic.o
1301 +lspst: debug.o libpst.o libstrfunc.o lspst.o timeconv.o vbuf.o generic.o
1302 getidblock: getidblock.o libpst.o debug.o libstrfunc.o
1303 testdebug: testdebug.o debug.o
1304 readpstlog: readpstlog.o debug.o
1305 diff -Naur ../orig/libpst-0.5.1/readpst.c libpst64-060926/readpst.c
1306 --- ../orig/libpst-0.5.1/readpst.c 2004-11-17 07:48:03.000000000 -0700
1307 +++ libpst64-060926/readpst.c 2006-09-26 14:09:55.000000000 -0600
1308 @@ -13,6 +13,8 @@
1309 #include <limits.h>
1310 #include <errno.h>
1311
1312 +#include "vbuf.h"
1313 +
1314 #ifndef _WIN32
1315 # include <unistd.h>
1316 # include <sys/stat.h> //mkdir
1317 @@ -70,19 +72,19 @@
1318 // Function Declarations {{{1
1319 void write_email_body(FILE *f, char *body);
1320 char *removeCR (char *c);
1321 -int32_t usage();
1322 -int32_t version();
1323 +int usage();
1324 +int version();
1325 char *mk_kmail_dir(char*);
1326 -int32_t close_kmail_dir();
1327 +int close_kmail_dir();
1328 char *mk_recurse_dir(char*);
1329 -int32_t close_recurse_dir();
1330 +int close_recurse_dir();
1331 char *mk_seperate_dir(char *dir, int overwrite);
1332 -int32_t close_seperate_dir();
1333 -int32_t mk_seperate_file(struct file_ll *f);
1334 +int close_seperate_dir();
1335 +int mk_seperate_file(struct file_ll *f);
1336 char *my_stristr(char *haystack, char *needle);
1337 char *check_filename(char *fname);
1338 char *rfc2426_escape(char *str);
1339 -int32_t chr_count(char *str, char x);
1340 +int chr_count(char *str, char x);
1341 char *rfc2425_datetime_format(FILETIME *ft);
1342 char *rfc2445_datetime_format(FILETIME *ft);
1343 char *skip_header_prologue(char *headers);
1344 @@ -107,6 +109,8 @@
1345 // saved as email_no-filename (e.g. 1-samplefile.doc or 000001-Attachment2.zip)
1346 #define MODE_SEPERATE 3
1347
1348 +// Decrypt the whole file (even the parts that aren't encrypted) and ralph it to stdout
1349 +#define MODE_DECSPEW 4
1350
1351 // Output Normal just prints the standard information about what is going on
1352 #define OUTPUT_NORMAL 0
1353 @@ -153,7 +157,7 @@
1354 prog_name = argv[0];
1355 // }}}2
1356
1357 - while ((c = getopt(argc, argv, "d:hko:qrSVwc:"))!= -1) {
1358 + while ((c = getopt(argc, argv, "C6d:hko:qrSVwc:"))!= -1) {
1359 switch (c) {
1360 case 'c':
1361 if (optarg!=NULL && optarg[0]=='v')
1362 @@ -168,6 +172,9 @@
1363 case 'd':
1364 d_log = optarg;
1365 break;
1366 + case '6':
1367 + set_read64();
1368 + break;
1369 case 'h':
1370 usage();
1371 exit(0);
1372 @@ -191,6 +198,9 @@
1373 case 'S':
1374 mode = MODE_SEPERATE;
1375 break;
1376 + case 'C':
1377 + mode = MODE_DECSPEW;
1378 + break;
1379 case 'w':
1380 overwrite = 1;
1381 break;
1382 @@ -201,6 +211,8 @@
1383 }
1384 }
1385
1386 + unicode_init();
1387 +
1388 #ifdef DEBUG_ALL
1389 // initialize log file
1390 if (d_log == NULL)
1391 @@ -218,6 +230,29 @@
1392 exit(2);
1393 }
1394
1395 +
1396 + if ( mode == MODE_DECSPEW ) {
1397 + FILE *fp;
1398 + char buf[1024];
1399 + int l=0;
1400 + if( NULL == ( fp = fopen(fname, "rb" ) ) ) {
1401 + fprintf(stderr, "Couldn't open file %s\n", fname );
1402 + return 1;
1403 + }
1404 +
1405 + while( 0 != ( l = fread( buf, 1, 1024, fp ) ) ) {
1406 + if( 0 != _pst_decrypt( buf, l, PST_COMP_ENCRYPT ) )
1407 + fprintf(stderr, "_pst_decrypt() failed (I'll try to continue)\n");
1408 +
1409 + if( l != fwrite( buf, 1, l, stdout ) ) {
1410 + fprintf(stderr, "Couldn't output to stdout?\n");
1411 + return 1;
1412 + }
1413 + }
1414 +
1415 + return 0;
1416 + }
1417 +
1418 if (output_mode != OUTPUT_QUIET) printf("Opening PST file and indexes...\n");
1419
1420 DEBUG_MAIN(("main: Opening PST file '%s'\n", fname));
1421 @@ -1139,6 +1174,8 @@
1422 printf("\t-S\t- Seperate. Write emails in the seperate format\n");
1423 printf("\t-V\t- Version. Display program version\n");
1424 printf("\t-w\t- Overwrite any output mbox files\n");
1425 + printf("\t-6\t- Attempt to read 64-bit Outlook file (Outlook 2003)\n");
1426 + printf("\t-C\t- Decrypt the entire file and output on stdout (not typically useful)\n");
1427 DEBUG_RET();
1428 return 0;
1429 }
1430 diff -Naur ../orig/libpst-0.5.1/vbuf.c libpst64-060926/vbuf.c
1431 --- ../orig/libpst-0.5.1/vbuf.c 1969-12-31 17:00:00.000000000 -0700
1432 +++ libpst64-060926/vbuf.c 2006-09-26 14:09:55.000000000 -0600
1433 @@ -0,0 +1,932 @@
1434 +// {{{ includes
1435 +
1436 +#include <ctype.h>
1437 +//#include "defines.h"
1438 +#include <errno.h>
1439 +#include <iconv.h>
1440 +#include <malloc.h>
1441 +#include <signal.h>
1442 +#include <stdarg.h>
1443 +#include <stdio.h>
1444 +#include <stdlib.h>
1445 +#include <string.h>
1446 +#include "vbuf.h"
1447 +#include "generic.h"
1448 +
1449 +#ifdef WITH_DMALLOC
1450 +#include <dmalloc.h>
1451 +#endif
1452 +
1453 +// }}}
1454 +
1455 +int skip_nl( char *s ) // {{{ returns the width of the newline at s[0]
1456 +{
1457 + if( s[0] == '\n' ) return 1;
1458 + if( s[0] == '\r' && s[1] == '\n' ) return 2;
1459 + if( s[0] == '\0' ) return 0;
1460 + return -1;
1461 +} // }}}
1462 +int find_nl( vstr *vs ) // {{{ find newline of type type in b
1463 +{
1464 + char *nextr, *nextn;
1465 +
1466 + nextr = memchr( vs->b, '\r', vs->dlen );
1467 + nextn = memchr( vs->b, '\n', vs->dlen );
1468 +
1469 + //case 1: UNIX, we find \n first
1470 + if( nextn && (nextr == NULL || nextr > nextn ) ) {
1471 + return nextn - vs->b;
1472 + }
1473 +
1474 + //case 2: DOS, we find \r\n
1475 + if( NULL != nextr && NULL != nextn && 1 == (char*)nextn - (char*)nextr ) {
1476 + return nextr - vs->b;
1477 + }
1478 +
1479 + //case 3: we find nothing
1480 +
1481 + return -1;
1482 +} // }}}
1483 +
1484 +// {{{ UTF8 <-> UTF16 <-> ISO8859 Character set conversion functions and (ack) their globals
1485 +
1486 +//TODO: the following should not be
1487 +char *wwbuf=NULL;
1488 +size_t nwwbuf=0;
1489 +static int unicode_up=0;
1490 +iconv_t i16to8, i8to16, i8859_1to8, i8toi8859_1;
1491 +
1492 +void unicode_init() // {{{
1493 +{
1494 + char *wipe = "";
1495 + char dump[4];
1496 +
1497 + if( unicode_up ) unicode_close();
1498 +
1499 + if( (iconv_t)-1 == (i16to8 = iconv_open( "UTF-8", "UTF-16" ) ) ) {
1500 + fprintf(stderr, "doexport(): Couldn't open iconv descriptor for UTF-16 to UTF-8.\n");
1501 + exit( 1 );
1502 + }
1503 +
1504 + if( (iconv_t)-1 == (i8to16 = iconv_open( "UTF-16", "UTF-8" ) ) ) {
1505 + fprintf(stderr, "doexport(): Couldn't open iconv descriptor for UTF-8 to UTF-16.\n");
1506 + exit( 2 );
1507 + }
1508 +
1509 + //iconv will prefix output with an FF FE (utf-16 start seq), the following dumps that.
1510 + memset( dump, 'x', 4 );
1511 + ASSERT( 0 == utf8to16( wipe, 1, dump, 4 ), "unicode_init(): attempt to dump FF FE failed." );
1512 +
1513 + if( (iconv_t)-1 == (i8859_1to8 = iconv_open( "UTF-8", "ISO_8859-1" ) ) ) {
1514 + fprintf(stderr, "doexport(): Couldn't open iconv descriptor for ASCII to UTF-8.\n");
1515 + exit( 1 );
1516 + }
1517 +
1518 +
1519 + if( (iconv_t)-1 == (i8toi8859_1 = iconv_open( "ISO_8859-1", "UTF-8" ) ) ) {
1520 + fprintf(stderr, "doexport(): Couldn't open iconv descriptor for UTF-8 to ASCII.\n");
1521 + exit( 1 );
1522 + }
1523 +
1524 + unicode_up = 1;
1525 +}
1526 +// }}}
1527 +void unicode_close() // {{{
1528 +{
1529 + unicode_up = 0;
1530 + iconv_close( i8to16 );
1531 + iconv_close( i16to8 );
1532 + iconv_close( i8859_1to8 );
1533 + iconv_close( i8toi8859_1 );
1534 +}
1535 +// }}}
1536 +
1537 +//int utf16_write( FILE* stream, const void *buf, size_t count ) // {{{ write utf-8 or iso_8869-1 to stream after converting it to utf-16
1538 +//{
1539 +//
1540 +// //TODO: if anything big comes through here we are sunk, should do it
1541 +// //bit-by-bit, not one-big-gulp
1542 +//
1543 +// size_t inbytesleft, outbytesleft;
1544 +// char *inbuf, *outbuf;
1545 +// size_t icresult;
1546 +// size_t rl;
1547 +//
1548 +// //do we have enough buffer space?
1549 +// if( !wwbuf || nwwbuf < (count * 2 + 2) ) {
1550 +// wwbuf = F_REALLOC( wwbuf, count * 2 +2 );
1551 +//
1552 +// nwwbuf = count * 2 + 2;
1553 +// }
1554 +//
1555 +// inbytesleft = count; outbytesleft = nwwbuf;
1556 +// inbuf = (char*)buf; outbuf = wwbuf;
1557 +//
1558 +//// fprintf(stderr, "X%s, %dX", (char*)buf, strlen( buf ));
1559 +//// fflush(stderr);
1560 +//
1561 +// if( (rl = strlen( buf ) + 1) != count ) {
1562 +// fprintf(stderr, "utf16_write(): reported buffer size (%d) does not match string length (%d)\n",
1563 +// count,
1564 +// rl);
1565 +//
1566 +// //hexdump( (char*)buf, 0, count, 1 );
1567 +//
1568 +// raise( SIGSEGV );
1569 +// inbytesleft = rl;
1570 +// }
1571 +//
1572 +//// fprintf(stderr, " attempting to convert:\n");
1573 +//// hexdump( (char*)inbuf, 0, count, 1 );
1574 +//
1575 +// icresult = iconv( i8to16, &inbuf, &inbytesleft, &outbuf, &outbytesleft );
1576 +//
1577 +//// fprintf(stderr, " converted:\n");
1578 +//// hexdump( (char*)buf, 0, count, 1 );
1579 +//
1580 +//// fprintf(stderr, " to:\n");
1581 +//// hexdump( (char*)wwbuf, 0, nwwbuf, 1 );
1582 +//
1583 +// if( (size_t)-1 == icresult ) {
1584 +// fprintf(stderr, "utf16_write(): iconv failure(%d): %s\n", errno, strerror( errno ) );
1585 +// fprintf(stderr, " attempted to convert:\n");
1586 +// hexdump( (char*)inbuf, 0, count, 1 );
1587 +//
1588 +// fprintf(stderr, " result:\n");
1589 +// hexdump( (char*)outbuf, 0, count, 1 );
1590 +//
1591 +// fprintf(stderr, "I'm going to segfault now.\n");
1592 +// raise( SIGSEGV );
1593 +// exit(1);
1594 +// }
1595 +//
1596 +// if( inbytesleft > 0 ) {
1597 +// fprintf(stderr, "utf16_write(): iconv returned a short count.\n");
1598 +// exit(1);
1599 +// }
1600 +//
1601 +// return fwrite( wwbuf, nwwbuf - outbytesleft - 2, 1, stream );
1602 +//}
1603 +// }}}
1604 +
1605 +//char *utf16buf = NULL;
1606 +//int utf16buf_len = 0;
1607 +//
1608 +//int utf16_fprintf( FILE* stream, const char *fmt, ... ) // {{{
1609 +//{
1610 +// int result=0;
1611 +// va_list ap;
1612 +//
1613 +// if( utf16buf == NULL ) {
1614 +// utf16buf = (char*)F_MALLOC( SZ_MAX + 1 );
1615 +//
1616 +// utf16buf_len = SZ_MAX + 1;
1617 +// }
1618 +//
1619 +// va_start( ap, fmt );
1620 +//
1621 +// result = vsnprintf( utf16buf, utf16buf_len, fmt, ap );
1622 +//
1623 +// if( result + 1 > utf16buf_len ) { //didn't have space, realloc() and try again
1624 +// fprintf(stderr, "utf16_fprintf(): buffer too small (%d), F_MALLOC(%d)\n", utf16buf_len, result);
1625 +// free( utf16buf );
1626 +// utf16buf_len = result + 1;
1627 +// utf16buf = (char*)F_MALLOC( utf16buf_len );
1628 +//
1629 +// result = vsnprintf( utf16buf, utf16buf_len, fmt, ap );
1630 +// }
1631 +//
1632 +//
1633 +// //didn't have space...again...something weird is going on...
1634 +// ASSERT( result + 1 <= utf16buf_len, "utf16_fprintf(): Unpossible error!\n");
1635 +//
1636 +// if( 1 != utf16_write( stream, utf16buf, result + 1 ) )
1637 +// DIE( "Write error? -> %s or %s\n", strerror( errno ), uerr_str( uerr_get() ) );
1638 +//
1639 +// return result;
1640 +//}
1641 +//// }}}
1642 +//int utf16to8( char *inbuf_o, char *outbuf_o, int length ) // {{{
1643 +//{
1644 +// int inbytesleft = length;
1645 +// int outbytesleft = length;
1646 +// char *inbuf = inbuf_o;
1647 +// char *outbuf = outbuf_o;
1648 +// int rlen = -1, tlen;
1649 +// int icresult = -1;
1650 +//
1651 +// int i, strlen=-1;
1652 +//
1653 +// DEBUG(
1654 +// fprintf(stderr, " utf16to8(): attempting to convert:\n");
1655 +// //hexdump( (char*)inbuf_o, 0, length, 1 );
1656 +// fflush(stderr);
1657 +// );
1658 +//
1659 +// for( i=0; i<length ; i+=2 ) {
1660 +// if( inbuf_o[i] == 0 && inbuf_o[i + 1] == 0 ) {
1661 +// //fprintf(stderr, "End of string found at: %d\n", i );
1662 +// strlen = i;
1663 +// }
1664 +// }
1665 +//
1666 +// //hexdump( (char*)inbuf_o, 0, strlen, 1 );
1667 +//
1668 +// if( -1 == strlen ) WARN("String is not zero-terminated.");
1669 +//
1670 +// //iconv does not like it when the inbytesleft > actual string length
1671 +// //enum: zero terminated, length valid
1672 +// // zero terminated, length short //we won't go beyond length ever, so this is same as NZT case
1673 +// // zero terminated, length long
1674 +// // not zero terminated
1675 +// // TODO: MEMORY BUG HERE!
1676 +// for( tlen = 0; tlen <= inbytesleft - 2; tlen+=2 ) {
1677 +// if( inbuf_o[tlen] == 0 && inbuf_o[tlen+1] == 0 ){
1678 +// rlen = tlen + 2;
1679 +// tlen = rlen;
1680 +// break;
1681 +// }
1682 +// if( tlen == inbytesleft )fprintf(stderr, "Space allocated for string > actual string length. Go windows!\n");
1683 +// }
1684 +//
1685 +// if( rlen >= 0 )
1686 +// icresult = iconv( i16to8, &inbuf, &rlen, &outbuf, &outbytesleft );
1687 +//
1688 +// if( icresult == (size_t)-1 ) {
1689 +// fprintf(stderr, "utf16to8(): iconv failure(%d): %s\n", errno, strerror( errno ) );
1690 +// fprintf(stderr, " attempted to convert:\n");
1691 +// hexdump( (char*)inbuf_o, 0, length, 1 );
1692 +// fprintf(stderr, " result:\n");
1693 +// hexdump( (char*)outbuf_o, 0, length, 1 );
1694 +// fprintf(stderr, " MyDirtyOut:\n");
1695 +// for( i=0; i<length; i++) {
1696 +// if( inbuf_o[i] != '\0' ) fprintf(stderr, "%c", inbuf_o[i] );
1697 +// }
1698 +//
1699 +// fprintf( stderr, "\n" );
1700 +// raise( SIGSEGV );
1701 +// exit(1);
1702 +// }
1703 +//
1704 +// DEBUG(
1705 +// fprintf(stderr, " result:\n");
1706 +// hexdump( (char*)outbuf_o, 0, length, 1 );
1707 +// )
1708 +//
1709 +// //fprintf(stderr, "utf16to8() returning %s\n", outbuf );
1710 +//
1711 +// return icresult;
1712 +//}
1713 +//// }}}
1714 +int utf16_is_terminated( char *str, int length ) // {{{
1715 +{
1716 + VSTR_STATIC( errbuf, 100 );
1717 + int len = -1;
1718 + int i;
1719 + for( i=0; i<length ; i+=2 ) {
1720 + if( str[i] == 0 && str[i + 1] == 0 ) {
1721 + //fprintf(stderr, "End of string found at: %d\n", i );
1722 + len = i;
1723 + }
1724 + }
1725 +
1726 + //hexdump( (char*)inbuf_o, 0, len, 1 );
1727 +
1728 + if( -1 == len ) {
1729 + vshexdump( errbuf, str, 0, length, 1 );
1730 + WARN("String is not zero terminated (probably broken data from registry) %s.", errbuf->b);
1731 + }
1732 +
1733 + return (-1 == len )?0:1;
1734 +} // }}}
1735 +int vb_utf16to8( vbuf *dest, char *buf, int len ) // {{{
1736 +{
1737 + int inbytesleft = len;
1738 + char *inbuf = buf;
1739 + //int rlen = -1, tlen;
1740 + int icresult = -1;
1741 + VBUF_STATIC( dumpster, 100 );
1742 +
1743 + //int i; //, strlen=-1;
1744 + int outbytesleft;
1745 + char *outbuf;
1746 +
1747 + ASSERT( unicode_up, "vb_utf16to8() called before unicode started." );
1748 +
1749 + if( 2 > dest->blen ) vbresize( dest, 2 );
1750 + dest->dlen = 0;
1751 +
1752 + //Bad Things can happen if a non-zero-terminated utf16 string comes through here
1753 + if( !utf16_is_terminated( buf, len ) ) return -1;
1754 +
1755 + do {
1756 + outbytesleft = dest->blen - dest->dlen;
1757 + outbuf = dest->b + dest->dlen;
1758 + icresult = iconv( i16to8, &inbuf, &inbytesleft, &outbuf, &outbytesleft );
1759 + dest->dlen = outbuf - dest->b;
1760 + vbgrow( dest, inbytesleft);
1761 + } while( (size_t)-1 == icresult && E2BIG == errno );
1762 +
1763 + if( 0 != vb_utf8to16T( dumpster, dest->b, dest->dlen ) )
1764 + DIE("Reverse conversion failed.");
1765 +
1766 + if( icresult == (size_t)-1 ) {
1767 + //TODO: error
1768 + //ERR_UNIX( errno, "vb_utf16to8():iconv failure: %s", strerror( errno ) );
1769 + unicode_init();
1770 + return -1;
1771 + /*
1772 + fprintf(stderr, " attempted to convert:\n");
1773 + hexdump( (char*)cin, 0, inlen, 1 );
1774 + fprintf(stderr, " result:\n");
1775 + hexdump( (char*)bout->b, 0, bout->dlen, 1 );
1776 + fprintf(stderr, " MyDirtyOut:\n");
1777 + for( i=0; i<inlen; i++) {
1778 + if( inbuf[i] != '\0' ) fprintf(stderr, "%c", inbuf[i] );
1779 + }
1780 +
1781 + fprintf( stderr, "\n" );
1782 + raise( SIGSEGV );
1783 + exit(1);
1784 + */
1785 + }
1786 +
1787 + if( icresult ) {
1788 + //ERR_UNIX( EILSEQ, "Uhhhh...vb_utf16to8() returning icresult == %d", icresult );
1789 + return -1;
1790 + }
1791 + return icresult;
1792 +}
1793 +// }}}
1794 +
1795 +int utf8to16( char *inbuf_o, int iblen, char *outbuf_o, int oblen) // {{{ iblen, oblen: bytes including \0
1796 +{
1797 + //TODO: this is *only* used to dump the utf16 preamble now...
1798 + //TODO: This (and 8to16) are the most horrible things I have ever seen...
1799 + int inbytesleft;
1800 + int outbytesleft = oblen;
1801 + char *inbuf = inbuf_o;
1802 + char *outbuf = outbuf_o;
1803 + //int rlen = -1, tlen;
1804 + int icresult = -1;
1805 +
1806 + char *stend;
1807 +
1808 + //int i; //, strlen=-1;
1809 +
1810 + DEBUG(
1811 + fprintf(stderr, " utf8to16(): attempting to convert:\n");
1812 + //hexdump( (char*)inbuf_o, 0, length, 1 );
1813 + fflush(stderr);
1814 + );
1815 +
1816 + stend = memchr( inbuf_o, '\0', iblen );
1817 + ASSERT( NULL != stend, "utf8to16(): in string not zero terminated." );
1818 +
1819 + inbytesleft = ( stend - inbuf_o + 1 < iblen )? stend - inbuf_o + 1: iblen;
1820 +
1821 + //iconv does not like it when the inbytesleft > actual string length
1822 + //enum: zero terminated, length valid
1823 + // zero terminated, length short //we won't go beyond length ever, so this is same as NZT case
1824 + // zero terminated, length long
1825 + // not zero terminated
1826 + // TODO: MEMORY BUG HERE!
1827 + //
1828 + /*
1829 + for( tlen = 0; tlen <= inbytesleft - 2; tlen+=2 ) {
1830 + if( inbuf_o[tlen] == 0 && inbuf_o[tlen+1] == 0 ){
1831 + rlen = tlen + 2;
1832 + tlen = rlen;
1833 + break;
1834 + }
1835 + if( tlen == inbytesleft )fprintf(stderr, "Space allocated for string > actual string length. Go windows!\n");
1836 + }
1837 + */
1838 +
1839 + //if( rlen >= 0 )
1840 + icresult = iconv( i8to16, &inbuf, &inbytesleft, &outbuf, &outbytesleft );
1841 +
1842 + if( icresult == (size_t)-1 ) {
1843 + DIE("iconv failure(%d): %s\n", errno, strerror( errno ) );
1844 + //fprintf(stderr, " attempted to convert:\n");
1845 + //hexdump( (char*)inbuf_o, 0, iblen, 1 );
1846 + //fprintf(stderr, " result:\n");
1847 + //hexdump( (char*)outbuf_o, 0, oblen, 1 );
1848 + //fprintf(stderr, " MyDirtyOut:\n");
1849 +// for( i=0; i<iblen; i++) {
1850 +// if( inbuf_o[i] != '\0' ) fprintf(stderr, "%c", inbuf_o[i] );
1851 +// }
1852 +//
1853 +// fprintf( stderr, "\n" );
1854 +// raise( SIGSEGV );
1855 +// exit(1);
1856 + }
1857 +
1858 +// DEBUG(
1859 +// fprintf(stderr, " result:\n");
1860 +// hexdump( (char*)outbuf_o, 0, oblen, 1 );
1861 +// )
1862 +
1863 + //fprintf(stderr, "utf8to16() returning %s\n", outbuf );
1864 +
1865 + //TODO: error
1866 + if( icresult ) printf("Uhhhh...utf8to16() returning icresult == %d\n", icresult );
1867 + return icresult;
1868 +}
1869 +// }}}
1870 +
1871 +int vb_utf8to16T( vbuf *bout, char *cin, int inlen ) // {{{
1872 +{
1873 + //TODO: This (and 8to16) are the most horrible things I have ever seen...
1874 + int inbytesleft = inlen;
1875 + char *inbuf = cin;
1876 + //int rlen = -1, tlen;
1877 + int icresult = -1;
1878 +
1879 + //int i; //, strlen=-1;
1880 +
1881 + //if( rlen >= 0 )
1882 + int outbytesleft;
1883 + char *outbuf;
1884 + if( 2 > bout->blen ) vbresize( bout, 2 );
1885 + bout->dlen = 0;
1886 +
1887 + do {
1888 + outbytesleft = bout->blen - bout->dlen;
1889 + outbuf = bout->b + bout->dlen;
1890 + icresult = iconv( i8to16, &inbuf, &inbytesleft, &outbuf, &outbytesleft );
1891 + bout->dlen = outbuf - bout->b;
1892 + vbgrow( bout, 20 );
1893 + } while( (size_t)-1 == icresult && E2BIG == errno );
1894 +
1895 + if( icresult == (size_t)-1 ) {
1896 + WARN("iconv failure: %s", strerror( errno ) );
1897 + //ERR_UNIX( errno, "vb_utf8to16():iconv failure: %s", strerror( errno ) );
1898 + unicode_init();
1899 + return -1;
1900 + /*
1901 + fprintf(stderr, "vb_utf8to16(): iconv failure(%d == %d?): %s\n", errno, E2BIG, strerror( errno ) );
1902 + fprintf(stderr, " attempted to convert:\n");
1903 + hexdump( (char*)cin, 0, inlen, 1 );
1904 + fprintf(stderr, " result:\n");
1905 + hexdump( (char*)bout->b, 0, bout->dlen, 1 );
1906 + fprintf(stderr, " MyDirtyOut:\n");
1907 + for( i=0; i<inlen; i++) {
1908 + if( inbuf[i] != '\0' ) fprintf(stderr, "%c", inbuf[i] );
1909 + }
1910 +
1911 + fprintf( stderr, "\n" );
1912 + raise( SIGSEGV );
1913 + exit(1);
1914 + */
1915 + }
1916 +
1917 + //TODO: error
1918 + if( icresult ) printf("Uhhhh...vb_utf8to16() returning icresult == %d\n", icresult );
1919 + return icresult;
1920 +}
1921 +// }}}
1922 +#if 1
1923 +void cheap_uni2ascii(char *src, char *dest, int l) /* {{{ Quick and dirty UNICODE to std. ascii */
1924 +{
1925 +
1926 + for (; l > 0; l -=2) {
1927 + *dest = *src;
1928 + dest++; src +=2;
1929 + }
1930 + *dest = 0;
1931 +}
1932 +// }}}
1933 +#endif
1934 +
1935 +void cheap_ascii2uni(char *src, char *dest, int l) /* {{{ Quick and dirty ascii to unicode */
1936 +{
1937 + for (; l > 0; l--) {
1938 + *dest++ = *src++;
1939 + *dest++ = 0;
1940 +
1941 + }
1942 +}
1943 +// }}}
1944 +
1945 +// }}}
1946 +// {{{ VARBUF Functions
1947 +vbuf *vballoc( size_t len ) // {{{
1948 +{
1949 + struct varbuf *result;
1950 +
1951 + result = F_MALLOC( sizeof( struct varbuf ) );
1952 +
1953 + result->dlen = 0;
1954 + result->blen = 0;
1955 + result->buf = NULL;
1956 +
1957 + vbresize( result, len );
1958 +
1959 + return result;
1960 +
1961 +} // }}}
1962 +void vbcheck( vbuf *vb ) // {{{
1963 +{
1964 + ASSERT( vb->b - vb->buf <= vb->blen, "vbcheck(): vb->b outside of buffer range.");
1965 + ASSERT( vb->dlen <= vb->blen, "vbcheck(): data length > buffer length.");
1966 +
1967 + ASSERT( vb->blen < 1024*1024, "vbcheck(): blen is a bit large...hmmm.");
1968 +} // }}}
1969 +void vbfree( vbuf *vb ) // {{{
1970 +{
1971 + free( vb->buf );
1972 + free( vb );
1973 +} // }}}
1974 +void vbclear( struct varbuf *vb ) // {{{ditch the data, keep the buffer
1975 +{
1976 + vbresize( vb, 0 );
1977 +} // }}}
1978 +void vbresize( struct varbuf *vb, size_t len ) // {{{ DESTRUCTIVELY grow or shrink buffer
1979 +{
1980 + vb->dlen = 0;
1981 +
1982 + if( vb->blen >= len ) {
1983 + vb->b = vb->buf;
1984 + return;
1985 + }
1986 +
1987 + vb->buf = F_REALLOC( vb->buf, len );
1988 + vb->b = vb->buf;
1989 + vb->blen = len;
1990 +} // }}}
1991 +int vbavail( vbuf *vb ) // {{{
1992 +{
1993 + return vb->blen - ((char*)vb->b - (char*)vb->buf + vb->dlen);
1994 +} // }}}
1995 +//void vbdump( vbuf *vb ) // {{{ TODO: to stdout? Yuck
1996 +//{
1997 +// printf("vb dump-------------\n");
1998 +// printf("dlen: %d\n", vb->dlen );
1999 +// printf("blen: %d\n", vb->blen );
2000 +// printf("b - buf: %d\n", vb->b - vb->buf );
2001 +// printf("buf:\n");
2002 +// hexdump( vb->buf, 0, vb->blen, 1 );
2003 +// printf("b:\n");
2004 +// hexdump( vb->b, 0, vb->dlen, 1 );
2005 +// printf("^^^^^^^^^^^^^^^^^^^^\n");
2006 +//} // }}}
2007 +void vbgrow( struct varbuf *vb, size_t len ) // {{{ out: vbavail(vb) >= len, data are preserved
2008 +{
2009 + if( 0 == len ) return;
2010 +
2011 + if( 0 == vb->blen ) {
2012 + vbresize( vb, len );
2013 + return;
2014 + }
2015 +
2016 + if( vb->dlen + len > vb->blen ) {
2017 + if( vb->dlen + len < vb->blen * 1.5 ) len = vb->blen * 1.5;
2018 + char *nb = F_MALLOC( vb->blen + len );
2019 + //printf("vbgrow() got %p back from malloc(%d)\n", nb, vb->blen + len);
2020 + vb->blen = vb->blen + len;
2021 + memcpy( nb, vb->b, vb->dlen );
2022 +
2023 + //printf("vbgrow() I am going to free %p\n", vb->buf );
2024 + free( vb->buf );
2025 + vb->buf = nb;
2026 + vb->b = vb->buf;
2027 + } else {
2028 + if( vb->b != vb->buf )
2029 + memcpy( vb->buf, vb->b, vb->dlen );
2030 + }
2031 +
2032 + vb->b = vb->buf;
2033 +
2034 + ASSERT( vbavail( vb ) >= len, "vbgrow(): I have failed in my mission." );
2035 +} // }}}
2036 +void vbset( vbuf *vb, void *b, size_t len ) // {{{ set vbuf b size=len, resize if necessary, relen = how much to over-allocate
2037 +{
2038 + vbresize( vb, len );
2039 +
2040 + memcpy( vb->b, b, len );
2041 + vb->dlen = len;
2042 +} // }}}
2043 +void vsskipws( vstr *vs ) // {{{
2044 +{
2045 + char *p = vs->b;
2046 + while( p - vs->b < vs->dlen && isspace( p[0] ) ) p++;
2047 +
2048 + vbskip( (vbuf*)vs, p - vs->b );
2049 +} // }}}
2050 +void vbappend( struct varbuf *vb, void *b, size_t len ) // {{{ append len bytes of b to vbuf, resize if necessary
2051 +{
2052 + if( 0 == vb->dlen ) {
2053 + vbset( vb, b, len );
2054 + return;
2055 + }
2056 +
2057 + vbgrow( vb, len );
2058 +
2059 + memcpy( vb->b + vb->dlen, b, len );
2060 + vb->dlen += len;
2061 +
2062 + //printf("vbappend() end: >%s/%d<\n", vbuf->b, vbuf->dlen );
2063 +} // }}}
2064 +void vbskip( struct varbuf *vb, size_t skip ) // {{{ dumps the first skip bytes from vbuf
2065 +{
2066 + ASSERT( skip <= vb->dlen, "vbskip(): Attempt to seek past end of buffer." );
2067 + //memmove( vbuf->b, vbuf->b + skip, vbuf->dlen - skip );
2068 + vb->b += skip;
2069 + vb->dlen -= skip;
2070 +} // }}}
2071 +void vboverwrite( struct varbuf *vbdest, struct varbuf *vbsrc ) // {{{ overwrite vbdest with vbsrc
2072 +{
2073 + vbresize( vbdest, vbsrc->blen );
2074 + memcpy( vbdest->b, vbsrc->b, vbsrc->dlen );
2075 + vbdest->blen = vbsrc->blen;
2076 + vbdest->dlen = vbsrc->dlen;
2077 +} // }}}
2078 +// }}}
2079 +// {{{ VARSTR Functions
2080 +vstr *vsalloc( size_t len ) // {{{
2081 +{
2082 + vstr *result = (vstr*)vballoc( len + 1 );
2083 + vsset( result, "" );
2084 + return result;
2085 +} // }}}
2086 +char *vsstr( vstr *vs ) // {{{
2087 +{
2088 + return vs->b;
2089 +} // }}}
2090 +size_t vslen( vstr *vs ) // {{{
2091 +{
2092 + return strlen( vsstr( vs ));
2093 +} // }}}
2094 +void vsfree( vstr *vs ) // {{{
2095 +{
2096 + vbfree( (vbuf*)vs );
2097 +} // }}}
2098 +void vscharcat( vstr *vb, int ch ) // {{{
2099 +{
2100 + vbgrow( (vbuf*)vb, 1);
2101 + vb->b[vb->dlen-1] = ch;
2102 + vb->b[vb->dlen] = '\0';
2103 + vb->dlen++;
2104 +} // }}}
2105 +void vsnprepend( vstr *vb, char *str, size_t len ) // {{{ prependappend string str to vbuf, vbuf must already contain a valid string
2106 +{
2107 + ASSERT( vb->b[vb->dlen-1] == '\0', "vsncat(): attempt to append string to non-string.");
2108 + int sl = strlen( str );
2109 + int n = (sl<len)?sl:len;
2110 + //string append
2111 + vbgrow( (vbuf*)vb, n + 1 );
2112 + memmove( vb->b + n, vb->b, vb->dlen - 1 );
2113 + memcpy( vb->b, str, n );
2114 + //strncat( vb->b, str, n );
2115 +
2116 + vb->dlen += n;
2117 + vb->b[ vb->dlen - 1 ] = '\0';
2118 +} // }}}
2119 +void vsskip( vstr *vs, size_t len ) // {{{ len < dlen-1 -> skip len chars, else DIE
2120 +{
2121 + ASSERT( len < vs->dlen - 1, "Attempt to skip past end of string" );
2122 + vbskip( (vbuf*)vs, len );
2123 +} // }}}
2124 +int vsskipline( vstr *vs ) // {{{ in: vb->b == "stuff\nmore_stuff"; out: vb->b == "more_stuff"
2125 +{
2126 + int nloff = find_nl( vs );
2127 + int nll = skip_nl( vs->b + nloff );
2128 +
2129 + if( nloff < 0 ) {
2130 + //TODO: error
2131 + printf("vb_skipline(): there seems to be no newline here.\n");
2132 + return -1;
2133 + }
2134 + if( skip_nl < 0 ) {
2135 + //TODO: error
2136 + printf("vb_skipline(): there seems to be no newline here...except there should be. :P\n");
2137 + return -1;
2138 + }
2139 +
2140 + memmove( vs->b, vs->b + nloff + nll, vs->dlen - nloff - nll );
2141 +
2142 + vs->dlen -= nloff + nll;
2143 +
2144 + return 0;
2145 +} // }}}
2146 +int vscatprintf( vstr *vs, char *fmt, ... ) // {{{
2147 +{
2148 + int size;
2149 + va_list ap;
2150 +
2151 + /* Guess we need no more than 100 bytes. */
2152 + //vsresize( vb, 100 );
2153 + if(!vs->b || vs->dlen == 0) {
2154 + vsset( vs, "" );
2155 + }
2156 +
2157 + while (1) {
2158 + /* Try to print in the allocated space. */
2159 + va_start(ap, fmt);
2160 + size = vsnprintf (vs->b + vs->dlen - 1, vs->blen - vs->dlen, fmt, ap);
2161 + va_end(ap);
2162 +
2163 + /* If that worked, return the string. */
2164 + if (size > -1 && size < vs->blen - vs->dlen ) {
2165 + vs->dlen += size;
2166 + return size;
2167 + }
2168 + /* Else try again with more space. */
2169 + if ( size >= 0 ) /* glibc 2.1 */
2170 + vbgrow( (vbuf*)vs, size+1 ); /* precisely what is needed */
2171 + else /* glibc 2.0 */
2172 + vbgrow( (vbuf*)vs, vs->blen);
2173 + }
2174 +} // }}}
2175 +int vslast( vstr *vs ) // {{{ returns the last character stored in a vstr
2176 +{
2177 + if( vs->dlen < 1 ) return -1;
2178 + if( vs->b[vs->dlen-1] != '\0' ) return -1;
2179 + if( vs->dlen == 1 ) return '\0';
2180 + return vs->b[vs->dlen-2];
2181 +} // }}}
2182 +void vs_printf( vstr *vs, char *fmt, ... ) // {{{ print over vb
2183 +{
2184 + int size;
2185 + va_list ap;
2186 +
2187 + /* Guess we need no more than 100 bytes. */
2188 + vbresize( (vbuf*)vs, 100 );
2189 +
2190 + while (1) {
2191 + /* Try to print in the allocated space. */
2192 + va_start(ap, fmt);
2193 + size = vsnprintf (vs->b, vs->blen, fmt, ap);
2194 + va_end(ap);
2195 +
2196 + /* If that worked, return the string. */
2197 + if (size > -1 && size < vs->blen) {
2198 + vs->dlen = size + 1;
2199 + return;
2200 + }
2201 + /* Else try again with more space. */
2202 + if ( size >= 0 ) /* glibc 2.1 */
2203 + vbresize( (vbuf*)vs, size+1 ); /* precisely what is needed */
2204 + else /* glibc 2.0 */
2205 + vbresize( (vbuf*)vs, vs->blen*2);
2206 + }
2207 +} // }}}
2208 +void vs_printfa( vstr *vs, char *fmt, ... ) // {{{ printf append to vs
2209 +{
2210 + int size;
2211 + va_list ap;
2212 +
2213 + if( vs->blen - vs->dlen < 50 )
2214 + vbgrow( (vbuf*)vs, 100 );
2215 +
2216 + while (1) {
2217 + /* Try to print in the allocated space. */
2218 + va_start(ap, fmt);
2219 + size = vsnprintf (vs->b + vs->dlen - 1, vs->blen - vs->dlen + 1, fmt, ap);
2220 + va_end(ap);
2221 +
2222 + /* If that worked, return the string. */
2223 + if (size > -1 && size < vs->blen) {
2224 + vs->dlen += size;
2225 + return;
2226 + }
2227 + /* Else try again with more space. */
2228 + if ( size >= 0 ) /* glibc 2.1 */
2229 + vbgrow( (vbuf*)vs, size+1 - vs->dlen ); /* precisely what is needed */
2230 + else /* glibc 2.0 */
2231 + vbgrow( (vbuf*)vs, size );
2232 + }
2233 +} // }}}
2234 +void vshexdump( vstr *vs, char *b, size_t start, size_t stop, int ascii ) // {{{
2235 +{
2236 + char c;
2237 + int diff,i;
2238 +
2239 + while (start < stop ) {
2240 + diff = stop - start;
2241 + if (diff > 16) diff = 16;
2242 +
2243 + vs_printfa(vs, ":%08X ",start);
2244 +
2245 + for (i = 0; i < diff; i++) {
2246 + if( 8 == i ) vs_printfa( vs, " " );
2247 + vs_printfa(vs, "%02X ",(unsigned char)*(b+start+i));
2248 + }
2249 + if (ascii) {
2250 + for (i = diff; i < 16; i++) vs_printfa(vs, " ");
2251 + for (i = 0; i < diff; i++) {
2252 + c = *(b+start+i);
2253 + vs_printfa(vs, "%c", isprint(c) ? c : '.');
2254 + }
2255 + }
2256 + vs_printfa(vs, "\n");
2257 + start += 16;
2258 + }
2259 +} // }}}
2260 +void vsset( vstr *vs, char *s ) // {{{ Store string s in vs
2261 +{
2262 + vsnset( vs, s, strlen( s ) );
2263 +} // }}}
2264 +void vsnset( vstr *vs, char *s, size_t n ) // {{{ Store string s in vs
2265 +{
2266 + vbresize( (vbuf*)vs, n + 1 );
2267 + memcpy( vs->b, s, n);
2268 + vs->b[n] = '\0';
2269 + vs->dlen = n+1;
2270 +} // }}}
2271 +void vsgrow( vstr *vs, size_t len ) // {{{ grow buffer by len bytes, data are preserved
2272 +{
2273 + vbgrow( (vbuf*)vs, len );
2274 +} // }}}
2275 +size_t vsavail( vstr *vs ) // {{{
2276 +{
2277 + return vbavail( (vbuf*)vs );
2278 +} // }}}
2279 +void vsnset16( vstr *vs, char *s, size_t len ) // {{{ Like vbstrnset, but for UTF16
2280 +{
2281 + vbresize( (vbuf*)vs, len+1 );
2282 + memcpy( vs->b, s, len );
2283 +
2284 + vs->b[len] = '\0';
2285 + vs->dlen = len+1;
2286 + vs->b[len] = '\0';
2287 +} // }}}
2288 +void vscat( vstr *vs, char *str ) // {{{
2289 +{
2290 + vsncat( vs, str, strlen(str ) );
2291 +} // }}}
2292 +int vscmp( vstr *vs, char *str ) // {{{
2293 +{
2294 + return strcmp( vs->b, str );
2295 +} // }}}
2296 +void vsncat( vstr *vs, char *str, size_t len ) // {{{ append string str to vstr, vstr must already contain a valid string
2297 +{
2298 + ASSERT( vs->b[vs->dlen-1] == '\0', "vsncat(): attempt to append string to non-string.");
2299 + int sl = strlen( str );
2300 + int n = (sl<len)?sl:len;
2301 + //string append
2302 + vbgrow( (vbuf*)vs, n + 1 );
2303 + memcpy( vs->b + vs->dlen - 1, str, n );
2304 + //strncat( vs->b, str, n );
2305 +
2306 + vs->dlen += n;
2307 + vs->b[ vs->dlen - 1 ] = '\0';
2308 +} // }}}
2309 +void vstrunc( vstr *v, int off ) // {{{ Drop chars [off..dlen]
2310 +{
2311 + if( off >= v->dlen - 1 ) return; //nothing to do
2312 + v->b[off] = '\0';
2313 + v->dlen = off + 1;
2314 +}
2315 +// }}}
2316 +// }}}
2317 +// {{{ User input
2318 +// TODO: not sure how useful this stuff is here
2319 +int fmyinput(char *prmpt, char *ibuf, int maxlen) /* {{{ get user input */
2320 +{
2321 + printf("%s",prmpt);
2322 +
2323 + fgets(ibuf,maxlen+1,stdin);
2324 +
2325 + ibuf[strlen(ibuf)-1] = 0;
2326 +
2327 + return(strlen(ibuf));
2328 +}
2329 +// }}}
2330 +//}}}
2331 +//
2332 +//
2333 +//{{{ String formatting and output to FILE *stream or just stdout, etc
2334 +// TODO: a lot of old, unused stuff in here
2335 +void vswinhex8(vstr *vs, unsigned char *hbuf, int start, int stop, int loff ) // {{{ Produce regedit-style hex output */
2336 +{
2337 + int i;
2338 + int lineflag=0;
2339 +
2340 + for( i=start; i<stop; i++)
2341 + {
2342 + loff += vscatprintf( vs, "%02x", hbuf[i] );
2343 + if( i < stop - 1 ) {
2344 + loff+=vscatprintf( vs, "," );
2345 + switch( lineflag ) {
2346 + case 0:
2347 + if( loff >= 77) {
2348 + lineflag=1;
2349 + loff=0;
2350 + vscatprintf( vs, "\\%s ", STUPID_CR );
2351 + }
2352 + break;
2353 + case 1:
2354 + if( loff >= 75 ) {
2355 + loff=0;
2356 + vscatprintf( vs, "\\%s ", STUPID_CR );
2357 + }
2358 + break;
2359 + }
2360 + // if( 24 < i || 0 == (i - 17) % 25 ) fprintf( stream, "\\\n " );
2361 + }
2362 + }
2363 +
2364 + // fprintf( stream, "\n" );
2365 +} // }}}
2366 diff -Naur ../orig/libpst-0.5.1/vbuf.h libpst64-060926/vbuf.h
2367 --- ../orig/libpst-0.5.1/vbuf.h 1969-12-31 17:00:00.000000000 -0700
2368 +++ libpst64-060926/vbuf.h 2006-09-26 14:09:55.000000000 -0600
2369 @@ -0,0 +1,142 @@
2370 +/* {{{ vbuf.h - variable length buffer functions
2371 + *
2372 + * Functions that try to make dealing with buffers easier.
2373 + *
2374 + * vbuf
2375 + *
2376 + * vstr
2377 + * - should always contain a valid string
2378 + *
2379 + * }}} */
2380 +
2381 +#ifndef VBUF_H
2382 +#define VBUF_H
2383 +#define SZ_MAX 4096
2384 +#include <stdlib.h>
2385 +#include <stdio.h>
2386 +#include <stdarg.h>
2387 +/***************************************************/
2388 +
2389 +// {{{ Tokenizer const TOK_EMPTY, TOK_ELEMENT, DELIM
2390 +#define DELIM '\\'
2391 +
2392 +#define TOK_EMPTY 0
2393 +#define TOK_DELIM 1
2394 +#define TOK_PARENT 2
2395 +#define TOK_CURRENT 3
2396 +#define TOK_ELEMENT 4
2397 +
2398 +#define TOK_ERROR 10
2399 +#define TOK_BUF_SMALL 11
2400 +// }}}
2401 +
2402 +
2403 +// Variable-length buffers
2404 +struct varbuf { // {{{
2405 + size_t dlen; //length of data stored in buffer
2406 + size_t blen; //length of buffer
2407 + char *buf; //buffer
2408 + char *b; //start of stored data
2409 +}; // }}}
2410 +
2411 +
2412 +// The exact same thing as a varbuf but should always contain at least '\0'
2413 +struct varstr { // {{{
2414 + size_t dlen; //length of data stored in buffer
2415 + size_t blen; //length of buffer
2416 + char *buf; //buffer
2417 + char *b; //start of stored data
2418 +}; // }}}
2419 +
2420 +
2421 +typedef struct varbuf vbuf;
2422 +typedef struct varstr vstr;
2423 +
2424 +#define VBUF_STATIC(x,y) static vbuf *x = NULL; if(!x) x = vballoc(y);
2425 +#define VSTR_STATIC(x,y) static vstr *x = NULL; if(!x) x = vsalloc(y);
2426 +
2427 +// vbuf functions
2428 +struct varbuf *vballoc( size_t len );
2429 +void vbfree( vbuf *vb );
2430 +void vbclear( vbuf *vb ); //ditch the data, keep the buffer
2431 +void vbresize( vbuf *vb, size_t len );
2432 +int vbavail( vbuf *vb );
2433 +void vbdump( vbuf *vb );
2434 +void vbgrow( vbuf *vb, size_t len ); // grow buffer by len bytes, data are preserved
2435 +void vbset( vbuf *vb, void *data, size_t len );
2436 +void vbskipws( vbuf *vb );
2437 +void vbappend( vbuf *vb, void *data, size_t length );
2438 +void vbskip( vbuf *vb, size_t skip );
2439 +void vboverwrite( vbuf *vbdest, vbuf *vbsrc );
2440 +
2441 +// vstr functions
2442 +vstr *vsalloc( size_t len );
2443 +char *vsb( vstr *vs );
2444 +size_t vslen( vstr *vs ); //strlen
2445 +void vsfree( vstr *vs );
2446 +void vsset( vstr *vs, char *s ); // Store string s in vb
2447 +void vsnset( vstr *vs, char *s, size_t n ); // Store string s in vb
2448 +void vsgrow( vstr *vs, size_t len ); // grow buffer by len bytes, data are preserved
2449 +size_t vsavail( vstr *vs );
2450 +void vscat( vstr *vs, char *str );
2451 +void vsncat( vstr *vs, char *str, size_t len );
2452 +void vsnprepend( vstr *vs, char *str, size_t len ) ;
2453 +void vsskip( vstr *vs, size_t len );
2454 +int vscmp( vstr *vs, char *str );
2455 +void vsskipws( vstr *vs );
2456 +void vs_printf( vstr *vs, char *fmt, ... );
2457 +void vs_printfa( vstr *vs, char *fmt, ... );
2458 +void vshexdump( vstr *vs, char *b, size_t start, size_t stop, int ascii );
2459 +int vscatprintf( vstr *vs, char *fmt, ... );
2460 +void vsvprintf( vstr *vs, char *fmt, va_list ap );
2461 +void vstrunc( vstr *vs, int off ); // Drop chars [off..dlen]
2462 +int vslast( vstr *vs ); // returns the last character stored in a vstr string
2463 +void vscharcat( vstr *vs, int ch );
2464 +int vsutf16( vstr *vs, vbuf *in ); //in: in=zero-terminated utf16; out: vs=utf8; returns: 0 on success, else on fail
2465 +
2466 +int vs_parse_escaped_string( vstr *vs, char *str, size_t len );
2467 +
2468 +
2469 +/*
2470 + * Windows unicode output trash - this stuff sucks
2471 + * TODO: most of this should not be here
2472 + */
2473 +
2474 +void unicode_init();
2475 +void unicode_close();
2476 +int utf16_write( FILE* stream, const void *buf, size_t count );
2477 +int utf16_fprintf( FILE* stream, const char *fmt, ... );
2478 +int utf16to8( char *inbuf_o, char *outbuf_o, int length );
2479 +int utf8to16( char *inbuf_o, int iblen, char *outbuf_o, int oblen);
2480 +int vb_utf8to16T( vbuf *bout, char *cin, int inlen );
2481 +int vb_utf16to8( vbuf *dest, char *buf, int len );
2482 +int iso8859_1to8( char *inbuf_o, char *outbuf_o, int length );
2483 +int utf8toascii( const char *inbuf_o, char *outbuf_o, int length );
2484 +
2485 +/* dump ascii hex in windoze format */
2486 +void winhex(FILE* stream, unsigned char *hbuf, int start, int stop, int loff);
2487 +void winhex8(FILE *stream, unsigned char *hbuf, int start, int stop, int loff );
2488 +
2489 +void vbwinhex8(vbuf *vb, unsigned char *hbuf, int start, int stop, int loff );
2490 +
2491 +/* general search routine, find something in something else */
2492 +int find_in_buf(char *buf, char *what, int sz, int len, int start);
2493 +
2494 +/* Get INTEGER from memory. This is probably low-endian specific? */
2495 +int get_int( char *array );
2496 +
2497 +int find_nl( vstr *vs ); // find newline of type type in b
2498 +int skip_nl( char *s ); // returns the width of the newline at s[0]
2499 +//int vb_readline( struct varbuf *vb, int *ctype, FILE *in ); // read *AT LEAST* one full line of data from in
2500 +int vb_skipline( struct varbuf *vb ); // in: vb->b == "stuff\nmore_stuff"; out: vb->b == "more_stuff"
2501 +/* Get a string of HEX bytes (space separated),
2502 + * or if first char is ' get an ASCII string instead. */
2503 +int gethexorstr(char **c, char *wb);
2504 +char *esc_index( char *s, int c ); // just like index(3), but works on strings with escape sequences
2505 +char *esc_rindex( char *s, int c ); // just like rindex(3), but works on strings with escape sequences
2506 +
2507 +char *tok_esc_char( char *s, int *is_esc, int *c );
2508 +int vb_path_token( vbuf *tok, char **path ); // returns things like TOK_EMPTY, TOK_ERROR, complete list at top
2509 +
2510 +int gettoken( char *tok, int len, char **path, char delim ); // Path tokenizer: increments path, dumps token in tok
2511 +#endif