Exemple #1
0
/**
 * Code from Dom Lachowicz and/or Robert Staudinger.
 */
UT_Error ODi_Abi_Data::_loadStream (GsfInfile* oo,
                                   const char* stream,
                                   UT_ByteBuf& buf ) {
    guint8 const *data = NULL;
    size_t len = 0;
    static const size_t BUF_SZ = 4096;
  
    buf.truncate (0);
    GsfInput * input = gsf_infile_child_by_name(oo, stream);

    if (!input)
        return UT_ERROR;
  
    if (gsf_input_size (input) > 0) {
        while ((len = gsf_input_remaining (input)) > 0) {
            len = UT_MIN (len, BUF_SZ);
            if (NULL == (data = gsf_input_read (input, len, NULL))) {
                g_object_unref (G_OBJECT (input));
                return UT_ERROR;
            }
            buf.append ((const UT_Byte *)data, len);
        }
    }
  
    g_object_unref (G_OBJECT (input));
    return UT_OK;
}
/**
 * Static utility method to read a file/stream embedded inside of the
 * zipfile into an xml parser
 */
UT_Error IE_Imp_OpenDocument::_parseStream (GsfInput* pInput, UT_XML & parser)
{
    guint8 const *data = NULL;
    size_t len = 0;
    UT_Error ret = UT_OK;

	UT_return_val_if_fail(pInput, UT_ERROR);
	
    if (gsf_input_size (pInput) > 0) {
        while ((len = gsf_input_remaining (pInput)) > 0) {
            // FIXME: we want to pass the stream in chunks, but libXML2 finds this disagreeable.
            // we probably need to pass some magic to our XML parser? 
            // len = UT_MIN (len, BUF_SZ);
            if (NULL == (data = gsf_input_read (pInput, len, NULL))) {
                g_object_unref (G_OBJECT (pInput));
                return UT_ERROR;
            }
            ret = parser.parse ((const char *)data, len);
        }
        // if there is an error we think we can recover.
        if(ret != UT_OK) {
            ret = UT_IE_TRY_RECOVER;
        }
    }
  
    return ret;
}
Exemple #3
0
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;
            }
        }
    }

    gsf_output_close(output);
    g_object_unref(G_OBJECT(output));
    g_object_unref(G_OBJECT(input));
}
Exemple #4
0
/**
 * 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;
}
/*!
  Detect encoding of text file
 \param fp File

 Supports UTF-8 and UCS-2 big and little endian
 CJK encodings could be added
 */
UT_Error IE_Imp_Text::_recognizeEncoding(GsfInput * fp)
{
	char szBuf[4096];  // 4096 ought to be enough
	UT_sint32 iNumbytes;

	iNumbytes = UT_MIN(4096, gsf_input_remaining(fp));
	gsf_input_read(fp, iNumbytes, (guint8 *)szBuf);
	gsf_input_seek(fp, 0, G_SEEK_SET);

	return _recognizeEncoding(szBuf, iNumbytes);
}
Exemple #6
0
static void
zip_thumbnail (GsfInfile *infile, const char *out_filename, int thumb_size)
{
	GsfInput *thumbnail;

	/* Office Document thumbnail */
	if (NULL != (thumbnail = gsf_infile_child_by_vname (infile,
			"Thumbnails", "thumbnail.png", NULL))) {
		gsf_off_t len = gsf_input_remaining (thumbnail);
		guint8 const *data = gsf_input_read (thumbnail, len, NULL);
		write_thumbnail (out_filename, data, len, thumb_size);
		g_object_unref (thumbnail);
	/* Check MS Office Open thumbnail */
	} else if (NULL != (thumbnail = gsf_open_pkg_open_rel_by_type (GSF_INPUT(infile),
				"http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail",
																   NULL))) {
		gsf_off_t len = gsf_input_remaining (thumbnail);
		guint8 const *data = gsf_input_read (thumbnail, len, NULL);
		write_thumbnail (out_filename, data, len, thumb_size);
		g_object_unref (thumbnail);
	} else
		show_error_string_and_exit ("Could not find thumbnail in zip file");
}
Exemple #7
0
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));
}
UT_Error OXMLi_PackageManager::_parseStream( GsfInput * stream, OXMLi_StreamListener * pListener)
{
	UT_return_val_if_fail(stream != NULL && pListener != NULL , UT_ERROR);

	//First, we check if this stream has already been parsed before
	std::string part_name = gsf_input_name(stream); //TODO: determine if part names are truly unique
	std::map<std::string, bool>::iterator it;
	it = m_parsedParts.find(part_name);
	if (it != m_parsedParts.end() && it->second) {
		//this stream has already been parsed successfully
		return UT_OK;
	}

	UT_Error ret = UT_OK;
	guint8 const *data = NULL;
	const char * cdata = NULL;
	size_t len = 0;

	UT_XML reader;
	reader.setListener(pListener);

	if (gsf_input_size (stream) > 0) {
		len = gsf_input_remaining (stream);
		if (len > 0) {
			data = gsf_input_read (stream, len, NULL);
			if (NULL == data) {
				g_object_unref (G_OBJECT (stream));
				return UT_ERROR;
			}
			cdata = (const char *)data;
			ret = reader.parse (cdata, len);
		}
	}

	//There are two error codes to check here.  
	if (ret == UT_OK && pListener->getStatus() == UT_OK)
		m_parsedParts[part_name] = true;

	//We prioritize the one from UT_XML when returning.
	return ret == UT_OK ? pListener->getStatus() : ret;
}
Exemple #9
0
static ArStatus
ar_read_header (GsfInput *fp, ArHeader *header)
{
	size_t len;

	if (fp == NULL || header == NULL)
		return AR_FAILURE;

	memset(header, 0, AR_HEADER_LEN);

	len = gsf_input_remaining (fp);
	if (len == 0)
		return AR_EOF;
	else if (len < AR_HEADER_LEN)
		return AR_FAILURE;
	else {
		gsf_input_read (fp, AR_HEADER_LEN, (guint8*)header);
		if (strncmp (header->fmag, AR_FMAG, 2))
			return AR_FAILURE;
		return AR_SUCCESS;
	}
}
Exemple #10
0
static void
clone_ (GsfInfile *in, GsfOutfile *out)
{
	GsfInput *input = GSF_INPUT (in);
	GsfOutput *output = GSF_OUTPUT (out);

	if (gsf_input_size (input) > 0) {
		size_t len;
		while ((len = gsf_input_remaining (input)) > 0) {
			guint8 const *data;
			/* 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 ?");
				break;
			}
			if (!gsf_output_write (output, len, data)) {
				g_warning ("error writing ?");
				break;
			}
		}
	} else {
		int i, n = gsf_infile_num_children (in);
		for (i = 0 ; i < n; i++) {
			int level;
			gboolean is_dir;
			char const *name = gsf_infile_name_by_index (in, i);
			char *display_name = name
				? g_filename_display_name (name)
				: NULL;

			input = gsf_infile_child_by_index (in, i);
			if (NULL == input) {
				g_print ("Error opening '%s, index = %d\n",
					 display_name ? display_name : "?", i);
				g_free (display_name);
				continue;
			}

			is_dir = gsf_infile_num_children (GSF_INFILE (input)) >= 0;

			g_object_get (G_OBJECT (input), "compression-level", &level, NULL);

			g_print ("%s: size=%ld, level=%d, %s\n",
				 display_name ? display_name : "?",
				 (long)gsf_input_size (input),
				 level,
				 is_dir ? "directory" : "file");
			g_free (display_name);

			output = gsf_outfile_new_child_full  (out, name, is_dir,
							      "compression-level", level,
							      NULL);
			clone_ (GSF_INFILE (input), GSF_OUTFILE (output));
		}
	}
	gsf_output_close (GSF_OUTPUT (out));
	g_object_unref (G_OBJECT (out));
	g_object_unref (G_OBJECT (in));
}
/**
 * gsf_input_textline_utf8_gets:
 * @textline: #GsfInputTextline
 *
 * A utility routine to read things line by line from the underlying source.
 * Trailing newlines and carriage returns are stripped, and the resultant buffer
 * can be edited.
 *
 * Returns: (transfer none): the string read, or %NULL on eof.
 **/
guint8 *
gsf_input_textline_utf8_gets (GsfInputTextline *textline)
{
	guint8 const *ptr ,*end;
	unsigned len, count = 0;

	g_return_val_if_fail (textline != NULL, NULL);

	while (1) {
		if (textline->remainder == NULL ||
		    textline->remainder_size == 0) {
			gsf_off_t remain = gsf_input_remaining (textline->source);
			len = MIN (remain, textline->max_line_size);

			textline->remainder = gsf_input_read (textline->source, len, NULL);
			if (textline->remainder == NULL)
				return NULL;
			textline->remainder_size = len;
		}

		ptr = textline->remainder;
		end = ptr + textline->remainder_size;
		for (; ptr < end ; ptr++)
			if (*ptr == '\n' || *ptr == '\r')
				break;

		/* copy the remains into the buffer, grow it if necessary */
		len = ptr - textline->remainder;
		if (count + len >= textline->buf_size) {
			textline->buf_size += len;
			textline->buf = g_renew (guint8, textline->buf,
						 textline->buf_size + 1);
		}

		g_return_val_if_fail (textline->buf != NULL, NULL);

		memcpy (textline->buf + count, textline->remainder, len);
		count += len;

		if (ptr < end) {
			unsigned char last = ptr[0];

			/* eat the trailing eol marker: \n, \r\n, or \r.  */
			ptr++;
			if (ptr >= end && last == '\r') {
				/* be extra careful, the CR is at the bound */
				if (gsf_input_remaining (textline->source) > 0) {
					ptr = gsf_input_read (textline->source, 1, NULL);
					if (ptr == NULL)
						return NULL;
					textline->remainder = ptr;
					textline->remainder_size = 1;
					end = ptr + 1;
				} else
					ptr = end = NULL;
			}
			if (ptr != NULL && last == '\r' && *ptr == '\n')
				ptr++;
			break;
		} else if (gsf_input_remaining (textline->source) <= 0) {
			ptr = end = NULL;
			break;
		} else
			textline->remainder = NULL;

	}

	textline->remainder = ptr;
	textline->remainder_size = end - ptr;

	textline->buf[count] = '\0';
	return textline->buf;
}
Exemple #12
0
static gboolean
csv_tsv_probe (GOFileOpener const *fo, GsfInput *input, GOFileProbeLevel pl)
{
	/* Rough and ready heuristic.  If the first N bytes have no
	 * unprintable characters this may be text */
	const gsf_off_t N = 512;

	if (pl == GO_FILE_PROBE_CONTENT) {
		guint8 const *header;
		gsf_off_t i;
		char const *enc = NULL;
		GString *header_utf8;
		char const *p;
		gboolean ok = TRUE;

		if (gsf_input_seek (input, 0, G_SEEK_SET))
			return FALSE;
		i = gsf_input_remaining (input);

		/* If someone ships us an empty file, accept it only if
		   it has a proper name.  */
		if (i == 0)
			return csv_tsv_probe (fo, input, GO_FILE_PROBE_FILE_NAME);

		if (i > N) i = N;
		if (NULL == (header = gsf_input_read (input, i, NULL)))
			return FALSE;

		enc = go_guess_encoding (header, i, NULL, &header_utf8, NULL);
		if (!enc)
			return FALSE;

		for (p = header_utf8->str; *p; p = g_utf8_next_char (p)) {
			gunichar uc = g_utf8_get_char (p);
			/* isprint might not be true for these: */
			if (uc == '\n' || uc == '\t' || uc == '\r')
				continue;
			/* Also, ignore a byte-order mark which may be used to
			 * indicate UTF-8; see
			 * http://en.wikipedia.org/wiki/Byte_Order_Mark for
			 * background.
			 */
			if (p == header_utf8->str && uc == 0x0000FEFF) {
				continue;
			}
			if (!g_unichar_isprint (uc)) {
				ok = FALSE;
				break;
			}
		}

		g_string_free (header_utf8, TRUE);
		return ok;
	} else {
		char const *name = gsf_input_name (input);
		if (name == NULL)
			return FALSE;
		name = gsf_extension_pointer (name);
		return (name != NULL &&
			(g_ascii_strcasecmp (name, "csv") == 0 ||
			 g_ascii_strcasecmp (name, "tsv") == 0 ||
			 g_ascii_strcasecmp (name, "txt") == 0));
	}
}
Exemple #13
0
static void make_stream (HwpHWP5File *file, GError **error)
{
  GsfInput  *input        = NULL;
  GsfInfile *ole          = GSF_INFILE (file->priv->olefile);
  gint       n_root_entry = gsf_infile_num_children (ole);

  if (n_root_entry < 1)
  {
    g_set_error_literal (error,
                         HWP_FILE_ERROR,
                         HWP_FILE_ERROR_INVALID,
                         "invalid hwp file");
    return;
  }

  /* 우선 순위에 따라 스트림을 만든다 */
  input = gsf_infile_child_by_name (ole, "FileHeader");
  if (input && gsf_infile_num_children (GSF_INFILE (input)) == -1)
  {
    file->file_header_stream = input;
    input = NULL;
    parse_file_header (file);
  }
  else
  {
    goto FAIL;
  }

  input = gsf_infile_child_by_name (ole, "DocInfo");
  if (input && gsf_infile_num_children (GSF_INFILE (input)) == -1)
  {
    if (file->is_compress)
    {
      GInputStream      *gis;
      GZlibDecompressor *zd;
      GInputStream      *cis;

      gis = (GInputStream *) gsf_input_stream_new (input);
      zd  = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_RAW);
      cis = g_converter_input_stream_new (gis, (GConverter *)   zd);
      g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (cis), TRUE);
      file->doc_info_stream = cis;

      g_object_unref (zd);
      g_object_unref (gis);

      input = NULL;
    }
    else
    {
      file->doc_info_stream = (GInputStream *) gsf_input_stream_new (input);
    }
  }
  else
  {
    goto FAIL;
  }

  if (!file->is_distribute)
    input = gsf_infile_child_by_name (ole, "BodyText");
  else
    input = gsf_infile_child_by_name (ole, "ViewText");

  if (input)
  {
    for (gint i = 0; i < gsf_infile_num_children (GSF_INFILE (input)); i++)
    {
      GsfInput *section =
                  gsf_infile_child_by_name (GSF_INFILE (input),
                                            g_strdup_printf("Section%d", i));

      if (gsf_infile_num_children (GSF_INFILE (section)) != -1)
      {
        if (GSF_IS_INPUT (section))
          g_object_unref (section);

        g_set_error_literal (error,
                             HWP_FILE_ERROR,
                             HWP_FILE_ERROR_INVALID,
                             "invalid hwp file");
        return;
      }

      if (file->is_distribute)
      {
        guint8 *data = g_malloc0 (256);
        gsf_input_read (section, 4, NULL);
        gsf_input_read (section, 256, data);
        guint32 seed = GSF_LE_GET_GUINT32 (data);
        msvc_srand (seed);
        gint n = 0, val = 0, offset;

        for (guint i = 0; i < 256; i++)
        {
          if (n == 0)
          {
            val = msvc_rand() & 0xff;
            n = (msvc_rand() & 0xf) + 1;
          }

          data[i] ^= val;

          n--;
        }

        offset = 4 + (seed & 0xf);
        gchar *key = g_malloc0 (16);
        memcpy (key, (const gchar *) data + offset, 16);
#ifdef HWP_ENABLE_DEBUG
        gchar *sha1 = g_convert ((const gchar *) data + offset, 80,
                                 "UTF-8", "UTF-16LE", NULL, NULL, error);
        printf ("sha1: %s\n", sha1);
        printf ("key: %s\n", key);
        g_free (sha1);
#endif
        g_free (data);

        EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new ();
        EVP_CIPHER_CTX_init (ctx);
        EVP_DecryptInit_ex (ctx, EVP_aes_128_ecb(), NULL,
                            (unsigned char *) key, NULL);
        g_free (key);
        EVP_CIPHER_CTX_set_padding(ctx, 0); /* no padding */

        gsf_off_t encrypted_data_len = gsf_input_remaining (section);
        guint8 const *encrypted_data = gsf_input_read (section, encrypted_data_len, NULL);

        guint8 *decrypted_data = g_malloc (encrypted_data_len);
        int decrypted_data_len, len;

        EVP_DecryptUpdate (ctx, decrypted_data, &len, encrypted_data, encrypted_data_len);
        decrypted_data_len = len;

        EVP_DecryptFinal_ex (ctx, decrypted_data + len, &len);
        decrypted_data_len += len;

        EVP_CIPHER_CTX_free (ctx);
        g_object_unref (section);

        section = gsf_input_memory_new (decrypted_data, decrypted_data_len, TRUE);
      }

      if (file->is_compress)
      {
        GInputStream      *gis;
        GZlibDecompressor *zd;
        GInputStream      *cis;

        gis = (GInputStream *) gsf_input_stream_new (section);
        zd  = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_RAW);
        cis = g_converter_input_stream_new (gis, (GConverter *) zd);
        g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (cis), TRUE);
        g_ptr_array_add (file->section_streams, cis);
        g_object_unref (zd);
        g_object_unref (gis);
      }
      else
      {
        GInputStream *stream = (GInputStream *) gsf_input_stream_new (section);
        g_ptr_array_add (file->section_streams, stream);
      }
    } /* for */
    g_object_unref (input);
    input = NULL;
  }
  else
  {
    goto FAIL;
  }

  input = gsf_infile_child_by_name (ole, "\005HwpSummaryInformation");
  if (input && gsf_infile_num_children (GSF_INFILE (input)) == -1)
  {
    file->summary_info_stream = input;
    input = NULL;
  }
  else
  {
    goto FAIL;
  }

  input = gsf_infile_child_by_name (ole, "BinData");

  if (input)
  {
    gint n_data = gsf_infile_num_children (GSF_INFILE (input));

    for (gint i = 0; i < n_data; i++)
    {
      GsfInput *bin_data_input =
                  gsf_infile_child_by_index (GSF_INFILE (input), i);

      if (gsf_infile_num_children (GSF_INFILE (bin_data_input)) != -1)
      {
        if (GSF_IS_INPUT (bin_data_input))
          g_object_unref (bin_data_input);

        g_set_error_literal (error,
                             HWP_FILE_ERROR,
                             HWP_FILE_ERROR_INVALID,
                             "invalid hwp file");
        return;
      }

      if (file->is_compress)
      {
        GInputStream      *gis;
        GZlibDecompressor *zd;
        GInputStream      *cis;

        gis = (GInputStream *) gsf_input_stream_new (bin_data_input);
        zd  = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_RAW);
        cis = g_converter_input_stream_new (gis, (GConverter *) zd);
        g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (cis), TRUE);
        g_ptr_array_add (file->bin_data_streams, cis);
        g_object_unref (zd);
        g_object_unref (gis);
      }
      else
      {
        GInputStream *stream = (GInputStream *) gsf_input_stream_new (bin_data_input);
        g_ptr_array_add (file->bin_data_streams, stream);
      }
    }

    g_object_unref (input);
    input = NULL;
  }

  input = gsf_infile_child_by_name (ole, "PrvText");
  if (input && gsf_infile_num_children (GSF_INFILE (input)) == -1)
  {
    file->prv_text_stream = input;
    input = NULL;
  }
  else
  {
    goto FAIL;
  }

  input = gsf_infile_child_by_name (ole, "PrvImage");
  if (input && gsf_infile_num_children (GSF_INFILE (input)) == -1)
  {
    file->prv_image_stream = input;
    input = NULL;
  }
  else
  {
    goto FAIL;
  }

  return;

  FAIL:

  if (GSF_IS_INPUT (input))
    g_object_unref (input);

  g_set_error_literal (error,
                       HWP_FILE_ERROR,
                       HWP_FILE_ERROR_INVALID,
                       "invalid hwp file");
  return;
}
Exemple #14
0
static gboolean
check_header (GsfInputGZip *input)
{
	if (input->raw) {
		input->header_size = 0;
		input->trailer_size = 0;
	} else {
		static guint8 const signature[2] = {0x1f, 0x8b};
		guint8 const *data;
		unsigned flags, len;

		/* Check signature */
		if (NULL == (data = gsf_input_read (input->source, 2 + 1 + 1 + 6, NULL)) ||
		    0 != memcmp (data, signature, sizeof (signature)))
			return TRUE;

		/* verify flags and compression type */
		flags  = data[3];
		if (data[2] != Z_DEFLATED || (flags & ~GZIP_HEADER_FLAGS) != 0)
			return TRUE;

		/* If we have the size, don't bother seeking to the end.  */
		if (input->uncompressed_size < 0) {
			/* Get the uncompressed size */
			if (gsf_input_seek (input->source, (gsf_off_t) -4, G_SEEK_END) ||
			    NULL == (data = gsf_input_read (input->source, 4, NULL)))
				return TRUE;
			/* FIXME, but how?  The size read here is modulo 2^32.  */
			input->uncompressed_size = GSF_LE_GET_GUINT32 (data);

			if (input->uncompressed_size / 1000 > gsf_input_size (input->source)) {
				g_warning ("Suspiciously well compressed file with better than 1000:1 ratio.\n"
					   "It is probably truncated or corrupt");
			}
		}

		if (gsf_input_seek (input->source, 2 + 1 + 1 + 6, G_SEEK_SET))
			return TRUE;

		if (flags & GZIP_EXTRA_FIELD) {
			if (NULL == (data = gsf_input_read (input->source, 2, NULL)))
				return TRUE;
			len = GSF_LE_GET_GUINT16 (data);
			if (NULL == gsf_input_read (input->source, len, NULL))
				return TRUE;
		}
		if (flags & GZIP_ORIGINAL_NAME) {
			/* Skip over the filename (which is in ISO 8859-1 encoding).  */
			do {
				if (NULL == (data = gsf_input_read (input->source, 1, NULL)))
					return TRUE;
			} while (*data != 0);
		}

		if (flags & GZIP_HAS_COMMENT) {
			/* Skip over the comment (which is in ISO 8859-1 encoding).  */
			do {
				if (NULL == (data = gsf_input_read (input->source, 1, NULL)))
					return TRUE;
			} while (*data != 0);
		}

		if (flags & GZIP_HEADER_CRC &&
		    NULL == (data = gsf_input_read (input->source, 2, NULL)))
			return TRUE;

		input->header_size = input->source->cur_offset;
		/* the last 8 bytes are the crc and size.  */
		input->trailer_size = 8;
	}

	gsf_input_set_size (GSF_INPUT (input), input->uncompressed_size);

	if (gsf_input_remaining (input->source) < input->trailer_size)
		return TRUE;	/* No room for payload */

	return FALSE;
}
Exemple #15
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;
}