Fix errors found by coverity:
[scilab.git] / scilab / modules / fileio / src / c / dlManager.c
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2012-2013 - S/E - Sylvestre LEDRU
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.1-en.txt
10  *
11  */
12
13 #ifndef _MSC_VER
14 #define _GNU_SOURCE             /* basename crashes this extension otherwise */
15 #endif
16 #include <curl/curl.h>
17 #include <libxml/uri.h>
18 #include <string.h>
19 #include "dlManager.h"
20 #include "Scierror.h"
21 #include "SCIHOME.h"
22 #include "getos.h"
23 #include "PATH_MAX.h"
24 #include "MALLOC.h"
25 #include "isdir.h"
26 #include "charEncoding.h"
27 #include "localization.h"
28 #include "getos.h"
29 /* ==================================================================== */
30 #ifndef HAVE_BASENAME
31 static char *Curl_basename(char *path);
32 #define basename(x)  Curl_basename((x))
33 #endif
34 /* ==================================================================== */
35 static char errorBuffer[CURL_ERROR_SIZE];
36 /* ==================================================================== */
37 static int getProxyValues(char **proxyHost, long *proxyPort, char **proxyUserPwd);
38 /* ==================================================================== */
39 struct inputString
40 {
41     char *ptr;
42     size_t len;
43 };
44 /* ==================================================================== */
45 static void init_string(struct inputString *s)
46 {
47     s->len = 0;
48     s->ptr = (char*)CALLOC(s->len + 1, sizeof(char));
49     if (s->ptr == NULL)
50     {
51         Scierror(999, "Internal error: calloc() failed.\n");
52         return;
53     }
54     s->ptr[0] = '\0';
55 }
56 /* ==================================================================== */
57 static size_t writefunc(void *ptr, size_t size, size_t nmemb, struct inputString *s)
58 {
59     size_t new_len = s->len + size * nmemb;
60
61     s->ptr = (char*)REALLOC(s->ptr, new_len + 1);
62     if (s->ptr == NULL)
63     {
64         Scierror(999, "Internal error: realloc() failed.\n");
65         return NULL;
66     }
67     memcpy(s->ptr + s->len, ptr, size * nmemb);
68     s->ptr[new_len] = '\0';
69     s->len = new_len;
70
71     return size * nmemb;
72 }
73 /* ==================================================================== */
74 static char *getFileNameFromURL(char *url)
75 {
76     char *filename = NULL;
77     xmlURIPtr c = xmlParseURI(url);
78
79     if (c == NULL)
80     {
81         Scierror(999, _("Could not parse the URL.\n"));
82         return NULL;
83     }
84
85     if (c->path == NULL || strcmp(c->path, "/") == 0)
86     {
87         filename = (char *)MALLOC((strlen(DEFAULT_FILENAME) + 1) * sizeof(char));
88         strcpy(filename, DEFAULT_FILENAME);
89     }
90     else
91     {
92         char bname[PATH_MAX];
93
94         if (c->path == NULL)
95         {
96             Scierror(43, "Internal error: c->path is null ?!\n");
97         }
98         strcpy(bname, basename(c->path));
99         filename = (char *)MALLOC((strlen(bname) + 1) * sizeof(char));
100         strcpy(filename, bname);
101     }
102     return filename;
103
104 }
105 /* ==================================================================== */
106 int getProxyValues(char **proxyHost, long *proxyPort, char **proxyUserPwd)
107 {
108     FILE * pFile;
109     long lSize;
110     char * buffer;
111     size_t result;
112
113     char *configPtr;
114     char *osName;
115
116     char *host, *user, *password, *userpwd;
117     long port;
118     int useproxy;
119
120     char *tp, *field, *value, *eqptr;
121     int eqpos = 0 , tplen;
122
123     //construct ATOMS config file path
124     configPtr = (char *)MALLOC(PATH_MAX * sizeof(char));
125     strcpy(configPtr, getSCIHOME());
126
127     osName = (char *)MALLOC(50 * sizeof(char));
128     strcpy(osName, getOSFullName());
129     if (strcmp(osName, "Windows") == 0)
130     {
131         char *osVer = (char *)MALLOC(50 * sizeof(char));
132         strcpy(osVer, getOSRelease());
133         if (strstr(osVer, "x64") != NULL)
134         {
135             strcat(configPtr, "/.atoms/x64/config");
136         }
137         else
138         {
139             strcat(configPtr, "/.atoms/config");
140         }
141     }
142     else
143     {
144         strcat(configPtr, "/.atoms/config");
145     }
146
147
148     wcfopen (pFile, configPtr , "rb" );
149     if (pFile == NULL)
150     {
151         //              Scierror(999,"Could not open scicurl_config file\n");
152         return 0;
153     }
154
155     fseek (pFile , 0 , SEEK_END);
156     lSize = ftell(pFile);
157     rewind (pFile);
158
159     // allocate memory to contain the whole file
160     buffer = (char*)MALLOC((lSize + 1) * sizeof(char));
161     if (buffer == NULL)
162     {
163         return 0;
164     }
165     buffer[lSize] = '\0';
166
167     // copy the file into the buffer
168     result = fread (buffer, 1, lSize, pFile);
169     if (result != lSize)
170     {
171         Scierror(999, _("Failed to read the scicurl_config file '%s'.\n"), configPtr);
172         return 0;
173     }
174
175     host = user = password = userpwd = NULL;
176     useproxy = 0;
177
178     tp = field = value = eqptr = NULL;
179
180
181     // parse each line to extract variables
182     tp = strtok(buffer, "\n");
183     while (tp != NULL)
184     {
185
186         eqptr = strrchr(tp, '=');
187         tplen = (int)strlen(tp);
188         if (eqptr == NULL)
189         {
190             Scierror(999, _("Improper syntax of scicurl_config file ('%s'), '=' not found %d:%s\n"), configPtr, tplen, tp);
191             return 0;
192         }
193         eqpos = (int)(eqptr - tp);
194         if (tplen <= eqpos + 1)
195         {
196             Scierror(999, _("Improper syntax of scicurl_config file ('%s'), after an '='\n"), configPtr);
197             return 0;
198         }
199         if (tp[eqpos - 1] != ' ' || tp[eqpos + 1] != ' ')
200         {
201             Scierror(999, _("Improper syntax of scicurl_config file ('%s'), space before and after '=' expected\n"), configPtr);
202             return 0;
203         }
204
205         //get field and value from each line
206         field = (char *)MALLOC(sizeof(char) * (eqpos));
207         value = (char *)MALLOC(sizeof(char) * (strlen(tp) - eqpos - 1));
208
209         memcpy(field, tp, eqpos - 1);
210         field[eqpos - 1] = '\0';
211
212         memcpy(value, tp + eqpos + 2, strlen(tp) - eqpos - 2);
213         value[strlen(tp) - eqpos - 2] = '\0';
214
215
216         //check and read proxy variables
217         if (strcmp(field, "useProxy") == 0)
218         {
219             if (strcmp(value, "False") == 0)
220             {
221                 return 0;
222             }
223             if (strcmp(value, "True") == 0)
224             {
225                 useproxy = 1;
226             }
227         }
228         else if (strcmp(field, "proxyHost") == 0)
229         {
230             host = (char *)MALLOC((strlen(value) + 1) * sizeof(char));
231             strcpy(host, value);
232         }
233         else if (strcmp(field, "proxyPort") == 0)
234         {
235             port = strtol(value, NULL, 10);
236         }
237         else if (strcmp(field, "proxyUser") == 0)
238         {
239             user = (char *)MALLOC((strlen(value) + 1) * sizeof(char));
240             strcpy(user, value);
241         }
242         else if (strcmp(field, "proxyPassword") == 0)
243         {
244             password = (char *)MALLOC((strlen(value) + 1) * sizeof(char));
245             strcpy(password, value);
246         }
247
248         free(field);
249         free(value);
250
251         tp = strtok(NULL, "\n");
252     }
253
254     // if proxy is set, update the parameters
255     if (useproxy == 1)
256     {
257
258         // proxyUserPwd = "user:password"
259         int userlen, passlen;
260         userlen = passlen = 0;
261         if (user != NULL)
262         {
263             userlen = (int)strlen(user);
264         }
265         if (password != NULL)
266         {
267             passlen = (int)strlen(user);
268         }
269         if (userlen + passlen != 0)
270         {
271             userpwd = (char *)MALLOC((userlen + passlen + 2) * sizeof(char));
272             strcpy(userpwd, user);
273             strcat(userpwd, ":");
274             if (password != NULL)
275             {
276                 strcat(userpwd, password);
277             }
278         }
279
280         *proxyHost = host;
281         *proxyPort = port;
282         *proxyUserPwd = userpwd;
283
284     }
285
286     fclose(pFile);
287     free(buffer);
288     return useproxy;
289 }
290 /* ==================================================================== */
291 char *downloadFile(char *url, char *dest, char *username, char *password, char **content)
292 {
293     CURL *curl;
294     CURLcode res;
295     char *filename = NULL;
296
297     curl = curl_easy_init();
298
299     if (curl)
300     {
301         FILE *file;
302
303         struct inputString buffer;
304
305         init_string(&buffer);
306
307         res = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
308         if (res != CURLE_OK)
309         {
310             Scierror(999, "Failed to set error buffer [%d]\n", res);
311             return NULL;
312         }
313
314         if (dest == NULL)
315         {
316             /* No second argument provided */
317             filename = getFileNameFromURL(url);
318         }
319         else
320         {
321             if (isdir(dest))
322             {
323                 /* The target is a directory. Select the name from the URL */
324                 char *name = getFileNameFromURL(url);
325
326                 filename = (char *)MALLOC((strlen(name) + strlen("/") + strlen(dest) + 1) * sizeof(char));
327                 strcpy(filename, dest);
328                 strcat(filename, "/");
329                 strcat(filename, name);
330                 FREE(name);
331             }
332             else
333             {
334                 filename = (char *)MALLOC((strlen(dest) + 1) * sizeof(char));
335                 strcpy(filename, dest);
336             }
337         }
338
339         wcfopen(file, (char*)filename, "wb");
340
341         if (file == NULL)
342         {
343             Scierror(999, _("Failed opening '%s' for writing.\n"), filename);
344             FREE(filename);
345             return NULL;
346         }
347
348         res = curl_easy_setopt(curl, CURLOPT_URL, url);
349         if (res != CURLE_OK)
350         {
351             Scierror(999, _("Failed to set URL [%s]\n"), errorBuffer);
352             FREE(filename);
353             return NULL;
354         }
355
356         //Set authentication variables
357         if (username != NULL)
358         {
359             char * userpass;
360             int uplen = (int)strlen(username);
361             if (password != NULL)
362             {
363                 uplen = uplen + (int)strlen(password);
364             }
365
366             userpass = (char *)MALLOC((uplen + 2) * sizeof(char));
367
368             strcpy(userpass, username);
369             strcat(userpass, ":");
370             if (password != NULL)
371             {
372                 strcat(userpass, password);
373             }
374
375             res = curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
376             if (res != CURLE_OK)
377             {
378                 FREE(userpass);
379                 Scierror(999, "Failed to set httpauth type to ANY [%s]\n", errorBuffer);
380                 return NULL;
381             }
382
383             res = curl_easy_setopt(curl, CURLOPT_USERPWD, userpass);
384             if (res != CURLE_OK)
385             {
386                 Scierror(999, _("Failed to set user:pwd [%s]\n"), errorBuffer);
387                 return NULL;
388             }
389         } /* end authentication section */
390
391         {
392             //Set proxy variables
393             char *proxyHost = NULL;
394             char *proxyUserPwd = NULL;
395             long proxyPort = 1080;
396             int proxySet = 0;
397
398             proxySet = getProxyValues(&proxyHost, &proxyPort, &proxyUserPwd);
399
400             if (proxySet == 1)
401             {
402                 res = curl_easy_setopt(curl, CURLOPT_PROXY, proxyHost);
403                 if (res != CURLE_OK)
404                 {
405                     Scierror(999, _("Failed to set proxy host [%s]\n"), errorBuffer);
406                     return NULL;
407                 }
408
409                 res = curl_easy_setopt(curl, CURLOPT_PROXYPORT, proxyPort);
410                 if (res != CURLE_OK)
411                 {
412                     Scierror(999, _("Failed to set proxy port [%s]\n"), errorBuffer);
413                     return NULL;
414                 }
415                 if (proxyUserPwd != NULL)
416                 {
417                     res = curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, proxyUserPwd);
418                     if (res != CURLE_OK)
419                     {
420                         Scierror(999, _("Failed to set proxy user:password [%s]\n"), errorBuffer);
421                         return NULL;
422                     }
423                 }
424
425             }
426         } /* end of the set of the proxy */
427
428         res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
429
430         if (res != CURLE_OK)
431         {
432             Scierror(999, _("Failed to set write function [%s]\n"), errorBuffer);
433             return NULL;
434         }
435
436         //Get data to be written to the variable
437         res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
438         if (res != CURLE_OK)
439         {
440             Scierror(999, _("Failed to set write data [%s]\n"), errorBuffer);
441             return NULL;
442         }
443
444         // Follow redirects
445         res = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
446         if (res != CURLE_OK)
447         {
448             Scierror(999, _("Failed to set 'Follow Location' [%s]\n"), errorBuffer);
449             return NULL;
450         }
451
452         res = curl_easy_perform(curl);
453
454         if (res != 0)
455         {
456             Scierror(999, _("Transfer did not complete successfully: %s\n"), errorBuffer);
457             FREE(file);
458             return NULL;
459         }
460
461         /* Write the file */
462         fwrite(buffer.ptr, sizeof(char), buffer.len, file);
463
464         /* Create the variable which contains the output argument */
465         *content = buffer.ptr;
466
467         /* always cleanup */
468         curl_easy_cleanup(curl);
469
470         fclose(file);
471
472         return filename;
473     }
474     else
475     {
476         Scierror(999, "Failed opening the curl handle.\n");
477         return NULL;
478     }
479     return NULL;
480 }
481 /* ==================================================================== */
482 static char *Curl_basename(char *path)
483 {
484     char *s1 = NULL;
485     char *s2 = NULL;
486
487     s1 = strrchr(path, '/');
488     s2 = strrchr(path, '\\');
489
490     if (s1 && s2)
491     {
492         path = (s1 > s2 ? s1 : s2) + 1;
493     }
494     else if (s1)
495     {
496         path = s1 + 1;
497     }
498     else if (s2)
499     {
500         path = s2 + 1;
501     }
502     return path;
503 }
504 /* ==================================================================== */