2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2012-2013 - S/E - Sylvestre LEDRU
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
14 #define _GNU_SOURCE /* basename crashes this extension otherwise */
17 #include <curl/curl.h>
18 #include <libxml/uri.h>
20 #include "dlManager.h"
25 #include "charEncoding.h"
26 #include "localization.h"
29 #include "scicurdir.h"
30 #include "splitpath.h"
31 #include "getScilabPreference.h"
33 #include "freeArrayOfString.h"
34 /* ==================================================================== */
36 static char *Curl_basename(char *path);
37 #define basename(x) Curl_basename((x))
39 /* ==================================================================== */
40 static char errorBuffer[CURL_ERROR_SIZE];
41 /* ==================================================================== */
42 static int getProxyValues(char **proxyHost, long *proxyPort, char **proxyUserPwd);
43 /* ==================================================================== */
44 typedef struct __INPUTSTRING__
49 /* ==================================================================== */
50 static void init_string(inputString *s)
53 s->ptr = (char*)CALLOC(s->len + 1, sizeof(char));
56 Scierror(999, "Internal error: calloc() failed.\n");
60 /* ==================================================================== */
61 static void free_string(inputString *s)
69 /* ==================================================================== */
70 static size_t writefunc(void *ptr, size_t size, size_t nmemb, inputString *s)
72 size_t new_len = s->len + size * nmemb;
74 s->ptr = (char*)REALLOC(s->ptr, new_len + 1);
77 Scierror(999, "Internal error: realloc() failed.\n");
80 memcpy(s->ptr + s->len, ptr, size * nmemb);
81 s->ptr[new_len] = '\0';
86 /* ==================================================================== */
87 static char *getFileNameFromURL(char *url)
89 char *filename = NULL;
90 xmlURIPtr c = xmlParseURI(url);
94 Scierror(999, _("Could not parse the URL.\n"));
98 if (c->path == NULL || strstr(c->path, "/") == 0 || strcmp(c->path, "/") == 0)
100 filename = (char *)MALLOC((strlen(DEFAULT_FILENAME) + 1) * sizeof(char));
101 strcpy(filename, DEFAULT_FILENAME);
105 char bname[PATH_MAX] = {0};
106 strncpy(bname, basename(c->path), sizeof(bname));
107 filename = (char *)MALLOC((strlen(bname) + 1) * sizeof(char));
108 strcpy(filename, bname);
113 /* ==================================================================== */
114 int getProxyValues(char **proxyHost, long *proxyPort, char **proxyUserPwd)
116 const char * attrs[] = {"enabled", "host", "port", "user", "password"};
117 const unsigned int N = sizeof(attrs) / sizeof(char*);
118 char ** values = getPrefAttributesValues("//web/body/proxy", attrs, N);
125 if (stricmp(values[0]/*enabled*/, "true") == 0)
127 const unsigned int ulen = (const unsigned int)strlen(values[3]);
128 const unsigned int plen = (const unsigned int)strlen(values[4]);
130 *proxyHost = values[1]; //host;
131 *proxyPort = strtol(values[2], NULL, 10); //port;
136 *proxyUserPwd = values[3]; //user
140 *proxyUserPwd = (char *)MALLOC((ulen + 1 + plen + 1) * sizeof(char *));
141 sprintf(*proxyUserPwd, "%s:%s", values[3]/*user*/, values[4]/*password*/);
142 (*proxyUserPwd)[ulen + 1 + plen] = '\0';
151 freeArrayOfString(values, N);
157 /* ==================================================================== */
158 char *downloadFile(char *url, char *dest, char *username, char *password, char **content)
162 char *filename = NULL;
165 char *destdir = NULL;
166 char *destfile = NULL;
168 curl = curl_easy_init();
171 Scierror(999, "Failed opening the curl handle.\n");
175 init_string(&buffer);
177 res = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
180 Scierror(999, "Failed to set error buffer [%d]\n", res);
184 // Get destination directory and filename
187 // Destination is specified in argument
188 char* pathdrive = (char*)MALLOC(sizeof(char) * (PATH_MAX + 1));
189 char* pathdir = (char*)MALLOC(sizeof(char) * (PATH_MAX + 1));
190 char* pathfile = (char*)MALLOC(sizeof(char) * (PATH_MAX + 1));
191 char* pathext = (char*)MALLOC(sizeof(char) * (PATH_MAX + 1));
193 splitpath(dest, TRUE, pathdrive, pathdir, pathfile, pathext);
197 // Destination is a file
198 destdir = (char *)MALLOC((strlen(pathdrive) + strlen(pathdir) + 1) * sizeof(char));
199 strcpy(destdir, pathdrive);
200 strcat(destdir, pathdir);
203 destfile = (char *)MALLOC((strlen(pathfile) + strlen(pathext) + 1) * sizeof(char));
204 strcpy(destfile, pathfile);
205 strcat(destfile, pathext);
209 // Destination is a directory
210 destdir = (char *)MALLOC((strlen(pathdrive) + strlen(pathdir) + strlen(pathfile) + strlen(pathext) + strlen(DIR_SEPARATOR) + 1) * sizeof(char));
211 strcpy(destdir, pathdrive);
212 strcat(destdir, pathdir);
213 strcat(destdir, pathfile);
214 strcat(destdir, pathext);
215 strcat(destdir, DIR_SEPARATOR);
217 // Retrieve filename from URL
218 destfile = getFileNameFromURL(url);
228 // Destination is not specified in argument
229 // Destination directory is current dir
232 currentdir = scigetcwd(&err);
235 destdir = (char *)MALLOC((strlen(currentdir) + strlen(DIR_SEPARATOR) + 1) * sizeof(char));
236 strcpy(destdir, currentdir);
237 strcat(destdir, DIR_SEPARATOR);
242 Scierror(999, _("Failed getting current dir, error code: %d\n"), err);
246 // Destination filename retrieved from URL
247 destfile = getFileNameFromURL(url);
250 if (destfile == NULL)
256 filename = (char *)MALLOC((strlen(destdir) + strlen(destfile) + 1) * sizeof(char));
257 strcpy(filename, destdir);
258 strcat(filename, destfile);
262 res = curl_easy_setopt(curl, CURLOPT_URL, url);
265 Scierror(999, _("Failed to set URL [%s]\n"), errorBuffer);
270 //Set authentication variables
271 if (username != NULL)
274 int uplen = (int)strlen(username);
275 if (password != NULL)
277 uplen = uplen + (int)strlen(password);
280 userpass = (char *)MALLOC((uplen + 2) * sizeof(char));
282 strcpy(userpass, username);
283 strcat(userpass, ":");
284 if (password != NULL)
286 strcat(userpass, password);
289 res = curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
294 Scierror(999, "Failed to set httpauth type to ANY [%s]\n", errorBuffer);
298 res = curl_easy_setopt(curl, CURLOPT_USERPWD, userpass);
302 Scierror(999, _("Failed to set user:pwd [%s]\n"), errorBuffer);
305 } /* end authentication section */
308 //Set proxy variables
309 char *proxyHost = NULL;
310 char *proxyUserPwd = NULL;
311 long proxyPort = 1080;
314 proxySet = getProxyValues(&proxyHost, &proxyPort, &proxyUserPwd);
318 res = curl_easy_setopt(curl, CURLOPT_PROXY, proxyHost);
322 Scierror(999, _("Failed to set proxy host [%s]\n"), errorBuffer);
326 res = curl_easy_setopt(curl, CURLOPT_PROXYPORT, proxyPort);
330 Scierror(999, _("Failed to set proxy port [%s]\n"), errorBuffer);
333 if (proxyUserPwd != NULL)
335 res = curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, proxyUserPwd);
339 Scierror(999, _("Failed to set proxy user:password [%s]\n"), errorBuffer);
345 } /* end of the set of the proxy */
347 res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
351 Scierror(999, _("Failed to set write function [%s]\n"), errorBuffer);
355 //Get data to be written to the variable
356 res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
360 free_string(&buffer);
361 Scierror(999, _("Failed to set write data [%s]\n"), errorBuffer);
366 res = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
370 free_string(&buffer);
371 Scierror(999, _("Failed to set 'Follow Location' [%s]\n"), errorBuffer);
375 res = curl_easy_perform(curl);
379 free_string(&buffer);
380 Scierror(999, _("Transfer did not complete successfully: %s\n"), errorBuffer);
384 wcfopen(file, (char*)filename, "wb");
387 Scierror(999, _("Failed opening '%s' for writing.\n"), filename);
393 fwrite(buffer.ptr, sizeof(char), buffer.len, file);
395 /* Create the variable which contains the output argument */
396 *content = buffer.ptr;
399 curl_easy_cleanup(curl);
404 /* ==================================================================== */
405 static char *Curl_basename(char *path)
410 s1 = strrchr(path, '/');
411 s2 = strrchr(path, '\\');
415 path = (s1 > s2 ? s1 : s2) + 1;
427 /* ==================================================================== */