1 /*
2 * Copyright (C) 2008 Giuseppe Torelli - <colossus73@gmail.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301 USA.
18 */
19
20 #include "config.h"
21 #include <errno.h>
22 #include <stdint.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <gdk/gdkkeysyms.h>
26 #include <glib/gprintf.h>
27 #include <glib/gstdio.h>
28 #include <sys/stat.h>
29 #include "window.h"
30 #include "add_dialog.h"
31 #include "exe.h"
32 #include "extract_dialog.h"
33 #include "interface.h"
34 #include "main.h"
35 #include "mime.h"
36 #include "new_dialog.h"
37 #include "open-with-dlg.h"
38 #include "pref_dialog.h"
39 #include "string_utils.h"
40 #include "support.h"
41 #include "tar.h"
42
43 #ifdef __APPLE__
44 #include <libkern/OSByteOrder.h>
45 #define le32toh(x) OSSwapLittleToHostInt32(x)
46 #elif defined(__FreeBSD__)
47 #include <sys/endian.h>
48 #else
49 #include <endian.h>
50 #endif
51
52 #ifdef HAVE_SOCKET
53 #include "socket.h"
54 #endif
55
56 #define XDS_FILENAME "xds.txt"
57 #define bswap(word) (((word << 8) & 0xff00) | ((word >> 8) & 0x00ff))
58
59 gchar *current_open_directory;
60
61 static GtkWidget *comment_dialog;
62
xa_remove_columns(XArchive * archive)63 static void xa_remove_columns (XArchive *archive)
64 {
65 GList *columns = gtk_tree_view_get_columns ( GTK_TREE_VIEW (archive->treeview));
66 while (columns != NULL)
67 {
68 gtk_tree_view_remove_column (GTK_TREE_VIEW (archive->treeview),columns->data);
69 columns = columns->next;
70 }
71 g_list_free (columns);
72 }
73
xa_open_file_dialog()74 static gchar *xa_open_file_dialog ()
75 {
76 static GtkWidget *File_Selector = NULL;
77 static GtkFileFilter *open_file_filter;
78 GtkFileFilter *filter;
79 GSList *sorted;
80 gchar *path = NULL;
81 int response;
82
83 if (File_Selector == NULL)
84 {
85 File_Selector = gtk_file_chooser_dialog_new ( _("Open an archive"),
86 GTK_WINDOW (xa_main_window),
87 GTK_FILE_CHOOSER_ACTION_OPEN,
88 GTK_STOCK_CANCEL,
89 GTK_RESPONSE_CANCEL,
90 "gtk-open",
91 GTK_RESPONSE_ACCEPT,
92 NULL);
93
94 gtk_dialog_set_default_response (GTK_DIALOG (File_Selector),GTK_RESPONSE_ACCEPT);
95 gtk_window_set_destroy_with_parent (GTK_WINDOW (File_Selector) ,TRUE);
96
97 filter = gtk_file_filter_new ();
98 gtk_file_filter_set_name ( filter ,_("All files"));
99 gtk_file_filter_add_pattern ( filter,"*");
100 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (File_Selector),filter);
101
102 filter = gtk_file_filter_new ();
103 gtk_file_filter_set_name ( filter ,_("Only archives"));
104 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (File_Selector),filter);
105
106 sorted = xa_file_filter_add_archiver_pattern_sort(filter);
107
108 while (sorted)
109 {
110 filter = gtk_file_filter_new();
111 gtk_file_filter_set_name(filter, sorted->data);
112 gtk_file_filter_add_pattern(filter, sorted->data);
113 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(File_Selector), filter);
114 sorted = sorted->next;
115 }
116
117 g_slist_free(sorted);
118
119 gtk_window_set_modal (GTK_WINDOW (File_Selector),TRUE);
120 }
121 if (open_file_filter != NULL)
122 gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (File_Selector) ,open_file_filter);
123
124 if (current_open_directory != NULL)
125 gtk_file_chooser_set_current_folder ( GTK_FILE_CHOOSER (File_Selector) ,current_open_directory);
126
127 response = gtk_dialog_run (GTK_DIALOG (File_Selector));
128
129 if (current_open_directory != NULL)
130 g_free (current_open_directory);
131
132 current_open_directory = gtk_file_chooser_get_current_folder ( GTK_FILE_CHOOSER (File_Selector));
133 open_file_filter = gtk_file_chooser_get_filter ( GTK_FILE_CHOOSER (File_Selector));
134
135 if (response == GTK_RESPONSE_ACCEPT)
136 path = gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER (File_Selector));
137 else if ( (response == GTK_RESPONSE_CANCEL) || (response == GTK_RESPONSE_DELETE_EVENT))
138 path = NULL;
139
140 /* Hiding the window instead of destroying it will preserve the pointers to the file chooser stuff */
141 gtk_widget_hide (File_Selector);
142 return path;
143 }
144
xa_detect_archive_comment(int type,gchar * filename,XArchive * archive)145 static gboolean xa_detect_archive_comment (int type, gchar *filename, XArchive *archive)
146 {
147 FILE *stream;
148 char sig = '1';
149 guint cmt_len = 0;
150 int byte;
151 unsigned char eocds[] = { 0x50,0x4b,0x05,0x06 };
152 guint64 eocds_position = 0;
153
154 unsigned short int len = 0;
155 int eof;
156 size_t seqptr = 0;
157
158 stream = fopen (filename,"r");
159 if (stream == NULL)
160 return FALSE;
161
162 if (type == XARCHIVETYPE_ZIP)
163 {
164 /* Let's position the file indicator to 64KB before the end of the archive */
165 if (fseek(stream, -65535 - 22, SEEK_END) == -1)
166 fseek(stream, 0L, SEEK_SET);
167 /* Let's reach the end of central directory signature now */
168 while( ! feof(stream))
169 {
170 byte = (eof = fgetc(stream));
171 if (eof == EOF)
172 break;
173 if (byte == eocds[seqptr])
174 {
175 if (++seqptr == sizeof(eocds))
176 {
177 eocds_position = ftell(stream) + 16 ;
178 seqptr = 0;
179 }
180 continue;
181 }
182 else
183 {
184 if (seqptr)
185 seqptr = 0;
186 }
187 }
188 fseek (stream,eocds_position,SEEK_SET);
189 fread(&len, sizeof(len), 1, stream);
190 if (len == 0)
191 {
192 fclose(stream);
193 return FALSE;
194 }
195 else
196 {
197 archive->comment = g_string_new("");
198 while (cmt_len != len)
199 {
200 fread(&sig, sizeof(sig), 1, stream);
201 g_string_append_c (archive->comment,sig);
202 cmt_len++;
203 }
204 fclose(stream);
205 return TRUE;
206 }
207 }
208 else if (type == XARCHIVETYPE_ARJ)
209 {
210 /* Let's avoid the archive name */
211 fseek ( stream,39 ,SEEK_SET);
212 while (sig != 0)
213 {
214 fread(&sig, sizeof(sig), 1, stream);
215 cmt_len++;
216 }
217 fseek ( stream,39 + cmt_len ,SEEK_SET);
218 sig = 1;
219 /* Let's read the archive comment byte after byte now */
220 archive->comment = g_string_new("");
221 while (sig != 0)
222 {
223 fread(&sig, sizeof(sig), 1, stream);
224
225 if (sig == 0 && archive->comment->len == 0)
226 {
227 g_string_free (archive->comment,FALSE);
228 archive->comment = NULL;
229 fclose(stream);
230 return FALSE;
231 }
232 else
233 g_string_append_c (archive->comment,sig);
234 }
235 fclose(stream);
236 return TRUE;
237 }
238 fclose(stream);
239 return FALSE;
240 }
241
xa_set_size_string(guint64 file_size)242 static gchar *xa_set_size_string (guint64 file_size)
243 {
244 gchar *message = NULL;
245 gchar *measure;
246 double content_size;
247
248 if (file_size > 1024*1024*1024)
249 {
250 content_size = (double)file_size / (1024*1024*1024);
251 measure = "GB";
252 }
253 else if (file_size > 1024*1024)
254 {
255 content_size = (double)file_size / (1024*1024);
256 measure = "MB";
257 }
258
259 else if (file_size > 1024)
260 {
261 content_size = (double)file_size / 1024;
262 measure = "KB";
263 }
264 else
265 {
266 measure = "Bytes";
267 content_size = file_size;
268 }
269 message = g_strdup_printf ("%.1f %s",content_size,measure);
270 return message;
271 }
272
xa_print_entry_in_file(XEntry * entry,gint idx,FILE * stream,int bp)273 static void xa_print_entry_in_file (XEntry *entry, gint idx, FILE *stream, int bp)
274 {
275 gchar *path, *path_utf8;
276 static int x = 1;
277 guint i;
278 gpointer current_column;
279 guint64 file_size = 0;
280
281 if (!entry)
282 return;
283
284 if (entry->filename && !entry->is_dir)
285 {
286 current_column = entry->columns;
287 /* Let's retrieve the sizes of the entry from its column */
288 if (!g_utf8_validate(entry->filename, -1, NULL))
289 {
290 gchar *entry_utf8 = g_filename_display_name(entry->filename);
291 g_free(entry->filename);
292 entry->filename = entry_utf8;
293 }
294 path = xa_build_full_path_name_from_entry(entry);
295 path_utf8 = g_filename_display_name(path);
296 g_free(path);
297 if (strlen(path_utf8) == 0)
298 goto here;
299 for (i = 2; i < archive[idx]->columns - 1; i++)
300 {
301 switch(archive[idx]->column_types[i])
302 {
303 case G_TYPE_STRING:
304 current_column += sizeof(gchar *);
305 break;
306
307 case G_TYPE_UINT64:
308 file_size = (*((guint64 *)current_column));
309 current_column += sizeof(guint64);
310 break;
311 }
312 }
313 if (bp)
314 {
315 g_fprintf(stream,"<tr class=\"row%d\">",x);
316 g_fprintf(stream, "<td>%s</td><td>%" G_GUINT64_FORMAT "</td></tr>", path_utf8, file_size);
317 if (x == 2)
318 x = 1;
319 else
320 x = 2;
321 }
322 else
323 g_fprintf(stream, "%-90s %" G_GUINT64_FORMAT "\n", path_utf8, file_size);
324
325 g_free(path_utf8);
326 }
327 here:
328 xa_print_entry_in_file(entry->child,idx,stream,bp);
329 xa_print_entry_in_file(entry->next,idx,stream,bp);
330 }
331
xa_open_sfx_file_selector()332 static gchar *xa_open_sfx_file_selector ()
333 {
334 gchar *sfx_name = NULL;
335 GtkWidget *sfx_file_selector = NULL;
336 int response;
337
338 sfx_file_selector = gtk_file_chooser_dialog_new ( _("Save the self-extracting archive as"),
339 GTK_WINDOW (xa_main_window),
340 GTK_FILE_CHOOSER_ACTION_SAVE,
341 GTK_STOCK_CANCEL,
342 GTK_RESPONSE_CANCEL,
343 "gtk-save",
344 GTK_RESPONSE_ACCEPT,
345 NULL);
346
347 gtk_dialog_set_default_response (GTK_DIALOG (sfx_file_selector),GTK_RESPONSE_ACCEPT);
348 gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER (sfx_file_selector),TRUE);
349 response = gtk_dialog_run ( GTK_DIALOG(sfx_file_selector));
350
351 if (response == GTK_RESPONSE_ACCEPT)
352 sfx_name = gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER (sfx_file_selector));
353
354 gtk_widget_destroy (sfx_file_selector);
355 return sfx_name;
356 }
357
xa_activate_link(GtkAboutDialog * about,const gchar * link,gpointer user_data)358 static void xa_activate_link (GtkAboutDialog *about, const gchar *link, gpointer user_data)
359 {
360 if (!xdg_open)
361 {
362 gchar *browser_path = NULL;
363 browser_path = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(prefs_window->combo_prefered_web_browser));
364 if (!browser_path || !*browser_path)
365 {
366 xa_show_message_dialog (GTK_WINDOW (xa_main_window),GTK_DIALOG_MODAL,GTK_MESSAGE_INFO,GTK_BUTTONS_OK,_("You didn't set which browser to use!"),_("Please go to Preferences->Advanced and set it."));
367 g_free (browser_path);
368 return;
369 }
370 xa_launch_external_program(browser_path, link);
371 g_free(browser_path);
372 }
373 else
374 xa_launch_external_program(xdg_open, link);
375 }
376
xa_rename_cell_edited_canceled(GtkCellRenderer * renderer,gpointer user_data)377 static void xa_rename_cell_edited_canceled (GtkCellRenderer *renderer, gpointer user_data)
378 {
379 g_object_set(renderer,"editable",FALSE,NULL);
380 gtk_widget_add_accelerator(delete_menu, "activate", accel_group, GDK_KEY_Delete, (GdkModifierType) 0, GTK_ACCEL_VISIBLE);
381 }
382
xa_rename_cell_edited(GtkCellRendererText * cell,const gchar * path_string,const gchar * new_name,XArchive * archive)383 static void xa_rename_cell_edited (GtkCellRendererText *cell, const gchar *path_string, const gchar *new_name, XArchive *archive)
384 {
385 GtkTreeIter iter;
386 GtkTreeModel *model;
387 XEntry *entry;
388 gchar *old_name, *q_old_name, *q_new_name, *command;
389 GSList *names = NULL, *file_list;
390 gboolean result = FALSE;
391
392 model = gtk_tree_view_get_model(GTK_TREE_VIEW(archive->treeview));
393 if (gtk_tree_model_get_iter_from_string(model,&iter,path_string))
394 {
395 gtk_tree_model_get(model, &iter, archive->columns - 1, &entry, -1);
396 if (entry->is_encrypted)
397 {
398 if (!xa_check_password(archive))
399 goto done;
400 }
401 g_free(archive->extraction_dir);
402 xa_create_working_directory(archive);
403 archive->extraction_dir = g_strdup(archive->working_dir);
404 old_name = xa_build_full_path_name_from_entry(entry);
405 q_old_name = g_shell_quote(old_name);
406 names = g_slist_append(names,old_name);
407
408 archive->do_overwrite = archive->do_full_path = TRUE;
409
410 archive->status = XARCHIVESTATUS_EXTRACT;
411 result = (*archive->archiver->extract) (archive,names);
412
413 if (result == FALSE)
414 {
415 g_free(q_old_name);
416 goto done;
417 }
418 /* Rename the file in the tmp dir as the new file entered by the user */
419 q_new_name = g_shell_quote(new_name);
420 if (strcmp(q_new_name, q_old_name) == 0)
421 {
422 g_free(q_old_name);
423 g_free(q_new_name);
424 goto done;
425 }
426 command = g_strconcat("mv -f ", archive->working_dir, "/", q_old_name, " ", archive->working_dir, "/", q_new_name, NULL);
427 xa_run_command(archive, command);
428 g_free(command);
429 g_free(q_old_name);
430 g_free(q_new_name);
431
432 /* Delete the selected file from the archive */
433 old_name = xa_build_full_path_name_from_entry(entry);
434 file_list = g_slist_append(NULL, old_name);
435
436 archive->status = XARCHIVESTATUS_DELETE;
437 (*archive->archiver->delete)(archive, file_list);
438
439 /* Add the renamed file to the archive */
440 file_list = g_slist_append(NULL, g_strdup(new_name));
441 chdir(archive->working_dir);
442 xa_execute_add_commands(archive, file_list, FALSE, NULL);
443 }
444 done:
445 xa_rename_cell_edited_canceled(GTK_CELL_RENDERER(cell), NULL);
446 }
447
xa_get_archive_format(XArchive * archive)448 static const gchar *xa_get_archive_format (XArchive *archive)
449 {
450 gint pos;
451
452 pos = g_slist_index(archiver[archive->type].tags, GUINT_TO_POINTER(archive->tag));
453
454 if (pos >= 0)
455 return g_slist_nth_data(archiver[archive->type].tags, pos + 1);
456 else
457 return archiver[archive->type].type->data;
458 }
459
xa_get_statusbar_message(guint64 total_size,gint n_elem,gint dirs,gboolean selection)460 static gchar *xa_get_statusbar_message (guint64 total_size, gint n_elem, gint dirs, gboolean selection)
461 {
462 gchar *measure = NULL,*info = NULL;
463 gchar *text = "";
464
465 measure = xa_set_size_string(total_size);
466 if (selection)
467 text = _("selected");
468
469 if (dirs)
470 {
471 if (n_elem)
472 {
473 gchar *format = g_strconcat(ngettext("%d file", "%d files", n_elem), " ", _("and"), " ", ngettext("%d dir %s (%s)", "%d dirs %s (%s)", dirs), NULL);
474 info = g_strdup_printf(format, n_elem, dirs, text, measure);
475 g_free(format);
476 }
477 else
478 info = g_strdup_printf(ngettext ("%d dir %s (%s)","%d dirs %s (%s)",dirs),dirs,text,measure);
479 }
480 else
481 info = g_strdup_printf(ngettext ("%d file %s (%s)","%d files %s (%s)",n_elem),n_elem,text,measure);
482
483 g_free(measure);
484 return info;
485 }
486
xa_set_environment(gpointer display)487 static void xa_set_environment (gpointer display)
488 {
489 if (!g_getenv("WAYLAND_DISPLAY"))
490 g_setenv("DISPLAY", display, TRUE);
491 }
492
xa_determine_program_to_run(gchar * file)493 static void xa_determine_program_to_run (gchar *file)
494 {
495 gchar *program;
496
497 if (xdg_open)
498 program = g_strdup(xdg_open);
499 else
500 {
501 gchar *basename;
502 const char *type;
503
504 basename = g_path_get_basename(file);
505 type = xa_get_stock_mime_icon(basename);
506
507 if (strcmp(type, "text-html") == 0)
508 {
509 program = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(prefs_window->combo_prefered_web_browser));
510 }
511 else if (strcmp(type, "text-x-generic") == 0)
512 {
513 program = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(prefs_window->combo_prefered_editor));
514 }
515 else if (strcmp(type, "image-x-generic") == 0)
516 program = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(prefs_window->combo_prefered_viewer));
517 else if (strcmp(type, "package-x-generic") == 0)
518 program = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(prefs_window->combo_prefered_archiver));
519 else
520 {
521 gchar *basename_utf8 = g_filename_display_name(basename);
522 xa_create_open_with_dialog(basename_utf8, g_shell_quote(file), 1);
523 g_free(basename_utf8);
524 g_free(basename);
525 return;
526 }
527
528 g_free(basename);
529 }
530
531 if (program && *program)
532 {
533 gchar *q_file = g_shell_quote(file);
534 xa_launch_external_program(program, q_file);
535 g_free(q_file);
536 }
537 else
538 xa_show_message_dialog(GTK_WINDOW(xa_main_window), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, _("You didn't set which program to use for opening this file!"), _("Please go to Preferences->Advanced and set it."));
539
540 g_free(program);
541 }
542
xa_clear_comment_window(GtkButton * button,gpointer buf)543 static void xa_clear_comment_window (GtkButton *button, gpointer buf)
544 {
545 GtkTextIter start,end;
546
547 gtk_text_buffer_get_iter_at_offset(buf,&start,0);
548 gtk_text_buffer_get_end_iter(buf,&end);
549 gtk_text_buffer_delete(buf,&start,&end);
550 }
551
xa_load_comment_window_from_file(GtkButton * button,gpointer buf)552 static void xa_load_comment_window_from_file (GtkButton *button, gpointer buf)
553 {
554 GtkTextMark *textmark;
555 GtkTextIter iter;
556 GtkWidget *file;
557 gchar *path = NULL;
558 gchar *utf8_data = NULL;
559 gchar *content = NULL;
560 GError *error = NULL;
561 gboolean response;
562 gsize bytes;
563
564 file = gtk_file_chooser_dialog_new (_("Open a text file"),
565 GTK_WINDOW (xa_main_window),
566 GTK_FILE_CHOOSER_ACTION_OPEN,
567 GTK_STOCK_CANCEL,
568 GTK_RESPONSE_CANCEL,
569 "gtk-open",
570 GTK_RESPONSE_ACCEPT,
571 NULL);
572
573 response = gtk_dialog_run (GTK_DIALOG(file));
574 if (response == GTK_RESPONSE_ACCEPT)
575 path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(file));
576 gtk_widget_destroy (file);
577 if (path != NULL)
578 {
579 response = g_file_get_contents(path, &content, &bytes, &error);
580
581 if (response == FALSE)
582 {
583 gchar *msg = g_strdup_printf (_("Can't open file %s:"),path);
584 g_free(path);
585 response = xa_show_message_dialog (GTK_WINDOW (xa_main_window),GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,
586 msg,error->message);
587 g_free (msg);
588 g_error_free(error);
589 return;
590 }
591 g_free(path);
592
593 if (g_utf8_validate(content, -1, NULL))
594 utf8_data = content;
595 else
596 {
597 utf8_data = g_locale_to_utf8(content, -1, NULL, &bytes, NULL);
598 g_free(content);
599 }
600
601 textmark = gtk_text_buffer_get_insert(buf);
602 gtk_text_buffer_get_iter_at_mark(buf,&iter,textmark);
603 gtk_text_buffer_insert_with_tags_by_name (buf,&iter,utf8_data,bytes,"font",NULL);
604 g_free (utf8_data);
605 }
606 }
607
xa_comment_window_insert_in_archive(GtkButton * button,gpointer buf)608 static void xa_comment_window_insert_in_archive (GtkButton *button, gpointer buf)
609 {
610 GtkTextIter start,end;
611 FILE *stream;
612 gint idx;
613 gchar *command, *content, *tmp = NULL;
614
615 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
616
617 gtk_text_buffer_get_iter_at_offset(buf,&start,0);
618 gtk_text_buffer_get_end_iter(buf,&end);
619 content = gtk_text_buffer_get_text(buf,&start,&end,FALSE);
620
621 xa_create_working_directory(archive[idx]);
622 tmp = g_strconcat(archive[idx]->working_dir, "/xa-tmp.comment", NULL);
623 gtk_widget_destroy(comment_dialog);
624
625 if (archive[idx]->comment == NULL)
626 {
627 archive[idx]->comment = g_string_new("");
628 archive[idx]->has_comment = TRUE;
629 }
630 /* Return if the user hasn't modified the comment */
631 if (strcmp(archive[idx]->comment->str,content) == 0)
632 return;
633
634 stream = fopen (tmp,"w");
635
636 if (stream == NULL)
637 {
638 g_free(tmp);
639 return;
640 }
641
642 fwrite(content, strlen(content), 1, stream);
643 fclose (stream);
644
645 switch (archive[idx]->type)
646 {
647 case XARCHIVETYPE_ARJ:
648 command = g_strconcat ("arj c ",archive[idx]->path[1]," -z",tmp,NULL);
649 break;
650
651 case XARCHIVETYPE_RAR:
652 command = g_strconcat ("rar c ",archive[idx]->path[1]," -z",tmp,NULL);
653 break;
654
655 case XARCHIVETYPE_ZIP:
656 command = g_strconcat ("sh -c \"zip ",archive[idx]->path[1]," -z <",tmp,"\"",NULL);
657 break;
658
659 default:
660 command = NULL;
661 break;
662 }
663 if (strlen(archive[idx]->comment->str) > 0)
664 g_string_erase(archive[idx]->comment,0,strlen(archive[idx]->comment->str));
665 if (strlen(content) > 0)
666 g_string_append(archive[idx]->comment,content);
667
668 if (command != NULL)
669 {
670 xa_run_command(archive[idx], command);
671 g_free(command);
672 }
673 g_free(tmp);
674 }
675
xa_clipboard_data_new()676 static XAClipboard *xa_clipboard_data_new ()
677 {
678 XAClipboard *data = NULL;
679
680 data = g_new0(XAClipboard,1);
681
682 return data;
683 }
684
xa_get_paste_data_from_clipboard_selection(const guchar * data)685 static XAClipboard *xa_get_paste_data_from_clipboard_selection (const guchar *data)
686 {
687 gchar **uris;
688 gint i;
689 XAClipboard *clipboard_data;
690
691 clipboard_data = xa_clipboard_data_new();
692 uris = g_strsplit((const gchar *) data,"\r\n",-1);
693 clipboard_data->mode = (strcmp(uris[0], "copy") == 0 ? XA_CLIPBOARD_COPY : XA_CLIPBOARD_CUT);
694 sscanf(uris[1], "%p", &clipboard_data->target);
695 for (i = 2; uris[i]; i++)
696 if (uris[i][0] != '\0')
697 clipboard_data->files = g_slist_prepend (clipboard_data->files,g_strdup (uris[i]));
698 clipboard_data->files = g_slist_reverse (clipboard_data->files);
699 g_strfreev(uris);
700 return clipboard_data;
701 }
702
xa_clipboard_get(GtkClipboard * clipboard,GtkSelectionData * selection_data,guint info,XArchive * archive)703 static void xa_clipboard_get (GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, XArchive *archive)
704 {
705 GSList *files = archive->clipboard->files;
706 GString *params = g_string_new("");
707 if (gtk_selection_data_get_target(selection_data) != XA_INFO_LIST)
708 return;
709
710 g_string_append(params, archive->clipboard->mode == XA_CLIPBOARD_COPY ? "copy" : "cut");
711 g_string_append (params,"\r\n");
712 g_string_append_printf (params,"%p",archive);
713 g_string_append (params,"\r\n");
714
715 while (files)
716 {
717 g_string_append(params, files->data);
718 g_string_append (params,"\r\n");
719 files = files->next;
720 }
721 gtk_selection_data_set(selection_data, gtk_selection_data_get_target(selection_data), 8, (guchar *) params->str, strlen(params->str));
722 g_string_free (params,TRUE);
723 }
724
xa_clipboard_cut_copy_operation(XArchive * archive,XAClipboardMode mode)725 static void xa_clipboard_cut_copy_operation (XArchive *archive, XAClipboardMode mode)
726 {
727 GtkClipboard *clipboard;
728 XAClipboard *clipboard_data = NULL;
729 GSList *files = NULL;
730 GtkTreeSelection *selection;
731 GtkTargetEntry targets[] =
732 {
733 { "application/xarchiver-info-list",0,1 }
734 };
735
736 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(archive->treeview));
737 gtk_tree_selection_selected_foreach(selection,(GtkTreeSelectionForeachFunc) xa_concat_selected_filenames,&files);
738
739 clipboard = gtk_clipboard_get (XA_CLIPBOARD);
740 clipboard_data = xa_clipboard_data_new();
741 if (clipboard_data == NULL)
742 return;
743
744 clipboard_data->files = xa_slist_copy(files);
745 clipboard_data->mode = mode;
746 gtk_clipboard_set_with_data(clipboard, targets, G_N_ELEMENTS(targets), (GtkClipboardGetFunc) xa_clipboard_get, (GtkClipboardClearFunc) xa_clipboard_clear, archive);
747 archive->clipboard = clipboard_data;
748 gtk_widget_set_sensitive(paste,TRUE);
749
750 /* Let's extract the selected files to the archive tmp dir */
751 if (archive->has_password)
752 {
753 if (!xa_check_password(archive))
754 return;
755 }
756 g_free(archive->extraction_dir);
757 xa_create_working_directory(archive);
758 archive->extraction_dir = g_strdup(archive->working_dir);
759 archive->do_full_path = TRUE;
760 archive->do_overwrite = TRUE;
761
762 archive->status = XARCHIVESTATUS_EXTRACT;
763 (*archive->archiver->extract) (archive,files);
764 }
765
xa_expand_containing_directory(XArchive * archive)766 static void xa_expand_containing_directory (XArchive *archive)
767 {
768 if (xa_has_containing_directory(archive))
769 {
770 GtkTreePath *path;
771 GtkTreeSelection *selection;
772
773 path = gtk_tree_path_new_first();
774 gtk_tree_view_expand_to_path(GTK_TREE_VIEW(archive_dir_treeview), path);
775 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(archive_dir_treeview));
776 gtk_tree_selection_select_path(selection, path);
777 gtk_tree_selection_unselect_path(selection, path);
778 gtk_tree_path_free(path);
779 }
780 }
781
xa_child_processed(XAChildProcess process,gboolean success,XArchive * archive)782 void xa_child_processed (XAChildProcess process, gboolean success, XArchive *archive)
783 {
784 static gboolean okay[XA_CHILD_PROCS];
785
786 okay[process] = success;
787
788 if (process == XA_CHILD_EXIT)
789 {
790 archive->child_pid = 0;
791
792 if (xa_main_window)
793 {
794 gtk_widget_set_sensitive(Stop_button, FALSE);
795 xa_set_button_state(1, 1, 1, 1, archive->can_test, 1, archive->can_add, archive->can_extract, archive->sorted, archive->can_sfx, archive->has_comment, archive->output, archive->has_password);
796 }
797 }
798
799 if (--archive->child_ref == 0)
800 {
801 if (archive->output)
802 archive->output = g_slist_reverse(archive->output);
803
804 if (okay[XA_CHILD_EXIT] && okay[XA_CHILD_STDOUT] && okay[XA_CHILD_STDERR])
805 {
806 if (xa_main_window)
807 {
808 if (archive->parse_output)
809 {
810 xa_block_signal_dir_treeview_selection(TRUE);
811 gtk_widget_grab_focus(archive_dir_treeview);
812 xa_block_signal_dir_treeview_selection(FALSE);
813 xa_update_window_with_archive_entries(archive, NULL);
814 xa_expand_containing_directory(archive);
815 gtk_tree_view_set_model(GTK_TREE_VIEW(archive->treeview), archive->model);
816 g_object_unref(archive->model);
817 }
818
819 xa_set_statusbar_message_for_displayed_rows(archive);
820
821 if (archive->status == XARCHIVESTATUS_LIST && archive->has_comment && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prefs_window->check_show_comment)))
822 xa_show_archive_comment(NULL, NULL);
823
824 if (archive->status == XARCHIVESTATUS_TEST)
825 {
826 if (archive->output)
827 xa_show_archive_output(GUINT_TO_POINTER(TRUE), archive);
828 else
829 xa_show_message_dialog(GTK_WINDOW(xa_main_window), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, _("Test result:"), _("The archive is okay."));
830 }
831 }
832
833 archive->parse_output = NULL;
834 archive->status = XARCHIVESTATUS_IDLE;
835 }
836 else
837 {
838 if (xa_main_window && archive->parse_output)
839 {
840 xa_update_window_with_archive_entries(archive, NULL);
841 archive->parse_output = NULL;
842 }
843
844 if (xa_main_window && !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prefs_window->store_output)))
845 xa_show_message_dialog(GTK_WINDOW(xa_main_window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("An error occurred!"), _("Please check the 'Store archiver output' option to see it."));
846 else
847 xa_show_archive_output(NULL, archive);
848
849 if (xa_main_window)
850 gtk_label_set_text(GTK_LABEL(total_label), _("An error occurred!"));
851
852 /* in case the user has supplied a wrong password, reset it so they can try again */
853 if (archive->password && (archive->status == XARCHIVESTATUS_TEST || archive->status == XARCHIVESTATUS_SFX))
854 {
855 g_free(archive->password);
856 archive->password = NULL;
857 }
858
859 archive->status = XARCHIVESTATUS_ERROR;
860 }
861 }
862 }
863
xa_reload_archive_content(XArchive * this_archive)864 void xa_reload_archive_content (XArchive *this_archive)
865 {
866 XEntry *entry;
867
868 g_slist_free(this_archive->forward);
869 this_archive->forward = NULL;
870
871 g_slist_free(this_archive->back);
872 this_archive->back = NULL;
873
874 xa_free_entry(this_archive, this_archive->root_entry);
875
876 g_free(this_archive->column_types);
877 xa_remove_columns(this_archive);
878
879 entry = g_new0(XEntry,1);
880 entry->filename = "";
881 this_archive->root_entry = entry;
882
883 gtk_label_set_text(GTK_LABEL(total_label), _("Reloading archive, please wait..."));
884
885 /* this reload will be called internally during adding and deleting */
886 this_archive->status = XARCHIVESTATUS_RELOAD;
887 (*this_archive->archiver->list)(this_archive);
888 }
889
xa_show_archive_output(GtkMenuItem * menuitem,XArchive * this_archive)890 void xa_show_archive_output (GtkMenuItem *menuitem, XArchive *this_archive)
891 {
892 GSList *output = NULL;
893 gchar *title = NULL, *cmd;
894 GtkWidget *dialog, *show_cmd, *label, *image, *hbox, *vbox, *textview, *scrolledwindow;
895 GtkTextBuffer *textbuffer;
896 GtkTextIter iter;
897 gint response;
898
899 if (this_archive == NULL)
900 {
901 gint idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
902
903 if (idx < 0)
904 return;
905 this_archive = archive[idx];
906 }
907
908 if (xa_main_window)
909 title = _("Archiver output");
910 else
911 title = PACKAGE_NAME " " VERSION;
912
913 dialog = gtk_dialog_new_with_buttons(title, GTK_WINDOW(xa_main_window), GTK_DIALOG_MODAL, NULL, NULL);
914
915 show_cmd = gtk_dialog_add_button(GTK_DIALOG(dialog), _("Show command"), GTK_RESPONSE_APPLY);
916 gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OK, GTK_RESPONSE_OK);
917 gtk_dialog_set_default_response (GTK_DIALOG (dialog),GTK_RESPONSE_OK);
918
919 gtk_container_set_border_width (GTK_CONTAINER (dialog),6);
920 gtk_container_set_border_width(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), 6);
921 gtk_box_set_spacing(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), 8);
922 gtk_widget_set_size_request(dialog, 672, 420);
923
924 scrolledwindow = gtk_scrolled_window_new (NULL,NULL);
925 g_object_set (G_OBJECT (scrolledwindow),"hscrollbar-policy",GTK_POLICY_AUTOMATIC,"shadow-type",GTK_SHADOW_IN,"vscrollbar-policy",GTK_POLICY_AUTOMATIC,NULL);
926 gtk_widget_set_size_request (scrolledwindow,-1,200);
927
928 textbuffer = gtk_text_buffer_new (NULL);
929 gtk_text_buffer_create_tag (textbuffer,"font","family","monospace",NULL);
930 gtk_text_buffer_get_iter_at_offset (textbuffer,&iter,0);
931
932 textview = gtk_text_view_new_with_buffer (textbuffer);
933 g_object_unref (textbuffer);
934 gtk_text_view_set_editable (GTK_TEXT_VIEW (textview),FALSE);
935 gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (textview),FALSE);
936
937 vbox = gtk_vbox_new (FALSE,6);
938 gtk_container_set_border_width (GTK_CONTAINER (vbox),5);
939
940 if (!menuitem)
941 {
942 image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_ERROR,GTK_ICON_SIZE_DIALOG);
943 gtk_misc_set_alignment (GTK_MISC (image),0.5,0.0);
944
945 label = gtk_label_new (_("An error occurred while accessing the archive:"));
946 hbox = gtk_hbox_new (FALSE,6);
947 gtk_box_pack_start (GTK_BOX (hbox),image,FALSE,FALSE,0);
948 gtk_box_pack_start (GTK_BOX (hbox),label,TRUE,TRUE,0);
949 gtk_box_pack_start (GTK_BOX (vbox),hbox,FALSE,FALSE,0);
950 }
951 gtk_container_add (GTK_CONTAINER (scrolledwindow),textview);
952 gtk_box_pack_start (GTK_BOX (vbox),scrolledwindow,TRUE,TRUE,0);
953 gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), vbox, TRUE, TRUE, 0);
954
955 output = this_archive->output;
956 while (output)
957 {
958 gtk_text_buffer_insert_with_tags_by_name(textbuffer, &iter, output->data, -1, "font", NULL);
959 output = output->next;
960 }
961 gtk_widget_show_all (vbox);
962
963 run_dialog:
964 response = gtk_dialog_run(GTK_DIALOG(dialog));
965
966 if (response == GTK_RESPONSE_APPLY)
967 {
968 gtk_text_buffer_get_iter_at_offset(textbuffer, &iter, 0);
969 cmd = g_strdup_printf("%s: %s\n\n", _("Command"), this_archive->command);
970 gtk_text_buffer_insert_with_tags_by_name(textbuffer, &iter, cmd, -1, "font", NULL);
971 g_free(cmd);
972 gtk_widget_hide(show_cmd);
973 goto run_dialog;
974 }
975
976 gtk_widget_destroy (GTK_WIDGET (dialog));
977 }
978
xa_new_archive(GtkMenuItem * menuitem,gpointer user_data)979 void xa_new_archive (GtkMenuItem *menuitem,gpointer user_data)
980 {
981 gint current_page;
982
983 current_page = xa_get_new_archive_idx();
984 if (current_page == -1)
985 return;
986
987 archive[current_page] = xa_new_archive_dialog(NULL, archive);
988
989 if (archive[current_page] == NULL)
990 return;
991
992 xa_add_page (archive[current_page]);
993 xa_set_button_state(1, 1, 1, 1, archive[current_page]->can_test, 1, archive[current_page]->can_add, archive[current_page]->can_extract, archive[current_page]->sorted, archive[current_page]->can_sfx, archive[current_page]->has_comment, archive[current_page]->output, archive[current_page]->has_password);
994 xa_disable_delete_buttons(FALSE);
995
996 xa_set_window_title(xa_main_window, archive[current_page]->path[0]);
997 gtk_label_set_text(GTK_LABEL(total_label),"");
998 }
999
xa_show_message_dialog(GtkWindow * window,int mode,int type,int button,const gchar * message1,const gchar * message2)1000 int xa_show_message_dialog (GtkWindow *window,int mode,int type,int button,const gchar *message1,const gchar *message2)
1001 {
1002 GtkWidget *dialog;
1003 int response;
1004
1005 dialog = gtk_message_dialog_new (window,mode,type,button,"%s",message1);
1006 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),"%s",message2);
1007 response = gtk_dialog_run (GTK_DIALOG (dialog));
1008 gtk_widget_destroy (GTK_WIDGET (dialog));
1009 return response;
1010 }
1011
xa_save_archive(GtkMenuItem * menuitem,gpointer user_data)1012 void xa_save_archive (GtkMenuItem *menuitem, gpointer user_data)
1013 {
1014 gint idx;
1015 GtkWidget *save = NULL;
1016 gchar *path = NULL, *command, *filename, *filename_utf8;
1017 int response;
1018
1019 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
1020
1021 save = gtk_file_chooser_dialog_new (_("Save the archive as"),
1022 GTK_WINDOW (xa_main_window),
1023 GTK_FILE_CHOOSER_ACTION_SAVE,
1024 GTK_STOCK_CANCEL,
1025 GTK_RESPONSE_CANCEL,
1026 "gtk-save",
1027 GTK_RESPONSE_ACCEPT,
1028 NULL);
1029 filename = g_path_get_basename(archive[idx]->path[1]);
1030 filename_utf8 = g_filename_display_name(filename);
1031 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(save), filename_utf8);
1032 gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER (save),TRUE);
1033 g_free(filename_utf8);
1034 g_free(filename);
1035 response = gtk_dialog_run (GTK_DIALOG(save));
1036 if (response == GTK_RESPONSE_ACCEPT)
1037 path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(save));
1038 gtk_widget_destroy (save);
1039 if (path != NULL)
1040 {
1041 command = g_strconcat ("cp ",archive[idx]->path[1]," ",path,NULL);
1042 g_free(path);
1043 xa_run_command(archive[idx], command);
1044 g_free(command);
1045 }
1046 }
1047
xa_open_archive(GtkWidget * widget,gchar * path)1048 void xa_open_archive (GtkWidget *widget, gchar *path)
1049 {
1050 gchar *utf8_path,*msg;
1051 gint current_page;
1052 gint x;
1053 ArchiveType xa;
1054
1055 if (path == NULL)
1056 {
1057 path = xa_open_file_dialog ();
1058 if (path == NULL)
1059 return;
1060 }
1061
1062 /* Let's check if the archive is already opened */
1063 for (x = 0; x < gtk_notebook_get_n_pages (notebook); x++)
1064 {
1065 current_page = xa_find_archive_index (x);
1066 if (current_page == -1)
1067 break;
1068 if (strcmp(path, archive[current_page]->path[0]) == 0)
1069 {
1070 g_free (path);
1071 gtk_notebook_set_current_page (notebook,current_page);
1072 return;
1073 }
1074 }
1075 xa = xa_detect_archive_type(path);
1076
1077 if (xa.type == XARCHIVETYPE_UNKNOWN || xa.type == XARCHIVETYPE_NOT_FOUND)
1078 {
1079 utf8_path = g_filename_to_utf8 (path,-1,NULL,NULL,NULL);
1080 msg = g_strdup_printf (_("Can't open file \"%s\":"),utf8_path);
1081 if (xa.type == XARCHIVETYPE_UNKNOWN)
1082 xa_show_message_dialog (GTK_WINDOW (xa_main_window),GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,msg,_("Archive format is not recognized!"));
1083 else
1084 xa_show_message_dialog (GTK_WINDOW (xa_main_window),GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,msg,g_strerror(errno));
1085
1086 g_free (utf8_path);
1087 g_free (msg);
1088 g_free (path);
1089 return;
1090 }
1091
1092 if (!archiver[xa.type].list)
1093 {
1094 xa_show_message_dialog(GTK_WINDOW(xa_main_window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Sorry, this archive format is not supported:"), _("The proper archiver is not installed!"));
1095 g_free(path);
1096 return;
1097 }
1098
1099 current_page = xa_get_new_archive_idx();
1100 if (current_page == -1)
1101 {
1102 g_free (path);
1103 return;
1104 }
1105 archive[current_page] = xa_init_archive_structure(xa);
1106 if (archive[current_page] == NULL)
1107 {
1108 xa_show_message_dialog (GTK_WINDOW (xa_main_window),GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_("Can't allocate memory for the archive structure:"),_("Operation aborted!"));
1109 g_free (path);
1110 return;
1111 }
1112 /* Detect archive comment,rar one is detected in rar.c */
1113 if (xa.type == XARCHIVETYPE_ZIP)
1114 archive[current_page]->has_comment = xa_detect_archive_comment (XARCHIVETYPE_ZIP,path,archive[current_page]);
1115 else if (xa.type == XARCHIVETYPE_ARJ)
1116 archive[current_page]->has_comment = xa_detect_archive_comment (XARCHIVETYPE_ARJ,path,archive[current_page]);
1117
1118 if (g_path_is_absolute(path) == FALSE)
1119 archive[current_page]->path[0] = g_strconcat(g_get_current_dir() ,"/", path, NULL);
1120 else
1121 archive[current_page]->path[0] = g_strdup(path);
1122
1123 archive[current_page]->path[1] = xa_escape_bad_chars(archive[current_page]->path[0], ESCAPES);
1124 xa_add_page (archive[current_page]);
1125
1126 xa_disable_delete_buttons (FALSE);
1127 g_free (path);
1128
1129 xa_set_button_state(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, 0);
1130 gtk_label_set_text(GTK_LABEL(total_label),_("Opening archive, please wait..."));
1131
1132 archive[current_page]->status = XARCHIVESTATUS_LIST;
1133 (*archive[current_page]->archiver->list)(archive[current_page]);
1134 }
1135
xa_test_archive(GtkMenuItem * menuitem,gpointer user_data)1136 void xa_test_archive (GtkMenuItem *menuitem,gpointer user_data)
1137 {
1138 gint idx;
1139
1140 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
1141
1142 if (archive[idx]->has_password)
1143 {
1144 if (!xa_check_password(archive[idx]))
1145 return;
1146 }
1147 gtk_label_set_text(GTK_LABEL(total_label),_("Testing archive, please wait..."));
1148
1149 archive[idx]->status = XARCHIVESTATUS_TEST;
1150 (*archive[idx]->archiver->test)(archive[idx]);
1151 }
1152
xa_list_archive(GtkMenuItem * menuitem,gpointer data)1153 void xa_list_archive (GtkMenuItem *menuitem,gpointer data)
1154 {
1155 unsigned short int bp = GPOINTER_TO_UINT(data);
1156 gint idx;
1157 FILE *stream;
1158 GtkWidget *save = NULL;
1159 gchar *t, *_filename, *filename, *filename_plus, *filename_plus_utf8, *pref_path, *pref_path_local = NULL;
1160 int response;
1161 struct stat my_stat;
1162 guint64 file_size;
1163
1164 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
1165
1166 if (bp)
1167 _filename = _("Print the archive content as HTML");
1168 else
1169 _filename = _("Print the archive content as text");
1170
1171 save = gtk_file_chooser_dialog_new (_filename,
1172 GTK_WINDOW (xa_main_window),
1173 GTK_FILE_CHOOSER_ACTION_SAVE,
1174 GTK_STOCK_CANCEL,
1175 GTK_RESPONSE_CANCEL,
1176 "gtk-save",
1177 GTK_RESPONSE_ACCEPT,
1178 NULL);
1179
1180 filename = g_path_get_basename(archive[idx]->path[1]);
1181 _filename = strstr(filename,".");
1182 if (_filename)
1183 _filename = g_strndup(filename,(_filename-filename));
1184 else
1185 _filename = filename;
1186
1187 filename_plus = g_strconcat (_filename,bp ? ".html" : ".txt",NULL);
1188 filename_plus_utf8 = g_filename_display_name(filename_plus);
1189 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(save), filename_plus_utf8);
1190 gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER (save),TRUE);
1191 g_free(filename);
1192 g_free(filename_plus);
1193 g_free(filename_plus_utf8);
1194 filename = NULL;
1195
1196 pref_path = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(prefs_window->combo_prefered_extract_dir));
1197
1198 if (pref_path && *pref_path)
1199 pref_path_local = g_filename_from_utf8(pref_path, -1, NULL, NULL, NULL);
1200 g_free(pref_path);
1201
1202 if (current_open_directory || pref_path_local)
1203 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(save), pref_path_local ? pref_path_local : current_open_directory);
1204 g_free(pref_path_local);
1205 response = gtk_dialog_run (GTK_DIALOG(save));
1206
1207 if (current_open_directory != NULL)
1208 g_free (current_open_directory);
1209
1210 current_open_directory = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(save));
1211
1212 if (response == GTK_RESPONSE_ACCEPT)
1213 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(save));
1214 gtk_widget_destroy (save);
1215
1216 if (filename != NULL)
1217 {
1218 stream = fopen (filename,"w");
1219 g_free(filename);
1220
1221 if (stream == NULL)
1222 return;
1223
1224 filename = g_filename_display_name(archive[idx]->path[1]);
1225 if (bp)
1226 {
1227 g_fprintf(stream, "<html><head><meta charset=\"UTF-8\"><meta name=GENERATOR content=\"" PACKAGE_NAME " " VERSION "\"><title>%s</title>\n", filename);
1228 g_fprintf (stream,"<style>\ntd { font: normal .7em ; }\nth { font: bold 0.7em ; color: #FFFFFF; text-align: left; background: #42578A}\n.row1 { background-color: #DDDDDD; }\n.row2 { background-color: #EEEEEE; }\n</style>\n");
1229 g_fprintf(stream,"</head>");
1230 g_fprintf (stream,"<body bgcolor=#FFFFFF>\n");
1231 g_fprintf (stream,"<b><u>");
1232 }
1233 g_fprintf (stream,_("Archive content:\n"));
1234
1235 if (bp)
1236 g_fprintf(stream, "</u></b><br><br><b>");
1237 g_fprintf (stream,_("\nName: "));
1238 if (bp)
1239 g_fprintf(stream, "</b><a href=\"file://%s\">", filename);
1240 g_fprintf(stream, "%s\n", filename);
1241 if (bp)
1242 g_fprintf(stream,"</a><br><br><b>");
1243 stat(archive[idx]->path[0], &my_stat);
1244 file_size = my_stat.st_size;
1245 t = xa_set_size_string(file_size);
1246 g_fprintf (stream,_("Compressed size: "));
1247 if (bp)
1248 g_fprintf (stream,"</b>");
1249 g_fprintf (stream,"%s\n",t);
1250 g_free(t);
1251 if (bp)
1252 g_fprintf(stream,"<br><br><b>");
1253 g_fprintf (stream,_("Uncompressed size: "));
1254 t = xa_set_size_string(archive[idx]->files_size);
1255 if (bp)
1256 g_fprintf (stream,"</b>");
1257 g_fprintf (stream,"%s\n",t);
1258 g_free(t);
1259 if (bp)
1260 g_fprintf(stream,"<br><br><b>");
1261 g_fprintf (stream,_("Number of files: "));
1262 if (bp)
1263 g_fprintf(stream,"</b>");
1264 g_fprintf(stream, "%u\n", archive[idx]->files);
1265 if (bp)
1266 g_fprintf(stream,"<br><br><b>");
1267 if (archive[idx]->has_comment)
1268 {
1269 g_fprintf (stream,_("Comment:\n"));
1270 if (bp)
1271 g_fprintf(stream,"</b><pre>");
1272 g_fprintf (stream,"%s",archive[idx]->comment->str);
1273 if (bp)
1274 g_fprintf(stream,"</pre>");
1275 g_fprintf (stream,"\n");
1276 if (bp)
1277 g_fprintf(stream,"<br>");
1278 }
1279 if ( ! bp)
1280 {
1281 g_fprintf (stream,"-------------------------------------------------------------------------------------------------------------\n");
1282 g_fprintf(stream, _("Files:%*s%s"), 80, " ", _("|Size\n"));
1283 g_fprintf (stream,"-------------------------------------------------------------------------------------------------------------\n");
1284 }
1285 else
1286 {
1287 g_fprintf(stream,"<br><table border=0 cellpadding=6 cellspacing=1><tr>");
1288 g_fprintf(stream,_("<th>Files:</th>"));
1289 g_fprintf(stream, _("<th>Size:</th>"));
1290 g_fprintf(stream, "</tr>");
1291
1292 }
1293 xa_print_entry_in_file(archive[idx]->root_entry,idx,stream,bp);
1294 if (bp)
1295 g_fprintf (stream,"</table></body></html>");
1296
1297 g_free(filename);
1298 fclose (stream);
1299 }
1300 }
1301
xa_close_archive(GtkWidget * widget,gpointer page)1302 void xa_close_archive (GtkWidget *widget, gpointer page)
1303 {
1304 gint current_page;
1305 gint idx;
1306
1307 current_page = gtk_notebook_page_num(notebook, page);
1308 idx = xa_find_archive_index (current_page);
1309 gtk_notebook_remove_page ( notebook ,current_page);
1310
1311 current_page = gtk_notebook_get_n_pages(notebook);
1312 if (current_page == 0)
1313 {
1314 gtk_widget_set_sensitive (up_button,FALSE);
1315 gtk_widget_set_sensitive (home_button,FALSE);
1316 gtk_widget_set_sensitive (deselect_all,FALSE);
1317 xa_disable_delete_buttons (FALSE);
1318 xa_set_button_state(1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, 0);
1319 xa_set_window_title (xa_main_window,NULL);
1320 gtk_tree_store_clear(archive_dir_treestore);
1321 gtk_entry_set_text(GTK_ENTRY(location_entry),"");
1322 gtk_label_set_text(GTK_LABEL(total_label),_("Select \"New\" to create or \"Open\" to open an archive"));
1323 gtk_widget_hide(selected_frame);
1324 }
1325 else if ( current_page == 1)
1326 gtk_notebook_set_show_tabs (notebook,FALSE);
1327 else
1328 gtk_notebook_set_show_tabs (notebook,TRUE);
1329
1330 xa_clean_archive_structure (archive[idx]);
1331 archive[idx] = NULL;
1332 }
1333
xa_quit_application(GtkWidget * widget,GdkEvent * event,gpointer user_data)1334 void xa_quit_application (GtkWidget *widget, GdkEvent *event, gpointer user_data)
1335 {
1336 gint i;
1337 gint idx;
1338
1339 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
1340
1341 if (idx > -1 && archive[idx]->child_pid)
1342 return;
1343
1344 for (i = 0; i < gtk_notebook_get_n_pages(notebook) ; i++)
1345 {
1346 idx = xa_find_archive_index (i);
1347 if (archive[idx] != NULL)
1348 {
1349 xa_clean_archive_structure (archive[idx]);
1350 archive[idx] = NULL;
1351 }
1352 }
1353
1354 if (current_open_directory != NULL)
1355 g_free (current_open_directory);
1356
1357 xa_prefs_save_options (prefs_window,config_file);
1358 gtk_widget_destroy(prefs_window->dialog1);
1359 g_free(prefs_window);
1360
1361 gtk_widget_destroy (extract_window->dialog1);
1362 g_free(extract_window);
1363
1364 gtk_widget_destroy (add_window->dialog1);
1365 g_free(add_window);
1366
1367 gtk_widget_destroy (multi_extract_window->multi_extract);
1368 g_free(multi_extract_window);
1369
1370 gtk_widget_destroy(xa_popup_menu);
1371 g_free (config_file);
1372 xa_free_icon_cache();
1373
1374 #ifdef HAVE_SOCKET
1375 socket_finalize();
1376 #endif
1377 gtk_main_quit();
1378 return;
1379 }
1380
xa_delete_archive(GtkMenuItem * menuitem,gpointer user_data)1381 void xa_delete_archive (GtkMenuItem *menuitem,gpointer user_data)
1382 {
1383 GList *row_list = NULL;
1384 XEntry *entry = NULL;
1385 GtkTreeIter iter;
1386 GSList *list = NULL;
1387 gint idx, response;
1388
1389 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
1390
1391 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(archive[idx]->treeview));
1392
1393 row_list = gtk_tree_selection_get_selected_rows(selection, &archive[idx]->model);
1394 if (row_list != NULL)
1395 {
1396 while (row_list)
1397 {
1398 gtk_tree_model_get_iter(archive[idx]->model, &iter, row_list->data);
1399 gtk_tree_model_get(archive[idx]->model, &iter, archive[idx]->columns - 1, &entry, -1);
1400 gtk_tree_path_free (row_list->data);
1401
1402 list = g_slist_prepend(list, xa_build_full_path_name_from_entry(entry));
1403
1404 if (entry->is_dir)
1405 xa_fill_list_with_recursed_entries(entry->child, &list);
1406
1407 row_list = row_list->next;
1408 }
1409 g_list_free (row_list);
1410 }
1411 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prefs_window->confirm_deletion)))
1412 {
1413 response = xa_show_message_dialog (GTK_WINDOW (xa_main_window),GTK_DIALOG_MODAL,GTK_MESSAGE_QUESTION,GTK_BUTTONS_OK_CANCEL,_("You are about to delete entries from the archive."),_( "Are you sure you want to do this?"));
1414 if (response == GTK_RESPONSE_CANCEL || response == GTK_RESPONSE_DELETE_EVENT)
1415 return;
1416 }
1417
1418 archive[idx]->status = XARCHIVESTATUS_DELETE;
1419 (*archive[idx]->archiver->delete)(archive[idx], list);
1420 xa_reload_archive_content(archive[idx]);
1421 }
1422
xa_add_files_archive(GtkMenuItem * menuitem,gpointer user_data)1423 void xa_add_files_archive (GtkMenuItem *menuitem, gpointer user_data)
1424 {
1425 gint idx;
1426
1427 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
1428
1429 xa_set_add_dialog_options(add_window,archive[idx]);
1430 xa_parse_add_dialog_options (archive[idx],add_window);
1431 }
1432
xa_extract_archive(GtkMenuItem * menuitem,gpointer user_data)1433 void xa_extract_archive (GtkMenuItem *menuitem,gpointer user_data)
1434 {
1435 gint idx, selected;
1436
1437 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
1438
1439 GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(archive[idx]->treeview));
1440 selected = gtk_tree_selection_count_selected_rows (selection);
1441 xa_set_extract_dialog_options(extract_window,selected,archive[idx]);
1442 xa_parse_extract_dialog_options(archive[idx],extract_window,selection);
1443 }
1444
xa_show_prefs_dialog(GtkMenuItem * menuitem,gpointer user_data)1445 void xa_show_prefs_dialog (GtkMenuItem *menuitem,gpointer user_data)
1446 {
1447 int response;
1448
1449 if (prefs_window == NULL)
1450 prefs_window = xa_create_prefs_dialog();
1451
1452 gtk_widget_show_all (prefs_window->dialog1);
1453 xa_prefs_iconview_changed(GTK_ICON_VIEW(prefs_window->iconview), prefs_window);
1454 response = gtk_dialog_run (GTK_DIALOG(prefs_window->dialog1));
1455 gtk_widget_hide (prefs_window->dialog1);
1456
1457 if (response == GTK_RESPONSE_OK)
1458 xa_prefs_apply_options(prefs_window);
1459 }
1460
xa_convert_sfx(GtkMenuItem * menuitem,gpointer user_data)1461 void xa_convert_sfx (GtkMenuItem *menuitem ,gpointer user_data)
1462 {
1463 gchar *command;
1464 gboolean result;
1465 gint idx;
1466
1467 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
1468
1469 archive[idx]->status = XARCHIVESTATUS_SFX;
1470 switch ( archive[idx]->type)
1471 {
1472 case XARCHIVETYPE_RAR:
1473 command = g_strconcat ("rar s -o+ ",archive[idx]->path[1],NULL);
1474 xa_run_command(archive[idx], command);
1475 g_free(command);
1476 break;
1477
1478 case XARCHIVETYPE_ZIP:
1479 {
1480 gchar *archive_name = NULL;
1481 gchar *archive_name_quoted;
1482 FILE *sfx_archive;
1483 FILE *archive_not_sfx;
1484 gchar *content;
1485 gsize length;
1486 GError *error = NULL;
1487 gchar *unzipsfx_path = NULL;
1488 gchar buffer[1024];
1489
1490 archive_name = xa_open_sfx_file_selector();
1491
1492 if (archive_name == NULL)
1493 return;
1494
1495 archive_name_quoted = g_shell_quote(archive_name);
1496 unzipsfx_path = g_find_program_in_path ("unzipsfx");
1497 if (unzipsfx_path != NULL)
1498 {
1499 /* Load the unzipsfx executable in memory,about 50 KB */
1500 result = g_file_get_contents (unzipsfx_path,&content,&length,&error);
1501 if ( ! result)
1502 {
1503 xa_show_message_dialog (GTK_WINDOW (xa_main_window),GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_("Can't convert the archive to self-extracting:"),error->message);
1504 g_error_free (error);
1505 g_free (unzipsfx_path);
1506 return;
1507 }
1508 g_free (unzipsfx_path);
1509
1510 /* Write unzipsfx to a new file */
1511 sfx_archive = fopen ( archive_name ,"w");
1512 if (sfx_archive == NULL)
1513 {
1514 xa_show_message_dialog (GTK_WINDOW (xa_main_window),GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_("Can't write the unzipsfx module to the archive:"),g_strerror(errno));
1515 return;
1516 }
1517 fwrite(content, length, 1, sfx_archive);
1518 g_free (content);
1519
1520 archive_not_sfx = fopen(archive[idx]->path[0], "r");
1521
1522 if (archive_not_sfx == NULL)
1523 {
1524 fclose(sfx_archive);
1525 return;
1526 }
1527
1528 /* Read archive data and write it after the sfx module in the new file */
1529 while ( ! feof(archive_not_sfx))
1530 {
1531 fread(&buffer, sizeof(buffer), 1, archive_not_sfx);
1532 fwrite(&buffer, sizeof(buffer), 1, sfx_archive);
1533 }
1534 fclose (archive_not_sfx);
1535 fclose (sfx_archive);
1536
1537 g_chmod(archive_name, 0755);
1538 command = g_strconcat ("zip -A ",archive_name_quoted,NULL);
1539 xa_run_command(archive[idx], command);
1540 g_free(command);
1541 }
1542 g_free (archive_name);
1543 g_free (archive_name_quoted);
1544 }
1545 break;
1546
1547 case XARCHIVETYPE_7ZIP:
1548 {
1549 gchar *archive_name = NULL;
1550 gchar *archive_name_quoted;
1551 FILE *sfx_archive;
1552 FILE *archive_not_sfx;
1553 gchar *content;
1554 gsize length;
1555 GError *error = NULL;
1556 gchar *sfx_path = NULL;
1557 gchar buffer[1024];
1558 int response;
1559 GtkWidget *locate_7zcon = NULL;
1560 GtkFileFilter *sfx_filter;
1561
1562 archive_name = xa_open_sfx_file_selector ();
1563
1564 if (archive_name == NULL)
1565 return;
1566 archive_name_quoted = g_shell_quote(archive_name);
1567
1568 if (g_file_test ( "/usr/lib/p7zip/7zCon.sfx",G_FILE_TEST_EXISTS))
1569 sfx_path = g_strdup("/usr/lib/p7zip/7zCon.sfx");
1570 else if (g_file_test ( "/usr/local/lib/p7zip/7zCon.sfx",G_FILE_TEST_EXISTS))
1571 sfx_path = g_strdup ("/usr/local/lib/p7zip/7zCon.sfx");
1572 else if (g_file_test ( "/usr/libexec/p7zip/7zCon.sfx",G_FILE_TEST_EXISTS))
1573 sfx_path = g_strdup ("/usr/libexec/p7zip/7zCon.sfx");
1574 else
1575 {
1576 sfx_filter = gtk_file_filter_new ();
1577 gtk_file_filter_set_name (sfx_filter,"");
1578 gtk_file_filter_add_pattern (sfx_filter,"*.sfx");
1579
1580 locate_7zcon = gtk_file_chooser_dialog_new ( _("Please select the 7zCon.sfx module"),
1581 GTK_WINDOW (xa_main_window),
1582 GTK_FILE_CHOOSER_ACTION_OPEN,
1583 GTK_STOCK_CANCEL,
1584 GTK_RESPONSE_CANCEL,
1585 "gtk-open",
1586 GTK_RESPONSE_ACCEPT,
1587 NULL);
1588
1589 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (locate_7zcon),sfx_filter);
1590 gtk_dialog_set_default_response (GTK_DIALOG (locate_7zcon),GTK_RESPONSE_ACCEPT);
1591 response = gtk_dialog_run (GTK_DIALOG(locate_7zcon));
1592 if (response == GTK_RESPONSE_ACCEPT)
1593 {
1594 sfx_path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(locate_7zcon));
1595 gtk_widget_destroy (locate_7zcon);
1596 }
1597 else
1598 {
1599 gtk_widget_destroy (locate_7zcon);
1600 return;
1601 }
1602 }
1603 if ( sfx_path != NULL)
1604 {
1605 /* Load the 7zCon.sfx executable in memory ~ 500 KB; is it too much for 128 MB equipped PCs ? */
1606 result = g_file_get_contents (sfx_path,&content,&length,&error);
1607 if ( ! result)
1608 {
1609 response = xa_show_message_dialog (GTK_WINDOW (xa_main_window),GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_("Can't convert the archive to self-extracting:"),error->message);
1610 g_error_free (error);
1611 g_free (sfx_path);
1612 return;
1613 }
1614 g_free (sfx_path);
1615
1616 /* Write 7zCon.sfx to a new file */
1617 sfx_archive = fopen ( archive_name ,"w");
1618 if (sfx_archive == NULL)
1619 {
1620 response = xa_show_message_dialog (GTK_WINDOW (xa_main_window),GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_("Can't write the unzipsfx module to the archive:"),g_strerror(errno));
1621 return;
1622 }
1623 fwrite(content, length, 1, sfx_archive);
1624 g_free (content);
1625
1626 archive_not_sfx = fopen(archive[idx]->path[0], "r");
1627
1628 if (archive_not_sfx == NULL)
1629 {
1630 fclose(sfx_archive);
1631 return;
1632 }
1633
1634 /* Read archive data and write it after the sfx module in the new file */
1635 while ( ! feof(archive_not_sfx))
1636 {
1637 fread(&buffer, sizeof(buffer), 1, archive_not_sfx);
1638 fwrite(&buffer, sizeof(buffer), 1, sfx_archive);
1639 }
1640 fclose (archive_not_sfx);
1641 fclose (sfx_archive);
1642
1643 command = g_strconcat ("chmod 755 ",archive_name_quoted,NULL);
1644 xa_run_command(archive[idx], command);
1645 g_free(command);
1646 }
1647 g_free (archive_name);
1648 g_free (archive_name_quoted);
1649 }
1650 break;
1651
1652 case XARCHIVETYPE_ARJ:
1653 command = g_strconcat ("arj y -je1 " ,archive[idx]->path[1],NULL);
1654 xa_run_command(archive[idx], command);
1655 g_free(command);
1656 break;
1657
1658 default:
1659 command = NULL;
1660 }
1661 }
1662
xa_about(GtkMenuItem * menuitem,gpointer user_data)1663 void xa_about (GtkMenuItem *menuitem,gpointer user_data)
1664 {
1665 static GtkWidget *about = NULL;
1666 const char *authors[] =
1667 {
1668 "",
1669 "This version:",
1670 MAINTAINER " <ib@wupperonline.de>",
1671 "",
1672 "Original developer:",
1673 "Giuseppe Torelli <colossus73@gmail.com>",
1674 "",
1675 "Archive navigation code:",
1676 "John Berthels",
1677 "",
1678 "Code fixing:",
1679 "Enrico Tröger",
1680 "",
1681 "LHA and DEB support:",
1682 "Łukasz Zemczak <sil2100@vexillium.org>",
1683 "",
1684 "LZMA support:",
1685 "Thomas Dy <dysprosium66@gmail.com>",
1686 "",
1687 "LZOP support:",
1688 "Kevin Day",
1689 "",
1690 "RARv5, XZ, TAR.XZ support:",
1691 "Frederick GUERIN <fguerin01@gmail.com>",
1692 "",
1693 "GTK+ 3 port:",
1694 "Balló György <ballogyor@gmail.com>",
1695 "",
1696 NULL
1697 };
1698 const char *documenters[] =
1699 {
1700 "",
1701 "Special thanks to Bjoern Martensen for",
1702 "bugs hunting and " PACKAGE_NAME "'s Tango logo.",
1703 "",
1704 "Thanks to:",
1705 "Benedikt Meurer",
1706 "Stephan Arts",
1707 "Bruno Jesus <00cpxxx@gmail.com>",
1708 "Uracile for the stunning logo",
1709 "",
1710 NULL
1711 };
1712
1713 if (about == NULL)
1714 {
1715 about = gtk_about_dialog_new ();
1716 GTK_COMPAT_ABOUT_DIALOG_URI(about, xa_activate_link);
1717 gtk_window_set_position (GTK_WINDOW (about),GTK_WIN_POS_CENTER_ON_PARENT);
1718 gtk_window_set_transient_for (GTK_WINDOW (about),GTK_WINDOW (xa_main_window));
1719 gtk_window_set_destroy_with_parent (GTK_WINDOW (about),TRUE);
1720 g_object_set (about,
1721 "program-name", PACKAGE_NAME,
1722 "version",PACKAGE_VERSION,
1723 "copyright","Copyright \xC2\xA9 " COPYRIGHT_YEAR " " COPYRIGHT_HOLDER "\n"
1724 "Copyright \xC2\xA9 " MAINTAINER_YEAR " " MAINTAINER,
1725 "comments",_("A GTK+ only lightweight archive manager"),
1726 "authors",authors,
1727 "documenters",documenters,
1728 "translator_credits",_("translator-credits"),
1729 "logo_icon_name","xarchiver",
1730 "website","https://wiki.github.com/ib/xarchiver",
1731 "license","Copyright \xC2\xA9 " COPYRIGHT_YEAR " " COPYRIGHT_HOLDER " - Colossus <colossus73@gmail.com>\n"
1732 "Copyright \xC2\xA9 " MAINTAINER_YEAR " " MAINTAINER "\n\n"
1733 "This program is free software; you can redistribute it and/or modify it\n"
1734 "under the terms of the GNU General Public License as published by the\n"
1735 "Free Software Foundation; either version 2 of the License, or (at your option)\n"
1736 "any later version.\n"
1737 "\n"
1738 "This program is distributed in the hope that it will be useful, but WITHOUT\n"
1739 "ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n"
1740 "or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n"
1741 "License for more details.\n"
1742 "\n"
1743 "You should have received a copy of the GNU General Public License\n"
1744 "along with this program; if not, write to the Free Software Foundation, Inc.,\n"
1745 "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.",
1746 NULL);
1747 }
1748 gtk_dialog_run ( GTK_DIALOG(about));
1749 gtk_widget_hide (about);
1750 }
1751
xa_detect_archive_type(const gchar * filename)1752 ArchiveType xa_detect_archive_type (const gchar *filename)
1753 {
1754 FILE *file;
1755 unsigned char magic[14];
1756 long bytes;
1757 uint32_t *uint32_magic = (uint32_t *) magic;
1758 unsigned short *short_magic = (unsigned short *) magic;
1759 ArchiveType xa = {XARCHIVETYPE_UNKNOWN, 0};
1760
1761 file = fopen(filename, "r");
1762
1763 if (!file)
1764 {
1765 xa.type = XARCHIVETYPE_NOT_FOUND;
1766 return xa;
1767 }
1768
1769 memset(magic, 0, sizeof(magic));
1770 bytes = fread(magic, 1, sizeof(magic), file);
1771
1772 /* lz4 and zstd skippable frame */
1773 while (memcmp(magic + 1, "\x2a\x4d\x18", 3) == 0 && (magic[0] & 0xf0) == 0x50 && bytes >= 8)
1774 {
1775 uint32_t frame_size = le32toh(uint32_magic[1]);
1776
1777 fseek(file, -bytes + 8, SEEK_CUR);
1778
1779 if (frame_size > 0x7fffffff)
1780 {
1781 fseek(file, 0x7fffffff, SEEK_CUR);
1782 frame_size -= 0x7fffffff;
1783 }
1784
1785 fseek(file, frame_size, SEEK_CUR);
1786
1787 memset(magic, 0, sizeof(magic));
1788 bytes = fread(magic, 1, sizeof(magic), file);
1789 }
1790
1791 if (memcmp(magic, "7z" "\xbc\xaf\x27\x1c", 6) == 0)
1792 xa.type = XARCHIVETYPE_7ZIP;
1793 else if (memcmp(magic, "!<arch>\n", 8) == 0)
1794 {
1795 xa.type = XARCHIVETYPE_AR;
1796
1797 if (memcmp(magic + 8, "debian", 6) == 0)
1798 xa.tag = 'd';
1799 }
1800 else if (memcmp(magic, "\x60\xea", 2) == 0)
1801 xa.type = XARCHIVETYPE_ARJ;
1802 else if (memcmp(magic, "BZh", 3) == 0)
1803 xa.type = XARCHIVETYPE_BZIP2;
1804 else if (memcmp(magic, "\x1f\x9d", 2) == 0)
1805 xa.type = XARCHIVETYPE_COMPRESS;
1806 else if (memcmp(magic, "070701", 6) == 0 ||
1807 memcmp(magic, "070702", 6) == 0 ||
1808 memcmp(magic, "070707", 6) == 0 ||
1809 *short_magic == 070707 ||
1810 *short_magic == bswap(070707))
1811 {
1812 xa.type = XARCHIVETYPE_CPIO;
1813
1814 if (*short_magic == bswap(070707))
1815 /* different endianness */
1816 xa.tag = 'E';
1817 }
1818 else if (memcmp(magic, "\x1f\x8b", 2) == 0 ||
1819 memcmp(magic, "\x1f\x9e", 2) == 0)
1820 xa.type = XARCHIVETYPE_GZIP;
1821 else if ((memcmp(magic + 2, "-lh", 3) == 0 && ((magic[5] >= '0' && magic[5] <= '7') || magic[5] == 'd') && magic[6] == '-') ||
1822 (memcmp(magic + 2, "-lz", 3) == 0 && (magic[5] == '4' || magic[5] == '5' || magic[5] == 's') && magic[6] == '-'))
1823 xa.type = XARCHIVETYPE_LHA;
1824 else if (memcmp(magic, "LRZI", 4) == 0)
1825 xa.type = XARCHIVETYPE_LRZIP;
1826 else if (memcmp(magic, "\x04\x22\x4d\x18", 4) == 0 ||
1827 memcmp(magic, "\x02\x21\x4c\x18", 4) == 0)
1828 xa.type = XARCHIVETYPE_LZ4;
1829 else if (memcmp(magic, "LZIP", 4) == 0)
1830 xa.type = XARCHIVETYPE_LZIP;
1831 else if (memcmp(magic, "\x5d\x00\x00", 3) == 0)
1832 xa.type = XARCHIVETYPE_LZMA;
1833 else if (memcmp(magic, "\211LZO", 4) == 0)
1834 xa.type = XARCHIVETYPE_LZOP;
1835 else if (memcmp(magic, "Rar!" "\x1a\x07\x00", 7) == 0 ||
1836 memcmp(magic, "Rar!" "\x1a\x07\x01", 7) == 0)
1837 {
1838 xa.type = XARCHIVETYPE_RAR;
1839
1840 if (magic[6] == 1)
1841 xa.tag = 5;
1842
1843 /* a rar5 archive without a rar v5 compatible executable can't be opened */
1844 if ((xa.tag == 5) && !g_slist_find(archiver[xa.type].tags, GUINT_TO_POINTER(xa.tag)))
1845 archiver[xa.type].list = NULL;
1846 }
1847 else if (memcmp(magic, "\xed\xab\xee\xdb", 4) == 0)
1848 xa.type = XARCHIVETYPE_RPM;
1849 else if (memcmp(magic, "\xfd" "7zXZ" "\x00", 6) == 0)
1850 xa.type = XARCHIVETYPE_XZ;
1851 else if (memcmp(magic, "PK" "\x03\x04", 4) == 0 ||
1852 memcmp(magic, "PK" "\x05\x06", 4) == 0 ||
1853 memcmp(magic + 4, "PK" "\x01\x02", 4) == 0)
1854 {
1855 xa.type = XARCHIVETYPE_ZIP;
1856
1857 if (g_str_has_suffix(filename, ".apk"))
1858 xa.tag = 'a';
1859 else if (g_str_has_suffix(filename, ".cbz"))
1860 xa.tag = 'c';
1861 else if (g_str_has_suffix(filename, ".epub"))
1862 xa.tag = 'e';
1863 else if (g_str_has_suffix(filename, ".jar"))
1864 xa.tag = 'j';
1865 else if (g_str_has_suffix(filename, ".oxt"))
1866 xa.tag = 'o';
1867 else if (g_str_has_suffix(filename, ".xpi"))
1868 xa.tag = 'x';
1869 }
1870 else if (g_str_has_suffix(filename, ".exe") && (memcmp(magic, "MZ", 2) == 0))
1871 xa = exetype(file);
1872 else if (memcmp(magic + 1, "\xb5\x2f\xfd", 3) == 0 &&
1873 (*magic == '\x1e' || (*magic >= '\x22' && *magic <= '\x28')))
1874 xa.type = XARCHIVETYPE_ZSTD;
1875 /* partly heuristic methods must come last */
1876 else if (isTar(file))
1877 xa.type = XARCHIVETYPE_TAR;
1878
1879 fclose(file);
1880
1881 return xa;
1882 }
1883
xa_create_liststore(XArchive * archive,const gchar * titles[])1884 void xa_create_liststore (XArchive *archive, const gchar *titles[])
1885 {
1886 guint i;
1887 GtkCellRenderer *renderer;
1888 GtkTreeViewColumn *column;
1889
1890 /* check for batch mode */
1891 if (!xa_main_window)
1892 return;
1893
1894 archive->liststore = gtk_list_store_newv(archive->columns, archive->column_types);
1895 gtk_tree_view_set_model ( GTK_TREE_VIEW (archive->treeview),GTK_TREE_MODEL (archive->liststore));
1896
1897 archive->model = GTK_TREE_MODEL(archive->liststore);
1898
1899 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prefs_window->check_sort_filename_column)))
1900 {
1901 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(archive->model), 1, GTK_SORT_ASCENDING);
1902 archive->sorted = TRUE;
1903 }
1904
1905 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(archive->liststore), 1, (GtkTreeIterCompareFunc) xa_sort_dirs_before_files, archive, NULL);
1906
1907 g_object_ref(archive->model);
1908 gtk_tree_view_set_model(GTK_TREE_VIEW(archive->treeview),NULL);
1909
1910 /* icon and filename */
1911 column = gtk_tree_view_column_new();
1912 archive->pixbuf_renderer = gtk_cell_renderer_pixbuf_new();
1913 gtk_tree_view_column_pack_start(column, archive->pixbuf_renderer, FALSE);
1914 gtk_tree_view_column_set_attributes(column, archive->pixbuf_renderer, "pixbuf", 0, NULL);
1915
1916 archive->text_renderer = gtk_cell_renderer_text_new();
1917 gtk_tree_view_column_pack_start(column, archive->text_renderer, TRUE);
1918 gtk_tree_view_column_set_attributes(column, archive->text_renderer, "text", 1, NULL);
1919 gtk_tree_view_column_set_title(column,_("Filename"));
1920 gtk_tree_view_column_set_resizable (column,TRUE);
1921 gtk_tree_view_column_set_sort_column_id (column,1);
1922 gtk_tree_view_append_column (GTK_TREE_VIEW (archive->treeview),column);
1923 gtk_tree_view_column_set_sizing (column,GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1924 g_signal_connect(archive->text_renderer, "editing-canceled", G_CALLBACK(xa_rename_cell_edited_canceled), archive);
1925 g_signal_connect(archive->text_renderer, "edited", G_CALLBACK(xa_rename_cell_edited), archive);
1926
1927 /* archive's individual items */
1928 for (i = 0; i < archive->columns - 3; i++)
1929 {
1930 renderer = gtk_cell_renderer_text_new();
1931 column = gtk_tree_view_column_new_with_attributes(titles[i], renderer, "text", i + 2, NULL);
1932 gtk_tree_view_column_set_resizable(column, TRUE);
1933 gtk_tree_view_column_set_sort_column_id(column, i + 2);
1934 gtk_tree_view_append_column(GTK_TREE_VIEW(archive->treeview), column);
1935 }
1936
1937 /* internally used pointer to XEntry (invisible) */
1938 column = gtk_tree_view_column_new();
1939 gtk_tree_view_column_set_visible(column, FALSE);
1940 gtk_tree_view_append_column(GTK_TREE_VIEW(archive->treeview), column);
1941 }
1942
treeview_select_search(GtkTreeModel * model,gint column,const gchar * key,GtkTreeIter * iter,gpointer user_data)1943 gboolean treeview_select_search (GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter, gpointer user_data)
1944 {
1945 char *filename;
1946 gboolean result;
1947
1948 gtk_tree_model_get(model,iter,1,&filename,-1);
1949 if (strcasestr (filename,key))
1950 result = FALSE;
1951 else
1952 result = TRUE;
1953 g_free (filename);
1954 return result;
1955 }
1956
xa_cancel_archive(GtkMenuItem * menuitem,gpointer user_data)1957 void xa_cancel_archive (GtkMenuItem *menuitem, gpointer user_data)
1958 {
1959 gint idx, response;
1960
1961 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
1962 if (gtk_widget_get_visible(multi_extract_window->multi_extract))
1963 {
1964 multi_extract_window->stop_pressed = TRUE;
1965 kill (multi_extract_window->archive->child_pid,SIGINT);
1966 }
1967 else
1968 {
1969 if (archive[idx]->status == XARCHIVESTATUS_ADD || archive[idx]->status == XARCHIVESTATUS_SFX)
1970 {
1971 response = xa_show_message_dialog (GTK_WINDOW(xa_main_window),GTK_DIALOG_MODAL,GTK_MESSAGE_QUESTION,GTK_BUTTONS_OK_CANCEL,_("Doing so will probably corrupt your archive!"),_("Do you really want to cancel?"));
1972 if (response == GTK_RESPONSE_CANCEL)
1973 return;
1974 }
1975 if (archive[idx]->child_pid)
1976 kill (archive[idx]->child_pid,SIGINT);
1977
1978 gtk_label_set_text(GTK_LABEL(total_label),"");
1979 /* !!! setting total_label isn't enough cleanup to be done !!! */
1980 }
1981 }
1982
xa_archive_properties(GtkMenuItem * menuitem,gpointer user_data)1983 void xa_archive_properties (GtkMenuItem *menuitem,gpointer user_data)
1984 {
1985 GtkWidget *archive_properties_window;
1986 struct stat my_stat;
1987 gchar *utf8_string ,*dummy_string,*t;
1988 char date[64];
1989 gint idx;
1990 guint64 file_size;
1991 double content_size;
1992
1993 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
1994 if (stat(archive[idx]->path[0], &my_stat) == 0)
1995 file_size = my_stat.st_size;
1996 else
1997 file_size = 0;
1998 archive_properties_window = xa_create_archive_properties_window();
1999 dummy_string = g_path_get_basename(archive[idx]->path[1]);
2000 utf8_string = g_filename_display_name(dummy_string);
2001 gtk_label_set_text(GTK_LABEL(name_data),utf8_string);
2002 g_free (utf8_string);
2003 g_free(dummy_string);
2004 /* Path */
2005 dummy_string = xa_remove_level_from_path(archive[idx]->path[0]);
2006 if (strlen(dummy_string) == 0 || strcmp(dummy_string,"..") == 0 || strcmp(dummy_string,".") == 0)
2007 utf8_string = g_filename_display_name (g_get_current_dir());
2008 else
2009 utf8_string = g_filename_display_name (dummy_string);
2010 g_free ( dummy_string);
2011
2012 gtk_label_set_text(GTK_LABEL(path_data),utf8_string);
2013 g_free ( utf8_string);
2014 /* Type */
2015 gtk_label_set_text(GTK_LABEL(type_data), xa_get_archive_format(archive[idx]));
2016 /* archiver */
2017 t = g_strconcat(archiver[archive[idx]->type].program[0], archiver[archive[idx]->type].program[1] ? "\n" : "", archiver[archive[idx]->type].program[1], NULL);
2018 utf8_string = g_filename_display_name(t);
2019 gtk_label_set_text(GTK_LABEL(archiver_data), utf8_string);
2020 g_free(utf8_string);
2021 g_free(t);
2022 /* Modified Date */
2023 strftime (date,64,"%c",localtime (&my_stat.st_mtime));
2024 t = g_locale_to_utf8(date, -1, NULL, NULL, NULL);
2025 gtk_label_set_text(GTK_LABEL(modified_data),t);
2026 g_free (t);
2027 /* Archive Size */
2028 t = xa_set_size_string(file_size);
2029 gtk_label_set_text(GTK_LABEL(size_data),t);
2030 g_free (t);
2031 /* content_size */
2032 t = xa_set_size_string(archive[idx]->files_size);
2033 gtk_label_set_text(GTK_LABEL(content_data),t);
2034 g_free (t);
2035 /* Has Comment */
2036 if (archive[idx]->has_comment)
2037 gtk_label_set_text(GTK_LABEL(comment_data),_("Yes"));
2038 else
2039 gtk_label_set_text(GTK_LABEL(comment_data),_("No"));
2040
2041 /* Compression_ratio */
2042 if (file_size)
2043 {
2044 content_size = (double) archive[idx]->files_size / file_size;
2045 t = g_strdup_printf("%.2f:1", content_size);
2046 }
2047 else
2048 t = g_strdup("-");
2049 gtk_label_set_text(GTK_LABEL(compression_data),t);
2050 g_free (t);
2051 /* Number of files */
2052 t = g_strdup_printf("%u", archive[idx]->files);
2053 gtk_label_set_text(GTK_LABEL(number_of_files_data),t);
2054 g_free (t);
2055
2056 if (archive[idx]->has_password)
2057 gtk_label_set_text(GTK_LABEL(encrypted_data),_("Yes"));
2058 else
2059 gtk_label_set_text(GTK_LABEL(encrypted_data),_("No"));
2060 gtk_widget_show_all (archive_properties_window);
2061 }
2062
xa_set_statusbar_message_for_displayed_rows(XArchive * archive)2063 void xa_set_statusbar_message_for_displayed_rows(XArchive *archive)
2064 {
2065 gchar *info = NULL;
2066 GtkTreePath *path = NULL;
2067 GtkTreeIter iter;
2068 gint n_elem = 0, dirs = 0;
2069 guint64 total_size = 0;
2070 guint64 size = 0;
2071 XEntry *entry = NULL;
2072
2073 path = gtk_tree_path_new_first();
2074 if (! GTK_IS_TREE_MODEL(archive->model) || gtk_tree_model_get_iter (archive->model,&iter,path) == FALSE)
2075 {
2076 gtk_tree_path_free(path);
2077 return;
2078 }
2079
2080 gtk_tree_path_free(path);
2081 do
2082 {
2083 gtk_tree_model_get(archive->model, &iter, archive->size_column, &size, -1);
2084 gtk_tree_model_get(archive->model, &iter, archive->columns - 1, &entry, -1);
2085 if (entry->is_dir)
2086 dirs++;
2087 else
2088 n_elem++;
2089 total_size += size;
2090 }
2091 while (gtk_tree_model_iter_next (archive->model,&iter));
2092 info = xa_get_statusbar_message(total_size,n_elem,dirs,FALSE);
2093 gtk_label_set_text (GTK_LABEL(total_label),info);
2094 g_free(info);
2095 }
2096
xa_row_selected(GtkTreeSelection * selection,XArchive * archive)2097 void xa_row_selected (GtkTreeSelection *selection,XArchive *archive)
2098 {
2099 GList *list = NULL;
2100 gchar *msg = NULL;
2101 GtkTreeIter iter;
2102 gint selected, dirs = 0;
2103 guint64 total_size = 0;
2104 guint64 size = 0;
2105 XEntry *entry;
2106
2107 selected = gtk_tree_selection_count_selected_rows (selection);
2108
2109 if (selected == 0)
2110 {
2111 xa_disable_delete_buttons (FALSE);
2112 gtk_widget_hide(selected_frame);
2113 return;
2114 }
2115
2116 gtk_widget_show(selected_frame);
2117 gtk_widget_set_sensitive(deselect_all, TRUE);
2118 gtk_widget_set_sensitive(delete_menu, archive->can_delete);
2119 gtk_widget_set_sensitive(rename_menu, selected == 1 ? can_rename(archive) : FALSE);
2120
2121 selected = 0;
2122 list = gtk_tree_selection_get_selected_rows(selection,NULL);
2123 while (list)
2124 {
2125 gtk_tree_model_get_iter(archive->model, &iter, list->data);
2126 gtk_tree_model_get(archive->model, &iter, archive->size_column, &size, -1);
2127 gtk_tree_model_get(archive->model, &iter, archive->columns - 1, &entry, -1);
2128 if (entry->is_dir)
2129 dirs++;
2130 else
2131 selected++;
2132 gtk_tree_path_free (list->data);
2133 total_size += size;
2134 list = list->next;
2135 }
2136 g_list_free(list);
2137 msg = xa_get_statusbar_message(total_size,selected,dirs,TRUE);
2138 gtk_label_set_text (GTK_LABEL(selected_label),msg);
2139 g_free(msg);
2140 }
2141
drag_begin(GtkWidget * widget,GdkDragContext * context,XArchive * archive)2142 void drag_begin (GtkWidget *widget, GdkDragContext *context, XArchive *archive)
2143 {
2144 GtkTreeSelection *selection;
2145 GtkTreeIter iter;
2146 GList *row_list;
2147 XEntry *entry;
2148
2149 if (archive->child_pid)
2150 gtk_drag_source_set_icon_stock(widget, "gtk-stop");
2151 else
2152 gtk_drag_source_set_icon_name(widget, "xarchiver");
2153
2154 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
2155
2156 row_list = gtk_tree_selection_get_selected_rows (selection,NULL);
2157 if (row_list == NULL)
2158 return;
2159
2160 gtk_tree_model_get_iter(archive->model,&iter,(GtkTreePath*) (row_list->data));
2161 gtk_tree_model_get(GTK_TREE_MODEL(archive->liststore), &iter, archive->columns - 1, &entry, -1);
2162
2163 gdk_property_change(gdk_drag_context_get_source_window(context),
2164 gdk_atom_intern ("XdndDirectSave0",FALSE),
2165 gdk_atom_intern ("text/plain",FALSE),
2166 8,GDK_PROP_MODE_REPLACE,
2167 (guchar *) XDS_FILENAME,
2168 strlen (XDS_FILENAME));
2169
2170 g_list_free_full(row_list, (GDestroyNotify) gtk_tree_path_free);
2171 }
2172
drag_data_get(GtkWidget * widget,GdkDragContext * context,GtkSelectionData * data,guint info,guint time,XArchive * archive)2173 void drag_data_get (GtkWidget *widget, GdkDragContext *context, GtkSelectionData *data, guint info, guint time, XArchive *archive)
2174 {
2175 GtkTreeSelection *selection;
2176 GList *row_list;
2177 GSList *names = NULL;
2178 gint length;
2179 guchar *_destination;
2180 gchar *destination, *to_send, *extraction_dir;
2181
2182 if (archive->child_pid)
2183 return;
2184
2185 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (archive->treeview));
2186 row_list = gtk_tree_selection_get_selected_rows (selection,NULL);
2187
2188 if (row_list == NULL)
2189 return;
2190
2191 g_list_free_full(row_list, (GDestroyNotify) gtk_tree_path_free);
2192
2193 gdk_property_get(gdk_drag_context_get_source_window(context),
2194 gdk_atom_intern("XdndDirectSave0", FALSE),
2195 gdk_atom_intern("text/plain", FALSE),
2196 0, 4096, FALSE, NULL, NULL, &length, &_destination);
2197
2198 if (_destination)
2199 {
2200 _destination = g_realloc(_destination, length + 1);
2201 _destination[length] = 0;
2202
2203 if (strcmp((const char *) _destination, XDS_FILENAME) == 0)
2204 {
2205 g_free(_destination);
2206 return;
2207 }
2208
2209 destination = g_filename_from_uri((gchar*)_destination,NULL,NULL);
2210 g_free(_destination);
2211
2212 if (!destination) return;
2213
2214 extraction_dir = xa_remove_level_from_path(destination);
2215 g_free(destination);
2216
2217 if (archive->has_password)
2218 {
2219 if (!xa_check_password(archive))
2220 {
2221 gtk_drag_finish(context, FALSE, FALSE, time);
2222 g_free(extraction_dir);
2223 return;
2224 }
2225 }
2226
2227 if (access(extraction_dir, R_OK | W_OK | X_OK))
2228 {
2229 gchar *utf8_path;
2230 gchar *msg;
2231
2232 utf8_path = g_filename_to_utf8(extraction_dir, -1, NULL, NULL, NULL);
2233 msg = g_strdup_printf (_("You don't have the right permissions to extract the files to the directory \"%s\"."),utf8_path);
2234 xa_show_message_dialog (GTK_WINDOW (xa_main_window),GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_("Can't perform extraction!"),msg );
2235 g_free (utf8_path);
2236 g_free (msg);
2237 to_send = "E";
2238 }
2239 else
2240 {
2241 gtk_tree_selection_selected_foreach (selection,(GtkTreeSelectionForeachFunc) xa_concat_selected_filenames,&names);
2242 archive->do_full_path = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(extract_window->extract_full));
2243 archive->do_overwrite = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(extract_window->overwrite_check));
2244 g_free(archive->extraction_dir);
2245 archive->extraction_dir = xa_escape_bad_chars(extraction_dir, ESCAPES);
2246
2247 gtk_label_set_text(GTK_LABEL(total_label), _("Extracting files from archive, please wait..."));
2248 archive->status = XARCHIVESTATUS_EXTRACT;
2249 (*archive->archiver->extract) (archive,names);
2250
2251 to_send = "S";
2252 }
2253
2254 g_free(extraction_dir);
2255
2256 gtk_selection_data_set(data, gtk_selection_data_get_target(data), 8, (const guchar *) to_send, 1);
2257 }
2258 }
2259
on_drag_data_received(GtkWidget * widget,GdkDragContext * context,int x,int y,GtkSelectionData * data,unsigned int info,unsigned int time,gpointer user_data)2260 void on_drag_data_received (GtkWidget *widget,GdkDragContext *context,int x,int y,GtkSelectionData *data,unsigned int info,unsigned int time,gpointer user_data)
2261 {
2262 gchar **array = NULL;
2263 gchar *filename = NULL;
2264 gchar *current_dir;
2265 GSList *list = NULL;
2266 gboolean one_file;
2267 unsigned int len = 0;
2268 gint current_page, idx;
2269 ArchiveType xa;
2270
2271 array = gtk_selection_data_get_uris(data);
2272
2273 if (array == NULL)
2274 {
2275 xa_show_message_dialog (GTK_WINDOW (xa_main_window),GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_("Sorry, I could not perform the operation!"),"");
2276 gtk_drag_finish(context,FALSE,FALSE,time);
2277 return;
2278 }
2279 gtk_drag_finish (context,TRUE,FALSE,time);
2280 one_file = (array[1] == NULL);
2281
2282 if (one_file)
2283 {
2284 filename = g_filename_from_uri(array[0],NULL,NULL);
2285
2286 if (filename == NULL)
2287 return;
2288
2289 xa = xa_detect_archive_type(filename);
2290
2291 if (xa.type != XARCHIVETYPE_UNKNOWN && xa.type != XARCHIVETYPE_NOT_FOUND)
2292 {
2293 xa_open_archive(NULL,filename);
2294 g_strfreev(array);
2295 return;
2296 }
2297 }
2298
2299 current_page = gtk_notebook_get_current_page(notebook);
2300
2301 if (current_page == -1)
2302 {
2303 idx = xa_get_new_archive_idx();
2304 if (idx == -1)
2305 return;
2306 archive[idx] = xa_new_archive_dialog(filename, archive);
2307 if (archive[idx] == NULL)
2308 return;
2309 xa_add_page (archive[idx]);
2310 }
2311 else
2312 idx = xa_find_archive_index (current_page);
2313
2314 if (!archive[idx]->can_add)
2315 {
2316 xa_show_message_dialog(GTK_WINDOW(xa_main_window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Can't perform this action:"), _("You can't add content to this archive type!"));
2317 gtk_drag_finish(context,FALSE,FALSE,time);
2318 return;
2319 }
2320 current_dir = g_path_get_dirname(array[0]);
2321 archive[idx]->child_dir = g_filename_from_uri(current_dir, NULL, NULL);
2322 g_free(current_dir);
2323 while (array[len])
2324 {
2325 filename = g_filename_from_uri (array[len],NULL,NULL);
2326 list = g_slist_append(list,filename);
2327 len++;
2328 }
2329 archive[idx]->do_full_path = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(add_window->store_path));
2330 xa_execute_add_commands(archive[idx], list, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prefs_window->allow_sub_dir)), NULL);
2331 g_strfreev (array);
2332 }
2333
xa_concat_selected_filenames(GtkTreeModel * model,GtkTreePath * treepath,GtkTreeIter * iter,GSList ** data)2334 void xa_concat_selected_filenames (GtkTreeModel *model,GtkTreePath *treepath,GtkTreeIter *iter,GSList **data)
2335 {
2336 XEntry *entry = NULL;
2337 gchar *filename = NULL;
2338 gint idx;
2339
2340 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
2341
2342 gtk_tree_model_get(model, iter, archive[idx]->columns - 1, &entry, -1);
2343 if (entry->is_dir)
2344 xa_fill_list_with_recursed_entries(entry->child,data);
2345 filename = xa_build_full_path_name_from_entry(entry);
2346 *data = g_slist_prepend (*data,filename);
2347 }
2348
xa_select_all(GtkMenuItem * menuitem,gpointer user_data)2349 void xa_select_all(GtkMenuItem *menuitem,gpointer user_data)
2350 {
2351 gint idx;
2352 gint current_page;
2353
2354 current_page = gtk_notebook_get_current_page (notebook);
2355 idx = xa_find_archive_index (current_page);
2356
2357 gtk_tree_selection_select_all ( gtk_tree_view_get_selection (GTK_TREE_VIEW (archive[idx]->treeview)));
2358 gtk_widget_set_sensitive (select_all,FALSE);
2359 gtk_widget_set_sensitive (deselect_all,TRUE);
2360 }
2361
xa_deselect_all(GtkMenuItem * menuitem,gpointer user_data)2362 void xa_deselect_all (GtkMenuItem *menuitem,gpointer user_data)
2363 {
2364 gint idx;
2365
2366 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
2367
2368 gtk_tree_selection_unselect_all (gtk_tree_view_get_selection(GTK_TREE_VIEW(archive[idx]->treeview)));
2369 gtk_widget_set_sensitive (select_all,TRUE);
2370 gtk_widget_set_sensitive (deselect_all,FALSE);
2371 }
2372
xa_launch_external_program(const gchar * program,const gchar * arg)2373 gboolean xa_launch_external_program (const gchar *program, const gchar *arg)
2374 {
2375 GtkWidget *message;
2376 GError *error = NULL;
2377 gchar *program_local, *arg_local, *command_line;
2378 gchar **argv;
2379 GdkDisplay *display;
2380 gboolean success = TRUE;
2381
2382 if (g_utf8_validate(program, -1, NULL))
2383 program_local = g_filename_from_utf8(program, -1, NULL, NULL, NULL);
2384 else
2385 program_local = g_strdup(program);
2386
2387 if (g_utf8_validate(arg, -1, NULL))
2388 arg_local = g_filename_from_utf8(arg, -1, NULL, NULL, NULL);
2389 else
2390 arg_local = g_strdup(arg);
2391
2392 command_line = g_strconcat(program_local, " ", arg_local, NULL);
2393 g_shell_parse_argv(command_line,NULL,&argv,NULL);
2394 g_free(command_line);
2395 g_free(program_local);
2396 g_free(arg_local);
2397
2398 display = gdk_display_get_default();
2399
2400 if (!GDK_COMPAT_SPAWN(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, xa_set_environment, (gpointer) gdk_display_get_name(display), NULL, &error))
2401 {
2402 message = gtk_message_dialog_new (GTK_WINDOW (xa_main_window),
2403 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
2404 GTK_MESSAGE_ERROR,
2405 GTK_BUTTONS_CLOSE,
2406 _("Failed to launch the application!"));
2407 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message),"%s.",error->message);
2408 gtk_dialog_run (GTK_DIALOG (message));
2409 gtk_widget_destroy (message);
2410 g_error_free (error);
2411 success = FALSE;
2412 }
2413 g_strfreev(argv);
2414 return success;
2415 }
2416
xa_show_help(GtkMenuItem * menuitem,gpointer user_data)2417 void xa_show_help (GtkMenuItem *menuitem,gpointer user_data)
2418 {
2419 xa_activate_link (NULL,"file://" HTMLDIR "/index.html",NULL);
2420 }
2421
xa_enter_password(GtkMenuItem * menuitem,gpointer user_data)2422 void xa_enter_password (GtkMenuItem *menuitem ,gpointer user_data)
2423 {
2424 gint idx;
2425
2426 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
2427
2428 if (archive[idx] == NULL)
2429 return;
2430 else
2431 {
2432 g_free(archive[idx]->password);
2433 archive[idx]->password = NULL;
2434 }
2435
2436 xa_check_password(archive[idx]);
2437 }
2438
xa_show_archive_comment(GtkMenuItem * menuitem,gpointer user_data)2439 void xa_show_archive_comment (GtkMenuItem *menuitem,gpointer user_data)
2440 {
2441 gchar *utf8_line;
2442 gsize len;
2443 gint idx;
2444 GtkWidget *textview;
2445 GtkWidget *dialog_vbox1;
2446 GtkWidget *scrolledwindow1;
2447 GtkWidget *tmp_image,*file,*clear,*close,*cancel,*file_hbox,*file_label;
2448 GtkWidget *alignment2;
2449 GtkTextBuffer *textbuffer;
2450 GtkTextIter iter;
2451
2452 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
2453
2454 comment_dialog = gtk_dialog_new_with_buttons (_("Comment"),GTK_WINDOW(xa_main_window),GTK_DIALOG_MODAL,NULL,NULL);
2455 gtk_window_set_position (GTK_WINDOW (comment_dialog),GTK_WIN_POS_CENTER_ON_PARENT);
2456 gtk_window_set_type_hint (GTK_WINDOW (comment_dialog),GDK_WINDOW_TYPE_HINT_DIALOG);
2457 dialog_vbox1 = gtk_dialog_get_content_area(GTK_DIALOG(comment_dialog));
2458 gtk_widget_set_size_request(comment_dialog, 672, 420);
2459
2460 scrolledwindow1 = gtk_scrolled_window_new (NULL,NULL);
2461 gtk_widget_show (scrolledwindow1);
2462 gtk_box_pack_start (GTK_BOX (dialog_vbox1),scrolledwindow1,TRUE,TRUE,0);
2463 g_object_set (G_OBJECT (scrolledwindow1),"hscrollbar-policy",GTK_POLICY_AUTOMATIC,"shadow-type",GTK_SHADOW_IN,"vscrollbar-policy",GTK_POLICY_AUTOMATIC,NULL);
2464
2465 textbuffer = gtk_text_buffer_new (NULL);
2466 gtk_text_buffer_create_tag (textbuffer,"font","family","monospace",NULL);
2467 gtk_text_buffer_get_iter_at_offset (textbuffer,&iter,0);
2468
2469 textview = gtk_text_view_new_with_buffer (textbuffer);
2470 g_object_unref (textbuffer);
2471 gtk_container_add (GTK_CONTAINER (scrolledwindow1),textview);
2472
2473 clear = gtk_button_new_from_stock ("gtk-clear");
2474 gtk_dialog_add_action_widget (GTK_DIALOG (comment_dialog),clear,0);
2475 g_signal_connect (G_OBJECT (clear),"clicked",G_CALLBACK (xa_clear_comment_window),textbuffer);
2476
2477 file = gtk_button_new();
2478 tmp_image = gtk_image_new_from_stock ("gtk-harddisk",GTK_ICON_SIZE_BUTTON);
2479 file_hbox = gtk_hbox_new(FALSE,4);
2480 file_label = gtk_label_new_with_mnemonic(_("From File"));
2481
2482 alignment2 = gtk_alignment_new (0.5,0.5,0,0);
2483 gtk_container_add (GTK_CONTAINER (alignment2),file_hbox);
2484 gtk_box_pack_start(GTK_BOX(file_hbox),tmp_image,FALSE,TRUE,0);
2485 gtk_box_pack_start(GTK_BOX(file_hbox),file_label,FALSE,TRUE,0);
2486 gtk_container_add(GTK_CONTAINER(file),alignment2);
2487 gtk_dialog_add_action_widget (GTK_DIALOG (comment_dialog),file,0);
2488 g_signal_connect (G_OBJECT (file),"clicked",G_CALLBACK (xa_load_comment_window_from_file),textbuffer);
2489
2490 cancel = gtk_button_new_from_stock ("gtk-cancel");
2491 gtk_dialog_add_action_widget (GTK_DIALOG (comment_dialog),cancel,GTK_RESPONSE_CANCEL);
2492 g_signal_connect_swapped(G_OBJECT(cancel), "clicked", G_CALLBACK(gtk_widget_destroy), comment_dialog);
2493
2494 close = gtk_button_new_from_stock ("gtk-ok");
2495 gtk_dialog_add_action_widget (GTK_DIALOG (comment_dialog),close,GTK_RESPONSE_OK);
2496 g_signal_connect (G_OBJECT (close),"clicked",G_CALLBACK (xa_comment_window_insert_in_archive),textbuffer);
2497
2498 if (archive[idx]->comment)
2499 {
2500 if (g_utf8_validate(archive[idx]->comment->str, -1, NULL))
2501 {
2502 utf8_line = g_strdup(archive[idx]->comment->str);
2503 len = -1;
2504 }
2505 else
2506 utf8_line = g_locale_to_utf8(archive[idx]->comment->str, -1, NULL, &len, NULL);
2507
2508 gtk_text_buffer_insert_with_tags_by_name (textbuffer,&iter,utf8_line,len,"font",NULL);
2509 g_free(utf8_line);
2510 }
2511 gtk_widget_show_all(comment_dialog);
2512 }
2513
xa_location_entry_activated(GtkEntry * entry,gpointer user_data)2514 void xa_location_entry_activated (GtkEntry *entry,gpointer user_data)
2515 {
2516 XEntry *prev_entry = NULL;
2517 XEntry *new_entry = NULL;
2518 gint idx;
2519 gchar* pathname_local;
2520
2521 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
2522
2523 /* Avoid segfault if there's no file opened */
2524 if(idx<0)
2525 return;
2526
2527 if (strlen(gtk_entry_get_text(GTK_ENTRY(location_entry))) == 0)
2528 {
2529 xa_update_window_with_archive_entries(archive[idx],new_entry);
2530 return;
2531 }
2532
2533 pathname_local = g_filename_from_utf8(gtk_entry_get_text(GTK_ENTRY(location_entry)), -1, NULL, NULL, NULL);
2534 new_entry = xa_find_entry_from_dirpath(archive[idx], pathname_local);
2535 g_free(pathname_local);
2536 if (new_entry == NULL)
2537 {
2538 if (archive[idx]->location_path)
2539 {
2540 gchar *entry_utf8 = g_filename_display_name(archive[idx]->location_path);
2541 gtk_entry_set_text(GTK_ENTRY(location_entry), entry_utf8);
2542 g_free(entry_utf8);
2543 }
2544 return;
2545 }
2546
2547 if (archive[idx]->location_path)
2548 prev_entry = xa_find_entry_from_dirpath(archive[idx], archive[idx]->location_path);
2549
2550 if (prev_entry != NULL)
2551 archive[idx]->back = g_slist_prepend(archive[idx]->back,prev_entry);
2552 else
2553 archive[idx]->back = g_slist_prepend(archive[idx]->back,NULL);
2554
2555 xa_dir_sidebar_select_row(new_entry);
2556 xa_update_window_with_archive_entries(archive[idx],new_entry);
2557 }
2558
xa_mouse_button_event(GtkWidget * widget,GdkEventButton * event,XArchive * archive)2559 gboolean xa_mouse_button_event (GtkWidget *widget, GdkEventButton *event, XArchive *archive)
2560 {
2561 XEntry *entry;
2562 GtkTreePath *path;
2563 GtkTreeIter iter;
2564 GtkTreeSelection *selection;
2565 gint selected;
2566 GtkClipboard *clipboard;
2567 GtkSelectionData *clipboard_selection;
2568 XAClipboard *paste_data;
2569 gboolean pasteable = FALSE;
2570
2571 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(archive->treeview));
2572 selected = gtk_tree_selection_count_selected_rows(selection);
2573 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(archive->treeview), event->x, event->y, &path, NULL, NULL, NULL);
2574
2575 if (path == NULL)
2576 return FALSE;
2577
2578 if (event->type == GDK_BUTTON_PRESS && (event->button == 2 || event->button == 3))
2579 {
2580 gtk_tree_model_get_iter(GTK_TREE_MODEL(archive->liststore), &iter, path);
2581 gtk_tree_model_get(archive->model, &iter, archive->columns - 1, &entry, -1);
2582
2583 if (!gtk_tree_selection_iter_is_selected(selection, &iter))
2584 {
2585 gtk_tree_selection_unselect_all(selection);
2586 gtk_tree_selection_select_iter(selection, &iter);
2587 selected = 1;
2588 }
2589
2590 if (event->button == 2 && selected <= 1)
2591 xa_treeview_row_activated(GTK_TREE_VIEW(archive->treeview), path, NULL, archive);
2592 else if (event->button == 3)
2593 {
2594 gtk_widget_set_sensitive(open_popupmenu, !entry->is_dir && archive->can_extract);
2595 gtk_widget_set_sensitive(view, (selected == 1) && !entry->is_dir && archive->can_extract);
2596 gtk_widget_set_sensitive(rrename, (selected == 1) && !entry->is_dir && can_rename(archive));
2597
2598 clipboard = gtk_clipboard_get(XA_CLIPBOARD);
2599 clipboard_selection = gtk_clipboard_wait_for_contents(clipboard, XA_INFO_LIST);
2600
2601 if (clipboard_selection != NULL)
2602 {
2603 paste_data = xa_get_paste_data_from_clipboard_selection(gtk_selection_data_get_data(clipboard_selection));
2604 gtk_selection_data_free(clipboard_selection);
2605
2606 pasteable = (strcmp(archive->path[1], paste_data->target->path[1]) != 0);
2607 }
2608
2609 gtk_widget_set_sensitive(eextract, archive->can_extract);
2610 gtk_widget_set_sensitive(cut, archive->can_extract && archive->can_delete);
2611 gtk_widget_set_sensitive(copy, archive->can_extract);
2612 gtk_widget_set_sensitive(paste, pasteable && archive->can_add);
2613 gtk_widget_set_sensitive(ddelete, archive->can_delete);
2614 gtk_menu_popup(GTK_MENU(xa_popup_menu), NULL, NULL, NULL, xa_main_window, event->button, event->time);
2615 }
2616
2617 return TRUE;
2618 }
2619
2620 gtk_tree_path_free(path);
2621
2622 return FALSE;
2623 }
2624
xa_clipboard_cut(GtkMenuItem * item,gpointer user_data)2625 void xa_clipboard_cut (GtkMenuItem *item, gpointer user_data)
2626 {
2627 gint idx;
2628
2629 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
2630
2631 xa_clipboard_cut_copy_operation(archive[idx],XA_CLIPBOARD_CUT);
2632 }
2633
xa_clipboard_copy(GtkMenuItem * item,gpointer user_data)2634 void xa_clipboard_copy (GtkMenuItem *item, gpointer user_data)
2635 {
2636 gint idx;
2637
2638 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
2639 xa_clipboard_cut_copy_operation(archive[idx],XA_CLIPBOARD_COPY);
2640 }
2641
xa_clipboard_paste(GtkMenuItem * item,gpointer user_data)2642 void xa_clipboard_paste (GtkMenuItem *item, gpointer user_data)
2643 {
2644 gint idx;
2645 GtkClipboard *clipboard;
2646 GtkSelectionData *selection;
2647 XAClipboard *paste_data;
2648 GSList *list = NULL;
2649
2650 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
2651
2652 clipboard = gtk_clipboard_get(XA_CLIPBOARD);
2653 selection = gtk_clipboard_wait_for_contents(clipboard,XA_INFO_LIST);
2654 if (selection == NULL)
2655 return;
2656 paste_data = xa_get_paste_data_from_clipboard_selection(gtk_selection_data_get_data(selection));
2657 gtk_selection_data_free (selection);
2658
2659 /* Let's add the already extracted files in the tmp dir to the current archive dir */
2660 list = xa_slist_copy(paste_data->files);
2661 archive[idx]->do_full_path = FALSE;
2662 archive[idx]->child_dir = g_strdup(paste_data->target->working_dir);
2663 xa_execute_add_commands(archive[idx], list, FALSE, NULL);
2664 if (archive[idx]->status == XARCHIVESTATUS_ERROR)
2665 return;
2666
2667 if (paste_data->mode == XA_CLIPBOARD_CUT)
2668 {
2669 list = xa_slist_copy(paste_data->files);
2670
2671 paste_data->target->status = XARCHIVESTATUS_DELETE;
2672 (*paste_data->target->archiver->delete)(paste_data->target, list);
2673 xa_reload_archive_content(paste_data->target);
2674 }
2675 }
2676
xa_clipboard_clear(GtkClipboard * clipboard,XArchive * archive)2677 void xa_clipboard_clear (GtkClipboard *clipboard, XArchive *archive)
2678 {
2679 if (archive->clipboard != NULL)
2680 {
2681 if (archive->clipboard->files != NULL)
2682 {
2683 g_slist_free_full(archive->clipboard->files, g_free);
2684 archive->clipboard->files = NULL;
2685 }
2686
2687 g_free(archive->clipboard);
2688 archive->clipboard = NULL;
2689 }
2690 }
2691
xa_rename_archive(GtkMenuItem * item,gpointer user_data)2692 void xa_rename_archive (GtkMenuItem *item, gpointer user_data)
2693 {
2694 gint idx;
2695 GtkTreeSelection *selection;
2696 GtkTreeViewColumn *column;
2697 GtkTreeModel *model;
2698 GList *row_list = NULL;
2699
2700 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
2701
2702 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (archive[idx]->treeview));
2703 model = gtk_tree_view_get_model(GTK_TREE_VIEW (archive[idx]->treeview));
2704 row_list = gtk_tree_selection_get_selected_rows(selection,&model);
2705
2706 g_object_set(archive[idx]->text_renderer, "editable", TRUE, NULL);
2707 gtk_widget_remove_accelerator(delete_menu, accel_group, GDK_KEY_Delete, (GdkModifierType) 0);
2708 column = gtk_tree_view_get_column(GTK_TREE_VIEW (archive[idx]->treeview),0);
2709 gtk_tree_view_set_cursor(GTK_TREE_VIEW(archive[idx]->treeview),row_list->data,column,TRUE);
2710 gtk_tree_path_free (row_list->data);
2711 g_list_free(row_list);
2712 }
2713
xa_open_with_from_popupmenu(GtkMenuItem * item,gpointer user_data)2714 void xa_open_with_from_popupmenu (GtkMenuItem *item, gpointer user_data)
2715 {
2716 gboolean result = FALSE;
2717 gint idx, nr;
2718 GtkTreeSelection *selection;
2719 GtkTreeIter iter;
2720 GList *row_list = NULL;
2721 GSList *list = NULL;
2722 GSList *list_of_files = NULL;
2723 GString *names = g_string_new("");
2724 gchar *dummy = NULL,*e_filename = NULL;
2725 XEntry *entry;
2726
2727 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
2728
2729 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (archive[idx]->treeview));
2730 row_list = gtk_tree_selection_get_selected_rows(selection,&archive[idx]->model);
2731 if (row_list == NULL)
2732 return;
2733
2734 nr = gtk_tree_selection_count_selected_rows(selection);
2735 while (row_list)
2736 {
2737 gtk_tree_model_get_iter(archive[idx]->model,&iter,row_list->data);
2738 gtk_tree_model_get(archive[idx]->model, &iter, archive[idx]->columns - 1, &entry, -1);
2739 gtk_tree_path_free(row_list->data);
2740 if (entry->is_encrypted)
2741 {
2742 if (!xa_check_password(archive[idx]))
2743 return;
2744 }
2745 list = g_slist_append(list, xa_build_full_path_name_from_entry(entry));
2746 row_list = row_list->next;
2747 }
2748 g_list_free (row_list);
2749 g_free(archive[idx]->extraction_dir);
2750 xa_create_working_directory(archive[idx]);
2751 archive[idx]->extraction_dir = g_strdup(archive[idx]->working_dir);
2752
2753 archive[idx]->do_full_path = FALSE;
2754 archive[idx]->do_overwrite = TRUE;
2755 list_of_files = xa_slist_copy(list);
2756
2757 archive[idx]->status = XARCHIVESTATUS_EXTRACT;
2758 result = (*archive[idx]->archiver->extract) (archive[idx],list);
2759 if (result == FALSE)
2760 return;
2761
2762 chdir(archive[idx]->working_dir);
2763 do
2764 {
2765 dummy = g_path_get_basename(list_of_files->data);
2766 e_filename = g_shell_quote(dummy);
2767 g_free(dummy);
2768 g_string_append (names,e_filename);
2769 g_string_append_c (names,' ');
2770 list_of_files = list_of_files->next;
2771 }
2772 while (list_of_files);
2773 xa_create_open_with_dialog(entry->filename,names->str,nr);
2774 g_string_free(names, FALSE);
2775 g_slist_free_full(list_of_files, g_free);
2776 }
2777
xa_view_from_popupmenu(GtkMenuItem * item,gpointer user_data)2778 void xa_view_from_popupmenu (GtkMenuItem *item, gpointer user_data)
2779 {
2780 GtkTreeSelection *selection;
2781 GtkTreeIter iter;
2782 GSList *list = NULL;
2783 GList *row_list = NULL;
2784 gboolean result = FALSE;
2785 gint idx;
2786 gchar *entry_local, *filename;
2787 XEntry *entry;
2788
2789 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
2790
2791 xa_create_working_directory(archive[idx]);
2792
2793 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (archive[idx]->treeview));
2794 row_list = gtk_tree_selection_get_selected_rows(selection,&archive[idx]->model);
2795 gtk_tree_model_get_iter(archive[idx]->model,&iter,row_list->data);
2796 gtk_tree_model_get(archive[idx]->model, &iter, archive[idx]->columns - 1, &entry, -1);
2797 gtk_tree_path_free(row_list->data);
2798 list = g_slist_append(list, xa_build_full_path_name_from_entry(entry));
2799 g_list_free(row_list);
2800
2801 if (entry->is_encrypted)
2802 {
2803 if (!xa_check_password(archive[idx]))
2804 return;
2805 }
2806 entry_local = g_filename_from_utf8(entry->filename, -1, NULL, NULL, NULL);
2807 filename = g_strconcat(archive[idx]->working_dir, "/", entry_local, NULL);
2808 g_free(entry_local);
2809 if (g_file_test(filename,G_FILE_TEST_EXISTS))
2810 goto here;
2811 g_free(archive[idx]->extraction_dir);
2812 archive[idx]->extraction_dir = g_strdup(archive[idx]->working_dir);
2813 archive[idx]->do_full_path = FALSE;
2814 archive[idx]->do_overwrite = TRUE;
2815
2816 archive[idx]->status = XARCHIVESTATUS_EXTRACT;
2817 result = (*archive[idx]->archiver->extract) (archive[idx],list);
2818 if (result == FALSE)
2819 return;
2820
2821 here:
2822 xa_determine_program_to_run(filename);
2823 g_free(filename);
2824 }
2825
xa_treeview_row_activated(GtkTreeView * tree_view,GtkTreePath * path,GtkTreeViewColumn * column,XArchive * archive)2826 void xa_treeview_row_activated(GtkTreeView *tree_view,GtkTreePath *path,GtkTreeViewColumn *column,XArchive *archive)
2827 {
2828 XEntry *entry;
2829 GtkTreeIter iter;
2830 gchar *item, *entry_local, *file;
2831 GSList *names = NULL;
2832 gboolean result = FALSE;
2833
2834 if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (archive->liststore),&iter,path))
2835 return;
2836
2837 gtk_tree_model_get(GTK_TREE_MODEL(archive->liststore), &iter, archive->columns - 1, &entry, -1);
2838 if (entry->is_dir)
2839 {
2840 if (archive->location_path)
2841 archive->back = g_slist_prepend(archive->back, xa_find_entry_from_dirpath(archive, archive->location_path));
2842 /* Put NULL so to display the root entry */
2843 else
2844 archive->back = g_slist_prepend(archive->back,NULL);
2845 xa_dir_sidebar_select_row(entry);
2846 }
2847 /* The selected entry it's not a dir so extract it to the tmp dir and send it to xa_determine_program_to_run() */
2848 else
2849 {
2850 if (entry->is_encrypted)
2851 {
2852 if (!xa_check_password(archive))
2853 return;
2854 }
2855 g_free(archive->extraction_dir);
2856 xa_create_working_directory(archive);
2857 archive->extraction_dir = g_strdup(archive->working_dir);
2858 item = xa_build_full_path_name_from_entry(entry);
2859 names = g_slist_append(names,item);
2860 archive->do_full_path = FALSE;
2861 archive->do_overwrite = TRUE;
2862 archive->status = XARCHIVESTATUS_EXTRACT;
2863 result = (*archive->archiver->extract) (archive,names);
2864
2865 if (result == FALSE)
2866 return;
2867 entry_local = g_filename_from_utf8(entry->filename, -1, NULL, NULL, NULL);
2868 file = g_strconcat(archive->working_dir, "/", entry_local, NULL);
2869 g_free(entry_local);
2870 xa_determine_program_to_run(file);
2871 g_free(file);
2872 }
2873 }
2874
xa_update_window_with_archive_entries(XArchive * archive,XEntry * entry)2875 void xa_update_window_with_archive_entries (XArchive *archive,XEntry *entry)
2876 {
2877 gboolean reload;
2878 GdkPixbuf *pixbuf = NULL;
2879 GtkTreeIter iter;
2880 guint i;
2881 gpointer current_column;
2882 gchar *location_path = NULL, *filename;
2883 gint size;
2884 gchar *entry_utf8;
2885
2886 if (archive->status == XARCHIVESTATUS_RELOAD && archive->location_path != NULL)
2887 {
2888 entry = xa_find_entry_from_dirpath(archive, archive->location_path);
2889
2890 if (entry) location_path = g_strdup(archive->location_path);
2891 }
2892 else
2893 archive->current_entry = entry;
2894
2895 g_free(archive->location_path);
2896 archive->location_path = NULL;
2897
2898 if (entry == NULL)
2899 {
2900 reload = TRUE;
2901 entry = archive->root_entry->child;
2902 gtk_entry_set_text(GTK_ENTRY(location_entry),"\0");
2903 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(archive_dir_treeview)));
2904
2905 gtk_widget_set_sensitive(back_button,FALSE);
2906 gtk_widget_set_sensitive(up_button,FALSE);
2907 gtk_widget_set_sensitive(home_button,FALSE);
2908 }
2909 else
2910 {
2911 reload = (archive->status == XARCHIVESTATUS_RELOAD);
2912 gtk_widget_set_sensitive(back_button, archive->back != NULL);
2913 gtk_widget_set_sensitive(up_button,TRUE);
2914 gtk_widget_set_sensitive(home_button,TRUE);
2915 archive->location_path = xa_build_full_path_name_from_entry(entry);
2916 entry_utf8 = g_filename_display_name(archive->location_path);
2917 gtk_entry_set_text(GTK_ENTRY(location_entry), entry_utf8);
2918 g_free(entry_utf8);
2919 entry = entry->child;
2920 }
2921 gtk_list_store_clear(archive->liststore);
2922
2923 while (entry)
2924 {
2925 current_column = entry->columns;
2926 gtk_list_store_prepend(archive->liststore, &iter);
2927 if(!g_utf8_validate(entry->filename,-1,NULL))
2928 {
2929 gchar *entry_utf8 = g_filename_display_name(entry->filename);
2930 g_free(entry->filename);
2931 entry->filename = entry_utf8;
2932 }
2933 if (entry->is_dir)
2934 filename = "folder";
2935 else if (entry->is_encrypted)
2936 filename = "lock";
2937 else
2938 filename = entry->filename;
2939
2940 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(prefs_window->combo_icon_size)))
2941 {
2942 case 0:
2943 size = 20;
2944 break;
2945
2946 case 1:
2947 size = 22;
2948 break;
2949
2950 case 2:
2951 size = 24;
2952 break;
2953
2954 case 3:
2955 size = 30;
2956 break;
2957
2958 default:
2959 size = 32;
2960 break;
2961 }
2962
2963 pixbuf = xa_get_pixbuf_icon_from_cache(filename,size);
2964 gtk_list_store_set(archive->liststore, &iter, archive->columns - 1, entry, -1);
2965 gtk_list_store_set (archive->liststore,&iter,0,pixbuf,1,entry->filename,-1);
2966
2967 for (i = 2; i < archive->columns - 1; i++)
2968 {
2969 switch(archive->column_types[i])
2970 {
2971 case G_TYPE_STRING:
2972 //g_message ("%d - %s",i,(*((gchar **)current_column)));
2973 gtk_list_store_set(archive->liststore, &iter, i, *(gchar **) current_column, -1);
2974 current_column += sizeof(gchar *);
2975 break;
2976
2977 case G_TYPE_UINT64:
2978 //g_message ("*%d - %lu",i,(*((guint64 *)current_column)));
2979 gtk_list_store_set(archive->liststore, &iter, i, *(guint64 *) current_column, -1);
2980 current_column += sizeof(guint64);
2981 break;
2982 }
2983 }
2984 entry = entry->next;
2985 }
2986 xa_fill_dir_sidebar(archive, reload);
2987
2988 if (location_path)
2989 {
2990 entry = xa_find_entry_from_dirpath(archive, location_path);
2991 xa_block_signal_dir_treeview_selection(TRUE);
2992 xa_dir_sidebar_select_row(entry);
2993 xa_block_signal_dir_treeview_selection(FALSE);
2994 g_free(location_path);
2995 }
2996
2997 xa_set_statusbar_message_for_displayed_rows(archive);
2998 }
2999
xa_show_multi_extract_dialog(GtkMenuItem * menu_item,gpointer user_data)3000 void xa_show_multi_extract_dialog (GtkMenuItem *menu_item, gpointer user_data)
3001 {
3002 xa_multi_extract_dialog(multi_extract_window);
3003 if (progress)
3004 gtk_widget_hide(progress->window);
3005 //xa_close_archive (NULL,data);
3006 }
3007
xa_unsort(GtkMenuItem * menu_item,gpointer user_data)3008 void xa_unsort (GtkMenuItem *menu_item, gpointer user_data)
3009 {
3010 gint idx;
3011 XArchiveStatus status;
3012
3013 idx = xa_find_archive_index(gtk_notebook_get_current_page(notebook));
3014
3015 if (idx < 0)
3016 return;
3017
3018 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(archive[idx]->model), GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, (GtkSortType) 0);
3019 gtk_widget_set_sensitive(unsort_menu, FALSE);
3020 archive[idx]->sorted = FALSE;
3021
3022 status = archive[idx]->status;
3023 archive[idx]->status = XARCHIVESTATUS_RELOAD;
3024 xa_update_window_with_archive_entries(archive[idx], NULL);
3025 archive[idx]->status = status;
3026 }
3027
xa_main_window_find_image(gchar * filename,GtkIconSize size)3028 GtkWidget *xa_main_window_find_image (gchar *filename, GtkIconSize size)
3029 {
3030 gchar *name, *ext, *path;
3031 GdkPixbuf *file_pixbuf = NULL;
3032 GtkWidget *file_image;
3033
3034 name = g_strdup(filename);
3035 ext = g_strrstr(name, ".png");
3036
3037 if (ext)
3038 {
3039 *ext = 0;
3040 file_pixbuf = gtk_icon_theme_load_icon(icon_theme, name, size, (GtkIconLookupFlags) 0, NULL);
3041 }
3042
3043 g_free(name);
3044
3045 if (file_pixbuf == NULL)
3046 {
3047 path = g_strconcat(PIXMAPSDIR, "/", filename, NULL);
3048 file_pixbuf = gdk_pixbuf_new_from_file(path, NULL);
3049 g_free(path);
3050 }
3051
3052 if (file_pixbuf == NULL)
3053 file_image = gtk_image_new_from_stock(GTK_STOCK_MISSING_IMAGE, size);
3054 else
3055 {
3056 file_image = gtk_image_new_from_pixbuf(file_pixbuf);
3057 g_object_unref(file_pixbuf);
3058 }
3059
3060 return file_image;
3061 }
3062