Rev 4821 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4821 | Rev 5043 | ||
---|---|---|---|
Line 26... | Line 26... | ||
26 | * |
26 | * |
27 | * The CURL handles are cached in the curl_handle_ring. There are at most |
27 | * The CURL handles are cached in the curl_handle_ring. There are at most |
28 | * ::max_cached_fetch_handles in this ring. |
28 | * ::max_cached_fetch_handles in this ring. |
29 | */ |
29 | */ |
Line 30... | Line 30... | ||
30 | 30 | ||
- | 31 | /* |
|
- | 32 | TODO: |
|
31 | 33 | Have a double linked list containing all the handles on work that needs to be done |
|
- | 34 | Inside fetch_poll_curl, do work on it. |
|
- | 35 | Let the overall structure remain intact |
|
Line 32... | Line 36... | ||
32 | #include "http.c" |
36 | */ |
33 | 37 | ||
34 | #include |
38 | #include |
35 | #include |
39 | #include |
- | 40 | #include |
|
36 | #include |
41 | #include |
37 | #include |
42 | #include |
38 | #include |
43 | #include |
39 | #include |
44 | #include |
Line 40... | Line 45... | ||
40 | #include |
45 | #include |
Line 41... | Line 46... | ||
41 | #include |
46 | #include |
42 | 47 | ||
43 | #include |
48 | #include |
44 | 49 | ||
45 | #include "utils/config.h" |
50 | #include "utils/config.h" |
46 | //#include |
51 | /* #include |
47 | #include "content/fetch.h" |
52 | #include "content/fetch.h" |
Line 60... | Line 65... | ||
60 | * poll on, until it has processed a bit of the handle. So we need schedules |
65 | * poll on, until it has processed a bit of the handle. So we need schedules |
61 | * in order to make this work. |
66 | * in order to make this work. |
62 | */ |
67 | */ |
63 | #include |
68 | #include |
Line -... | Line 69... | ||
- | 69 | ||
- | 70 | #include "http_msg.h" |
|
- | 71 | #include "http.h" |
|
- | 72 | ||
- | 73 | /********************************************************************** |
|
- | 74 | ********This section added for resolving compile errors***************/ |
|
- | 75 | #define CURL_ERROR_SIZE 100 |
|
- | 76 | /*Definitions for CURL EASY Codes*/ |
|
- | 77 | ||
- | 78 | #define CURLE_OK 0 |
|
- | 79 | #define CURLE_PARTIAL_FILE 18 |
|
- | 80 | #define CURLE_WRITE_ERROR 23 |
|
- | 81 | #define CURLE_SSL_CONNECT_ERROR 35 |
|
- | 82 | ||
- | 83 | /*Definitions for CURL MULTI Codes*/ |
|
- | 84 | ||
- | 85 | #define CURLM_OK 0 |
|
- | 86 | #define CURLM_CALL_MULTI_PERFORM -1 |
|
- | 87 | #define CURLM_FAILED 123123 |
|
- | 88 | /* KOSH stands for KolibriOS HTTP :) */ |
|
- | 89 | ||
- | 90 | int FLAG_HTTP11 = 1 << 0; |
|
- | 91 | int FLAG_GOT_HEADER = 1 << 1; |
|
- | 92 | int FLAG_GOT_ALL_DATA = 1 << 2; |
|
- | 93 | int FLAG_CONTENT_LENGTH = 1 << 3; |
|
- | 94 | int FLAG_CHUNKED = 1 << 4; |
|
- | 95 | int FLAG_CONNECTED = 1 << 5; |
|
- | 96 | ||
- | 97 | /* ERROR flags go into the upper word */ |
|
- | 98 | int FLAG_INVALID_HEADER = 1 << 16; |
|
- | 99 | int FLAG_NO_RAM = 1 << 17; |
|
- | 100 | int FLAG_SOCKET_ERROR = 1 << 18; |
|
- | 101 | int FLAG_TIMEOUT_ERROR = 1 << 19; |
|
- | 102 | int FLAG_TRANSFER_FAILED = 1 << 20; |
|
- | 103 | ||
- | 104 | ||
- | 105 | struct KOSHcode { |
|
- | 106 | long code; |
|
- | 107 | }; |
|
- | 108 | ||
- | 109 | struct KOSHMcode { |
|
- | 110 | long code; |
|
- | 111 | }; |
|
- | 112 | ||
- | 113 | struct KOSHMsg { |
|
- | 114 | char *msg; |
|
- | 115 | }; |
|
- | 116 | ||
- | 117 | typedef struct KOSHcode KOSHcode; |
|
- | 118 | typedef struct KOSHMcode KOSHMcode; |
|
- | 119 | struct kosh_infotype { |
|
- | 120 | int type; |
|
- | 121 | }; |
|
- | 122 | typedef struct kosh_infotype kosh_infotype; |
|
- | 123 | ||
- | 124 | struct curl_slist { |
|
- | 125 | char *data; |
|
- | 126 | struct curl_slist *next; |
|
- | 127 | }; |
|
- | 128 | ||
- | 129 | /**********************************************************************/ |
|
64 | 130 | ||
65 | /* uncomment this to use scheduler based calling |
131 | /* uncomment this to use scheduler based calling |
66 | #define FETCHER_CURLL_SCHEDULED 1 |
132 | #define FETCHER_CURLL_SCHEDULED 1 |
Line -... | Line 133... | ||
- | 133 | */ |
|
- | 134 | ||
- | 135 | /** SSL certificate info */ |
|
- | 136 | /* struct cert_info { */ |
|
- | 137 | /* X509 *cert; /\**< Pointer to certificate *\/ */ |
|
- | 138 | /* long err; /\**< OpenSSL error code *\/ */ |
|
- | 139 | /* }; */ |
|
- | 140 | ||
- | 141 | /** Information for a single fetch. */ |
|
- | 142 | struct curl_fetch_info { |
|
- | 143 | struct fetch *fetch_handle; /**< The fetch handle we're parented by. */ |
|
- | 144 | struct http_msg * curl_handle; /**< cURL handle if being fetched, or 0. */ |
|
- | 145 | bool had_headers; /**< Headers have been processed. */ |
|
- | 146 | bool abort; /**< Abort requested. */ |
|
- | 147 | bool stopped; /**< Download stopped on purpose. */ |
|
- | 148 | bool only_2xx; /**< Only HTTP 2xx responses acceptable. */ |
|
- | 149 | bool downgrade_tls; /**< Downgrade to TLS <= 1.0 */ |
|
- | 150 | nsurl *url; /**< URL of this fetch. */ |
|
- | 151 | lwc_string *host; /**< The hostname of this fetch. */ |
|
- | 152 | struct curl_slist *headers; /**< List of request headers. */ |
|
- | 153 | char *location; /**< Response Location header, or 0. */ |
|
- | 154 | unsigned long content_length; /**< Response Content-Length, or 0. */ |
|
- | 155 | char *cookie_string; /**< Cookie string for this fetch */ |
|
- | 156 | char *realm; /**< HTTP Auth Realm */ |
|
- | 157 | char *post_urlenc; /**< Url encoded POST string, or 0. */ |
|
- | 158 | long http_code; /**< HTTP result code from cURL. */ |
|
- | 159 | struct curl_httppost *post_multipart; /**< Multipart post data, or 0. */ |
|
- | 160 | /* #define MAX_CERTS 10 */ |
|
- | 161 | /* struct cert_info cert_data[MAX_CERTS]; /\**< HTTPS certificate data *\/ */ |
|
Line 67... | Line 162... | ||
67 | */ |
162 | unsigned int last_progress_update; /**< Time of last progress update */ |
68 | - | ||
69 | - | ||
70 | struct fetch_curl_context { |
163 | }; |
71 | struct fetch_curl_context *r_next, *r_prev; |
- | |
72 | 164 | ||
73 | struct fetch *fetchh; /**< Handle for this fetch */ |
- | |
Line 74... | Line 165... | ||
74 | 165 | struct cache_handle { |
|
75 | bool aborted; /**< Flag indicating fetch has been aborted */ |
166 | struct http_msg *handle; /**< The cached struct http_msg handle */ |
- | 167 | lwc_string *host; /**< The host for which this handle is cached */ |
|
Line -... | Line 168... | ||
- | 168 | ||
76 | bool locked; /**< Flag indicating entry is already entered */ |
169 | struct cache_handle *r_prev; /**< Previous cached handle in ring. */ |
- | 170 | struct cache_handle *r_next; /**< Next cached handle in ring. */ |
|
- | 171 | }; |
|
- | 172 | ||
77 | 173 | struct fetch_info_slist { |
|
Line 78... | Line -... | ||
78 | nsurl *url; /**< The full url the fetch refers to */ |
- | |
Line -... | Line 174... | ||
- | 174 | struct curl_fetch_info *fetch_info; /* this fetch_info contains the same handle as the struct */ |
|
Line -... | Line 175... | ||
- | 175 | struct http_msg *handle; |
|
- | 176 | bool fetch_curl_header_called; |
|
- | 177 | struct fetch_info_slist *next; |
|
- | 178 | }; |
|
- | 179 | ||
- | 180 | ||
- | 181 | struct fetch_info_slist *fetch_curl_multi; /**< Global cURL multi handle. */ |
|
- | 182 | ||
- | 183 | /** Curl handle with default options set; not used for transfers. */ |
|
79 | char *path; /**< The actual path to be used with open() */ |
184 | static struct http_msg *fetch_blank_curl; |
80 | 185 | static struct cache_handle *curl_handle_ring = 0; /**< Ring of cached handles */ |
|
81 | time_t file_etag; /**< Request etag for file (previous st.m_time) */ |
186 | static int curl_fetchers_registered = 0; |
82 | }; |
187 | static bool curl_with_openssl; |
83 | 188 | ||
84 | static struct fetch_curl_context *ring = NULL; |
189 | static char fetch_error_buffer[CURL_ERROR_SIZE]; /**< Error buffer for cURL. */ |
85 | 190 | static char fetch_proxy_userpwd[100]; /**< Proxy authentication details. */ |
|
86 | 191 | ||
87 | static bool fetch_curl_initialise(lwc_string *scheme); //here |
- | |
- | 192 | static bool fetch_curl_initialise(lwc_string *scheme); |
|
- | 193 | static void fetch_curl_finalise(lwc_string *scheme); |
|
- | 194 | static bool fetch_curl_can_fetch(const nsurl *url); |
|
- | 195 | static void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url, |
|
- | 196 | bool only_2xx, bool downgrade_tls, const char *post_urlenc, |
|
- | 197 | const struct fetch_multipart_data *post_multipart, |
|
- | 198 | const char **headers); |
|
88 | static void fetch_curl_finalise(lwc_string *scheme); //here |
199 | static bool fetch_curl_start(void *vfetch); |
- | 200 | static bool fetch_curl_initiate_fetch(struct curl_fetch_info *fetch, |
|
89 | static bool fetch_curl_can_fetch(const nsurl *url); //here |
201 | struct http_msg *handle); |
90 | static void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url, |
202 | static struct http_msg *fetch_curl_get_handle(lwc_string *host); |
- | 203 | static void fetch_curl_cache_handle(struct http_msg *handle, lwc_string *host); |
|
- | 204 | static KOSHcode fetch_curl_set_options(struct curl_fetch_info *f); |
|
- | 205 | /* static KOSHcode fetch_curl_sslctxfun(CURL *curl_handle, void *_sslctx, */ |
|
- | 206 | /* void *p); */ |
|
- | 207 | static void fetch_curl_abort(void *vf); |
|
- | 208 | static void fetch_curl_stop(struct fetch_info_slist *f); |
|
- | 209 | static void fetch_curl_free(void *f); |
|
- | 210 | static void fetch_curl_poll(lwc_string *scheme_ignored); |
|
- | 211 | static void fetch_curl_done(struct fetch_info_slist *curl_handle); |
|
- | 212 | static int fetch_curl_progress(void *clientp, double dltotal, double dlnow, |
|
- | 213 | double ultotal, double ulnow); |
|
- | 214 | static int fetch_curl_ignore_debug(struct http_msg *handle, |
|
- | 215 | kosh_infotype type, |
|
- | 216 | char *data, |
|
- | 217 | size_t size, |
|
- | 218 | void *userptr); |
|
- | 219 | static size_t fetch_curl_data(void *_f); |
|
- | 220 | /* static size_t fetch_curl_header(char *data, size_t size, size_t nmemb, */ |
|
- | 221 | /* void *_f); */ |
|
- | 222 | void fetch_curl_header(void *_f); |
|
91 | bool only_2xx, bool downgrade_tls, const char *post_urlenc, |
223 | static bool fetch_curl_process_headers(struct curl_fetch_info *f); |
- | 224 | static struct curl_httppost *fetch_curl_post_convert( |
|
- | 225 | const struct fetch_multipart_data *control); |
|
- | 226 | ||
- | 227 | /* static int fetch_curl_verify_callback(int preverify_ok, */ |
|
- | 228 | /* X509_STORE_CTX *x509_ctx); */ |
|
- | 229 | /* static int fetch_curl_cert_verify_callback(X509_STORE_CTX *x509_ctx, */ |
|
- | 230 | /* void *parm); */ |
|
Line 92... | Line 231... | ||
92 | const struct fetch_multipart_data *post_multipart, |
231 | |
93 | const char **headers); //here |
232 | /**************Functions added for replacing curl's provided functionality ************/ |
94 | static bool fetch_curl_start(void *vfetch); //here |
233 | struct curl_slist *curl_slist_append(struct curl_slist * list, const char * string ); |
95 | 234 | void curl_slist_free_all(struct curl_slist *); |
|
96 | static void fetch_curl_abort(void *vf); //here |
235 | struct fetch_info_slist *curl_multi_remove_handle(struct fetch_info_slist *multi_handle, struct curl_fetch_info *fetch_to_delete); |
Line 97... | Line 236... | ||
97 | static void fetch_curl_free(void *f); //here |
236 | struct http_msg * curl_easy_init(void); |
98 | static void fetch_curl_poll(lwc_string *scheme_ignored); //here |
237 | void curl_easy_cleanup(struct http_msg *handle); |
- | 238 | int curl_multi_add_handle(struct fetch_info_slist **multi_handle, struct curl_fetch_info *new_fetch_info); |
|
- | 239 | ||
99 | 240 | /** |
|
100 | 241 | * Initialise the fetcher. |
|
Line -... | Line 242... | ||
- | 242 | * |
|
Line -... | Line 243... | ||
- | 243 | * Must be called once before any other function. |
|
- | 244 | */ |
|
- | 245 | ||
- | 246 | void fetch_curl_register(void) |
|
- | 247 | { |
|
- | 248 | /* KOSHcode code; */ |
|
101 | /** |
249 | /* curl_version_info_data *data; */ |
- | 250 | int i; |
|
- | 251 | lwc_string *scheme; |
|
- | 252 | ||
Line 102... | Line -... | ||
102 | * Initialise the fetcher. |
- | |
Line -... | Line 253... | ||
- | 253 | LOG(("curl_version (no CURL XD)")); |
|
103 | * |
254 | |
- | 255 | const struct fetcher_operation_table fetcher_ops = { |
|
104 | * Must be called once before any other function. |
256 | .initialise = fetch_curl_initialise, |
- | 257 | .acceptable = fetch_curl_can_fetch, |
|
- | 258 | .setup = fetch_curl_setup, |
|
- | 259 | .start = fetch_curl_start, |
|
- | 260 | .abort = fetch_curl_abort, |
|
- | 261 | .free = fetch_curl_free, |
|
105 | */ |
262 | .poll = fetch_curl_poll, |
106 | 263 | .finalise = fetch_curl_finalise |
|
- | 264 | }; |
|
- | 265 | ||
- | 266 | ||
- | 267 | /* code = curl_global_init(CURL_GLOBAL_ALL); */ |
|
107 | void fetch_curl_register(void) |
268 | /* if (code != CURLE_OK) */ |
- | 269 | /* die("Failed to initialise the fetch module " */ |
|
- | 270 | /* "(curl_global_init failed)."); */ |
|
108 | { |
271 | |
109 | 272 | /*TODO : Put the init function for our global queue here */ |
|
- | 273 | /* What do we need for an init? Just setting the list to NULL should be enough. |
|
110 | lwc_string *scheme; |
274 | We might track the number of nodes in the list, but that's not required since we usean SLL. |
- | 275 | */ |
|
- | 276 | /* fetch_curl_multi = curl_multi_init(); */ |
|
- | 277 | /* if (!fetch_curl_multi) */ |
|
- | 278 | /* die("Failed to initialise the fetch module " */ |
|
111 | 279 | /* "(curl_multi_init failed)."); */ |
|
112 | 280 | ||
- | 281 | /* Create a curl easy handle with the options that are common to all |
|
- | 282 | fetches. */ |
|
113 | LOG(("curl register\n")); |
283 | |
- | 284 | /*HTTP Library initiated using volatime asm code in http.c */ |
|
- | 285 | DBG("Calling curl_easy_init\n"); |
|
- | 286 | /* fetch_blank_curl = curl_easy_init(); */ |
|
- | 287 | ||
- | 288 | /* if (!fetch_blank_curl) */ |
|
- | 289 | /* { */ |
|
- | 290 | /* DBG("fetch_blank_curl is NULL"); */ |
|
- | 291 | /* die("Failed to initialise the fetch module " */ |
|
- | 292 | /* "(curl_easy_init failed)."); */ |
|
- | 293 | /* } */ |
|
- | 294 | /* else */ |
|
- | 295 | /* DBG("fetch_blank_curl is usable."); */ |
|
- | 296 | ||
- | 297 | fetch_blank_curl = NULL; |
|
- | 298 | ||
- | 299 | /* TODO: The SETOPT calls set up the parameters for the curl handle. |
|
- | 300 | Since we don't want to use curl, these are of no use, but our native handle |
|
- | 301 | should consider all these fields while being set up for proper functioning |
|
- | 302 | */ |
|
- | 303 | ||
- | 304 | /* #undef SETOPT */ |
|
- | 305 | /* #define SETOPT(option, value) \ */ |
|
- | 306 | /* code = curl_easy_setopt(fetch_blank_curl, option, value); \ */ |
|
- | 307 | /* if (code != CURLE_OK) \ */ |
|
- | 308 | /* goto curl_easy_setopt_failed; */ |
|
- | 309 | ||
- | 310 | /* if (verbose_log) { */ |
|
- | 311 | /* SETOPT(CURLOPT_VERBOSE, 1); */ |
|
- | 312 | /* } else { */ |
|
- | 313 | /* SETOPT(CURLOPT_VERBOSE, 0); */ |
|
- | 314 | /* } */ |
|
- | 315 | /* SETOPT(CURLOPT_ERRORBUFFER, fetch_error_buffer); */ |
|
- | 316 | /* if (nsoption_bool(suppress_curl_debug)) */ |
|
- | 317 | /* SETOPT(CURLOPT_DEBUGFUNCTION, fetch_curl_ignore_debug); */ |
|
- | 318 | /* SETOPT(CURLOPT_WRITEFUNCTION, fetch_curl_data); */ |
|
- | 319 | /* SETOPT(CURLOPT_HEADERFUNCTION, fetch_curl_header); */ /* Calling fetch_curl_header inside fetch_curl_process_headers */ |
|
- | 320 | /* SETOPT(CURLOPT_PROGRESSFUNCTION, fetch_curl_progress); */ /* TODO: Add this with httplib somehow */ |
|
- | 321 | /* SETOPT(CURLOPT_NOPROGRESS, 0); */ |
|
- | 322 | /* SETOPT(CURLOPT_USERAGENT, user_agent_string()); */ |
|
114 | 323 | /* SETOPT(CURLOPT_ENCODING, "gzip"); */ |
|
- | 324 | /* SETOPT(CURLOPT_LOW_SPEED_LIMIT, 1L); */ |
|
- | 325 | /* SETOPT(CURLOPT_LOW_SPEED_TIME, 180L); */ |
|
- | 326 | /* SETOPT(CURLOPT_NOSIGNAL, 1L); */ |
|
- | 327 | /* SETOPT(CURLOPT_CONNECTTIMEOUT, 30L); */ |
|
115 | lwc_intern_string("http", SLEN("http"), &scheme); |
328 | |
- | 329 | /* if (nsoption_charp(ca_bundle) && */ |
|
- | 330 | /* strcmp(nsoption_charp(ca_bundle), "")) { */ |
|
- | 331 | /* LOG(("ca_bundle: '%s'", nsoption_charp(ca_bundle))); */ |
|
- | 332 | /* SETOPT(CURLOPT_CAINFO, nsoption_charp(ca_bundle)); */ |
|
- | 333 | /* } */ |
|
- | 334 | /* if (nsoption_charp(ca_path) && strcmp(nsoption_charp(ca_path), "")) { */ |
|
- | 335 | /* LOG(("ca_path: '%s'", nsoption_charp(ca_path))); */ |
|
- | 336 | /* SETOPT(CURLOPT_CAPATH, nsoption_charp(ca_path)); */ |
|
- | 337 | /* } */ |
|
- | 338 | ||
- | 339 | /*TODO: Useless for now, no SSL Support*/ |
|
- | 340 | ||
- | 341 | /* /\* Detect whether the SSL CTX function API works *\/ */ |
|
- | 342 | /* curl_with_openssl = true; */ |
|
- | 343 | /* code = curl_easy_setopt(fetch_blank_curl, */ |
|
- | 344 | /* CURLOPT_SSL_CTX_FUNCTION, NULL); */ |
|
- | 345 | /* if (code != CURLE_OK) { */ |
|
- | 346 | /* curl_with_openssl = false; */ |
|
- | 347 | /* } */ |
|
- | 348 | ||
- | 349 | /* /\* LOG(("cURL %slinked against openssl", curl_with_openssl ? "" : "not ")); *\/ */ |
|
116 | 350 | ||
- | 351 | /* /\* cURL initialised okay, register the fetchers *\/ */ |
|
117 | if (!fetch_add_fetcher(scheme, |
352 | |
Line -... | Line 353... | ||
- | 353 | /* data = curl_version_info(CURLVERSION_NOW); */ |
|
- | 354 | ||
- | 355 | /*TODO: We strictly want to deal with only http as a protocol right now, this stuff can come |
|
- | 356 | handy later, so it shall sit here for a while XD |
|
- | 357 | Removing the for loop for a single http fetcher setup scheme. |
|
- | 358 | */ |
|
Line -... | Line 359... | ||
- | 359 | ||
118 | fetch_curl_initialise, //here |
360 | /* for (i = 0; data->protocols[i]; i++) { |
- | 361 | if (strcmp(data->protocols[i], "http") == 0) { |
|
- | 362 | if (lwc_intern_string("http", SLEN("http"), |
|
Line 119... | Line 363... | ||
119 | fetch_curl_can_fetch, //here |
363 | &scheme) != lwc_error_ok) { |
120 | fetch_curl_setup, |
364 | die("Failed to initialise the fetch module " |
121 | fetch_curl_start, |
365 | "(couldn't intern \"http\")."); |
122 | fetch_curl_abort, //here |
366 | } |
123 | fetch_curl_free, //here |
367 | |
124 | #ifdef FETCHER_CURLL_SCHEDULED |
368 | } else if (strcmp(data->protocols[i], "https") == 0) { |
125 | NULL, |
369 | if (lwc_intern_string("https", SLEN("https"), |
126 | #else |
370 | &scheme) != lwc_error_ok) { |
127 | fetch_curl_poll, //here |
371 | die("Failed to initialise the fetch module " |
128 | #endif |
372 | "(couldn't intern \"https\")."); |
129 | fetch_curl_finalise)) { //here |
373 | } |
130 | LOG(("Unable to register cURL fetcher for HTTP")); |
374 | |
131 | } |
375 | } else { |
132 | 376 | // Ignore non-http(s) protocols |
|
- | 377 | continue; |
|
133 | 378 | } |
|
- | 379 | ||
- | 380 | if (!fetch_add_fetcher(scheme, |
|
- | 381 | fetch_curl_initialise, |
|
- | 382 | fetch_curl_can_fetch, |
|
- | 383 | fetch_curl_setup, |
|
- | 384 | fetch_curl_start, |
|
- | 385 | fetch_curl_abort, |
|
- | 386 | sfetch_curl_free, |
|
- | 387 | #ifdef FETCHER_CURLL_SCHEDULED |
|
- | 388 | NULL, |
|
- | 389 | #else |
|
- | 390 | fetch_curl_poll, |
|
- | 391 | #endif |
|
- | 392 | fetch_curl_finalise)) { |
|
- | 393 | LOG(("Unable to register cURL fetcher for %s", |
|
- | 394 | data->protocols[i])); |
|
- | 395 | } |
|
- | 396 | } |
|
- | 397 | */ |
|
- | 398 | ||
- | 399 | /* if (lwc_intern_string("http", SLEN("http"), */ |
|
- | 400 | /* &scheme) != lwc_error_ok) { */ |
|
- | 401 | /* die("Failed to initialise the fetch module " */ |
|
- | 402 | /* "(couldn't intern \"http\")."); */ |
|
- | 403 | /* } */ |
|
- | 404 | ||
- | 405 | /* if (!fetch_add_fetcher(scheme, */ |
|
Line -... | Line 406... | ||
- | 406 | /* fetch_curl_initialise, */ |
|
- | 407 | /* fetch_curl_can_fetch, */ |
|
- | 408 | /* fetch_curl_setup, */ |
|
134 | lwc_intern_string("https", SLEN("https"), &scheme); |
409 | /* fetch_curl_start, */ |
Line 135... | Line 410... | ||
135 | 410 | /* fetch_curl_abort, */ |
|
136 | if (!fetch_add_fetcher(scheme, |
411 | /* fetch_curl_free, */ |
137 | fetch_curl_initialise, |
412 | /* #ifdef FETCHER_CURLL_SCHEDULED */ |
Line -... | Line 413... | ||
- | 413 | /* NULL, */ |
|
138 | fetch_curl_can_fetch, |
414 | /* #else */ |
139 | fetch_curl_setup, |
415 | /* fetch_curl_poll, */ |
- | 416 | /* #endif */ |
|
140 | fetch_curl_start, |
417 | /* fetch_curl_finalise)) { */ |
141 | fetch_curl_abort, |
418 | /* LOG(("Unable to register cURL fetcher for %s", */ |
142 | fetch_curl_free, |
419 | /* "http")); */ |
Line 143... | Line 420... | ||
143 | #ifdef FETCHER_CURLL_SCHEDULED |
420 | /* } */ |
144 | NULL, |
421 | /* DBG("fetch_curl_register returning."); */ |
145 | #else |
422 | return; |
Line 146... | Line 423... | ||
146 | fetch_curl_poll, |
423 | |
147 | #endif |
424 | curl_easy_setopt_failed: |
- | 425 | die("Failed to initialise the fetch module " |
|
- | 426 | "(curl_easy_setopt failed)."); |
|
- | 427 | } |
|
- | 428 | ||
- | 429 | ||
- | 430 | /** |
|
- | 431 | * Initialise a cURL fetcher. |
|
- | 432 | */ |
|
- | 433 | ||
- | 434 | /* Seems to not need any work right now, curl_fetchers_registered variable seems handy*/ |
|
- | 435 | bool fetch_curl_initialise(lwc_string *scheme) |
|
- | 436 | { |
|
- | 437 | LOG(("Initialise cURL fetcher for %s", lwc_string_data(scheme))); |
|
- | 438 | curl_fetchers_registered++; |
|
- | 439 | return true; /* Always succeeds */ |
|
- | 440 | } |
|
- | 441 | ||
- | 442 | ||
148 | fetch_curl_finalise)) { |
443 | /** |
149 | LOG(("Unable to register cURL fetcher for HTTPS")); |
444 | * Finalise a cURL fetcher |
Line -... | Line 445... | ||
- | 445 | */ |
|
- | 446 | ||
- | 447 | void fetch_curl_finalise(lwc_string *scheme) |
|
- | 448 | { |
|
- | 449 | struct cache_handle *h; |
|
- | 450 | curl_fetchers_registered--; |
|
- | 451 | LOG(("Finalise cURL fetcher %s", lwc_string_data(scheme))); |
|
- | 452 | if (curl_fetchers_registered == 0) { |
|
150 | } |
453 | /* KOSHMcode codem; */ |
151 | 454 | int codem; |
|
152 | } |
- | |
153 | 455 | /* All the fetchers have been finalised. */ |
|
154 | 456 | LOG(("All cURL fetchers finalised, closing down cURL")); |
|
Line 155... | Line 457... | ||
155 | /** |
457 | |
156 | * Initialise a cURL fetcher. |
458 | /* TODO: Add any clean up functions for httplib here. */ |
157 | */ |
459 | /* curl_easy_cleanup now contains http_free() */ |
Line 198... | Line 500... | ||
198 | * |
500 | * |
199 | * Some private data can be passed as the last parameter to fetch_start, and |
501 | * Some private data can be passed as the last parameter to fetch_start, and |
200 | * callbacks will contain this. |
502 | * callbacks will contain this. |
201 | */ |
503 | */ |
Line 202... | Line 504... | ||
202 | 504 | ||
203 | void * fetch_curl_setup (struct fetch *fetchh, |
- | |
204 | nsurl *url, |
- | |
205 | bool only_2xx, |
- | |
206 | bool downgrade_tls, |
505 | void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url, |
207 | const char *post_urlenc, |
506 | bool only_2xx, bool downgrade_tls, const char *post_urlenc, |
208 | const struct fetch_multipart_data *post_multipart, |
507 | const struct fetch_multipart_data *post_multipart, |
209 | const char **headers) |
508 | const char **headers) |
- | 509 | { |
|
- | 510 | struct curl_fetch_info *fetch; |
|
- | 511 | struct curl_slist *slist; |
|
Line 210... | Line 512... | ||
210 | { |
512 | int i; |
Line 211... | Line 513... | ||
211 | 513 | ||
212 | LOG(("curl setup\n")); |
514 | fetch = malloc(sizeof (*fetch)); |
- | 515 | ||
- | 516 | if (fetch == NULL) |
|
- | 517 | { |
|
- | 518 | LOG(("Fetch was NULL. Aborting fetch_curl_setup")); |
|
Line -... | Line 519... | ||
- | 519 | return 0; |
|
- | 520 | } |
|
- | 521 | fetch->fetch_handle = parent_fetch; |
|
- | 522 | ||
- | 523 | LOG(("fetch %p, url '%s'", fetch, nsurl_access(url))); |
|
- | 524 | ||
- | 525 | /* construct a new fetch structure */ |
|
- | 526 | fetch->curl_handle = NULL; |
|
- | 527 | fetch->had_headers = false; |
|
- | 528 | fetch->abort = false; |
|
213 | 529 | fetch->stopped = false; |
|
- | 530 | fetch->only_2xx = only_2xx; |
|
- | 531 | fetch->downgrade_tls = downgrade_tls; |
|
- | 532 | fetch->headers = NULL; |
|
- | 533 | fetch->url = nsurl_ref(url); |
|
- | 534 | fetch->host = nsurl_get_component(url, NSURL_HOST); |
|
- | 535 | fetch->location = NULL; |
|
- | 536 | fetch->content_length = 0; |
|
- | 537 | fetch->http_code = 0; |
|
- | 538 | fetch->cookie_string = NULL; |
|
- | 539 | fetch->realm = NULL; |
|
- | 540 | fetch->post_urlenc = NULL; |
|
- | 541 | fetch->post_multipart = NULL; |
|
- | 542 | ||
- | 543 | if (post_urlenc) |
|
- | 544 | { |
|
- | 545 | LOG(("post_urlenc is not NULL : %s.\n", post_urlenc)); |
|
- | 546 | fetch->post_urlenc = strdup(post_urlenc); |
|
- | 547 | } |
|
- | 548 | else if (post_multipart) |
|
- | 549 | { |
|
- | 550 | LOG(("post_multipart is not NULL : %x.\n", post_multipart)); |
|
- | 551 | /*TODO: Need a post converter here, shouldn't be large though*/ |
|
- | 552 | fetch->post_multipart = fetch_curl_post_convert(post_multipart); |
|
- | 553 | } |
|
- | 554 | /* memset(fetch->cert_data, 0, sizeof(fetch->cert_data)); */ |
|
- | 555 | fetch->last_progress_update = 0; |
|
- | 556 | ||
- | 557 | if (fetch->host == NULL || |
|
- | 558 | (post_multipart != NULL && fetch->post_multipart == NULL) || |
|
- | 559 | (post_urlenc != NULL && fetch->post_urlenc == NULL)) |
|
- | 560 | goto failed; |
|
- | 561 | ||
- | 562 | /* TODO : Write an implementation for curl_slist_append for adding and appending fields to header*/ |
|
- | 563 | /* This is done for now */ |
|
- | 564 | ||
- | 565 | /* #define APPEND(list, value) \ */ |
|
- | 566 | /* slist = curl_slist_append(list, value); \ */ |
|
- | 567 | /* if (slist == NULL) \ */ |
|
- | 568 | /* goto failed; \ */ |
|
- | 569 | /* list = slist; */ |
|
- | 570 | ||
- | 571 | /*TODO : This section will need some work because we don't use curl headers but use the ones |
|
- | 572 | provided by http.obj which does not necessarily include the same prefed headers |
|
- | 573 | */ |
|
- | 574 | /* remove curl default headers */ |
|
- | 575 | /* APPEND(fetch->headers, "Pragma:"); */ |
|
- | 576 | ||
- | 577 | /* when doing a POST libcurl sends Expect: 100-continue" by default |
|
- | 578 | * which fails with lighttpd, so disable it (see bug 1429054) */ |
|
- | 579 | /* APPEND(fetch->headers, "Expect:"); */ |
|
- | 580 | ||
- | 581 | /* if ((nsoption_charp(accept_language) != NULL) && */ |
|
- | 582 | /* (nsoption_charp(accept_language)[0] != '\0')) { */ |
|
- | 583 | /* char s[80]; */ |
|
- | 584 | /* snprintf(s, sizeof s, "Accept-Language: %s, *;q=0.1", */ |
|
- | 585 | /* nsoption_charp(accept_language)); */ |
|
- | 586 | /* s[sizeof s - 1] = 0; */ |
|
- | 587 | /* APPEND(fetch->headers, s); */ |
|
- | 588 | /* } */ |
|
- | 589 | ||
- | 590 | /* if (nsoption_charp(accept_charset) != NULL && */ |
|
- | 591 | /* nsoption_charp(accept_charset)[0] != '\0') { */ |
|
- | 592 | /* char s[80]; */ |
|
- | 593 | /* snprintf(s, sizeof s, "Accept-Charset: %s, *;q=0.1", */ |
|
- | 594 | /* nsoption_charp(accept_charset)); */ |
|
- | 595 | /* s[sizeof s - 1] = 0; */ |
|
- | 596 | /* APPEND(fetch->headers, s); */ |
|
- | 597 | /* } */ |
|
- | 598 | ||
- | 599 | /* if (nsoption_bool(do_not_track) == true) { */ |
|
- | 600 | /* APPEND(fetch->headers, "DNT: 1"); */ |
|
- | 601 | /* } */ |
|
- | 602 | ||
- | 603 | /* /\* And add any headers specified by the caller *\/ */ |
|
- | 604 | /* for (i = 0; headers[i] != NULL; i++) { */ |
|
- | 605 | /* APPEND(fetch->headers, headers[i]); */ |
|
- | 606 | /* } */ |
|
214 | struct fetch_curl_context *ctx; |
607 | |
- | 608 | return fetch; |
|
- | 609 | ||
- | 610 | failed: |
|
- | 611 | if (fetch->host != NULL) |
|
- | 612 | lwc_string_unref(fetch->host); |
|
- | 613 | ||
- | 614 | nsurl_unref(fetch->url); |
|
- | 615 | free(fetch->post_urlenc); |
|
- | 616 | /* TOOD: Figure out a way to deal with post data. */ |
|
215 | int i; |
617 | /* if (fetch->post_multipart) */ |
- | 618 | /* curl_formfree(fetch->post_multipart); */ |
|
Line -... | Line 619... | ||
- | 619 | curl_slist_free_all(fetch->headers); |
|
- | 620 | free(fetch); |
|
- | 621 | return NULL; |
|
- | 622 | } |
|
- | 623 | ||
- | 624 | ||
- | 625 | /** |
|
- | 626 | * Dispatch a single job |
|
- | 627 | */ |
|
- | 628 | bool fetch_curl_start(void *vfetch) |
|
216 | 629 | { |
|
- | 630 | ||
- | 631 | struct curl_fetch_info *fetch = (struct curl_fetch_info*)vfetch; |
|
- | 632 | DBG("Inside fetch_curl_start\n"); |
|
- | 633 | return fetch_curl_initiate_fetch(fetch, |
|
- | 634 | fetch_curl_get_handle(fetch->host)); |
|
- | 635 | } |
|
- | 636 | ||
- | 637 | ||
- | 638 | /** |
|
- | 639 | * Initiate a fetch from the queue. |
|
- | 640 | * |
|
- | 641 | * Called with a fetch structure and a CURL handle to be used to fetch the |
|
- | 642 | * content. |
|
- | 643 | * |
|
- | 644 | * This will return whether or not the fetch was successfully initiated. |
|
- | 645 | */ |
|
- | 646 | ||
217 | ctx = calloc(1, sizeof(*ctx)); |
647 | bool fetch_curl_initiate_fetch(struct curl_fetch_info *fetch, struct http_msg *handle) |
218 | if (ctx == NULL) |
648 | { |
219 | return NULL; |
- | |
Line -... | Line 649... | ||
- | 649 | KOSHcode code; |
|
- | 650 | KOSHMcode codem; |
|
- | 651 | unsigned int wererat; /* Like soUrcerer wanted it :D */ |
|
- | 652 | char *zz; |
|
- | 653 | int pr; |
|
- | 654 | ||
- | 655 | /* fetch->curl_handle = handle; */ |
|
- | 656 | /* Don't need to add options to handle from http obj */ |
|
- | 657 | /* Initialise the handle */ |
|
220 | 658 | /* DBG("inside fetch_curl_initiate_fetch()...\n"); */ |
|
- | 659 | ||
- | 660 | /* code = fetch_curl_set_options(fetch); */ |
|
- | 661 | /* if (code.code != CURLE_OK) { */ |
|
- | 662 | /* fetch->curl_handle = 0; */ |
|
- | 663 | /* return false; */ |
|
- | 664 | /* } */ |
|
- | 665 | ||
- | 666 | /* TODO : Write a curl_multi_add_handle alternative which puts the handle in our global queue |
|
- | 667 | for polling later on multiple transfers together*/ |
|
- | 668 | ||
221 | //ctx->path = url_to_path(nsurl_access(url)); |
669 | /* add to the global curl multi handle */ |
- | 670 | ||
222 | char *zz; |
671 | DBG("inside fetch_curl_initiate_fetch()...\n"); |
- | 672 | ||
- | 673 | nsurl_get(fetch->url, NSURL_WITH_FRAGMENT, &zz, &pr); |
|
- | 674 | ||
- | 675 | if (zz == NULL) { |
|
- | 676 | fetch_curl_abort(fetch); |
|
- | 677 | return NULL; |
|
- | 678 | } |
|
- | 679 | ||
- | 680 | /*TODO : Always clear the flags for the handle here*/ |
|
- | 681 | ||
- | 682 | if(fetch->post_urlenc) |
|
- | 683 | { |
|
- | 684 | LOG(("http_post on %s with headers: %s", zz, fetch->post_urlenc)); |
|
223 | int pr; |
685 | wererat = http_post(zz, NULL, "application/x-www-form-urlencoded", strlen(fetch->post_urlenc)); |
224 | nsurl_get(url, NSURL_WITH_FRAGMENT, &zz, &pr); |
686 | |
- | 687 | if(wererat == 0) |
|
- | 688 | { |
|
- | 689 | LOG(("Error. http_post failed. Aborting fetch.\n")); |
|
- | 690 | fetch_curl_abort(fetch); |
|
- | 691 | return NULL; |
|
- | 692 | } |
|
- | 693 | else /*Send the post request body*/ |
|
- | 694 | { |
|
- | 695 | int sent = http_send(wererat, fetch->post_urlenc, strlen(fetch->post_urlenc)); |
|
- | 696 | LOG(("Sent %d bytes in http_send for %s", sent, fetch->post_urlenc)); |
|
Line -... | Line 697... | ||
- | 697 | } |
|
- | 698 | } |
|
- | 699 | else /* GET Request */ |
|
225 | 700 | { |
|
- | 701 | LOG(("http_get on URL : %s", zz)); |
|
- | 702 | wererat = http_get(zz, NULL); /* Initiates the GET on the handle we want to initiate for */ |
|
- | 703 | ||
- | 704 | if(wererat == 0) /* http_get failed. Something wrong. Can't do anything here */ |
|
- | 705 | { |
|
- | 706 | DBG("Error. http_get failed. Aborting fetch.\n"); |
|
- | 707 | fetch_curl_abort(fetch); |
|
Line -... | Line 708... | ||
- | 708 | return NULL; |
|
Line 226... | Line 709... | ||
226 | ctx->path = zz; |
709 | } |
Line -... | Line 710... | ||
- | 710 | } |
|
227 | if (ctx->path == NULL) { |
711 | |
Line -... | Line 712... | ||
- | 712 | /* Probably check for the older curl_handle here and http_free() or http_disconnect accordingly TODO */ |
|
- | 713 | ||
- | 714 | fetch->curl_handle = (struct http_msg *)wererat; /* Adding the http_msg handle to fetch->handle */ |
|
228 | free(ctx); |
715 | |
229 | return NULL; |
716 | LOG(("wererat is %u with flags = %u", wererat, fetch->curl_handle->flags)); |
Line 230... | Line 717... | ||
230 | } |
717 | |
231 | 718 | codem.code = curl_multi_add_handle(&fetch_curl_multi, fetch); |
|
232 | ctx->url = nsurl_ref(url); |
719 | |
- | 720 | /* Probably drop the assert and handle this properly, but that's for later */ |
|
233 | 721 | assert(codem.code == CURLM_OK || codem.code == CURLM_CALL_MULTI_PERFORM); |
|
234 | 722 | ||
- | 723 | /* TODO: No idea what this does right now. Shouldn't this be inside an #if macro call? to enable/disable curll scheduling.*/ |
|
- | 724 | schedule(1, (schedule_callback_fn)fetch_curl_poll, NULL); |
|
- | 725 | ||
- | 726 | return true; |
|
- | 727 | } |
|
- | 728 | ||
- | 729 | ||
- | 730 | /** |
|
- | 731 | * Find a CURL handle to use to dispatch a job |
|
- | 732 | */ |
|
- | 733 | ||
- | 734 | struct http_msg *fetch_curl_get_handle(lwc_string *host) |
|
- | 735 | { |
|
- | 736 | struct cache_handle *h; |
|
235 | ctx->fetchh = fetchh; |
737 | struct http_msg *ret; |
- | 738 | ||
- | 739 | DBG("inside fetch_curl_get_handle()...\n"); |
|
236 | 740 | ||
237 | RING_INSERT(ring, ctx); |
741 | RING_FINDBYLWCHOST(curl_handle_ring, h, host); |
Line -... | Line 742... | ||
- | 742 | if (h) { |
|
- | 743 | ret = h->handle; |
|
- | 744 | lwc_string_unref(h->host); |
|
Line -... | Line 745... | ||
- | 745 | RING_REMOVE(curl_handle_ring, h); |
|
Line -... | Line 746... | ||
- | 746 | free(h); |
|
- | 747 | } else { |
|
- | 748 | /* ret = curl_easy_duphandle(fetch_blank_curl); */ |
|
- | 749 | /* TODO: Verify if this is equivalent to curl_easy_duphandle call above this */ |
|
- | 750 | ret = curl_easy_init(); |
|
- | 751 | } |
|
- | 752 | ||
- | 753 | return ret; |
|
- | 754 | } |
|
- | 755 | ||
- | 756 | ||
- | 757 | /** |
|
- | 758 | * Cache a CURL handle for the provided host (if wanted) |
|
- | 759 | */ |
|
- | 760 | ||
- | 761 | /*TODO : Useful for using a pre existing cached handle for faster lookup*/ |
|
- | 762 | ||
- | 763 | void fetch_curl_cache_handle(struct http_msg *handle, lwc_string *host) |
|
- | 764 | { |
|
- | 765 | struct cache_handle *h = 0; |
|
- | 766 | int c; |
|
- | 767 | ||
- | 768 | DBG("inside fetch_curl_cache_handle...\n"); |
|
- | 769 | ||
- | 770 | RING_FINDBYLWCHOST(curl_handle_ring, h, host); |
|
- | 771 | if (h) { |
|
- | 772 | /*TODO: Replace curl_easy_cleanup function for something useful for use with KOSH*/ |
|
- | 773 | /* Already have a handle cached for this hostname */ |
|
- | 774 | curl_easy_cleanup(handle); |
|
- | 775 | return; |
|
- | 776 | } |
|
- | 777 | /* We do not have a handle cached, first up determine if the cache is full */ |
|
- | 778 | RING_GETSIZE(struct cache_handle, curl_handle_ring, c); |
|
- | 779 | if (c >= nsoption_int(max_cached_fetch_handles)) { |
|
- | 780 | /* Cache is full, so, we rotate the ring by one and |
|
- | 781 | * replace the oldest handle with this one. We do this |
|
- | 782 | * without freeing/allocating memory (except the |
|
- | 783 | * hostname) and without removing the entry from the |
|
- | 784 | * ring and then re-inserting it, in order to be as |
|
- | 785 | * efficient as we can. |
|
- | 786 | */ |
|
- | 787 | if (curl_handle_ring != NULL) { |
|
- | 788 | h = curl_handle_ring; |
|
- | 789 | curl_handle_ring = h->r_next; |
|
Line 238... | Line 790... | ||
238 | 790 | curl_easy_cleanup(h->handle); |
|
- | 791 | h->handle = handle; |
|
- | 792 | lwc_string_unref(h->host); |
|
- | 793 | h->host = lwc_string_ref(host); |
|
- | 794 | } else { |
|
- | 795 | /* Actually, we don't want to cache any handles */ |
|
- | 796 | curl_easy_cleanup(handle); |
|
- | 797 | } |
|
- | 798 | ||
- | 799 | return; |
|
- | 800 | } |
|
- | 801 | /* The table isn't full yet, so make a shiny new handle to add to the ring */ |
|
- | 802 | h = (struct cache_handle*)malloc(sizeof(struct cache_handle)); |
|
- | 803 | h->handle = handle; |
|
- | 804 | h->host = lwc_string_ref(host); |
|
- | 805 | RING_INSERT(curl_handle_ring, h); |
|
- | 806 | } |
|
- | 807 | ||
- | 808 | ||
- | 809 | /** |
|
- | 810 | * Set options specific for a fetch. |
|
- | 811 | */ |
|
- | 812 | ||
- | 813 | /*TODO: This function sets up a specific fetch. Need a replacement for SETOPT for setting parameters |
|
- | 814 | in our implementation |
|
- | 815 | */ |
|
- | 816 | ||
- | 817 | KOSHcode |
|
- | 818 | fetch_curl_set_options(struct curl_fetch_info *f) |
|
- | 819 | { |
|
- | 820 | KOSHcode code; |
|
- | 821 | const char *auth; |
|
- | 822 | ||
- | 823 | DBG("Inside fetch_curl_set_options\n"); |
|
- | 824 | ||
- | 825 | /*TODO: Replace SETOPT with sane set up of parameters for our handle*/ |
|
- | 826 | ||
- | 827 | /* #undef SETOPT */ |
|
- | 828 | /* #define SETOPT(option, value) { \ */ |
|
- | 829 | /* code = curl_easy_setopt(f->curl_handle, option, value); \ */ |
|
- | 830 | /* if (code != CURLE_OK) \ */ |
|
- | 831 | /* return code; \ */ |
|
- | 832 | /* } */ |
|
- | 833 | ||
- | 834 | /* SETOPT(CURLOPT_URL, nsurl_access(f->url)); */ |
|
- | 835 | /* SETOPT(CURLOPT_PRIVATE, f); */ |
|
- | 836 | /* SETOPT(CURLOPT_WRITEDATA, f); */ |
|
- | 837 | /* SETOPT(CURLOPT_WRITEHEADER, f); */ |
|
- | 838 | /* SETOPT(CURLOPT_PROGRESSDATA, f); */ |
|
- | 839 | /* SETOPT(CURLOPT_REFERER, fetch_get_referer_to_send(f->fetch_handle)); */ |
|
- | 840 | /* SETOPT(CURLOPT_HTTPHEADER, f->headers); */ |
|
- | 841 | /* if (f->post_urlenc) { */ |
|
- | 842 | /* SETOPT(CURLOPT_HTTPPOST, NULL); */ |
|
- | 843 | /* SETOPT(CURLOPT_HTTPGET, 0L); */ |
|
- | 844 | /* SETOPT(CURLOPT_POSTFIELDS, f->post_urlenc); */ |
|
- | 845 | /* } else if (f->post_multipart) { */ |
|
- | 846 | /* SETOPT(CURLOPT_POSTFIELDS, NULL); */ |
|
- | 847 | /* SETOPT(CURLOPT_HTTPGET, 0L); */ |
|
- | 848 | /* SETOPT(CURLOPT_HTTPPOST, f->post_multipart); */ |
|
- | 849 | /* } else { */ |
|
- | 850 | /* SETOPT(CURLOPT_POSTFIELDS, NULL); */ |
|
- | 851 | /* SETOPT(CURLOPT_HTTPPOST, NULL); */ |
|
- | 852 | /* SETOPT(CURLOPT_HTTPGET, 1L); */ |
|
- | 853 | /* } */ |
|
- | 854 | ||
- | 855 | ||
- | 856 | /* f->cookie_string = urldb_get_cookie(f->url, true); */ |
|
- | 857 | ||
- | 858 | ||
- | 859 | /* if (f->cookie_string) { */ |
|
- | 860 | /* SETOPT(CURLOPT_COOKIE, f->cookie_string); */ |
|
- | 861 | /* } else { */ |
|
- | 862 | /* SETOPT(CURLOPT_COOKIE, NULL); */ |
|
- | 863 | /* } */ |
|
- | 864 | ||
- | 865 | /* if ((auth = urldb_get_auth_details(f->url, NULL)) != NULL) { */ |
|
- | 866 | /* SETOPT(CURLOPT_HTTPAUTH, CURLAUTH_ANY); */ |
|
- | 867 | /* SETOPT(CURLOPT_USERPWD, auth); */ |
|
- | 868 | /* } else { */ |
|
- | 869 | /* SETOPT(CURLOPT_USERPWD, NULL); */ |
|
- | 870 | /* } */ |
|
- | 871 | ||
- | 872 | /* if (nsoption_bool(http_proxy) && */ |
|
- | 873 | /* (nsoption_charp(http_proxy_host) != NULL) && */ |
|
- | 874 | /* (strncmp(nsurl_access(f->url), "file:", 5) != 0)) { */ |
|
- | 875 | /* SETOPT(CURLOPT_PROXY, nsoption_charp(http_proxy_host)); */ |
|
- | 876 | /* SETOPT(CURLOPT_PROXYPORT, (long) nsoption_int(http_proxy_port)); */ |
|
- | 877 | /* if (nsoption_int(http_proxy_auth) != OPTION_HTTP_PROXY_AUTH_NONE) { */ |
|
- | 878 | /* SETOPT(CURLOPT_PROXYAUTH, */ |
|
- | 879 | /* nsoption_int(http_proxy_auth) == */ |
|
- | 880 | /* OPTION_HTTP_PROXY_AUTH_BASIC ? */ |
|
- | 881 | /* (long) CURLAUTH_BASIC : */ |
|
- | 882 | /* (long) CURLAUTH_NTLM); */ |
|
- | 883 | /* snprintf(fetch_proxy_userpwd, */ |
|
- | 884 | /* sizeof fetch_proxy_userpwd, */ |
|
- | 885 | /* "%s:%s", */ |
|
- | 886 | /* nsoption_charp(http_proxy_auth_user), */ |
|
- | 887 | /* nsoption_charp(http_proxy_auth_pass)); */ |
|
- | 888 | /* SETOPT(CURLOPT_PROXYUSERPWD, fetch_proxy_userpwd); */ |
|
- | 889 | /* } */ |
|
- | 890 | /* } else { */ |
|
- | 891 | /* SETOPT(CURLOPT_PROXY, NULL); */ |
|
- | 892 | /* } */ |
|
- | 893 | ||
- | 894 | /* /\* Disable SSL session ID caching, as some servers can't cope. *\/ */ |
|
- | 895 | /* SETOPT(CURLOPT_SSL_SESSIONID_CACHE, 0); */ |
|
- | 896 | ||
- | 897 | /* if (urldb_get_cert_permissions(f->url)) { */ |
|
- | 898 | /* /\* Disable certificate verification *\/ */ |
|
- | 899 | /* SETOPT(CURLOPT_SSL_VERIFYPEER, 0L); */ |
|
- | 900 | /* SETOPT(CURLOPT_SSL_VERIFYHOST, 0L); */ |
|
- | 901 | /* if (curl_with_openssl) { */ |
|
- | 902 | /* SETOPT(CURLOPT_SSL_CTX_FUNCTION, NULL); */ |
|
- | 903 | /* SETOPT(CURLOPT_SSL_CTX_DATA, NULL); */ |
|
- | 904 | /* } */ |
|
- | 905 | /* } else { */ |
|
- | 906 | /* /\* do verification *\/ */ |
|
- | 907 | /* SETOPT(CURLOPT_SSL_VERIFYPEER, 1L); */ |
|
- | 908 | /* SETOPT(CURLOPT_SSL_VERIFYHOST, 2L); */ |
|
- | 909 | /* if (curl_with_openssl) { */ |
|
- | 910 | /* SETOPT(CURLOPT_SSL_CTX_FUNCTION, fetch_curl_sslctxfun); */ |
|
- | 911 | /* SETOPT(CURLOPT_SSL_CTX_DATA, f); */ |
|
- | 912 | /* } */ |
|
- | 913 | /* } */ |
|
- | 914 | code.code = CURLE_OK; |
|
- | 915 | return code; |
|
- | 916 | /* return CURLE_OK; */ |
|
- | 917 | } |
|
- | 918 | ||
- | 919 | ||
- | 920 | /** |
|
- | 921 | * cURL SSL setup callback |
|
- | 922 | */ |
|
- | 923 | /*TODO : Commenting this out because of lack of SSL support right now */ |
|
- | 924 | ||
- | 925 | /****************************************************************** |
|
- | 926 | KOSHcode |
|
- | 927 | fetch_curl_sslctxfun(CURL *curl_handle, void *_sslctx, void *parm) |
|
- | 928 | { |
|
- | 929 | struct curl_fetch_info *f = (struct curl_fetch_info *) parm; |
|
- | 930 | SSL_CTX *sslctx = _sslctx; |
|
- | 931 | long options = SSL_OP_ALL; |
|
- | 932 | ||
- | 933 | SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, fetch_curl_verify_callback); |
|
- | 934 | SSL_CTX_set_cert_verify_callback(sslctx, fetch_curl_cert_verify_callback, |
|
- | 935 | parm); |
|
- | 936 | ||
239 | return ctx; |
937 | if (f->downgrade_tls) { |
240 | } |
938 | #ifdef SSL_OP_NO_TLSv1_1 |
- | 939 | // Disable TLS1.1, if the server can't cope with it |
|
Line 241... | Line 940... | ||
241 | 940 | options |= SSL_OP_NO_TLSv1_1; |
|
242 | 941 | #endif |
|
- | 942 | } |
|
- | 943 | ||
- | 944 | #ifdef SSL_OP_NO_TLSv1_2 |
|
- | 945 | // Disable TLS1.2, as it causes some servers to stall. |
|
- | 946 | options |= SSL_OP_NO_TLSv1_2; |
|
- | 947 | #endif |
|
- | 948 | ||
- | 949 | SSL_CTX_set_options(sslctx, options); |
|
- | 950 | ||
- | 951 | return CURLE_OK; |
|
243 | /** |
952 | } |
- | 953 | ******************************************************************/ |
|
- | 954 | ||
- | 955 | /** |
|
Line -... | Line 956... | ||
- | 956 | * Abort a fetch. |
|
244 | * Dispatch a single job |
957 | */ |
245 | */ |
- | |
- | 958 | /* TODO: Seems usable until further action */ |
|
246 | bool fetch_curl_start(void *vfetch) |
959 | |
247 | { |
960 | void fetch_curl_abort(void *vf) |
- | 961 | { |
|
- | 962 | struct curl_fetch_info *f = (struct curl_fetch_info *)vf; |
|
- | 963 | assert(f); |
|
- | 964 | LOG(("fetch %p, url '%s'", f, nsurl_access(f->url))); |
|
- | 965 | ||
- | 966 | fetch_curl_multi = curl_multi_remove_handle(fetch_curl_multi, f); |
|
- | 967 | ||
- | 968 | if (f->curl_handle) { |
|
- | 969 | f->abort = true; |
|
- | 970 | } else { |
|
- | 971 | fetch_remove_from_queues(f->fetch_handle); |
|
- | 972 | fetch_free(f->fetch_handle); |
|
- | 973 | } |
|
- | 974 | } |
|
- | 975 | ||
- | 976 | ||
- | 977 | /** |
|
- | 978 | * Clean up the provided fetch object and free it. |
|
- | 979 | * |
|
- | 980 | * Will prod the queue afterwards to allow pending requests to be initiated. |
|
- | 981 | */ |
|
- | 982 | ||
- | 983 | void fetch_curl_stop(struct fetch_info_slist *node) |
|
- | 984 | { |
|
- | 985 | KOSHMcode codem; |
|
248 | LOG(("curl start\n")); |
986 | |
- | 987 | /* TODO: Assert doesn't look like a safe option, but this is probably a fatal condition */ |
|
- | 988 | ||
- | 989 | struct curl_fetch_info *f = node->fetch_info; |
|
- | 990 | ||
249 | return true; |
991 | assert(f); |
Line 250... | Line 992... | ||
250 | } |
992 | LOG(("fetch %p, url '%s'", f, nsurl_access(f->url))); |
251 | 993 | ||
252 | 994 | if (f->curl_handle) { |
|
- | 995 | /* remove from curl multi handle */ |
|
Line 253... | Line 996... | ||
253 | 996 | /*TODO: Need a replacement for curl_multi_remove_handle function*/ |
|
254 | 997 | /* LOG(("fetch_curl_multi : %u", fetch_curl_multi)); */ |
|
- | 998 | fetch_curl_multi = curl_multi_remove_handle(fetch_curl_multi, f); |
|
- | 999 | /* assert(codem.code == CURLM_OK); */ |
|
255 | 1000 | /* Put this curl handle into the cache if wanted. */ |
|
- | 1001 | /* TODO: Cache? */ |
|
- | 1002 | /* fetch_curl_cache_handle(f->curl_handle, f->host); */ |
|
- | 1003 | ||
- | 1004 | if(f && f->curl_handle) |
|
256 | 1005 | http_free(f->curl_handle); |
|
- | 1006 | ||
- | 1007 | f->curl_handle = 0; |
|
- | 1008 | } |
|
257 | /** |
1009 | |
- | 1010 | fetch_remove_from_queues(f->fetch_handle); |
|
- | 1011 | LOG(("Returning")); |
|
258 | * Abort a fetch. |
1012 | } |
- | 1013 | ||
- | 1014 | ||
- | 1015 | /** |
|
- | 1016 | * Free a fetch structure and associated resources. |
|
- | 1017 | */ |
|
- | 1018 | /*TODO: Except the cert details at the bottom of the function, everything else seems workable*/ |
|
- | 1019 | ||
- | 1020 | void fetch_curl_free(void *vf) |
|
- | 1021 | { |
|
- | 1022 | struct curl_fetch_info *f = (struct curl_fetch_info *)vf; |
|
259 | */ |
1023 | int i; |
260 | 1024 | DBG("inside fetch_curl_free()..\n"); |
|
Line -... | Line 1025... | ||
- | 1025 | ||
- | 1026 | if (f->curl_handle) |
|
- | 1027 | curl_easy_cleanup(f->curl_handle); |
|
- | 1028 | ||
261 | void fetch_curl_abort(void *ctx) |
1029 | nsurl_unref(f->url); |
- | 1030 | lwc_string_unref(f->host); |
|
- | 1031 | free(f->location); |
|
- | 1032 | free(f->cookie_string); |
|
- | 1033 | free(f->realm); |
|
- | 1034 | if (f->headers) |
|
- | 1035 | curl_slist_free_all(f->headers); |
|
- | 1036 | free(f->post_urlenc); |
|
262 | { |
1037 | /* TODO: Deal with POST data asap */ |
263 | struct fetch_curl_context *c = ctx; |
1038 | /* if (f->post_multipart) */ |
264 | 1039 | /* curl_formfree(f->post_multipart); */ |
|
265 | /* To avoid the poll loop having to deal with the fetch context |
1040 | |
Line -... | Line 1041... | ||
- | 1041 | /* for (i = 0; i < MAX_CERTS && f->cert_data[i].cert; i++) { */ |
|
266 | * disappearing from under it, we simply flag the abort here. |
1042 | /* f->cert_data[i].cert->references--; */ |
267 | * The poll loop itself will perform the appropriate cleanup. |
1043 | /* if (f->cert_data[i].cert->references == 0) */ |
- | 1044 | /* X509_free(f->cert_data[i].cert); */ |
|
- | 1045 | /* } */ |
|
- | 1046 | ||
268 | */ |
1047 | free(f); |
Line 269... | Line 1048... | ||
269 | c->aborted = true; |
1048 | } |
- | 1049 | ||
- | 1050 | ||
- | 1051 | /** |
|
- | 1052 | * Do some work on current fetches. |
|
- | 1053 | * |
|
- | 1054 | * Must be called regularly to make progress on fetches. |
|
- | 1055 | */ |
|
- | 1056 | ||
270 | } |
1057 | /*TODO: This is our slave (from master slave) function that will poll fetches. |
Line 271... | Line 1058... | ||
271 | 1058 | We will maintain our own global ring of handles and let this function poll the entries |
|
272 | - | ||
273 | /** |
1059 | and do some work accordingly. Useful for multiple transfers simultaneously. |
274 | * Free a fetch structure and associated resources. |
1060 | */ |
275 | */ |
1061 | |
276 | - | ||
277 | void fetch_curl_free(void *ctx) |
1062 | void fetch_curl_poll(lwc_string *scheme_ignored) |
278 | { |
1063 | { |
279 | struct fetch_curl_context *c = ctx; |
- | |
280 | nsurl_unref(c->url); |
1064 | int running, queue; |
281 | free(c->path); |
- | |
282 | RING_REMOVE(ring, c); |
1065 | KOSHMcode codem; |
283 | free(ctx); |
- | |
284 | } |
- | |
Line 285... | Line -... | ||
285 | - | ||
286 | static inline bool fetch_curl_send_callback(const fetch_msg *msg, |
- | |
287 | struct fetch_curl_context *ctx) |
1066 | |
288 | { |
- | |
Line -... | Line 1067... | ||
- | 1067 | if(!fetch_curl_multi) |
|
- | 1068 | LOG(("fetch_curl_multi is NULL")); |
|
- | 1069 | else |
|
289 | ctx->locked = true; |
1070 | { |
- | 1071 | struct fetch_info_slist *temp = fetch_curl_multi; |
|
- | 1072 | ||
- | 1073 | curl_multi_perform(fetch_curl_multi); |
|
- | 1074 | ||
Line -... | Line 1075... | ||
- | 1075 | while(temp) |
|
- | 1076 | { |
|
- | 1077 | struct fetch_info_slist *new_temp = temp->next; |
|
- | 1078 | ||
- | 1079 | /* Check if the headers were received. thanks hidnplayr :P */ |
|
- | 1080 | if ((temp->handle->flags & FLAG_GOT_HEADER) && (!temp->fetch_curl_header_called)) |
|
- | 1081 | { |
|
- | 1082 | fetch_curl_header(temp->fetch_info); |
|
- | 1083 | temp->fetch_curl_header_called = true; |
|
- | 1084 | } |
|
- | 1085 | ||
- | 1086 | if(temp->handle->flags & FLAG_GOT_ALL_DATA) /* FLAG_GOT_ALL_DATA is set */ |
|
- | 1087 | { |
|
- | 1088 | /* DBG(("calling fetch_curl_data")); */ |
|
- | 1089 | /* LOG(("content in handle is : %s", temp->handle->content_ptr)); */ |
|
- | 1090 | fetch_curl_data(temp->fetch_info); |
|
290 | __menuet__debug_out("Inside curl_send_cb, Calling send_cb()\n"); |
1091 | fetch_curl_done(temp); |
- | 1092 | fetch_curl_multi = curl_multi_remove_handle(fetch_curl_multi, temp->fetch_info); |
|
- | 1093 | } |
|
- | 1094 | ||
- | 1095 | /*Add Error FLAG handle here TODO*/ |
|
- | 1096 | ||
- | 1097 | temp = new_temp; |
|
- | 1098 | } |
|
- | 1099 | } |
|
- | 1100 | /* TODO: Add more flags here */ |
|
291 | 1101 | ||
- | 1102 | /*TODO: Handle various conditions here, and set the status code accordinpgly when |
|
292 | fetch_send_callback(msg, ctx->fetchh); |
1103 | calling fetch_curL_done |
- | 1104 | */ |
|
- | 1105 | ||
- | 1106 | /* TODO: Probably decide the condition of the fetch here */ |
|
- | 1107 | ||
- | 1108 | /* The whole data recieved is shown by FLAG_GOT_ALL_DATA that is 1 SHL 2, meaning 4. Check for it right here. */ |
|
- | 1109 | ||
- | 1110 | /* process curl results */ |
|
- | 1111 | /*TODO: Needs to be replaced , no idea how to do it right now */ |
|
- | 1112 | /* Go through each http_msg handle from http.obj and check if it's done yet or not , |
|
- | 1113 | using the return value from http_receive. If done, remove it. Else let it stay. |
|
Line -... | Line 1114... | ||
- | 1114 | */ |
|
- | 1115 | /*TODO: This has been commented to figure out linker errors. |
|
- | 1116 | Uncomment this and combine this with the above chunk toget the main process loop |
|
293 | ctx->locked = false; |
1117 | */ |
294 | __menuet__debug_out("Returning ctx->aborted.\n"); |
1118 | /* curl_msg = curl_multi_info_read(fetch_curl_multi, &queue); */ |
295 | 1119 | /* while (curl_msg) { */ |
|
- | 1120 | /* switch (curl_msg->msg) { */ |
|
296 | return ctx->aborted; |
1121 | /* case CURLMSG_DONE: */ |
297 | } |
1122 | /* fetch_curl_done(curl_msg->easy_handle, */ |
- | 1123 | /* curl_msg->data.result); */ |
|
- | 1124 | /* break; */ |
|
- | 1125 | /* default: */ |
|
298 | 1126 | /* break; */ |
|
- | 1127 | /* } */ |
|
- | 1128 | /* curl_msg = curl_multi_info_read(fetch_curl_multi, &queue); */ |
|
- | 1129 | /* } */ |
|
299 | static bool fetch_curl_send_header(struct fetch_curl_context *ctx, |
1130 | |
300 | const char *fmt, ...) |
1131 | #ifdef FETCHER_CURLL_SCHEDULED |
301 | { |
1132 | if (running != 0) { |
302 | fetch_msg msg; |
1133 | schedule(1, (schedule_callback_fn)fetch_curl_poll, fetch_curl_poll); |
303 | char header[64]; |
1134 | } |
- | 1135 | #endif |
|
- | 1136 | /* LOG(("Returning froms fetch_curl_poll\n")); */ |
|
304 | va_list ap; |
1137 | } |
305 | __menuet__debug_out("Inside fetch_curl_send_header\n"); |
1138 | |
306 | va_start(ap, fmt); |
1139 | |
307 | 1140 | /** |
|
308 | vsnprintf(header, sizeof header, fmt, ap); |
1141 | * Handle a completed fetch (CURLMSG_DONE from curl_multi_info_read()). |
309 | 1142 | * |
|
- | 1143 | * \param curl_handle curl easy handle of fetch |
|
- | 1144 | */ |
|
- | 1145 | ||
- | 1146 | /* TODO: curl_easy_getinfo needs a replacement for getting the status of things around |
|
- | 1147 | SSL stuff needs to go away , as usual. |
|
- | 1148 | */ |
|
310 | va_end(ap); |
1149 | void fetch_curl_done(struct fetch_info_slist *node) |
- | 1150 | { |
|
- | 1151 | fetch_msg msg; |
|
- | 1152 | bool finished = false; |
|
- | 1153 | bool error = false; |
|
- | 1154 | bool cert = false; |
|
- | 1155 | bool abort_fetch; |
|
- | 1156 | struct curl_fetch_info *f = node->fetch_info; |
|
- | 1157 | char **_hideous_hack = (char **) (void *) &f; |
|
- | 1158 | KOSHcode code; |
|
- | 1159 | int result = CURLE_OK; |
|
- | 1160 | ||
- | 1161 | /* TODO: Remove this definition and get a better replacement for CURLINFO_PRIVATE */ |
|
- | 1162 | ||
- | 1163 | /* struct cert_info certs[MAX_CERTS]; */ |
|
- | 1164 | /* memset(certs, 0, sizeof(certs)); */ |
|
- | 1165 | ||
311 | __menuet__debug_out("Header is : "); |
1166 | /* find the structure associated with this fetch */ |
- | 1167 | /* For some reason, cURL thinks CURLINFO_PRIVATE should be a string?! */ |
|
- | 1168 | /* TODO: Do we really need curl_easy_getinfo? Our library struct provides us with all of this info already */ |
|
- | 1169 | /* code.code = curl_easy_getinfo(curl_handle, CURLINFO_PRIVATE, _hideous_hack); */ |
|
312 | __menuet__debug_out(header); |
1170 | /* assert(code.code == CURLE_OK); */ |
- | 1171 | ||
- | 1172 | abort_fetch = f->abort; |
|
- | 1173 | LOG(("done %s", nsurl_access(f->url))); |
|
- | 1174 | ||
- | 1175 | if (abort_fetch == false && (result == CURLE_OK || |
|
- | 1176 | (result == CURLE_WRITE_ERROR && f->stopped == false))) { |
|
- | 1177 | /* fetch completed normally or the server fed us a junk gzip |
|
313 | 1178 | * stream (usually in the form of garbage at the end of the |
|
- | 1179 | * stream). Curl will have fed us all but the last chunk of |
|
- | 1180 | * decoded data, which is sad as, if we'd received the last |
|
Line 314... | Line -... | ||
314 | msg.type = FETCH_HEADER; |
- | |
315 | msg.data.header_or_data.buf = (const uint8_t *) header; |
- | |
316 | msg.data.header_or_data.len = strlen(header); |
- | |
317 | __menuet__debug_out("\nCalling fetch_curl_send_callback\n"); |
1181 | * chunk, too, we'd be able to render the whole object. |
318 | - | ||
Line -... | Line 1182... | ||
- | 1182 | * As is, we'll just have to accept that the end of the |
|
- | 1183 | * object will be truncated in this case and leave it to |
|
- | 1184 | * the content handlers to cope. */ |
|
319 | fetch_curl_send_callback(&msg, ctx); |
1185 | if (f->stopped || |
- | 1186 | (!f->had_headers && |
|
- | 1187 | fetch_curl_process_headers(f))) |
|
- | 1188 | ; /* redirect with no body or similar */ |
|
- | 1189 | else |
|
- | 1190 | finished = true; |
|
- | 1191 | } else if (result == CURLE_PARTIAL_FILE) { |
|
- | 1192 | /* CURLE_PARTIAL_FILE occurs if the received body of a |
|
- | 1193 | * response is smaller than that specified in the |
|
- | 1194 | * Content-Length header. */ |
|
- | 1195 | if (!f->had_headers && fetch_curl_process_headers(f)) |
|
- | 1196 | ; /* redirect with partial body, or similar */ |
|
- | 1197 | else { |
|
- | 1198 | finished = true; |
|
- | 1199 | } |
|
- | 1200 | } else if (result == CURLE_WRITE_ERROR && f->stopped) { |
|
- | 1201 | /* CURLE_WRITE_ERROR occurs when fetch_curl_data |
|
- | 1202 | * returns 0, which we use to abort intentionally */ |
|
- | 1203 | ; |
|
- | 1204 | /* } else if (result == CURLE_SSL_PEER_CERTIFICATE || */ |
|
- | 1205 | /* result == CURLE_SSL_CACERT) { */ |
|
- | 1206 | /* memcpy(certs, f->cert_data, sizeof(certs)); */ |
|
- | 1207 | /* memset(f->cert_data, 0, sizeof(f->cert_data)); */ |
|
- | 1208 | /* cert = true; */ |
|
- | 1209 | } else { |
|
- | 1210 | LOG(("Unknown cURL response code %d", result)); |
|
- | 1211 | error = true; |
|
- | 1212 | } |
|
- | 1213 | ||
- | 1214 | fetch_curl_stop(node); |
|
- | 1215 | ||
- | 1216 | if (abort_fetch) |
|
- | 1217 | ; /* fetch was aborted: no callback */ |
|
- | 1218 | else if (finished) { |
|
- | 1219 | msg.type = FETCH_FINISHED; |
|
- | 1220 | __menuet__debug_out("Calling FETCH_FINISHED callback inside fetch_curl_data\n"); |
|
- | 1221 | fetch_send_callback(&msg, f->fetch_handle); |
|
- | 1222 | /* } else if (cert) { */ |
|
- | 1223 | /* int i; */ |
|
- | 1224 | /* BIO *mem; */ |
|
- | 1225 | /* BUF_MEM *buf; */ |
|
- | 1226 | /* /\* struct ssl_cert_info ssl_certs[MAX_CERTS]; *\/ */ |
|
- | 1227 | ||
- | 1228 | /* for (i = 0; i < MAX_CERTS && certs[i].cert; i++) { */ |
|
- | 1229 | /* ssl_certs[i].version = */ |
|
- | 1230 | /* X509_get_version(certs[i].cert); */ |
|
- | 1231 | ||
- | 1232 | /* mem = BIO_new(BIO_s_mem()); */ |
|
- | 1233 | /* ASN1_TIME_print(mem, */ |
|
- | 1234 | /* X509_get_notBefore(certs[i].cert)); */ |
|
- | 1235 | /* BIO_get_mem_ptr(mem, &buf); */ |
|
- | 1236 | /* (void) BIO_set_close(mem, BIO_NOCLOSE); */ |
|
- | 1237 | /* BIO_free(mem); */ |
|
- | 1238 | /* snprintf(ssl_certs[i].not_before, */ |
|
- | 1239 | /* min(sizeof ssl_certs[i].not_before, */ |
|
- | 1240 | /* (unsigned) buf->length + 1), */ |
|
- | 1241 | /* "%s", buf->data); */ |
|
- | 1242 | /* BUF_MEM_free(buf); */ |
|
- | 1243 | ||
- | 1244 | /* mem = BIO_new(BIO_s_mem()); */ |
|
- | 1245 | /* ASN1_TIME_print(mem, */ |
|
- | 1246 | /* X509_get_notAfter(certs[i].cert)); */ |
|
- | 1247 | /* BIO_get_mem_ptr(mem, &buf); */ |
|
- | 1248 | /* (void) BIO_set_close(mem, BIO_NOCLOSE); */ |
|
- | 1249 | /* BIO_free(mem); */ |
|
- | 1250 | /* snprintf(ssl_certs[i].not_after, */ |
|
- | 1251 | /* min(sizeof ssl_certs[i].not_after, */ |
|
- | 1252 | /* (unsigned) buf->length + 1), */ |
|
- | 1253 | /* "%s", buf->data); */ |
|
- | 1254 | /* BUF_MEM_free(buf); */ |
|
- | 1255 | ||
- | 1256 | /* ssl_certs[i].sig_type = */ |
|
- | 1257 | /* X509_get_signature_type(certs[i].cert); */ |
|
- | 1258 | /* ssl_certs[i].serial = */ |
|
- | 1259 | /* ASN1_INTEGER_get( */ |
|
- | 1260 | /* X509_get_serialNumber(certs[i].cert)); */ |
|
- | 1261 | /* mem = BIO_new(BIO_s_mem()); */ |
|
- | 1262 | /* X509_NAME_print_ex(mem, */ |
|
- | 1263 | /* X509_get_issuer_name(certs[i].cert), */ |
|
- | 1264 | /* 0, XN_FLAG_SEP_CPLUS_SPC | */ |
|
- | 1265 | /* XN_FLAG_DN_REV | XN_FLAG_FN_NONE); */ |
|
- | 1266 | /* BIO_get_mem_ptr(mem, &buf); */ |
|
- | 1267 | /* (void) BIO_set_close(mem, BIO_NOCLOSE); */ |
|
- | 1268 | /* BIO_free(mem); */ |
|
- | 1269 | /* snprintf(ssl_certs[i].issuer, */ |
|
- | 1270 | /* min(sizeof ssl_certs[i].issuer, */ |
|
- | 1271 | /* (unsigned) buf->length + 1), */ |
|
- | 1272 | /* "%s", buf->data); */ |
|
- | 1273 | /* BUF_MEM_free(buf); */ |
|
- | 1274 | ||
- | 1275 | /* mem = BIO_new(BIO_s_mem()); */ |
|
320 | 1276 | /* X509_NAME_print_ex(mem, */ |
|
- | 1277 | /* X509_get_subject_name(certs[i].cert), */ |
|
Line 321... | Line 1278... | ||
321 | __menuet__debug_out("Returning ctx->aborted\n"); |
1278 | /* 0, XN_FLAG_SEP_CPLUS_SPC | */ |
322 | return ctx->aborted; |
1279 | /* XN_FLAG_DN_REV | XN_FLAG_FN_NONE); */ |
323 | } |
1280 | /* BIO_get_mem_ptr(mem, &buf); */ |
Line -... | Line 1281... | ||
- | 1281 | /* (void) BIO_set_close(mem, BIO_NOCLOSE); */ |
|
324 | 1282 | /* BIO_free(mem); */ |
|
325 | static void fetch_curl_process_error(struct fetch_curl_context *ctx, int code) |
1283 | /* snprintf(ssl_certs[i].subject, */ |
326 | { |
- | |
327 | fetch_msg msg; |
- | |
Line -... | Line 1284... | ||
- | 1284 | /* min(sizeof ssl_certs[i].subject, */ |
|
- | 1285 | /* (unsigned) buf->length + 1), */ |
|
- | 1286 | /* "%s", buf->data); */ |
|
- | 1287 | /* BUF_MEM_free(buf); */ |
|
- | 1288 | ||
- | 1289 | /* ssl_certs[i].cert_type = */ |
|
- | 1290 | /* X509_certificate_type(certs[i].cert, */ |
|
- | 1291 | /* X509_get_pubkey(certs[i].cert)); */ |
|
- | 1292 | ||
- | 1293 | /* /\* and clean up *\/ */ |
|
328 | char buffer[1024]; |
1294 | /* certs[i].cert->references--; */ |
Line 329... | Line 1295... | ||
329 | const char *title; |
1295 | /* if (certs[i].cert->references == 0) */ |
330 | char key[8]; |
- | |
Line 331... | Line 1296... | ||
331 | 1296 | /* X509_free(certs[i].cert); */ |
|
332 | /* content is going to return error code */ |
1297 | /* } */ |
333 | fetch_set_http_code(ctx->fetchh, code); |
- | |
334 | - | ||
335 | /* content type */ |
- | |
Line 336... | Line 1298... | ||
336 | if (fetch_curl_send_header(ctx, "Content-Type: text/html")) |
1298 | |
337 | goto fetch_file_process_error_aborted; |
1299 | /* msg.type = FETCH_CERT_ERR; */ |
338 | - | ||
339 | snprintf(key, sizeof key, "HTTP%03d", code); |
- | |
Line -... | Line 1300... | ||
- | 1300 | /* msg.data.cert_err.certs = ssl_certs; */ |
|
- | 1301 | /* msg.data.cert_err.num_certs = i; */ |
|
- | 1302 | /* fetch_send_callback(&msg, f->fetch_handle); */ |
|
- | 1303 | } else if (error) { |
|
- | 1304 | if (result != CURLE_SSL_CONNECT_ERROR) { |
|
- | 1305 | msg.type = FETCH_ERROR; |
|
340 | title = messages_get(key); |
1306 | msg.data.error = fetch_error_buffer; |
- | 1307 | } else { |
|
- | 1308 | msg.type = FETCH_SSL_ERR; |
|
- | 1309 | } |
|
341 | 1310 | fetch_send_callback(&msg, f->fetch_handle); |
|
- | 1311 | } |
|
342 | snprintf(buffer, sizeof buffer, " |
1312 | |
- | 1313 | fetch_free(f->fetch_handle); |
|
- | 1314 | LOG(("Returning")); |
|
- | 1315 | } |
|
- | 1316 | ||
- | 1317 | ||
343 | " |
1318 | /** |
- | 1319 | * Callback function for fetch progress. |
|
- | 1320 | */ |
|
- | 1321 | ||
Line 344... | Line 1322... | ||
344 | " |
1322 | /* TODO: Useful for showing the fetch's progress. Need to figure out a way to hook this up with http.obj |
- | 1323 | More of an interface feature, but it'll be nice to have in a browser. |
|
Line 345... | Line -... | ||
345 | title, title, code, nsurl_access(ctx->url)); |
- | |
346 | - | ||
Line -... | Line 1324... | ||
- | 1324 | */ |
|
347 | msg.type = FETCH_DATA; |
1325 | |
- | 1326 | int fetch_curl_progress(void *clientp, double dltotal, double dlnow, |
|
- | 1327 | double ultotal, double ulnow) |
|
- | 1328 | { |
|
Line 348... | Line -... | ||
348 | msg.data.header_or_data.buf = (const uint8_t *) buffer; |
- | |
349 | msg.data.header_or_data.len = strlen(buffer); |
- | |
350 | if (fetch_curl_send_callback(&msg, ctx)) |
1329 | static char fetch_progress_buffer[256]; /**< Progress buffer for cURL */ |
351 | goto fetch_file_process_error_aborted; |
- | |
352 | - | ||
Line 353... | Line 1330... | ||
353 | msg.type = FETCH_FINISHED; |
1330 | struct curl_fetch_info *f = (struct curl_fetch_info *) clientp; |
354 | fetch_curl_send_callback(&msg, ctx); |
1331 | unsigned int time_now_cs; |
355 | 1332 | fetch_msg msg; |
|
- | 1333 | ||
356 | fetch_file_process_error_aborted: |
1334 | DBG("inside fetch_curl_progress()..\n"); |
- | 1335 | ||
- | 1336 | if (f->abort) |
|
- | 1337 | return 0; |
|
Line 357... | Line 1338... | ||
357 | return; |
1338 | |
- | 1339 | msg.type = FETCH_PROGRESS; |
|
- | 1340 | msg.data.progress = fetch_progress_buffer; |
|
- | 1341 | ||
- | 1342 | /* Rate limit each fetch's progress notifications to 2 a second */ |
|
Line 358... | Line 1343... | ||
358 | } |
1343 | #define UPDATES_PER_SECOND 2 |
359 | - | ||
360 | - | ||
361 | static void fetch_curl_process(struct fetch_curl_context *ctx) { |
- | |
Line -... | Line 1344... | ||
- | 1344 | #define UPDATE_DELAY_CS (100 / UPDATES_PER_SECOND) |
|
- | 1345 | time_now_cs = wallclock(); |
|
- | 1346 | if (time_now_cs - f->last_progress_update < UPDATE_DELAY_CS) |
|
- | 1347 | return 0; |
|
362 | char ps[96], str[128]; |
1348 | f->last_progress_update = time_now_cs; |
363 | sprintf(ps, "Yay! Path is %s", ctx->path); |
1349 | #undef UPDATE_DELAY_CS |
364 | execl ("/sys/@notify", ps, 0); |
1350 | #undef UPDATES_PERS_SECOND |
Line 365... | Line 1351... | ||
365 | 1351 | ||
366 | fetch_msg msg; |
- | |
367 | 1352 | if (dltotal > 0) { |
|
368 | __menuet__debug_out("AHOY!\n"); |
- | |
- | 1353 | snprintf(fetch_progress_buffer, 255, |
|
- | 1354 | messages_get("Progress"), |
|
- | 1355 | human_friendly_bytesize(dlnow), |
|
Line 369... | Line -... | ||
369 | struct http_msg *http_ahoy; |
- | |
370 | - | ||
- | 1356 | human_friendly_bytesize(dltotal)); |
|
371 | unsigned int wererat = 0; |
1357 | fetch_send_callback(&msg, f->fetch_handle); |
372 | char * pa=ctx->path; |
1358 | } else { |
- | 1359 | snprintf(fetch_progress_buffer, 255, |
|
Line -... | Line 1360... | ||
- | 1360 | messages_get("ProgressU"), |
|
- | 1361 | human_friendly_bytesize(dlnow)); |
|
- | 1362 | fetch_send_callback(&msg, f->fetch_handle); |
|
- | 1363 | } |
|
- | 1364 | ||
- | 1365 | return 0; |
|
- | 1366 | } |
|
- | 1367 | ||
- | 1368 | ||
- | 1369 | /** |
|
- | 1370 | * Ignore everything given to it. |
|
- | 1371 | * |
|
- | 1372 | * Used to ignore cURL debug. |
|
- | 1373 | */ |
|
- | 1374 | ||
- | 1375 | /*TODO: No idea what it does exactly, so let it be like it was*/ |
|
- | 1376 | ||
- | 1377 | int fetch_curl_ignore_debug(struct http_msg *handle, |
|
- | 1378 | kosh_infotype type, |
|
- | 1379 | char *data, |
|
- | 1380 | size_t size, |
|
- | 1381 | void *userptr) |
|
- | 1382 | { |
|
- | 1383 | return 0; |
|
373 | // asm volatile ("pusha"); // TODO: verify if this is still needed. It used to be an issue with the library but should be fixed now. |
1384 | } |
- | 1385 | ||
- | 1386 | void send_header_callbacks(char *header, unsigned int header_length, struct curl_fetch_info *f) |
|
- | 1387 | { |
|
374 | wererat = http_get(pa, NULL); // TODO: a pointer to additional headers (for cookies etc) can be placed here in the future. |
1388 | fetch_msg msg; |
- | 1389 | int newline = 0; |
|
375 | // asm volatile ("popa"); // .... |
1390 | int i; |
- | 1391 | ||
- | 1392 | msg.type = FETCH_HEADER; |
|
- | 1393 | ||
376 | 1394 | for(i = 0;i < header_length; i++) |
|
- | 1395 | { |
|
- | 1396 | if(header[i] == '\n') |
|
Line -... | Line 1397... | ||
- | 1397 | { |
|
- | 1398 | msg.data.header_or_data.len = i - newline; |
|
- | 1399 | msg.data.header_or_data.buf = (const uint8_t *) (header + newline); |
|
- | 1400 | /* LOG(("buf inside send_header_cb is : %.*s\n", i - newline, header+newline)); */ |
|
- | 1401 | ||
- | 1402 | newline = i+1; |
|
- | 1403 | fetch_send_callback(&msg, f->fetch_handle); |
|
- | 1404 | } |
|
- | 1405 | } |
|
- | 1406 | } |
|
- | 1407 | ||
- | 1408 | /** |
|
- | 1409 | * Callback function for cURL. |
|
- | 1410 | */ |
|
- | 1411 | /*TODO: Seems okay for now */ |
|
- | 1412 | ||
- | 1413 | size_t fetch_curl_data(void *_f) |
|
- | 1414 | { |
|
- | 1415 | struct curl_fetch_info *f = _f; |
|
- | 1416 | char *data = f->curl_handle->content_ptr; |
|
- | 1417 | KOSHcode code; |
|
- | 1418 | fetch_msg msg; |
|
- | 1419 | ||
- | 1420 | DBG("inside fetch_curl_data()..\n"); |
|
- | 1421 | ||
- | 1422 | /* if(f->curl_handle) */ |
|
- | 1423 | /* LOG(("curl_handle is not NULL\n")); */ |
|
- | 1424 | /* else */ |
|
- | 1425 | /* LOG(("curl_handle is NULL\n")); */ |
|
- | 1426 | ||
- | 1427 | LOG(("Will be Setting HTTP Code to : %u\n", f->curl_handle->status)); |
|
- | 1428 | ||
- | 1429 | /* ensure we only have to get this information once */ |
|
- | 1430 | if (!f->http_code) |
|
- | 1431 | { |
|
- | 1432 | /* TODO: For extracting the http response code of what happened in case we don't already have that. |
|
Line 377... | Line -... | ||
377 | if(wererat == 0) /* Error condition : http_get returned 0 */ |
- | |
378 | __menuet__debug_out("http_get() failed. [ Return Value 0 ]\n"); |
- | |
379 | else |
1433 | http_msg struct should have this info available for query. |
- | 1434 | ||
- | 1435 | code = curl_easy_getinfo(f->curl_handle, CURLINFO_HTTP_CODE, */ |
|
- | 1436 | /* &f->http_code); */ |
|
- | 1437 | __menuet__debug_out("f->http_code is 0\n"); |
|
- | 1438 | LOG(("f->http_code was 0\n")); |
|
- | 1439 | ||
- | 1440 | f->http_code = f->curl_handle->status; |
|
- | 1441 | fetch_set_http_code(f->fetch_handle, f->http_code); |
|
- | 1442 | ||
- | 1443 | /* assert(code.code == CURLE_OK); */ |
|
- | 1444 | } |
|
Line 380... | Line 1445... | ||
380 | __menuet__debug_out("http_get() Succeeded!. [ Return Value Non zero ]\n"); |
1445 | else |
- | 1446 | { |
|
- | 1447 | f->http_code = f->curl_handle->status; |
|
Line -... | Line 1448... | ||
- | 1448 | fetch_set_http_code(f->fetch_handle, f->http_code); |
|
381 | 1449 | } |
|
382 | __menuet__debug_out("HTTP GOT!\n"); |
1450 | |
- | 1451 | __menuet__debug_out("fetch_curl_data: "); |
|
383 | int result = 1337; |
1452 | |
- | 1453 | LOG(("fetch->http_code is : %ld\n", f->http_code)); |
|
Line 384... | Line 1454... | ||
384 | char result_str[12]; |
1454 | |
385 | char wererat_str[13]; |
- | |
386 | - | ||
387 | http_ahoy = wererat; |
- | |
Line 388... | Line 1455... | ||
388 | 1455 | /* ignore body if this is a 401 reply by skipping it and reset |
|
Line -... | Line 1456... | ||
- | 1456 | the HTTP response code to enable follow up fetches */ |
|
- | 1457 | ||
- | 1458 | if (f->http_code == 401) |
|
- | 1459 | { |
|
- | 1460 | f->http_code = 0; |
|
- | 1461 | return; |
|
- | 1462 | /* return size * nmemb; */ |
|
389 | sprintf (str, "Header %u bytes, content %u bytes, received %u bytes\n", http_ahoy->header_length, http_ahoy->content_length, http_ahoy->content_received); |
1463 | } |
- | 1464 | ||
- | 1465 | if (f->abort || (!f->had_headers && fetch_curl_process_headers(f))) { |
|
- | 1466 | __menuet__debug_out("Setting f->stopped = true\n"); |
|
- | 1467 | f->stopped = true; |
|
- | 1468 | return 0; |
|
390 | __menuet__debug_out(str); |
1469 | } |
- | 1470 | ||
- | 1471 | /* send data to the caller */ |
|
- | 1472 | ||
- | 1473 | LOG(("Inside fetch_curl_data, http_code is : %li", f->http_code)); |
|
- | 1474 | ||
- | 1475 | if(f->http_code == 200) |
|
- | 1476 | { |
|
- | 1477 | send_header_callbacks(&f->curl_handle->header, f->curl_handle->header_length, f); |
|
- | 1478 | LOG(("Finished sending header callbacks\n")); |
|
- | 1479 | ||
- | 1480 | if (f->abort) { |
|
- | 1481 | f->stopped = true; |
|
- | 1482 | return 0; |
|
- | 1483 | } |
|
- | 1484 | } |
|
391 | 1485 | else |
|
- | 1486 | LOG(("Error, http_code is not 200 but is : %u", f->http_code)); |
|
- | 1487 | ||
- | 1488 | msg.type = FETCH_DATA; |
|
- | 1489 | msg.data.header_or_data.buf = (const uint8_t *) data; |
|
- | 1490 | msg.data.header_or_data.len = (size_t)f->curl_handle->content_received; |
|
- | 1491 | /* LOG(("FETCH_DATA with buf = %s and length = %u", msg.data.header_or_data.buf, msg.data.header_or_data.len)); */ |
|
- | 1492 | fetch_send_callback(&msg, f->fetch_handle); |
|
- | 1493 | ||
- | 1494 | /* __menuet__debug_out("After Calling callback_send_fetch\n in fetch_curl_data"); */ |
|
- | 1495 | ||
- | 1496 | if (f->abort) { |
|
- | 1497 | f->stopped = true; |
|
- | 1498 | return 0; |
|
392 | __menuet__debug_out("Going into the do while loop for http_process\n"); |
1499 | } |
- | 1500 | ||
393 | 1501 | /* __menuet__debug_out("Exiting fetch_curl_data"); */ |
|
- | 1502 | /* return size * nmemb; */ |
|
- | 1503 | } |
|
- | 1504 | ||
- | 1505 | /** |
|
- | 1506 | Convertor function for converting a header field to its dedicated buffer |
|
- | 1507 | Also terminates with a NULL character so that the string is safe for further use. |
|
- | 1508 | field_name: Append the field name: to the generated string. Pass NULL for no field name. |
|
- | 1509 | source -> Refers to the original data which needs to be copied into dest. |
|
- | 1510 | dest -> destination. This will be allocated using malloc in the function as size is determined here.1 |
|
- | 1511 | ||
- | 1512 | dest uses a double pointer in order to allocate storage for the original pointer and not it's temporary copy. |
|
394 | do { |
1513 | |
- | 1514 | **/ |
|
- | 1515 | ||
- | 1516 | void convert_to_asciiz(char *field_name, char *source, char **dest) |
|
- | 1517 | { |
|
395 | // sprintf(result_str, "%d", result); |
1518 | char *i; |
Line 396... | Line 1519... | ||
396 | // __menuet__debug_out("Result is : "); |
1519 | |
397 | // __menuet__debug_out(result_str); |
1520 | if(source == NULL) |
- | 1521 | return; |
|
- | 1522 | ||
- | 1523 | if(field_name == NULL) |
|
- | 1524 | { |
|
- | 1525 | for(i = source; !isspace(*i); i++); |
|
- | 1526 | ||
- | 1527 | *dest = (char *)malloc(i - source + 1); /* Allocate a big enough buffer with +1 for NULL character */ |
|
- | 1528 | strncpy(*dest, source, i - source); /* Copy to buffer */ |
|
- | 1529 | (*dest)[i - source] = '\0'; |
|
- | 1530 | } |
|
- | 1531 | else |
|
398 | // __menuet__debug_out("\n"); |
1532 | { |
- | 1533 | char *temp; |
|
- | 1534 | for(i = source; !isspace(*i); i++); |
|
- | 1535 | ||
- | 1536 | *dest = (char *)malloc(i - source + 1 + strlen(field_name) + 2); /* Allocate a big enough buffer with +1 for NULL character */ |
|
- | 1537 | strcpy(*dest, field_name); |
|
- | 1538 | temp = *dest + strlen(field_name); |
|
- | 1539 | *temp = ':'; |
|
- | 1540 | temp++; |
|
- | 1541 | *temp = ' '; |
|
- | 1542 | temp++; |
|
- | 1543 | ||
- | 1544 | strncpy(temp, source, i - source); /* Copy to buffer */ |
|
- | 1545 | temp[i - source] = '\0'; |
|
- | 1546 | } |
|
- | 1547 | ||
- | 1548 | } |
|
- | 1549 | ||
- | 1550 | /** |
|
- | 1551 | * Callback function for headers. |
|
- | 1552 | * |
|
- | 1553 | * See RFC 2616 4.2. |
|
- | 1554 | */ |
|
- | 1555 | ||
- | 1556 | /*TODO: Seems okay for now */ |
|
- | 1557 | /* Called when the headers have been received. A callback should be sent for each header line and not the entire thing at once*/ |
|
- | 1558 | ||
- | 1559 | void fetch_curl_header(void *_f) /* Change type to curl_fetch_infO? TODO*/ |
|
- | 1560 | { |
|
- | 1561 | struct curl_fetch_info *f = _f; |
|
- | 1562 | struct http_msg *handle = f->curl_handle; |
|
- | 1563 | char *realm = NULL; /*Remove me ? TODO*/ |
|
- | 1564 | char *cookie = NULL; |
|
- | 1565 | char *content_length = NULL; |
|
- | 1566 | char *content_type = NULL; |
|
- | 1567 | int realm_start; |
|
- | 1568 | int i; |
|
- | 1569 | fetch_msg msg; |
|
- | 1570 | ||
- | 1571 | /* size *= nmemb; */ /* ???? */ |
|
- | 1572 | ||
- | 1573 | __menuet__debug_out("inside fetch_curl_header()..\n"); |
|
- | 1574 | ||
- | 1575 | if (f->abort) { |
|
- | 1576 | f->stopped = true; |
|
- | 1577 | return; |
|
- | 1578 | } |
|
- | 1579 | ||
- | 1580 | f->http_code = handle->status; |
|
- | 1581 | fetch_set_http_code(f->fetch_handle, f->http_code); |
|
- | 1582 | ||
- | 1583 | LOG(("fetch->http_code is : %ld\n", f->http_code)); |
|
- | 1584 | ||
- | 1585 | convert_to_asciiz(NULL,http_find_header_field(f->curl_handle, "location"), &f->location); |
|
- | 1586 | convert_to_asciiz("content-length", http_find_header_field(f->curl_handle, "content-length"), &content_length); |
|
- | 1587 | convert_to_asciiz("set-cookie", http_find_header_field(f->curl_handle, "set-cookie"), &cookie); |
|
- | 1588 | ||
- | 1589 | f->content_length = atol(content_length); |
|
- | 1590 | ||
- | 1591 | if(cookie) |
|
- | 1592 | fetch_set_cookie(f->fetch_handle, cookie+12); |
|
- | 1593 | return; |
|
- | 1594 | /* if(f->had_headers) */ |
|
- | 1595 | /* __menuet__debug_out("curl_fetch_data BEFORE: Had headers is true!\n"); */ |
|
- | 1596 | /* else */ |
|
- | 1597 | /* __menuet__debug_out("curl_fetch_data BEFORE: Had headers is false!\n"); */ |
|
- | 1598 | ||
- | 1599 | /* LOG(("Calling fetch_send_callback from fetch_curl_header")); */ |
|
- | 1600 | /* fetch_send_callback(&msg, f->fetch_handle); */ |
|
- | 1601 | /* LOG(("AFTER Calling fetch_send_callback from fetch_curl_header")); */ |
|
- | 1602 | ||
- | 1603 | /* if(f->had_headers) */ |
|
- | 1604 | /* __menuet__debug_out("curl_fetch_data : Had headers is true!\n"); */ |
|
- | 1605 | /* else */ |
|
- | 1606 | /* __menuet__debug_out("curl_fetch_data : Had headers is false!\n"); */ |
|
- | 1607 | ||
- | 1608 | /* Remember to use lower case names for header field names for http.obj */ |
|
- | 1609 | /* We extract only these fields */ |
|
- | 1610 | ||
- | 1611 | /* convert_to_asciiz("content-length", http_find_header_field(f->curl_handle, "content-length"), &content_length); */ |
|
- | 1612 | /* convert_to_asciiz("content-type", http_find_header_field(f->curl_handle, "content-type"), &content_type); */ |
|
- | 1613 | ||
- | 1614 | /* TODO: Uncomment following line and add more fields if required later */ |
|
- | 1615 | /* convert_to_asciiz("www-authenticate", http_find_header_field(f->curl_handle, "www-authenticate"), &realm); */ |
|
- | 1616 | ||
- | 1617 | /* LOG(("The &header is : %s", &(f->curl_handle->header))); */ |
|
- | 1618 | ||
- | 1619 | /* if(f->location) */ |
|
- | 1620 | /* { */ |
|
- | 1621 | /* LOG(("Setting data buf to %s with length %d", f->location, strlen(f->location))); */ |
|
- | 1622 | /* msg.type = FETCH_HEADER; */ |
|
- | 1623 | /* msg.data.header_or_data.buf = (const uint8_t *) f->location; */ |
|
- | 1624 | /* msg.data.header_or_data.len = strlen(f->location); */ |
|
- | 1625 | /* fetch_send_callback(&msg, f->fetch_handle); */ |
|
- | 1626 | /* } */ |
|
- | 1627 | ||
- | 1628 | /* if(content_type) */ |
|
- | 1629 | /* { */ |
|
- | 1630 | /* LOG(("Setting data buf to %s with length %d", content_type, strlen(content_type))); */ |
|
- | 1631 | /* f->content_length = atoi(content_type); */ |
|
- | 1632 | /* msg.type = FETCH_HEADER; */ |
|
- | 1633 | /* msg.data.header_or_data.buf = (const uint8_t *) content_type; */ |
|
- | 1634 | /* msg.data.header_or_data.len = strlen(content_type); */ |
|
- | 1635 | /* fetch_send_callback(&msg, f->fetch_handle); */ |
|
- | 1636 | /* } */ |
|
- | 1637 | ||
- | 1638 | /* if(content_length) */ |
|
- | 1639 | /* { */ |
|
- | 1640 | /* f->content_length = atoi(content_length); */ |
|
- | 1641 | /* msg.type = FETCH_HEADER; */ |
|
- | 1642 | /* msg.data.header_or_data.buf = (const uint8_t *) content_length; */ |
|
- | 1643 | /* msg.data.header_or_data.len = strlen(content_length); */ |
|
- | 1644 | /* fetch_send_callback(&msg, f->fetch_handle); */ |
|
- | 1645 | /* } */ |
|
- | 1646 | ||
- | 1647 | /* Set appropriate fetch properties */ |
|
- | 1648 | /* if(cookie) */ |
|
- | 1649 | /* { */ |
|
- | 1650 | /* fetch_set_cookie(f->fetch_handle, cookie); */ |
|
- | 1651 | /* msg.type = FETCH_HEADER; */ |
|
- | 1652 | /* msg.data.header_or_data.buf = (const uint8_t *) cookie; */ |
|
- | 1653 | /* msg.data.header_or_data.len = strlen(cookie); */ |
|
- | 1654 | /* fetch_send_callback(&msg, f->fetch_handle); */ |
|
- | 1655 | /* } */ |
|
- | 1656 | ||
- | 1657 | /* if(realm) /\* Don't worry about this for now , fix it later TODO *\/ */ |
|
- | 1658 | /* { */ |
|
- | 1659 | /* /\* For getting the realm, this was used as an example : ('WWW-Authenticate: Basic realm="My Realm"') *\/ */ |
|
- | 1660 | ||
- | 1661 | /* for(i = strlen("www-authenticate: "); realm[i]; i++) */ |
|
- | 1662 | /* if(realm[i] == '"') { */ |
|
- | 1663 | /* realm_start = i+1; */ |
|
- | 1664 | /* break; */ |
|
- | 1665 | /* } */ |
|
- | 1666 | ||
- | 1667 | /* for(i = realm_start ; realm[i]; i++) */ |
|
- | 1668 | /* if(realm[i] == '"') { */ |
|
- | 1669 | /* realm[i] = '\0'; */ |
|
- | 1670 | /* break; */ |
|
- | 1671 | /* } */ |
|
- | 1672 | ||
- | 1673 | /* f->realm = realm; */ |
|
- | 1674 | /* } */ |
|
- | 1675 | ||
- | 1676 | /* TODO: call the fetch_callback for www authenticate field and any other fields that will be added here later */ |
|
- | 1677 | ||
- | 1678 | /* LOG(("fetch->http_code is ( AT THE END of f_c_header): %ld\n", f->http_code)); */ |
|
- | 1679 | /* __menuet__debug_out("Leaving fetch_curl_header\n"); */ |
|
- | 1680 | ||
- | 1681 | /* if(f->had_headers) */ |
|
- | 1682 | /* __menuet__debug_out("curl_fetch_data : Had headers is true!\n"); */ |
|
- | 1683 | /* else */ |
|
Line -... | Line 1684... | ||
- | 1684 | /* __menuet__debug_out("curl_fetch_data : Had headers is false!\n"); */ |
|
- | 1685 | ||
399 | 1686 | /* f->http_code = handle->status; */ |
|
Line 400... | Line 1687... | ||
400 | // asm volatile ("pusha"); // TODO: verify if this is still needed. It used to be an issue with the library but should be fixed now. |
1687 | /* fetch_set_http_code(f->fetch_handle, f->http_code); */ |
401 | result = http_process(wererat); |
1688 | |
402 | // asm volatile ("popa"); // .... |
1689 | /* #define SKIP_ST(o) for (i = (o); i < (int) size && (data[i] == ' ' || data[i] == '\t'); i++) */ |
403 | } while ((result != 0)); |
1690 | |
404 | 1691 | /* if (12 < size && strncasecmp(data, "Location:", 9) == 0) { */ |
|
- | 1692 | /* /\* extract Location header *\/ */ |
|
Line 405... | Line 1693... | ||
405 | __menuet__debug_out("After the do while loop for http_process.\n"); |
1693 | /* free(f->location); */ |
406 | 1694 | /* f->location = malloc(size); */ |
|
- | 1695 | /* if (!f->location) { */ |
|
407 | if(result == 0) |
1696 | /* LOG(("malloc failed")); */ |
- | 1697 | /* return size; */ |
|
- | 1698 | /* } */ |
|
- | 1699 | /* SKIP_ST(9); */ |
|
- | 1700 | /* strncpy(f->location, data + i, size - i); */ |
|
- | 1701 | /* f->location[size - i] = '\0'; */ |
|
- | 1702 | /* for (i = size - i - 1; i >= 0 && */ |
|
- | 1703 | /* (f->location[i] == ' ' || */ |
|
- | 1704 | /* f->location[i] == '\t' || */ |
|
- | 1705 | /* f->location[i] == '\r' || */ |
|
- | 1706 | /* f->location[i] == '\n'); i--) */ |
|
- | 1707 | /* f->location[i] = '\0'; */ |
|
- | 1708 | /* } else if (15 < size && strncasecmp(data, "Content-Length:", 15) == 0) { */ |
|
- | 1709 | /* /\* extract Content-Length header *\/ */ |
|
- | 1710 | /* SKIP_ST(15); */ |
|
- | 1711 | /* if (i < (int)size && '0' <= data[i] && data[i] <= '9') */ |
|
- | 1712 | /* f->content_length = atol(data + i); */ |
|
- | 1713 | /* } else if (17 < size && strncasecmp(data, "WWW-Authenticate:", 17) == 0) { */ |
|
- | 1714 | /* /\* extract the first Realm from WWW-Authenticate header *\/ */ |
|
- | 1715 | /* SKIP_ST(17); */ |
|
- | 1716 | ||
- | 1717 | /* while (i < (int) size - 5 && */ |
|
- | 1718 | /* strncasecmp(data + i, "realm", 5)) */ |
|
- | 1719 | /* i++; */ |
|
- | 1720 | /* while (i < (int) size - 1 && data[++i] != '"') */ |
|
- | 1721 | /* /\* *\/; */ |
|
- | 1722 | /* i++; */ |
|
- | 1723 | ||
- | 1724 | /* if (i < (int) size) { */ |
|
- | 1725 | /* size_t end = i; */ |
|
- | 1726 | ||
- | 1727 | /* while (end < size && data[end] != '"') */ |
|
- | 1728 | /* ++end; */ |
|
- | 1729 | ||
- | 1730 | /* if (end < size) { */ |
|
- | 1731 | /* free(f->realm); */ |
|
- | 1732 | /* f->realm = malloc(end - i + 1); */ |
|
- | 1733 | /* if (f->realm != NULL) { */ |
|
- | 1734 | /* strncpy(f->realm, data + i, end - i); */ |
|
- | 1735 | /* f->realm[end - i] = '\0'; */ |
|
- | 1736 | /* } */ |
|
- | 1737 | /* } */ |
|
- | 1738 | /* } */ |
|
- | 1739 | /* } else if (11 < size && strncasecmp(data, "Set-Cookie:", 11) == 0) { */ |
|
- | 1740 | /* /\* extract Set-Cookie header *\/ */ |
|
- | 1741 | /* SKIP_ST(11); */ |
|
- | 1742 | ||
- | 1743 | /* fetch_set_cookie(f->fetch_handle, &data[i]); */ |
|
Line -... | Line 1744... | ||
- | 1744 | /* } */ |
|
- | 1745 | ||
- | 1746 | /* return size; */ |
|
- | 1747 | /* #undef SKIP_ST */ |
|
- | 1748 | } |
|
- | 1749 | ||
408 | __menuet__debug_out("http_process() worked successfully!\n"); |
1750 | /** |
- | 1751 | * Find the status code and content type and inform the caller. |
|
- | 1752 | * |
|
- | 1753 | * Return true if the fetch is being aborted. |
|
- | 1754 | */ |
|
- | 1755 | /*TODO: Handling the http status codes here and performing accordingly*/ |
|
- | 1756 | ||
- | 1757 | bool fetch_curl_process_headers(struct curl_fetch_info *f) |
|
- | 1758 | { |
|
- | 1759 | long http_code; |
|
- | 1760 | KOSHcode code; |
|
Line 409... | Line -... | ||
409 | else |
- | |
Line 410... | Line -... | ||
410 | __menuet__debug_out("http_process() failed!\n"); |
- | |
411 | - | ||
412 | // http_ahoy = wererat; // really needed again?? |
1761 | fetch_msg msg; |
413 | sprintf (str, "Header %u bytes, content %u bytes, received %u bytes\n", http_ahoy->header_length, http_ahoy->content_length, http_ahoy->content_received); |
- | |
414 | __menuet__debug_out(str); |
1762 | |
415 | 1763 | __menuet__debug_out("Setting had_headers to true\n"); |
|
416 | /* fetch is going to be successful */ |
- | |
417 | __menuet__debug_out("Calling fetch_set_http_code call\n"); |
- | |
418 | fetch_set_http_code(ctx->fetchh, http_ahoy->status); |
1764 | |
- | 1765 | f->had_headers = true; |
|
- | 1766 | ||
- | 1767 | http_code = f->curl_handle->status; |
|
- | 1768 | LOG(("Inside fetch_curl_process_headers..HTTP CODE : %ld\n", http_code)); |
|
- | 1769 | ||
- | 1770 | if (!f->http_code) |
|
- | 1771 | { |
|
- | 1772 | /* TODO: Handle this like another similar piece of code in the file with HTTP_CODE_CURLINFO */ |
|
- | 1773 | /* code = curl_easy_getinfo(f->curl_handle, CURLINFO_HTTP_CODE, */ |
|
- | 1774 | /* &f->http_code); */ |
|
- | 1775 | /* Replaced with this : */ |
|
- | 1776 | /* Have a fetch_set_http_code here? TODO*/ |
|
- | 1777 | ||
- | 1778 | f->http_code = http_code; |
|
419 | __menuet__debug_out("Returned from fetch_set_http_code call\n"); |
1779 | fetch_set_http_code(f->fetch_handle, f->http_code); |
420 | 1780 | /* assert(code.code == CURLE_OK); */ |
|
- | 1781 | } |
|
- | 1782 | ||
- | 1783 | LOG(("HTTP status code %li\n", http_code)); |
|
- | 1784 | ||
421 | /* Any callback can result in the fetch being aborted. |
1785 | if (http_code == 304 && !f->post_urlenc && !f->post_multipart) { |
- | 1786 | /* Not Modified && GET request */ |
|
- | 1787 | msg.type = FETCH_NOTMODIFIED; |
|
- | 1788 | fetch_send_callback(&msg, f->fetch_handle); |
|
- | 1789 | return true; |
|
- | 1790 | } |
|
- | 1791 | ||
- | 1792 | /* handle HTTP redirects (3xx response codes) */ |
|
- | 1793 | if (300 <= http_code && http_code < 400) { |
|
- | 1794 | LOG(("FETCH_REDIRECT, '%s'", f->location)); |
|
- | 1795 | msg.type = FETCH_REDIRECT; |
|
- | 1796 | msg.data.redirect = f->location; |
|
- | 1797 | fetch_send_callback(&msg, f->fetch_handle); |
|
- | 1798 | return true; |
|
- | 1799 | } |
|
- | 1800 | ||
- | 1801 | /* handle HTTP 401 (Authentication errors) */ |
|
- | 1802 | if (http_code == 401) { |
|
- | 1803 | msg.type = FETCH_AUTH; |
|
- | 1804 | msg.data.auth.realm = f->realm; |
|
- | 1805 | fetch_send_callback(&msg, f->fetch_handle); |
|
- | 1806 | return true; |
|
- | 1807 | } |
|
- | 1808 | ||
- | 1809 | /* handle HTTP errors (non 2xx response codes) */ |
|
- | 1810 | if (f->only_2xx && strncmp(nsurl_access(f->url), "http", 4) == 0 && |
|
- | 1811 | (http_code < 200 || 299 < http_code)) { |
|
- | 1812 | msg.type = FETCH_ERROR; |
|
- | 1813 | DBG("FETCH_ERROR\n"); |
|
- | 1814 | msg.data.error = messages_get("Not2xx"); |
|
- | 1815 | fetch_send_callback(&msg, f->fetch_handle); |
|
- | 1816 | return true; |
|
- | 1817 | } |
|
- | 1818 | ||
- | 1819 | if (f->abort) |
|
- | 1820 | return true; |
|
- | 1821 | ||
- | 1822 | DBG("Returning false from fetch_curl_process_headers()\n"); |
|
- | 1823 | ||
- | 1824 | return false; |
|
- | 1825 | } |
|
- | 1826 | ||
- | 1827 | ||
- | 1828 | /** |
|
- | 1829 | * Convert a list of struct ::fetch_multipart_data to a list of |
|
- | 1830 | * struct curl_httppost for libcurl. |
|
- | 1831 | */ |
|
- | 1832 | ||
- | 1833 | /* TODO: Not sure how to handle multipart data yet, but hopefully it'll be figured out soon */ |
|
- | 1834 | /* TODO: Seems like the forms that are being created use sequential fields, so we can probably craft the same */ |
|
- | 1835 | /* using post from http,obj */ |
|
- | 1836 | ||
422 | * Therefore, we _must_ check for this after _every_ call to |
1837 | struct curl_httppost * |
Line 423... | Line -... | ||
423 | * fetch_file_send_callback(). |
- | |
424 | */ |
- | |
425 | - | ||
426 | __menuet__debug_out("Calling fetch_curl_send_header: 1\n"); |
1838 | fetch_curl_post_convert(const struct fetch_multipart_data *control) |
427 | if (fetch_curl_send_header(ctx, "Content-Type: %s", |
1839 | { |
Line -... | Line 1840... | ||
- | 1840 | struct curl_httppost *post = 0, *last = 0; |
|
- | 1841 | /* TODO: CURLFORMcode code; */ |
|
428 | fetch_filetype(ctx->path))) |
1842 | |
429 | goto fetch_file_process_aborted; |
1843 | DBG("inside fetch_curl_post_convert()..\n"); |
430 | 1844 | ||
431 | - | ||
Line -... | Line 1845... | ||
- | 1845 | for (; control; control = control->next) { |
|
- | 1846 | if (control->file) { |
|
- | 1847 | char *leafname = 0; |
|
- | 1848 | ||
- | 1849 | leafname = filename_from_path(control->value); |
|
- | 1850 | ||
- | 1851 | if (leafname == NULL) |
|
- | 1852 | continue; |
|
- | 1853 | ||
- | 1854 | /* We have to special case filenames of "", so curl |
|
- | 1855 | * a) actually attempts the fetch and |
|
- | 1856 | * b) doesn't attempt to open the file "" |
|
432 | /* main data loop */ |
1857 | */ |
- | 1858 | if (control->value[0] == '\0') { |
|
- | 1859 | /* dummy buffer - needs to be static so |
|
- | 1860 | * pointer's still valid when we go out |
|
- | 1861 | * of scope (not that libcurl should be |
|
433 | __menuet__debug_out("inside main data loop\n"); |
1862 | * attempting to access it, of course). */ |
- | 1863 | /* static char buf; */ |
|
Line -... | Line 1864... | ||
- | 1864 | /* code = curl_formadd(&post, &last, */ |
|
- | 1865 | /* CURLFORM_COPYNAME, control->name, */ |
|
434 | msg.type = FETCH_DATA; |
1866 | /* CURLFORM_BUFFER, control->value, */ |
435 | 1867 | /* /\* needed, as basename("") == "." *\/ */ |
|
436 | msg.data.header_or_data.buf = http_ahoy->content_ptr; // lets pray this works..x2 |
1868 | /* CURLFORM_FILENAME, "", */ |
437 | - | ||
Line -... | Line 1869... | ||
- | 1869 | /* CURLFORM_BUFFERPTR, &buf, */ |
|
- | 1870 | /* CURLFORM_BUFFERLENGTH, 0, */ |
|
- | 1871 | /* CURLFORM_CONTENTTYPE, */ |
|
- | 1872 | /* "application/octet-stream", */ |
|
- | 1873 | /* CURLFORM_END); */ |
|
- | 1874 | /* if (code != CURL_FORMADD_OK) */ |
|
- | 1875 | /* LOG(("curl_formadd: %d (%s)", */ |
|
- | 1876 | /* code, control->name)); */ |
|
- | 1877 | } else { |
|
- | 1878 | /* char *mimetype = fetch_mimetype(control->value); */ |
|
- | 1879 | /* code = curl_formadd(&post, &last, */ |
|
- | 1880 | /* CURLFORM_COPYNAME, control->name, */ |
|
- | 1881 | /* CURLFORM_FILE, control->value, */ |
|
- | 1882 | /* CURLFORM_FILENAME, leafname, */ |
|
- | 1883 | /* CURLFORM_CONTENTTYPE, */ |
|
- | 1884 | /* (mimetype != 0 ? mimetype : "text/plain"), */ |
|
- | 1885 | /* CURLFORM_END); */ |
|
- | 1886 | /* if (code != CURL_FORMADD_OK) */ |
|
- | 1887 | /* LOG(("curl_formadd: %d (%s=%s)", */ |
|
- | 1888 | /* code, control->name, */ |
|
- | 1889 | /* control->value)); */ |
|
- | 1890 | /* free(mimetype); */ |
|
- | 1891 | } |
|
- | 1892 | free(leafname); |
|
- | 1893 | } |
|
- | 1894 | else { |
|
- | 1895 | /* code = curl_formadd(&post, &last, */ |
|
- | 1896 | /* CURLFORM_COPYNAME, control->name, */ |
|
- | 1897 | /* CURLFORM_COPYCONTENTS, control->value, */ |
|
- | 1898 | /* CURLFORM_END); */ |
|
438 | msg.data.header_or_data.len = http_ahoy->content_received; |
1899 | /* if (code != CURL_FORMADD_OK) */ |
- | 1900 | /* LOG(("curl_formadd: %d (%s=%s)", code, */ |
|
- | 1901 | /* control->name, */ |
|
- | 1902 | /* control->value)); */ |
|
Line -... | Line 1903... | ||
- | 1903 | } |
|
- | 1904 | } |
|
Line -... | Line 1905... | ||
- | 1905 | ||
- | 1906 | return post; |
|
Line -... | Line 1907... | ||
- | 1907 | } |
|
- | 1908 | ||
- | 1909 | ||
- | 1910 | /** |
|
- | 1911 | * OpenSSL Certificate verification callback |
|
- | 1912 | * Stores certificate details in fetch struct. |
|
- | 1913 | */ |
|
- | 1914 | ||
- | 1915 | /* TODO: SSL Stuff, useless as of now */ |
|
- | 1916 | ||
- | 1917 | /* int fetch_curl_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) */ |
|
- | 1918 | /* { */ |
|
- | 1919 | /* X509 *cert = X509_STORE_CTX_get_current_cert(x509_ctx); */ |
|
- | 1920 | /* int depth = X509_STORE_CTX_get_error_depth(x509_ctx); */ |
|
- | 1921 | /* int err = X509_STORE_CTX_get_error(x509_ctx); */ |
|
Line -... | Line 1922... | ||
- | 1922 | /* struct curl_fetch_info *f = X509_STORE_CTX_get_app_data(x509_ctx); */ |
|
- | 1923 | ||
- | 1924 | /* /\* save the certificate by incrementing the reference count and */ |
|
- | 1925 | /* * keeping a pointer *\/ */ |
|
- | 1926 | /* if (depth < MAX_CERTS && !f->cert_data[depth].cert) { */ |
|
- | 1927 | /* f->cert_data[depth].cert = cert; */ |
|
- | 1928 | /* f->cert_data[depth].err = err; */ |
|
- | 1929 | /* cert->references++; */ |
|
- | 1930 | /* } */ |
|
- | 1931 | ||
- | 1932 | /* return preverify_ok; */ |
|
- | 1933 | /* } */ |
|
- | 1934 | ||
- | 1935 | ||
- | 1936 | /** |
|
- | 1937 | * OpenSSL certificate chain verification callback |
|
- | 1938 | * Verifies certificate chain, setting up context for fetch_curl_verify_callback |
|
- | 1939 | */ |
|
- | 1940 | ||
- | 1941 | /* int fetch_curl_cert_verify_callback(X509_STORE_CTX *x509_ctx, void *parm) */ |
|
- | 1942 | /* { */ |
|
- | 1943 | /* int ok; */ |
|
- | 1944 | ||
- | 1945 | /* /\* Store fetch struct in context for verify callback *\/ */ |
|
- | 1946 | /* ok = X509_STORE_CTX_set_app_data(x509_ctx, parm); */ |
|
- | 1947 | ||
- | 1948 | /* /\* and verify the certificate chain *\/ */ |
|
- | 1949 | /* if (ok) */ |
|
- | 1950 | /* ok = X509_verify_cert(x509_ctx); */ |
|
- | 1951 | ||
- | 1952 | /* return ok; */ |
|
- | 1953 | /* } */ |
|
- | 1954 | ||
- | 1955 | struct curl_slist *curl_slist_append(struct curl_slist * list, const char * string ) |
|
- | 1956 | { |
|
- | 1957 | struct curl_slist *newnode = NULL; |
|
- | 1958 | DBG("Inside curl_slist_append..\n"); |
|
- | 1959 | newnode = malloc(sizeof(struct curl_slist)); |
|
- | 1960 | ||
- | 1961 | if(newnode == NULL) |
|
- | 1962 | return NULL; |
|
- | 1963 | ||
- | 1964 | strcpy(newnode->data, string); |
|
- | 1965 | ||
- | 1966 | newnode->next = NULL; |
|
- | 1967 | ||
- | 1968 | if(!list) |
|
- | 1969 | { |
|
- | 1970 | list = newnode; |
|
- | 1971 | } |
|
- | 1972 | else /*list isn't null*/ |
|
- | 1973 | { |
|
- | 1974 | struct curl_slist *temp = list; |
|
- | 1975 | ||
- | 1976 | while(temp->next!=NULL) |
|
- | 1977 | temp = temp->next; |
|
- | 1978 | ||
- | 1979 | temp->next = newnode; |
|
- | 1980 | } |
|
- | 1981 | ||
- | 1982 | return list; |
|
- | 1983 | } |
|
- | 1984 | ||
- | 1985 | void curl_slist_free_all(struct curl_slist *list) |
|
- | 1986 | { |
|
- | 1987 | struct curl_slist *temp = list; |
|
- | 1988 | DBG("Inside curl_slist_free_all..\n"); |
|
- | 1989 | ||
- | 1990 | while(list) |
|
- | 1991 | { |
|
- | 1992 | temp = list->next; |
|
- | 1993 | free(list); |
|
- | 1994 | list = temp; |
|
- | 1995 | } |
|
- | 1996 | } |
|
- | 1997 | ||
- | 1998 | int curl_multi_add_handle(struct fetch_info_slist **multi_handle, struct curl_fetch_info *new_fetch) |
|
- | 1999 | { |
|
- | 2000 | DBG("Inside curl_multi_add_handle..Adding handle\n"); |
|
- | 2001 | ||
- | 2002 | if(*multi_handle == NULL) |
|
- | 2003 | { |
|
- | 2004 | struct fetch_info_slist *new_node = (struct fetch_info_slist *)malloc(sizeof(struct fetch_info_slist)); |
|
- | 2005 | ||
- | 2006 | if(new_node == NULL || new_fetch == NULL) //add failture for malloc here TODO |
|
- | 2007 | return CURLM_FAILED; |
|
- | 2008 | ||
- | 2009 | new_node->fetch_info = new_fetch; |
|
- | 2010 | new_node->handle = new_fetch->curl_handle; |
|
- | 2011 | new_node->fetch_curl_header_called = false; |
|
- | 2012 | *multi_handle = new_node; |
|
- | 2013 | (*multi_handle)->next = NULL; |
|
- | 2014 | } |
|
- | 2015 | else |
|
- | 2016 | { |
|
- | 2017 | struct fetch_info_slist *temp = *multi_handle; |
|
- | 2018 | struct fetch_info_slist *new_node = (struct fetch_info_slist *)malloc(sizeof(struct fetch_info_slist)); |
|
- | 2019 | ||
- | 2020 | if(new_node == NULL || new_fetch == NULL) //add failture for malloc here TODO |
|
- | 2021 | return CURLM_FAILED; |
|
- | 2022 | ||
- | 2023 | while(temp->next) |
|
- | 2024 | { |
|
- | 2025 | temp = temp->next; |
|
- | 2026 | } |
|
- | 2027 | ||
- | 2028 | new_node->fetch_info = new_fetch; |
|
- | 2029 | new_node->handle = new_fetch->curl_handle; |
|
- | 2030 | new_node->next = NULL; |
|
- | 2031 | new_node->fetch_curl_header_called = false; |
|
- | 2032 | temp->next = new_node; |
|
- | 2033 | } |
|
- | 2034 | ||
- | 2035 | return CURLM_OK; |
|
- | 2036 | } |