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 "plugin",
30 };
32 // These strings are for XML attribute comparisons and should not be translated
33 gchar const * Dependency::_location_str[] = {
34 "path",
35 "extensions",
36 "absolute",
37 };
39 /**
40 \brief Create a dependency using an XML definition
41 \param in_repr XML definition of the dependency
43 This function mostly looks for the 'location' and 'type' attributes
44 and turns them into the enums of the same name. This makes things
45 a little bit easier to use later. Also, a pointer to the core
46 content is pulled out -- also to make things easier.
47 */
48 Dependency::Dependency (Inkscape::XML::Node * in_repr)
49 {
50 _type = TYPE_FILE;
51 _location = LOCATION_PATH;
52 _repr = in_repr;
53 _string = NULL;
54 _description = NULL;
56 Inkscape::GC::anchor(_repr);
58 const gchar * location = _repr->attribute("location");
59 for (int i = 0; i < LOCATION_CNT && location != NULL; i++) {
60 if (!strcmp(location, _location_str[i])) {
61 _location = (location_t)i;
62 break;
63 }
64 }
66 const gchar * type = _repr->attribute("type");
67 for (int i = 0; i < TYPE_CNT && type != NULL; i++) {
68 if (!strcmp(type, _type_str[i])) {
69 _type = (type_t)i;
70 break;
71 }
72 }
74 _string = sp_repr_children(_repr)->content();
76 _description = _repr->attribute("description");
77 if (_description == NULL)
78 _description = _repr->attribute("_description");
80 return;
81 }
83 /**
84 \brief This depenency is not longer needed
86 Unreference the XML structure.
87 */
88 Dependency::~Dependency (void)
89 {
90 Inkscape::GC::release(_repr);
91 }
93 /**
94 \brief Check if the dependency passes.
95 \return Whether or not the dependency passes.
97 This function depends largely on all of the enums. The first level
98 that is evaluted is the \c _type.
100 If the type is \c TYPE_EXTENSION then the id for the extension is
101 looked up in the database. If the extension is found, and it is
102 not deactivated, the dependency passes.
104 If the type is \c TYPE_PLUGIN then the path for the plugin is found
105 using the Glib::Module routines. When the path is found, then there
106 is a check to see if the file exists using the \c file_test function.
108 If the type is \c TYPE_EXECUTABLE or \c TYPE_FILE things are getting
109 even more interesting because now the \c _location variable is also
110 taken into account. First, the difference between the two is that
111 the file test for \c TYPE_EXECUTABLE also tests to make sure the
112 file is executable, besides checking that it exists.
114 If the \c _location is \c LOCATION_EXTENSIONS then the \c INKSCAPE_EXTENSIONDIR
115 is put on the front of the string with \c build_filename. Then the
116 appopriate filetest is run.
118 If the \c _location is \c LOCATION_ABSOLUTE then the file test is
119 run directly on the string.
121 If the \c _location is \c LOCATION_PATH or not specified then the
122 path is used to find the file. Each entry in the path is stepped
123 through, attached to the string, and then tested. If the file is
124 found then a TRUE is returned. If we get all the way through the
125 path then a FALSE is returned, the command could not be found.
126 */
127 bool
128 Dependency::check (void) const
129 {
130 // std::cout << "Checking: " << *this << std::endl;
132 if (_string == NULL) return FALSE;
134 switch (_type) {
135 case TYPE_EXTENSION: {
136 Extension * myext = db.get(_string);
137 if (myext == NULL) return FALSE;
138 if (myext->deactivated()) return FALSE;
139 break;
140 }
141 case TYPE_PLUGIN: {
142 if (!Glib::Module::get_supported()) {
143 return FALSE;
144 }
146 std::string path = Glib::Module::build_path(INKSCAPE_PLUGINDIR, _string);
147 if (!Glib::file_test(path, Glib::FILE_TEST_EXISTS))
148 return FALSE;
149 break;
150 }
151 case TYPE_EXECUTABLE:
152 case TYPE_FILE: {
153 Glib::FileTest filetest = Glib::FILE_TEST_EXISTS;
154 if (_type == TYPE_EXECUTABLE) {
155 filetest |= Glib::FILE_TEST_IS_EXECUTABLE;
156 }
158 std::string location(_string);
159 switch (_location) {
160 case LOCATION_EXTENSIONS: {
161 for (unsigned int i=0; i<Inkscape::Extension::Extension::search_path.size(); i++) {
162 std::string temploc = Glib::build_filename(Inkscape::Extension::Extension::search_path[i], location);
163 if (Glib::file_test(temploc, filetest)) {
164 location = temploc;
165 break;
166 }
167 }
168 } /* PASS THROUGH!!! */
169 case LOCATION_ABSOLUTE: {
170 if (!Glib::file_test(location, filetest)) {
171 // std::cout << "Failing on location: " << location << std::endl;
172 return FALSE;
173 }
174 break;
175 }
176 /* The default case is to look in the path */
177 case LOCATION_PATH:
178 default: {
179 gchar * path = g_strdup(g_getenv("PATH"));
181 if (path == NULL) {
182 /* There is no `PATH' in the environment.
183 The default search path is the current directory */
184 path = g_strdup(G_SEARCHPATH_SEPARATOR_S);
185 }
187 gchar * orig_path = path;
189 for (; path != NULL;) {
190 gchar * local_path;
191 gchar * final_name;
193 local_path = path;
194 path = g_utf8_strchr(path, -1, G_SEARCHPATH_SEPARATOR);
195 /* Not sure whether this is UTF8 happy, but it would seem
196 like it considering that I'm searching (and finding)
197 the ':' character */
198 if (path != local_path && path != NULL) {
199 path[0] = '\0';
200 path++;
201 } else {
202 path = NULL;
203 }
205 if (local_path == '\0') {
206 final_name = g_strdup(_string);
207 } else {
208 final_name = g_build_filename(local_path, _string, NULL);
209 }
211 if (Glib::file_test(final_name, filetest)) {
212 g_free(final_name);
213 g_free(orig_path);
214 return TRUE;
215 }
216 // give it a 2nd try with ".exe" added
217 gchar * final_name_exe = g_strdup_printf ("%s.exe", final_name);
218 if (Glib::file_test(final_name_exe, filetest)) {
219 g_free(final_name);
220 g_free(final_name_exe);
221 g_free(orig_path);
222 return TRUE;
223 }
225 g_free(final_name);
226 g_free(final_name_exe);
227 }
229 g_free(orig_path);
230 return FALSE; /* Reverse logic in this one */
231 break;
232 }
233 } /* switch _location */
234 break;
235 } /* TYPE_FILE, TYPE_EXECUTABLE */
236 default:
237 return FALSE;
238 } /* switch _type */
240 return TRUE;
241 }
243 /**
244 \brief Print out a dependency to a string.
245 */
246 std::ostream &
247 operator<< (std::ostream &out_file, const Dependency & in_dep)
248 {
249 out_file << _("Dependency:") << '\n';
250 out_file << _(" type: ") << _(in_dep._type_str[in_dep._type]) << '\n';
251 out_file << _(" location: ") << _(in_dep._location_str[in_dep._location]) << '\n';
252 out_file << _(" string: ") << in_dep._string << '\n';
254 if (in_dep._description != NULL) {
255 out_file << _(" description: ") << _(in_dep._description) << '\n';
256 }
258 out_file << std::flush;
260 return out_file;
261 }
263 } } /* namespace Inkscape, Extension */
265 /*
266 Local Variables:
267 mode:c++
268 c-file-style:"stroustrup"
269 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
270 indent-tabs-mode:nil
271 fill-column:99
272 End:
273 */
274 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :