Subversion Repositories Kolibri OS

Rev

Rev 3584 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3584 Rev 3616
1
/*
1
/*
2
 * Copyright 2006 Daniel Silverstone 
2
 * Copyright 2006 Daniel Silverstone 
3
 * Copyright 2007 James Bursa 
3
 * Copyright 2007 James Bursa 
4
 * Copyright 2003 Phil Mellor 
4
 * Copyright 2003 Phil Mellor 
5
 *
5
 *
6
 * This file is part of NetSurf.
6
 * This file is part of NetSurf.
7
 *
7
 *
8
 * NetSurf is free software; you can redistribute it and/or modify
8
 * NetSurf is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; version 2 of the License.
10
 * the Free Software Foundation; version 2 of the License.
11
 *
11
 *
12
 * NetSurf is distributed in the hope that it will be useful,
12
 * NetSurf is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
15
 * GNU General Public License for more details.
15
 * GNU General Public License for more details.
16
 *
16
 *
17
 * You should have received a copy of the GNU General Public License
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program.  If not, see .
18
 * along with this program.  If not, see .
19
 */
19
 */
20
 
20
 
21
/** \file
21
/** \file
22
 * Fetching of data from a URL (implementation).
22
 * Fetching of data from a URL (implementation).
23
 *
23
 *
24
 * This implementation uses libcurl's 'multi' interface.
24
 * This implementation uses libcurl's 'multi' interface.
25
 *
25
 *
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
 */
30
 
30
 
31
#include 
31
#include 
32
#include 
32
#include 
33
#include 
33
#include 
34
#include 
34
#include 
35
#include 
35
#include 
36
#include 
36
#include 
37
#include 
37
#include 
38
#include 
38
#include 
39
 
39
 
40
#include 
40
#include 
41
 
41
 
42
#include "utils/config.h"
42
#include "utils/config.h"
43
//#include 
43
//#include 
44
#include "content/fetch.h"
44
#include "content/fetch.h"
45
#include "content/fetchers/curl.h"
45
#include "content/fetchers/curl.h"
46
#include "content/urldb.h"
46
#include "content/urldb.h"
47
#include "desktop/netsurf.h"
47
#include "desktop/netsurf.h"
48
#include "desktop/options.h"
48
#include "desktop/options.h"
49
#include "utils/log.h"
49
#include "utils/log.h"
50
#include "utils/messages.h"
50
#include "utils/messages.h"
51
#include "utils/schedule.h"
51
#include "utils/schedule.h"
52
#include "utils/utils.h"
52
#include "utils/utils.h"
53
#include "utils/ring.h"
53
#include "utils/ring.h"
54
#include "utils/useragent.h"
54
#include "utils/useragent.h"
55
 
55
 
56
/* BIG FAT WARNING: This is here because curl doesn't give you an FD to
56
/* BIG FAT WARNING: This is here because curl doesn't give you an FD to
57
 * poll on, until it has processed a bit of the handle.	 So we need schedules
57
 * poll on, until it has processed a bit of the handle.	 So we need schedules
58
 * in order to make this work.
58
 * in order to make this work.
59
 */
59
 */
60
#include 
60
#include 
61
 
61
 
62
/* uncomment this to use scheduler based calling
62
/* uncomment this to use scheduler based calling
63
#define FETCHER_CURLL_SCHEDULED 1
63
#define FETCHER_CURLL_SCHEDULED 1
64
*/
64
*/
65
 
-
 
66
typedef int X509_STORE_CTX;
-
 
67
typedef int X509;
-
 
68
#define CURL_ERROR_SIZE 0
-
 
69
typedef int CURLcode;
-
 
70
typedef int curl_infotype;
-
 
71
/** SSL certificate info */
-
 
72
struct cert_info {
-
 
73
	X509 *cert;		/**< Pointer to certificate */
-
 
74
	long err;		/**< OpenSSL error code */
-
 
75
};
-
 
76
 
65
 
77
/** Information for a single fetch. */
66
 
-
 
67
struct fetch_curl_context {
78
struct curl_fetch_info {
68
	struct fetch_curl_context *r_next, *r_prev;
-
 
69
 
79
	struct fetch *fetch_handle; /**< The fetch handle we're parented by. */
70
	struct fetch *fetchh; /**< Handle for this fetch */
80
	CURL * curl_handle;	/**< cURL handle if being fetched, or 0. */
-
 
81
	bool had_headers;	/**< Headers have been processed. */
71
 
82
	bool abort;		/**< Abort requested. */
-
 
83
	bool stopped;		/**< Download stopped on purpose. */
-
 
84
	bool only_2xx;		/**< Only HTTP 2xx responses acceptable. */
-
 
85
	bool downgrade_tls;	/**< Downgrade to TLS <= 1.0 */
-
 
86
	nsurl *url;		/**< URL of this fetch. */
-
 
87
	lwc_string *host;	/**< The hostname of this fetch. */
-
 
88
	struct curl_slist *headers;	/**< List of request headers. */
-
 
89
	char *location;		/**< Response Location header, or 0. */
-
 
90
	unsigned long content_length;	/**< Response Content-Length, or 0. */
-
 
91
	char *cookie_string;	/**< Cookie string for this fetch */
-
 
92
	char *realm;		/**< HTTP Auth Realm */
-
 
93
	char *post_urlenc;	/**< Url encoded POST string, or 0. */
-
 
94
	long http_code; /**< HTTP result code from cURL. */
-
 
95
	struct curl_httppost *post_multipart;	/**< Multipart post data, or 0. */
-
 
96
#define MAX_CERTS 10
-
 
97
	struct cert_info cert_data[MAX_CERTS];	/**< HTTPS certificate data */
-
 
98
	unsigned int last_progress_update;	/**< Time of last progress update */
-
 
99
};
72
	bool aborted; /**< Flag indicating fetch has been aborted */
100
 
73
	bool locked; /**< Flag indicating entry is already entered */
101
struct cache_handle {
74
 
102
	CURL *handle; /**< The cached cURL handle */
-
 
103
	lwc_string *host;   /**< The host for which this handle is cached */
75
	nsurl *url; /**< The full url the fetch refers to */
104
 
-
 
105
	struct cache_handle *r_prev; /**< Previous cached handle in ring. */
-
 
106
	struct cache_handle *r_next; /**< Next cached handle in ring. */
-
 
107
};
-
 
108
 
76
	char *path; /**< The actual path to be used with open() */
109
CURLM *fetch_curl_multi;		/**< Global cURL multi handle. */
-
 
110
/** Curl handle with default options set; not used for transfers. */
77
 
111
static CURL *fetch_blank_curl;
-
 
112
static struct cache_handle *curl_handle_ring = 0; /**< Ring of cached handles */
-
 
113
static int curl_fetchers_registered = 0;
78
	time_t file_etag; /**< Request etag for file (previous st.m_time) */
114
static bool curl_with_openssl;
79
};
115
 
80
 
116
static char fetch_error_buffer[CURL_ERROR_SIZE]; /**< Error buffer for cURL. */
81
static struct fetch_curl_context *ring = NULL;
117
static char fetch_proxy_userpwd[100];	/**< Proxy authentication details. */
82
 
118
 
83
 
119
static bool fetch_curl_initialise(lwc_string *scheme);
84
static bool fetch_curl_initialise(lwc_string *scheme); //here
120
static void fetch_curl_finalise(lwc_string *scheme);
85
static void fetch_curl_finalise(lwc_string *scheme); //here
121
static bool fetch_curl_can_fetch(const nsurl *url);
86
static bool fetch_curl_can_fetch(const nsurl *url); //here
122
static void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
87
static void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
123
		 bool only_2xx, bool downgrade_tls, const char *post_urlenc,
88
		 bool only_2xx, bool downgrade_tls, const char *post_urlenc,
124
		 const struct fetch_multipart_data *post_multipart,
89
		 const struct fetch_multipart_data *post_multipart,
125
		 const char **headers);
90
		 const char **headers); //here
126
static bool fetch_curl_start(void *vfetch);
91
static bool fetch_curl_start(void *vfetch); //here 
127
static bool fetch_curl_initiate_fetch(struct curl_fetch_info *fetch,
-
 
128
		CURL *handle);
-
 
129
static CURL *fetch_curl_get_handle(lwc_string *host);
-
 
130
static void fetch_curl_cache_handle(CURL *handle, lwc_string *host);
-
 
131
static CURLcode fetch_curl_set_options(struct curl_fetch_info *f);
-
 
132
static CURLcode fetch_curl_sslctxfun(CURL *curl_handle, void *_sslctx,
-
 
133
				     void *p);
-
 
-
 
92
 
134
static void fetch_curl_abort(void *vf);
93
static void fetch_curl_abort(void *vf); //here
135
static void fetch_curl_stop(struct curl_fetch_info *f);
-
 
136
static void fetch_curl_free(void *f);
94
static void fetch_curl_free(void *f); //here
137
static void fetch_curl_poll(lwc_string *scheme_ignored);
95
static void fetch_curl_poll(lwc_string *scheme_ignored); //here
138
static void fetch_curl_done(CURL *curl_handle, CURLcode result);
-
 
139
static int fetch_curl_progress(void *clientp, double dltotal, double dlnow,
-
 
140
		double ultotal, double ulnow);
-
 
141
static int fetch_curl_ignore_debug(CURL *handle,
-
 
142
				   curl_infotype type,
-
 
143
				   char *data,
-
 
144
				   size_t size,
-
 
145
				   void *userptr);
-
 
146
static size_t fetch_curl_data(char *data, size_t size, size_t nmemb,
-
 
147
			      void *_f);
-
 
148
static size_t fetch_curl_header(char *data, size_t size, size_t nmemb,
-
 
149
				void *_f);
-
 
150
static bool fetch_curl_process_headers(struct curl_fetch_info *f);
-
 
151
static struct curl_httppost *fetch_curl_post_convert(
-
 
152
		const struct fetch_multipart_data *control);
-
 
153
static int fetch_curl_verify_callback(int preverify_ok,
-
 
154
		X509_STORE_CTX *x509_ctx);
-
 
155
static int fetch_curl_cert_verify_callback(X509_STORE_CTX *x509_ctx,
-
 
156
		void *parm);
-
 
157
 
96
 
158
 
97
 
159
/**
98
/**
160
 * Initialise the fetcher.
99
 * Initialise the fetcher.
161
 *
100
 *
162
 * Must be called once before any other function.
101
 * Must be called once before any other function.
163
 */
102
 */
164
 
103
 
165
void fetch_curl_register(void)
104
void fetch_curl_register(void)
166
{
105
{
167
 
106
 
168
lwc_string *scheme;
107
lwc_string *scheme;
169
 
108
 
170
 
109
 
171
LOG(("curl register\n"));
110
LOG(("curl register\n"));
172
 
111
 
173
lwc_intern_string("http", SLEN("http"), &scheme);
112
lwc_intern_string("http", SLEN("http"), &scheme);
174
 
113
 
175
	if (!fetch_add_fetcher(scheme,
114
	if (!fetch_add_fetcher(scheme,
176
				fetch_curl_initialise,
115
				fetch_curl_initialise, //here
177
				fetch_curl_can_fetch,
116
				fetch_curl_can_fetch, //here
178
				fetch_curl_setup,
117
				fetch_curl_setup,
179
				fetch_curl_start,
118
				fetch_curl_start,
180
				fetch_curl_abort,
119
				fetch_curl_abort, //here
181
				fetch_curl_free,
120
				fetch_curl_free, //here
182
#ifdef FETCHER_CURLL_SCHEDULED
121
#ifdef FETCHER_CURLL_SCHEDULED
183
				       NULL,
122
				       NULL,
184
#else
123
#else
185
				fetch_curl_poll,
124
				fetch_curl_poll, //here
186
#endif
125
#endif
187
				fetch_curl_finalise)) {
126
				fetch_curl_finalise)) {  //here
188
			LOG(("Unable to register cURL fetcher for HTTP"));
127
			LOG(("Unable to register cURL fetcher for HTTP"));
189
		}
128
		}
190
		
129
		
191
		
130
		
192
		lwc_intern_string("https", SLEN("https"), &scheme);
131
		lwc_intern_string("https", SLEN("https"), &scheme);
193
 
132
 
194
	if (!fetch_add_fetcher(scheme,
133
	if (!fetch_add_fetcher(scheme,
195
				fetch_curl_initialise,
134
				fetch_curl_initialise,
196
				fetch_curl_can_fetch,
135
				fetch_curl_can_fetch,
197
				fetch_curl_setup,
136
				fetch_curl_setup,
198
				fetch_curl_start,
137
				fetch_curl_start,
199
				fetch_curl_abort,
138
				fetch_curl_abort,
200
				fetch_curl_free,
139
				fetch_curl_free,
201
#ifdef FETCHER_CURLL_SCHEDULED
140
#ifdef FETCHER_CURLL_SCHEDULED
202
				       NULL,
141
				       NULL,
203
#else
142
#else
204
				fetch_curl_poll,
143
				fetch_curl_poll,
205
#endif
144
#endif
206
				fetch_curl_finalise)) {
145
				fetch_curl_finalise)) {
207
			LOG(("Unable to register cURL fetcher for HTTPS"));
146
			LOG(("Unable to register cURL fetcher for HTTPS"));
208
		}
147
		}
209
 
148
 
210
}
149
}
211
 
150
 
212
 
151
 
213
/**
152
/**
214
 * Initialise a cURL fetcher.
153
 * Initialise a cURL fetcher.
215
 */
154
 */
216
 
155
 
217
bool fetch_curl_initialise(lwc_string *scheme)
156
bool fetch_curl_initialise(lwc_string *scheme)
218
{
157
{
219
 
158
 
220
LOG(("curl initi lwc\n"));
159
LOG(("curl initi lwc\n"));
221
	return true; /* Always succeeds */
160
	return true; /* Always succeeds */
222
}
161
}
223
 
162
 
224
 
163
 
225
/**
164
/**
226
 * Finalise a cURL fetcher
165
 * Finalise a cURL fetcher
227
 */
166
 */
228
 
167
 
229
void fetch_curl_finalise(lwc_string *scheme)
168
void fetch_curl_finalise(lwc_string *scheme)
230
{
169
{
231
LOG(("curl finali\n"));
170
LOG(("curl finali\n"));
232
}
171
}
233
 
172
 
234
bool fetch_curl_can_fetch(const nsurl *url)
173
static bool fetch_curl_can_fetch(const nsurl *url)
235
{
174
{
236
	LOG(("curl can fetch\n"));
175
	LOG(("curl can fetch\n"));
237
	return false;
176
	return true; //let's lie a bit
238
}
177
}
239
 
178
 
240
/**
179
/**
241
 * Start fetching data for the given URL.
180
 * Start fetching data for the given URL.
242
 *
181
 *
243
 * The function returns immediately. The fetch may be queued for later
182
 * The function returns immediately. The fetch may be queued for later
244
 * processing.
183
 * processing.
245
 *
184
 *
246
 * A pointer to an opaque struct curl_fetch_info is returned, which can be 
185
 * A pointer to an opaque struct curl_fetch_info is returned, which can be 
247
 * passed to fetch_abort() to abort the fetch at any time. Returns 0 if memory 
186
 * passed to fetch_abort() to abort the fetch at any time. Returns 0 if memory 
248
 * is exhausted (or some other fatal error occurred).
187
 * is exhausted (or some other fatal error occurred).
249
 *
188
 *
250
 * The caller must supply a callback function which is called when anything
189
 * The caller must supply a callback function which is called when anything
251
 * interesting happens. The callback function is first called with msg
190
 * interesting happens. The callback function is first called with msg
252
 * FETCH_HEADER, with the header in data, then one or more times
191
 * FETCH_HEADER, with the header in data, then one or more times
253
 * with FETCH_DATA with some data for the url, and finally with
192
 * with FETCH_DATA with some data for the url, and finally with
254
 * FETCH_FINISHED. Alternatively, FETCH_ERROR indicates an error occurred:
193
 * FETCH_FINISHED. Alternatively, FETCH_ERROR indicates an error occurred:
255
 * data contains an error message. FETCH_REDIRECT may replace the FETCH_HEADER,
194
 * data contains an error message. FETCH_REDIRECT may replace the FETCH_HEADER,
256
 * FETCH_DATA, FETCH_FINISHED sequence if the server sends a replacement URL.
195
 * FETCH_DATA, FETCH_FINISHED sequence if the server sends a replacement URL.
257
 *
196
 *
258
 * Some private data can be passed as the last parameter to fetch_start, and
197
 * Some private data can be passed as the last parameter to fetch_start, and
259
 * callbacks will contain this.
198
 * callbacks will contain this.
260
 */
199
 */
261
 
200
 
-
 
201
void * fetch_curl_setup (struct fetch *fetchh,
-
 
202
		 nsurl *url,
-
 
203
		 bool only_2xx,
262
void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
204
		 bool downgrade_tls,
263
		 bool only_2xx, bool downgrade_tls, const char *post_urlenc,
205
		 const char *post_urlenc,
264
		 const struct fetch_multipart_data *post_multipart,
206
		 const struct fetch_multipart_data *post_multipart,
265
		 const char **headers)
207
		 const char **headers)
266
{
208
{
-
 
209
 
267
LOG(("curl setup\n"));
210
	LOG(("curl setup\n"));
-
 
211
	
268
 
212
	struct fetch_curl_context *ctx;
269
return;
-
 
-
 
213
	int i;
-
 
214
 
-
 
215
	ctx = calloc(1, sizeof(*ctx));
270
}
-
 
271
 
216
	if (ctx == NULL)
272
 
-
 
273
/**
217
		return NULL;
274
 * Dispatch a single job
-
 
275
 */
218
 
276
bool fetch_curl_start(void *vfetch)
219
	ctx->path = url_to_path(nsurl_access(url));
277
{
220
	if (ctx->path == NULL) {
-
 
221
		free(ctx);
278
LOG(("curl start\n"));
-
 
279
	return 0;
-
 
280
}
-
 
281
 
-
 
282
 
-
 
283
/**
-
 
284
 * Initiate a fetch from the queue.
-
 
285
 *
-
 
286
 * Called with a fetch structure and a CURL handle to be used to fetch the
-
 
287
 * content.
-
 
288
 *
-
 
289
 * This will return whether or not the fetch was successfully initiated.
-
 
290
 */
-
 
291
 
-
 
-
 
222
		return NULL;
292
bool fetch_curl_initiate_fetch(struct curl_fetch_info *fetch, CURL *handle)
-
 
293
{
223
	}
294
	LOG(("curl initi fetch\n"));
-
 
295
	return 0;
-
 
296
}
-
 
297
 
-
 
298
 
224
 
299
/**
225
	ctx->url = nsurl_ref(url);
300
 * Find a CURL handle to use to dispatch a job
226
 
301
 */
227
 
302
 
228
	ctx->fetchh = fetchh;
303
CURL *fetch_curl_get_handle(lwc_string *host)
229
 
304
{
230
	RING_INSERT(ring, ctx);
305
LOG(("curl get handle\n"));
231
 
306
	return 0;
232
	return ctx;
307
}
233
}
308
 
234
 
309
 
235
 
310
/**
236
/**
311
 * Cache a CURL handle for the provided host (if wanted)
237
 * Dispatch a single job
312
 */
238
 */
313
 
-
 
314
void fetch_curl_cache_handle(CURL *handle, lwc_string *host)
239
bool fetch_curl_start(void *vfetch)
315
{
240
{
316
	LOG(("curl cache handle\n"));
241
LOG(("curl start\n"));
-
 
242
	return true;
317
}
243
}
318
 
244
 
319
 
-
 
320
/**
-
 
321
 * Set options specific for a fetch.
-
 
322
 */
-
 
323
 
-
 
324
typedef int CURLcode;
-
 
325
 
-
 
326
CURLcode
-
 
327
fetch_curl_set_options(struct curl_fetch_info *f)
-
 
328
{
-
 
329
	LOG(("curl set options\n"));
245
 
330
	return -1;
246
 
331
}
247
 
332
 
248
 
333
 
249
 
334
/**
250
/**
335
 * cURL SSL setup callback
251
 * Abort a fetch.
336
 */
252
 */
337
 
-
 
338
CURLcode
253
 
339
fetch_curl_sslctxfun(CURL *curl_handle, void *_sslctx, void *parm)
254
void fetch_curl_abort(void *ctx)
340
{
255
{
-
 
256
	struct fetch_curl_context *c = ctx;
-
 
257
 
-
 
258
	/* To avoid the poll loop having to deal with the fetch context
-
 
259
	 * disappearing from under it, we simply flag the abort here.
341
	LOG(("curlcodessl\n"));
260
	 * The poll loop itself will perform the appropriate cleanup.
342
	
261
	 */
343
	return -1;
262
	c->aborted = true;
344
}
263
}
345
 
264
 
346
 
265
 
347
/**
266
/**
348
 * Abort a fetch.
267
 * Free a fetch structure and associated resources.
349
 */
268
 */
350
 
269
 
351
void fetch_curl_abort(void *vf)
270
void fetch_curl_free(void *ctx)
-
 
271
{
352
{
272
	struct fetch_curl_context *c = ctx;
-
 
273
	nsurl_unref(c->url);
-
 
274
	free(c->path);
-
 
275
	RING_REMOVE(ring, c);
353
LOG(("curl abort\n"));
276
	free(ctx);
-
 
277
}
-
 
278
 
-
 
279
static inline bool fetch_curl_send_callback(const fetch_msg *msg,
-
 
280
		struct fetch_curl_context *ctx)
-
 
281
{
-
 
282
	ctx->locked = true;
354
}
-
 
355
 
283
	fetch_send_callback(msg, ctx->fetchh);
356
 
284
	ctx->locked = false;
357
/**
-
 
358
 * Clean up the provided fetch object and free it.
-
 
359
 *
285
 
-
 
286
	return ctx->aborted;
360
 * Will prod the queue afterwards to allow pending requests to be initiated.
287
}
361
 */
288
 
-
 
289
static bool fetch_curl_send_header(struct fetch_curl_context *ctx,
362
 
290
		const char *fmt, ...)
-
 
291
{
363
void fetch_curl_stop(struct curl_fetch_info *f)
-
 
364
{
292
	fetch_msg msg;
365
	LOG(("curl stop\n"));
-
 
366
}
-
 
367
 
-
 
368
 
293
	char header[64];
369
/**
-
 
-
 
294
	va_list ap;
-
 
295
 
-
 
296
	va_start(ap, fmt);
-
 
297
 
370
 * Free a fetch structure and associated resources.
-
 
371
 */
298
	vsnprintf(header, sizeof header, fmt, ap);
372
 
299
 
373
void fetch_curl_free(void *vf)
-
 
374
{
-
 
375
	LOG(("curl free\n"));
300
	va_end(ap);
376
}
301
 
-
 
302
	msg.type = FETCH_HEADER;
-
 
303
	msg.data.header_or_data.buf = (const uint8_t *) header;
377
 
304
	msg.data.header_or_data.len = strlen(header);
378
 
305
	fetch_curl_send_callback(&msg, ctx);
-
 
306
 
-
 
307
	return ctx->aborted;
379
/**
308
}
380
 * Do some work on current fetches.
309
 
381
 *
-
 
382
 * Must be called regularly to make progress on fetches.
310
static void fetch_curl_process_error(struct fetch_curl_context *ctx, int code)
383
 */
-
 
384
 
311
{
385
void fetch_curl_poll(lwc_string *scheme_ignored)
-
 
386
{
312
	fetch_msg msg;
387
	LOG(("curl poll\n"));
-
 
-
 
313
	char buffer[1024];
-
 
314
	const char *title;
-
 
315
	char key[8];
-
 
316
 
388
}
317
	/* content is going to return error code */
-
 
318
	fetch_set_http_code(ctx->fetchh, code);
-
 
319
 
389
 
320
	/* content type */
390
 
-
 
-
 
321
	if (fetch_curl_send_header(ctx, "Content-Type: text/html"))
391
/**
322
		goto fetch_file_process_error_aborted;
392
 * Handle a completed fetch (CURLMSG_DONE from curl_multi_info_read()).
323
 
393
 *
324
	snprintf(key, sizeof key, "HTTP%03d", code);
394
 * \param  curl_handle	curl easy handle of fetch
325
	title = messages_get(key);
395
 */
326
 
396
 
327
	snprintf(buffer, sizeof buffer, "%s"
397
void fetch_curl_done(CURL *curl_handle, CURLcode result)
328
			"

%s

"
398
{
329
			"

Error %d while fetching file %s

",
399
	LOG(("curl done\n"));
330
			title, title, code, nsurl_access(ctx->url));
400
}
331
 
401
 
332
	msg.type = FETCH_DATA;
402
 
333
	msg.data.header_or_data.buf = (const uint8_t *) buffer;
403
/**
334
	msg.data.header_or_data.len = strlen(buffer);
404
 * Callback function for fetch progress.
335
	if (fetch_curl_send_callback(&msg, ctx))
405
 */
336
		goto fetch_file_process_error_aborted;
406
 
337
 
407
int fetch_curl_progress(void *clientp, double dltotal, double dlnow,
338
	msg.type = FETCH_FINISHED;
408
			double ultotal, double ulnow)
339
	fetch_curl_send_callback(&msg, ctx);
409
{
340
 
410
	LOG(("curl progress\n"));
341
fetch_file_process_error_aborted:
411
	return 0;
342
	return;
412
}
343
}
413
 
344
 
-
 
345
 
-
 
346
static void fetch_curl_process(struct fetch_curl_context *ctx) {
-
 
347
	
-
 
348
	fetch_msg msg;
-
 
349
	const char * buf = "

Hello, file fetcher!

";
414
 
350
//	fetch_curl_process_error(ctx, 501);
415
 
351
//	return;
-
 
352
 
416
/**
353
/* fetch is going to be successful */
-
 
354
	fetch_set_http_code(ctx->fetchh, 200);
-
 
355
 
417
 * Ignore everything given to it.
356
	/* Any callback can result in the fetch being aborted.
418
 *
357
	 * Therefore, we _must_ check for this after _every_ call to
419
 * Used to ignore cURL debug.
-
 
420
 */
358
	 * fetch_file_send_callback().
421
 
-
 
422
int fetch_curl_ignore_debug(CURL *handle,
-
 
423
			    curl_infotype type,
359
	 */
424
			    char *data,
-
 
425
			    size_t size,
360
 
426
			    void *userptr)
-
 
427
{
-
 
428
	LOG(("curl igdebug\n"));
-
 
429
	return 0;
361
	/* content type */
430
}
-
 
-
 
362
	if (fetch_curl_send_header(ctx, "Content-Type: text/html"))
431
 
363
		goto fetch_file_process_aborted;
432
 
364
 
433
/**
-
 
434
 * Callback function for cURL.
365
	
435
 */
-
 
436
 
-
 
437
size_t fetch_curl_data(char *data, size_t size, size_t nmemb,
-
 
438
		       void *_f)
-
 
439
{
-
 
440
	LOG(("curl callback\n"));
-
 
441
		return 0;
-
 
-
 
366
	/* main data loop */
-
 
367
 
442
}
368
		msg.type = FETCH_DATA;
-
 
369
		msg.data.header_or_data.buf = (const uint8_t *) buf;
-
 
370
		msg.data.header_or_data.len = strlen(buf);
-
 
371
		fetch_curl_send_callback(&msg, ctx);
443
 
372
			
444
 
-
 
445
/**
-
 
446
 * Callback function for headers.
-
 
447
 *
373
	
-
 
374
 
448
 * See RFC 2616 4.2.
375
	if (ctx->aborted == false) {
449
 */
376
		msg.type = FETCH_FINISHED;
450
 
377
		fetch_curl_send_callback(&msg, ctx);
451
size_t fetch_curl_header(char *data, size_t size, size_t nmemb,
378
	}
452
			 void *_f)
379
 
453
			 
380
fetch_file_process_aborted:
454
{
381
return;
455
	LOG(("curl header\n"));
382
 
456
		return 0;
-
 
457
}
-
 
-
 
383
}
458
 
-
 
459
/**
-
 
460
 * Find the status code and content type and inform the caller.
-
 
461
 *
-
 
462
 * Return true if the fetch is being aborted.
-
 
463
 */
-
 
464
 
-
 
465
bool fetch_curl_process_headers(struct curl_fetch_info *f)
384
 
-
 
385
 
-
 
386
/**
-
 
387
 * Do some work on current fetches.
-
 
388
 *
-
 
389
 * Must be called regularly to make progress on fetches.
-
 
390
 */
-
 
391
 
-
 
392
void fetch_curl_poll(lwc_string *scheme_ignored)
-
 
393
{
466
{
394
	LOG(("curl poll\n"));
-
 
395
	
467
LOG(("curl proc head\n"));
396
	struct fetch_curl_context *c, *next;
468
	return false;
397
 
-
 
398
	if (ring == NULL) return;
-
 
399
 
-
 
400
	/* Iterate over ring, processing each pending fetch */
-
 
401
	c = ring;
-
 
402
	do {
469
}
-
 
470
 
403
		/* Ignore fetches that have been flagged as locked.
471
 
404
		 * This allows safe re-entrant calls to this function.
472
/**
405
		 * Re-entrancy can occur if, as a result of a callback,
-
 
406
		 * the interested party causes fetch_poll() to be called
473
 * Convert a list of struct ::fetch_multipart_data to a list of
407
		 * again.
-
 
408
		 */
474
 * struct curl_httppost for libcurl.
409
		if (c->locked == true) {
-
 
410
			next = c->r_next;
-
 
411
			continue;
-
 
412
		}
-
 
413
 
475
 */
-
 
476
struct curl_httppost *
-
 
477
fetch_curl_post_convert(const struct fetch_multipart_data *control)
414
		/* Only process non-aborted fetches */
478
{
415
		if (c->aborted == false) {
479
	struct curl_httppost *post = 0;
416
			/* file fetches can be processed in one go */
480
	
417
			fetch_curl_process(c);
481
	LOG(("curl post - FAIL\n"));
418
		}
482
	return post;
419
 
483
}
420
		/* Compute next fetch item at the last possible moment as
484
 
421
		 * processing this item may have added to the ring.
485
 
422
		 */
486
/**
423
		next = c->r_next;
487
 * OpenSSL Certificate verification callback
424
 
488
 * Stores certificate details in fetch struct.
425
		fetch_remove_from_queues(c->fetchh);
489
 */
426
		fetch_free(c->fetchh);
490
 
427
 
491
int fetch_curl_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
428
		/* Advance to next ring entry, exiting if we've reached
492
{
429
		 * the start of the ring or the ring has become empty
493
	
430
		 */
494
	LOG(("curl verify\n"));
431
	} while ( (c = next) != ring && ring != NULL);
495
	return 0;
432
 
496
}
433
}
497
 
434
498
 
-
 
499
/**
-
 
500
 * OpenSSL certificate chain verification callback
-
 
501
 * Verifies certificate chain, setting up context for fetch_curl_verify_callback
-
 
502
 */
-
 
503
 
-
 
504
int fetch_curl_cert_verify_callback(X509_STORE_CTX *x509_ctx, void *parm)
-
 
505
{
-
 
506
 
-
 
507
LOG(("curl cert verify\n"));
-
 
508
	return 0;
-
 
509
}
-