ole.c 17.6 KB
Newer Older
1 2 3 4 5 6 7 8 9
/**
 * ole.c: OLE2 file format helper program,
 *        good for dumping OLE streams, and
 * corresponding biff records, and hopefuly
 * some more ...
 *
 * Author:
 *    Michael Meeks (michael@imaginator.com)
 **/
Michael Meeks's avatar
Michael Meeks committed
10 11 12
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
13
#include <ctype.h>
Michael Meeks's avatar
Michael Meeks committed
14 15

#include "ms-ole.h"
16
#include "ms-ole-summary.h"
17 18
#include "ms-biff.h"

19
#define BIFF_TYPES_FILE    "biff-types.h"
20

21
static char delim[]=" \t\n";
22

23 24 25
typedef struct {
	guint16 opcode;
	char *name;
26
} GENERIC_TYPE;
27

28
static GPtrArray *biff_types   = NULL;
29

30
static char *cur_dir = NULL;
Michael Meeks's avatar
Michael Meeks committed
31 32 33

static void dump_vba (MsOle *f);

34
static void
35
read_types (char *fname, GPtrArray **types)
36
{
37
	FILE *file = fopen(fname, "r");
38
	char buffer[1024];
39
	*types = g_ptr_array_new ();
Michael Meeks's avatar
Michael Meeks committed
40 41 42 43
	if (!file) {
		char *newname = g_strconcat ("../", fname, NULL);
		file = fopen (newname, "r");
	}
44
	if (!file) {
45
		printf ("Can't find vital file '%s'\n", fname);
46 47
		return;
	}
48 49 50 51 52
	while (!feof(file)) {
		char *p;
		fgets(buffer,1023,file);
		for (p=buffer;*p;p++)
			if (*p=='0' && *(p+1)=='x') {
53
				GENERIC_TYPE *bt = g_new (GENERIC_TYPE,1);
54 55 56 57 58 59
				char *name, *pt;
				bt->opcode=strtol(p+2,0,16);
				pt = buffer;
				while (*pt && *pt != '#') pt++;      /* # */
				while (*pt && !isspace(*pt)) pt++;  /* define */
				while (*pt &&  isspace(*pt)) pt++;  /* '   ' */
60 61
				while (*pt && *pt != '_') pt++;     /* BIFF_ */
				name = *pt?pt+1:pt;
62 63
				while (*pt && !isspace(*pt)) pt++;
				bt->name=g_strndup(name, (pt-name));
64
				g_ptr_array_add (*types, bt);
65 66 67 68 69 70 71
				break;
			}
	}
	fclose (file);
}

static char*
72
get_biff_opcode_name (guint16 opcode)
73 74
{
	int lp;
75
	if (!biff_types)
76
		read_types (BIFF_TYPES_FILE, &biff_types);
Michael Meeks's avatar
Michael Meeks committed
77 78
	/* Count backwars to give preference to non-filtered record types */
	for (lp=biff_types->len; --lp >= 0 ;) {
79 80 81 82 83 84 85 86 87 88 89 90
		GENERIC_TYPE *bt = g_ptr_array_index (biff_types, lp);
		if (bt->opcode>0xff) {
			if (bt->opcode == opcode)
				return bt->name;
		} else {
			if (bt->opcode == (opcode&0xff))
				return bt->name;
		}
	}
	return "Unknown";
}

Michael Meeks's avatar
Michael Meeks committed
91
static void
Michael Meeks's avatar
Michael Meeks committed
92
list_files (MsOle *ole)
Michael Meeks's avatar
Michael Meeks committed
93
{
Michael Meeks's avatar
Michael Meeks committed
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
	char     **names;
	MsOleErr   result;
	int        lp;

	result = ms_ole_directory (&names, ole, cur_dir);
	if (result != MS_OLE_ERR_OK) {
		g_warning ("Failed dir");
		return;
	}

	if (!names[0])
		g_warning ("You entered a file !");

	for (lp = 0; names[lp]; lp++) {
		MsOleStat s;
		result = ms_ole_stat (&s, ole, cur_dir, names[lp]);

		if (s.type == MsOleStreamT)
			printf ("'%25s : length %d bytes\n", names[lp], s.size);
Michael Meeks's avatar
Michael Meeks committed
113
		else
Michael Meeks's avatar
Michael Meeks committed
114 115
			printf ("'[%s] : Storage ( directory )\n", names [lp]);
		
Michael Meeks's avatar
Michael Meeks committed
116 117 118 119
	}
}

static void
Michael Meeks's avatar
Michael Meeks committed
120
list_commands ()
Michael Meeks's avatar
Michael Meeks committed
121 122 123
{
	printf ("command can be one or all of:\n");
	printf (" * ls:                   list files\n");
Michael Meeks's avatar
Michael Meeks committed
124
	printf (" * cd:                   enter storage\n");
125 126 127
	printf (" * biff    <stream name>:   dump biff records, merging continues\n");
	printf (" * biffraw <stream name>:   dump biff records no merge + raw data\n");
	printf (" * dump    <stream name>:   dump stream\n");
128
	printf (" * summary              :   dump document summary info\n");
Michael Meeks's avatar
Michael Meeks committed
129
	printf (" * debug                :   dump internal ole library status\n");
Jody Goldberg's avatar
Jody Goldberg committed
130
	printf (" * vba                  :   attempt to dump vba \n");
131 132 133
	printf (" Raw transfer commands\n");
	printf (" * get     <stream name> <fname>\n");
	printf (" * put     <fname> <stream name>\n");
Michael Meeks's avatar
Michael Meeks committed
134
	printf (" * copyin  [<fname>,]...\n");
Michael Meeks's avatar
Michael Meeks committed
135
	printf (" * copyout [<fname>,]...\n");
Michael Meeks's avatar
Michael Meeks committed
136
	printf (" * quit,exit,bye:        exit\n");
Michael Meeks's avatar
Michael Meeks committed
137 138 139 140 141 142 143 144 145 146 147 148 149 150
}

static void
syntax_error(char *err)
{
	if (err) {
		printf("Error; '%s'\n",err);
		exit(1);
	}
		
	printf ("Sytax:\n");
	printf (" ole <ole-file> [-i] [commands...]\n\n");
	printf (" -i: Interactive, queries for fresh commands\n\n");
	list_commands ();
Michael Meeks's avatar
Michael Meeks committed
151
	exit(1);
Michael Meeks's avatar
Michael Meeks committed
152 153
}

154 155
/* ---------------------------- End cut ---------------------------- */

Michael Meeks's avatar
Michael Meeks committed
156 157 158
static void
enter_dir (MsOle *ole)
{
159
	char *newpath, *ptr;
Michael Meeks's avatar
Michael Meeks committed
160 161 162 163 164 165 166

	ptr = strtok (NULL, delim);
	if (!ptr) {
		printf ("Takes a directory argument\n");
		return;
	}

167 168 169 170 171 172 173 174
	if (!g_strcasecmp (ptr, "..")) {
		guint lp;
		char **tmp;
		GString *newp = g_string_new ("");

		tmp = g_strsplit (cur_dir, "/", -1);
		lp  = 0;
		if (!tmp[lp])
Michael Meeks's avatar
Michael Meeks committed
175 176
			return;

177 178 179 180 181 182 183 184
		while (tmp[lp+1]) {
			g_string_sprintfa (newp, "%s/", tmp[lp]);
			lp++;
		}
		g_free (cur_dir);
		cur_dir = newp->str;
		g_string_free (newp, FALSE);
	} else {
Michael Meeks's avatar
Michael Meeks committed
185 186 187
		MsOleStat s;
		MsOleErr  result;

188 189
		newpath = g_strconcat (cur_dir, ptr, "/", NULL);

Michael Meeks's avatar
Michael Meeks committed
190 191
		result = ms_ole_stat (&s, ole, newpath, "");
		if (result == MS_OLE_ERR_EXIST) {
192
			printf ("Storage '%s' not found\n", ptr);
Michael Meeks's avatar
Michael Meeks committed
193 194 195 196 197 198 199
			g_free (newpath);
			return;
		}
		if (result != MS_OLE_ERR_OK) {
			g_warning ("internal error");
			g_free (newpath);
			return;
200
		}
201
		if (s.type == MsOleStreamT) {
Jody Goldberg's avatar
Jody Goldberg committed
202
			printf ("Trying to enter a stream. (%d)\n", s.type);
Michael Meeks's avatar
Michael Meeks committed
203 204 205 206 207 208
			g_free (newpath);
			return;
		}

		g_free (cur_dir);
		cur_dir = newpath;
209
	}
Michael Meeks's avatar
Michael Meeks committed
210 211
}

212
static void
Michael Meeks's avatar
Michael Meeks committed
213
do_dump (MsOle *ole)
214
{
Michael Meeks's avatar
Michael Meeks committed
215 216 217
	char        *ptr;
	MsOleStream *stream;
	guint8      *buffer;
218 219

	ptr = strtok (NULL, delim);
Michael Meeks's avatar
Michael Meeks committed
220
	if (!ptr) {
221
		printf ("Need a stream name\n");
Michael Meeks's avatar
Michael Meeks committed
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
		return;
	}
       
	if (ms_ole_stream_open (&stream, ole, cur_dir, ptr, 'r') !=
	    MS_OLE_ERR_OK) {
		printf ("Error opening '%s'\n", ptr);
		return;
	}
	buffer = g_malloc (stream->size);
	stream->read_copy (stream, buffer, stream->size);
	printf ("Stream : '%s' length 0x%x\n", ptr, stream->size);
	if (buffer)
		dump (buffer, stream->size);
	else
		printf ("Failed read\n");
	ms_ole_stream_close (&stream);
238 239 240
}

static void
Michael Meeks's avatar
Michael Meeks committed
241
do_biff (MsOle *ole)
242 243
{
	char *ptr;
Michael Meeks's avatar
Michael Meeks committed
244
	MsOleStream *stream;
245 246
	
	ptr = strtok (NULL, delim);
Michael Meeks's avatar
Michael Meeks committed
247 248 249 250 251 252 253 254 255 256
	if (!ptr) {
		printf ("Need a stream name\n");
		return;
	}
       
	if (ms_ole_stream_open (&stream, ole, cur_dir, ptr, 'r') !=
	    MS_OLE_ERR_OK) {
		printf ("Error opening '%s'\n", ptr);
		return;
	}
257
	{
Michael Meeks's avatar
Michael Meeks committed
258
		BiffQuery *q = ms_biff_query_new (stream);
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
		guint16 last_opcode=0xffff;
		guint32 last_length=0;
		guint32 count=0;
		while (ms_biff_query_next(q)) {
			if (q->opcode == last_opcode &&
			    q->length == last_length)
				count++;
			else {
				if (count>0)
					printf (" x %d\n", count+1);
				else
					printf ("\n");
				count=0;
				printf ("Opcode 0x%3x : %15s, length %d",
					q->opcode, get_biff_opcode_name (q->opcode), q->length);
			}
			last_opcode=q->opcode;
			last_length=q->length;
		}
		printf ("\n");
Michael Meeks's avatar
Michael Meeks committed
279 280
		ms_ole_stream_close (&stream);
	}
281 282 283
}

static void
Michael Meeks's avatar
Michael Meeks committed
284
do_biff_raw (MsOle *ole)
285 286
{
	char *ptr;
Michael Meeks's avatar
Michael Meeks committed
287
	MsOleStream *stream;
288 289
	
	ptr = strtok (NULL, delim);
Michael Meeks's avatar
Michael Meeks committed
290 291 292 293 294 295 296 297 298 299
	if (!ptr) {
		printf ("Need a stream name\n");
		return;
	}
       
	if (ms_ole_stream_open (&stream, ole, cur_dir, ptr, 'r') !=
	    MS_OLE_ERR_OK) {
		printf ("Error opening '%s'\n", ptr);
		return;
	}
300 301 302 303 304
	{
		guint8 data[4], *buffer;
		
		buffer = g_new (guint8, 65550);
		while (stream->read_copy (stream, data, 4)) {
305
			guint32 len=MS_OLE_GET_GUINT16(data+2);
306 307 308 309
/*			printf ("0x%4x Opcode 0x%3x : %15s, length 0x%x (=%d)\n", stream->position,
				MS_OLE_GET_GUINT16(data), get_biff_opcode_name (MS_OLE_GET_GUINT16(data)),
				len, len);*/
			printf ("Opcode 0x%3x : %15s, length 0x%x (=%d)\n",
310
				MS_OLE_GET_GUINT16(data), get_biff_opcode_name (MS_OLE_GET_GUINT16(data)),
311 312 313 314 315 316
				len, len);
			stream->read_copy (stream, buffer, len);
			dump (buffer, len);
			buffer[0]=0;
			buffer[len-1]=0;
		}
Michael Meeks's avatar
Michael Meeks committed
317 318
		ms_ole_stream_close (&stream);
	}
319 320 321
}

static void
Michael Meeks's avatar
Michael Meeks committed
322
really_get (MsOle *ole, char *from, char *to)
323
{
Michael Meeks's avatar
Michael Meeks committed
324 325 326 327 328 329 330 331
	MsOleStream *stream;
	
	if (ms_ole_stream_open (&stream, ole, cur_dir, from, 'r') !=
	    MS_OLE_ERR_OK) {
		printf ("Error opening '%s'\n", from);
		return;
	} else {
		guint8 *buffer = g_malloc (stream->size);
332
		FILE *f = fopen (to, "w");
Michael Meeks's avatar
Michael Meeks committed
333 334
		stream->read_copy (stream, buffer, stream->size);
		printf ("Stream : '%s' length 0x%x\n", from, stream->size);
335
		if (f && buffer) {
Michael Meeks's avatar
Michael Meeks committed
336
			fwrite (buffer, 1, stream->size, f);
337 338 339
			fclose (f);
		} else
			printf ("Failed write to '%s'\n", to);
Michael Meeks's avatar
Michael Meeks committed
340
		ms_ole_stream_close (&stream);
341

Michael Meeks's avatar
Michael Meeks committed
342
	}
343 344
}

Michael Meeks's avatar
Michael Meeks committed
345 346 347 348 349 350 351 352 353 354
static void
do_get (MsOle *ole)
{
	char *from, *to;

	from = strtok (NULL, delim);
	to   = strtok (NULL, delim);
	really_get (ole, from, to);
}

355
static void
Michael Meeks's avatar
Michael Meeks committed
356
really_put (MsOle *ole, char *from, char *to)
357
{
Michael Meeks's avatar
Michael Meeks committed
358
	MsOleStream *stream;
Michael Meeks's avatar
Michael Meeks committed
359
	char buffer[8200];
360 361

	if (!from || !to) {
Michael Meeks's avatar
Michael Meeks committed
362
		printf ("Null name\n");
363 364
		return;
	}
Michael Meeks's avatar
Michael Meeks committed
365

Michael Meeks's avatar
Michael Meeks committed
366 367 368 369 370
	if (ms_ole_stream_open (&stream, ole, cur_dir, to, 'w') !=
	    MS_OLE_ERR_OK) {
		printf ("Error opening '%s'\n", to);
		return;
	} else {
371 372
		FILE *f = fopen (from, "r");
		size_t len;
373
		int block=0;
374 375 376 377 378 379

		if (!f || !stream) {
			printf ("Failed write\n");
			return;
		}

Michael Meeks's avatar
Michael Meeks committed
380
		stream->lseek (stream, 0, MsOleSeekSet);
381 382
	       
		do {
Michael Meeks's avatar
Michael Meeks committed
383 384
			guint32 lenr = 1+ (int)(8192.0*rand()/(RAND_MAX+1.0));
			len = fread (buffer, 1, lenr, f);
385
			printf ("Transfering block %d = %d bytes\n", block++, len); 
386
			stream->write (stream, buffer, len);
387
		} while (!feof(f) && len>0);
388 389

		fclose (f);
Michael Meeks's avatar
Michael Meeks committed
390 391
		ms_ole_stream_close (&stream);
	}
392 393
}

Michael Meeks's avatar
Michael Meeks committed
394 395 396
static void
do_summary (MsOle *ole)
{
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
	MsOleSummary        *si;
	MsOleSummaryPreview  preview;
	gboolean             ok;
	gchar               *txt;
	guint32              num;

	si = ms_ole_summary_open (ole);
	if (!si) {
		printf ("No summary information\n");
		return;
	}

	txt = ms_ole_summary_get_string (si, MS_OLE_SUMMARY_TITLE, &ok);
	if (ok)
		printf ("The title is %s\n", txt);
	else
		printf ("no title found\n");
	g_free (txt);

	txt = ms_ole_summary_get_string (si, MS_OLE_SUMMARY_SUBJECT, &ok);
	if (ok)
		printf ("The subject is %s\n", txt);
	else
		printf ("no subject found\n");
	g_free (txt);

	txt = ms_ole_summary_get_string (si, MS_OLE_SUMMARY_AUTHOR, &ok);
	if (ok)
		printf ("The author is %s\n", txt);
	else
		printf ("no author found\n");
	g_free (txt);

	txt = ms_ole_summary_get_string (si, MS_OLE_SUMMARY_KEYWORDS, &ok);
	if (ok)
		printf ("The keywords are %s\n", txt);
	else
		printf ("no keywords found\n");
	g_free (txt);

	txt = ms_ole_summary_get_string (si, MS_OLE_SUMMARY_COMMENTS, &ok);
	if (ok)
		printf ("The comments are %s\n", txt);
	else
		printf ("no comments found\n");
	g_free (txt);

	txt = ms_ole_summary_get_string (si, MS_OLE_SUMMARY_TEMPLATE, &ok);
	if (ok)
		printf ("The template was %s\n", txt);
	else
		printf ("no template found\n");
	g_free (txt);

	txt = ms_ole_summary_get_string (si, MS_OLE_SUMMARY_LASTAUTHOR, &ok);
	if (ok)
		printf ("The last author was %s\n", txt);
	else
		printf ("no last author found\n");
	g_free (txt);

	txt = ms_ole_summary_get_string (si, MS_OLE_SUMMARY_REVNUMBER, &ok);
	if (ok)
		printf ("The rev no was %s\n", txt);
	else
		printf ("no rev no found\n");
	g_free (txt);

	txt = ms_ole_summary_get_string (si, MS_OLE_SUMMARY_APPNAME, &ok);
	if (ok)
		printf ("The app name was %s\n", txt);
	else
		printf ("no app name found\n");
	g_free (txt);

/*	txt = wvSumInfoGetTime(&yr, &mon, &day, &hr, &min, &sec,PID_TOTAL_EDITTIME,&si);
	if (ok)
		printf ("Total edit time was %d/%d/%d %d:%d:%d\n",day,mon,yr,hr,min,sec);
	else
		printf ("no total edit time found\n");
	g_free (txt);

	txt = wvSumInfoGetTime(&yr, &mon, &day, &hr, &min, &sec,PID_LASTPRINTED,&si);
	if (ok)
	    printf ("Last printed on %d/%d/%d %d:%d:%d\n",day,mon,yr,hr,min,sec);
	else
		printf ("no last printed time found\n");

	txt = wvSumInfoGetTime(&yr, &mon, &day, &hr, &min, &sec,PID_CREATED,&si);
	if (ok)
	    printf ("Created on %d/%d/%d %d:%d:%d\n",day,mon,yr,hr,min,sec);
	else
		printf ("no creation time found\n");

	txt = wvSumInfoGetTime(&yr, &mon, &day, &hr, &min, &sec,PID_LASTSAVED,&si);
	if (ok)
	    printf ("Last Saved on %d/%d/%d %d:%d:%d\n",day,mon,yr,hr,min,sec);
	else
	printf ("no lastsaved date found\n");*/

	num = ms_ole_summary_get_long (si, MS_OLE_SUMMARY_PAGECOUNT, &ok);

	if (ok)
		printf ("PageCount is %d\n", num);
	else
		printf ("no pagecount\n");

	num = ms_ole_summary_get_long (si, MS_OLE_SUMMARY_WORDCOUNT, &ok);
	if (ok)
		printf ("WordCount is %d\n", num);
	else
		printf ("no wordcount\n");

	num = ms_ole_summary_get_long (si, MS_OLE_SUMMARY_CHARCOUNT, &ok);

	if (ok)
		printf ("CharCount is %d\n", num);
	else
		printf ("no charcount\n");

	num = ms_ole_summary_get_long (si, MS_OLE_SUMMARY_SECURITY, &ok);
	if (ok)
		printf ("Security is %d\n", num);
	else
		printf ("no security\n");

	preview = ms_ole_summary_get_preview (si, MS_OLE_SUMMARY_THUMBNAIL, &ok);
	if (ok) {
		printf ("preview is %d bytes long\n", preview.len);
		ms_ole_summary_preview_destroy (preview);
Michael Meeks's avatar
Michael Meeks committed
527
	} else
528 529
		printf ("no preview found\n");

530
	ms_ole_summary_close (si);
Michael Meeks's avatar
Michael Meeks committed
531 532
}

Michael Meeks's avatar
Michael Meeks committed
533
static void
Michael Meeks's avatar
Michael Meeks committed
534
do_put (MsOle *ole)
Michael Meeks's avatar
Michael Meeks committed
535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
{
	char *from, *to;

	from = strtok (NULL, delim);
	to   = strtok (NULL, delim);

	if (!from || !to) {
		printf ("put <filename> <stream>\n");
		return;
	}

	really_put (ole, from, to);
}

static void
Michael Meeks's avatar
Michael Meeks committed
550
do_copyin (MsOle *ole)
Michael Meeks's avatar
Michael Meeks committed
551 552 553 554 555 556 557 558 559 560
{
	char *from;

	do {
		from = strtok (NULL, delim);
		if (from)
			really_put (ole, from, from);
	} while (from);
}

Michael Meeks's avatar
Michael Meeks committed
561 562 563 564 565 566 567 568 569 570 571 572
static void
do_copyout (MsOle *ole)
{
	char *from;

	do {
		from = strtok (NULL, delim);
		if (from)
			really_get (ole, from, from);
	} while (from);
}

Michael Meeks's avatar
Michael Meeks committed
573 574
int main (int argc, char **argv)
{
Michael Meeks's avatar
Michael Meeks committed
575
	MsOle *ole;
Michael Meeks's avatar
Michael Meeks committed
576 577 578
	int lp,exit=0,interact=0;
	char *buffer = g_new (char, 1024) ;

Michael Meeks's avatar
Michael Meeks committed
579
	if (argc<2)
Michael Meeks's avatar
Michael Meeks committed
580 581 582
		syntax_error(0);

	printf ("Ole file '%s'\n", argv[1]);
Michael Meeks's avatar
Michael Meeks committed
583
	if (ms_ole_open (&ole, argv[1]) != MS_OLE_ERR_OK) {
584
		printf ("Creating new file '%s'\n", argv[1]);
Michael Meeks's avatar
Michael Meeks committed
585 586
		if (ms_ole_create (&ole, argv[1]) != MS_OLE_ERR_OK)
			syntax_error ("Can't open file or create new one");
587
	}
Michael Meeks's avatar
Michael Meeks committed
588

589 590 591
	if (argc<=2)
		syntax_error ("Need command or -i");

Michael Meeks's avatar
Michael Meeks committed
592 593 594 595 596 597 598 599 600 601
	if (argc>2 && argv[argc-1][0]=='-'
	    && argv[argc-1][1]=='i') 
		interact=1;
	else {
		char *str=g_strdup(argv[2]) ;
		for (lp=3;lp<argc;lp++)
			str=g_strconcat(str," ",argv[lp],NULL); /* Mega leak :-) */
		buffer = str; /* and again */
	}

602
	cur_dir = g_strdup ("/");
Michael Meeks's avatar
Michael Meeks committed
603

Michael Meeks's avatar
Michael Meeks committed
604 605 606 607 608 609 610 611 612 613 614
	do
	{
		char *ptr;

		if (interact) {
			fprintf (stdout,"> ");
			fflush (stdout);
			fgets (buffer, 1023, stdin);
		}

		ptr = strtok (buffer, delim);
615
		if (!ptr && interact) continue;
Michael Meeks's avatar
Michael Meeks committed
616 617
		if (!interact)
			printf ("Command : '%s'\n", ptr);
Michael Meeks's avatar
Michael Meeks committed
618 619
		if (g_strcasecmp(ptr, "ls")==0) {
			list_files (ole);
Michael Meeks's avatar
Michael Meeks committed
620 621 622
		} else if (g_strcasecmp(ptr, "cd")==0)
			enter_dir (ole);
		else if (g_strcasecmp(ptr, "dump")==0)
623 624 625 626 627 628 629 630 631
			do_dump (ole);
		else if (g_strcasecmp(ptr, "biff")==0)
			do_biff (ole);
		else if (g_strcasecmp(ptr, "biffraw")==0)
			do_biff_raw (ole);
		else if (g_strcasecmp(ptr, "get")==0)
			do_get (ole);
		else if (g_strcasecmp(ptr, "put")==0)
			do_put (ole);
Michael Meeks's avatar
Michael Meeks committed
632 633
		else if (g_strcasecmp(ptr, "copyin")==0)
			do_copyin (ole);
Michael Meeks's avatar
Michael Meeks committed
634 635
		else if (g_strcasecmp(ptr, "copyout")==0)
			do_copyout (ole);
Michael Meeks's avatar
Michael Meeks committed
636 637
		else if (g_strcasecmp(ptr, "summary")==0)
			do_summary (ole);
638 639
		else if (g_strcasecmp(ptr, "debug")==0)
			ms_ole_debug (ole, 1);
Michael Meeks's avatar
Michael Meeks committed
640 641
		else if (g_strcasecmp(ptr, "vba")==0)
			dump_vba (ole);
Michael Meeks's avatar
Michael Meeks committed
642 643 644 645 646
		else if (g_strcasecmp(ptr,"help")==0 ||
			   g_strcasecmp(ptr,"?")==0 ||
			   g_strcasecmp(ptr,"info")==0 ||
			   g_strcasecmp(ptr,"man")==0)
			list_commands ();
647
		else if (g_strcasecmp(ptr,"exit")==0 ||
Michael Meeks's avatar
Michael Meeks committed
648
			   g_strcasecmp(ptr,"quit")==0 ||
649
			   g_strcasecmp(ptr,"q")==0 ||
Michael Meeks's avatar
Michael Meeks committed
650 651
			   g_strcasecmp(ptr,"bye")==0)
			exit = 1;
Michael Meeks's avatar
Michael Meeks committed
652
	}
Michael Meeks's avatar
Michael Meeks committed
653 654
	while (!exit && interact);

Michael Meeks's avatar
Michael Meeks committed
655
	ms_ole_destroy (&ole);
Michael Meeks's avatar
Michael Meeks committed
656
	return 1;
Michael Meeks's avatar
Michael Meeks committed
657
}
Michael Meeks's avatar
Michael Meeks committed
658

Michael Meeks's avatar
Michael Meeks committed
659 660 661 662 663 664 665
static void
decompress_vba (guint8 *data, guint32 len)
{
	#define BUF_SIZE 4096
	#define BUF_BITS 6
	#define BUF_MASK 0x3f

Michael Meeks's avatar
Michael Meeks committed
666
	int      shift;
Michael Meeks's avatar
Michael Meeks committed
667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
	guint8   buffer[BUF_SIZE];
	guint8  *ptr;
	guint32  pos;

	for (pos = 0; pos < BUF_SIZE; pos++)
		buffer[pos] = ' ';

	printf ("My compressed stream:\n");
	dump (data, len);

	ptr = data;
	while (ptr < data + len) {
		guint8 hdr = *ptr++;

		for (shift = 0x01; shift < 0x100; shift = shift<<1) {
			if (hdr & shift) {
				guint16 dt = MS_OLE_GET_GUINT16 (ptr);
				int lp, i;
Michael Meeks's avatar
Michael Meeks committed
685
				printf ("|match 0x%x = %d, %d|\n", dt, ((dt >> 9)&0xf) + 1,
Michael Meeks's avatar
Michael Meeks committed
686 687 688 689 690 691 692 693 694 695 696 697
					(dt & BUF_MASK));
				/* Perhaps dt & SHIFT = dist. to end of run */
				for (i = 16; i >= 0; i--) {
					if (dt & (1 << i))
						printf ("1");
					else
						printf ("0");
					if (i == 8)
						printf ("|");
				}
				printf ("\n");
				for (lp = 0; lp < (dt & BUF_MASK); lp++) {
Michael Meeks's avatar
Michael Meeks committed
698
					guint8 c = buffer[( pos - (dt >> BUF_BITS) + lp ) % BUF_SIZE];
Michael Meeks's avatar
Michael Meeks committed
699 700 701 702 703 704 705 706 707 708 709 710 711
					buffer [pos++ % BUF_SIZE] = c;
					printf ("%c", c);
				}
				printf ("\n");
				ptr += 2;
			} else {
				buffer [pos++ % BUF_SIZE] = *ptr;
				printf ("%c", *ptr++);
			}
		}
	}
}

Michael Meeks's avatar
Michael Meeks committed
712
static void
Michael Meeks's avatar
Michael Meeks committed
713
dump_vba_module (MsOle *f, const char *path, const char *name)
Michael Meeks's avatar
Michael Meeks committed
714 715 716
{
	MsOleStream *s;

Michael Meeks's avatar
Michael Meeks committed
717 718 719
	if (ms_ole_stream_open (&s, f, path, name, 'r') !=
	    MS_OLE_ERR_OK) {
		printf ("Strange: can't open '%s%s'\n", path, name);
Michael Meeks's avatar
Michael Meeks committed
720 721 722 723 724 725 726
		return;
	}

	/* Very, very, very, very, very crude :-) */
	{
		guint8  *data, *ptr;
		guint32  i;
Michael Meeks's avatar
Michael Meeks committed
727
		
Michael Meeks's avatar
Michael Meeks committed
728 729
		data = g_new (guint8, s->size);
		if (!s->read_copy (s, data, s->size)) {
Michael Meeks's avatar
Michael Meeks committed
730
			printf ("Strange: failed read of module '%s%s'\n", path, name);
Michael Meeks's avatar
Michael Meeks committed
731 732 733 734 735 736
			return;
		}
		
		ptr = data;
		i   = 0;
		do {
Michael Meeks's avatar
Michael Meeks committed
737 738
			if (!g_strncasecmp (ptr, "Attribut", 8))
				decompress_vba (ptr - 1, s->size - (ptr - data));
Michael Meeks's avatar
Michael Meeks committed
739 740
			ptr++; i++;
		} while (i < s->size - 10);
741 742

		g_free (data);
Michael Meeks's avatar
Michael Meeks committed
743 744
	}
	
Michael Meeks's avatar
Michael Meeks committed
745
	ms_ole_stream_close (&s);
Michael Meeks's avatar
Michael Meeks committed
746 747 748 749 750 751
}

/* Hack - leave it here for now */
static void
dump_vba (MsOle *f)
{
Michael Meeks's avatar
Michael Meeks committed
752 753
	const char *vbapath = "/_VBA_PROJECT_CUR";
	char **dir;
Michael Meeks's avatar
Michael Meeks committed
754
	MsOleStream *s;
Michael Meeks's avatar
Michael Meeks committed
755
	MsOleStat    st;
Michael Meeks's avatar
Michael Meeks committed
756
	char *txt;
Michael Meeks's avatar
Michael Meeks committed
757 758
	int   i;
	int   module_count;
Michael Meeks's avatar
Michael Meeks committed
759

Michael Meeks's avatar
Michael Meeks committed
760 761 762
	if (ms_ole_stat (&st, f, vbapath, "") != MS_OLE_ERR_OK ||
	    st.type == MsOleStreamT) {
		printf ("No valid VBA found\n");
Michael Meeks's avatar
Michael Meeks committed
763 764 765
		return;
	}

Michael Meeks's avatar
Michael Meeks committed
766 767
	if (ms_ole_stream_open (&s, f, vbapath, "PROJECT", 'r') !=
	    MS_OLE_ERR_OK) {
Michael Meeks's avatar
Michael Meeks committed
768
		printf ("No project file... wierd\n");
Michael Meeks's avatar
Michael Meeks committed
769
	} else {
Michael Meeks's avatar
Michael Meeks committed
770 771 772 773 774 775 776 777 778
		txt = g_new (guint8, s->size);
		if (!s->read_copy (s, txt, s->size))
			printf ("Failed to read project stream\n");
		else {
			printf ("----------\n");
			printf ("Project file:\n");
			printf ("%s", txt);
			printf ("----------\n");
		}
Michael Meeks's avatar
Michael Meeks committed
779
		ms_ole_stream_close (&s);
Michael Meeks's avatar
Michael Meeks committed
780 781
	}

Michael Meeks's avatar
Michael Meeks committed
782 783 784 785
	txt = g_strconcat (vbapath, "/VBA", NULL);
	if (ms_ole_directory (&dir, f, txt) != MS_OLE_ERR_OK) {
		printf ("No VBA subdirectory found");
		g_free (txt);
Michael Meeks's avatar
Michael Meeks committed
786 787 788
		return;
	}

Michael Meeks's avatar
Michael Meeks committed
789 790
	module_count = 0;
	for (i = 0; dir[i]; i++) {
Michael Meeks's avatar
Michael Meeks committed
791

Michael Meeks's avatar
Michael Meeks committed
792 793 794 795 796 797
		if (!g_strncasecmp (dir[i], "Module", 6)) {
			printf ("Module : %d = '%s'\n", module_count, dir[i]);
			printf ("----------\n");
			dump_vba_module (f, txt, dir[i]);
			printf ("----------\n");
			module_count++;
Michael Meeks's avatar
Michael Meeks committed
798 799
		}	
	}
Michael Meeks's avatar
Michael Meeks committed
800 801 802 803
	if (!module_count)
		printf ("Strange no modules found\n");

	g_free (txt);
Michael Meeks's avatar
Michael Meeks committed
804
}