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