1 /*
2  *  Copyright (C) 2008 Giuseppe Torelli - <colossus73@gmail.com>
3  *  Copyright (C) 2006 Lukasz 'Sil2100' Zemczak - <sil2100@vexillium.org>
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18  *  MA 02110-1301 USA.
19  */
20 
21 #include <string.h>
22 #include "lha.h"
23 #include "date_utils.h"
24 #include "main.h"
25 #include "string_utils.h"
26 #include "support.h"
27 #include "window.h"
28 
29 static gboolean data_line, last_line;
30 
xa_lha_check_program(gchar * path)31 gboolean xa_lha_check_program (gchar *path)
32 {
33 	gchar *output, *discard;
34 	gboolean full_lha;
35 
36 	g_spawn_command_line_sync(path, &output, &discard, NULL, NULL);
37 	full_lha = (g_ascii_strncasecmp("Lhasa ", output, 6) != 0);
38 	g_free(discard);
39 	g_free(output);
40 
41 	return full_lha;
42 }
43 
xa_lha_ask(XArchive * archive)44 void xa_lha_ask (XArchive *archive)
45 {
46 	archive->can_test = TRUE;
47 	archive->can_extract = TRUE;
48 	archive->can_add = archiver[archive->type].is_compressor;
49 	archive->can_delete = archiver[archive->type].is_compressor;
50 	archive->can_full_path[0] = TRUE;
51 	archive->can_full_path[1] = archiver[archive->type].is_compressor;   // n.b.: adds leading slash
52 	archive->can_overwrite = TRUE;
53 	archive->can_update[1] = archiver[archive->type].is_compressor;
54 	archive->can_move = archiver[archive->type].is_compressor;
55 }
56 
xa_lha_parse_output(gchar * line,XArchive * archive)57 static void xa_lha_parse_output (gchar *line, XArchive *archive)
58 {
59 	XEntry *entry;
60 	gpointer item[7];
61 	gchar *filename, time[6];
62 	unsigned int linesize,n,a;
63 	gboolean dir;
64 
65 	if (last_line)
66 		return;
67 	if (!data_line)
68 	{
69 		if (line[0] == '-')
70 		{
71 			data_line = TRUE;
72 			return;
73 		}
74 		return;
75 	}
76 	if (strncmp(line,"----",4) == 0)
77 	{
78 		last_line = TRUE;
79 		return;
80 	}
81 	linesize = strlen(line);
82 
83 	/* Permission */
84 	line[10] = '\0';
85 	item[5] = line;
86 	dir = (line[0] == 'd');
87 
88 	/* UID/GID */
89 	line[22] = '\0';
90 	item[6] = line + 11;
91 
92 	//TODO verify the len of the size column with a big archive
93 	/* Size */
94 	for(n = 23;n < linesize;n++)
95 	if(line[n] != ' ')
96 		break;
97 
98 	a = n;
99 	for(;n < linesize;n++)
100 	if(line[n] == ' ')
101 		break;
102 
103 	line[a+(n-a)] = '\0';
104 	item[1] = line + a;
105 
106     /* Ratio */
107     line[37] = '\0';
108     item[2] = line + 31;
109 
110     /* Date and Time */
111     line[50] = '\0';
112     item[3] = line + 38;
113 
114 	/* Time */
115 	if (((char *) item[3])[9] == ':')
116 	{
117 		memcpy(time, item[3] + 7, 5);
118 		time[5] = 0;
119 	}
120 	else
121 		strcpy(time, "-----");
122 
123 	item[3] = date_MMM_dD_HourYear(item[3]);
124 	item[4] = time;
125 
126 	line[(linesize- 1)] = '\0';
127 	filename = line + 51;
128 
129 	/* Symbolic link */
130 	gchar *temp = g_strrstr (filename,"->");
131 	if (temp)
132 	{
133 		gint len = strlen(filename) - strlen(temp);
134 		item[0] = (filename +=3) + len;
135 		filename -= 3;
136 		filename[strlen(filename) - strlen(temp)-1] = '\0';
137 	}
138 	else
139 		item[0] = NULL;
140 
141 	entry = xa_set_archive_entries_for_each_row(archive, filename, item);
142 
143 	if (entry)
144 	{
145 		if (dir)
146 			entry->is_dir = TRUE;
147 
148 		if (!entry->is_dir)
149 			archive->files++;
150 
151 		archive->files_size += g_ascii_strtoull(item[1], NULL, 0);
152 	}
153 }
154 
xa_lha_list(XArchive * archive)155 void xa_lha_list (XArchive *archive)
156 {
157 	const GType types[] = {GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT64, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER};
158 	const gchar *titles[] = {_("Points to"), _("Original Size"), _("Occupancy"), _("Date"), _("Time"), _("Permissions"), _("UID/GID")};
159 	gchar *command;
160 	guint i;
161 
162 	data_line = FALSE;
163 	last_line = FALSE;
164 	command = g_strconcat(archiver[archive->type].program[0], " l ", archive->path[1], NULL);
165 	archive->files_size = 0;
166 	archive->files = 0;
167 	archive->parse_output = xa_lha_parse_output;
168 	xa_spawn_async_process (archive,command);
169 	g_free (command);
170 
171 	archive->columns = 10;
172 	archive->size_column = 3;
173 	archive->column_types = g_malloc0(sizeof(types));
174 
175 	for (i = 0; i < archive->columns; i++)
176 		archive->column_types[i] = types[i];
177 
178 	xa_create_liststore(archive, titles);
179 }
180 
xa_lha_test(XArchive * archive)181 void xa_lha_test (XArchive *archive)
182 {
183 	gchar *command;
184 
185 	command = g_strconcat(archiver[archive->type].program[0], " t ", archive->path[1], NULL);
186 
187 	xa_run_command(archive, command);
188 	g_free(command);
189 }
190 
191 /*
192  * Note: lha does not seem to be able to handle wildcards in file names.
193  */
194 
xa_lha_extract(XArchive * archive,GSList * file_list)195 gboolean xa_lha_extract (XArchive *archive, GSList *file_list)
196 {
197 	GString *files;
198 	gchar *command;
199 	gboolean result;
200 
201 	files = xa_quote_filenames(file_list, NULL, TRUE);
202 	command = g_strconcat(archiver[archive->type].program[0],
203 	                      archive->do_full_path ? " x" : " xi",
204 	                      archive->do_overwrite ? "f" : "",
205 	                      "w=", archive->extraction_dir, " ",
206 	                      archive->path[1], files->str, NULL);
207 	g_string_free(files,TRUE);
208 
209 	result = xa_run_command(archive, command);
210 	g_free(command);
211 
212 	return result;
213 }
214 
xa_lha_add(XArchive * archive,GSList * file_list,gchar * compression)215 void xa_lha_add (XArchive *archive, GSList *file_list, gchar *compression)
216 {
217 	GString *files;
218 	gchar *command;
219 
220 	if (archive->location_path != NULL)
221 		archive->child_dir = g_strdup(archive->working_dir);
222 
223 	if (!compression)
224 		compression = "5";
225 
226 	files = xa_quote_filenames(file_list, NULL, TRUE);
227 	command = g_strconcat(archiver[archive->type].program[0],
228 	                      archive->do_update ? " u" : " a",
229 	                      archive->do_move ? "d" : "",
230 	                      "o", compression, " ",
231 	                      archive->path[1], files->str, NULL);
232 	g_string_free(files,TRUE);
233 
234 	xa_run_command(archive, command);
235 	g_free(command);
236 }
237 
xa_lha_delete(XArchive * archive,GSList * file_list)238 void xa_lha_delete (XArchive *archive, GSList *file_list)
239 {
240 	GString *files;
241 	gchar *command;
242 
243 	files = xa_quote_filenames(file_list, NULL, TRUE);
244 	command = g_strconcat(archiver[archive->type].program[0], " d ", archive->path[1], files->str, NULL);
245 	g_string_free(files,TRUE);
246 
247 	xa_run_command(archive, command);
248 	g_free(command);
249 }
250