diff --git a/src/examples/ecore/efl_net_dialer_http_example.c b/src/examples/ecore/efl_net_dialer_http_example.c index b882a0d8f6..0ccc36ba9d 100644 --- a/src/examples/ecore/efl_net_dialer_http_example.c +++ b/src/examples/ecore/efl_net_dialer_http_example.c @@ -184,6 +184,7 @@ static const Ecore_Getopt options = { ECORE_GETOPT_STORE_DOUBLE('t', "connect-timeout", "timeout in seconds for the connection phase"), ECORE_GETOPT_APPEND('H', "header", "Add custom headers. Format must be 'Key: Value'", ECORE_GETOPT_TYPE_STR), ECORE_GETOPT_STORE_STR('X', "proxy", "Set a specific proxy for the connection"), + ECORE_GETOPT_STORE_STR('c', "cookie-jar", "Set the cookie-jar file to read/save cookies from. Empty means an in-memory cookie-jar"), ECORE_GETOPT_STORE_STR('i', "input-file", "Input file to use when uploading"), ECORE_GETOPT_VERSION('V', "version"), ECORE_GETOPT_COPYRIGHT('C', "copyright"), @@ -211,6 +212,7 @@ main(int argc, char **argv) char *output_fname = NULL; char *input_fname = NULL; char *proxy = NULL; + char *cookie_jar = NULL; Eina_Bool quit_option = EINA_FALSE; Eina_Bool authentication_restricted = EINA_FALSE; Eina_Bool allow_redirects = EINA_TRUE; @@ -228,6 +230,7 @@ main(int argc, char **argv) ECORE_GETOPT_VALUE_DOUBLE(timeout_dial), ECORE_GETOPT_VALUE_LIST(headers), ECORE_GETOPT_VALUE_STR(proxy), + ECORE_GETOPT_VALUE_STR(cookie_jar), ECORE_GETOPT_VALUE_STR(input_fname), /* standard block to provide version, copyright, license and help */ @@ -309,6 +312,9 @@ main(int argc, char **argv) http_version = _parse_http_version(http_version_str); authentication_method = _parse_authentication_method(authentication_method_str); + if (cookie_jar && cookie_jar[0] == ' ') + cookie_jar = ""; + dialer = efl_add(EFL_NET_DIALER_HTTP_CLASS, loop, efl_name_set(efl_self, "dialer"), efl_net_dialer_http_method_set(efl_self, method), @@ -316,6 +322,7 @@ main(int argc, char **argv) efl_net_dialer_http_version_set(efl_self, http_version), efl_net_dialer_http_authentication_set(efl_self, username, password, authentication_method, authentication_restricted), efl_net_dialer_http_allow_redirects_set(efl_self, allow_redirects), + efl_net_dialer_http_cookie_jar_set(efl_self, cookie_jar), efl_net_dialer_proxy_set(efl_self, proxy), efl_net_dialer_timeout_dial_set(efl_self, timeout_dial), efl_event_callback_array_add(efl_self, dialer_cbs(), NULL)); @@ -371,6 +378,7 @@ main(int argc, char **argv) "INFO: - primary_mode=%d\n" "INFO: - version=%d\n" "INFO: - allow_redirects=%d\n" + "INFO: - cookie_jar=%s\n" "INFO: - timeout_dial=%fs\n" "INFO: - proxy=%s\n" "INFO: - request headers:\n", @@ -379,6 +387,7 @@ main(int argc, char **argv) efl_net_dialer_http_primary_mode_get(dialer), efl_net_dialer_http_version_get(dialer), efl_net_dialer_http_allow_redirects_get(dialer), + efl_net_dialer_http_cookie_jar_get(dialer), efl_net_dialer_timeout_dial_get(dialer), efl_net_dialer_proxy_get(dialer)); diff --git a/src/lib/ecore_con/efl_net_dialer_http.c b/src/lib/ecore_con/efl_net_dialer_http.c index 22b9b13992..55b008b0f9 100644 --- a/src/lib/ecore_con/efl_net_dialer_http.c +++ b/src/lib/ecore_con/efl_net_dialer_http.c @@ -175,6 +175,7 @@ typedef struct Ecore_Fd_Handler *fdhandler; Eina_Stringshare *address_dial; Eina_Stringshare *proxy; + Eina_Stringshare *cookie_jar; Eina_Stringshare *address_local; Eina_Stringshare *address_remote; Eina_Stringshare *method; @@ -992,6 +993,7 @@ _efl_net_dialer_http_efl_object_destructor(Eo *o, Efl_Net_Dialer_Http_Data *pd) eina_stringshare_replace(&pd->address_dial, NULL); eina_stringshare_replace(&pd->proxy, NULL); + eina_stringshare_replace(&pd->cookie_jar, NULL); eina_stringshare_replace(&pd->address_local, NULL); eina_stringshare_replace(&pd->address_remote, NULL); eina_stringshare_replace(&pd->method, NULL); @@ -1025,8 +1027,6 @@ _efl_net_dialer_http_efl_net_dialer_dial(Eo *o, Efl_Net_Dialer_Http_Data *pd, co return EINVAL; } - // TODO cookies - // TODO: move this to be per-loop once multiple mainloops are supported // this would need to attach something to the loop cm = &_cm_global; @@ -1713,4 +1713,54 @@ _efl_net_dialer_http_progress_upload_get(Eo *o EINA_UNUSED, Efl_Net_Dialer_Http_ if (total) *total = pd->progress.upload.total; } +EOLIAN static void +_efl_net_dialer_http_cookie_jar_set(Eo *o EINA_UNUSED, Efl_Net_Dialer_Http_Data *pd, const char *path) +{ + CURLcode r; + + if (pd->cookie_jar) + { + r = curl_easy_setopt(pd->easy, CURLOPT_COOKIELIST, "FLUSH"); + if (r != CURLE_OK) + ERR("dialer=%p could not flush cookie_jar to '%s': %s", + o, pd->cookie_jar, curl_easy_strerror(r)); + + r = curl_easy_setopt(pd->easy, CURLOPT_COOKIELIST, "ALL"); + if (r != CURLE_OK) + ERR("dialer=%p could not empty cookie_jar: %s", + o, curl_easy_strerror(r)); + + r = curl_easy_setopt(pd->easy, CURLOPT_COOKIEFILE, NULL); + if (r != CURLE_OK) + ERR("dialer=%p could not unset cookie_jar (read): %s", + o, curl_easy_strerror(r)); + + r = curl_easy_setopt(pd->easy, CURLOPT_COOKIEJAR, NULL); + if (r != CURLE_OK) + ERR("dialer=%p could not unset cookie_jar (write): %s", + o, curl_easy_strerror(r)); + } + + if (!path) goto end; + + r = curl_easy_setopt(pd->easy, CURLOPT_COOKIEFILE, path); + if (r != CURLE_OK) + ERR("dialer=%p could not set cookie_jar (read) to '%s': %s", + o, path, curl_easy_strerror(r)); + + r = curl_easy_setopt(pd->easy, CURLOPT_COOKIEJAR, path); + if (r != CURLE_OK) + ERR("dialer=%p could not set cookie_jar (write) to '%s': %s", + o, path, curl_easy_strerror(r)); + + end: + eina_stringshare_replace(&pd->cookie_jar, path); +} + +EOLIAN static const char * +_efl_net_dialer_http_cookie_jar_get(Eo *o EINA_UNUSED, Efl_Net_Dialer_Http_Data *pd) +{ + return pd->cookie_jar; +} + #include "efl_net_dialer_http.eo.c" diff --git a/src/lib/ecore_con/efl_net_dialer_http.eo b/src/lib/ecore_con/efl_net_dialer_http.eo index 0f2d945827..c0a20cf205 100644 --- a/src/lib/ecore_con/efl_net_dialer_http.eo +++ b/src/lib/ecore_con/efl_net_dialer_http.eo @@ -283,6 +283,39 @@ class Efl.Net.Dialer.Http (Efl.Loop_User, Efl.Net.Dialer, Efl.Io.Reader, Efl.Io. total: uint64 @optional; [[0 if unknown]] } } + + @property cookie_jar { + [[This property sets the filename where to read and write cookies. + + By setting a file to load and persist cookies to, the + internal cookie system will be activated, automatically + handling HTTP headers such as 'Set-cookie:' and sending + the appropriate cookies for a server. + + If a new, empty session is to be used, start with an + empty or non-existent file such as created with + mkstemp() or tmpfile(). An alternative is to use an + empty string ("") to keep it in memory. + + If it is desired to start from a pre-existent cookie jar + but do not want to modify that, first copy that file and + then pass the new, temporary file. + + Likewise, if it's desired to fill some cookies to the + system, create a cookie jar and pass its path to this + property. + + \@note that whenever this property is set, even if to the + same value, it will flush all cookies to the previously + set file, then erase all known cookies, then use the new + file (if any). + ]] + get { } + set { } + values { + path: string; + } + } } events {