9 # include "Ecore_Con.h"
12 #include "ecore_file_private.h"
14 #ifdef BUILD_ECORE_CON
16 #define ECORE_MAGIC_FILE_DOWNLOAD_JOB 0xf7427cb8
18 struct _Ecore_File_Download_Job
22 Ecore_Con_Url *url_con;
27 void (*completion_cb)(void *data, const char *file, int status);
29 int (*progress_cb) (void *data, const char *file,
30 long int dltotal, long int dlnow,
31 long int ultotal, long int ulnow);
35 Ecore_File_Download_Job *_ecore_file_download_curl(const char *url, const char *dst,
36 void (*completion_cb)(void *data, const char *file, int status),
37 int (*progress_cb)(void *data, const char *file, long int dltotal, long int dlnow, long int ultotal, long int ulnow),
40 static Eina_Bool _ecore_file_download_url_complete_cb(void *data, int type, void *event);
41 static Eina_Bool _ecore_file_download_url_progress_cb(void *data, int type, void *event);
44 static Ecore_Event_Handler *_url_complete_handler = NULL;
45 static Ecore_Event_Handler *_url_progress_download = NULL;
46 static Eina_List *_job_list;
48 #endif /* BUILD_ECORE_CON */
51 ecore_file_download_init(void)
53 #ifdef BUILD_ECORE_CON
54 if (!ecore_con_url_init())
58 _url_complete_handler = ecore_event_handler_add(ECORE_CON_EVENT_URL_COMPLETE, _ecore_file_download_url_complete_cb, NULL);
59 _url_progress_download = ecore_event_handler_add(ECORE_CON_EVENT_URL_PROGRESS, _ecore_file_download_url_progress_cb, NULL);
62 #endif /* BUILD_ECORE_CON */
68 ecore_file_download_shutdown(void)
70 #ifdef BUILD_ECORE_CON
71 if (_url_complete_handler)
72 ecore_event_handler_del(_url_complete_handler);
73 if (_url_progress_download)
74 ecore_event_handler_del(_url_progress_download);
75 _url_complete_handler = NULL;
76 _url_progress_download = NULL;
77 ecore_file_download_abort_all();
79 ecore_con_url_shutdown();
80 #endif /* BUILD_ECORE_CON */
84 ecore_file_download_abort_all(void)
86 #ifdef BUILD_ECORE_CON
87 Ecore_File_Download_Job *job;
89 EINA_LIST_FREE(_job_list, job)
90 ecore_file_download_abort(job);
91 #endif /* BUILD_ECORE_CON */
95 * Download @p url to the given @p dst
96 * @param url The complete url to download
97 * @param dst The local file to save the downloaded to
98 * @param completion_cb A callback called on download complete
99 * @param progress_cb A callback called during the download operation
100 * @param data User data passed to both callbacks
101 * @param job_ret If the protocol in use is http or ftp, this parameter will be
102 * filled with the job. Then you can use ecore_file_download_abort() to cancel it.
104 * @return 1 if the download start or 0 on failure
106 * You must provide the full url, including 'http://', 'ftp://' or 'file://'.\n
107 * If @p dst already exist it will not be overwritten and the function will fail.\n
108 * Ecore must be compiled with CURL to download using http and ftp protocols.\n
109 * The @p status param in the @p completion_cb() will be 0 if the download goes well or
110 * 1 in case of failure.
113 ecore_file_download(const char *url, const char *dst,
114 void (*completion_cb)(void *data, const char *file, int status),
115 int (*progress_cb)(void *data, const char *file, long int dltotal, long int dlnow, long int ultotal, long int ulnow),
116 void *data, Ecore_File_Download_Job **job_ret)
118 #ifdef BUILD_ECORE_CON
119 char *dir = ecore_file_dir_get(dst);
121 if (!ecore_file_is_dir(dir))
127 if (ecore_file_exists(dst)) return 0;
129 /* FIXME: Add handlers for http and ftp! */
130 if (!strncmp(url, "file://", 7))
132 /* FIXME: Maybe fork? Might take a while to copy.
138 url = strchr(url, '/');
139 return ecore_file_cp(url, dst);
142 else if ((!strncmp(url, "http://", 7)) ||
143 (!strncmp(url, "ftp://", 6)))
146 Ecore_File_Download_Job *job;
148 job = _ecore_file_download_curl(url, dst, completion_cb, progress_cb, data);
149 if(job_ret) *job_ret = job;
158 completion_cb = NULL;
162 #endif /* BUILD_ECORE_CON */
166 * Check if the given protocol is available
167 * @param protocol The protocol to check
168 * @return 1 if protocol is handled or 0 if not
170 * @p protocol can be 'http://', 'ftp://' or 'file://'.\n
171 * Ecore must be compiled with CURL to handle http and ftp protocols.
174 ecore_file_download_protocol_available(const char *protocol)
176 #ifdef BUILD_ECORE_CON
177 if (!strncmp(protocol, "file://", 7)) return 1;
179 else if (!strncmp(protocol, "http://", 7)) return 1;
180 else if (!strncmp(protocol, "ftp://", 6)) return 1;
182 #endif /* BUILD_ECORE_CON */
187 #ifdef BUILD_ECORE_CON
191 _ecore_file_download_url_compare_job(const void *data1, const void *data2)
193 const Ecore_File_Download_Job *job = data1;
194 const Ecore_Con_Url *url = data2;
196 if (job->url_con == url) return 0;
201 _ecore_file_download_url_complete_cb(void *data __UNUSED__, int type __UNUSED__, void *event)
203 Ecore_Con_Event_Url_Complete *ev = event;
204 Ecore_File_Download_Job *job;
206 job = eina_list_search_unsorted(_job_list, _ecore_file_download_url_compare_job, ev->url_con);
207 if (!ECORE_MAGIC_CHECK(job, ECORE_MAGIC_FILE_DOWNLOAD_JOB)) return ECORE_CALLBACK_PASS_ON;
209 if (job->completion_cb)
210 job->completion_cb(ecore_con_url_data_get(job->url_con), job->dst, !ev->status);
212 _job_list = eina_list_remove(_job_list, job);
217 return ECORE_CALLBACK_DONE;
221 _ecore_file_download_url_progress_cb(void *data __UNUSED__, int type __UNUSED__, void *event)
223 /* this reports the downloads progress. if we return 0, then download
224 * continues, if we return anything else, then the download stops */
225 Ecore_Con_Event_Url_Progress *ev = event;
226 Ecore_File_Download_Job *job;
228 job = eina_list_search_unsorted(_job_list, _ecore_file_download_url_compare_job, ev->url_con);
229 if (!ECORE_MAGIC_CHECK(job, ECORE_MAGIC_FILE_DOWNLOAD_JOB)) return ECORE_CALLBACK_PASS_ON;
231 if (job->progress_cb)
232 if (job->progress_cb(ecore_con_url_data_get(job->url_con), job->dst,
233 (long int) ev->down.total, (long int) ev->down.now,
234 (long int) ev->up.total, (long int) ev->up.now) != 0)
236 _job_list = eina_list_remove(_job_list, job);
241 return ECORE_CALLBACK_PASS_ON;
244 return ECORE_CALLBACK_DONE;
247 Ecore_File_Download_Job *
248 _ecore_file_download_curl(const char *url, const char *dst,
249 void (*completion_cb)(void *data, const char *file,
251 int (*progress_cb)(void *data, const char *file,
252 long int dltotal, long int dlnow,
253 long int ultotal, long int ulnow),
256 Ecore_File_Download_Job *job;
258 job = calloc(1, sizeof(Ecore_File_Download_Job));
259 if (!job) return NULL;
261 ECORE_MAGIC_SET(job, ECORE_MAGIC_FILE_DOWNLOAD_JOB);
263 job->file = fopen(dst, "wb");
269 job->url_con = ecore_con_url_new(url);
277 ecore_con_url_fd_set(job->url_con, fileno(job->file));
278 ecore_con_url_data_set(job->url_con, data);
280 job->dst = strdup(dst);
282 job->completion_cb = completion_cb;
283 job->progress_cb = progress_cb;
284 _job_list = eina_list_append(_job_list, job);
286 ecore_con_url_send(job->url_con, NULL, 0, NULL);
294 * Abort the given download job and call the @p completion_cb function with a
295 * @status of 1 (error)
296 * @param job The download job to abort
300 ecore_file_download_abort(Ecore_File_Download_Job *job)
302 #ifdef BUILD_ECORE_CON
303 if (job->completion_cb)
304 job->completion_cb(ecore_con_url_data_get(job->url_con), job->dst, 1);
306 ecore_con_url_destroy(job->url_con);
308 _job_list = eina_list_remove(_job_list, job);
312 #endif /* BUILD_ECORE_CON */