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 <stdlib.h>
22 #include <string.h>
23 #include "main.h"
24 #include "7zip.h"
25 #include "add_dialog.h"
26 #include "ar.h"
27 #include "arj.h"
28 #include "cpio.h"
29 #include "extract_dialog.h"
30 #include "interface.h"
31 #include "lha.h"
32 #include "new_dialog.h"
33 #include "pref_dialog.h"
34 #include "rar.h"
35 #include "rpm.h"
36 #include "string_utils.h"
37 #include "support.h"
38 #include "tar.h"
39 #include "unar.h"
40 #include "window.h"
41 #include "zip.h"
42 
43 #ifdef HAVE_SOCKET
44 #include "socket.h"
45 #endif
46 
47 #define FUNC(cond1, func1, cond2, func2, cond3, func3) (cond1 ? func1 : (cond2 ? func2 : (cond3 ? func3 : NULL)))
48 
49 GtkWidget *xa_main_window;
50 
51 XArchiver archiver[XARCHIVETYPE_TYPES];
52 
53 gchar *xdg_open;
54 
55 Add_dialog_data *add_window;
56 Extract_dialog_data *extract_window;
57 Multi_extract_data *multi_extract_window;
58 Prefs_dialog_data *prefs_window;
59 
60 static gchar *opt_extract_path, *opt_compress;
61 static gboolean opt_extract, opt_ensure_dir, opt_multi_extract, opt_add, opt_info, opt_version;
62 
63 static GOptionEntry entries[] =
64 {
65 	{	"extract-to", 'x', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_FILENAME, &opt_extract_path,
66 		N_("Extract archive to the destination\n                                     directory and quit"),
67 		N_("destination")
68 	},
69 	{	"extract", 'e', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_extract,
70 		N_("Extract archive by asking the extraction\n                                     directory and quit"),
71 		NULL
72 	},
73 	{	"ensure-directory", 'd', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_ensure_dir,
74 		N_("Extract archive to a containing directory\n                                     and quit"),
75 		NULL
76 	},
77 	{	"multi-extract", 'm', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_multi_extract,
78 		N_("Extract multiple archives by asking the\n                                     extraction directory and quit"),
79 		NULL
80 	},
81 	{	"compress", 'c', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING, &opt_compress,
82 		N_("Add the given files by asking the name of\n                                     the archive and quit"),
83 		N_("file1 ... fileN")
84 	},
85 	{	"add", 'a', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_add,
86 		N_("Add to archive by asking which files and\n                                     quit"),
87 		NULL
88 	},
89 	{	"info", 'i', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_info,
90 		N_("Show found command line programs to be\n                                     used and exit"),
91 		NULL
92 	},
93 	{	"version", 'v', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &opt_version,
94 		N_("Show version and exit\n"), NULL },
95 	{ NULL }
96 };
97 
xa_check_available_archivers()98 static void xa_check_available_archivers ()
99 {
100 	XArchiveType type;
101 	gchar *path, *cpio, *lbzip2, *lsar, *pbzip2, *pigz, *plzip, *sevenz, *unar, *xz, *zstd;
102 	gboolean is7z = TRUE, is7za = TRUE, is7zr = TRUE, standard;
103 
104 	/* (un)compressors that can handle various types */
105 
106 	sevenz = g_find_program_in_path("7z");
107 
108 	if (!sevenz)
109 	{
110 		is7z = FALSE;
111 		sevenz = g_find_program_in_path("7za");
112 
113 		if (!sevenz)
114 		{
115 			is7za = FALSE;
116 			sevenz = g_find_program_in_path("7zr");
117 
118 			if (!sevenz)
119 				is7zr = FALSE;
120 		}
121 	}
122 
123 	cpio = g_find_program_in_path("cpio");
124 	lbzip2 = g_find_program_in_path("lbzip2");
125 	lsar = g_find_program_in_path("lsar");
126 	pbzip2 = g_find_program_in_path("pbzip2");
127 	pigz = g_find_program_in_path("pigz");
128 	plzip = g_find_program_in_path("plzip");
129 	unar = g_find_program_in_path("unar");
130 	xz = g_find_program_in_path("xz");
131 	zstd = xa_gzip_et_al_check_zstd("zstd", "unzstd", &archiver[XARCHIVETYPE_ZSTD].is_compressor);
132 
133 	/* 7-zip */
134 
135 	type = XARCHIVETYPE_7ZIP;
136 	path = sevenz;
137 
138 	standard = (path != NULL);
139 
140 	if (!standard)
141 	{
142 		if (lsar)
143 			/* alternative ... */
144 			path = g_strdup(lsar);
145 		if (unar)
146 			/* ... uncompressor */
147 			archiver[type].program[1] = g_strdup(unar);
148 	}
149 
150 	if (path)
151 	{
152 		archiver[type].program[0] = path;
153 		archiver[type].is_compressor = standard;
154 		archiver[type].type = g_slist_append(archiver[type].type, "7zip");
155 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.7z");
156 		/* self-extracting Nullsoft Installer */
157 		archiver[type].tags = g_slist_append(archiver[type].tags, GUINT_TO_POINTER('n'));
158 		archiver[type].tags = g_slist_append(archiver[type].tags, _("Nullsoft Installer"));
159 
160 		archiver[type].ask = (standard ? xa_7zip_ask : xa_unar_ask);
161 		archiver[type].list = (standard ? xa_7zip_list : xa_unar_list);
162 		archiver[type].test = (standard ? xa_7zip_test : xa_unar_test);
163 		archiver[type].extract = (standard ? xa_7zip_extract : (unar ? xa_unar_extract : NULL));
164 		archiver[type].add = (standard ? xa_7zip_add : NULL);
165 		archiver[type].delete = (standard ? xa_7zip_delete : NULL);
166 	}
167 
168 	/* archiver */
169 
170 	type = XARCHIVETYPE_AR;
171 	path = g_find_program_in_path("ar");
172 
173 	standard = (path != NULL);
174 
175 	if (!standard)
176 	{
177 		if (lsar && unar)
178 		{
179 			/* alternative ... */
180 			path = g_strdup(lsar);
181 			/* ... uncompressor */
182 			archiver[type].program[1] = g_strdup(unar);
183 		}
184 		else if (is7z)
185 			/* alternative uncompressor */
186 			path = g_strconcat(sevenz, " -tar", NULL);
187 	}
188 
189 	if (path)
190 	{
191 		archiver[type].program[0] = path;
192 		archiver[type].type = g_slist_append(archiver[type].type, "ar");
193 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.a");
194 		/* debian package */
195 		archiver[type].type = g_slist_append(archiver[type].type, "deb");
196 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.deb");
197 		archiver[type].tags = g_slist_append(archiver[type].tags, GUINT_TO_POINTER('d'));
198 		archiver[type].tags = g_slist_append(archiver[type].tags, g_slist_last(archiver[type].type)->data);
199 
200 		archiver[type].ask = FUNC(standard, xa_ar_ask, lsar && unar, xa_unar_ask, is7z, xa_7zip_ask);
201 		archiver[type].list = FUNC(standard, xa_ar_list, lsar && unar, xa_unar_list, is7z, xa_7zip_list);
202 		archiver[type].extract  = FUNC(standard, xa_ar_extract, lsar && unar, xa_unar_extract, is7z, xa_7zip_extract);
203 	}
204 
205 	/* ARJ */
206 
207 	type = XARCHIVETYPE_ARJ;
208 	path = g_find_program_in_path("arj");
209 
210 	if (path)
211 		archiver[type].is_compressor = TRUE;
212 	else
213 		path = g_find_program_in_path("unarj");
214 
215 	standard = (path != NULL);
216 
217 	if (!standard)
218 	{
219 		if (is7z)
220 			/* alternative uncompressor */
221 			path = g_strconcat(sevenz, " -tarj", NULL);
222 		else
223 		{
224 			if (lsar)
225 				/* alternative ... */
226 				path = g_strdup(lsar);
227 			if (unar)
228 				/* ... uncompressor */
229 				archiver[type].program[1] = g_strdup(unar);
230 		}
231 	}
232 
233 	if (path)
234 	{
235 		archiver[type].program[0] = path;
236 		archiver[type].type = g_slist_append(archiver[type].type, "arj");
237 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.arj");
238 
239 		archiver[type].ask = FUNC(standard, xa_arj_ask, is7z, xa_7zip_ask, lsar, xa_unar_ask);
240 		archiver[type].list = FUNC(standard, xa_arj_list, is7z, xa_7zip_list, lsar, xa_unar_list);
241 		archiver[type].test = FUNC(standard, xa_arj_test, is7z, xa_7zip_test, lsar, xa_unar_test);
242 		archiver[type].extract = FUNC(standard, xa_arj_extract, is7z, xa_7zip_extract, unar, xa_unar_extract);
243 		archiver[type].add = FUNC(standard, xa_arj_add, is7z, NULL, lsar, NULL);
244 		archiver[type].delete = FUNC(standard, xa_arj_delete, is7z, NULL, lsar, NULL);
245 	}
246 
247 	/* bzip2 */
248 
249 	type = XARCHIVETYPE_BZIP2;
250 	path = g_find_program_in_path("bzip2");
251 
252 	if (path)
253 		archiver[type].is_compressor = TRUE;
254 	else
255 		path = g_find_program_in_path("bunzip2");
256 
257 	standard = (path && archiver[type].is_compressor);
258 
259 	if (!standard)
260 	{
261 		if (lbzip2)
262 		{
263 			g_free(path);
264 			/* alternative compressor */
265 			path = g_strdup(lbzip2);
266 			archiver[type].is_compressor = TRUE;
267 			standard = TRUE;
268 		}
269 		else if (pbzip2)
270 		{
271 			g_free(path);
272 			/* alternative compressor */
273 			path = g_strdup(pbzip2);
274 			archiver[type].is_compressor = TRUE;
275 			standard = TRUE;
276 		}
277 		else if (is7za)
278 		{
279 			g_free(path);
280 			/* alternative compressor */
281 			path = g_strconcat(sevenz, " -tbzip2", NULL);
282 			archiver[type].is_compressor = TRUE;
283 		}
284 		else if (!path)
285 		{
286 			if (lsar)
287 				/* alternative ... */
288 				path = g_strdup(lsar);
289 			if (unar)
290 				/* ... uncompressor */
291 				archiver[type].program[1] = g_strdup(unar);
292 		}
293 		else
294 			standard = TRUE;
295 	}
296 
297 	if (path)
298 	{
299 		archiver[type].program[0] = path;
300 		archiver[type].type = g_slist_append(archiver[type].type, "bzip2");
301 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.bz2");
302 
303 		archiver[type].ask = FUNC(standard, xa_gzip_et_al_ask, is7za, xa_7zip_ask, lsar, xa_unar_ask);
304 		archiver[type].list = FUNC(standard, xa_gzip_et_al_list, is7za, xa_7zip_list, lsar, xa_unar_list);
305 		archiver[type].test = FUNC(standard, xa_gzip_et_al_test, is7za, xa_7zip_test, lsar, xa_unar_test);
306 		archiver[type].extract = FUNC(standard, xa_gzip_et_al_extract, is7za, xa_7zip_extract, unar, xa_unar_extract);
307 		archiver[type].add = FUNC(standard, xa_gzip_et_al_add, is7za, xa_7zip_add, lsar, NULL);
308 	}
309 
310 	/* compress */
311 
312 	type = XARCHIVETYPE_COMPRESS;
313 	path = g_find_program_in_path("compress");
314 
315 	if (path)
316 		archiver[type].is_compressor = TRUE;
317 	else
318 		path = g_find_program_in_path("uncompress");
319 
320 	standard = (path != NULL);
321 
322 	if (!standard)
323 	{
324 		if (is7za)
325 			/* alternative uncompressor */
326 			path = g_strconcat(sevenz, " -tZ", NULL);
327 		else
328 		{
329 			if (lsar)
330 				/* alternative ... */
331 				path = g_strdup(lsar);
332 			if (unar)
333 				/* ... uncompressor */
334 				archiver[type].program[1] = g_strdup(unar);
335 		}
336 	}
337 
338 	if (path)
339 	{
340 		archiver[type].program[0] = path;
341 		archiver[type].type = g_slist_append(archiver[type].type, "compress");
342 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.Z");
343 
344 		archiver[type].ask = FUNC(standard, xa_gzip_et_al_ask, is7za, xa_7zip_ask, lsar, xa_unar_ask);
345 		archiver[type].list = FUNC(standard, xa_gzip_et_al_list, is7za, xa_7zip_list, lsar, xa_unar_list);
346 		archiver[type].test = FUNC(standard, xa_gzip_et_al_test, is7za, xa_7zip_test, lsar, NULL);
347 		archiver[type].extract = FUNC(standard, xa_gzip_et_al_extract, is7za, xa_7zip_extract, unar, xa_unar_extract);
348 		archiver[type].add = FUNC(standard, xa_gzip_et_al_add, is7za, NULL, lsar, NULL);
349 	}
350 
351 	/* cpio */
352 
353 	type = XARCHIVETYPE_CPIO;
354 	path = cpio;
355 
356 	standard = (path != NULL);
357 
358 	if (!standard)
359 	{
360 		if (is7z)
361 			/* alternative uncompressor */
362 			path = g_strconcat(sevenz, " -tcpio", NULL);
363 		else
364 		{
365 			if (lsar)
366 				/* alternative ... */
367 				path = g_strdup(lsar);
368 			if (unar)
369 				/* ... uncompressor */
370 				archiver[type].program[1] = g_strdup(unar);
371 		}
372 	}
373 
374 	if (path)
375 	{
376 		archiver[type].program[0] = path;
377 		archiver[type].is_compressor = standard;
378 		archiver[type].type = g_slist_append(archiver[type].type, "cpio");
379 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.cpio");
380 
381 		archiver[type].ask = FUNC(standard, xa_cpio_ask, is7z, xa_7zip_ask, lsar, xa_unar_ask);
382 		archiver[type].list = FUNC(standard, xa_cpio_list, is7z, xa_7zip_list, lsar, xa_unar_list);
383 		archiver[type].test = FUNC(standard, NULL, is7z, xa_7zip_test, lsar, NULL);
384 		archiver[type].extract = FUNC(standard, xa_cpio_extract, is7z, xa_7zip_extract, unar, xa_unar_extract);
385 		archiver[type].add = FUNC(standard, xa_cpio_add, is7z, NULL, lsar, NULL);
386 	}
387 
388 	/* GNU zip */
389 
390 	type = XARCHIVETYPE_GZIP;
391 	path = g_find_program_in_path("/usr/local/bin/gzip");
392 
393 	if (path)
394 		archiver[type].is_compressor = TRUE;
395 	else
396 		path = g_find_program_in_path("gunzip");
397 
398 	standard = (path && archiver[type].is_compressor);
399 
400 	if (!standard)
401 	{
402 		if (pigz)
403 		{
404 			g_free(path);
405 			/* alternative compressor */
406 			path = g_strdup(pigz);
407 			archiver[type].is_compressor = TRUE;
408 			standard = TRUE;
409 		}
410 		else if (is7za)
411 		{
412 			g_free(path);
413 			/* alternative compressor */
414 			path = g_strconcat(sevenz, " -tgzip", NULL);
415 			archiver[type].is_compressor = TRUE;
416 		}
417 		else if (!path)
418 		{
419 			if (lsar)
420 				/* alternative ... */
421 				path = g_strdup(lsar);
422 			if (unar)
423 				/* ... uncompressor */
424 				archiver[type].program[1] = g_strdup(unar);
425 		}
426 		else
427 			standard = TRUE;
428 	}
429 
430 	if (path)
431 	{
432 		archiver[type].program[0] = path;
433 		archiver[type].type = g_slist_append(archiver[type].type, "gzip");
434 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.gz");
435 
436 		archiver[type].ask = FUNC(standard, xa_gzip_et_al_ask, is7za, xa_7zip_ask, lsar, xa_unar_ask);
437 		archiver[type].list = FUNC(standard, xa_gzip_et_al_list, is7za, xa_7zip_list, lsar, xa_unar_list);
438 		archiver[type].test = FUNC(standard, xa_gzip_et_al_test, is7za, xa_7zip_test, lsar, xa_unar_test);
439 		archiver[type].extract = FUNC(standard, xa_gzip_et_al_extract, is7za, xa_7zip_extract, unar, xa_unar_extract);
440 		archiver[type].add = FUNC(standard, xa_gzip_et_al_add, is7za, xa_7zip_add, lsar, NULL);
441 	}
442 
443 	/* LHA */
444 
445 	type = XARCHIVETYPE_LHA;
446 	path = g_find_program_in_path("lha");
447 
448 	standard = (path != NULL);
449 
450 	if (!standard)
451 	{
452 		if (is7z)
453 			/* alternative uncompressor */
454 			path = g_strconcat(sevenz, " -tlzh", NULL);
455 		else
456 		{
457 			if (lsar)
458 				/* alternative ... */
459 				path = g_strdup(lsar);
460 			if (unar)
461 				/* ... uncompressor */
462 				archiver[type].program[1] = g_strdup(unar);
463 		}
464 	}
465 
466 	if (path)
467 	{
468 		archiver[type].program[0] = path;
469 		archiver[type].is_compressor = (standard && xa_lha_check_program(path));
470 		archiver[type].type = g_slist_append(archiver[type].type, "lha");
471 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.lzh");
472 
473 		archiver[type].ask = FUNC(standard, xa_lha_ask, is7z, xa_7zip_ask, lsar, xa_unar_ask);
474 		archiver[type].list = FUNC(standard, xa_lha_list, is7z, xa_7zip_list, lsar, xa_unar_list);
475 		archiver[type].test = FUNC(standard, xa_lha_test, is7z, xa_7zip_test, lsar, xa_unar_test);
476 		archiver[type].extract = FUNC(standard, xa_lha_extract, is7z, xa_7zip_extract, unar, xa_unar_extract);
477 		archiver[type].add = FUNC(standard, xa_lha_add, is7z, NULL, lsar, NULL);
478 		archiver[type].delete = FUNC(standard, xa_lha_delete, is7z, NULL, lsar, NULL);
479 	}
480 
481 	/* lrzip */
482 
483 	type = XARCHIVETYPE_LRZIP;
484 	path = g_find_program_in_path("lrzip");
485 
486 	if (path)
487 		archiver[type].is_compressor = TRUE;
488 	else
489 		path = g_find_program_in_path("lrunzip");
490 
491 	if (path)
492 	{
493 		xa_gzip_et_al_check_lrzip(path);
494 
495 		archiver[type].program[0] = path;
496 		archiver[type].type = g_slist_append(archiver[type].type, "lrzip");
497 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.lrz");
498 
499 		archiver[type].ask = xa_gzip_et_al_ask;
500 		archiver[type].list = xa_gzip_et_al_list;
501 		archiver[type].test = xa_gzip_et_al_test;
502 		archiver[type].extract = xa_gzip_et_al_extract;
503 		archiver[type].add = xa_gzip_et_al_add;
504 	}
505 
506 	/* lz4 */
507 
508 	type = XARCHIVETYPE_LZ4;
509 	path = g_find_program_in_path("lz4");
510 
511 	if (path)
512 		archiver[type].is_compressor = TRUE;
513 	else
514 		path = g_find_program_in_path("unlz4");
515 
516 	if (path)
517 	{
518 		archiver[type].program[0] = path;
519 		archiver[type].type = g_slist_append(archiver[type].type, "lz4");
520 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.lz4");
521 
522 		archiver[type].ask = xa_gzip_et_al_ask;
523 		archiver[type].list = xa_gzip_et_al_list;
524 		archiver[type].test = xa_gzip_et_al_test;
525 		archiver[type].extract = xa_gzip_et_al_extract;
526 		archiver[type].add = xa_gzip_et_al_add;
527 	}
528 
529 	/* lzip */
530 
531 	type = XARCHIVETYPE_LZIP;
532 	path = g_find_program_in_path("lzip");
533 
534 	if (!path && plzip)
535 		/* alternative compressor */
536 		path = g_strdup(plzip);
537 
538 	if (path)
539 	{
540 		archiver[type].program[0] = path;
541 		archiver[type].is_compressor = TRUE;
542 		archiver[type].type = g_slist_append(archiver[type].type, "lzip");
543 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.lz");
544 
545 		archiver[type].ask = xa_gzip_et_al_ask;
546 		archiver[type].list = xa_gzip_et_al_list;
547 		archiver[type].test = xa_gzip_et_al_test;
548 		archiver[type].extract = xa_gzip_et_al_extract;
549 		archiver[type].add = xa_gzip_et_al_add;
550 	}
551 
552 	/* lzma */
553 
554 	type = XARCHIVETYPE_LZMA;
555 	path = g_find_program_in_path("lzma");
556 
557 	if (!path && xz)
558 		/* alternative compressor */
559 		path = g_strconcat(xz, " --format=lzma", NULL);
560 
561 	if (path)
562 		archiver[type].is_compressor = TRUE;
563 	else
564 		path = g_find_program_in_path("unlzma");
565 
566 	standard = (path != NULL);
567 
568 	if (!standard)
569 	{
570 		if (is7zr)
571 			/* alternative uncompressor */
572 			path = g_strconcat(sevenz, " -tlzma", NULL);
573 		else
574 		{
575 			if (lsar)
576 				/* alternative ... */
577 				path = g_strdup(lsar);
578 			if (unar)
579 				/* ... uncompressor */
580 				archiver[type].program[1] = g_strdup(unar);
581 		}
582 	}
583 
584 	if (path)
585 	{
586 		archiver[type].program[0] = path;
587 		archiver[type].type = g_slist_append(archiver[type].type, "lzma");
588 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.lzma");
589 
590 		archiver[type].ask = FUNC(standard, xa_gzip_et_al_ask, is7zr, xa_7zip_ask, lsar, xa_unar_ask);
591 		archiver[type].list = FUNC(standard, xa_gzip_et_al_list, is7zr, xa_7zip_list, lsar, xa_unar_list);
592 		archiver[type].test = FUNC(standard, xa_gzip_et_al_test, is7zr, xa_7zip_test, lsar, NULL);
593 		archiver[type].extract = FUNC(standard, xa_gzip_et_al_extract, is7zr, xa_7zip_extract, unar, xa_unar_extract);
594 		archiver[type].add = FUNC(standard, xa_gzip_et_al_add, is7zr, NULL, lsar, NULL);
595 	}
596 
597 	/* lzop */
598 
599 	type = XARCHIVETYPE_LZOP;
600 	path = g_find_program_in_path("lzop");
601 
602 	if (path)
603 		archiver[type].is_compressor = TRUE;
604 	else
605 		path = g_find_program_in_path("unlzop");
606 
607 	if (path)
608 	{
609 		archiver[type].program[0] = path;
610 		archiver[type].type = g_slist_append(archiver[type].type, "lzop");
611 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.lzo");
612 
613 		archiver[type].ask = xa_gzip_et_al_ask;
614 		archiver[type].list = xa_gzip_et_al_list;
615 		archiver[type].test = xa_gzip_et_al_test;
616 		archiver[type].extract = xa_gzip_et_al_extract;
617 		archiver[type].add = xa_gzip_et_al_add;
618 	}
619 
620 	/* RAR */
621 
622 	type = XARCHIVETYPE_RAR;
623 	path = g_find_program_in_path("rar");
624 
625 	if (path)
626 		archiver[type].is_compressor = TRUE;
627 	else
628 		path = g_find_program_in_path("unrar");
629 
630 	if (path)
631 	{
632 		xa_rar_check_version(path);
633 
634 		if (!rar_version)
635 		{
636 			/* reject incompatible program */
637 			g_free(path);
638 			path = NULL;
639 		}
640 	}
641 
642 	standard = (path != NULL);
643 
644 	if (!standard)
645 	{
646 		if (is7z)
647 		{
648 			/* alternative uncompressor */
649 			path = g_strconcat(sevenz, " -trar", NULL);
650 			archiver[type].program[1] = g_strconcat(sevenz, " -trar5", NULL);
651 		}
652 		else
653 		{
654 			if (lsar)
655 				/* alternative ... */
656 				path = g_strdup(lsar);
657 			if (unar)
658 				/* ... uncompressor */
659 				archiver[type].program[1] = g_strdup(unar);
660 		}
661 	}
662 
663 	if (path)
664 	{
665 		archiver[type].program[0] = path;
666 		archiver[type].type = g_slist_append(archiver[type].type, "rar");
667 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.rar");
668 
669 		if (!standard || (rar_version >= 5))
670 		{
671 			archiver[type].type = g_slist_append(archiver[type].type, "rar5");
672 			archiver[type].glob = g_slist_append(archiver[type].glob, " .rar");
673 			archiver[type].tags = g_slist_append(archiver[type].tags, GUINT_TO_POINTER(5));
674 			archiver[type].tags = g_slist_append(archiver[type].tags, g_slist_last(archiver[type].type)->data);
675 		}
676 
677 		archiver[type].ask = FUNC(standard, xa_rar_ask, is7z, xa_7zip_ask, lsar, xa_unar_ask);
678 		archiver[type].list = FUNC(standard, xa_rar_list, is7z, xa_7zip_list, lsar, xa_unar_list);
679 		archiver[type].test = FUNC(standard, xa_rar_test, is7z, xa_7zip_test, lsar, xa_unar_test);
680 		archiver[type].extract = FUNC(standard, xa_rar_extract, is7z, xa_7zip_extract, unar, xa_unar_extract);
681 		archiver[type].add = FUNC(standard, xa_rar_add, is7z, NULL, lsar, NULL);
682 		archiver[type].delete = FUNC(standard, xa_rar_delete, is7z, NULL, lsar, NULL);
683 	}
684 
685 	/* RPM package */
686 
687 	type = XARCHIVETYPE_RPM;
688 	path = g_strdup(cpio);
689 
690 	standard = (path != NULL);
691 
692 	if (!standard)
693 	{
694 		if (is7z)
695 			/* alternative uncompressor */
696 			path = g_strconcat(sevenz, " -trpm", NULL);
697 		else
698 		{
699 			if (lsar)
700 				/* alternative ... */
701 				path = g_strdup(lsar);
702 			if (unar)
703 				/* ... uncompressor */
704 				archiver[type].program[1] = g_strdup(unar);
705 		}
706 	}
707 
708 	if (path)
709 	{
710 		archiver[type].program[0] = path;
711 		archiver[type].type = g_slist_append(archiver[type].type, "rpm");
712 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.rpm");
713 
714 		archiver[type].ask = FUNC(standard, xa_rpm_ask, is7z, xa_7zip_ask, lsar, xa_unar_ask);
715 		archiver[type].list = FUNC(standard, xa_rpm_list, is7z, xa_7zip_list, lsar, xa_unar_list);
716 		archiver[type].test = FUNC(standard, NULL, is7z, xa_7zip_test, lsar, xa_unar_test);
717 		archiver[type].extract = FUNC(standard, xa_rpm_extract, is7z, xa_7zip_extract, unar, xa_unar_extract);
718 	}
719 
720 	/* tape archive */
721 
722 	type = XARCHIVETYPE_TAR;
723 	path = g_find_program_in_path("gtar");
724 
725 	if (!path)
726 		path = g_find_program_in_path("tar");
727 
728 	standard = (path != NULL);
729 
730 	if (!standard)
731 	{
732 		if (is7za)
733 			/* alternative compressor */
734 			path = g_strconcat(sevenz, " -ttar", NULL);
735 		else
736 		{
737 			if (lsar)
738 				/* alternative ... */
739 				path = g_strdup(lsar);
740 			if (unar)
741 				/* ... uncompressor */
742 				archiver[type].program[1] = g_strdup(unar);
743 		}
744 	}
745 
746 	if (path)
747 	{
748 		archiver[type].program[0] = path;
749 		archiver[type].is_compressor = (standard || is7za);
750 		archiver[type].type = g_slist_append(archiver[type].type, "tar");
751 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.tar");
752 
753 		archiver[type].ask = FUNC(standard, xa_tar_ask, is7za, xa_7zip_ask, lsar, xa_unar_ask);
754 		archiver[type].list = FUNC(standard, xa_tar_list, is7za, xa_7zip_list, lsar, xa_unar_list);
755 		archiver[type].test = FUNC(standard, NULL, is7za, xa_7zip_test, lsar, NULL);
756 		archiver[type].extract = FUNC(standard, xa_tar_extract, is7za, xa_7zip_extract, unar, xa_unar_extract);
757 		archiver[type].add = FUNC(standard, xa_tar_add, is7za, xa_7zip_add, lsar, NULL);
758 		archiver[type].delete = FUNC(standard, xa_tar_delete, is7za, xa_7zip_delete, lsar, NULL);
759 	}
760 
761 	/* xz */
762 
763 	type = XARCHIVETYPE_XZ;
764 	path = xz;
765 
766 	if (path)
767 		archiver[type].is_compressor = TRUE;
768 	else
769 		path = g_find_program_in_path("unxz");
770 
771 	standard = (path && archiver[type].is_compressor);
772 
773 	if (!standard)
774 	{
775 		if (is7zr)
776 		{
777 			g_free(path);
778 			/* alternative compressor */
779 			path = g_strconcat(sevenz, " -txz", NULL);
780 			archiver[type].is_compressor = TRUE;
781 		}
782 		else if (!path)
783 		{
784 			if (lsar)
785 				/* alternative ... */
786 				path = g_strdup(lsar);
787 			if (unar)
788 				/* ... uncompressor */
789 				archiver[type].program[1] = g_strdup(unar);
790 		}
791 		else
792 			standard = TRUE;
793 	}
794 
795 	if (path)
796 	{
797 		archiver[type].program[0] = path;
798 		archiver[type].type = g_slist_append(archiver[type].type, "xz");
799 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.xz");
800 
801 		archiver[type].ask = FUNC(standard, xa_gzip_et_al_ask, is7zr, xa_7zip_ask, lsar, xa_unar_ask);
802 		archiver[type].list = FUNC(standard, xa_gzip_et_al_list, is7zr, xa_7zip_list, lsar, xa_unar_list);
803 		archiver[type].test = FUNC(standard, xa_gzip_et_al_test, is7zr, xa_7zip_test, lsar, xa_unar_test);
804 		archiver[type].extract = FUNC(standard, xa_gzip_et_al_extract, is7zr, xa_7zip_extract, unar, xa_unar_extract);
805 		archiver[type].add = FUNC(standard, xa_gzip_et_al_add, is7zr, xa_7zip_add, lsar, NULL);
806 	}
807 
808 	/* zip */
809 
810 	type = XARCHIVETYPE_ZIP;
811 
812 	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prefs_window->prefer_unzip)) ||
813 	    (!is7za && !lsar))
814 	{
815 		path = g_find_program_in_path("/usr/local/bin/unzip");
816 
817 		if (path)
818 		{
819 			gchar *zip = g_find_program_in_path("/usr/local/bin/zip");
820 
821 			if (zip)
822 			{
823 				archiver[type].program[1] = zip;
824 				archiver[type].is_compressor = TRUE;
825 			}
826 		}
827 	}
828 	else
829 		path = NULL;
830 
831 	standard = (path && archiver[type].is_compressor);
832 
833 	if (!standard)
834 	{
835 		if (is7za)
836 		{
837 			g_free(path);
838 			/* alternative compressor */
839 			path = g_strconcat(sevenz, " -tzip", NULL);
840 			archiver[type].is_compressor = TRUE;
841 		}
842 		else if (!path)
843 		{
844 			if (lsar)
845 				/* alternative ... */
846 				path = g_strdup(lsar);
847 			if (unar)
848 				/* ... uncompressor */
849 				archiver[type].program[1] = g_strdup(unar);
850 		}
851 		else
852 			standard = TRUE;
853 	}
854 
855 	if (path)
856 	{
857 		archiver[type].program[0] = path;
858 		archiver[type].type = g_slist_append(archiver[type].type, "zip");
859 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.zip");
860 		/* Android application package */
861 		archiver[type].type = g_slist_append(archiver[type].type, "apk");
862 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.apk");
863 		archiver[type].tags = g_slist_append(archiver[type].tags, GUINT_TO_POINTER('a'));
864 		archiver[type].tags = g_slist_append(archiver[type].tags, g_slist_last(archiver[type].type)->data);
865 		/* comic book */
866 		archiver[type].type = g_slist_append(archiver[type].type, "cbz");
867 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.cbz");
868 		archiver[type].tags = g_slist_append(archiver[type].tags, GUINT_TO_POINTER('c'));
869 		archiver[type].tags = g_slist_append(archiver[type].tags, g_slist_last(archiver[type].type)->data);
870 		/* electronic publication */
871 		archiver[type].type = g_slist_append(archiver[type].type, "epub");
872 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.epub");
873 		archiver[type].tags = g_slist_append(archiver[type].tags, GUINT_TO_POINTER('e'));
874 		archiver[type].tags = g_slist_append(archiver[type].tags, g_slist_last(archiver[type].type)->data);
875 		/* java archive */
876 		archiver[type].type = g_slist_append(archiver[type].type, "jar");
877 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.jar");
878 		archiver[type].tags = g_slist_append(archiver[type].tags, GUINT_TO_POINTER('j'));
879 		archiver[type].tags = g_slist_append(archiver[type].tags, g_slist_last(archiver[type].type)->data);
880 		/* OpenOffice.org extension */
881 		archiver[type].type = g_slist_append(archiver[type].type, "oxt");
882 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.oxt");
883 		archiver[type].tags = g_slist_append(archiver[type].tags, GUINT_TO_POINTER('o'));
884 		archiver[type].tags = g_slist_append(archiver[type].tags, g_slist_last(archiver[type].type)->data);
885 		/* XPInstall */
886 		archiver[type].type = g_slist_append(archiver[type].type, "xpi");
887 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.xpi");
888 		archiver[type].tags = g_slist_append(archiver[type].tags, GUINT_TO_POINTER('x'));
889 		archiver[type].tags = g_slist_append(archiver[type].tags, g_slist_last(archiver[type].type)->data);
890 
891 		archiver[type].ask = FUNC(standard, xa_zip_ask, is7za, xa_7zip_ask, lsar, xa_unar_ask);
892 		archiver[type].list = FUNC(standard, xa_zip_list, is7za, xa_7zip_list, lsar, xa_unar_list);
893 		archiver[type].test = FUNC(standard, xa_zip_test, is7za, xa_7zip_test, lsar, xa_unar_test);
894 		archiver[type].extract = FUNC(standard, xa_zip_extract, is7za, xa_7zip_extract, unar, xa_unar_extract);
895 		archiver[type].add = FUNC(standard, xa_zip_add, is7za, xa_7zip_add, lsar, NULL);
896 		archiver[type].delete = FUNC(standard, xa_zip_delete, is7za, xa_7zip_delete, lsar, NULL);
897 	}
898 
899 	/* Zstandard */
900 
901 	type = XARCHIVETYPE_ZSTD;
902 	path = zstd;                // either zstd or unzstd
903 
904 	if (path)
905 	{
906 		archiver[type].program[0] = path;
907 		archiver[type].type = g_slist_append(archiver[type].type, "zstd");
908 		archiver[type].glob = g_slist_append(archiver[type].glob, "*.zst");
909 
910 		archiver[type].ask = xa_gzip_et_al_ask;
911 		archiver[type].list = xa_gzip_et_al_list;
912 		archiver[type].test = xa_gzip_et_al_test;
913 		archiver[type].extract = xa_gzip_et_al_extract;
914 		archiver[type].add = xa_gzip_et_al_add;
915 	}
916 
917 	/* compressed tar */
918 
919 	if (archiver[XARCHIVETYPE_TAR].ask == xa_tar_ask || archiver[XARCHIVETYPE_TAR].ask == xa_unar_ask)
920 	{
921 		struct
922 		{
923 			XArchiveType compressor;
924 			gchar *type[2];
925 			gchar *glob[2];
926 		} compressed_tar_infos[] =
927 		{
928 			{XARCHIVETYPE_BZIP2, {"tar.bzip2", NULL}, {"*.tar.bz2", "*.tbz2"}},
929 			{XARCHIVETYPE_COMPRESS, {"tar.compress", NULL}, {"*.tar.Z", ""}},
930 			{XARCHIVETYPE_GZIP, {"tar.gzip", NULL}, {"*.tar.gz", "*.tgz"}},
931 			{XARCHIVETYPE_LRZIP, {"tar.lrzip", NULL}, {"*.tar.lrz", "*.tlrz"}},
932 			{XARCHIVETYPE_LZ4, {"tar.lz4", NULL}, {"*.tar.lz4", ""}},
933 			{XARCHIVETYPE_LZIP, {"tar.lzip", NULL}, {"*.tar.lz", ""}},
934 			{XARCHIVETYPE_LZMA, {"tar.lzma", NULL}, {"*.tar.lzma", "*.tlz"}},
935 			{XARCHIVETYPE_LZOP, {"tar.lzop", NULL}, {"*.tar.lzo", "*.tzo"}},
936 			{XARCHIVETYPE_XZ, {"tar.xz", NULL}, {"*.tar.xz", "*.txz"}},
937 			{XARCHIVETYPE_ZSTD, {"tar.zstd", NULL}, {"*.tar.zst", "*.tzst"}},
938 			{XARCHIVETYPE_UNKNOWN, {NULL, NULL}, {NULL, NULL}}
939 		}, *i;
940 
941 		for (i = compressed_tar_infos; i->compressor != XARCHIVETYPE_UNKNOWN; i++)
942 		{
943 			if (archiver[i->compressor].type)
944 			{
945 				type = i->compressor;
946 
947 				if (!xa_get_compressed_tar_type(&type))
948 					continue;
949 
950 				if ((archiver[XARCHIVETYPE_TAR].ask == xa_tar_ask && archiver[i->compressor].ask == xa_gzip_et_al_ask) ||
951 				    (archiver[XARCHIVETYPE_TAR].ask == xa_unar_ask && archiver[i->compressor].ask == xa_unar_ask))
952 				{
953 					archiver[type].is_compressor = archiver[i->compressor].is_compressor;
954 					archiver[type].type = g_slist_append(archiver[type].type, i->type[0]);
955 					archiver[type].glob = g_slist_append(archiver[type].glob, i->glob[0]);
956 					archiver[type].type = g_slist_append(archiver[type].type, i->type[1]);
957 					archiver[type].glob = g_slist_append(archiver[type].glob, i->glob[1]);
958 
959 					archiver[type].ask = archiver[XARCHIVETYPE_TAR].ask;
960 					archiver[type].list = archiver[XARCHIVETYPE_TAR].list;
961 					archiver[type].extract = archiver[XARCHIVETYPE_TAR].extract;
962 					archiver[type].add = archiver[XARCHIVETYPE_TAR].add;
963 					archiver[type].delete = archiver[XARCHIVETYPE_TAR].delete;
964 				}
965 			}
966 		}
967 	}
968 
969 	g_free(lbzip2);
970 	g_free(lsar);
971 	g_free(pbzip2);
972 	g_free(pigz);
973 	g_free(plzip);
974 	g_free(unar);
975 }
976 
xa_init_structure_from_cmd_line(char * filename)977 static XArchive *xa_init_structure_from_cmd_line (char *filename)
978 {
979 	XArchive *archive;
980 	ArchiveType xa;
981 	gchar *path;
982 
983 	xa = xa_detect_archive_type(filename);
984 
985 	if (xa.type == XARCHIVETYPE_UNKNOWN || xa.type == XARCHIVETYPE_NOT_FOUND)
986 		return NULL;
987 
988 	if (!archiver[xa.type].list)
989 	{
990 		xa_show_message_dialog(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Sorry, this archive format is not supported:"), _("The proper archiver is not installed!"));
991 		return NULL;
992 	}
993 
994 	archive = xa_init_archive_structure(xa);
995 
996 	if (archive == NULL)
997 	{
998 		xa_show_message_dialog (NULL,GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_("Can't allocate memory for the archive structure!"),"" );
999 		return NULL;
1000 	}
1001 
1002 	if (*filename != '/')
1003 	{
1004 		gchar *cur_dir = g_get_current_dir();
1005 		path = g_strconcat(cur_dir, "/", filename, NULL);
1006 		g_free(cur_dir);
1007 	}
1008 	else
1009 		path = g_strdup(filename);
1010 
1011 	archive->path[0] = g_strdup(path);
1012 	archive->path[1] = xa_escape_bad_chars(path, ESCAPES);
1013 
1014 	g_free(path);
1015 
1016 	return archive;
1017 }
1018 
xa_cmd_line_error(const char * argv1,const gchar * header)1019 static void xa_cmd_line_error (const char *argv1, const gchar *header)
1020 {
1021 	if (argv1)
1022 		xa_show_message_dialog(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, header, _("Can't open the archive!\n"));
1023 	else
1024 		xa_show_message_dialog(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, header, _("You missed the archive name!\n"));
1025 }
1026 
main(int argc,char ** argv)1027 int main (int argc, char **argv)
1028 {
1029 	GError *cli_error = NULL;
1030 	XArchive *archive;
1031 	gchar *current_dir;
1032 	int i, result = -1;
1033 
1034 #ifdef ENABLE_NLS
1035 	GTK_COMPAT_PARAMETER_STRING;
1036 	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
1037 	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1038 	textdomain (GETTEXT_PACKAGE);
1039 #endif
1040 
1041 #ifdef HAVE_SOCKET
1042 	socket_info.lock_socket = -1;
1043 	socket_info.lock_socket_tag = 0;
1044 	socket_info.lock_socket = socket_init(argc, argv);
1045 
1046 	if (socket_info.lock_socket < 0)
1047 	{
1048 		/* Socket exists; filenames were sent to first instance, so quit */
1049 		if (argc > 1)
1050 			return 0;
1051 	}
1052 #endif
1053 	gtk_init_with_args(&argc, &argv, _("[ARCHIVE]"), entries, GETTEXT_PACKAGE, &cli_error);
1054 
1055 	if ( cli_error != NULL )
1056 	{
1057 		g_print (_("xarchiver: %s\nTry xarchiver --help to see a full list of available command line options.\n"),cli_error->message);
1058 		g_error_free (cli_error);
1059 		return 0;
1060 	}
1061     /* print version information */
1062     if (opt_version)
1063     {
1064         g_print("%s %s \n\n", PACKAGE_NAME, PACKAGE_VERSION);
1065         g_print (_("Maintained by "));
1066         g_print (MAINTAINER ".\n\n");
1067         g_print ("%s\n", "Copyright (c) " COPYRIGHT_YEAR);
1068         g_print ("\t%s\n\n", COPYRIGHT_HOLDER " - Colossus <colossus73@gmail.com>");
1069         g_print (_("Please report bugs to <%s>."), PACKAGE_BUGREPORT);
1070         g_print ("\n");
1071 
1072         return EXIT_SUCCESS;
1073     }
1074 
1075 	xdg_open = g_find_program_in_path("xdg-open");
1076 
1077 	prefs_window   = xa_create_prefs_dialog();
1078 	extract_window = xa_create_extract_dialog();
1079 	add_window     = xa_create_add_dialog();
1080 	multi_extract_window = xa_create_multi_extract_dialog();
1081 
1082 	xa_prefs_load_options(prefs_window);
1083 	xa_check_available_archivers();
1084 	xa_prefs_adapt_options(prefs_window);
1085 
1086 	if (opt_extract || opt_extract_path || opt_ensure_dir || opt_multi_extract || opt_add || opt_compress || opt_info)
1087 	{
1088 		archive = xa_init_structure_from_cmd_line (argv[1]);
1089 		g_print(PACKAGE_NAME " 0.5.4 \xC2\xA9  " COPYRIGHT_YEAR " " COPYRIGHT_HOLDER "\n");
1090 		g_print(PACKAGE_NAME " %-8s " MAINTAINER "\n", VERSION);
1091 
1092 		/* Switches -d and -x */
1093 		if (opt_ensure_dir || opt_extract_path)
1094 		{
1095 			gchar *extraction_dir = NULL;
1096 
1097 			if (!archive)
1098 			{
1099 				xa_cmd_line_error(argv[1], _("Can't extract files from the archive:"));
1100 				goto leave;
1101 			}
1102 
1103 			if (!archive->can_extract)
1104 			{
1105 				xa_show_message_dialog(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Can't extract files from the archive:"), argv[1]);
1106 				goto leave;
1107 			}
1108 
1109 			xa_detect_encrypted_archive(archive);
1110 
1111 			if (archive->status == XARCHIVESTATUS_ERROR)
1112 				goto leave;
1113 
1114 			if (archive->has_password)
1115 			{
1116 				if (!xa_check_password(archive))
1117 					goto leave;
1118 			}
1119 
1120 			if (opt_ensure_dir)
1121 			{
1122 				current_dir = g_get_current_dir();
1123 
1124 				if (xa_has_containing_directory(archive))
1125 					extraction_dir = g_strdup(current_dir);
1126 				else
1127 				{
1128 					extraction_dir = xa_create_containing_directory(archive, current_dir);
1129 
1130 					if (!extraction_dir)
1131 					{
1132 						xa_show_message_dialog(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Can't create directory!"), "");
1133 						g_free(current_dir);
1134 						goto leave;
1135 					}
1136 				}
1137 
1138 				opt_extract_path = extraction_dir;
1139 				g_free(current_dir);
1140 			}
1141 
1142 			archive->do_full_path = TRUE;
1143 			archive->do_overwrite = TRUE;
1144 			archive->extraction_dir = xa_escape_bad_chars(opt_extract_path, ESCAPES);
1145 			g_free(extraction_dir);
1146 
1147 			archive->status = XARCHIVESTATUS_EXTRACT;
1148 			(*archive->archiver->extract)(archive, NULL);
1149 		}
1150 		/* Switch -e */
1151 		else if (opt_extract)
1152 		{
1153 			if (!archive)
1154 			{
1155 				xa_cmd_line_error(argv[1], _("Can't extract files from the archive:"));
1156 				goto leave;
1157 			}
1158 
1159 			if (!archive->can_extract)
1160 			{
1161 				xa_show_message_dialog(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Can't extract files from the archive:"), argv[1]);
1162 				goto leave;
1163 			}
1164 
1165 			xa_detect_encrypted_archive(archive);
1166 
1167 			if (archive->status == XARCHIVESTATUS_ERROR)
1168 				goto leave;
1169 
1170 			if (archive->has_password)
1171 			{
1172 				if (!xa_check_password(archive))
1173 					goto leave;
1174 			}
1175 
1176 			xa_set_extract_dialog_options(extract_window,0,archive);
1177 			xa_parse_extract_dialog_options (archive,extract_window,NULL);
1178 			gtk_widget_destroy (extract_window->dialog1);
1179 			g_free (extract_window);
1180 		}
1181 		/* Switch -m */
1182 		else if (opt_multi_extract)
1183 		{
1184 			Multi_extract_data *multi_extract = NULL;
1185 			multi_extract = xa_create_multi_extract_dialog();
1186 			for (i = 1; i < argc; i++)
1187 				if (!g_file_test(argv[i], G_FILE_TEST_IS_DIR))
1188 					xa_multi_extract_dialog_add_file(argv[i], multi_extract);
1189 
1190 			xa_multi_extract_dialog(multi_extract);
1191 			gtk_widget_destroy (multi_extract->multi_extract);
1192 			g_free(multi_extract);
1193 		}
1194 		/* Switch -c */
1195 		else if (opt_compress)
1196 		{
1197 			archive = xa_new_archive_dialog(opt_compress, NULL);
1198 
1199 			if (archive == NULL)
1200 				goto leave;
1201 
1202 			if (archive->path[0] != NULL)
1203 			{
1204 				xa_create_working_directory(archive);
1205 				current_dir = g_path_get_dirname(opt_compress);
1206 				chdir(current_dir);
1207 				g_free(current_dir);
1208 				GSList *files = NULL;
1209 				current_dir = g_path_get_basename(opt_compress);
1210 				files = g_slist_append(files, g_strdup(current_dir));
1211 				g_free(current_dir);
1212 				g_free(opt_compress);
1213 				for (i = 1; i < argc; i++)
1214 				{
1215 					current_dir = g_path_get_basename(argv[i]);
1216 					files = g_slist_append(files, g_strdup(current_dir));
1217 					g_free(current_dir);
1218 				}
1219 				xa_execute_add_commands(archive, files, TRUE, NULL);
1220 			}
1221 		}
1222 		/* Switch -a */
1223 		else if (opt_add)
1224 		{
1225 			if (!archive)
1226 			{
1227 				xa_cmd_line_error(argv[1], _("Can't add files to the archive:"));
1228 				goto leave;
1229 			}
1230 			if (!archive->can_add)
1231 			{
1232 				xa_show_message_dialog(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("Can't add files to the archive:"), argv[1]);
1233 				goto leave;
1234 			}
1235 
1236 			xa_detect_encrypted_archive(archive);
1237 
1238 			if (archive->status == XARCHIVESTATUS_ERROR)
1239 				goto leave;
1240 
1241 			if (archive->has_password)
1242 			{
1243 				if (!xa_check_password(archive))
1244 					goto leave;
1245 			}
1246 
1247 			xa_set_add_dialog_options(add_window, archive);
1248 			xa_parse_add_dialog_options(archive, add_window);
1249 			gtk_widget_destroy(add_window->dialog1);
1250 			g_free(add_window);
1251 		}
1252 		/* Switch -i */
1253 		else if (opt_info)
1254 		{
1255 			GSList *list;
1256 
1257 			for (i = XARCHIVETYPE_FIRST; i < XARCHIVETYPE_TYPES; i++)
1258 			{
1259 				list = archiver[i].type;
1260 
1261 				while (list)
1262 				{
1263 					if (list->data)
1264 					{
1265 						if (strncmp(list->data, "tar.", 4) == 0)
1266 							break;
1267 
1268 						g_print("%s", (char *) list->data);
1269 					}
1270 
1271 					list = list->next;
1272 
1273 					if (list && list->data)
1274 						g_print(", ");
1275 					else
1276 					{
1277 						g_print(":\n  %s\n", archiver[i].program[0]);
1278 
1279 						if (archiver[i].program[1])
1280 							g_print("  %s\n", archiver[i].program[1]);
1281 					}
1282 				}
1283 			}
1284 		}
1285 
1286 		result = EXIT_SUCCESS;
1287 
1288 leave:
1289 
1290 		if (progress)
1291 		{
1292 			gtk_widget_destroy(progress->window);
1293 			g_free(progress);
1294 			progress = NULL;
1295 		}
1296 		if (archive != NULL)
1297 			xa_clean_archive_structure (archive);
1298 		#ifdef HAVE_SOCKET
1299 			socket_finalize();
1300 		#endif
1301 	}
1302 	else
1303 	{
1304 		xa_main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1305 		xa_create_main_window (xa_main_window,	gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (prefs_window->show_location_bar)),
1306 												gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (prefs_window->show_sidebar)),
1307 												gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (prefs_window->show_toolbar)));
1308 
1309 		gtk_window_set_transient_for (GTK_WINDOW (extract_window->dialog1),GTK_WINDOW (xa_main_window));
1310 		gtk_window_set_transient_for (GTK_WINDOW (add_window->dialog1),GTK_WINDOW (xa_main_window));
1311 		gtk_window_set_transient_for (GTK_WINDOW (prefs_window->dialog1),GTK_WINDOW (xa_main_window));
1312 		gtk_window_set_transient_for (GTK_WINDOW (multi_extract_window->multi_extract),GTK_WINDOW (xa_main_window));
1313 		if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prefs_window->check_save_geometry)) && prefs_window->geometry[0] != -1)
1314 		{
1315 			gtk_window_move (GTK_WINDOW(xa_main_window), prefs_window->geometry[0], prefs_window->geometry[1]);
1316 			gtk_window_set_default_size(GTK_WINDOW(xa_main_window), prefs_window->geometry[2], prefs_window->geometry[3]);
1317 			gtk_paned_set_position(GTK_PANED(hpaned1), prefs_window->geometry[4]);
1318 		}
1319 		else
1320 		{
1321 			gtk_window_set_position (GTK_WINDOW(xa_main_window),GTK_WIN_POS_CENTER);
1322 			gtk_window_set_default_size (GTK_WINDOW(xa_main_window), 600, 400);
1323 			gtk_paned_set_position (GTK_PANED (hpaned1),200);
1324 		}
1325 		gtk_label_set_text(GTK_LABEL(total_label),_("Select \"New\" to create or \"Open\" to open an archive"));
1326 		gtk_widget_show (xa_main_window);
1327 
1328 		/* This to open the archive from the command line */
1329 		if ( argc == 2 )
1330 		{
1331 			gchar *dummy;
1332 			if (g_str_has_prefix(argv[1], "file://") == TRUE)
1333 				dummy = g_strdup(argv[1]+6);
1334 			else
1335 				dummy = g_strdup(argv[1]);
1336 
1337 			current_open_directory = g_path_get_dirname (dummy);
1338 			if (strcmp(current_open_directory,"..") == 0)
1339 			{
1340 				g_free (current_open_directory);
1341 				current_open_directory = g_get_current_dir();
1342 			}
1343 			xa_open_archive (NULL,dummy);
1344 		}
1345 		#ifdef HAVE_SOCKET
1346 		if (! socket_info.ignore_socket && socket_info.lock_socket > 0)
1347 		{
1348 			socket_info.read_ioc = g_io_channel_unix_new(socket_info.lock_socket);
1349 			socket_info.lock_socket_tag = g_io_add_watch(socket_info.read_ioc, G_IO_IN | G_IO_ERR, socket_lock_input_cb, xa_main_window);
1350 		}
1351 		#endif
1352 		gtk_main ();
1353 
1354 		result = EXIT_SUCCESS;
1355 	}
1356 
1357 	for (i = XARCHIVETYPE_FIRST; i < XARCHIVETYPE_TYPES; i++)
1358 	{
1359 		g_free(archiver[i].program[0]);
1360 		g_free(archiver[i].program[1]);
1361 		g_slist_free(archiver[i].type);
1362 		g_slist_free(archiver[i].glob);
1363 		g_slist_free(archiver[i].tags);
1364 	}
1365 
1366 	g_free(xdg_open);
1367 
1368 	return result;
1369 }
1370