Plug back the error manager
[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-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, 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     eqpos = tplen = 0;
180
181
182     // parse each line to extract variables
183     tp = strtok(buffer, "\n");
184     while (tp != NULL)
185     {
186
187         eqptr = strrchr(tp, '=');
188         tplen = (int)strlen(tp);
189         if (eqptr == NULL)
190         {
191             Scierror(999, _("Improper syntax of scicurl_config file ('%s'), '=' not found %d:%s\n"), configPtr, tplen, tp);
192             return 0;
193         }
194         eqpos = (int)(eqptr - tp);
195         if (tplen <= eqpos + 1)
196         {
197             Scierror(999, _("Improper syntax of scicurl_config file ('%s'), after an '='\n"), configPtr);
198             return 0;
199         }
200         if (tp[eqpos - 1] != ' ' || tp[eqpos + 1] != ' ')
201         {
202             Scierror(999, _("Improper syntax of scicurl_config file ('%s'), space before and after '=' expected\n"), configPtr);
203             return 0;
204         }
205
206         //get field and value from each line
207         field = (char *)MALLOC(sizeof(char) * (eqpos));
208         value = (char *)MALLOC(sizeof(char) * (strlen(tp) - eqpos - 1));
209
210         memcpy(field, tp, eqpos - 1);
211         field[eqpos - 1] = '\0';
212
213         memcpy(value, tp + eqpos + 2, strlen(tp) - eqpos - 2);
214         value[strlen(tp) - eqpos - 2] = '\0';
215
216
217         //check and read proxy variables
218         if (strcmp(field, "useProxy") == 0)
219         {
220             if (strcmp(value, "False") == 0)
221             {
222                 return 0;
223             }
224             if (strcmp(value, "True") == 0)
225             {
226                 useproxy = 1;
227             }
228         }
229         else if (strcmp(field, "proxyHost") == 0)
230         {
231             host = (char *)MALLOC((strlen(value) + 1) * sizeof(char));
232             strcpy(host, value);
233         }
234         else if (strcmp(field, "proxyPort") == 0)
235         {
236             port = strtol(value, NULL, 10);
237         }
238         else if (strcmp(field, "proxyUser") == 0)
239         {
240             user = (char *)MALLOC((strlen(value) + 1) * sizeof(char));
241             strcpy(user, value);
242         }
243         else if (strcmp(field, "proxyPassword") == 0)
244         {
245             password = (char *)MALLOC((strlen(value) + 1) * sizeof(char));
246             strcpy(password, value);
247         }
248
249         free(field);
250         free(value);
251
252         tp = strtok(NULL, "\n");
253     }
254
255     // if proxy is set, update the parameters
256     if (useproxy == 1)
257     {
258
259         // proxyUserPwd = "user:password"
260         int userlen, passlen;
261         userlen = passlen = 0;
262         if (user != NULL)
263         {
264             userlen = (int)strlen(user);
265         }
266         if (password != NULL)
267         {
268             passlen = (int)strlen(user);
269         }
270         if (userlen + passlen != 0)
271         {
272             userpwd = (char *)MALLOC((userlen + passlen + 2) * sizeof(char));
273             strcpy(userpwd, user);
274             strcat(userpwd, ":");
275             if (password != NULL)
276             {
277                 strcat(userpwd, password);
278             }
279         }
280
281         *proxyHost = host;
282         *proxyPort = port;
283         *proxyUserPwd = userpwd;
284
285     }
286
287     fclose(pFile);
288     free(buffer);
289     return useproxy;
290 }
291 /* ==================================================================== */
292 char *downloadFile(char *url, char *dest, char *username, char *password, char **content)
293 {
294     CURL *curl;
295     CURLcode res;
296     char *filename = NULL;
297
298     curl = curl_easy_init();
299
300     if (curl)
301     {
302         FILE *file;
303
304         struct inputString buffer;
305
306         init_string(&buffer);
307
308         res = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
309         if (res != CURLE_OK)
310         {
311             Scierror(999, "Failed to set error buffer [%d]\n", res);
312             return NULL;
313         }
314
315         if (dest == NULL)
316         {
317             /* No second argument provided */
318             filename = getFileNameFromURL(url);
319         }
320         else
321         {
322             if (isdir(dest))
323             {
324                 /* The target is a directory. Select the name from the URL */
325                 char *name = getFileNameFromURL(url);
326
327                 filename = (char *)MALLOC((strlen(name) + strlen("/") + strlen(dest) + 1) * sizeof(char));
328                 strcpy(filename, dest);
329                 strcat(filename, "/");
330                 strcat(filename, name);
331
332             }
333             else
334             {
335                 filename = (char *)MALLOC((strlen(dest) + 1) * sizeof(char));
336                 strcpy(filename, dest);
337             }
338         }
339
340         wcfopen(file, (char*)filename, "wb");
341
342         if (file == NULL)
343         {
344             Scierror(999, _("Failed opening '%s' for writing.\n"), 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             return NULL;
353         }
354
355         //Set authentication variables
356         if (username != NULL)
357         {
358             char * userpass;
359             int uplen = (int)strlen(username);
360             if (password != NULL)
361             {
362                 uplen = uplen + (int)strlen(password);
363             }
364
365             userpass = (char *)MALLOC((uplen + 2) * sizeof(char));
366
367             strcpy(userpass, username);
368             strcat(userpass, ":");
369             if (password != NULL)
370             {
371                 strcat(userpass, password);
372             }
373
374             res = curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
375             if (res != CURLE_OK)
376             {
377                 Scierror(999, "Failed to set httpauth type to ANY [%s]\n", errorBuffer);
378                 return NULL;
379             }
380             res = curl_easy_setopt(curl, CURLOPT_USERPWD, userpass);
381             if (res != CURLE_OK)
382             {
383                 Scierror(999, _("Failed to set user:pwd [%s]\n"), errorBuffer);
384                 return NULL;
385             }
386         } /* end authentication section */
387
388         {
389             //Set proxy variables
390             char *proxyHost = NULL;
391             char *proxyUserPwd = NULL;
392             long proxyPort = 1080;
393             int proxySet = 0;
394
395             proxySet = getProxyValues(&proxyHost, &proxyPort, &proxyUserPwd);
396
397             if (proxySet == 1)
398             {
399                 res = curl_easy_setopt(curl, CURLOPT_PROXY, proxyHost);
400                 if (res != CURLE_OK)
401                 {
402                     Scierror(999, _("Failed to set proxy host [%s]\n"), errorBuffer);
403                     return NULL;
404                 }
405                 curl_easy_setopt(curl, CURLOPT_PROXYPORT, proxyPort);
406                 if (res != CURLE_OK)
407                 {
408                     Scierror(999, _("Failed to set proxy port [%s]\n"), errorBuffer);
409                     return NULL;
410                 }
411                 if (proxyUserPwd != NULL)
412                 {
413                     res = curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, proxyUserPwd);
414                     if (res != CURLE_OK)
415                     {
416                         Scierror(999, _("Failed to set proxy user:password [%s]\n"), errorBuffer);
417                         return NULL;
418                     }
419                 }
420
421             }
422         } /* end of the set of the proxy */
423
424         res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
425
426         if (res != CURLE_OK)
427         {
428             Scierror(999, _("Failed to set write data [%s]\n"), errorBuffer);
429             return NULL;
430         }
431
432         //Get data to be written to the variable
433         res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
434         if (res != CURLE_OK)
435         {
436             Scierror(999, _("Failed to set write data [%s]\n"), errorBuffer);
437             return NULL;
438         }
439
440         // Follow redirects
441         curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
442
443         res = curl_easy_perform(curl);
444
445         if (res != 0)
446         {
447             Scierror(999, _("Transfer did not complete successfully: %s\n"), errorBuffer);
448             return NULL;
449         }
450
451         /* Write the file */
452         fwrite(buffer.ptr, sizeof(char), buffer.len, file);
453
454         /* Create the variable which contains the output argument */
455         *content = buffer.ptr;
456
457         /* always cleanup */
458         curl_easy_cleanup(curl);
459
460         fclose(file);
461
462         return filename;
463     }
464     else
465     {
466         Scierror(999, "Failed opening the curl handle.\n");
467         return NULL;
468     }
469     return NULL;
470 }
471 /* ==================================================================== */
472 static char *Curl_basename(char *path)
473 {
474     char *s1 = NULL;
475     char *s2 = NULL;
476
477     s1 = strrchr(path, '/');
478     s2 = strrchr(path, '\\');
479
480     if (s1 && s2)
481     {
482         path = (s1 > s2 ? s1 : s2) + 1;
483     }
484     else if (s1)
485     {
486         path = s1 + 1;
487     }
488     else if (s2)
489     {
490         path = s2 + 1;
491     }
492     return path;
493 }
494 /* ==================================================================== */