During my testing of Ecore_Con, I found some little bug when you are doing
multiple download simultaneously :
- The data buffer we are receiving must be copied, or it could be
reused by curl and we will receive garbage in the event handler.
- Sometime the complete event show up before we receive the last chunk
of data. I put all the complete event inside a list and the event are send
inside an ecore_idler.
I also added some functionnality :
- Use ECORE_MAGIC.
- The status code is no longer curl internal status, but ftp or http
return code (I think it's more usefull than CURLE_OK).
- You can now add a time condition on you requested url (see HTTP code
304).
- Normally we must receive progress events also (I admit I didn't test
if it worked fine, but it should).
I used this modified ecore_con_url to developpe a library downloading file in a
cache directory cleanly. I needed to include it inside Ecore as I wanted to use
some ecore private facility like ECORE_MAGIC. I attached the patch if people
are interested.
Cedric
diff -Nrau -X exclude.cvs e17-clean/libs/ecore/src/lib/ecore_con/Ecore_Con.h e17-dev/libs/ecore/src/lib/ecore_con/Ecore_Con.h
--- e17-clean/libs/ecore/src/lib/ecore_con/Ecore_Con.h 2007-03-20 18:54:38.000000000 +0100
+++ e17-dev/libs/ecore/src/lib/ecore_con/Ecore_Con.h 2007-08-08 20:30:15.000000000 +0200
@@ -76,7 +76,15 @@
ECORE_CON_REMOTE_SYSTEM,
ECORE_CON_USE_SSL = 16
} Ecore_Con_Type;
-
+
+ typedef enum _Ecore_Con_Url_Time
+ {
+ ECORE_CON_URL_TIME_NONE = 0,
+ ECORE_CON_URL_TIME_IFMODSINCE,
+ ECORE_CON_URL_TIME_IFUNMODSINCE,
+ ECORE_CON_URL_TIME_LASTMOD
+ } Ecore_Con_Url_Time;
+
typedef struct _Ecore_Con_Event_Client_Add Ecore_Con_Event_Client_Add;
typedef struct _Ecore_Con_Event_Client_Del Ecore_Con_Event_Client_Del;
typedef struct _Ecore_Con_Event_Server_Add Ecore_Con_Event_Server_Add;
@@ -85,6 +93,8 @@
typedef struct _Ecore_Con_Event_Server_Data Ecore_Con_Event_Server_Data;
typedef struct _Ecore_Con_Event_Url_Data Ecore_Con_Event_Url_Data;
typedef struct _Ecore_Con_Event_Url_Complete Ecore_Con_Event_Url_Complete;
+ typedef struct _Ecore_Con_Event_Url_Progress_Upload Ecore_Con_Event_Url_Progress_Upload;
+ typedef struct _Ecore_Con_Event_Url_Progress_Download Ecore_Con_Event_Url_Progress_Download;
struct _Ecore_Con_Event_Client_Add
{
@@ -132,7 +142,21 @@
Ecore_Con_Url *url_con;
int status;
};
-
+
+ struct _Ecore_Con_Event_Url_Progress_Download
+ {
+ Ecore_Con_Url *url_con;
+ double total;
+ double now;
+ };
+
+ struct _Ecore_Con_Event_Url_Progress_Upload
+ {
+ Ecore_Con_Url *url_con;
+ double total;
+ double now;
+ };
+
EAPI extern int ECORE_CON_EVENT_CLIENT_ADD;
EAPI extern int ECORE_CON_EVENT_CLIENT_DEL;
EAPI extern int ECORE_CON_EVENT_SERVER_ADD;
@@ -141,6 +165,8 @@
EAPI extern int ECORE_CON_EVENT_SERVER_DATA;
EAPI extern int ECORE_CON_EVENT_URL_DATA;
EAPI extern int ECORE_CON_EVENT_URL_COMPLETE;
+ EAPI extern int ECORE_CON_EVENT_URL_PROGRESS_DOWNLOAD;
+ EAPI extern int ECORE_CON_EVENT_URL_PROGRESS_UPLOAD;
EAPI int ecore_con_init(void);
EAPI int ecore_con_shutdown(void);
@@ -171,8 +197,11 @@
EAPI int ecore_con_url_shutdown(void);
EAPI Ecore_Con_Url *ecore_con_url_new(const char *url);
EAPI void ecore_con_url_destroy(Ecore_Con_Url *url_con);
+ EAPI void *ecore_con_url_data_set(Ecore_Con_Url *url_con, const void *data);
+ EAPI void *ecore_con_url_data_get(Ecore_Con_Url *url_con);
EAPI int ecore_con_url_url_set(Ecore_Con_Url *url_con, const char *url);
EAPI int ecore_con_url_send(Ecore_Con_Url *url_con, void *data, size_t length, char *content_type);
+ EAPI void ecore_con_url_time(Ecore_Con_Url *url_con, Ecore_Con_Url_Time condition, time_t tm);
EAPI int ecore_con_dns_lookup(const char *name,
void (*done_cb)(void *data, struct hostent *hostent),
diff -Nrau -X exclude.cvs e17-clean/libs/ecore/src/lib/ecore_con/ecore_con_private.h e17-dev/libs/ecore/src/lib/ecore_con/ecore_con_private.h
--- e17-clean/libs/ecore/src/lib/ecore_con/ecore_con_private.h 2007-03-20 18:54:38.000000000 +0100
+++ e17-dev/libs/ecore/src/lib/ecore_con/ecore_con_private.h 2007-08-08 20:23:46.000000000 +0200
@@ -6,6 +6,7 @@
#define ECORE_MAGIC_CON_SERVER 0x77665544
#define ECORE_MAGIC_CON_CLIENT 0x77556677
+#define ECORE_MAGIC_CON_URL 0x77074255
#if USE_OPENSSL
#include <openssl/ssl.h>
@@ -66,12 +67,18 @@
#ifdef HAVE_CURL
struct _Ecore_Con_Url
{
- /* FIXME: ECORE_MAGIC ? */
- CURL *curl_easy;
- char *url;
+ ECORE_MAGIC;
+ CURL *curl_easy;
struct curl_slist *headers;
- Ecore_Fd_Handler *fd_handler;
- char active : 1;
+ char *url;
+
+ Ecore_Con_Url_Time condition;
+ time_t time;
+ const void *data;
+
+ Ecore_Fd_Handler *fd_handler;
+
+ char active : 1;
};
#endif
diff -Nrau -X exclude.cvs e17-clean/libs/ecore/src/lib/ecore_con/ecore_con_url.c e17-dev/libs/ecore/src/lib/ecore_con/ecore_con_url.c
--- e17-clean/libs/ecore/src/lib/ecore_con/ecore_con_url.c 2007-08-06 16:51:03.000000000 +0200
+++ e17-dev/libs/ecore/src/lib/ecore_con/ecore_con_url.c 2007-09-14 20:54:37.000000000 +0200
@@ -44,17 +44,64 @@
static int _ecore_con_url_fd_handler(void *data, Ecore_Fd_Handler *fd_handler);
static int _ecore_con_url_perform(Ecore_Con_Url *url_con);
static size_t _ecore_con_url_data_cb(void *buffer, size_t size, size_t nmemb, void *userp);
-static void _ecore_con_event_url_complete_free(void *data __UNUSED__, void *ev);
-static void _ecore_con_event_url_data_free(void *data __UNUSED__, void *ev);
+static int _ecore_con_url_progress_cb(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
+static void _ecore_con_event_url_free(void *data __UNUSED__, void *ev);
static int _ecore_con_url_process_completed_jobs(Ecore_Con_Url *url_con_to_match);
int ECORE_CON_EVENT_URL_DATA = 0;
int ECORE_CON_EVENT_URL_COMPLETE = 0;
+int ECORE_CON_EVENT_URL_PROGRESS_DOWNLOAD = 0;
+int ECORE_CON_EVENT_URL_PROGRESS_UPLOAD = 0;
static CURLM *curlm = NULL;
static Ecore_List *_url_con_list = NULL;
static fd_set _current_fd_set;
static int init_count = 0;
+
+static Ecore_Idler *_url_complete_idler = NULL;
+static Ecore_List *_url_complete_list = NULL;
+
+struct _litle_ecore_con_url_event_s
+{
+ int type;
+ void *ev;
+};
+typedef struct _litle_ecore_con_url_event_s _litle_ecore_con_url_event_t;
+
+static int
+_url_complete_idler_cb(void *data)
+{
+ _litle_ecore_con_url_event_t *lev;
+
+ ecore_list_first_goto(_url_complete_list);
+ while ((lev = ecore_list_current(_url_complete_list)))
+ {
+ ecore_event_add(lev->type, lev->ev, _ecore_con_event_url_free, NULL);
+ ecore_list_remove(_url_complete_list);
+ free(lev);
+ }
+
+ ecore_idler_del(_url_complete_idler);
+ _url_complete_idler = NULL;
+
+ return 1;
+}
+
+static void
+_url_complete_push_event(int type, void *ev)
+{
+ _litle_ecore_con_url_event_t *lev;
+
+ lev = malloc(sizeof (_litle_ecore_con_url_event_t));
+ lev->type = type;
+ lev->ev = ev;
+
+ ecore_list_append(_url_complete_list, lev);
+
+ if (_url_complete_idler == NULL)
+ _url_complete_idler = ecore_idler_add(_url_complete_idler_cb, NULL);
+}
+
#endif
EAPI int
@@ -65,6 +112,8 @@
{
ECORE_CON_EVENT_URL_DATA = ecore_event_type_new();
ECORE_CON_EVENT_URL_COMPLETE = ecore_event_type_new();
+ ECORE_CON_EVENT_URL_PROGRESS_DOWNLOAD = ecore_event_type_new();
+ ECORE_CON_EVENT_URL_PROGRESS_UPLOAD = ecore_event_type_new();
}
if (!_url_con_list)
@@ -73,6 +122,12 @@
if (!_url_con_list) return 0;
}
+ if (!_url_complete_list)
+ {
+ _url_complete_list = ecore_list_new();
+ if (!_url_complete_list) return 0;
+ }
+
if (!curlm)
{
FD_ZERO(&_current_fd_set);
@@ -127,6 +182,12 @@
curlm = NULL;
}
+ if (_url_complete_list)
+ {
+ ecore_list_destroy(_url_complete_list);
+ _url_complete_list = NULL;
+ }
+
curl_global_cleanup();
#endif
return 1;
@@ -149,11 +210,18 @@
free(url_con);
return NULL;
}
-
+
+ ECORE_MAGIC_SET(url_con, ECORE_MAGIC_CON_URL);
+
ecore_con_url_url_set(url_con, url);
curl_easy_setopt(url_con->curl_easy, CURLOPT_WRITEFUNCTION, _ecore_con_url_data_cb);
curl_easy_setopt(url_con->curl_easy, CURLOPT_WRITEDATA, url_con);
+
+ curl_easy_setopt(url_con->curl_easy, CURLOPT_PROGRESSFUNCTION, _ecore_con_url_progress_cb);
+ curl_easy_setopt(url_con->curl_easy, CURLOPT_PROGRESSDATA, url_con);
+ curl_easy_setopt(url_con->curl_easy, CURLOPT_NOPROGRESS, FALSE);
+
/*
* FIXME: Check that these timeouts are sensible defaults
* FIXME: Provide a means to change these timeouts
@@ -174,7 +242,13 @@
{
#ifdef HAVE_CURL
if (!url_con) return;
+ if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+ {
+ ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_destroy");
+ return ;
+ }
+ ECORE_MAGIC_SET(url_con, ECORE_MAGIC_NONE);
if (url_con->fd_handler)
ecore_main_fd_handler_del(url_con->fd_handler);
if (url_con->curl_easy)
@@ -195,6 +269,12 @@
ecore_con_url_url_set(Ecore_Con_Url *url_con, const char *url)
{
#ifdef HAVE_CURL
+ if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+ {
+ ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_url_set");
+ return 0;
+ }
+
if (url_con->active) return 0;
free(url_con->url);
@@ -209,12 +289,79 @@
return 1;
}
+EAPI void*
+ecore_con_url_data_set(Ecore_Con_Url *url_con, const void *data)
+{
+#ifdef HAVE_CURL
+ const void* result;
+
+ if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+ {
+ ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_data_set");
+ return NULL;
+ }
+
+ result = url_con->data;
+ url_con->data = data;
+
+ return (void*) result;
+#else
+ (void*) url_con;
+ (const void*) data;
+
+ return NULL;
+#endif
+}
+
+EAPI void*
+ecore_con_url_data_get(Ecore_Con_Url *url_con)
+{
+#ifdef HAVE_CURL
+ if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+ {
+ ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_data_get");
+ return NULL;
+ }
+
+ return (void*) url_con->data;
+#else
+ (void*) url_con;
+
+ return NULL;
+#endif
+}
+
+EAPI void
+ecore_con_url_time(Ecore_Con_Url *url_con, Ecore_Con_Url_Time condition, time_t tm)
+{
+#ifdef HAVE_CURL
+ if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+ {
+ ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_time");
+ return ;
+ }
+
+ url_con->condition = condition;
+ url_con->time = tm;
+#else
+ (void*) url_con;
+ condition;
+ tm;
+#endif
+}
+
EAPI int
ecore_con_url_send(Ecore_Con_Url *url_con, void *data, size_t length, char *content_type)
{
#ifdef HAVE_CURL
char tmp[256];
+ if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
+ {
+ ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_send");
+ return 0;
+ }
+
if (url_con->active) return 0;
if (!url_con->url) return 0;
@@ -235,6 +382,25 @@
url_con->headers = curl_slist_append(url_con->headers, tmp);
}
+ switch (url_con->condition)
+ {
+ case ECORE_CON_URL_TIME_NONE:
+ curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
+ break;
+ case ECORE_CON_URL_TIME_IFMODSINCE:
+ curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
+ curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMEVALUE, url_con->time);
+ break;
+ case ECORE_CON_URL_TIME_IFUNMODSINCE:
+ curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFUNMODSINCE);
+ curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMEVALUE, url_con->time);
+ break;
+ case ECORE_CON_URL_TIME_LASTMOD:
+ curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMECONDITION, CURL_TIMECOND_LASTMOD);
+ curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMEVALUE, url_con->time);
+ break;
+ }
+
curl_easy_setopt(url_con->curl_easy, CURLOPT_HTTPHEADER, url_con->headers);
return _ecore_con_url_perform(url_con);
@@ -256,18 +422,46 @@
size_t real_size = size * nmemb;
url_con = (Ecore_Con_Url *)userp;
- e = calloc(1, sizeof(Ecore_Con_Event_Url_Data));
+ e = calloc(1, sizeof(Ecore_Con_Event_Url_Data) + sizeof(char) * real_size);
if (e)
{
e->url_con = url_con;
- e->data = buffer;
+ e->data = (void*) ((Ecore_Con_Event_Url_Data*)(e + 1));
e->size = real_size;
+ memcpy(e->data, buffer, real_size);
ecore_event_add(ECORE_CON_EVENT_URL_DATA, e,
- _ecore_con_event_url_data_free, NULL);
+ _ecore_con_event_url_free, NULL);
}
return real_size;
}
+#define ECORE_CON_URL_TRANSMISSION(Transmit, Event, Url_con, Total, Now) \
+ { \
+ Ecore_Con_Event_Url_Progress_##Transmit *e; \
+ if (Total != 0 || Now != 0) { \
+ e = calloc(1, sizeof(Ecore_Con_Event_Url_Progress_##Transmit)); \
+ if (e) { \
+ e->url_con = url_con; \
+ e->total = Total; \
+ e->now = Now; \
+ ecore_event_add(Event, e, _ecore_con_event_url_free, NULL); \
+ } \
+ } \
+ }
+
+static int
+_ecore_con_url_progress_cb(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
+{
+ Ecore_Con_Url *url_con;
+
+ url_con = clientp;
+
+ ECORE_CON_URL_TRANSMISSION(Download, ECORE_CON_EVENT_URL_PROGRESS_DOWNLOAD, url_con, dltotal, dlnow);
+ ECORE_CON_URL_TRANSMISSION(Upload, ECORE_CON_EVENT_URL_PROGRESS_UPLOAD, url_con, ultotal, ulnow);
+
+ return 0;
+}
+
/*
* FIXME: Use
* CURLOPT_PROGRESSFUNCTION and CURLOPT_PROGRESSDATA to
@@ -373,7 +567,6 @@
url_con->fd_handler = NULL;
}
ecore_list_remove(_url_con_list);
- curl_multi_remove_handle(curlm, url_con->curl_easy);
url_con->active = 0;
{
Ecore_Con_Event_Url_Complete *e;
@@ -381,11 +574,14 @@
if (e)
{
e->url_con = url_con;
- e->status = curlmsg->data.result;
- ecore_event_add(ECORE_CON_EVENT_URL_COMPLETE, e,
- _ecore_con_event_url_complete_free, NULL);
+
+ e->status = 0;
+ curl_easy_getinfo(curlmsg->easy_handle, CURLINFO_RESPONSE_CODE, &e->status);
+
+ _url_complete_push_event(ECORE_CON_EVENT_URL_COMPLETE, e);
}
}
+ curl_multi_remove_handle(curlm, url_con->curl_easy);
break;
}
ecore_list_next(_url_con_list);
@@ -394,20 +590,9 @@
return job_matched;
}
static void
-_ecore_con_event_url_data_free(void *data __UNUSED__, void *ev)
+_ecore_con_event_url_free(void *data __UNUSED__, void *ev)
{
- Ecore_Con_Event_Url_Data *e;
-
- e = ev;
- free(e);
+ free(ev);
}
-static void
-_ecore_con_event_url_complete_free(void *data __UNUSED__, void *ev)
-{
- Ecore_Con_Event_Url_Complete *e;
-
- e = ev;
- free(e);
-}
#endif
diff -Nrau -X exclude.cvs e17-clean/libs/ecore/configure.in e17-dev/libs/ecore/configure.in
--- e17-clean/libs/ecore/configure.in 2007-08-06 16:51:03.000000000 +0200
+++ e17-dev/libs/ecore/configure.in 2007-09-15 19:51:16.000000000 +0200
@@ -805,6 +830,7 @@
AC_SUBST(requirements_ecore_config)
AC_SUBST(requirements_ecore_desktop)
AC_SUBST(requirements_ecore_directfb)
+AC_SUBST(requirements_ecore_download)
AC_SUBST(requirements_ecore_evas)
AC_SUBST(requirements_ecore_fb)
AC_SUBST(requirements_ecore_file)
@@ -823,6 +849,7 @@
AM_CONDITIONAL(BUILD_ECORE_EVAS_DIRECTFB, test $have_ecore_evas_dfb = yes)
AM_CONDITIONAL(BUILD_ECORE_EVAS_FB, test $have_ecore_evas_fb = yes)
AM_CONDITIONAL(BUILD_ECORE_EVAS_BUFFER, test $have_ecore_evas_buffer = yes)
+AM_CONDITIONAL(BUILD_ECORE_DOWNLOAD, test "x$have_ecore_download" = "xyes")
AC_OUTPUT([
Makefile
@@ -830,6 +857,7 @@
ecore-config.pc
ecore-desktop.pc
ecore-directfb.pc
+ecore-download.pc
ecore-evas.pc
ecore-fb.pc
ecore-file.pc
@@ -849,6 +877,7 @@
src/lib/ecore_sdl/Makefile
src/lib/ecore_evas/Makefile
src/lib/ecore_con/Makefile
+src/lib/ecore_download/Makefile
src/lib/ecore_ipc/Makefile
src/lib/ecore_txt/Makefile
src/lib/ecore_config/Makefile
@@ -866,7 +895,8 @@
echo "Optional Modules:"
echo
echo " Ecore_Job....................: $have_ecore_job"
-echo " Ecore_Con....................: $have_ecore_con (OpenSSL: $use_openssl)"
+echo " Ecore_Con....................: $have_ecore_con (OpenSSL: $use_openssl) (CURL: $use_curl)"
+echo " Ecore_Download...............: $have_ecore_download"
echo " Ecore_Txt....................: $have_ecore_txt"
if test "x$have_ecore_x_xcb" = "xyes" ; then
echo " Ecore_X (XCB backend)........: $have_ecore_x_xcb (Xprint: $have_ecore_x_xcb_xprint) (Xinerama: $have_ecore_x_xcb_xinerama) (Xrandr: $have_ecore_x_xcb_randr) (Xscreensaver: $have_ecore_x_xcb_screensaver) (Xshape: $have_ecore_x_xcb_shape) (Xsync: $have_ecore_x_xcb_sync) (Xrender: $have_ecore_x_xcb_render) (Xfixes: $have_ecore_x_xcb_xfixes) (Xdamage: $have_ecore_x_xcb_damage) (Xdpms: $have_ecore_x_xcb_dpms)"
diff -Nrau -X exclude.cvs e17-clean/libs/ecore/ecore-download.pc.in e17-dev/libs/ecore/ecore-download.pc.in
--- e17-clean/libs/ecore/ecore-download.pc.in 1970-01-01 01:00:00.000000000 +0100
+++ e17-dev/libs/ecore/ecore-download.pc.in 2007-08-10 19:03:54.000000000 +0200
@@ -0,0 +1,11 @@
[EMAIL PROTECTED]@
[EMAIL PROTECTED]@
[EMAIL PROTECTED]@
[EMAIL PROTECTED]@
+
+Name: ecore-download
+Description: E core library, Download module
+Requires: ecore @requirements_ecore_download@
+Version: @VERSION@
+Libs: -L${libdir} -lecore_download
+Cflags: -I${includedir}
diff -Nrau -X exclude.cvs e17-clean/libs/ecore/Makefile.am e17-dev/libs/ecore/Makefile.am
--- e17-clean/libs/ecore/Makefile.am 2007-07-16 20:17:59.000000000 +0200
+++ e17-dev/libs/ecore/Makefile.am 2007-08-10 20:08:40.000000000 +0200
@@ -15,6 +15,7 @@
ecore-desktop.pc \
ecore-directfb.pc\
ecore-evas.pc \
+ ecore-download.pc \
ecore-fb.pc \
ecore-file.pc \
ecore-ipc.pc \
@@ -41,6 +42,7 @@
ecore-txt.pc.in \
ecore-x.pc.in \
ecore-sdl.pc.in \
+ ecore-download.pc.in \
ecore.spec.in ecore.spec \
debian/changelog \
debian/changelog.in \
@@ -61,6 +63,10 @@
debian/libecore0.install \
debian/rules
+if BUILD_ECORE_DOWNLOAD
+pdownload = ecore-download.pc
+endif
+
if BUILD_ECORE_CON
pcon = ecore-con.pc
endif
@@ -116,4 +122,4 @@
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = \
ecore.pc $(pcon) $(pconfig) $(pdfb) $(pevas) \
- $(pfb) $(pfile) $(pdesktop) $(pipc) $(pjob) $(ptxt) $(px) $(psdl)
+ $(pfb) $(pfile) $(pdesktop) $(pipc) $(pjob) $(ptxt) $(px) $(psdl) $(pdownload)
diff -Nrau -X exclude.cvs e17-clean/libs/ecore/src/lib/ecore/ecore_private.h e17-dev/libs/ecore/src/lib/ecore/ecore_private.h
--- e17-clean/libs/ecore/src/lib/ecore/ecore_private.h 2007-07-06 11:58:55.000000000 +0200
+++ e17-dev/libs/ecore/src/lib/ecore/ecore_private.h 2007-08-09 15:41:53.000000000 +0200
@@ -88,6 +88,8 @@
#define ECORE_MAGIC_EVENT_FILTER 0xf78218ff
#define ECORE_MAGIC_EVENT 0xf77119fe
#define ECORE_MAGIC_ANIMATOR 0xf7643ea5
+#define ECORE_MAGIC_DOWNLOAD_FILES 0xf7742cb5
+#define ECORE_MAGIC_DOWNLOAD_DIR 0xf775cb42
#define ECORE_MAGIC Ecore_Magic __magic
diff -Nrau -X exclude.cvs e17-clean/libs/ecore/src/lib/ecore_download/ecore_download.c e17-dev/libs/ecore/src/lib/ecore_download/ecore_download.c
--- e17-clean/libs/ecore/src/lib/ecore_download/ecore_download.c 1970-01-01 01:00:00.000000000 +0100
+++ e17-dev/libs/ecore/src/lib/ecore_download/ecore_download.c 2007-09-14 20:54:56.000000000 +0200
@@ -0,0 +1,530 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <curl/curl.h>
+
+#include "Ecore.h"
+#include "ecore_private.h"
+#include "Ecore_Con.h"
+#include "Ecore_Data.h"
+#include "Ecore_Download.h"
+
+struct _Ecore_Download_Dir
+{
+ ECORE_MAGIC;
+
+ const char *files_directory;
+ const char *temp_directory;
+ const char *prefix;
+
+ const void *data;
+
+ Ecore_List *download;
+};
+
+struct _Ecore_Download_File
+{
+ ECORE_MAGIC;
+
+ Ecore_Download_Dir *dir;
+
+ Ecore_Con_Url *url_con;
+ const char *url;
+
+ const char *file;
+ time_t tm;
+
+ const char *temp;
+ int fd;
+
+ const void *data;
+
+ int active : 1;
+ int updated : 1;
+};
+
+int ECORE_DOWNLOAD_EVENT_CANCEL = 0;
+int ECORE_DOWNLOAD_EVENT_COMPLETE = 0;
+int ECORE_DOWNLOAD_EVENT_PROGRESS = 0;
+
+static Ecore_Event_Handler *ed_url_data = NULL;
+static Ecore_Event_Handler *ed_url_complete = NULL;
+static Ecore_Event_Handler *ed_url_progress_download = NULL;
+
+static int
+_ecore_download_url_data_cb(void *data, int type, void *event)
+{
+ Ecore_Con_Event_Url_Data *e;
+ Ecore_Download_File *edf;
+
+ e = event;
+
+ edf = ecore_con_url_data_get(e->url_con);
+
+ if (!ECORE_MAGIC_CHECK(edf, ECORE_MAGIC_DOWNLOAD_FILES)) return 1;
+
+ if (edf->fd != -1)
+ {
+ edf->updated = 1;
+ write(edf->fd, e->data, e->size);
+ }
+
+ return 0;
+}
+
+static Ecore_Download_Event_Complete*
+_ecore_download_event_complete_new(Ecore_Download_File *edf, int status)
+{
+ Ecore_Download_Event_Complete *edec;
+
+ edec = calloc(1, sizeof(Ecore_Download_Event_Complete) + strlen(edf->file) + 1);
+ if (edec == NULL) return NULL;
+
+ edec->edf = edf;
+ edec->status = status;
+ edec->file = (const char*)((Ecore_Download_Event_Complete*) (edec + 1));
+ memcpy((char*)edec->file, edf->file, strlen(edf->file) + 1);
+
+ edf->fd = -1;
+ edf->active = 0;
+
+ return edec;
+}
+
+static int
+_ecore_download_url_complete_cb(void *data, int type, void *event)
+{
+ Ecore_Download_Event_Cancel *edec;
+ Ecore_Con_Event_Url_Complete *e;
+ Ecore_Download_File *edf;
+
+ e = event;
+
+ edf = ecore_con_url_data_get(e->url_con);
+
+ if (!ECORE_MAGIC_CHECK(edf, ECORE_MAGIC_DOWNLOAD_FILES)) return 1;
+
+ /* Restart download. */
+ if (e->status == 304)
+ {
+ unlink(edf->temp);
+ if (edf->fd >= 0)
+ close(edf->fd);
+
+ ecore_event_add(ECORE_DOWNLOAD_EVENT_COMPLETE, _ecore_download_event_complete_new(edf, e->status), NULL, NULL);
+
+ return 0;
+ }
+
+ /* File download ok. */
+ if (e->status == 200)
+ {
+ /* File update. */
+ if (edf->updated != 0)
+ {
+ unlink(edf->file);
+ if (rename(edf->temp, edf->file) != 0)
+ e->status = -200;
+ }
+ else
+ {
+ unlink(edf->temp);
+ }
+
+ if (edf->fd >= 0)
+ close(edf->fd);
+
+ ecore_event_add(ECORE_DOWNLOAD_EVENT_COMPLETE, _ecore_download_event_complete_new(edf, e->status), NULL, NULL);
+
+ return 0;
+ }
+
+ if (edf->fd != -1)
+ {
+ close(edf->fd);
+ edf->fd = -1;
+ unlink(edf->temp);
+ }
+
+ snprintf((char*)edf->temp,
+ strlen(edf->dir->temp_directory) + strlen(edf->dir->prefix) + 5,
+ "%s/%sXXXXXX",
+ edf->dir->temp_directory,
+ edf->dir->prefix);
+ edf->fd = mkstemp((char*)edf->temp);
+
+ edf->active = 0;
+
+ edec = calloc(1, sizeof(Ecore_Download_Event_Cancel) + strlen(edf->url) + 1);
+ if (edec == NULL) return 0;
+
+ edec->edf = edf;
+ edec->status = e->status;
+ edec->url = (const char*) ((Ecore_Download_Event_Cancel*) (edec + 1));
+ memcpy((char*)edec->url, edf->url, strlen(edf->url) + 1);
+
+ ecore_event_add(ECORE_DOWNLOAD_EVENT_CANCEL, edec, NULL, NULL);
+
+ return 0;
+}
+
+static int
+_ecore_download_url_progress_download_cb(void *data, int type, void *event)
+{
+ Ecore_Con_Event_Url_Progress_Download *e;
+ Ecore_Download_Event_Progress *edep;
+ Ecore_Download_File *edf;
+
+ e = event;
+ edf = ecore_con_url_data_get(e->url_con);
+
+ if (!ECORE_MAGIC_CHECK(edf, ECORE_MAGIC_DOWNLOAD_FILES)) return 0;
+
+ edep = calloc(1, sizeof(Ecore_Download_Event_Progress) + strlen(edf->url) + 1);
+ if (edep == NULL) return 0;
+
+ edep->edf = edf;
+ edep->total = e->total;
+ edep->now = e->now;
+ edep->url = (const char*) ((Ecore_Download_Event_Progress*) (edep + 1));
+ memcpy((char*)edep->url, edf->url, strlen(edf->url) + 1);
+
+ ecore_event_add(ECORE_DOWNLOAD_EVENT_PROGRESS, edep, NULL, NULL);
+
+ return 1;
+}
+
+int
+ecore_download_init(void)
+{
+ ecore_init();
+ ecore_con_url_init();
+
+ if (!ECORE_DOWNLOAD_EVENT_COMPLETE)
+ {
+ ECORE_DOWNLOAD_EVENT_PROGRESS = ecore_event_type_new();
+ ECORE_DOWNLOAD_EVENT_COMPLETE = ecore_event_type_new();
+ ECORE_DOWNLOAD_EVENT_CANCEL = ecore_event_type_new();
+
+ ed_url_data = ecore_event_handler_add(ECORE_CON_EVENT_URL_DATA, _ecore_download_url_data_cb, NULL);
+ ed_url_complete = ecore_event_handler_add(ECORE_CON_EVENT_URL_COMPLETE, _ecore_download_url_complete_cb, NULL);
+ ed_url_progress_download = ecore_event_handler_add(ECORE_CON_EVENT_URL_PROGRESS_DOWNLOAD, _ecore_download_url_progress_download_cb, NULL);
+ }
+
+ return 1;
+}
+
+int
+ecore_download_shutdown(void)
+{
+ ecore_con_url_shutdown();
+ ecore_shutdown();
+
+ return 1;
+}
+
+static int
+_ecore_download_directory_cleanup(const char *temp, const char *prefix)
+{
+ char *todel = NULL;
+ DIR *dr;
+ struct dirent *dirent;
+
+ dr = opendir(temp);
+ if (dr == NULL)
+ return -1;
+
+ while ((dirent = readdir(dr)) != NULL)
+ {
+ if (strncmp(dirent->d_name, prefix, strlen(prefix)) == 0)
+ {
+ int length;
+
+ length = strlen(dirent->d_name) + strlen(temp) + 2;
+ todel = realloc(todel, sizeof(char) * length);
+
+ if (todel == NULL)
+ return -1;
+
+ snprintf((char*)todel, length, "%s/%s", temp, dirent->d_name);
+
+ unlink(todel);
+ }
+ }
+ IF_FREE(todel);
+
+ if (closedir(dr) != 0)
+ return -1;
+
+ return 0;
+}
+
+Ecore_Download_Dir*
+ecore_download_directory_new(const char *files, const char *temp, const char *prefix)
+{
+ Ecore_Download_Dir *edd;
+ struct stat st;
+
+ if (prefix == NULL)
+ return NULL;
+
+ if (stat(files, &st) != 0)
+ return NULL;
+
+ if (!S_ISDIR(st.st_mode))
+ return NULL;
+
+ if (stat(temp, &st) != 0)
+ return NULL;
+
+ if (!S_ISDIR(st.st_mode))
+ return NULL;
+
+ /* On crach some data could have survived, clean them all. */
+ if (_ecore_download_directory_cleanup(temp, prefix) != 0)
+ return NULL;
+
+ edd = calloc(1, sizeof(Ecore_Download_Dir) + strlen(files) + strlen(temp) + strlen(prefix) + 3);
+ if (edd == NULL)
+ return NULL;
+
+ edd->files_directory = (const char*) ((Ecore_Download_Dir*) (edd + 1));
+ edd->temp_directory = edd->files_directory + strlen(files) + 1;
+ edd->prefix = edd->temp_directory + strlen(temp) + 1;
+
+ memcpy((char*)edd->files_directory, files, strlen(files) + 1);
+ memcpy((char*)edd->temp_directory, temp, strlen(temp) + 1);
+ memcpy((char*)edd->prefix, prefix, strlen(prefix) + 1);
+
+ edd->download = ecore_list_new();
+
+ ECORE_MAGIC_SET(edd, ECORE_MAGIC_DOWNLOAD_DIR);
+ return edd;
+}
+
+static void
+_ecore_destroy_cb(void *value, void *user_data __UNUSED__)
+{
+ ecore_download_file_destroy(value);
+}
+
+void
+ecore_download_directory_destroy(Ecore_Download_Dir* dir)
+{
+ if (!ECORE_MAGIC_CHECK(dir, ECORE_MAGIC_DOWNLOAD_DIR))
+ {
+ ECORE_MAGIC_FAIL(dir, ECORE_MAGIC_DOWNLOAD_DIR, "ecore_download_directory_destroy");
+ return ;
+ }
+
+ ecore_list_for_each(dir->download, _ecore_destroy_cb, NULL);
+
+ /* Just in case, clean temp dir. */
+ _ecore_download_directory_cleanup(dir->temp_directory, dir->prefix);
+
+ ECORE_MAGIC_SET(dir, ECORE_MAGIC_NONE);
+ free(dir);
+}
+
+void*
+ecore_download_directory_data_set(Ecore_Download_Dir *dir, const void *data)
+{
+ void *old;
+
+ if (!ECORE_MAGIC_CHECK(dir, ECORE_MAGIC_DOWNLOAD_DIR))
+ {
+ ECORE_MAGIC_FAIL(dir, ECORE_MAGIC_DOWNLOAD_DIR, "ecore_download_directory_data_set");
+ return NULL;
+ }
+
+ old = (void*) dir->data;
+ dir->data = data;
+
+ return old;
+}
+
+void*
+ecore_download_directory_data_get(Ecore_Download_Dir *dir)
+{
+ if (!ECORE_MAGIC_CHECK(dir, ECORE_MAGIC_DOWNLOAD_DIR))
+ {
+ ECORE_MAGIC_FAIL(dir, ECORE_MAGIC_DOWNLOAD_DIR, "ecore_download_directory_data_get");
+ return NULL;
+ }
+
+ return (void*) dir->data;
+}
+
+Ecore_Download_File*
+ecore_download_file_add(Ecore_Download_Dir* dir, const char* file, const char* url)
+{
+ Ecore_Download_File *edf = NULL;
+ Ecore_Con_Url *ecu;
+ int length_temp;
+ int length_file;
+ struct stat st;
+
+ if (!ECORE_MAGIC_CHECK(dir, ECORE_MAGIC_DOWNLOAD_DIR))
+ {
+ ECORE_MAGIC_FAIL(dir, ECORE_MAGIC_DOWNLOAD_DIR, "ecore_download_file_add");
+ return NULL;
+ }
+
+ ecu = ecore_con_url_new(url);
+ if (ecu == NULL) goto on_error;
+
+ length_temp = strlen(dir->temp_directory) + strlen(dir->prefix) + 8;
+ length_file = strlen(dir->files_directory) + strlen(file) + 2;
+ edf = calloc(1, sizeof (Ecore_Download_File)
+ + length_file
+ + strlen(url) + 1
+ + length_temp);
+ if (edf == NULL) goto on_error;
+
+ edf->url_con = ecu;
+ edf->dir = dir;
+ edf->file = (const char*) ((Ecore_Download_File*)(edf + 1));
+ edf->url = edf->file + length_file + 1;
+ edf->temp = edf->url + strlen(url);
+
+ memcpy((char*)edf->file, file, strlen(file) + 1);
+ memcpy((char*)edf->url, url, strlen(url) + 1);
+
+ snprintf((char*)edf->temp, length_temp, "%s/%sXXXXXX", dir->temp_directory, dir->prefix);
+ edf->fd = mkstemp((char*)edf->temp);
+ if (edf->fd < 0) goto on_error;
+
+ snprintf((char*)edf->file, length_file, "%s/%s", dir->files_directory, file);
+ if (stat(edf->file, &st) == 0)
+ edf->tm = st.st_mtime;
+
+ ecore_list_append(dir->download, edf);
+ ecore_con_url_data_set(ecu, edf);
+
+ ECORE_MAGIC_SET(edf, ECORE_MAGIC_DOWNLOAD_FILES);
+ return edf;
+
+ on_error:
+ if (ecu != NULL) ecore_con_url_destroy(ecu);
+ if (edf != NULL) free(edf);
+ return NULL;
+}
+
+int
+ecore_download_file_start(Ecore_Download_File* edf)
+{
+ if (!ECORE_MAGIC_CHECK(edf, ECORE_MAGIC_DOWNLOAD_FILES))
+ {
+ ECORE_MAGIC_FAIL(edf, ECORE_MAGIC_DOWNLOAD_FILES, "ecore_download_file_start");
+ return -1;
+ }
+
+ if (edf->active)
+ return 0;
+
+ edf->active = 1;
+
+ if (edf->tm != 0)
+ ecore_con_url_time(edf->url_con, ECORE_CON_URL_TIME_IFMODSINCE, edf->tm);
+
+ return ecore_con_url_send(edf->url_con, NULL, 0, NULL);
+}
+
+int
+ecore_download_file_stop(Ecore_Download_File* edf)
+{
+ if (!ECORE_MAGIC_CHECK(edf, ECORE_MAGIC_DOWNLOAD_FILES))
+ {
+ ECORE_MAGIC_FAIL(edf, ECORE_MAGIC_DOWNLOAD_FILES, "ecore_download_file_stop");
+ return -1;
+ }
+
+ if (!edf->active) return 0;
+
+ ecore_con_url_destroy(edf->url_con);
+ edf->url_con = ecore_con_url_new(edf->url);
+
+ if (edf->fd != -1)
+ {
+ close(edf->fd);
+ unlink(edf->temp);
+ }
+
+ snprintf((char*)edf->temp,
+ strlen(edf->dir->temp_directory) + strlen(edf->dir->prefix) + 5,
+ "%s/%sXXXXXX",
+ edf->dir->temp_directory,
+ edf->dir->prefix);
+ edf->fd = mkstemp((char*)edf->temp);
+ if (edf->fd < 0) goto on_error;
+
+ edf->active = 0;
+
+ return 0;
+
+ on_error:
+ /* FIXME: edf is now completely useless. */
+ return -1;
+}
+
+void
+ecore_download_file_destroy(Ecore_Download_File* edf)
+{
+ Ecore_Download_File* lookup;
+
+ if (!ECORE_MAGIC_CHECK(edf, ECORE_MAGIC_DOWNLOAD_FILES))
+ {
+ ECORE_MAGIC_FAIL(edf, ECORE_MAGIC_DOWNLOAD_FILES, "ecore_download_file_destroy");
+ return ;
+ }
+
+ ecore_con_url_destroy(edf->url_con);
+ edf->url_con = NULL;
+
+ if (edf->fd != -1)
+ {
+ close(edf->fd);
+ unlink(edf->temp);
+ }
+
+ for (lookup = ecore_list_first_goto(edf->dir->download);
+ lookup != NULL && lookup != edf;
+ lookup = ecore_list_next(edf->dir->download))
+ ;
+
+ if (lookup == edf)
+ ecore_list_remove(edf->dir->download);
+
+ ECORE_MAGIC_SET(edf, ECORE_MAGIC_NONE);
+}
+
+void*
+ecore_download_file_data_set(Ecore_Download_File *edf, const void *data)
+{
+ void* old;
+
+ if (!ECORE_MAGIC_CHECK(edf, ECORE_MAGIC_DOWNLOAD_FILES))
+ {
+ ECORE_MAGIC_FAIL(edf, ECORE_MAGIC_DOWNLOAD_FILES, "ecore_download_file_data_set");
+ return NULL;
+ }
+
+ old = (void*) edf->data;
+ edf->data = data;
+
+ return old;
+}
+
+void*
+ecore_download_file_data_get(Ecore_Download_File *edf)
+{
+ if (!ECORE_MAGIC_CHECK(edf, ECORE_MAGIC_DOWNLOAD_FILES))
+ {
+ ECORE_MAGIC_FAIL(edf, ECORE_MAGIC_DOWNLOAD_FILES, "ecore_download_file_data_get");
+ return NULL;
+ }
+
+ return (void*) edf->data;
+}
diff -Nrau -X exclude.cvs e17-clean/libs/ecore/src/lib/ecore_download/Ecore_Download.h e17-dev/libs/ecore/src/lib/ecore_download/Ecore_Download.h
--- e17-clean/libs/ecore/src/lib/ecore_download/Ecore_Download.h 1970-01-01 01:00:00.000000000 +0100
+++ e17-dev/libs/ecore/src/lib/ecore_download/Ecore_Download.h 2007-09-13 16:08:01.000000000 +0200
@@ -0,0 +1,60 @@
+#ifndef ECORE_DOWNLOAD_H__
+# define ECORE_DOWNLOAD_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ typedef struct _Ecore_Download_Event_Complete Ecore_Download_Event_Complete;
+ typedef struct _Ecore_Download_Event_Cancel Ecore_Download_Event_Cancel;
+ typedef struct _Ecore_Download_Event_Progress Ecore_Download_Event_Progress;
+
+ typedef struct _Ecore_Download_File Ecore_Download_File;
+ typedef struct _Ecore_Download_Dir Ecore_Download_Dir;
+
+ struct _Ecore_Download_Event_Complete
+ {
+ Ecore_Download_File *edf;
+ const char *file;
+ int status;
+ };
+
+ struct _Ecore_Download_Event_Cancel
+ {
+ Ecore_Download_File *edf;
+ const char *url;
+ int status;
+ };
+
+ struct _Ecore_Download_Event_Progress
+ {
+ Ecore_Download_File *edf;
+ const char *url;
+ double total;
+ double now;
+ };
+
+ EAPI extern int ECORE_DOWNLOAD_EVENT_CANCEL;
+ EAPI extern int ECORE_DOWNLOAD_EVENT_COMPLETE;
+ EAPI extern int ECORE_DOWNLOAD_EVENT_PROGRESS;
+
+ EAPI int ecore_download_init(void);
+ EAPI int ecore_download_shutdown(void);
+
+ EAPI Ecore_Download_Dir *ecore_download_directory_new(const char *files, const char *temp, const char *prefix);
+ EAPI void ecore_download_directory_destroy(Ecore_Download_Dir *dir);
+ EAPI void *ecore_download_directory_data_set(Ecore_Download_Dir *dir, const void *data);
+ EAPI void *ecore_download_directory_data_get(Ecore_Download_Dir *dir);
+
+ EAPI Ecore_Download_File *ecore_download_file_add(Ecore_Download_Dir *dir, const char *file, const char *url);
+ EAPI int ecore_download_file_start(Ecore_Download_File *edf);
+ EAPI int ecore_download_file_stop(Ecore_Download_File *edf);
+ EAPI void ecore_download_file_destroy(Ecore_Download_File *edf);
+ EAPI void *ecore_download_file_data_set(Ecore_Download_File *edf, const void *data);
+ EAPI void *ecore_download_file_data_get(Ecore_Download_File *edf);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ECORE_DOWNLOAD_H__ */
diff -Nrau -X exclude.cvs e17-clean/libs/ecore/src/lib/ecore_download/Makefile.am e17-dev/libs/ecore/src/lib/ecore_download/Makefile.am
--- e17-clean/libs/ecore/src/lib/ecore_download/Makefile.am 1970-01-01 01:00:00.000000000 +0100
+++ e17-dev/libs/ecore/src/lib/ecore_download/Makefile.am 2007-08-10 14:04:20.000000000 +0200
@@ -0,0 +1,35 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+INCLUDES = \
+-I$(top_builddir)/src/lib/ecore \
+-I$(top_builddir)/src/lib/ecore_con \
+-I$(top_builddir)/src/lib/ecore_download \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_srcdir)/src/lib/ecore_con \
+-I$(top_srcdir)/src/lib/ecore_download
+
+libecore_download_la_LDFLAGS = -version-info 1:0:0 \
+-L$(top_builddir)/src/lib/ecore/.libs
+
+if BUILD_ECORE_DOWNLOAD
+
+lib_LTLIBRARIES = libecore_download.la
+include_HEADERS = \
+Ecore_Download.h
+
+libecore_download_la_SOURCES = \
+ecore_download.c
+
+libecore_download_la_LIBADD = \
+$(top_builddir)/src/lib/ecore/libecore.la \
+$(top_builddir)/src/lib/ecore_con/libecore_con.la
+
+libecore_download_la_DEPENDENCIES = \
+$(top_builddir)/src/lib/ecore/libecore.la \
+$(top_builddir)/src/lib/ecore_con/libecore_con.la
+
+endif
+
+EXTRA_DIST = \
+ecore_download.c \
+Ecore_Download.h
diff -Nrau -X exclude.cvs e17-clean/libs/ecore/src/lib/Makefile.am e17-dev/libs/ecore/src/lib/Makefile.am
--- e17-clean/libs/ecore/src/lib/Makefile.am 2007-07-16 20:17:59.000000000 +0200
+++ e17-dev/libs/ecore/src/lib/Makefile.am 2007-08-10 13:45:50.000000000 +0200
@@ -12,4 +12,5 @@
ecore_evas \
ecore_config \
ecore_file \
-ecore_desktop
+ecore_desktop \
+ecore_download
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel