aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTing-Wei Lan <lantw44@gmail.com>2013-07-08 14:26:57 +0800
committerLAN-TW <lantw44@gmail.com>2013-07-08 14:31:21 +0800
commit43bc4e374edc6699382e601beff0c3f750cb428e (patch)
tree8ebc0bb3f0cc5b28ba9924ed3a1abb609097e0da
parent62b660cd64722a6fef7c43446fadbf6a8aa31b23 (diff)
downloadgsoc2013-epiphany-43bc4e374edc6699382e601beff0c3f750cb428e.tar
gsoc2013-epiphany-43bc4e374edc6699382e601beff0c3f750cb428e.tar.gz
gsoc2013-epiphany-43bc4e374edc6699382e601beff0c3f750cb428e.tar.bz2
gsoc2013-epiphany-43bc4e374edc6699382e601beff0c3f750cb428e.tar.lz
gsoc2013-epiphany-43bc4e374edc6699382e601beff0c3f750cb428e.tar.xz
gsoc2013-epiphany-43bc4e374edc6699382e601beff0c3f750cb428e.tar.zst
gsoc2013-epiphany-43bc4e374edc6699382e601beff0c3f750cb428e.zip
Add basic archive support using libarchive
All files I/O are currently done by archive_write_disk. However, epiphany will get a segfault if the archive contains absolute path. This may be able to be solved by using GIO for file I/O.
-rw-r--r--embed/ephy-download.c100
1 files changed, 99 insertions, 1 deletions
diff --git a/embed/ephy-download.c b/embed/ephy-download.c
index 60cbbb873..369e0ebff 100644
--- a/embed/ephy-download.c
+++ b/embed/ephy-download.c
@@ -648,6 +648,102 @@ ephy_download_do_download_action (EphyDownload *download,
gboolean
ephy_download_do_extract_archive (EphyDownload *download)
{
+ gboolean failed;
+ struct archive *ar;
+ struct archive *ar_writer;
+ struct archive_entry *entry;
+ char *archive_filename;
+ char *output_dir;
+ int r;
+
+ failed = FALSE;
+
+ archive_filename = g_filename_from_uri (download->priv->destination, NULL, NULL);
+ if (archive_filename == NULL)
+ return FALSE;
+
+ output_dir = g_path_get_dirname (archive_filename);
+ if (*output_dir == '.') {
+ g_free (output_dir);
+ output_dir = ephy_file_get_downloads_dir ();
+ }
+
+ LOG ("ephy_download_do_extract_archive archive file: %s", archive_filename);
+ LOG ("ephy_download_do_extract_archive output dir: %s", output_dir);
+
+ ar = archive_read_new ();
+ archive_read_support_filter_all (ar);
+ archive_read_support_format_all (ar);
+
+ ar_writer = archive_write_disk_new ();
+ archive_write_disk_set_options (ar_writer,
+ ARCHIVE_EXTRACT_OWNER |
+ ARCHIVE_EXTRACT_PERM |
+ ARCHIVE_EXTRACT_TIME |
+ ARCHIVE_EXTRACT_NO_OVERWRITE |
+ ARCHIVE_EXTRACT_ACL |
+ ARCHIVE_EXTRACT_FFLAGS |
+ ARCHIVE_EXTRACT_XATTR |
+ ARCHIVE_EXTRACT_SPARSE);
+ archive_write_disk_set_standard_lookup (ar_writer);
+
+ if (archive_read_open_filename(ar, archive_filename, BUFFER_SIZE) != ARCHIVE_OK) {
+ LOG ("ephy_download_do_extract_archive cannot open then archive file");
+ archive_read_free (ar);
+ archive_write_free (ar_writer);
+ g_free (archive_filename);
+ return FALSE;
+ }
+
+ while(archive_read_next_header (ar, &entry) == ARCHIVE_OK) {
+ struct archive_entry *entry_writer;
+ char *extracted_filename;
+
+ extracted_filename = (char*)archive_entry_pathname (entry);
+ LOG ("ephy_download_do_extract_archive file name in archive: %s", extracted_filename);
+ entry_writer = archive_entry_clone (entry);
+
+ if(*extracted_filename != '/')
+ extracted_filename = g_build_path (G_DIR_SEPARATOR_S, output_dir, extracted_filename, NULL);
+
+ LOG ("ephy_download_do_extract_archive extracted file: %s", extracted_filename);
+ archive_entry_set_pathname (entry_writer, extracted_filename);
+
+ if ((r = archive_write_header (ar_writer, entry_writer)) != ARCHIVE_OK) {
+ LOG ("ephy_download_do_extract_archive header FAILED");
+ g_free (extracted_filename);
+ archive_entry_free (entry_writer);
+ continue;
+ }
+
+ LOG ("ephy_download_do_extract_archive header OK");
+
+ if (archive_entry_size (entry) > 0) {
+ size_t size;
+ off_t offset;
+ const void* buffer;
+ while ((r = archive_read_data_block (ar, &buffer, &size, &offset) == ARCHIVE_OK) &&
+ archive_write_data (ar_writer, buffer, size) >= 0);
+ if (r != ARCHIVE_EOF)
+ failed = TRUE;
+ }
+
+ archive_write_finish_entry (ar_writer);
+ archive_entry_free (entry_writer);
+ g_free (extracted_filename);
+ }
+
+ archive_read_close (ar);
+ archive_read_free (ar);
+ archive_write_close (ar_writer);
+ archive_write_free (ar_writer);
+ g_free (archive_filename);
+ g_free (output_dir);
+
+ if (failed) {
+ return FALSE;
+ }
+
return TRUE;
}
@@ -912,7 +1008,9 @@ download_finished_cb (WebKitDownload *wk_download,
g_signal_emit_by_name (download, "completed");
if(g_settings_get_boolean (EPHY_SETTINGS_MAIN, EPHY_PREFS_EXTRACT_DOWNLOADED_ARCHIVES)){
- ephy_download_do_extract_archive (download);
+ gboolean extract_ok;
+ extract_ok = ephy_download_do_extract_archive (download);
+ LOG ("download_finished_cb extract_ok: %hhd", extract_ok);
}
if (g_settings_get_boolean (EPHY_SETTINGS_MAIN, EPHY_PREFS_AUTO_DOWNLOADS) &&