aboutsummaryrefslogtreecommitdiffstats
path: root/grpmi/curl_download/curl_download.xs
diff options
context:
space:
mode:
Diffstat (limited to 'grpmi/curl_download/curl_download.xs')
-rw-r--r--grpmi/curl_download/curl_download.xs279
1 files changed, 279 insertions, 0 deletions
diff --git a/grpmi/curl_download/curl_download.xs b/grpmi/curl_download/curl_download.xs
new file mode 100644
index 00000000..9fd8b766
--- /dev/null
+++ b/grpmi/curl_download/curl_download.xs
@@ -0,0 +1,279 @@
+/* -*- c -*-
+ *
+ * Copyright (c) 2002 Guillaume Cottenceau (gc at mandrakesoft dot com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ ******************************************************************************/
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+#include <curl/curl.h>
+#include <curl/easy.h>
+
+#include <libintl.h>
+#undef _
+#define _(arg) dgettext("grpmi", arg)
+
+char * my_asprintf(char *msg, ...)
+{
+ char * out;
+ va_list args;
+ va_start(args, msg);
+ if (vasprintf(&out, msg, args) == -1)
+ out = "";
+ va_end(args);
+ return out;
+}
+
+
+SV * downloadprogress_callback_sv = NULL;
+
+int my_progress_func(void *ptr, double td, double dd, double tu, double du)
+{
+ dSP;
+ if (!downloadprogress_callback_sv)
+ return 0;
+ ENTER;
+ SAVETMPS;
+ PUSHMARK(SP);
+ XPUSHs(sv_2mortal(newSVnv(td)));
+ XPUSHs(sv_2mortal(newSVnv(dd)));
+ PUTBACK;
+ perl_call_sv(downloadprogress_callback_sv, G_DISCARD);
+ FREETMPS;
+ LEAVE;
+ return 0;
+}
+
+char * download_url_real(char * url, char * location, char * proxy)
+{
+ CURL *curl;
+ CURLcode rescurl = CURL_LAST;
+
+ if ((curl = curl_easy_init())) {
+ char * outfilename;
+ struct stat statbuf;
+ char * filename = basename(url);
+ FILE * outfile;
+
+ if (stat(location, &statbuf) || !S_ISDIR(statbuf.st_mode))
+ return _("Directory where to put download must be existing");
+
+ if (asprintf(&outfilename, "%s/%s", location, filename) == -1)
+ return _("Out of memory\n");
+
+ if (!stat(outfilename, &statbuf) && S_ISREG(statbuf.st_mode)) {
+ curl_easy_setopt(curl, CURLOPT_RESUME_FROM, statbuf.st_size);
+ } else {
+ unlink(outfilename);
+ curl_easy_setopt(curl, CURLOPT_RESUME_FROM, 0);
+ }
+
+ outfile = fopen(outfilename, "a");
+ free(outfilename);
+
+ if (!outfile)
+ return _("Could not open output file in append mode");
+
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_FILE, outfile);
+ curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
+ curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress_func);
+
+ if (proxy && strcmp(proxy, ""))
+ curl_easy_setopt(curl, CURLOPT_PROXY, proxy);
+
+ rescurl = curl_easy_perform(curl);
+
+ if (rescurl == CURLE_ALREADY_COMPLETE)
+ rescurl = CURLE_OK;
+
+ fclose(outfile);
+ curl_easy_cleanup(curl);
+ }
+
+ if (rescurl != CURLE_OK) {
+ switch (rescurl) {
+ case CURLE_UNSUPPORTED_PROTOCOL:
+ return _("Unsupported protocol\n");
+ break;
+ case CURLE_FAILED_INIT:
+ return _("Failed init\n");
+ break;
+ case CURLE_URL_MALFORMAT:
+ return _("Bad URL format\n");
+ break;
+ case CURLE_URL_MALFORMAT_USER:
+ return _("Bad user format in URL\n");
+ break;
+ case CURLE_COULDNT_RESOLVE_PROXY:
+ return _("Couldn't resolve proxy\n");
+ break;
+ case CURLE_COULDNT_RESOLVE_HOST:
+ return _("Couldn't resolve host\n");
+ break;
+ case CURLE_COULDNT_CONNECT:
+ return _("Couldn't connect\n");
+ break;
+ case CURLE_FTP_WEIRD_SERVER_REPLY:
+ return _("Ftp weird server reply\n");
+ break;
+ case CURLE_FTP_ACCESS_DENIED:
+ return _("Ftp access denied\n");
+ break;
+ case CURLE_FTP_USER_PASSWORD_INCORRECT:
+ return _("Ftp user password incorrect\n");
+ break;
+ case CURLE_FTP_WEIRD_PASS_REPLY:
+ return _("Ftp weird PASS reply\n");
+ break;
+ case CURLE_FTP_WEIRD_USER_REPLY:
+ return _("Ftp weird USER reply\n");
+ break;
+ case CURLE_FTP_WEIRD_PASV_REPLY:
+ return _("ftp weird PASV reply\n");
+ break;
+ case CURLE_FTP_WEIRD_227_FORMAT:
+ return _("Ftp weird 227 format\n");
+ break;
+ case CURLE_FTP_CANT_GET_HOST:
+ return _("Ftp can't get host\n");
+ break;
+ case CURLE_FTP_CANT_RECONNECT:
+ return _("Ftp can't reconnect\n");
+ break;
+ case CURLE_FTP_COULDNT_SET_BINARY:
+ return _("Ftp couldn't set binary\n");
+ break;
+ case CURLE_PARTIAL_FILE:
+ return _("Partial file\n");
+ break;
+ case CURLE_FTP_COULDNT_RETR_FILE:
+ return _("Ftp couldn't RETR file\n");
+ break;
+ case CURLE_FTP_WRITE_ERROR:
+ return _("Ftp write error\n");
+ break;
+ case CURLE_FTP_QUOTE_ERROR:
+ /* "quote" is an ftp command, not the typographic things, so
+ * don't translate that word */
+ return _("Ftp quote error\n");
+ break;
+ case CURLE_HTTP_NOT_FOUND:
+ return _("http not found\n");
+ break;
+ case CURLE_WRITE_ERROR:
+ return _("Write error\n");
+ break;
+ case CURLE_MALFORMAT_USER: /* the user name is illegally specified */
+ return _("User name illegally specified\n");
+ break;
+ case CURLE_FTP_COULDNT_STOR_FILE: /* failed FTP upload */
+ return _("ftp couldn't STOR file\n");
+ break;
+ case CURLE_READ_ERROR: /* could open/read from file */
+ return _("Read error\n");
+ break;
+ case CURLE_OUT_OF_MEMORY:
+ return _("Out of memory\n");
+ break;
+ case CURLE_OPERATION_TIMEOUTED: /* the timeout time was reached */
+ return _("Time out\n");
+ break;
+ case CURLE_FTP_COULDNT_SET_ASCII: /* TYPE A failed */
+ return _("Ftp couldn't set ASCII\n");
+ break;
+ case CURLE_FTP_PORT_FAILED: /* FTP PORT operation failed */
+ return _("Ftp PORT failed\n");
+ break;
+ case CURLE_FTP_COULDNT_USE_REST: /* the REST command failed */
+ return _("Ftp couldn't use REST\n");
+ break;
+ case CURLE_FTP_COULDNT_GET_SIZE: /* the SIZE command failed */
+ return _("Ftp couldn't get size\n");
+ break;
+ case CURLE_HTTP_RANGE_ERROR: /* The RANGE "command" didn't seem to work */
+ return _("Http range error\n");
+ break;
+ case CURLE_HTTP_POST_ERROR:
+ return _("Http POST error\n");
+ break;
+ case CURLE_SSL_CONNECT_ERROR: /* something was wrong when connecting with SSL */
+ return _("Ssl connect error\n");
+ break;
+ case CURLE_FTP_BAD_DOWNLOAD_RESUME: /* couldn't resume download */
+ return _("Ftp bad download resume\n");
+ break;
+ case CURLE_FILE_COULDNT_READ_FILE:
+ return _("File couldn't read file\n");
+ break;
+ case CURLE_LDAP_CANNOT_BIND:
+ return _("LDAP cannot bind\n");
+ break;
+ case CURLE_LDAP_SEARCH_FAILED:
+ return _("LDAP search failed\n");
+ break;
+ case CURLE_LIBRARY_NOT_FOUND:
+ return _("Library not found\n");
+ break;
+ case CURLE_FUNCTION_NOT_FOUND:
+ return _("Function not found\n");
+ break;
+ case CURLE_ABORTED_BY_CALLBACK:
+ return _("Aborted by callback\n");
+ break;
+ case CURLE_BAD_FUNCTION_ARGUMENT:
+ return _("Bad function argument\n");
+ break;
+ case CURLE_BAD_CALLING_ORDER:
+ return _("Bad calling order\n");
+ break;
+ default:
+ return my_asprintf(_("Unknown error code %d\n"), rescurl);
+ break;
+ }
+ }
+ return "";
+}
+
+
+/************************** Gateway to Perl ****************************/
+
+MODULE = curl_download PACKAGE = curl_download
+PROTOTYPES : DISABLE
+
+char *
+download(url, location, proxy, downloadprogress_callback)
+ char * url
+ char * location
+ char * proxy
+ SV * downloadprogress_callback
+ CODE:
+ downloadprogress_callback_sv = downloadprogress_callback;
+ RETVAL = download_url_real(url, location, proxy);
+ OUTPUT:
+ RETVAL
+