"Initial commit to Gerrit"
[profile/ivi/libgsf.git] / tests / test-msole1.c
1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * test-msole1.c: test program to dump biff streams
4  *
5  * Copyright (C) 2002-2006      Jody Goldberg (jody@gnome.org)
6  * Copyright (C) 2002-2003      Michael Meeks (michael.meeks@novell.com)
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of version 2.1 of the GNU Lesser General Public
10  * License as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
20  * USA
21  *
22  * Parts of this code are taken from libole2/test/test-ole.c
23  */
24
25 #include <gsf/gsf-input-stdio.h>
26 #include <gsf/gsf-input-memory.h>
27 #include <gsf/gsf-utils.h>
28 #include <gsf/gsf-infile.h>
29 #include <gsf/gsf-infile-msole.h>
30 #include <gsf/gsf-msole-utils.h>
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <ctype.h>
35
36 #define BIFF_TYPES_FILE    "biff-types.h"
37 #define DUMP_CONTENT
38
39 typedef struct {
40         guint16 opcode;
41         char *name;
42 } GENERIC_TYPE;
43
44 #ifdef DUMP_CONTENT
45 static GPtrArray *biff_types   = NULL;
46 static void
47 read_types (char const *fname, GPtrArray **types)
48 {
49         FILE *file = fopen(fname, "r");
50         unsigned char buffer[1024];
51         *types = g_ptr_array_new ();
52         if (!file) {
53                 char *newname = g_strconcat ("../", fname, NULL);
54                 file = fopen (newname, "r");
55         }
56         if (!file) {
57                 g_printerr ("Can't find vital file '%s'\n", fname);
58                 return;
59         }
60         while (!feof(file)) {
61                 unsigned char *p;
62                 fgets ((char *)buffer, sizeof (buffer)-1, file);
63                 for (p=buffer;*p;p++)
64                         if (*p=='0' && *(p+1)=='x') {
65                                 GENERIC_TYPE *bt = g_new (GENERIC_TYPE,1);
66                                 unsigned char *name, *pt;
67                                 bt->opcode=strtol((char *)p+2,0,16);
68                                 pt = buffer;
69                                 while (*pt && *pt != '#') pt++;      /* # */
70                                 while (*pt && !isspace(*pt))
71                                         pt++;  /* define */
72                                 while (*pt && isspace((unsigned char)*pt))
73                                         pt++;  /* '   ' */
74                                 while (*pt && *pt != '_') pt++;     /* BIFF_ */
75                                 name = *pt?pt+1:pt;
76                                 while (*pt && !isspace((unsigned char)*pt))
77                                         pt++;
78                                 bt->name = g_strndup ((gchar *)name, (unsigned)(pt - name));
79                                 g_ptr_array_add (*types, bt);
80                                 break;
81                         }
82         }
83         fclose (file);
84 }
85
86 static char const *
87 get_biff_opcode_name (unsigned opcode)
88 {
89         int lp;
90         if (!biff_types)
91                 read_types (BIFF_TYPES_FILE, &biff_types);
92         /* Count backwars to give preference to non-filtered record types */
93         for (lp=biff_types->len; --lp >= 0 ;) {
94                 GENERIC_TYPE *bt = g_ptr_array_index (biff_types, lp);
95                 if (bt->opcode == opcode)
96                         return bt->name;
97         }
98         return "Unknown";
99 }
100
101 static void
102 dump_biff_stream (GsfInput *stream)
103 {
104         guint8 const *data;
105         guint16 len, opcode;
106         unsigned pos = gsf_input_tell (stream);
107
108         while (NULL != (data = gsf_input_read (stream, 4, NULL))) {
109                 gboolean enable_dump = TRUE;
110
111                 opcode  = GSF_LE_GET_GUINT16 (data);
112                 len     = GSF_LE_GET_GUINT16 (data+2);
113
114                 if (len > 15000) {
115                         enable_dump = TRUE;
116                         g_warning ("Suspicious import of biff record > 15,000 (0x%x) for opcode 0x%hx",
117                                    len, opcode);
118                 } else if ((opcode & 0xff00) > 0x1000) {
119                         enable_dump = TRUE;
120                         g_warning ("Suspicious import of biff record with opcode 0x%hx",
121                                    opcode);
122                 }
123
124                 if (enable_dump)
125                         printf ("Opcode 0x%3hx : %15s, length 0x%hx (=%hd)\n",
126                                 opcode, get_biff_opcode_name (opcode),
127                                 len, len);
128
129                 if (len > 0) {
130                         data = gsf_input_read (stream, len, NULL);
131                         if (data == NULL)
132                                 break;
133                         if (enable_dump)
134                                 gsf_mem_dump (data, len);
135                 }
136                 pos = gsf_input_tell (stream);
137         }
138 }
139 #endif /* DUMP_CONTENT */
140
141 static int
142 test (unsigned argc, char *argv[])
143 {
144         static char const * const stream_names[] = {
145                 "Workbook",     "WORKBOOK",     "workbook",
146                 "Book",         "BOOK",         "book"
147         };
148
149         GsfInput  *input, *stream, *pcache_dir;
150         GsfInfile *infile;
151         GError    *err = NULL;
152         unsigned i, j;
153
154         for (i = 1 ; i < argc ; i++) {
155                 fprintf( stderr, "%s\n",argv[i]);
156
157                 input = gsf_input_mmap_new (argv[i], NULL);
158                 if (input == NULL)      /* Only report error if stdio fails too */
159                         input = gsf_input_stdio_new (argv[i], &err);
160                 if (input == NULL) {
161                         g_return_val_if_fail (err != NULL, 1);
162                         g_warning ("'%s' error: %s", argv[i], err->message);
163                         g_error_free (err);
164                         err = NULL;
165                         continue;
166                 }
167
168                 input = gsf_input_uncompress (input);
169
170                 infile = gsf_infile_msole_new (input, &err);
171
172                 if (infile == NULL) {
173                         g_return_val_if_fail (err != NULL, 1);
174
175                         g_warning ("'%s' Not an OLE file: %s", argv[i], err->message);
176                         g_error_free (err);
177                         err = NULL;
178
179 #ifdef DUMP_CONTENT
180                         dump_biff_stream (input);
181 #endif
182
183                         g_object_unref (G_OBJECT (input));
184                         continue;
185                 }
186 #if 0
187                 stream = gsf_infile_child_by_name (infile, "\01CompObj");
188                 if (stream != NULL) {
189                         gsf_off_t len = gsf_input_size (stream);
190                         guint8 const *data = gsf_input_read (stream, len, NULL);
191                         if (data != NULL)
192                                 gsf_mem_dump (data, len);
193                         g_object_unref (G_OBJECT (stream));
194                 }
195                 return 0;
196 #endif
197
198                 stream = gsf_infile_child_by_name (infile, "\05SummaryInformation");
199                 if (stream != NULL) {
200                         GsfDocMetaData *meta_data = gsf_doc_meta_data_new ();
201
202                         puts ( "SummaryInfo");
203                         err = gsf_msole_metadata_read (stream, meta_data);
204                         if (err != NULL) {
205                                 g_warning ("'%s' error: %s", argv[i], err->message);
206                                 g_error_free (err);
207                                 err = NULL;
208                         } else
209                                 gsf_doc_meta_dump (meta_data);
210
211                         g_object_unref (meta_data);
212                         g_object_unref (G_OBJECT (stream));
213                 }
214
215                 stream = gsf_infile_child_by_name (infile, "\05DocumentSummaryInformation");
216                 if (stream != NULL) {
217                         GsfDocMetaData *meta_data = gsf_doc_meta_data_new ();
218
219                         puts ( "DocSummaryInfo");
220                         err = gsf_msole_metadata_read (stream, meta_data);
221                         if (err != NULL) {
222                                 g_warning ("'%s' error: %s", argv[i], err->message);
223                                 g_error_free (err);
224                                 err = NULL;
225                         } else
226                                 gsf_doc_meta_dump (meta_data);
227
228                         g_object_unref (meta_data);
229                         g_object_unref (G_OBJECT (stream));
230                 }
231
232                 for (j = 0 ; j < G_N_ELEMENTS (stream_names) ; j++) {
233                         stream = gsf_infile_child_by_name (infile, stream_names[j]);
234                         if (stream != NULL) {
235                                 puts (j < 3 ? "Excel97" : "Excel95");
236 #ifdef DUMP_CONTENT
237                                 dump_biff_stream (stream);
238 #endif
239                                 g_object_unref (G_OBJECT (stream));
240                                 break;
241                         }
242                 }
243
244 #ifdef DUMP_CONTENT
245                 pcache_dir = gsf_infile_child_by_name (infile, "_SX_DB_CUR");   /* Excel 97 */
246                 if (NULL == pcache_dir)
247                         pcache_dir = gsf_infile_child_by_name (infile, "_SX_DB");       /* Excel 95 */
248                 if (NULL != pcache_dir) {
249                         int i, n = gsf_infile_num_children (infile);
250                         for (i = 0 ; i < n ; i++) {
251                                 stream = gsf_infile_child_by_index  (GSF_INFILE (pcache_dir), i);
252                                 if (stream != NULL) {
253                                         printf ("=================================================\nPivot cache '%04hX'\n\n", i);
254
255                                         dump_biff_stream (stream);
256                                         g_object_unref (G_OBJECT (stream));
257                                 }
258                         }
259                         g_object_unref (G_OBJECT (pcache_dir));
260                 }
261 #endif
262
263                 g_object_unref (G_OBJECT (infile));
264                 g_object_unref (G_OBJECT (input));
265         }
266
267         return 0;
268 }
269
270 int
271 main (int argc, char *argv[])
272 {
273         int res;
274
275         gsf_init ();
276         res = test (argc, argv);
277         gsf_shutdown ();
278
279         return res;
280 }