a83cac88d039cb430256fc76b00c7c0495a679c6
1 /*
2 * Author:
3 * Ted Gould <ted@gould.cx>
4 *
5 * Copyright (C) 2006 Johan Engelen, johan@shouraizou.nl
6 * Copyright (C) 2004 Author
7 *
8 * Released under GNU GPL, read the file 'COPYING' for more information
9 */
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif
15 #include <glibmm/i18n.h>
16 #include "config.h"
17 #include "path-prefix.h"
18 #include "dependency.h"
19 #include "db.h"
21 namespace Inkscape {
22 namespace Extension {
24 // These strings are for XML attribute comparisons and should not be translated
25 gchar const * Dependency::_type_str[] = {
26 "executable",
27 "file",
28 "extension",
29 };
31 // These strings are for XML attribute comparisons and should not be translated
32 gchar const * Dependency::_location_str[] = {
33 "path",
34 "extensions",
35 "absolute",
36 };
38 /**
39 \brief Create a dependency using an XML definition
40 \param in_repr XML definition of the dependency
42 This function mostly looks for the 'location' and 'type' attributes
43 and turns them into the enums of the same name. This makes things
44 a little bit easier to use later. Also, a pointer to the core
45 content is pulled out -- also to make things easier.
46 */
47 Dependency::Dependency (Inkscape::XML::Node * in_repr)
48 {
49 _type = TYPE_FILE;
50 _location = LOCATION_PATH;
51 _repr = in_repr;
52 _string = NULL;
53 _description = NULL;
55 Inkscape::GC::anchor(_repr);
57 const gchar * location = _repr->attribute("location");
58 for (int i = 0; i < LOCATION_CNT && location != NULL; i++) {
59 if (!strcmp(location, _location_str[i])) {
60 _location = (location_t)i;
61 break;
62 }
63 }
65 const gchar * type = _repr->attribute("type");
66 for (int i = 0; i < TYPE_CNT && type != NULL; i++) {
67 if (!strcmp(type, _type_str[i])) {
68 _type = (type_t)i;
69 break;
70 }
71 }
73 _string = sp_repr_children(_repr)->content();
75 _description = _repr->attribute("description");
76 if (_description == NULL)
77 _description = _repr->attribute("_description");
79 return;
80 }
82 /**
83 \brief This depenency is not longer needed
85 Unreference the XML structure.
86 */
87 Dependency::~Dependency (void)
88 {
89 Inkscape::GC::release(_repr);
90 }
92 /**
93 \brief Check if the dependency passes.
94 \return Whether or not the dependency passes.
96 This function depends largely on all of the enums. The first level
97 that is evaluted is the \c _type.
99 If the type is \c TYPE_EXTENSION then the id for the extension is
100 looked up in the database. If the extension is found, and it is
101 not deactivated, the dependency passes.
103 If the type is \c TYPE_EXECUTABLE or \c TYPE_FILE things are getting
104 even more interesting because now the \c _location variable is also
105 taken into account. First, the difference between the two is that
106 the file test for \c TYPE_EXECUTABLE also tests to make sure the
107 file is executable, besides checking that it exists.
109 If the \c _location is \c LOCATION_EXTENSIONS then the \c INKSCAPE_EXTENSIONDIR
110 is put on the front of the string with \c build_filename. Then the
111 appopriate filetest is run.
113 If the \c _location is \c LOCATION_ABSOLUTE then the file test is
114 run directly on the string.
116 If the \c _location is \c LOCATION_PATH or not specified then the
117 path is used to find the file. Each entry in the path is stepped
118 through, attached to the string, and then tested. If the file is
119 found then a TRUE is returned. If we get all the way through the
120 path then a FALSE is returned, the command could not be found.
121 */
122 bool
123 Dependency::check (void) const
124 {
125 // std::cout << "Checking: " << *this << std::endl;
127 if (_string == NULL) return FALSE;
129 switch (_type) {
130 case TYPE_EXTENSION: {
131 Extension * myext = db.get(_string);
132 if (myext == NULL) return FALSE;
133 if (myext->deactivated()) return FALSE;
134 break;
135 }
136 case TYPE_EXECUTABLE:
137 case TYPE_FILE: {
138 Glib::FileTest filetest = Glib::FILE_TEST_EXISTS;
139 if (_type == TYPE_EXECUTABLE) {
140 filetest |= Glib::FILE_TEST_IS_EXECUTABLE;
141 }
143 std::string location(_string);
144 switch (_location) {
145 case LOCATION_EXTENSIONS: {
146 for (unsigned int i=0; i<Inkscape::Extension::Extension::search_path.size(); i++) {
147 std::string temploc = Glib::build_filename(Inkscape::Extension::Extension::search_path[i], location);
148 if (Glib::file_test(temploc, filetest)) {
149 location = temploc;
150 break;
151 }
152 }
153 } /* PASS THROUGH!!! */
154 case LOCATION_ABSOLUTE: {
155 if (!Glib::file_test(location, filetest)) {
156 // std::cout << "Failing on location: " << location << std::endl;
157 return FALSE;
158 }
159 break;
160 }
161 /* The default case is to look in the path */
162 case LOCATION_PATH:
163 default: {
164 gchar * path = g_strdup(g_getenv("PATH"));
166 if (path == NULL) {
167 /* There is no `PATH' in the environment.
168 The default search path is the current directory */
169 path = g_strdup(G_SEARCHPATH_SEPARATOR_S);
170 }
172 gchar * orig_path = path;
174 for (; path != NULL;) {
175 gchar * local_path;
176 gchar * final_name;
178 local_path = path;
179 path = g_utf8_strchr(path, -1, G_SEARCHPATH_SEPARATOR);
180 /* Not sure whether this is UTF8 happy, but it would seem
181 like it considering that I'm searching (and finding)
182 the ':' character */
183 if (path != local_path && path != NULL) {
184 path[0] = '\0';
185 path++;
186 } else {
187 path = NULL;
188 }
190 if (local_path == '\0') {
191 final_name = g_strdup(_string);
192 } else {
193 final_name = g_build_filename(local_path, _string, NULL);
194 }
196 if (Glib::file_test(final_name, filetest)) {
197 g_free(final_name);
198 g_free(orig_path);
199 return TRUE;
200 }
202 // give it a 2nd try with ".exe" added
203 gchar * final_name_exe = g_strdup_printf("%s.exe", final_name);
204 if (Glib::file_test(final_name_exe, filetest)) {
205 g_free(final_name);
206 g_free(final_name_exe);
207 g_free(orig_path);
208 return TRUE;
209 }
210 g_free(final_name_exe);
212 // and a 3rd try with ".cmd" added (mainly for UniConvertor)
213 gchar * final_name_cmd = g_strdup_printf("%s.cmd", final_name);
214 if (Glib::file_test(final_name_cmd, filetest)) {
215 g_free(final_name);
216 g_free(final_name_cmd);
217 g_free(orig_path);
218 return TRUE;
219 }
220 g_free(final_name_cmd);
222 // give up
223 g_free(final_name);
224 }
226 g_free(orig_path);
227 return FALSE; /* Reverse logic in this one */
228 break;
229 }
230 } /* switch _location */
231 break;
232 } /* TYPE_FILE, TYPE_EXECUTABLE */
233 default:
234 return FALSE;
235 } /* switch _type */
237 return TRUE;
238 }
240 /**
241 \brief Print out a dependency to a string.
242 */
243 std::ostream &
244 operator<< (std::ostream &out_file, const Dependency & in_dep)
245 {
246 out_file << _("Dependency:") << '\n';
247 out_file << _(" type: ") << _(in_dep._type_str[in_dep._type]) << '\n';
248 out_file << _(" location: ") << _(in_dep._location_str[in_dep._location]) << '\n';
249 out_file << _(" string: ") << in_dep._string << '\n';
251 if (in_dep._description != NULL) {
252 out_file << _(" description: ") << _(in_dep._description) << '\n';
253 }
255 out_file << std::flush;
257 return out_file;
258 }
260 } } /* namespace Inkscape, Extension */
262 /*
263 Local Variables:
264 mode:c++
265 c-file-style:"stroustrup"
266 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
267 indent-tabs-mode:nil
268 fill-column:99
269 End:
270 */
271 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :