Ejemplo n.º 1
0
/**
 * hwp_hwp3_parser_parse:
 * @parser: a #HwpHWP3Parser
 * @file: a #HwpHWP3File
 * @error: a #GError
 *
 * Since: 0.0.1
 */
void hwp_hwp3_parser_parse (HwpHWP3Parser *parser,
                            HwpHWP3File   *file,
                            GError       **error)
{
  g_return_if_fail (HWP_IS_HWP3_FILE (file));

  parser->stream = file->priv->stream;

  _hwp_hwp3_parser_parse_signature (parser, file, error);
  _hwp_hwp3_parser_parse_doc_info (parser, file, error);
  _hwp_hwp3_parser_parse_summary_info (parser, file, error);
  _hwp_hwp3_parser_parse_info_block (parser, file, error);

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

    zd  = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_RAW);
    cis = g_converter_input_stream_new (file->priv->stream, G_CONVERTER (zd));
    g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (cis),
                                                 TRUE);
    g_object_unref (file->priv->stream);
    file->priv->stream = g_object_ref (cis);
    g_object_unref (zd);
  }

  parser->stream = file->priv->stream;

  _hwp_hwp3_parser_parse_font_names (parser, file, error);
  _hwp_hwp3_parser_parse_styles (parser, file, error);
  _hwp_hwp3_parser_parse_paragraphs (parser, file, error);
  _hwp_hwp3_parser_parse_supplementary_info_block1 (parser, file, error);
  _hwp_hwp3_parser_parse_supplementary_info_block2 (parser, file, error);
}
Ejemplo n.º 2
0
int
main (int argc, char **argv)
{
    GConverter *converter;
    GFile *file;
    GFileInputStream *file_stream;
    GInputStream *stream;
    gchar buf[1024];
    gssize bytes;
        
    if (argc < 2) {
        g_printerr ("Usage: test-bz2 FILE\n");
        return 1;
    }

    file = g_file_new_for_path (argv[1]);
    file_stream = g_file_read (file, NULL, NULL);
    converter = G_CONVERTER (yelp_bz2_decompressor_new ());
    stream = g_converter_input_stream_new (G_INPUT_STREAM (file_stream),
                                           converter);

    while ((bytes = g_input_stream_read (stream, buf, 1024, NULL, NULL)) > 0) {
        gchar *out = g_strndup (buf, bytes);
        puts (out);
        g_free (out);
    }

    return 0;
}
static gboolean
decompress_all (GConverter   *converter,
                GBytes       *data,
                GBytes      **out_uncompressed,
                GCancellable *cancellable,
                GError      **error)
{
  gboolean ret = FALSE;
  g_autoptr(GMemoryInputStream) memin = (GMemoryInputStream*)g_memory_input_stream_new_from_bytes (data);
  g_autoptr(GMemoryOutputStream) memout = (GMemoryOutputStream*)g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
  g_autoptr(GInputStream) convin = g_converter_input_stream_new ((GInputStream*)memin, converter);

  {
    gssize n_bytes_written = g_output_stream_splice ((GOutputStream*)memout, convin,
                                                     G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
                                                     G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
                                                     cancellable, error);
      if (n_bytes_written < 0)
        goto out;
  }

  ret = TRUE;
  *out_uncompressed = g_memory_output_stream_steal_as_bytes (memout);
 out:
  return ret;
}
Ejemplo n.º 4
0
/**
 * g_resource_open_stream:
 * @resource: A #GResource
 * @path: A pathname inside the resource
 * @lookup_flags: A #GResourceLookupFlags
 * @error: return location for a #GError, or %NULL
 *
 * Looks for a file at the specified @path in the resource and
 * returns a #GInputStream that lets you read the data.
 *
 * @lookup_flags controls the behaviour of the lookup.
 *
 * Returns: (transfer full): #GInputStream or %NULL on error.
 *     Free the returned object with g_object_unref()
 *
 * Since: 2.32
 **/
GInputStream *
g_resource_open_stream (GResource             *resource,
                        const gchar           *path,
                        GResourceLookupFlags   lookup_flags,
                        GError               **error)
{
  const void *data;
  gsize data_size;
  guint32 flags;
  GInputStream *stream, *stream2;

  if (!do_lookup (resource, path, lookup_flags, NULL, &flags, &data, &data_size, error))
    return NULL;

  stream = g_memory_input_stream_new_from_data (data, data_size, NULL);
  g_object_set_data_full (G_OBJECT (stream), "g-resource",
                          g_resource_ref (resource),
                          (GDestroyNotify)g_resource_unref);

  if (flags & G_RESOURCE_FLAGS_COMPRESSED)
    {
      GZlibDecompressor *decompressor =
        g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_ZLIB);

      stream2 = g_converter_input_stream_new (stream, G_CONVERTER (decompressor));
      g_object_unref (decompressor);
      g_object_unref (stream);
      stream = stream2;
    }

  return stream;
}
Ejemplo n.º 5
0
static VALUE
rg_initialize(VALUE self, VALUE base_stream, VALUE converter)
{
        G_INITIALIZE(self,
                     g_converter_input_stream_new(RVAL2GINPUTSTREAM(base_stream),
                                                  RVAL2GCONVERTER(converter)));

        return Qnil;
}
Ejemplo n.º 6
0
static int
compress_blob_to_tmp (GInputStream *file_stream)
{
  char tmpl[] = "/tmp/shardXXXXXX";
  int fd = mkstemp (tmpl);
  unlink (tmpl);

  /* Compress the given GInputStream to the tmpfile. */

  g_autoptr(GZlibCompressor) compressor = g_zlib_compressor_new (G_ZLIB_COMPRESSOR_FORMAT_ZLIB, -1);
  g_autoptr(GInputStream) stream = g_converter_input_stream_new (G_INPUT_STREAM (file_stream), G_CONVERTER (compressor));

  uint8_t buf[4096*4];
  int size;
  while ((size = g_input_stream_read (stream, buf, sizeof (buf), NULL, NULL)) != 0) {
    g_assert (write (fd, buf, size) >= 0);
  }

  return fd;
}
Ejemplo n.º 7
0
static void _ghwp_file_v3_parse_info_block (GHWPDocument *doc)
{
    g_return_if_fail (doc != NULL);
    GInputStream *stream = GHWP_FILE_V3 (doc->file)->priv->stream;
    g_input_stream_skip (stream, GHWP_FILE_V3 (doc->file)->info_block_len, NULL, NULL);

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

        zd  = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_RAW);
        cis = g_converter_input_stream_new ((GInputStream*) stream,
                                            (GConverter*) zd);
        g_object_unref (GHWP_FILE_V3 (doc->file)->priv->stream);
        g_object_ref (cis);
        /* NOTE 기존의 스트림은 어떻게 ? */
        GHWP_FILE_V3 (doc->file)->priv->stream = G_INPUT_STREAM (cis);

        g_object_unref (zd);
    }
}
Ejemplo n.º 8
0
static void
write_blob (int fd, struct eos_shard_writer_v1_blob_entry *blob)
{
  g_autoptr(GError) error = NULL;

  if (!blob->file)
    return;

  GFileInputStream *file_stream = g_file_read (blob->file, NULL, &error);
  if (!file_stream) {
    g_error ("Could not read from %s: %s", g_file_get_path (blob->file), error->message);
    return;
  }

  g_autoptr(GInputStream) stream;

  if (blob->flags & EOS_SHARD_BLOB_FLAG_COMPRESSED_ZLIB) {
    g_autoptr(GZlibCompressor) compressor = g_zlib_compressor_new (G_ZLIB_COMPRESSOR_FORMAT_ZLIB, -1);
    stream = g_converter_input_stream_new (G_INPUT_STREAM (file_stream), G_CONVERTER (compressor));
    g_object_unref (file_stream);
  } else {
    stream = G_INPUT_STREAM (file_stream);
  }

  blob->offs = lalign (fd);

  uint8_t buf[4096*4];
  int size, total_size = 0;
  g_autoptr(GChecksum) checksum = g_checksum_new (G_CHECKSUM_SHA256);
  while ((size = g_input_stream_read (stream, buf, sizeof (buf), NULL, NULL)) != 0) {
    g_assert (write (fd, buf, size) >= 0);
    g_checksum_update (checksum, buf, size);
    total_size += size;
  }
  size_t checksum_buf_len = sizeof (blob->checksum);
  g_checksum_get_digest (checksum, blob->checksum, &checksum_buf_len);
  g_assert (checksum_buf_len == sizeof (blob->checksum));

  blob->size = total_size;
}
Ejemplo n.º 9
0
/**
 * as_get_yml_data_origin:
 *
 * Extract the data origin from the AppStream YAML file.
 * We don't use the #AsYAMLData loader, because it is much
 * slower than just loading the initial parts of the file and
 * extracting the origin manually.
 */
static gchar*
as_get_yml_data_origin (const gchar *fname)
{
	const gchar *data;
	GZlibDecompressor *zdecomp;
	g_autoptr(GFileInputStream) fistream = NULL;
	g_autoptr(GMemoryOutputStream) mem_os = NULL;
	g_autoptr(GInputStream) conv_stream = NULL;
	g_autoptr(GFile) file = NULL;
	g_autofree gchar *str = NULL;
	g_auto(GStrv) strv = NULL;
	GError *err;
	guint i;
	gchar *start, *end;
	gchar *origin = NULL;

	file = g_file_new_for_path (fname);
	fistream = g_file_read (file, NULL, &err);

	if (!fistream) {
		g_critical ("Unable to open file '%s' for reading: %s, skipping.", fname, err->message);
		g_error_free (err);
		return NULL;
	}

	mem_os = (GMemoryOutputStream*) g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
	zdecomp = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
	conv_stream = g_converter_input_stream_new (G_INPUT_STREAM (fistream), G_CONVERTER (zdecomp));
	g_object_unref (zdecomp);

	g_output_stream_splice (G_OUTPUT_STREAM (mem_os), conv_stream, 0, NULL, NULL);
	data = (const gchar*) g_memory_output_stream_get_data (mem_os);

	/* faster than a regular expression?
	 * Get the first YAML document, then extract the origin string.
	 */
	if (data == NULL)
		return NULL;
	/* start points to the start of the document, i.e. "File:" normally */
	start = g_strstr_len (data, 400, YAML_SEPARATOR) + YAML_SEPARATOR_LEN;
	if (start == NULL)
		return NULL;
	/* Find the end of the first document - can be NULL if there is only one,
	 * for example if we're given YAML for an empty archive */
	end = g_strstr_len (start, -1, YAML_SEPARATOR);
	str = g_strndup (start, strlen(start) - (end ? strlen(end) : 0));

	strv = g_strsplit (str, "\n", -1);
	for (i = 0; strv[i] != NULL; i++) {
		g_auto(GStrv) strv2 = NULL;
		if (!g_str_has_prefix (strv[i], "Origin:"))
			continue;

		strv2 = g_strsplit (strv[i], ":", 2);
		g_strstrip (strv2[1]);
		origin = g_strdup (strv2[1]);

		/* remove quotes, in case the string is quoted */
		if ((g_str_has_prefix (origin, "\"")) && (g_str_has_suffix (origin, "\""))) {
			g_autofree gchar *tmp = NULL;

			tmp = origin;
			origin = g_strndup (tmp + 1, strlen (tmp) - 2);
		}

		break;
	}

	return origin;
}
Ejemplo n.º 10
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;
}
Ejemplo n.º 11
0
/**
 * as_node_from_file: (skip)
 * @file: file
 * @flags: #AsNodeFromXmlFlags, e.g. %AS_NODE_FROM_XML_FLAG_NONE
 * @cancellable: A #GCancellable, or %NULL
 * @error: A #GError or %NULL
 *
 * Parses an XML file into a DOM tree.
 *
 * Returns: (transfer none): A populated #AsNode tree
 *
 * Since: 0.1.0
 **/
AsNode *
as_node_from_file (GFile *file,
		   AsNodeFromXmlFlags flags,
		   GCancellable *cancellable,
		   GError **error)
{
	AsNodeToXmlHelper helper;
	GError *error_local = NULL;
	AsNode *root = NULL;
	const gchar *content_type = NULL;
	gboolean ret = TRUE;
	gsize chunk_size = 32 * 1024;
	gssize len;
	g_autofree gchar *data = NULL;
	g_autoptr(GMarkupParseContext) ctx = NULL;
	g_autoptr(GConverter) conv = NULL;
	g_autoptr(GFileInfo) info = NULL;
	g_autoptr(GInputStream) file_stream = NULL;
	g_autoptr(GInputStream) stream_data = NULL;
	const GMarkupParser parser = {
		as_node_start_element_cb,
		as_node_end_element_cb,
		as_node_text_cb,
		as_node_passthrough_cb,
		NULL };

	/* what kind of file is this */
	info = g_file_query_info (file,
				  G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
				  G_FILE_QUERY_INFO_NONE,
				  cancellable,
				  error);
	if (info == NULL)
		return NULL;

	/* decompress if required */
	file_stream = G_INPUT_STREAM (g_file_read (file, cancellable, error));
	if (file_stream == NULL)
		return NULL;
	content_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
	if (g_strcmp0 (content_type, "application/gzip") == 0 ||
	    g_strcmp0 (content_type, "application/x-gzip") == 0) {
		conv = G_CONVERTER (g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP));
		stream_data = g_converter_input_stream_new (file_stream, conv);
	} else if (g_strcmp0 (content_type, "application/xml") == 0) {
		stream_data = g_object_ref (file_stream);
	} else {
		g_set_error (error,
			     AS_NODE_ERROR,
			     AS_NODE_ERROR_FAILED,
			     "cannot process file of type %s",
			     content_type);
		return NULL;
	}

	/* parse */
	root = as_node_new ();
	helper.flags = flags;
	helper.current = root;
	ctx = g_markup_parse_context_new (&parser,
					  G_MARKUP_PREFIX_ERROR_POSITION,
					  &helper,
					  NULL);

	data = g_malloc (chunk_size);
	while ((len = g_input_stream_read (stream_data,
					   data,
					   chunk_size,
					   cancellable,
					   error)) > 0) {
		ret = g_markup_parse_context_parse (ctx,
						    data,
						    len,
						    &error_local);
		if (!ret) {
			g_set_error_literal (error,
					     AS_NODE_ERROR,
					     AS_NODE_ERROR_FAILED,
					     error_local->message);
			g_error_free (error_local);
			as_node_unref (root);
			return NULL;
		}
	}
	if (len < 0) {
		as_node_unref (root);
		return NULL;
	}

	/* more opening than closing */
	if (root != helper.current) {
		g_set_error_literal (error,
				     AS_NODE_ERROR,
				     AS_NODE_ERROR_FAILED,
				     "Mismatched XML");
		as_node_unref (root);
		return NULL;
	}
	return root;
}
Ejemplo n.º 12
0
/**
 * as_validator_validate_file:
 * @validator: An instance of #AsValidator.
 * @metadata_file: An AppStream XML file.
 *
 * Validate an AppStream XML file
 **/
gboolean
as_validator_validate_file (AsValidator *validator, GFile *metadata_file)
{
	g_autoptr(GFileInfo) info = NULL;
	g_autoptr(GInputStream) file_stream = NULL;
	g_autoptr(GInputStream) stream_data = NULL;
	g_autoptr(GConverter) conv = NULL;
	g_autoptr(GString) asxmldata = NULL;
	g_autofree gchar *fname = NULL;
	gssize len;
	const gsize buffer_size = 1024 * 32;
	g_autofree gchar *buffer = NULL;
	const gchar *content_type = NULL;
	g_autoptr(GError) tmp_error = NULL;
	gboolean ret;

	info = g_file_query_info (metadata_file,
				G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
				G_FILE_QUERY_INFO_NONE,
				NULL, NULL);
	if (info != NULL)
		content_type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);

	fname = g_file_get_basename (metadata_file);
	as_validator_set_current_fname (validator, fname);

	file_stream = G_INPUT_STREAM (g_file_read (metadata_file, NULL, &tmp_error));
	if (tmp_error != NULL) {
		as_validator_add_issue (validator, NULL,
					AS_ISSUE_IMPORTANCE_ERROR,
					AS_ISSUE_KIND_READ_ERROR,
					"Unable to read file: %s", tmp_error->message);
		return FALSE;
	}
	if (file_stream == NULL)
		return FALSE;

	if ((g_strcmp0 (content_type, "application/gzip") == 0) || (g_strcmp0 (content_type, "application/x-gzip") == 0)) {
		/* decompress the GZip stream */
		conv = G_CONVERTER (g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP));
		stream_data = g_converter_input_stream_new (file_stream, conv);
	} else {
		stream_data = g_object_ref (file_stream);
	}

	asxmldata = g_string_new ("");
	buffer = g_malloc (buffer_size);
	while ((len = g_input_stream_read (stream_data, buffer, buffer_size, NULL, &tmp_error)) > 0) {
		g_string_append_len (asxmldata, buffer, len);
	}
	if (tmp_error != NULL) {
		as_validator_add_issue (validator, NULL,
					AS_ISSUE_IMPORTANCE_ERROR,
					AS_ISSUE_KIND_READ_ERROR,
					"Unable to read file: %s", tmp_error->message);
		return FALSE;
	}
	/* check if there was an error */
	if (len < 0)
		return FALSE;

	ret = as_validator_validate_data (validator, asxmldata->str);
	as_validator_clear_current_fname (validator);

	return ret;
}
gboolean
_ostree_static_delta_part_open (GInputStream   *part_in,
                                GBytes         *inline_part_bytes,
                                OstreeStaticDeltaOpenFlags flags,
                                const char     *expected_checksum,
                                GVariant    **out_part,
                                GCancellable *cancellable,
                                GError      **error)
{
  gboolean ret = FALSE;
  const gboolean trusted = (flags & OSTREE_STATIC_DELTA_OPEN_FLAGS_VARIANT_TRUSTED) > 0;
  const gboolean skip_checksum = (flags & OSTREE_STATIC_DELTA_OPEN_FLAGS_SKIP_CHECKSUM) > 0;
  gsize bytes_read;
  guint8 comptype;
  g_autoptr(GChecksum) checksum = NULL;
  g_autoptr(GInputStream) checksum_in = NULL;
  g_autoptr(GVariant) ret_part = NULL;
  GInputStream *source_in;

  /* We either take a fd or a GBytes reference */
  g_return_val_if_fail (G_IS_FILE_DESCRIPTOR_BASED (part_in) || inline_part_bytes != NULL, FALSE);
  g_return_val_if_fail (skip_checksum || expected_checksum != NULL, FALSE);

  if (!skip_checksum)
    {
      checksum = g_checksum_new (G_CHECKSUM_SHA256);
      checksum_in = (GInputStream*)ostree_checksum_input_stream_new (part_in, checksum);
      source_in = checksum_in;
    }
  else
    {
      source_in = part_in;
    }

  { guint8 buf[1];
    /* First byte is compression type */
    if (!g_input_stream_read_all (source_in, buf, sizeof(buf), &bytes_read,
                                  cancellable, error))
      {
        g_prefix_error (error, "Reading initial compression flag byte: ");
      goto out;
      }
    comptype = buf[0];
  }

  switch (comptype)
    {
    case 0:
      if (!inline_part_bytes)
        {
          int part_fd = g_file_descriptor_based_get_fd ((GFileDescriptorBased*)part_in);

          /* No compression, no checksums - a fast path */
          if (!ot_util_variant_map_fd (part_fd, 1, G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
                                       trusted, &ret_part, error))
            goto out;
        }
      else
        {
          g_autoptr(GBytes) content_bytes = g_bytes_new_from_bytes (inline_part_bytes, 1,
                                                                    g_bytes_get_size (inline_part_bytes) - 1);
          ret_part = g_variant_new_from_bytes (G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
                                               content_bytes, trusted);
          g_variant_ref_sink (ret_part);
        }

      if (!skip_checksum)
        g_checksum_update (checksum, g_variant_get_data (ret_part),
                           g_variant_get_size (ret_part));
      
      break;
    case 'x':
      {
        g_autofree char *tmppath = g_strdup ("/var/tmp/ostree-delta-XXXXXX");
        g_autoptr(GConverter) decomp = (GConverter*) _ostree_lzma_decompressor_new ();
        g_autoptr(GInputStream) convin = g_converter_input_stream_new (source_in, decomp);
        g_autoptr(GOutputStream) unpacked_out = NULL;
        glnx_fd_close int unpacked_fd = -1;
        gssize n_bytes_written;

        unpacked_fd = g_mkstemp_full (tmppath, O_RDWR | O_CLOEXEC, 0640);
        if (unpacked_fd < 0)
          {
            glnx_set_error_from_errno (error);
            goto out;
          }
        
        /* Now make it autocleanup on process exit - in the future, we
         * should consider caching unpacked deltas as well.
         */
        if (unlink (tmppath) < 0)
          {
            glnx_set_error_from_errno (error);
            goto out;
          }
        
        unpacked_out = g_unix_output_stream_new (unpacked_fd, FALSE);

        n_bytes_written = g_output_stream_splice (unpacked_out, convin,
                                                  G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
                                                  G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
                                                  cancellable, error);
        if (n_bytes_written < 0)
          goto out;

        if (!ot_util_variant_map_fd (unpacked_fd, 0, G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
                                     trusted, &ret_part, error))
          goto out;
      }
      break;
    default:
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Invalid compression type '%u'", comptype);
      goto out;
    }

  if (checksum)
    {
      const char *actual_checksum = g_checksum_get_string (checksum);
      g_assert (expected_checksum != NULL);
      if (strcmp (actual_checksum, expected_checksum) != 0)
        {
          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "Checksum mismatch in static delta part; expected=%s actual=%s",
                       expected_checksum, actual_checksum);
          goto out;
        }
    }
        
  ret = TRUE;
  *out_part = g_steal_pointer (&ret_part);
 out:
  return ret;
}
Ejemplo n.º 14
0
static void
render_card_init (char *card_fname)
{
	int i;
	if (render_init) {
		for (i = 0; i < 52; i++)
			g_object_unref (card_pixbuf[i]);
		cairo_surface_destroy (grey_surface);
		render_init = 0;
	}

	/* gdk_pixbuf_new_from_file doesn't seem to support .svgz (while
	 * librsvg does), so decompress it here. Code from aisleriot
	 * src/lib/ar-svg.c */
	GFile *cf = g_file_new_for_path (card_fname);
	GFileInfo *info;
	GError *error = NULL;
	if (!(info = g_file_query_info (cf,
					G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE,
					G_FILE_QUERY_INFO_NONE,
					NULL,
					&error))) {
		printf ("%s: %s\n", card_fname, error->message);
		g_object_unref (cf);
		g_error_free (error);
		return;
	}

	const char *type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
	char *gz_type = g_content_type_from_mime_type ("application/x-gzip");
	gboolean is_gzip = (type != NULL && g_content_type_is_a (type, gz_type));
	g_free (gz_type);
	g_object_unref (info);

	GInputStream *stream;
	if (!(stream = G_INPUT_STREAM (g_file_read (cf, NULL, &error)))) {
		printf ("%s: %s\n", card_fname, error->message);
		g_object_unref (cf);
		g_error_free (error);
		return;
	}
	g_object_unref (cf);

	if (is_gzip) {
		GZlibDecompressor *decompressor;
		GInputStream *converter_stream;

		decompressor = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
		converter_stream = g_converter_input_stream_new (stream,
				G_CONVERTER (decompressor));
		g_object_unref (stream);
		stream = converter_stream;
	}

	/* file contains cards in 13 columns (A/2..10/J/Q/K) and 5 rows (C/D/H/S/Jokers) */
	/* actual card height is computed from resulting actual size */
	GdkPixbuf *pb = gdk_pixbuf_new_from_stream_at_scale (stream,
			card_width * 13, -1, TRUE, NULL, &error);
	g_object_unref (stream);
	if (!pb) {
		printf ("%s: %s.\n", card_fname, error->message);
		g_error_free (error);
		return;
	}
	int buf_width = gdk_pixbuf_get_width (pb);
	int buf_height = gdk_pixbuf_get_height (pb);
	card_width = ceil (gdk_pixbuf_get_width (pb) / 13.0);
	card_height = ceil (gdk_pixbuf_get_height (pb) / 5.0);
	for (i = 0; i < 52; i++) {
		card_pixbuf[i] = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, card_width, card_height);
		if (!card_pixbuf[i]) {
			printf ("%s: rendering card_pixbuf failed\n", card_fname);
			return;
		}
		int col = (i + 1) % 13;
		int row = i / 13;
		gdk_pixbuf_copy_area (pb, buf_width * col / 13.0, buf_height * row / 5.0,
		//gdk_pixbuf_copy_area (pb, card_width * col, card_height * row,
			card_width, card_height, card_pixbuf[i], 0, 0);
	}
	g_object_unref (pb);

	/* construct a alpha channel in card shape for greying out cards */
	grey_surface = cairo_image_surface_create (CAIRO_FORMAT_A8, card_width, card_height);
	cairo_t *ct = cairo_create (grey_surface);
	gdk_cairo_set_source_pixbuf (ct, card_pixbuf[0], 0, 0);
	cairo_paint_with_alpha (ct, 0.3);
	cairo_destroy (ct);

	render_init = 1;
}
Ejemplo n.º 15
0
gboolean
_ostree_static_delta_part_open (GInputStream   *part_in,
                                GBytes         *inline_part_bytes,
                                OstreeStaticDeltaOpenFlags flags,
                                const char     *expected_checksum,
                                GVariant    **out_part,
                                GCancellable *cancellable,
                                GError      **error)
{
  const gboolean trusted = (flags & OSTREE_STATIC_DELTA_OPEN_FLAGS_VARIANT_TRUSTED) > 0;
  const gboolean skip_checksum = (flags & OSTREE_STATIC_DELTA_OPEN_FLAGS_SKIP_CHECKSUM) > 0;
  gsize bytes_read;
  guint8 comptype;
  g_autoptr(GChecksum) checksum = NULL;
  g_autoptr(GInputStream) checksum_in = NULL;
  GInputStream *source_in;

  /* We either take a fd or a GBytes reference */
  g_return_val_if_fail (G_IS_FILE_DESCRIPTOR_BASED (part_in) || inline_part_bytes != NULL, FALSE);
  g_return_val_if_fail (skip_checksum || expected_checksum != NULL, FALSE);

  if (!skip_checksum)
    {
      checksum = g_checksum_new (G_CHECKSUM_SHA256);
      checksum_in = (GInputStream*)ostree_checksum_input_stream_new (part_in, checksum);
      source_in = checksum_in;
    }
  else
    {
      source_in = part_in;
    }

  { guint8 buf[1];
    /* First byte is compression type */
    if (!g_input_stream_read_all (source_in, buf, sizeof(buf), &bytes_read,
                                  cancellable, error))
      return glnx_prefix_error (error, "Reading initial compression flag byte");
    comptype = buf[0];
  }

  g_autoptr(GVariant) ret_part = NULL;
  switch (comptype)
    {
    case 0:
      if (!inline_part_bytes)
        {
          int part_fd = g_file_descriptor_based_get_fd ((GFileDescriptorBased*)part_in);

          /* No compression, no checksums - a fast path */
          if (!ot_util_variant_map_fd (part_fd, 1, G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
                                       trusted, &ret_part, error))
            return FALSE;
        }
      else
        {
          g_autoptr(GBytes) content_bytes = g_bytes_new_from_bytes (inline_part_bytes, 1,
                                                                    g_bytes_get_size (inline_part_bytes) - 1);
          ret_part = g_variant_new_from_bytes (G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
                                               content_bytes, trusted);
          g_variant_ref_sink (ret_part);
        }

      if (!skip_checksum)
        g_checksum_update (checksum, g_variant_get_data (ret_part),
                           g_variant_get_size (ret_part));

      break;
    case 'x':
      {
        g_autoptr(GConverter) decomp = (GConverter*) _ostree_lzma_decompressor_new ();
        g_autoptr(GInputStream) convin = g_converter_input_stream_new (source_in, decomp);
        g_autoptr(GBytes) buf = ot_map_anonymous_tmpfile_from_content (convin, cancellable, error);
        if (!buf)
          return FALSE;

        ret_part = g_variant_new_from_bytes (G_VARIANT_TYPE (OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0),
                                             buf, FALSE);
      }
      break;
    default:
      return glnx_throw (error, "Invalid compression type '%u'", comptype);
    }

  if (checksum)
    {
      const char *actual_checksum = g_checksum_get_string (checksum);
      g_assert (expected_checksum != NULL);
      if (strcmp (actual_checksum, expected_checksum) != 0)
        return glnx_throw (error, "Checksum mismatch in static delta part; expected=%s actual=%s",
                           expected_checksum, actual_checksum);
    }

  *out_part = g_steal_pointer (&ret_part);
  return TRUE;
}
Ejemplo n.º 16
0
static void
decompress_db (GFile *db, const char *path)
{
        GFile *db_decomp;
        GFile *db_decomp_tmp;
        GError *error = NULL;
        GZlibDecompressor *conv;
        GInputStream *instream;
        GInputStream *instream_conv;
        GOutputStream *outstream;
        char *tmp_db_path;

        instream = (GInputStream *) g_file_read (db, NULL, &error);
        if (!instream) {
                g_print ("Error opening file: %s", error->message);
                g_error_free (error);
                return;
        }

        conv = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
        instream_conv = (GInputStream *) g_converter_input_stream_new (instream, G_CONVERTER (conv));
        g_object_unref (instream);

        tmp_db_path = g_strdup_printf ("%s.%s", path, "tmp");
        db_decomp_tmp =  g_file_new_for_path (tmp_db_path);
        g_free (tmp_db_path);
        outstream = (GOutputStream *) g_file_replace (db_decomp_tmp,
                                                      NULL,
                                                      FALSE,
                                                      G_FILE_CREATE_NONE,
                                                      NULL,
                                                      &error);
        if (!outstream) {
                g_print ("Error creating file: %s\n", error->message);
                g_error_free (error);
                goto end;
        }

        if (g_output_stream_splice (outstream,
                                    instream_conv,
                                    0,
                                    NULL,
                                    &error) == -1) {
                g_print ("Error decompressing the database: %s\n", error->message);
                g_object_unref (outstream);
                g_error_free (error);
                goto end;
        }

        if (g_output_stream_close (outstream,
                                   NULL,
                                   &error) == FALSE) {
                g_print ("Error decompressing the database: %s\n", error->message);
                g_error_free (error);
        } else {
                db_decomp = g_file_new_for_path (path);
                if (g_file_move (db_decomp_tmp,
                                 db_decomp,
                                 G_FILE_COPY_OVERWRITE,
                                 NULL,
                                 NULL,
                                 NULL,
                                 &error) == FALSE) {
                        g_print ("Error moving the temporary database file to the" \
                                 " original database file: %s\n", error->message);
                        g_error_free (error);
                } else {
                        g_print ("Database updated\n");
                }

                g_object_unref (db_decomp);
        }
        g_object_unref (outstream);

end:
        g_object_unref (db_decomp_tmp);
        g_object_unref (conv);
        g_object_unref (instream_conv);
}
Ejemplo n.º 17
0
/**
 * gs_plugin_file_to_app:
 */
gboolean
gs_plugin_file_to_app (GsPlugin *plugin,
		       GList **list,
		       GFile *file,
		       GCancellable *cancellable,
		       GError **error)
{
	g_autofree gchar *content_type = NULL;
	g_autofree gchar *id_prefixed = NULL;
	g_autoptr(GBytes) appstream_gz = NULL;
	g_autoptr(GBytes) icon_data = NULL;
	g_autoptr(GBytes) metadata = NULL;
	g_autoptr(GsApp) app = NULL;
	g_autoptr(XdgAppBundleRef) xref_bundle = NULL;
	const gchar *mimetypes[] = {
		"application/vnd.xdgapp",
		NULL };

	/* does this match any of the mimetypes we support */
	content_type = gs_utils_get_content_type (file, cancellable, error);
	if (content_type == NULL)
		return FALSE;
	if (!g_strv_contains (mimetypes, content_type))
		return TRUE;

	/* load bundle */
	xref_bundle = xdg_app_bundle_ref_new (file, error);
	if (xref_bundle == NULL) {
		g_prefix_error (error, "error loading bundle: ");
		return FALSE;
	}

	/* create a virtual ID */
	id_prefixed = gs_plugin_xdg_app_build_id (XDG_APP_REF (xref_bundle));

	/* load metadata */
	app = gs_app_new (id_prefixed);
	gs_app_set_kind (app, AS_APP_KIND_DESKTOP);
	gs_app_set_state (app, AS_APP_STATE_AVAILABLE_LOCAL);
	gs_app_set_size_installed (app, xdg_app_bundle_ref_get_installed_size (xref_bundle));
	gs_plugin_xdg_app_set_metadata (app, XDG_APP_REF (xref_bundle));
	metadata = xdg_app_bundle_ref_get_metadata (xref_bundle);
	if (!gs_plugin_xdg_app_set_app_metadata (app,
						 g_bytes_get_data (metadata, NULL),
						 g_bytes_get_size (metadata),
						 error))
		return FALSE;

	/* load AppStream */
	appstream_gz = xdg_app_bundle_ref_get_appstream (xref_bundle);
	if (appstream_gz != NULL) {
		g_autoptr(GZlibDecompressor) decompressor = NULL;
		g_autoptr(GInputStream) stream_gz = NULL;
		g_autoptr(GInputStream) stream_data = NULL;
		g_autoptr(GBytes) appstream = NULL;
		g_autoptr(AsStore) store = NULL;
		g_autofree gchar *id = NULL;
		AsApp *item;

		/* decompress data */
		decompressor = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
		stream_gz = g_memory_input_stream_new_from_bytes (appstream_gz);
		if (stream_gz == NULL)
			return FALSE;
		stream_data = g_converter_input_stream_new (stream_gz,
							    G_CONVERTER (decompressor));

		appstream = g_input_stream_read_bytes (stream_data,
						       0x100000, /* 1Mb */
						       cancellable,
						       error);
		if (appstream == NULL)
			return FALSE;
		store = as_store_new ();
		if (!as_store_from_bytes (store, appstream, cancellable, error))
			return FALSE;

		/* find app */
		id = g_strdup_printf ("%s.desktop", gs_app_get_xdgapp_name (app));
		item = as_store_get_app_by_id (store, id);
		if (item == NULL) {
			g_set_error (error,
				     GS_PLUGIN_ERROR,
				     GS_PLUGIN_ERROR_FAILED,
				     "application %s not found",
				     id);
			return FALSE;
		}

		/* copy details from AppStream to app */
		if (!gs_appstream_refine_app (plugin, app, item, error))
			return FALSE;
	}

	/* load icon */
	icon_data = xdg_app_bundle_ref_get_icon (xref_bundle,
						 64 * gs_plugin_get_scale (plugin));
	if (icon_data == NULL)
		icon_data = xdg_app_bundle_ref_get_icon (xref_bundle, 64);
	if (icon_data != NULL) {
		g_autoptr(GInputStream) stream_icon = NULL;
		g_autoptr(GdkPixbuf) pixbuf = NULL;
		stream_icon = g_memory_input_stream_new_from_bytes (icon_data);
		pixbuf = gdk_pixbuf_new_from_stream (stream_icon, cancellable, error);
		if (pixbuf == NULL)
			return FALSE;
		gs_app_set_pixbuf (app, pixbuf);
	} else {
		g_autoptr(AsIcon) icon = NULL;
		icon = as_icon_new ();
		as_icon_set_kind (icon, AS_ICON_KIND_STOCK);
		as_icon_set_name (icon, "application-x-executable");
		gs_app_set_icon (app, icon);
	}

	/* not quite true: this just means we can update this specific app */
	if (xdg_app_bundle_ref_get_origin (xref_bundle))
		gs_app_add_quirk (app, AS_APP_QUIRK_HAS_SOURCE);

	g_debug ("created local app: %s", gs_app_to_string (app));
	gs_app_list_add (list, app);
	return TRUE;
}
Ejemplo n.º 18
0
gboolean
ostree_content_stream_parse (gboolean                compressed,
                             GInputStream           *input,
                             guint64                 input_length,
                             gboolean                trusted,
                             GInputStream          **out_input,
                             GFileInfo             **out_file_info,
                             GVariant              **out_xattrs,
                             GCancellable           *cancellable,
                             GError                **error)
{
  gboolean ret = FALSE;
  guint32 archive_header_size;
  guchar dummy[4];
  gsize bytes_read;
  ot_lobj GInputStream *ret_input = NULL;
  ot_lobj GFileInfo *content_file_info = NULL;
  ot_lobj GFileInfo *ret_file_info = NULL;
  ot_lvariant GVariant *ret_xattrs = NULL;
  ot_lvariant GVariant *file_header = NULL;
  ot_lfree guchar *buf = NULL;

  if (!g_input_stream_read_all (input,
                                &archive_header_size, 4, &bytes_read,
                                cancellable, error))
    goto out;
  archive_header_size = GUINT32_FROM_BE (archive_header_size);
  if (archive_header_size > input_length)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "File header size %u exceeds size %" G_GUINT64_FORMAT,
                   (guint)archive_header_size, input_length);
      goto out;
    }
  if (archive_header_size == 0)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "File header size is zero");
      goto out;
    }

  /* Skip over padding */
  if (!g_input_stream_read_all (input,
                                dummy, 4, &bytes_read,
                                cancellable, error))
    goto out;

  buf = g_malloc (archive_header_size);
  if (!g_input_stream_read_all (input, buf, archive_header_size, &bytes_read,
                                cancellable, error))
    goto out;
  file_header = g_variant_new_from_data (compressed ? OSTREE_ZLIB_FILE_HEADER_GVARIANT_FORMAT : OSTREE_FILE_HEADER_GVARIANT_FORMAT,
                                         buf, archive_header_size, trusted,
                                         g_free, buf);
  buf = NULL;

  if (compressed)
    {
      if (!ostree_zlib_file_header_parse (file_header,
                                          out_file_info ? &ret_file_info : NULL,
                                          out_xattrs ? &ret_xattrs : NULL,
                                          error))
        goto out;
    }
  else
    {
      if (!ostree_file_header_parse (file_header,
                                     out_file_info ? &ret_file_info : NULL,
                                     out_xattrs ? &ret_xattrs : NULL,
                                     error))
        goto out;
      if (ret_file_info)
        g_file_info_set_size (ret_file_info, input_length - archive_header_size - 8);
    }
  
  if (g_file_info_get_file_type (ret_file_info) == G_FILE_TYPE_REGULAR
      && out_input)
    {
      /* Give the input stream at its current position as return value;
       * assuming the caller doesn't seek, this should be fine.  We might
       * want to wrap it though in a non-seekable stream.
       **/
      if (compressed)
        {
          ot_lobj GConverter *zlib_decomp = (GConverter*)g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_RAW);
          ret_input = g_converter_input_stream_new (input, zlib_decomp);
        }
      else
        ret_input = g_object_ref (input);
    }

  ret = TRUE;
  ot_transfer_out_value (out_input, &ret_input);
  ot_transfer_out_value (out_file_info, &ret_file_info);
  ot_transfer_out_value (out_xattrs, &ret_xattrs);
 out:
  return ret;
}