Code

Fixing hash sort for null
[inkscape.git] / src / extension / dependency.cpp
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
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;
232 /**
233     \brief   Print out a dependency to a string.
234 */
235 std::ostream &
236 operator<< (std::ostream &out_file, const Dependency & in_dep)
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;
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 :