cc1c98248110cff33b7780d2bf29d0b20e0db240
[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         if (write(fd, text, strlen(text)) < 0)
305                 perror("write");
306         close(fd);
307         g_free(text);
308 }
309
310 static gchar* descriptive_file_name(
311                 struct ArchivePage* page, const gchar* file, MsgInfo *msginfo) {
312         gchar* new_file = NULL;
313         gchar *name, *p, *to, *from, *date, *subject;
314
315         debug_print("renaming file\n");
316         p = g_strrstr_len(file, strlen(file), "/");
317         p = g_strndup(file, p - file);
318         if (!p)
319                 return NULL;
320         if (msginfo->to) {
321                 to = g_strdup(msginfo->to);
322                 extract_address(to);
323         }
324         else
325                 to = g_strdup("");
326         if (msginfo->from) {
327                 from = g_strdup(msginfo->from);
328                 extract_address(from);
329         }
330         else
331                 from = g_strdup("");
332         if (msginfo->date) {
333                 date = g_strdup(msginfo->date);
334                 subst_for_shellsafe_filename(date);
335                 /* if not on windows we need to subst some more */
336                 subst_chars(date, ":", '_');
337         }
338         else
339                 date = g_strdup("");
340         if (msginfo->subject) {
341                 subject = g_strdup(msginfo->subject);
342                 subst_for_shellsafe_filename(subject);
343                 /* if not on windows we need to subst some more */
344                 subst_chars(subject, ":", '_');
345         }
346         else
347                 subject = g_strdup("");
348         name = g_strdup_printf("%s_%s@%s@%s", date, from, to, subject);
349         /* ensure file name is not larger than 96 chars (max file name size
350          * is 100 chars but reserve for .md5)
351          */
352         if (strlen(name) > 96) {
353                 name = realloc(name, 97);
354                 name[96] = 0;
355         }
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         struct stat 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 #if NEW_ARCHIVE_API
683                 case COMPRESS:
684                         method = g_strdup("Compress");
685                         break;
686 #endif
687                 case NO_COMPRESS:
688                         method = g_strdup("No Compression");
689                         break;
690         }
691         
692         switch (get_archive_format(page->archive_formats)) {
693                 case TAR:
694                         format = g_strdup("TAR");
695                         break;
696                 case SHAR:
697                         format = g_strdup("SHAR");
698                         break;
699                 case PAX:
700                         format = g_strdup("PAX");
701                         break;
702                 case CPIO:
703                         format = g_strdup("CPIO");
704                         break;
705                 case NO_FORMAT:
706                         format = g_strdup("NO FORMAT");
707         }
708
709         g_stat(page->name, &st);
710         dialog = gtk_dialog_new_with_buttons(
711                         _("Archive result"),
712                         GTK_WINDOW(mainwin->window),
713                         GTK_DIALOG_DESTROY_WITH_PARENT,
714                         GTK_STOCK_OK,
715                         GTK_RESPONSE_NONE,
716                         NULL);
717         g_signal_connect_swapped(
718                                 dialog,
719                                 "response",
720                                 G_CALLBACK(gtk_widget_destroy),
721                                 dialog);
722
723         list = gtk_list_store_new(N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING);
724         
725         view = g_object_new(
726                                 GTK_TYPE_TREE_VIEW,
727                                 "model", list,
728                                 "rules-hint", FALSE,
729                                 "headers-clickable", FALSE,
730                                 "reorderable", FALSE,
731                                 "enable-search", FALSE,
732                                 NULL);
733
734         renderer = gtk_cell_renderer_text_new();
735
736         header = gtk_tree_view_column_new_with_attributes(
737                                 _("Attributes"), renderer, "text", STRING1, NULL);
738         gtk_tree_view_append_column(view, header);
739
740         header = gtk_tree_view_column_new_with_attributes(
741                                 _("Values"), renderer, "text", STRING2, NULL);
742         gtk_tree_view_append_column(view, header);
743
744         gtk_container_add(
745                                 GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), GTK_WIDGET(view));
746
747         gtk_list_store_append(list, &iter);
748         gtk_list_store_set(
749                                 list, &iter,
750                                 STRING1, _("Archive"),
751                                 STRING2, page->name, -1);
752
753         gtk_list_store_append(list, &iter);
754         gtk_list_store_set(
755                                 list, &iter,
756                                 STRING1, _("Archive format"),
757                                 STRING2, format, -1);
758         g_free(format);
759
760         gtk_list_store_append(list, &iter);
761         gtk_list_store_set(
762                                 list, &iter,
763                                 STRING1, _("Compression method"),
764                                 STRING2, method, -1);
765         g_free(method);
766
767         gtk_list_store_append(list, &iter);
768         msg = g_strdup_printf("%d", (page->md5) ? page->files * 2 : page->files);
769         gtk_list_store_set(
770                                 list, &iter,
771                                 STRING1, _("Number of files"),
772                                 STRING2, msg, -1);
773         g_free(msg);
774
775         gtk_list_store_append(list, &iter);
776         msg = g_strdup_printf("%d byte(s)", (guint) st.st_size);
777         gtk_list_store_set(
778                                 list, &iter,
779                                 STRING1, _("Archive Size"),
780                                 STRING2, msg, -1);
781         g_free(msg);
782
783         gtk_list_store_append(list, &iter);
784         msg = g_strdup_printf("%d byte(s)", page->total_size);
785         gtk_list_store_set(
786                                 list, &iter,
787                                 STRING1, _("Folder Size"),
788                                 STRING2, msg, -1);
789         g_free(msg);
790
791         gtk_list_store_append(list, &iter);
792         msg = g_strdup_printf("%d%%", 
793                                         (guint)((st.st_size * 100) / page->total_size));
794         gtk_list_store_set(
795                                 list, &iter,
796                                 STRING1, _("Compression level"),
797                                 STRING2, msg, -1);
798         g_free(msg);
799
800         gtk_list_store_append(list, &iter);
801         msg = g_strdup_printf("%s", (page->md5) ? _("Yes") : _("No"));
802         gtk_list_store_set(
803                                 list, &iter,
804                                 STRING1, _("MD5 checksum"),
805                                 STRING2, msg, -1);
806         g_free(msg);
807
808         gtk_list_store_append(list, &iter);
809         msg = g_strdup_printf("%s", (page->rename) ? _("Yes") : _("No"));
810         gtk_list_store_set(
811                                 list, &iter,
812                                 STRING1, _("Descriptive names"),
813                                 STRING2, msg, -1);
814         g_free(msg);
815
816         gtk_list_store_append(list, &iter);
817         msg = g_strdup_printf("%s", (page->unlink) ? _("Yes") : _("No"));
818         gtk_list_store_set(
819                                 list, &iter,
820                                 STRING1, _("Delete selected files"),
821                                 STRING2, msg, -1);
822         g_free(msg);
823         
824         msg = g_strdup(gtk_entry_get_text(GTK_ENTRY(page->isoDate)));
825         if (msg) {
826             gtk_list_store_append(list, &iter);
827             gtk_list_store_set(
828                                 list, &iter,
829                                 STRING1, _("Select mails before"),
830                                 STRING2, msg, -1);
831         }
832         g_free(msg);
833
834         gtk_window_set_default_size(GTK_WINDOW(dialog), 320, 260);
835
836         gtk_widget_show_all(dialog);
837 }
838
839 static void archiver_dialog_cb(GtkWidget* widget, gint action, gpointer data) {
840         struct ArchivePage* page = (struct ArchivePage *) data;
841         gboolean result = FALSE;
842
843         switch (action) {
844                 case GTK_RESPONSE_ACCEPT:
845                         debug_print("User chose OK\n");
846                         page->response = TRUE;
847                         break;
848                 default:
849                         debug_print("User chose CANCEL\n");
850                         page->response = FALSE;
851                         archiver_gtk_done(page, widget);
852                         return;
853         }
854         debug_print("Settings:\naction: %d\n", page->response);
855         if (page->response) {
856                 debug_print("Settings:\nfolder: %s\nname: %s\n",
857                                 (page->path) ? page->path : "(null)",
858                                 (page->name) ? page->name : "(null)");
859                 result = archiver_save_files(page);
860                 debug_print("Result->archiver_save_files: %d\n", result);
861                 if (progress->progress_dialog && 
862                                                 GTK_IS_WIDGET(progress->progress_dialog))
863                         gtk_widget_destroy(progress->progress_dialog);          
864                 if (result && ! page->cancelled) {
865                         show_result(page);
866                         archive_free_file_list(page->md5, page->rename);
867                         archiver_gtk_done(page, widget);
868                         return;
869                 }
870                 if (page->cancelled) {
871                         archiver_gtk_done(page, widget);
872                         archiver_gtk_show();
873                 }
874         }
875 }
876
877 static void foldersel_cb(GtkWidget *widget, gpointer data)
878 {
879         FolderItem *item;
880         gchar *item_id;
881         gint newpos = 0;
882         struct ArchivePage* page = (struct ArchivePage *) data;
883
884         item = foldersel_folder_sel(NULL, FOLDER_SEL_MOVE, NULL, FALSE);
885         if (item && (item_id = folder_item_get_identifier(item)) != NULL) {
886                 gtk_editable_delete_text(GTK_EDITABLE(page->folder), 0, -1);
887                 gtk_editable_insert_text(GTK_EDITABLE(page->folder),
888                                         item_id, strlen(item_id), &newpos);
889                 page->path = g_strdup(item_id);
890                 g_free(item_id);
891         }
892         debug_print("Folder to archive: %s\n", 
893                                 gtk_entry_get_text(GTK_ENTRY(page->folder)));
894 }
895
896 static void filesel_cb(GtkWidget *widget, gpointer data)
897 {
898         GtkWidget *dialog;
899         gchar* file;
900         gint newpos = 0;
901         const gchar* homedir;
902         struct ArchivePage* page = (struct ArchivePage *) data;
903
904         dialog = gtk_file_chooser_dialog_new(
905                 _("Select file name for archive [suffix should reflect archive like .tgz]"),
906                         NULL,
907                         GTK_FILE_CHOOSER_ACTION_SAVE,
908                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
909                         GTK_STOCK_APPLY, GTK_RESPONSE_APPLY,
910                         NULL);
911         homedir = g_getenv("HOME");
912         if (!homedir)
913                 homedir = g_get_home_dir();
914
915         if (archiver_prefs.save_folder)
916                 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), 
917                                                     archiver_prefs.save_folder);
918         else
919                 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), homedir);
920         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_APPLY) {
921                 file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
922                 if (file) {
923                         gtk_editable_delete_text(GTK_EDITABLE(page->file), 0, -1);
924                         gtk_editable_insert_text(GTK_EDITABLE(page->file),
925                                                 file, strlen(file), &newpos);
926                         page->name = g_strdup(file);
927                         g_free(file);
928                         page->force_overwrite = TRUE;
929                 }
930         }
931         gtk_widget_destroy(dialog);
932         debug_print("Name for archive: %s\n",
933                                 gtk_entry_get_text(GTK_ENTRY(page->file)));
934 }
935
936 void set_progress_file_label(const gchar* file) {
937         debug_print("IsLabel: %s, Update label: %s\n", 
938                                 GTK_IS_WIDGET(progress->file_label)? "Yes" : "No", file);
939         if (GTK_IS_WIDGET(progress->file_label))
940                 gtk_label_set_text(GTK_LABEL(progress->file_label), file);
941 }
942
943 void set_progress_print_all(guint fraction, guint total, guint step) {
944         gchar* text_count;
945
946         if (GTK_IS_WIDGET(progress->progress)) {
947                 if ((fraction - progress->position) % step == 0) {
948                         debug_print("frac: %d, total: %d, step: %d, prog->pos: %d\n",
949                                         fraction, total, step, progress->position);
950                         gtk_progress_bar_set_fraction(
951                                         GTK_PROGRESS_BAR(progress->progress), 
952                                         (total == 0) ? 0 : (gfloat)fraction / (gfloat)total);
953                         text_count = g_strdup_printf(_("%ld of %ld"), 
954                                         (long) fraction, (long) total);
955                         gtk_progress_bar_set_text(
956                                         GTK_PROGRESS_BAR(progress->progress), text_count);
957                         g_free(text_count);
958                         progress->position = fraction;
959                         GTK_EVENTS_FLUSH();
960                 }
961         }
962 }
963
964 void archiver_gtk_show() {
965         GtkWidget* dialog;
966         GtkWidget* frame;
967         GtkWidget* vbox1;
968         GtkWidget* hbox1;
969         GtkWidget* folder_label;
970         GtkWidget* folder_select;
971         GtkWidget* file_label;
972         GtkWidget* file_select;
973         GtkWidget* zip_radio_btn;
974         GtkWidget* bzip_radio_btn;
975 #if NEW_ARCHIVE_API
976         GtkWidget* compress_radio_btn;
977 #endif
978         GtkWidget* no_radio_btn;
979         GtkWidget* shar_radio_btn;
980         GtkWidget* pax_radio_btn;
981         GtkWidget* cpio_radio_btn;
982         GtkWidget* tar_radio_btn;
983         struct ArchivePage* page;
984         MainWindow* mainwin = mainwindow_get_mainwindow();
985
986         /*debug_set_mode(TRUE);*/
987         progress = init_progress();
988
989         page = init_archive_page();
990
991         dialog = gtk_dialog_new_with_buttons (
992                                 _("Create Archive"),
993                                 GTK_WINDOW(mainwin->window),
994                                 GTK_DIALOG_DESTROY_WITH_PARENT,
995                                 GTK_STOCK_CANCEL,
996                                 GTK_RESPONSE_CANCEL,
997                                 GTK_STOCK_OK,
998                                 GTK_RESPONSE_ACCEPT,
999                                 NULL);
1000
1001         g_signal_connect (
1002                                 dialog,
1003                                 "response",
1004                                 G_CALLBACK(archiver_dialog_cb),
1005                                 page);
1006
1007         frame = gtk_frame_new(_("Enter Archiver arguments"));
1008         gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
1009         gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
1010         gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), frame);
1011
1012         vbox1 = gtk_vbox_new (FALSE, 4);
1013         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 4);
1014         gtk_container_add(GTK_CONTAINER(frame), vbox1);
1015         
1016         hbox1 = gtk_hbox_new(FALSE, 4);
1017         gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1018         gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, FALSE, 0);
1019
1020         folder_label = gtk_label_new(_("Folder to archive"));
1021         gtk_box_pack_start(GTK_BOX(hbox1), folder_label, FALSE, FALSE, 0);
1022         
1023         page->folder = gtk_entry_new();
1024         gtk_widget_set_name(page->folder, "folder");
1025         gtk_box_pack_start(GTK_BOX(hbox1), page->folder, TRUE, TRUE, 0);
1026         CLAWS_SET_TIP(page->folder,
1027                         _("Folder which is the root of the archive"));
1028
1029         folder_select = gtkut_get_browse_directory_btn(_("_Browse"));
1030         gtk_box_pack_start(GTK_BOX(hbox1), folder_select, FALSE, FALSE, 0);
1031         CLAWS_SET_TIP(folder_select,
1032                         _("Click this button to select a folder which is to be root of the archive"));
1033
1034         hbox1 = gtk_hbox_new(FALSE, 4);
1035         gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1036         gtk_box_pack_start(GTK_BOX(vbox1), hbox1, FALSE, FALSE, 0);
1037
1038         file_label = gtk_label_new(_("Name for archive"));
1039         gtk_box_pack_start(GTK_BOX(hbox1), file_label, FALSE, FALSE, 0);
1040         
1041         page->file = gtk_entry_new();
1042         gtk_widget_set_name(page->file, "file");
1043         gtk_box_pack_start(GTK_BOX(hbox1), page->file, TRUE, TRUE, 0);
1044         CLAWS_SET_TIP(page->file, _("Archive location and name"));
1045
1046         file_select = gtkut_get_browse_directory_btn(_("_Select"));
1047         gtk_box_pack_start(GTK_BOX(hbox1), file_select, FALSE, FALSE, 0);
1048         CLAWS_SET_TIP(file_select,
1049                         _("Click this button to select a name and location for the archive"));
1050
1051         frame = gtk_frame_new(_("Choose compression"));
1052         gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
1053         gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
1054         gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
1055
1056         hbox1 = gtk_hbox_new(FALSE, 4);
1057         gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1058         gtk_container_add(GTK_CONTAINER(frame), hbox1);
1059
1060         zip_radio_btn = gtk_radio_button_new_with_mnemonic(NULL, "_ZIP");
1061         gtk_widget_set_name(zip_radio_btn, "ZIP");
1062         gtk_box_pack_start(GTK_BOX(hbox1), zip_radio_btn, FALSE, FALSE, 0);
1063         CLAWS_SET_TIP(zip_radio_btn,
1064                         _("Choose this option to use ZIP compression for the archive"));
1065
1066         bzip_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1067                                         GTK_RADIO_BUTTON(zip_radio_btn), "BZIP_2");
1068         gtk_widget_set_name(bzip_radio_btn, "BZIP");
1069         gtk_box_pack_start(GTK_BOX(hbox1), bzip_radio_btn, FALSE, FALSE, 0);
1070         CLAWS_SET_TIP(bzip_radio_btn,
1071                         _("Choose this option to use BZIP2 compression for the archive"));
1072
1073 #if NEW_ARCHIVE_API
1074         compress_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1075                                         GTK_RADIO_BUTTON(zip_radio_btn), "Com_press");
1076         gtk_widget_set_name(compress_radio_btn, "COMPRESS");
1077         gtk_box_pack_start(GTK_BOX(hbox1), compress_radio_btn, FALSE, FALSE, 0);
1078         CLAWS_SET_TIP(compress_radio_btn,
1079                 _("Choose this to use Compress compression for your archive"));
1080 #endif
1081
1082         no_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1083                                         GTK_RADIO_BUTTON(zip_radio_btn), _("_None"));
1084         gtk_widget_set_name(no_radio_btn, "NONE");
1085         gtk_box_pack_start(GTK_BOX(hbox1), no_radio_btn, FALSE, FALSE, 0);
1086         CLAWS_SET_TIP(no_radio_btn,
1087                 _("Choose this option to disable compression for the archive"));
1088
1089         page->compress_methods = 
1090                         gtk_radio_button_get_group(GTK_RADIO_BUTTON(zip_radio_btn));
1091
1092         switch (archiver_prefs.compression) {
1093         case COMPRESSION_ZIP:
1094                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(zip_radio_btn), TRUE);
1095                 break;
1096         case COMPRESSION_BZIP:
1097                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bzip_radio_btn), TRUE);
1098                 break;
1099 #if NEW_ARCHIVE_API
1100         case COMPRESSION_COMPRESS:
1101                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(compress_radio_btn), TRUE);
1102                 break;
1103 #endif
1104         case COMPRESSION_NONE:
1105                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(no_radio_btn), TRUE);
1106                 break;
1107         }
1108
1109         frame = gtk_frame_new(_("Choose format"));
1110         gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
1111         gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
1112         gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
1113
1114         hbox1 = gtk_hbox_new(FALSE, 4);
1115         gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1116         gtk_container_add(GTK_CONTAINER(frame), hbox1);
1117
1118         tar_radio_btn = gtk_radio_button_new_with_mnemonic(NULL, "_TAR");
1119         gtk_widget_set_name(tar_radio_btn, "TAR");
1120         gtk_box_pack_start(GTK_BOX(hbox1), tar_radio_btn, FALSE, FALSE, 0);
1121         CLAWS_SET_TIP(tar_radio_btn,
1122                         _("Choose this option to use TAR as format for the archive"));
1123
1124         shar_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1125                                         GTK_RADIO_BUTTON(tar_radio_btn), "S_HAR");
1126         gtk_widget_set_name(shar_radio_btn, "SHAR");
1127         gtk_box_pack_start(GTK_BOX(hbox1), shar_radio_btn, FALSE, FALSE, 0);
1128         CLAWS_SET_TIP(shar_radio_btn,
1129                         _("Choose this to use SHAR as format for the archive"));
1130
1131         cpio_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1132                                         GTK_RADIO_BUTTON(tar_radio_btn), "CP_IO");
1133         gtk_widget_set_name(cpio_radio_btn, "CPIO");
1134         gtk_box_pack_start(GTK_BOX(hbox1), cpio_radio_btn, FALSE, FALSE, 0);
1135         CLAWS_SET_TIP(cpio_radio_btn,
1136                 _("Choose this option to use CPIO as format for the archive"));
1137
1138         pax_radio_btn = gtk_radio_button_new_with_mnemonic_from_widget(
1139                                         GTK_RADIO_BUTTON(tar_radio_btn), "PA_X");
1140         gtk_widget_set_name(pax_radio_btn, "PAX");
1141         gtk_box_pack_start(GTK_BOX(hbox1), pax_radio_btn, FALSE, FALSE, 0);
1142         CLAWS_SET_TIP(pax_radio_btn,
1143                 _("Choose this option to use PAX as format for the archive"));
1144
1145         page->archive_formats = 
1146                         gtk_radio_button_get_group(GTK_RADIO_BUTTON(tar_radio_btn));
1147
1148         switch (archiver_prefs.format) {
1149         case FORMAT_TAR:
1150                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tar_radio_btn), TRUE);
1151                 break;
1152         case FORMAT_SHAR:
1153                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(shar_radio_btn), TRUE);
1154                 break;
1155         case FORMAT_CPIO:
1156                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cpio_radio_btn), TRUE);
1157                 break;
1158         case FORMAT_PAX:
1159                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pax_radio_btn), TRUE);
1160                 break;
1161         }
1162
1163         frame = gtk_frame_new(_("Miscellaneous options"));
1164         gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
1165         gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
1166         gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
1167
1168         hbox1 = gtk_hbox_new(FALSE, 4);
1169         gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1170         gtk_container_add(GTK_CONTAINER(frame), hbox1);
1171
1172         page->recursive = gtk_check_button_new_with_mnemonic(_("_Recursive"));
1173         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->recursive), archiver_prefs.recursive);
1174         gtk_box_pack_start(GTK_BOX(hbox1), page->recursive, FALSE, FALSE, 0);
1175         CLAWS_SET_TIP(page->recursive,
1176                 _("Choose this option to include subfolders in the archive"));
1177         
1178         page->md5sum = gtk_check_button_new_with_mnemonic(_("_MD5sum"));
1179         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->md5sum), archiver_prefs.md5sum);
1180         gtk_box_pack_start(GTK_BOX(hbox1), page->md5sum, FALSE, FALSE, 0);
1181         CLAWS_SET_TIP(page->md5sum,
1182                 _("Choose this option to add MD5 checksums for each file in the archive.\n"
1183                   "Be aware though, that this dramatically increases the time it\n"
1184                   "will take to create the archive"));
1185
1186         page->rename_files = gtk_check_button_new_with_mnemonic(_("R_ename"));
1187         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->rename_files), archiver_prefs.rename);
1188         gtk_box_pack_start(GTK_BOX(hbox1), page->rename_files, FALSE, FALSE, 0);
1189         CLAWS_SET_TIP(page->rename_files,
1190                 _("Choose this option to use descriptive names for each file in the archive.\n"
1191                   "The naming scheme: date_from@to@subject.\n"
1192                   "Names will be truncated to max 96 characters"));
1193
1194         page->unlink_files = gtk_check_button_new_with_mnemonic(_("_Delete"));
1195         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(page->unlink_files), archiver_prefs.unlink);
1196         gtk_box_pack_start(GTK_BOX(hbox1), page->unlink_files, FALSE, FALSE, 0);
1197         CLAWS_SET_TIP(page->unlink_files,
1198                 _("Choose this option to delete mails after archiving\n"
1199                   "At this point only handles IMAP4, Local mbox and POP3"));
1200
1201
1202         frame = gtk_frame_new(_("Selection options"));
1203         gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
1204         gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
1205         gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0);
1206
1207         hbox1 = gtk_hbox_new(FALSE, 4);
1208         gtk_container_set_border_width(GTK_CONTAINER(hbox1), 4);
1209         gtk_container_add(GTK_CONTAINER(frame), hbox1);
1210
1211         file_label = gtk_label_new(_("Select mails before"));
1212         gtk_box_pack_start(GTK_BOX(hbox1), file_label, FALSE, FALSE, 0);
1213         
1214         page->isoDate = gtk_entry_new();
1215         gtk_widget_set_name(page->isoDate, "isoDate");
1216         gtk_box_pack_start(GTK_BOX(hbox1), page->isoDate, TRUE, TRUE, 0);
1217         CLAWS_SET_TIP(page->isoDate, 
1218                 _("Select emails before a certain date\n"
1219                   "Date must comply to ISO-8601 [YYYY-MM-DD]"));
1220
1221         g_signal_connect(G_OBJECT(folder_select), "clicked", 
1222                          G_CALLBACK(foldersel_cb), page);
1223         g_signal_connect(G_OBJECT(file_select), "clicked",
1224                          G_CALLBACK(filesel_cb), page);
1225         g_signal_connect(G_OBJECT(page->folder), "activate",
1226                          G_CALLBACK(entry_change_cb), page);
1227         g_signal_connect(G_OBJECT(page->file), "activate",
1228                          G_CALLBACK(entry_change_cb), page);
1229
1230         gtk_widget_show_all(dialog);
1231 }
1232
1233 void archiver_gtk_done(struct ArchivePage* page, GtkWidget* widget) {
1234         dispose_archive_page(page);
1235         free(progress);
1236         gtk_widget_destroy(widget);
1237         /*debug_set_mode(FALSE);*/
1238 }
1239