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