Enlightenment CVS committal Author : sebastid Project : e17 Module : libs/ecore
Dir : e17/libs/ecore/src/lib/ecore_file Modified Files: Ecore_File.h Makefile.am ecore_file.c ecore_file_download.c ecore_file_private.h Log Message: Download files with CURL. Thanks to Simon Poole. =================================================================== RCS file: /cvsroot/enlightenment/e17/libs/ecore/src/lib/ecore_file/Ecore_File.h,v retrieving revision 1.11 retrieving revision 1.12 diff -u -3 -r1.11 -r1.12 --- Ecore_File.h 16 Jun 2005 01:54:12 -0000 1.11 +++ Ecore_File.h 17 Jun 2005 23:52:32 -0000 1.12 @@ -78,7 +78,11 @@ 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 } =================================================================== RCS file: /cvsroot/enlightenment/e17/libs/ecore/src/lib/ecore_file/Makefile.am,v retrieving revision 1.7 retrieving revision 1.8 diff -u -3 -r1.7 -r1.8 --- Makefile.am 16 Jun 2005 01:54:12 -0000 1.7 +++ Makefile.am 17 Jun 2005 23:52:32 -0000 1.8 @@ -2,7 +2,8 @@ INCLUDES = \ -I$(top_srcdir)/src/lib/ecore \ --I$(top_builddir)/src/lib/ecore +-I$(top_builddir)/src/lib/ecore \ [EMAIL PROTECTED]@ libecore_file_la_LDFLAGS = -version-info 1:0:0 \ -L$(top_builddir)/src/lib/ecore/.libs @@ -24,7 +25,7 @@ libecore_file_la_LIBADD = \ $(top_builddir)/src/lib/ecore/libecore.la \ [EMAIL PROTECTED]@ [EMAIL PROTECTED]@ @curl_libs@ endif =================================================================== RCS file: /cvsroot/enlightenment/e17/libs/ecore/src/lib/ecore_file/ecore_file.c,v retrieving revision 1.10 retrieving revision 1.11 diff -u -3 -r1.10 -r1.11 --- ecore_file.c 11 Jun 2005 13:29:09 -0000 1.10 +++ ecore_file.c 17 Jun 2005 23:52:32 -0000 1.11 @@ -11,6 +11,8 @@ return 0; if (!ecore_file_path_init()) return 0; + if (!ecore_file_download_init()) + return 0; return 1; } @@ -21,6 +23,8 @@ return 0; if (!ecore_file_path_shutdown()) return 0; + if (!ecore_file_download_shutdown()) + return 0; return 1; } =================================================================== RCS file: /cvsroot/enlightenment/e17/libs/ecore/src/lib/ecore_file/ecore_file_download.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -3 -r1.1 -r1.2 --- ecore_file_download.c 16 Jun 2005 01:54:12 -0000 1.1 +++ ecore_file_download.c 17 Jun 2005 23:52:32 -0000 1.2 @@ -3,23 +3,282 @@ */ #include "ecore_file_private.h" +#ifdef HAVE_CURL +#include <curl/curl.h> + +typedef struct _Ecore_File_Download_Job Ecore_File_Download_Job; + +struct _Ecore_File_Download_Job +{ + 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(const char *url, const char *dst_dir) +ecore_file_download_init(void) { - if (!ecore_file_is_dir(dst_dir)) return 0; +#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 =================================================================== RCS file: /cvsroot/enlightenment/e17/libs/ecore/src/lib/ecore_file/ecore_file_private.h,v retrieving revision 1.6 retrieving revision 1.7 diff -u -3 -r1.6 -r1.7 --- ecore_file_private.h 11 Jun 2005 13:29:09 -0000 1.6 +++ ecore_file_private.h 17 Jun 2005 23:52:32 -0000 1.7 @@ -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 @@ 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 ------------------------------------------------------- SF.Net email is sponsored by: Discover Easy Linux Migration Strategies from IBM. Find simple to follow Roadmaps, straightforward articles, informative Webcasts and more! Get everything you need to get up to speed, fast. http://ads.osdn.com/?ad_id=7477&alloc_id=16492&op=click _______________________________________________ enlightenment-cvs mailing list enlightenment-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs