static void clone (GsfInput *input, GsfOutput *output) { guint8 const *data; size_t len; int i; if (gsf_input_size (input) > 0) { while ((len = gsf_input_remaining (input)) > 0) { /* copy in odd sized chunks to exercise system */ if (len > 314) len = 314; if (NULL == (data = gsf_input_read (input, len, NULL))) { g_warning ("error reading ?"); return; } if (!gsf_output_write (output, len, data)) { g_warning ("error writing ?"); return; } } } /* See test-cp-msole.c for explanation how to distinct directories * from regular files. */ if (GSF_IS_INFILE (input) && gsf_infile_num_children (GSF_INFILE (input)) > 0) { GsfInfile *in = GSF_INFILE (input); GsfOutfile *out = GSF_OUTFILE (output); GsfInput *src; GsfOutput *dst; gboolean is_dir; for (i = 0 ; i < gsf_infile_num_children (in) ; i++) { src = gsf_infile_child_by_index (in, i); is_dir = GSF_IS_INFILE (src) && gsf_infile_num_children (GSF_INFILE (src)) >= 0; dst = gsf_outfile_new_child (out, gsf_infile_name_by_index (in, i), is_dir); clone (src, dst); } } gsf_output_close (output); g_object_unref (G_OBJECT (output)); g_object_unref (G_OBJECT (input)); }
static void ls_R (GsfInput *input) { char const *name = gsf_input_name (input); gboolean is_dir = GSF_IS_INFILE (input) && (gsf_infile_num_children (GSF_INFILE (input)) >= 0); /* Please see the comment on is_dir in test-cp-msole.c. */ printf ("%c '%s'\t\t%" GSF_OFF_T_FORMAT "\n", (is_dir ? 'd' : ' '), (name != NULL) ? name : "", gsf_input_size (input)); if (is_dir) { GsfInfile *infile = GSF_INFILE (input); int i; puts ("{"); for (i = 0 ; i < gsf_infile_num_children (infile) ; i++) ls_R (gsf_infile_child_by_index (infile, i)); puts ("}"); } g_object_unref (G_OBJECT (input)); }
static void clone_dir (GsfInfile *in, GsfOutfile *out) { GsfInput *new_input; GsfOutput *new_output; gboolean is_dir; int i; for (i = 0 ; i < gsf_infile_num_children (in) ; i++) { new_input = gsf_infile_child_by_index (in, i); /* In theory, if new_file is a regular file (not directory), * it should be GsfInput only, not GsfInfile, as it is not * structured. However, having each Infile define a 2nd class * that only inherited from Input was cumbersome. So in * practice, the convention is that new_input is always * GsfInfile, but regular file is distinguished by having -1 * children. */ is_dir = GSF_IS_INFILE (new_input) && gsf_infile_num_children (GSF_INFILE (new_input)) >= 0; new_output = gsf_outfile_new_child (out, gsf_infile_name_by_index (in, i), is_dir); clone (new_input, new_output); } /* An observation: when you think about the explanation to is_dir * above, you realize that clone_dir is called even for regular files. * But nothing bad happens, as the loop is never entered. */ }
static void clone (GsfInput *input, GsfOutput *output) { if (gsf_input_size (input) > 0) { guint8 const *data; size_t len; while ((len = gsf_input_remaining (input)) > 0) { /* copy in odd sized chunks to exercise system */ if (len > 314) len = 314; if (NULL == (data = gsf_input_read (input, len, NULL))) { g_warning ("error reading ?"); return; } if (!gsf_output_write (output, len, data)) { g_warning ("error writing ?"); return; } } } else if (GSF_IS_INFILE(input)) clone_dir (GSF_INFILE(input), GSF_OUTFILE(output)); gsf_output_close (output); g_object_unref (G_OBJECT (output)); g_object_unref (G_OBJECT (input)); }
/** * gsf_structured_blob_read: * @input: An input (potentially a GsfInfile) holding the blob * * Create a tree of binary blobs with unknown content from a #GsfInput or * #GsfInfile and store it in a newly created #GsfStructuredBlob. * * Returns: (transfer full): a new #GsfStructuredBlob object which the caller is responsible for. **/ GsfStructuredBlob * gsf_structured_blob_read (GsfInput *input) { GsfStructuredBlob *blob; gsf_off_t content_size; int i = 0; g_return_val_if_fail (GSF_IS_INPUT (input), NULL); blob = g_object_new (GSF_STRUCTURED_BLOB_TYPE, NULL); content_size = gsf_input_remaining (input); if (content_size > 0) { guint8 *buf = (guint8*)g_try_malloc (content_size); if (buf == NULL) { g_warning ("Failed attempting to allocate %" GSF_OFF_T_FORMAT " bytes", content_size); g_object_unref (blob); return NULL; } gsf_input_read (input, content_size, buf); blob->data = gsf_shared_memory_new (buf, content_size, TRUE); } gsf_input_set_name (GSF_INPUT (blob), gsf_input_name (input)); if (GSF_IS_INFILE (input)) i = gsf_infile_num_children (GSF_INFILE (input)); if (i > 0) { GsfInput *child; GsfStructuredBlob *child_blob; blob->children = g_ptr_array_sized_new (i); g_ptr_array_set_size (blob->children, i); while (i-- > 0) { child = gsf_infile_child_by_index (GSF_INFILE (input), i); child_blob = gsf_structured_blob_read (child); g_object_unref (child); g_ptr_array_index (blob->children, i) = child_blob; #if 0 /* * We don't need this, and setting it causes circular * links. */ gsf_input_set_container (GSF_INPUT (child_blob), GSF_INFILE (blob)); #endif } } return blob; }
/** * gsf_open_pkg_open_rel: * @opkg: #GsfInput * @rel: #GsfOpenPkgRel * @err: #GError. * * Returns: (transfer full): a new #GsfInput which the called needs to unref, or %NULL and sets @err **/ GsfInput * gsf_open_pkg_open_rel (GsfInput *opkg, GsfOpenPkgRel const *rel, G_GNUC_UNUSED GError **err /* just in case we need it one day */ ) { GsfInput *res = NULL; GsfInfile *parent, *prev_parent; gchar **elems; unsigned i; g_return_val_if_fail (rel != NULL, NULL); g_return_val_if_fail (opkg != NULL, NULL); /* References from the root use children of opkg * References from a child are relative to siblings of opkg */ parent = gsf_input_name (opkg) ? gsf_input_container (opkg) : GSF_INFILE (opkg); g_object_ref (parent); elems = g_strsplit (rel->target, "/", 0); for (i = 0 ; elems[i] && NULL != parent ; i++) { if (0 == strcmp (elems[i], ".") || '\0' == *elems[i]) continue; /* ignore '.' and empty */ prev_parent = parent; if (0 == strcmp (elems[i], "..")) { parent = gsf_input_container (GSF_INPUT (parent)); res = NULL; /* only return newly created children */ if (NULL != parent) { /* check for attempt to gain access outside the zip file */ if (G_OBJECT_TYPE (parent) == G_OBJECT_TYPE (prev_parent)) g_object_ref (parent); else parent = NULL; } } else { res = gsf_infile_child_by_name (parent, elems[i]); if (NULL != elems[i+1]) { g_return_val_if_fail (GSF_IS_INFILE (res), NULL); parent = GSF_INFILE (res); } } g_object_unref (prev_parent); } g_strfreev (elems); return res; }
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); /* We can get NULL here in case of file corruption. */ if (child) { ls_R (child, new_prefix); g_object_unref (child); } } } g_free (full_name); g_free (new_prefix); }
GsfInfile * gsf_infile_msvba_new (GsfInfile *source, GError **err) { GsfInfileMSVBA *vba; g_return_val_if_fail (GSF_IS_INFILE (source), NULL); vba = g_object_new (GSF_INFILE_MSVBA_TYPE, NULL); vba->source = g_object_ref (source); /* vba_project_read (vba, err); */ /* find the name offset pairs */ if (vba_dir_read (vba, err)) return GSF_INFILE (vba); if (err != NULL && *err == NULL) *err = g_error_new (gsf_input_error_id (), 0, _("Unable to parse VBA header")); g_object_unref (vba); return NULL; }
static int test (int argc, char *argv[]) { GsfInput *input; GsfInfile *infile; GError *err = NULL; fprintf (stderr, "%s\n", argv [1]); input = gsf_input_stdio_new (argv[1], &err); if (input == NULL) { g_return_val_if_fail (err != NULL, 1); g_warning ("'%s' error: %s", argv[1], err->message); g_error_free (err); return 1; } input = gsf_input_uncompress (input); infile = gsf_infile_msole_new (input, &err); g_object_unref (G_OBJECT (input)); if (infile == NULL) { g_return_val_if_fail (err != NULL, 1); g_warning ("'%s' Not an OLE file: %s", argv[1], err->message); g_error_free (err); return 1; } if (argc > 2) { int i; GsfInput *child, *ptr = GSF_INPUT (infile); for (i = 2 ; i < argc && ptr != NULL; i++, ptr = child) { fprintf (stderr, "--> '%s'\n", argv [i]); if (GSF_IS_INFILE (ptr) && gsf_infile_num_children (GSF_INFILE (ptr)) >= 0) { child = gsf_infile_child_by_name (GSF_INFILE (ptr), argv [i]); if (child == NULL) { g_warning ("No child named '%s'", argv [i]); child = NULL; } } else { g_warning ("stream is not a directory '%s'", argv [i]); child = NULL; } g_object_unref (G_OBJECT (ptr)); } if (ptr != NULL) { /* See the comment on is_dir in test-cp-msole.c. */ if (GSF_IS_INFILE (ptr) && gsf_infile_num_children (GSF_INFILE (ptr)) >= 0) ls_R (ptr); /* unrefs infile */ else { gsf_input_dump (GSF_INPUT (ptr), dump_as_hex); g_object_unref (G_OBJECT (ptr)); } } } else ls_R (GSF_INPUT (infile)); /* unrefs infile */ return 0; }