1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 
3 /*
4  *  File-Roller
5  *
6  *  Copyright (C) 2006 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, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <config.h>
23 #include <glib.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <errno.h>
27 #include "file-utils.h"
28 #include "fr-command.h"
29 #include "fr-command-zip.h"
30 #include "fr-command-jar.h"
31 #include "glib-utils.h"
32 #include "java-utils.h"
33 
34 
35 struct _FrCommandJar
36 {
37 	FrCommandZip  parent_instance;
38 };
39 
40 
41 G_DEFINE_TYPE (FrCommandJar, fr_command_jar, fr_command_zip_get_type ())
42 
43 
44 typedef struct {
45 	char *filename;
46 	char *rel_path;
47 	char *package_minus_one_level;
48 	char *link_name;		/* package dir = package_minus_one_level + '/' + link_name */
49 } JarData;
50 
51 
52 static void
fr_command_jar_add(FrCommand * comm,const char * from_file,GList * file_list,const char * base_dir,gboolean update,gboolean follow_links)53 fr_command_jar_add (FrCommand  *comm,
54 		    const char *from_file,
55 		    GList      *file_list,
56 		    const char *base_dir,
57 		    gboolean    update,
58 		    gboolean    follow_links)
59 {
60 	FrProcess *proc = comm->process;
61 	GList     *zip_list = NULL, *jardata_list = NULL, *jar_list = NULL;
62 	GList     *scan;
63 	char      *tmp_dir;
64 
65 	for (scan = file_list; scan; scan = scan->next) {
66 		char *filename = scan->data;
67 		char *path = g_build_filename (base_dir, filename, NULL);
68 		char *package = NULL;
69 
70 		if (_g_filename_has_extension (filename, ".java"))
71 			package = get_package_name_from_java_file (path);
72 		else if (_g_filename_has_extension (filename, ".class"))
73 			package = get_package_name_from_class_file (path);
74 
75 		if ((package == NULL) || (strlen (package) == 0))
76 			zip_list = g_list_append (zip_list, g_strdup (filename));
77 		else {
78 			JarData *newdata = g_new0 (JarData, 1);
79 
80 			newdata->package_minus_one_level = _g_path_remove_level (package);
81 			newdata->link_name = g_strdup (_g_path_get_basename (package));
82 			newdata->rel_path = _g_path_remove_level (filename);
83 			newdata->filename = g_strdup (_g_path_get_basename (filename));
84 			jardata_list = g_list_append (jardata_list, newdata);
85 		}
86 
87 		g_free (package);
88 		g_free (path);
89 	}
90 
91 	tmp_dir = _g_path_get_temp_work_dir (NULL);
92 	for (scan = jardata_list; scan ; scan = scan->next) {
93 		JarData *jdata = scan->data;
94 		char    *pack_path;
95 		GFile   *directory;
96 		char    *old_link;
97 		char    *link_name;
98 		int      retval;
99 
100 		pack_path = g_build_filename (tmp_dir, jdata->package_minus_one_level, NULL);
101 		directory = g_file_new_for_path (pack_path);
102 		if (! _g_file_make_directory_tree (directory, 0755, NULL)) {
103 			g_object_unref (directory);
104 			g_free (pack_path);
105 			continue;
106 		}
107 
108 		old_link = g_build_filename (base_dir, jdata->rel_path, NULL);
109 		link_name = g_build_filename (pack_path, jdata->link_name, NULL);
110 
111 		retval = symlink (old_link, link_name);
112 		if ((retval != -1) || (errno == EEXIST))
113 			jar_list = g_list_append (jar_list,
114 						  g_build_filename (jdata->package_minus_one_level,
115 							            jdata->link_name,
116 						      	            jdata->filename,
117 						      	            NULL));
118 
119 		g_free (link_name);
120 		g_free (old_link);
121 		g_object_unref (directory);
122 		g_free (pack_path);
123 	}
124 
125 	if (zip_list != NULL)
126 		FR_COMMAND_CLASS (fr_command_jar_parent_class)->add (comm, NULL, zip_list, base_dir, update, follow_links);
127 
128 	if (jar_list != NULL)
129 		FR_COMMAND_CLASS (fr_command_jar_parent_class)->add (comm, NULL, jar_list, tmp_dir, update, follow_links);
130 
131 	fr_process_begin_command (proc, "rm");
132 	fr_process_set_working_dir (proc, "/");
133 	fr_process_add_arg (proc, "-r");
134 	fr_process_add_arg (proc, "-f");
135 	fr_process_add_arg (proc, tmp_dir);
136 	fr_process_end_command (proc);
137 	fr_process_set_sticky (proc, TRUE);
138 
139 	for (scan = jardata_list; scan ; scan = scan->next) {
140 		JarData *jdata = scan->data;
141 		g_free (jdata->filename);
142 		g_free (jdata->package_minus_one_level);
143 		g_free (jdata->link_name);
144 		g_free (jdata->rel_path);
145 	}
146 
147 	_g_string_list_free (jardata_list);
148 	_g_string_list_free (jar_list);
149 	_g_string_list_free (zip_list);
150 	g_free (tmp_dir);
151 }
152 
153 
154 const char *jar_mime_type[] = { "application/x-java-archive",
155 				NULL };
156 
157 
158 static const char **
fr_command_jar_get_mime_types(FrArchive * archive)159 fr_command_jar_get_mime_types (FrArchive *archive)
160 {
161 	return jar_mime_type;
162 }
163 
164 
165 static FrArchiveCap
fr_command_jar_get_capabilities(FrArchive * archive,const char * mime_type,gboolean check_command)166 fr_command_jar_get_capabilities (FrArchive  *archive,
167 			         const char *mime_type,
168 				 gboolean    check_command)
169 {
170 	FrArchiveCap capabilities;
171 
172 	capabilities = FR_ARCHIVE_CAN_STORE_MANY_FILES;
173 	if (_g_program_is_available ("zip", check_command))
174 		capabilities |= FR_ARCHIVE_CAN_READ_WRITE;
175 
176 	return capabilities;
177 }
178 
179 
180 static const char *
fr_command_jar_get_packages(FrArchive * archive,const char * mime_type)181 fr_command_jar_get_packages (FrArchive  *archive,
182 			     const char *mime_type)
183 {
184 	return PACKAGES ("zip,unzip");
185 }
186 
187 
188 static void
fr_command_jar_finalize(GObject * object)189 fr_command_jar_finalize (GObject *object)
190 {
191         g_return_if_fail (object != NULL);
192         g_return_if_fail (FR_IS_COMMAND_JAR (object));
193 
194         if (G_OBJECT_CLASS (fr_command_jar_parent_class)->finalize)
195 		G_OBJECT_CLASS (fr_command_jar_parent_class)->finalize (object);
196 }
197 
198 
199 static void
fr_command_jar_class_init(FrCommandJarClass * klass)200 fr_command_jar_class_init (FrCommandJarClass *klass)
201 {
202 	GObjectClass   *gobject_class;
203 	FrArchiveClass *archive_class;
204 	FrCommandClass *command_class;
205 
206 	fr_command_jar_parent_class = g_type_class_peek_parent (klass);
207 
208 	gobject_class = G_OBJECT_CLASS(klass);
209 	gobject_class->finalize = fr_command_jar_finalize;
210 
211 	archive_class = FR_ARCHIVE_CLASS (klass);
212 	archive_class->get_mime_types   = fr_command_jar_get_mime_types;
213 	archive_class->get_capabilities = fr_command_jar_get_capabilities;
214 	archive_class->get_packages     = fr_command_jar_get_packages;
215 
216 	command_class = FR_COMMAND_CLASS (klass);
217 	command_class->add              = fr_command_jar_add;
218 }
219 
220 
221 static void
fr_command_jar_init(FrCommandJar * self)222 fr_command_jar_init (FrCommandJar *self)
223 {
224 	/* void */
225 }
226