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