1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * test-msole1.c: test program to dump biff streams
5 * Copyright (C) 2002-2006 Jody Goldberg (jody@gnome.org)
6 * Copyright (C) 2002-2003 Michael Meeks (michael.meeks@novell.com)
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.
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.
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
22 * Parts of this code are taken from libole2/test/test-ole.c
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>
36 #define BIFF_TYPES_FILE "biff-types.h"
45 static GPtrArray *biff_types = NULL;
47 read_types (char const *fname, GPtrArray **types)
49 FILE *file = fopen(fname, "r");
50 unsigned char buffer[1024];
51 *types = g_ptr_array_new ();
53 char *newname = g_strconcat ("../", fname, NULL);
54 file = fopen (newname, "r");
57 g_printerr ("Can't find vital file '%s'\n", fname);
62 fgets ((char *)buffer, sizeof (buffer)-1, file);
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);
69 while (*pt && *pt != '#') pt++; /* # */
70 while (*pt && !isspace(*pt))
72 while (*pt && isspace((unsigned char)*pt))
74 while (*pt && *pt != '_') pt++; /* BIFF_ */
76 while (*pt && !isspace((unsigned char)*pt))
78 bt->name = g_strndup ((gchar *)name, (unsigned)(pt - name));
79 g_ptr_array_add (*types, bt);
87 get_biff_opcode_name (unsigned opcode)
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)
102 dump_biff_stream (GsfInput *stream)
106 unsigned pos = gsf_input_tell (stream);
108 while (NULL != (data = gsf_input_read (stream, 4, NULL))) {
109 gboolean enable_dump = TRUE;
111 opcode = GSF_LE_GET_GUINT16 (data);
112 len = GSF_LE_GET_GUINT16 (data+2);
116 g_warning ("Suspicious import of biff record > 15,000 (0x%x) for opcode 0x%hx",
118 } else if ((opcode & 0xff00) > 0x1000) {
120 g_warning ("Suspicious import of biff record with opcode 0x%hx",
125 printf ("Opcode 0x%3hx : %15s, length 0x%hx (=%hd)\n",
126 opcode, get_biff_opcode_name (opcode),
130 data = gsf_input_read (stream, len, NULL);
134 gsf_mem_dump (data, len);
136 pos = gsf_input_tell (stream);
139 #endif /* DUMP_CONTENT */
142 test (unsigned argc, char *argv[])
144 static char const * const stream_names[] = {
145 "Workbook", "WORKBOOK", "workbook",
146 "Book", "BOOK", "book"
149 GsfInput *input, *stream, *pcache_dir;
154 for (i = 1 ; i < argc ; i++) {
155 fprintf( stderr, "%s\n",argv[i]);
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);
161 g_return_val_if_fail (err != NULL, 1);
162 g_warning ("'%s' error: %s", argv[i], err->message);
168 input = gsf_input_uncompress (input);
170 infile = gsf_infile_msole_new (input, &err);
172 if (infile == NULL) {
173 g_return_val_if_fail (err != NULL, 1);
175 g_warning ("'%s' Not an OLE file: %s", argv[i], err->message);
180 dump_biff_stream (input);
183 g_object_unref (G_OBJECT (input));
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);
192 gsf_mem_dump (data, len);
193 g_object_unref (G_OBJECT (stream));
198 stream = gsf_infile_child_by_name (infile, "\05SummaryInformation");
199 if (stream != NULL) {
200 GsfDocMetaData *meta_data = gsf_doc_meta_data_new ();
202 puts ( "SummaryInfo");
203 err = gsf_msole_metadata_read (stream, meta_data);
205 g_warning ("'%s' error: %s", argv[i], err->message);
209 gsf_doc_meta_dump (meta_data);
211 g_object_unref (meta_data);
212 g_object_unref (G_OBJECT (stream));
215 stream = gsf_infile_child_by_name (infile, "\05DocumentSummaryInformation");
216 if (stream != NULL) {
217 GsfDocMetaData *meta_data = gsf_doc_meta_data_new ();
219 puts ( "DocSummaryInfo");
220 err = gsf_msole_metadata_read (stream, meta_data);
222 g_warning ("'%s' error: %s", argv[i], err->message);
226 gsf_doc_meta_dump (meta_data);
228 g_object_unref (meta_data);
229 g_object_unref (G_OBJECT (stream));
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");
237 dump_biff_stream (stream);
239 g_object_unref (G_OBJECT (stream));
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);
255 dump_biff_stream (stream);
256 g_object_unref (G_OBJECT (stream));
259 g_object_unref (G_OBJECT (pcache_dir));
263 g_object_unref (G_OBJECT (infile));
264 g_object_unref (G_OBJECT (input));
271 main (int argc, char *argv[])
276 res = test (argc, argv);