Download files with CURL. Thanks to Simon Poole.

SVN revision: 15400
This commit is contained in:
sebastid 2005-06-17 23:52:32 +00:00 committed by sebastid
parent cb818ba304
commit 4548e51fa5
6 changed files with 309 additions and 14 deletions

View File

@ -793,6 +793,7 @@ ecore_file_libs=""
use_fam="no"
use_inotify="no"
use_poll="no"
use_curl="no"
AC_MSG_CHECKING(whether ecore_file module is to be built)
AC_ARG_ENABLE(ecore-file,
@ -882,6 +883,23 @@ if test "x$use_poll" = "xyes"; then
AC_DEFINE(HAVE_POLL, 1, [ File monitoring with polling ])
fi
curl_flags=""
curl_libs=""
# Check for CURL
AC_ARG_WITH(curl-config, [ --with-curl-config=CURL_CONFIG use curl-config specified ],
[ CURL_CONFIG=$withval;
echo "using "$CURL_CONFIG" for curl-config"; ],
[ if test -z "$CURL_CONFIG"; then
AC_PATH_PROG(CURL_CONFIG, "curl-config", "", $PATH)
fi
])
if test "$CURL_CONFIG"; then
use_curl="yes"
curl_cflags=`$CURL_CONFIG --cflags`
curl_libs=`$CURL_CONFIG --libs`
AC_DEFINE(HAVE_CURL, 1, [Downloading with CURL])
fi
if test "x$have_ecore_file" = "xyes"; then
AM_CONDITIONAL(BUILD_ECORE_FILE, true)
ecore_file_libs="-lecore_file"
@ -889,7 +907,9 @@ if test "x$have_ecore_file" = "xyes"; then
else
AM_CONDITIONAL(BUILD_ECORE_FILE, false)
fi
ecore_file_libs="$ecore_file_libs $fam_libs"
ecore_file_libs="$ecore_file_libs $fam_libs $curl_libs"
AC_SUBST(curl_cflags)
AC_SUBST(curl_libs)
AC_SUBST(fam_libs)
AC_SUBST(ecore_file_libs)
@ -1000,7 +1020,7 @@ echo " Ecore_Ipc...............: $have_ecore_ipc (OpenSSL: $use_openssl)"
echo " Ecore_Config............: $have_ecore_config"
echo " Ecore_DBUS..............: $have_ecore_dbus"
#echo " Ecore_File..............: $have_ecore_file (Inotify: $use_inotify) (FAM: $use_fam) (Poll: $use_poll)"
echo " Ecore_File..............: $have_ecore_file (Inotify: $use_inotify) (Poll: $use_poll)"
echo " Ecore_File..............: $have_ecore_file (Inotify: $use_inotify) (Poll: $use_poll) (CURL: $use_curl)"
echo
echo "Now type 'make' ('gmake' on some systems) to compile $PACKAGE."
echo

View File

@ -78,7 +78,11 @@ extern "C" {
EAPI int ecore_file_app_installed(const char *app);
EAPI int ecore_file_download(const char *url, const char *dst_dir);
EAPI int ecore_file_download(const char *url, const char *dst,
void (*completion_cb)(void *data,
const char *file,
int status),
void *data);
#ifdef __cplusplus
}

View File

@ -2,7 +2,8 @@ MAINTAINERCLEANFILES = Makefile.in
INCLUDES = \
-I$(top_srcdir)/src/lib/ecore \
-I$(top_builddir)/src/lib/ecore
-I$(top_builddir)/src/lib/ecore \
@curl_cflags@
libecore_file_la_LDFLAGS = -version-info 1:0:0 \
-L$(top_builddir)/src/lib/ecore/.libs
@ -24,7 +25,7 @@ ecore_file_download.c
libecore_file_la_LIBADD = \
$(top_builddir)/src/lib/ecore/libecore.la \
@fam_libs@
@fam_libs@ @curl_libs@
endif

View File

@ -11,6 +11,8 @@ ecore_file_init()
return 0;
if (!ecore_file_path_init())
return 0;
if (!ecore_file_download_init())
return 0;
return 1;
}
@ -21,6 +23,8 @@ ecore_file_shutdown()
return 0;
if (!ecore_file_path_shutdown())
return 0;
if (!ecore_file_download_shutdown())
return 0;
return 1;
}

View File

@ -3,23 +3,282 @@
*/
#include "ecore_file_private.h"
int
ecore_file_download(const char *url, const char *dst_dir)
#ifdef HAVE_CURL
#include <curl/curl.h>
typedef struct _Ecore_File_Download_Job Ecore_File_Download_Job;
struct _Ecore_File_Download_Job
{
if (!ecore_file_is_dir(dst_dir)) return 0;
Ecore_Fd_Handler *fd_handler;
CURL *curl;
void (*completion_cb)(void *data, const char *file, int status);
void *data;
FILE *file;
char *dst;
};
Ecore_File_Download_Job *_ecore_file_download_curl(const char *url, const char *dst,
void (*completion_cb)(void *data, const char *file, int status),
void *data);
static int _ecore_file_download_curl_fd_handler(void *data, Ecore_Fd_Handler *fd_handler);
static CURLM *curlm;
static Ecore_List *_job_list;
static fd_set _current_fd_set;
#endif
int
ecore_file_download_init(void)
{
#ifdef HAVE_CURL
FD_ZERO(&_current_fd_set);
_job_list = ecore_list_new();
if (!_job_list) return 0;
if (curl_global_init(CURL_GLOBAL_NOTHING)) return 0;
curlm = curl_multi_init();
if (!curlm)
{
ecore_list_destroy(_job_list);
_job_list = NULL;
return 0;
}
#endif
return 1;
}
int
ecore_file_download_shutdown(void)
{
#ifdef HAVE_CURL
Ecore_File_Download_Job *job;
if (!ecore_list_is_empty(_job_list))
{
ecore_list_goto_first(_job_list);
while ((job = ecore_list_next(_job_list)))
{
ecore_main_fd_handler_del(job->fd_handler);
curl_multi_remove_handle(curlm, job->curl);
curl_easy_cleanup(job->curl);
fclose(job->file);
free(job->dst);
free(job);
}
}
ecore_list_destroy(_job_list);
curl_multi_cleanup(curlm);
curl_global_cleanup();
#endif
return 1;
}
int
ecore_file_download(const char *url, const char *dst,
void (*completion_cb)(void *data, const char *file, int status),
void *data)
{
if (!ecore_file_is_dir(ecore_file_get_dir(dst))) return 0;
if (ecore_file_exists(dst)) return 0;
/* FIXME: Add handlers for http and ftp! */
if (!strncmp(url, "file://", 7))
{
/* FIXME: Maybe fork? Might take a while to copy.
* Check filesize? */
/* Just copy it */
char buf[PATH_MAX];
url += 7;
snprintf(buf, sizeof(buf), "%s/%s", dst_dir, ecore_file_get_file(url));
return ecore_file_cp(url, buf);
/* skip hostname */
url = strchr(url, '/');
return ecore_file_cp(url, dst);
}
#ifdef HAVE_CURL
else if ((!strncmp(url, "http://", 7)) ||
(!strncmp(url, "ftp://", 7)))
{
/* download */
Ecore_File_Download_Job *job;
job = _ecore_file_download_curl(url, dst, completion_cb, data);
if (job)
return 1;
else
return 0;
}
#endif
else
{
return 0;
}
}
#ifdef HAVE_CURL
/*
* FIXME: Use
* CURLOPT_PROGRESSFUNCTION and CURLOPT_PROGRESSDATA to
* get reports on progress.
* And maybe other nifty functions...
*/
Ecore_File_Download_Job *
_ecore_file_download_curl(const char *url, const char *dst,
void (*completion_cb)(void *data, const char *file,
int status),
void *data)
{
CURLMsg *curlmsg;
fd_set read_set, write_set, exc_set;
int fd_max;
int fd;
int flags;
int n_remaining, still_running;
Ecore_File_Download_Job *job;
job = calloc(1, sizeof(Ecore_File_Download_Job));
if (!job) return NULL;
job->file = fopen(dst, "wb");
if (!job->file)
{
free(job);
return NULL;
}
job->curl = curl_easy_init();
if (!job->curl)
{
fclose(job->file);
free(job);
return NULL;
}
curl_easy_setopt(job->curl, CURLOPT_URL, url);
curl_easy_setopt(job->curl, CURLOPT_WRITEDATA, job->file);
job->data = data;
job->completion_cb = completion_cb;
job->dst = strdup(dst);
ecore_list_append(_job_list, job);
curl_multi_add_handle(curlm, job->curl);
while (curl_multi_perform(curlm, &still_running) == CURLM_CALL_MULTI_PERFORM);
/* check for completed jobs */
while ((curlmsg = curl_multi_info_read(curlm, &n_remaining)) != NULL)
{
Ecore_File_Download_Job *current;
if (curlmsg->msg != CURLMSG_DONE) continue;
/* find the job which is done */
ecore_list_goto_first(_job_list);
while ((current = ecore_list_current(_job_list)))
{
if (curlmsg->easy_handle == current->curl)
{
/* We have a match -- delete the job */
if (current == job)
job = NULL;
if (current->fd_handler)
{
FD_CLR(ecore_main_fd_handler_fd_get(current->fd_handler),
&_current_fd_set);
ecore_main_fd_handler_del(current->fd_handler);
}
if (current->completion_cb)
current->completion_cb(current->data, current->dst,
curlmsg->data.result);
ecore_list_remove(_job_list);
curl_multi_remove_handle(curlm, current->curl);
curl_easy_cleanup(current->curl);
fclose(current->file);
free(current->dst);
free(current);
break;
}
ecore_list_next(_job_list);
}
}
if (job)
{
FD_ZERO(&read_set);
FD_ZERO(&write_set);
FD_ZERO(&exc_set);
/* Stupid curl, why can't I get the fd to the current added job? */
curl_multi_fdset(curlm, &read_set, &write_set, &exc_set, &fd_max);
printf("max: %d\n", fd_max);
for (fd = 0; fd <= fd_max; fd++)
{
if (!FD_ISSET(fd, &_current_fd_set))
{
printf("Found %d!!!\n", fd);
flags = 0;
if (FD_ISSET(fd, &read_set)) flags |= ECORE_FD_READ;
if (FD_ISSET(fd, &write_set)) flags |= ECORE_FD_WRITE;
if (FD_ISSET(fd, &exc_set)) flags |= ECORE_FD_ERROR;
printf("flags: %d\n", flags);
if (flags)
{
FD_SET(fd, &_current_fd_set);
job->fd_handler = ecore_main_fd_handler_add(fd, flags,
_ecore_file_download_curl_fd_handler,
NULL, NULL, NULL);
}
}
}
if (!job->fd_handler)
{
printf("No fd handler?\n");
curl_easy_cleanup(job->curl);
fclose(job->file);
free(job);
job = NULL;
}
}
return job;
}
static int
_ecore_file_download_curl_fd_handler(void *data, Ecore_Fd_Handler *fd_handler)
{
Ecore_File_Download_Job *job;
CURLMsg *curlmsg;
int n_remaining, still_running;
/* FIXME: Can this run for a long time? Maybe limit how long it can run */
while (curl_multi_perform(curlm, &still_running) == CURLM_CALL_MULTI_PERFORM);
/* Loop jobs and check if any are done */
while ((curlmsg = curl_multi_info_read(curlm, &n_remaining)) != NULL)
{
if (curlmsg->msg != CURLMSG_DONE) continue;
/* find the job which is done */
ecore_list_goto_first(_job_list);
while ((job = ecore_list_current(_job_list)))
{
if (curlmsg->easy_handle == job->curl)
{
/* We have a match -- delete the job */
FD_CLR(ecore_main_fd_handler_fd_get(job->fd_handler),
&_current_fd_set);
if (job->completion_cb)
job->completion_cb(job->data, job->dst, !curlmsg->data.result);
ecore_list_remove(_job_list);
ecore_main_fd_handler_del(job->fd_handler);
curl_multi_remove_handle(curlm, job->curl);
curl_easy_cleanup(job->curl);
fclose(job->file);
free(job->dst);
free(job);
break;
}
ecore_list_next(_job_list);
}
}
return 1;
}
#endif

View File

@ -10,12 +10,10 @@
#include "Ecore.h"
#include "Ecore_File.h"
/* ecore_file_monitor */
int ecore_file_monitor_init(void);
int ecore_file_monitor_shutdown(void);
int ecore_file_path_init(void);
int ecore_file_path_shutdown(void);
#define ECORE_FILE_MONITOR(x) ((Ecore_File_Monitor *)(x))
struct _Ecore_File_Monitor
@ -65,4 +63,13 @@ EAPI Ecore_File_Monitor *ecore_file_monitor_poll_add(const char *path,
const char *path),
void *data);
EAPI void ecore_file_monitor_poll_del(Ecore_File_Monitor *ecore_file_monitor);
/* ecore_file_path */
int ecore_file_path_init(void);
int ecore_file_path_shutdown(void);
/* ecore_file_download */
int ecore_file_download_init(void);
int ecore_file_download_shutdown(void);
#endif