/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
#include <gsf/gsf-infile-msole.h>
#include <gsf/gsf-infile-zip.h>
#include <gsf/gsf-infile.h>
#include <gsf/gsf-input-stdio.h>
#include <gsf/gsf-utils.h>
#include <gsf/gsf-doc-meta-data.h>
#include <gsf/gsf-msole-utils.h>
#include <glib/gi18n.h>
#include <string.h>
#define GETTEXT_PACKAGE NULL /* FIXME */
static gboolean show_version;
static GOptionEntry const gsf_options [] = {
{
"version", 'v',
0, G_OPTION_ARG_NONE, &show_version,
N_("Display program version"),
NULL
},
/* ---------------------------------------- */
{ NULL, 0, 0, 0, NULL, NULL, NULL}
};
/* ------------------------------------------------------------------------- */
static GsfInfile *
open_archive (char const *filename)
{
GsfInfile *infile;
GError *error = NULL;
GsfInput *src;
char *display_name;
src = gsf_input_stdio_new (filename, &error);
if (error) {
display_name = g_filename_display_name (filename);
g_printerr (_("%s: Failed to open %s: %s\n"),
g_get_prgname (),
display_name,
error->message);
g_free (display_name);
return NULL;
}
infile = gsf_infile_zip_new (src, NULL);
if (infile)
return infile;
infile = gsf_infile_msole_new (src, NULL);
if (infile)
return infile;
display_name = g_filename_display_name (filename);
g_printerr (_("%s: Failed to recognize %s as an archive\n"),
g_get_prgname (),
display_name);
g_free (display_name);
return NULL;
}
/* ------------------------------------------------------------------------- */
static GsfInput *
find_member (GsfInfile *arch, char const *name)
{
char const *slash = strchr (name, '/');
if (slash) {
char *dirname = g_strndup (name, slash - name);
GsfInput *member;
GsfInfile *dir;
member = gsf_infile_child_by_name (arch, dirname);
g_free (dirname);
if (!member)
return NULL;
dir = GSF_INFILE (member);
member = find_member (dir, slash + 1);
g_object_unref (dir);
return member;
} else {
return gsf_infile_child_by_name (arch, name);
}
}
/* ------------------------------------------------------------------------- */
static int
gsf_help (G_GNUC_UNUSED int argc, G_GNUC_UNUSED char **argv)
{
g_print (_("Available subcommands are...\n"));
g_print (_("* cat output one or more files in archive\n"));
g_print (_("* dump dump one or more files in archive as hex\n"));
g_print (_("* help list subcommands\n"));
g_print (_("* list list files in archive\n"));
g_print (_("* props archive list of property names\n"));
return 0;
}
/* ------------------------------------------------------------------------- */
static void
ls_R (GsfInput *input, char const *prefix)
{
char const *name = gsf_input_name (input);
GsfInfile *infile = GSF_IS_INFILE (input) ? GSF_INFILE (input) : NULL;
gboolean is_dir = infile && gsf_infile_num_children (infile) > 0;
char *full_name;
char *new_prefix;
if (prefix) {
char *display_name = name ?
g_filename_display_name (name)
: g_strdup ("?");
full_name = g_strconcat (prefix,
display_name,
NULL);
new_prefix = g_strconcat (full_name, "/", NULL);
g_free (display_name);
} else {
full_name = g_strdup ("*root*");
new_prefix = g_strdup ("");
}
g_print ("%c %10" GSF_OFF_T_FORMAT " %s\n",
(is_dir ? 'd' : 'f'),
gsf_input_size (input),
full_name);
if (is_dir) {
int i;
for (i = 0 ; i < gsf_infile_num_children (infile) ; i++) {
GsfInput *child = gsf_infile_child_by_index (infile, i);
ls_R (child, new_prefix);
g_object_unref (child);
}
}
g_free (full_name);
g_free (new_prefix);
}
static int
gsf_list (int argc, char **argv)
{
int i;
for (i = 0; i < argc; i++) {
char const *filename = argv[i];
char *display_name;
GsfInfile *infile = open_archive (filename);
if (!infile)
return 1;
if (i > 0)
g_print ("\n");
display_name = g_filename_display_name (filename);
g_print ("%s:\n", display_name);
g_free (display_name);
ls_R (GSF_INPUT (infile), NULL);
g_object_unref (infile);
}
return 0;
}
/* ------------------------------------------------------------------------- */
static int
gsf_dump (int argc, char **argv, gboolean hex)
{
char const *filename;
GsfInfile *infile;
int i;
int res = 0;
if (argc < 2)
return 1;
filename = argv[0];
infile = open_archive (filename);
if (!infile)
return 1;
for (i = 1; i < argc; i++) {
char const *name = argv[i];
GsfInput *member = find_member (infile, name);
if (!member) {
char *display_name = g_filename_display_name (name);
g_print ("%s: archive has no member %s\n",
g_get_prgname (), display_name);
g_free (display_name);
res = 1;
break;
}
if (hex) {
char *display_name = g_filename_display_name (name);
g_print ("%s:\n", display_name);
g_free (display_name);
}
gsf_input_dump (member, hex);
g_object_unref (member);
}
g_object_unref (infile);
return res;
}
static int
gsf_dump_props (int argc, char **argv)
{
GsfInfile *infile;
GsfInput *in;
GsfDocProp const *prop;
GsfDocMetaData *meta_data;
GError *err;
char const *filename;
int i, res = 0;
if (argc < 2)
return 1;
filename = argv[0];
infile = open_archive (filename);
if (!infile)
return 1;
meta_data = gsf_doc_meta_data_new ();
if (GSF_IS_INFILE_MSOLE (infile)) {
in = gsf_infile_child_by_name (infile, "\05SummaryInformation");
if (NULL != in) {
err = gsf_msole_metadata_read (in, meta_data);
if (err != NULL) {
g_warning ("'%s' error: %s", filename, err->message);
g_error_free (err);
err = NULL;
}
g_object_unref (G_OBJECT (in));
}
in = gsf_infile_child_by_name (infile, "\05DocumentSummaryInformation");
if (NULL != in) {
err = gsf_msole_metadata_read (in, meta_data);
if (err != NULL) {
g_warning ("'%s' error: %s", filename, err->message);
g_error_free (err);
err = NULL;
}
g_object_unref (G_OBJECT (in));
}
}
for (i = 1; i < argc; i++)
if (NULL != (prop = gsf_doc_meta_data_lookup(meta_data, argv[i]))) {
if (argc > 2)
g_print ("%s:", argv[i]);
gsf_doc_prop_dump (prop);
}
g_object_unref (G_OBJECT (meta_data));
g_object_unref (infile);
return res;
}
/* ------------------------------------------------------------------------- */
int
main (int argc, char **argv)
{
GOptionContext *ocontext;
GError *error = NULL;
char const *usage;
char const *cmd;
g_set_prgname (argv[0]);
gsf_init ();
#if 0
bindtextdomain (GETTEXT_PACKAGE, gnm_locale_dir ());
textdomain (GETTEXT_PACKAGE);
setlocale (LC_ALL, "");
#endif
usage = _("SUBCOMMAND ARCHIVE...");
ocontext = g_option_context_new (usage);
g_option_context_add_main_entries (ocontext, gsf_options, GETTEXT_PACKAGE);
g_option_context_parse (ocontext, &argc, &argv, &error);
g_option_context_free (ocontext);
if (error) {
g_printerr (_("%s\nRun '%s --help' to see a full list of available command line options.\n"),
error->message, argv[0]);
g_error_free (error);
return 1;
}
if (show_version) {
g_print (_("gsf version %d.%d.%d\n"),
libgsf_major_version, libgsf_minor_version, libgsf_micro_version);
return 0;
}
if (argc <= 1) {
g_printerr (_("Usage: %s %s\n"), (argv[0] ? argv[0] : "gsf"), usage);
return 1;
}
cmd = argv[1];
if (strcmp (cmd, "help") == 0)
return gsf_help (argc - 2, argv + 2);
if (strcmp (cmd, "list") == 0 || strcmp (cmd, "l") == 0)
return gsf_list (argc - 2, argv + 2);
if (strcmp (cmd, "cat") == 0)
return gsf_dump (argc - 2, argv + 2, FALSE);
if (strcmp (cmd, "dump") == 0)
return gsf_dump (argc - 2, argv + 2, TRUE);
if (strcmp (cmd, "props") == 0)
return gsf_dump_props (argc - 2, argv + 2);
g_printerr (_("Run '%s help' to see a list subcommands.\n"), argv[0]);
return 1;
}
syntax highlighted by Code2HTML, v. 0.9.1