forked from enlightenment/efl
Download files with CURL. Thanks to Simon Poole.
SVN revision: 15400
This commit is contained in:
parent
cb818ba304
commit
4548e51fa5
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue