109d5ed1211ab76d36d225666df8bc01f4276199
1 /*
2 * Authors:
3 * Ted Gould <ted@gould.cx>
4 *
5 * Copyright (C) 2004 Authors
6 *
7 * Released under GNU GPL, read the file 'COPYING' for more information
8 */
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
14 #include <glibmm/i18n.h>
15 #include "config.h"
16 #include "path-prefix.h"
17 #include "dependency.h"
18 #include "db.h"
20 namespace Inkscape {
21 namespace Extension {
23 // These strings are for XML attribute comparisons and should not be translated
24 gchar const * Dependency::_type_str[] = {
25 "executable",
26 "file",
27 "extension",
28 "plugin",
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_PLUGIN then the path for the plugin is found
104 using the Glib::Module routines. When the path is found, then there
105 is a check to see if the file exists using the \c file_test function.
107 If the type is \c TYPE_EXECUTABLE or \c TYPE_FILE things are getting
108 even more interesting because now the \c _location variable is also
109 taken into account. First, the difference between the two is that
110 the file test for \c TYPE_EXECUTABLE also tests to make sure the
111 file is executable, besides checking that it exists.
113 If the \c _location is \c LOCATION_EXTENSIONS then the \c INKSCAPE_EXTENSIONDIR
114 is put on the front of the string with \c build_filename. Then the
115 appopriate filetest is run.
117 If the \c _location is \c LOCATION_ABSOLUTE then the file test is
118 run directly on the string.
120 If the \c _location is \c LOCATION_PATH or not specified then the
121 path is used to find the file. Each entry in the path is stepped
122 through, attached to the string, and then tested. If the file is
123 found then a TRUE is returned. If we get all the way through the
124 path then a FALSE is returned, the command could not be found.
125 */
126 bool
127 Dependency::check (void) const
128 {
129 // std::cout << "Checking: " << *this << std::endl;
131 if (_string == NULL) return FALSE;
133 switch (_type) {
134 case TYPE_EXTENSION: {
135 Extension * myext = db.get(_string);
136 if (myext == NULL) return FALSE;
137 if (myext->deactivated()) return FALSE;
138 break;
139 }
140 case TYPE_PLUGIN: {
141 if (!Glib::Module::get_supported()) {
142 return FALSE;
143 }
145 std::string path = Glib::Module::build_path(INKSCAPE_PLUGINDIR, _string);
146 if (!Glib::file_test(path, Glib::FILE_TEST_EXISTS))
147 return FALSE;
148 break;
149 }
150 case TYPE_EXECUTABLE:
151 case TYPE_FILE: {
152 Glib::FileTest filetest = Glib::FILE_TEST_EXISTS;
153 if (_type == TYPE_EXECUTABLE) {
154 filetest |= Glib::FILE_TEST_IS_EXECUTABLE;
155 }
157 std::string location(_string);
158 switch (_location) {
159 case LOCATION_EXTENSIONS: {
160 for (unsigned int i=0; i<Inkscape::Extension::Extension::search_path.size(); i++) {
161 std::string temploc = Glib::build_filename(Inkscape::Extension::Extension::search_path[i], location);
162 if (Glib::file_test(temploc, filetest)) {
163 location = temploc;
164 break;
165 }
166 }
167 } /* PASS THROUGH!!! */
168 case LOCATION_ABSOLUTE: {
169 if (!Glib::file_test(location, filetest)) {
170 // std::cout << "Failing on location: " << location << std::endl;
171 return FALSE;
172 }
173 break;
174 }
175 /* The default case is to look in the path */
176 case LOCATION_PATH:
177 default: {
178 gchar * path = g_strdup(g_getenv("PATH"));
180 if (path == NULL) {
181 /* There is no `PATH' in the environment.
182 The default search path is the current directory */
183 path = g_strdup(G_SEARCHPATH_SEPARATOR_S);
184 }
186 gchar * orig_path = path;
188 for (; path != NULL;) {
189 gchar * local_path;
190 gchar * final_name;
192 local_path = path;
193 path = g_utf8_strchr(path, -1, G_SEARCHPATH_SEPARATOR);
194 /* Not sure whether this is UTF8 happy, but it would seem
195 like it considering that I'm searching (and finding)
196 the ':' character */
197 if (path != local_path && path != NULL) {
198 path[0] = '\0';
199 path++;
200 } else {
201 path = NULL;
202 }
204 if (local_path == '\0') {
205 final_name = g_strdup(_string);
206 } else {
207 final_name = g_build_filename(local_path, _string, NULL);
208 }
210 if (Glib::file_test(final_name, filetest)) {
211 g_free(final_name);
212 g_free(orig_path);
213 return TRUE;
214 }
215 // give it a 2nd try with ".exe" added
216 gchar * final_name_exe = g_strdup_printf ("%s.exe", final_name);
217 if (Glib::file_test(final_name_exe, filetest)) {
218 g_free(final_name);
219 g_free(final_name_exe);
220 g_free(orig_path);
221 return TRUE;
222 }
224 g_free(final_name);
225 g_free(final_name_exe);
226 }
228 g_free(orig_path);
229 return FALSE; /* Reverse logic in this one */
230 break;
231 }
232 } /* switch _location */
233 break;
234 } /* TYPE_FILE, TYPE_EXECUTABLE */
235 default:
236 return FALSE;
237 } /* switch _type */
239 return TRUE;
240 }
242 /**
243 \brief Print out a dependency to a string.
244 */
245 std::ostream &
246 operator<< (std::ostream &out_file, const Dependency & in_dep)
247 {
248 out_file << _("Dependency::") << '\n';
249 out_file << _(" type: ") << _(in_dep._type_str[in_dep._type]) << '\n';
250 out_file << _(" location: ") << _(in_dep._location_str[in_dep._location]) << '\n';
251 out_file << _(" string: ") << in_dep._string << '\n';
253 if (in_dep._description != NULL) {
254 out_file << _(" description: ") << _(in_dep._description) << '\n';
255 }
257 out_file << std::flush;
259 return out_file;
260 }
262 } } /* namespace Inkscape, Extension */
264 /*
265 Local Variables:
266 mode:c++
267 c-file-style:"stroustrup"
268 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
269 indent-tabs-mode:nil
270 fill-column:99
271 End:
272 */
273 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :