1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 #include <gsf/gsf-infile-msole.h>
4 #include <gsf/gsf-infile-tar.h>
5 #include <gsf/gsf-infile-zip.h>
6 #include <gsf/gsf-infile.h>
7 #include <gsf/gsf-input-stdio.h>
8 #include <gsf/gsf-utils.h>
9 #include <gsf/gsf-doc-meta-data.h>
10 #include <gsf/gsf-msole-utils.h>
11 #include <glib/gi18n.h>
14 #define GETTEXT_PACKAGE NULL /* FIXME */
16 static gboolean show_version;
18 static GOptionEntry const gsf_options [] = {
21 0, G_OPTION_ARG_NONE, &show_version,
22 N_("Display program version"),
26 /* ---------------------------------------- */
28 { NULL, 0, 0, 0, NULL, NULL, NULL}
31 /* ------------------------------------------------------------------------- */
34 open_archive (char const *filename)
41 src = gsf_input_stdio_new (filename, &error);
43 display_name = g_filename_display_name (filename);
44 g_printerr (_("%s: Failed to open %s: %s\n"),
48 g_free (display_name);
52 infile = gsf_infile_zip_new (src, NULL);
56 infile = gsf_infile_msole_new (src, NULL);
60 infile = gsf_infile_tar_new (src, NULL);
64 display_name = g_filename_display_name (filename);
65 g_printerr (_("%s: Failed to recognize %s as an archive\n"),
68 g_free (display_name);
72 /* ------------------------------------------------------------------------- */
75 find_member (GsfInfile *arch, char const *name)
77 char const *slash = strchr (name, '/');
80 char *dirname = g_strndup (name, slash - name);
84 member = gsf_infile_child_by_name (arch, dirname);
88 dir = GSF_INFILE (member);
89 member = find_member (dir, slash + 1);
93 return gsf_infile_child_by_name (arch, name);
97 /* ------------------------------------------------------------------------- */
100 gsf_help (G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv)
102 g_print (_("Available subcommands are...\n"));
103 g_print (_("* cat output one or more files in archive\n"));
104 g_print (_("* dump dump one or more files in archive as hex\n"));
105 g_print (_("* help list subcommands\n"));
106 g_print (_("* list list files in archive\n"));
107 g_print (_("* listprops list document properties in archive\n"));
108 g_print (_("* props print specified document properties\n"));
112 /* ------------------------------------------------------------------------- */
115 ls_R (GsfInput *input, char const *prefix)
117 char const *name = gsf_input_name (input);
118 GsfInfile *infile = GSF_IS_INFILE (input) ? GSF_INFILE (input) : NULL;
119 gboolean is_dir = infile && gsf_infile_num_children (infile) > 0;
124 char *display_name = name ?
125 g_filename_display_name (name)
127 full_name = g_strconcat (prefix,
130 new_prefix = g_strconcat (full_name, "/", NULL);
131 g_free (display_name);
133 full_name = g_strdup ("*root*");
134 new_prefix = g_strdup ("");
137 g_print ("%c %10" GSF_OFF_T_FORMAT " %s\n",
138 (is_dir ? 'd' : 'f'),
139 gsf_input_size (input),
144 for (i = 0 ; i < gsf_infile_num_children (infile) ; i++) {
145 GsfInput *child = gsf_infile_child_by_index (infile, i);
146 /* We can get NULL here in case of file corruption. */
148 ls_R (child, new_prefix);
149 g_object_unref (child);
159 gsf_list (int argc, char **argv)
163 for (i = 0; i < argc; i++) {
164 char const *filename = argv[i];
166 GsfInfile *infile = open_archive (filename);
173 display_name = g_filename_display_name (filename);
174 g_print ("%s:\n", display_name);
175 g_free (display_name);
177 ls_R (GSF_INPUT (infile), NULL);
178 g_object_unref (infile);
184 /* ------------------------------------------------------------------------- */
187 gsf_dump (int argc, char **argv, gboolean hex)
189 char const *filename;
198 infile = open_archive (filename);
202 for (i = 1; i < argc; i++) {
203 char const *name = argv[i];
204 GsfInput *member = find_member (infile, name);
206 char *display_name = g_filename_display_name (name);
207 g_print ("%s: archive has no member %s\n",
208 g_get_prgname (), display_name);
209 g_free (display_name);
215 char *display_name = g_filename_display_name (name);
216 g_print ("%s:\n", display_name);
217 g_free (display_name);
219 gsf_input_dump (member, hex);
220 g_object_unref (member);
223 g_object_unref (infile);
227 static GsfDocMetaData *
228 get_meta_data (GsfInfile *infile, const char *filename)
230 GsfDocMetaData *meta_data = gsf_doc_meta_data_new ();
232 if (GSF_IS_INFILE_MSOLE (infile)) {
236 in = gsf_infile_child_by_name (infile, "\05SummaryInformation");
238 err = gsf_msole_metadata_read (in, meta_data);
240 g_warning ("'%s' error: %s", filename, err->message);
244 g_object_unref (G_OBJECT (in));
247 in = gsf_infile_child_by_name (infile, "\05DocumentSummaryInformation");
249 err = gsf_msole_metadata_read (in, meta_data);
251 g_warning ("'%s' error: %s", filename, err->message);
256 g_object_unref (G_OBJECT (in));
264 gsf_dump_props (int argc, char **argv)
267 GsfDocMetaData *meta_data;
268 char const *filename;
276 infile = open_archive (filename);
280 meta_data = get_meta_data (infile, filename);
282 for (i = 1; i < argc; i++) {
283 const char *name = argv[i];
284 GsfDocProp const *prop =
285 gsf_doc_meta_data_lookup (meta_data, name);
288 g_print ("%s: ", name);
289 gsf_doc_prop_dump (prop);
291 g_printerr (_("No property named %s\n"), name);
295 g_object_unref (meta_data);
296 g_object_unref (infile);
301 cb_collect_names (gpointer key,
302 G_GNUC_UNUSED gpointer value,
305 const char *name = key;
306 GSList **names = user;
308 *names = g_slist_prepend (*names, g_strdup (name));
312 cb_print_names (const char *name)
314 g_print ("%s\n", name);
318 gsf_list_props (int argc, char **argv)
321 GsfDocMetaData *meta_data;
322 char const *filename;
323 GSList *names = NULL;
329 infile = open_archive (filename);
333 meta_data = get_meta_data (infile, filename);
334 gsf_doc_meta_data_foreach (meta_data, cb_collect_names, &names);
335 names = g_slist_sort (names, (GCompareFunc)strcmp);
336 g_slist_foreach (names, (GFunc)cb_print_names, NULL);
337 g_slist_free (names);
339 g_object_unref (meta_data);
340 g_object_unref (infile);
344 /* ------------------------------------------------------------------------- */
347 main (int argc, char **argv)
349 GOptionContext *ocontext;
350 GError *error = NULL;
353 char const *me = (argv[0] ? argv[0] : "gsf");
359 bindtextdomain (GETTEXT_PACKAGE, gnm_locale_dir ());
360 textdomain (GETTEXT_PACKAGE);
361 setlocale (LC_ALL, "");
364 usage = _("SUBCOMMAND ARCHIVE...");
365 ocontext = g_option_context_new (usage);
366 g_option_context_add_main_entries (ocontext, gsf_options, GETTEXT_PACKAGE);
367 g_option_context_parse (ocontext, &argc, &argv, &error);
368 g_option_context_free (ocontext);
371 g_printerr (_("%s\nRun '%s --help' to see a full list of available command line options.\n"),
373 g_error_free (error);
378 g_print (_("gsf version %d.%d.%d\n"),
379 libgsf_major_version, libgsf_minor_version, libgsf_micro_version);
384 g_printerr (_("Usage: %s %s\n"), me, usage);
390 if (strcmp (cmd, "help") == 0)
391 return gsf_help (argc - 2, argv + 2);
393 if (strcmp (cmd, "list") == 0 || strcmp (cmd, "l") == 0)
394 return gsf_list (argc - 2, argv + 2);
396 if (strcmp (cmd, "cat") == 0)
397 return gsf_dump (argc - 2, argv + 2, FALSE);
398 if (strcmp (cmd, "dump") == 0)
399 return gsf_dump (argc - 2, argv + 2, TRUE);
400 if (strcmp (cmd, "props") == 0)
401 return gsf_dump_props (argc - 2, argv + 2);
402 if (strcmp (cmd, "listprops") == 0)
403 return gsf_list_props (argc - 2, argv + 2);
405 g_printerr (_("Run '%s help' to see a list subcommands.\n"), me);