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