loadlib fixed about path file
[scilab.git] / scilab / modules / io / src / cpp / loadlib.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2014 - Scilab Enterprises - Antoine ELIAS
4 *
5 * This file must be used under the terms of the CeCILL.
6 * This source file is licensed as described in the file COPYING, which
7 * you should have received as part of this distribution.  The terms
8 * are also available at
9 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10 *
11 */
12
13 #include "configvariable.hxx"
14 #include "context.hxx"
15 #include "loadlib.hxx"
16 #include "macrofile.hxx"
17
18 extern "C"
19 {
20 #include "FileExist.h"
21 #include "sci_malloc.h"
22 #include "os_string.h"
23 #include "expandPathVariable.h"
24 #include "fullpath.h"
25 #include "PATH_MAX.h"
26 #include <libxml/xpath.h>
27 #include <libxml/xmlreader.h>
28 }
29
30 #define DEFAULT_ENCODING "UTF-8"
31
32 static char *GetXmlFileEncoding(std::string _filename);
33
34 types::Library* loadlib(const std::wstring& _wstXML, int* err, bool _isFile, bool _bAddInContext)
35 {
36     types::Library* lib = NULL;
37
38     wchar_t* pwstPathLib = expandPathVariableW((wchar_t*)_wstXML.c_str());
39
40     wchar_t* pwstTemp = (wchar_t*)MALLOC(sizeof(wchar_t) * (PATH_MAX * 2));
41     get_full_pathW(pwstTemp, pwstPathLib, PATH_MAX * 2);
42     FREE(pwstPathLib);
43
44     std::wstring wstOriginalPath(pwstTemp);
45     std::wstring wstFile(pwstTemp);
46     std::wstring wstPath(pwstTemp);
47     FREE(pwstTemp);
48
49     if (_isFile)
50     {
51         //remove / or \ at the end
52         size_t pos = wstPath.find_last_of(L"/\\");
53         wstPath = wstPath.substr(0, pos);
54         pos = wstOriginalPath.find_last_of(L"/\\");
55         wstOriginalPath = wstOriginalPath.substr(0, pos + 1); //with ending /
56     }
57     else
58     {
59         if (wstFile.empty() == false && *wstFile.rbegin() != DIR_SEPARATORW[0])
60         {
61             wstFile += DIR_SEPARATORW;
62         }
63
64         wstFile += L"lib";
65     }
66
67     std::wstring libname;
68     MacroInfoList lst;
69     *err = parseLibFile(wstFile, lst, libname);
70     if (*err)
71     {
72         return lib;
73     }
74
75     lib = new types::Library(wstOriginalPath);
76
77     std::wstring stFilename(wstPath);
78     if (stFilename.empty() == false && *stFilename.rbegin() != DIR_SEPARATORW[0])
79     {
80         stFilename += DIR_SEPARATORW;
81     }
82
83
84     for (const auto & macro : lst)
85     {
86         lib->add(macro.second.name, new types::MacroFile(macro.second.name, stFilename + macro.second.file, libname));
87     }
88
89
90     if (_bAddInContext)
91     {
92         symbol::Context* ctx = symbol::Context::getInstance();
93         symbol::Symbol sym = symbol::Symbol(libname);
94         if (ctx->isprotected(sym) == false)
95         {
96             ctx->put(sym, lib);
97         }
98         else
99         {
100             *err = 2;
101             delete lib;
102             lib = NULL;
103         }
104     }
105
106     return lib;
107 }
108
109 int parseLibFile(const std::wstring& _wstXML, MacroInfoList& info, std::wstring& libname)
110 {
111     info.clear();
112
113     char* pstFile = wide_string_to_UTF8(_wstXML.data());
114
115     if (FileExist(pstFile) == FALSE)
116     {
117         FREE(pstFile);
118         return 1;
119     }
120
121     char *encoding = GetXmlFileEncoding(pstFile);
122
123     /* Don't care about line return / empty line */
124     xmlKeepBlanksDefault(0);
125     /* check if the XML file has been encoded with utf8 (unicode) or not */
126     if (stricmp("utf-8", encoding))
127     {
128         FREE(pstFile);
129         free(encoding);
130         return NULL;
131     }
132
133     xmlDocPtr doc;
134     xmlXPathContextPtr xpathCtxt = NULL;
135     xmlXPathObjectPtr xpathObj = NULL;
136     wchar_t* pstName = NULL;
137     wchar_t* pstLibName = NULL;
138     wchar_t* pstFileName = NULL;
139     wchar_t* pstMd5 = NULL;
140
141     free(encoding);
142
143     doc = xmlParseFile(pstFile);
144
145     if (doc == NULL)
146     {
147         FREE(pstFile);
148         return 1;
149     }
150
151     FREE(pstFile);
152
153     xpathCtxt = xmlXPathNewContext(doc);
154     xpathObj = xmlXPathEval((const xmlChar*)"//scilablib", xpathCtxt);
155     if (xpathObj && xpathObj->nodesetval->nodeMax)
156     {
157         xmlAttrPtr attrib = xpathObj->nodesetval->nodeTab[0]->properties;
158         if (xmlStrEqual(attrib->name, (const xmlChar*)"name"))
159         {
160             /* we found the tag name */
161             const char *str = (const char*)attrib->children->content;
162             pstLibName = to_wide_string(str);
163             libname = pstLibName;
164             FREE(pstLibName);
165             xmlXPathFreeObject(xpathObj);
166         }
167         else
168         {
169             if (xpathCtxt)
170             {
171                 xmlXPathFreeContext(xpathCtxt);
172             }
173             xmlXPathFreeObject(xpathObj);
174             return 1;
175         }
176     }
177
178     xpathObj = xmlXPathEval((const xmlChar*)"//scilablib/macro", xpathCtxt);
179     if (xpathObj && xpathObj->nodesetval->nodeMax)
180     {
181         /* the Xpath has been understood and there are node */
182         for (int i = 0; i < xpathObj->nodesetval->nodeNr; i++)
183         {
184             xmlAttrPtr attrib = xpathObj->nodesetval->nodeTab[i]->properties;
185             /* Get the properties of <module>  */
186             while (attrib != NULL)
187             {
188                 /* loop until when have read all the attributes */
189                 if (xmlStrEqual(attrib->name, (const xmlChar*)"name"))
190                 {
191                     /* we found the tag name */
192                     const char *str = (const char*)attrib->children->content;
193                     pstName = to_wide_string(str);
194                 }
195                 else if (xmlStrEqual(attrib->name, (const xmlChar*)"file"))
196                 {
197                     /* we found the tag activate */
198                     const char *str = (const char*)attrib->children->content;
199                     pstFileName = to_wide_string(str);
200                 }
201                 else if (xmlStrEqual(attrib->name, (const xmlChar*)"md5"))
202                 {
203                     /* we found the tag activate */
204                     const char *str = (const char*)attrib->children->content;
205                     pstMd5 = to_wide_string(str);
206                 }
207                 attrib = attrib->next;
208             }
209
210             if (pstName && pstFileName && pstMd5)
211             {
212                 info[pstFileName] = MacroInfo(pstName, pstFileName, pstMd5);
213             }
214
215             if (pstName)
216             {
217                 FREE(pstName);
218                 pstName = NULL;
219             }
220
221             if (pstFileName)
222             {
223                 FREE(pstFileName);
224                 pstFileName = NULL;
225             }
226
227             if (pstMd5)
228             {
229                 FREE(pstMd5);
230                 pstMd5 = NULL;
231             }
232         }
233     }
234
235     if (xpathObj)
236     {
237         xmlXPathFreeObject(xpathObj);
238     }
239     if (xpathCtxt)
240     {
241         xmlXPathFreeContext(xpathCtxt);
242     }
243
244     xmlFreeDoc(doc);
245     return 0;
246 }
247
248 static char *GetXmlFileEncoding(std::string _filename)
249 {
250     char *encoding = NULL;
251     xmlDocPtr doc = NULL;
252
253     /* default */
254     encoding = os_strdup(DEFAULT_ENCODING);
255
256     doc = xmlParseFile(_filename.c_str());
257     if (doc)
258     {
259         if (doc->encoding)
260         {
261             if (encoding)
262             {
263                 free(encoding);
264                 encoding = NULL;
265             }
266             encoding = os_strdup((char*)doc->encoding);
267         }
268     }
269
270     xmlFreeDoc(doc);
271     return encoding;
272 }