Logo Search packages:      
Sourcecode: deb-gview version File versions  Download package

dvarchive.c

/********************************************************************
 *            dvarchive.c
 *
 *  Tue Aug  1 00:50:52 2006
 *  Copyright  2006  Neil Williams
 *  linux@codehelp.co.uk
 * Copyright (C) 1994,1995 Ian Jackson <ian@chiark.greenend.org.uk>
 *******************************************************************/
/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <gtk/gtk.h>
#include <ar.h>
#include <archive.h>
#include <archive_entry.h>
#include <zlib.h>
#include "dvpreview.h"
#include "callbacks.h"
#include "support.h"
#include "dvarchive.h"

#define BLOCKSIZE 10240
#define MAXGZ 1024*1024*sizeof(gint)

typedef enum
{
      DV_AR_FAIL = -1,
      DV_OK,
      DV_ERR_NO_FILE,
      DV_ERR_FILE_READ,
      DV_ERR_VERSION,
      DV_ERR_CORRUPT_FILE,
      DV_ERR_NOT_DPKG,
      DV_ERR_COMPRESS,
} DVError;

typedef struct
{
      gint64 size;
      gpointer content;
      gboolean compressed;
      gpointer gzbuffer;
      GtkWidget *parent;
      const gchar * filewithin;
      gboolean image; /*unused so far */
}DVFileData;

struct DV_s
{
      const gchar *filename;
      gpointer readbuffer;
      gchar *pkg_name;
      gchar *author_name;
      gchar *copyright;
      gint64 expand_size;
      GHashTable *control_files;
      GHashTable *data_files;
      struct archive *control_tar;
      struct archive *data_tar;
      struct ar_hdr *current;
      gulong skip;
      FILE *pkg;
      GtkWidget *parent;
      DVError error;
      gboolean store_set;
      GList * subwindows;
      const gchar * ar_message; /* error string from archive/ar_hdr */
      gchar * selected_file;
};

enum compression_type
{ CAT, GZ, BZ2 };

DVContents*
dv_create (void)
{
      DVContents *deb;

      deb = g_new0 (DVContents, 1);
      deb->control_files = 
            g_hash_table_new (g_str_hash, g_str_equal);
      deb->data_files = 
            g_hash_table_new (g_str_hash, g_str_equal);
      deb->subwindows = NULL;
      return deb;
}

void
dv_archive_clear (DVContents *deb)
{
      g_return_if_fail (deb); 
      if (deb->control_files)
      {
            g_hash_table_destroy (deb->control_files);
            deb->control_files = 
                  g_hash_table_new (g_str_hash, g_str_equal);
      }
      if (deb->data_files)
      {
            g_hash_table_destroy (deb->data_files);
            deb->data_files = 
                  g_hash_table_new (g_str_hash, g_str_equal);
      }
      if (deb->copyright)
            g_free (deb->copyright);
}

void
dv_archive_free (DVContents *deb)
{
      if (!deb)
            return;
      if (deb->control_files)
            g_hash_table_destroy (deb->control_files);
      if (deb->data_files)
            g_hash_table_destroy (deb->data_files);
      if (deb->copyright)
            g_free (deb->copyright);
      g_free (deb);
      preview_shutdown ();
      deb = NULL;
}

GtkWidget *
dv_get_parent (DVContents *deb)
{
      g_return_val_if_fail (deb, NULL);
      return deb->parent;
}

void
set_dv_parent (GtkWidget * widget)
{
      DVContents *deb;

      g_return_if_fail (widget);
      deb = (DVContents*) lookup_widget (widget, DVCONTENTS);
      g_return_if_fail (deb);
      deb->parent = widget;
}

const gchar *
dv_get_selected_file (DVContents * deb)
{
      return deb->selected_file;
}

static void
dv_show_error (DVError dve, GtkWidget * widget)
{
      GtkDialog *dialog;
      GtkWidget *parent;
      gboolean fatal;
      gchar *fmt;
      DVContents *deb;

      g_return_if_fail (widget);
      fatal = FALSE;
      fmt = NULL;
      deb = (DVContents*) lookup_widget (widget, DVCONTENTS);
      parent = (!widget) ? deb->parent : widget;
      switch (dve)
      {
            case DV_OK:
                  return;
            case DV_ERR_NO_FILE:
            {
                  fmt = _("Unable to locate package file, "
                        "the file may be empty.");
                  break;
            }
            case DV_AR_FAIL :
            case DV_ERR_FILE_READ:
            {
                  fmt = _("Failed to read package file.");
                  break;
            }
            case DV_ERR_VERSION:
            {
                  fmt = _("Unsupported archive version.");
                  break;
            }
            case DV_ERR_CORRUPT_FILE :
            {
                  fmt = _("Possible corrupted file.");
                  break;
            }
            case DV_ERR_NOT_DPKG :
            {
                  fmt = _("Not a debian binary archive.");
                  break;
            }
            case DV_ERR_COMPRESS :
            {
                  fmt = _("Unable to decompress file within package.");
                  break;
            }
      }
      if (deb->ar_message)
            fmt = g_strconcat (fmt, "\n", deb->ar_message, NULL);
      dialog = GTK_DIALOG (gtk_message_dialog_new (GTK_WINDOW(parent),
                  GTK_DIALOG_DESTROY_WITH_PARENT,
                  GTK_MESSAGE_ERROR,
                  GTK_BUTTONS_CLOSE, _("Error loading file '%s'. %s"),
                  deb->filename, fmt));
      deb->ar_message = NULL;
      gtk_dialog_run (dialog);
      gtk_widget_destroy (GTK_WIDGET (dialog));
      if (fatal)
      {
            dv_archive_free (deb);
            gtk_main_quit ();
      }
}

void
set_deb_file (const gchar * filename, DVContents *deb)
{
      g_return_if_fail (deb);
      if (!filename)
      {
            dv_show_error (DV_ERR_NO_FILE, deb->parent);
            return;
      }
      deb->filename = filename;
}

static gint
dv_archive_open (struct archive *a, gpointer client_data)
{     
      DVContents *d = (DVContents*)client_data;

      g_return_val_if_fail (d, ARCHIVE_FATAL);
      g_return_val_if_fail (d->readbuffer == NULL, ARCHIVE_FATAL);
      /* deb->pkg already open */
      {
            gchar *size;
            d->skip = 0;
            size = g_strndup (d->current->ar_size, 10);
            d->skip = g_ascii_strtod (size, NULL);
            g_free (size);
            d->readbuffer = malloc (d->skip);
      }
      if( d->readbuffer == NULL ) {
            archive_set_error(a, ENOMEM, _("Out of memory."));
            d->ar_message = archive_error_string (a);
            return ARCHIVE_FATAL;
      }
      return 0;
}
struct read_memory_data {
        gpointer buffer;
        size_t   size;
};

static ssize_t
dv_archive_read (struct archive *a, gpointer client_data,
      gconstpointer *buffer)
{
      ssize_t bytesread;
      DVContents *d = (DVContents*)client_data;

      g_return_val_if_fail (d, DV_AR_FAIL);
      *buffer = d->readbuffer;
      g_return_val_if_fail (d->readbuffer != NULL, DV_AR_FAIL);
      if (d->skip == 0)
            return 0;
      bytesread = fread (d->readbuffer, 1, d->skip, d->pkg);
      if (bytesread < 0)
      {
            archive_set_error (a, errno, 
                  _("Error reading from file: %m"));
            d->ar_message = archive_error_string (a);
            dv_show_error (DV_ERR_FILE_READ, d->parent);
            return DV_AR_FAIL;
      }
      if (bytesread == 0)
      {
            archive_set_error (a, EIO, 
                  _("Unexpected end of file."));
            d->ar_message = archive_error_string (a);
            dv_show_error (DV_ERR_FILE_READ, d->parent);
            return DV_AR_FAIL;
      }
      d->skip -= bytesread;
      return bytesread;
}

static gint
dv_archive_close (struct archive *r __attribute__ ((unused)),
                          gpointer client_data)
{
      DVContents *d = (DVContents*)client_data;

      g_free(d->readbuffer);
      d->readbuffer = NULL;
      return ARCHIVE_OK;
}

/* from dpkg extract.c */
static gulong
parseheaderlength (const gchar *inh, size_t len)
{
      gchar lintbuf[15];
      gulong r;
      gchar *endp;

      if (memchr (inh, 0, len))
            return 0;
      g_assert (sizeof (lintbuf) > len);
      memcpy (lintbuf, inh, len);
      lintbuf[len] = ' ';
      *strchr (lintbuf, ' ') = 0;
      r = strtoul (lintbuf, &endp, 10);
      if (*endp)
            return 0;
      return r;
}

void
prepare_contents (const gchar * filename, DVContents * deb)
{
      gint memberlen, error_num;
      gchar *infobuf;
      struct ar_hdr debian_binary;
      struct ar_hdr controlgz;
      struct ar_hdr datagz;
      gchar versionbuf[40];

      g_return_if_fail (deb);
      deb->pkg = fopen (filename, "r");
      if (!deb->pkg)
      {
            dv_show_error (DV_ERR_FILE_READ, deb->parent);
            fclose (deb->pkg);
            return;
      }
      if ((!fgets (versionbuf, sizeof (versionbuf), deb->pkg)) ||
            (strcmp (versionbuf, ARMAG)))
      {
            dv_show_error (DV_ERR_VERSION, deb->parent);
            fclose (deb->pkg);
            return;
      }
      fread (&debian_binary, 1, sizeof (struct ar_hdr), deb->pkg);
      if (memcmp (debian_binary.ar_name, "debian-binary   ",
                  sizeof (debian_binary.ar_name)) &&
            memcmp (debian_binary.ar_name, "debian-binary/   ",
                  sizeof (debian_binary.ar_name)))
      {
            dv_show_error (DV_ERR_NOT_DPKG, deb->parent);
      }
      memberlen = parseheaderlength (debian_binary.ar_size,
            sizeof (debian_binary.ar_size));
      if (!memberlen)
            dv_show_error (DV_ERR_CORRUPT_FILE, deb->parent);
      infobuf = malloc (memberlen + 1);
      fread (infobuf, 1, memberlen + (memberlen & 1), deb->pkg);
      fread (&controlgz, 1, sizeof (struct ar_hdr), deb->pkg);
      deb->current = &controlgz;
      deb->control_tar = archive_read_new ();
      archive_read_support_compression_gzip (deb->control_tar);
      archive_read_support_format_tar (deb->control_tar);
      error_num = ARCHIVE_OK;
      error_num = archive_read_open (deb->control_tar, deb,
            dv_archive_open, dv_archive_read, dv_archive_close);
      if (error_num != ARCHIVE_OK)
      {
            dv_show_error (DV_ERR_CORRUPT_FILE, deb->parent);
            deb->ar_message = archive_error_string (deb->control_tar);
            fclose (deb->pkg);
            return;
      }
      else
      {
            struct archive_entry *entry;
            gchar *locate;
            gpointer content;
            gint64 size;
            DVFileData *dvfd;

            while (archive_read_next_header (deb->control_tar, 
                  &entry) == ARCHIVE_OK)
            {
                  size = archive_entry_size (entry);
                  locate = g_strdup (archive_entry_pathname (entry));
                  content = g_new0(gpointer, size);
                  archive_read_data (deb->control_tar, content, size);
                  dvfd = g_new0 (DVFileData, 1);
                  dvfd->size = size;
                  if(S_ISREG(archive_entry_mode(entry)))
                  dvfd->content = content;
                  dvfd->compressed = FALSE;
                  g_hash_table_insert (deb->control_files, 
                        locate, dvfd);
                  if ((0 == strcmp (locate, "./control")) ||
                        (0 == strcmp (locate, "control")))
                  {
                        GtkWidget *display_area;
                        GtkTextBuffer *buffer;

                        /* todo: pattern match Package: Version: for
                        title of window.*/
                        display_area = lookup_widget 
                              (deb->parent, "display");
                        buffer =
                              gtk_text_view_get_buffer (GTK_TEXT_VIEW
                              (display_area));
                        gtk_text_buffer_set_text (buffer, (gchar*)content, -1);
                        gtk_text_view_set_buffer (GTK_TEXT_VIEW 
                              (display_area),   buffer);
                  }
                  archive_read_data_skip (deb->control_tar);
            }
      }
      dv_archive_close (deb->control_tar, deb);
      {
            /* if the size of control.tar.gz is odd,
            seek one byte to the start of data.tar.gz */
            gulong bytes_left;
            off_t s;
            gint seek;
            bytes_left = strtoul(controlgz.ar_size,NULL,10);
            seek = (bytes_left & 1);
            s = fseek(deb->pkg,seek,SEEK_CUR);
            if( s == (off_t)-1 ) {
                  dv_show_error (DV_ERR_CORRUPT_FILE, deb->parent);
                  deb->ar_message = archive_error_string (deb->control_tar);
                  fclose (deb->pkg);
                  return;
            }
      }
      fread (&datagz, 1, sizeof (struct ar_hdr), deb->pkg);
      deb->current = &datagz;
      deb->data_tar = archive_read_new ();
      archive_read_support_compression_gzip (deb->data_tar);
      archive_read_support_format_tar (deb->data_tar);
      error_num = ARCHIVE_OK;
      error_num = archive_read_open (deb->data_tar, deb,
            dv_archive_open, dv_archive_read, dv_archive_close);
      if (error_num != ARCHIVE_OK)
      {
            dv_show_error (DV_ERR_CORRUPT_FILE, deb->parent);
            deb->ar_message = archive_error_string (deb->data_tar);
      }
      else
      {
            struct archive_entry *entry;
            gpointer *content;
            gint64 size;
            gchar *locate;
            DVFileData *dvfd;

            content = NULL;
            size = 0;
            while (archive_read_next_header (deb->data_tar, &entry) ==
                  ARCHIVE_OK)
            {
                  size = archive_entry_size (entry);
                  content = g_new0 (gpointer, size);
                  archive_read_data (deb->data_tar, content, size);
                  /* locate is the name of the .gz file */
                  locate = g_strdup (archive_entry_pathname (entry));
                  dvfd = g_new0 (DVFileData, 1);
                  dvfd->size = size;
                  if (g_str_has_suffix (locate, ".gz"))
                  {
                        gchar *temp_file;
                        gint err;
                        gzFile t;
                        gpointer h;
                        gint f = g_file_open_tmp ("dvXXXXXX", 
                              &temp_file, NULL);
                        g_file_set_contents (temp_file, (gchar*)content, 
                              size, NULL);
                        close (f);
                        h = g_new0 (gpointer, MAXGZ);
                        t = gzopen (temp_file, "rb");
                        err = gzread (t, h, MAXGZ);
                        if (err <= -1)
                        {
                              deb->ar_message = locate;
                              dv_show_error (DV_ERR_COMPRESS, deb->parent);
                        }
                        gzclose (t);
                        dvfd->content = h;
                        g_remove (temp_file);
                  }
                  else
                  {
                        if (g_str_has_suffix (locate, "copyright"))
                        {
                              g_hash_table_insert (deb->control_files, 
                                    "./copyright", dvfd);
                              deb->copyright = g_strdup ((gchar*)content);
                        }
                        dvfd->content = content;
                  }
                  g_hash_table_insert (deb->data_files, locate, dvfd);
                  archive_read_data_skip (deb->data_tar);
            }
            archive_read_finish (deb->data_tar);
      }
      fclose (deb->pkg);
}

static void
add_control_files (gpointer key, gpointer value, gpointer user_data)
{
      DVIter *dvi = (DVIter *) user_data;
      gchar *path = (gchar *) key;
      DVFileData *dvfd = (DVFileData*)value;
      gchar *size_str;

      if (g_str_has_suffix(path, "/"))
            return;
      size_str = g_strdup_printf ("%" G_GINT64_FORMAT, dvfd->size);
      gtk_tree_store_append (dvi->store, dvi->child_iter, 
            dvi->parent_iter);
      gtk_tree_store_set (dvi->store, dvi->child_iter, PKG_COLUMN,
            g_filename_to_utf8 ((gchar*)key, -1, NULL, NULL, NULL),
            SIZE_COLUMN, size_str, LOCATION_COLUMN,
            g_filename_to_utf8 ((gchar*)key, -1, NULL, NULL, NULL), -1);
}

static void
add_data_files (gpointer key, gpointer value, gpointer user_data)
{
      DVIter *dvi = (DVIter *) user_data;
      gchar *path = (gchar *) key;
      gchar *file = g_path_get_basename (path);
      DVFileData *dvfd = (DVFileData*)value;
      gchar *size_str;

      if (g_str_has_suffix(path, "/"))
            return;
      size_str = g_strdup_printf ("%" G_GINT64_FORMAT, dvfd->size);
      gtk_tree_store_append (dvi->store, dvi->child_iter, 
            dvi->parent_iter);
      gtk_tree_store_set (dvi->store, dvi->child_iter, PKG_COLUMN,
            g_filename_to_utf8 (file, -1, NULL, NULL, NULL),
            SIZE_COLUMN, size_str, LOCATION_COLUMN,
            g_filename_to_utf8 (path, -1, NULL, NULL, NULL), -1);
}

void
dv_archive_get_control (DVIter * dvi, DVContents *deb)
{
      g_return_if_fail (deb);
      g_hash_table_foreach (deb->control_files, add_control_files, dvi);
}

void
dv_archive_get_data (DVIter * dvi, DVContents *deb)
{
      g_return_if_fail (deb);
      g_hash_table_foreach (deb->data_files, add_data_files, dvi);
}

static void
columns_reset (gpointer value, gpointer user_data)
{
      guint cols;
      GtkTreeView *treeview;
      GtkTreeViewColumn *column;

      column = (GtkTreeViewColumn*)value;
      treeview = (GtkTreeView*)user_data;
      gtk_tree_view_column_clear (column);
      cols = gtk_tree_view_remove_column (treeview, column);
}

static gint
size_compare (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b,
            gpointer user_data)
{
      gint result;
      gchar *str_a, *str_b;
      guint64 sz_a, sz_b;

      result = 0;
      gtk_tree_model_get(model, a, SIZE_COLUMN, &str_a, -1);
      gtk_tree_model_get(model, b, SIZE_COLUMN, &str_b, -1);
      if (!str_a)
            return -1;
      if (!str_b)
            return 1;
      sz_a = g_ascii_strtoull (str_a, NULL, 10);
      sz_b = g_ascii_strtoull (str_b, NULL, 10);
      if(sz_a != sz_b)
            result = (sz_a > sz_b) ? 1 : -1;
      g_free(str_a);
      g_free(str_b);
      return result;
}

static void 
tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data)
{
      GtkTreeIter iter;
      GtkTreeModel *model;
      DVContents *deb;

      deb = (DVContents*) data;
      g_return_if_fail (deb);

      if (gtk_tree_selection_get_selected (selection, &model, &iter))
      {
            if (deb->selected_file)
                  g_free (deb->selected_file);
            gtk_tree_model_get (model, &iter, LOCATION_COLUMN, 
                  &deb->selected_file, -1);
      }
}

void
open_deb (const gchar * filename, DVContents * deb)
{
      GtkWidget *treeview;
      GtkTreeStore *store;
      GtkTreeModel *model;
      GtkTreeSortable * sort;
      GtkTreeIter parent_iter, orig_iter;
      GtkTreeIter deb_iter, tar_iter, file_iter;
      GtkCellRenderer *renderer;
      GtkTreeViewColumn *column;
      GtkTreeSelection *select;
      DVIter dvi;
      struct stat statinfo;
      gint stat_val;

      g_return_if_fail (deb);
      if (!filename)
            return;
      stat_val = g_stat (filename, &statinfo);
      deb->filename = filename;
      if (!S_ISREG (statinfo.st_mode) || statinfo.st_size == 0)
      {
            dv_show_error (DV_ERR_NO_FILE, deb->parent);
            return;
      }
      prepare_contents (filename, deb);
      treeview = lookup_widget (deb->parent, "treeview");
      g_return_if_fail (treeview);
      model = gtk_tree_view_get_model (GTK_TREE_VIEW(treeview));
      if (deb->store_set)
      {
            GList *columns = NULL;
            store = GTK_TREE_STORE (model);
            sort = GTK_TREE_SORTABLE(store);
            gtk_tree_store_clear (store);
            columns = gtk_tree_view_get_columns 
                  (GTK_TREE_VIEW(treeview));
            g_list_foreach (columns, columns_reset, treeview);
      }
      else
      {
            store = gtk_tree_store_new (N_COLUMNS,
                  G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
            sort = GTK_TREE_SORTABLE(store);
            gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
                  GTK_TREE_MODEL (sort));
            deb->store_set = TRUE;
      }
      gtk_tree_store_append (store, &parent_iter, NULL);
      gtk_tree_store_set (store, &parent_iter, PKG_COLUMN, "name",
            SIZE_COLUMN, "size", LOCATION_COLUMN, filename, -1);
      renderer = gtk_cell_renderer_text_new ();
      column = gtk_tree_view_column_new_with_attributes
            (_("Package"), renderer, "text", PKG_COLUMN, NULL);
      gtk_tree_view_column_set_sort_column_id (column, PKG_COLUMN);
      gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
      column = gtk_tree_view_column_new_with_attributes
            (_("Size"), renderer, "text", SIZE_COLUMN, NULL);
      gtk_tree_view_column_set_sort_column_id (column, SIZE_COLUMN);
      gtk_tree_sortable_set_sort_func (sort, SIZE_COLUMN, size_compare,
            NULL, NULL);
      gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
      column = gtk_tree_view_column_new_with_attributes
            (_("Location"), renderer, "text", LOCATION_COLUMN, NULL);
      gtk_tree_view_column_set_sort_column_id (column, LOCATION_COLUMN);
      gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
      gtk_tree_store_append (store, &deb_iter, &parent_iter);
      gtk_tree_store_set (store, &deb_iter, PKG_COLUMN,
            _("Debian data"), SIZE_COLUMN, NULL, LOCATION_COLUMN, 
            NULL, -1);
      dvi.store = store;
      dvi.child_iter = &file_iter;
      dvi.parent_iter = &deb_iter;
      dv_archive_get_control (&dvi, deb);

      gtk_tree_store_append (store, &orig_iter, &parent_iter);
      gtk_tree_store_set (store, &orig_iter, PKG_COLUMN,
            _("Upstream data"), SIZE_COLUMN, "", LOCATION_COLUMN, "", -1);
      dvi.store = store;
      dvi.child_iter = &tar_iter;
      dvi.parent_iter = &orig_iter;
      dv_archive_get_data (&dvi, deb);
      gtk_tree_view_expand_all (GTK_TREE_VIEW(treeview));
      select = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
      gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
      g_signal_connect (G_OBJECT (select), "changed",
                                G_CALLBACK (tree_selection_changed_cb), deb);
      gtk_widget_show_all (treeview);
}

void
dv_archive_preload (GtkWidget * widget)
{
      DVContents *deb;

      deb = (DVContents*) lookup_widget (widget, DVCONTENTS);
      if (deb)
            open_deb (deb->filename, deb);
}

gchar *
dv_get_control_content (const gchar * file, GtkWidget * widget)
{
      DVFileData *dvfd;
      DVContents *deb;

      deb = (DVContents*) lookup_widget (widget, DVCONTENTS);
      g_return_val_if_fail (deb, NULL);
      dvfd = (DVFileData*)
            g_hash_table_lookup (deb->control_files, file);
      if (!dvfd)
            return NULL;
      {
            guint s_id;
            GtkWidget *sbar;
            sbar = lookup_widget(GTK_WIDGET(widget), "dvstatusbar");
            s_id = gtk_statusbar_get_context_id (GTK_STATUSBAR(sbar), 
                  "errors");
            gtk_statusbar_pop (GTK_STATUSBAR(sbar), s_id);
      }
      return (g_utf8_validate (dvfd->content, -1, NULL)) ? 
            dvfd->content : NULL;
}     

static gchar *
dv_make_utf8 (gchar * string)
{
      gchar *value;

      if (!string)
            return NULL;
      if (g_utf8_validate (string, -1, NULL))
            return string;
      value = g_locale_to_utf8 (string, -1, NULL, NULL, NULL);
      if (!value)
      {
            value = g_convert (string, -1, "UTF-8", "ISO-8859-15",
                  NULL, NULL, NULL);
            if (!value)
                  return NULL;
            return value;
      }
      return value;
}

gint64
dv_get_content_length (DVContents * deb)
{
      DVFileData *dvfd;
      const gchar * file;

      g_return_val_if_fail (deb, 0);
      file = dv_get_selected_file (deb);
      dvfd = (DVFileData*)
            g_hash_table_lookup (deb->data_files, file);
      if (!dvfd)
            return 0;
      return dvfd->size;      
}

gpointer
dv_get_raw_content (DVContents * deb)
{
      guint s_id;
      GtkWidget *sbar;
      DVFileData *dvfd;
      const gchar * file;

      g_return_val_if_fail (deb, NULL);
      file = dv_get_selected_file (deb);
      dvfd = (DVFileData*)
            g_hash_table_lookup (deb->data_files, file);
      if (!dvfd)
            return NULL;
      sbar = lookup_widget(deb->parent, "dvstatusbar");
      s_id = gtk_statusbar_get_context_id (GTK_STATUSBAR(sbar), 
            "errors");
      gtk_statusbar_pop (GTK_STATUSBAR(sbar), s_id);
      if (dvfd->size == 0)
      {
            gtk_statusbar_push (GTK_STATUSBAR(sbar), s_id,
                  _("Empty file."));
            return NULL;
      }
      return (gpointer)dvfd->content;
}

gchar *
dv_get_data_content (const gchar * file, GtkWidget * widget)
{
      guint s_id;
      GtkWidget *sbar;
      gchar *check;
      DVFileData *dvfd;
      DVContents *deb;

      deb = (DVContents*) lookup_widget (widget, DVCONTENTS);
      g_return_val_if_fail (deb, NULL);
      dvfd = (DVFileData*)
            g_hash_table_lookup (deb->data_files, file);
      if (!dvfd)
            return NULL;
      sbar = lookup_widget(GTK_WIDGET(widget), "dvstatusbar");
      s_id = gtk_statusbar_get_context_id (GTK_STATUSBAR(sbar), 
            "errors");
      gtk_statusbar_pop (GTK_STATUSBAR(sbar), s_id);
      if (dvfd->size == 0)
      {
            gtk_statusbar_push (GTK_STATUSBAR(sbar), s_id,
                  _("Empty file."));
            return NULL;
      }
      check = dv_make_utf8((gchar*)dvfd->content);
      if (check == NULL)
      {
            gtk_statusbar_push (GTK_STATUSBAR(sbar), s_id,
                  _("Error: Failed to convert the contents of "
                  "the selected file to UTF-8."));
      }
      return check;
}

gboolean
quit_last_window (gpointer data)
{
      gtk_widget_destroy (gtk_widget_get_toplevel(GTK_WIDGET(data)));
      return FALSE;
}

Generated by  Doxygen 1.6.0   Back to index