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