mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Fold branches/goffice-update/ back into trunk/.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@12096 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
134
lib/libgsf-1.12.3/gsf/Makefile.am
Normal file
134
lib/libgsf-1.12.3/gsf/Makefile.am
Normal file
@@ -0,0 +1,134 @@
|
||||
if OS_WIN32
|
||||
|
||||
install-libtool-import-lib:
|
||||
$(INSTALL) .libs/libgsf-1.dll.a $(DESTDIR)$(libdir)
|
||||
|
||||
uninstall-libtool-import-lib:
|
||||
-rm $(DESTDIR)$(libdir)/libgsf-1.dll.a
|
||||
else
|
||||
install-libtool-import-lib:
|
||||
uninstall-libtool-import-lib:
|
||||
endif
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/lib/libgsf-1.12.3 $(LIBGSF_CFLAGS) $(Z_CPPFLAGS) \
|
||||
-DGNOMELOCALEDIR=\"$(datadir)/locale\"
|
||||
|
||||
lib_LTLIBRARIES = libgsf-1.la
|
||||
|
||||
libgsf_1_la_LIBADD = $(LIBGSF_LIBS) $(Z_LIBS) $(BZ2_LIBS)
|
||||
libgsf_1_la_LDFLAGS = -version-info $(VERSION_INFO)
|
||||
if PLATFORM_WIN32
|
||||
libgsf_1_la_LDFLAGS += -no-undefined
|
||||
endif
|
||||
|
||||
libgsf_1_la_SOURCES = \
|
||||
gsf-utils.c \
|
||||
gsf-libxml.c \
|
||||
gsf-doc-meta-data.c \
|
||||
gsf-docprop-vector.c \
|
||||
gsf-msole-impl.h \
|
||||
gsf-msole-utils.c \
|
||||
gsf-timestamp.c \
|
||||
gsf-zip-impl.h \
|
||||
gsf-zip-utils.c \
|
||||
\
|
||||
gsf-input.c \
|
||||
gsf-input-bzip.c \
|
||||
gsf-input-gzip.c \
|
||||
gsf-input-iochannel.c \
|
||||
gsf-input-memory.c \
|
||||
gsf-input-proxy.c \
|
||||
gsf-input-stdio.c \
|
||||
gsf-input-textline.c \
|
||||
\
|
||||
gsf-infile.c \
|
||||
gsf-infile-msole.c \
|
||||
gsf-infile-msvba.c \
|
||||
gsf-infile-stdio.c \
|
||||
gsf-infile-zip.c \
|
||||
\
|
||||
gsf-output.c \
|
||||
gsf-output-bzip.c \
|
||||
gsf-output-csv.c \
|
||||
gsf-output-gzip.c \
|
||||
gsf-output-iconv.c \
|
||||
gsf-output-iochannel.c \
|
||||
gsf-output-memory.c \
|
||||
gsf-output-stdio.c \
|
||||
\
|
||||
gsf-outfile.c \
|
||||
gsf-outfile-msole.c \
|
||||
gsf-outfile-stdio.c \
|
||||
gsf-outfile-zip.c \
|
||||
\
|
||||
gsf-shared-memory.c \
|
||||
gsf-shared-memory.h \
|
||||
gsf-structured-blob.c \
|
||||
gsf-blob.c \
|
||||
gsf-clip-data.c
|
||||
# gsf-output-transaction.c \
|
||||
# gsf-command-context.c \
|
||||
# gsf-io-context.c
|
||||
|
||||
if !HAVE_GLIB26
|
||||
libgsf_1_la_SOURCES += glib24_26-compat.c
|
||||
endif
|
||||
|
||||
libgsf_1_includedir = $(includedir)/libgsf-1/gsf
|
||||
libgsf_1_include_HEADERS = \
|
||||
gsf.h \
|
||||
gsf-utils.h \
|
||||
gsf-libxml.h \
|
||||
gsf-impl-utils.h \
|
||||
gsf-doc-meta-data.h \
|
||||
gsf-docprop-vector.h \
|
||||
gsf-msole-utils.h \
|
||||
gsf-timestamp.h \
|
||||
\
|
||||
gsf-input.h \
|
||||
gsf-input-impl.h \
|
||||
gsf-input-bzip.h \
|
||||
gsf-input-gzip.h \
|
||||
gsf-input-iochannel.h \
|
||||
gsf-input-memory.h \
|
||||
gsf-input-proxy.h \
|
||||
gsf-input-stdio.h \
|
||||
gsf-input-textline.h \
|
||||
\
|
||||
gsf-infile.h \
|
||||
gsf-infile-impl.h \
|
||||
gsf-infile-msole.h \
|
||||
gsf-infile-msvba.h \
|
||||
gsf-infile-stdio.h \
|
||||
gsf-infile-zip.h \
|
||||
\
|
||||
gsf-output.h \
|
||||
gsf-output-impl.h \
|
||||
gsf-output-bzip.h \
|
||||
gsf-output-csv.h \
|
||||
gsf-output-gzip.h \
|
||||
gsf-output-iconv.h \
|
||||
gsf-output-iochannel.h \
|
||||
gsf-output-memory.h \
|
||||
gsf-output-stdio.h \
|
||||
\
|
||||
gsf-outfile.h \
|
||||
gsf-outfile-impl.h \
|
||||
gsf-outfile-msole.h \
|
||||
gsf-outfile-stdio.h \
|
||||
gsf-outfile-zip.h \
|
||||
\
|
||||
gsf-structured-blob.h \
|
||||
gsf-meta-names.h \
|
||||
gsf-blob.h \
|
||||
gsf-clip-data.h
|
||||
# gsf-command-context.h \
|
||||
# gsf-io-context.h
|
||||
|
||||
if !HAVE_GLIB26
|
||||
libgsf_1_include_HEADERS += glib24_26-compat.h
|
||||
endif
|
||||
|
||||
install-data-local: install-libtool-import-lib
|
||||
|
||||
uninstall-local: uninstall-libtool-import-lib
|
||||
204
lib/libgsf-1.12.3/gsf/glib24_26-compat.c
Normal file
204
lib/libgsf-1.12.3/gsf/glib24_26-compat.c
Normal file
@@ -0,0 +1,204 @@
|
||||
/** jsled, 2005-11-08: copied from glib-2.6.6 to support libgsf compilation
|
||||
against glib-2.4.14. **/
|
||||
|
||||
#include <gsf/glib24_26-compat.h>
|
||||
|
||||
/* gstdio.c - wrappers for C library functions
|
||||
*
|
||||
* Copyright 2004 Tor Lillqvist
|
||||
*
|
||||
* GLib is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* GLib is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with GLib; see the file COPYING.LIB. If not,
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
//#include <stdio.h>
|
||||
#include <string.h>
|
||||
//#include <stdlib.h>
|
||||
|
||||
/** ------------------------------------------------------------ **/
|
||||
/* START gconvert.c */
|
||||
|
||||
#include <glib/gunicode.h>
|
||||
#include <glib/gconvert.h>
|
||||
#include <glib/gthread.h>
|
||||
|
||||
typedef struct _GFilenameCharsetCache GFilenameCharsetCache;
|
||||
|
||||
struct _GFilenameCharsetCache {
|
||||
gboolean is_utf8;
|
||||
gchar *charset;
|
||||
gchar **filename_charsets;
|
||||
};
|
||||
|
||||
/**
|
||||
* g_get_filename_charsets:
|
||||
* @charsets: return location for the %NULL-terminated list of encoding names
|
||||
*
|
||||
* Determines the preferred character sets used for filenames.
|
||||
* The first character set from the @charsets is the filename encoding, the
|
||||
* subsequent character sets are used when trying to generate a displayable
|
||||
* representation of a filename, see g_filename_display_name().
|
||||
*
|
||||
* On Unix, the character sets are determined by consulting the
|
||||
* environment variables <envar>G_FILENAME_ENCODING</envar> and
|
||||
* <envar>G_BROKEN_FILENAMES</envar>. On Windows, the character set
|
||||
* used in the GLib API is always UTF-8 and said environment variables
|
||||
* have no effect.
|
||||
*
|
||||
* <envar>G_FILENAME_ENCODING</envar> may be set to a comma-separated list
|
||||
* of character set names. The special token "@locale" is taken to mean the
|
||||
* character set for the current locale. If <envar>G_FILENAME_ENCODING</envar>
|
||||
* is not set, but <envar>G_BROKEN_FILENAMES</envar> is, the character set of
|
||||
* the current locale is taken as the filename encoding. If neither environment
|
||||
* variable is set, UTF-8 is taken as the filename encoding, but the character
|
||||
* set of the current locale is also put in the list of encodings.
|
||||
*
|
||||
* The returned @charsets belong to GLib and must not be freed.
|
||||
*
|
||||
* Note that on Unix, regardless of the locale character set or
|
||||
* <envar>G_FILENAME_ENCODING</envar> value, the actual file names present on a
|
||||
* system might be in any random encoding or just gibberish.
|
||||
*
|
||||
* Return value: %TRUE if the filename encoding is UTF-8.
|
||||
*
|
||||
* Since: 2.6
|
||||
*/
|
||||
gboolean
|
||||
g_get_filename_charsets (G_CONST_RETURN gchar ***filename_charsets)
|
||||
{
|
||||
static const gchar *charsets[] = {
|
||||
"UTF-8",
|
||||
NULL
|
||||
};
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
/* On Windows GLib pretends that the filename charset is UTF-8 */
|
||||
if (filename_charsets)
|
||||
*filename_charsets = charsets;
|
||||
|
||||
return TRUE;
|
||||
#else
|
||||
gboolean result;
|
||||
|
||||
/* Cygwin works like before */
|
||||
result = g_get_charset (&(charsets[0]));
|
||||
|
||||
if (filename_charsets)
|
||||
*filename_charsets = charsets;
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
static gchar *
|
||||
make_valid_utf8 (const gchar *name)
|
||||
{
|
||||
GString *string;
|
||||
const gchar *remainder, *invalid;
|
||||
gint remaining_bytes, valid_bytes;
|
||||
|
||||
string = NULL;
|
||||
remainder = name;
|
||||
remaining_bytes = strlen (name);
|
||||
|
||||
while (remaining_bytes != 0)
|
||||
{
|
||||
if (g_utf8_validate (remainder, remaining_bytes, &invalid))
|
||||
break;
|
||||
valid_bytes = invalid - remainder;
|
||||
|
||||
if (string == NULL)
|
||||
string = g_string_sized_new (remaining_bytes);
|
||||
|
||||
g_string_append_len (string, remainder, valid_bytes);
|
||||
g_string_append_c (string, '?');
|
||||
|
||||
remaining_bytes -= valid_bytes + 1;
|
||||
remainder = invalid + 1;
|
||||
}
|
||||
|
||||
if (string == NULL)
|
||||
return g_strdup (name);
|
||||
|
||||
g_string_append (string, remainder);
|
||||
g_string_append (string, " (invalid encoding)");
|
||||
|
||||
g_assert (g_utf8_validate (string->str, -1, NULL));
|
||||
|
||||
return g_string_free (string, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_filename_display_name:
|
||||
* @filename: a pathname hopefully in the GLib file name encoding
|
||||
*
|
||||
* Converts a filename into a valid UTF-8 string. The
|
||||
* conversion is not necessarily reversible, so you
|
||||
* should keep the original around and use the return
|
||||
* value of this function only for display purposes.
|
||||
* Unlike g_filename_to_utf8(), the result is guaranteed
|
||||
* to be non-NULL even if the filename actually isn't in the GLib
|
||||
* file name encoding.
|
||||
*
|
||||
* If you know the whole pathname of the file you should use
|
||||
* g_filename_display_basename(), since that allows location-based
|
||||
* translation of filenames.
|
||||
*
|
||||
* Return value: a newly allocated string containing
|
||||
* a rendition of the filename in valid UTF-8
|
||||
*
|
||||
* Since: 2.6
|
||||
**/
|
||||
gchar *
|
||||
g_filename_display_name (const gchar *filename)
|
||||
{
|
||||
gint i;
|
||||
const gchar **charsets;
|
||||
gchar *display_name = NULL;
|
||||
gboolean is_utf8;
|
||||
|
||||
is_utf8 = g_get_filename_charsets (&charsets);
|
||||
|
||||
if (is_utf8)
|
||||
{
|
||||
if (g_utf8_validate (filename, -1, NULL))
|
||||
display_name = g_strdup (filename);
|
||||
}
|
||||
|
||||
if (!display_name)
|
||||
{
|
||||
/* Try to convert from the filename charsets to UTF-8.
|
||||
* Skip the first charset if it is UTF-8.
|
||||
*/
|
||||
for (i = is_utf8 ? 1 : 0; charsets[i]; i++)
|
||||
{
|
||||
display_name = g_convert (filename, -1, "UTF-8", charsets[i],
|
||||
NULL, NULL, NULL);
|
||||
|
||||
if (display_name)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* if all conversions failed, we replace invalid UTF-8
|
||||
* by a question mark
|
||||
*/
|
||||
if (!display_name)
|
||||
display_name = make_valid_utf8 (filename);
|
||||
|
||||
return display_name;
|
||||
}
|
||||
79
lib/libgsf-1.12.3/gsf/glib24_26-compat.h
Normal file
79
lib/libgsf-1.12.3/gsf/glib24_26-compat.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/* This file has been copied from glib-2.6.6 into libgsf-1.12.3 to support
|
||||
* compilation against glib-2.4.14. -- jsled, 2005-11-08
|
||||
*/
|
||||
|
||||
#ifndef __GLIB_24_26_COMPAT_H__
|
||||
#define __GLIB_24_26_COMPAT_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
// START from gstdio.h
|
||||
/* gstdio.h - GFilename wrappers for C library functions
|
||||
*
|
||||
* Copyright 2004 Tor Lillqvist
|
||||
*
|
||||
* GLib is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* GLib is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with GLib; see the file COPYING.LIB. If not,
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* Just pass on to the system functions, so there's no potential for data
|
||||
* format mismatches, especially with large file interfaces.
|
||||
*/
|
||||
|
||||
#define g_open open
|
||||
#define g_rename rename
|
||||
#define g_mkdir mkdir
|
||||
#define g_stat stat
|
||||
#define g_lstat lstat
|
||||
#define g_unlink unlink
|
||||
#define g_remove remove
|
||||
#define g_rmdir rmdir
|
||||
#define g_fopen fopen
|
||||
#define g_freopen freopen
|
||||
|
||||
// END from gstdio.h
|
||||
|
||||
// START from gconvert.h
|
||||
gchar *g_filename_display_name (const gchar *filename); // G_GNUC_MALLOC;
|
||||
// END from gconvert.h
|
||||
|
||||
/* from glib-2.6[.6] gutils.h */
|
||||
#ifdef G_OS_WIN32
|
||||
|
||||
/* On Win32, the canonical directory separator is the backslash, and
|
||||
* the search path separator is the semicolon. Note that also the
|
||||
* (forward) slash works as directory separator.
|
||||
*/
|
||||
#define G_DIR_SEPARATOR '\\'
|
||||
#define G_DIR_SEPARATOR_S "\\"
|
||||
#define G_IS_DIR_SEPARATOR(c) ((c) == G_DIR_SEPARATOR || (c) == '/')
|
||||
#define G_SEARCHPATH_SEPARATOR ';'
|
||||
#define G_SEARCHPATH_SEPARATOR_S ";"
|
||||
|
||||
#else /* !G_OS_WIN32 */
|
||||
|
||||
/* Unix */
|
||||
|
||||
#define G_DIR_SEPARATOR '/'
|
||||
#define G_DIR_SEPARATOR_S "/"
|
||||
#define G_IS_DIR_SEPARATOR(c) ((c) == G_DIR_SEPARATOR)
|
||||
#define G_SEARCHPATH_SEPARATOR ':'
|
||||
#define G_SEARCHPATH_SEPARATOR_S ":"
|
||||
|
||||
#endif /* !G_OS_WIN32 */
|
||||
|
||||
#endif /* __GLIB_24_26_COMPAT_H__ */
|
||||
142
lib/libgsf-1.12.3/gsf/gsf-blob.c
Normal file
142
lib/libgsf-1.12.3/gsf/gsf-blob.c
Normal file
@@ -0,0 +1,142 @@
|
||||
#include "gsf-config.h"
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <string.h>
|
||||
#include "gsf-utils.h"
|
||||
#include "gsf-blob.h"
|
||||
|
||||
/* Private part of the GsfBlob structure */
|
||||
struct _GsfBlobPrivate {
|
||||
gsize size;
|
||||
gpointer data;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GsfBlob, gsf_blob, G_TYPE_OBJECT);
|
||||
|
||||
static void gsf_blob_finalize (GObject *object);
|
||||
|
||||
static void
|
||||
gsf_blob_class_init (GsfBlobClass *class)
|
||||
{
|
||||
GObjectClass *object_class;
|
||||
|
||||
object_class = (GObjectClass *) class;
|
||||
|
||||
object_class->finalize = gsf_blob_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_blob_init (GsfBlob *blob)
|
||||
{
|
||||
GsfBlobPrivate *priv;
|
||||
|
||||
priv = g_new0 (GsfBlobPrivate, 1);
|
||||
blob->priv = priv;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_blob_finalize (GObject *object)
|
||||
{
|
||||
GsfBlob *blob;
|
||||
GsfBlobPrivate *priv;
|
||||
|
||||
blob = GSF_BLOB (object);
|
||||
priv = blob->priv;
|
||||
|
||||
g_free (priv->data);
|
||||
g_free (priv);
|
||||
|
||||
G_OBJECT_CLASS (gsf_blob_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_blob_new:
|
||||
* @size: Size of the data in bytes.
|
||||
* @data_to_copy: Data which will be copied into the blob, or %NULL if @size is zero.
|
||||
* @error: location to store error, or %NULL.
|
||||
*
|
||||
* Creates a new #GsfBlob object to hold the specified data. The blob can then
|
||||
* be used as a facility for reference-counting for the data. The data is
|
||||
* copied internally, so the blob does not hold references to external chunks
|
||||
* of memory.
|
||||
*
|
||||
* Return value: A newly-created #GsfBlob, or %NULL if the data could not be copied.
|
||||
*
|
||||
* Error domain: #GSF_ERROR
|
||||
*
|
||||
* Possible errors: #GSF_ERROR_OUT_OF_MEMORY if the @data_to_copy could not be copied.
|
||||
**/
|
||||
GsfBlob *
|
||||
gsf_blob_new (gsize size, gconstpointer data_to_copy, GError **error)
|
||||
{
|
||||
GsfBlob *blob;
|
||||
GsfBlobPrivate *priv;
|
||||
gpointer data;
|
||||
|
||||
g_return_val_if_fail ((size > 0 && data_to_copy != NULL) || (size == 0 && data_to_copy == NULL), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
if (data_to_copy) {
|
||||
data = g_try_malloc (size);
|
||||
if (!data) {
|
||||
g_set_error (error,
|
||||
GSF_ERROR,
|
||||
GSF_ERROR_OUT_OF_MEMORY,
|
||||
_("Not enough memory to copy %" G_GSIZE_FORMAT " bytes of data"),
|
||||
size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy (data, data_to_copy, size);
|
||||
} else
|
||||
data = NULL;
|
||||
|
||||
blob = g_object_new (GSF_TYPE_BLOB,
|
||||
NULL);
|
||||
priv = blob->priv;
|
||||
|
||||
priv->size = size;
|
||||
priv->data = data;
|
||||
|
||||
return blob;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_blob_get_size:
|
||||
* @blob: A #GsfBlob.
|
||||
*
|
||||
* Queries the size in bytes of the data stored in the blob.
|
||||
*
|
||||
* Return value: Size in bytes, or 0 if the data is %NULL.
|
||||
**/
|
||||
gsize
|
||||
gsf_blob_get_size (GsfBlob *blob)
|
||||
{
|
||||
GsfBlobPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GSF_IS_BLOB (blob), 0);
|
||||
|
||||
priv = blob->priv;
|
||||
return priv->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_blob_peek_data:
|
||||
* @blob: A #GsfBlob.
|
||||
*
|
||||
* Queries a pointer to the data stored in the blob. This does not copy the data
|
||||
* for you; it returns a pointer to the actual buffer which the blob uses internally,
|
||||
* so you should not free this buffer on your own.
|
||||
*
|
||||
* Return value: Pointer to the data stored in the blob, or %NULL if the size
|
||||
* of the data is zero.
|
||||
**/
|
||||
gconstpointer
|
||||
gsf_blob_peek_data (GsfBlob *blob)
|
||||
{
|
||||
GsfBlobPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GSF_IS_BLOB (blob), NULL);
|
||||
|
||||
priv = blob->priv;
|
||||
return priv->data;
|
||||
}
|
||||
40
lib/libgsf-1.12.3/gsf/gsf-blob.h
Normal file
40
lib/libgsf-1.12.3/gsf/gsf-blob.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#include <glib-object.h>
|
||||
|
||||
#ifndef GSF_BLOB_H
|
||||
#define GSF_BLOB_H
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSF_TYPE_BLOB (gsf_blob_get_type ())
|
||||
#define GSF_BLOB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSF_TYPE_BLOB, GsfBlob))
|
||||
#define GSF_BLOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSF_TYPE_BLOB, GsfBlobClass))
|
||||
#define GSF_IS_BLOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSF_TYPE_BLOB))
|
||||
#define GSF_IS_BLOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSF_TYPE_BLOB))
|
||||
#define GSF_BLOB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSF_TYPE_BLOB, GsfBlobClass))
|
||||
|
||||
typedef struct _GsfBlob GsfBlob;
|
||||
typedef struct _GsfBlobClass GsfBlobClass;
|
||||
typedef struct _GsfBlobPrivate GsfBlobPrivate;
|
||||
|
||||
struct _GsfBlob {
|
||||
GObject object;
|
||||
GsfBlobPrivate *priv;
|
||||
};
|
||||
|
||||
struct _GsfBlobClass {
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
GType gsf_blob_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GsfBlob *gsf_blob_new (gsize size,
|
||||
gconstpointer data_to_copy,
|
||||
GError **error);
|
||||
|
||||
gsize gsf_blob_get_size (GsfBlob *blob);
|
||||
|
||||
gconstpointer gsf_blob_peek_data (GsfBlob *blob);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
293
lib/libgsf-1.12.3/gsf/gsf-clip-data.c
Normal file
293
lib/libgsf-1.12.3/gsf/gsf-clip-data.c
Normal file
@@ -0,0 +1,293 @@
|
||||
#include "gsf-config.h"
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include "gsf-clip-data.h"
|
||||
#include "gsf-utils.h"
|
||||
|
||||
/* Private part of the GsfClipData structure */
|
||||
struct _GsfClipDataPrivate {
|
||||
GsfClipFormat format;
|
||||
GsfBlob *data_blob;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GsfClipData, gsf_clip_data, G_TYPE_OBJECT);
|
||||
|
||||
static void gsf_clip_data_finalize (GObject *object);
|
||||
|
||||
static void
|
||||
gsf_clip_data_class_init (GsfClipDataClass *class)
|
||||
{
|
||||
GObjectClass *object_class;
|
||||
|
||||
object_class = (GObjectClass *) class;
|
||||
|
||||
object_class->finalize = gsf_clip_data_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_clip_data_init (GsfClipData *clip_data)
|
||||
{
|
||||
GsfClipDataPrivate *priv;
|
||||
|
||||
priv = g_new0 (GsfClipDataPrivate, 1);
|
||||
clip_data->priv = priv;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_clip_data_finalize (GObject *object)
|
||||
{
|
||||
GsfClipData *clip_data;
|
||||
GsfClipDataPrivate *priv;
|
||||
|
||||
clip_data = GSF_CLIP_DATA (object);
|
||||
priv = clip_data->priv;
|
||||
|
||||
if (priv->data_blob)
|
||||
g_object_unref (priv->data_blob);
|
||||
|
||||
G_OBJECT_CLASS (gsf_clip_data_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_clip_data_new:
|
||||
* @format: Format for the data inside the @data_blob
|
||||
* @data_blob: Object which holds the binary contents for the #GsfClipData
|
||||
*
|
||||
* Creates a new #GsfClipData object. This function acquires a reference to the
|
||||
* @data_blob, so you should unref the blob on your own if you no longer need it
|
||||
* directly.
|
||||
*
|
||||
* Return value: A newly-created #GsfClipData.
|
||||
**/
|
||||
GsfClipData *
|
||||
gsf_clip_data_new (GsfClipFormat format, GsfBlob *data_blob)
|
||||
{
|
||||
GsfClipData *clip_data;
|
||||
GsfClipDataPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GSF_IS_BLOB (data_blob), NULL);
|
||||
|
||||
clip_data = g_object_new (GSF_TYPE_CLIP_DATA,
|
||||
NULL);
|
||||
priv = clip_data->priv;
|
||||
|
||||
priv->format = format;
|
||||
priv->data_blob = g_object_ref (data_blob);
|
||||
|
||||
return clip_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_clip_data_get_format:
|
||||
* @clip_data: A #GsfClipData.
|
||||
*
|
||||
* Queries the clipboard data format of a #GsfClipData. The format refers to the data
|
||||
* blob inside the @clip_data; use gsf_clip_data_get_data_blob() to get that data blob.
|
||||
*
|
||||
* Return value: The format in which the #GsfClipData's data blob is stored.
|
||||
**/
|
||||
GsfClipFormat
|
||||
gsf_clip_data_get_format (GsfClipData *clip_data)
|
||||
{
|
||||
GsfClipDataPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GSF_IS_CLIP_DATA (clip_data), GSF_CLIP_FORMAT_UNKNOWN);
|
||||
|
||||
priv = clip_data->priv;
|
||||
return priv->format;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_clip_data_get_data_blob:
|
||||
* @clip_data: A #GsfClipData.
|
||||
*
|
||||
* Queries the data blob that actually stores a #GsfClipData's binary data.
|
||||
*
|
||||
* Return value: A new reference to the #GsfBlob that stores this @clip_data's
|
||||
* binary data. You must use g_object_unref() to dispose of that data blob when
|
||||
* you are done with it.
|
||||
**/
|
||||
GsfBlob *
|
||||
gsf_clip_data_get_data_blob (GsfClipData *clip_data)
|
||||
{
|
||||
GsfClipDataPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GSF_IS_CLIP_DATA (clip_data), NULL);
|
||||
|
||||
priv = clip_data->priv;
|
||||
return g_object_ref (priv->data_blob);
|
||||
}
|
||||
|
||||
static void
|
||||
set_error_missing_clipboard_data (GError **error, const char *format_name, gsize at_least_size)
|
||||
{
|
||||
g_set_error (error,
|
||||
GSF_ERROR,
|
||||
GSF_ERROR_INVALID_DATA,
|
||||
_("The clip_data is in %s, but it is smaller than "
|
||||
"at least %" G_GSIZE_FORMAT " bytes"),
|
||||
format_name,
|
||||
at_least_size);
|
||||
}
|
||||
|
||||
static gsize
|
||||
get_windows_clipboard_data_offset (GsfClipFormatWindows format)
|
||||
{
|
||||
struct format_offset_pair {
|
||||
GsfClipFormatWindows format;
|
||||
gsize offset;
|
||||
};
|
||||
|
||||
static const struct format_offset_pair pairs[] = {
|
||||
{ GSF_CLIP_FORMAT_WINDOWS_UNKNOWN, 4 },
|
||||
{ GSF_CLIP_FORMAT_WINDOWS_METAFILE, 12 },
|
||||
{ GSF_CLIP_FORMAT_WINDOWS_DIB, 4 },
|
||||
{ GSF_CLIP_FORMAT_WINDOWS_ENHANCED_METAFILE, 4 } /* FIXME: does this have a PACKEDMETA in front
|
||||
* as well, similar to GSF_CLIP_FORMAT_WINDOWS_METAFILE? */
|
||||
};
|
||||
static const int num_pairs = G_N_ELEMENTS (pairs);
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_pairs; i++)
|
||||
if (pairs[i].format == format)
|
||||
return pairs[i].offset;
|
||||
|
||||
g_assert_not_reached ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Checks that the specified blob size matches the expected size for the format.
|
||||
* Returns the same format if the size is correct, or
|
||||
* GSF_CLIP_FORMAT_WINDOWS_ERROR if the size is too small.
|
||||
*/
|
||||
static GsfClipFormatWindows
|
||||
check_format_windows (GsfClipFormatWindows format, const char *format_name, gsize blob_size, GError **error)
|
||||
{
|
||||
gsize offset;
|
||||
|
||||
offset = get_windows_clipboard_data_offset (format);
|
||||
if (blob_size <= offset) {
|
||||
set_error_missing_clipboard_data (error, format_name, offset + 1);
|
||||
format = GSF_CLIP_FORMAT_WINDOWS_ERROR;
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_clip_data_get_windows_clipboard_format:
|
||||
* @clip_data: A #GsfClipData.
|
||||
* @error: Location to store error, or %NULL
|
||||
*
|
||||
* Queries the Windows clipboard data format for a #GsfClipData. The @clip_data must
|
||||
* have been created with #GSF_CLIP_FORMAT_WINDOWS_CLIPBOARD.
|
||||
*
|
||||
* Return value: A #GsfClipFormatWindows value.
|
||||
*
|
||||
* Possible errors: #GSF_ERROR_INVALID_DATA if the data blob in the @clip_data is
|
||||
* smaller than it should be; in this case GSF_CLIP_FORMAT_WINDOWS_ERROR will be returned.
|
||||
**/
|
||||
GsfClipFormatWindows
|
||||
gsf_clip_data_get_windows_clipboard_format (GsfClipData *clip_data, GError **error)
|
||||
{
|
||||
GsfClipDataPrivate *priv;
|
||||
gsize size;
|
||||
guint32 value;
|
||||
gconstpointer data;
|
||||
GsfClipFormatWindows format;
|
||||
|
||||
g_return_val_if_fail (GSF_IS_CLIP_DATA (clip_data), GSF_CLIP_FORMAT_WINDOWS_ERROR);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, GSF_CLIP_FORMAT_WINDOWS_ERROR);
|
||||
|
||||
priv = clip_data->priv;
|
||||
g_return_val_if_fail (priv->format == GSF_CLIP_FORMAT_WINDOWS_CLIPBOARD, GSF_CLIP_FORMAT_WINDOWS_ERROR);
|
||||
|
||||
size = gsf_blob_get_size (priv->data_blob);
|
||||
|
||||
if (size < 4) {
|
||||
g_set_error (error,
|
||||
GSF_ERROR,
|
||||
GSF_ERROR_INVALID_DATA,
|
||||
_("The clip_data is in Windows clipboard format, but it is smaller than "
|
||||
"the required 4 bytes."));
|
||||
return GSF_CLIP_FORMAT_WINDOWS_ERROR;
|
||||
}
|
||||
|
||||
data = gsf_blob_peek_data (priv->data_blob);
|
||||
|
||||
value = GSF_LE_GET_GUINT32 (data);
|
||||
|
||||
switch (value) {
|
||||
case GSF_CLIP_FORMAT_WINDOWS_METAFILE:
|
||||
format = check_format_windows (GSF_CLIP_FORMAT_WINDOWS_METAFILE, _("Windows Metafile format"),
|
||||
size, error);
|
||||
break;
|
||||
|
||||
case GSF_CLIP_FORMAT_WINDOWS_DIB:
|
||||
case 2: /* CF_BITMAP */
|
||||
format = check_format_windows (GSF_CLIP_FORMAT_WINDOWS_DIB, _("Windows DIB or BITMAP format"),
|
||||
size, error);
|
||||
break;
|
||||
|
||||
case GSF_CLIP_FORMAT_WINDOWS_ENHANCED_METAFILE:
|
||||
format = check_format_windows (GSF_CLIP_FORMAT_WINDOWS_ENHANCED_METAFILE, _("Windows Enhanced Metafile format"),
|
||||
size, error);
|
||||
break;
|
||||
|
||||
default:
|
||||
format = GSF_CLIP_FORMAT_WINDOWS_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_clip_data_peek_real_data:
|
||||
* @clip_data: A #GsfClipData.
|
||||
* @ret_size: Location to return the size of the returned data buffer.
|
||||
* @error: Location to store error, or %NULL.
|
||||
*
|
||||
* Queries a pointer directly to the clipboard data of a #GsfClipData. The
|
||||
* resulting pointer is not necessarily the same data pointer that was passed to
|
||||
* gsf_blob_new() prior to creating the @clip_data. For example, if the data is
|
||||
* in #GSF_CLIP_FORMAT_WINDOWS_CLIPBOARD format, then it will have extra header
|
||||
* bytes in front of the actual metafile data. This function will skip over
|
||||
* those header bytes if necessary and return a pointer to the "real" data.
|
||||
*
|
||||
* Return value: Pointer to the real clipboard data. The size in bytes of this
|
||||
* buffer is returned in the @ret_size argument.
|
||||
**/
|
||||
gconstpointer
|
||||
gsf_clip_data_peek_real_data (GsfClipData *clip_data, gsize *ret_size, GError **error)
|
||||
{
|
||||
GsfClipDataPrivate *priv;
|
||||
gconstpointer data;
|
||||
gsize offset;
|
||||
|
||||
g_return_val_if_fail (GSF_IS_CLIP_DATA (clip_data), NULL);
|
||||
g_return_val_if_fail (ret_size != NULL, NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
priv = clip_data->priv;
|
||||
|
||||
data = gsf_blob_peek_data (priv->data_blob);
|
||||
|
||||
if (priv->format == GSF_CLIP_FORMAT_WINDOWS_CLIPBOARD) {
|
||||
GsfClipFormatWindows win_format;
|
||||
|
||||
win_format = gsf_clip_data_get_windows_clipboard_format (clip_data, error);
|
||||
if (win_format == GSF_CLIP_FORMAT_WINDOWS_ERROR)
|
||||
return NULL;
|
||||
|
||||
/* gsf_clip_data_get_windows_clipboard_format() already did the size checks for us,
|
||||
* so we can jump to the offset right away without doing extra checks.
|
||||
*/
|
||||
|
||||
offset = get_windows_clipboard_data_offset (win_format);
|
||||
} else
|
||||
offset = 0;
|
||||
|
||||
*ret_size = gsf_blob_get_size (priv->data_blob) - offset;
|
||||
return (char *) data + offset; /* cast to avoid warning about void pointer arithmetic */
|
||||
}
|
||||
65
lib/libgsf-1.12.3/gsf/gsf-clip-data.h
Normal file
65
lib/libgsf-1.12.3/gsf/gsf-clip-data.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#include <gsf/gsf-blob.h>
|
||||
|
||||
#ifndef GSF_CLIP_DATA_H
|
||||
#define GSF_CLIP_DATA_H
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum {
|
||||
GSF_CLIP_FORMAT_WINDOWS_CLIPBOARD = -1,
|
||||
GSF_CLIP_FORMAT_MACINTOSH_CLIPBOARD = -2,
|
||||
GSF_CLIP_FORMAT_GUID = -3,
|
||||
GSF_CLIP_FORMAT_NO_DATA = 0,
|
||||
GSF_CLIP_FORMAT_CLIPBOARD_FORMAT_NAME = 1, /* in the file it's actually any positive integer */
|
||||
GSF_CLIP_FORMAT_UNKNOWN /* this is our own value for unknown types or invalid data */
|
||||
} GsfClipFormat;
|
||||
|
||||
typedef enum {
|
||||
GSF_CLIP_FORMAT_WINDOWS_ERROR = -1, /* our own value */
|
||||
GSF_CLIP_FORMAT_WINDOWS_UNKNOWN = -2, /* our own value */
|
||||
GSF_CLIP_FORMAT_WINDOWS_METAFILE = 3, /* CF_METAFILEPICT */
|
||||
GSF_CLIP_FORMAT_WINDOWS_DIB = 8, /* CF_DIB */
|
||||
GSF_CLIP_FORMAT_WINDOWS_ENHANCED_METAFILE = 14 /* CF_ENHMETAFILE */
|
||||
} GsfClipFormatWindows;
|
||||
|
||||
#define GSF_TYPE_CLIP_DATA (gsf_clip_data_get_type ())
|
||||
#define GSF_CLIP_DATA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSF_TYPE_CLIP_DATA, GsfClipData))
|
||||
#define GSF_CLIP_DATA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSF_TYPE_CLIP_DATA, GsfClipDataClass))
|
||||
#define GSF_IS_CLIP_DATA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSF_TYPE_CLIP_DATA))
|
||||
#define GSF_IS_CLIP_DATA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSF_TYPE_CLIP_DATA))
|
||||
#define GSF_CLIP_DATA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSF_TYPE_CLIP_DATA, GsfClipDataClass))
|
||||
|
||||
typedef struct _GsfClipData GsfClipData;
|
||||
typedef struct _GsfClipDataClass GsfClipDataClass;
|
||||
typedef struct _GsfClipDataPrivate GsfClipDataPrivate;
|
||||
|
||||
struct _GsfClipData {
|
||||
GObject object;
|
||||
|
||||
GsfClipDataPrivate *priv;
|
||||
};
|
||||
|
||||
struct _GsfClipDataClass {
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
GType gsf_clip_data_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GsfClipData *gsf_clip_data_new (GsfClipFormat format,
|
||||
GsfBlob *data_blob);
|
||||
|
||||
GsfClipFormat gsf_clip_data_get_format (GsfClipData *clip_data);
|
||||
|
||||
GsfBlob *gsf_clip_data_get_data_blob (GsfClipData *clip_data);
|
||||
|
||||
GsfClipFormatWindows gsf_clip_data_get_windows_clipboard_format (GsfClipData *clip_data,
|
||||
GError **error);
|
||||
|
||||
gconstpointer gsf_clip_data_peek_real_data (GsfClipData *clip_data,
|
||||
gsize *ret_size,
|
||||
GError **error);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
332
lib/libgsf-1.12.3/gsf/gsf-doc-meta-data.c
Normal file
332
lib/libgsf-1.12.3/gsf/gsf-doc-meta-data.c
Normal file
@@ -0,0 +1,332 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-doc-meta-data.c:
|
||||
*
|
||||
* Copyright (C) 2002-2005 Dom Lachowicz (cinamod@hotmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-doc-meta-data.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
|
||||
struct _GsfDocMetaData {
|
||||
GObject base;
|
||||
|
||||
GHashTable *table;
|
||||
};
|
||||
typedef GObjectClass GsfDocMetaDataClass;
|
||||
|
||||
struct _GsfDocProp {
|
||||
char *name;
|
||||
GValue *val;
|
||||
char *linked_to; /* optionally NULL */
|
||||
};
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
static void
|
||||
gsf_doc_meta_data_finalize (GObject *obj)
|
||||
{
|
||||
g_hash_table_destroy (GSF_DOC_META_DATA (obj)->table);
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_doc_meta_data_init (GObject *obj)
|
||||
{
|
||||
GsfDocMetaData *meta = GSF_DOC_META_DATA (obj);
|
||||
meta->table = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
NULL, (GDestroyNotify) gsf_doc_prop_free);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_doc_meta_data_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
gobject_class->finalize = gsf_doc_meta_data_finalize;
|
||||
parent_class = g_type_class_peek_parent (gobject_class);
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfDocMetaData, gsf_doc_meta_data,
|
||||
gsf_doc_meta_data_class_init, gsf_doc_meta_data_init,
|
||||
G_TYPE_OBJECT)
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/**
|
||||
* gsf_doc_meta_data_new :
|
||||
*
|
||||
* Returns a new metadata property collection
|
||||
**/
|
||||
GsfDocMetaData *
|
||||
gsf_doc_meta_data_new (void)
|
||||
{
|
||||
return g_object_new (GSF_DOC_META_DATA_TYPE, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_doc_meta_data_lookup :
|
||||
* @meta : #GsfDocMetaData
|
||||
* @name :
|
||||
*
|
||||
* Returns the property with name @id in @meta. The caller can modify the
|
||||
* property value and link but not the name.
|
||||
**/
|
||||
GsfDocProp *
|
||||
gsf_doc_meta_data_lookup (GsfDocMetaData const *meta, char const *name)
|
||||
{
|
||||
g_return_val_if_fail (IS_GSF_DOC_META_DATA (meta), NULL);
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
return g_hash_table_lookup (meta->table, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_doc_meta_data_insert :
|
||||
* @meta : #GsfDocMetaData
|
||||
* @name :
|
||||
* @value : #GValue
|
||||
*
|
||||
* Take ownership of @name and @value and insert a property into @meta.
|
||||
* If a property exists with @name, it is replaced (The link is lost)
|
||||
**/
|
||||
void
|
||||
gsf_doc_meta_data_insert (GsfDocMetaData *meta, char *name, GValue *value)
|
||||
{
|
||||
GsfDocProp *prop;
|
||||
|
||||
g_return_if_fail (IS_GSF_DOC_META_DATA (meta));
|
||||
g_return_if_fail (name != NULL);
|
||||
prop = g_new (GsfDocProp, 1);
|
||||
prop->name = name;
|
||||
prop->val = value;
|
||||
prop->linked_to = NULL;
|
||||
g_hash_table_replace (meta->table, prop->name, prop);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_doc_meta_data_remove :
|
||||
* @meta : the collection
|
||||
* @name : the non-null string name of the property
|
||||
*
|
||||
* If @name does not exist in the collection, do nothing. If @name does exist,
|
||||
* remove it and its value from the collection
|
||||
**/
|
||||
void
|
||||
gsf_doc_meta_data_remove (GsfDocMetaData *meta, char const *name)
|
||||
{
|
||||
g_return_if_fail (IS_GSF_DOC_META_DATA (meta));
|
||||
g_return_if_fail (name != NULL);
|
||||
g_hash_table_remove (meta->table, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_doc_meta_data_store :
|
||||
* @meta : #GsfDocMetaData
|
||||
* @name :
|
||||
*
|
||||
**/
|
||||
GsfDocProp *
|
||||
gsf_doc_meta_data_steal (GsfDocMetaData *meta, char const *name)
|
||||
{
|
||||
GsfDocProp *prop;
|
||||
g_return_val_if_fail (IS_GSF_DOC_META_DATA (meta), NULL);
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
prop = g_hash_table_lookup (meta->table, name);
|
||||
if (NULL != prop)
|
||||
g_hash_table_steal (meta->table, name);
|
||||
return prop;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_doc_meta_data_store :
|
||||
* @meta : #GsfDocMetaData
|
||||
* @prop : #GsfDocProp
|
||||
*
|
||||
**/
|
||||
void
|
||||
gsf_doc_meta_data_store (GsfDocMetaData *meta, GsfDocProp *prop)
|
||||
{
|
||||
g_return_if_fail (IS_GSF_DOC_META_DATA (meta));
|
||||
g_return_if_fail (prop != NULL);
|
||||
g_return_if_fail (prop != g_hash_table_lookup (meta->table, prop->name));
|
||||
g_hash_table_replace (meta->table, prop->name, prop);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_doc_meta_data_foreach :
|
||||
* @meta : the collection
|
||||
* @func : the function called once for each element in the collection
|
||||
* @user_data : any supplied user data or NULL
|
||||
*
|
||||
* Iterate through each (key, value) pair in this collection
|
||||
**/
|
||||
void
|
||||
gsf_doc_meta_data_foreach (GsfDocMetaData const *meta, GHFunc func, gpointer user_data)
|
||||
{
|
||||
g_return_if_fail (IS_GSF_DOC_META_DATA (meta));
|
||||
g_hash_table_foreach (meta->table, func, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_doc_meta_data_size :
|
||||
* @meta : the collection
|
||||
*
|
||||
* Returns the number of items in this collection
|
||||
**/
|
||||
gsize
|
||||
gsf_doc_meta_data_size (GsfDocMetaData const *meta)
|
||||
{
|
||||
g_return_val_if_fail (meta != NULL, 0);
|
||||
return (gsize) g_hash_table_size (meta->table);
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
/**
|
||||
* gsf_doc_prop_new :
|
||||
* @name :
|
||||
*
|
||||
* Returns a new #GsfDocProp which the caller is responsible for freeing.
|
||||
* Takes ownership of @name.
|
||||
**/
|
||||
GsfDocProp *
|
||||
gsf_doc_prop_new (char *name)
|
||||
{
|
||||
GsfDocProp *prop;
|
||||
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
|
||||
prop = g_new (GsfDocProp, 1);
|
||||
prop->name = name;
|
||||
prop->val = NULL;
|
||||
prop->linked_to = NULL;
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_doc_prop_free :
|
||||
* @prop : #GsfDocProp
|
||||
*
|
||||
* If @prop is non NULL free the memory assosociated with it
|
||||
**/
|
||||
void
|
||||
gsf_doc_prop_free (GsfDocProp *prop)
|
||||
{
|
||||
if (NULL != prop) {
|
||||
g_free (prop->linked_to);
|
||||
if (prop->val) {
|
||||
g_value_unset (prop->val);
|
||||
g_free (prop->val);
|
||||
}
|
||||
g_free (prop->name);
|
||||
g_free (prop);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_doc_prop_get_name :
|
||||
* @prop : #GsfDocProp
|
||||
*
|
||||
* Returns the name of the property, the caller should not modify the result.
|
||||
**/
|
||||
char const *
|
||||
gsf_doc_prop_get_name (GsfDocProp const *prop)
|
||||
{
|
||||
g_return_val_if_fail (prop != NULL, NULL);
|
||||
return prop->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_doc_prop_get_val :
|
||||
* @prop : the property
|
||||
*
|
||||
* Returns the value of the property, the caller should not modify the result.
|
||||
**/
|
||||
GValue const *
|
||||
gsf_doc_prop_get_val (GsfDocProp const *prop)
|
||||
{
|
||||
g_return_val_if_fail (prop != NULL, NULL);
|
||||
return prop->val;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_doc_prop_set_val :
|
||||
* @prop : #GsfDocProp
|
||||
* @val : #GValue
|
||||
*
|
||||
* Assigns @val to @prop, and unsets and frees the current value.
|
||||
**/
|
||||
void
|
||||
gsf_doc_prop_set_val (GsfDocProp *prop, GValue *val)
|
||||
{
|
||||
g_return_if_fail (prop != NULL);
|
||||
|
||||
if (val != prop->val) {
|
||||
g_value_unset (prop->val);
|
||||
g_free (prop->val);
|
||||
prop->val = val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_doc_prop_swap_val :
|
||||
* @prop : #GsfDocProp
|
||||
* @val : #GValue
|
||||
*
|
||||
* Returns the current value of @prop, and replaces it with @val
|
||||
* Caller is responsible for unsetting and freeing the result.
|
||||
**/
|
||||
GValue *
|
||||
gsf_doc_prop_swap_val (GsfDocProp *prop, GValue *val)
|
||||
{
|
||||
GValue *old_val;
|
||||
g_return_val_if_fail (prop != NULL, NULL);
|
||||
|
||||
old_val = prop->val;
|
||||
prop->val = val;
|
||||
return old_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_doc_prop_get_link :
|
||||
* @prop : #GsfDocProp
|
||||
*
|
||||
* Returns the current link descriptor of @prop. The result should not be
|
||||
* freed or modified.
|
||||
**/
|
||||
char const *
|
||||
gsf_doc_prop_get_link (GsfDocProp const *prop)
|
||||
{
|
||||
g_return_val_if_fail (prop != NULL, NULL);
|
||||
return prop->linked_to;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_doc_prop_set_link :
|
||||
* @prop : #GsfDocProp
|
||||
* @link :
|
||||
**/
|
||||
void
|
||||
gsf_doc_prop_set_link (GsfDocProp *prop, char *link)
|
||||
{
|
||||
g_return_if_fail (prop != NULL);
|
||||
if (link != prop->linked_to) {
|
||||
g_free (prop->linked_to);
|
||||
prop->linked_to = link;
|
||||
}
|
||||
}
|
||||
|
||||
62
lib/libgsf-1.12.3/gsf/gsf-doc-meta-data.h
Normal file
62
lib/libgsf-1.12.3/gsf/gsf-doc-meta-data.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-doc-meta-data.h: get, set, remove custom meta properties associated with documents
|
||||
*
|
||||
* Copyright (C) 2002-2005 Dom Lachowicz (cinamod@hotmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_DOC_META_DATA_H
|
||||
#define GSF_DOC_META_DATA_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
#include <glib-object.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSF_DOC_META_DATA_TYPE (gsf_doc_meta_data_get_type ())
|
||||
#define GSF_DOC_META_DATA(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_DOC_META_DATA_TYPE, GsfDocMetaData))
|
||||
#define IS_GSF_DOC_META_DATA(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_DOC_META_DATA_TYPE))
|
||||
|
||||
GType gsf_doc_meta_data_get_type (void);
|
||||
GsfDocMetaData *gsf_doc_meta_data_new (void);
|
||||
GsfDocProp *gsf_doc_meta_data_lookup (GsfDocMetaData const *meta,
|
||||
char const *name);
|
||||
void gsf_doc_meta_data_insert (GsfDocMetaData *meta,
|
||||
char *name, GValue *value);
|
||||
void gsf_doc_meta_data_remove (GsfDocMetaData *meta,
|
||||
char const *name);
|
||||
GsfDocProp *gsf_doc_meta_data_steal (GsfDocMetaData *meta,
|
||||
char const *name);
|
||||
void gsf_doc_meta_data_store (GsfDocMetaData *meta,
|
||||
GsfDocProp *prop);
|
||||
void gsf_doc_meta_data_foreach (GsfDocMetaData const *meta,
|
||||
GHFunc func, gpointer user_data);
|
||||
gsize gsf_doc_meta_data_size (GsfDocMetaData const *meta);
|
||||
|
||||
GsfDocProp *gsf_doc_prop_new (char *name);
|
||||
void gsf_doc_prop_free (GsfDocProp *prop);
|
||||
char const *gsf_doc_prop_get_name (GsfDocProp const *prop);
|
||||
GValue const *gsf_doc_prop_get_val (GsfDocProp const *prop);
|
||||
void gsf_doc_prop_set_val (GsfDocProp *prop, GValue *val);
|
||||
GValue *gsf_doc_prop_swap_val (GsfDocProp *prop, GValue *val);
|
||||
char const *gsf_doc_prop_get_link (GsfDocProp const *prop);
|
||||
void gsf_doc_prop_set_link (GsfDocProp *prop, char *link);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_DOC_META_DATA_H */
|
||||
158
lib/libgsf-1.12.3/gsf/gsf-docprop-vector.c
Normal file
158
lib/libgsf-1.12.3/gsf/gsf-docprop-vector.c
Normal file
@@ -0,0 +1,158 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-docprop-vector.c: A type implementing OLE Document Property vectors using a GValueArray
|
||||
*
|
||||
* Copyright (C) 2004-2005 Frank Chiulli (fc-linux@cox.net)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-docprop-vector.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct _GsfDocPropVector {
|
||||
GObject parent;
|
||||
|
||||
GValueArray *gva;
|
||||
};
|
||||
typedef GObjectClass GsfDocPropVectorClass;
|
||||
|
||||
#define GSF_DOCPROP_VECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GSF_DOCPROP_VECTOR_TYPE, GsfDocPropVectorClass))
|
||||
#define GSF_DOCPROP_VECTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GSF_DOCPROP_VECTOR_TYPE, GsfDocPropVectorClass))
|
||||
#define IS_GSF_DOCPROP_VECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GSF_DOCPROP_VECTOR_TYPE))
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
GValueArray *
|
||||
gsf_value_get_docprop_varray (GValue const *value)
|
||||
{
|
||||
GsfDocPropVector *v = gsf_value_get_docprop_vector (value);
|
||||
return v ? v->gva : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_docprop_value_get_vector
|
||||
* @value: A GValue of type #GsfDocPropVector.
|
||||
*
|
||||
* This function returns a pointer to the GsfDocPropVector structure in @value.
|
||||
* No additional references are created.
|
||||
*
|
||||
* Returns: A pointer to the #GsfDocPropVector structure in @value
|
||||
**/
|
||||
GsfDocPropVector *
|
||||
gsf_value_get_docprop_vector (GValue const *value)
|
||||
{
|
||||
g_return_val_if_fail (VAL_IS_GSF_DOCPROP_VECTOR (value), NULL);
|
||||
|
||||
return (GsfDocPropVector *) g_value_get_object (value);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_docprop_vector_append
|
||||
* @vector: The vector to which the GValue will be added
|
||||
* @value: The GValue to add to @vector
|
||||
*
|
||||
* Insert a copy of @value as the last element of @vector.
|
||||
**/
|
||||
void
|
||||
gsf_docprop_vector_append (GsfDocPropVector *vector, GValue *value)
|
||||
{
|
||||
g_return_if_fail (vector != NULL);
|
||||
g_return_if_fail (value != NULL);
|
||||
|
||||
if (G_IS_VALUE (value))
|
||||
vector->gva = g_value_array_append (vector->gva, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_docprop_vector_as_string
|
||||
* @vector: The #GsfDocPropVector from which GValues will be extracted.
|
||||
*
|
||||
* This function returns a string which represents all the GValues in @vector.
|
||||
* The caller is responsible for freeing the result.
|
||||
*
|
||||
* Returns: a string of comma-separated values
|
||||
**/
|
||||
gchar*
|
||||
gsf_docprop_vector_as_string (GsfDocPropVector *vector)
|
||||
{
|
||||
gchar *rstring;
|
||||
|
||||
guint i;
|
||||
guint num_values;
|
||||
|
||||
g_return_val_if_fail (vector != NULL, NULL);
|
||||
g_return_val_if_fail (vector->gva != NULL, NULL);
|
||||
|
||||
rstring = g_new0 (gchar, 1);
|
||||
num_values = vector->gva->n_values;
|
||||
|
||||
for (i = 0; i < num_values; i++) {
|
||||
char *str;
|
||||
GValue *v;
|
||||
|
||||
v = g_value_array_get_nth (vector->gva, i);
|
||||
str = g_strdup_value_contents (v);
|
||||
rstring = g_strconcat (rstring, str, ",", NULL);
|
||||
g_free (str);
|
||||
g_value_unset (v);
|
||||
}
|
||||
|
||||
return rstring;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_docprop_vector_finalize (GObject *obj)
|
||||
{
|
||||
GsfDocPropVector *vector = (GsfDocPropVector *) obj;
|
||||
if (vector->gva != NULL) {
|
||||
g_value_array_free (vector->gva);
|
||||
vector->gva = NULL;
|
||||
}
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_docprop_vector_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
parent_class = g_type_class_peek (G_TYPE_OBJECT);
|
||||
gobject_class->finalize = gsf_docprop_vector_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_docprop_vector_init (GsfDocPropVector *vector)
|
||||
{
|
||||
vector->gva = g_value_array_new (0);
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfDocPropVector, gsf_docprop_vector,
|
||||
gsf_docprop_vector_class_init, gsf_docprop_vector_init,
|
||||
G_TYPE_OBJECT)
|
||||
|
||||
/**
|
||||
* gsf_docprop_vector_new
|
||||
*
|
||||
* This function creates a new gsf_docprop_vector object.
|
||||
*
|
||||
* Returns: GsfDocPropVector*
|
||||
**/
|
||||
GsfDocPropVector*
|
||||
gsf_docprop_vector_new (void)
|
||||
{
|
||||
return g_object_new (GSF_DOCPROP_VECTOR_TYPE, NULL);
|
||||
}
|
||||
|
||||
46
lib/libgsf-1.12.3/gsf/gsf-docprop-vector.h
Normal file
46
lib/libgsf-1.12.3/gsf/gsf-docprop-vector.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-docprop-vectors.h: A type implementing OLE Document Property vectors
|
||||
*
|
||||
* Copyright (C) 2004-2005 Frank Chiulli (fc-linux@cox.net)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_DOCPROP_VECTOR_H
|
||||
#define GSF_DOCPROP_VECTOR_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSF_DOCPROP_VECTOR_TYPE (gsf_docprop_vector_get_type ())
|
||||
#define GSF_DOCPROP_VECTOR(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GSF_DOCPROP_VECTOR, GsfDocPropVector))
|
||||
#define IS_GSF_DOCPROP_VECTOR(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GSF_DOCPROP_VECTOR_TYPE))
|
||||
|
||||
typedef struct _GsfDocPropVector GsfDocPropVector;
|
||||
GType gsf_docprop_vector_get_type (void);
|
||||
GsfDocPropVector *gsf_docprop_vector_new (void);
|
||||
void gsf_docprop_vector_append (GsfDocPropVector *vector, GValue *value);
|
||||
gchar *gsf_docprop_vector_as_string (GsfDocPropVector *vector);
|
||||
|
||||
#define VAL_IS_GSF_DOCPROP_VECTOR(v) (G_TYPE_CHECK_VALUE_TYPE((v), GSF_DOCPROP_VECTOR_TYPE))
|
||||
GsfDocPropVector *gsf_value_get_docprop_vector (GValue const *value);
|
||||
GValueArray *gsf_value_get_docprop_varray (GValue const *value);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_DOCPROP_VECTOR_H */
|
||||
140
lib/libgsf-1.12.3/gsf/gsf-impl-utils.h
Normal file
140
lib/libgsf-1.12.3/gsf/gsf-impl-utils.h
Normal file
@@ -0,0 +1,140 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-impl-utils.h:
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_IMPL_UTILS_H
|
||||
#define GSF_IMPL_UTILS_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* We need to do this with a version check as this header gets installed. */
|
||||
#if GLIB_CHECK_VERSION(2,7,0)
|
||||
#define GSF_PARAM_STATIC (G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)
|
||||
#else
|
||||
#define GSF_PARAM_STATIC 0
|
||||
#endif
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#define GSF_CLASS_FULL(name, prefix, base_init, base_finalize, \
|
||||
class_init, class_finalize, instance_init, parent_type, \
|
||||
abstract, interface_decl) \
|
||||
GType \
|
||||
prefix ## _get_type (void) \
|
||||
{ \
|
||||
static GType type = 0; \
|
||||
if (type == 0) { \
|
||||
static GTypeInfo const object_info = { \
|
||||
sizeof (name ## Class), \
|
||||
(GBaseInitFunc) base_init, \
|
||||
(GBaseFinalizeFunc) base_finalize, \
|
||||
(GClassInitFunc) class_init, \
|
||||
(GClassFinalizeFunc) class_finalize, \
|
||||
NULL, /* class_data */ \
|
||||
sizeof (name), \
|
||||
0, /* n_preallocs */ \
|
||||
(GInstanceInitFunc) instance_init, \
|
||||
NULL \
|
||||
}; \
|
||||
type = g_type_register_static (parent_type, #name, \
|
||||
&object_info, (GTypeFlags) abstract); \
|
||||
interface_decl \
|
||||
} \
|
||||
return type; \
|
||||
}
|
||||
|
||||
#define GSF_CLASS(name, prefix, class_init, instance_init, parent) \
|
||||
GSF_CLASS_FULL(name, prefix, NULL, NULL, class_init, NULL, \
|
||||
instance_init, parent, 0, {})
|
||||
#define GSF_CLASS_ABSTRACT(name, prefix, class_init, instance_init, parent) \
|
||||
GSF_CLASS_FULL(name, prefix, NULL, NULL, class_init, NULL, \
|
||||
instance_init, parent, G_TYPE_FLAG_ABSTRACT, {})
|
||||
|
||||
#define GSF_INTERFACE_FULL(type, init_func, iface_type) { \
|
||||
static GInterfaceInfo const iface = { \
|
||||
(GInterfaceInitFunc) init_func, NULL, NULL }; \
|
||||
g_type_add_interface_static (type, iface_type, &iface); \
|
||||
}
|
||||
|
||||
#define GSF_INTERFACE(init_func, iface_type) \
|
||||
GSF_INTERFACE_FULL(type, init_func, iface_type)
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#define GSF_DYNAMIC_CLASS_FULL(name, prefix, base_init, base_finalize, \
|
||||
class_init, class_finalize, instance_init, parent_type, \
|
||||
abstract, interface_decl) \
|
||||
static GType prefix ## _type; \
|
||||
\
|
||||
GType prefix ## _get_type (void); \
|
||||
void prefix ## _register_type (GTypeModule *module); \
|
||||
\
|
||||
GType \
|
||||
prefix ## _get_type () \
|
||||
{ \
|
||||
g_return_val_if_fail (prefix ## _type != 0, 0); \
|
||||
return prefix ## _type; \
|
||||
} \
|
||||
void \
|
||||
prefix ## _register_type (GTypeModule *module) \
|
||||
{ \
|
||||
static GTypeInfo const type_info = { \
|
||||
sizeof (name ## Class), \
|
||||
(GBaseInitFunc) base_init, \
|
||||
(GBaseFinalizeFunc) base_finalize, \
|
||||
(GClassInitFunc) class_init, \
|
||||
(GClassFinalizeFunc) class_finalize, \
|
||||
NULL, /* class_data */ \
|
||||
sizeof (name), \
|
||||
0, /* n_preallocs */ \
|
||||
(GInstanceInitFunc) instance_init, \
|
||||
NULL \
|
||||
}; \
|
||||
GType type; \
|
||||
\
|
||||
g_return_if_fail (prefix ## _type == 0); \
|
||||
\
|
||||
type = prefix ## _type = g_type_module_register_type (module, \
|
||||
parent_type, #name, &type_info, (GTypeFlags) abstract); \
|
||||
interface_decl \
|
||||
}
|
||||
|
||||
#define GSF_DYNAMIC_CLASS(name, prefix, class_init, instance_init, parent) \
|
||||
GSF_DYNAMIC_CLASS_FULL(name, prefix, NULL, NULL, class_init, NULL, \
|
||||
instance_init, parent, 0, {})
|
||||
#define GSF_DYNAMIC_CLASS_ABSTRACT(name, prefix, class_init, instance_init, parent) \
|
||||
GSF_DYNAMIC_CLASS_FULL(name, prefix, NULL, NULL, class_init, NULL, \
|
||||
instance_init, parent, G_TYPE_FLAG_ABSTRACT, {})
|
||||
|
||||
#define GSF_DYNAMIC_INTERFACE_FULL(type, init_func, iface_type, module) { \
|
||||
static GInterfaceInfo const iface = { \
|
||||
(GInterfaceInitFunc) init_func, NULL, NULL }; \
|
||||
g_type_module_add_interface (module, type, iface_type, &iface); \
|
||||
}
|
||||
|
||||
#define GSF_DYNAMIC_INTERFACE(init_func, iface_type, module) \
|
||||
GSF_DYNAMIC_INTERFACE_FULL(type, init_func, iface_type, module)
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_IMPL_UTILS_H */
|
||||
50
lib/libgsf-1.12.3/gsf/gsf-infile-impl.h
Normal file
50
lib/libgsf-1.12.3/gsf/gsf-infile-impl.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-infile-impl.h:
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_INFILE_IMPL_H
|
||||
#define GSF_INFILE_IMPL_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
#include <gsf/gsf-input-impl.h>
|
||||
#include <gsf/gsf-infile.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
struct _GsfInfile {
|
||||
GsfInput parent;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
GsfInputClass input_class;
|
||||
int (*num_children) (GsfInfile *infile);
|
||||
char const *(*name_by_index) (GsfInfile *infile, int i);
|
||||
GsfInput *(*child_by_index) (GsfInfile *infile,
|
||||
int i, GError **err);
|
||||
GsfInput *(*child_by_name) (GsfInfile *infile,
|
||||
char const *name, GError **err);
|
||||
} GsfInfileClass;
|
||||
|
||||
#define GSF_INFILE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSF_INFILE_TYPE, GsfInfileClass))
|
||||
#define GSF_IS_INFILE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSF_INFILE_TYPE))
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_INFILE_IMPL_H */
|
||||
949
lib/libgsf-1.12.3/gsf/gsf-infile-msole.c
Normal file
949
lib/libgsf-1.12.3/gsf/gsf-infile-msole.c
Normal file
@@ -0,0 +1,949 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-infile-msole.c :
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
/* Lots of useful information in
|
||||
* http://www.aafassociation.org/html/specs/aafcontainerspec-v1.0.1.pdf
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-infile-impl.h>
|
||||
#include <gsf/gsf-infile-msole.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <gsf/gsf-utils.h>
|
||||
#include <gsf/gsf-msole-impl.h>
|
||||
#include <gsf/gsf-input-proxy.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#undef G_LOG_DOMAIN
|
||||
#define G_LOG_DOMAIN "libgsf:msole"
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
typedef struct {
|
||||
guint32 *block;
|
||||
guint32 num_blocks;
|
||||
} MSOleBAT;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
char *collation_name;
|
||||
int index;
|
||||
size_t size;
|
||||
gboolean use_sb;
|
||||
guint32 first_block;
|
||||
gboolean is_directory;
|
||||
GList *children;
|
||||
unsigned char clsid[16]; /* 16 byte GUID used by some apps */
|
||||
} MSOleDirent;
|
||||
|
||||
typedef struct {
|
||||
struct {
|
||||
MSOleBAT bat;
|
||||
unsigned shift;
|
||||
unsigned filter;
|
||||
size_t size;
|
||||
} bb, sb;
|
||||
gsf_off_t max_block;
|
||||
guint32 threshold; /* transition between small and big blocks */
|
||||
guint32 sbat_start, num_sbat;
|
||||
|
||||
MSOleDirent *root_dir;
|
||||
GsfInput *sb_file;
|
||||
|
||||
int ref_count;
|
||||
} MSOleInfo;
|
||||
|
||||
struct _GsfInfileMSOle {
|
||||
GsfInfile parent;
|
||||
|
||||
GsfInput *input;
|
||||
MSOleInfo *info;
|
||||
MSOleDirent *dirent;
|
||||
MSOleBAT bat;
|
||||
gsf_off_t cur_block;
|
||||
|
||||
struct {
|
||||
guint8 *buf;
|
||||
size_t buf_size;
|
||||
} stream;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
GsfInfileClass parent_class;
|
||||
} GsfInfileMSOleClass;
|
||||
|
||||
#define GSF_INFILE_MSOLE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSF_INFILE_MSOLE_TYPE, GsfInfileMSOleClass))
|
||||
#define GSF_IS_INFILE_MSOLE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSF_INFILE_MSOLE_TYPE))
|
||||
|
||||
/* utility macros */
|
||||
#define OLE_BIG_BLOCK(index, ole) ((index) >> ole->info->bb.shift)
|
||||
|
||||
static GsfInput *gsf_infile_msole_new_child (GsfInfileMSOle *parent,
|
||||
MSOleDirent *dirent, GError **err);
|
||||
static void ole_info_unref (MSOleInfo *info);
|
||||
|
||||
/**
|
||||
* ole_get_block :
|
||||
* @ole : the infile
|
||||
* @block :
|
||||
* @buffer : optionally NULL
|
||||
*
|
||||
* Read a block of data from the underlying input.
|
||||
* Be really anal.
|
||||
**/
|
||||
static guint8 const *
|
||||
ole_get_block (GsfInfileMSOle const *ole, guint32 block, guint8 *buffer)
|
||||
{
|
||||
g_return_val_if_fail (block < ole->info->max_block, NULL);
|
||||
|
||||
/* OLE_HEADER_SIZE is fixed at 512, but the sector containing the
|
||||
* header is padded out to bb.size (sector size) when bb.size > 512. */
|
||||
if (gsf_input_seek (ole->input,
|
||||
(gsf_off_t)(MAX (OLE_HEADER_SIZE, ole->info->bb.size) + (block << ole->info->bb.shift)),
|
||||
G_SEEK_SET) < 0)
|
||||
return NULL;
|
||||
|
||||
return gsf_input_read (ole->input, ole->info->bb.size, buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* ole_make_bat :
|
||||
* @metabat : a meta bat to connect to the raw blocks (small or large)
|
||||
* @size_guess : An optional guess as to how many blocks are in the file
|
||||
* @block : The first block in the list.
|
||||
* @res : where to store the result.
|
||||
*
|
||||
* Walk the linked list of the supplied block allocation table and build up a
|
||||
* table for the list starting in @block.
|
||||
*
|
||||
* Retrurns TRUE on error.
|
||||
*/
|
||||
static gboolean
|
||||
ole_make_bat (MSOleBAT const *metabat, size_t size_guess, guint32 block,
|
||||
MSOleBAT *res)
|
||||
{
|
||||
/* NOTE : Only use size as a suggestion, sometimes it is wrong */
|
||||
GArray *bat = g_array_sized_new (FALSE, FALSE,
|
||||
sizeof (guint32), size_guess);
|
||||
|
||||
guint8 *used = (guint8*)g_alloca (1 + metabat->num_blocks / 8);
|
||||
memset (used, 0, 1 + metabat->num_blocks / 8);
|
||||
|
||||
if (block < metabat->num_blocks)
|
||||
do {
|
||||
/* Catch cycles in the bat list */
|
||||
g_return_val_if_fail (0 == (used[block/8] & (1 << (block & 0x7))), TRUE);
|
||||
used[block/8] |= 1 << (block & 0x7);
|
||||
|
||||
g_array_append_val (bat, block);
|
||||
block = metabat->block [block];
|
||||
} while (block < metabat->num_blocks);
|
||||
|
||||
res->block = NULL;
|
||||
|
||||
res->num_blocks = bat->len;
|
||||
res->block = (guint32 *) (gpointer) g_array_free (bat, FALSE);
|
||||
|
||||
if (block != BAT_MAGIC_END_OF_CHAIN) {
|
||||
g_warning ("This OLE2 file is invalid.\n"
|
||||
"The Block Allocation Table for one of the streams had %x instead of a terminator (%x).\n"
|
||||
"We might still be able to extract some data, but you'll want to check the file.",
|
||||
block, BAT_MAGIC_END_OF_CHAIN);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
ols_bat_release (MSOleBAT *bat)
|
||||
{
|
||||
if (bat->block != NULL) {
|
||||
g_free (bat->block);
|
||||
bat->block = NULL;
|
||||
bat->num_blocks = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ole_info_read_metabat :
|
||||
* @ole :
|
||||
* @bats :
|
||||
*
|
||||
* A small utility routine to read a set of references to bat blocks
|
||||
* either from the OLE header, or a meta-bat block.
|
||||
*
|
||||
* Returns a pointer to the element after the last position filled.
|
||||
**/
|
||||
static guint32 *
|
||||
ole_info_read_metabat (GsfInfileMSOle *ole, guint32 *bats, guint32 max,
|
||||
guint32 const *metabat, guint32 const *metabat_end)
|
||||
{
|
||||
guint8 const *bat, *end;
|
||||
|
||||
for (; metabat < metabat_end; metabat++) {
|
||||
bat = ole_get_block (ole, *metabat, NULL);
|
||||
if (bat == NULL)
|
||||
return NULL;
|
||||
end = bat + ole->info->bb.size;
|
||||
for ( ; bat < end ; bat += BAT_INDEX_SIZE, bats++) {
|
||||
*bats = GSF_LE_GET_GUINT32 (bat);
|
||||
g_return_val_if_fail (*bats < max ||
|
||||
*bats >= BAT_MAGIC_METABAT, NULL);
|
||||
}
|
||||
}
|
||||
return bats;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_ole_get_guint32s :
|
||||
* @dst :
|
||||
* @src :
|
||||
* @num_bytes :
|
||||
*
|
||||
* Copy some some raw data into an array of guint32.
|
||||
**/
|
||||
static void
|
||||
gsf_ole_get_guint32s (guint32 *dst, guint8 const *src, int num_bytes)
|
||||
{
|
||||
for (; (num_bytes -= BAT_INDEX_SIZE) >= 0 ; src += BAT_INDEX_SIZE)
|
||||
*dst++ = GSF_LE_GET_GUINT32 (src);
|
||||
}
|
||||
|
||||
static GsfInput *
|
||||
ole_info_get_sb_file (GsfInfileMSOle *parent)
|
||||
{
|
||||
MSOleBAT meta_sbat;
|
||||
|
||||
if (parent->info->sb_file != NULL)
|
||||
return parent->info->sb_file;
|
||||
|
||||
parent->info->sb_file = gsf_infile_msole_new_child (parent,
|
||||
parent->info->root_dir, NULL);
|
||||
if (!parent->info->sb_file)
|
||||
return NULL;
|
||||
|
||||
/* avoid creating a circular reference */
|
||||
ole_info_unref (((GsfInfileMSOle *)parent->info->sb_file)->info);
|
||||
|
||||
g_return_val_if_fail (parent->info->sb.bat.block == NULL, NULL);
|
||||
|
||||
if (ole_make_bat (&parent->info->bb.bat,
|
||||
parent->info->num_sbat, parent->info->sbat_start, &meta_sbat))
|
||||
return NULL;
|
||||
|
||||
parent->info->sb.bat.num_blocks = meta_sbat.num_blocks * (parent->info->bb.size / BAT_INDEX_SIZE);
|
||||
parent->info->sb.bat.block = g_new0 (guint32, parent->info->sb.bat.num_blocks);
|
||||
ole_info_read_metabat (parent, parent->info->sb.bat.block,
|
||||
parent->info->sb.bat.num_blocks,
|
||||
meta_sbat.block, meta_sbat.block + meta_sbat.num_blocks);
|
||||
ols_bat_release (&meta_sbat);
|
||||
|
||||
return parent->info->sb_file;
|
||||
}
|
||||
|
||||
static gint
|
||||
ole_dirent_cmp (MSOleDirent const *a, MSOleDirent const *b)
|
||||
{
|
||||
g_return_val_if_fail (a, 0);
|
||||
g_return_val_if_fail (b, 0);
|
||||
|
||||
g_return_val_if_fail (a->collation_name, 0);
|
||||
g_return_val_if_fail (b->collation_name, 0);
|
||||
|
||||
return strcmp (b->collation_name, a->collation_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* ole_dirent_new :
|
||||
* @ole :
|
||||
* @entry :
|
||||
* @parent : optional
|
||||
*
|
||||
* Parse dirent number @entry and recursively handle its siblings and children.
|
||||
**/
|
||||
static MSOleDirent *
|
||||
ole_dirent_new (GsfInfileMSOle *ole, guint32 entry, MSOleDirent *parent)
|
||||
{
|
||||
MSOleDirent *dirent;
|
||||
guint32 block, next, prev, child, size;
|
||||
guint8 const *data;
|
||||
guint8 type;
|
||||
guint16 name_len;
|
||||
|
||||
if (entry >= DIRENT_MAGIC_END)
|
||||
return NULL;
|
||||
|
||||
block = OLE_BIG_BLOCK (entry * DIRENT_SIZE, ole);
|
||||
|
||||
g_return_val_if_fail (block < ole->bat.num_blocks, NULL);
|
||||
data = ole_get_block (ole, ole->bat.block [block], NULL);
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
data += (DIRENT_SIZE * entry) % ole->info->bb.size;
|
||||
|
||||
type = GSF_LE_GET_GUINT8 (data + DIRENT_TYPE);
|
||||
if (type != DIRENT_TYPE_DIR &&
|
||||
type != DIRENT_TYPE_FILE &&
|
||||
type != DIRENT_TYPE_ROOTDIR) {
|
||||
g_warning ("Unknown stream type 0x%x", type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* It looks like directory (and root directory) sizes are sometimes bogus */
|
||||
size = GSF_LE_GET_GUINT32 (data + DIRENT_FILE_SIZE);
|
||||
g_return_val_if_fail (type == DIRENT_TYPE_DIR || type == DIRENT_TYPE_ROOTDIR ||
|
||||
size <= (guint32)ole->input->size, NULL);
|
||||
|
||||
dirent = g_new0 (MSOleDirent, 1);
|
||||
dirent->index = entry;
|
||||
dirent->size = size;
|
||||
/* Store the class id which is 16 byte identifier used by some apps */
|
||||
memcpy(dirent->clsid, data + DIRENT_CLSID, sizeof(dirent->clsid));
|
||||
|
||||
/* root dir is always big block */
|
||||
dirent->use_sb = parent && (size < ole->info->threshold);
|
||||
dirent->first_block = (GSF_LE_GET_GUINT32 (data + DIRENT_FIRSTBLOCK));
|
||||
dirent->is_directory = (type != DIRENT_TYPE_FILE);
|
||||
dirent->children = NULL;
|
||||
prev = GSF_LE_GET_GUINT32 (data + DIRENT_PREV);
|
||||
next = GSF_LE_GET_GUINT32 (data + DIRENT_NEXT);
|
||||
child = GSF_LE_GET_GUINT32 (data + DIRENT_CHILD);
|
||||
name_len = GSF_LE_GET_GUINT16 (data + DIRENT_NAME_LEN);
|
||||
dirent->name = NULL;
|
||||
if (0 < name_len && name_len <= DIRENT_MAX_NAME_SIZE) {
|
||||
gunichar2 uni_name [DIRENT_MAX_NAME_SIZE+1];
|
||||
gchar const *end;
|
||||
int i;
|
||||
|
||||
/* !#%!@$#^
|
||||
* Sometimes, rarely, people store the stream name as ascii
|
||||
* rather than utf16. Do a validation first just in case.
|
||||
*/
|
||||
if (!g_utf8_validate (data, -1, &end) ||
|
||||
((guint8 const *)end - data + 1) != name_len) {
|
||||
/* be wary about endianness */
|
||||
for (i = 0 ; i < name_len ; i += 2)
|
||||
uni_name [i/2] = GSF_LE_GET_GUINT16 (data + i);
|
||||
uni_name [i/2] = 0;
|
||||
|
||||
dirent->name = g_utf16_to_utf8 (uni_name, -1, NULL, NULL, NULL);
|
||||
} else
|
||||
dirent->name = g_strndup ((gchar *)data, (gsize)((guint8 const *)end - data + 1));
|
||||
}
|
||||
/* be really anal in the face of screwups */
|
||||
if (dirent->name == NULL)
|
||||
dirent->name = g_strdup ("");
|
||||
dirent->collation_name = g_utf8_collate_key (dirent->name, -1);
|
||||
|
||||
#if 0
|
||||
printf ("%c '%s' :\tsize = %d\tfirst_block = 0x%x\n",
|
||||
dirent->is_directory ? 'd' : ' ',
|
||||
dirent->name, dirent->size, dirent->first_block);
|
||||
#endif
|
||||
|
||||
if (parent != NULL)
|
||||
parent->children = g_list_insert_sorted (parent->children,
|
||||
dirent, (GCompareFunc)ole_dirent_cmp);
|
||||
|
||||
/* NOTE : These links are a tree, not a linked list */
|
||||
if (prev == entry) {
|
||||
g_warning ("Invalid OLE file with a cycle in its directory tree");
|
||||
} else
|
||||
ole_dirent_new (ole, prev, parent);
|
||||
if (next == entry) {
|
||||
g_warning ("Invalid OLE file with a cycle in its directory tree");
|
||||
} else
|
||||
ole_dirent_new (ole, next, parent);
|
||||
|
||||
if (dirent->is_directory)
|
||||
ole_dirent_new (ole, child, dirent);
|
||||
else if (child != DIRENT_MAGIC_END)
|
||||
g_warning ("A non directory stream with children ?");
|
||||
|
||||
return dirent;
|
||||
}
|
||||
|
||||
static void
|
||||
ole_dirent_free (MSOleDirent *dirent)
|
||||
{
|
||||
GList *tmp;
|
||||
g_return_if_fail (dirent != NULL);
|
||||
|
||||
g_free (dirent->name);
|
||||
g_free (dirent->collation_name);
|
||||
|
||||
for (tmp = dirent->children; tmp; tmp = tmp->next)
|
||||
ole_dirent_free ((MSOleDirent *)tmp->data);
|
||||
g_list_free (dirent->children);
|
||||
g_free (dirent);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
ole_info_unref (MSOleInfo *info)
|
||||
{
|
||||
if (info->ref_count-- != 1)
|
||||
return;
|
||||
|
||||
ols_bat_release (&info->bb.bat);
|
||||
ols_bat_release (&info->sb.bat);
|
||||
if (info->root_dir != NULL) {
|
||||
ole_dirent_free (info->root_dir);
|
||||
info->root_dir = NULL;
|
||||
}
|
||||
if (info->sb_file != NULL) {
|
||||
g_object_unref (G_OBJECT (info->sb_file));
|
||||
info->sb_file = NULL;
|
||||
}
|
||||
g_free (info);
|
||||
}
|
||||
|
||||
static MSOleInfo *
|
||||
ole_info_ref (MSOleInfo *info)
|
||||
{
|
||||
info->ref_count++;
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* ole_dup :
|
||||
* @src :
|
||||
*
|
||||
* Utility routine to _partially_ replicate a file. It does NOT copy the bat
|
||||
* blocks, or init the dirent.
|
||||
*
|
||||
* Return value: the partial duplicate.
|
||||
**/
|
||||
static GsfInfileMSOle *
|
||||
ole_dup (GsfInfileMSOle const *src, GError **err)
|
||||
{
|
||||
GsfInfileMSOle *dst;
|
||||
GsfInput *input;
|
||||
|
||||
g_return_val_if_fail (src != NULL, NULL);
|
||||
|
||||
input = gsf_input_dup (src->input, err);
|
||||
if (input == NULL) {
|
||||
if (err != NULL)
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"Failed to duplicate input stream");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dst = (GsfInfileMSOle *)g_object_new (GSF_INFILE_MSOLE_TYPE, NULL);
|
||||
dst->input = input;
|
||||
dst->info = ole_info_ref (src->info);
|
||||
|
||||
/* buf and buf_size are initialized to NULL */
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
/**
|
||||
* ole_init_info :
|
||||
* @ole :
|
||||
* @err : optionally NULL
|
||||
*
|
||||
* Read an OLE header and do some sanity checking
|
||||
* along the way.
|
||||
*
|
||||
* Return value: TRUE on error setting @err if it is supplied.
|
||||
**/
|
||||
static gboolean
|
||||
ole_init_info (GsfInfileMSOle *ole, GError **err)
|
||||
{
|
||||
static guint8 const signature[] =
|
||||
{ 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 };
|
||||
guint8 const *header, *tmp;
|
||||
guint32 *metabat = NULL;
|
||||
MSOleInfo *info;
|
||||
guint32 bb_shift, sb_shift, num_bat, num_metabat, last, dirent_start;
|
||||
guint32 metabat_block, *ptr;
|
||||
|
||||
/* check the header */
|
||||
if (gsf_input_seek (ole->input, 0, G_SEEK_SET) ||
|
||||
NULL == (header = gsf_input_read (ole->input, OLE_HEADER_SIZE, NULL)) ||
|
||||
0 != memcmp (header, signature, sizeof (signature))) {
|
||||
if (err != NULL)
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"No OLE2 signature");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bb_shift = GSF_LE_GET_GUINT16 (header + OLE_HEADER_BB_SHIFT);
|
||||
sb_shift = GSF_LE_GET_GUINT16 (header + OLE_HEADER_SB_SHIFT);
|
||||
num_bat = GSF_LE_GET_GUINT32 (header + OLE_HEADER_NUM_BAT);
|
||||
dirent_start = GSF_LE_GET_GUINT32 (header + OLE_HEADER_DIRENT_START);
|
||||
metabat_block = GSF_LE_GET_GUINT32 (header + OLE_HEADER_METABAT_BLOCK);
|
||||
num_metabat = GSF_LE_GET_GUINT32 (header + OLE_HEADER_NUM_METABAT);
|
||||
|
||||
/* Some sanity checks
|
||||
* 1) There should always be at least 1 BAT block
|
||||
* 2) It makes no sense to have a block larger than 2^31 for now.
|
||||
* Maybe relax this later, but not much.
|
||||
*/
|
||||
if (6 > bb_shift || bb_shift >= 31 || sb_shift > bb_shift) {
|
||||
if (err != NULL)
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"Unreasonable block sizes");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
info = g_new0 (MSOleInfo, 1);
|
||||
ole->info = info;
|
||||
|
||||
info->ref_count = 1;
|
||||
info->bb.shift = bb_shift;
|
||||
info->bb.size = 1 << info->bb.shift;
|
||||
info->bb.filter = info->bb.size - 1;
|
||||
info->sb.shift = sb_shift;
|
||||
info->sb.size = 1 << info->sb.shift;
|
||||
info->sb.filter = info->sb.size - 1;
|
||||
info->threshold = GSF_LE_GET_GUINT32 (header + OLE_HEADER_THRESHOLD);
|
||||
info->sbat_start = GSF_LE_GET_GUINT32 (header + OLE_HEADER_SBAT_START);
|
||||
info->num_sbat = GSF_LE_GET_GUINT32 (header + OLE_HEADER_NUM_SBAT);
|
||||
info->max_block = (gsf_input_size (ole->input) - OLE_HEADER_SIZE) / info->bb.size;
|
||||
info->sb_file = NULL;
|
||||
|
||||
if (info->num_sbat == 0 && info->sbat_start != BAT_MAGIC_END_OF_CHAIN) {
|
||||
g_warning ("There is are not supposed to be any blocks in the small block allocation table, yet there is a link to some. Ignoring it.");
|
||||
}
|
||||
|
||||
/* very rough heuristic, just in case */
|
||||
if (num_bat < info->max_block) {
|
||||
info->bb.bat.num_blocks = num_bat * (info->bb.size / BAT_INDEX_SIZE);
|
||||
info->bb.bat.block = g_new0 (guint32, info->bb.bat.num_blocks);
|
||||
|
||||
metabat = (guint32 *)g_alloca (MAX (info->bb.size, OLE_HEADER_SIZE));
|
||||
|
||||
/* Reading the elements invalidates this memory, make copy */
|
||||
gsf_ole_get_guint32s (metabat, header + OLE_HEADER_START_BAT,
|
||||
OLE_HEADER_SIZE - OLE_HEADER_START_BAT);
|
||||
last = num_bat;
|
||||
if (last > OLE_HEADER_METABAT_SIZE)
|
||||
last = OLE_HEADER_METABAT_SIZE;
|
||||
|
||||
ptr = ole_info_read_metabat (ole, info->bb.bat.block,
|
||||
info->bb.bat.num_blocks, metabat, metabat + last);
|
||||
num_bat -= last;
|
||||
} else
|
||||
ptr = NULL;
|
||||
|
||||
last = (info->bb.size - BAT_INDEX_SIZE) / BAT_INDEX_SIZE;
|
||||
while (ptr != NULL && num_metabat-- > 0) {
|
||||
tmp = ole_get_block (ole, metabat_block, NULL);
|
||||
if (tmp == NULL) {
|
||||
ptr = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Reading the elements invalidates this memory, make copy */
|
||||
gsf_ole_get_guint32s (metabat, tmp, (int)info->bb.size);
|
||||
|
||||
if (num_metabat == 0) {
|
||||
if (last < num_bat) {
|
||||
/* there should be less that a full metabat block
|
||||
* remaining */
|
||||
ptr = NULL;
|
||||
break;
|
||||
}
|
||||
last = num_bat;
|
||||
} else if (num_metabat > 0) {
|
||||
metabat_block = metabat[last];
|
||||
num_bat -= last;
|
||||
}
|
||||
|
||||
ptr = ole_info_read_metabat (ole, ptr,
|
||||
info->bb.bat.num_blocks, metabat, metabat + last);
|
||||
}
|
||||
|
||||
if (ptr == NULL) {
|
||||
if (err != NULL)
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"Inconsistent block allocation table");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Read the directory's bat, we do not know the size */
|
||||
if (ole_make_bat (&info->bb.bat, 0, dirent_start, &ole->bat)) {
|
||||
if (err != NULL)
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"Problems making block allocation table");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Read the directory */
|
||||
ole->dirent = info->root_dir = ole_dirent_new (ole, 0, NULL);
|
||||
if (ole->dirent == NULL) {
|
||||
if (err != NULL)
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"Problems reading directory");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_infile_msole_finalize (GObject *obj)
|
||||
{
|
||||
GsfInfileMSOle *ole = GSF_INFILE_MSOLE (obj);
|
||||
|
||||
if (ole->input != NULL) {
|
||||
g_object_unref (G_OBJECT (ole->input));
|
||||
ole->input = NULL;
|
||||
}
|
||||
if (ole->info != NULL &&
|
||||
ole->info->sb_file != (GsfInput *)ole) {
|
||||
ole_info_unref (ole->info);
|
||||
ole->info = NULL;
|
||||
}
|
||||
ols_bat_release (&ole->bat);
|
||||
|
||||
g_free (ole->stream.buf);
|
||||
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static GsfInput *
|
||||
gsf_infile_msole_dup (GsfInput *src_input, GError **err)
|
||||
{
|
||||
GsfInfileMSOle const *src = GSF_INFILE_MSOLE (src_input);
|
||||
GsfInfileMSOle *dst = ole_dup (src, err);
|
||||
|
||||
if (dst == NULL)
|
||||
return NULL;
|
||||
|
||||
if (src->bat.block != NULL) {
|
||||
dst->bat.block = g_new (guint32, src->bat.num_blocks),
|
||||
memcpy (dst->bat.block, src->bat.block,
|
||||
sizeof (guint32) * src->bat.num_blocks);
|
||||
}
|
||||
dst->bat.num_blocks = src->bat.num_blocks;
|
||||
dst->dirent = src->dirent;
|
||||
|
||||
return GSF_INPUT (dst);
|
||||
}
|
||||
|
||||
static guint8 const *
|
||||
gsf_infile_msole_read (GsfInput *input, size_t num_bytes, guint8 *buffer)
|
||||
{
|
||||
GsfInfileMSOle *ole = GSF_INFILE_MSOLE (input);
|
||||
gsf_off_t first_block, last_block, raw_block, offset, i;
|
||||
guint8 const *data;
|
||||
guint8 *ptr;
|
||||
size_t count;
|
||||
|
||||
/* small block files are preload */
|
||||
if (ole->dirent != NULL && ole->dirent->use_sb) {
|
||||
if (buffer != NULL) {
|
||||
memcpy (buffer, ole->stream.buf + input->cur_offset, num_bytes);
|
||||
return buffer;
|
||||
}
|
||||
return ole->stream.buf + input->cur_offset;
|
||||
}
|
||||
|
||||
/* GsfInput guarantees that num_bytes > 0 */
|
||||
first_block = OLE_BIG_BLOCK (input->cur_offset, ole);
|
||||
last_block = OLE_BIG_BLOCK (input->cur_offset + num_bytes - 1, ole);
|
||||
offset = input->cur_offset & ole->info->bb.filter;
|
||||
|
||||
/* optimization : are all the raw blocks contiguous */
|
||||
i = first_block;
|
||||
raw_block = ole->bat.block [i];
|
||||
while (++i <= last_block && ++raw_block == ole->bat.block [i])
|
||||
;
|
||||
if (i > last_block) {
|
||||
/* optimization don't seek if we don't need to */
|
||||
if (ole->cur_block != first_block) {
|
||||
if (gsf_input_seek (ole->input,
|
||||
(gsf_off_t)(MAX (OLE_HEADER_SIZE, ole->info->bb.size) + (ole->bat.block [first_block] << ole->info->bb.shift) + offset),
|
||||
G_SEEK_SET) < 0)
|
||||
return NULL;
|
||||
}
|
||||
ole->cur_block = last_block;
|
||||
return gsf_input_read (ole->input, num_bytes, buffer);
|
||||
}
|
||||
|
||||
/* damn, we need to copy it block by block */
|
||||
if (buffer == NULL) {
|
||||
if (ole->stream.buf_size < num_bytes) {
|
||||
if (ole->stream.buf != NULL)
|
||||
g_free (ole->stream.buf);
|
||||
ole->stream.buf_size = num_bytes;
|
||||
ole->stream.buf = g_new (guint8, num_bytes);
|
||||
}
|
||||
buffer = ole->stream.buf;
|
||||
}
|
||||
|
||||
ptr = buffer;
|
||||
for (i = first_block ; i <= last_block ; i++ , ptr += count, num_bytes -= count) {
|
||||
count = ole->info->bb.size - offset;
|
||||
if (count > num_bytes)
|
||||
count = num_bytes;
|
||||
data = ole_get_block (ole, ole->bat.block [i], NULL);
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
|
||||
/* TODO : this could be optimized to avoid the copy */
|
||||
memcpy (ptr, data + offset, count);
|
||||
offset = 0;
|
||||
}
|
||||
ole->cur_block = BAT_MAGIC_UNUSED;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_infile_msole_seek (GsfInput *input, gsf_off_t offset, GSeekType whence)
|
||||
{
|
||||
GsfInfileMSOle *ole = GSF_INFILE_MSOLE (input);
|
||||
|
||||
(void) offset;
|
||||
(void) whence;
|
||||
|
||||
ole->cur_block = BAT_MAGIC_UNUSED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GsfInput *
|
||||
gsf_infile_msole_new_child (GsfInfileMSOle *parent,
|
||||
MSOleDirent *dirent, GError **err)
|
||||
{
|
||||
GsfInfileMSOle *child;
|
||||
MSOleInfo *info;
|
||||
MSOleBAT const *metabat;
|
||||
GsfInput *sb_file = NULL;
|
||||
size_t size_guess;
|
||||
|
||||
child = ole_dup (parent, err);
|
||||
if (!child)
|
||||
return NULL;
|
||||
|
||||
child->dirent = dirent;
|
||||
gsf_input_set_size (GSF_INPUT (child), (gsf_off_t) dirent->size);
|
||||
|
||||
/* The root dirent defines the small block file */
|
||||
if (dirent->index != 0) {
|
||||
gsf_input_set_name (GSF_INPUT (child), dirent->name);
|
||||
gsf_input_set_container (GSF_INPUT (child), GSF_INFILE (parent));
|
||||
|
||||
if (dirent->is_directory) {
|
||||
/* be wary. It seems as if some implementations pretend that the
|
||||
* directories contain data */
|
||||
gsf_input_set_size (GSF_INPUT (child), 0);
|
||||
return GSF_INPUT (child);
|
||||
}
|
||||
}
|
||||
|
||||
info = parent->info;
|
||||
|
||||
/* build the bat */
|
||||
if (dirent->use_sb) {
|
||||
metabat = &info->sb.bat;
|
||||
size_guess = dirent->size >> info->sb.shift;
|
||||
sb_file = ole_info_get_sb_file (parent);
|
||||
if (!sb_file) {
|
||||
if (err != NULL)
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"Failed to access child");
|
||||
g_object_unref (G_OBJECT (child));
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
metabat = &info->bb.bat;
|
||||
size_guess = dirent->size >> info->bb.shift;
|
||||
}
|
||||
if (ole_make_bat (metabat, size_guess + 1, dirent->first_block, &child->bat)) {
|
||||
g_object_unref (G_OBJECT (child));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dirent->use_sb) {
|
||||
unsigned i;
|
||||
guint8 const *data;
|
||||
|
||||
g_return_val_if_fail (sb_file != NULL, NULL);
|
||||
|
||||
child->stream.buf_size = info->threshold;
|
||||
child->stream.buf = g_new (guint8, info->threshold);
|
||||
|
||||
for (i = 0 ; i < child->bat.num_blocks; i++)
|
||||
if (gsf_input_seek (GSF_INPUT (sb_file),
|
||||
(gsf_off_t)(child->bat.block [i] << info->sb.shift), G_SEEK_SET) < 0 ||
|
||||
(data = gsf_input_read (GSF_INPUT (sb_file),
|
||||
info->sb.size,
|
||||
child->stream.buf + (i << info->sb.shift))) == NULL) {
|
||||
|
||||
g_warning ("failure reading block %d", i);
|
||||
|
||||
g_object_unref (G_OBJECT (child));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return GSF_INPUT (child);
|
||||
}
|
||||
|
||||
static GsfInput *
|
||||
gsf_infile_msole_child_by_index (GsfInfile *infile, int target, GError **err)
|
||||
{
|
||||
GsfInfileMSOle *ole = GSF_INFILE_MSOLE (infile);
|
||||
GList *p;
|
||||
|
||||
for (p = ole->dirent->children; p != NULL ; p = p->next)
|
||||
if (target-- <= 0)
|
||||
return gsf_infile_msole_new_child (ole,
|
||||
(MSOleDirent *)p->data, err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char const *
|
||||
gsf_infile_msole_name_by_index (GsfInfile *infile, int target)
|
||||
{
|
||||
GsfInfileMSOle *ole = GSF_INFILE_MSOLE (infile);
|
||||
GList *p;
|
||||
|
||||
for (p = ole->dirent->children; p != NULL ; p = p->next)
|
||||
if (target-- <= 0)
|
||||
return ((MSOleDirent *)p->data)->name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GsfInput *
|
||||
gsf_infile_msole_child_by_name (GsfInfile *infile, char const *name, GError **err)
|
||||
{
|
||||
GsfInfileMSOle *ole = GSF_INFILE_MSOLE (infile);
|
||||
GList *p;
|
||||
|
||||
for (p = ole->dirent->children; p != NULL ; p = p->next) {
|
||||
MSOleDirent *dirent = p->data;
|
||||
if (dirent->name != NULL && !strcmp (name, dirent->name))
|
||||
return gsf_infile_msole_new_child (ole, dirent, err);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
gsf_infile_msole_num_children (GsfInfile *infile)
|
||||
{
|
||||
GsfInfileMSOle *ole = GSF_INFILE_MSOLE (infile);
|
||||
|
||||
g_return_val_if_fail (ole->dirent != NULL, -1);
|
||||
|
||||
if (!ole->dirent->is_directory)
|
||||
return -1;
|
||||
return g_list_length (ole->dirent->children);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_infile_msole_init (GObject *obj)
|
||||
{
|
||||
GsfInfileMSOle *ole = GSF_INFILE_MSOLE (obj);
|
||||
|
||||
ole->input = NULL;
|
||||
ole->info = NULL;
|
||||
ole->bat.block = NULL;
|
||||
ole->bat.num_blocks = 0;
|
||||
ole->cur_block = BAT_MAGIC_UNUSED;
|
||||
ole->stream.buf = NULL;
|
||||
ole->stream.buf_size = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_infile_msole_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
GsfInputClass *input_class = GSF_INPUT_CLASS (gobject_class);
|
||||
GsfInfileClass *infile_class = GSF_INFILE_CLASS (gobject_class);
|
||||
|
||||
gobject_class->finalize = gsf_infile_msole_finalize;
|
||||
input_class->Dup = gsf_infile_msole_dup;
|
||||
input_class->Read = gsf_infile_msole_read;
|
||||
input_class->Seek = gsf_infile_msole_seek;
|
||||
infile_class->num_children = gsf_infile_msole_num_children;
|
||||
infile_class->name_by_index = gsf_infile_msole_name_by_index;
|
||||
infile_class->child_by_index = gsf_infile_msole_child_by_index;
|
||||
infile_class->child_by_name = gsf_infile_msole_child_by_name;
|
||||
|
||||
parent_class = g_type_class_peek_parent (gobject_class);
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfInfileMSOle, gsf_infile_msole,
|
||||
gsf_infile_msole_class_init, gsf_infile_msole_init,
|
||||
GSF_INFILE_TYPE)
|
||||
|
||||
/**
|
||||
* gsf_infile_msole_new :
|
||||
* @source :
|
||||
* @err :
|
||||
*
|
||||
* Opens the root directory of an MS OLE file.
|
||||
* NOTE : adds a reference to @source
|
||||
*
|
||||
* Returns : the new ole file handler
|
||||
**/
|
||||
GsfInfile *
|
||||
gsf_infile_msole_new (GsfInput *source, GError **err)
|
||||
{
|
||||
GsfInfileMSOle *ole;
|
||||
gsf_off_t calling_pos;
|
||||
|
||||
g_return_val_if_fail (GSF_IS_INPUT (source), NULL);
|
||||
|
||||
ole = (GsfInfileMSOle *)g_object_new (GSF_INFILE_MSOLE_TYPE, NULL);
|
||||
ole->input = gsf_input_proxy_new (source);
|
||||
gsf_input_set_size (GSF_INPUT (ole), 0);
|
||||
|
||||
calling_pos = gsf_input_tell (source);
|
||||
if (ole_init_info (ole, err)) {
|
||||
/* It's not clear to me why we do this. And if this
|
||||
fails, there's really nothing we can do. */
|
||||
(void)gsf_input_seek (source, calling_pos, G_SEEK_SET);
|
||||
|
||||
g_object_unref (G_OBJECT (ole));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return GSF_INFILE (ole);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_infile_msole_get_class_id :
|
||||
* @ole: a #GsfInfileMSOle
|
||||
* @res: 16 byte identifier (often a GUID in MS Windows apps)
|
||||
*
|
||||
* Retrieves the 16 byte indentifier (often a GUID in MS Windows apps)
|
||||
* stored within the directory associated with @ole and stores it in @res.
|
||||
*
|
||||
* Returns TRUE on success
|
||||
**/
|
||||
gboolean
|
||||
gsf_infile_msole_get_class_id (GsfInfileMSOle const *ole, guint8 *res)
|
||||
{
|
||||
g_return_val_if_fail (ole != NULL && ole->dirent != NULL, FALSE);
|
||||
|
||||
memcpy (res, ole->dirent->clsid,
|
||||
sizeof(ole->dirent->clsid));
|
||||
return TRUE;
|
||||
}
|
||||
42
lib/libgsf-1.12.3/gsf/gsf-infile-msole.h
Normal file
42
lib/libgsf-1.12.3/gsf/gsf-infile-msole.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-infile-msole.h:
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_INFILE_MSOLE_H
|
||||
#define GSF_INFILE_MSOLE_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GsfInfileMSOle GsfInfileMSOle;
|
||||
|
||||
#define GSF_INFILE_MSOLE_TYPE (gsf_infile_msole_get_type ())
|
||||
#define GSF_INFILE_MSOLE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_INFILE_MSOLE_TYPE, GsfInfileMSOle))
|
||||
#define GSF_IS_INFILE_MSOLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_INFILE_MSOLE_TYPE))
|
||||
|
||||
GType gsf_infile_msole_get_type (void);
|
||||
GsfInfile *gsf_infile_msole_new (GsfInput *source, GError **err);
|
||||
gboolean gsf_infile_msole_get_class_id (GsfInfileMSOle const *ole,
|
||||
guint8 *res);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_INFILE_MSOLE_H */
|
||||
441
lib/libgsf-1.12.3/gsf/gsf-infile-msvba.c
Normal file
441
lib/libgsf-1.12.3/gsf/gsf-infile-msvba.c
Normal file
@@ -0,0 +1,441 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-infile-msvba.c :
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
/* Info extracted from
|
||||
* svx/source/msfilter/msvbasic.cxx
|
||||
* Costin Raiu, Kaspersky Labs, 'Apple of Discord'
|
||||
* Virus bulletin's bontchev.pdf, svajcer.pdf
|
||||
*
|
||||
* and lots and lots of reading. There are lots of pieces missing still
|
||||
* but the structure seems to hold together.
|
||||
*/
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-infile-msvba.h>
|
||||
#include <gsf/gsf-infile.h>
|
||||
#include <gsf/gsf-input-memory.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <gsf/gsf-msole-utils.h>
|
||||
#include <gsf/gsf-utils.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
struct _GsfInfileMSVBA {
|
||||
GObject parent;
|
||||
|
||||
GsfInfile *source;
|
||||
GList *children;
|
||||
};
|
||||
typedef GObjectClass GsfInfileMSVBAClass;
|
||||
|
||||
#define GSF_INFILE_MSVBA_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSF_INFILE_MSVBA_TYPE, GsfInfileMSVBAClass))
|
||||
#define GSF_IS_INFILE_MSVBA_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSF_INFILE_MSVBA_TYPE))
|
||||
|
||||
|
||||
static guint8 *
|
||||
gsf_vba_inflate (GsfInput *input, gsf_off_t offset, int *size, gboolean add_null_terminator)
|
||||
{
|
||||
GByteArray *res = gsf_msole_inflate (input, offset + 3);
|
||||
if (res == NULL)
|
||||
return NULL;
|
||||
*size = res->len;
|
||||
if (add_null_terminator)
|
||||
g_byte_array_append (res, "", 1);
|
||||
return g_byte_array_free (res, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
vba_extract_module_source (GsfInfileMSVBA *vba, char const *name, guint32 src_offset)
|
||||
{
|
||||
GsfInput *module;
|
||||
guint8 *src_code;
|
||||
int inflated_size;
|
||||
|
||||
g_return_if_fail (name != NULL);
|
||||
|
||||
module = gsf_infile_child_by_name (vba->source, name);
|
||||
if (module == NULL)
|
||||
return;
|
||||
|
||||
src_code = gsf_vba_inflate (module, (gsf_off_t) src_offset, &inflated_size, TRUE);
|
||||
if (src_code != NULL) {
|
||||
printf ("======================\n%s\n>>>>>>\n%s<<<<<<\n", name, src_code);
|
||||
g_free (src_code);
|
||||
} else
|
||||
g_warning ("Problems extracting the source for %s @ %u", name, src_offset);
|
||||
|
||||
g_object_unref (module);
|
||||
module = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* vba_dir_read :
|
||||
* @vba :
|
||||
* @err : optionally NULL
|
||||
*
|
||||
* Read an VBA dirctory and its project file.
|
||||
* along the way.
|
||||
*
|
||||
* Return value: 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, FALSE);
|
||||
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);
|
||||
g_print ("Project Name : '%s'\n", name);
|
||||
g_free (name);
|
||||
break;
|
||||
case 9:
|
||||
g_print ("Quirk - duff tag 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: 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);
|
||||
g_free (elem_stream);
|
||||
|
||||
if (element_count != 0)
|
||||
g_warning ("Number of elements differs from expectations");
|
||||
|
||||
failed = FALSE;
|
||||
|
||||
fail_content :
|
||||
g_free (inflated_data);
|
||||
fail_compression :
|
||||
g_object_unref (G_OBJECT (dir));
|
||||
fail_stream :
|
||||
|
||||
if (failed) {
|
||||
if (err != NULL)
|
||||
*err = g_error_new (gsf_input_error_id (), 0, msg);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define VBA56_DIRENT_RECORD_COUNT (2 + /* magic */ \
|
||||
4 + /* version */ \
|
||||
2 + /* 0x00 0xff */ \
|
||||
22) /* unknown */
|
||||
#define VBA56_DIRENT_HEADER_SIZE (VBA56_DIRENT_RECORD_COUNT + \
|
||||
2 + /* type1 record count */ \
|
||||
2) /* unknown */
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* vba_project_read :
|
||||
* @vba :
|
||||
* @err : optionally NULL
|
||||
*
|
||||
* Read an VBA dirctory and its project file.
|
||||
* along the way.
|
||||
*
|
||||
* Return value: 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;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
gsf_infile_msvba_finalize (GObject *obj)
|
||||
{
|
||||
GsfInfileMSVBA *vba = GSF_INFILE_MSVBA (obj);
|
||||
|
||||
if (vba->source != NULL) {
|
||||
g_object_unref (G_OBJECT (vba->source));
|
||||
vba->source = NULL;
|
||||
}
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_infile_msvba_init (GObject *obj)
|
||||
{
|
||||
GsfInfileMSVBA *vba = GSF_INFILE_MSVBA (obj);
|
||||
|
||||
vba->source = NULL;
|
||||
vba->children = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_infile_msvba_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
gobject_class->finalize = gsf_infile_msvba_finalize;
|
||||
parent_class = g_type_class_peek_parent (gobject_class);
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfInfileMSVBA, gsf_infile_msvba,
|
||||
gsf_infile_msvba_class_init, gsf_infile_msvba_init,
|
||||
G_TYPE_OBJECT)
|
||||
|
||||
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);
|
||||
g_object_ref (G_OBJECT (source));
|
||||
vba->source = 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 (G_OBJECT (vba));
|
||||
return NULL;
|
||||
}
|
||||
42
lib/libgsf-1.12.3/gsf/gsf-infile-msvba.h
Normal file
42
lib/libgsf-1.12.3/gsf/gsf-infile-msvba.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-infile-msvba.h:
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_INFILE_MSVBA_H
|
||||
#define GSF_INFILE_MSVBA_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GsfInfileMSVBA GsfInfileMSVBA;
|
||||
|
||||
#define GSF_INFILE_MSVBA_TYPE (gsf_infile_msvba_get_type ())
|
||||
#define GSF_INFILE_MSVBA(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_INFILE_MSVBA_TYPE, GsfInfileMSVBA))
|
||||
#define GSF_IS_INFILE_MSVBA(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_INFILE_MSVBA_TYPE))
|
||||
|
||||
GType gsf_infile_msvba_get_type (void);
|
||||
|
||||
GsfInfile *gsf_infile_msvba_new (GsfInfile *source, GError **err);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_INFILE_MSVBA_H */
|
||||
201
lib/libgsf-1.12.3/gsf/gsf-infile-stdio.c
Normal file
201
lib/libgsf-1.12.3/gsf/gsf-infile-stdio.c
Normal file
@@ -0,0 +1,201 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-infile-stdio.c: read a directory tree
|
||||
*
|
||||
* Copyright (C) 2004 Novell, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-infile.h>
|
||||
#include <gsf/gsf-infile-impl.h>
|
||||
#include <gsf/gsf-infile-stdio.h>
|
||||
#include <gsf/gsf-input-impl.h>
|
||||
#include <gsf/gsf-input-stdio.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <gsf/gsf-utils.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <glib/gdir.h>
|
||||
#include <string.h>
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
struct _GsfInfileStdio {
|
||||
GsfInfile parent;
|
||||
char *root;
|
||||
GList *children;
|
||||
};
|
||||
|
||||
typedef GsfInfileClass GsfInfileStdioClass;
|
||||
|
||||
static void
|
||||
gsf_infile_stdio_finalize (GObject *obj)
|
||||
{
|
||||
GsfInfileStdio *ifs = GSF_INFILE_STDIO (obj);
|
||||
|
||||
g_free (ifs->root);
|
||||
g_list_foreach (ifs->children, (GFunc) g_free, NULL);
|
||||
g_list_free (ifs->children);
|
||||
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static GsfInput *
|
||||
gsf_infile_stdio_dup (GsfInput *src_input, G_GNUC_UNUSED GError **err)
|
||||
{
|
||||
GsfInfileStdio *src = GSF_INFILE_STDIO (src_input);
|
||||
GsfInfileStdio *dst = g_object_new (gsf_infile_stdio_get_type(), NULL);
|
||||
GList *ptr;
|
||||
|
||||
dst->root = g_strdup (src->root);
|
||||
|
||||
for (ptr = src->children; ptr != NULL ; ptr = ptr->next)
|
||||
dst->children = g_list_prepend (dst->children,
|
||||
g_strdup (ptr->data));
|
||||
dst->children = g_list_reverse (dst->children);
|
||||
return GSF_INPUT (dst);
|
||||
}
|
||||
|
||||
static guint8 const *
|
||||
gsf_infile_stdio_read (G_GNUC_UNUSED GsfInput *input, G_GNUC_UNUSED size_t num_bytes,
|
||||
G_GNUC_UNUSED guint8 *buffer)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GsfInput *
|
||||
open_child (GsfInfileStdio *ifs, char const *name, GError **err)
|
||||
{
|
||||
GsfInput *child;
|
||||
char *path = g_build_filename (ifs->root, name, NULL);
|
||||
|
||||
if (g_file_test (path, G_FILE_TEST_IS_DIR))
|
||||
child = (GsfInput *) gsf_infile_stdio_new (path, err);
|
||||
else
|
||||
child = gsf_input_stdio_new (path, err);
|
||||
g_free (path);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
static GsfInput *
|
||||
gsf_infile_stdio_child_by_index (GsfInfile *infile, int target, GError **err)
|
||||
{
|
||||
GsfInfileStdio *ifs = GSF_INFILE_STDIO (infile);
|
||||
char const *name = g_list_nth_data (ifs->children, target);
|
||||
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
return open_child (ifs, name, err);
|
||||
}
|
||||
|
||||
static char const *
|
||||
gsf_infile_stdio_name_by_index (GsfInfile *infile, int target)
|
||||
{
|
||||
GsfInfileStdio *ifs = GSF_INFILE_STDIO (infile);
|
||||
|
||||
return g_list_nth_data (ifs->children, target);
|
||||
}
|
||||
|
||||
static GsfInput *
|
||||
gsf_infile_stdio_child_by_name (GsfInfile *infile, char const *name, GError **err)
|
||||
{
|
||||
GsfInfileStdio *ifs = GSF_INFILE_STDIO (infile);
|
||||
GList *ptr;
|
||||
|
||||
for (ptr = ifs->children; ptr != NULL; ptr = ptr->next)
|
||||
if (!strcmp (ptr->data, name))
|
||||
return open_child (ifs, name, err);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
gsf_infile_stdio_num_children (GsfInfile *infile)
|
||||
{
|
||||
GsfInfileStdio *ifs = GSF_INFILE_STDIO (infile);
|
||||
|
||||
return g_list_length (ifs->children);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_infile_stdio_init (GsfInfileStdio *ifs)
|
||||
{
|
||||
ifs->root = NULL;
|
||||
ifs->children = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_infile_stdio_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
GsfInputClass *input_class = GSF_INPUT_CLASS (gobject_class);
|
||||
GsfInfileClass *infile_class = GSF_INFILE_CLASS (gobject_class);
|
||||
|
||||
parent_class = g_type_class_peek (GSF_INFILE_TYPE);
|
||||
|
||||
gobject_class->finalize = gsf_infile_stdio_finalize;
|
||||
input_class->Dup = gsf_infile_stdio_dup;
|
||||
input_class->Read = gsf_infile_stdio_read;
|
||||
input_class->Seek = NULL;
|
||||
infile_class->num_children = gsf_infile_stdio_num_children;
|
||||
infile_class->name_by_index = gsf_infile_stdio_name_by_index;
|
||||
infile_class->child_by_index = gsf_infile_stdio_child_by_index;
|
||||
infile_class->child_by_name = gsf_infile_stdio_child_by_name;
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfInfileStdio, gsf_infile_stdio,
|
||||
gsf_infile_stdio_class_init, gsf_infile_stdio_init,
|
||||
GSF_INFILE_TYPE)
|
||||
|
||||
/**
|
||||
* gsf_infile_stdio_new :
|
||||
* @root : in locale dependent encoding
|
||||
* @err : optionally NULL.
|
||||
*
|
||||
* Returns a new file or NULL.
|
||||
**/
|
||||
GsfInfile *
|
||||
gsf_infile_stdio_new (char const *root, GError **err)
|
||||
{
|
||||
GsfInfileStdio *ifs;
|
||||
GDir *dir;
|
||||
char const *child;
|
||||
|
||||
dir = g_dir_open (root, 0, err);
|
||||
if (dir == NULL)
|
||||
return NULL;
|
||||
|
||||
ifs = g_object_new (gsf_infile_stdio_get_type(), NULL);
|
||||
ifs->root = g_strdup (root);
|
||||
|
||||
while ((child = g_dir_read_name (dir)))
|
||||
ifs->children = g_list_prepend (ifs->children,
|
||||
g_strdup (child));
|
||||
g_dir_close (dir);
|
||||
|
||||
gsf_input_set_name_from_filename (GSF_INPUT (ifs), root);
|
||||
|
||||
return GSF_INFILE (ifs);
|
||||
}
|
||||
40
lib/libgsf-1.12.3/gsf/gsf-infile-stdio.h
Normal file
40
lib/libgsf-1.12.3/gsf/gsf-infile-stdio.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-infile-stdio.h:
|
||||
*
|
||||
* Copyright (C) 2004 Novell, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_INFILE_STDIO_H
|
||||
#define GSF_INFILE_STDIO_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GsfInfileStdio GsfInfileStdio;
|
||||
|
||||
#define GSF_INFILE_STDIO_TYPE (gsf_infile_stdio_get_type ())
|
||||
#define GSF_INFILE_STDIO(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_INFILE_STDIO_TYPE, GsfInfileStdio))
|
||||
#define GSF_IS_INFILE_STDIO(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_INFILE_STDIO_TYPE))
|
||||
|
||||
GType gsf_infile_stdio_get_type (void);
|
||||
GsfInfile *gsf_infile_stdio_new (char const *root, GError **err);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_INFILE_STDIO_H */
|
||||
866
lib/libgsf-1.12.3/gsf/gsf-infile-zip.c
Normal file
866
lib/libgsf-1.12.3/gsf/gsf-infile-zip.c
Normal file
@@ -0,0 +1,866 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-infile-zip.c :
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
* Tambet Ingo (tambet@ximian.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-infile-impl.h>
|
||||
#include <gsf/gsf-infile-zip.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <gsf/gsf-utils.h>
|
||||
#include <gsf/gsf-zip-impl.h>
|
||||
#include <gsf/gsf-input-proxy.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#undef G_LOG_DOMAIN
|
||||
#define G_LOG_DOMAIN "libgsf:zip"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_SOURCE,
|
||||
PROP_COMPRESSION_LEVEL,
|
||||
PROP_INTERNAL_PARENT,
|
||||
};
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
typedef struct {
|
||||
guint16 entries;
|
||||
guint32 dir_pos;
|
||||
GList *dirent_list;
|
||||
GsfZipVDir *vdir;
|
||||
|
||||
int ref_count;
|
||||
} ZipInfo;
|
||||
|
||||
struct _GsfInfileZip {
|
||||
GsfInfile parent;
|
||||
|
||||
GsfInput *source;
|
||||
ZipInfo *info;
|
||||
|
||||
GsfZipVDir *vdir;
|
||||
|
||||
z_stream *stream;
|
||||
guint32 restlen;
|
||||
guint32 crestlen;
|
||||
|
||||
guint8 *buf;
|
||||
size_t buf_size;
|
||||
gsf_off_t seek_skipped;
|
||||
|
||||
GError *err;
|
||||
GsfInfileZip *dup_parent;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
GsfInfileClass parent_class;
|
||||
} GsfInfileZipClass;
|
||||
|
||||
#define GSF_INFILE_ZIP_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSF_INFILE_ZIP_TYPE, GsfInfileZipClass))
|
||||
#define GSF_IS_INFILE_ZIP_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSF_INFILE_ZIP_TYPE))
|
||||
|
||||
static GsfZipVDir *
|
||||
vdir_child_by_name (GsfZipVDir *vdir, char const *name)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
for (l = vdir->children; l; l = l->next) {
|
||||
GsfZipVDir *child = (GsfZipVDir *) l->data;
|
||||
if (strcmp (child->name, name) == 0)
|
||||
return child;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GsfZipVDir *
|
||||
vdir_child_by_index (GsfZipVDir *vdir, int target)
|
||||
{
|
||||
return g_slist_nth_data (vdir->children, target);
|
||||
}
|
||||
|
||||
static void
|
||||
vdir_insert (GsfZipVDir *vdir, char const * name, GsfZipDirent *dirent)
|
||||
{
|
||||
char const *p;
|
||||
char *dirname;
|
||||
GsfZipVDir *child;
|
||||
|
||||
p = strchr (name, ZIP_NAME_SEPARATOR);
|
||||
if (p) { /* A directory */
|
||||
dirname = g_strndup (name, (gsize) (p - name));
|
||||
child = vdir_child_by_name (vdir, dirname);
|
||||
if (!child) {
|
||||
child = gsf_vdir_new (dirname, TRUE, NULL);
|
||||
gsf_vdir_add_child (vdir, child);
|
||||
}
|
||||
g_free (dirname);
|
||||
if (*(p+1) != '\0') {
|
||||
name = p+1;
|
||||
vdir_insert (child, name, dirent);
|
||||
}
|
||||
} else { /* A simple file name */
|
||||
child = gsf_vdir_new (name, FALSE, dirent);
|
||||
gsf_vdir_add_child (vdir, child);
|
||||
}
|
||||
}
|
||||
|
||||
static gsf_off_t
|
||||
zip_find_trailer (GsfInfileZip *zip)
|
||||
{
|
||||
static guint8 const trailer_signature[] =
|
||||
{ 'P', 'K', 0x05, 0x06 };
|
||||
gsf_off_t offset, trailer_offset, filesize;
|
||||
gsf_off_t maplen;
|
||||
guint8 const *data;
|
||||
|
||||
filesize = gsf_input_size (zip->source);
|
||||
if (filesize < ZIP_TRAILER_SIZE)
|
||||
return -1;
|
||||
|
||||
trailer_offset = filesize;
|
||||
maplen = filesize & (ZIP_BUF_SIZE - 1);
|
||||
if (maplen == 0)
|
||||
maplen = ZIP_BUF_SIZE;
|
||||
offset = filesize - maplen; /* offset is now BUFSIZ aligned */
|
||||
|
||||
while (TRUE) {
|
||||
guchar *p, *s;
|
||||
|
||||
if (gsf_input_seek (zip->source, offset, G_SEEK_SET))
|
||||
return -1;
|
||||
|
||||
if ((data = gsf_input_read (zip->source, maplen, NULL)) == NULL)
|
||||
return -1;
|
||||
|
||||
p = (guchar *) data;
|
||||
|
||||
for (s = p + maplen - 1; (s >= p); s--, trailer_offset--) {
|
||||
if ((*s == 'P') &&
|
||||
(p + maplen - 1 - s > ZIP_TRAILER_SIZE - 2) &&
|
||||
!memcmp (s, trailer_signature, sizeof (trailer_signature))) {
|
||||
return --trailer_offset;
|
||||
}
|
||||
}
|
||||
|
||||
/* not found in currently mapped block, so update it if
|
||||
* there is some room in before. The requirements are..
|
||||
* (a) mappings should overlap so that trailer can cross BUFSIZ-boundary
|
||||
* (b) trailer cannot be farther away than 64K from fileend
|
||||
*/
|
||||
|
||||
/* outer loop cond */
|
||||
if (offset <= 0)
|
||||
return -1;
|
||||
|
||||
/* outer loop step */
|
||||
offset -= ZIP_BUF_SIZE / 2;
|
||||
maplen = MIN (filesize - offset, ZIP_BUF_SIZE);
|
||||
trailer_offset = offset + maplen;
|
||||
|
||||
if (filesize - offset > 64 * 1024)
|
||||
return -1;
|
||||
} /*outer loop*/
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static GsfZipDirent *
|
||||
zip_dirent_new_in (GsfInfileZip *zip, gsf_off_t *offset)
|
||||
{
|
||||
static guint8 const dirent_signature[] =
|
||||
{ 'P', 'K', 0x01, 0x02 };
|
||||
GsfZipDirent *dirent;
|
||||
guint8 const *data;
|
||||
guint16 name_len, extras_len, comment_len, compr_method;
|
||||
guint32 crc32, csize, usize, off;
|
||||
gchar *name;
|
||||
|
||||
/* Read data and check the header */
|
||||
if (gsf_input_seek (zip->source, *offset, G_SEEK_SET) ||
|
||||
NULL == (data = gsf_input_read (zip->source, ZIP_DIRENT_SIZE, NULL)) ||
|
||||
0 != memcmp (data, dirent_signature, sizeof (dirent_signature))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
name_len = GSF_LE_GET_GUINT16 (data + ZIP_DIRENT_NAME_SIZE);
|
||||
extras_len = GSF_LE_GET_GUINT16 (data + ZIP_DIRENT_EXTRAS_SIZE);
|
||||
comment_len = GSF_LE_GET_GUINT16 (data + ZIP_DIRENT_COMMENT_SIZE);
|
||||
|
||||
compr_method = GSF_LE_GET_GUINT16 (data + ZIP_DIRENT_COMPR_METHOD);
|
||||
crc32 = GSF_LE_GET_GUINT32 (data + ZIP_DIRENT_CRC32);
|
||||
csize = GSF_LE_GET_GUINT32 (data + ZIP_DIRENT_CSIZE);
|
||||
usize = GSF_LE_GET_GUINT32 (data + ZIP_DIRENT_USIZE);
|
||||
off = GSF_LE_GET_GUINT32 (data + ZIP_DIRENT_OFFSET);
|
||||
|
||||
if ((data = gsf_input_read (zip->source, name_len, NULL)) == NULL)
|
||||
return NULL;
|
||||
|
||||
name = g_new (gchar, (gulong) (name_len + 1));
|
||||
memcpy (name, data, name_len);
|
||||
name[name_len] = '\0';
|
||||
|
||||
dirent = gsf_zip_dirent_new ();
|
||||
dirent->name = name;
|
||||
|
||||
dirent->compr_method = compr_method;
|
||||
dirent->crc32 = crc32;
|
||||
dirent->csize = csize;
|
||||
dirent->usize = usize;
|
||||
dirent->offset = off;
|
||||
|
||||
*offset += ZIP_DIRENT_SIZE + name_len + extras_len + comment_len;
|
||||
|
||||
return dirent;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static ZipInfo *
|
||||
zip_info_ref (ZipInfo *info)
|
||||
{
|
||||
info->ref_count++;
|
||||
return info;
|
||||
}
|
||||
|
||||
static void
|
||||
zip_info_unref (ZipInfo *info)
|
||||
{
|
||||
GList *p;
|
||||
|
||||
if (info->ref_count-- != 1)
|
||||
return;
|
||||
|
||||
gsf_vdir_free (info->vdir, FALSE);
|
||||
for (p = info->dirent_list; p != NULL; p = p->next)
|
||||
gsf_zip_dirent_free ((GsfZipDirent *) p->data);
|
||||
|
||||
g_list_free (info->dirent_list);
|
||||
|
||||
g_free (info);
|
||||
}
|
||||
|
||||
/**
|
||||
* zip_dup :
|
||||
* @src :
|
||||
*
|
||||
* Return value: the partial duplicate.
|
||||
**/
|
||||
static GsfInfileZip *
|
||||
zip_dup (GsfInfileZip const *src, GError **err)
|
||||
{
|
||||
GsfInfileZip *dst;
|
||||
|
||||
g_return_val_if_fail (src != NULL, NULL);
|
||||
|
||||
dst = g_object_new (GSF_INFILE_ZIP_TYPE,
|
||||
"internal-parent", src,
|
||||
NULL);
|
||||
|
||||
if (dst->err) {
|
||||
if (err)
|
||||
*err = g_error_copy (dst->err);
|
||||
g_object_unref (dst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
/**
|
||||
* zip_read_dirents:
|
||||
* @zip :
|
||||
*
|
||||
* Read zip headers and do some sanity checking
|
||||
* along the way.
|
||||
*
|
||||
* Return value: TRUE on error setting zip->err.
|
||||
**/
|
||||
static gboolean
|
||||
zip_read_dirents (GsfInfileZip *zip)
|
||||
{
|
||||
guint8 const *trailer;
|
||||
guint16 entries, i;
|
||||
guint32 dir_pos;
|
||||
ZipInfo *info;
|
||||
gsf_off_t offset;
|
||||
|
||||
/* Find and check the trailing header */
|
||||
offset = zip_find_trailer (zip);
|
||||
if (offset < 0) {
|
||||
zip->err = g_error_new (gsf_input_error_id (), 0,
|
||||
"No Zip trailer");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (gsf_input_seek (zip->source, offset, G_SEEK_SET) ||
|
||||
NULL == (trailer = gsf_input_read (zip->source, ZIP_TRAILER_SIZE, NULL))) {
|
||||
zip->err = g_error_new (gsf_input_error_id (), 0,
|
||||
"Error reading Zip signature");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
entries = GSF_LE_GET_GUINT32 (trailer + ZIP_TRAILER_ENTRIES);
|
||||
dir_pos = GSF_LE_GET_GUINT32 (trailer + ZIP_TRAILER_DIR_POS);
|
||||
|
||||
info = g_new0 (ZipInfo, 1);
|
||||
zip->info = info;
|
||||
|
||||
info->ref_count = 1;
|
||||
info->entries = entries;
|
||||
info->dir_pos = dir_pos;
|
||||
|
||||
/* Read the directory */
|
||||
for (i = 0, offset = dir_pos; i < entries; i++) {
|
||||
GsfZipDirent *d;
|
||||
|
||||
d = zip_dirent_new_in (zip, &offset);
|
||||
if (d == NULL) {
|
||||
zip->err = g_error_new (gsf_input_error_id (), 0,
|
||||
"Error reading zip dirent");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
info->dirent_list = g_list_append (info->dirent_list, d);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
zip_build_vdirs (GsfInfileZip *zip)
|
||||
{
|
||||
GList *l;
|
||||
GsfZipDirent *dirent;
|
||||
ZipInfo *info = zip->info;
|
||||
|
||||
info->vdir = gsf_vdir_new ("", TRUE, NULL);
|
||||
for (l = info->dirent_list; l; l = l->next) {
|
||||
dirent = (GsfZipDirent *) l->data;
|
||||
vdir_insert (info->vdir, dirent->name, dirent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* zip_init_info :
|
||||
* @zip :
|
||||
*
|
||||
* Read zip headers and do some sanity checking
|
||||
* along the way.
|
||||
*
|
||||
* Return value: TRUE on error setting zip->err.
|
||||
**/
|
||||
static gboolean
|
||||
zip_init_info (GsfInfileZip *zip)
|
||||
{
|
||||
gboolean ret;
|
||||
|
||||
ret = zip_read_dirents (zip);
|
||||
if (ret != FALSE)
|
||||
return ret;
|
||||
zip_build_vdirs (zip);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* returns TRUE on error */
|
||||
static gboolean
|
||||
zip_child_init (GsfInfileZip *child, GError **errmsg)
|
||||
{
|
||||
static guint8 const header_signature[] =
|
||||
{ 'P', 'K', 0x03, 0x04 };
|
||||
guint8 const *data;
|
||||
guint16 name_len, extras_len;
|
||||
GsfZipDirent *dirent = child->vdir->dirent;
|
||||
|
||||
/* skip local header
|
||||
* should test tons of other info, but trust that those are correct
|
||||
**/
|
||||
|
||||
if (gsf_input_seek (child->source, (gsf_off_t) dirent->offset, G_SEEK_SET) ||
|
||||
NULL == (data = gsf_input_read (child->source, ZIP_FILE_HEADER_SIZE, NULL)) ||
|
||||
0 != memcmp (data, header_signature, sizeof (header_signature))) {
|
||||
if (errmsg != NULL)
|
||||
*errmsg = g_error_new (gsf_input_error_id (), 0,
|
||||
"Unable to read zip header.");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
name_len = GSF_LE_GET_GUINT16 (data + ZIP_FILE_HEADER_NAME_SIZE);
|
||||
extras_len = GSF_LE_GET_GUINT16 (data + ZIP_FILE_HEADER_EXTRAS_SIZE);
|
||||
|
||||
dirent->data_offset = dirent->offset + ZIP_FILE_HEADER_SIZE + name_len + extras_len;
|
||||
child->restlen = dirent->usize;
|
||||
child->crestlen = dirent->csize;
|
||||
|
||||
if (dirent->compr_method != GSF_ZIP_STORED) {
|
||||
int err;
|
||||
|
||||
if (!child->stream)
|
||||
child->stream = g_new0 (z_stream, 1);
|
||||
|
||||
err = inflateInit2 (child->stream, -MAX_WBITS);
|
||||
if (err != Z_OK) {
|
||||
if (errmsg != NULL)
|
||||
*errmsg = g_error_new (gsf_input_error_id (), 0,
|
||||
"problem uncompressing stream");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* GsfInput class functions */
|
||||
|
||||
static GsfInput *
|
||||
gsf_infile_zip_dup (GsfInput *src_input, GError **err)
|
||||
{
|
||||
GsfInfileZip const *src = GSF_INFILE_ZIP (src_input);
|
||||
GsfInfileZip *dst = zip_dup (src, err);
|
||||
|
||||
if (dst == NULL)
|
||||
return NULL;
|
||||
|
||||
dst->vdir = src->vdir;
|
||||
|
||||
if (dst->vdir->dirent && zip_child_init (dst, err)) {
|
||||
g_object_unref (dst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return GSF_INPUT (dst);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
zip_update_stream_in (GsfInfileZip *zip)
|
||||
{
|
||||
guint32 read_now;
|
||||
guint8 const *data;
|
||||
gsf_off_t pos;
|
||||
|
||||
if (zip->crestlen == 0)
|
||||
return FALSE;
|
||||
|
||||
read_now = MIN (zip->crestlen, ZIP_BLOCK_SIZE);
|
||||
|
||||
pos = zip->vdir->dirent->data_offset + zip->stream->total_in;
|
||||
if (gsf_input_seek (zip->source, pos, G_SEEK_SET))
|
||||
return FALSE;
|
||||
if ((data = gsf_input_read (zip->source, read_now, NULL)) == NULL)
|
||||
return FALSE;
|
||||
|
||||
zip->crestlen -= read_now;
|
||||
zip->stream->next_in = (unsigned char *) data; /* next input byte */
|
||||
zip->stream->avail_in = read_now; /* number of bytes available at next_in */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint8 const *
|
||||
gsf_infile_zip_read (GsfInput *input, size_t num_bytes, guint8 *buffer)
|
||||
{
|
||||
GsfInfileZip *zip = GSF_INFILE_ZIP (input);
|
||||
GsfZipVDir *vdir = zip->vdir;
|
||||
gsf_off_t pos;
|
||||
|
||||
if (zip->restlen < num_bytes)
|
||||
return NULL;
|
||||
|
||||
switch (vdir->dirent->compr_method) {
|
||||
case GSF_ZIP_STORED:
|
||||
zip->restlen -= num_bytes;
|
||||
pos = zip->vdir->dirent->data_offset + input->cur_offset;
|
||||
if (gsf_input_seek (zip->source, pos, G_SEEK_SET))
|
||||
return NULL;
|
||||
return gsf_input_read (zip->source, num_bytes, buffer);
|
||||
|
||||
case GSF_ZIP_DEFLATED:
|
||||
if (buffer == NULL) {
|
||||
if (zip->buf_size < num_bytes) {
|
||||
zip->buf_size = MAX (num_bytes, 256);
|
||||
g_free (zip->buf);
|
||||
zip->buf = g_new (guint8, zip->buf_size);
|
||||
}
|
||||
buffer = zip->buf;
|
||||
}
|
||||
|
||||
zip->stream->avail_out = num_bytes;
|
||||
zip->stream->next_out = (unsigned char *)buffer;
|
||||
|
||||
do {
|
||||
int err;
|
||||
int startlen;
|
||||
|
||||
if (zip->crestlen > 0 && zip->stream->avail_in == 0)
|
||||
if (!zip_update_stream_in (zip))
|
||||
break;
|
||||
|
||||
startlen = zip->stream->total_out;
|
||||
err = inflate(zip->stream, Z_NO_FLUSH);
|
||||
|
||||
if (err == Z_STREAM_END)
|
||||
zip->restlen = 0;
|
||||
else if (err == Z_OK)
|
||||
zip->restlen -= (zip->stream->total_out - startlen);
|
||||
else
|
||||
break;
|
||||
|
||||
} while (zip->restlen && zip->stream->avail_out);
|
||||
|
||||
return buffer;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_infile_zip_seek (GsfInput *input, gsf_off_t offset, GSeekType whence)
|
||||
{
|
||||
GsfInfileZip *zip = GSF_INFILE_ZIP (input);
|
||||
/* Global flag -- we don't want one per stream. */
|
||||
static gboolean warned = FALSE;
|
||||
gsf_off_t pos = offset;
|
||||
|
||||
/* Note, that pos has already been sanity checked. */
|
||||
switch (whence) {
|
||||
case G_SEEK_SET : break;
|
||||
case G_SEEK_CUR : pos += input->cur_offset; break;
|
||||
case G_SEEK_END : pos += input->size; break;
|
||||
default : return TRUE;
|
||||
}
|
||||
|
||||
if (zip->stream) {
|
||||
zip->stream->next_in = NULL;
|
||||
zip->stream->avail_in = 0;
|
||||
zip->stream->total_in = 0;
|
||||
}
|
||||
|
||||
if (zip_child_init (zip, NULL)) {
|
||||
g_warning ("failure initializing zip child");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
input->cur_offset = 0;
|
||||
if (gsf_input_seek_emulate (input, pos))
|
||||
return TRUE;
|
||||
|
||||
zip->seek_skipped += pos;
|
||||
if (!warned &&
|
||||
zip->seek_skipped != pos && /* Don't warn for single seek. */
|
||||
zip->seek_skipped >= 1000000) {
|
||||
warned = TRUE;
|
||||
g_warning ("Seeking in zip child streams is awfully slow.");
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* GsfInfile class functions */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
static GsfInput *
|
||||
gsf_infile_zip_new_child (GsfInfileZip *parent, GsfZipVDir *vdir, GError **err)
|
||||
{
|
||||
GsfInfileZip *child;
|
||||
GsfZipDirent *dirent = vdir->dirent;
|
||||
child = zip_dup (parent, err);
|
||||
|
||||
if (child == NULL)
|
||||
return NULL;
|
||||
|
||||
gsf_input_set_name (GSF_INPUT (child), vdir->name);
|
||||
gsf_input_set_container (GSF_INPUT (child), GSF_INFILE (parent));
|
||||
|
||||
child->vdir = vdir;
|
||||
|
||||
if (dirent) {
|
||||
gsf_input_set_size (GSF_INPUT (child),
|
||||
(gsf_off_t) dirent->usize);
|
||||
if (zip_child_init (child, err) != FALSE) {
|
||||
g_object_unref (child);
|
||||
return NULL;
|
||||
}
|
||||
} else
|
||||
gsf_input_set_size (GSF_INPUT (child), 0);
|
||||
|
||||
return GSF_INPUT (child);
|
||||
}
|
||||
|
||||
static GsfInput *
|
||||
gsf_infile_zip_child_by_index (GsfInfile *infile, int target, GError **err)
|
||||
{
|
||||
GsfInfileZip *zip = GSF_INFILE_ZIP (infile);
|
||||
GsfZipVDir *child_vdir = vdir_child_by_index (zip->vdir, target);
|
||||
|
||||
if (child_vdir)
|
||||
return gsf_infile_zip_new_child (zip, child_vdir, err);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char const *
|
||||
gsf_infile_zip_name_by_index (GsfInfile *infile, int target)
|
||||
{
|
||||
GsfInfileZip *zip = GSF_INFILE_ZIP (infile);
|
||||
GsfZipVDir *child_vdir = vdir_child_by_index (zip->vdir, target);
|
||||
|
||||
if (child_vdir)
|
||||
return child_vdir->name;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GsfInput *
|
||||
gsf_infile_zip_child_by_name (GsfInfile *infile, char const *name, GError **err)
|
||||
{
|
||||
GsfInfileZip *zip = GSF_INFILE_ZIP (infile);
|
||||
GsfZipVDir *child_vdir = vdir_child_by_name (zip->vdir, name);
|
||||
|
||||
if (child_vdir)
|
||||
return gsf_infile_zip_new_child (zip, child_vdir, err);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
gsf_infile_zip_num_children (GsfInfile *infile)
|
||||
{
|
||||
GsfInfileZip *zip = GSF_INFILE_ZIP (infile);
|
||||
|
||||
g_return_val_if_fail (zip->vdir != NULL, -1);
|
||||
|
||||
if (!zip->vdir->is_directory)
|
||||
return -1;
|
||||
return g_slist_length (zip->vdir->children);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_infile_zip_finalize (GObject *obj)
|
||||
{
|
||||
GsfInfileZip *zip = GSF_INFILE_ZIP (obj);
|
||||
|
||||
if (zip->source != NULL) {
|
||||
g_object_unref (G_OBJECT (zip->source));
|
||||
zip->source = NULL;
|
||||
}
|
||||
if (zip->info != NULL) {
|
||||
zip_info_unref (zip->info);
|
||||
zip->info = NULL;
|
||||
}
|
||||
|
||||
if (zip->stream)
|
||||
(void) inflateEnd (zip->stream);
|
||||
g_free (zip->stream);
|
||||
g_free (zip->buf);
|
||||
|
||||
g_clear_error (&zip->err);
|
||||
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static GObject*
|
||||
gsf_infile_zip_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_params)
|
||||
{
|
||||
GsfInfileZip *zip;
|
||||
|
||||
zip = (GsfInfileZip *)(parent_class->constructor (type,
|
||||
n_construct_properties,
|
||||
construct_params));
|
||||
if (zip->dup_parent) {
|
||||
/* Special call from zip_dup. */
|
||||
zip->source = gsf_input_dup (zip->dup_parent->source, &zip->err);
|
||||
zip->info = zip_info_ref (zip->dup_parent->info);
|
||||
zip->dup_parent = NULL;
|
||||
} else {
|
||||
if (!zip_init_info (zip))
|
||||
zip->vdir = zip->info->vdir;
|
||||
}
|
||||
|
||||
return (GObject *)zip;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gsf_infile_zip_init (GObject *obj)
|
||||
{
|
||||
GsfInfileZip *zip = (GsfInfileZip *)obj;
|
||||
zip->source = NULL;
|
||||
zip->info = NULL;
|
||||
zip->vdir = NULL;
|
||||
zip->stream = NULL;
|
||||
zip->restlen = 0;
|
||||
zip->crestlen = 0;
|
||||
zip->buf = NULL;
|
||||
zip->buf_size = 0;
|
||||
zip->seek_skipped = 0;
|
||||
zip->err = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_infile_zip_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GsfInfileZip *zip = (GsfInfileZip *)object;
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_SOURCE:
|
||||
g_value_set_object (value, zip->source);
|
||||
break;
|
||||
case PROP_COMPRESSION_LEVEL:
|
||||
g_value_set_int (value,
|
||||
zip->vdir->dirent
|
||||
? zip->vdir->dirent->compr_method
|
||||
: 0);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_infile_zip_set_source (GsfInfileZip *zip, GsfInput *src)
|
||||
{
|
||||
if (src)
|
||||
src = gsf_input_proxy_new (src);
|
||||
if (zip->source)
|
||||
g_object_unref (zip->source);
|
||||
zip->source = src;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_infile_zip_set_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue const *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GsfInfileZip *zip = (GsfInfileZip *)object;
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_SOURCE:
|
||||
gsf_infile_zip_set_source (zip, g_value_get_object (value));
|
||||
break;
|
||||
case PROP_INTERNAL_PARENT:
|
||||
zip->dup_parent = g_value_get_object (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gsf_infile_zip_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
GsfInputClass *input_class = GSF_INPUT_CLASS (gobject_class);
|
||||
GsfInfileClass *infile_class = GSF_INFILE_CLASS (gobject_class);
|
||||
|
||||
gobject_class->constructor = gsf_infile_zip_constructor;
|
||||
gobject_class->finalize = gsf_infile_zip_finalize;
|
||||
gobject_class->get_property = gsf_infile_zip_get_property;
|
||||
gobject_class->set_property = gsf_infile_zip_set_property;
|
||||
|
||||
input_class->Dup = gsf_infile_zip_dup;
|
||||
input_class->Read = gsf_infile_zip_read;
|
||||
input_class->Seek = gsf_infile_zip_seek;
|
||||
infile_class->num_children = gsf_infile_zip_num_children;
|
||||
infile_class->name_by_index = gsf_infile_zip_name_by_index;
|
||||
infile_class->child_by_index = gsf_infile_zip_child_by_index;
|
||||
infile_class->child_by_name = gsf_infile_zip_child_by_name;
|
||||
|
||||
parent_class = g_type_class_peek_parent (gobject_class);
|
||||
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_SOURCE,
|
||||
g_param_spec_object ("source",
|
||||
"Source",
|
||||
"The archive being interpreted.",
|
||||
GSF_INPUT_TYPE,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_COMPRESSION_LEVEL,
|
||||
g_param_spec_int ("compression-level",
|
||||
"Compression Level",
|
||||
"The level of compression used, zero meaning none.",
|
||||
0, 10,
|
||||
0,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READABLE));
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_INTERNAL_PARENT,
|
||||
g_param_spec_object ("internal-parent",
|
||||
"",
|
||||
"Internal use only",
|
||||
GSF_INFILE_ZIP_TYPE,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_WRITABLE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfInfileZip, gsf_infile_zip,
|
||||
gsf_infile_zip_class_init, gsf_infile_zip_init,
|
||||
GSF_INFILE_TYPE)
|
||||
|
||||
/**
|
||||
* gsf_infile_zip_new :
|
||||
* @source : A base #GsfInput
|
||||
* @err : A #GError, optionally %null
|
||||
*
|
||||
* Opens the root directory of a Zip file.
|
||||
* NOTE : adds a reference to @source
|
||||
*
|
||||
* Returns : the new zip file handler
|
||||
**/
|
||||
GsfInfile *
|
||||
gsf_infile_zip_new (GsfInput *source, GError **err)
|
||||
{
|
||||
GsfInfileZip *zip;
|
||||
|
||||
g_return_val_if_fail (GSF_IS_INPUT (source), NULL);
|
||||
|
||||
zip = g_object_new (GSF_INFILE_ZIP_TYPE,
|
||||
"source", source,
|
||||
NULL);
|
||||
if (zip->err) {
|
||||
if (err)
|
||||
*err = g_error_copy (zip->err);
|
||||
g_object_unref (zip);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return GSF_INFILE (zip);
|
||||
}
|
||||
40
lib/libgsf-1.12.3/gsf/gsf-infile-zip.h
Normal file
40
lib/libgsf-1.12.3/gsf/gsf-infile-zip.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-infile-zip.h:
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_INFILE_ZIP_H
|
||||
#define GSF_INFILE_ZIP_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GsfInfileZip GsfInfileZip;
|
||||
|
||||
#define GSF_INFILE_ZIP_TYPE (gsf_infile_zip_get_type ())
|
||||
#define GSF_INFILE_ZIP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_INFILE_ZIP_TYPE, GsfInfileZip))
|
||||
#define GSF_IS_INFILE_ZIP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_INFILE_ZIP_TYPE))
|
||||
|
||||
GType gsf_infile_zip_get_type (void);
|
||||
GsfInfile *gsf_infile_zip_new (GsfInput *source, GError **err);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_INFILE_ZIP_H */
|
||||
159
lib/libgsf-1.12.3/gsf/gsf-infile.c
Normal file
159
lib/libgsf-1.12.3/gsf/gsf-infile.c
Normal file
@@ -0,0 +1,159 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-infile.c :
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-infile-impl.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#define GET_CLASS(instance) G_TYPE_INSTANCE_GET_CLASS (instance, GSF_INFILE_TYPE, GsfInfileClass)
|
||||
|
||||
/**
|
||||
* gsf_infile_num_children :
|
||||
* @infile : the structured storage
|
||||
*
|
||||
* Returns the number of children the storage has, or -1 if the storage can not
|
||||
* have children.
|
||||
**/
|
||||
int
|
||||
gsf_infile_num_children (GsfInfile *infile)
|
||||
{
|
||||
g_return_val_if_fail (infile != NULL, -1);
|
||||
|
||||
return GET_CLASS (infile)->num_children (infile);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_infile_name_by_index :
|
||||
* @infile :
|
||||
* @i :
|
||||
*
|
||||
* Returns the utf8 encoded name of the @i-th child
|
||||
* NOTE : DO NOT FREE THE STRING
|
||||
**/
|
||||
char const *
|
||||
gsf_infile_name_by_index (GsfInfile *infile, int i)
|
||||
{
|
||||
g_return_val_if_fail (infile != NULL, NULL);
|
||||
|
||||
return GET_CLASS (infile)->name_by_index (infile, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_infile_child_by_index :
|
||||
* @infile :
|
||||
* @i :
|
||||
*
|
||||
* TODO : For 2.0 api will change to include a GError.
|
||||
* Returns a newly created child which must be unrefed.
|
||||
**/
|
||||
GsfInput *
|
||||
gsf_infile_child_by_index (GsfInfile *infile, int i)
|
||||
{
|
||||
GError *err = NULL;
|
||||
GsfInput *res;
|
||||
|
||||
g_return_val_if_fail (GSF_INFILE (infile) != NULL, NULL);
|
||||
|
||||
res = GET_CLASS (infile)->child_by_index (infile, i, &err);
|
||||
|
||||
if (err != NULL) {
|
||||
char const *iname = gsf_input_name (GSF_INPUT (infile));
|
||||
g_warning ("Unable to get child[%d] for infile '%s' because : %s",
|
||||
i, iname ? iname : "?", err->message);
|
||||
g_error_free (err);
|
||||
g_return_val_if_fail (res == NULL, NULL); /* be anal */
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_infile_child_by_name :
|
||||
* @infile :
|
||||
* @name :
|
||||
*
|
||||
* TODO : For 2.0 api will change to include a GError.
|
||||
* Returns a newly created child which must be unrefed.
|
||||
**/
|
||||
GsfInput *
|
||||
gsf_infile_child_by_name (GsfInfile *infile, char const *name)
|
||||
{
|
||||
GError *err = NULL;
|
||||
GsfInput *res;
|
||||
|
||||
g_return_val_if_fail (GSF_INFILE (infile) != NULL, NULL);
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
|
||||
res = GET_CLASS (infile)->child_by_name (infile, name, &err);
|
||||
|
||||
if (err != NULL) {
|
||||
char const *iname = gsf_input_name (GSF_INPUT (infile));
|
||||
g_warning ("Unable to get child['%s'] for infile '%s' because : %s",
|
||||
name, iname ? iname : "?", err->message);
|
||||
g_error_free (err);
|
||||
g_return_val_if_fail (res == NULL, NULL); /* be anal */
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_infile_child_by_vname :
|
||||
* @infile :
|
||||
* @name : A %null terminated list of names
|
||||
* @Varargs : the rest of the names
|
||||
*
|
||||
* Returns a newly created child which must be unrefed.
|
||||
**/
|
||||
GsfInput *
|
||||
gsf_infile_child_by_vname (GsfInfile *infile, char const *name, ...)
|
||||
{
|
||||
va_list ap;
|
||||
GsfInput *child = GSF_INPUT (infile);
|
||||
GsfInfile *tmp = NULL;
|
||||
|
||||
g_return_val_if_fail (GSF_IS_INFILE (infile), NULL);
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
|
||||
va_start (ap, name);
|
||||
while (1) {
|
||||
child = gsf_infile_child_by_name (infile, name);
|
||||
|
||||
name = va_arg (ap, char *);
|
||||
if (tmp != NULL)
|
||||
g_object_unref (G_OBJECT (tmp));
|
||||
if (name == NULL)
|
||||
break;
|
||||
if (child == NULL)
|
||||
break;
|
||||
|
||||
g_return_val_if_fail (GSF_IS_INFILE (child), NULL);
|
||||
|
||||
infile = tmp = GSF_INFILE (child);
|
||||
}
|
||||
va_end (ap);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
GSF_CLASS_ABSTRACT (GsfInfile, gsf_infile, NULL, NULL, GSF_INPUT_TYPE)
|
||||
44
lib/libgsf-1.12.3/gsf/gsf-infile.h
Normal file
44
lib/libgsf-1.12.3/gsf/gsf-infile.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-infile.h:
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_INFILE_H
|
||||
#define GSF_INFILE_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSF_INFILE_TYPE (gsf_infile_get_type ())
|
||||
#define GSF_INFILE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_INFILE_TYPE, GsfInfile))
|
||||
#define GSF_IS_INFILE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_INFILE_TYPE))
|
||||
|
||||
GType gsf_infile_get_type (void);
|
||||
|
||||
int gsf_infile_num_children (GsfInfile *infile);
|
||||
char const *gsf_infile_name_by_index (GsfInfile *infile, int i);
|
||||
GsfInput *gsf_infile_child_by_index (GsfInfile *infile, int i);
|
||||
GsfInput *gsf_infile_child_by_name (GsfInfile *infile, char const *name);
|
||||
GsfInput *gsf_infile_child_by_vname (GsfInfile *infile, char const *name, ...);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_INFILE_H */
|
||||
109
lib/libgsf-1.12.3/gsf/gsf-input-bzip.c
Normal file
109
lib/libgsf-1.12.3/gsf/gsf-input-bzip.c
Normal file
@@ -0,0 +1,109 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-input-iochannel.c: BZ2 based input
|
||||
*
|
||||
* Copyright (C) 2003-2004 Dom Lachowicz (cinamod@hotmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf-input-bzip.h>
|
||||
#include <gsf-output-memory.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_BZ2
|
||||
/* For getting FILE. Don't ask. */
|
||||
#include <stdio.h>
|
||||
#include <bzlib.h>
|
||||
#define BZ_BUFSIZ 1024
|
||||
#endif
|
||||
|
||||
/**
|
||||
* gsf_input_memory_new_from_bzip :
|
||||
* @source : a #GsfInput
|
||||
* @err : a #GError
|
||||
*
|
||||
* Returns a new #GsfInputMemory or NULL.
|
||||
*/
|
||||
GsfInput *
|
||||
gsf_input_memory_new_from_bzip (GsfInput *source, GError **err)
|
||||
{
|
||||
#ifndef HAVE_BZ2
|
||||
if (err)
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"BZ2 support not enabled");
|
||||
return NULL;
|
||||
#else
|
||||
bz_stream bzstm;
|
||||
GsfInput *mem = NULL;
|
||||
GsfOutput *sink = NULL;
|
||||
guint8 out_buf [BZ_BUFSIZ];
|
||||
int bzerr = BZ_OK;
|
||||
|
||||
g_return_val_if_fail (source != NULL, NULL);
|
||||
|
||||
memset (&bzstm, 0, sizeof (bzstm));
|
||||
if (BZ_OK != BZ2_bzDecompressInit (&bzstm, 0, 0)) {
|
||||
if (err)
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"BZ2 decompress init failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sink = gsf_output_memory_new ();
|
||||
|
||||
for (;;) {
|
||||
bzstm.next_out = (char *)out_buf;
|
||||
bzstm.avail_out = (unsigned int)sizeof (out_buf);
|
||||
|
||||
if (bzstm.avail_in == 0) {
|
||||
bzstm.avail_in = (unsigned int)MIN (gsf_input_remaining (source), BZ_BUFSIZ);
|
||||
bzstm.next_in = (char *)gsf_input_read (source, bzstm.avail_in, NULL);
|
||||
}
|
||||
|
||||
bzerr = BZ2_bzDecompress (&bzstm);
|
||||
if (bzerr != BZ_OK && bzerr != BZ_STREAM_END) {
|
||||
if (err)
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"BZ2 decompress failed");
|
||||
BZ2_bzDecompressEnd (&bzstm);
|
||||
gsf_output_close (sink);
|
||||
g_object_unref (G_OBJECT (sink));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gsf_output_write (sink, BZ_BUFSIZ - bzstm.avail_out, out_buf);
|
||||
if (bzerr == BZ_STREAM_END)
|
||||
break;
|
||||
}
|
||||
|
||||
gsf_output_close (sink);
|
||||
|
||||
if (BZ_OK != BZ2_bzDecompressEnd (&bzstm)) {
|
||||
if (err)
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"BZ2 decompress end failed");
|
||||
g_object_unref (G_OBJECT (sink));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mem = gsf_input_memory_new_clone (
|
||||
gsf_output_memory_get_bytes (GSF_OUTPUT_MEMORY (sink)),
|
||||
gsf_output_size (sink));
|
||||
g_object_unref (G_OBJECT (sink));
|
||||
return mem;
|
||||
#endif
|
||||
}
|
||||
33
lib/libgsf-1.12.3/gsf/gsf-input-bzip.h
Normal file
33
lib/libgsf-1.12.3/gsf/gsf-input-bzip.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-input-bzip.h: wrapper to compress to bzipped output
|
||||
*
|
||||
* Copyright (C) 2003-2004 Dom Lachowicz (cinamod@hotmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_INPUT_BZIP_H
|
||||
#define GSF_INPUT_BZIP_H
|
||||
|
||||
#include <gsf/gsf-input-memory.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GsfInput *gsf_input_memory_new_from_bzip (GsfInput *source, GError **err);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_INPUT_BZIP_H */
|
||||
533
lib/libgsf-1.12.3/gsf/gsf-input-gzip.c
Normal file
533
lib/libgsf-1.12.3/gsf/gsf-input-gzip.c
Normal file
@@ -0,0 +1,533 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-input-gzip.c: wrapper to uncompress gzipped input
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
* Copyright (C) 2005 Morten Welinder (terra@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-input-gzip.h>
|
||||
#include <gsf/gsf-input-impl.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <gsf/gsf-utils.h>
|
||||
|
||||
#include <zlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define Z_BUFSIZE 0x100
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
struct _GsfInputGZip {
|
||||
GsfInput input;
|
||||
|
||||
GsfInput *source; /* compressed data */
|
||||
gboolean raw; /* No header and no trailer. */
|
||||
GError *err;
|
||||
gsf_off_t uncompressed_size;
|
||||
gboolean stop_byte_added;
|
||||
|
||||
z_stream stream;
|
||||
guint8 const *gzipped_data;
|
||||
uLong crc; /* crc32 of uncompressed data */
|
||||
|
||||
guint8 *buf;
|
||||
size_t buf_size;
|
||||
|
||||
size_t header_size, trailer_size;
|
||||
gsf_off_t seek_skipped;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
GsfInputClass input_class;
|
||||
} GsfInputGZipClass;
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_RAW,
|
||||
PROP_SOURCE,
|
||||
PROP_UNCOMPRESSED_SIZE
|
||||
};
|
||||
|
||||
/* 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 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;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
init_zip (GsfInputGZip *gzip, GError **err)
|
||||
{
|
||||
gsf_off_t cur_pos;
|
||||
|
||||
if (Z_OK != inflateInit2 (&(gzip->stream), -MAX_WBITS)) {
|
||||
if (err != NULL)
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"Unable to initialize zlib");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
cur_pos = gsf_input_tell (gzip->source);
|
||||
if (gsf_input_seek (gzip->source, 0, G_SEEK_SET)) {
|
||||
if (err)
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"Failed to rewind source");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (check_header (gzip) != FALSE) {
|
||||
if (err != NULL)
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"Invalid gzip header");
|
||||
if (gsf_input_seek (gzip->source, cur_pos, G_SEEK_SET)) {
|
||||
g_warning ("attempt to restore position failed ??");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_input_gzip_new :
|
||||
* @source : The underlying data source.
|
||||
* @err : optionally NULL.
|
||||
*
|
||||
* Adds a reference to @source.
|
||||
*
|
||||
* Returns a new file or NULL.
|
||||
**/
|
||||
GsfInput *
|
||||
gsf_input_gzip_new (GsfInput *source, GError **err)
|
||||
{
|
||||
GsfInputGZip *gzip;
|
||||
|
||||
g_return_val_if_fail (GSF_IS_INPUT (source), NULL);
|
||||
|
||||
gzip = g_object_new (GSF_INPUT_GZIP_TYPE,
|
||||
"source", source,
|
||||
NULL);
|
||||
if (gzip->err) {
|
||||
if (err)
|
||||
*err = g_error_copy (gzip->err);
|
||||
g_object_unref (gzip);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return GSF_INPUT (gzip);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_gzip_finalize (GObject *obj)
|
||||
{
|
||||
GsfInputGZip *gzip = (GsfInputGZip *)obj;
|
||||
|
||||
if (gzip->source != NULL) {
|
||||
g_object_unref (G_OBJECT (gzip->source));
|
||||
gzip->source = NULL;
|
||||
}
|
||||
|
||||
g_free (gzip->buf);
|
||||
|
||||
if (gzip->stream.state != NULL)
|
||||
inflateEnd (&(gzip->stream));
|
||||
|
||||
g_clear_error (&gzip->err);
|
||||
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static GsfInput *
|
||||
gsf_input_gzip_dup (GsfInput *src_input, GError **err)
|
||||
{
|
||||
GsfInputGZip const *src = (GsfInputGZip *)src_input;
|
||||
GsfInputGZip *dst;
|
||||
GsfInput *src_source_copy;
|
||||
|
||||
if (src->source) {
|
||||
src_source_copy = gsf_input_dup (src->source, err);
|
||||
if (err)
|
||||
return NULL;
|
||||
} else
|
||||
src_source_copy = NULL;
|
||||
|
||||
dst = g_object_new (GSF_INPUT_GZIP_TYPE,
|
||||
"source", src_source_copy,
|
||||
"raw", src->raw,
|
||||
NULL);
|
||||
if (src_source_copy)
|
||||
g_object_unref (src_source_copy);
|
||||
|
||||
if (src->err) {
|
||||
g_clear_error (&dst->err);
|
||||
dst->err = g_error_copy (src->err);
|
||||
} else if (dst->err) {
|
||||
if (err)
|
||||
*err = g_error_copy (dst->err);
|
||||
g_object_unref (dst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return GSF_INPUT (dst);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_input_gzip_seek (GsfInput *input, gsf_off_t offset, GSeekType whence)
|
||||
{
|
||||
GsfInputGZip *gzip = GSF_INPUT_GZIP (input);
|
||||
/* Global flag -- we don't want one per stream. */
|
||||
static gboolean warned = FALSE;
|
||||
gsf_off_t pos = offset;
|
||||
|
||||
/* Note, that pos has already been sanity checked. */
|
||||
switch (whence) {
|
||||
case G_SEEK_SET : break;
|
||||
case G_SEEK_CUR : pos += input->cur_offset; break;
|
||||
case G_SEEK_END : pos += input->size; break;
|
||||
default : return TRUE;
|
||||
}
|
||||
|
||||
if (pos < input->cur_offset) {
|
||||
if (gsf_input_seek (gzip->source,
|
||||
(gsf_off_t)gzip->header_size,
|
||||
G_SEEK_SET))
|
||||
return TRUE;
|
||||
gzip->crc = crc32 (0L, Z_NULL, 0);
|
||||
gzip->stream.avail_in = 0;
|
||||
if (inflateReset (&(gzip->stream)) != Z_OK)
|
||||
return TRUE;
|
||||
input->cur_offset = 0;
|
||||
}
|
||||
|
||||
if (gsf_input_seek_emulate (input, pos))
|
||||
return TRUE;
|
||||
|
||||
gzip->seek_skipped += pos;
|
||||
if (!warned &&
|
||||
gzip->seek_skipped != pos && /* Don't warn for single seek. */
|
||||
gzip->seek_skipped >= 1000000) {
|
||||
warned = TRUE;
|
||||
g_warning ("Seeking in gzipped streams is awfully slow.");
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_gzip_init (GObject *obj)
|
||||
{
|
||||
GsfInputGZip *gzip = GSF_INPUT_GZIP (obj);
|
||||
|
||||
gzip->source = NULL;
|
||||
gzip->raw = FALSE;
|
||||
gzip->uncompressed_size = -1;
|
||||
gzip->err = NULL;
|
||||
gzip->stream.zalloc = (alloc_func)0;
|
||||
gzip->stream.zfree = (free_func)0;
|
||||
gzip->stream.opaque = (voidpf)0;
|
||||
gzip->stream.next_in = Z_NULL;
|
||||
gzip->stream.next_out = Z_NULL;
|
||||
gzip->stream.avail_in = gzip->stream.avail_out = 0;
|
||||
gzip->crc = crc32 (0L, Z_NULL, 0);
|
||||
gzip->buf = NULL;
|
||||
gzip->buf_size = 0;
|
||||
gzip->seek_skipped = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_gzip_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GsfInputGZip *gzip = (GsfInputGZip *)object;
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_RAW:
|
||||
g_value_set_boolean (value, gzip->raw);
|
||||
break;
|
||||
case PROP_SOURCE:
|
||||
g_value_set_object (value, gzip->source);
|
||||
break;
|
||||
case PROP_UNCOMPRESSED_SIZE:
|
||||
g_value_set_int64 (value, gzip->uncompressed_size);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_gzip_set_source (GsfInputGZip *gzip, GsfInput *source)
|
||||
{
|
||||
if (source)
|
||||
g_object_ref (GSF_INPUT (source));
|
||||
if (gzip->source)
|
||||
g_object_unref (gzip->source);
|
||||
gzip->source = source;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_gzip_set_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue const *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GsfInputGZip *gzip = (GsfInputGZip *)object;
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_RAW:
|
||||
gzip->raw = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_SOURCE:
|
||||
gsf_input_gzip_set_source (gzip, g_value_get_object (value));
|
||||
break;
|
||||
case PROP_UNCOMPRESSED_SIZE:
|
||||
gzip->uncompressed_size = g_value_get_int64 (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static GObject*
|
||||
gsf_input_gzip_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_params)
|
||||
{
|
||||
GsfInputGZip *gzip;
|
||||
|
||||
gzip = (GsfInputGZip *)(parent_class->constructor (type,
|
||||
n_construct_properties,
|
||||
construct_params));
|
||||
|
||||
if (!gzip->source) {
|
||||
g_clear_error (&gzip->err);
|
||||
gzip->err = g_error_new (gsf_input_error_id (), 0,
|
||||
"NULL source");
|
||||
} else if (gzip->raw && gzip->uncompressed_size < 0) {
|
||||
g_clear_error (&gzip->err);
|
||||
gzip->err = g_error_new (gsf_input_error_id (), 0,
|
||||
"Uncompressed size not set");
|
||||
} else if (init_zip (gzip, &gzip->err) != FALSE) {
|
||||
/* Nothing more. */
|
||||
}
|
||||
|
||||
return (GObject *)gzip;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_gzip_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
GsfInputClass *input_class = GSF_INPUT_CLASS (gobject_class);
|
||||
|
||||
gobject_class->constructor = gsf_input_gzip_constructor;
|
||||
gobject_class->finalize = gsf_input_gzip_finalize;
|
||||
gobject_class->set_property = gsf_input_gzip_set_property;
|
||||
gobject_class->get_property = gsf_input_gzip_get_property;
|
||||
input_class->Dup = gsf_input_gzip_dup;
|
||||
input_class->Read = gsf_input_gzip_read;
|
||||
input_class->Seek = gsf_input_gzip_seek;
|
||||
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_RAW,
|
||||
g_param_spec_boolean ("raw", "Raw",
|
||||
"Whether to read compressed data with no header and no trailer.",
|
||||
FALSE,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_SOURCE,
|
||||
g_param_spec_object ("source", "Source",
|
||||
"Where the compressed data comes from.",
|
||||
GSF_INPUT_TYPE,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
/**
|
||||
* GsfInputGzip:uncompressed_size:
|
||||
*
|
||||
* The size that the data will have after uncompression.
|
||||
* The is mandatory for raw streams and if the uncompressed size is
|
||||
* larger than 4GB.
|
||||
*/
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_UNCOMPRESSED_SIZE,
|
||||
g_param_spec_int64 ("uncompressed-size", "Size after decompression",
|
||||
"The source's uncompressed size",
|
||||
-1, G_MAXINT64, -1,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
parent_class = g_type_class_peek_parent (gobject_class);
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfInputGZip, gsf_input_gzip,
|
||||
gsf_input_gzip_class_init, gsf_input_gzip_init, GSF_INPUT_TYPE)
|
||||
40
lib/libgsf-1.12.3/gsf/gsf-input-gzip.h
Normal file
40
lib/libgsf-1.12.3/gsf/gsf-input-gzip.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-input-gzip.h: wrapper to uncompress gzipped input
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_INPUT_GZIP_H
|
||||
#define GSF_INPUT_GZIP_H
|
||||
|
||||
#include "gsf-input.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSF_INPUT_GZIP_TYPE (gsf_input_gzip_get_type ())
|
||||
#define GSF_INPUT_GZIP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_INPUT_GZIP_TYPE, GsfInputGZip))
|
||||
#define GSF_IS_INPUT_GZIP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_INPUT_GZIP_TYPE))
|
||||
|
||||
typedef struct _GsfInputGZip GsfInputGZip;
|
||||
|
||||
GType gsf_input_gzip_get_type (void);
|
||||
GsfInput *gsf_input_gzip_new (GsfInput *source, GError **err);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_INPUT_GZIP_H */
|
||||
69
lib/libgsf-1.12.3/gsf/gsf-input-impl.h
Normal file
69
lib/libgsf-1.12.3/gsf/gsf-input-impl.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-input.h-impl.h: interface for used by the ole layer to read raw data
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_INPUT_IMPL_H
|
||||
#define GSF_INPUT_IMPL_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
#include <gsf/gsf-input.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
struct _GsfInput {
|
||||
GObject g_object;
|
||||
|
||||
gsf_off_t size, cur_offset;
|
||||
char *name;
|
||||
GsfInfile *container;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
GObjectClass g_object_class;
|
||||
|
||||
GsfInput *(*Dup) (GsfInput *input, GError **err);
|
||||
const guint8 *(*Read) (GsfInput *input, size_t num_bytes,
|
||||
guint8 *optional_buffer);
|
||||
gboolean (*Seek) (GsfInput *input, gsf_off_t offset,
|
||||
GSeekType whence);
|
||||
GsfInput *(*OpenSibling) (GsfInput const *input,
|
||||
char const *path, GError **err);
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (*_gsf_reserved0) (void);
|
||||
void (*_gsf_reserved1) (void);
|
||||
void (*_gsf_reserved2) (void);
|
||||
void (*_gsf_reserved3) (void);
|
||||
} GsfInputClass;
|
||||
|
||||
#define GSF_INPUT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSF_INPUT_TYPE, GsfInputClass))
|
||||
#define GSF_IS_INPUT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSF_INPUT_TYPE))
|
||||
|
||||
/* protected */
|
||||
gboolean gsf_input_set_name (GsfInput *input, char const *name);
|
||||
gboolean gsf_input_set_name_from_filename (GsfInput *input, char const *filename);
|
||||
gboolean gsf_input_set_container (GsfInput *input, GsfInfile *container);
|
||||
gboolean gsf_input_set_size (GsfInput *input, gsf_off_t size);
|
||||
gboolean gsf_input_seek_emulate (GsfInput *input, gsf_off_t pos);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_INPUT_IMPL_H */
|
||||
46
lib/libgsf-1.12.3/gsf/gsf-input-iochannel.c
Normal file
46
lib/libgsf-1.12.3/gsf/gsf-input-iochannel.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-input-iochannel.c: GIOChannel based input
|
||||
*
|
||||
* Copyright (C) 2003-2004 Rodrigo Moya (rodrigo@gnome-db.org)
|
||||
* Copyright (C) 2003-2004 Dom Lachowicz (cinamod@hotmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf-input-iochannel.h>
|
||||
|
||||
/**
|
||||
* gsf_input_memory_new_from_iochannel :
|
||||
* @channel : a #GIOChannel.
|
||||
* @error : a #GError
|
||||
*
|
||||
* Returns a new #GsfInputMemory or NULL.
|
||||
*/
|
||||
GsfInput *
|
||||
gsf_input_memory_new_from_iochannel (GIOChannel *channel,
|
||||
GError **err)
|
||||
{
|
||||
gchar *buf;
|
||||
gsize len;
|
||||
|
||||
g_return_val_if_fail (channel != NULL, NULL);
|
||||
|
||||
if (G_IO_STATUS_NORMAL != g_io_channel_read_to_end (channel, &buf, &len, err))
|
||||
return NULL;
|
||||
|
||||
return gsf_input_memory_new (buf, len, TRUE);
|
||||
}
|
||||
34
lib/libgsf-1.12.3/gsf/gsf-input-iochannel.h
Normal file
34
lib/libgsf-1.12.3/gsf/gsf-input-iochannel.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-input-iochannel.h: interface for use by the structured file layer to read data from IO channels
|
||||
*
|
||||
* Copyright (C) 2002-2004 Rodrigo Moya (rodrigo@gnome-db.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_INPUT_IOCHANNEL_H
|
||||
#define GSF_INPUT_IOCHANNEL_H
|
||||
|
||||
#include <gsf/gsf-input-memory.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GsfInput *gsf_input_memory_new_from_iochannel (GIOChannel *channel,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_INPUT_IOCHANNEL_H */
|
||||
313
lib/libgsf-1.12.3/gsf/gsf-input-memory.c
Normal file
313
lib/libgsf-1.12.3/gsf/gsf-input-memory.c
Normal file
@@ -0,0 +1,313 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-input-memory.c:
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <string.h>
|
||||
#include <gsf/gsf-input-memory.h>
|
||||
#include <gsf/gsf-input-impl.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <gsf/gsf-utils.h>
|
||||
#include <gsf/gsf-shared-memory.h>
|
||||
#ifdef HAVE_GLIB26
|
||||
#include <glib/gstdio.h>
|
||||
#else
|
||||
#include "glib24_26-compat.h"
|
||||
#endif // HAVE_GLIB26
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
|
||||
#if defined(FREEBSD) || defined(__FreeBSD__)
|
||||
/* We must keep the file open while pages are mapped. */
|
||||
/* http://www.freebsd.org/cgi/query-pr.cgi?pr=48291 */
|
||||
#define HAVE_BROKEN_MMAP
|
||||
#endif /* defined(FREEBSD) || defined(__FreeBSD__) */
|
||||
|
||||
#elif defined(G_OS_WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define MAP_FAILED NULL
|
||||
#endif /* HAVE_MMAP */
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
struct _GsfInputMemory {
|
||||
GsfInput parent;
|
||||
GsfSharedMemory *shared;
|
||||
#ifdef HAVE_BROKEN_MMAP
|
||||
int fd;
|
||||
#endif
|
||||
};
|
||||
typedef GsfInputClass GsfInputMemoryClass;
|
||||
|
||||
/**
|
||||
* gsf_input_memory_new:
|
||||
* @buf: The input bytes
|
||||
* @length: The length of @buf
|
||||
* @needs_free: Whether you want this memory to be free'd at object destruction
|
||||
*
|
||||
* Returns: A new #GsfInputMemory
|
||||
*/
|
||||
GsfInput *
|
||||
gsf_input_memory_new (guint8 const *buf, gsf_off_t length, gboolean needs_free)
|
||||
{
|
||||
GsfInputMemory *mem = g_object_new (GSF_INPUT_MEMORY_TYPE, NULL);
|
||||
mem->shared = gsf_shared_memory_new ((void *)buf, length, needs_free);
|
||||
gsf_input_set_size (GSF_INPUT (mem), length);
|
||||
return GSF_INPUT (mem);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_input_memory_new_clone:
|
||||
* @buf: The input bytes
|
||||
* @length: The length of @buf
|
||||
*
|
||||
* Returns: A new #GsfInputMemory
|
||||
*/
|
||||
GsfInput *
|
||||
gsf_input_memory_new_clone (guint8 const *buf, gsf_off_t length)
|
||||
{
|
||||
GsfInputMemory *mem = NULL;
|
||||
guint8 * cpy = g_try_malloc (length * sizeof (guint8));
|
||||
if (cpy == NULL)
|
||||
return NULL;
|
||||
|
||||
memcpy (cpy, buf, length);
|
||||
mem = g_object_new (GSF_INPUT_MEMORY_TYPE, NULL);
|
||||
mem->shared = gsf_shared_memory_new ((void *)cpy, length, TRUE);
|
||||
gsf_input_set_size (GSF_INPUT (mem), length);
|
||||
return GSF_INPUT (mem);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_memory_finalize (GObject *obj)
|
||||
{
|
||||
GsfInputMemory *mem = (GsfInputMemory *) (obj);
|
||||
|
||||
if (mem->shared)
|
||||
g_object_unref (G_OBJECT (mem->shared));
|
||||
|
||||
#ifdef HAVE_BROKEN_MMAP
|
||||
if (mem->fd != -1)
|
||||
close (mem->fd);
|
||||
#endif
|
||||
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static GsfInput *
|
||||
gsf_input_memory_dup (GsfInput *src_input, G_GNUC_UNUSED GError **err)
|
||||
{
|
||||
GsfInputMemory const *src = (GsfInputMemory *) (src_input);
|
||||
GsfInputMemory *dst = g_object_new (GSF_INPUT_MEMORY_TYPE, NULL);
|
||||
|
||||
dst->shared = src->shared;
|
||||
g_object_ref (G_OBJECT (dst->shared));
|
||||
gsf_input_set_size (GSF_INPUT (dst), src->shared->size);
|
||||
|
||||
#ifdef HAVE_BROKEN_MMAP
|
||||
if (src->fd != -1)
|
||||
dst->fd = dup (src->fd);
|
||||
#endif
|
||||
|
||||
return GSF_INPUT (dst);
|
||||
}
|
||||
|
||||
static guint8 const *
|
||||
gsf_input_memory_read (GsfInput *input, size_t num_bytes, guint8 *optional_buffer)
|
||||
{
|
||||
GsfInputMemory *mem = (GsfInputMemory *) (input);
|
||||
guchar const *src = mem->shared->buf;
|
||||
|
||||
if (src == NULL)
|
||||
return NULL;
|
||||
if (optional_buffer) {
|
||||
memcpy (optional_buffer, src + input->cur_offset, num_bytes);
|
||||
return optional_buffer;
|
||||
} else
|
||||
return src + input->cur_offset;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_input_memory_seek (G_GNUC_UNUSED GsfInput *input,
|
||||
G_GNUC_UNUSED gsf_off_t offset,
|
||||
G_GNUC_UNUSED GSeekType whence)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_memory_init (GObject *obj)
|
||||
{
|
||||
GsfInputMemory *mem = (GsfInputMemory *) (obj);
|
||||
mem->shared = NULL;
|
||||
#ifdef HAVE_BROKEN_MMAP
|
||||
mem->fd = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_memory_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
GsfInputClass *input_class = GSF_INPUT_CLASS (gobject_class);
|
||||
|
||||
gobject_class->finalize = gsf_input_memory_finalize;
|
||||
input_class->Dup = gsf_input_memory_dup;
|
||||
input_class->Read = gsf_input_memory_read;
|
||||
input_class->Seek = gsf_input_memory_seek;
|
||||
|
||||
parent_class = g_type_class_peek_parent (gobject_class);
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfInputMemory, gsf_input_memory,
|
||||
gsf_input_memory_class_init, gsf_input_memory_init,
|
||||
GSF_INPUT_TYPE)
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef PROT_READ
|
||||
#define PROT_READ 0x1
|
||||
#endif /* PROT_READ */
|
||||
|
||||
#if !defined(MAP_FAILED) || defined(__osf__)
|
||||
/* Someone needs their head examined - BSD ? */
|
||||
# define MAP_FAILED ((void *)-1)
|
||||
#endif /* !defined(MAP_FAILED) || defined(__osf__) */
|
||||
|
||||
#endif /* HAVE_MMAP */
|
||||
|
||||
/**
|
||||
* gsf_input_mmap_new:
|
||||
* @filename: The file on disk that you want to mmap
|
||||
* @err: A #GError, or optionally %null
|
||||
*
|
||||
* Returns: A new #GsfInputMemory
|
||||
*/
|
||||
GsfInput *
|
||||
gsf_input_mmap_new (char const *filename, GError **err)
|
||||
{
|
||||
#if defined(HAVE_MMAP) || defined(G_OS_WIN32)
|
||||
GsfInputMemory *mem;
|
||||
guint8 *buf = NULL;
|
||||
struct stat st;
|
||||
int fd;
|
||||
size_t size;
|
||||
|
||||
fd = g_open (filename, O_RDONLY | O_BINARY, 0);
|
||||
if (fd < 0 || fstat (fd, &st) < 0) {
|
||||
if (err != NULL) {
|
||||
int save_errno = errno;
|
||||
char *utf8name = g_filename_display_name (filename);
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"%s: %s",
|
||||
utf8name, g_strerror (save_errno));
|
||||
g_free (utf8name);
|
||||
}
|
||||
if (fd >= 0) close (fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!S_ISREG (st.st_mode)) {
|
||||
if (err != NULL) {
|
||||
char *utf8name = g_filename_display_name (filename);
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"%s: Is not a regular file",
|
||||
utf8name);
|
||||
g_free (utf8name);
|
||||
}
|
||||
close (fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size = (size_t) st.st_size;
|
||||
if ((off_t) size != st.st_size) { /* Check for overflow */
|
||||
if (err != NULL) {
|
||||
char *utf8name = g_filename_display_name (filename);
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"%s: File too large to be memory mapped",
|
||||
utf8name);
|
||||
g_free (utf8name);
|
||||
}
|
||||
close (fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
{
|
||||
HANDLE handle = CreateFileMapping ((HANDLE)_get_osfhandle (fd), NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
buf = MapViewOfFile (handle, FILE_MAP_READ, 0, 0, 0);
|
||||
CloseHandle (handle);
|
||||
}
|
||||
#else
|
||||
buf = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, (off_t) 0);
|
||||
#endif
|
||||
|
||||
if (buf == MAP_FAILED) {
|
||||
if (err != NULL) {
|
||||
int save_errno = errno;
|
||||
char *utf8name = g_filename_display_name (filename);
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"%s: %s",
|
||||
utf8name, g_strerror (save_errno));
|
||||
g_free (utf8name);
|
||||
}
|
||||
close (fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mem = g_object_new (GSF_INPUT_MEMORY_TYPE, NULL);
|
||||
mem->shared = gsf_shared_memory_mmapped_new (buf, (gsf_off_t) size);
|
||||
gsf_input_set_size (GSF_INPUT (mem), (gsf_off_t) size);
|
||||
gsf_input_set_name (GSF_INPUT (mem), filename);
|
||||
|
||||
#ifdef HAVE_BROKEN_MMAP
|
||||
mem->fd = fd;
|
||||
#else
|
||||
close (fd);
|
||||
#endif
|
||||
|
||||
return GSF_INPUT (mem);
|
||||
#else
|
||||
(void)filename;
|
||||
if (err != NULL)
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"mmap not supported");
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
43
lib/libgsf-1.12.3/gsf/gsf-input-memory.h
Normal file
43
lib/libgsf-1.12.3/gsf/gsf-input-memory.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-input-memory.h: interface for used by the ole layer to read raw data
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_INPUT_MEMORY_H
|
||||
#define GSF_INPUT_MEMORY_H
|
||||
|
||||
#include "gsf-input.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSF_INPUT_MEMORY_TYPE (gsf_input_memory_get_type ())
|
||||
#define GSF_INPUT_MEMORY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_INPUT_MEMORY_TYPE, GsfInputMemory))
|
||||
#define GSF_IS_INPUT_MEMORY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_INPUT_MEMORY_TYPE))
|
||||
|
||||
typedef struct _GsfInputMemory GsfInputMemory;
|
||||
|
||||
GType gsf_input_memory_get_type (void);
|
||||
GsfInput *gsf_input_memory_new (guint8 const *buf, gsf_off_t length,
|
||||
gboolean needs_free);
|
||||
GsfInput *gsf_input_memory_new_clone (guint8 const *buf, gsf_off_t length);
|
||||
GsfInput *gsf_input_mmap_new (char const *filename, GError **err);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_INPUT_MEMORY_H */
|
||||
169
lib/libgsf-1.12.3/gsf/gsf-input-proxy.c
Normal file
169
lib/libgsf-1.12.3/gsf/gsf-input-proxy.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-input-proxy.c: proxy object (with its own current position)
|
||||
*
|
||||
* Copyright (C) 2004 Morten Welinder (terra@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-input-proxy.h>
|
||||
#include <gsf/gsf-input-impl.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <gsf/gsf-utils.h>
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
struct _GsfInputProxy {
|
||||
GsfInput input;
|
||||
|
||||
GsfInput *source;
|
||||
gsf_off_t offset;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
GsfInputClass input_class;
|
||||
} GsfInputProxyClass;
|
||||
|
||||
|
||||
/**
|
||||
* gsf_input_proxy_new_section :
|
||||
* @source : The underlying data source.
|
||||
* @offset : Offset into source for start of section.
|
||||
* @size : Length of section.
|
||||
*
|
||||
* This creates a new proxy to a section of the given source. The new
|
||||
* object will have its own current position, but any operation on it
|
||||
* can change the source's position.
|
||||
*
|
||||
* If a proxy to a proxy is created, the intermediate proxy is short-
|
||||
* circuited.
|
||||
*
|
||||
* This function will ref the source.
|
||||
*
|
||||
* Returns a new input object.
|
||||
**/
|
||||
GsfInput *
|
||||
gsf_input_proxy_new_section (GsfInput *source,
|
||||
gsf_off_t offset,
|
||||
gsf_off_t size)
|
||||
{
|
||||
GsfInputProxy *proxy;
|
||||
gsf_off_t source_size;
|
||||
|
||||
g_return_val_if_fail (GSF_IS_INPUT (source), NULL);
|
||||
g_return_val_if_fail (offset >= 0, NULL);
|
||||
|
||||
source_size = gsf_input_size (source);
|
||||
g_return_val_if_fail (offset <= source_size, NULL);
|
||||
g_return_val_if_fail (size <= source_size - offset, NULL);
|
||||
|
||||
proxy = g_object_new (GSF_INPUT_PROXY_TYPE, NULL);
|
||||
proxy->offset = offset;
|
||||
gsf_input_set_size (GSF_INPUT (proxy), size);
|
||||
|
||||
/* Short-circuit multiple proxies. */
|
||||
if (GSF_IS_INPUT_PROXY (source)) {
|
||||
GsfInputProxy *proxy_source = GSF_INPUT_PROXY (source);
|
||||
proxy->offset += proxy_source->offset;
|
||||
source = proxy_source->source;
|
||||
}
|
||||
|
||||
proxy->source = g_object_ref (source);
|
||||
return GSF_INPUT (proxy);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_input_proxy_new :
|
||||
* @source : The underlying data source.
|
||||
*
|
||||
* This creates a new proxy to the entire, given input source. See
|
||||
* gsf_input_proxy_new_section for details.
|
||||
*
|
||||
* Returns a new input object.
|
||||
**/
|
||||
GsfInput *
|
||||
gsf_input_proxy_new (GsfInput *source)
|
||||
{
|
||||
return gsf_input_proxy_new_section (source, 0, gsf_input_size (source));
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_proxy_finalize (GObject *obj)
|
||||
{
|
||||
GsfInputProxy *proxy = (GsfInputProxy *)obj;
|
||||
|
||||
if (proxy->source != NULL) {
|
||||
g_object_unref (G_OBJECT (proxy->source));
|
||||
proxy->source = NULL;
|
||||
}
|
||||
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static GsfInput *
|
||||
gsf_input_proxy_dup (GsfInput *src_input, G_GNUC_UNUSED GError **err)
|
||||
{
|
||||
return gsf_input_proxy_new (src_input);
|
||||
}
|
||||
|
||||
static guint8 const *
|
||||
gsf_input_proxy_read (GsfInput *input, size_t num_bytes, guint8 *buffer)
|
||||
{
|
||||
GsfInputProxy *proxy = GSF_INPUT_PROXY (input);
|
||||
|
||||
/* Seek to our position in the source. */
|
||||
if (gsf_input_seek (proxy->source,
|
||||
proxy->offset + gsf_input_tell (input),
|
||||
G_SEEK_SET))
|
||||
return NULL;
|
||||
|
||||
/* Read the data. */
|
||||
return gsf_input_read (proxy->source, num_bytes, buffer);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_input_proxy_seek (G_GNUC_UNUSED GsfInput *input,
|
||||
G_GNUC_UNUSED gsf_off_t offset,
|
||||
G_GNUC_UNUSED GSeekType whence)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_proxy_init (GObject *obj)
|
||||
{
|
||||
GsfInputProxy *proxy = GSF_INPUT_PROXY (obj);
|
||||
|
||||
proxy->source = NULL;
|
||||
proxy->offset = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_proxy_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
GsfInputClass *input_class = GSF_INPUT_CLASS (gobject_class);
|
||||
|
||||
gobject_class->finalize = gsf_input_proxy_finalize;
|
||||
input_class->Dup = gsf_input_proxy_dup;
|
||||
input_class->Read = gsf_input_proxy_read;
|
||||
input_class->Seek = gsf_input_proxy_seek;
|
||||
|
||||
parent_class = g_type_class_peek_parent (gobject_class);
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfInputProxy, gsf_input_proxy,
|
||||
gsf_input_proxy_class_init, gsf_input_proxy_init, GSF_INPUT_TYPE)
|
||||
43
lib/libgsf-1.12.3/gsf/gsf-input-proxy.h
Normal file
43
lib/libgsf-1.12.3/gsf/gsf-input-proxy.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-input-proxy.h: proxy object (with its own current position)
|
||||
*
|
||||
* Copyright (C) 2004 Morten Welinder (terra@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_INPUT_PROXY_H
|
||||
#define GSF_INPUT_PROXY_H
|
||||
|
||||
#include "gsf-input.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSF_INPUT_PROXY_TYPE (gsf_input_proxy_get_type ())
|
||||
#define GSF_INPUT_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_INPUT_PROXY_TYPE, GsfInputProxy))
|
||||
#define GSF_IS_INPUT_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_INPUT_PROXY_TYPE))
|
||||
|
||||
typedef struct _GsfInputProxy GsfInputProxy;
|
||||
|
||||
GType gsf_input_proxy_get_type (void);
|
||||
GsfInput *gsf_input_proxy_new (GsfInput *source);
|
||||
GsfInput *gsf_input_proxy_new_section (GsfInput *source,
|
||||
gsf_off_t offset,
|
||||
gsf_off_t size);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_INPUT_PROXY_H */
|
||||
281
lib/libgsf-1.12.3/gsf/gsf-input-stdio.c
Normal file
281
lib/libgsf-1.12.3/gsf/gsf-input-stdio.c
Normal file
@@ -0,0 +1,281 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-input-stdio.c: stdio based input
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-input-stdio.h>
|
||||
#include <gsf/gsf-input-impl.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <gsf/gsf-utils.h>
|
||||
#ifdef HAVE_GLIB26
|
||||
#include <glib/gstdio.h>
|
||||
#else
|
||||
#include "glib24_26-compat.h"
|
||||
#endif // HAVE_GLIB26
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
struct _GsfInputStdio {
|
||||
GsfInput input;
|
||||
|
||||
FILE *file;
|
||||
char *filename;
|
||||
guint8 *buf;
|
||||
size_t buf_size;
|
||||
gboolean keep_open;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
GsfInputClass input_class;
|
||||
} GsfInputStdioClass;
|
||||
|
||||
/**
|
||||
* gsf_input_stdio_new :
|
||||
* @filename : in utf8.
|
||||
* @err : optionally NULL.
|
||||
*
|
||||
* Returns a new file or NULL.
|
||||
**/
|
||||
GsfInput *
|
||||
gsf_input_stdio_new (char const *filename, GError **err)
|
||||
{
|
||||
GsfInputStdio *input;
|
||||
struct stat st;
|
||||
FILE *file;
|
||||
gsf_off_t size;
|
||||
|
||||
g_return_val_if_fail (filename != NULL, NULL);
|
||||
|
||||
file = g_fopen (filename, "rb");
|
||||
if (file == NULL || fstat (fileno (file), &st) < 0) {
|
||||
if (err) {
|
||||
int save_errno = errno;
|
||||
char *utf8name = g_filename_display_name (filename);
|
||||
g_set_error (err,
|
||||
G_FILE_ERROR,
|
||||
g_file_error_from_errno (save_errno),
|
||||
"%s: %s",
|
||||
utf8name, g_strerror (save_errno));
|
||||
g_free (utf8name);
|
||||
}
|
||||
if (file) fclose (file); /* Just in case. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!S_ISREG (st.st_mode)) {
|
||||
if (err) {
|
||||
char *utf8name = g_filename_display_name (filename);
|
||||
g_set_error (err, gsf_input_error_id (), 0,
|
||||
"%s: not a regular file",
|
||||
utf8name);
|
||||
g_free (utf8name);
|
||||
}
|
||||
fclose (file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size = st.st_size;
|
||||
input = (GsfInputStdio *)g_object_new (GSF_INPUT_STDIO_TYPE, NULL);
|
||||
input->file = file;
|
||||
input->filename = g_strdup (filename);
|
||||
input->buf = NULL;
|
||||
input->buf_size = 0;
|
||||
input->keep_open = FALSE;
|
||||
gsf_input_set_size (GSF_INPUT (input), size);
|
||||
gsf_input_set_name_from_filename (GSF_INPUT (input), filename);
|
||||
|
||||
return GSF_INPUT (input);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_input_stdio_new_FILE :
|
||||
* @filename : The filename corresponding to @file.
|
||||
* @file : an existing stdio FILE *
|
||||
* @keep_open : Should @file be closed when the wrapper is closed
|
||||
*
|
||||
* Assumes ownership of @file. If @keep_open is true, ownership reverts
|
||||
* to caller when the GsfObject is closed.
|
||||
*
|
||||
* Returns a new GsfInput wrapper for @file. Note: the file must be
|
||||
* seekable, so this will not work for stdin when that is a tty or pipe.
|
||||
**/
|
||||
GsfInput *
|
||||
gsf_input_stdio_new_FILE (char const *filename, FILE *file, gboolean keep_open)
|
||||
{
|
||||
GsfInputStdio *stdio;
|
||||
struct stat st;
|
||||
gsf_off_t size;
|
||||
|
||||
g_return_val_if_fail (filename != NULL, NULL);
|
||||
g_return_val_if_fail (file != NULL, NULL);
|
||||
|
||||
if (fstat (fileno (file), &st) < 0)
|
||||
return NULL;
|
||||
if (!S_ISREG (st.st_mode))
|
||||
/* It's not that we really care, but we need st.st_size to be sane. */
|
||||
return NULL;
|
||||
size = st.st_size;
|
||||
|
||||
stdio = g_object_new (GSF_INPUT_STDIO_TYPE, NULL);
|
||||
stdio->file = file;
|
||||
stdio->keep_open = keep_open;
|
||||
stdio->filename = g_strdup (filename);
|
||||
gsf_input_set_size (GSF_INPUT (stdio), size);
|
||||
gsf_input_set_name_from_filename (GSF_INPUT (stdio), filename);
|
||||
return GSF_INPUT (stdio);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_stdio_finalize (GObject *obj)
|
||||
{
|
||||
GsfInputStdio *input = (GsfInputStdio *)obj;
|
||||
|
||||
if (input->file != NULL) {
|
||||
if (!input->keep_open)
|
||||
fclose (input->file);
|
||||
input->file = NULL;
|
||||
}
|
||||
|
||||
g_free (input->buf);
|
||||
input->buf = NULL;
|
||||
input->buf_size = 0;
|
||||
|
||||
g_free (input->filename);
|
||||
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static GsfInput *
|
||||
gsf_input_stdio_dup (GsfInput *src_input, GError **err)
|
||||
{
|
||||
GsfInputStdio const *src = (GsfInputStdio *)src_input;
|
||||
return gsf_input_stdio_new (src->filename, err);
|
||||
}
|
||||
|
||||
static guint8 const *
|
||||
gsf_input_stdio_read (GsfInput *input, size_t num_bytes,
|
||||
guint8 *buffer)
|
||||
{
|
||||
GsfInputStdio *stdio = GSF_INPUT_STDIO (input);
|
||||
size_t nread = 0, total_read = 0;
|
||||
|
||||
g_return_val_if_fail (stdio != NULL, NULL);
|
||||
g_return_val_if_fail (stdio->file != NULL, NULL);
|
||||
|
||||
if (buffer == NULL) {
|
||||
if (stdio->buf_size < num_bytes) {
|
||||
stdio->buf_size = num_bytes;
|
||||
g_free (stdio->buf);
|
||||
stdio->buf = g_new (guint8, stdio->buf_size);
|
||||
}
|
||||
buffer = stdio->buf;
|
||||
}
|
||||
|
||||
while (total_read < num_bytes) {
|
||||
nread = fread (buffer + total_read, 1,
|
||||
num_bytes - total_read, stdio->file);
|
||||
total_read += nread;
|
||||
if (total_read < num_bytes &&
|
||||
(ferror (stdio->file) || feof (stdio->file)))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_input_stdio_seek (GsfInput *input, gsf_off_t offset, GSeekType whence)
|
||||
{
|
||||
GsfInputStdio const *stdio = GSF_INPUT_STDIO (input);
|
||||
int stdio_whence = SEEK_SET;
|
||||
|
||||
#ifndef HAVE_FSEEKO
|
||||
long loffset;
|
||||
#else
|
||||
off_t loffset;
|
||||
#endif
|
||||
|
||||
if (stdio->file == NULL)
|
||||
return TRUE;
|
||||
|
||||
loffset = offset;
|
||||
if ((gsf_off_t) loffset != offset) { /* Check for overflow */
|
||||
#ifdef HAVE_FSEEKO
|
||||
g_warning ("offset too large for fseeko");
|
||||
#else
|
||||
g_warning ("offset too large for fseek");
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
switch (whence) {
|
||||
case G_SEEK_CUR : stdio_whence = SEEK_CUR; break;
|
||||
case G_SEEK_END : stdio_whence = SEEK_END; break;
|
||||
case G_SEEK_SET:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
#ifdef HAVE_FSEEKO
|
||||
if (0 == fseeko (stdio->file, loffset, stdio_whence))
|
||||
return FALSE;
|
||||
#else
|
||||
if (0 == fseek (stdio->file, loffset, stdio_whence))
|
||||
return FALSE;
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_stdio_init (GObject *obj)
|
||||
{
|
||||
GsfInputStdio *stdio = GSF_INPUT_STDIO (obj);
|
||||
|
||||
stdio->file = NULL;
|
||||
stdio->filename = NULL;
|
||||
stdio->buf = NULL;
|
||||
stdio->buf_size = 0;
|
||||
stdio->keep_open = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_stdio_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
GsfInputClass *input_class = GSF_INPUT_CLASS (gobject_class);
|
||||
|
||||
gobject_class->finalize = gsf_input_stdio_finalize;
|
||||
input_class->Dup = gsf_input_stdio_dup;
|
||||
input_class->Read = gsf_input_stdio_read;
|
||||
input_class->Seek = gsf_input_stdio_seek;
|
||||
|
||||
parent_class = g_type_class_peek_parent (gobject_class);
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfInputStdio, gsf_input_stdio,
|
||||
gsf_input_stdio_class_init, gsf_input_stdio_init, GSF_INPUT_TYPE)
|
||||
44
lib/libgsf-1.12.3/gsf/gsf-input-stdio.h
Normal file
44
lib/libgsf-1.12.3/gsf/gsf-input-stdio.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-input-stdio.h: interface for use by the structured file layer to read raw data
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_INPUT_STDIO_H
|
||||
#define GSF_INPUT_STDIO_H
|
||||
|
||||
#include "gsf-input.h"
|
||||
#include <stdio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSF_INPUT_STDIO_TYPE (gsf_input_stdio_get_type ())
|
||||
#define GSF_INPUT_STDIO(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_INPUT_STDIO_TYPE, GsfInputStdio))
|
||||
#define GSF_IS_INPUT_STDIO(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_INPUT_STDIO_TYPE))
|
||||
|
||||
typedef struct _GsfInputStdio GsfInputStdio;
|
||||
|
||||
GType gsf_input_stdio_get_type (void);
|
||||
GsfInput *gsf_input_stdio_new (char const *filename, GError **err);
|
||||
|
||||
GsfInput *gsf_input_stdio_new_FILE (char const *filename, FILE *file,
|
||||
gboolean keep_open);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_INPUT_STDIO_H */
|
||||
322
lib/libgsf-1.12.3/gsf/gsf-input-textline.c
Normal file
322
lib/libgsf-1.12.3/gsf/gsf-input-textline.c
Normal file
@@ -0,0 +1,322 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-input-textline.c: textline based input
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-input-textline.h>
|
||||
#include <gsf/gsf-input-impl.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
struct _GsfInputTextline {
|
||||
GsfInput input;
|
||||
|
||||
GsfInput *source;
|
||||
guint8 const *remainder;
|
||||
unsigned remainder_size;
|
||||
unsigned max_line_size;
|
||||
|
||||
unsigned char *buf;
|
||||
unsigned buf_size;
|
||||
|
||||
/* int current_line; */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
GsfInputClass input_class;
|
||||
} GsfInputTextlineClass;
|
||||
|
||||
/**
|
||||
* gsf_input_textline_new :
|
||||
* @source : in some combination of ascii and utf8
|
||||
*
|
||||
* NOTE : adds a reference to @source
|
||||
*
|
||||
* Returns a new file or NULL.
|
||||
**/
|
||||
GsfInput *
|
||||
gsf_input_textline_new (GsfInput *source)
|
||||
{
|
||||
GsfInputTextline *input;
|
||||
|
||||
g_return_val_if_fail (source != NULL, NULL);
|
||||
|
||||
input = g_object_new (GSF_INPUT_TEXTLINE_TYPE, NULL);
|
||||
g_object_ref (G_OBJECT (source));
|
||||
input->source = source;
|
||||
input->buf = NULL;
|
||||
input->buf_size = 0;
|
||||
gsf_input_set_size (GSF_INPUT (source), gsf_input_size (source));
|
||||
|
||||
return GSF_INPUT (input);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_textline_finalize (GObject *obj)
|
||||
{
|
||||
GsfInputTextline *input = (GsfInputTextline *)obj;
|
||||
|
||||
if (input->source != NULL) {
|
||||
g_object_unref (G_OBJECT (input->source));
|
||||
input->source = NULL;
|
||||
}
|
||||
if (input->buf != NULL) {
|
||||
g_free (input->buf);
|
||||
input->buf = NULL;
|
||||
}
|
||||
input->buf_size = 0;
|
||||
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static GsfInput *
|
||||
gsf_input_textline_dup (GsfInput *src_input, G_GNUC_UNUSED GError **err)
|
||||
{
|
||||
GsfInputTextline const *src = (GsfInputTextline *)src_input;
|
||||
GsfInputTextline *dst = g_object_new (GSF_INPUT_TEXTLINE_TYPE, NULL);
|
||||
|
||||
dst->source = src->source;
|
||||
g_object_ref (G_OBJECT (dst->source));
|
||||
gsf_input_set_size (GSF_INPUT (dst), gsf_input_size (src_input));
|
||||
|
||||
return GSF_INPUT (dst);
|
||||
}
|
||||
|
||||
static guint8 const *
|
||||
gsf_input_textline_read (GsfInput *input, size_t num_bytes, guint8 *buffer)
|
||||
{
|
||||
GsfInputTextline *textline = GSF_INPUT_TEXTLINE (input);
|
||||
textline->remainder = NULL;
|
||||
return gsf_input_read (textline->source, num_bytes, buffer);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_input_textline_seek (GsfInput *input, gsf_off_t offset, GSeekType whence)
|
||||
{
|
||||
GsfInputTextline *textline = GSF_INPUT_TEXTLINE (input);
|
||||
textline->remainder = NULL;
|
||||
return gsf_input_seek (textline->source, offset, whence);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_textline_init (GObject *obj)
|
||||
{
|
||||
GsfInputTextline *textline = GSF_INPUT_TEXTLINE (obj);
|
||||
|
||||
textline->source = NULL;
|
||||
textline->remainder = NULL;
|
||||
textline->remainder_size = 0;
|
||||
textline->max_line_size = 512; /* an initial guess */
|
||||
textline->buf = NULL;
|
||||
textline->buf_size = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_textline_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
GsfInputClass *input_class = GSF_INPUT_CLASS (gobject_class);
|
||||
|
||||
gobject_class->finalize = gsf_input_textline_finalize;
|
||||
input_class->Dup = gsf_input_textline_dup;
|
||||
input_class->Read = gsf_input_textline_read;
|
||||
input_class->Seek = gsf_input_textline_seek;
|
||||
|
||||
parent_class = g_type_class_peek_parent (gobject_class);
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfInputTextline, gsf_input_textline,
|
||||
gsf_input_textline_class_init, gsf_input_textline_init, GSF_INPUT_TYPE)
|
||||
|
||||
/**
|
||||
* gsf_input_textline_ascii_gets :
|
||||
* @input :
|
||||
*
|
||||
* 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 the string read, or NULL on eof.
|
||||
**/
|
||||
unsigned char *
|
||||
gsf_input_textline_ascii_gets (GsfInputTextline *textline)
|
||||
{
|
||||
guint8 const *ptr ,*end;
|
||||
gsf_off_t remain;
|
||||
unsigned len, count = 0;
|
||||
|
||||
g_return_val_if_fail (textline != NULL, NULL);
|
||||
|
||||
while (1) {
|
||||
if (textline->remainder == NULL ||
|
||||
textline->remainder_size == 0) {
|
||||
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 new line */
|
||||
ptr++;
|
||||
if (ptr >= end) {
|
||||
/* be extra careful, the newline 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 == '\n' && *ptr == '\r') ||
|
||||
(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;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_input_textline_utf8_gets :
|
||||
* @input :
|
||||
*
|
||||
* 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 the string read, or NULL on eof.
|
||||
**/
|
||||
guint8 *
|
||||
gsf_input_textline_utf8_gets (GsfInputTextline *textline)
|
||||
{
|
||||
guint8 const *ptr ,*end;
|
||||
gsf_off_t remain;
|
||||
unsigned len, count = 0;
|
||||
|
||||
g_return_val_if_fail (textline != NULL, NULL);
|
||||
|
||||
while (1) {
|
||||
if (textline->remainder == NULL ||
|
||||
textline->remainder_size == 0) {
|
||||
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 = (guint8 *) g_utf8_next_char (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 new line */
|
||||
ptr++;
|
||||
if (ptr >= end) {
|
||||
/* be extra careful, the newline 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 == '\n' && *ptr == '\r') ||
|
||||
(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;
|
||||
}
|
||||
43
lib/libgsf-1.12.3/gsf/gsf-input-textline.h
Normal file
43
lib/libgsf-1.12.3/gsf/gsf-input-textline.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-input-textline.h: a utility wrapper to pull in text, line by line.
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_INPUT_TEXTLINE_H
|
||||
#define GSF_INPUT_TEXTLINE_H
|
||||
|
||||
#include "gsf-input.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSF_INPUT_TEXTLINE_TYPE (gsf_input_textline_get_type ())
|
||||
#define GSF_INPUT_TEXTLINE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_INPUT_TEXTLINE_TYPE, GsfInputTextline))
|
||||
#define GSF_IS_INPUT_TEXTLINE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_INPUT_TEXTLINE_TYPE))
|
||||
|
||||
typedef struct _GsfInputTextline GsfInputTextline;
|
||||
|
||||
GType gsf_input_textline_get_type (void);
|
||||
|
||||
GsfInput *gsf_input_textline_new (GsfInput *source);
|
||||
unsigned char *gsf_input_textline_ascii_gets (GsfInputTextline *input);
|
||||
guint8 *gsf_input_textline_utf8_gets (GsfInputTextline *input);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_INPUT_TEXTLINE_H */
|
||||
651
lib/libgsf-1.12.3/gsf/gsf-input.c
Normal file
651
lib/libgsf-1.12.3/gsf/gsf-input.c
Normal file
@@ -0,0 +1,651 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-input.c: interface for used by the ole layer to read raw data
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-input-impl.h>
|
||||
#include <gsf/gsf-input-gzip.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_BZIP
|
||||
#include <gsf/gsf-input-bzip.h>
|
||||
#endif
|
||||
|
||||
#define GET_CLASS(instance) G_TYPE_INSTANCE_GET_CLASS (instance, GSF_INPUT_TYPE, GsfInputClass)
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_NAME,
|
||||
PROP_SIZE,
|
||||
PROP_EOF,
|
||||
PROP_REMAINING,
|
||||
PROP_POS
|
||||
};
|
||||
|
||||
#if 0
|
||||
static void
|
||||
gsf_input_set_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue const *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
switch (property_id)
|
||||
{
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
gsf_input_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
/* gsf_off_t is typedef'd to gint64 */
|
||||
switch (property_id) {
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, gsf_input_name (GSF_INPUT (object)));
|
||||
break;
|
||||
case PROP_SIZE:
|
||||
g_value_set_int64 (value, gsf_input_size (GSF_INPUT (object)));
|
||||
break;
|
||||
case PROP_EOF:
|
||||
g_value_set_boolean (value, gsf_input_eof (GSF_INPUT (object)));
|
||||
break;
|
||||
case PROP_REMAINING:
|
||||
g_value_set_int64 (value, gsf_input_remaining (GSF_INPUT (object)));
|
||||
break;
|
||||
case PROP_POS:
|
||||
g_value_set_int64 (value, gsf_input_tell (GSF_INPUT (object)));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_finalize (GObject *obj)
|
||||
{
|
||||
GsfInput *input = GSF_INPUT (obj);
|
||||
|
||||
if (input->name != NULL) {
|
||||
g_free (input->name);
|
||||
input->name = NULL;
|
||||
}
|
||||
if (input->container != NULL) {
|
||||
g_object_unref (G_OBJECT (input->container));
|
||||
input->container = NULL;
|
||||
}
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_init (GObject *obj)
|
||||
{
|
||||
GsfInput *input = GSF_INPUT (obj);
|
||||
|
||||
input->size = 0;
|
||||
input->cur_offset = 0;
|
||||
input->name = NULL;
|
||||
input->container = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_input_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
parent_class = g_type_class_peek_parent (gobject_class);
|
||||
|
||||
gobject_class->finalize = gsf_input_finalize;
|
||||
/* gobject_class->set_property = gsf_input_set_property; */
|
||||
gobject_class->get_property = gsf_input_get_property;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_NAME,
|
||||
g_param_spec_string ("name", "Name",
|
||||
"The Input's Name",
|
||||
NULL,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READABLE));
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_SIZE,
|
||||
g_param_spec_int64 ("size", "Size",
|
||||
"The Input's Size",
|
||||
0, G_MAXINT64, 0,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READABLE));
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_EOF,
|
||||
g_param_spec_boolean ("eof", "OEF",
|
||||
"End Of File",
|
||||
FALSE,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READABLE));
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_REMAINING,
|
||||
g_param_spec_int64 ("remaining", "Remaining",
|
||||
"Amount of Data Remaining",
|
||||
0, G_MAXINT64, 0,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READABLE));
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_POS,
|
||||
g_param_spec_int64 ("position", "Position",
|
||||
"The Output's Current Position",
|
||||
0, G_MAXINT64, 0,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READABLE));
|
||||
}
|
||||
|
||||
GSF_CLASS_ABSTRACT (GsfInput, gsf_input,
|
||||
gsf_input_class_init, gsf_input_init,
|
||||
G_TYPE_OBJECT)
|
||||
|
||||
/**
|
||||
* gsf_input_name :
|
||||
* @input : the input stream
|
||||
*
|
||||
* Returns @input's name in utf8 form, or NULL if it has no name.
|
||||
**/
|
||||
char const *
|
||||
gsf_input_name (GsfInput *input)
|
||||
{
|
||||
g_return_val_if_fail (GSF_IS_INPUT (input), NULL);
|
||||
return input->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_input_container :
|
||||
* @input : the input stream
|
||||
*
|
||||
* Returns, but does not add a reference to @input's container.
|
||||
* Potentially NULL
|
||||
**/
|
||||
GsfInfile *
|
||||
gsf_input_container (GsfInput *input)
|
||||
{
|
||||
g_return_val_if_fail (GSF_IS_INPUT (input), NULL);
|
||||
return input->container;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_input_dup :
|
||||
* @input : The input to duplicate
|
||||
* @err : optionally NULL
|
||||
*
|
||||
* Duplicates input @src leaving the new one at the same offset.
|
||||
*
|
||||
* Returns : the duplicate, or NULL on error
|
||||
**/
|
||||
GsfInput *
|
||||
gsf_input_dup (GsfInput *input, GError **err)
|
||||
{
|
||||
GsfInput *dst;
|
||||
|
||||
g_return_val_if_fail (input != NULL, NULL);
|
||||
|
||||
dst = GET_CLASS (input)->Dup (input, err);
|
||||
if (dst != NULL) {
|
||||
if (dst->size != input->size) {
|
||||
if (err != NULL)
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"Duplicate size mismatch");
|
||||
g_object_unref (dst);
|
||||
return NULL;
|
||||
}
|
||||
if (gsf_input_seek (dst, input->cur_offset, G_SEEK_SET)) {
|
||||
if (err != NULL)
|
||||
*err = g_error_new (gsf_input_error_id (), 0,
|
||||
"Seek failed");
|
||||
g_object_unref (dst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (input->name != NULL)
|
||||
gsf_input_set_name (dst, input->name);
|
||||
dst->container = input->container;
|
||||
if (dst->container != NULL)
|
||||
g_object_ref (G_OBJECT (dst->container));
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_input_open_sibling :
|
||||
* @input : The input
|
||||
*
|
||||
* NOT CURRENTLY IMPLEMENTED
|
||||
*
|
||||
* Attempts to open a 'sibling' of @input. The caller is responsible for
|
||||
* managing the resulting object.
|
||||
*
|
||||
* NOT CURRENTLY IMPLEMENTED
|
||||
*
|
||||
* Returns : the size or -1 on error
|
||||
**/
|
||||
GsfInput *
|
||||
gsf_input_sibling (GsfInput const *input, char const *name, GError **err)
|
||||
{
|
||||
g_return_val_if_fail (GET_CLASS (input)->OpenSibling, NULL);
|
||||
|
||||
return GET_CLASS (input)->OpenSibling (input, name, err);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_input_size :
|
||||
* @input : The input
|
||||
*
|
||||
* Looks up and caches the number of bytes in the input
|
||||
*
|
||||
* Returns : the size or -1 on error
|
||||
**/
|
||||
gsf_off_t
|
||||
gsf_input_size (GsfInput *input)
|
||||
{
|
||||
g_return_val_if_fail (input != NULL, -1);
|
||||
return input->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_input_eof :
|
||||
* @input : the input
|
||||
*
|
||||
* Are we at the end of the file ?
|
||||
*
|
||||
* Returns : TRUE if the input is at the eof.
|
||||
**/
|
||||
gboolean
|
||||
gsf_input_eof (GsfInput *input)
|
||||
{
|
||||
g_return_val_if_fail (input != NULL, FALSE);
|
||||
|
||||
return input->cur_offset >= input->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_input_read :
|
||||
* @input : the input stream
|
||||
* @num_bytes : number of bytes to read
|
||||
* @optional_buffer : NULL, or pointer to destination memory area
|
||||
*
|
||||
* Read at least @num_bytes. Does not change the current position if there
|
||||
* is an error. Will only read if the entire amount can be read. Invalidates
|
||||
* the buffer associated with previous calls to gsf_input_read.
|
||||
*
|
||||
* Returns : pointer to the buffer or NULL if there is an error or 0 bytes are
|
||||
* requested.
|
||||
**/
|
||||
guint8 const *
|
||||
gsf_input_read (GsfInput *input, size_t num_bytes, guint8 *optional_buffer)
|
||||
{
|
||||
guint8 const *res;
|
||||
|
||||
g_return_val_if_fail (input != NULL, NULL);
|
||||
|
||||
if (num_bytes == 0 || (input->cur_offset + num_bytes) > input->size)
|
||||
return NULL;
|
||||
res = GET_CLASS (input)->Read (input, num_bytes, optional_buffer);
|
||||
if (res == NULL)
|
||||
return NULL;
|
||||
|
||||
input->cur_offset += num_bytes;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_input_remaining :
|
||||
* @input : the input stream
|
||||
*
|
||||
* Returns the number of bytes left in the file.
|
||||
**/
|
||||
gsf_off_t
|
||||
gsf_input_remaining (GsfInput *input)
|
||||
{
|
||||
g_return_val_if_fail (input != NULL, 0);
|
||||
|
||||
return input->size - input->cur_offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_input_tell :
|
||||
* @input : the input stream
|
||||
*
|
||||
* Returns the current offset in the file.
|
||||
**/
|
||||
gsf_off_t
|
||||
gsf_input_tell (GsfInput *input)
|
||||
{
|
||||
g_return_val_if_fail (input != NULL, 0);
|
||||
|
||||
return input->cur_offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_input_seek :
|
||||
* @input : the input stream
|
||||
* @offset : target offset
|
||||
* @whence : determines whether the offset is relative to the beginning or
|
||||
* the end of the stream, or to the current location.
|
||||
*
|
||||
* Returns TRUE on error.
|
||||
**/
|
||||
gboolean
|
||||
gsf_input_seek (GsfInput *input, gsf_off_t offset, GSeekType whence)
|
||||
{
|
||||
gsf_off_t pos = offset;
|
||||
|
||||
g_return_val_if_fail (input != NULL, TRUE);
|
||||
|
||||
switch (whence) {
|
||||
case G_SEEK_SET : break;
|
||||
case G_SEEK_CUR : pos += input->cur_offset; break;
|
||||
case G_SEEK_END : pos += input->size; break;
|
||||
default : return TRUE;
|
||||
}
|
||||
|
||||
if (pos < 0 || pos > input->size)
|
||||
return TRUE;
|
||||
|
||||
/*
|
||||
* If we go nowhere, just return. This in particular handles null
|
||||
* seeks for streams with no seek method.
|
||||
*/
|
||||
if (pos == input->cur_offset)
|
||||
return FALSE;
|
||||
|
||||
if (GET_CLASS (input)->Seek (input, offset, whence))
|
||||
return TRUE;
|
||||
|
||||
input->cur_offset = pos;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_input_set_name :
|
||||
* @input : the input stream
|
||||
* @name : the new name of the stream, or NULL.
|
||||
*
|
||||
* protected.
|
||||
*
|
||||
* Returns : TRUE if the assignment was ok.
|
||||
**/
|
||||
gboolean
|
||||
gsf_input_set_name (GsfInput *input, char const *name)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
g_return_val_if_fail (input != NULL, FALSE);
|
||||
|
||||
buf = g_strdup (name);
|
||||
g_free (input->name);
|
||||
input->name = buf;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_input_set_name_from_filename :
|
||||
* @input : the input stream
|
||||
* @filename : the (fs-sys encoded) filename
|
||||
*
|
||||
* protected.
|
||||
*
|
||||
* Returns : TRUE if the assignment was ok.
|
||||
**/
|
||||
gboolean
|
||||
gsf_input_set_name_from_filename (GsfInput *input, char const *filename)
|
||||
{
|
||||
g_return_val_if_fail (input != NULL, FALSE);
|
||||
|
||||
g_free (input->name);
|
||||
input->name = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gsf_input_set_container :
|
||||
* @input : the input stream
|
||||
* @container :
|
||||
*
|
||||
* Returns : TRUE if the assignment was ok.
|
||||
*/
|
||||
gboolean
|
||||
gsf_input_set_container (GsfInput *input, GsfInfile *container)
|
||||
{
|
||||
g_return_val_if_fail (input != NULL, FALSE);
|
||||
|
||||
if (container != NULL)
|
||||
g_object_ref (G_OBJECT (container));
|
||||
if (input->container != NULL)
|
||||
g_object_unref (G_OBJECT (input->container));
|
||||
input->container = container;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_input_set_size :
|
||||
* @input : the input stream
|
||||
* @size : the size of the stream
|
||||
*
|
||||
* Returns : TRUE if the assignment was ok.
|
||||
*/
|
||||
gboolean
|
||||
gsf_input_set_size (GsfInput *input, gsf_off_t size)
|
||||
{
|
||||
g_return_val_if_fail (input != NULL, FALSE);
|
||||
g_return_val_if_fail (size >= 0, FALSE);
|
||||
|
||||
input->size = size;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_input_seek_emulate: Emulate forward seeks by reading.
|
||||
* @input : stream to emulate seek for
|
||||
* @pos : absolute position to seek to
|
||||
*
|
||||
* Returns : TRUE if the emulation failed.
|
||||
*/
|
||||
gboolean
|
||||
gsf_input_seek_emulate (GsfInput *input, gsf_off_t pos)
|
||||
{
|
||||
if (pos < input->cur_offset)
|
||||
return TRUE;
|
||||
|
||||
while (pos > input->cur_offset) {
|
||||
gsf_off_t readcount = MIN (pos - input->cur_offset, 8192);
|
||||
if (!gsf_input_read (input, readcount, NULL))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/**
|
||||
* gsf_input_error_id :
|
||||
*
|
||||
* Returns : A utility quark to flag a GError as being an input problem.
|
||||
*/
|
||||
GQuark
|
||||
gsf_input_error_id (void)
|
||||
{
|
||||
static GQuark quark;
|
||||
if (!quark)
|
||||
quark = g_quark_from_static_string ("gsf_input_error_id");
|
||||
return quark;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_input_error :
|
||||
*
|
||||
* Deprecated in 1.12.0
|
||||
* Returns : A utility quark to flag a GError as being an input problem.
|
||||
*/
|
||||
GQuark
|
||||
gsf_input_error (void)
|
||||
{
|
||||
return gsf_input_error_id ();
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#define GSF_READ_BUFSIZE (1024 * 4)
|
||||
|
||||
/**
|
||||
* gsf_input_copy :
|
||||
* @input : a non-null #GsfInput
|
||||
* @output : a non-null #GsfOutput
|
||||
*
|
||||
* Copy the contents from @input to @output from their respective
|
||||
* current positions. So if you want to be sure to copy *everything*,
|
||||
* make sure to call gsf_input_seek (input, 0, G_SEEK_SET) and
|
||||
* gsf_output_seek (output, 0, G_SEEK_SET) first, if applicable.
|
||||
*
|
||||
* Returns : TRUE on Success
|
||||
**/
|
||||
gboolean
|
||||
gsf_input_copy (GsfInput *input, GsfOutput *output)
|
||||
{
|
||||
gsf_off_t remaining = 0;
|
||||
gsf_off_t toread = 0;
|
||||
const guint8 * buffer = NULL;
|
||||
gboolean success = TRUE;
|
||||
|
||||
g_return_val_if_fail (input != NULL, FALSE);
|
||||
g_return_val_if_fail (output != NULL, FALSE);
|
||||
|
||||
while ((remaining = gsf_input_remaining (input)) > 0 && (success)) {
|
||||
toread = MIN (remaining, GSF_READ_BUFSIZE);
|
||||
if (NULL == (buffer = gsf_input_read (input, toread, NULL)))
|
||||
success = FALSE;
|
||||
else
|
||||
success = gsf_output_write (output, toread, buffer);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/**
|
||||
* gsf_input_uncompress: maybe uncompress stream.
|
||||
* @src: stream to be uncompressed.
|
||||
*
|
||||
* Returns: A stream equivalent to the source stream, but uncompressed if
|
||||
* the source was compressed.
|
||||
*
|
||||
* This functions takes ownership of the incoming reference and yields a
|
||||
* new one as its output.
|
||||
*/
|
||||
GsfInput *
|
||||
gsf_input_uncompress (GsfInput *src)
|
||||
{
|
||||
gsf_off_t cur_offset = src->cur_offset;
|
||||
const guint8 *data;
|
||||
|
||||
if (gsf_input_seek (src, 0, G_SEEK_SET))
|
||||
goto error;
|
||||
|
||||
/* Read header up front, so we avoid extra seeks in tests. */
|
||||
data = gsf_input_read (src, 4, NULL);
|
||||
if (!data)
|
||||
goto error;
|
||||
|
||||
/* Let's try gzip. */
|
||||
{
|
||||
const unsigned char gzip_sig[2] = { 0x1f, 0x8b };
|
||||
|
||||
if (memcmp (gzip_sig, data, sizeof (gzip_sig)) == 0) {
|
||||
GsfInput *res = gsf_input_gzip_new (src, NULL);
|
||||
if (res) {
|
||||
g_object_unref (G_OBJECT (src));
|
||||
return gsf_input_uncompress (res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_BZIP
|
||||
/* Let's try bzip. */
|
||||
{
|
||||
guint8 const *bzip_sig = "BZh";
|
||||
|
||||
if (memcmp (gzip_sig, data, strlen (bzip_sig)) == 0) {
|
||||
GsfInput *res = gsf_input_memory_new_from_bzip (src, NULL);
|
||||
if (res) {
|
||||
g_object_unref (G_OBJECT (src));
|
||||
return gsf_input_uncompress (res);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Other methods go here. */
|
||||
|
||||
error:
|
||||
(void)gsf_input_seek (src, cur_offset, G_SEEK_SET);
|
||||
return src;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
#include <gsf/gsf-input-stdio.h>
|
||||
|
||||
#ifdef HAVE_GNOME
|
||||
#include <gsf-gnome/gsf-input-gnomevfs.h>
|
||||
#endif
|
||||
|
||||
GsfInput *
|
||||
gsf_input_new_for_uri (char const * uri, GError ** err)
|
||||
{
|
||||
GsfInput * input = NULL;
|
||||
size_t len;
|
||||
|
||||
g_return_val_if_fail (uri, NULL);
|
||||
|
||||
len = strlen (uri);
|
||||
g_return_val_if_fail (len, NULL);
|
||||
|
||||
if (len > 3 && !strstr (uri, ":/")) {
|
||||
/* assume plain file */
|
||||
input = gsf_input_stdio_new (uri, err);
|
||||
} else {
|
||||
#if HAVE_GNOME
|
||||
/* have gnome, let GnomeVFS deal with this */
|
||||
input = gsf_input_gnomevfs_new (uri, err);
|
||||
#else
|
||||
if (len > 7 && !strncmp (uri, "file:/", 6)) {
|
||||
/* dumb attempt to translate this into a local path */
|
||||
input = gsf_input_stdio_new (uri+7, err);
|
||||
}
|
||||
/* else: unknown or unhandled protocol - bail */
|
||||
#endif
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
#endif
|
||||
64
lib/libgsf-1.12.3/gsf/gsf-input.h
Normal file
64
lib/libgsf-1.12.3/gsf/gsf-input.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-input.h: interface for used by the ole layer to read raw data
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_INPUT_H
|
||||
#define GSF_INPUT_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
#include <glib-object.h>
|
||||
#include <sys/types.h>
|
||||
#include <gsf/gsf-output.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSF_INPUT_TYPE (gsf_input_get_type ())
|
||||
#define GSF_INPUT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_INPUT_TYPE, GsfInput))
|
||||
#define GSF_IS_INPUT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_INPUT_TYPE))
|
||||
|
||||
GType gsf_input_get_type (void);
|
||||
|
||||
char const *gsf_input_name (GsfInput *input);
|
||||
GsfInfile *gsf_input_container (GsfInput *input);
|
||||
|
||||
GsfInput *gsf_input_dup (GsfInput *input, GError **err);
|
||||
GsfInput *gsf_input_sibling (GsfInput const *input, char const *name, GError **err);
|
||||
gsf_off_t gsf_input_size (GsfInput *input);
|
||||
gboolean gsf_input_eof (GsfInput *input);
|
||||
guint8 const *gsf_input_read (GsfInput *input, size_t num_bytes,
|
||||
guint8 *optional_buffer);
|
||||
gsf_off_t gsf_input_remaining (GsfInput *input);
|
||||
gsf_off_t gsf_input_tell (GsfInput *input);
|
||||
gboolean gsf_input_seek (GsfInput *input,
|
||||
gsf_off_t offset, GSeekType whence);
|
||||
|
||||
/* Utilities */
|
||||
gboolean gsf_input_copy (GsfInput *input, GsfOutput *output);
|
||||
GsfInput *gsf_input_uncompress (GsfInput *src);
|
||||
|
||||
GQuark gsf_input_error_id (void);
|
||||
#ifndef GSF_DISABLE_DEPRECATED
|
||||
/* deprecated in 1.12.0, use gsf_input_error_id */
|
||||
GQuark gsf_input_error (void);
|
||||
#endif /* GSF_DISABLE_DEPRECATED */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_INPUT_H */
|
||||
1131
lib/libgsf-1.12.3/gsf/gsf-libxml.c
Normal file
1131
lib/libgsf-1.12.3/gsf/gsf-libxml.c
Normal file
File diff suppressed because it is too large
Load Diff
174
lib/libgsf-1.12.3/gsf/gsf-libxml.h
Normal file
174
lib/libgsf-1.12.3/gsf/gsf-libxml.h
Normal file
@@ -0,0 +1,174 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-libxml.h: Utility wrappers for using gsf with libxml
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_LIBXML_H
|
||||
#define GSF_LIBXML_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
#include <glib-object.h>
|
||||
#include <libxml/tree.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/****************************************************************************/
|
||||
/* GSF wrappers for libxml2 */
|
||||
xmlParserCtxt *gsf_xml_parser_context (GsfInput *input);
|
||||
#if 0
|
||||
/* this is cleaner, tack it on for 2.0 */
|
||||
xmlSAXHandlerPtr sax, gpointer user);
|
||||
#endif
|
||||
int gsf_xmlDocFormatDump (GsfOutput *output,
|
||||
xmlDoc *cur,
|
||||
char const *encoding,
|
||||
gboolean format);
|
||||
|
||||
/****************************************************************************/
|
||||
/* Simplified GSF based xml import (based on libxml2 SAX) */
|
||||
typedef struct _GsfXMLBlob GsfXMLBlob;
|
||||
|
||||
typedef struct _GsfXMLIn GsfXMLIn;
|
||||
typedef struct _GsfXMLInDoc GsfXMLInDoc;
|
||||
typedef struct _GsfXMLInNode GsfXMLInNode;
|
||||
typedef struct _GsfXMLInNS GsfXMLInNS;
|
||||
|
||||
typedef enum {
|
||||
GSF_XML_NO_CONTENT,
|
||||
GSF_XML_CONTENT,
|
||||
GSF_XML_SHARED_CONTENT
|
||||
} GsfXMLContent;
|
||||
|
||||
typedef gboolean (*GsfXMLInUnknownFunc) (GsfXMLIn *state, xmlChar const *elem, xmlChar const **attrs);
|
||||
struct _GsfXMLIn {
|
||||
GsfXMLInDoc const *doc; /* init before parsing */
|
||||
|
||||
/* look but do not change */
|
||||
GsfXMLInNode const *node; /* current node */
|
||||
GSList *state_stack;
|
||||
|
||||
GsfXMLInNS const *default_ns; /* optionally NULL */
|
||||
GSList *ns_stack;
|
||||
|
||||
GString *content;
|
||||
gint unknown_depth; /* handle recursive unknown tags */
|
||||
GHashTable *ns_prefixes; /* current ns prefixes */
|
||||
GPtrArray *ns_by_id; /* indexed by id */
|
||||
};
|
||||
|
||||
struct _GsfXMLInNode {
|
||||
char const *id;
|
||||
int ns_id;
|
||||
char const *name;
|
||||
char const *parent_id;
|
||||
gboolean parent_initialized;
|
||||
GSList *groups;
|
||||
|
||||
unsigned has_content;
|
||||
gboolean deprecated_unused_allow_unknown; /* remains here for binary compat */
|
||||
gboolean check_children_for_ns;
|
||||
|
||||
void (*start) (GsfXMLIn *state, xmlChar const **attrs);
|
||||
void (*end) (GsfXMLIn *state, GsfXMLBlob *unknown);
|
||||
|
||||
union {
|
||||
int v_int;
|
||||
gboolean v_bool;
|
||||
gpointer v_blob;
|
||||
char const *v_str;
|
||||
} user_data;
|
||||
};
|
||||
|
||||
struct _GsfXMLInNS {
|
||||
char const *uri;
|
||||
unsigned ns_id;
|
||||
};
|
||||
|
||||
#define GSF_XML_IN_NS(id, uri) \
|
||||
{ uri, id}
|
||||
|
||||
#define GSF_XML_IN_NODE_FULL(parent_id, id, ns, name, has_content, \
|
||||
deprecated_unused_allow_unknown, check_ns, start, end, user) \
|
||||
{ \
|
||||
#id, ns, name, #parent_id, FALSE, NULL, \
|
||||
has_content, deprecated_unused_allow_unknown, check_ns, start, end, { user } \
|
||||
}
|
||||
|
||||
#define GSF_XML_IN_NODE(parent_id, id, ns, name, has_content, start, end) \
|
||||
GSF_XML_IN_NODE_FULL(parent_id, id, ns, name, has_content, \
|
||||
FALSE, FALSE, start, end, 0)
|
||||
|
||||
GsfXMLInDoc *gsf_xml_in_doc_new (GsfXMLInNode *root, GsfXMLInNS *ns);
|
||||
void gsf_xml_in_doc_free (GsfXMLInDoc *doc);
|
||||
void gsf_xml_in_doc_extend (GsfXMLInDoc *doc,
|
||||
GsfXMLInNode *nodes);
|
||||
void gsf_xml_in_doc_set_unknown_handler (GsfXMLInDoc *doc,
|
||||
GsfXMLInUnknownFunc handler);
|
||||
|
||||
gboolean gsf_xml_in_parse (GsfXMLIn *state, GsfInput *input);
|
||||
char const *gsf_xml_in_check_ns (GsfXMLIn const *state, char const *str,
|
||||
unsigned int ns_id);
|
||||
gboolean gsf_xml_in_namecmp (GsfXMLIn const *state, char const *str,
|
||||
unsigned int ns_id, char const *name);
|
||||
|
||||
/****************************************************************************/
|
||||
/* Simplified GSF based xml export (does not use libxml) */
|
||||
|
||||
typedef struct _GsfXMLOut GsfXMLOut;
|
||||
|
||||
#define GSF_XML_OUT_TYPE (gsf_xml_out_get_type ())
|
||||
#define GSF_XML_OUT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_XML_OUT_TYPE, GsfXMLOut))
|
||||
#define GSF_IS_XML_OUT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_XML_OUT_TYPE))
|
||||
|
||||
GType gsf_xml_out_get_type (void);
|
||||
GsfXMLOut *gsf_xml_out_new (GsfOutput *output);
|
||||
|
||||
void gsf_xml_out_set_doc_type (GsfXMLOut *xml, char const *type);
|
||||
void gsf_xml_out_start_element (GsfXMLOut *xml, char const *id);
|
||||
char const *gsf_xml_out_end_element (GsfXMLOut *xml);
|
||||
|
||||
void gsf_xml_out_simple_element (GsfXMLOut *xml, char const *id,
|
||||
char const *content);
|
||||
void gsf_xml_out_simple_int_element (GsfXMLOut *xml, char const *id,
|
||||
int val);
|
||||
void gsf_xml_out_simple_float_element (GsfXMLOut *xml, char const *id,
|
||||
double val, int precision);
|
||||
|
||||
void gsf_xml_out_add_cstr_unchecked (GsfXMLOut *xml, char const *id,
|
||||
char const *val_utf8);
|
||||
void gsf_xml_out_add_cstr (GsfXMLOut *xml, char const *id,
|
||||
char const *val_utf8);
|
||||
void gsf_xml_out_add_bool (GsfXMLOut *xml, char const *id,
|
||||
gboolean val);
|
||||
void gsf_xml_out_add_int (GsfXMLOut *xml, char const *id,
|
||||
int val);
|
||||
void gsf_xml_out_add_uint (GsfXMLOut *xml, char const *id,
|
||||
unsigned int val);
|
||||
void gsf_xml_out_add_float (GsfXMLOut *xml, char const *id,
|
||||
double val, int precision);
|
||||
void gsf_xml_out_add_color (GsfXMLOut *xml, char const *id,
|
||||
unsigned int r, unsigned int g, unsigned int b);
|
||||
void gsf_xml_out_add_base64 (GsfXMLOut *xml, char const *id,
|
||||
guint8 const *data, unsigned int len);
|
||||
void gsf_xml_out_add_enum (GsfXMLOut *xml, char const *id,
|
||||
GType etype, gint val);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_LIBXML_H */
|
||||
182
lib/libgsf-1.12.3/gsf/gsf-meta-names.h
Normal file
182
lib/libgsf-1.12.3/gsf/gsf-meta-names.h
Normal file
@@ -0,0 +1,182 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-meta-names.h: a list of gsf-meta-names to "generically" represent
|
||||
* all diviserly available implementation-specific
|
||||
* meta-names.
|
||||
*
|
||||
* Author: Veerapuram Varadhan (vvaradhan@novell.com)
|
||||
*
|
||||
* Copyright (C) 2004 Novell, Inc
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
#ifndef GSF_META_NAMES_H
|
||||
#define GSF_META_NAMES_H
|
||||
|
||||
/* (String) A formal name given to the resource */
|
||||
#define GSF_META_NAME_TITLE "dc:title"
|
||||
|
||||
/* (String) An account of the content of the resource */
|
||||
#define GSF_META_NAME_DESCRIPTION "dc:description"
|
||||
|
||||
/* (String) The topic of the content of the resource, *typically* including keywords */
|
||||
#define GSF_META_NAME_SUBJECT "dc:subject"
|
||||
|
||||
/* (Date as ISO String) The last time this document was saved */
|
||||
#define GSF_META_NAME_DATE_MODIFIED "dc:date-modified"
|
||||
|
||||
/* (Date as ISO String) A date associated with an event in the life cycle of the resource (creation/publication date) */
|
||||
#define GSF_META_NAME_DATE_CREATED "gsf:date-created"
|
||||
|
||||
/* (String) Searchable, indexable keywords. Similar to PDF keywords or HTML's meta block */
|
||||
#define GSF_META_NAME_KEYWORDS "dc:keywords"
|
||||
|
||||
/* (String) A language of the intellectual content of the resource (basically xx_YY form for us) */
|
||||
#define GSF_META_NAME_LANGUAGE "dc:language"
|
||||
|
||||
/* (Integer) Count of revision on the document, if appropriate */
|
||||
#define GSF_META_NAME_REVISION_COUNT "gsf:revision-count"
|
||||
|
||||
/* (Date as ISO String) The total-time taken till last-modified */
|
||||
#define GSF_META_NAME_EDITING_DURATION "gsf:editing-duration"
|
||||
|
||||
/* (Integer) Count of tables in the document, if appropriate */
|
||||
#define GSF_META_NAME_TABLE_COUNT "gsf:table-count"
|
||||
|
||||
/* (Integer) Count of images in the document, if appropriate */
|
||||
#define GSF_META_NAME_IMAGE_COUNT "gsf:image-count"
|
||||
|
||||
/* (Integer) Count of objects (OLE and other graphics) in the document, if appropriate */
|
||||
#define GSF_META_NAME_OBJECT_COUNT "gsf:object-count"
|
||||
|
||||
/* (Integer) Count of pages in the document, if appropriate */
|
||||
#define GSF_META_NAME_PAGE_COUNT "gsf:page-count"
|
||||
|
||||
/* (Integer) Count of paragraphs in the document, if appropriate */
|
||||
#define GSF_META_NAME_PARAGRAPH_COUNT "gsf:paragraph-count"
|
||||
|
||||
/* (Integer) Count of words in the document */
|
||||
#define GSF_META_NAME_WORD_COUNT "gsf:word-count"
|
||||
|
||||
/* (Integer) Count of characters in the document */
|
||||
#define GSF_META_NAME_CHARACTER_COUNT "gsf:character-count"
|
||||
|
||||
/* (Integer) Count of cells in the spread-sheet document, if appropriate */
|
||||
#define GSF_META_NAME_CELL_COUNT "gsf:cell-count"
|
||||
|
||||
/* (Integer) Count of pages in the document, if appropriate */
|
||||
#define GSF_META_NAME_SPREADSHEET_COUNT "gsf:spreadsheet-count"
|
||||
|
||||
/* (String) An entity primarily responsible for making the content of the resource
|
||||
* typically a person, organization, or service
|
||||
*/
|
||||
#define GSF_META_NAME_CREATOR "gsf:creator"
|
||||
|
||||
/* (String) The template file that is been used to generate this document */
|
||||
#define GSF_META_NAME_TEMPLATE "gsf:template"
|
||||
|
||||
/* (String) The entity that made the last change to the document,
|
||||
* typically a person, organization, or service
|
||||
*/
|
||||
#define GSF_META_NAME_LAST_SAVED_BY "gsf:last-saved-by"
|
||||
|
||||
/* (Date as ISO String) The last time this document was printed */
|
||||
#define GSF_META_NAME_LAST_PRINTED "gsf:last-printed"
|
||||
|
||||
/* (Integer) Level of security.
|
||||
* Level Value
|
||||
* ----- -----
|
||||
* None 0
|
||||
* Password protected 1
|
||||
* Read-only recommended 2
|
||||
* Read-only enforced 3
|
||||
* Locked for annotations 4
|
||||
*
|
||||
*/
|
||||
#define GSF_META_NAME_SECURITY "gsf:security"
|
||||
|
||||
/* (String) Category of the document (example???) */
|
||||
#define GSF_META_NAME_CATEGORY "gsf:category"
|
||||
|
||||
/* (String) Type of presentation, like "On-screen Show", "SlideView" etc */
|
||||
#define GSF_META_NAME_PRESENTATION_FORMAT "gsf:presentation-format"
|
||||
|
||||
/* (Clipboard Format (VT_CF)) Thumbnail data of the document, typically
|
||||
* a preview image of the document
|
||||
*/
|
||||
#define GSF_META_NAME_THUMBNAIL "gsf:thumbnail"
|
||||
|
||||
/* (String) The creator (product) of this document. AbiWord, Gnumeric, etc... */
|
||||
#define GSF_META_NAME_GENERATOR "gsf:generator"
|
||||
|
||||
/* (Integer) Count of liness in the document */
|
||||
#define GSF_META_NAME_LINE_COUNT "gsf:line-count"
|
||||
|
||||
/* (Integer) Count of slides in the presentation document */
|
||||
#define GSF_META_NAME_SLIDE_COUNT "gsf:slide-count"
|
||||
|
||||
/* (Integer) Count of "notes" in the document */
|
||||
#define GSF_META_NAME_NOTE_COUNT "gsf:note-count"
|
||||
|
||||
/* (Integer) Count of hidden-slides in the presentation document */
|
||||
#define GSF_META_NAME_HIDDEN_SLIDE_COUNT "gsf:hidden-slide-count"
|
||||
|
||||
/* (Integer) Count of "multi-media" clips in the document */
|
||||
#define GSF_META_NAME_MM_CLIP_COUNT "gsf:MM-clip-count"
|
||||
|
||||
/* (Integer) Count of bytes in the document */
|
||||
#define GSF_META_NAME_BYTE_COUNT "gsf:byte-count"
|
||||
|
||||
/* (Boolean) ????? */
|
||||
#define GSF_META_NAME_SCALE "gsf:scale"
|
||||
|
||||
/* (VT_VECTOR|VT_VARIANT) ??????? */
|
||||
#define GSF_META_NAME_HEADING_PAIRS "gsf:heading-pairs"
|
||||
|
||||
/* (VT_VECTOR|VT_LPSTR) ??????? */
|
||||
#define GSF_META_NAME_DOCUMENT_PARTS "gsf:document-parts"
|
||||
|
||||
/* (String) Name of the manager of "CREATOR" entity */
|
||||
#define GSF_META_NAME_MANAGER "gsf:manager"
|
||||
|
||||
/* (String) Name of the company/organization that
|
||||
* the "CREATOR" entity is associated with.
|
||||
*/
|
||||
#define GSF_META_NAME_COMPANY "gsf:company"
|
||||
|
||||
/* (Boolean) ??????? */
|
||||
#define GSF_META_NAME_LINKS_DIRTY "gsf:links-dirty"
|
||||
|
||||
/* (Unknown) User-defined names */
|
||||
#define GSF_META_NAME_MSOLE_UNKNOWN_17 "msole:unknown-doc-17"
|
||||
#define GSF_META_NAME_MSOLE_UNKNOWN_18 "msole:unknown-doc-18"
|
||||
#define GSF_META_NAME_MSOLE_UNKNOWN_19 "msole:unknown-doc-19" /* bool */
|
||||
#define GSF_META_NAME_MSOLE_UNKNOWN_20 "msole:unknown-doc-20"
|
||||
#define GSF_META_NAME_MSOLE_UNKNOWN_21 "msole:unknown-doc-21"
|
||||
#define GSF_META_NAME_MSOLE_UNKNOWN_22 "msole:unknown-doc-22" /* bool */
|
||||
#define GSF_META_NAME_MSOLE_UNKNOWN_23 "msole:unknown-doc-23" /* i4 */
|
||||
|
||||
/* (None) Reserved name (PID) for Dictionary */
|
||||
#define GSF_META_NAME_DICTIONARY "gsf:dictionary"
|
||||
|
||||
/* (Unsigned Integer) Identifier representing the default
|
||||
* system locale.
|
||||
*/
|
||||
#define GSF_META_NAME_LOCALE_SYSTEM_DEFAULT "gsf:default-locale"
|
||||
|
||||
/* (Unsigned Integer) Identifier representing the case-sensitiveness */
|
||||
#define GSF_META_NAME_CASE_SENSITIVE "gsf:case-sensitivity"
|
||||
|
||||
#endif /* GSF_META_NAMES_H */
|
||||
84
lib/libgsf-1.12.3/gsf/gsf-msole-impl.h
Normal file
84
lib/libgsf-1.12.3/gsf/gsf-msole-impl.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-msole-impl.h:
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_MSOLE_IMPL_H
|
||||
#define GSF_MSOLE_IMPL_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define OLE_HEADER_SIZE 0x200 /* independent of big block size size */
|
||||
#define OLE_HEADER_SIGNATURE 0x00
|
||||
#define OLE_HEADER_CLSID 0x08 /* See ReadClassStg */
|
||||
#define OLE_HEADER_MINOR_VER 0x18 /* 0x33 and 0x3e have been seen */
|
||||
#define OLE_HEADER_MAJOR_VER 0x1a /* 0x3 been seen in wild */
|
||||
#define OLE_HEADER_BYTE_ORDER 0x1c /* 0xfe 0xff == Intel Little Endian */
|
||||
#define OLE_HEADER_BB_SHIFT 0x1e
|
||||
#define OLE_HEADER_SB_SHIFT 0x20
|
||||
/* 0x22..0x27 reserved == 0 */
|
||||
#define OLE_HEADER_CSECTDIR 0x28
|
||||
#define OLE_HEADER_NUM_BAT 0x2c
|
||||
#define OLE_HEADER_DIRENT_START 0x30
|
||||
/* 0x34..0x37 transacting signature must be 0 */
|
||||
#define OLE_HEADER_THRESHOLD 0x38
|
||||
#define OLE_HEADER_SBAT_START 0x3c
|
||||
#define OLE_HEADER_NUM_SBAT 0x40
|
||||
#define OLE_HEADER_METABAT_BLOCK 0x44
|
||||
#define OLE_HEADER_NUM_METABAT 0x48
|
||||
#define OLE_HEADER_START_BAT 0x4c
|
||||
#define BAT_INDEX_SIZE 4
|
||||
#define OLE_HEADER_METABAT_SIZE ((OLE_HEADER_SIZE - OLE_HEADER_START_BAT) / BAT_INDEX_SIZE)
|
||||
|
||||
#define DIRENT_MAX_NAME_SIZE 0x40
|
||||
#define DIRENT_DETAILS_SIZE 0x40
|
||||
#define DIRENT_SIZE (DIRENT_MAX_NAME_SIZE + DIRENT_DETAILS_SIZE)
|
||||
#define DIRENT_NAME_LEN 0x40 /* length in bytes incl 0 terminator */
|
||||
#define DIRENT_TYPE 0x42
|
||||
#define DIRENT_COLOUR 0x43
|
||||
#define DIRENT_PREV 0x44
|
||||
#define DIRENT_NEXT 0x48
|
||||
#define DIRENT_CHILD 0x4c
|
||||
#define DIRENT_CLSID 0x50 /* only for dirs */
|
||||
#define DIRENT_USERFLAGS 0x60 /* only for dirs */
|
||||
#define DIRENT_CREATE_TIME 0x64 /* for files */
|
||||
#define DIRENT_MODIFY_TIME 0x6c /* for files */
|
||||
#define DIRENT_FIRSTBLOCK 0x74
|
||||
#define DIRENT_FILE_SIZE 0x78
|
||||
/* 0x7c..0x7f reserved == 0 */
|
||||
|
||||
#define DIRENT_TYPE_INVALID 0
|
||||
#define DIRENT_TYPE_DIR 1
|
||||
#define DIRENT_TYPE_FILE 2
|
||||
#define DIRENT_TYPE_LOCKBYTES 3 /* ? */
|
||||
#define DIRENT_TYPE_PROPERTY 4 /* ? */
|
||||
#define DIRENT_TYPE_ROOTDIR 5
|
||||
#define DIRENT_MAGIC_END 0xffffffff
|
||||
|
||||
/* flags in the block allocation list to denote special blocks */
|
||||
#define BAT_MAGIC_UNUSED 0xffffffff /* -1 */
|
||||
#define BAT_MAGIC_END_OF_CHAIN 0xfffffffe /* -2 */
|
||||
#define BAT_MAGIC_BAT 0xfffffffd /* a bat block, -3 */
|
||||
#define BAT_MAGIC_METABAT 0xfffffffc /* a metabat block -4 */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_MSOLE_IMPL_H */
|
||||
2228
lib/libgsf-1.12.3/gsf/gsf-msole-utils.c
Normal file
2228
lib/libgsf-1.12.3/gsf/gsf-msole-utils.c
Normal file
File diff suppressed because it is too large
Load Diff
54
lib/libgsf-1.12.3/gsf/gsf-msole-utils.h
Normal file
54
lib/libgsf-1.12.3/gsf/gsf-msole-utils.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-msole-utils.h: various tools for handling MS OLE files
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_MSOLE_UTILS_H
|
||||
#define GSF_MSOLE_UTILS_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
#include <gsf/gsf-doc-meta-data.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GError *gsf_msole_metadata_read (GsfInput *in,
|
||||
GsfDocMetaData *accum);
|
||||
gboolean gsf_msole_metadata_write (GsfOutput *out,
|
||||
GsfDocMetaData const *meta_data,
|
||||
gboolean doc_not_component);
|
||||
|
||||
guint gsf_msole_lid_for_language (char const *lang);
|
||||
guint gsf_msole_codepage_to_lid (int codepage);
|
||||
int gsf_msole_lid_to_codepage (guint lid);
|
||||
gchar *gsf_msole_lid_to_codepage_str (guint lid);
|
||||
char const *gsf_msole_language_for_lid (guint lid);
|
||||
|
||||
int gsf_msole_iconv_win_codepage (void) ;
|
||||
GIConv gsf_msole_iconv_open_for_import (int codepage) ;
|
||||
GIConv gsf_msole_iconv_open_for_export (void) ;
|
||||
|
||||
GIConv gsf_msole_iconv_open_codepage_for_import (char const *to, int codepage);
|
||||
GIConv gsf_msole_iconv_open_codepages_for_export (int codepage_to, char const *from);
|
||||
GIConv gsf_msole_iconv_open_codepage_for_export (int codepage_to);
|
||||
|
||||
GByteArray *gsf_msole_inflate (GsfInput *input, gsf_off_t offset);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_MSOLE_UTILS_H */
|
||||
48
lib/libgsf-1.12.3/gsf/gsf-outfile-impl.h
Normal file
48
lib/libgsf-1.12.3/gsf/gsf-outfile-impl.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-outfile-impl.h:
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_OUTFILE_IMPL_H
|
||||
#define GSF_OUTFILE_IMPL_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
#include <gsf/gsf-output-impl.h>
|
||||
#include <gsf/gsf-outfile.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
struct _GsfOutfile {
|
||||
GsfOutput parent;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
GsfOutputClass output_class;
|
||||
GsfOutput *(*new_child) (GsfOutfile *outfile,
|
||||
char const *name, gboolean is_dir,
|
||||
char const *first_property_name,
|
||||
va_list args);
|
||||
} GsfOutfileClass;
|
||||
|
||||
#define GSF_OUTFILE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSF_OUTFILE_TYPE, GsfOutfileClass))
|
||||
#define GSF_IS_OUTFILE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSF_OUTFILE_TYPE))
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_OUTFILE_IMPL_H */
|
||||
795
lib/libgsf-1.12.3/gsf/gsf-outfile-msole.c
Normal file
795
lib/libgsf-1.12.3/gsf/gsf-outfile-msole.c
Normal file
@@ -0,0 +1,795 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-outfile-msole.c:
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Outc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-outfile-impl.h>
|
||||
#include <gsf/gsf-outfile-msole.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <gsf/gsf-msole-impl.h>
|
||||
#include <gsf/gsf-utils.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
static GsfOutputClass *gsf_output_class;
|
||||
|
||||
#undef G_LOG_DOMAIN
|
||||
#define G_LOG_DOMAIN "libgsf:msole"
|
||||
|
||||
typedef enum { MSOLE_DIR, MSOLE_SMALL_BLOCK, MSOLE_BIG_BLOCK } MSOleOutfileType;
|
||||
|
||||
/* The most common values */
|
||||
#define OLE_DEFAULT_THRESHOLD 0x1000
|
||||
#define OLE_DEFAULT_BB_SIZE (1 << OLE_DEFAULT_BB_SHIFT)
|
||||
#define OLE_DEFAULT_SB_SIZE (1 << OLE_DEFAULT_SB_SHIFT)
|
||||
|
||||
struct _GsfOutfileMSOle {
|
||||
GsfOutfile parent;
|
||||
|
||||
GsfOutput *sink;
|
||||
GsfOutfileMSOle *root;
|
||||
|
||||
MSOleOutfileType type;
|
||||
unsigned first_block;
|
||||
unsigned blocks;
|
||||
unsigned child_index;
|
||||
|
||||
struct {
|
||||
unsigned shift;
|
||||
unsigned size;
|
||||
} bb, sb;
|
||||
|
||||
union {
|
||||
struct {
|
||||
GSList *children;
|
||||
GPtrArray *root_order; /* only valid for the root */
|
||||
} dir;
|
||||
struct {
|
||||
guint8 *buf;
|
||||
} small_block;
|
||||
struct {
|
||||
size_t start_offset; /* in bytes */
|
||||
} big_block;
|
||||
} content;
|
||||
unsigned char clsid[16]; /* 16 byte GUID used by some apps */
|
||||
};
|
||||
typedef GsfOutfileClass GsfOutfileMSOleClass;
|
||||
|
||||
static void
|
||||
gsf_outfile_msole_finalize (GObject *obj)
|
||||
{
|
||||
GsfOutfileMSOle *ole = GSF_OUTFILE_MSOLE (obj);
|
||||
GsfOutput *output = GSF_OUTPUT (obj);
|
||||
|
||||
if (!gsf_output_is_closed (output))
|
||||
gsf_output_close (output);
|
||||
|
||||
if (ole->sink != NULL) {
|
||||
g_object_unref (G_OBJECT (ole->sink));
|
||||
ole->sink = NULL;
|
||||
}
|
||||
switch (ole->type) {
|
||||
case MSOLE_DIR:
|
||||
if (ole->content.dir.children != NULL) {
|
||||
g_slist_free (ole->content.dir.children);
|
||||
ole->content.dir.children = NULL;
|
||||
}
|
||||
if (ole->content.dir.root_order != NULL)
|
||||
g_warning ("Finalizing a MSOle Outfile without closing it.");
|
||||
break;
|
||||
|
||||
case MSOLE_SMALL_BLOCK:
|
||||
if (ole->content.small_block.buf != NULL) {
|
||||
g_free (ole->content.small_block.buf);
|
||||
ole->content.small_block.buf = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case MSOLE_BIG_BLOCK:
|
||||
break;
|
||||
default :
|
||||
g_warning ("Unknown file type");
|
||||
}
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_outfile_msole_seek (GsfOutput *output, gsf_off_t offset,
|
||||
GSeekType whence)
|
||||
{
|
||||
GsfOutfileMSOle *ole = (GsfOutfileMSOle *)output;
|
||||
|
||||
switch (whence) {
|
||||
case G_SEEK_SET : break;
|
||||
case G_SEEK_CUR : offset += output->cur_offset; break;
|
||||
case G_SEEK_END : offset += output->cur_size; break;
|
||||
default :
|
||||
break; /*checked in GsfOutput wrapper */
|
||||
}
|
||||
|
||||
switch (ole->type) {
|
||||
case MSOLE_DIR:
|
||||
if (offset != 0) {
|
||||
g_warning ("Attempt to seek a directory");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case MSOLE_SMALL_BLOCK:
|
||||
/* it is ok to seek past the big block threshold
|
||||
* we don't convert until they _write_ something
|
||||
*/
|
||||
return TRUE;
|
||||
|
||||
case MSOLE_BIG_BLOCK:
|
||||
return gsf_output_seek (ole->sink,
|
||||
(gsf_off_t)(ole->content.big_block.start_offset + offset),
|
||||
G_SEEK_SET);
|
||||
|
||||
default :
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Globals to support variable OLE sector size. */
|
||||
/* 512 and 4096 bytes are the only known values for sector size on */
|
||||
/* Win2k/XP platforms. Attempts to create OLE files on Win2k/XP with */
|
||||
/* other values using StgCreateStorageEx() fail with invalid parameter. */
|
||||
/* This code has been tested with 128,256,512,4096,8192 sizes for */
|
||||
/* libgsf read/write. Interoperability with MS OLE32.DLL has been */
|
||||
/* tested with 512 and 4096 block size for filesizes up to 2GB. */
|
||||
|
||||
#define ZERO_PAD_BUF_SIZE 4096
|
||||
|
||||
/* static objects are zero-initialized as per C/C++ standards */
|
||||
static guint8 const zero_buf [ZERO_PAD_BUF_SIZE];
|
||||
|
||||
/* Calculate the block of the current offset in the file. A useful idiom is to
|
||||
* pad_zero to move to the start of the next block, then get the block number.
|
||||
* This avoids fence post type problems with partial blocks. */
|
||||
static inline guint32
|
||||
ole_cur_block (GsfOutfileMSOle const *ole)
|
||||
{
|
||||
return (gsf_output_tell (ole->sink) - OLE_HEADER_SIZE) >> ole->bb.shift;
|
||||
}
|
||||
|
||||
static inline unsigned
|
||||
ole_bytes_left_in_block (GsfOutfileMSOle *ole)
|
||||
{
|
||||
/* blocks are multiples of bb.size (the header is padded out to bb.size) */
|
||||
unsigned r = gsf_output_tell (ole->sink) % ole->bb.size;
|
||||
return (r != 0) ? (ole->bb.size - r) : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ole_pad_zero (GsfOutfileMSOle *ole)
|
||||
{
|
||||
/* no need to bounds check. len will always be less than bb.size, and
|
||||
* we already check that zero_buf is big enough at creation */
|
||||
unsigned len = ole_bytes_left_in_block (ole);
|
||||
if (len > 0)
|
||||
gsf_output_write (ole->sink, len, zero_buf);
|
||||
}
|
||||
|
||||
/* Utility routine to generate a BAT for a file known to be sequential and
|
||||
* continuous. */
|
||||
static void
|
||||
ole_write_bat (GsfOutput *sink, guint32 block, unsigned blocks)
|
||||
{
|
||||
guint8 buf [BAT_INDEX_SIZE];
|
||||
|
||||
/* FIXME FIXME FIXME optimize this to dump a buffer in 1 step */
|
||||
while (blocks-- > 1) {
|
||||
block++;
|
||||
GSF_LE_SET_GUINT32 (buf, block);
|
||||
gsf_output_write (sink, BAT_INDEX_SIZE, buf);
|
||||
}
|
||||
GSF_LE_SET_GUINT32 (buf, BAT_MAGIC_END_OF_CHAIN);
|
||||
gsf_output_write (sink, BAT_INDEX_SIZE, buf);
|
||||
}
|
||||
|
||||
static void
|
||||
ole_write_const (GsfOutput *sink, guint32 value, unsigned n)
|
||||
{
|
||||
guint8 buf [BAT_INDEX_SIZE];
|
||||
|
||||
GSF_LE_SET_GUINT32 (buf, value);
|
||||
while (n-- > 0)
|
||||
gsf_output_write (sink, BAT_INDEX_SIZE, buf);
|
||||
}
|
||||
|
||||
static void
|
||||
ole_pad_bat_unused (GsfOutfileMSOle *ole, unsigned residual)
|
||||
{
|
||||
ole_write_const (ole->sink, BAT_MAGIC_UNUSED,
|
||||
(ole_bytes_left_in_block (ole) / BAT_INDEX_SIZE) - residual);
|
||||
}
|
||||
|
||||
/* write the metadata (dirents, small block, xbats) and close the sink */
|
||||
static gboolean
|
||||
gsf_outfile_msole_close_root (GsfOutfileMSOle *ole)
|
||||
{
|
||||
GsfOutfile *tmp;
|
||||
guint8 buf [OLE_HEADER_SIZE];
|
||||
guint32 sbat_start, num_sbat, sb_data_start, sb_data_size, sb_data_blocks;
|
||||
guint32 bat_start, num_bat, dirent_start, num_dirent_blocks, next, child_index;
|
||||
unsigned i, j, blocks, num_xbat, xbat_pos;
|
||||
gsf_off_t data_size;
|
||||
unsigned metabat_size = ole->bb.size / BAT_INDEX_SIZE - 1;
|
||||
GPtrArray *elem = ole->root->content.dir.root_order;
|
||||
|
||||
/* write small block data */
|
||||
blocks = 0;
|
||||
sb_data_start = ole_cur_block (ole);
|
||||
data_size = gsf_output_tell (ole->sink);
|
||||
for (i = 0 ; i < elem->len ; i++) {
|
||||
GsfOutfileMSOle *child = g_ptr_array_index (elem, i);
|
||||
if (child->type == MSOLE_SMALL_BLOCK) {
|
||||
gsf_off_t size = gsf_output_size (GSF_OUTPUT (child));
|
||||
if (size > 0) {
|
||||
child->blocks = ((size - 1) >> ole->sb.shift) + 1;
|
||||
gsf_output_write (ole->sink,
|
||||
child->blocks << ole->sb.shift,
|
||||
child->content.small_block.buf);
|
||||
child->first_block = blocks;
|
||||
blocks += child->blocks;
|
||||
} else {
|
||||
child->blocks = 0;
|
||||
child->first_block = BAT_MAGIC_END_OF_CHAIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
data_size = gsf_output_tell (ole->sink) - data_size;
|
||||
sb_data_size = data_size;
|
||||
if ((gsf_off_t) sb_data_size != data_size) {
|
||||
/* Check for overflow */
|
||||
g_warning ("File too big");
|
||||
return FALSE;
|
||||
}
|
||||
ole_pad_zero (ole);
|
||||
sb_data_blocks = ole_cur_block (ole) - sb_data_start;
|
||||
|
||||
/* write small block BAT (the meta bat is in a file) */
|
||||
sbat_start = ole_cur_block (ole);
|
||||
for (i = 0 ; i < elem->len ; i++) {
|
||||
GsfOutfileMSOle *child = g_ptr_array_index (elem, i);
|
||||
if (child->type == MSOLE_SMALL_BLOCK && child->blocks > 0)
|
||||
ole_write_bat (ole->sink, child->first_block, child->blocks);
|
||||
}
|
||||
ole_pad_bat_unused (ole, 0);
|
||||
num_sbat = ole_cur_block (ole) - sbat_start;
|
||||
|
||||
/* write dirents */
|
||||
dirent_start = ole_cur_block (ole);
|
||||
for (i = 0 ; i < elem->len ; i++) {
|
||||
GsfOutfileMSOle *child = g_ptr_array_index (elem, i);
|
||||
glong j, name_len = 0;
|
||||
|
||||
memset (buf, 0, DIRENT_SIZE);
|
||||
|
||||
/* Hard code 'Root Entry' for the root */
|
||||
if (i == 0 || gsf_output_name (GSF_OUTPUT (child)) != NULL) {
|
||||
char const *name = (i == 0)
|
||||
? "Root Entry" : gsf_output_name (GSF_OUTPUT (child));
|
||||
gunichar2 *name_utf16 = g_utf8_to_utf16 (name,
|
||||
-1, NULL, &name_len, NULL);
|
||||
if (name_len >= DIRENT_MAX_NAME_SIZE)
|
||||
name_len = DIRENT_MAX_NAME_SIZE-1;
|
||||
|
||||
/* be wary about endianness */
|
||||
for (j = 0 ; j < name_len ; j++)
|
||||
GSF_LE_SET_GUINT16 (buf + j*2, name_utf16 [j]);
|
||||
g_free (name_utf16);
|
||||
name_len++;
|
||||
}
|
||||
GSF_LE_SET_GUINT16 (buf + DIRENT_NAME_LEN, name_len*2);
|
||||
|
||||
if (child->root == child) {
|
||||
GSF_LE_SET_GUINT8 (buf + DIRENT_TYPE, DIRENT_TYPE_ROOTDIR);
|
||||
GSF_LE_SET_GUINT32 (buf + DIRENT_FIRSTBLOCK,
|
||||
(sb_data_size > 0) ? sb_data_start : BAT_MAGIC_END_OF_CHAIN);
|
||||
GSF_LE_SET_GUINT32 (buf + DIRENT_FILE_SIZE, sb_data_size);
|
||||
memcpy (buf + DIRENT_CLSID, child->clsid, sizeof (child->clsid));
|
||||
} else if (child->type == MSOLE_DIR) {
|
||||
GSF_LE_SET_GUINT8 (buf + DIRENT_TYPE, DIRENT_TYPE_DIR);
|
||||
GSF_LE_SET_GUINT32 (buf + DIRENT_FIRSTBLOCK, BAT_MAGIC_END_OF_CHAIN);
|
||||
GSF_LE_SET_GUINT32 (buf + DIRENT_FILE_SIZE, 0);
|
||||
/* write the class id */
|
||||
memcpy (buf + DIRENT_CLSID, child->clsid, sizeof (child->clsid));
|
||||
} else {
|
||||
guint32 size = child->parent.parent.cur_size;
|
||||
|
||||
if ((gsf_off_t) size != child->parent.parent.cur_size)
|
||||
g_warning ("File too big");
|
||||
GSF_LE_SET_GUINT8 (buf + DIRENT_TYPE, DIRENT_TYPE_FILE);
|
||||
GSF_LE_SET_GUINT32 (buf + DIRENT_FIRSTBLOCK, child->first_block);
|
||||
GSF_LE_SET_GUINT32 (buf + DIRENT_FILE_SIZE, size);
|
||||
}
|
||||
/* make everything black (red == 0) */
|
||||
GSF_LE_SET_GUINT8 (buf + DIRENT_COLOUR, 1);
|
||||
|
||||
tmp = gsf_output_container (GSF_OUTPUT (child));
|
||||
next = DIRENT_MAGIC_END;
|
||||
if (child->root != child && tmp != NULL) {
|
||||
GSList *ptr = GSF_OUTFILE_MSOLE (tmp)->content.dir.children;
|
||||
for (; ptr != NULL ; ptr = ptr->next)
|
||||
if (ptr->data == child) {
|
||||
if (ptr->next != NULL) {
|
||||
GsfOutfileMSOle *sibling = ptr->next->data;
|
||||
next = sibling->child_index;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* make linked list rather than tree, only use next */
|
||||
GSF_LE_SET_GUINT32 (buf + DIRENT_PREV, DIRENT_MAGIC_END);
|
||||
GSF_LE_SET_GUINT32 (buf + DIRENT_NEXT, next);
|
||||
|
||||
child_index = DIRENT_MAGIC_END;
|
||||
if (child->type == MSOLE_DIR && child->content.dir.children != NULL) {
|
||||
GsfOutfileMSOle *first = child->content.dir.children->data;
|
||||
child_index = first->child_index;
|
||||
}
|
||||
GSF_LE_SET_GUINT32 (buf + DIRENT_CHILD, child_index);
|
||||
|
||||
gsf_output_write (ole->sink, DIRENT_SIZE, buf);
|
||||
}
|
||||
ole_pad_zero (ole);
|
||||
num_dirent_blocks = ole_cur_block (ole) - dirent_start;
|
||||
|
||||
/* write BAT */
|
||||
bat_start = ole_cur_block (ole);
|
||||
for (i = 0 ; i < elem->len ; i++) {
|
||||
GsfOutfileMSOle *child = g_ptr_array_index (elem, i);
|
||||
if (child->type == MSOLE_BIG_BLOCK)
|
||||
ole_write_bat (ole->sink, child->first_block, child->blocks);
|
||||
}
|
||||
if (sb_data_blocks > 0)
|
||||
ole_write_bat (ole->sink, sb_data_start, sb_data_blocks);
|
||||
if (num_sbat > 0)
|
||||
ole_write_bat (ole->sink, sbat_start, num_sbat);
|
||||
ole_write_bat (ole->sink, dirent_start, num_dirent_blocks);
|
||||
|
||||
/* List the BAT and meta-BAT blocks in the BAT. Doing this may
|
||||
* increase the size of the bat and hence the metabat, so be
|
||||
* prepared to iterate.
|
||||
*/
|
||||
num_bat = 0;
|
||||
num_xbat = 0;
|
||||
recalc_bat_bat :
|
||||
i = ((ole->sink->cur_size
|
||||
+ BAT_INDEX_SIZE * (num_bat + num_xbat)
|
||||
- OLE_HEADER_SIZE - 1) >> ole->bb.shift) + 1;
|
||||
i -= bat_start;
|
||||
if (num_bat != i) {
|
||||
num_bat = i;
|
||||
goto recalc_bat_bat;
|
||||
}
|
||||
i = 0;
|
||||
if (num_bat > OLE_HEADER_METABAT_SIZE)
|
||||
i = 1 + ((num_bat - OLE_HEADER_METABAT_SIZE - 1)
|
||||
/ metabat_size);
|
||||
if (num_xbat != i) {
|
||||
num_xbat = i;
|
||||
goto recalc_bat_bat;
|
||||
}
|
||||
|
||||
ole_write_const (ole->sink, BAT_MAGIC_BAT, num_bat);
|
||||
ole_write_const (ole->sink, BAT_MAGIC_METABAT, num_xbat);
|
||||
ole_pad_bat_unused (ole, 0);
|
||||
|
||||
if (num_xbat > 0) {
|
||||
xbat_pos = ole_cur_block (ole);
|
||||
blocks = OLE_HEADER_METABAT_SIZE;
|
||||
} else {
|
||||
xbat_pos = BAT_MAGIC_END_OF_CHAIN;
|
||||
blocks = num_bat;
|
||||
}
|
||||
|
||||
/* fix up the header */
|
||||
if (ole->bb.size == 4096) {
|
||||
/* set _cSectDir for 4k sector files */
|
||||
GSF_LE_SET_GUINT32 (buf, num_dirent_blocks);
|
||||
gsf_output_seek (ole->sink,
|
||||
(gsf_off_t) OLE_HEADER_CSECTDIR, G_SEEK_SET);
|
||||
gsf_output_write (ole->sink, 4, buf);
|
||||
}
|
||||
GSF_LE_SET_GUINT32 (buf, num_bat);
|
||||
GSF_LE_SET_GUINT32 (buf+4, dirent_start);
|
||||
gsf_output_seek (ole->sink,
|
||||
(gsf_off_t) OLE_HEADER_NUM_BAT, G_SEEK_SET);
|
||||
gsf_output_write (ole->sink, 8, buf);
|
||||
|
||||
GSF_LE_SET_GUINT32 (buf+0x0,
|
||||
(num_sbat > 0) ? sbat_start : BAT_MAGIC_END_OF_CHAIN);
|
||||
GSF_LE_SET_GUINT32 (buf+0x4, num_sbat);
|
||||
GSF_LE_SET_GUINT32 (buf+0x8, xbat_pos);
|
||||
GSF_LE_SET_GUINT32 (buf+0xc, num_xbat);
|
||||
gsf_output_seek (ole->sink, (gsf_off_t) OLE_HEADER_SBAT_START,
|
||||
G_SEEK_SET);
|
||||
gsf_output_write (ole->sink, 0x10, buf);
|
||||
|
||||
/* write initial Meta-BAT */
|
||||
for (i = 0 ; i < blocks ; i++) {
|
||||
GSF_LE_SET_GUINT32 (buf, bat_start + i);
|
||||
gsf_output_write (ole->sink, BAT_INDEX_SIZE, buf);
|
||||
}
|
||||
|
||||
/* write extended Meta-BAT */
|
||||
if (num_xbat > 0) {
|
||||
gsf_output_seek (ole->sink, 0, G_SEEK_END);
|
||||
for (i = 0 ; i++ < num_xbat ; ) {
|
||||
bat_start += blocks;
|
||||
num_bat -= blocks;
|
||||
blocks = (num_bat > metabat_size) ? metabat_size : num_bat;
|
||||
for (j = 0 ; j < blocks ; j++) {
|
||||
GSF_LE_SET_GUINT32 (buf, bat_start + j);
|
||||
gsf_output_write (ole->sink, BAT_INDEX_SIZE, buf);
|
||||
}
|
||||
|
||||
if (i == num_xbat) {
|
||||
ole_pad_bat_unused (ole, 1);
|
||||
xbat_pos = BAT_MAGIC_END_OF_CHAIN;
|
||||
} else
|
||||
xbat_pos++;
|
||||
GSF_LE_SET_GUINT32 (buf, xbat_pos);
|
||||
gsf_output_write (ole->sink, BAT_INDEX_SIZE, buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* free the children */
|
||||
for (i = 0 ; i < elem->len ; i++)
|
||||
g_object_unref (G_OBJECT (g_ptr_array_index (elem, i)));
|
||||
g_ptr_array_free (elem, TRUE);
|
||||
ole->content.dir.root_order = NULL;
|
||||
|
||||
return gsf_output_close (ole->sink);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_outfile_msole_close (GsfOutput *output)
|
||||
{
|
||||
GsfOutfileMSOle *ole = (GsfOutfileMSOle *)output;
|
||||
|
||||
if (gsf_output_container (output) == NULL) /* The root dir */
|
||||
return gsf_outfile_msole_close_root (ole);
|
||||
|
||||
if (ole->type == MSOLE_BIG_BLOCK) {
|
||||
gsf_outfile_msole_seek (output, 0, G_SEEK_END);
|
||||
ole_pad_zero (ole);
|
||||
ole->blocks = ole_cur_block (ole) - ole->first_block;
|
||||
return gsf_output_unwrap (G_OBJECT (output), ole->sink);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_outfile_msole_write (GsfOutput *output,
|
||||
size_t num_bytes, guint8 const *data)
|
||||
{
|
||||
GsfOutfileMSOle *ole = (GsfOutfileMSOle *)output;
|
||||
size_t wsize;
|
||||
|
||||
g_return_val_if_fail (ole->type != MSOLE_DIR, FALSE);
|
||||
if (ole->type == MSOLE_SMALL_BLOCK) {
|
||||
gboolean ok;
|
||||
guint8 *buf;
|
||||
gsf_off_t start_offset;
|
||||
|
||||
if ((output->cur_offset + num_bytes) < OLE_DEFAULT_THRESHOLD) {
|
||||
memcpy (ole->content.small_block.buf + output->cur_offset,
|
||||
data, num_bytes);
|
||||
return TRUE;
|
||||
}
|
||||
ok = gsf_output_wrap (G_OBJECT (output), ole->sink);
|
||||
if (!ok)
|
||||
return FALSE;
|
||||
|
||||
buf = ole->content.small_block.buf;
|
||||
ole->content.small_block.buf = NULL;
|
||||
start_offset = gsf_output_tell (ole->sink);
|
||||
ole->content.big_block.start_offset = start_offset;
|
||||
if ((gsf_off_t) ole->content.big_block.start_offset
|
||||
!= start_offset) {
|
||||
/* Check for overflow */
|
||||
g_warning ("File too big");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ole->first_block = ole_cur_block (ole);
|
||||
ole->type = MSOLE_BIG_BLOCK;
|
||||
wsize = output->cur_size;
|
||||
if ((gsf_off_t) wsize != output->cur_size) {
|
||||
/* Check for overflow */
|
||||
g_warning ("File too big");
|
||||
return FALSE;
|
||||
}
|
||||
gsf_output_write (ole->sink, wsize, buf);
|
||||
g_free (buf);
|
||||
}
|
||||
|
||||
g_return_val_if_fail (ole->type == MSOLE_BIG_BLOCK, FALSE);
|
||||
|
||||
gsf_output_write (ole->sink, num_bytes, data);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gsf_off_t gsf_outfile_msole_vprintf (GsfOutput *output,
|
||||
char const *format, va_list args) G_GNUC_PRINTF (2, 0);
|
||||
|
||||
static gsf_off_t
|
||||
gsf_outfile_msole_vprintf (GsfOutput *output, char const *format, va_list args)
|
||||
{
|
||||
GsfOutfileMSOle *ole = (GsfOutfileMSOle *)output;
|
||||
|
||||
/* An optimization. */
|
||||
if (ole->type == MSOLE_BIG_BLOCK)
|
||||
return gsf_output_vprintf (ole->sink, format, args);
|
||||
|
||||
/* In other cases, use the gsf_output_real_vprintf fallback method.
|
||||
* (This eventually calls gsf_outfile_msole_write, which will also
|
||||
* check that ole->type != MSOLE_DIR.)
|
||||
*/
|
||||
return gsf_output_class->Vprintf (output, format, args);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ole_register_child (GsfOutfileMSOle *root, GsfOutfileMSOle *child)
|
||||
{
|
||||
child->root = root;
|
||||
g_object_ref (G_OBJECT (child));
|
||||
child->child_index = root->content.dir.root_order->len;
|
||||
g_ptr_array_add (root->content.dir.root_order, child);
|
||||
}
|
||||
|
||||
static gint
|
||||
ole_name_cmp (GsfOutfileMSOle const *a, GsfOutfileMSOle const *b)
|
||||
{
|
||||
/* According to the docs length is more important than lexical order */
|
||||
char const *a_name = gsf_output_name ((GsfOutput const *)a);
|
||||
char const *b_name = gsf_output_name ((GsfOutput const *)b);
|
||||
|
||||
/* be anal */
|
||||
if (a_name == NULL)
|
||||
return (b_name == NULL) ? 0 : -1;
|
||||
else if (b_name == NULL)
|
||||
return 1;
|
||||
else {
|
||||
unsigned a_len = g_utf8_strlen (a_name, -1);
|
||||
unsigned b_len = g_utf8_strlen (b_name, -1);
|
||||
|
||||
if (a_len != b_len)
|
||||
return a_len - b_len;
|
||||
return g_utf8_collate (a_name, b_name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_outfile_msole_set_block_shift (GsfOutfileMSOle *ole,
|
||||
unsigned bb_shift, unsigned sb_shift)
|
||||
{
|
||||
ole->bb.shift = bb_shift;
|
||||
ole->bb.size = (1 << ole->bb.shift);
|
||||
ole->sb.shift = sb_shift;
|
||||
ole->sb.size = (1 << ole->sb.shift);
|
||||
}
|
||||
|
||||
static GsfOutput *
|
||||
gsf_outfile_msole_new_child (GsfOutfile *parent,
|
||||
char const *name, gboolean is_dir,
|
||||
char const *first_property_name, va_list args)
|
||||
{
|
||||
GsfOutfileMSOle *ole_parent = (GsfOutfileMSOle *)parent;
|
||||
GsfOutfileMSOle *child;
|
||||
|
||||
g_return_val_if_fail (ole_parent != NULL, NULL);
|
||||
g_return_val_if_fail (ole_parent->type == MSOLE_DIR, NULL);
|
||||
|
||||
child = (GsfOutfileMSOle *)g_object_new_valist (
|
||||
GSF_OUTFILE_MSOLE_TYPE, first_property_name, args);
|
||||
if (is_dir) {
|
||||
child->type = MSOLE_DIR;
|
||||
child->content.dir.children = NULL;
|
||||
} else {
|
||||
/* start as small block */
|
||||
child->type = MSOLE_SMALL_BLOCK;
|
||||
child->content.small_block.buf = g_new0 (guint8, OLE_DEFAULT_THRESHOLD);
|
||||
}
|
||||
g_object_ref (G_OBJECT (ole_parent->sink));
|
||||
child->sink = ole_parent->sink;
|
||||
child->root = ole_parent->root;
|
||||
gsf_outfile_msole_set_block_shift (child,
|
||||
ole_parent->bb.shift, ole_parent->sb.shift);
|
||||
gsf_output_set_name (GSF_OUTPUT (child), name);
|
||||
gsf_output_set_container (GSF_OUTPUT (child), parent);
|
||||
|
||||
ole_parent->content.dir.children = g_slist_insert_sorted (
|
||||
ole_parent->content.dir.children, child,
|
||||
(GCompareFunc)ole_name_cmp);
|
||||
ole_register_child (ole_parent->root, child);
|
||||
|
||||
return GSF_OUTPUT (child);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_outfile_msole_init (GObject *obj)
|
||||
{
|
||||
GsfOutfileMSOle *ole = GSF_OUTFILE_MSOLE (obj);
|
||||
|
||||
ole->sink = NULL;
|
||||
ole->root = NULL;
|
||||
ole->type = MSOLE_DIR;
|
||||
|
||||
gsf_outfile_msole_set_block_shift (ole,
|
||||
OLE_DEFAULT_BB_SHIFT, OLE_DEFAULT_SB_SHIFT);
|
||||
|
||||
ole->content.dir.children = NULL;
|
||||
ole->content.dir.root_order = NULL;
|
||||
memset (ole->clsid, 0, sizeof (ole->clsid));
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_outfile_msole_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
GsfOutputClass *output_class = GSF_OUTPUT_CLASS (gobject_class);
|
||||
GsfOutfileClass *outfile_class = GSF_OUTFILE_CLASS (gobject_class);
|
||||
|
||||
gobject_class->finalize = gsf_outfile_msole_finalize;
|
||||
output_class->Close = gsf_outfile_msole_close;
|
||||
output_class->Seek = gsf_outfile_msole_seek;
|
||||
output_class->Write = gsf_outfile_msole_write;
|
||||
output_class->Vprintf = gsf_outfile_msole_vprintf;
|
||||
outfile_class->new_child = gsf_outfile_msole_new_child;
|
||||
|
||||
parent_class = g_type_class_peek_parent (gobject_class);
|
||||
gsf_output_class = g_type_class_peek (GSF_OUTPUT_TYPE);
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfOutfileMSOle, gsf_outfile_msole,
|
||||
gsf_outfile_msole_class_init, gsf_outfile_msole_init,
|
||||
GSF_OUTFILE_TYPE)
|
||||
|
||||
/* returns the number of times 1 must be shifted left to reach value */
|
||||
static unsigned
|
||||
compute_shift (unsigned value)
|
||||
{
|
||||
unsigned i = 0;
|
||||
while ((value >> i) > 1)
|
||||
i++;
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_outfile_msole_new_full :
|
||||
* @sink : a #GsfOutput to hold the OLE2 file.
|
||||
* @bb_size : size of large blocks.
|
||||
* @sb_size : size of small blocks.
|
||||
*
|
||||
* Creates the root directory of an MS OLE file and manages the addition of
|
||||
* children.
|
||||
*
|
||||
* NOTE : adds a reference to @sink
|
||||
*
|
||||
* Returns the new ole file handler
|
||||
**/
|
||||
GsfOutfile *
|
||||
gsf_outfile_msole_new_full (GsfOutput *sink, guint bb_size, guint sb_size)
|
||||
{
|
||||
static guint8 const default_header [] = {
|
||||
/* 0x00 */ 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1,
|
||||
/* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 0x18 */ 0x3e, 0x00, 0x03, 0x00, 0xfe, 0xff, 0x09, 0x00,
|
||||
/* 0x20 */ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x28 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x30 */ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x38 */ 0x00, 0x10, 0x00, 0x00 /* 0x3c-0x4b: filled on close */
|
||||
};
|
||||
guint8 *buf;
|
||||
GsfOutfileMSOle *ole;
|
||||
|
||||
g_return_val_if_fail (GSF_IS_OUTPUT (sink), NULL);
|
||||
|
||||
ole = g_object_new (GSF_OUTFILE_MSOLE_TYPE, NULL);
|
||||
g_object_ref (G_OBJECT (sink));
|
||||
ole->sink = sink;
|
||||
ole->type = MSOLE_DIR;
|
||||
ole->content.dir.root_order = g_ptr_array_new ();
|
||||
ole_register_child (ole, ole);
|
||||
|
||||
gsf_outfile_msole_set_block_shift (ole,
|
||||
compute_shift (bb_size), compute_shift (sb_size));
|
||||
if (ole->bb.size != bb_size ||
|
||||
ole->sb.size != sb_size ||
|
||||
bb_size <= sb_size ||
|
||||
bb_size < DIRENT_SIZE ||
|
||||
sb_size < 8 ||
|
||||
ZERO_PAD_BUF_SIZE < ole->bb.size) {
|
||||
if (ZERO_PAD_BUF_SIZE < ole->bb.size)
|
||||
g_warning ("Block size is too big, failing back to defaults.");
|
||||
else
|
||||
g_warning ("Incorrect block sizes, failing back to defaults.");
|
||||
gsf_outfile_msole_set_block_shift (ole,
|
||||
OLE_DEFAULT_BB_SHIFT, OLE_DEFAULT_SB_SHIFT);
|
||||
}
|
||||
|
||||
/* The names are the same */
|
||||
gsf_output_set_name (GSF_OUTPUT (ole), gsf_output_name (sink));
|
||||
gsf_output_set_container (GSF_OUTPUT (ole), NULL);
|
||||
|
||||
/* build the header */
|
||||
buf = g_new (guint8, OLE_HEADER_SIZE);
|
||||
memcpy (buf, default_header, sizeof (default_header));
|
||||
memset (buf + sizeof (default_header), 0xff,
|
||||
OLE_HEADER_SIZE - sizeof (default_header));
|
||||
GSF_LE_SET_GUINT16 (buf + OLE_HEADER_BB_SHIFT, ole->bb.shift);
|
||||
GSF_LE_SET_GUINT16 (buf + OLE_HEADER_SB_SHIFT, ole->sb.shift);
|
||||
/* 4k sector OLE files seen in the wild have version 4 */
|
||||
if (ole->bb.size == 4096)
|
||||
GSF_LE_SET_GUINT16 (buf + OLE_HEADER_MAJOR_VER, 4);
|
||||
gsf_output_write (sink, OLE_HEADER_SIZE, buf);
|
||||
g_free (buf);
|
||||
|
||||
/* header must be padded out to bb.size with zeros */
|
||||
ole_pad_zero(ole);
|
||||
|
||||
return GSF_OUTFILE (ole);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_outfile_msole_new :
|
||||
* @sink : a #GsfOutput to hold the OLE2 file
|
||||
*
|
||||
* Creates the root directory of an MS OLE file and manages the addition of
|
||||
* children.
|
||||
*
|
||||
* NOTE : adds a reference to @sink
|
||||
*
|
||||
* Returns the new ole file handler
|
||||
**/
|
||||
GsfOutfile *
|
||||
gsf_outfile_msole_new (GsfOutput *sink)
|
||||
{
|
||||
return gsf_outfile_msole_new_full (sink,
|
||||
OLE_DEFAULT_BB_SIZE, OLE_DEFAULT_SB_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_outfile_msole_set_class_id :
|
||||
* @ole: a #GsfOutfileMSOle
|
||||
* @clsid: 16 byte identifier (often a GUID in MS Windows apps)
|
||||
*
|
||||
* Write @clsid to the directory associated with @ole.
|
||||
*
|
||||
* Returns TRUE on success.
|
||||
**/
|
||||
gboolean
|
||||
gsf_outfile_msole_set_class_id (GsfOutfileMSOle *ole, guint8 const *clsid)
|
||||
{
|
||||
g_return_val_if_fail (ole != NULL && ole->type == MSOLE_DIR, FALSE);
|
||||
memcpy (ole->clsid, clsid, sizeof (ole->clsid));
|
||||
return TRUE;
|
||||
}
|
||||
48
lib/libgsf-1.12.3/gsf/gsf-outfile-msole.h
Normal file
48
lib/libgsf-1.12.3/gsf/gsf-outfile-msole.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-outfile-msole.h: interface for creating OLE files
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_OUTFILE_MSOLE_H
|
||||
#define GSF_OUTFILE_MSOLE_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GsfOutfileMSOle GsfOutfileMSOle;
|
||||
|
||||
#define GSF_OUTFILE_MSOLE_TYPE (gsf_outfile_msole_get_type ())
|
||||
#define GSF_OUTFILE_MSOLE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_OUTFILE_MSOLE_TYPE, GsfOutfileMSOle))
|
||||
#define GSF_IS_OUTFILE_MSOLE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_OUTFILE_MSOLE_TYPE))
|
||||
|
||||
#define OLE_DEFAULT_SB_SHIFT 6
|
||||
#define OLE_DEFAULT_BB_SHIFT 9
|
||||
|
||||
GType gsf_outfile_msole_get_type (void);
|
||||
GsfOutfile *gsf_outfile_msole_new (GsfOutput *sink);
|
||||
GsfOutfile *gsf_outfile_msole_new_full (GsfOutput *sink,
|
||||
guint bb_size, guint sb_size);
|
||||
gboolean gsf_outfile_msole_set_class_id (GsfOutfileMSOle *ole,
|
||||
guint8 const *clsid);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_OUTFILE_H */
|
||||
170
lib/libgsf-1.12.3/gsf/gsf-outfile-stdio.c
Normal file
170
lib/libgsf-1.12.3/gsf/gsf-outfile-stdio.c
Normal file
@@ -0,0 +1,170 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-outfile-stdio.c: A directory tree wrapper for Outfile
|
||||
*
|
||||
* Copyright (C) 2004 Novell, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-outfile-impl.h>
|
||||
#include <gsf/gsf-outfile-stdio.h>
|
||||
#include <gsf/gsf-output-impl.h>
|
||||
#include <gsf/gsf-output-stdio.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <gsf/gsf-utils.h>
|
||||
#ifdef HAVE_GLIB26
|
||||
#include <glib/gstdio.h>
|
||||
#else
|
||||
#include "glib24_26-compat.h"
|
||||
#endif // HAVE_GLIB26
|
||||
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
struct _GsfOutfileStdio {
|
||||
GsfOutfile parent;
|
||||
char *root;
|
||||
};
|
||||
typedef GsfOutfileClass GsfOutfileStdioClass;
|
||||
|
||||
static void
|
||||
gsf_outfile_stdio_finalize (GObject *obj)
|
||||
{
|
||||
GsfOutfileStdio *ofs = GSF_OUTFILE_STDIO (obj);
|
||||
g_free (ofs->root);
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static GsfOutput *
|
||||
gsf_outfile_stdio_new_child (GsfOutfile *parent,
|
||||
char const *name, gboolean is_dir,
|
||||
G_GNUC_UNUSED char const *first_property_name,
|
||||
G_GNUC_UNUSED va_list args)
|
||||
{
|
||||
GsfOutfileStdio *ofs = GSF_OUTFILE_STDIO (parent);
|
||||
GsfOutput *child;
|
||||
char *path = g_build_filename (ofs->root, name, NULL);
|
||||
|
||||
/* FIXME FIXME FIXME FIX : allow args */
|
||||
if (is_dir)
|
||||
child = (GsfOutput *)gsf_outfile_stdio_new (path, NULL);
|
||||
else
|
||||
child = gsf_output_stdio_new (path, NULL);
|
||||
g_free (path);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_outfile_stdio_close (G_GNUC_UNUSED GsfOutput *output)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_outfile_stdio_init (GsfOutfileStdio *ofs)
|
||||
{
|
||||
ofs->root = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_outfile_stdio_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
GsfOutputClass *output_class = GSF_OUTPUT_CLASS (gobject_class);
|
||||
GsfOutfileClass *outfile_class = GSF_OUTFILE_CLASS (gobject_class);
|
||||
|
||||
parent_class = g_type_class_peek (GSF_OUTFILE_TYPE);
|
||||
|
||||
gobject_class->finalize = gsf_outfile_stdio_finalize;
|
||||
|
||||
output_class->Close = gsf_outfile_stdio_close;
|
||||
output_class->Seek = NULL;
|
||||
output_class->Write = NULL;
|
||||
output_class->Vprintf = NULL;
|
||||
|
||||
outfile_class->new_child = gsf_outfile_stdio_new_child;
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfOutfileStdio, gsf_outfile_stdio,
|
||||
gsf_outfile_stdio_class_init, gsf_outfile_stdio_init,
|
||||
GSF_OUTFILE_TYPE)
|
||||
|
||||
/**
|
||||
* gsf_outfile_stdio_new :
|
||||
* @root : root directory in utf8.
|
||||
* @err : optionally NULL.
|
||||
*
|
||||
* Returns a new outfile or NULL.
|
||||
**/
|
||||
GsfOutfile *
|
||||
gsf_outfile_stdio_new_valist (char const *root, GError **err,
|
||||
char const *first_property_name,
|
||||
va_list var_args)
|
||||
{
|
||||
GsfOutfileStdio *ofs;
|
||||
|
||||
if (0 != g_mkdir (root, 0777)) {
|
||||
if (err != NULL) {
|
||||
int save_errno = errno;
|
||||
char *utf8name = g_filename_display_name (root);
|
||||
*err = g_error_new (gsf_output_error_id (), 0,
|
||||
"%s: %s",
|
||||
utf8name, g_strerror (save_errno));
|
||||
g_free (utf8name);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ofs = (GsfOutfileStdio *) g_object_new_valist (GSF_OUTFILE_STDIO_TYPE,
|
||||
first_property_name, var_args);
|
||||
ofs->root = g_strdup (root);
|
||||
gsf_output_set_name_from_filename (GSF_OUTPUT (ofs), root);
|
||||
|
||||
return GSF_OUTFILE (ofs);
|
||||
}
|
||||
|
||||
GsfOutfile *
|
||||
gsf_outfile_stdio_new_full (char const *root, GError **err,
|
||||
const gchar *first_property_name,
|
||||
...)
|
||||
{
|
||||
GsfOutfile *res;
|
||||
va_list var_args;
|
||||
|
||||
va_start (var_args, first_property_name);
|
||||
res = gsf_outfile_stdio_new_valist (root, err, first_property_name, var_args);
|
||||
va_end (var_args);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_outfile_stdio_new :
|
||||
* @root : root directory in utf8.
|
||||
* @err : optionally NULL.
|
||||
*
|
||||
* Returns a new outfile or NULL.
|
||||
**/
|
||||
GsfOutfile *
|
||||
gsf_outfile_stdio_new (char const *root, GError **err)
|
||||
{
|
||||
return gsf_outfile_stdio_new_full (root, err, NULL);
|
||||
}
|
||||
46
lib/libgsf-1.12.3/gsf/gsf-outfile-stdio.h
Normal file
46
lib/libgsf-1.12.3/gsf/gsf-outfile-stdio.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-outfile-stdio.h: write a directory tree
|
||||
*
|
||||
* Copyright (C) 2004 Novell, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_OUTFILE_STDIO_H
|
||||
#define GSF_OUTFILE_STDIO_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GsfOutfileStdio GsfOutfileStdio;
|
||||
|
||||
#define GSF_OUTFILE_STDIO_TYPE (gsf_outfile_stdio_get_type ())
|
||||
#define GSF_OUTFILE_STDIO(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_OUTFILE_STDIO_TYPE, GsfOutfileStdio))
|
||||
#define GSF_IS_OUTFILE_STDIO(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_OUTFILE_STDIO_TYPE))
|
||||
|
||||
GType gsf_outfile_stdio_get_type (void);
|
||||
GsfOutfile *gsf_outfile_stdio_new (char const *root, GError **err);
|
||||
GsfOutfile *gsf_outfile_stdio_new_full (char const *root, GError **err,
|
||||
char const *first_property_name,
|
||||
...); /* G_GNUC_NULL_TERMINATED */
|
||||
GsfOutfile *gsf_outfile_stdio_new_valist (char const *root, GError **err,
|
||||
char const *first_property_name,
|
||||
va_list var_args);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_OUTFILE_H */
|
||||
764
lib/libgsf-1.12.3/gsf/gsf-outfile-zip.c
Normal file
764
lib/libgsf-1.12.3/gsf/gsf-outfile-zip.c
Normal file
@@ -0,0 +1,764 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-outfile-zip.c: zip archive output.
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jon K Hellan (hellan@acm.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Outc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-outfile-impl.h>
|
||||
#include <gsf/gsf-outfile-zip.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <gsf/gsf-utils.h>
|
||||
#include <gsf/gsf-zip-impl.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#ifndef HAVE_GLIB26
|
||||
#include <gsf/glib24_26-compat.h>
|
||||
#endif
|
||||
|
||||
#undef G_LOG_DOMAIN
|
||||
#define G_LOG_DOMAIN "libgsf:zip"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_SINK,
|
||||
PROP_ENTRY_NAME,
|
||||
PROP_COMPRESSION_LEVEL
|
||||
};
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
struct _GsfOutfileZip {
|
||||
GsfOutfile parent;
|
||||
|
||||
GsfOutput *sink;
|
||||
GsfOutfileZip *root;
|
||||
|
||||
char *entry_name;
|
||||
|
||||
GsfZipVDir *vdir;
|
||||
GPtrArray *root_order; /* only valid for the root */
|
||||
|
||||
z_stream *stream;
|
||||
GsfZipCompressionMethod compression_method;
|
||||
|
||||
gboolean writing;
|
||||
|
||||
guint8 *buf;
|
||||
size_t buf_size;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
GsfOutfileClass parent_class;
|
||||
} GsfOutfileZipClass;
|
||||
|
||||
#define GSF_OUTFILE_ZIP_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSF_OUTFILE_ZIP_TYPE, GsfOutfileZipClass))
|
||||
#define GSF_IS_OUTFILE_ZIP_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSF_OUTFILE_ZIP_TYPE))
|
||||
|
||||
static void
|
||||
disconnect_children (GsfOutfileZip *zip)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if (!zip->root_order)
|
||||
return;
|
||||
|
||||
for (i = 0 ; i < zip->root_order->len ; i++) {
|
||||
GsfOutfileZip *child =
|
||||
g_ptr_array_index (zip->root_order, i);
|
||||
if (child)
|
||||
g_object_unref (child);
|
||||
}
|
||||
g_ptr_array_free (zip->root_order, TRUE);
|
||||
zip->root_order = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_outfile_zip_finalize (GObject *obj)
|
||||
{
|
||||
GsfOutfileZip *zip = GSF_OUTFILE_ZIP (obj);
|
||||
|
||||
/* If the closing failed, we might have stuff here. */
|
||||
disconnect_children (zip);
|
||||
|
||||
if (zip->sink != NULL) {
|
||||
g_object_unref (zip->sink);
|
||||
zip->sink = NULL;
|
||||
}
|
||||
|
||||
g_free (zip->entry_name);
|
||||
|
||||
if (zip->stream)
|
||||
(void) deflateEnd (zip->stream);
|
||||
g_free (zip->stream);
|
||||
g_free (zip->buf);
|
||||
|
||||
if (zip == zip->root)
|
||||
gsf_vdir_free (zip->vdir, TRUE); /* Frees vdirs recursively */
|
||||
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static GObject *
|
||||
gsf_outfile_zip_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_params)
|
||||
{
|
||||
GsfOutfileZip *zip =(GsfOutfileZip *)
|
||||
(parent_class->constructor (type,
|
||||
n_construct_properties,
|
||||
construct_params));
|
||||
|
||||
if (!zip->entry_name) {
|
||||
zip->vdir = gsf_vdir_new ("", TRUE, NULL);
|
||||
zip->root_order = g_ptr_array_new ();
|
||||
zip->root = zip;
|
||||
|
||||
/* The names are the same */
|
||||
gsf_output_set_name (GSF_OUTPUT (zip), gsf_output_name (zip->sink));
|
||||
gsf_output_set_container (GSF_OUTPUT (zip), NULL);
|
||||
}
|
||||
|
||||
return (GObject *)zip;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_outfile_zip_seek (G_GNUC_UNUSED GsfOutput *output,
|
||||
G_GNUC_UNUSED gsf_off_t offset,
|
||||
G_GNUC_UNUSED GSeekType whence)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
zip_dirent_write (GsfOutput *sink, GsfZipDirent *dirent)
|
||||
{
|
||||
static guint8 const dirent_signature[] =
|
||||
{ 'P', 'K', 0x01, 0x02 };
|
||||
guint8 buf[ZIP_DIRENT_SIZE];
|
||||
int nlen = strlen (dirent->name);
|
||||
gboolean ret;
|
||||
|
||||
memset (buf, 0, sizeof buf);
|
||||
memcpy (buf, dirent_signature, sizeof dirent_signature);
|
||||
GSF_LE_SET_GUINT16 (buf + ZIP_DIRENT_ENCODER, 0x317); /* Unix */
|
||||
GSF_LE_SET_GUINT16 (buf + ZIP_DIRENT_EXTRACT, 0x14);
|
||||
GSF_LE_SET_GUINT16 (buf + ZIP_DIRENT_FLAGS, 0x08);
|
||||
GSF_LE_SET_GUINT16 (buf + ZIP_DIRENT_COMPR_METHOD,
|
||||
dirent->compr_method);
|
||||
GSF_LE_SET_GUINT32 (buf + ZIP_DIRENT_DOSTIME, dirent->dostime);
|
||||
GSF_LE_SET_GUINT32 (buf + ZIP_DIRENT_CRC32, dirent->crc32);
|
||||
GSF_LE_SET_GUINT32 (buf + ZIP_DIRENT_CSIZE, dirent->csize);
|
||||
GSF_LE_SET_GUINT32 (buf + ZIP_DIRENT_USIZE, dirent->usize);
|
||||
GSF_LE_SET_GUINT16 (buf + ZIP_DIRENT_NAME_SIZE, nlen);
|
||||
GSF_LE_SET_GUINT16 (buf + ZIP_DIRENT_EXTRAS_SIZE, 0);
|
||||
GSF_LE_SET_GUINT16 (buf + ZIP_DIRENT_COMMENT_SIZE, 0);
|
||||
GSF_LE_SET_GUINT16 (buf + ZIP_DIRENT_DISKSTART, 0);
|
||||
GSF_LE_SET_GUINT16 (buf + ZIP_DIRENT_FILE_TYPE, 0);
|
||||
/* Hardcode file mode 644 */
|
||||
GSF_LE_SET_GUINT32 (buf + ZIP_DIRENT_FILE_MODE, 0644 << 16);
|
||||
GSF_LE_SET_GUINT32 (buf + ZIP_DIRENT_OFFSET, dirent->offset);
|
||||
|
||||
ret = gsf_output_write (sink, sizeof buf, buf);
|
||||
if (ret)
|
||||
ret = gsf_output_write (sink, nlen, dirent->name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
zip_trailer_write (GsfOutfileZip *zip, unsigned entries, gsf_off_t dirpos)
|
||||
{
|
||||
static guint8 const trailer_signature[] =
|
||||
{ 'P', 'K', 0x05, 0x06 };
|
||||
guint8 buf[ZIP_TRAILER_SIZE];
|
||||
gsf_off_t pos = gsf_output_tell (zip->sink);
|
||||
|
||||
memset (buf, 0, sizeof buf);
|
||||
memcpy (buf, trailer_signature, sizeof trailer_signature);
|
||||
GSF_LE_SET_GUINT16 (buf + ZIP_TRAILER_ENTRIES, entries);
|
||||
GSF_LE_SET_GUINT16 (buf + ZIP_TRAILER_TOTAL_ENTRIES, entries);
|
||||
GSF_LE_SET_GUINT32 (buf + ZIP_TRAILER_DIR_SIZE, pos - dirpos);
|
||||
GSF_LE_SET_GUINT32 (buf + ZIP_TRAILER_DIR_POS, dirpos);
|
||||
|
||||
return gsf_output_write (zip->sink, sizeof buf, buf);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
zip_close_root (GsfOutput *output)
|
||||
{
|
||||
GsfOutfileZip *zip = GSF_OUTFILE_ZIP (output);
|
||||
GsfOutfileZip *child;
|
||||
gsf_off_t dirpos = gsf_output_tell (zip->sink);
|
||||
GPtrArray *elem = zip->root_order;
|
||||
unsigned entries = elem->len;
|
||||
unsigned i;
|
||||
|
||||
/* Check that children are closed */
|
||||
for (i = 0 ; i < elem->len ; i++) {
|
||||
child = g_ptr_array_index (elem, i);
|
||||
if (!gsf_output_is_closed (GSF_OUTPUT (child))) {
|
||||
g_warning ("Child still open");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write directory */
|
||||
for (i = 0 ; i < entries ; i++) {
|
||||
child = g_ptr_array_index (elem, i);
|
||||
if (!zip_dirent_write (zip->sink, child->vdir->dirent))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
disconnect_children (zip);
|
||||
|
||||
return zip_trailer_write (zip, entries, dirpos);
|
||||
}
|
||||
|
||||
static void
|
||||
stream_name_write_to_buf (GsfOutfileZip *zip, GString *res)
|
||||
{
|
||||
GsfOutput *output = GSF_OUTPUT (zip);
|
||||
GsfOutfile *container;
|
||||
|
||||
if (zip == zip->root)
|
||||
return;
|
||||
|
||||
container = gsf_output_container (output);
|
||||
if (container) {
|
||||
stream_name_write_to_buf (GSF_OUTFILE_ZIP (container), res);
|
||||
if (res->len) {
|
||||
/* Forward slash is specified by the format. */
|
||||
g_string_append_c (res, '/');
|
||||
}
|
||||
}
|
||||
|
||||
if (zip->entry_name)
|
||||
g_string_append (res, zip->entry_name);
|
||||
}
|
||||
|
||||
static char *
|
||||
stream_name_build (GsfOutfileZip *zip)
|
||||
{
|
||||
GString *str = g_string_sized_new (80);
|
||||
stream_name_write_to_buf (zip, str);
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
static guint32
|
||||
zip_time_make (time_t t)
|
||||
{
|
||||
struct tm *localnow = localtime (&t);
|
||||
guint32 ztime;
|
||||
|
||||
ztime = (localnow->tm_year - 80) & 0x7f;
|
||||
ztime = (ztime << 4) | ((localnow->tm_mon + 1) & 0x0f);
|
||||
ztime = (ztime << 5) | (localnow->tm_mday & 0x1f);
|
||||
ztime = (ztime << 5) | (localnow->tm_hour & 0x1f);
|
||||
ztime = (ztime << 6) | (localnow->tm_min & 0x3f);
|
||||
ztime = (ztime << 5) | ((localnow->tm_sec / 2) & 0x1f);
|
||||
|
||||
return ztime;
|
||||
}
|
||||
|
||||
static GsfZipDirent*
|
||||
zip_dirent_new_out (GsfOutfileZip *zip)
|
||||
{
|
||||
GsfZipDirent *dirent = gsf_zip_dirent_new ();
|
||||
dirent->name = stream_name_build (zip);
|
||||
dirent->compr_method = zip->compression_method;
|
||||
dirent->dostime = zip_time_make (time (NULL));
|
||||
return dirent;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
zip_header_write (GsfOutfileZip *zip)
|
||||
{
|
||||
static guint8 const header_signature[] =
|
||||
{ 'P', 'K', 0x03, 0x04 };
|
||||
guint8 hbuf[ZIP_HEADER_SIZE];
|
||||
GsfZipDirent *dirent = zip->vdir->dirent;
|
||||
guint16 flags = 0;
|
||||
char *name = dirent->name;
|
||||
int nlen = strlen (name);
|
||||
gboolean ret;
|
||||
|
||||
memset (hbuf, 0, sizeof hbuf);
|
||||
memcpy (hbuf, header_signature, sizeof header_signature);
|
||||
GSF_LE_SET_GUINT16 (hbuf + ZIP_HEADER_VERSION, 0x14);
|
||||
if (dirent->compr_method == GSF_ZIP_DEFLATED)
|
||||
flags = 0x08;
|
||||
GSF_LE_SET_GUINT16 (hbuf + ZIP_HEADER_FLAGS, flags);
|
||||
GSF_LE_SET_GUINT16 (hbuf + ZIP_HEADER_COMP_METHOD,
|
||||
dirent->compr_method);
|
||||
GSF_LE_SET_GUINT32 (hbuf + ZIP_HEADER_TIME, dirent->dostime);
|
||||
GSF_LE_SET_GUINT16 (hbuf + ZIP_HEADER_NAME_LEN, nlen);
|
||||
ret = gsf_output_write (zip->sink, sizeof hbuf, hbuf);
|
||||
if (ret)
|
||||
ret = gsf_output_write (zip->sink, nlen, name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
zip_init_write (GsfOutput *output)
|
||||
{
|
||||
GsfOutfileZip *zip = GSF_OUTFILE_ZIP (output);
|
||||
GsfZipDirent *dirent;
|
||||
int ret;
|
||||
|
||||
if (zip->root->writing) {
|
||||
g_warning ("Already writing to another stream in archive");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!gsf_output_wrap (G_OBJECT (output), zip->sink))
|
||||
return FALSE;
|
||||
|
||||
dirent = zip_dirent_new_out (zip);
|
||||
dirent->offset = gsf_output_tell (zip->sink);
|
||||
if (zip->vdir->dirent)
|
||||
g_warning ("Leak.");
|
||||
|
||||
zip->vdir->dirent = dirent;
|
||||
zip_header_write (zip);
|
||||
zip->writing = TRUE;
|
||||
zip->root->writing = TRUE;
|
||||
dirent->crc32 = crc32 (0L, Z_NULL, 0);
|
||||
if (zip->compression_method == GSF_ZIP_DEFLATED) {
|
||||
if (!zip->stream) {
|
||||
zip->stream = g_new0 (z_stream, 1);
|
||||
}
|
||||
ret = deflateInit2 (zip->stream, Z_DEFAULT_COMPRESSION,
|
||||
Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL,
|
||||
Z_DEFAULT_STRATEGY);
|
||||
if (ret != Z_OK)
|
||||
return FALSE;
|
||||
if (!zip->buf) {
|
||||
zip->buf_size = ZIP_BUF_SIZE;
|
||||
zip->buf = g_new (guint8, zip->buf_size);
|
||||
}
|
||||
zip->stream->next_out = zip->buf;
|
||||
zip->stream->avail_out = zip->buf_size;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
zip_output_block (GsfOutfileZip *zip)
|
||||
{
|
||||
size_t num_bytes = zip->buf_size - zip->stream->avail_out;
|
||||
GsfZipDirent *dirent = zip->vdir->dirent;
|
||||
|
||||
if (!gsf_output_write (zip->sink, num_bytes, zip->buf)) {
|
||||
return FALSE;
|
||||
}
|
||||
dirent->csize += num_bytes;
|
||||
zip->stream->next_out = zip->buf;
|
||||
zip->stream->avail_out = zip->buf_size;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
zip_flush (GsfOutfileZip *zip)
|
||||
{
|
||||
int zret;
|
||||
|
||||
do {
|
||||
zret = deflate (zip->stream, Z_FINISH);
|
||||
if (zret == Z_OK || (zret == Z_BUF_ERROR && zip->stream->avail_out == 0)) {
|
||||
/* In this case Z_OK or Z_BUF_ERROR means more buffer
|
||||
space is needed */
|
||||
if (!zip_output_block (zip))
|
||||
return FALSE;
|
||||
}
|
||||
} while (zret == Z_OK || zret == Z_BUF_ERROR);
|
||||
if (zret != Z_STREAM_END)
|
||||
return FALSE;
|
||||
if (!zip_output_block (zip))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Write the per stream data descriptor */
|
||||
static gboolean
|
||||
zip_ddesc_write (GsfOutfileZip *zip)
|
||||
{
|
||||
static guint8 const ddesc_signature[] =
|
||||
{ 'P', 'K', 0x07, 0x08 };
|
||||
guint8 buf[16];
|
||||
GsfZipDirent *dirent = zip->vdir->dirent;
|
||||
|
||||
memcpy (buf, ddesc_signature, sizeof ddesc_signature);
|
||||
GSF_LE_SET_GUINT32 (buf + 4, dirent->crc32);
|
||||
GSF_LE_SET_GUINT32 (buf + 8, dirent->csize);
|
||||
GSF_LE_SET_GUINT32 (buf + 12, dirent->usize);
|
||||
if (!gsf_output_write (zip->sink, sizeof buf, buf)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
zip_header_write_sizes (GsfOutfileZip *zip)
|
||||
{
|
||||
guint8 hbuf[ZIP_HEADER_SIZE];
|
||||
GsfZipDirent *dirent = zip->vdir->dirent;
|
||||
gsf_off_t pos = gsf_output_tell (zip->sink);
|
||||
|
||||
if (!gsf_output_seek (zip->sink, dirent->offset + ZIP_HEADER_CRC,
|
||||
G_SEEK_SET))
|
||||
return FALSE;
|
||||
|
||||
GSF_LE_SET_GUINT32 (hbuf + ZIP_HEADER_CRC, dirent->crc32);
|
||||
GSF_LE_SET_GUINT32 (hbuf + ZIP_HEADER_COMP_SIZE, dirent->csize);
|
||||
GSF_LE_SET_GUINT32 (hbuf + ZIP_HEADER_UNCOMP_SIZE, dirent->usize);
|
||||
if (!gsf_output_write (zip->sink, 12, hbuf + ZIP_HEADER_CRC))
|
||||
return FALSE;
|
||||
if (!gsf_output_seek (zip->sink, pos, G_SEEK_SET))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
zip_close_stream (GsfOutput *output)
|
||||
{
|
||||
GsfOutfileZip *zip = GSF_OUTFILE_ZIP (output);
|
||||
gboolean result;
|
||||
|
||||
if (!zip->writing)
|
||||
if (!zip_init_write (output))
|
||||
return FALSE;
|
||||
|
||||
if (zip->compression_method == GSF_ZIP_DEFLATED) {
|
||||
if (!zip_flush (zip))
|
||||
return FALSE;
|
||||
|
||||
if (!zip_ddesc_write (zip)) /* Write data descriptor */
|
||||
return FALSE;
|
||||
} else {
|
||||
if (!zip_header_write_sizes (zip)) /* Write crc, sizes */
|
||||
return FALSE;
|
||||
}
|
||||
zip->root->writing = FALSE;
|
||||
|
||||
result = gsf_output_unwrap (G_OBJECT (output), zip->sink);
|
||||
|
||||
/* Free unneeded memory */
|
||||
if (zip->stream) {
|
||||
(void) deflateEnd (zip->stream);
|
||||
g_free (zip->stream);
|
||||
zip->stream = NULL;
|
||||
g_free (zip->buf);
|
||||
zip->buf = NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_outfile_zip_close (GsfOutput *output)
|
||||
{
|
||||
GsfOutfileZip *zip = GSF_OUTFILE_ZIP (output);
|
||||
gboolean ret;
|
||||
|
||||
/* The root dir */
|
||||
if (zip == zip->root)
|
||||
ret = zip_close_root (output);
|
||||
else if (zip->vdir->is_directory)
|
||||
/* Directories: Do nothing. Should change this to actually
|
||||
* write dirs which don't have children. */
|
||||
ret = TRUE;
|
||||
else
|
||||
ret = zip_close_stream (output);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_outfile_zip_write (GsfOutput *output,
|
||||
size_t num_bytes, guint8 const *data)
|
||||
{
|
||||
GsfOutfileZip *zip = GSF_OUTFILE_ZIP (output);
|
||||
GsfZipDirent *dirent;
|
||||
int ret;
|
||||
|
||||
g_return_val_if_fail (zip && zip->vdir, FALSE);
|
||||
g_return_val_if_fail (!zip->vdir->is_directory, FALSE);
|
||||
g_return_val_if_fail (data, FALSE);
|
||||
|
||||
if (!zip->writing)
|
||||
if (!zip_init_write (output))
|
||||
return FALSE;
|
||||
|
||||
dirent = zip->vdir->dirent;
|
||||
if (zip->compression_method == GSF_ZIP_DEFLATED) {
|
||||
zip->stream->next_in = (unsigned char *) data;
|
||||
zip->stream->avail_in = num_bytes;
|
||||
|
||||
while (zip->stream->avail_in > 0) {
|
||||
if (zip->stream->avail_out == 0) {
|
||||
if (!zip_output_block (zip))
|
||||
return FALSE;
|
||||
}
|
||||
ret = deflate (zip->stream, Z_NO_FLUSH);
|
||||
if (ret != Z_OK)
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
if (!gsf_output_write (zip->sink, num_bytes, data))
|
||||
return FALSE;
|
||||
dirent->csize += num_bytes;
|
||||
}
|
||||
dirent->crc32 = crc32 (dirent->crc32, data, num_bytes);
|
||||
dirent->usize += num_bytes;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
root_register_child (GsfOutfileZip *root, GsfOutfileZip *child)
|
||||
{
|
||||
child->root = root;
|
||||
if (!child->vdir->is_directory) {
|
||||
g_object_ref (child);
|
||||
g_ptr_array_add (root->root_order, child);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_outfile_zip_set_sink (GsfOutfileZip *zip, GsfOutput *sink)
|
||||
{
|
||||
if (sink)
|
||||
g_object_ref (sink);
|
||||
if (zip->sink)
|
||||
g_object_unref (zip->sink);
|
||||
zip->sink = sink;
|
||||
}
|
||||
|
||||
static GsfOutput *
|
||||
gsf_outfile_zip_new_child (GsfOutfile *parent,
|
||||
char const *name, gboolean is_dir,
|
||||
char const *first_property_name, va_list args)
|
||||
{
|
||||
GsfOutfileZip *zip_parent = (GsfOutfileZip *)parent;
|
||||
GsfOutfileZip *child;
|
||||
size_t n_params = 0;
|
||||
GParameter *params = NULL;
|
||||
char *display_name;
|
||||
|
||||
g_return_val_if_fail (zip_parent != NULL, NULL);
|
||||
g_return_val_if_fail (zip_parent->vdir, NULL);
|
||||
g_return_val_if_fail (zip_parent->vdir->is_directory, NULL);
|
||||
g_return_val_if_fail (name && *name, NULL);
|
||||
|
||||
gsf_property_settings_collect (GSF_OUTFILE_ZIP_TYPE,
|
||||
¶ms, &n_params,
|
||||
"sink", zip_parent->sink,
|
||||
"entry-name", name,
|
||||
NULL);
|
||||
gsf_property_settings_collect_valist (GSF_OUTFILE_ZIP_TYPE,
|
||||
¶ms, &n_params,
|
||||
first_property_name,
|
||||
args);
|
||||
child = (GsfOutfileZip *)g_object_newv (GSF_OUTFILE_ZIP_TYPE,
|
||||
n_params,
|
||||
params);
|
||||
gsf_property_settings_free (params, n_params);
|
||||
|
||||
child->vdir = gsf_vdir_new (name, is_dir, NULL);
|
||||
|
||||
/* FIXME: It isn't clear what encoding name is in. */
|
||||
display_name = g_filename_display_name (name);
|
||||
gsf_output_set_name (GSF_OUTPUT (child), display_name);
|
||||
g_free (display_name);
|
||||
|
||||
gsf_output_set_container (GSF_OUTPUT (child), parent);
|
||||
gsf_vdir_add_child (zip_parent->vdir, child->vdir);
|
||||
root_register_child (zip_parent->root, child);
|
||||
|
||||
return GSF_OUTPUT (child);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_outfile_zip_init (GObject *obj)
|
||||
{
|
||||
GsfOutfileZip *zip = GSF_OUTFILE_ZIP (obj);
|
||||
|
||||
zip->sink = NULL;
|
||||
zip->root = NULL;
|
||||
zip->entry_name = NULL;
|
||||
zip->vdir = NULL;
|
||||
zip->root_order = NULL;
|
||||
zip->stream = NULL;
|
||||
zip->compression_method = GSF_ZIP_DEFLATED;
|
||||
zip->writing = FALSE;
|
||||
zip->buf = NULL;
|
||||
zip->buf_size = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_outfile_zip_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GsfOutfileZip *zip = (GsfOutfileZip *)object;
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_SINK:
|
||||
g_value_set_object (value, zip->sink);
|
||||
break;
|
||||
case PROP_ENTRY_NAME:
|
||||
g_value_set_string (value, zip->entry_name);
|
||||
break;
|
||||
case PROP_COMPRESSION_LEVEL:
|
||||
g_value_set_int (value,
|
||||
zip->vdir->dirent
|
||||
? zip->vdir->dirent->compr_method
|
||||
: 0);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_outfile_zip_set_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue const *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GsfOutfileZip *zip = (GsfOutfileZip *)object;
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_SINK:
|
||||
gsf_outfile_zip_set_sink (zip, g_value_get_object (value));
|
||||
break;
|
||||
case PROP_ENTRY_NAME:
|
||||
zip->entry_name = g_strdup (g_value_get_string (value));
|
||||
break;
|
||||
case PROP_COMPRESSION_LEVEL: {
|
||||
int level = g_value_get_int (value);
|
||||
switch (level) {
|
||||
case GSF_ZIP_STORED:
|
||||
case GSF_ZIP_DEFLATED:
|
||||
zip->compression_method = level;
|
||||
break;
|
||||
default:
|
||||
g_warning ("Unsupported compression level %d", level);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_outfile_zip_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
GsfOutputClass *input_class = GSF_OUTPUT_CLASS (gobject_class);
|
||||
GsfOutfileClass *outfile_class = GSF_OUTFILE_CLASS (gobject_class);
|
||||
|
||||
gobject_class->constructor = gsf_outfile_zip_constructor;
|
||||
gobject_class->finalize = gsf_outfile_zip_finalize;
|
||||
gobject_class->get_property = gsf_outfile_zip_get_property;
|
||||
gobject_class->set_property = gsf_outfile_zip_set_property;
|
||||
|
||||
input_class->Write = gsf_outfile_zip_write;
|
||||
input_class->Seek = gsf_outfile_zip_seek;
|
||||
input_class->Close = gsf_outfile_zip_close;
|
||||
outfile_class->new_child = gsf_outfile_zip_new_child;
|
||||
|
||||
parent_class = g_type_class_peek_parent (gobject_class);
|
||||
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_SINK,
|
||||
g_param_spec_object ("sink", "Sink",
|
||||
"Where the archive is written.",
|
||||
GSF_OUTPUT_TYPE,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_ENTRY_NAME,
|
||||
g_param_spec_string ("entry-name", "Entry Name",
|
||||
"The filename of this member in the archive without path.",
|
||||
NULL,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_COMPRESSION_LEVEL,
|
||||
g_param_spec_int ("compression-level",
|
||||
"Compression Level",
|
||||
"The level of compression used, zero meaning none.",
|
||||
0, 10,
|
||||
GSF_ZIP_DEFLATED,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfOutfileZip, gsf_outfile_zip,
|
||||
gsf_outfile_zip_class_init, gsf_outfile_zip_init,
|
||||
GSF_OUTFILE_TYPE)
|
||||
|
||||
/**
|
||||
* gsf_outfile_zip_new :
|
||||
* @sink :
|
||||
* @err :
|
||||
*
|
||||
* Creates the root directory of a Zip file and manages the addition of
|
||||
* children.
|
||||
*
|
||||
* NOTE : adds a reference to @sink
|
||||
*
|
||||
* Returns : the new zip file handler
|
||||
**/
|
||||
GsfOutfile *
|
||||
gsf_outfile_zip_new (GsfOutput *sink, G_GNUC_UNUSED GError **err)
|
||||
{
|
||||
g_return_val_if_fail (GSF_IS_OUTPUT (sink), NULL);
|
||||
|
||||
return (GsfOutfile *)g_object_new (GSF_OUTFILE_ZIP_TYPE,
|
||||
"sink", sink,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* deprecated has no effect */
|
||||
gboolean
|
||||
gsf_outfile_zip_set_compression_method (G_GNUC_UNUSED GsfOutfileZip *zip,
|
||||
G_GNUC_UNUSED GsfZipCompressionMethod method)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
59
lib/libgsf-1.12.3/gsf/gsf-outfile-zip.h
Normal file
59
lib/libgsf-1.12.3/gsf/gsf-outfile-zip.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-outfile-zip.h: interface for zip archive output.
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jon K Hellan (hellan@acm.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_OUTFILE_ZIP_H
|
||||
#define GSF_OUTFILE_ZIP_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum {
|
||||
GSF_ZIP_STORED = 0, /* supported for export */
|
||||
GSF_ZIP_SHRUNK = 1,
|
||||
GSF_ZIP_REDUCEDx1 = 2,
|
||||
GSF_ZIP_REDUCEDx2 = 3,
|
||||
GSF_ZIP_REDUCEDx3 = 4,
|
||||
GSF_ZIP_REDUCEDx4 = 5,
|
||||
GSF_ZIP_IMPLODED = 6,
|
||||
GSF_ZIP_TOKENIZED = 7,
|
||||
GSF_ZIP_DEFLATED = 8, /* supported for export */
|
||||
GSF_ZIP_DEFLATED_BETTER = 9,
|
||||
GSF_ZIP_IMPLODED_BETTER = 10
|
||||
} GsfZipCompressionMethod;
|
||||
|
||||
typedef struct _GsfOutfileZip GsfOutfileZip;
|
||||
|
||||
#define GSF_OUTFILE_ZIP_TYPE (gsf_outfile_zip_get_type ())
|
||||
#define GSF_OUTFILE_ZIP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_OUTFILE_ZIP_TYPE, GsfOutfileZip))
|
||||
#define GSF_IS_OUTFILE_ZIP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_OUTFILE_ZIP_TYPE))
|
||||
|
||||
GType gsf_outfile_zip_get_type (void);
|
||||
GsfOutfile *gsf_outfile_zip_new (GsfOutput *sink, GError **err);
|
||||
|
||||
/* Deprecated. Has no effect. */
|
||||
gboolean gsf_outfile_zip_set_compression_method (GsfOutfileZip *zip,
|
||||
GsfZipCompressionMethod method);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_OUTFILE_H */
|
||||
83
lib/libgsf-1.12.3/gsf/gsf-outfile.c
Normal file
83
lib/libgsf-1.12.3/gsf/gsf-outfile.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-outfile.c :
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-outfile-impl.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
|
||||
#define GET_CLASS(instance) G_TYPE_INSTANCE_GET_CLASS (instance, GSF_OUTFILE_TYPE, GsfOutfileClass)
|
||||
|
||||
/**
|
||||
* gsf_outfile_new_child :
|
||||
* @outfile : A #GsfOutfile
|
||||
* @name : The name of the new child to create
|
||||
* @is_dir : TRUE to create a directory, FALSE to create a plain file
|
||||
*
|
||||
* Returns a newly created child
|
||||
**/
|
||||
GsfOutput *
|
||||
gsf_outfile_new_child (GsfOutfile *outfile,
|
||||
char const *name, gboolean is_dir)
|
||||
{
|
||||
return gsf_outfile_new_child_full (outfile, name, is_dir, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_outfile_new_child_full :
|
||||
* @outfile : A #GsfOutfile
|
||||
* @name : The name of the new child to create
|
||||
* @is_dir : TRUE to create a directory, FALSE to create a plain file
|
||||
* @first_property_name :
|
||||
* @Varargs :
|
||||
*
|
||||
* Returns a newly created child
|
||||
**/
|
||||
GsfOutput *
|
||||
gsf_outfile_new_child_full (GsfOutfile *outfile,
|
||||
char const *name, gboolean is_dir,
|
||||
char const *first_property_name,
|
||||
...)
|
||||
{
|
||||
GsfOutput *res;
|
||||
va_list args;
|
||||
|
||||
g_return_val_if_fail (outfile != NULL, NULL);
|
||||
|
||||
va_start (args, first_property_name);
|
||||
res = gsf_outfile_new_child_varg (outfile, name, is_dir,
|
||||
first_property_name, args);
|
||||
va_end (args);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
GsfOutput *
|
||||
gsf_outfile_new_child_varg (GsfOutfile *outfile,
|
||||
char const *name, gboolean is_dir,
|
||||
char const *first_property_name,
|
||||
va_list args)
|
||||
{
|
||||
g_return_val_if_fail (outfile != NULL, NULL);
|
||||
return GET_CLASS (outfile)->new_child (outfile, name, is_dir,
|
||||
first_property_name, args);
|
||||
}
|
||||
|
||||
GSF_CLASS_ABSTRACT (GsfOutfile, gsf_outfile, NULL, NULL, GSF_OUTPUT_TYPE)
|
||||
48
lib/libgsf-1.12.3/gsf/gsf-outfile.h
Normal file
48
lib/libgsf-1.12.3/gsf/gsf-outfile.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-outfile.h: interface for creating structured files
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_OUTFILE_H
|
||||
#define GSF_OUTFILE_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSF_OUTFILE_TYPE (gsf_outfile_get_type ())
|
||||
#define GSF_OUTFILE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_OUTFILE_TYPE, GsfOutfile))
|
||||
#define GSF_IS_OUTFILE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_OUTFILE_TYPE))
|
||||
|
||||
GType gsf_outfile_get_type (void);
|
||||
|
||||
GsfOutput *gsf_outfile_new_child (GsfOutfile *outfile,
|
||||
char const *name, gboolean is_dir);
|
||||
GsfOutput *gsf_outfile_new_child_full (GsfOutfile *outfile,
|
||||
char const *name, gboolean is_dir,
|
||||
char const *first_property_name,
|
||||
...);
|
||||
GsfOutput *gsf_outfile_new_child_varg (GsfOutfile *outfile,
|
||||
char const *name, gboolean is_dir,
|
||||
char const *first_property_name,
|
||||
va_list args);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_OUTFILE_H */
|
||||
264
lib/libgsf-1.12.3/gsf/gsf-output-bzip.c
Normal file
264
lib/libgsf-1.12.3/gsf/gsf-output-bzip.c
Normal file
@@ -0,0 +1,264 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-output-bzip.c: wrapper to compress to bzipped output
|
||||
*
|
||||
* Copyright (C) 2003-2004 Dom Lachowicz (cinamod@hotmail.com)
|
||||
* 2002-2004 Jon K Hellan (hellan@acm.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
|
||||
#include <gsf/gsf-output-bzip.h>
|
||||
#include <gsf/gsf-output-impl.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <gsf/gsf-utils.h>
|
||||
|
||||
#ifdef HAVE_BZ2
|
||||
/* For getting FILE. Don't ask. */
|
||||
#include <stdio.h>
|
||||
#include <bzlib.h>
|
||||
#define BZ_BUFSIZE 1024
|
||||
#endif
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
struct _GsfOutputBzip {
|
||||
GsfOutput output;
|
||||
|
||||
#ifdef HAVE_BZ2
|
||||
GsfOutput *sink; /* compressed data */
|
||||
bz_stream stream;
|
||||
guint8 *buf;
|
||||
size_t buf_size;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
GsfOutputClass output_class;
|
||||
} GsfOutputBzipClass;
|
||||
|
||||
static void
|
||||
gsf_output_bzip_finalize (GObject *obj)
|
||||
{
|
||||
#ifdef HAVE_BZ2
|
||||
GsfOutputBzip *bzip = (GsfOutputBzip *)obj;
|
||||
|
||||
if (bzip->sink != NULL) {
|
||||
g_object_unref (G_OBJECT (bzip->sink));
|
||||
bzip->sink = NULL;
|
||||
}
|
||||
g_free (bzip->buf);
|
||||
#endif
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
#ifdef HAVE_BZ2
|
||||
static gboolean
|
||||
init_bzip (GsfOutputBzip *bzip, GError **err)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = BZ2_bzCompressInit (&bzip->stream, 6, 0, 0);
|
||||
|
||||
if (ret != BZ_OK) {
|
||||
if (err != NULL)
|
||||
*err = g_error_new (gsf_output_error_id (), 0,
|
||||
"Unable to initialize BZ2 library");
|
||||
return FALSE;
|
||||
}
|
||||
if (!bzip->buf) {
|
||||
bzip->buf_size = BZ_BUFSIZE;
|
||||
bzip->buf = g_new (guint8, bzip->buf_size);
|
||||
}
|
||||
bzip->stream.next_out = bzip->buf;
|
||||
bzip->stream.avail_out = bzip->buf_size;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
bzip_output_block (GsfOutputBzip *bzip)
|
||||
{
|
||||
size_t num_bytes = bzip->buf_size - bzip->stream.avail_out;
|
||||
|
||||
if (!gsf_output_write (bzip->sink, num_bytes, bzip->buf))
|
||||
return FALSE;
|
||||
|
||||
bzip->stream.next_out = bzip->buf;
|
||||
bzip->stream.avail_out = bzip->buf_size;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
bzip_flush (GsfOutputBzip *bzip)
|
||||
{
|
||||
int zret;
|
||||
|
||||
do {
|
||||
zret = BZ2_bzCompress (&bzip->stream, BZ_FINISH);
|
||||
if (zret == BZ_FINISH_OK) {
|
||||
/* In this case BZ_FINISH_OK means more buffer space
|
||||
needed */
|
||||
if (!bzip_output_block (bzip))
|
||||
return FALSE;
|
||||
}
|
||||
} while (zret == BZ_FINISH_OK);
|
||||
if (zret != BZ_STREAM_END) {
|
||||
g_warning ("Unexpected error code %d from bzlib during compression.",
|
||||
zret);
|
||||
return FALSE;
|
||||
}
|
||||
if (!bzip_output_block (bzip))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
gsf_output_bzip_write (GsfOutput *output,
|
||||
size_t num_bytes, guint8 const *data)
|
||||
{
|
||||
#ifdef HAVE_BZ2
|
||||
GsfOutputBzip *bzip = GSF_OUTPUT_BZIP (output);
|
||||
|
||||
g_return_val_if_fail (data, FALSE);
|
||||
|
||||
bzip->stream.next_in = (unsigned char *) data;
|
||||
bzip->stream.avail_in = num_bytes;
|
||||
|
||||
while (bzip->stream.avail_in > 0) {
|
||||
int zret;
|
||||
|
||||
if (bzip->stream.avail_out == 0) {
|
||||
if (!bzip_output_block (bzip))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
zret = BZ2_bzCompress (&bzip->stream, BZ_RUN);
|
||||
if (zret != BZ_RUN_OK) {
|
||||
g_warning ("Unexpected error code %d from bzlib during compression.",
|
||||
zret);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (bzip->stream.avail_out == 0) {
|
||||
if (!bzip_output_block (bzip))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_bzip_seek (G_GNUC_UNUSED GsfOutput *output,
|
||||
G_GNUC_UNUSED gsf_off_t offset,
|
||||
G_GNUC_UNUSED GSeekType whence)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_bzip_close (GsfOutput *output)
|
||||
{
|
||||
#ifdef HAVE_BZ2
|
||||
GsfOutputBzip *bzip = GSF_OUTPUT_BZIP (output);
|
||||
gboolean rt;
|
||||
|
||||
rt = bzip_flush (bzip);
|
||||
BZ2_bzCompressEnd (&bzip->stream);
|
||||
|
||||
return rt;
|
||||
#else
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_bzip_init (GObject *obj)
|
||||
{
|
||||
#ifdef HAVE_BZ2
|
||||
GsfOutputBzip *bzip = GSF_OUTPUT_BZIP (obj);
|
||||
|
||||
bzip->sink = NULL;
|
||||
bzip->stream.bzalloc = NULL;
|
||||
bzip->stream.bzfree = NULL;
|
||||
bzip->stream.opaque = NULL;
|
||||
bzip->stream.next_in = NULL;
|
||||
bzip->stream.next_out = NULL;
|
||||
bzip->stream.avail_in = bzip->stream.avail_out = 0;
|
||||
bzip->buf = NULL;
|
||||
bzip->buf_size = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_bzip_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
GsfOutputClass *output_class = GSF_OUTPUT_CLASS (gobject_class);
|
||||
|
||||
gobject_class->finalize = gsf_output_bzip_finalize;
|
||||
output_class->Write = gsf_output_bzip_write;
|
||||
output_class->Seek = gsf_output_bzip_seek;
|
||||
output_class->Close = gsf_output_bzip_close;
|
||||
|
||||
parent_class = g_type_class_peek_parent (gobject_class);
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfOutputBzip, gsf_output_bzip,
|
||||
gsf_output_bzip_class_init, gsf_output_bzip_init,
|
||||
GSF_OUTPUT_TYPE)
|
||||
|
||||
/**
|
||||
* gsf_output_bzip_new :
|
||||
* @sink : The underlying data source.
|
||||
* @err : optionally NULL.
|
||||
*
|
||||
* Adds a reference to @sink.
|
||||
*
|
||||
* Returns a new file or NULL.
|
||||
**/
|
||||
GsfOutput *
|
||||
gsf_output_bzip_new (GsfOutput *sink, GError **err)
|
||||
{
|
||||
#ifdef HAVE_BZ2
|
||||
GsfOutputBzip *bzip;
|
||||
|
||||
g_return_val_if_fail (GSF_IS_OUTPUT (sink), NULL);
|
||||
|
||||
bzip = g_object_new (GSF_OUTPUT_BZIP_TYPE, NULL);
|
||||
g_object_ref (G_OBJECT (sink));
|
||||
bzip->sink = sink;
|
||||
|
||||
if (!init_bzip (bzip, err)) {
|
||||
g_object_unref (G_OBJECT (bzip));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return GSF_OUTPUT (bzip);
|
||||
#else
|
||||
if (err)
|
||||
*err = g_error_new (gsf_output_error_id (), 0,
|
||||
"BZ2 support not enabled");
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
40
lib/libgsf-1.12.3/gsf/gsf-output-bzip.h
Normal file
40
lib/libgsf-1.12.3/gsf/gsf-output-bzip.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-output-bzip.h: wrapper to compress to bzipped output
|
||||
*
|
||||
* Copyright (C) 2003-2004 Dom Lachowicz (cinamod@hotmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_OUTPUT_BZIP_H
|
||||
#define GSF_OUTPUT_BZIP_H
|
||||
|
||||
#include "gsf-output.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSF_OUTPUT_BZIP_TYPE (gsf_output_bzip_get_type ())
|
||||
#define GSF_OUTPUT_BZIP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_OUTPUT_BZIP_TYPE, GsfOutputBzip))
|
||||
#define GSF_IS_OUTPUT_BZIP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_OUTPUT_BZIP_TYPE))
|
||||
|
||||
typedef struct _GsfOutputBzip GsfOutputBzip;
|
||||
|
||||
GType gsf_output_bzip_get_type (void);
|
||||
GsfOutput *gsf_output_bzip_new (GsfOutput *sink, GError **err);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_OUTPUT_BZIP_H */
|
||||
352
lib/libgsf-1.12.3/gsf/gsf-output-csv.c
Normal file
352
lib/libgsf-1.12.3/gsf/gsf-output-csv.c
Normal file
@@ -0,0 +1,352 @@
|
||||
/*
|
||||
* gsf-output-csv.c: a GsfOutput to write .csv style files.
|
||||
*
|
||||
* Copyright (C) 2005 Morten Welinder (terra@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-output-csv.h>
|
||||
#include <gsf/gsf-output-impl.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <gsf/gsf-utils.h>
|
||||
#include <glib/gconvert.h>
|
||||
#include <string.h>
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_SINK,
|
||||
PROP_QUOTE,
|
||||
PROP_QUOTING_MODE,
|
||||
PROP_QUOTING_TRIGGERS,
|
||||
PROP_EOL,
|
||||
PROP_SEPARATOR
|
||||
};
|
||||
|
||||
static void
|
||||
gsf_output_csv_finalize (GObject *obj)
|
||||
{
|
||||
GsfOutputCsv *csv = (GsfOutputCsv *)obj;
|
||||
|
||||
if (csv->sink != NULL)
|
||||
g_object_unref (G_OBJECT (csv->sink));
|
||||
g_free (csv->quote);
|
||||
g_free (csv->quoting_triggers);
|
||||
g_free (csv->eol);
|
||||
g_free (csv->separator);
|
||||
g_string_free (csv->buf, TRUE);
|
||||
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_csv_write (GsfOutput *output,
|
||||
size_t num_bytes, guint8 const *data)
|
||||
{
|
||||
GsfOutputCsv *csv = GSF_OUTPUT_CSV (output);
|
||||
return gsf_output_write (csv->sink, num_bytes, data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_csv_seek (GsfOutput *output,
|
||||
gsf_off_t offset,
|
||||
GSeekType whence)
|
||||
{
|
||||
GsfOutputCsv *csv = GSF_OUTPUT_CSV (output);
|
||||
return gsf_output_seek (csv->sink, offset, whence);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_csv_close (G_GNUC_UNUSED GsfOutput *output)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gsf_output_csv_write_field (GsfOutputCsv *csv, char const *field, size_t len)
|
||||
{
|
||||
gboolean quote;
|
||||
gboolean ok;
|
||||
char const *end;
|
||||
|
||||
g_return_val_if_fail (GSF_IS_OUTPUT_CSV (csv), FALSE);
|
||||
g_return_val_if_fail (field != NULL, FALSE);
|
||||
|
||||
if (len == (size_t)-1)
|
||||
len = strlen (field);
|
||||
end = field + len;
|
||||
|
||||
if (csv->fields_on_line && csv->separator_len)
|
||||
g_string_append_len (csv->buf,
|
||||
csv->separator,
|
||||
csv->separator_len);
|
||||
csv->fields_on_line = TRUE;
|
||||
|
||||
switch (csv->quoting_mode) {
|
||||
default:
|
||||
case GSF_OUTPUT_CSV_QUOTING_MODE_NEVER:
|
||||
quote = FALSE;
|
||||
break;
|
||||
case GSF_OUTPUT_CSV_QUOTING_MODE_ALWAYS:
|
||||
quote = TRUE;
|
||||
break;
|
||||
case GSF_OUTPUT_CSV_QUOTING_MODE_AUTO: {
|
||||
char const *p = field;
|
||||
quote = FALSE;
|
||||
while (p < end) {
|
||||
gunichar c = g_utf8_get_char (p);
|
||||
if (g_utf8_strchr (csv->quoting_triggers, -1, c)) {
|
||||
quote = TRUE;
|
||||
break;
|
||||
}
|
||||
p = g_utf8_next_char (p);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (quote && csv->quote_len > 0) {
|
||||
g_string_append_len (csv->buf,
|
||||
csv->quote,
|
||||
csv->quote_len);
|
||||
|
||||
while (field < end) {
|
||||
gunichar c = g_utf8_get_char (field);
|
||||
if (g_utf8_strchr (csv->quote, -1, c))
|
||||
g_string_append_len (csv->buf,
|
||||
csv->quote,
|
||||
csv->quote_len);
|
||||
g_string_append_unichar (csv->buf, c);
|
||||
field = g_utf8_next_char (field);
|
||||
}
|
||||
|
||||
g_string_append_len (csv->buf,
|
||||
csv->quote,
|
||||
csv->quote_len);
|
||||
} else
|
||||
g_string_append_len (csv->buf, field, len);
|
||||
|
||||
ok = gsf_output_write (csv->sink, csv->buf->len, csv->buf->str);
|
||||
|
||||
g_string_truncate (csv->buf, 0);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
gboolean
|
||||
gsf_output_csv_write_eol (GsfOutputCsv *csv)
|
||||
{
|
||||
g_return_val_if_fail (GSF_IS_OUTPUT_CSV (csv), FALSE);
|
||||
|
||||
csv->fields_on_line = FALSE;
|
||||
return gsf_output_write (csv->sink, csv->eol_len, csv->eol);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
GType
|
||||
gsf_output_csv_quoting_mode_get_type (void)
|
||||
{
|
||||
static GType etype = 0;
|
||||
if (etype == 0) {
|
||||
static const GEnumValue values[] = {
|
||||
{ GSF_OUTPUT_CSV_QUOTING_MODE_NEVER, (char *)"GSF_OUTPUT_CSV_QUOTING_MODE_NEVER", (char *)"never" },
|
||||
{ GSF_OUTPUT_CSV_QUOTING_MODE_AUTO, (char *)"GSF_OUTPUT_CSV_QUOTING_MODE_AUTO", (char *)"auto" },
|
||||
{ GSF_OUTPUT_CSV_QUOTING_MODE_ALWAYS, (char *)"GSF_OUTPUT_CSV_QUOTING_MODE_ALWAYS", (char *)"always" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
etype = g_enum_register_static ("GsfOutputCsvQuotingMode", values);
|
||||
}
|
||||
return etype;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
gsf_output_csv_init (GObject *obj)
|
||||
{
|
||||
GsfOutputCsv *csv = (GsfOutputCsv *)obj;
|
||||
csv->quoting_triggers = g_strdup ("");
|
||||
csv->eol = g_strdup ("\n");
|
||||
csv->buf = g_string_new (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_csv_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GsfOutputCsv *csv = (GsfOutputCsv *)object;
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_SINK:
|
||||
g_value_set_object (value, csv->sink);
|
||||
break;
|
||||
case PROP_QUOTE:
|
||||
g_value_set_string (value, csv->quote);
|
||||
break;
|
||||
case PROP_QUOTING_MODE:
|
||||
g_value_set_enum (value, csv->quoting_mode);
|
||||
break;
|
||||
case PROP_QUOTING_TRIGGERS:
|
||||
g_value_set_string (value, csv->quoting_triggers);
|
||||
break;
|
||||
case PROP_EOL:
|
||||
g_value_set_string (value, csv->eol);
|
||||
break;
|
||||
case PROP_SEPARATOR:
|
||||
g_value_set_string (value, csv->separator);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_csv_set_sink (GsfOutputCsv *csv, GsfOutput *sink)
|
||||
{
|
||||
g_return_if_fail (GSF_IS_OUTPUT (sink));
|
||||
g_object_ref (sink);
|
||||
if (csv->sink)
|
||||
g_object_unref (csv->sink);
|
||||
csv->sink = sink;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_csv_set_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue const *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GsfOutputCsv *csv = (GsfOutputCsv *)object;
|
||||
char *scopy;
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_SINK:
|
||||
gsf_output_csv_set_sink (csv, g_value_get_object (value));
|
||||
break;
|
||||
case PROP_QUOTE:
|
||||
scopy = g_strdup (g_value_get_string (value));
|
||||
g_free (csv->quote);
|
||||
csv->quote = scopy;
|
||||
csv->quote_len = scopy ? strlen (scopy) : 0;
|
||||
break;
|
||||
case PROP_QUOTING_MODE:
|
||||
csv->quoting_mode = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_QUOTING_TRIGGERS:
|
||||
scopy = g_strdup (g_value_get_string (value));
|
||||
g_free (csv->quoting_triggers);
|
||||
csv->quoting_triggers = scopy ? scopy : g_strdup ("");
|
||||
if (*csv->quoting_triggers)
|
||||
csv->quoting_mode = GSF_OUTPUT_CSV_QUOTING_MODE_AUTO;
|
||||
break;
|
||||
case PROP_EOL:
|
||||
scopy = g_strdup (g_value_get_string (value));
|
||||
g_free (csv->eol);
|
||||
csv->eol = scopy ? scopy : g_strdup ("");
|
||||
csv->eol_len = strlen (csv->eol);
|
||||
break;
|
||||
case PROP_SEPARATOR:
|
||||
scopy = g_strdup (g_value_get_string (value));
|
||||
g_free (csv->separator);
|
||||
csv->separator = scopy;
|
||||
csv->separator_len = scopy ? strlen (scopy) : 0;
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_csv_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
GsfOutputClass *output_class = GSF_OUTPUT_CLASS (gobject_class);
|
||||
|
||||
gobject_class->finalize = gsf_output_csv_finalize;
|
||||
gobject_class->set_property = gsf_output_csv_set_property;
|
||||
gobject_class->get_property = gsf_output_csv_get_property;
|
||||
output_class->Write = gsf_output_csv_write;
|
||||
output_class->Seek = gsf_output_csv_seek;
|
||||
output_class->Close = gsf_output_csv_close;
|
||||
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_SINK,
|
||||
g_param_spec_object ("sink", "Sink",
|
||||
"Where the compressed data is written.",
|
||||
GSF_OUTPUT_TYPE,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_QUOTE,
|
||||
g_param_spec_string ("quote", "Quote",
|
||||
"The string used for quoting fields.",
|
||||
"\"",
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_CONSTRUCT |
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_QUOTING_MODE,
|
||||
g_param_spec_enum ("quoting-mode",
|
||||
"Quoting Mode",
|
||||
"When to quote fields.",
|
||||
GSF_OUTPUT_CSV_QUOTING_MODE_TYPE,
|
||||
GSF_OUTPUT_CSV_QUOTING_MODE_NEVER,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_CONSTRUCT |
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_QUOTING_TRIGGERS,
|
||||
g_param_spec_string ("quoting-triggers", "Quoting Triggers",
|
||||
"Characters that cause field quoting.",
|
||||
NULL,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_SEPARATOR,
|
||||
g_param_spec_string ("separator", "Separator",
|
||||
"The field separator.",
|
||||
",",
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_CONSTRUCT |
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_EOL,
|
||||
g_param_spec_string ("eol", "eol",
|
||||
"The end-of-line marker.",
|
||||
"\n",
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_CONSTRUCT |
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
parent_class = g_type_class_peek_parent (gobject_class);
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfOutputCsv, gsf_output_csv,
|
||||
gsf_output_csv_class_init, gsf_output_csv_init, GSF_OUTPUT_TYPE)
|
||||
70
lib/libgsf-1.12.3/gsf/gsf-output-csv.h
Normal file
70
lib/libgsf-1.12.3/gsf/gsf-output-csv.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* gsf-output-csv.h: a GsfOutput to write .csv style files.
|
||||
*
|
||||
* Copyright (C) 2005 Morten Welinder (terra@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_OUTPUT_CSV_H
|
||||
#define GSF_OUTPUT_CSV_H
|
||||
|
||||
#include "gsf-output.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum {
|
||||
GSF_OUTPUT_CSV_QUOTING_MODE_NEVER,
|
||||
GSF_OUTPUT_CSV_QUOTING_MODE_AUTO,
|
||||
GSF_OUTPUT_CSV_QUOTING_MODE_ALWAYS
|
||||
} GsfOutputCsvQuotingMode;
|
||||
GType gsf_output_csv_quoting_mode_get_type (void);
|
||||
#define GSF_OUTPUT_CSV_QUOTING_MODE_TYPE (gsf_output_csv_quoting_mode_get_type ())
|
||||
|
||||
typedef struct {
|
||||
GsfOutput output;
|
||||
|
||||
GsfOutput *sink;
|
||||
|
||||
char *quote;
|
||||
size_t quote_len;
|
||||
GsfOutputCsvQuotingMode quoting_mode;
|
||||
char *quoting_triggers;
|
||||
|
||||
char *eol;
|
||||
size_t eol_len;
|
||||
char *separator;
|
||||
size_t separator_len;
|
||||
gboolean fields_on_line;
|
||||
|
||||
GString *buf;
|
||||
} GsfOutputCsv;
|
||||
|
||||
#define GSF_OUTPUT_CSV_TYPE (gsf_output_csv_get_type ())
|
||||
#define GSF_OUTPUT_CSV(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_OUTPUT_CSV_TYPE, GsfOutputCsv))
|
||||
#define GSF_IS_OUTPUT_CSV(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_OUTPUT_CSV_TYPE))
|
||||
GType gsf_output_csv_get_type (void);
|
||||
gboolean gsf_output_csv_write_field (GsfOutputCsv *csv,
|
||||
char const *field,
|
||||
size_t len);
|
||||
gboolean gsf_output_csv_write_eol (GsfOutputCsv *csv);
|
||||
|
||||
typedef struct {
|
||||
GsfOutputClass output_class;
|
||||
} GsfOutputCsvClass;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_OUTPUT_CSV_H */
|
||||
401
lib/libgsf-1.12.3/gsf/gsf-output-gzip.c
Normal file
401
lib/libgsf-1.12.3/gsf/gsf-output-gzip.c
Normal file
@@ -0,0 +1,401 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-output-gzip.c: wrapper to compress to gzipped output. See rfc1952.
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jon K Hellan (hellan@acm.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-output-gzip.h>
|
||||
#include <gsf/gsf-output-impl.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <gsf/gsf-utils.h>
|
||||
|
||||
#include <zlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
struct _GsfOutputGZip {
|
||||
GsfOutput output;
|
||||
|
||||
GsfOutput *sink; /* compressed data */
|
||||
gboolean raw; /* No header and no trailer. */
|
||||
|
||||
z_stream stream;
|
||||
uLong crc; /* crc32 of uncompressed data */
|
||||
size_t isize;
|
||||
|
||||
guint8 *buf;
|
||||
size_t buf_size;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
GsfOutputClass output_class;
|
||||
} GsfOutputGZipClass;
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_RAW,
|
||||
PROP_SINK
|
||||
};
|
||||
|
||||
|
||||
/* gzip flag byte */
|
||||
#define GZIP_ORIGINAL_NAME 0x08 /* the original is stored */
|
||||
|
||||
static gboolean
|
||||
init_gzip (GsfOutputGZip *gzip)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = deflateInit2 (&gzip->stream, Z_DEFAULT_COMPRESSION,
|
||||
Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL,
|
||||
Z_DEFAULT_STRATEGY);
|
||||
if (ret != Z_OK)
|
||||
return FALSE;
|
||||
|
||||
if (!gzip->buf) {
|
||||
gzip->buf_size = 0x100;
|
||||
gzip->buf = g_new (guint8, gzip->buf_size);
|
||||
}
|
||||
gzip->stream.next_out = gzip->buf;
|
||||
gzip->stream.avail_out = gzip->buf_size;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gzip_output_header (GsfOutputGZip *gzip)
|
||||
{
|
||||
guint8 buf[3 + 1 + 4 + 2];
|
||||
static guint8 const gzip_signature[] = { 0x1f, 0x8b, 0x08 } ;
|
||||
time_t mtime = time (NULL);
|
||||
char const *name = gsf_output_name (gzip->sink);
|
||||
/* FIXME: What to do about gz extension ... ? */
|
||||
int nlen = 0; /* name ? strlen (name) : 0; */
|
||||
gboolean ret;
|
||||
|
||||
memset (buf, 0, sizeof buf);
|
||||
memcpy (buf, gzip_signature, 3);
|
||||
if (nlen > 0)
|
||||
buf[3] = GZIP_ORIGINAL_NAME;
|
||||
GSF_LE_SET_GUINT32 (buf + 4, (guint32) mtime);
|
||||
buf[9] = 3; /* UNIX */
|
||||
ret = gsf_output_write (gzip->sink, sizeof buf, buf);
|
||||
if (ret && name && nlen > 0)
|
||||
ret = gsf_output_write (gzip->sink, nlen, name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_gzip_new :
|
||||
* @sink : The underlying data source.
|
||||
* @err : optionally NULL.
|
||||
*
|
||||
* Adds a reference to @sink.
|
||||
*
|
||||
* Returns a new file or NULL.
|
||||
**/
|
||||
GsfOutput *
|
||||
gsf_output_gzip_new (GsfOutput *sink, GError **err)
|
||||
{
|
||||
GsfOutput *output;
|
||||
const GError *con_err;
|
||||
|
||||
g_return_val_if_fail (GSF_IS_OUTPUT (sink), NULL);
|
||||
|
||||
output = g_object_new (GSF_OUTPUT_GZIP_TYPE, "sink", sink, NULL);
|
||||
con_err = gsf_output_error (output);
|
||||
|
||||
if (con_err) {
|
||||
if (err)
|
||||
*err = g_error_copy (con_err);
|
||||
g_object_unref (output);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_gzip_finalize (GObject *obj)
|
||||
{
|
||||
GsfOutputGZip *gzip = (GsfOutputGZip *)obj;
|
||||
|
||||
if (gzip->sink != NULL) {
|
||||
g_object_unref (G_OBJECT (gzip->sink));
|
||||
gzip->sink = NULL;
|
||||
}
|
||||
|
||||
g_free (gzip->buf);
|
||||
|
||||
/* FIXME: check for error? */
|
||||
deflateEnd (&gzip->stream);
|
||||
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gzip_output_block (GsfOutputGZip *gzip)
|
||||
{
|
||||
size_t num_bytes = gzip->buf_size - gzip->stream.avail_out;
|
||||
|
||||
if (!gsf_output_write (gzip->sink, num_bytes, gzip->buf)) {
|
||||
gsf_output_set_error (GSF_OUTPUT (gzip), 0,
|
||||
"Failed to write");
|
||||
return FALSE;
|
||||
}
|
||||
gzip->stream.next_out = gzip->buf;
|
||||
gzip->stream.avail_out = gzip->buf_size;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gzip_flush (GsfOutputGZip *gzip)
|
||||
{
|
||||
int zret;
|
||||
|
||||
do {
|
||||
zret = deflate (&gzip->stream, Z_FINISH);
|
||||
if (zret == Z_OK) {
|
||||
/* In this case Z_OK means more buffer space
|
||||
needed */
|
||||
if (!gzip_output_block (gzip))
|
||||
return FALSE;
|
||||
}
|
||||
} while (zret == Z_OK);
|
||||
if (zret != Z_STREAM_END) {
|
||||
gsf_output_set_error (GSF_OUTPUT (gzip), 0,
|
||||
"Unexpected compression failure");
|
||||
g_warning ("Unexpected error code %d from zlib during compression.",
|
||||
zret);
|
||||
return FALSE;
|
||||
}
|
||||
if (!gzip_output_block (gzip))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_gzip_write (GsfOutput *output,
|
||||
size_t num_bytes, guint8 const *data)
|
||||
{
|
||||
GsfOutputGZip *gzip = GSF_OUTPUT_GZIP (output);
|
||||
|
||||
g_return_val_if_fail (data, FALSE);
|
||||
|
||||
gzip->stream.next_in = (unsigned char *) data;
|
||||
gzip->stream.avail_in = num_bytes;
|
||||
|
||||
while (gzip->stream.avail_in > 0) {
|
||||
int zret;
|
||||
if (gzip->stream.avail_out == 0) {
|
||||
if (!gzip_output_block (gzip))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
zret = deflate (&gzip->stream, Z_NO_FLUSH);
|
||||
if (zret != Z_OK) {
|
||||
gsf_output_set_error (output, 0,
|
||||
"Unexpected compression failure");
|
||||
g_warning ("Unexpected error code %d from zlib during compression.",
|
||||
zret);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gzip->crc = crc32 (gzip->crc, data, num_bytes);
|
||||
gzip->isize += num_bytes;
|
||||
|
||||
if (gzip->stream.avail_out == 0) {
|
||||
if (!gzip_output_block (gzip))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_gzip_seek (G_GNUC_UNUSED GsfOutput *output,
|
||||
G_GNUC_UNUSED gsf_off_t offset,
|
||||
G_GNUC_UNUSED GSeekType whence)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_gzip_close (GsfOutput *output)
|
||||
{
|
||||
if (!gsf_output_error (output)) {
|
||||
GsfOutputGZip *gzip = GSF_OUTPUT_GZIP (output);
|
||||
|
||||
if (!gzip_flush (gzip))
|
||||
return FALSE;
|
||||
|
||||
if (!gzip->raw) {
|
||||
guint8 buf[8];
|
||||
|
||||
GSF_LE_SET_GUINT32 (buf, gzip->crc);
|
||||
GSF_LE_SET_GUINT32 (buf + 4, gzip->isize);
|
||||
if (!gsf_output_write (gzip->sink, 8, buf))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_gzip_init (GObject *obj)
|
||||
{
|
||||
GsfOutputGZip *gzip = GSF_OUTPUT_GZIP (obj);
|
||||
|
||||
gzip->sink = NULL;
|
||||
gzip->stream.zalloc = (alloc_func)0;
|
||||
gzip->stream.zfree = (free_func)0;
|
||||
gzip->stream.opaque = (voidpf)0;
|
||||
gzip->stream.next_in = Z_NULL;
|
||||
gzip->stream.next_out = Z_NULL;
|
||||
gzip->stream.avail_in = gzip->stream.avail_out = 0;
|
||||
gzip->crc = crc32 (0L, Z_NULL, 0);
|
||||
gzip->isize = 0;
|
||||
gzip->buf = NULL;
|
||||
gzip->buf_size = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_gzip_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GsfOutputGZip *gzip = (GsfOutputGZip *)object;
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_RAW:
|
||||
g_value_set_boolean (value, gzip->raw);
|
||||
break;
|
||||
case PROP_SINK:
|
||||
g_value_set_object (value, gzip->sink);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_gzip_set_sink (GsfOutputGZip *gzip, GsfOutput *sink)
|
||||
{
|
||||
if (sink)
|
||||
g_object_ref (GSF_OUTPUT (sink));
|
||||
if (gzip->sink)
|
||||
g_object_unref (gzip->sink);
|
||||
gzip->sink = sink;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_gzip_set_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue const *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GsfOutputGZip *gzip = (GsfOutputGZip *)object;
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_RAW:
|
||||
gzip->raw = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_SINK:
|
||||
gsf_output_gzip_set_sink (gzip, g_value_get_object (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static GObject*
|
||||
gsf_output_gzip_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_params)
|
||||
{
|
||||
GsfOutputGZip *gzip;
|
||||
|
||||
gzip = (GsfOutputGZip *)(parent_class->constructor (type,
|
||||
n_construct_properties,
|
||||
construct_params));
|
||||
|
||||
if (!gzip->sink)
|
||||
gsf_output_set_error (GSF_OUTPUT (gzip),
|
||||
0,
|
||||
"NULL sink");
|
||||
else if (!init_gzip (gzip))
|
||||
gsf_output_set_error (GSF_OUTPUT (gzip),
|
||||
0,
|
||||
"Failed to initialize zlib structure");
|
||||
else if (!gzip->raw && !gzip_output_header (gzip))
|
||||
gsf_output_set_error (GSF_OUTPUT (gzip),
|
||||
0,
|
||||
"Failed to write gzip header");
|
||||
|
||||
return (GObject *)gzip;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_gzip_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
GsfOutputClass *output_class = GSF_OUTPUT_CLASS (gobject_class);
|
||||
|
||||
gobject_class->constructor = gsf_output_gzip_constructor;
|
||||
gobject_class->finalize = gsf_output_gzip_finalize;
|
||||
gobject_class->set_property = gsf_output_gzip_set_property;
|
||||
gobject_class->get_property = gsf_output_gzip_get_property;
|
||||
output_class->Write = gsf_output_gzip_write;
|
||||
output_class->Seek = gsf_output_gzip_seek;
|
||||
output_class->Close = gsf_output_gzip_close;
|
||||
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_RAW,
|
||||
g_param_spec_boolean ("raw", "Raw",
|
||||
"Whether to write compressed data with no header/tailer.",
|
||||
FALSE,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_SINK,
|
||||
g_param_spec_object ("sink", "Sink",
|
||||
"Where the compressed data is written.",
|
||||
GSF_OUTPUT_TYPE,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
parent_class = g_type_class_peek_parent (gobject_class);
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfOutputGZip, gsf_output_gzip,
|
||||
gsf_output_gzip_class_init, gsf_output_gzip_init, GSF_OUTPUT_TYPE)
|
||||
40
lib/libgsf-1.12.3/gsf/gsf-output-gzip.h
Normal file
40
lib/libgsf-1.12.3/gsf/gsf-output-gzip.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-output-gzip.h: wrapper to compress to gzipped output
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jon K Hellan (hellan@acm.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_OUTPUT_GZIP_H
|
||||
#define GSF_OUTPUT_GZIP_H
|
||||
|
||||
#include "gsf-output.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSF_OUTPUT_GZIP_TYPE (gsf_output_gzip_get_type ())
|
||||
#define GSF_OUTPUT_GZIP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_OUTPUT_GZIP_TYPE, GsfOutputGZip))
|
||||
#define GSF_IS_OUTPUT_GZIP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_OUTPUT_GZIP_TYPE))
|
||||
|
||||
typedef struct _GsfOutputGZip GsfOutputGZip;
|
||||
|
||||
GType gsf_output_gzip_get_type (void);
|
||||
GsfOutput *gsf_output_gzip_new (GsfOutput *sink, GError **err);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_OUTPUT_GZIP_H */
|
||||
320
lib/libgsf-1.12.3/gsf/gsf-output-iconv.c
Normal file
320
lib/libgsf-1.12.3/gsf/gsf-output-iconv.c
Normal file
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* gsf-output-iconv.c: wrapper to convert character sets.
|
||||
*
|
||||
* Copyright (C) 2005 Morten Welinder (terra@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-output-iconv.h>
|
||||
#include <gsf/gsf-output-impl.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <gsf/gsf-utils.h>
|
||||
#include <glib/gconvert.h>
|
||||
#include <string.h>
|
||||
|
||||
#define BUF_SIZE 0x400
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
struct _GsfOutputIconv {
|
||||
GsfOutput output;
|
||||
|
||||
GsfOutput *sink;
|
||||
char *input_charset;
|
||||
char *output_charset;
|
||||
char *fallback;
|
||||
|
||||
guint8 *buf;
|
||||
size_t buf_len;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_SINK,
|
||||
PROP_INPUT_CHARSET,
|
||||
PROP_OUTPUT_CHARSET,
|
||||
PROP_FALLBACK
|
||||
};
|
||||
|
||||
/**
|
||||
* gsf_output_iconv_new :
|
||||
* @sink : The underlying data source.
|
||||
* @dst : The target character set.
|
||||
* @src : The source character set.
|
||||
*
|
||||
* Adds a reference to @sink.
|
||||
*
|
||||
* Returns a new GsfOutput object or NULL.
|
||||
**/
|
||||
GsfOutput *
|
||||
gsf_output_iconv_new (GsfOutput *sink, char const *dst, char const *src)
|
||||
{
|
||||
GError *error = NULL;
|
||||
g_return_val_if_fail (GSF_IS_OUTPUT (sink), NULL);
|
||||
|
||||
if (!dst) dst = "UTF-8";
|
||||
if (!src) src = "UTF-8";
|
||||
g_free (g_convert ("", 0, dst, src, NULL, NULL, &error));
|
||||
|
||||
if (error) {
|
||||
g_error_free (error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return g_object_new (GSF_OUTPUT_ICONV_TYPE,
|
||||
"sink", sink,
|
||||
"input-charset", src,
|
||||
"output-charset", dst,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_iconv_finalize (GObject *obj)
|
||||
{
|
||||
GsfOutputIconv *ic = (GsfOutputIconv *)obj;
|
||||
|
||||
if (ic->sink != NULL)
|
||||
g_object_unref (G_OBJECT (ic->sink));
|
||||
g_free (ic->input_charset);
|
||||
g_free (ic->output_charset);
|
||||
g_free (ic->buf);
|
||||
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
iconv_flush (GsfOutputIconv *ic, gboolean must_empty)
|
||||
{
|
||||
if (gsf_output_error (GSF_OUTPUT (ic)))
|
||||
return FALSE;
|
||||
|
||||
if (ic->buf_len > 0) {
|
||||
gsize bytes_read, bytes_written;
|
||||
gboolean ok;
|
||||
char *data = g_convert_with_fallback (ic->buf, ic->buf_len,
|
||||
ic->output_charset,
|
||||
ic->input_charset,
|
||||
ic->fallback,
|
||||
&bytes_read,
|
||||
&bytes_written,
|
||||
NULL);
|
||||
if (data == NULL || bytes_read <= 0) {
|
||||
gsf_output_set_error (GSF_OUTPUT (ic),
|
||||
0,
|
||||
"Failed to convert string");
|
||||
ok = FALSE;
|
||||
} else {
|
||||
ic->buf_len -= bytes_read;
|
||||
if (ic->buf_len)
|
||||
g_memmove (ic->buf, ic->buf + ic->buf_len, ic->buf_len);
|
||||
|
||||
ok = gsf_output_write (ic->sink, bytes_written, data);
|
||||
if (!ok) {
|
||||
gsf_output_set_error (GSF_OUTPUT (ic),
|
||||
0,
|
||||
"Failed to write");
|
||||
}
|
||||
}
|
||||
|
||||
g_free (data);
|
||||
return ok && (!must_empty || ic->buf_len == 0);
|
||||
} else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_iconv_write (GsfOutput *output,
|
||||
size_t num_bytes, guint8 const *data)
|
||||
{
|
||||
GsfOutputIconv *ic = GSF_OUTPUT_ICONV (output);
|
||||
|
||||
g_return_val_if_fail (data, FALSE);
|
||||
|
||||
while (num_bytes > 0) {
|
||||
if (gsf_output_error (output))
|
||||
return FALSE;
|
||||
if (ic->buf_len == BUF_SIZE)
|
||||
iconv_flush (ic, FALSE);
|
||||
else {
|
||||
size_t count = MIN (BUF_SIZE - ic->buf_len, num_bytes);
|
||||
memcpy (ic->buf + ic->buf_len, data, count);
|
||||
ic->buf_len += count;
|
||||
num_bytes -= count;
|
||||
data += count;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_iconv_seek (G_GNUC_UNUSED GsfOutput *output,
|
||||
G_GNUC_UNUSED gsf_off_t offset,
|
||||
G_GNUC_UNUSED GSeekType whence)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_iconv_close (GsfOutput *output)
|
||||
{
|
||||
if (!gsf_output_error (output)) {
|
||||
GsfOutputIconv *ic = GSF_OUTPUT_ICONV (output);
|
||||
|
||||
if (!iconv_flush (ic, TRUE))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_iconv_init (GObject *obj)
|
||||
{
|
||||
GsfOutputIconv *ic = GSF_OUTPUT_ICONV (obj);
|
||||
|
||||
ic->buf = g_malloc (BUF_SIZE);
|
||||
ic->buf_len = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_iconv_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GsfOutputIconv *ic = (GsfOutputIconv *)object;
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_SINK:
|
||||
g_value_set_object (value, ic->sink);
|
||||
break;
|
||||
case PROP_INPUT_CHARSET:
|
||||
g_value_set_string (value, ic->input_charset);
|
||||
break;
|
||||
case PROP_OUTPUT_CHARSET:
|
||||
g_value_set_string (value, ic->output_charset);
|
||||
break;
|
||||
case PROP_FALLBACK:
|
||||
g_value_set_string (value, ic->fallback);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_iconv_set_sink (GsfOutputIconv *ic, GsfOutput *sink)
|
||||
{
|
||||
g_return_if_fail (GSF_IS_OUTPUT (sink));
|
||||
g_object_ref (sink);
|
||||
if (ic->sink)
|
||||
g_object_unref (ic->sink);
|
||||
ic->sink = sink;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_iconv_set_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue const *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GsfOutputIconv *ic = (GsfOutputIconv *)object;
|
||||
char *scopy;
|
||||
|
||||
switch (property_id) {
|
||||
case PROP_SINK:
|
||||
gsf_output_iconv_set_sink (ic, g_value_get_object (value));
|
||||
break;
|
||||
case PROP_INPUT_CHARSET:
|
||||
ic->input_charset = g_strdup (g_value_get_string (value));
|
||||
break;
|
||||
case PROP_OUTPUT_CHARSET:
|
||||
ic->output_charset = g_strdup (g_value_get_string (value));
|
||||
break;
|
||||
case PROP_FALLBACK:
|
||||
scopy = g_strdup (g_value_get_string (value));
|
||||
g_free (ic->fallback);
|
||||
ic->fallback = scopy;
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_iconv_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
GsfOutputClass *output_class = GSF_OUTPUT_CLASS (gobject_class);
|
||||
|
||||
gobject_class->finalize = gsf_output_iconv_finalize;
|
||||
gobject_class->set_property = gsf_output_iconv_set_property;
|
||||
gobject_class->get_property = gsf_output_iconv_get_property;
|
||||
output_class->Write = gsf_output_iconv_write;
|
||||
output_class->Seek = gsf_output_iconv_seek;
|
||||
output_class->Close = gsf_output_iconv_close;
|
||||
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_SINK,
|
||||
g_param_spec_object ("sink", "Sink",
|
||||
"Where the converted data is written.",
|
||||
GSF_OUTPUT_TYPE,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_INPUT_CHARSET,
|
||||
g_param_spec_string ("input-charset", "Input Charset",
|
||||
"The character set to convert from.",
|
||||
"UTF-8",
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_OUTPUT_CHARSET,
|
||||
g_param_spec_string ("output-charset", "Output Charset",
|
||||
"The character set to convert to.",
|
||||
"UTF-8",
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
/**
|
||||
* GsfOutputIconv:fallback:
|
||||
*
|
||||
* Either NULL or a UTF-8 string (representable in the target encoding)
|
||||
* to convert and output in place of characters that cannot be represented
|
||||
* in the target encoding. NULL means use \u1234 or \U12345678 format.
|
||||
*/
|
||||
g_object_class_install_property
|
||||
(gobject_class,
|
||||
PROP_FALLBACK,
|
||||
g_param_spec_string ("fallback", "Fallback",
|
||||
"The string to use for invalid characters.",
|
||||
NULL,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
parent_class = g_type_class_peek_parent (gobject_class);
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfOutputIconv, gsf_output_iconv,
|
||||
gsf_output_iconv_class_init, gsf_output_iconv_init, GSF_OUTPUT_TYPE)
|
||||
43
lib/libgsf-1.12.3/gsf/gsf-output-iconv.h
Normal file
43
lib/libgsf-1.12.3/gsf/gsf-output-iconv.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* gsf-output-iconv.h: wrapper to convert character sets.
|
||||
*
|
||||
* Copyright (C) 2005 Morten Welinder (terra@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_OUTPUT_ICONV_H
|
||||
#define GSF_OUTPUT_ICONV_H
|
||||
|
||||
#include "gsf-output.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct {
|
||||
GsfOutputClass output_class;
|
||||
} GsfOutputIconvClass;
|
||||
|
||||
#define GSF_OUTPUT_ICONV_TYPE (gsf_output_iconv_get_type ())
|
||||
#define GSF_OUTPUT_ICONV(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_OUTPUT_ICONV_TYPE, GsfOutputIconv))
|
||||
#define GSF_IS_OUTPUT_ICONV(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_OUTPUT_ICONV_TYPE))
|
||||
|
||||
typedef struct _GsfOutputIconv GsfOutputIconv;
|
||||
|
||||
GType gsf_output_iconv_get_type (void);
|
||||
GsfOutput *gsf_output_iconv_new (GsfOutput *sink, char const *dst, char const *src);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_OUTPUT_ICONV_H */
|
||||
38
lib/libgsf-1.12.3/gsf/gsf-output-impl.h
Normal file
38
lib/libgsf-1.12.3/gsf/gsf-output-impl.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-output-impl.h: interface for storing data
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_OUTPUT_IMPL_H
|
||||
#define GSF_OUTPUT_IMPL_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
#include <gsf/gsf-output.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* protected */
|
||||
gboolean gsf_output_set_name (GsfOutput *output, char const *name);
|
||||
gboolean gsf_output_set_name_from_filename (GsfOutput *output, char const *filename);
|
||||
gboolean gsf_output_set_container (GsfOutput *output, GsfOutfile *container);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_OUTPUT_IMPL_H */
|
||||
130
lib/libgsf-1.12.3/gsf/gsf-output-iochannel.c
Normal file
130
lib/libgsf-1.12.3/gsf/gsf-output-iochannel.c
Normal file
@@ -0,0 +1,130 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-output-iochannel.c
|
||||
*
|
||||
* Copyright (C) 2002-2004 Dom Lachowicz (cinamod@hotmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-output-iochannel.h>
|
||||
#include <gsf/gsf-output-impl.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
|
||||
static GsfOutputClass *parent_class;
|
||||
|
||||
struct _GsfOutputIOChannel {
|
||||
GsfOutput output;
|
||||
GIOChannel * channel;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
GsfOutputClass output_class;
|
||||
} GsfOutputIOChannelClass;
|
||||
|
||||
/**
|
||||
* gsf_output_iochannel_new :
|
||||
* @channel: A #GIOChannel
|
||||
*
|
||||
* Returns a new file or NULL.
|
||||
**/
|
||||
GsfOutput *
|
||||
gsf_output_iochannel_new (GIOChannel *channel)
|
||||
{
|
||||
GsfOutputIOChannel *output = NULL;
|
||||
|
||||
g_return_val_if_fail (channel != NULL, NULL);
|
||||
|
||||
output = g_object_new (GSF_OUTPUT_IOCHANNEL_TYPE, NULL);
|
||||
output->channel = channel;
|
||||
return GSF_OUTPUT (output);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_iochannel_close (GsfOutput *output)
|
||||
{
|
||||
g_io_channel_shutdown (GSF_OUTPUT_IOCHANNEL (output)->channel, TRUE, NULL);
|
||||
|
||||
if (parent_class->Close)
|
||||
parent_class->Close (output);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_iochannel_finalize (GObject *obj)
|
||||
{
|
||||
g_io_channel_unref (GSF_OUTPUT_IOCHANNEL (obj)->channel);
|
||||
G_OBJECT_CLASS (parent_class)->finalize (obj);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_iochannel_seek (GsfOutput *output, gsf_off_t offset,
|
||||
GSeekType whence)
|
||||
{
|
||||
GsfOutputIOChannel *io = GSF_OUTPUT_IOCHANNEL (output);
|
||||
GIOStatus status = G_IO_STATUS_NORMAL;
|
||||
|
||||
status = g_io_channel_seek_position (io->channel, offset, whence, NULL);
|
||||
if (status == G_IO_STATUS_NORMAL)
|
||||
return TRUE;
|
||||
|
||||
gsf_output_set_error (output, status, " ");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_iochannel_write (GsfOutput *output,
|
||||
size_t num_bytes,
|
||||
guint8 const *buffer)
|
||||
{
|
||||
GsfOutputIOChannel *io = GSF_OUTPUT_IOCHANNEL (output);
|
||||
GIOStatus status = G_IO_STATUS_NORMAL;
|
||||
size_t bytes_written = 0, total_written = 0;
|
||||
|
||||
g_return_val_if_fail (io != NULL, FALSE);
|
||||
|
||||
while ((status == G_IO_STATUS_NORMAL) && (total_written < num_bytes)) {
|
||||
status = g_io_channel_write_chars (io->channel, (const gchar *)(buffer + total_written),
|
||||
num_bytes - total_written, &bytes_written, NULL);
|
||||
total_written += bytes_written;
|
||||
}
|
||||
|
||||
return (status == G_IO_STATUS_NORMAL && total_written == num_bytes);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_iochannel_init (GObject *obj)
|
||||
{
|
||||
GsfOutputIOChannel *io = GSF_OUTPUT_IOCHANNEL (obj);
|
||||
|
||||
io->channel = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_iochannel_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
GsfOutputClass *output_class = GSF_OUTPUT_CLASS (gobject_class);
|
||||
|
||||
gobject_class->finalize = gsf_output_iochannel_finalize;
|
||||
output_class->Close = gsf_output_iochannel_close;
|
||||
output_class->Seek = gsf_output_iochannel_seek;
|
||||
output_class->Write = gsf_output_iochannel_write;
|
||||
|
||||
parent_class = GSF_OUTPUT_CLASS (g_type_class_peek_parent (gobject_class));
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfOutputIOChannel, gsf_output_iochannel,
|
||||
gsf_output_iochannel_class_init, gsf_output_iochannel_init, GSF_OUTPUT_TYPE)
|
||||
40
lib/libgsf-1.12.3/gsf/gsf-output-iochannel.h
Normal file
40
lib/libgsf-1.12.3/gsf/gsf-output-iochannel.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-output-iochannel.h
|
||||
*
|
||||
* Copyright (C) 2002-2004 Dom Lachowicz (cinamod@hotmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_OUTPUT_IOCHANNEL_H
|
||||
#define GSF_OUTPUT_IOCHANNEL_H
|
||||
|
||||
#include "gsf-output.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSF_OUTPUT_IOCHANNEL_TYPE (gsf_output_iochannel_get_type ())
|
||||
#define GSF_OUTPUT_IOCHANNEL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_OUTPUT_IOCHANNEL_TYPE, GsfOutputIOChannel))
|
||||
#define GSF_IS_OUTPUT_IOCHANNEL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_OUTPUT_IOCHANNEL_TYPE))
|
||||
|
||||
typedef struct _GsfOutputIOChannel GsfOutputIOChannel;
|
||||
|
||||
GType gsf_output_iochannel_get_type (void);
|
||||
GsfOutput *gsf_output_iochannel_new (GIOChannel * channel);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_OUTPUT_IOCHANNEL_H */
|
||||
200
lib/libgsf-1.12.3/gsf/gsf-output-memory.c
Normal file
200
lib/libgsf-1.12.3/gsf/gsf-output-memory.c
Normal file
@@ -0,0 +1,200 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-output-memory.c:
|
||||
*
|
||||
* Copyright (C) 2002-2004 Dom Lachowicz (cinamod@hotmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-output-memory.h>
|
||||
#include <gsf/gsf-output-impl.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MIN_BLOCK 512
|
||||
#define MAX_STEP (MIN_BLOCK * 128)
|
||||
|
||||
static GsfOutputClass *parent_class;
|
||||
|
||||
struct _GsfOutputMemory {
|
||||
GsfOutput output;
|
||||
guint8 *buffer;
|
||||
size_t capacity;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
GsfOutputClass output_class;
|
||||
} GsfOutputMemoryClass;
|
||||
|
||||
/**
|
||||
* gsf_output_memory_new :
|
||||
*
|
||||
* Returns a new file or NULL.
|
||||
**/
|
||||
GsfOutput *
|
||||
gsf_output_memory_new (void)
|
||||
{
|
||||
return g_object_new (GSF_OUTPUT_MEMORY_TYPE, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_memory_close (GsfOutput *output)
|
||||
{
|
||||
return (parent_class->Close == NULL) ||
|
||||
parent_class->Close (output);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_memory_finalize (GObject *obj)
|
||||
{
|
||||
GsfOutputMemory *mem = GSF_OUTPUT_MEMORY (obj);
|
||||
|
||||
g_free (mem->buffer);
|
||||
mem->buffer = NULL;
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (obj);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_memory_seek (G_GNUC_UNUSED GsfOutput *output,
|
||||
G_GNUC_UNUSED gsf_off_t offset,
|
||||
G_GNUC_UNUSED GSeekType whence)
|
||||
{
|
||||
/* let parent implementation handle maneuvering cur_offset */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_memory_expand (GsfOutputMemory *mem, gsf_off_t needed)
|
||||
{
|
||||
gsf_off_t capacity = MAX (mem->capacity, MIN_BLOCK);
|
||||
gsize lcapacity;
|
||||
|
||||
/* If we need >= MAX_STEP, align to a next multiple of MAX_STEP.
|
||||
* Since MAX_STEP is probably a power of two, this computation
|
||||
* should reduce to "dec, shr, inc, shl", which is probably
|
||||
* quicker then branching.
|
||||
*/
|
||||
if (needed < MAX_STEP)
|
||||
while (capacity < needed)
|
||||
capacity *= 2;
|
||||
else
|
||||
capacity = ((needed - 1) / MAX_STEP + 1) * MAX_STEP;
|
||||
|
||||
/* Check for overflow: g_renew() casts its parameters to gsize. */
|
||||
lcapacity = capacity;
|
||||
if ((gsf_off_t) lcapacity != capacity || capacity < 0) {
|
||||
g_warning ("overflow in gsf_output_memory_expand");
|
||||
return FALSE;
|
||||
}
|
||||
mem->buffer = g_renew (guint8, mem->buffer, lcapacity);
|
||||
mem->capacity = capacity;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_memory_write (GsfOutput *output,
|
||||
size_t num_bytes,
|
||||
guint8 const *buffer)
|
||||
{
|
||||
GsfOutputMemory *mem = GSF_OUTPUT_MEMORY (output);
|
||||
|
||||
g_return_val_if_fail (mem != NULL, FALSE);
|
||||
|
||||
if (!mem->buffer) {
|
||||
mem->buffer = g_new (guint8, MIN_BLOCK);
|
||||
mem->capacity = MIN_BLOCK;
|
||||
}
|
||||
if (num_bytes + output->cur_offset > mem->capacity) {
|
||||
if (!gsf_output_memory_expand (mem, output->cur_offset + num_bytes))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memcpy (mem->buffer + output->cur_offset, buffer, num_bytes);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gsf_off_t gsf_output_memory_vprintf (GsfOutput *output,
|
||||
char const *format, va_list args) G_GNUC_PRINTF (2, 0);
|
||||
|
||||
static gsf_off_t
|
||||
gsf_output_memory_vprintf (GsfOutput *output, char const *format, va_list args)
|
||||
{
|
||||
GsfOutputMemory *mem = (GsfOutputMemory *)output;
|
||||
|
||||
if (mem->buffer) {
|
||||
va_list args2;
|
||||
gsf_off_t len;
|
||||
|
||||
/*
|
||||
* We need to make a copy as args will become unusable after
|
||||
* the g_vsnprintf call.
|
||||
*/
|
||||
G_VA_COPY (args2, args);
|
||||
|
||||
len =
|
||||
g_vsnprintf (mem->buffer + output->cur_offset,
|
||||
mem->capacity - output->cur_offset,
|
||||
format, args);
|
||||
|
||||
if (len < mem->capacity - output->cur_offset)
|
||||
return len; /* There was sufficient space */
|
||||
|
||||
return parent_class->Vprintf (output, format, args2);
|
||||
}
|
||||
return parent_class->Vprintf (output, format, args);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_memory_init (GObject *obj)
|
||||
{
|
||||
GsfOutputMemory *mem = GSF_OUTPUT_MEMORY (obj);
|
||||
|
||||
mem->buffer = NULL;
|
||||
mem->capacity = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_memory_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
GsfOutputClass *output_class = GSF_OUTPUT_CLASS (gobject_class);
|
||||
|
||||
gobject_class->finalize = gsf_output_memory_finalize;
|
||||
output_class->Close = gsf_output_memory_close;
|
||||
output_class->Seek = gsf_output_memory_seek;
|
||||
output_class->Write = gsf_output_memory_write;
|
||||
output_class->Vprintf = gsf_output_memory_vprintf;
|
||||
|
||||
parent_class = GSF_OUTPUT_CLASS (g_type_class_peek_parent (gobject_class));
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_memory_get_bytes :
|
||||
* @mem : the output device.
|
||||
*
|
||||
* Returns: The data that has been written to @mem, or %null
|
||||
**/
|
||||
const guint8 *
|
||||
gsf_output_memory_get_bytes (GsfOutputMemory * mem)
|
||||
{
|
||||
g_return_val_if_fail (mem != NULL, NULL);
|
||||
return mem->buffer;
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfOutputMemory, gsf_output_memory,
|
||||
gsf_output_memory_class_init, gsf_output_memory_init, GSF_OUTPUT_TYPE)
|
||||
|
||||
41
lib/libgsf-1.12.3/gsf/gsf-output-memory.h
Normal file
41
lib/libgsf-1.12.3/gsf/gsf-output-memory.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-output-memory.h
|
||||
*
|
||||
* Copyright (C) 2002-2004 Dom Lachowicz (cinamod@hotmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_OUTPUT_MEMORY_H
|
||||
#define GSF_OUTPUT_MEMORY_H
|
||||
|
||||
#include "gsf-output.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSF_OUTPUT_MEMORY_TYPE (gsf_output_memory_get_type ())
|
||||
#define GSF_OUTPUT_MEMORY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_OUTPUT_MEMORY_TYPE, GsfOutputMemory))
|
||||
#define GSF_IS_OUTPUT_MEMORY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_OUTPUT_MEMORY_TYPE))
|
||||
|
||||
typedef struct _GsfOutputMemory GsfOutputMemory;
|
||||
|
||||
GType gsf_output_memory_get_type (void);
|
||||
GsfOutput *gsf_output_memory_new (void);
|
||||
const guint8* gsf_output_memory_get_bytes (GsfOutputMemory * mem);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_OUTPUT_MEMORY_H */
|
||||
574
lib/libgsf-1.12.3/gsf/gsf-output-stdio.c
Normal file
574
lib/libgsf-1.12.3/gsf/gsf-output-stdio.c
Normal file
@@ -0,0 +1,574 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-output-stdio.c: stdio based output
|
||||
*
|
||||
* Copyright (C) 2002-2005 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-output-stdio.h>
|
||||
#include <gsf/gsf-output-impl.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <gsf/gsf-utils.h>
|
||||
#ifdef HAVE_GLIB26
|
||||
#include <glib/gstdio.h>
|
||||
#else
|
||||
#include "glib24_26-compat.h"
|
||||
#endif // HAVE_GLIB26
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#include <wchar.h>
|
||||
#include <direct.h>
|
||||
#include <glib/gwin32.h>
|
||||
#ifdef HAVE_IO_H
|
||||
#include <io.h>
|
||||
#endif
|
||||
#endif /* G_OS_WIN32 */
|
||||
|
||||
#ifndef W_OK
|
||||
#define W_OK 2
|
||||
#endif
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
struct _GsfOutputStdio {
|
||||
GsfOutput output;
|
||||
|
||||
FILE *file;
|
||||
char *real_filename, *temp_filename;
|
||||
gboolean create_backup_copy, keep_open;
|
||||
struct stat st;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
GsfOutputClass output_class;
|
||||
} GsfOutputStdioClass;
|
||||
|
||||
static int
|
||||
rename_wrapper (char const *oldfilename, char const *newfilename)
|
||||
{
|
||||
int result = g_rename (oldfilename, newfilename);
|
||||
#ifdef G_OS_WIN32
|
||||
if (result) {
|
||||
/* Win32's rename does not unlink the target. */
|
||||
(void)g_unlink (newfilename);
|
||||
result = g_rename (oldfilename, newfilename);
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
chmod_wrapper (const char *filename, mode_t mode)
|
||||
{
|
||||
#ifdef HAVE_G_CHMOD
|
||||
return g_chmod (filename, mode);
|
||||
#else
|
||||
return chmod (filename, mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
access_wrapper (char const *filename, int what)
|
||||
{
|
||||
#ifdef HAVE_G_ACCESS
|
||||
return g_access (filename, what);
|
||||
#else
|
||||
return access (filename, what);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define GSF_MAX_LINK_LEVEL 256
|
||||
|
||||
/* Calls g_file_read_link() until we find a real filename. */
|
||||
static char *
|
||||
follow_symlinks (char const *filename, GError **error)
|
||||
{
|
||||
gchar *followed_filename, *link;
|
||||
gint link_count = 0;
|
||||
|
||||
g_return_val_if_fail (filename != NULL, NULL);
|
||||
|
||||
followed_filename = g_strdup (filename);
|
||||
|
||||
while ((link = g_file_read_link (followed_filename, NULL)) != NULL &&
|
||||
++link_count <= GSF_MAX_LINK_LEVEL) {
|
||||
if (g_path_is_absolute (link)) {
|
||||
g_free (followed_filename);
|
||||
followed_filename = link;
|
||||
} else {
|
||||
/* If the linkname is not an absolute path name, append
|
||||
* it to the directory name of the followed filename. E.g.
|
||||
* we may have /foo/bar/baz.lnk -> eek.txt, which really
|
||||
* is /foo/bar/eek.txt. */
|
||||
gchar *dir = g_path_get_dirname (followed_filename);
|
||||
g_free (followed_filename);
|
||||
followed_filename = g_build_filename (dir, link, NULL);
|
||||
g_free (dir);
|
||||
g_free (link);
|
||||
}
|
||||
}
|
||||
|
||||
if (link == NULL)
|
||||
return followed_filename;
|
||||
|
||||
/* Too many symlinks */
|
||||
if (error != NULL) {
|
||||
#ifdef ELOOP
|
||||
int err = ELOOP;
|
||||
#else
|
||||
/* We have links, but not ELOOP. Very strange. */
|
||||
int err = EINVAL;
|
||||
#endif
|
||||
*error = g_error_new_literal (gsf_output_error_id (), err,
|
||||
g_strerror (err));
|
||||
}
|
||||
g_free (followed_filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
close_file_helper (GsfOutputStdio *stdio, gboolean seterr)
|
||||
{
|
||||
gboolean res = (0 == fclose (stdio->file));
|
||||
stdio->file = NULL;
|
||||
if (!res && seterr)
|
||||
gsf_output_set_error (GSF_OUTPUT (stdio), errno,
|
||||
"Failed to close file: %s",
|
||||
g_strerror (errno));
|
||||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
unlink_file_helper (GsfOutputStdio *stdio)
|
||||
{
|
||||
if (!stdio->temp_filename)
|
||||
return TRUE;
|
||||
|
||||
if (g_unlink (stdio->temp_filename) == 0) {
|
||||
g_free (stdio->temp_filename);
|
||||
stdio->temp_filename = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_stdio_close (GsfOutput *output)
|
||||
{
|
||||
GsfOutputStdio *stdio = GSF_OUTPUT_STDIO (output);
|
||||
gboolean res;
|
||||
char *backup_filename = NULL;
|
||||
|
||||
if (stdio->file == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (gsf_output_error (output)) {
|
||||
res = TRUE;
|
||||
if (!stdio->keep_open && !close_file_helper (stdio, FALSE))
|
||||
res = FALSE;
|
||||
|
||||
if (!unlink_file_helper (stdio))
|
||||
res = FALSE;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
if (stdio->keep_open) {
|
||||
gboolean res = (0 == fflush (stdio->file));
|
||||
if (!res)
|
||||
gsf_output_set_error (output, errno,
|
||||
"Failed to flush.");
|
||||
stdio->file = NULL;
|
||||
return res;
|
||||
}
|
||||
|
||||
res = close_file_helper (stdio, TRUE);
|
||||
|
||||
/* short circuit our when dealing with raw FILE */
|
||||
if (!stdio->real_filename)
|
||||
return res;
|
||||
if (!res) {
|
||||
unlink_file_helper (stdio);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Move the original file to a backup */
|
||||
if (stdio->create_backup_copy) {
|
||||
gint result;
|
||||
backup_filename = g_strconcat (stdio->real_filename, ".bak", NULL);
|
||||
result = rename_wrapper (stdio->real_filename, backup_filename);
|
||||
if (result != 0) {
|
||||
char *utf8name = g_filename_display_name (backup_filename);
|
||||
gsf_output_set_error (output, errno,
|
||||
"Could not backup the original as %s.",
|
||||
utf8name);
|
||||
g_free (utf8name);
|
||||
g_free (backup_filename);
|
||||
g_unlink (stdio->temp_filename);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move the temp file to the original file */
|
||||
if (rename_wrapper (stdio->temp_filename, stdio->real_filename) != 0) {
|
||||
gint saved_errno = errno;
|
||||
if (backup_filename != NULL &&
|
||||
rename_wrapper (backup_filename, stdio->real_filename) != 0)
|
||||
saved_errno = errno;
|
||||
res = gsf_output_set_error (output,
|
||||
saved_errno,
|
||||
g_strerror (saved_errno));
|
||||
} else {
|
||||
/* Restore permissions. There is not much error checking we
|
||||
* can do here, I'm afraid. The final data is saved anyways.
|
||||
* Note the order: mode, uid+gid, gid, uid, mode.
|
||||
*/
|
||||
chmod_wrapper (stdio->real_filename, stdio->st.st_mode);
|
||||
#ifdef HAVE_CHOWN
|
||||
if (chown (stdio->real_filename,
|
||||
stdio->st.st_uid,
|
||||
stdio->st.st_gid)) {
|
||||
/* We cannot set both. Maybe we can set one. */
|
||||
chown (stdio->real_filename, -1, stdio->st.st_gid);
|
||||
chown (stdio->real_filename, stdio->st.st_uid, -1);
|
||||
}
|
||||
chmod_wrapper (stdio->real_filename, stdio->st.st_mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
g_free (backup_filename);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_stdio_finalize (GObject *obj)
|
||||
{
|
||||
GsfOutput *output = (GsfOutput *)obj;
|
||||
GsfOutputStdio *stdio = GSF_OUTPUT_STDIO (output);
|
||||
|
||||
if (!gsf_output_is_closed (output))
|
||||
gsf_output_close (output);
|
||||
|
||||
g_free (stdio->real_filename);
|
||||
stdio->real_filename = NULL;
|
||||
g_free (stdio->temp_filename);
|
||||
stdio->temp_filename = NULL;
|
||||
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_stdio_seek (GsfOutput *output, gsf_off_t offset, GSeekType whence)
|
||||
{
|
||||
GsfOutputStdio const *stdio = GSF_OUTPUT_STDIO (output);
|
||||
int stdio_whence = 0; /* make compiler shut up */
|
||||
|
||||
#ifndef HAVE_FSEEKO
|
||||
long loffset;
|
||||
#else
|
||||
off_t loffset;
|
||||
#endif
|
||||
|
||||
g_return_val_if_fail (stdio->file != NULL,
|
||||
gsf_output_set_error (output, 0, "missing file"));
|
||||
|
||||
loffset = offset;
|
||||
if ((gsf_off_t) loffset != offset) { /* Check for overflow */
|
||||
#ifdef HAVE_FSEEKO
|
||||
g_warning ("offset too large for fseeko");
|
||||
return gsf_output_set_error (output, 0, "offset too large for fseeko");
|
||||
#else
|
||||
g_warning ("offset too large for fseek");
|
||||
return gsf_output_set_error (output, 0, "offset too large for fseek");
|
||||
#endif
|
||||
}
|
||||
switch (whence) {
|
||||
default : ; /*checked in GsfOutput wrapper */
|
||||
case G_SEEK_SET : stdio_whence = SEEK_SET; break;
|
||||
case G_SEEK_CUR : stdio_whence = SEEK_CUR; break;
|
||||
case G_SEEK_END : stdio_whence = SEEK_END; break;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
#ifdef HAVE_FSEEKO
|
||||
if (0 == fseeko (stdio->file, loffset, stdio_whence))
|
||||
return TRUE;
|
||||
#else
|
||||
if (0 == fseek (stdio->file, loffset, stdio_whence))
|
||||
return TRUE;
|
||||
#endif
|
||||
return gsf_output_set_error (output, errno, g_strerror (errno));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsf_output_stdio_write (GsfOutput *output,
|
||||
size_t num_bytes,
|
||||
guint8 const *buffer)
|
||||
{
|
||||
GsfOutputStdio *stdio = GSF_OUTPUT_STDIO (output);
|
||||
size_t written, remaining;
|
||||
|
||||
g_return_val_if_fail (stdio != NULL, FALSE);
|
||||
g_return_val_if_fail (stdio->file != NULL, FALSE);
|
||||
|
||||
remaining = num_bytes;
|
||||
|
||||
while (remaining > 0) {
|
||||
written = fwrite (buffer + (num_bytes - remaining), 1,
|
||||
remaining, stdio->file);
|
||||
if ((written < remaining) && ferror (stdio->file) != 0)
|
||||
return gsf_output_set_error (output, errno, g_strerror (errno));
|
||||
|
||||
remaining -= written;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gsf_off_t gsf_output_stdio_vprintf (GsfOutput *output,
|
||||
char const *fmt, va_list args) G_GNUC_PRINTF (2, 0);
|
||||
|
||||
static gsf_off_t
|
||||
gsf_output_stdio_vprintf (GsfOutput *output, char const *fmt, va_list args)
|
||||
{
|
||||
return vfprintf (((GsfOutputStdio *)output)->file, fmt, args);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_stdio_init (GObject *obj)
|
||||
{
|
||||
GsfOutputStdio *stdio = GSF_OUTPUT_STDIO (obj);
|
||||
|
||||
stdio->file = NULL;
|
||||
stdio->create_backup_copy = FALSE;
|
||||
stdio->keep_open = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_stdio_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
GsfOutputClass *output_class = GSF_OUTPUT_CLASS (gobject_class);
|
||||
|
||||
gobject_class->finalize = gsf_output_stdio_finalize;
|
||||
output_class->Close = gsf_output_stdio_close;
|
||||
output_class->Seek = gsf_output_stdio_seek;
|
||||
output_class->Write = gsf_output_stdio_write;
|
||||
output_class->Vprintf = gsf_output_stdio_vprintf;
|
||||
|
||||
parent_class = g_type_class_peek_parent (gobject_class);
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfOutputStdio, gsf_output_stdio,
|
||||
gsf_output_stdio_class_init, gsf_output_stdio_init, GSF_OUTPUT_TYPE)
|
||||
|
||||
GsfOutput *
|
||||
gsf_output_stdio_new_valist (char const *filename, GError **err,
|
||||
char const *first_property_name,
|
||||
va_list var_args)
|
||||
{
|
||||
GsfOutputStdio *stdio;
|
||||
FILE *file = NULL;
|
||||
char *dirname = NULL;
|
||||
char *temp_filename = NULL;
|
||||
char *real_filename = follow_symlinks (filename, err);
|
||||
int fd;
|
||||
mode_t saved_umask;
|
||||
struct stat st;
|
||||
gboolean fixup_mode = FALSE;
|
||||
|
||||
if (real_filename == NULL)
|
||||
goto failure;
|
||||
|
||||
/* Get the directory in which the real filename lives */
|
||||
dirname = g_path_get_dirname (real_filename);
|
||||
|
||||
if (g_stat (real_filename, &st) == 0) {
|
||||
if (!S_ISREG (st.st_mode)) {
|
||||
if (err != NULL) {
|
||||
char *dname = g_filename_display_name
|
||||
(real_filename);
|
||||
*err = g_error_new (gsf_output_error_id (), 0,
|
||||
"%s: Is not a regular file",
|
||||
dname);
|
||||
g_free (dname);
|
||||
}
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* FIXME? Race conditions en masse. */
|
||||
if (access_wrapper (real_filename, W_OK) == -1) {
|
||||
if (err != NULL) {
|
||||
int save_errno = errno;
|
||||
char *dname = g_filename_display_name
|
||||
(real_filename);
|
||||
*err = g_error_new
|
||||
(gsf_output_error_id (), errno,
|
||||
"%s: %s",
|
||||
dname, g_strerror (save_errno));
|
||||
g_free (dname);
|
||||
}
|
||||
goto failure;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* File does not exist. Compute the permissions and uid/gid
|
||||
* that we will use for the newly-created file.
|
||||
*/
|
||||
|
||||
memset (&st, 0, sizeof (st));
|
||||
|
||||
/* Use default permissions */
|
||||
st.st_mode = 0666; fixup_mode = TRUE;
|
||||
#ifdef HAVE_CHOWN
|
||||
{
|
||||
struct stat dir_st;
|
||||
|
||||
st.st_uid = getuid ();
|
||||
|
||||
if (g_stat (dirname, &dir_st) == 0 &&
|
||||
S_ISDIR (dir_st.st_mode) &&
|
||||
(dir_st.st_mode & S_ISGID))
|
||||
st.st_gid = dir_st.st_gid;
|
||||
else
|
||||
st.st_gid = getgid ();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Save to a temporary file. We set the umask because some (buggy)
|
||||
* implementations of mkstemp() use permissions 0666 and we want 0600.
|
||||
*/
|
||||
temp_filename = g_build_filename (dirname, ".gsf-save-XXXXXX", NULL);
|
||||
/* Oh, joy. What about threads? --MW */
|
||||
saved_umask = umask (0077);
|
||||
fd = g_mkstemp (temp_filename); /* this modifies temp_filename to the used name */
|
||||
umask (saved_umask);
|
||||
|
||||
if (fixup_mode)
|
||||
st.st_mode &= ~saved_umask;
|
||||
|
||||
if (fd < 0 || NULL == (file = fdopen (fd, "wb"))) {
|
||||
if (err != NULL) {
|
||||
int save_errno = errno;
|
||||
char *dname = g_filename_display_name
|
||||
(temp_filename);
|
||||
*err = g_error_new
|
||||
(gsf_output_error_id (), errno,
|
||||
"%s: %s",
|
||||
dname, g_strerror (save_errno));
|
||||
g_free (dname);
|
||||
}
|
||||
goto failure;
|
||||
}
|
||||
|
||||
stdio = (GsfOutputStdio *)g_object_new_valist (GSF_OUTPUT_STDIO_TYPE,
|
||||
first_property_name, var_args);
|
||||
stdio->file = file;
|
||||
stdio->st = st;
|
||||
stdio->create_backup_copy = FALSE;
|
||||
stdio->real_filename = real_filename;
|
||||
stdio->temp_filename = temp_filename;
|
||||
|
||||
gsf_output_set_name_from_filename (GSF_OUTPUT (stdio), filename);
|
||||
|
||||
g_free (dirname);
|
||||
|
||||
return GSF_OUTPUT (stdio);
|
||||
|
||||
failure:
|
||||
g_free (temp_filename);
|
||||
g_free (real_filename);
|
||||
g_free (dirname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_stdio_new_full :
|
||||
* @filename : name of file to create or replace.
|
||||
* @err : optionally NULL.
|
||||
* @first_property_name : NULL terminated list of properties
|
||||
* @Varargs :
|
||||
*
|
||||
* Returns a new file or NULL.
|
||||
**/
|
||||
GsfOutput *
|
||||
gsf_output_stdio_new_full (char const *filename, GError **err,
|
||||
char const *first_property_name, ...)
|
||||
{
|
||||
GsfOutput *res;
|
||||
va_list var_args;
|
||||
|
||||
va_start (var_args, first_property_name);
|
||||
res = gsf_output_stdio_new_valist (filename, err, first_property_name, var_args);
|
||||
va_end (var_args);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_stdio_new :
|
||||
* @filename : name of file to create or replace.
|
||||
* @err : optionally NULL.
|
||||
*
|
||||
* Returns a new file or NULL.
|
||||
**/
|
||||
GsfOutput *
|
||||
gsf_output_stdio_new (char const *filename, GError **err)
|
||||
{
|
||||
return gsf_output_stdio_new_full (filename, err, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_stdio_new_FILE :
|
||||
* @filename : The filename corresponding to @file.
|
||||
* @file : an existing stdio FILE *
|
||||
* @keep_open : Should @file be closed when the wrapper is closed
|
||||
*
|
||||
* Assumes ownership of @file. If @keep_open is true, ownership reverts
|
||||
* to caller when the GsfObject is closed.
|
||||
*
|
||||
* Returns a new GsfOutput wrapper for @file. Warning: the result will be
|
||||
* seekable only if @file is seekable. If it is seekable, the resulting
|
||||
* GsfOutput object will seek relative to @file's beginning, not its
|
||||
* current location at the time the GsfOutput object is created.
|
||||
**/
|
||||
GsfOutput *
|
||||
gsf_output_stdio_new_FILE (char const *filename, FILE *file, gboolean keep_open)
|
||||
{
|
||||
GsfOutputStdio *stdio;
|
||||
|
||||
g_return_val_if_fail (filename != NULL, NULL);
|
||||
g_return_val_if_fail (file != NULL, NULL);
|
||||
|
||||
stdio = g_object_new (GSF_OUTPUT_STDIO_TYPE, NULL);
|
||||
stdio->file = file;
|
||||
stdio->keep_open = keep_open;
|
||||
stdio->real_filename = stdio->temp_filename = NULL;
|
||||
gsf_output_set_name_from_filename (GSF_OUTPUT (stdio), filename);
|
||||
return GSF_OUTPUT (stdio);
|
||||
}
|
||||
49
lib/libgsf-1.12.3/gsf/gsf-output-stdio.h
Normal file
49
lib/libgsf-1.12.3/gsf/gsf-output-stdio.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-output-stdio.h: stdio based output
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_OUTPUT_STDIO_H
|
||||
#define GSF_OUTPUT_STDIO_H
|
||||
|
||||
#include "gsf-output.h"
|
||||
#include <stdio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSF_OUTPUT_STDIO_TYPE (gsf_output_stdio_get_type ())
|
||||
#define GSF_OUTPUT_STDIO(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_OUTPUT_STDIO_TYPE, GsfOutputStdio))
|
||||
#define GSF_IS_OUTPUT_STDIO(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_OUTPUT_STDIO_TYPE))
|
||||
|
||||
typedef struct _GsfOutputStdio GsfOutputStdio;
|
||||
|
||||
GType gsf_output_stdio_get_type (void);
|
||||
GsfOutput *gsf_output_stdio_new (char const *filename, GError **err);
|
||||
GsfOutput *gsf_output_stdio_new_full (char const *filename, GError **err,
|
||||
char const *first_property_name,
|
||||
...); /* G_GNUC_NULL_TERMINATED */
|
||||
GsfOutput *gsf_output_stdio_new_valist (char const *filename, GError **err,
|
||||
char const *first_property_name,
|
||||
va_list var_args);
|
||||
GsfOutput *gsf_output_stdio_new_FILE (char const *filename, FILE *file,
|
||||
gboolean keep_open);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_OUTPUT_STDIO_H */
|
||||
605
lib/libgsf-1.12.3/gsf/gsf-output.c
Normal file
605
lib/libgsf-1.12.3/gsf/gsf-output.c
Normal file
@@ -0,0 +1,605 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-output.c: interface for storing data
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-output-impl.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <string.h>
|
||||
|
||||
static gsf_off_t gsf_output_real_vprintf (GsfOutput *output,
|
||||
char const* format, va_list args) G_GNUC_PRINTF (2, 0);
|
||||
|
||||
#define GET_CLASS(instance) G_TYPE_INSTANCE_GET_CLASS (instance, GSF_OUTPUT_TYPE, GsfOutputClass)
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_NAME,
|
||||
PROP_SIZE,
|
||||
PROP_CLOSED,
|
||||
PROP_POS
|
||||
};
|
||||
|
||||
static void
|
||||
gsf_output_set_property (GObject *object,
|
||||
guint property_id,
|
||||
G_GNUC_UNUSED GValue const *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
switch (property_id) {
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
/* gsf_off_t is typedef'd to gint64 */
|
||||
switch (property_id) {
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, gsf_output_name (GSF_OUTPUT (object)));
|
||||
break;
|
||||
case PROP_SIZE:
|
||||
g_value_set_int64 (value, gsf_output_size (GSF_OUTPUT (object)));
|
||||
break;
|
||||
case PROP_POS:
|
||||
g_value_set_int64 (value, gsf_output_tell (GSF_OUTPUT (object)));
|
||||
break;
|
||||
case PROP_CLOSED:
|
||||
g_value_set_boolean (value, gsf_output_is_closed (GSF_OUTPUT (object)));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_dispose (GObject *obj)
|
||||
{
|
||||
GsfOutput *output = GSF_OUTPUT (obj);
|
||||
|
||||
if (!output->is_closed) {
|
||||
/* g_warning ("Disposing of an unclosed stream"); */
|
||||
gsf_output_close (output);
|
||||
}
|
||||
|
||||
g_free (output->name);
|
||||
output->name = NULL;
|
||||
g_free (output->printf_buf);
|
||||
output->printf_buf = NULL;
|
||||
|
||||
g_clear_error (&output->err);
|
||||
|
||||
if (output->container != NULL) {
|
||||
g_object_unref (G_OBJECT (output->container));
|
||||
output->container = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_init (GObject *obj)
|
||||
{
|
||||
GsfOutput *output = GSF_OUTPUT (obj);
|
||||
|
||||
output->cur_offset = 0;
|
||||
output->cur_size = 0;
|
||||
output->name = NULL;
|
||||
output->wrapped_by = NULL;
|
||||
output->container = NULL;
|
||||
output->err = NULL;
|
||||
output->is_closed = FALSE;
|
||||
output->printf_buf = NULL;
|
||||
output->printf_buf_size = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_output_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
GsfOutputClass *output_class = GSF_OUTPUT_CLASS (gobject_class);
|
||||
|
||||
gobject_class->dispose = gsf_output_dispose;
|
||||
gobject_class->set_property = gsf_output_set_property;
|
||||
gobject_class->get_property = gsf_output_get_property;
|
||||
output_class->Vprintf = gsf_output_real_vprintf;
|
||||
|
||||
parent_class = g_type_class_peek_parent (gobject_class);
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_NAME,
|
||||
g_param_spec_string ("name", "Name",
|
||||
"The Output's Name",
|
||||
NULL,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READABLE));
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_SIZE,
|
||||
g_param_spec_int64 ("size", "Size",
|
||||
"The Output's Size",
|
||||
0, G_MAXINT64, 0,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READABLE));
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_POS,
|
||||
g_param_spec_int64 ("position", "Position",
|
||||
"The Output's Current Position",
|
||||
0, G_MAXINT64, 0,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READABLE));
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_CLOSED,
|
||||
g_param_spec_boolean ("is-closed", "Is Closed",
|
||||
"Whether the Output is Closed",
|
||||
FALSE,
|
||||
GSF_PARAM_STATIC |
|
||||
G_PARAM_READABLE));
|
||||
}
|
||||
|
||||
GSF_CLASS_ABSTRACT (GsfOutput, gsf_output,
|
||||
gsf_output_class_init, gsf_output_init,
|
||||
G_TYPE_OBJECT)
|
||||
|
||||
/**
|
||||
* gsf_output_name :
|
||||
* @output :
|
||||
*
|
||||
* Returns @output's name in utf8 form, DO NOT FREE THIS STRING
|
||||
**/
|
||||
char const *
|
||||
gsf_output_name (GsfOutput const *output)
|
||||
{
|
||||
g_return_val_if_fail (GSF_IS_OUTPUT (output), NULL);
|
||||
return output->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_container :
|
||||
* @output :
|
||||
*
|
||||
* Returns, but does not add a reference to @output's container.
|
||||
* Potentially NULL
|
||||
**/
|
||||
GsfOutfile *
|
||||
gsf_output_container (GsfOutput const *output)
|
||||
{
|
||||
g_return_val_if_fail (GSF_IS_OUTPUT (output), NULL);
|
||||
return output->container;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_size :
|
||||
* @output :
|
||||
*
|
||||
* Returns the size of the output, or -1 if it does not have a size.
|
||||
**/
|
||||
gsf_off_t
|
||||
gsf_output_size (GsfOutput *output)
|
||||
{
|
||||
g_return_val_if_fail (GSF_IS_OUTPUT (output), -1);
|
||||
return output->cur_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_close :
|
||||
* @output :
|
||||
*
|
||||
* Close a stream.
|
||||
* Returns FALSE on error
|
||||
**/
|
||||
gboolean
|
||||
gsf_output_close (GsfOutput *output)
|
||||
{
|
||||
gboolean res;
|
||||
|
||||
g_return_val_if_fail (GSF_IS_OUTPUT (output),
|
||||
gsf_output_set_error (output, 0, "<internal>"));
|
||||
g_return_val_if_fail (!output->is_closed,
|
||||
gsf_output_set_error (output, 0, "<internal>"));
|
||||
|
||||
/* The implementation will log any errors, but we can never try to
|
||||
* close multiple times even on failure.
|
||||
*/
|
||||
res = GET_CLASS (output)->Close (output);
|
||||
output->is_closed = TRUE;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_is_closed :
|
||||
* @output :
|
||||
*
|
||||
* Returns TRUE if @output has already been closed.
|
||||
**/
|
||||
gboolean
|
||||
gsf_output_is_closed (GsfOutput const *output)
|
||||
{
|
||||
g_return_val_if_fail (GSF_IS_OUTPUT (output), TRUE);
|
||||
return output->is_closed;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_tell :
|
||||
* @output :
|
||||
*
|
||||
* Returns the current position in the file
|
||||
**/
|
||||
gsf_off_t
|
||||
gsf_output_tell (GsfOutput *output)
|
||||
{
|
||||
g_return_val_if_fail (output != NULL, 0);
|
||||
|
||||
return output->cur_offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_seek :
|
||||
* @output :
|
||||
* @offset :
|
||||
* @whence :
|
||||
*
|
||||
* Returns FALSE on error.
|
||||
**/
|
||||
gboolean
|
||||
gsf_output_seek (GsfOutput *output, gsf_off_t offset, GSeekType whence)
|
||||
{
|
||||
gsf_off_t pos = offset;
|
||||
|
||||
g_return_val_if_fail (output != NULL, FALSE);
|
||||
|
||||
switch (whence) {
|
||||
case G_SEEK_SET: break;
|
||||
case G_SEEK_CUR: pos += output->cur_offset; break;
|
||||
case G_SEEK_END: pos += output->cur_size; break;
|
||||
default :
|
||||
g_warning ("Invalid seek type %d", (int)whence);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (pos < 0) {
|
||||
g_warning ("Invalid seek position %" GSF_OFF_T_FORMAT
|
||||
", which is before the start of the file", pos);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* If we go nowhere, just return. This in particular handles null
|
||||
* seeks for streams with no seek method.
|
||||
*/
|
||||
if (pos == output->cur_offset)
|
||||
return TRUE;
|
||||
|
||||
if (GET_CLASS (output)->Seek (output, offset, whence)) {
|
||||
/* NOTE : it is possible for the current pos to be beyond the
|
||||
* end of the file. The intervening space is not filled with 0
|
||||
* until something is written.
|
||||
*/
|
||||
output->cur_offset = pos;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* the implementation should have assigned whatever errors are necessary */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
gsf_output_inc_cur_offset (GsfOutput *output, gsf_off_t num_bytes)
|
||||
{
|
||||
output->cur_offset += num_bytes;
|
||||
if (output->cur_offset < num_bytes)
|
||||
return gsf_output_set_error (output, 0, "Output size overflow.");
|
||||
if (output->cur_size < output->cur_offset)
|
||||
output->cur_size = output->cur_offset;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_write :
|
||||
* @output :
|
||||
* @num_bytes :
|
||||
* @data :
|
||||
*
|
||||
* Returns FALSE on error.
|
||||
**/
|
||||
gboolean
|
||||
gsf_output_write (GsfOutput *output,
|
||||
size_t num_bytes, guint8 const *data)
|
||||
{
|
||||
g_return_val_if_fail (output != NULL, FALSE);
|
||||
|
||||
if (num_bytes == 0)
|
||||
return TRUE;
|
||||
if (GET_CLASS (output)->Write (output, num_bytes, data))
|
||||
return gsf_output_inc_cur_offset (output, num_bytes);
|
||||
|
||||
/* the implementation should have assigned whatever errors are necessary */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_error :
|
||||
* @output :
|
||||
*
|
||||
* Returns the last error logged on the output, or NULL.
|
||||
**/
|
||||
GError const *
|
||||
gsf_output_error (GsfOutput const *output)
|
||||
{
|
||||
g_return_val_if_fail (GSF_IS_OUTPUT (output), NULL);
|
||||
return output->err;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_set_name :
|
||||
* @output :
|
||||
* @name :
|
||||
*
|
||||
* <note>This is a utility routine that should only be used by derived
|
||||
* outputs.</note>
|
||||
*
|
||||
* Returns : TRUE if the assignment was ok.
|
||||
**/
|
||||
gboolean
|
||||
gsf_output_set_name (GsfOutput *output, char const *name)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
g_return_val_if_fail (GSF_IS_OUTPUT (output), FALSE);
|
||||
|
||||
buf = g_strdup (name);
|
||||
g_free (output->name);
|
||||
output->name = buf;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_set_name_from_filename :
|
||||
* @output : the output stream
|
||||
* @filename : the (fs-sys encoded) filename
|
||||
*
|
||||
* <note>This is a utility routine that should only be used by derived
|
||||
* outputs.</note>
|
||||
*
|
||||
* Returns : TRUE if the assignment was ok.
|
||||
**/
|
||||
gboolean
|
||||
gsf_output_set_name_from_filename (GsfOutput *output, char const *filename)
|
||||
{
|
||||
g_return_val_if_fail (GSF_IS_OUTPUT (output), FALSE);
|
||||
|
||||
g_free (output->name);
|
||||
output->name = filename
|
||||
? g_filename_to_utf8 (filename, -1, NULL, NULL, NULL)
|
||||
: NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_set_container :
|
||||
* @output :
|
||||
* @container :
|
||||
*
|
||||
* <note>This is a utility routine that should only be used by derived
|
||||
* outputs.</note>
|
||||
*
|
||||
* Returns : TRUE if the assignment was ok.
|
||||
**/
|
||||
gboolean
|
||||
gsf_output_set_container (GsfOutput *output, GsfOutfile *container)
|
||||
{
|
||||
g_return_val_if_fail (GSF_IS_OUTPUT (output), FALSE);
|
||||
|
||||
if (container != NULL)
|
||||
g_object_ref (G_OBJECT (container));
|
||||
if (output->container != NULL)
|
||||
g_object_unref (G_OBJECT (output->container));
|
||||
output->container = container;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_set_error :
|
||||
* @output :
|
||||
* @code :
|
||||
* @format :
|
||||
* @Varargs :
|
||||
*
|
||||
* <note>This is a utility routine that should only be used by derived
|
||||
* outputs.</note>
|
||||
*
|
||||
* Returns Always returns FALSE to facilitate its use.
|
||||
**/
|
||||
gboolean
|
||||
gsf_output_set_error (GsfOutput *output,
|
||||
gint code,
|
||||
char const *format,
|
||||
...)
|
||||
{
|
||||
g_return_val_if_fail (GSF_IS_OUTPUT (output), FALSE);
|
||||
|
||||
g_clear_error (&output->err);
|
||||
|
||||
if (format != NULL) {
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
output->err = g_new (GError, 1);
|
||||
output->err->domain = gsf_output_error_id ();
|
||||
output->err->code = code;
|
||||
output->err->message = g_strdup_vprintf (format, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
cb_output_unwrap (GsfOutput *wrapee, G_GNUC_UNUSED GObject *wrapper)
|
||||
{
|
||||
wrapee->wrapped_by = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_wrap :
|
||||
* @wrapper :
|
||||
* @wrapee :
|
||||
*
|
||||
* Returns TRUE if the wrapping succeeded.
|
||||
**/
|
||||
gboolean
|
||||
gsf_output_wrap (GObject *wrapper, GsfOutput *wrapee)
|
||||
{
|
||||
g_return_val_if_fail (wrapper != NULL, FALSE);
|
||||
g_return_val_if_fail (wrapee != NULL, FALSE);
|
||||
|
||||
if (wrapee->wrapped_by != NULL) {
|
||||
g_warning ("Attempt to wrap an output that is already wrapped.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_object_weak_ref (G_OBJECT (wrapper),
|
||||
(GWeakNotify) cb_output_unwrap, wrapee);
|
||||
wrapee->wrapped_by = wrapper;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_unwrap :
|
||||
* @wrapper :
|
||||
* @wrapee :
|
||||
*
|
||||
* Returns TRUE if the unwrapping succeeded.
|
||||
**/
|
||||
gboolean
|
||||
gsf_output_unwrap (GObject *wrapper, GsfOutput *wrapee)
|
||||
{
|
||||
g_return_val_if_fail (wrapee != NULL, FALSE);
|
||||
g_return_val_if_fail (wrapee->wrapped_by == wrapper, FALSE);
|
||||
|
||||
wrapee->wrapped_by = NULL;
|
||||
g_object_weak_unref (G_OBJECT (wrapper),
|
||||
(GWeakNotify) cb_output_unwrap, wrapee);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GQuark
|
||||
gsf_output_error_id (void)
|
||||
{
|
||||
static GQuark quark;
|
||||
if (!quark)
|
||||
quark = g_quark_from_static_string ("gsf_output_error");
|
||||
return quark;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_printf:
|
||||
* @output: A #GsfOutput
|
||||
* @format: The printf-style format string
|
||||
* @Varargs: the arguments for @format
|
||||
*
|
||||
* Returns: TRUE if successful, FALSE if not
|
||||
**/
|
||||
gboolean
|
||||
gsf_output_printf (GsfOutput *output, char const *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
gboolean res;
|
||||
|
||||
va_start (args, format);
|
||||
res = (gsf_output_vprintf (output, format, args) >= 0);
|
||||
va_end (args);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_vprintf:
|
||||
* @output: A #GsfOutput
|
||||
* @format: The printf-style format string
|
||||
* @args: the arguments for @format
|
||||
*
|
||||
* Returns: number of bytes printed, a negative value if not successful
|
||||
**/
|
||||
gsf_off_t
|
||||
gsf_output_vprintf (GsfOutput *output, char const *format, va_list args)
|
||||
{
|
||||
gsf_off_t num_bytes;
|
||||
|
||||
g_return_val_if_fail (output != NULL, -1);
|
||||
g_return_val_if_fail (format != NULL, -1);
|
||||
/* g_return_val_if_fail (strlen (format) > 0, -1); -- Why? */
|
||||
|
||||
num_bytes = GET_CLASS (output)->Vprintf (output, format, args);
|
||||
|
||||
if (num_bytes >= 0)
|
||||
if (!gsf_output_inc_cur_offset (output, num_bytes))
|
||||
return -1;
|
||||
return num_bytes;
|
||||
}
|
||||
|
||||
static gsf_off_t
|
||||
gsf_output_real_vprintf (GsfOutput *output, char const *fmt, va_list args)
|
||||
{
|
||||
gsf_off_t reslen;
|
||||
|
||||
if (NULL == output->printf_buf) {
|
||||
output->printf_buf_size = 128;
|
||||
output->printf_buf = g_new (char, output->printf_buf_size);
|
||||
}
|
||||
reslen = g_vsnprintf (output->printf_buf, output->printf_buf_size, fmt, args);
|
||||
|
||||
/* handle C99 or older -1 case of vsnprintf */
|
||||
if (reslen < 0 || reslen >= output->printf_buf_size) {
|
||||
g_free (output->printf_buf);
|
||||
output->printf_buf = g_strdup_vprintf (fmt, args);
|
||||
reslen = output->printf_buf_size = strlen (output->printf_buf);
|
||||
}
|
||||
|
||||
if (reslen == 0 ||
|
||||
GET_CLASS (output)->Write (output, reslen, output->printf_buf))
|
||||
return reslen;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_output_puts:
|
||||
* @output: A #GsfOutput
|
||||
* @line: %null terminated string to write
|
||||
*
|
||||
* Like fputs, this assumes that the line already ends with a newline
|
||||
*
|
||||
* Returns: TRUE if successful, FALSE if not
|
||||
**/
|
||||
gboolean
|
||||
gsf_output_puts (GsfOutput *output, char const *line)
|
||||
{
|
||||
size_t nbytes = 0;
|
||||
|
||||
g_return_val_if_fail (line != NULL, FALSE);
|
||||
|
||||
nbytes = strlen (line);
|
||||
return gsf_output_write (output, nbytes, line);
|
||||
}
|
||||
96
lib/libgsf-1.12.3/gsf/gsf-output.h
Normal file
96
lib/libgsf-1.12.3/gsf/gsf-output.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-output.h: interface for storing data
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_OUTPUT_H
|
||||
#define GSF_OUTPUT_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
#include <sys/types.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct {
|
||||
GObjectClass g_object_class;
|
||||
|
||||
gboolean (*Close) (GsfOutput *output);
|
||||
gboolean (*Seek) (GsfOutput *output,
|
||||
gsf_off_t offset, GSeekType whence);
|
||||
gboolean (*Write) (GsfOutput *output,
|
||||
size_t num_bytes, guint8 const *data);
|
||||
gsf_off_t (*Vprintf) (GsfOutput *output,
|
||||
char const *format, va_list args);
|
||||
} GsfOutputClass;
|
||||
#define GSF_OUTPUT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSF_OUTPUT_TYPE, GsfOutputClass))
|
||||
#define GSF_IS_OUTPUT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSF_OUTPUT_TYPE))
|
||||
|
||||
struct _GsfOutput {
|
||||
GObject g_object;
|
||||
|
||||
/*< protected >*/
|
||||
gsf_off_t cur_size, cur_offset;
|
||||
char *name;
|
||||
GObject *wrapped_by;
|
||||
GsfOutfile *container;
|
||||
GError *err;
|
||||
gboolean is_closed;
|
||||
|
||||
char *printf_buf;
|
||||
int printf_buf_size;
|
||||
};
|
||||
#define GSF_OUTPUT_TYPE (gsf_output_get_type ())
|
||||
#define GSF_OUTPUT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_OUTPUT_TYPE, GsfOutput))
|
||||
#define GSF_IS_OUTPUT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_OUTPUT_TYPE))
|
||||
|
||||
GType gsf_output_get_type (void);
|
||||
|
||||
char const *gsf_output_name (GsfOutput const *output);
|
||||
GsfOutfile *gsf_output_container (GsfOutput const *output);
|
||||
|
||||
GError const *gsf_output_error (GsfOutput const *output);
|
||||
gboolean gsf_output_set_error (GsfOutput *output,
|
||||
gint code,
|
||||
char const *format,
|
||||
...) G_GNUC_PRINTF (3, 4);
|
||||
|
||||
gsf_off_t gsf_output_size (GsfOutput *output);
|
||||
gboolean gsf_output_close (GsfOutput *output);
|
||||
gboolean gsf_output_is_closed (GsfOutput const *output);
|
||||
gsf_off_t gsf_output_tell (GsfOutput *output);
|
||||
gboolean gsf_output_seek (GsfOutput *output,
|
||||
gsf_off_t offset, GSeekType whence);
|
||||
gboolean gsf_output_write (GsfOutput *output,
|
||||
size_t num_bytes, guint8 const *data);
|
||||
|
||||
gboolean gsf_output_wrap (GObject *wrapper, GsfOutput *wrapee);
|
||||
gboolean gsf_output_unwrap (GObject *wrapper, GsfOutput *wrapee);
|
||||
|
||||
GQuark gsf_output_error_id (void);
|
||||
|
||||
gboolean gsf_output_printf (GsfOutput *output, char const *format,
|
||||
...) G_GNUC_PRINTF (2, 3);
|
||||
gsf_off_t gsf_output_vprintf (GsfOutput *output, char const *format,
|
||||
va_list args) G_GNUC_PRINTF (2, 0);
|
||||
gboolean gsf_output_puts (GsfOutput *output, char const *line);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_OUTPUT_H */
|
||||
107
lib/libgsf-1.12.3/gsf/gsf-shared-memory.c
Normal file
107
lib/libgsf-1.12.3/gsf/gsf-shared-memory.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-shared-memory.c:
|
||||
*
|
||||
* Copyright (C) 2002-2004 Morten Welinder (terra@diku.dk)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-shared-memory.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#elif defined(G_OS_WIN32)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
GObjectClass g_object_class;
|
||||
} GsfSharedMemoryClass;
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
GsfSharedMemory *
|
||||
gsf_shared_memory_new (void *buf, gsf_off_t size, gboolean needs_free)
|
||||
{
|
||||
GsfSharedMemory *mem = g_object_new (GSF_SHARED_MEMORY_TYPE, NULL);
|
||||
mem->buf = buf;
|
||||
mem->size = size;
|
||||
mem->needs_free = needs_free;
|
||||
mem->needs_unmap = FALSE;
|
||||
return mem;
|
||||
}
|
||||
|
||||
GsfSharedMemory *
|
||||
gsf_shared_memory_mmapped_new (void *buf, gsf_off_t size)
|
||||
{
|
||||
#if defined(HAVE_MMAP) || defined(G_OS_WIN32)
|
||||
size_t msize = size;
|
||||
if ((gsf_off_t)msize != size) {
|
||||
g_warning ("memory buffer size too large");
|
||||
return NULL;
|
||||
} else {
|
||||
GsfSharedMemory *mem = gsf_shared_memory_new (buf, size, FALSE);
|
||||
mem->needs_unmap = TRUE;
|
||||
return mem;
|
||||
}
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_shared_memory_finalize (GObject *obj)
|
||||
{
|
||||
GsfSharedMemory *mem = (GsfSharedMemory *) (obj);
|
||||
|
||||
if (mem->buf != NULL) {
|
||||
if (mem->needs_free)
|
||||
g_free (mem->buf);
|
||||
else if (mem->needs_unmap) {
|
||||
#ifdef HAVE_MMAP
|
||||
munmap (mem->buf, mem->size);
|
||||
#elif defined(G_OS_WIN32)
|
||||
UnmapViewOfFile (mem->buf);
|
||||
#else
|
||||
g_assert_not_reached ();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_shared_memory_init (GObject *obj)
|
||||
{
|
||||
GsfSharedMemory *mem = (GsfSharedMemory *) (obj);
|
||||
mem->buf = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_shared_memory_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
parent_class = g_type_class_peek_parent (gobject_class);
|
||||
|
||||
gobject_class->finalize = gsf_shared_memory_finalize;
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfSharedMemory, gsf_shared_memory,
|
||||
gsf_shared_memory_class_init, gsf_shared_memory_init,
|
||||
G_TYPE_OBJECT)
|
||||
50
lib/libgsf-1.12.3/gsf/gsf-shared-memory.h
Normal file
50
lib/libgsf-1.12.3/gsf/gsf-shared-memory.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-shared-memory.h
|
||||
*
|
||||
* Copyright (C) 2002-2004 Morten Welinder (terra@diku.dk)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_SHARED_MEMORY_H
|
||||
#define GSF_SHARED_MEMORY_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSF_SHARED_MEMORY_TYPE (gsf_shared_memory_get_type ())
|
||||
#define GSF_SHARED_MEMORY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_SHARED_MEMORY_TYPE, GsfSharedMemory))
|
||||
#define GSF_IS_SHARED_MEMORY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_SHARED_MEMORY_TYPE))
|
||||
|
||||
typedef struct _GsfSharedMemory GsfSharedMemory;
|
||||
struct _GsfSharedMemory {
|
||||
GObject g_object;
|
||||
void *buf;
|
||||
gsf_off_t size;
|
||||
|
||||
gboolean needs_free;
|
||||
gboolean needs_unmap;
|
||||
};
|
||||
|
||||
GType gsf_shared_memory_get_type (void);
|
||||
GsfSharedMemory *gsf_shared_memory_new (void *buf, gsf_off_t size, gboolean needs_free);
|
||||
GsfSharedMemory *gsf_shared_memory_mmapped_new (void *buf, gsf_off_t size);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_SHARED_MEMORY_H */
|
||||
298
lib/libgsf-1.12.3/gsf/gsf-structured-blob.c
Normal file
298
lib/libgsf-1.12.3/gsf/gsf-structured-blob.c
Normal file
@@ -0,0 +1,298 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-structured_blob.c : Utility storage to blob in/out a tree of data
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-structured-blob.h>
|
||||
#include <gsf/gsf-impl-utils.h>
|
||||
#include <gsf/gsf-infile-impl.h>
|
||||
#include <gsf/gsf-input.h>
|
||||
#include <gsf/gsf-outfile.h>
|
||||
#include <gsf/gsf-output.h>
|
||||
#include <gsf/gsf-shared-memory.h>
|
||||
#include <string.h>
|
||||
|
||||
static GObjectClass *parent_class;
|
||||
|
||||
struct _GsfStructuredBlob {
|
||||
GsfInfile base;
|
||||
|
||||
GsfSharedMemory *data;
|
||||
GPtrArray *children;
|
||||
};
|
||||
typedef struct {
|
||||
GsfInfileClass base;
|
||||
} GsfStructuredBlobClass;
|
||||
|
||||
static void
|
||||
blob_finalize (GObject *obj)
|
||||
{
|
||||
unsigned i;
|
||||
GsfStructuredBlob *blob = GSF_STRUCTURED_BLOB (obj);
|
||||
|
||||
if (blob->data != NULL) {
|
||||
g_object_unref (G_OBJECT (blob->data));
|
||||
blob->data = NULL;
|
||||
}
|
||||
|
||||
if (blob->children != NULL) {
|
||||
for (i = 0; i < blob->children->len ; i++)
|
||||
g_object_unref (g_ptr_array_index (blob->children, i));
|
||||
g_ptr_array_free (blob->children, TRUE);
|
||||
blob->children = NULL;
|
||||
}
|
||||
|
||||
parent_class->finalize (obj);
|
||||
}
|
||||
|
||||
static GsfInput *
|
||||
blob_dup (GsfInput *input, G_GNUC_UNUSED GError **err)
|
||||
{
|
||||
GsfStructuredBlob const *src = (GsfStructuredBlob *) input;
|
||||
GsfStructuredBlob *dst = g_object_new (GSF_STRUCTURED_BLOB_TYPE, NULL);
|
||||
|
||||
if (src->data != NULL) {
|
||||
dst->data = src->data;
|
||||
g_object_ref (G_OBJECT (dst->data));
|
||||
}
|
||||
if (src->children != NULL) {
|
||||
unsigned i;
|
||||
gpointer child;
|
||||
|
||||
dst->children = g_ptr_array_sized_new (src->children->len);
|
||||
g_ptr_array_set_size (dst->children, src->children->len);
|
||||
for (i = 0; i < src->children->len ; i++) {
|
||||
child = g_ptr_array_index (src->children, i);
|
||||
g_ptr_array_index (dst->children, i) = child;
|
||||
g_object_ref (child);
|
||||
}
|
||||
}
|
||||
|
||||
return GSF_INPUT (dst);
|
||||
}
|
||||
|
||||
static guint8 const *
|
||||
blob_read (GsfInput *input, size_t num_bytes, guint8 *optional_buffer)
|
||||
{
|
||||
GsfStructuredBlob *blob = (GsfStructuredBlob *) input;
|
||||
guchar const *src = blob->data->buf;
|
||||
|
||||
if (src == NULL)
|
||||
return NULL;
|
||||
if (optional_buffer) {
|
||||
memcpy (optional_buffer, src + input->cur_offset, num_bytes);
|
||||
return optional_buffer;
|
||||
} else
|
||||
return src + input->cur_offset;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
blob_seek (G_GNUC_UNUSED GsfInput *input,
|
||||
G_GNUC_UNUSED gsf_off_t offset,
|
||||
G_GNUC_UNUSED GSeekType whence)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
blob_num_children (GsfInfile *infile)
|
||||
{
|
||||
GsfStructuredBlob const *blob = (GsfStructuredBlob *) infile;
|
||||
|
||||
if (blob->children != NULL)
|
||||
return blob->children->len;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char const *
|
||||
blob_name_by_index (GsfInfile *infile, int i)
|
||||
{
|
||||
GsfStructuredBlob const *blob = (GsfStructuredBlob *) infile;
|
||||
if (blob->children != NULL) {
|
||||
g_return_val_if_fail (i < 0 || (unsigned)i >= blob->children->len, NULL);
|
||||
return gsf_input_name (g_ptr_array_index (blob->children, i));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GsfInput *
|
||||
blob_child_by_index (GsfInfile *infile, int i, GError **err)
|
||||
{
|
||||
GsfStructuredBlob const *blob = (GsfStructuredBlob *) infile;
|
||||
if (blob->children != NULL) {
|
||||
g_return_val_if_fail (i < 0 || (unsigned)i >= blob->children->len, NULL);
|
||||
return gsf_input_dup (g_ptr_array_index (blob->children, i), err);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GsfInput *
|
||||
blob_child_by_name (GsfInfile *infile, char const *name, GError **err)
|
||||
{
|
||||
GsfStructuredBlob const *blob = (GsfStructuredBlob *) infile;
|
||||
if (blob->children != NULL) {
|
||||
unsigned i;
|
||||
GsfInput *child;
|
||||
|
||||
for (i = 0 ; i < blob->children->len ;) {
|
||||
child = g_ptr_array_index (blob->children, i);
|
||||
if (!strcmp (gsf_input_name (child), name))
|
||||
return gsf_input_dup (child, err);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_structured_blob_init (GObject *obj)
|
||||
{
|
||||
GsfStructuredBlob *blob = GSF_STRUCTURED_BLOB (obj);
|
||||
|
||||
blob->data = NULL;
|
||||
blob->children = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_structured_blob_class_init (GObjectClass *gobject_class)
|
||||
{
|
||||
GsfInputClass *input_class = GSF_INPUT_CLASS (gobject_class);
|
||||
GsfInfileClass *infile_class = GSF_INFILE_CLASS (gobject_class);
|
||||
|
||||
gobject_class->finalize = blob_finalize;
|
||||
input_class->Dup = blob_dup;
|
||||
input_class->Read = blob_read;
|
||||
input_class->Seek = blob_seek;
|
||||
infile_class->num_children = blob_num_children;
|
||||
infile_class->name_by_index = blob_name_by_index;
|
||||
infile_class->child_by_index = blob_child_by_index;
|
||||
infile_class->child_by_name = blob_child_by_name;
|
||||
|
||||
parent_class = g_type_class_peek_parent (gobject_class);
|
||||
}
|
||||
|
||||
GSF_CLASS (GsfStructuredBlob, gsf_structured_blob,
|
||||
gsf_structured_blob_class_init, gsf_structured_blob_init,
|
||||
GSF_INFILE_TYPE)
|
||||
|
||||
/**
|
||||
* gsf_structured_blob_read :
|
||||
* @input : An input (potentially a GsfInfile) holding the blob
|
||||
*
|
||||
* Returns a freshly created tree of blobs
|
||||
**/
|
||||
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 (G_OBJECT (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 (G_OBJECT (child));
|
||||
|
||||
g_ptr_array_index (blob->children, i) = child_blob;
|
||||
#if 0
|
||||
/*
|
||||
* We don't need this, and setting it causes circular
|
||||
* links.
|
||||
*/
|
||||
gsf_input_set_container (GSF_INPUT (child_blob),
|
||||
GSF_INFILE (blob));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return blob;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_structured_blob_write :
|
||||
* @blob :
|
||||
* @container :
|
||||
*
|
||||
* Dumps structured blob @blob onto the @container. Will fail if the output is
|
||||
* not an Outfile and blob has multiple streams.
|
||||
*
|
||||
* Returns : TRUE on success.
|
||||
**/
|
||||
gboolean
|
||||
gsf_structured_blob_write (GsfStructuredBlob *blob, GsfOutfile *container)
|
||||
{
|
||||
GsfOutput *output;
|
||||
gboolean has_kids;
|
||||
|
||||
g_return_val_if_fail (GSF_IS_STRUCTURED_BLOB (blob), FALSE);
|
||||
g_return_val_if_fail (GSF_IS_OUTFILE (container), FALSE);
|
||||
|
||||
has_kids = (blob->children != NULL && blob->children->len > 0);
|
||||
|
||||
output = gsf_outfile_new_child (GSF_OUTFILE (container),
|
||||
gsf_input_name (GSF_INPUT (blob)),
|
||||
has_kids);
|
||||
if (has_kids) {
|
||||
GsfStructuredBlob *child_blob;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0 ; i < blob->children->len ; i++) {
|
||||
child_blob = g_ptr_array_index (blob->children, i);
|
||||
if (!gsf_structured_blob_write (child_blob, GSF_OUTFILE (output)))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (blob->data != NULL)
|
||||
gsf_output_write (output, blob->data->size, blob->data->buf);
|
||||
gsf_output_close (output);
|
||||
g_object_unref (G_OBJECT (output));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
45
lib/libgsf-1.12.3/gsf/gsf-structured-blob.h
Normal file
45
lib/libgsf-1.12.3/gsf/gsf-structured-blob.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-structured-blob.h: Utility storage to blob in/out a tree of data
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_STRUCTURED_BLOB_H
|
||||
#define GSF_STRUCTURED_BLOB_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSF_STRUCTURED_BLOB_TYPE (gsf_structured_blob_get_type ())
|
||||
#define GSF_STRUCTURED_BLOB(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSF_STRUCTURED_BLOB_TYPE, GsfStructuredBlob))
|
||||
#define GSF_IS_STRUCTURED_BLOB(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSF_STRUCTURED_BLOB_TYPE))
|
||||
|
||||
typedef struct _GsfStructuredBlob GsfStructuredBlob;
|
||||
|
||||
/* inherits from GsfInfile */
|
||||
GType gsf_structured_blob_get_type (void);
|
||||
|
||||
GsfStructuredBlob *gsf_structured_blob_read (GsfInput *input);
|
||||
gboolean gsf_structured_blob_write (GsfStructuredBlob *blob,
|
||||
GsfOutfile *container);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_STRUCTURED_BLOB_H */
|
||||
99
lib/libgsf-1.12.3/gsf/gsf-timestamp.c
Normal file
99
lib/libgsf-1.12.3/gsf/gsf-timestamp.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-timestamp.c:
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-timestamp.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
static void
|
||||
timestamp_to_string (GValue const *src_value, GValue *dest_value)
|
||||
{
|
||||
char *str = gsf_timestamp_as_string (g_value_get_boxed (src_value));
|
||||
g_value_set_string (dest_value, str);
|
||||
g_free (str);
|
||||
}
|
||||
|
||||
GType
|
||||
gsf_timestamp_get_type (void)
|
||||
{
|
||||
static GType our_type = 0;
|
||||
|
||||
if (our_type == 0) {
|
||||
our_type = g_boxed_type_register_static ("GsfTimestamp",
|
||||
(GBoxedCopyFunc)gsf_timestamp_copy,
|
||||
(GBoxedFreeFunc)gsf_timestamp_free);
|
||||
g_value_register_transform_func (our_type, G_TYPE_STRING,
|
||||
×tamp_to_string);
|
||||
}
|
||||
return our_type;
|
||||
}
|
||||
|
||||
GsfTimestamp *
|
||||
gsf_timestamp_copy (GsfTimestamp const *stamp)
|
||||
{
|
||||
GsfTimestamp *res = g_new0 (GsfTimestamp, 1);
|
||||
res->timet = stamp->timet;
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
gsf_timestamp_free (GsfTimestamp *stamp)
|
||||
{
|
||||
g_free (stamp);
|
||||
}
|
||||
|
||||
int
|
||||
gsf_timestamp_parse (G_GNUC_UNUSED char const *spec,
|
||||
G_GNUC_UNUSED GsfTimestamp *stamp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
gsf_timestamp_as_string (GsfTimestamp const *stamp)
|
||||
{
|
||||
time_t t;
|
||||
g_return_val_if_fail (stamp != NULL, g_strdup ("<invalid>"));
|
||||
|
||||
/* Use an honest time_t for ctime. */
|
||||
t = stamp->timet;
|
||||
/* FIXME FIXME FIXME ctime is not thread safe, use ctime_r if available */
|
||||
return g_strdup (ctime (&t));
|
||||
}
|
||||
|
||||
guint
|
||||
gsf_timestamp_hash (GsfTimestamp const *stamp)
|
||||
{
|
||||
return stamp->timet;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gsf_timestamp_equal (GsfTimestamp const *a, GsfTimestamp const *b)
|
||||
{
|
||||
return a->timet == b->timet;
|
||||
}
|
||||
|
||||
void
|
||||
gsf_value_set_timestamp (GValue *value, GsfTimestamp const *stamp)
|
||||
{
|
||||
g_value_set_boxed (value, stamp);
|
||||
}
|
||||
60
lib/libgsf-1.12.3/gsf/gsf-timestamp.h
Normal file
60
lib/libgsf-1.12.3/gsf/gsf-timestamp.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-timestamp.h: A useful little type for metadata, contains a superset of
|
||||
* all the features it would be nice to have.
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_TIMESTAMP_H
|
||||
#define GSF_TIMESTAMP_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSF_TIMESTAMP_TYPE (gsf_timestamp_get_type ())
|
||||
#define VAL_IS_GSF_TIMESTAMP(v) (G_TYPE_CHECK_VALUE_TYPE((v), GSF_TIMESTAMP_TYPE))
|
||||
|
||||
struct _GsfTimestamp {
|
||||
GDate date; /* In local timezone */
|
||||
glong seconds; /* time of day */
|
||||
GString time_zone; /* possibly blank */
|
||||
|
||||
guint32 timet;
|
||||
};
|
||||
|
||||
GType gsf_timestamp_get_type (void);
|
||||
|
||||
GsfTimestamp *gsf_timestamp_new_now (void);
|
||||
GsfTimestamp *gsf_timestamp_new (GDate const *date, glong seconds,
|
||||
char const *tz);
|
||||
|
||||
GsfTimestamp *gsf_timestamp_copy (GsfTimestamp const *stamp);
|
||||
void gsf_timestamp_free (GsfTimestamp *stamp);
|
||||
int gsf_timestamp_parse (char const *spec, GsfTimestamp *stamp);
|
||||
char *gsf_timestamp_as_string (GsfTimestamp const *stamp);
|
||||
guint gsf_timestamp_hash (GsfTimestamp const *stamp);
|
||||
gboolean gsf_timestamp_equal (GsfTimestamp const *a,
|
||||
GsfTimestamp const *b);
|
||||
|
||||
void gsf_value_set_timestamp (GValue *value, GsfTimestamp const *stamp);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_TIMESTAMP_H */
|
||||
773
lib/libgsf-1.12.3/gsf/gsf-utils.c
Normal file
773
lib/libgsf-1.12.3/gsf/gsf-utils.c
Normal file
@@ -0,0 +1,773 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-utils.c:
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf-utils.h>
|
||||
#include <gsf/gsf-input.h>
|
||||
#include <gobject/gvaluecollector.h>
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef HAVE_GLIB26
|
||||
#include <gsf/glib24_26-compat.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Glib gets this wrong, really. ARM's floating point format is a weird
|
||||
* mixture.
|
||||
*/
|
||||
#define G_ARMFLOAT_ENDIAN 56781234
|
||||
#if defined(__arm__) && !defined(__vfp__) && (G_BYTE_ORDER == G_LITTLE_ENDIAN)
|
||||
#define G_FLOAT_BYTE_ORDER G_ARMFLOAT_ENDIAN
|
||||
#else
|
||||
#define G_FLOAT_BYTE_ORDER G_BYTE_ORDER
|
||||
#endif
|
||||
|
||||
|
||||
static void base64_init (void);
|
||||
|
||||
/**
|
||||
* gsf_init :
|
||||
*
|
||||
* Initializes the GSF library
|
||||
*/
|
||||
void
|
||||
gsf_init (void)
|
||||
{
|
||||
#ifdef ENABLE_NLS
|
||||
bindtextdomain(GETTEXT_PACKAGE, GNOMELOCALEDIR);
|
||||
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
|
||||
#endif
|
||||
|
||||
g_type_init ();
|
||||
base64_init ();
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_shutdown:
|
||||
*
|
||||
* De-intializes the GSF library
|
||||
*/
|
||||
void
|
||||
gsf_shutdown (void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
gsf_init_dynamic (GTypeModule *module)
|
||||
{
|
||||
(void)module;
|
||||
}
|
||||
|
||||
void
|
||||
gsf_shutdown_dynamic (GTypeModule *module)
|
||||
{
|
||||
(void)module;
|
||||
}
|
||||
|
||||
static void
|
||||
gsf_mem_dump_full (guint8 const *ptr, size_t len, gsf_off_t offset)
|
||||
{
|
||||
gsf_off_t i, j, off;
|
||||
|
||||
for (i = 0 ; i < (len+15)/16 ; i++) {
|
||||
g_print ("%8lx | ", (long)(i*16 + offset));
|
||||
for (j = 0;j < 16; j++) {
|
||||
off = j + (i << 4);
|
||||
off<len ? g_print("%2x ", ptr[off]) : g_print("XX ");
|
||||
}
|
||||
g_print ("| ");
|
||||
for (j = 0 ; j < 16 ; j++) {
|
||||
off = j + (i<<4);
|
||||
g_print ("%c", off < len ? (ptr[off] >= '!' && ptr[off] < 127 ? ptr[off] : '.') : '*');
|
||||
}
|
||||
g_print ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_mem_dump :
|
||||
* @ptr: memory area to be dumped.
|
||||
* @len: how many bytes will be dumped.
|
||||
*
|
||||
* Dump @len bytes from the memory location given by @ptr.
|
||||
**/
|
||||
void
|
||||
gsf_mem_dump (guint8 const *ptr, size_t len)
|
||||
{
|
||||
gsf_mem_dump_full (ptr, len, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_input_dump :
|
||||
* @input: a #GsfInput
|
||||
* @dump_as_hex: If TRUE, dump in hexidecmal format
|
||||
*
|
||||
* Dumps @input's contents to STDOUT, optionally in hex format.
|
||||
*/
|
||||
void
|
||||
gsf_input_dump (GsfInput *input, gboolean dump_as_hex)
|
||||
{
|
||||
gsf_off_t offset = 0;
|
||||
size_t size, count;
|
||||
guint8 const *data;
|
||||
|
||||
/* read in small blocks to excercise things */
|
||||
size = gsf_input_size (GSF_INPUT (input));
|
||||
while (size > 0) {
|
||||
count = size;
|
||||
if (count > 0x100)
|
||||
count = 0x100;
|
||||
data = gsf_input_read (GSF_INPUT (input), count, NULL);
|
||||
g_return_if_fail (data != NULL);
|
||||
if (dump_as_hex)
|
||||
gsf_mem_dump_full (data, count, offset);
|
||||
else
|
||||
fwrite (data, 1, count, stdout);
|
||||
size -= count;
|
||||
offset += count;
|
||||
}
|
||||
if (!dump_as_hex)
|
||||
fflush (stdout);
|
||||
}
|
||||
|
||||
guint64
|
||||
gsf_le_get_guint64 (void const *p)
|
||||
{
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
if (sizeof (guint64) == 8) {
|
||||
guint64 li;
|
||||
int i;
|
||||
guint8 *t = (guint8 *)&li;
|
||||
guint8 *p2 = (guint8 *)p;
|
||||
int sd = sizeof (li);
|
||||
|
||||
for (i = 0; i < sd; i++)
|
||||
t[i] = p2[sd - 1 - i];
|
||||
|
||||
return li;
|
||||
} else {
|
||||
g_error ("Big endian machine, but weird size of guint64");
|
||||
}
|
||||
#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
if (sizeof (guint64) == 8) {
|
||||
/*
|
||||
* On i86, we could access directly, but Alphas require
|
||||
* aligned access.
|
||||
*/
|
||||
guint64 data;
|
||||
memcpy (&data, p, sizeof (data));
|
||||
return data;
|
||||
} else {
|
||||
g_error ("Little endian machine, but weird size of guint64");
|
||||
}
|
||||
#else
|
||||
#error "Byte order not recognised -- out of luck"
|
||||
#endif
|
||||
}
|
||||
|
||||
float
|
||||
gsf_le_get_float (void const *p)
|
||||
{
|
||||
#if G_FLOAT_BYTE_ORDER == G_BIG_ENDIAN
|
||||
if (sizeof (float) == 4) {
|
||||
float f;
|
||||
int i;
|
||||
guint8 *t = (guint8 *)&f;
|
||||
guint8 *p2 = (guint8 *)p;
|
||||
int sd = sizeof (f);
|
||||
|
||||
for (i = 0; i < sd; i++)
|
||||
t[i] = p2[sd - 1 - i];
|
||||
|
||||
return f;
|
||||
} else {
|
||||
g_error ("Big endian machine, but weird size of floats");
|
||||
}
|
||||
#elif (G_FLOAT_BYTE_ORDER == G_LITTLE_ENDIAN) || (G_FLOAT_BYTE_ORDER == G_ARMFLOAT_ENDIAN)
|
||||
if (sizeof (float) == 4) {
|
||||
/*
|
||||
* On i86, we could access directly, but Alphas require
|
||||
* aligned access.
|
||||
*/
|
||||
float data;
|
||||
memcpy (&data, p, sizeof (data));
|
||||
return data;
|
||||
} else {
|
||||
g_error ("Little endian machine, but weird size of floats");
|
||||
}
|
||||
#else
|
||||
#error "Floating-point byte order not recognised -- out of luck"
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
gsf_le_set_float (void *p, float d)
|
||||
{
|
||||
#if G_FLOAT_BYTE_ORDER == G_BIG_ENDIAN
|
||||
if (sizeof (float) == 4) {
|
||||
int i;
|
||||
guint8 *t = (guint8 *)&d;
|
||||
guint8 *p2 = (guint8 *)p;
|
||||
int sd = sizeof (d);
|
||||
|
||||
for (i = 0; i < sd; i++)
|
||||
p2[sd - 1 - i] = t[i];
|
||||
} else {
|
||||
g_error ("Big endian machine, but weird size of floats");
|
||||
}
|
||||
#elif (G_FLOAT_BYTE_ORDER == G_LITTLE_ENDIAN) || (G_FLOAT_BYTE_ORDER == G_ARMFLOAT_ENDIAN)
|
||||
if (sizeof (float) == 4) {
|
||||
/*
|
||||
* On i86, we could access directly, but Alphas require
|
||||
* aligned access.
|
||||
*/
|
||||
memcpy (p, &d, sizeof (d));
|
||||
} else {
|
||||
g_error ("Little endian machine, but weird size of floats");
|
||||
}
|
||||
#else
|
||||
#error "Floating-point byte order not recognised -- out of luck"
|
||||
#endif
|
||||
}
|
||||
|
||||
double
|
||||
gsf_le_get_double (void const *p)
|
||||
{
|
||||
#if G_FLOAT_BYTE_ORDER == G_ARMFLOAT_ENDIAN
|
||||
double data;
|
||||
memcpy ((char *)&data + 4, p, 4);
|
||||
memcpy ((char *)&data, (char const *)p + 4, 4);
|
||||
return data;
|
||||
#elif G_FLOAT_BYTE_ORDER == G_BIG_ENDIAN
|
||||
if (sizeof (double) == 8) {
|
||||
double d;
|
||||
int i;
|
||||
guint8 *t = (guint8 *)&d;
|
||||
guint8 *p2 = (guint8 *)p;
|
||||
int sd = sizeof (d);
|
||||
|
||||
for (i = 0; i < sd; i++)
|
||||
t[i] = p2[sd - 1 - i];
|
||||
|
||||
return d;
|
||||
} else {
|
||||
g_error ("Big endian machine, but weird size of doubles");
|
||||
}
|
||||
#elif G_FLOAT_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
if (sizeof (double) == 8) {
|
||||
/*
|
||||
* On i86, we could access directly, but Alphas require
|
||||
* aligned access.
|
||||
*/
|
||||
double data;
|
||||
memcpy (&data, p, sizeof (data));
|
||||
return data;
|
||||
} else {
|
||||
g_error ("Little endian machine, but weird size of doubles");
|
||||
}
|
||||
#else
|
||||
#error "Floating-point byte order not recognised -- out of luck"
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
gsf_le_set_double (void *p, double d)
|
||||
{
|
||||
#if G_FLOAT_BYTE_ORDER == G_ARMFLOAT_ENDIAN
|
||||
memcpy (p, (char const *)&d + 4, 4);
|
||||
memcpy ((char *)p + 4, &d, 4);
|
||||
#elif G_FLOAT_BYTE_ORDER == G_BIG_ENDIAN
|
||||
if (sizeof (double) == 8) {
|
||||
int i;
|
||||
guint8 *t = (guint8 *)&d;
|
||||
guint8 *p2 = (guint8 *)p;
|
||||
int sd = sizeof (d);
|
||||
|
||||
for (i = 0; i < sd; i++)
|
||||
p2[sd - 1 - i] = t[i];
|
||||
} else {
|
||||
g_error ("Big endian machine, but weird size of doubles");
|
||||
}
|
||||
#elif G_FLOAT_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
if (sizeof (double) == 8) {
|
||||
/*
|
||||
* On i86, we could access directly, but Alphas require
|
||||
* aligned access.
|
||||
*/
|
||||
memcpy (p, &d, sizeof (d));
|
||||
} else {
|
||||
g_error ("Little endian machine, but weird size of doubles");
|
||||
}
|
||||
#else
|
||||
#error "Floating-point byte order not recognised -- out of luck"
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_extension_pointer:
|
||||
* @path: A filename or file path.
|
||||
*
|
||||
* Extracts the extension from the end of a filename (the part after the final
|
||||
* '.' in the filename).
|
||||
*
|
||||
* Returns: A pointer to the extension part of the filename, or a
|
||||
* pointer to the end of the string if the filename does not
|
||||
* have an extension.
|
||||
*/
|
||||
char const *
|
||||
gsf_extension_pointer (char const *path)
|
||||
{
|
||||
char const *s, *end;
|
||||
|
||||
g_return_val_if_fail (path != NULL, NULL);
|
||||
|
||||
end = path + strlen (path);
|
||||
for (s = end; s > path; ) {
|
||||
s--;
|
||||
if (G_IS_DIR_SEPARATOR (*s))
|
||||
break;
|
||||
if (*s == '.')
|
||||
return s + 1;
|
||||
}
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_iconv_close : A utility wrapper to safely close an iconv handle
|
||||
* @handle :
|
||||
**/
|
||||
void
|
||||
gsf_iconv_close (GIConv handle)
|
||||
{
|
||||
if (handle != NULL && handle != ((GIConv)-1))
|
||||
g_iconv_close (handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* gsf_filename_to_utf8:
|
||||
* @filename: file name suitable for open(2).
|
||||
* @quoted: if TRUE, the resulting utf8 file name will be quoted
|
||||
* (unless it is invalid).
|
||||
*
|
||||
* A utility wrapper to make sure filenames are valid utf8.
|
||||
* Caller must g_free the result.
|
||||
*
|
||||
* Returns @filename using utf-8 encoding for display
|
||||
**/
|
||||
char *
|
||||
gsf_filename_to_utf8 (char const *filename, gboolean quoted)
|
||||
{
|
||||
char *dname = g_filename_display_name (filename);
|
||||
char *result;
|
||||
|
||||
if (quoted) {
|
||||
result = g_strconcat ("\"", dname, "\"", NULL);
|
||||
g_free (dname);
|
||||
} else
|
||||
result = dname;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/* some code taken from evolution/camel/camel-mime-utils.c */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 Ximian Inc.
|
||||
*
|
||||
* Authors: Michael Zucchi <notzed@ximian.com>
|
||||
* Jeffrey Stedfast <fejj@ximian.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* dont touch this file without my permission - Michael */
|
||||
static guint8 camel_mime_base64_rank[256];
|
||||
static char const *base64_alphabet =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
#define d(x)
|
||||
|
||||
/* Line length for base64 encoding. Must be a multiple of 4. */
|
||||
enum { BASE64_LINE_LEN = 76 };
|
||||
|
||||
static void
|
||||
base64_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
memset(camel_mime_base64_rank, 0xff, sizeof(camel_mime_base64_rank));
|
||||
for (i=0;i<64;i++) {
|
||||
camel_mime_base64_rank[(unsigned int)base64_alphabet[i]] = i;
|
||||
}
|
||||
camel_mime_base64_rank['='] = 0;
|
||||
}
|
||||
|
||||
/* call this when finished encoding everything, to
|
||||
flush off the last little bit */
|
||||
size_t
|
||||
gsf_base64_encode_close (guint8 const *in, size_t inlen,
|
||||
gboolean break_lines, guint8 *out, int *state, unsigned int *save)
|
||||
{
|
||||
int c1, c2;
|
||||
guint8 *outptr = out;
|
||||
|
||||
if (inlen>0)
|
||||
outptr += gsf_base64_encode_step(in, inlen, break_lines, outptr, state, save);
|
||||
|
||||
c1 = ((guint8 *)save)[1];
|
||||
c2 = ((guint8 *)save)[2];
|
||||
|
||||
d(printf("mode = %d\nc1 = %c\nc2 = %c\n",
|
||||
(int)((char *)save)[0],
|
||||
(int)((char *)save)[1],
|
||||
(int)((char *)save)[2]));
|
||||
|
||||
switch (((char *)save)[0]) {
|
||||
case 2:
|
||||
outptr[2] = base64_alphabet[ ( (c2 &0x0f) << 2 ) ];
|
||||
g_assert(outptr[2] != 0);
|
||||
goto skip;
|
||||
case 1:
|
||||
outptr[2] = '=';
|
||||
skip:
|
||||
outptr[0] = base64_alphabet[ c1 >> 2 ];
|
||||
outptr[1] = base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 )];
|
||||
outptr[3] = '=';
|
||||
outptr += 4;
|
||||
++*state;
|
||||
break;
|
||||
}
|
||||
if (break_lines && *state > 0)
|
||||
*outptr++ = '\n';
|
||||
|
||||
*save = 0;
|
||||
*state = 0;
|
||||
|
||||
return outptr-out;
|
||||
}
|
||||
|
||||
/*
|
||||
performs an 'encode step', only encodes blocks of 3 characters to the
|
||||
output at a time, saves left-over state in state and save (initialise to
|
||||
0 on first invocation).
|
||||
*/
|
||||
size_t
|
||||
gsf_base64_encode_step (guint8 const *in, size_t len,
|
||||
gboolean break_lines, guint8 *out, int *state, unsigned int *save)
|
||||
{
|
||||
register guint8 const *inptr;
|
||||
register guint8 *outptr;
|
||||
|
||||
if (len<=0)
|
||||
return 0;
|
||||
|
||||
inptr = in;
|
||||
outptr = out;
|
||||
|
||||
d(printf("we have %d chars, and %d saved chars\n", len, ((char *)save)[0]));
|
||||
|
||||
if (len + ((char *)save)[0] > 2) {
|
||||
guint8 const *inend = in+len-2;
|
||||
register int c1, c2, c3;
|
||||
register int already;
|
||||
|
||||
already = *state;
|
||||
|
||||
switch (((char *)save)[0]) {
|
||||
case 1: c1 = ((guint8 *)save)[1]; goto skip1;
|
||||
case 2: c1 = ((guint8 *)save)[1];
|
||||
c2 = ((guint8 *)save)[2]; goto skip2;
|
||||
}
|
||||
|
||||
/* yes, we jump into the loop, no i'm not going to change it, it's beautiful! */
|
||||
while (inptr < inend) {
|
||||
c1 = *inptr++;
|
||||
skip1:
|
||||
c2 = *inptr++;
|
||||
skip2:
|
||||
c3 = *inptr++;
|
||||
*outptr++ = base64_alphabet[ c1 >> 2 ];
|
||||
*outptr++ = base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 ) ];
|
||||
*outptr++ = base64_alphabet[ ( (c2 &0x0f) << 2 ) | (c3 >> 6) ];
|
||||
*outptr++ = base64_alphabet[ c3 & 0x3f ];
|
||||
/* this is a bit ugly ... */
|
||||
if (break_lines && (++already) * 4 >= BASE64_LINE_LEN) {
|
||||
*outptr++='\n';
|
||||
already = 0;
|
||||
}
|
||||
}
|
||||
|
||||
((char *)save)[0] = 0;
|
||||
len = 2-(inptr-inend);
|
||||
*state = already;
|
||||
}
|
||||
|
||||
d(printf("state = %d, len = %d\n",
|
||||
(int)((char *)save)[0],
|
||||
len));
|
||||
|
||||
if (len>0) {
|
||||
register char *saveout;
|
||||
|
||||
/* points to the slot for the next char to save */
|
||||
saveout = & (((char *)save)[1]) + ((char *)save)[0];
|
||||
|
||||
/* len can only be 0 1 or 2 */
|
||||
switch(len) {
|
||||
case 2: *saveout++ = *inptr++;
|
||||
case 1: *saveout++ = *inptr++;
|
||||
}
|
||||
((char *)save)[0]+=len;
|
||||
}
|
||||
|
||||
d(printf("mode = %d\nc1 = %c\nc2 = %c\n",
|
||||
(int)((char *)save)[0],
|
||||
(int)((char *)save)[1],
|
||||
(int)((char *)save)[2]));
|
||||
|
||||
return outptr-out;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gsf_base64_decode_step: decode a chunk of base64 encoded data
|
||||
* @in: input stream
|
||||
* @len: max length of data to decode
|
||||
* @out: output stream
|
||||
* @state: holds the number of bits that are stored in @save
|
||||
* @save: leftover bits that have not yet been decoded
|
||||
*
|
||||
* Decodes a chunk of base64 encoded data
|
||||
*
|
||||
* Returns the number of bytes converted
|
||||
**/
|
||||
size_t
|
||||
gsf_base64_decode_step (guint8 const *in, size_t len, guint8 *out,
|
||||
int *state, guint *save)
|
||||
{
|
||||
register guint8 const *inptr;
|
||||
register guint8 *outptr, c;
|
||||
register unsigned int v;
|
||||
guint8 const *inend;
|
||||
int i;
|
||||
|
||||
inend = in+len;
|
||||
outptr = out;
|
||||
|
||||
/* convert 4 base64 bytes to 3 normal bytes */
|
||||
v=*save;
|
||||
i=*state;
|
||||
inptr = in;
|
||||
while (inptr<inend) {
|
||||
c = camel_mime_base64_rank[*inptr++];
|
||||
if (c != 0xff) {
|
||||
v = (v<<6) | c;
|
||||
i++;
|
||||
if (i==4) {
|
||||
*outptr++ = v>>16;
|
||||
*outptr++ = v>>8;
|
||||
*outptr++ = v;
|
||||
i=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*save = v;
|
||||
*state = i;
|
||||
|
||||
/* quick scan back for '=' on the end somewhere */
|
||||
/* fortunately we can drop 1 output char for each trailing = (upto 2) */
|
||||
i=2;
|
||||
while (inptr>in && i) {
|
||||
inptr--;
|
||||
if (camel_mime_base64_rank[*inptr] != 0xff) {
|
||||
if (*inptr == '=' && outptr>out)
|
||||
outptr--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
/* if i!= 0 then there is a truncation error! */
|
||||
return outptr-out;
|
||||
}
|
||||
|
||||
guint8 *
|
||||
gsf_base64_encode_simple (guint8 const *data, size_t len)
|
||||
{
|
||||
guint8 *out;
|
||||
int state = 0, outlen;
|
||||
unsigned int save = 0;
|
||||
gboolean break_lines = TRUE;
|
||||
|
||||
outlen = len * 4 / 3 + 5;
|
||||
if (break_lines)
|
||||
outlen += outlen / BASE64_LINE_LEN + 1;
|
||||
out = g_new (guint8, outlen);
|
||||
outlen = gsf_base64_encode_close (data, len, break_lines,
|
||||
out, &state, &save);
|
||||
out [outlen] = '\0';
|
||||
return out;
|
||||
}
|
||||
|
||||
size_t
|
||||
gsf_base64_decode_simple (guint8 *data, size_t len)
|
||||
{
|
||||
int state = 0;
|
||||
unsigned int save = 0;
|
||||
return gsf_base64_decode_step (data, len, data, &state, &save);
|
||||
}
|
||||
|
||||
|
||||
/* Largely a copy of g_object_new_valist. */
|
||||
/**
|
||||
* gsf_property_settings_collect_valist: collect property setting from a va_list.
|
||||
* @object_type: the GType for which the properties are being set.
|
||||
* @p_n_params: a pointer to the number of properties collected. (Used for
|
||||
* both input and output.)
|
||||
* @p_params: a pointer to the GParameter array that holds the properties.
|
||||
* (Used for both input and output. This may point to a NULL pointer if
|
||||
* there are no properties collected yet.)
|
||||
* @first_property_name: the name of the first property being set, or NULL.
|
||||
* @var_args: a va_list holding the remainder of the property names and
|
||||
* values, terminated by a NULL.
|
||||
*
|
||||
* This function builds a GParameter array suitable for g_object_newv.
|
||||
**/
|
||||
void
|
||||
gsf_property_settings_collect_valist (GType object_type,
|
||||
GParameter **p_params,
|
||||
size_t *p_n_params,
|
||||
const gchar *first_property_name,
|
||||
va_list var_args)
|
||||
{
|
||||
GObjectClass *class;
|
||||
GParameter *params = *p_params;
|
||||
const gchar *name;
|
||||
size_t n_params = *p_n_params;
|
||||
size_t n_alloced_params = n_params; /* We might have more. */
|
||||
|
||||
g_return_if_fail (G_TYPE_IS_OBJECT (object_type));
|
||||
|
||||
class = g_type_class_ref (object_type);
|
||||
|
||||
name = first_property_name;
|
||||
while (name)
|
||||
{
|
||||
gchar *error = NULL;
|
||||
GParamSpec *pspec = g_object_class_find_property (class, name);
|
||||
if (!pspec)
|
||||
{
|
||||
g_warning ("%s: object class `%s' has no property named `%s'",
|
||||
G_STRFUNC,
|
||||
g_type_name (object_type),
|
||||
name);
|
||||
break;
|
||||
}
|
||||
|
||||
if (n_params >= n_alloced_params)
|
||||
{
|
||||
n_alloced_params += 16;
|
||||
params = g_renew (GParameter, params, n_alloced_params);
|
||||
}
|
||||
params[n_params].name = name;
|
||||
params[n_params].value.g_type = 0;
|
||||
g_value_init (¶ms[n_params].value, G_PARAM_SPEC_VALUE_TYPE (pspec));
|
||||
G_VALUE_COLLECT (¶ms[n_params].value, var_args, 0, &error);
|
||||
if (error)
|
||||
{
|
||||
g_warning ("%s: %s", G_STRFUNC, error);
|
||||
g_free (error);
|
||||
g_value_unset (¶ms[n_params].value);
|
||||
break;
|
||||
}
|
||||
n_params++;
|
||||
name = va_arg (var_args, gchar*);
|
||||
}
|
||||
|
||||
g_type_class_unref (class);
|
||||
|
||||
*p_params = params;
|
||||
*p_n_params = n_params;
|
||||
}
|
||||
|
||||
/* This is a vararg version of gsf_property_settings_collect_valist. */
|
||||
void
|
||||
gsf_property_settings_collect (GType object_type,
|
||||
GParameter **p_params,
|
||||
size_t *p_n_params,
|
||||
const gchar *first_property_name,
|
||||
...)
|
||||
{
|
||||
va_list var_args;
|
||||
va_start (var_args, first_property_name);
|
||||
gsf_property_settings_collect_valist (object_type, p_params, p_n_params, first_property_name, var_args);
|
||||
va_end (var_args);
|
||||
}
|
||||
|
||||
void
|
||||
gsf_property_settings_free (GParameter *params,
|
||||
size_t n_params)
|
||||
{
|
||||
while (n_params--)
|
||||
g_value_unset (¶ms[n_params].value);
|
||||
g_free (params);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Errors */
|
||||
|
||||
/**
|
||||
* gsf_error_quark:
|
||||
*
|
||||
* Returns the #GQuark used to identify libgsf errors in #GError structures.
|
||||
* Specific error codes come from the #GsfError enumeration.
|
||||
*
|
||||
* Return value: A #GQuark.
|
||||
**/
|
||||
GQuark
|
||||
gsf_error_quark (void)
|
||||
{
|
||||
static GQuark quark;
|
||||
|
||||
if (quark == 0)
|
||||
quark = g_quark_from_static_string ("gsf-error-quark");
|
||||
|
||||
return quark;
|
||||
}
|
||||
142
lib/libgsf-1.12.3/gsf/gsf-utils.h
Normal file
142
lib/libgsf-1.12.3/gsf/gsf-utils.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-utils.h:
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_UTILS_H
|
||||
#define GSF_UTILS_H
|
||||
|
||||
#include <gsf/gsf.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* Do this the ugly way so that we don't have to worry about alignment */
|
||||
#define GSF_LE_GET_GUINT8(p) (*(guint8 const *)(p))
|
||||
#define GSF_LE_GET_GUINT16(p) \
|
||||
(guint16)((((guint8 const *)(p))[0] << 0) | \
|
||||
(((guint8 const *)(p))[1] << 8))
|
||||
#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))
|
||||
#define GSF_LE_GET_GUINT64(p) (gsf_le_get_guint64 (p))
|
||||
#define GSF_LE_GET_GINT8(p) ((gint8)GSF_LE_GET_GUINT8(p))
|
||||
#define GSF_LE_GET_GINT16(p) ((gint16)GSF_LE_GET_GUINT16(p))
|
||||
#define GSF_LE_GET_GINT32(p) ((gint32)GSF_LE_GET_GUINT32(p))
|
||||
#define GSF_LE_GET_GINT64(p) ((gint64)GSF_LE_GET_GUINT64(p))
|
||||
#define GSF_LE_GET_FLOAT(p) (gsf_le_get_float (p))
|
||||
#define GSF_LE_GET_DOUBLE(p) (gsf_le_get_double (p))
|
||||
guint64 gsf_le_get_guint64 (void const *p);
|
||||
float gsf_le_get_float (void const *p);
|
||||
double gsf_le_get_double (void const *p);
|
||||
|
||||
#define GSF_LE_SET_GUINT8(p, dat) \
|
||||
(*((guint8 *)(p)) = ((dat) & 0xff))
|
||||
#define GSF_LE_SET_GUINT16(p, dat) \
|
||||
((*((guint8 *)(p) + 0) = ((dat) & 0xff)),\
|
||||
(*((guint8 *)(p) + 1) = ((dat) >> 8) & 0xff))
|
||||
#define GSF_LE_SET_GUINT32(p, dat) \
|
||||
((*((guint8 *)(p) + 0) = (guchar) ((dat)) & 0xff), \
|
||||
(*((guint8 *)(p) + 1) = (guchar) ((dat) >> 8) & 0xff), \
|
||||
(*((guint8 *)(p) + 2) = (guchar) ((dat) >> 16) & 0xff), \
|
||||
(*((guint8 *)(p) + 3) = (guchar) ((dat) >> 24) & 0xff))
|
||||
#define GSF_LE_SET_GUINT64(p, dat) \
|
||||
((*((guint8 *)(p) + 0) = (guchar) ((dat)) & 0xff), \
|
||||
(*((guint8 *)(p) + 1) = (guchar) ((dat) >> 8) & 0xff), \
|
||||
(*((guint8 *)(p) + 2) = (guchar) ((dat) >> 16) & 0xff), \
|
||||
(*((guint8 *)(p) + 3) = (guchar) ((dat) >> 24) & 0xff), \
|
||||
(*((guint8 *)(p) + 4) = (guchar) ((dat) >> 32) & 0xff), \
|
||||
(*((guint8 *)(p) + 5) = (guchar) ((dat) >> 40) & 0xff), \
|
||||
(*((guint8 *)(p) + 6) = (guchar) ((dat) >> 48) & 0xff), \
|
||||
(*((guint8 *)(p) + 7) = (guchar) ((dat) >> 56) & 0xff))
|
||||
#define GSF_LE_SET_GINT8(p,dat) GSF_LE_SET_GUINT8((p),(dat))
|
||||
#define GSF_LE_SET_GINT16(p,dat) GSF_LE_SET_GUINT16((p),(dat))
|
||||
#define GSF_LE_SET_GINT32(p,dat) GSF_LE_SET_GUINT32((p),(dat))
|
||||
#define GSF_LE_SET_GINT64(p,dat) GSF_LE_SET_GUINT64((p),(dat))
|
||||
#define GSF_LE_SET_FLOAT(p,dat) gsf_le_set_float((p),(dat))
|
||||
#define GSF_LE_SET_DOUBLE(p,dat) gsf_le_set_double((p),(dat))
|
||||
void gsf_le_set_float (void *p, float f);
|
||||
void gsf_le_set_double (void *p, double d);
|
||||
|
||||
void gsf_init (void);
|
||||
void gsf_shutdown (void);
|
||||
void gsf_init_dynamic (GTypeModule *module);
|
||||
void gsf_shutdown_dynamic (GTypeModule *module);
|
||||
|
||||
/* Debugging utilities */
|
||||
void gsf_mem_dump (guint8 const *ptr, size_t len);
|
||||
void gsf_input_dump (GsfInput *input, gboolean dump_as_hex);
|
||||
|
||||
/* base64 encoding utilities */
|
||||
guint8 *gsf_base64_encode_simple (guint8 const *data, size_t len);
|
||||
size_t gsf_base64_encode_close (guint8 const *in, size_t inlen,
|
||||
gboolean break_lines, guint8 *out,
|
||||
int *state, guint *save);
|
||||
size_t gsf_base64_encode_step (guint8 const *in, size_t len,
|
||||
gboolean break_lines, guint8 *out,
|
||||
int *state, guint *save);
|
||||
|
||||
size_t gsf_base64_decode_simple (guint8 *data, size_t len);
|
||||
size_t gsf_base64_decode_step (guint8 const *in, size_t len,
|
||||
guint8 *out, int *state, guint *save);
|
||||
|
||||
|
||||
/* For putting filenames into error messages. */
|
||||
char *gsf_filename_to_utf8 (char const *filename, gboolean quoted);
|
||||
|
||||
/* Some version checking */
|
||||
extern int libgsf_major_version;
|
||||
extern int libgsf_minor_version;
|
||||
extern int libgsf_micro_version;
|
||||
|
||||
char const *gsf_extension_pointer (char const * path);
|
||||
void gsf_iconv_close (GIConv handle);
|
||||
|
||||
void gsf_property_settings_collect_valist (GType object_type,
|
||||
GParameter **p_params,
|
||||
size_t *p_n_params,
|
||||
const gchar *first_property_name,
|
||||
va_list var_args);
|
||||
void gsf_property_settings_collect (GType object_type,
|
||||
GParameter **p_params,
|
||||
size_t *p_n_params,
|
||||
const gchar *first_property_name,
|
||||
...);
|
||||
void gsf_property_settings_free (GParameter *params,
|
||||
size_t n_params);
|
||||
|
||||
|
||||
|
||||
/* Errors */
|
||||
|
||||
#define GSF_ERROR (gsf_error_quark ())
|
||||
|
||||
typedef enum {
|
||||
GSF_ERROR_OUT_OF_MEMORY,
|
||||
GSF_ERROR_INVALID_DATA
|
||||
} GsfError;
|
||||
|
||||
GQuark gsf_error_quark (void);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_UTILS_H */
|
||||
117
lib/libgsf-1.12.3/gsf/gsf-zip-impl.h
Normal file
117
lib/libgsf-1.12.3/gsf/gsf-zip-impl.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-zip-impl.h:
|
||||
*
|
||||
* Copyright (C) 2002-2004 Tambet Ingo (tambet@ximian.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_ZIP_IMPL_H
|
||||
#define GSF_ZIP_IMPL_H
|
||||
|
||||
#include <gsf/gsf-outfile-zip.h> /* for GsfZipCompressionMethod */
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define ZIP_HEADER_SIZE 30
|
||||
#define ZIP_HEADER_VERSION 4
|
||||
#define ZIP_HEADER_OS 5
|
||||
#define ZIP_HEADER_FLAGS 6
|
||||
#define ZIP_HEADER_COMP_METHOD 8
|
||||
#define ZIP_HEADER_TIME 10
|
||||
#define ZIP_HEADER_CRC 14
|
||||
#define ZIP_HEADER_COMP_SIZE 18
|
||||
#define ZIP_HEADER_UNCOMP_SIZE 22
|
||||
#define ZIP_HEADER_NAME_LEN 26
|
||||
#define ZIP_HEADER_EXTRA_LEN 28
|
||||
|
||||
#define ZIP_TRAILER_SIZE 22
|
||||
#define ZIP_TRAILER_DISK 4
|
||||
#define ZIP_TRAILER_DIR_DISK 6
|
||||
#define ZIP_TRAILER_ENTRIES 8
|
||||
#define ZIP_TRAILER_TOTAL_ENTRIES 10
|
||||
#define ZIP_TRAILER_DIR_SIZE 12
|
||||
#define ZIP_TRAILER_DIR_POS 16
|
||||
#define ZIP_TRAILER_COMMENT_SIZE 20
|
||||
|
||||
#define ZIP_DIRENT_SIZE 46
|
||||
#define ZIP_DIRENT_ENCODER 4
|
||||
#define ZIP_DIRENT_EXTRACT 6
|
||||
#define ZIP_DIRENT_FLAGS 8
|
||||
#define ZIP_DIRENT_COMPR_METHOD 10
|
||||
#define ZIP_DIRENT_DOSTIME 12
|
||||
#define ZIP_DIRENT_CRC32 16
|
||||
#define ZIP_DIRENT_CSIZE 20
|
||||
#define ZIP_DIRENT_USIZE 24
|
||||
#define ZIP_DIRENT_NAME_SIZE 28
|
||||
#define ZIP_DIRENT_EXTRAS_SIZE 30
|
||||
#define ZIP_DIRENT_COMMENT_SIZE 32
|
||||
#define ZIP_DIRENT_DISKSTART 34
|
||||
#define ZIP_DIRENT_FILE_TYPE 36
|
||||
#define ZIP_DIRENT_FILE_MODE 38
|
||||
#define ZIP_DIRENT_OFFSET 42
|
||||
|
||||
#define ZIP_FILE_HEADER_SIZE 30
|
||||
#define ZIP_FILE_HEADER_EXTRACT 4
|
||||
#define ZIP_FILE_HEADER_FLAGS 6
|
||||
#define ZIP_FILE_HEADER_COMPR_METHOD 8
|
||||
#define ZIP_FILE_HEADER_DOSTIME 10
|
||||
#define ZIP_FILE_HEADER_CRC32 14
|
||||
#define ZIP_FILE_HEADER_CSIZE 18
|
||||
#define ZIP_FILE_HEADER_USIZE 22
|
||||
#define ZIP_FILE_HEADER_NAME_SIZE 26
|
||||
#define ZIP_FILE_HEADER_EXTRAS_SIZE 28
|
||||
|
||||
#define ZIP_NAME_SEPARATOR '/'
|
||||
|
||||
#define ZIP_BLOCK_SIZE 32768
|
||||
#define ZIP_BUF_SIZE 512
|
||||
|
||||
|
||||
/* z_flags */
|
||||
#define ZZIP_IS_ENCRYPTED(p) ((*(unsigned char*)p)&1)
|
||||
#define ZZIP_IS_COMPRLEVEL(p) (((*(unsigned char*)p)>>1)&3)
|
||||
#define ZZIP_IS_STREAMED(p) (((*(unsigned char*)p)>>3)&1)
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
GsfZipCompressionMethod compr_method;
|
||||
guint32 crc32;
|
||||
size_t csize;
|
||||
size_t usize;
|
||||
gsf_off_t offset;
|
||||
gsf_off_t data_offset;
|
||||
guint32 dostime;
|
||||
} GsfZipDirent;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
gboolean is_directory;
|
||||
GsfZipDirent *dirent;
|
||||
GSList *children, *last_child;
|
||||
} GsfZipVDir;
|
||||
|
||||
GsfZipDirent *gsf_zip_dirent_new (void);
|
||||
void gsf_zip_dirent_free (GsfZipDirent *dirent);
|
||||
|
||||
GsfZipVDir *gsf_vdir_new (char const *name, gboolean is_directory,
|
||||
GsfZipDirent *dirent);
|
||||
void gsf_vdir_free (GsfZipVDir *vdir, gboolean free_dirent);
|
||||
void gsf_vdir_add_child (GsfZipVDir *vdir, GsfZipVDir *child);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_ZIP_IMPL_H */
|
||||
85
lib/libgsf-1.12.3/gsf/gsf-zip-utils.c
Normal file
85
lib/libgsf-1.12.3/gsf/gsf-zip-utils.c
Normal file
@@ -0,0 +1,85 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf-zip-utils.c: tools for zip archive output.
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jon K Hellan (hellan@acm.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Outc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include <gsf-config.h>
|
||||
#include <gsf/gsf.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include "gsf-zip-impl.h"
|
||||
|
||||
/* Doesn't do much, but include for symmetry */
|
||||
GsfZipDirent*
|
||||
gsf_zip_dirent_new (void)
|
||||
{
|
||||
return g_new0 (GsfZipDirent, 1);
|
||||
}
|
||||
|
||||
void
|
||||
gsf_zip_dirent_free (GsfZipDirent *dirent)
|
||||
{
|
||||
g_return_if_fail (dirent != NULL);
|
||||
|
||||
g_free (dirent->name);
|
||||
dirent->name = NULL;
|
||||
|
||||
g_free (dirent);
|
||||
}
|
||||
|
||||
GsfZipVDir *
|
||||
gsf_vdir_new (char const *name, gboolean is_directory, GsfZipDirent *dirent)
|
||||
{
|
||||
GsfZipVDir *vdir = g_new (GsfZipVDir, 1);
|
||||
|
||||
vdir->name = g_strdup (name);
|
||||
vdir->is_directory = is_directory;
|
||||
vdir->dirent = dirent;
|
||||
vdir->children = NULL;
|
||||
return vdir;
|
||||
}
|
||||
|
||||
void
|
||||
gsf_vdir_free (GsfZipVDir *vdir, gboolean free_dirent)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
if (!vdir)
|
||||
return;
|
||||
|
||||
for (l = vdir->children; l; l = l->next)
|
||||
gsf_vdir_free ((GsfZipVDir *)l->data, free_dirent);
|
||||
|
||||
g_slist_free (vdir->children);
|
||||
g_free (vdir->name);
|
||||
if (free_dirent && vdir->dirent)
|
||||
gsf_zip_dirent_free (vdir->dirent);
|
||||
g_free (vdir);
|
||||
}
|
||||
|
||||
void
|
||||
gsf_vdir_add_child (GsfZipVDir *vdir, GsfZipVDir *child)
|
||||
{
|
||||
GSList *tail = g_slist_append (NULL, child);
|
||||
if (vdir->children)
|
||||
vdir->last_child->next = tail;
|
||||
else
|
||||
vdir->children = tail;
|
||||
vdir->last_child = tail;
|
||||
}
|
||||
48
lib/libgsf-1.12.3/gsf/gsf.h
Normal file
48
lib/libgsf-1.12.3/gsf/gsf.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* gsf.h:
|
||||
*
|
||||
* Copyright (C) 2002-2004 Jody Goldberg (jody@gnome.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
* USA
|
||||
*/
|
||||
|
||||
#ifndef GSF_H
|
||||
#define GSF_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GsfInput GsfInput;
|
||||
typedef struct _GsfInfile GsfInfile;
|
||||
|
||||
typedef struct _GsfOutput GsfOutput;
|
||||
typedef struct _GsfOutfile GsfOutfile;
|
||||
|
||||
typedef struct _GsfDocProp GsfDocProp;
|
||||
typedef struct _GsfDocMetaData GsfDocMetaData;
|
||||
typedef struct _GsfTimestamp GsfTimestamp;
|
||||
|
||||
/* FIXME:
|
||||
* gsf_off_t is really supposed to be the widest type off_t can be configured
|
||||
* to on the platform
|
||||
*/
|
||||
typedef gint64 gsf_off_t;
|
||||
#define GSF_OFF_T_FORMAT G_GINT64_FORMAT
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GSF_H */
|
||||
3
lib/libgsf-1.12.3/gsf/version.c.in
Normal file
3
lib/libgsf-1.12.3/gsf/version.c.in
Normal file
@@ -0,0 +1,3 @@
|
||||
int libgsf_major_version = @LIBGSF_MAJOR_VERSION@; /* The ABI version */
|
||||
int libgsf_minor_version = @LIBGSF_MINOR_VERSION@; /* The API version */
|
||||
int libgsf_micro_version = @LIBGSF_MICRO_VERSION@; /* bug fixes */
|
||||
Reference in New Issue
Block a user