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