1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 
3 /*
4  *  Engrampa
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, write to the Free Software
20  *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02110-1301, USA.
21  */
22 
23 #include <glib.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <errno.h>
27 
28 #include "file-utils.h"
29 #include "fr-command.h"
30 #include "fr-command-zip.h"
31 #include "fr-command-jar.h"
32 #include "java-utils.h"
33 
34 
35 typedef struct {
36 	char *filename;
37 	char *rel_path;
38 	char *package_minus_one_level;
39 	char *link_name;		/* package dir = package_minus_one_level + '/' + link_name */
40 } JarData;
41 
42 
43 static void fr_command_jar_class_init  (FrCommandJarClass *class);
44 static void fr_command_jar_init        (FrCommand         *afile);
45 static void fr_command_jar_finalize    (GObject           *object);
46 
47 
48 static FrCommandClass *parent_class = NULL;
49 
50 
51 static void
fr_command_jar_add(FrCommand * comm,const char * from_file,GList * file_list,const char * base_dir,gboolean update,gboolean recursive)52 fr_command_jar_add (FrCommand     *comm,
53 		    const char    *from_file,
54 		    GList         *file_list,
55 		    const char    *base_dir,
56 		    gboolean       update,
57 		    gboolean       recursive)
58 {
59 	FrProcess *proc = comm->process;
60 	GList     *zip_list = NULL, *jardata_list = NULL, *jar_list = NULL;
61 	GList     *scan;
62 	char      *tmp_dir;
63 
64 	for (scan = file_list; scan; scan = scan->next) {
65 		char *filename = scan->data;
66 		char *path = build_uri (base_dir, filename, NULL);
67 		char *package = NULL;
68 
69 		if (file_extension_is (filename, ".java"))
70 			package = get_package_name_from_java_file (path);
71 		else if (file_extension_is (filename, ".class"))
72 			package = get_package_name_from_class_file (path);
73 
74 		if ((package == NULL) || (strlen (package) == 0))
75 			zip_list = g_list_append (zip_list, g_strdup (filename));
76 		else {
77 			JarData *newdata = g_new0 (JarData, 1);
78 
79 			newdata->package_minus_one_level = remove_level_from_path (package);
80 			newdata->link_name = g_strdup (file_name_from_path (package));
81 			newdata->rel_path = remove_level_from_path (filename);
82 			newdata->filename = g_strdup (file_name_from_path (filename));
83 			jardata_list = g_list_append (jardata_list, newdata);
84 		}
85 
86 		g_free (package);
87 		g_free (path);
88 	}
89 
90 	tmp_dir = get_temp_work_dir (NULL);
91 	for (scan = jardata_list; scan ; scan = scan->next) {
92 		JarData *jdata = scan->data;
93 		char    *pack_path;
94 		char    *old_link;
95 		char    *link_name;
96 		int      retval;
97 
98 		pack_path = build_uri (tmp_dir, jdata->package_minus_one_level, NULL);
99 		if (! make_directory_tree_from_path (pack_path, 0755, NULL)) {
100 			g_free (pack_path);
101 			continue;
102 		}
103 
104 		old_link = build_uri (base_dir, jdata->rel_path, NULL);
105 		link_name = g_build_filename (pack_path, jdata->link_name, NULL);
106 
107 		retval = symlink (old_link, link_name);
108 		if ((retval != -1) || (errno == EEXIST))
109 			jar_list = g_list_append (jar_list,
110 						  g_build_filename (jdata->package_minus_one_level,
111 							            jdata->link_name,
112 						      	            jdata->filename,
113 						      	            NULL));
114 
115 		g_free (link_name);
116 		g_free (old_link);
117 		g_free (pack_path);
118 	}
119 
120 	if (zip_list != NULL)
121 		parent_class->add (comm, NULL, zip_list, base_dir, update, FALSE);
122 
123 	if (jar_list != NULL)
124 		parent_class->add (comm, NULL, jar_list, tmp_dir, update, FALSE);
125 
126 	fr_process_begin_command (proc, "rm");
127 	fr_process_set_working_dir (proc, "/");
128 	fr_process_add_arg (proc, "-r");
129 	fr_process_add_arg (proc, "-f");
130 	fr_process_add_arg (proc, tmp_dir);
131 	fr_process_end_command (proc);
132 	fr_process_set_sticky (proc, TRUE);
133 
134 	for (scan = jardata_list; scan ; scan = scan->next) {
135 		JarData *jdata = scan->data;
136 		g_free (jdata->filename);
137 		g_free (jdata->package_minus_one_level);
138 		g_free (jdata->link_name);
139 		g_free (jdata->rel_path);
140 	}
141 
142 	path_list_free (jardata_list);
143 	path_list_free (jar_list);
144 	path_list_free (zip_list);
145 	g_free (tmp_dir);
146 }
147 
148 
149 const char *jar_mime_type[] = { "application/x-java-archive",
150 				NULL };
151 
152 
153 static const char **
fr_command_jar_get_mime_types(FrCommand * comm)154 fr_command_jar_get_mime_types (FrCommand *comm)
155 {
156 	return jar_mime_type;
157 }
158 
159 
160 static FrCommandCap
fr_command_jar_get_capabilities(FrCommand * comm,const char * mime_type,gboolean check_command)161 fr_command_jar_get_capabilities (FrCommand  *comm,
162 			         const char *mime_type,
163 				 gboolean    check_command)
164 {
165 	FrCommandCap capabilities;
166 
167 	capabilities = FR_COMMAND_CAN_ARCHIVE_MANY_FILES;
168 	if (is_program_available ("zip", check_command))
169 		capabilities |= FR_COMMAND_CAN_READ_WRITE;
170 
171 	return capabilities;
172 }
173 
174 
175 static const char *
fr_command_jar_get_packages(FrCommand * comm,const char * mime_type)176 fr_command_jar_get_packages (FrCommand  *comm,
177 			     const char *mime_type)
178 {
179 	return PACKAGES ("zip,unzip");
180 }
181 
182 
183 static void
fr_command_jar_class_init(FrCommandJarClass * class)184 fr_command_jar_class_init (FrCommandJarClass *class)
185 {
186 	GObjectClass   *gobject_class = G_OBJECT_CLASS(class);
187 	FrCommandClass *afc = FR_COMMAND_CLASS (class);
188 
189 	parent_class = g_type_class_peek_parent (class);
190 
191 	gobject_class->finalize = fr_command_jar_finalize;
192 
193 	afc->add = fr_command_jar_add;
194 	afc->get_mime_types = fr_command_jar_get_mime_types;
195 	afc->get_capabilities = fr_command_jar_get_capabilities;
196 	afc->get_packages     = fr_command_jar_get_packages;
197 }
198 
199 
200 static void
fr_command_jar_init(FrCommand * comm)201 fr_command_jar_init (FrCommand *comm)
202 {
203 }
204 
205 
206 static void
fr_command_jar_finalize(GObject * object)207 fr_command_jar_finalize (GObject *object)
208 {
209         g_return_if_fail (object != NULL);
210         g_return_if_fail (FR_IS_COMMAND_JAR (object));
211 
212 	/* Chain up */
213         if (G_OBJECT_CLASS (parent_class)->finalize)
214 		G_OBJECT_CLASS (parent_class)->finalize (object);
215 }
216 
217 
218 GType
fr_command_jar_get_type()219 fr_command_jar_get_type ()
220 {
221         static GType type = 0;
222 
223         if (! type) {
224                 GTypeInfo type_info = {
225 			sizeof (FrCommandJarClass),
226 			NULL,
227 			NULL,
228 			(GClassInitFunc) fr_command_jar_class_init,
229 			NULL,
230 			NULL,
231 			sizeof (FrCommandJar),
232 			0,
233 			(GInstanceInitFunc) fr_command_jar_init
234 		};
235 
236 		type = g_type_register_static (FR_TYPE_COMMAND_ZIP,
237 					       "FRCommandJar",
238 					       &type_info,
239 					       0);
240         }
241 
242         return type;
243 }
244