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

Reply via email to