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