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 <string.h>
21 #include "arj.h"
22 #include "date_utils.h"
23 #include "main.h"
24 #include "string_utils.h"
25 #include "support.h"
26 #include "window.h"
27
28 static gboolean data_line, fname_line;
29
xa_arj_ask(XArchive * archive)30 void xa_arj_ask (XArchive *archive)
31 {
32 archive->can_test = TRUE;
33 archive->can_extract = TRUE;
34 archive->can_add = archiver[archive->type].is_compressor;
35 archive->can_delete = archiver[archive->type].is_compressor;
36 archive->can_sfx = archiver[archive->type].is_compressor;
37 archive->can_password = archiver[archive->type].is_compressor;
38 archive->can_full_path[0] = archiver[archive->type].is_compressor;
39 archive->can_full_path[1] = archiver[archive->type].is_compressor;
40 archive->can_overwrite = TRUE;
41 archive->can_update[0] = TRUE;
42 archive->can_update[1] = archiver[archive->type].is_compressor;
43 archive->can_freshen[0] = archiver[archive->type].is_compressor;
44 archive->can_freshen[1] = archiver[archive->type].is_compressor;
45 archive->can_move = archiver[archive->type].is_compressor;
46 }
47
xa_arj_password_str(XArchive * archive)48 static gchar *xa_arj_password_str (XArchive *archive)
49 {
50 if (archive->password && archiver[archive->type].is_compressor)
51 return g_strconcat(" -g", archive->password, NULL);
52 else
53 return g_strdup("");
54 }
55
xa_arj_parse_output(gchar * line,XArchive * archive)56 static void xa_arj_parse_output (gchar *line, XArchive *archive)
57 {
58 XEntry *entry;
59 gpointer item[7];
60 unsigned int linesize,n,a;
61 static gchar *filename;
62 gboolean unarj, lfn, dir, encrypted;
63
64 unarj = !archiver[archive->type].is_compressor;
65
66 if (!data_line)
67 {
68 if (line[0] == '-')
69 {
70 data_line = TRUE;
71 return;
72 }
73 return;
74 }
75
76 if (!fname_line)
77 {
78 linesize = strlen(line);
79 line[linesize - 1] = '\0';
80
81 if (!unarj && (*line == ' '))
82 return;
83
84 if (line[0] == '-' && linesize == (unarj ? 59 : 41))
85 {
86 data_line = FALSE;
87 return;
88 }
89
90 if (unarj)
91 {
92 /* simple column separator check */
93 lfn = (linesize < 76 || line[34] != ' ' || line[40] != ' ' || line[49] != ' ' || line[58] != ' ' || line[67] != ' ');
94
95 if (lfn)
96 filename = g_strdup(line);
97 else
98 {
99 filename = g_strchomp(g_strndup(line, 12));
100
101 if (!*filename)
102 {
103 g_free(filename);
104 filename = g_strdup(" "); // just a wild guess in order to have an entry
105 }
106 }
107 }
108 else
109 {
110 lfn = TRUE;
111 filename = g_strdup(line + 5);
112 }
113
114 fname_line = TRUE;
115 if (lfn)
116 return;
117 }
118
119 if (fname_line)
120 {
121 linesize = strlen(line);
122 /* Size */
123 for(n=12; n < linesize && line[n] == ' '; n++);
124 a = n;
125 for(; n < linesize && line[n] != ' '; n++);
126 line[n]='\0';
127 item[0] = line + a;
128 n++;
129
130 /* Compressed */
131 for(; n < linesize && line[n] == ' '; n++);
132 a = n;
133 for(; n < linesize && line[n] != ' '; n++);
134 line[n]='\0';
135 item[1] = line + a;
136 n++;
137
138 /* Ratio */
139 line[40] = '\0';
140 item[2] = line + 35;
141
142 /* Date */
143 line[49] = '\0';
144 item[3] = date_YY_MM_DD(line + 41);
145
146 /* Time */
147 line[58] = '\0';
148 item[4] = line + 50;
149
150 /* CRC */
151 if (unarj)
152 {
153 line[67] = '\0';
154 item[6] = line + 59;
155 }
156
157 /* Permissions */
158 line[unarj ? 72 : 69] = '\0';
159 item[5] = line + (unarj ? 68 : 59);
160
161 /* BTPMGVX */
162 if (unarj)
163 {
164 dir = (line[73] == 'D');
165 encrypted = (line[76] == 'G');
166 }
167 /* BPMGS */
168 else
169 {
170 dir = (line[59] == 'd');
171 encrypted = (line[77] == '1');
172 }
173
174 if (encrypted)
175 archive->has_password = TRUE;
176
177 if (unarj && dir)
178 /* skip entry since unarj lacks directory structure information */
179 entry = NULL;
180 else
181 entry = xa_set_archive_entries_for_each_row(archive, filename, item);
182
183 if (entry)
184 {
185 if (dir)
186 entry->is_dir = TRUE;
187
188 entry->is_encrypted = encrypted;
189
190 if (!entry->is_dir)
191 archive->files++;
192
193 archive->files_size += g_ascii_strtoull(item[0], NULL, 0);
194 }
195
196 g_free(filename);
197 fname_line = FALSE;
198 }
199 }
200
xa_arj_list(XArchive * archive)201 void xa_arj_list (XArchive *archive)
202 {
203 const GType types[] = {GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_UINT64, G_TYPE_UINT64, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, archiver[archive->type].is_compressor ? G_TYPE_POINTER : G_TYPE_STRING, G_TYPE_POINTER};
204 const gchar *titles[] = {_("Original Size"), _("Compressed"), _("Ratio"), _("Date"), _("Time"), archiver[archive->type].is_compressor ? _("Permissions") : _("Attributes"), archiver[archive->type].is_compressor ? NULL : _("Checksum")};
205 guint i;
206
207 data_line = FALSE;
208 fname_line = FALSE;
209 gchar *command = g_strconcat(archiver[archive->type].program[0], archiver[archive->type].is_compressor ? " v " : " l ", archive->path[1], NULL);
210 archive->files_size = 0;
211 archive->files = 0;
212 archive->parse_output = xa_arj_parse_output;
213 xa_spawn_async_process (archive,command);
214 g_free (command);
215
216 archive->columns = (archiver[archive->type].is_compressor ? 9 : 10);
217 archive->size_column = 2;
218 archive->column_types = g_malloc0(sizeof(types));
219
220 for (i = 0; i < archive->columns; i++)
221 archive->column_types[i] = types[i];
222
223 xa_create_liststore(archive, titles);
224 }
225
xa_arj_test(XArchive * archive)226 void xa_arj_test (XArchive *archive)
227 {
228 gchar *password_str, *command;
229
230 password_str = xa_arj_password_str(archive);
231 command = g_strconcat(archiver[archive->type].program[0], " t", password_str, archiver[archive->type].is_compressor ? " -i -y " : " ", archive->path[1], NULL);
232 g_free(password_str);
233
234 xa_run_command(archive, command);
235 g_free(command);
236 }
237
xa_arj_extract(XArchive * archive,GSList * file_list)238 gboolean xa_arj_extract (XArchive *archive, GSList *file_list)
239 {
240 GString *files;
241 gchar *command;
242 gboolean result;
243
244 files = xa_quote_filenames(file_list, "*?[]", FALSE);
245
246 if (archiver[archive->type].is_compressor)
247 {
248 gchar *password_str = xa_arj_password_str(archive);
249 command = g_strconcat(archiver[archive->type].program[0],
250 archive->do_full_path ? " x" : " e",
251 archive->do_overwrite ? "" : (archive->do_update ? " -u" : (archive->do_freshen ? " -f" : " -n")),
252 password_str, " -i -y ",
253 archive->path[1], " ",
254 archive->extraction_dir, files->str, NULL);
255 g_free(password_str);
256 }
257 else
258 {
259 if (xa_create_working_directory(archive))
260 {
261 gchar *files_str, *extraction_dir, *archive_path, *move;
262
263 files_str = xa_escape_bad_chars(files->str, "\"");
264 extraction_dir = xa_quote_shell_command(archive->extraction_dir, FALSE);
265 archive_path = xa_quote_shell_command(archive->path[0], TRUE);
266
267 if (strcmp(archive->extraction_dir, archive->working_dir) == 0)
268 move = g_strdup("");
269 else
270 move = g_strconcat(" && mv",
271 archive->do_overwrite ? " -f" : " -n",
272 archive->do_update ? " -fu" : "",
273 *files->str ? files_str : " *", " ",
274 extraction_dir, NULL);
275
276 archive->child_dir = g_strdup(archive->working_dir);
277 command = g_strconcat("sh -c \"rm -f * && ",
278 archiver[archive->type].program[0], " e ",
279 archive_path, move, "\"", NULL);
280 g_free(move);
281 g_free(archive_path);
282 g_free(extraction_dir);
283 g_free(files_str);
284 }
285 else
286 command = g_strdup("sh -c \"\"");
287 }
288
289 g_string_free(files,TRUE);
290
291 result = xa_run_command(archive, command);
292 g_free(command);
293
294 g_free(archive->child_dir);
295 archive->child_dir = NULL;
296
297 return result;
298 }
299
xa_arj_add(XArchive * archive,GSList * file_list,gchar * compression)300 void xa_arj_add (XArchive *archive, GSList *file_list, gchar *compression)
301 {
302 GString *files;
303 gchar *password_str, *command;
304
305 if (archive->location_path != NULL)
306 archive->child_dir = g_strdup(archive->working_dir);
307
308 if (!compression)
309 compression = "1";
310
311 files = xa_quote_filenames(file_list, "*?[]", FALSE);
312 password_str = xa_arj_password_str(archive);
313 command = g_strconcat(archiver[archive->type].program[0],
314 archive->do_update ? " u" : " a",
315 archive->do_freshen ? " -f" : "",
316 archive->do_move ? " -d1" : "",
317 " -m", compression,
318 password_str, " -2d -i -y ",
319 archive->path[1], files->str, NULL);
320 g_free(password_str);
321 g_string_free(files,TRUE);
322
323 xa_run_command(archive, command);
324 g_free(command);
325 }
326
xa_arj_delete(XArchive * archive,GSList * file_list)327 void xa_arj_delete (XArchive *archive, GSList *file_list)
328 {
329 GString *files;
330 gchar *command;
331
332 files = xa_quote_filenames(file_list, "*?[]", FALSE);
333 command = g_strconcat(archiver[archive->type].program[0], " d -i -y ", archive->path[1], files->str, NULL);
334 g_string_free(files,TRUE);
335
336 xa_run_command(archive, command);
337 g_free(command);
338 }
339