1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3 /*
4 * Engrampa
5 *
6 * Copyright (C) 2001 The Free Software Foundation, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Street #330, Boston, MA 02110-1301, USA.
21 */
22
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26 #include <unistd.h>
27
28 #include <glib.h>
29
30 #include "file-data.h"
31 #include "file-utils.h"
32 #include "fr-command.h"
33 #include "fr-command-alz.h"
34 #include "glib-utils.h"
35
36 static void fr_command_alz_class_init (FrCommandAlzClass *class);
37 static void fr_command_alz_init (FrCommand *afile);
38 static void fr_command_alz_finalize (GObject *object);
39
40 /* Parent Class */
41
42 static FrCommandClass *parent_class = NULL;
43
44
45 /* -- list -- */
46
47
48 static time_t
mktime_from_string(char * date_s,char * time_s)49 mktime_from_string (char *date_s,
50 char *time_s)
51 {
52 struct tm tm = {0, };
53 char **fields;
54
55 /* date */
56
57 fields = g_strsplit (date_s, "/", 3);
58 if (fields[0] != NULL) {
59 tm.tm_mon = atoi (fields[0]) - 1;
60 if (fields[1] != NULL) {
61 tm.tm_mday = atoi (fields[1]);
62 if (fields[2] != NULL)
63 tm.tm_year = 100 + atoi (fields[2]);
64 }
65 }
66 g_strfreev (fields);
67
68 /* time */
69
70 fields = g_strsplit (time_s, ":", 3);
71 if (fields[0] != NULL) {
72 tm.tm_hour = atoi (fields[0]);
73 if (fields[1] != NULL)
74 tm.tm_min = atoi (fields[1]);
75 }
76 g_strfreev (fields);
77
78 return mktime (&tm);
79 }
80
81
82 static void
process_line(char * line,gpointer data)83 process_line (char *line,
84 gpointer data)
85 {
86 FrCommand *comm = FR_COMMAND (data);
87 FrCommandAlz *alz_comm = FR_COMMAND_ALZ (comm);
88 FileData *fdata;
89 char **fields;
90 char *name_field;
91 char name_last;
92 gsize name_len;
93
94 g_return_if_fail (line != NULL);
95
96
97 if (! alz_comm->list_started) {
98 if (strncmp (line, "-----", 5 ) == 0 )
99 alz_comm->list_started = TRUE;
100 return;
101 }
102
103 if (strncmp (line, "-----", 5 ) == 0) {
104 alz_comm->list_started = FALSE;
105 return;
106
107 }
108
109 if (! alz_comm->list_started)
110 return;
111
112 fdata = file_data_new ();
113 fields = split_line (line, 5);
114 fdata->modified = mktime_from_string (fields[0], fields[1]);
115 fdata->size = g_ascii_strtoull (fields[3], NULL, 10);
116
117 name_field = g_strdup (get_last_field (line, 6));
118 name_len = strlen (name_field);
119
120 name_last = name_field[name_len - 1];
121 fdata->dir = name_last == '\\';
122 fdata->encrypted = name_last == '*';
123
124 if (fdata->dir || fdata->encrypted)
125 name_field[--name_len] = '\0';
126
127 if (*name_field == '/') {
128 fdata->full_path = g_strdup (name_field);
129 fdata->original_path = fdata->full_path;
130 }
131 else {
132 fdata->full_path = g_strconcat ("/", name_field, NULL);
133 fdata->original_path = fdata->full_path + 1;
134 }
135
136 if (fdata->dir) {
137 char *s;
138 for (s = fdata->full_path; *s != '\0'; ++s)
139 if (*s == '\\') *s = '/';
140 for (s = fdata->original_path; *s != '\0'; ++s)
141 if (*s == '\\') *s = '/';
142 fdata->name = dir_name_from_path (fdata->full_path);
143 }
144 else {
145 fdata->name = g_strdup (file_name_from_path (fdata->full_path));
146 }
147
148 fdata->path = remove_level_from_path (fdata->full_path);
149
150 if (*fdata->name == 0)
151 file_data_free (fdata);
152 else
153 fr_command_add_file (comm, fdata);
154
155 g_free (name_field);
156 g_strfreev (fields);
157 }
158
159
160 static void
add_codepage_arg(FrCommand * comm)161 add_codepage_arg (FrCommand *comm)
162 {
163 const char *env_list[] = { "LC_CTYPE", "LC_ALL", "LANG", NULL };
164 const char **scan;
165 const char *arg = "-cp949";
166
167 for (scan = env_list; *scan != NULL; ++scan) {
168 char *env = getenv (*scan);
169
170 if (! env)
171 continue;
172
173 if (strstr (env, "UTF-8") || strstr (env, "utf-8"))
174 arg = "-utf8";
175 else if (strstr (env, "euc") || strstr (env, "EUC"))
176 arg = "-euc-kr";
177 else
178 continue;
179 break;
180 }
181
182 fr_process_add_arg (comm->process, arg);
183 }
184
185
186 static void
add_password_arg(FrCommand * comm,const char * password,gboolean disable_query)187 add_password_arg (FrCommand *comm,
188 const char *password,
189 gboolean disable_query)
190 {
191 if (password != NULL) {
192 fr_process_add_arg (comm->process, "-pwd");
193 fr_process_add_arg (comm->process, password);
194 }
195 else if (disable_query) {
196 fr_process_add_arg (comm->process, "-pwd");
197 fr_process_add_arg (comm->process, "");
198 }
199 }
200
201
202 static void
list__begin(gpointer data)203 list__begin (gpointer data)
204 {
205 FrCommandAlz *comm = data;
206
207 comm->list_started = FALSE;
208 comm->invalid_password = FALSE;
209 }
210
211
212 static void
fr_command_alz_list(FrCommand * comm)213 fr_command_alz_list (FrCommand *comm)
214 {
215 fr_process_set_out_line_func (FR_COMMAND (comm)->process, process_line, comm);
216
217 fr_process_begin_command (comm->process, "unalz");
218 fr_process_set_begin_func (comm->process, list__begin, comm);
219 fr_process_add_arg (comm->process, "-l");
220 add_codepage_arg(comm);
221 fr_process_add_arg (comm->process, comm->filename);
222 fr_process_end_command (comm->process);
223 fr_process_use_standard_locale (comm->process, TRUE);
224 fr_process_start (comm->process);
225 }
226
227
228 /* -- extract -- */
229
230 static void
process_extract_line(char * line,gpointer data)231 process_extract_line (char *line,
232 gpointer data)
233 {
234 FrCommand *comm = FR_COMMAND (data);
235 FrCommandAlz *alz_comm = FR_COMMAND_ALZ (comm);
236
237 g_return_if_fail (line != NULL);
238
239 /* - error check - */
240
241 if (strncmp (line, "err code(28) (invalid password)", 31) == 0) {
242 alz_comm->invalid_password = TRUE;
243 fr_process_stop (comm->process);
244 return;
245 }
246
247 if (alz_comm->extract_none && (strncmp (line, "unalziiiing :", 13) == 0)) {
248 alz_comm->extract_none = FALSE;
249 }
250 else if ((strncmp (line, "done..", 6) == 0) && alz_comm->extract_none) {
251 fr_process_stop (comm->process);
252 return;
253 }
254 }
255
256
257 static void
fr_command_alz_extract(FrCommand * comm,const char * from_file,GList * file_list,const char * dest_dir,gboolean overwrite,gboolean skip_older,gboolean junk_paths)258 fr_command_alz_extract (FrCommand *comm,
259 const char *from_file,
260 GList *file_list,
261 const char *dest_dir,
262 gboolean overwrite,
263 gboolean skip_older,
264 gboolean junk_paths)
265 {
266 GList *scan;
267
268 FR_COMMAND_ALZ (comm)->extract_none = TRUE;
269
270 fr_process_set_out_line_func (FR_COMMAND (comm)->process,
271 process_extract_line,
272 comm);
273
274 fr_process_begin_command (comm->process, "unalz");
275 if (dest_dir != NULL) {
276 fr_process_add_arg (comm->process, "-d");
277 fr_process_add_arg (comm->process, dest_dir);
278 }
279 add_codepage_arg (comm);
280 add_password_arg (comm, comm->password, TRUE);
281 fr_process_add_arg (comm->process, comm->filename);
282 for (scan = file_list; scan; scan = scan->next)
283 fr_process_add_arg (comm->process, scan->data);
284 fr_process_end_command (comm->process);
285 }
286
287
288 static void
fr_command_alz_handle_error(FrCommand * comm,FrProcError * error)289 fr_command_alz_handle_error (FrCommand *comm,
290 FrProcError *error)
291 {
292 if ((error->type == FR_PROC_ERROR_STOPPED)) {
293 if (FR_COMMAND_ALZ (comm)->extract_none ||
294 FR_COMMAND_ALZ (comm)->invalid_password ) {
295 error->type = FR_PROC_ERROR_ASK_PASSWORD;
296 }
297 }
298 }
299
300
301 const char *alz_mime_type[] = { "application/x-alz", NULL };
302
303
304 static const char **
fr_command_alz_get_mime_types(FrCommand * comm)305 fr_command_alz_get_mime_types (FrCommand *comm)
306 {
307 return alz_mime_type;
308 }
309
310
311 static FrCommandCap
fr_command_alz_get_capabilities(FrCommand * comm,const char * mime_type,gboolean check_command)312 fr_command_alz_get_capabilities (FrCommand *comm,
313 const char *mime_type,
314 gboolean check_command)
315 {
316 FrCommandCap capabilities;
317
318 capabilities = FR_COMMAND_CAN_ARCHIVE_MANY_FILES;
319 if (is_program_available ("unalz", check_command))
320 capabilities |= FR_COMMAND_CAN_READ;
321
322 return capabilities;
323 }
324
325
326 static const char *
fr_command_alz_get_packages(FrCommand * comm,const char * mime_type)327 fr_command_alz_get_packages (FrCommand *comm,
328 const char *mime_type)
329 {
330 return PACKAGES ("unalz");
331 }
332
333
334 static void
fr_command_alz_class_init(FrCommandAlzClass * class)335 fr_command_alz_class_init (FrCommandAlzClass *class)
336 {
337 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
338 FrCommandClass *afc;
339
340 parent_class = g_type_class_peek_parent (class);
341 afc = (FrCommandClass*) class;
342
343 gobject_class->finalize = fr_command_alz_finalize;
344
345 afc->list = fr_command_alz_list;
346 afc->add = NULL;
347 afc->delete_ = NULL;
348 afc->extract = fr_command_alz_extract;
349 afc->handle_error = fr_command_alz_handle_error;
350 afc->get_mime_types = fr_command_alz_get_mime_types;
351 afc->get_capabilities = fr_command_alz_get_capabilities;
352 afc->get_packages = fr_command_alz_get_packages;
353 }
354
355
356 static void
fr_command_alz_init(FrCommand * comm)357 fr_command_alz_init (FrCommand *comm)
358 {
359 comm->propAddCanUpdate = TRUE;
360 comm->propAddCanReplace = TRUE;
361 comm->propExtractCanAvoidOverwrite = FALSE;
362 comm->propExtractCanSkipOlder = FALSE;
363 comm->propExtractCanJunkPaths = FALSE;
364 comm->propPassword = TRUE;
365 comm->propTest = FALSE;
366 }
367
368
369 static void
fr_command_alz_finalize(GObject * object)370 fr_command_alz_finalize (GObject *object)
371 {
372 g_return_if_fail (object != NULL);
373 g_return_if_fail (FR_IS_COMMAND_ALZ (object));
374
375 /* Chain up */
376 if (G_OBJECT_CLASS (parent_class)->finalize)
377 G_OBJECT_CLASS (parent_class)->finalize (object);
378 }
379
380
381 GType
fr_command_alz_get_type()382 fr_command_alz_get_type ()
383 {
384 static GType type = 0;
385
386 if (! type) {
387 GTypeInfo type_info = {
388 sizeof (FrCommandAlzClass),
389 NULL,
390 NULL,
391 (GClassInitFunc) fr_command_alz_class_init,
392 NULL,
393 NULL,
394 sizeof (FrCommandAlz),
395 0,
396 (GInstanceInitFunc) fr_command_alz_init
397 };
398
399 type = g_type_register_static (FR_TYPE_COMMAND,
400 "FrCommandAlz",
401 &type_info,
402 0);
403 }
404
405 return type;
406 }
407