[totem-pl-parser] Use GZlibDecompressor



commit 71ab73dd80816243958f997460b68c81192f6341
Author: Christian Persch <chpe gnome org>
Date:   Wed May 5 01:40:37 2010 +0200

    Use GZlibDecompressor
    
    Untested!
    
    Bug #617664.

 configure.in                      |    2 +-
 plparse/totem-pl-parser-podcast.c |  180 +++++++++++++------------------------
 2 files changed, 64 insertions(+), 118 deletions(-)
---
diff --git a/configure.in b/configure.in
index a3b56d4..d2249c0 100644
--- a/configure.in
+++ b/configure.in
@@ -40,7 +40,7 @@ AC_PATH_PROG([GLIB_MKENUMS],[glib-mkenums])
 
 # Requirements
 GLIB_REQS=2.21.6
-GIO_REQS=2.17.3
+GIO_REQS=2.24.0
 
 # Before making a release, the PLPARSER_LT_VERSION string should be modified.
 # The string is of the form C:R:A.
diff --git a/plparse/totem-pl-parser-podcast.c b/plparse/totem-pl-parser-podcast.c
index 6b91894..7ca0319 100644
--- a/plparse/totem-pl-parser-podcast.c
+++ b/plparse/totem-pl-parser-podcast.c
@@ -572,91 +572,6 @@ totem_pl_parser_add_xml_feed (TotemPlParser *parser,
 #endif /* !HAVE_GMIME */
 }
 
-/* From libgsf's gsf-utils.h */
-#define GSF_LE_GET_GUINT32(p)				\
-	(guint32)((((guint8 const *)(p))[0] << 0)  |	\
-		  (((guint8 const *)(p))[1] << 8)  |	\
-		  (((guint8 const *)(p))[2] << 16) |	\
-		  (((guint8 const *)(p))[3] << 24))
-
-/* From libgsf's gsf-input-gzip.c */
-/* gzip flag byte */
-#define GZIP_IS_ASCII		0x01 /* file contains text ? */
-#define GZIP_HEADER_CRC		0x02 /* there is a CRC in the header */
-#define GZIP_EXTRA_FIELD	0x04 /* there is an 'extra' field */
-#define GZIP_ORIGINAL_NAME	0x08 /* the original is stored */
-#define GZIP_HAS_COMMENT	0x10 /* There is a comment in the header */
-#define GZIP_HEADER_FLAGS (unsigned)(GZIP_IS_ASCII |GZIP_HEADER_CRC |GZIP_EXTRA_FIELD |GZIP_ORIGINAL_NAME |GZIP_HAS_COMMENT)
-
-static guint32
-check_header (char *data, gsize len)
-{
-	static guint8 const signature[2] = {0x1f, 0x8b};
-	unsigned flags;
-
-	if (len < 2 + 1 + 1 + 6)
-		return 0;
-
-	/* Check signature */
-	if (memcmp (data, signature, sizeof (signature)) != 0)
-		return 0;
-
-	/* verify flags and compression type */
-	flags  = data[3];
-	if (data[2] != Z_DEFLATED || (flags & ~GZIP_HEADER_FLAGS) != 0)
-		return 0;
-
-	/* Get the uncompressed size */
-	/* FIXME, but how?  The size read here is modulo 2^32.  */
-	return GSF_LE_GET_GUINT32 (data + len - 4);
-}
-
-static char *
-decompress_gzip (char *data, gsize len)
-{
-	guint32 retlen;
-	char *ret;
-	int zerr;
-	z_stream  stream;
-
-	retlen = check_header (data, len);
-	if (retlen == 0)
-		return g_strdup (data);
-
-	stream.zalloc    = (alloc_func)0;
-	stream.zfree     = (free_func)0;
-	stream.opaque    = (voidpf)0;
-	stream.next_in   = Z_NULL;
-	stream.next_out  = Z_NULL;
-	stream.avail_in  = stream.avail_out = 0;
-
-	/* 16 + MAX_WBITS as per http://hewgill.com/journal/entries/349 */
-	if (Z_OK != inflateInit2 (&stream, 16 + MAX_WBITS))
-		return NULL;
-
-	/* +1 so it's NULL-terminated */
-	ret = g_malloc0 (retlen + 1);
-
-	stream.next_in = (unsigned char *) data;
-	stream.avail_in = len;
-
-	stream.next_out = (unsigned char *) ret;
-	stream.avail_out = retlen;
-
-	zerr = inflate (&stream, Z_NO_FLUSH);
-	if (zerr != Z_OK && zerr != Z_STREAM_END) {
-		g_free (ret);
-		return NULL;
-	}
-	zerr = inflateEnd (&stream);
-	if (zerr != Z_OK) {
-		g_free (ret);
-		return NULL;
-	}
-
-	return ret;
-}
-
 static const char *
 totem_pl_parser_parse_itms_doc (xml_node_t *item)
 {
@@ -713,8 +628,49 @@ totem_pl_parser_get_feed_uri (char *data, gsize len)
 	return ret;
 }
 
+static GByteArray *
+totem_pl_parser_get_content_decompressed (GFile *file)
+{
+	GFileInputStream *file_in;
+	GInputStream *converter_in;
+	GConverter *decompressor;
+	GByteArray *data;
+	gsize position;
+	gssize n_read;
+
+	file_in = g_file_read (file, NULL, NULL);
+	if (file_in == NULL)
+		return NULL;
+
+	decompressor = G_CONVERTER (g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP));
+	converter_in = g_converter_input_stream_new (G_INPUT_STREAM (file_in), decompressor);
+	g_object_unref (file_in);
+	g_object_unref (decompressor);
+
+#define BLOCK_SIZE 8192
+	position = 0;
+	data = g_byte_array_sized_new (BLOCK_SIZE + 1);
+	while ((n_read = g_input_stream_read (converter_in,
+					      data->data + position,
+					      BLOCK_SIZE,
+					      NULL, NULL)) > 0) {
+		position += n_read;
+		g_byte_array_set_size (data, position + BLOCK_SIZE + 1);
+	}
+
+	g_object_unref (converter_in);
+
+	if (n_read < 0) {
+		g_byte_array_free (data, TRUE);
+		return NULL;
+	}
+
+	return data;
+}
+
 static char *
-totem_pl_parser_get_itms_uri (const char *data)
+totem_pl_parser_get_itms_uri (const char *data,
+			      gsize data_len)
 {
 	char *s, *end, *ret;
 #define ITMS_OPEN "<body onload=\"return itmsOpen('"
@@ -722,11 +678,14 @@ totem_pl_parser_get_itms_uri (const char *data)
 	/* The bit of text looks like:
 	 * <body onload="return itmsOpen('itms://ax.phobos.apple.com.edgesuite.net/WebObjects/MZStore.woa/wa/viewPodcast?id=207870198&amp;ign-mscache=1','http://www.apple.com/uk/itunes/affiliates/download/?itmsUrl=itms%3A%2F%2Fax.phobos.apple.com.edgesuite.net%2FWebObjects%2FMZStore.woa%2Fwa%2FviewPodcast%3Fid%3D207870198%26ign-mscache%3D1','userOverridePanel',false)"> */
 
-	s = strstr (data, ITMS_OPEN);
+	s = g_strstr_len (data, data_len, ITMS_OPEN);
 	if (s == NULL)
 		return NULL;
-	s = s + strlen (ITMS_OPEN);
-	end = strchr (s, '\'');
+	s += strlen (ITMS_OPEN);
+	if (s[0] != 'i' || s[1] != 't' || s[2] != 'm' || s[3] != 's')
+		return NULL;
+
+	end = g_strstr_len (s, data + data_len - s, "\'");
 	if (end == NULL)
 		return NULL;
 
@@ -745,57 +704,44 @@ totem_pl_parser_add_itms (TotemPlParser *parser,
 #ifndef HAVE_GMIME
 	WARN_NO_GMIME;
 #else
-	char *contents, *uncompressed, *itms_uri;
+	GByteArray *content;
+	char *itms_uri;
 	GFile *itms_file, *feed_file;
 	TotemPlParserResult ret;
-	gsize size;
 
 	if (g_file_has_uri_scheme (file, "itms") == FALSE) {
-		/* Get the webpage */
-		if (g_file_load_contents (file, NULL, &contents, &size, NULL, NULL) == FALSE) {
-			DEBUG(file, g_print ("Couldn't load contents for %s\n", uri));
-			return TOTEM_PL_PARSER_RESULT_ERROR;
-		}
-
-		uncompressed = decompress_gzip (contents, size);
-		g_free (contents);
-		if (uncompressed == NULL) {
-			DEBUG(file, g_print ("Couldn't decompress %s\n", uri));
+		content = totem_pl_parser_get_content_decompressed (file);
+		if (content == NULL)
 			return TOTEM_PL_PARSER_RESULT_ERROR;
-		}
 
 		/* Look for the link to the itms on phobos */
-		itms_uri = totem_pl_parser_get_itms_uri (uncompressed);
-		g_free (uncompressed);
+		itms_uri = totem_pl_parser_get_itms_uri ((const char*) content->data, content->len);
+		g_byte_array_free (content, TRUE);
 	} else {
 		itms_uri= g_file_get_uri (file);
 		memcpy (itms_uri, "http", 4);
 	}
 
+	if (itms_uri == NULL)
+		return TOTEM_PL_PARSER_RESULT_ERROR;
+
 	/* Get the phobos linked, in some weird iTunes only format */
 	itms_file = g_file_new_for_uri (itms_uri);
 	g_free (itms_uri);
 
-	if (g_file_load_contents (itms_file, NULL, &contents, &size, NULL, NULL) == FALSE) {
+	content = totem_pl_parser_get_content_decompressed (itms_file);
+	if (content == NULL) {
 		DEBUG(itms_file, g_print ("Couldn't load contents for itms_file %s\n", uri));
 		g_object_unref (itms_file);
 		return TOTEM_PL_PARSER_RESULT_ERROR;
 	}
 	g_object_unref (itms_file);
 
-	uncompressed = decompress_gzip (contents, size);
-	g_free (contents);
-	if (uncompressed == NULL) {
-		DEBUG(itms_file, g_print ("Couldn't decompress itms_file %s\n", uri));
-		return TOTEM_PL_PARSER_RESULT_ERROR;
-	}
-
 	/* And look in the file for the feedURL */
-	feed_file = totem_pl_parser_get_feed_uri (uncompressed, strlen (uncompressed) + 1);
-	if (feed_file == NULL) {
-		g_free (uncompressed);
+	feed_file = totem_pl_parser_get_feed_uri ((char *) content->data, content->len);
+	g_byte_array_free (content, TRUE);
+	if (feed_file == NULL)
 		return TOTEM_PL_PARSER_RESULT_ERROR;
-	}
 
 	DEBUG(feed_file, g_print ("Found feed URI: %s\n", uri));
 
@@ -827,7 +773,7 @@ totem_pl_parser_is_itms_feed (GFile *file)
 
 	if (strstr (uri, "phobos.apple.com/") != NULL
 	    && strstr (uri, "viewPodcast") != NULL) {
-	    	g_free (uri);
+		g_free (uri);
 		return TRUE;
 	}
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]