Пример #1
0
/**
 * gsf_open_pkg_open_rel_by_id:
 * @opkg: #GsfInput
 * @id: target id
 * @err: optionally %NULL
 *
 * New in 1.14.7
 *
 * Open @opkg's relation @id
 *
 * Returns: (transfer full): A new GsfInput or %NULL, and sets @err if possible.
 **/
GsfInput *
gsf_open_pkg_open_rel_by_id (GsfInput *opkg, char const *id, GError **err)
{
	GsfOpenPkgRel *rel = gsf_open_pkg_lookup_rel_by_id (opkg, id);

	if (rel)
		return gsf_open_pkg_open_rel (opkg, rel, err);

	if (err)
		*err = g_error_new (gsf_input_error_id(), gsf_open_pkg_error_id (),
			_("Unable to find part id='%s' for '%s'"),
			id, gsf_input_name (opkg) );
	return NULL;
}
Пример #2
0
/**
 * gsf_open_pkg_open_rel_by_id :
 * @opkg : #GsfInput
 * @id : target id
 * @err : optionally %NULL
 *
 * New in 1.14.7
 *
 * Open @opkg's relation @id
 *
 * Returns: A new GsfInput or %NULL, and sets @err if possible.
 **/
GsfInput *
gsf_open_pkg_open_rel_by_id (GsfInput *opkg, char const *id, GError **err)
{
	GsfOpenPkgRel *rel = NULL;
	GsfOpenPkgRels *rels = gsf_open_pkg_get_rels (opkg);

	if (NULL != rels && NULL != (rel = g_hash_table_lookup (rels->by_id, id)))
		return gsf_open_pkg_open_rel (opkg, rel, err);
	if (err)
		*err = g_error_new (gsf_input_error_id(), gsf_open_pkg_error_id (),
			_("Unable to find part id='%s' for '%s'"),
			id, gsf_input_name (opkg) );
	return NULL;
}
Пример #3
0
static gsf_off_t
unpack_octal (GsfInfileTar *tar, const char *s, size_t len)
{
	gsf_off_t res = 0;

	while (len--) {
		unsigned char c = *s++;
		if (c == 0)
			break;
		if (c < '0' || c > '7') {
			tar->err = g_error_new (gsf_input_error_id (), 0,
						"Invalid tar header");
			return 0;
		}
		res = (res << 3) + (c - '0');
	}

	return res;
}
Пример #4
0
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;
}
Пример #5
0
/**
 * tar_init_info :
 * @tar : #GsfInfileTar
 *
 * Read tar headers and do some sanity checking
 * along the way.
 **/
static void
tar_init_info (GsfInfileTar *tar)
{
	TarHeader end;
	const TarHeader *header;
	gsf_off_t pos0 = gsf_input_tell (tar->source);
	char *pending_longname = NULL;

	memset (&end, 0, sizeof (end));

	while (tar->err == NULL &&
	       (header = (const TarHeader *)gsf_input_read (tar->source,
							    HEADER_SIZE,
							    NULL))) {
		char *name;
		gsf_off_t length;
		gsf_off_t offset;

		if (memcmp (header->filler, end.filler, sizeof (end.filler))) {
			tar->err = g_error_new (gsf_input_error_id (), 0,
						"Invalid tar header");
			break;
		}

		if (memcmp (header, &end, HEADER_SIZE) == 0)
			break;

		if (pending_longname) {
			name = pending_longname;
			pending_longname = NULL;
		} else
			name = g_strndup (header->name, sizeof (header->name));
		length = unpack_octal (tar, header->size, sizeof (header->size));
		offset = gsf_input_tell (tar->source);

#if 0
		g_printerr ("[%s]: %d\n", name, (int)length);
#endif

		switch (header->typeflag) {
		case '0': case 0: {
			/* Regular file. */
			GsfInfileTar *dir;
			const char *n = name, *s;
			TarChild c;

			/* This is deliberately slash-only.  */
			while ((s = strchr (n, '/')))
				n = s + 1;
			c.name = g_strdup (n);
			c.offset = offset;
			c.length = length;
			c.dir = NULL;
			dir = tar_directory_for_file (tar, name, FALSE);
			g_array_append_val (dir->children, c);
			break;
		}
		case '5': {
			/* Directory */
			(void)tar_directory_for_file (tar, name, TRUE);
			break;
		}
		case 'L': {
			const char *n;

			if (pending_longname ||
			    strcmp (name, MAGIC_LONGNAME) != 0) {
				tar->err = g_error_new (gsf_input_error_id (), 0,
							"Invalid longname header");
				break;
			}

			n = gsf_input_read (tar->source, length, NULL);
			if (!n) {
				tar->err = g_error_new (gsf_input_error_id (), 0,
							"Failed to read longname");
				break;
			}

			pending_longname = g_strndup (n, length);
			break;
		}
		default:
			/* Other -- ignore */
			break;
		}

		g_free (name);

		/* Round up to block size */
		length = (length + (BLOCK_SIZE - 1)) / BLOCK_SIZE * BLOCK_SIZE;
		
		if (!tar->err &&
		    gsf_input_seek (tar->source, offset + length, G_SEEK_SET)) {
			tar->err = g_error_new (gsf_input_error_id (), 0,
						"Seek failed");
			break;
		}
	}

	if (pending_longname) {
		if (!tar->err)
			tar->err = g_error_new (gsf_input_error_id (), 0,
						"Truncated archive");
		g_free (pending_longname);
	}

	if (tar->err)
		gsf_input_seek (tar->source, pos0, G_SEEK_SET);
}
Пример #6
0
static guint8 const *
gsf_input_gzip_read (GsfInput *input, size_t num_bytes, guint8 *buffer)
{
	GsfInputGZip *gzip = GSF_INPUT_GZIP (input);

	if (buffer == NULL) {
		if (gzip->buf_size < num_bytes) {
			gzip->buf_size = MAX (num_bytes, 256);
			g_free (gzip->buf);
			gzip->buf = g_new (guint8, gzip->buf_size);
		}
		buffer = gzip->buf;
	}

	gzip->stream.next_out = buffer;
	gzip->stream.avail_out = num_bytes;
	while (gzip->stream.avail_out != 0) {
		int zerr;
		if (gzip->stream.avail_in == 0) {
			gsf_off_t remain = gsf_input_remaining (gzip->source);
			if (remain <= gzip->trailer_size) {
				if (remain < gzip->trailer_size || gzip->stop_byte_added) {
					g_clear_error (&gzip->err);
					gzip->err = g_error_new
						(gsf_input_error_id (), 0,
						 "truncated source");
					return NULL;
				}
				/* zlib requires an extra byte.  */
				gzip->stream.avail_in = 1;
				gzip->gzipped_data = "";
				gzip->stop_byte_added = TRUE;
			} else {
				size_t n = MIN (remain - gzip->trailer_size,
						Z_BUFSIZE);

				gzip->gzipped_data =
					gsf_input_read (gzip->source, n, NULL);
				if (!gzip->gzipped_data) {
					g_clear_error (&gzip->err);
					gzip->err = g_error_new
						(gsf_input_error_id (), 0,
						 "Failed to read from source");
					return NULL;
				}
				gzip->stream.avail_in = n;
			}
			gzip->stream.next_in = (Byte *)gzip->gzipped_data;
		}
		zerr = inflate (&(gzip->stream), Z_NO_FLUSH);
		if (zerr != Z_OK) {
			if (zerr != Z_STREAM_END)
				return NULL;
			/* Premature end of stream.  */
			if (gzip->stream.avail_out != 0)
				return NULL;
		}
	}

	gzip->crc = crc32 (gzip->crc, buffer, (uInt)(gzip->stream.next_out - buffer));
	return buffer;
}
Пример #7
0
/**
 * vba_project_read:
 * @vba: #GsfInfileMSVBA
 * @err: (allow-none): place to store a #GError if anything goes wrong
 *
 * Read an VBA dirctory and its project file.
 * along the way.
 *
 * Returns: %FALSE on error setting @err if it is supplied.
 **/
static gboolean
vba_project_read (GsfInfileMSVBA *vba, GError **err)
{
	/* NOTE : This seems constant, find some confirmation */
	static guint8 const signature[]	  = { 0xcc, 0x61 };
	static struct {
		guint8 const signature[4];
		char const * const name;
		int const vba_version;
		gboolean const is_mac;
	} const  versions [] = {
		{ { 0x5e, 0x00, 0x00, 0x01 }, "Office 97",              5, FALSE},
		{ { 0x5f, 0x00, 0x00, 0x01 }, "Office 97 SR1",          5, FALSE },
		{ { 0x65, 0x00, 0x00, 0x01 }, "Office 2000 alpha?",     6, FALSE },
		{ { 0x6b, 0x00, 0x00, 0x01 }, "Office 2000 beta?",      6, FALSE },
		{ { 0x6d, 0x00, 0x00, 0x01 }, "Office 2000",            6, FALSE },
		{ { 0x6f, 0x00, 0x00, 0x01 }, "Office 2000",            6, FALSE },
		{ { 0x70, 0x00, 0x00, 0x01 }, "Office XP beta 1/2",     6, FALSE },
		{ { 0x73, 0x00, 0x00, 0x01 }, "Office XP",              6, FALSE },
		{ { 0x76, 0x00, 0x00, 0x01 }, "Office 2003",            6, FALSE },
		{ { 0x79, 0x00, 0x00, 0x01 }, "Office 2003",            6, FALSE },
		{ { 0x60, 0x00, 0x00, 0x0e }, "MacOffice 98",           5, TRUE },
		{ { 0x62, 0x00, 0x00, 0x0e }, "MacOffice 2001",         5, TRUE },
		{ { 0x63, 0x00, 0x00, 0x0e }, "MacOffice X",		6, TRUE },
		{ { 0x64, 0x00, 0x00, 0x0e }, "MacOffice 2004",         6, TRUE },
	};

	guint8 const *data;
	unsigned i, count, len;
	gunichar2 *uni_name;
	char *name;
	GsfInput *dir;

	dir = gsf_infile_child_by_name (vba->source, "dir");
	if (dir == NULL) {
		if (err != NULL)
			*err = g_error_new (gsf_input_error_id (), 0,
					    _("Can't find the VBA directory stream"));
		return FALSE;
	}

	if (gsf_input_seek (dir, 0, G_SEEK_SET) ||
	    NULL == (data = gsf_input_read (dir, VBA56_DIRENT_HEADER_SIZE, NULL)) ||
	    0 != memcmp (data, signature, sizeof (signature))) {
		if (err != NULL)
			*err = g_error_new (gsf_input_error_id (), 0,
					    _("No VBA signature"));
		return FALSE;
	}

	for (i = 0 ; i < G_N_ELEMENTS (versions); i++)
		if (!memcmp (data+2, versions[i].signature, 4))
			break;

	if (i >= G_N_ELEMENTS (versions)) {
		if (err != NULL)
			*err = g_error_new (gsf_input_error_id (), 0,
					    _("Unknown VBA version signature 0x%x%x%x%x"),
					    data[2], data[3], data[4], data[5]);
		return FALSE;
	}

	puts (versions[i].name);

	/* these depend strings seem to come in 2 blocks */
	count = GSF_LE_GET_GUINT16 (data + VBA56_DIRENT_RECORD_COUNT);
	for (; count > 0 ; count--) {
		if (NULL == ((data = gsf_input_read (dir, 2, NULL))))
			break;
		len = GSF_LE_GET_GUINT16 (data);
		if (NULL == ((data = gsf_input_read (dir, len, NULL)))) {
			printf ("len == 0x%x ??\n", len);
			break;
		}

		uni_name = g_new0 (gunichar2, len/2 + 1);

		/* be wary about endianness */
		for (i = 0 ; i < len ; i += 2)
			uni_name [i/2] = GSF_LE_GET_GUINT16 (data + i);
		name = g_utf16_to_utf8 (uni_name, -1, NULL, NULL, NULL);
		g_free (uni_name);

		printf ("%d %s\n", count, name);

		/* ignore this blob ???? */
		if (!strncmp ("*\\G", name, 3)) {
			if (NULL == ((data = gsf_input_read (dir, 12, NULL)))) {
				printf ("len == 0x%x ??\n", len);
				break;
			}
		}

		g_free (name);
	}

	g_return_val_if_fail (count == 0, FALSE);

	return TRUE;
}
Пример #8
0
/**
 * vba_dir_read:
 * @vba: #GsfInfileMSVBA
 * @err: (allow-none): place to store a #GError if anything goes wrong
 *
 * Read an VBA dirctory and its project file.
 * along the way.
 *
 * Returns: %FALSE on error setting @err if it is supplied.
 **/
static gboolean
vba_dir_read (GsfInfileMSVBA *vba, GError **err)
{
	int inflated_size, element_count = -1;
	char const *msg = NULL;
	char *name, *elem_stream = NULL;
	guint32 len;
	guint16 tag;
	guint8   *inflated_data, *end, *ptr;
	GsfInput *dir;
	gboolean  failed = TRUE;

	/* 0. get the stream */
	dir = gsf_infile_child_by_name (vba->source, "dir");
	if (dir == NULL) {
		msg = _("Can't find the VBA directory stream");
		goto fail_stream;
	}

	/* 1. decompress it */
	ptr = inflated_data = gsf_vba_inflate (dir, 0, &inflated_size, TRUE);
	if (inflated_data == NULL)
		goto fail_compression;
	end = inflated_data + inflated_size;

	/* 2. GUESS : based on several xls with macros and XL8GARY this looks like a
	 * series of sized records.  Be _extra_ careful */
	do {
		/* I have seen
		 * type		len	data
		 *  1		 4	 1 0 0 0
		 *  2		 4	 9 4 0 0
		 *  3		 2	 4 e4
		 *  4		<var>	 project name
		 *  5		 0
		 *  6		 0
		 *  7		 4
		 *  8		 4
		 *  0x3d	 0
		 *  0x40	 0
		 *  0x14	 4	 9 4 0 0
		 *
		 *  0x0f == number of elements
		 *  0x1c == (Size 0)
		 *  0x1e == (Size 4)
		 *  0x48 == (Size 0)
		 *  0x31 == stream offset of the compressed source !
		 *
		 *  0x16 == an ascii dependency name
		 *  0x3e == a unicode dependency name
		 *  0x33 == a classid for a dependency with no trialing data
		 *
		 *  0x2f == a dummy classid
		 *  0x30 == a classid
		 *  0x0d == the classid
		 *  0x2f, and 0x0d appear contain
		 * 	uint32 classid_size;
		 * 	<classid>
		 *	00 00 00 00 00 00
		 *	and sometimes some trailing junk
		 **/
		if ((ptr + 6) > end) {
			msg = _("vba project header problem");
			goto fail_content;
		}
		tag = GSF_LE_GET_GUINT16 (ptr);
		len = GSF_LE_GET_GUINT32 (ptr + 2);

		ptr += 6;
		if ((ptr + len) > end) {
			msg = _("vba project header problem");
			goto fail_content;
		}

		switch (tag) {
		case 4:
			name = g_strndup (ptr, len);
#ifdef OLD_VBA_DUMP
			puts ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
			printf ("<project name=\"%s\">", name);
#endif
			g_free (name);
			break;
		case 9:
			/* this seems to have an extra two bytes that are not
			 * part of the length ..?? */
			len += 2;
			break;
		case 0xf  :
			if (len != 2) {
				g_warning ("element count is not what we expected");
				break;
			}
			if (element_count >= 0) {
				g_warning ("More than one element count ??");
				break;
			}
			element_count = GSF_LE_GET_GUINT16 (ptr);
			break;

		/* dependencies */
		case 0x0d : break;
		case 0x2f : break;
		case 0x30 : break;
		case 0x33 : break;
		case 0x3e : break;
		case 0x16:
#if 0
			name = g_strndup (ptr, len);
			g_print ("Depend Name : '%s'\n", name);
			g_free (name);
#endif
			break;

		/* elements */
		case 0x47 : break;
		case 0x32 : break;
		case 0x1a:
#if 0
			name = g_strndup (ptr, len);
			g_print ("Element Name : '%s'\n", name);
			g_free (name);
#endif
			break;
		case 0x19:
			g_free (elem_stream);
			elem_stream = g_strndup (ptr, len);
			break;

		case 0x31:
			if (len != 4) {
				g_warning ("source offset property is not what we expected");
				break;
			}
			vba_extract_module_source (vba, elem_stream,
				GSF_LE_GET_GUINT32 (ptr));
			g_free (elem_stream); elem_stream = NULL;
			element_count--;
			break;

		default :
#if 0
			g_print ("tag %hx : len %u\n", tag, len);
			gsf_mem_dump (ptr, len);
#endif
			break;
		}

		ptr += len;
	} while (tag != 0x10);

	if (element_count != 0)
		g_warning ("Number of elements differs from expectations");

	failed = FALSE;

fail_content :
	g_free (inflated_data);
#ifdef OLD_VBA_DUMP
	puts ("</project>");
#endif

fail_compression :
	g_object_unref (dir);
fail_stream :

	g_free (elem_stream);

	if (failed) {
		if (err != NULL)
			*err = g_error_new_literal (gsf_input_error_id (), 0, msg);
		return FALSE;
	}

	return TRUE;
}