19a842d12a890efc7121de187a1e29191a393fd4
[claws.git] / src / plugins / archive / archiver_gtk.c
1 /* vim: set textwidth=80 tabstop=4 */
2
3 /*
4  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
5  * Copyright (C) 1999-2017 Michael Rasmussen and the Claws Mail Team
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  ii*
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  * 
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #  include "config.h"
24 #include "claws-features.h"
25 #endif
26
27 #include <glib.h>
28 #include <glib/gi18n.h>
29
30 #include "defs.h"
31
32 #include <gtk/gtk.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <errno.h>
37
38 #include "gtk/gtkutils.h"
39 #include "common/claws.h"
40 #include "common/version.h"
41 #include "common/md5.h"
42 #include "plugin.h"
43 #include "mainwindow.h"
44 #include "utils.h"
45 #include "prefs.h"
46 #include "folder.h"
47 #include "foldersel.h"
48 #include "procmsg.h"
49 #include "procheader.h"
50 #include "libarchive_archive.h"
51 #include "archiver.h"
52 #include "archiver_prefs.h"
53 #include "alertpanel.h"
54
55 #include <archive.h>
56
57 typedef struct _progress_widget progress_widget;
58 struct _progress_widget {
59         GtkWidget*      progress_dialog;
60         GtkWidget*      frame;
61         GtkWidget*      vbox1;
62         GtkWidget*      hbox1;
63         GtkWidget*      add_label;
64         GtkWidget*      file_label;
65         GtkWidget*      progress;
66         guint           position;
67 };
68
69 typedef enum {
70     A_FILE_OK           = 1 << 0,
71     A_FILE_EXISTS       = 1 << 1,
72     A_FILE_IS_LINK      = 1 << 2,
73     A_FILE_IS_DIR       = 1 << 3,
74     A_FILE_NO_WRITE     = 1 << 4,
75     A_FILE_UNKNOWN      = 1 << 5
76 } AFileTest;
77
78 static progress_widget* progress = NULL;
79
80 static progress_widget* init_progress() {
81         progress_widget* ptr = malloc(sizeof(*ptr));
82
83         debug_print("creating progress struct\n");
84         ptr->progress_dialog = NULL;
85         ptr->frame = NULL;
86         ptr->vbox1 = NULL;
87         ptr->hbox1 = NULL;
88         ptr->add_label = NULL;
89         ptr->file_label = NULL;
90         ptr->progress = NULL;
91         ptr->position = 0;
92
93         return ptr;
94 }
95
96 static void progress_dialog_cb(GtkWidget* widget, gint action, gpointer data) {
97         struct ArchivePage* page = (struct ArchivePage *) data;
98
99         debug_print("Cancel operation\n");
100         stop_archiving();
101         page->cancelled = TRUE;
102         archive_free_file_list(page->md5, page->rename);
103         gtk_widget_destroy(widget);
104 }
105
106 static void create_progress_dialog(struct ArchivePage* page) {
107         gchar* title = g_strdup_printf("%s %s", _("Archiving"), page->path);
108         MainWindow* mainwin = mainwindow_get_mainwindow();
109
110         progress->position = 0;
111         progress->progress_dialog = gtk_dialog_new_with_buttons (
112                                 title,
113                                 GTK_WINDOW(mainwin->window),
114                                 GTK_DIALOG_DESTROY_WITH_PARENT,
115                                 GTK_STOCK_CANCEL,
116                                 GTK_RESPONSE_CANCEL,
117                                 NULL);
118
119         g_signal_connect (
120                                 progress->progress_dialog,
121                                 "response",
122                                 G_CALLBACK(progress_dialog_cb),
123                                 page);
124
125         progress->frame = gtk_frame_new(_("Press Cancel button to stop archiving"));
126         gtk_frame_set_shadow_type(GTK_FRAME(progress->frame),
127                                         GTK_SHADOW_ETCHED_OUT);
128         gtk_container_set_border_width(GTK_CONTAINER(progress->frame), 4);
129         gtk_container_add(GTK_CONTAINER(
130                                 GTK_DIALOG(progress->progress_dialog)->vbox), progress->frame);
131
132         progress->vbox1 = gtk_vbox_new (FALSE, 4);
133         gtk_container_set_border_width (GTK_CONTAINER (progress->vbox1), 4);
134         gtk_container_add(GTK_CONTAINER(progress->frame), progress->vbox1);
135         
136         progress->hbox1 = gtk_hbox_new(FALSE, 8);
137         gtk_container_set_border_width(GTK_CONTAINER(progress->hbox1), 8);
138         gtk_box_pack_start(GTK_BOX(progress->vbox1),
139                                         progress->hbox1, FALSE, FALSE, 0);
140
141         progress->add_label = gtk_label_new(_("Archiving:"));
142         gtk_box_pack_start(GTK_BOX(progress->hbox1),
143                                         progress->add_label, FALSE, FALSE, 0);
144
145         progress->file_label = gtk_label_new("");
146         gtk_label_set_ellipsize(GTK_LABEL(progress->file_label),
147                                         PANGO_ELLIPSIZE_START);
148         gtk_box_pack_start(GTK_BOX(progress->hbox1),
149                                         progress->file_label, TRUE, TRUE, 0);
150
151         progress->hbox1 = gtk_hbox_new(FALSE, 8);
152         gtk_container_set_border_width(GTK_CONTAINER(progress->hbox1), 8);
153         gtk_box_pack_start(GTK_BOX(progress->vbox1),
154                                         progress->hbox1, FALSE, FALSE, 0);
155
156         progress->progress = gtk_progress_bar_new();
157         gtk_box_pack_start(GTK_BOX(progress->hbox1), 
158                                         progress->progress, TRUE, TRUE, 0);
159         gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(progress->progress), 0.25);
160
161         gtk_window_set_default_size(GTK_WINDOW(progress->progress_dialog), 400, 80);
162         gtk_widget_show_all(progress->progress_dialog);
163 }
164
165 static struct ArchivePage* init_archive_page() {
166         struct ArchivePage* page = malloc(sizeof(struct ArchivePage));
167
168         debug_print("creating ArchivePage\n");
169         page->path = NULL;
170         page->name = NULL;
171         page->file = NULL;
172         page->folder = NULL;
173         page->response = FALSE;
174         page->force_overwrite = FALSE;
175         page->compress_methods = NULL;
176         page->archive_formats = NULL;
177         page->recursive = NULL;
178         page->cancelled = FALSE;
179         page->md5 = FALSE;
180         page->md5sum = NULL;
181         page->rename = FALSE;
182         page->rename_files = NULL;
183         page->isoDate = NULL;
184         page->unlink_files = NULL;
185         page->unlink = FALSE;
186
187         return page;
188 }
189
190 static void dispose_archive_page(struct ArchivePage* page) {
191         debug_print("freeing ArchivePage\n");
192         if (page->path)
193                 g_free(page->path);
194         page->path = NULL;
195         if (page->name)
196                 g_free(page->name);
197         page->name = NULL;
198         g_free(page);
199 }
200
201 static gboolean valid_file_name(gchar* file) {
202         int i;
203
204         for (i = 0; INVALID_UNIX_CHARS[i] != '\0'; i++) {
205                 if (g_utf8_strchr(file, g_utf8_strlen(file, -1), INVALID_UNIX_CHARS[i]))
206                         return FALSE;
207         }
208         return TRUE;
209 }
210
211 static COMPRESS_METHOD get_compress_method(GSList* btn) {
212         const gchar* name;
213
214         while (btn) {
215                 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn->data))) {
216                         name = gtk_widget_get_name(GTK_WIDGET(btn->data));
217                         if (strcmp("GZIP", name) == 0) {
218                                 debug_print("GZIP compression enabled\n");
219                                 return GZIP;
220                         }
221                         else if (strcmp("BZIP", name) == 0) {
222                                 debug_print("BZIP2 compression enabled\n");
223                                 return BZIP2;
224                         }
225             else if (strcmp("COMPRESS", name) == 0) {
226                                 debug_print("COMPRESS compression enabled\n");
227                                 return COMPRESS;
228                         }
229 #if ARCHIVE_VERSION_NUMBER >= 2006990
230                         else if (strcmp("LZMA", name) == 0) {
231                                 debug_print("LZMA compression enabled\n");
232                                 return LZMA;
233                         }
234                         else if (strcmp("XZ", name) == 0) {
235                                 debug_print("XZ compression enabled\n");
236                                 return XZ;
237                         }
238 #endif
239 #if ARCHIVE_VERSION_NUMBER >= 3000000
240                         else if (strcmp("LZIP", name) == 0) {
241                                 debug_print("LZIP compression enabled\n");
242                                 return LZIP;
243                         }
244 #endif
245 #if ARCHIVE_VERSION_NUMBER >= 3001000
246                         else if (strcmp("LRZIP", name) == 0) {
247                                 debug_print("LRZIP compression enabled\n");
248                                 return LRZIP;
249                         }
250                         else if (strcmp("LZOP", name) == 0) {
251                                 debug_print("LZOP compression enabled\n");
252                                 return LZOP;
253                         }
254                         else if (strcmp("GRZIP", name) == 0) {
255                                 debug_print("GRZIP compression enabled\n");
256                                 return GRZIP;
257                         }
258 #endif
259 #if ARCHIVE_VERSION_NUMBER >= 3001900
260                         else if (strcmp("LZ4", name) == 0) {
261                                 debug_print("LZ4 compression enabled\n");
262                                 return LZ4;
263                         }
264 #endif
265                         else if (strcmp("NONE", name) == 0) {
266                                 debug_print("Compression disabled\n");
267                                 return NO_COMPRESS;
268                         }
269                 }
270                 btn = g_slist_next(btn);
271         }
272         return NO_COMPRESS;
273 }
274
275 static ARCHIVE_FORMAT get_archive_format(GSList* btn) {
276         const gchar* name;
277
278         while (btn) {
279                 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(btn->data))) {
280                         name = gtk_widget_get_name(GTK_WIDGET(btn->data));
281                         if (strcmp("TAR", name) == 0) {
282                                 debug_print("TAR archive enabled\n");
283                                 return TAR;
284                         }
285                         else if (strcmp("SHAR", name) == 0) {
286                                 debug_print("SHAR archive enabled\n");
287                                 return SHAR;
288                         }
289                         else if (strcmp("PAX", name) == 0) {
290                                 debug_print("PAX archive enabled\n");
291                                 return PAX;
292                         }
293                         else if (strcmp("CPIO", name) == 0) {
294                                 debug_print("CPIO archive enabled\n");
295                                 return CPIO;
296                         }
297                 }
298                 btn = g_slist_next(btn);
299         }
300         return NO_FORMAT;
301 }
302
303 static void create_md5sum(const gchar* file, const gchar* md5_file) {
304         int fd;
305         gchar* text = NULL;
306         gchar* md5sum = malloc(33);
307
308         debug_print("Creating md5sum file: %s\n", md5_file);
309         if (md5_hex_digest_file(md5sum, (const unsigned char *) file) == -1) {
310                 free(md5sum);
311                 return;
312         }
313         debug_print("md5sum: %s\n", md5sum);
314         if ((fd = 
315                 open(md5_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) == -1) {
316                 FILE_OP_ERROR(md5_file, "create");
317                 free(md5sum);
318                 return;
319         }
320         text = g_strrstr_len(file, strlen(file), "/");
321         if (text) {
322                 text++;
323                 text = g_strdup_printf("%s  %s\n", md5sum, text);
324         }
325         else
326                 text = g_strdup_printf("%s  %s\n", md5sum, file);
327         g_free(md5sum);
328         debug_print("md5sum: %s\n", text);
329         if (write(fd, text, strlen(text)) < 0)
330                 FILE_OP_ERROR(md5_file, "write");
331         close(fd);
332         g_free(text);
333 }
334
335 static gchar* descriptive_file_name(
336                 struct ArchivePage* page, const gchar* file, MsgInfo *msginfo) {
337         gchar* new_file = NULL;
338         gchar *name, *p, *to, *from, *date, *subject;
339
340         debug_print("renaming file\n");
341         p = g_strrstr_len(file, strlen(file), "/");
342         p = g_strndup(file, p - file);
343         if (!p)
344                 return NULL;
345         if (msginfo->to) {
346                 to = g_strdup(msginfo->to);
347                 extract_address(to);
348         }
349         else
350                 to = g_strdup("");
351         if (msginfo->from) {
352                 from = g_strdup(msginfo->from);
353                 extract_address(from);
354         }
355         else
356                 from = g_strdup("");
357         if (msginfo->date) {
358                 date = g_strdup(msginfo->date);
359                 subst_for_shellsafe_filename(date);
360                 /* if not on windows we need to subst some more */
361                 subst_chars(date, ":", '_');
362         }
363         else
364                 date = g_strdup("");
365         if (msginfo->subject) {
366                 subject = g_strdup(msginfo->subject);
367                 subst_for_shellsafe_filename(subject);
368                 /* if not on windows we need to subst some more */
369                 subst_chars(subject, ":", '_');
370         }
371         else
372                 subject = g_strdup("");
373         name = g_strdup_printf("%s_%s@%s@%s", date, from, to, subject);
374         /* ensure file name is not larger than 96 chars (max file name size
375          * is 100 chars but reserve for .md5)
376          */
377         if (strlen(name) > 96)
378                 name[96] = 0;
379         
380         new_file = g_strconcat(p, "/", name, NULL);
381
382         g_free(name);
383         g_free(p);
384         g_free(to);
385         g_free(from);
386         g_free(date);
387         g_free(subject);
388
389         debug_print("New_file: %s\n", new_file);
390         if (link(file, new_file) != 0) {
391                 if (errno != EEXIST) {
392                         FILE_OP_ERROR(new_file, "link");
393                         g_free(new_file);
394                         new_file = g_strdup(file);
395                         page->rename = FALSE;
396                 }
397         }
398
399         return new_file;
400 }
401
402 static void walk_folder(struct ArchivePage* page, FolderItem* item,
403                                 gboolean recursive) {
404         FolderItem* child;
405         GSList *msglist;
406         GSList *cur;
407         MsgInfo *msginfo;
408         GNode* node;
409         int count;
410         gchar* md5_file = NULL;
411         gchar* text = NULL;
412         gchar* file = NULL;
413         MsgTrash* msg_trash = NULL;
414         const gchar* date = NULL;
415
416         if (recursive && ! page->cancelled) {
417                 debug_print("Scanning recursive\n");
418                 node = item->node->children;
419                 while(node && ! page->cancelled) {
420                         debug_print("Number of nodes: %d\n", g_node_n_children(node));
421                         if (node->data) {
422                                 child = FOLDER_ITEM(node->data);
423                                 debug_print("new node: %d messages\n", child->total_msgs);
424                                 walk_folder(page, child, recursive);
425                         }
426                         node = node->next;
427                 }
428         }
429         if (! page->cancelled) {
430                 date = gtk_entry_get_text(GTK_ENTRY(page->isoDate));
431                 debug_print("cut-off date: %s\n", date);
432                 count = 0;
433                 page->files += item->total_msgs;
434                 msglist = folder_item_get_msg_list(item);
435                 msg_trash = new_msg_trash(item);
436                 for (cur = msglist; cur && ! page->cancelled; cur = cur->next) {
437                         msginfo = (MsgInfo *) cur->data;
438                         debug_print("%s_%s_%s_%s\n",
439                                 msginfo->date, msginfo->to, msginfo->from, msginfo->subject);
440                         file = folder_item_fetch_msg(item, msginfo->msgnum);
441                         if (date && strlen(date) > 0 && !before_date(msginfo->date_t, date)) {
442                             page->files--;
443                             continue;
444                         }
445                         page->total_size += msginfo->size;
446                         /*debug_print("Processing: %s\n", file);*/
447                         if (file) {
448                                 if (page->unlink) {
449                                     archive_add_msg_mark(msg_trash, msginfo);
450                                 }
451                                 if (page->rename) {
452                                         file = descriptive_file_name(page, file, msginfo);
453                                         if (!file) {
454                                                 /* Could not create a descriptive name */
455                                             file = folder_item_fetch_msg(item, msginfo->msgnum);
456                                         }
457                                 }
458                                 if (page->md5) {
459                                         md5_file = g_strdup_printf("%s.md5", file);
460                                         create_md5sum(file, md5_file);
461                                         archive_add_file(md5_file);
462                                         g_free(md5_file);
463                                 }
464                                 archive_add_file(file);
465                                 if (page->rename)
466                                         g_free(file);
467                         }
468                         if (count % 350 == 0) {
469                                 debug_print("pulse progressbar\n");
470                                 text = g_strdup_printf(
471                                                         "Scanning %s: %d files", item->name, count);
472                                 gtk_progress_bar_set_text(
473                                                 GTK_PROGRESS_BAR(progress->progress), text);
474                                 g_free(text);
475                                 gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progress->progress));
476                                 GTK_EVENTS_FLUSH();
477                         }
478                         count++;
479                 }
480                 procmsg_msg_list_free(msglist);
481         }
482 }
483
484 static AFileTest file_is_writeable(struct ArchivePage* page) {
485     int fd;
486
487     if (g_file_test(page->name, G_FILE_TEST_EXISTS) &&
488                                 ! page->force_overwrite)
489         return A_FILE_EXISTS;
490     if (g_file_test(page->name, G_FILE_TEST_IS_SYMLINK))
491         return A_FILE_IS_LINK;
492     if (g_file_test(page->name, G_FILE_TEST_IS_DIR))
493         return A_FILE_IS_DIR;
494     if ((fd = open(page->name, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) == -1) {
495         switch (errno) {
496             case EACCES: return A_FILE_NO_WRITE;
497             case EEXIST: return A_FILE_OK;
498             default:     return A_FILE_UNKNOWN;
499         }
500     }
501     else {
502         close(fd);
503         claws_unlink(page->name);
504     }
505     return A_FILE_OK;
506 }
507
508 static gboolean archiver_save_files(struct ArchivePage* page) {
509         FolderItem* item;
510         COMPRESS_METHOD method;
511         ARCHIVE_FORMAT format;
512         gboolean recursive;
513         guint orig_file;
514         GSList* list = NULL;
515         const gchar* res = NULL;
516         AFileTest perm;
517         gchar* msg = NULL;
518         gboolean folder_not_set;
519         gboolean file_not_set;
520
521         /* check if folder to archive and target archive filename are set */
522         folder_not_set = (*gtk_entry_get_text(GTK_ENTRY(page->folder)) == '\0');
523         file_not_set = (*gtk_entry_get_text(GTK_ENTRY(page->file)) == '\0');
524         if (folder_not_set || file_not_set) {
525                 alertpanel_error(_("Some uninitialized data prevents from starting\n"
526                                         "the archiving process:\n"
527                                         "%s%s"),
528                         folder_not_set ? _("\n- the folder to archive is not set") : "",
529                         file_not_set ? _("\n- the name for archive is not set") : "");
530                 return FALSE;
531         }
532         /* sync page struct info with folder and archive name edit widgets */
533         if (page->path) {
534                 g_free(page->path);
535                 page->path = NULL;
536         }
537         page->path = g_strdup(gtk_entry_get_text(GTK_ENTRY(page->folder)));
538         g_strstrip(page->path);
539         debug_print("page->path: %s\n", page->path);
540
541         if (page->name) {
542                 g_free(page->name);
543                 page->name = NULL;
544         }
545         page->name = g_strdup(gtk_entry_get_text(GTK_ENTRY(page->file)));
546         g_strstrip(page->name);
547         debug_print("page->name: %s\n", page->name);
548
549         if ((perm = file_is_writeable(page)) != A_FILE_OK) {
550                 switch (perm) {
551                         case A_FILE_EXISTS:
552                                 msg = g_strdup_printf(_("%s: Exists. Continue anyway?"), page->name);
553                                 break;
554                         case A_FILE_IS_LINK:
555                                 msg = g_strdup_printf(_("%s: Is a link. Cannot continue"), page->name);
556                                 break;
557                          case A_FILE_IS_DIR:
558                                  msg = g_strdup_printf(_("%s: Is a directory. Cannot continue"), page->name);
559                                 break;
560                         case A_FILE_NO_WRITE:
561                                  msg = g_strdup_printf(_("%s: Missing permissions. Cannot continue"), page->name);
562                                 break;
563                         case A_FILE_UNKNOWN:
564                                 msg = g_strdup_printf(_("%s: Unknown error. Cannot continue"), page->name);
565                                 break;
566                         default:
567                                 break;
568                 }
569                 if (perm == A_FILE_EXISTS) {
570                         AlertValue aval;
571
572                         aval = alertpanel_full(_("Creating archive"), msg,
573                                 GTK_STOCK_CANCEL, GTK_STOCK_OK, NULL, FALSE,
574                                 NULL, ALERT_WARNING, G_ALERTDEFAULT);
575                         g_free(msg);
576                         if (aval != G_ALERTALTERNATE)
577                                 return FALSE;
578                 } else {
579                         alertpanel_error(msg);
580                         g_free(msg);
581                         return FALSE;
582                 }
583         }
584         if (! valid_file_name(page->name)) {
585                 alertpanel_error(_("Not a valid file name:\n%s."), page->name);
586                 return FALSE;
587         }
588         item = folder_find_item_from_identifier(page->path);
589         if (! item) {
590                 alertpanel_error(_("Not a valid Claws Mail folder:\n%s."), page->name);
591                 return FALSE;
592         }
593         page->files = 0;
594         page->total_size = 0;
595         page->rename = gtk_toggle_button_get_active(
596                         GTK_TOGGLE_BUTTON(page->rename_files));
597         recursive = gtk_toggle_button_get_active(
598                                         GTK_TOGGLE_BUTTON(page->recursive));
599         page->md5 = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->md5sum));
600         page->unlink = gtk_toggle_button_get_active(
601                         GTK_TOGGLE_BUTTON(page->unlink_files));
602         create_progress_dialog(page);
603         walk_folder(page, item, recursive);
604         if (page->cancelled)
605                 return FALSE;
606         list = archive_get_file_list();
607         orig_file = (page->md5) ? page->files * 2 : page->files;
608         debug_print("md5: %d, orig: %d, md5: %d\n", 
609                                         page->md5, page->files, orig_file);
610         if (orig_file != g_slist_length(list)) {
611                 AlertValue aval;
612
613                 msg = g_strdup_printf(
614                                 _("Adding files in folder failed\n"
615                                   "Files in folder: %d\n"
616                                   "Files in list:   %d\n"
617                                   "\nContinue anyway?"),
618                                 orig_file, g_slist_length(list));
619                 aval = alertpanel_full(_("Creating archive"), msg,
620                         GTK_STOCK_CANCEL, GTK_STOCK_OK, NULL, FALSE,
621                         NULL, ALERT_WARNING, G_ALERTDEFAULT);
622                 g_free(msg);
623                 if (aval != G_ALERTALTERNATE) {
624                         archive_free_file_list(page->md5, page->rename);
625                         return FALSE;
626                 }
627         }
628         method = get_compress_method(page->compress_methods);
629         format = get_archive_format(page->archive_formats);
630         if ((res = archive_create(page->name, list, method, format)) != NULL) {
631                 alertpanel_error(_("Archive creation error:\n%s"), res);
632                 archive_free_file_list(page->md5, page->rename);
633                 return FALSE;
634         }
635         if (page->unlink) {
636                 archive_free_archived_files();
637         }
638         return TRUE;
639 }
640
641 static void entry_change_cb(GtkWidget* widget, gpointer data) {
642         const gchar* name = gtk_widget_get_name(widget);
643         struct ArchivePage* page = (struct ArchivePage *) data;
644
645         if (strcmp("folder", name) == 0) {
646                 page->path = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
647                 debug_print("page->folder = %s\n", page->path);
648         }
649         else if (strcmp("file", name) == 0) {
650                 page->name = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget)));
651                 page->force_overwrite = FALSE;
652                 debug_print("page->name = %s\n", page->name);
653         }
654 }
655
656 static void show_result(struct ArchivePage* page) {
657         
658         enum {
659                 STRING1,
660                 STRING2,
661                 N_COLUMNS
662         };
663
664         GStatBuf st;
665         GtkListStore* list;
666         GtkTreeIter iter;
667         GtkTreeView* view;
668         GtkTreeViewColumn* header;
669         GtkCellRenderer* renderer;
670         GtkWidget* dialog;
671         gchar* msg = NULL;
672         gchar* method = NULL;
673         gchar* format = NULL;
674
675         MainWindow* mainwin = mainwindow_get_mainwindow();
676
677         switch (get_compress_method(page->compress_methods)) {
678                 case GZIP:
679                         method = g_strdup("GZIP");
680                         break;
681                 case BZIP2:
682                         method = g_strdup("BZIP2");
683                         break;
684         case COMPRESS:
685                         method = g_strdup("Compress");
686                         break;
687 #if ARCHIVE_VERSION_NUMBER >= 2006990
688                 case LZMA:
689                         method = g_strdup("LZMA");
690                         break;
691                 case XZ:
692                         method = g_strdup("XZ");
693                         break;
694 #endif
695 #if ARCHIVE_VERSION_NUMBER >= 3000000
696                 case LZIP:
697                         method = g_strdup("LZIP");
698                         break;
699 #endif
700 #if ARCHIVE_VERSION_NUMBER >= 3001000
701                 case LRZIP:
702                         method = g_strdup("LRZIP");
703                         break;
704                 case LZOP:
705                         method = g_strdup("LZOP");
706                         break;
707                 case GRZIP:
708                         method = g_strdup("GRZIP");
709                         break;
710 #endif
711 #if ARCHIVE_VERSION_NUMBER >= 3001900
712                 case LZ4:
713                         method = g_strdup("LZ4");
714                         break;
715 #endif
716                 case NO_COMPRESS:
717                         method = g_strdup("No Compression");
718                         break;
719         }
720         
721         switch (get_archive_format(page->archive_formats)) {
722                 case TAR:
723                         format = g_strdup("TAR");
724                         break;
725                 case SHAR:
726                         format = g_strdup("SHAR");
727                         break;
728                 case PAX:
729                         format = g_strdup("PAX");
730                         break;
731                 case CPIO:
732                         format = g_strdup("CPIO");
733                         break;
734                 case NO_FORMAT:
735                         format = g_strdup("NO FORMAT");
736         }
737
738         if (g_stat(page->name, &st) == -1) {
739                 alertpanel_error("Could not get size of archive file '%s'.", page->name);
740                 return;
741         }
742         dialog = gtk_dialog_new_with_buttons(
743                         _("Archive result"),
744                         GTK_WINDOW(mainwin->window),
745                         GTK_DIALOG_DESTROY_WITH_PARENT,
746                         GTK_STOCK_OK,
747                         GTK_RESPONSE_NONE,
748                         NULL);
749         g_signal_connect_swapped(
750                                 dialog,
751                                 "response",
752                                 G_CALLBACK(gtk_widget_destroy),
753                                 dialog);
754
755         list = gtk_list_store_new(N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
756         
757         view = g_object_new(
758                                 GTK_TYPE_TREE_VIEW,
759                                 "model", list,
760                                 "rules-hint", FALSE,
761                                 "headers-clickable", FALSE,
762                                 "reorderable", FALSE,
763                                 "enable-search", FALSE,
764                                 NULL);
765
766         renderer = gtk_cell_renderer_text_new();
767
768         header = gtk_tree_view_column_new_with_attributes(
769                                 _("Attributes"), renderer, "text", STRING1, NULL);
770         gtk_tree_view_append_column(view, header);
771
772         header = gtk_tree_view_column_new_with_attributes(
773                                 _("Values"), renderer, "text", STRING2, NULL);
774         gtk_tree_view_append_column(view, header);
775
776         gtk_container_add(
777                                 GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), GTK_WIDGET(view));
778
779         gtk_list_store_append(list, &iter);
780         gtk_list_store_set(
781                                 list, &iter,
782                                 STRING1, _("Archive"),
783                                 STRING2, page->name, -1);
784
785         gtk_list_store_append(list, &iter);
786         gtk_list_store_set(
787                                 list, &iter,
788                                 STRING1, _("Archive format"),
789                                 STRING2, format, -1);
790         g_free(format);
791
792         gtk_list_store_append(list, &iter);
793         gtk_list_store_set(
794                                 list, &iter,
795                                 STRING1, _("Compression method"),
796                                 STRING2, method, -1);
797         g_free(method);
798
799         gtk_list_store_append(list, &iter);
800         msg = g_strdup_printf("%d", (page->md5) ? page->files * 2 : page->files);
801         gtk_list_store_set(
802                                 list, &iter,
803                                 STRING1, _("Number of files"),
804                                 STRING2, msg, -1);
805         g_free(msg);
806
807         gtk_list_store_append(list, &iter);
808         msg = g_strdup_printf("%d byte(s)", (guint) st.st_size);
809         gtk_list_store_set(
810                                 list, &iter,
811                                 STRING1, _("Archive Size"),
812                                 STRING2, msg, -1);
813         g_free(msg);
814
815         gtk_list_store_append(list, &iter);
816         msg = g_strdup_printf("%d byte(s)", page->total_size);
817         gtk_list_store_set(
818                                 list, &iter,
819                                 STRING1, _("Folder Size"),
820                                 STRING2, msg, -1);
821         g_free(msg);
822
823         gtk_list_store_append(list, &iter);
824         msg = g_strdup_printf("%d%%", 
825                                         (guint)((st.st_size * 100) / page->total_size));
826         gtk_list_store_set(
827                                 list, &iter,
828                                 STRING1, _("Compression level"),
829                                 STRING2, msg, -1);
830         g_free(msg);
831
832         gtk_list_store_append(list, &iter);
833         msg = g_strdup_printf("%s", (page->md5) ? _("Yes") : _("No"));
834         gtk_list_store_set(
835                                 list, &iter,
836                                 STRING1, _("MD5 checksum"),
837                                 STRING2, msg, -1);
838         g_free(msg);
839
840         gtk_list_store_append(list, &iter);
841         msg = g_strdup_printf("%s", (page->rename) ? _("Yes") : _("No"));
842         gtk_list_store_set(
843                                 list, &iter,
844                                 STRING1, _("Descriptive names"),
845                                 STRING2, msg, -1);
846         g_free(msg);
847
848         gtk_list_store_append(list, &iter);
849         msg = g_strdup_printf("%s", (page->unlink) ? _("Yes") : _("No"));
850         gtk_list_store_set(
851                                 list, &iter,
852                                 STRING1, _("Delete selected files"),
853                                 STRING2, msg, -1);
854         g_free(msg);
855         
856         msg = g_strdup(gtk_entry_get_text(GTK_ENTRY(page->isoDate)));
857         if (msg) {
858         gtk_list_store_append(list, &iter);
859         gtk_list_store_set(
860                         list, &iter,
861                         STRING1, _("Select mails before"),
862                         STRING2, msg, -1);
863         }
864         g_free(msg);
865
866         gtk_window_set_default_size(GTK_WINDOW(dialog), 320, 260);
867
868         gtk_widget_show_all(dialog);
869 }
870
871 static void archiver_dialog_cb(GtkWidget* widget, gint action, gpointer data) {
872         struct ArchivePage* page = (struct ArchivePage *) data;
873         gboolean result = FALSE;
874
875         switch (action) {
876                 case GTK_RESPONSE_ACCEPT:
877                         debug_print("User chose OK\n");
878                         page->response = TRUE;
879                         break;
880                 default:
881                         debug_print("User chose CANCEL\n");
882                         page->response = FALSE;
883                         archiver_gtk_done(page, widget);
884                         return;
885         }
886         debug_print("Settings:\naction: %d\n", page->response);
887         if (page->response) {
888                 debug_print("Settings:\nfolder: %s\nname: %s\n",
889                                 (page->path) ? page->path : "(null)",
890                                 (page->name) ? page->name : "(null)");
891                 result = archiver_save_files(page);
892                 debug_print("Result->archiver_save_files: %d\n", result);
893                 if (progress->progress_dialog && 
894                                                 GTK_IS_WIDGET(progress->progress_dialog))
895                         gtk_widget_destroy(progress->progress_dialog);          
896                 if (result && ! page->cancelled) {
897                         show_result(page);
898                         archive_free_file_list(page->md5, page->rename);
899                         archiver_gtk_done(page, widget);
900                         return;
901                 }
902                 if (page->cancelled) {
903                         archiver_gtk_done(page, widget);
904                         archiver_gtk_show();
905                 }
906         }
907 }
908
909 static void foldersel_cb(GtkWidget *widget, gpointer data)
910 {
911         FolderItem *item;
912         gchar *item_id;
913         gint newpos = 0;
914         struct ArchivePage* page = (struct ArchivePage *) data;
915
916         item = foldersel_folder_sel(NULL, FOLDER_SEL_MOVE, NULL, FALSE,
917                         _("Select folder to archive"));
918         if (item && (item_id = folder_item_get_identifier(item)) != NULL) {
919                 gtk_editable_delete_text(GTK_EDITABLE(page->folder), 0, -1);
920                 gtk_editable_insert_text(GTK_EDITABLE(page->folder),
921                                         item_id, strlen(item_id), &newpos);
922                 page->path = g_strdup(item_id);
923                 g_free(item_id);
924         }
925         debug_print("Folder to archive: %s\n", 
926                                 gtk_entry_get_text(GTK_ENTRY(page->folder)));
927 }
928
929 static void filesel_cb(GtkWidget *widget, gpointer data)
930 {
931         GtkWidget *dialog;
932         gchar* file;
933         gint newpos = 0;
934         const gchar* homedir;
935         struct ArchivePage* page = (struct ArchivePage *) data;
936
937         dialog = gtk_file_chooser_dialog_new(
938                 _("Select file name for archive [suffix should reflect archive like .tgz]"),
939                         NULL,
940                         GTK_FILE_CHOOSER_ACTION_SAVE,
941                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
942                         GTK_STOCK_APPLY, GTK_RESPONSE_APPLY,
943                         NULL);
944         homedir = g_getenv("HOME");
945         if (!homedir)
946                 homedir = g_get_home_dir();
947
948         if (archiver_prefs.save_folder)
949                 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), 
950                                                     archiver_prefs.save_folder);
951         else
952                 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), homedir);
953         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_APPLY) {
954                 file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
955                 if (file) {
956                         gtk_editable_delete_text(GTK_EDITABLE(page->file), 0, -1);
957                         gtk_editable_insert_text(GTK_EDITABLE(page->file),
958                                                 file, strlen(file), &newpos);
959                         page->name = g_strdup(file);
960                         g_free(file);
961                         page->force_overwrite = TRUE;
962                 }
963         }
964         gtk_widget_destroy(dialog);
965         debug_print("Name for archive: %s\n",
966                                 gtk_entry_get_text(GTK_ENTRY(page->file)));
967 }
968
969 void set_progress_file_label(const gchar* file) {
970         debug_print("IsLabel: %s, Update label: %s\n", 
971                                 GTK_IS_WIDGET(progress->file_label)? "Yes" : "No", file);
972         if (GTK_IS_WIDGET(progress->file_label))
973                 gtk_label_set_text(GTK_LABEL(progress->file_label), file);
974 }
975
976 void set_progress_print_all(guint fraction, guint total, guint step) {
977         gchar* text_count;
978
979         if (GTK_IS_WIDGET(progress->progress)) {
980                 if ((fraction - progress->position) % step == 0) {
981                         debug_print("frac: %d, total: %d, step: %d, prog->pos: %d\n",
982                                         fraction, total, step, progress->position);
983                         gtk_progress_bar_set_fraction(
984                                         GTK_PROGRESS_BAR(progress->progress), 
985                                         (total == 0) ? 0 : (gfloat)fraction / (gfloat)total);
986                         text_count = g_strdup_printf(_("%ld of %ld"), 
987                                         (long) fraction, (long) total);
988                         gtk_progress_bar_set_text(
989                                         GTK_PROGRESS_BAR(progress->progress), text_count);
990                         g_free(text_count);
991                         progress->position = fraction;
992                         GTK_EVENTS_FLUSH();
993                 }
994         }
995 }
996
997 void archiver_gtk_show() {
998         GtkWidget* dialog;
999         GtkWidget* frame;
1000         GtkWidget* vbox1;
1001         GtkWidget* hbox1;
1002         GtkWidget* folder_label;
1003         GtkWidget* folder_select;
1004         GtkWidget* file_label;
1005         GtkWidget* file_select;
1006         GtkWidget* gzip_radio_btn;
1007         GtkWidget* bzip_radio_btn;
1008     GtkWidget* compress_radio_btn;
1009 #if ARCHIVE_VERSION_NUMBER >= 2006990
1010         GtkWidget* lzma_radio_btn;
1011         GtkWidget* xz_radio_btn;
1012 #endif
1013 #if ARCHIVE_VERSION_NUMBER >= 3000000
1014         GtkWidget* lzip_radio_btn;
1015 #endif
1016 #if ARCHIVE_VERSION_NUMBER >= 3001000
1017         GtkWidget* lrzip_radio_btn;
1018         GtkWidget* lzop_radio_btn;
1019         GtkWidget* grzip_radio_btn;
1020 #endif
1021 #if ARCHIVE_VERSION_NUMBER >= 3001900
1022         GtkWidget* lz4_radio_btn;
1023 #endif
1024         GtkWidget* no_radio_btn;
1025         GtkWidget* shar_radio_btn;
1026         GtkWidget* pax_radio_btn;
1027         GtkWidget* cpio_radio_btn;
1028         GtkWidget* tar_radio_btn;
1029         struct ArchivePage* page;
1030         MainWindow* mainwin = mainwindow_get_mainwindow();
1031
1032         /*debug_set_mode(TRUE);*/
1033         progress = init_progress();
1034
1035         page = init_archive_page();
1036
1037         dialog = gtk_dialog_new_with_buttons (
1038                                 _("Create Archive"),
1039                                 GTK_WINDOW(mainwin->window),
1040                                 GTK_DIALOG_DESTROY_WITH_PARENT,
1041                                 GTK_STOCK_CANCEL,
1042                                 GTK_RESPONSE_CANCEL,
1043                                 GTK_STOCK_OK,
1044                                 GTK_RESPONSE_ACCEPT,
1045                                 NULL);
1046
1047         g_signal_connect (
1048                                 dialog,
1049                                 "response",
1050                                 G_CALLBACK(archiver_dialog_cb),
1051                                 page);
1052
1053         frame = gtk_frame_new(_("Enter Archiver arguments"));
1054         gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
1055         gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
1056         gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), frame);
1057
1058         vbox1 = gtk_vbox_new (FALSE, 4);
1059         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 4);
1060         gtk_container_add(GTK_CONTAINER(frame), vbox1);
1061         
1062         hbox1 = gtk_hbox_new(FALSE, 4);
1063         gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1064         gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, FALSE, 0);
1065
1066         folder_label = gtk_label_new(_("Folder to archive"));
1067         gtk_box_pack_start(GTK_BOX(hbox1), folder_label, FALSE, FALSE, 0);
1068         
1069         page->folder = gtk_entry_new();
1070         gtk_widget_set_name(page->folder, "folder");
1071         gtk_box_pack_start(GTK_BOX(hbox1), page->folder, TRUE, TRUE, 0);
1072         CLAWS_SET_TIP(page->folder,
1073                         _("Folder which is the root of the archive"));
1074
1075         folder_select = gtkut_get_browse_directory_btn(_("_Browse"));
1076         gtk_box_pack_start(GTK_BOX(hbox1), folder_select, FALSE, FALSE, 0);
1077         CLAWS_SET_TIP(folder_select,
1078                         _("Click this button to select a folder which is to be root of the archive"));
1079
1080         hbox1 = gtk_hbox_new(FALSE, 4);
1081         gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1082         gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, FALSE, 0);
1083
1084         file_label = gtk_label_new(_("Name for archive"));
1085         gtk_box_pack_start(GTK_BOX(hbox1), file_label, FALSE, FALSE, 0);
1086         
1087         page->file = gtk_entry_new();
1088         gtk_widget_set_name(page->file, "file");
1089         gtk_box_pack_start(GTK_BOX(hbox1), page->file, TRUE, TRUE, 0);
1090         CLAWS_SET_TIP(page->file, _("Archive location and name"));
1091
1092         file_select = gtkut_get_browse_directory_btn(_("_Select"));
1093         gtk_box_pack_start(GTK_BOX(hbox1), file_select, FALSE, FALSE, 0);
1094         CLAWS_SET_TIP(file_select,
1095                         _("Click this button to select a name and location for the archive"));
1096
1097         frame = gtk_frame_new(_("Choose compression"));
1098         gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
1099         gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
1100         gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
1101
1102         hbox1 = gtk_hbox_new(FALSE, 4);
1103         gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1104         gtk_container_add(GTK_CONTAINER(frame), hbox1);
1105
1106         gzip_radio_btn = gtk_radio_button_new_with_mnemonic(NULL, "G_ZIP");
1107         gtk_widget_set_name(gzip_radio_btn, "GZIP");
1108         gtk_box_pack_start(GTK_BOX(hbox1), gzip_radio_btn, FALSE, FALSE, 0);
1109         archiver_set_tooltip(gzip_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "GZIP"));
1110
1111         bzip_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1112                                         GTK_RADIO_BUTTON(gzip_radio_btn), "BZIP_2");
1113         gtk_widget_set_name(bzip_radio_btn, "BZIP");
1114         gtk_box_pack_start(GTK_BOX(hbox1), bzip_radio_btn, FALSE, FALSE, 0);
1115         archiver_set_tooltip(bzip_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "BZIP2"));
1116
1117         compress_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1118                                         GTK_RADIO_BUTTON(gzip_radio_btn), "Com_press");
1119         gtk_widget_set_name(compress_radio_btn, "COMPRESS");
1120         gtk_box_pack_start(GTK_BOX(hbox1), compress_radio_btn, FALSE, FALSE, 0);
1121         archiver_set_tooltip(compress_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "COMPRESS"));
1122
1123 #if ARCHIVE_VERSION_NUMBER >= 2006990
1124         lzma_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1125                                         GTK_RADIO_BUTTON(gzip_radio_btn), "_LZMA");
1126         gtk_widget_set_name(lzma_radio_btn, "LZMA");
1127         gtk_box_pack_start(GTK_BOX(hbox1), lzma_radio_btn, FALSE, FALSE, 0);
1128         archiver_set_tooltip(lzma_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "LZMA"));
1129
1130         xz_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1131                                         GTK_RADIO_BUTTON(gzip_radio_btn), "_XZ");
1132         gtk_widget_set_name(xz_radio_btn, "XZ");
1133         gtk_box_pack_start(GTK_BOX(hbox1), xz_radio_btn, FALSE, FALSE, 0);
1134         archiver_set_tooltip(xz_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "XZ"));
1135 #endif
1136
1137 #if ARCHIVE_VERSION_NUMBER >= 3000000
1138         lzip_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1139                                         GTK_RADIO_BUTTON(gzip_radio_btn), "_LZIP");
1140         gtk_widget_set_name(lzip_radio_btn, "LZIP");
1141         gtk_box_pack_start(GTK_BOX(hbox1), lzip_radio_btn, FALSE, FALSE, 0);
1142         archiver_set_tooltip(lzip_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "LZIP"));
1143 #endif
1144
1145 #if ARCHIVE_VERSION_NUMBER >= 3001000
1146         lrzip_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1147                                         GTK_RADIO_BUTTON(gzip_radio_btn), "L_RZIP");
1148         gtk_widget_set_name(lrzip_radio_btn, "LRZIP");
1149         gtk_box_pack_start(GTK_BOX(hbox1), lrzip_radio_btn, FALSE, FALSE, 0);
1150         archiver_set_tooltip(lrzip_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "LRZIP"));
1151
1152         lzop_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1153                                         GTK_RADIO_BUTTON(gzip_radio_btn), "LZ_OP");
1154         gtk_widget_set_name(lzop_radio_btn, "LZOP");
1155         gtk_box_pack_start(GTK_BOX(hbox1), lzop_radio_btn, FALSE, FALSE, 0);
1156         archiver_set_tooltip(lzop_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "LZOP"));
1157
1158         grzip_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1159                                         GTK_RADIO_BUTTON(gzip_radio_btn), "_GRZIP");
1160         gtk_widget_set_name(grzip_radio_btn, "GRZIP");
1161         gtk_box_pack_start(GTK_BOX(hbox1), grzip_radio_btn, FALSE, FALSE, 0);
1162         archiver_set_tooltip(grzip_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "GRZIP"));
1163 #endif
1164
1165 #if ARCHIVE_VERSION_NUMBER >= 3001900
1166         lz4_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1167                                         GTK_RADIO_BUTTON(gzip_radio_btn), "LZ_4");
1168         gtk_widget_set_name(lz4_radio_btn, "LZ4");
1169         gtk_box_pack_start(GTK_BOX(hbox1), lz4_radio_btn, FALSE, FALSE, 0);
1170         archiver_set_tooltip(lz4_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "LZ4"));
1171 #endif
1172
1173         no_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1174                                         GTK_RADIO_BUTTON(gzip_radio_btn), _("_None"));
1175         gtk_widget_set_name(no_radio_btn, "NONE");
1176         gtk_box_pack_start(GTK_BOX(hbox1), no_radio_btn, FALSE, FALSE, 0);
1177         archiver_set_tooltip(no_radio_btn, g_strdup_printf(_("Choose this option to use %s compression for the archive"), "NO"));
1178
1179         page->compress_methods = 
1180                         gtk_radio_button_get_group(GTK_RADIO_BUTTON(gzip_radio_btn));
1181
1182         switch (archiver_prefs.compression) {
1183         case COMPRESSION_GZIP:
1184                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gzip_radio_btn), TRUE);
1185                 break;
1186         case COMPRESSION_BZIP:
1187                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bzip_radio_btn), TRUE);
1188                 break;
1189         case COMPRESSION_COMPRESS:
1190                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compress_radio_btn), TRUE);
1191                 break;
1192 #if ARCHIVE_VERSION_NUMBER >= 2006990
1193         case COMPRESSION_LZMA:
1194                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lzma_radio_btn), TRUE);
1195                 break;
1196         case COMPRESSION_XZ:
1197                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(xz_radio_btn), TRUE);
1198                 break;
1199 #endif
1200 #if ARCHIVE_VERSION_NUMBER >= 3000000
1201         case COMPRESSION_LZIP:
1202                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lzip_radio_btn), TRUE);
1203                 break;
1204 #endif
1205 #if ARCHIVE_VERSION_NUMBER >= 3001000
1206         case COMPRESSION_LRZIP:
1207                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lrzip_radio_btn), TRUE);
1208                 break;
1209         case COMPRESSION_LZOP:
1210                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lzop_radio_btn), TRUE);
1211                 break;
1212         case COMPRESSION_GRZIP:
1213                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(grzip_radio_btn), TRUE);
1214                 break;
1215 #endif
1216 #if ARCHIVE_VERSION_NUMBER >= 3001900
1217         case COMPRESSION_LZ4:
1218                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lz4_radio_btn), TRUE);
1219                 break;
1220 #endif
1221         case COMPRESSION_NONE:
1222                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(no_radio_btn), TRUE);
1223                 break;
1224         }
1225
1226         frame = gtk_frame_new(_("Choose format"));
1227         gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
1228         gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
1229         gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
1230
1231         hbox1 = gtk_hbox_new(FALSE, 4);
1232         gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1233         gtk_container_add(GTK_CONTAINER(frame), hbox1);
1234
1235         tar_radio_btn = gtk_radio_button_new_with_mnemonic(NULL, "_TAR");
1236         gtk_widget_set_name(tar_radio_btn, "TAR");
1237         gtk_box_pack_start(GTK_BOX(hbox1), tar_radio_btn, FALSE, FALSE, 0);
1238         archiver_set_tooltip(tar_radio_btn, g_strdup_printf(_("Choose this to use %s as format for the archive"), "TAR"));
1239
1240         shar_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1241                                         GTK_RADIO_BUTTON(tar_radio_btn), "S_HAR");
1242         gtk_widget_set_name(shar_radio_btn, "SHAR");
1243         gtk_box_pack_start(GTK_BOX(hbox1), shar_radio_btn, FALSE, FALSE, 0);
1244         archiver_set_tooltip(shar_radio_btn, g_strdup_printf(_("Choose this to use %s as format for the archive"), "SHAR"));
1245
1246         cpio_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1247                                         GTK_RADIO_BUTTON(tar_radio_btn), "CP_IO");
1248         gtk_widget_set_name(cpio_radio_btn, "CPIO");
1249         gtk_box_pack_start(GTK_BOX(hbox1), cpio_radio_btn, FALSE, FALSE, 0);
1250         archiver_set_tooltip(cpio_radio_btn, g_strdup_printf(_("Choose this to use %s as format for the archive"), "CPIO"));
1251
1252         pax_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1253                                         GTK_RADIO_BUTTON(tar_radio_btn), "PA_X");
1254         gtk_widget_set_name(pax_radio_btn, "PAX");
1255         gtk_box_pack_start(GTK_BOX(hbox1), pax_radio_btn, FALSE, FALSE, 0);
1256         archiver_set_tooltip(pax_radio_btn, g_strdup_printf(_("Choose this to use %s as format for the archive"), "PAX"));
1257
1258         page->archive_formats = 
1259                         gtk_radio_button_get_group(GTK_RADIO_BUTTON(tar_radio_btn));
1260
1261         switch (archiver_prefs.format) {
1262         case FORMAT_TAR:
1263                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tar_radio_btn), TRUE);
1264                 break;
1265         case FORMAT_SHAR:
1266                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(shar_radio_btn), TRUE);
1267                 break;
1268         case FORMAT_CPIO:
1269                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cpio_radio_btn), TRUE);
1270                 break;
1271         case FORMAT_PAX:
1272                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pax_radio_btn), TRUE);
1273                 break;
1274         }
1275
1276         frame = gtk_frame_new(_("Miscellaneous options"));
1277         gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
1278         gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
1279         gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
1280
1281         hbox1 = gtk_hbox_new(FALSE, 4);
1282         gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1283         gtk_container_add(GTK_CONTAINER(frame), hbox1);
1284
1285         page->recursive = gtk_check_button_new_with_mnemonic(_("_Recursive"));
1286         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->recursive), archiver_prefs.recursive);
1287         gtk_box_pack_start(GTK_BOX(hbox1), page->recursive, FALSE, FALSE, 0);
1288         CLAWS_SET_TIP(page->recursive,
1289                 _("Choose this option to include subfolders in the archive"));
1290         
1291         page->md5sum = gtk_check_button_new_with_mnemonic(_("_MD5sum"));
1292         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->md5sum), archiver_prefs.md5sum);
1293         gtk_box_pack_start(GTK_BOX(hbox1), page->md5sum, FALSE, FALSE, 0);
1294         CLAWS_SET_TIP(page->md5sum,
1295                 _("Choose this option to add MD5 checksums for each file in the archive.\n"
1296                   "Be aware though, that this dramatically increases the time it\n"
1297                   "will take to create the archive"));
1298
1299         page->rename_files = gtk_check_button_new_with_mnemonic(_("R_ename"));
1300         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->rename_files), archiver_prefs.rename);
1301         gtk_box_pack_start(GTK_BOX(hbox1), page->rename_files, FALSE, FALSE, 0);
1302         CLAWS_SET_TIP(page->rename_files,
1303                 _("Choose this option to use descriptive names for each file in the archive.\n"
1304                   "The naming scheme: date_from@to@subject.\n"
1305                   "Names will be truncated to max 96 characters"));
1306
1307         page->unlink_files = gtk_check_button_new_with_mnemonic(_("_Delete"));
1308         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->unlink_files), archiver_prefs.unlink);
1309         gtk_box_pack_start(GTK_BOX(hbox1), page->unlink_files, FALSE, FALSE, 0);
1310         CLAWS_SET_TIP(page->unlink_files,
1311                 _("Choose this option to delete mails after archiving\n"
1312                   "At this point only handles IMAP4, Local mbox and POP3"));
1313
1314
1315         frame = gtk_frame_new(_("Selection options"));
1316         gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
1317         gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
1318         gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
1319
1320         hbox1 = gtk_hbox_new(FALSE, 4);
1321         gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1322         gtk_container_add(GTK_CONTAINER(frame), hbox1);
1323
1324         file_label = gtk_label_new(_("Select mails before"));
1325         gtk_box_pack_start(GTK_BOX(hbox1), file_label, FALSE, FALSE, 0);
1326         
1327         page->isoDate = gtk_entry_new();
1328         gtk_widget_set_name(page->isoDate, "isoDate");
1329         gtk_box_pack_start(GTK_BOX(hbox1), page->isoDate, TRUE, TRUE, 0);
1330         CLAWS_SET_TIP(page->isoDate, 
1331                 _("Select emails before a certain date\n"
1332                   "Date must comply to ISO-8601 [YYYY-MM-DD]"));
1333
1334         g_signal_connect(G_OBJECT(folder_select), "clicked", 
1335                          G_CALLBACK(foldersel_cb), page);
1336         g_signal_connect(G_OBJECT(file_select), "clicked",
1337                          G_CALLBACK(filesel_cb), page);
1338         g_signal_connect(G_OBJECT(page->folder), "activate",
1339                          G_CALLBACK(entry_change_cb), page);
1340         g_signal_connect(G_OBJECT(page->file), "activate",
1341                          G_CALLBACK(entry_change_cb), page);
1342
1343         gtk_widget_show_all(dialog);
1344 }
1345
1346 void archiver_gtk_done(struct ArchivePage* page, GtkWidget* widget) {
1347         dispose_archive_page(page);
1348         free(progress);
1349         gtk_widget_destroy(widget);
1350         /*debug_set_mode(FALSE);*/
1351 }
1352