1 /* wvWare
2 * Copyright (C) Caolan McNamara, Dom Lachowicz, and others
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17 * 02111-1307, USA.
18 */
19
20 /*
21 Released under GPL, written by Caolan.McNamara@ul.ie.
22
23 Copyright (C) 1998,1999
24 Caolan McNamara
25
26 Real Life: Caolan McNamara * Doing: MSc in HCI
27 Work: Caolan.McNamara@ul.ie * Phone: +353-86-8790257
28 URL: http://skynet.csn.ul.ie/~caolan * Sig: an oblique strategy
29 How would you have done it?
30 */
31
32 /*
33
34 this code is often all over the shop, being more of an organic entity
35 that a carefully planed piece of code, so no laughing there at the back!
36
37 and send me patches by all means, but think carefully before sending me
38 a patch that doesnt fix a bug or add a feature but instead just changes
39 the style of coding, i.e no more thousand line patches that fix my
40 indentation.
41
42 */
43
44 #ifdef HAVE_CONFIG_H
45 #include "config.h"
46 #endif
47
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <ctype.h>
51 #include <string.h>
52 #include <time.h>
53 #include <math.h>
54
55 #include <glib.h>
56 #include <gsf/gsf-input.h>
57
58 #include "wv.h"
59 #include "wvinternal.h"
60
61 #if defined(WORDS_BIGENDIAN) || !defined(MATCHED_TYPE)
62
63 /* Basic bit swapping functions from Glib
64 */
65
66 #define TO_LE_16(val) ((U16) ( \
67 (((U16) (val) & (U16) 0x00ffU) << 8) | \
68 (((U16) (val) & (U16) 0xff00U) >> 8)))
69
70 #define TO_LE_32(val) ((U32) ( \
71 (((U32) (val) & (U32) 0x000000ffU) << 24) | \
72 (((U32) (val) & (U32) 0x0000ff00U) << 8) | \
73 (((U32) (val) & (U32) 0x00ff0000U) >> 8) | \
74 (((U32) (val) & (U32) 0xff000000U) >> 24)))
75
76 #define TO_LE_8(val) (val)
77
78 #else
79
80 /* noop macros for little-endian machines */
81
82 #define TO_LE_32(i) (i)
83 #define TO_LE_16(i) (i)
84 #define TO_LE_8(i) (i)
85
86 #endif
87
88 #ifdef HAVE_WMF
89 # include "gdwmfapi.h"
90 /*
91 extern listentry *ourlist;
92 extern int list;
93 */
94 #endif
95
96 static wvStream_list *streams = NULL;
97 static U32 wvStream_close_stream(wvStream * in);
98
99 void
wvOLEFree(wvParseStruct * ps)100 wvOLEFree (wvParseStruct * ps)
101 {
102 if(wvQuerySupported (&ps->fib, NULL) != WORD2 && !ps->fib.fEncrypted) {
103 wvStream_list *tempList = streams;
104
105 while (tempList != NULL)
106 {
107 wvStream_close(tempList->stream);
108 tempList = tempList->next;
109 }
110
111 while (streams != NULL)
112 {
113 tempList = streams->next;
114 wvFree (streams);
115 streams = tempList;
116 }
117 }
118
119 if (ps->ole_file != NULL)
120 {
121 g_object_unref (G_OBJECT(ps->ole_file));
122 ps->ole_file = NULL;
123 }
124
125 if (ps->input != NULL)
126 {
127 g_object_unref (G_OBJECT(ps->input));
128 ps->input = NULL;
129 }
130 }
131
132 wvStream *
wvStream_TMP_create(size_t size)133 wvStream_TMP_create (size_t size)
134 {
135 wvStream * stm = NULL;
136
137 char * buf;
138
139 buf = wvMalloc(size);
140
141 if (buf)
142 wvStream_memory_create (&stm, buf, size);
143
144 return stm;
145 }
146
147 void
wvStream_FILE_create(wvStream ** in,FILE * inner)148 wvStream_FILE_create (wvStream ** in, FILE * inner)
149 {
150 wvInternalStream str;
151 str.file_stream = inner;
152 wvStream_create (in, FILE_STREAM, str);
153 }
154
155 void
wvStream_gsf_create(wvStream ** in,GsfInput * inner)156 wvStream_gsf_create (wvStream ** in, GsfInput * inner)
157 {
158 wvInternalStream str;
159 str.gsf_stream = inner;
160 wvStream_create (in, GSF_STREAM, str);
161 }
162
163 void
wvStream_memory_create(wvStream ** in,char * buf,size_t size)164 wvStream_memory_create (wvStream ** in, char *buf, size_t size)
165 {
166 wvInternalStream str;
167 MemoryStream *inner = (MemoryStream *)wvMalloc(sizeof(MemoryStream));
168
169 inner->mem = buf;
170 inner->size = size;
171 inner->current = 0;
172
173 str.memory_stream = inner;
174 wvStream_create (in, MEMORY_STREAM, str);
175 }
176
177
178 void
wvStream_create(wvStream ** in,wvStreamKind kind,wvInternalStream inner)179 wvStream_create (wvStream ** in, wvStreamKind kind, wvInternalStream inner)
180 {
181 wvStream_list *listEntry;
182 *in = (wvStream *) wvMalloc (sizeof (wvStream));
183 (*in)->kind = kind;
184 (*in)->stream = inner;
185 listEntry = wvMalloc (sizeof (wvStream_list));
186 listEntry->stream = (*in);
187 listEntry->next = streams;
188 streams = listEntry;
189 }
190
memorystream_read(MemoryStream * stream,void * buf,size_t count)191 static size_t memorystream_read(MemoryStream *stream, void *buf, size_t count)
192 {
193 size_t ret;
194
195 if ( stream->current + count <= stream->size)
196 {
197 memcpy(buf, stream->mem + stream->current, count);
198 stream->current += count;
199 ret = count;
200 }
201 else
202 {
203 ret = stream->size - stream->current;
204 memcpy(buf, stream->mem + stream->current, ret);
205 memset( (void *) ((size_t)buf + ret), 0, count - ret);
206 stream->current = stream->size;
207 wvTrace(("read out of bounds\n"));
208 }
209 return ret;
210 }
211
212 U32
read_32ubit(wvStream * in)213 read_32ubit (wvStream * in)
214 {
215 U32 ret;
216 U16 temp1, temp2;
217 temp1 = read_16ubit (in);
218 temp2 = read_16ubit (in);
219 ret = temp2;
220 ret = ret << 16;
221 ret += temp1;
222
223 return (ret);
224 }
225
226 U16
read_16ubit(wvStream * in)227 read_16ubit (wvStream * in)
228 {
229 U16 ret;
230 U8 temp1, temp2;
231 temp1 = read_8ubit (in);
232 temp2 = read_8ubit (in);
233 ret = temp2;
234 ret = ret << 8;
235 ret += temp1;
236 return (ret);
237 }
238
239 U8
read_8ubit(wvStream * in)240 read_8ubit (wvStream * in)
241 {
242 if (in->kind == GSF_STREAM)
243 {
244 U8 ret = 0;
245 gsf_input_read (GSF_INPUT (in->stream.gsf_stream), 1, &ret);
246 return (ret);
247 }
248 else if (in->kind == FILE_STREAM)
249 {
250 return (getc (in->stream.file_stream));
251 }
252 else
253 {
254 U8 ret = 0;
255 memorystream_read(in->stream.memory_stream, &ret, 1);
256 return ret;
257 }
258 }
259
260 U32
wvStream_read(void * ptr,size_t size,size_t nmemb,wvStream * in)261 wvStream_read (void *ptr, size_t size, size_t nmemb, wvStream * in)
262 {
263 if (in->kind == GSF_STREAM)
264 {
265 gsf_input_read (GSF_INPUT (in->stream.gsf_stream), size*nmemb, ptr);
266 return size*nmemb;
267 }
268 else if (in->kind == FILE_STREAM)
269 {
270 return (fread (ptr, size, nmemb, in->stream.file_stream));
271 }
272 else
273 {
274 return memorystream_read(in->stream.memory_stream, ptr, size * nmemb);
275 }
276 }
277
278 void
wvStream_rewind(wvStream * in)279 wvStream_rewind (wvStream * in)
280 {
281 if (in->kind == GSF_STREAM)
282 {
283 gsf_input_seek (GSF_INPUT (in->stream.gsf_stream), 0, G_SEEK_SET);
284 }
285 else if (in->kind == FILE_STREAM)
286 {
287 rewind (in->stream.file_stream);
288 }
289 else
290 {
291 in->stream.memory_stream->current = 0;
292 }
293 }
294
295 U32
wvStream_goto(wvStream * in,long position)296 wvStream_goto (wvStream * in, long position)
297 {
298 if (in->kind == GSF_STREAM)
299 {
300 gsf_input_seek (GSF_INPUT (in->stream.gsf_stream), position, G_SEEK_SET);
301 return (U32)gsf_input_tell(GSF_INPUT (in->stream.gsf_stream));
302 }
303 else if (in->kind == FILE_STREAM)
304 {
305 return ((U32) fseek (in->stream.file_stream, position, SEEK_SET));
306 }
307 else
308 {
309 in->stream.memory_stream->current = position;
310 return in->stream.memory_stream->current;
311 }
312 }
313
314 U32
wvStream_offset(wvStream * in,long offset)315 wvStream_offset (wvStream * in, long offset)
316 {
317 if (in->kind == GSF_STREAM)
318 {
319 gsf_input_seek (GSF_INPUT (in->stream.gsf_stream), offset, G_SEEK_CUR);
320 return (U32)gsf_input_tell(GSF_INPUT (in->stream.gsf_stream));
321 }
322 else if (in->kind == FILE_STREAM)
323 {
324 return ((U32) fseek (in->stream.file_stream, offset, SEEK_CUR));
325 }
326 else
327 {
328 in->stream.memory_stream->current += offset;
329 return in->stream.memory_stream->current;
330 }
331 }
332
333 U32
wvStream_offset_from_end(wvStream * in,long offset)334 wvStream_offset_from_end (wvStream * in, long offset)
335 {
336 if (in->kind == GSF_STREAM)
337 {
338 gsf_input_seek (GSF_INPUT (in->stream.gsf_stream), offset, G_SEEK_END);
339 return (U32)gsf_input_tell(GSF_INPUT (in->stream.gsf_stream));
340 }
341 else if(in->kind == FILE_STREAM)
342 {
343 return ((U32) fseek (in->stream.file_stream, offset, SEEK_END));
344 }
345 else
346 {
347 in->stream.memory_stream->current =
348 in->stream.memory_stream->size + offset;
349 return in->stream.memory_stream->current;
350 }
351 }
352
353 U32
wvStream_tell(wvStream * in)354 wvStream_tell (wvStream * in)
355 {
356 if (in->kind == GSF_STREAM)
357 {
358 return (U32)gsf_input_tell(GSF_INPUT (in->stream.gsf_stream));
359 }
360 else if(in->kind == FILE_STREAM)
361 {
362 return ((U32) ftell (in->stream.file_stream));
363 }
364 else
365 {
366 return (in->stream.memory_stream->current);
367 }
368 }
369
370 U32
wvStream_size(wvStream * in)371 wvStream_size (wvStream * in)
372 {
373 U32 size;
374
375 long offset = wvStream_tell(in);
376 wvStream_offset_from_end(in,0);
377 size = wvStream_tell(in);
378 wvStream_goto(in,offset);
379
380 return size;
381 }
382
383
384 U32
wvStream_close(wvStream * in)385 wvStream_close(wvStream * in)
386 {
387 wvStream_list *s;
388 U32 ret;
389
390 ret = wvStream_close_stream (in);
391
392 for ( s = streams;s != NULL; s=s->next)
393 {
394 if (s->stream == in)
395 {
396 s->stream = 0;
397 }
398 }
399
400 return ret;
401 }
402
403 static U32
wvStream_close_stream(wvStream * in)404 wvStream_close_stream (wvStream * in)
405 {
406 if ( !in )
407 return 0;
408
409 if (in->kind == GSF_STREAM)
410 {
411 g_object_unref (G_OBJECT(in->stream.gsf_stream));
412 in->stream.gsf_stream = NULL;
413 wvFree (in);
414 return 0;
415 }
416 else
417 if (in->kind == FILE_STREAM)
418 {
419 U32 ret;
420 ret = (U32) fclose (in->stream.file_stream);
421 wvFree (in);
422 return (ret);
423 }
424 else
425 if (in->kind == MEMORY_STREAM)
426 {
427 wvFree (in->stream.memory_stream->mem);
428 wvFree (in->stream.memory_stream);
429 wvFree (in);
430 return 0;
431 }
432 else abort();
433 }
434
435 /* wvStream-kind-independent functions below */
436
437 U32
sread_32ubit(const U8 * in)438 sread_32ubit (const U8 * in)
439 {
440 U16 temp1, temp2;
441 U32 ret;
442 temp1 = sread_16ubit (in);
443 temp2 = sread_16ubit (in + 2);
444 ret = temp2;
445 ret = ret << 16;
446 ret += temp1;
447 return (ret);
448 }
449
450 U32
bread_32ubit(U8 * in,U16 * pos)451 bread_32ubit (U8 * in, U16 * pos)
452 {
453 U16 temp1, temp2;
454 U32 ret;
455 temp1 = sread_16ubit (in);
456 temp2 = sread_16ubit (in + 2);
457 ret = temp2;
458 ret = ret << 16;
459 ret += temp1;
460 (*pos) += 4;
461 return (ret);
462 }
463
464 U32
dread_32ubit(wvStream * in,U8 ** list)465 dread_32ubit (wvStream * in, U8 ** list)
466 {
467 U8 *temp;
468 U32 ret;
469 if (in != NULL)
470 return (read_32ubit (in));
471 else
472 {
473 temp = *list;
474 (*list) += 4;
475 ret = sread_32ubit (temp);
476 return (ret);
477 }
478 }
479
480 U16
sread_16ubit(const U8 * in)481 sread_16ubit (const U8 * in)
482 {
483 U8 temp1, temp2;
484 U16 ret;
485 temp1 = *in;
486 temp2 = *(in + 1);
487 ret = temp2;
488 ret = ret << 8;
489 ret += temp1;
490 return (ret);
491 }
492
493 U16
bread_16ubit(U8 * in,U16 * pos)494 bread_16ubit (U8 * in, U16 * pos)
495 {
496 U8 temp1, temp2;
497 U16 ret;
498
499 if (in == 0) /* this really ought to be called more sanely */
500 {
501 (*pos) = 0xffff;
502 return 0;
503 }
504
505 temp1 = *in;
506 temp2 = *(in + 1);
507 ret = temp2;
508 ret = ret << 8;
509 ret += temp1;
510 (*pos) += 2;
511 return (ret);
512 }
513
514 U16
dread_16ubit(wvStream * in,U8 ** list)515 dread_16ubit (wvStream * in, U8 ** list)
516 {
517 U8 *temp;
518 U16 ret;
519 if (in != NULL)
520 return (read_16ubit (in));
521 else
522 {
523 temp = *list;
524 (*list) += 2;
525 ret = sread_16ubit (temp);
526 return (ret);
527 }
528 }
529
530 U8
sread_8ubit(const U8 * in)531 sread_8ubit (const U8 * in)
532 {
533 return (*in);
534 }
535
536 U8
bread_8ubit(U8 * in,U16 * pos)537 bread_8ubit (U8 * in, U16 * pos)
538 {
539 (*pos)++;
540 return (*in);
541 }
542
543 U8
dread_8ubit(wvStream * in,U8 ** list)544 dread_8ubit (wvStream * in, U8 ** list)
545 {
546 U8 *temp;
547 if (in != NULL)
548 return (read_8ubit (in));
549 else
550 {
551 temp = *list;
552 (*list)++;
553 return (sread_8ubit (temp));
554 }
555 }
556
557 int
write_32ubit(wvStream * in,U32 out)558 write_32ubit (wvStream * in, U32 out)
559 {
560
561 guint32 cpy = (guint32) TO_LE_32 (out);
562 int nwr = 0;
563
564 if (in->kind == GSF_STREAM)
565 {
566 #if 0
567 nwr =
568 (int) in->stream.gsf_stream->write (in->stream.gsf_stream,
569 (guint8 *) & cpy, 32);
570 #endif
571 }
572 else if (in->kind == FILE_STREAM)
573 {
574 nwr =
575 (int) fwrite (&cpy, sizeof (guint32), 1, in->stream.file_stream);
576 }
577 else{
578 nwr = 4;
579 *((U32 *) (in->stream.memory_stream->mem +
580 in->stream.memory_stream->current)) = cpy;
581 in->stream.memory_stream->current +=4;
582 }
583 return nwr;
584 }
585
586 int
write_16ubit(wvStream * in,U16 out)587 write_16ubit (wvStream * in, U16 out)
588 {
589
590 guint16 cpy = (guint16) TO_LE_16 (out);
591 int nwr = 0;
592
593 if (in->kind == GSF_STREAM)
594 {
595 #if 0
596 nwr =
597 (int) in->stream.gsf_stream->write (in->stream.gsf_stream,
598 (guint8 *) & cpy, 16);
599 #endif
600 }
601 else if (in->kind == FILE_STREAM)
602 {
603 nwr =
604 (int) fwrite (&cpy, sizeof (guint16), 1, in->stream.file_stream);
605 }
606 else{
607 nwr = 2;
608 *((U16 *) (in->stream.memory_stream->mem +
609 in->stream.memory_stream->current))= cpy;
610 in->stream.memory_stream->current+=2;
611 }
612
613 return nwr;
614 }
615
616 int
write_8ubit(wvStream * in,U8 out)617 write_8ubit (wvStream * in, U8 out)
618 {
619 guint8 cpy = (guint8) TO_LE_8 (out);
620 int nwr = 0;
621 wvTrace (("About to write 16-bit value"));
622
623 if (in->kind == GSF_STREAM)
624 {
625 #if 0
626 nwr =
627 (int) in->stream.gsf_stream->write (in->stream.gsf_stream,
628 (guint8 *) & cpy, 8);
629 #endif
630 }
631 else if (in->kind == FILE_STREAM)
632 {
633 nwr = (int) fwrite (&cpy, sizeof (guint8), 1, in->stream.file_stream);
634 }
635 else{
636 nwr = 1;
637 *((U8 *)(in->stream.memory_stream->mem +
638 in->stream.memory_stream->current)) = cpy;
639 in->stream.memory_stream->current++;
640 }
641 return nwr;
642 }
643
644 int
wvStream_write(void * ptr,size_t size,size_t nmemb,wvStream * in)645 wvStream_write (void *ptr, size_t size, size_t nmemb, wvStream * in)
646 {
647 int nwr = 0;
648 if (in->kind == GSF_STREAM)
649 {
650 #if 0
651 nwr =
652 (int) in->stream.gsf_stream->write (in->stream.gsf_stream,
653 ptr, size * nmemb);
654 #endif
655 }
656 else if (in->kind == FILE_STREAM)
657 {
658 nwr = (int) fwrite (ptr, size, nmemb, in->stream.file_stream);
659 }
660 else{
661 nwr = size * nmemb;
662 memcpy(in->stream.memory_stream->mem +
663 in->stream.memory_stream->current,ptr, size * nmemb);
664 in->stream.memory_stream->current+=size* nmemb;
665 }
666 return nwr;
667 }
668
669