3d8d436bb1aaa0036eeb33abb0fd110ec1ea9257
[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         if (dest == NULL)
309         {
310             /* No second argument provided */
311             filename = getFileNameFromURL(url);
312         }
313         else
314         {
315             if (isdir(dest))
316             {
317                 /* The target is a directory. Select the name from the URL */
318                 char *name = getFileNameFromURL(url);
319
320                 filename = (char *)MALLOC((strlen(name) + strlen("/") + strlen(dest) + 1) * sizeof(char));
321                 strcpy(filename, dest);
322                 strcat(filename, "/");
323                 strcat(filename, name);
324
325             }
326             else
327             {
328                 filename = (char *)MALLOC((strlen(dest) + 1) * sizeof(char));
329                 strcpy(filename, dest);
330             }
331         }
332
333         wcfopen(file, (char*)filename, "wb");
334
335         if (file == NULL)
336         {
337             Scierror(999, _("Failed opening '%s' for writing.\n"), filename);
338             return NULL;
339         }
340
341         res = curl_easy_setopt(curl, CURLOPT_URL, url);
342         if (res != CURLE_OK)
343         {
344             Scierror(999, _("Failed to set URL [%s]\n"), errorBuffer);
345             return NULL;
346         }
347
348         //Set authentication variables
349         if (username != NULL)
350         {
351             char * userpass;
352             int uplen = (int)strlen(username);
353             if (password != NULL)
354             {
355                 uplen = uplen + (int)strlen(password);
356             }
357
358             userpass = (char *)MALLOC((uplen + 2) * sizeof(char));
359
360             strcpy(userpass, username);
361             strcat(userpass, ":");
362             if (password != NULL)
363             {
364                 strcat(userpass, password);
365             }
366
367             res = curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
368             if (res != CURLE_OK)
369             {
370                 Scierror(999, "Failed to set httpauth type to ANY [%s]\n", errorBuffer);
371                 return NULL;
372             }
373             res = curl_easy_setopt(curl, CURLOPT_USERPWD, userpass);
374             if (res != CURLE_OK)
375             {
376                 Scierror(999, _("Failed to set user:pwd [%s]\n"), errorBuffer);
377                 return NULL;
378             }
379         } /* end authentication section */
380
381         {
382             //Set proxy variables
383             char *proxyHost = NULL;
384             char *proxyUserPwd = NULL;
385             long proxyPort = 1080;
386             int proxySet = 0;
387
388             proxySet = getProxyValues(&proxyHost, &proxyPort, &proxyUserPwd);
389
390             if (proxySet == 1)
391             {
392                 res = curl_easy_setopt(curl, CURLOPT_PROXY, proxyHost);
393                 if (res != CURLE_OK)
394                 {
395                     Scierror(999, _("Failed to set proxy host [%s]\n"), errorBuffer);
396                     return NULL;
397                 }
398                 curl_easy_setopt(curl, CURLOPT_PROXYPORT, proxyPort);
399                 if (res != CURLE_OK)
400                 {
401                     Scierror(999, _("Failed to set proxy port [%s]\n"), errorBuffer);
402                     return NULL;
403                 }
404                 if (proxyUserPwd != NULL)
405                 {
406                     res = curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, proxyUserPwd);
407                     if (res != CURLE_OK)
408                     {
409                         Scierror(999, _("Failed to set proxy user:password [%s]\n"), errorBuffer);
410                         return NULL;
411                     }
412                 }
413
414             }
415         } /* end of the set of the proxy */
416
417         res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
418
419         if (res != CURLE_OK)
420         {
421             Scierror(999, _("Failed to set write data [%s]\n"), errorBuffer);
422             return NULL;
423         }
424
425         //Get data to be written to the variable
426         res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
427         if (res != CURLE_OK)
428         {
429             Scierror(999, _("Failed to set write data [%s]\n"), errorBuffer);
430             return NULL;
431         }
432
433         // Follow redirects
434         curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
435
436         res = curl_easy_perform(curl);
437
438         if (res != 0)
439         {
440             Scierror(999, _("Transfer did not complete successfully: %s\n"), errorBuffer);
441             return NULL;
442         }
443
444         /* Write the file */
445         fwrite(buffer.ptr, sizeof(char), buffer.len, file);
446
447         /* Create the variable which contains the output argument */
448         *content = buffer.ptr;
449
450         /* always cleanup */
451         curl_easy_cleanup(curl);
452
453         fclose(file);
454
455         return filename;
456     }
457     else
458     {
459         Scierror(999, "Failed opening the curl handle.\n");
460         return NULL;
461     }
462     return NULL;
463 }
464 /* ==================================================================== */
465 static char *Curl_basename(char *path)
466 {
467     char *s1 = NULL;
468     char *s2 = NULL;
469
470     s1 = strrchr(path, '/');
471     s2 = strrchr(path, '\\');
472
473     if (s1 && s2)
474     {
475         path = (s1 > s2 ? s1 : s2) + 1;
476     }
477     else if (s1)
478     {
479         path = s1 + 1;
480     }
481     else if (s2)
482     {
483         path = s2 + 1;
484     }
485     return path;
486 }
487 /* ==================================================================== */