Subversion Repositories Kolibri OS

Rev

Rev 3624 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3584 sourcerer 1
/*
2
 * Copyright 2006 Daniel Silverstone 
3
 * Copyright 2007 James Bursa 
4
 * Copyright 2003 Phil Mellor 
5
 *
6
 * This file is part of NetSurf.
7
 *
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
10
 * the Free Software Foundation; version 2 of the License.
11
 *
12
 * NetSurf is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program.  If not, see .
19
 */
20
 
21
/** \file
22
 * Fetching of data from a URL (implementation).
23
 *
24
 * This implementation uses libcurl's 'multi' interface.
25
 *
26
 *
27
 * The CURL handles are cached in the curl_handle_ring. There are at most
28
 * ::max_cached_fetch_handles in this ring.
29
 */
30
 
4224 sourcerer 31
 
32
#include "http.c"
33
 
3584 sourcerer 34
#include 
35
#include 
36
#include 
37
#include 
38
#include 
39
#include 
40
#include 
41
#include 
42
 
43
#include 
44
 
45
#include "utils/config.h"
46
//#include 
47
#include "content/fetch.h"
48
#include "content/fetchers/curl.h"
49
#include "content/urldb.h"
50
#include "desktop/netsurf.h"
51
#include "desktop/options.h"
52
#include "utils/log.h"
53
#include "utils/messages.h"
54
#include "utils/schedule.h"
55
#include "utils/utils.h"
56
#include "utils/ring.h"
57
#include "utils/useragent.h"
58
 
59
/* BIG FAT WARNING: This is here because curl doesn't give you an FD to
60
 * poll on, until it has processed a bit of the handle.	 So we need schedules
61
 * in order to make this work.
62
 */
63
#include 
64
 
65
/* uncomment this to use scheduler based calling
66
#define FETCHER_CURLL_SCHEDULED 1
67
*/
68
 
69
 
3616 sourcerer 70
struct fetch_curl_context {
71
	struct fetch_curl_context *r_next, *r_prev;
3584 sourcerer 72
 
3616 sourcerer 73
	struct fetch *fetchh; /**< Handle for this fetch */
3584 sourcerer 74
 
3616 sourcerer 75
	bool aborted; /**< Flag indicating fetch has been aborted */
76
	bool locked; /**< Flag indicating entry is already entered */
77
 
78
	nsurl *url; /**< The full url the fetch refers to */
79
	char *path; /**< The actual path to be used with open() */
80
 
81
	time_t file_etag; /**< Request etag for file (previous st.m_time) */
3584 sourcerer 82
};
83
 
3616 sourcerer 84
static struct fetch_curl_context *ring = NULL;
3584 sourcerer 85
 
86
 
3616 sourcerer 87
static bool fetch_curl_initialise(lwc_string *scheme); //here
88
static void fetch_curl_finalise(lwc_string *scheme); //here
89
static bool fetch_curl_can_fetch(const nsurl *url); //here
3584 sourcerer 90
static void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
91
		 bool only_2xx, bool downgrade_tls, const char *post_urlenc,
92
		 const struct fetch_multipart_data *post_multipart,
3616 sourcerer 93
		 const char **headers); //here
94
static bool fetch_curl_start(void *vfetch); //here
3584 sourcerer 95
 
3616 sourcerer 96
static void fetch_curl_abort(void *vf); //here
97
static void fetch_curl_free(void *f); //here
98
static void fetch_curl_poll(lwc_string *scheme_ignored); //here
3584 sourcerer 99
 
3616 sourcerer 100
 
3584 sourcerer 101
/**
102
 * Initialise the fetcher.
103
 *
104
 * Must be called once before any other function.
105
 */
106
 
107
void fetch_curl_register(void)
108
{
109
 
110
lwc_string *scheme;
111
 
112
 
113
LOG(("curl register\n"));
114
 
115
lwc_intern_string("http", SLEN("http"), &scheme);
116
 
117
	if (!fetch_add_fetcher(scheme,
3616 sourcerer 118
				fetch_curl_initialise, //here
119
				fetch_curl_can_fetch, //here
3584 sourcerer 120
				fetch_curl_setup,
121
				fetch_curl_start,
3616 sourcerer 122
				fetch_curl_abort, //here
123
				fetch_curl_free, //here
3584 sourcerer 124
#ifdef FETCHER_CURLL_SCHEDULED
125
				       NULL,
126
#else
3616 sourcerer 127
				fetch_curl_poll, //here
3584 sourcerer 128
#endif
3616 sourcerer 129
				fetch_curl_finalise)) {  //here
3584 sourcerer 130
			LOG(("Unable to register cURL fetcher for HTTP"));
131
		}
132
 
133
 
134
		lwc_intern_string("https", SLEN("https"), &scheme);
135
 
136
	if (!fetch_add_fetcher(scheme,
137
				fetch_curl_initialise,
138
				fetch_curl_can_fetch,
139
				fetch_curl_setup,
140
				fetch_curl_start,
141
				fetch_curl_abort,
142
				fetch_curl_free,
143
#ifdef FETCHER_CURLL_SCHEDULED
144
				       NULL,
145
#else
146
				fetch_curl_poll,
147
#endif
148
				fetch_curl_finalise)) {
149
			LOG(("Unable to register cURL fetcher for HTTPS"));
150
		}
151
 
152
}
153
 
154
 
155
/**
156
 * Initialise a cURL fetcher.
157
 */
158
 
159
bool fetch_curl_initialise(lwc_string *scheme)
160
{
161
LOG(("curl initi lwc\n"));
162
	return true; /* Always succeeds */
163
}
164
 
165
 
166
/**
167
 * Finalise a cURL fetcher
168
 */
169
 
170
void fetch_curl_finalise(lwc_string *scheme)
171
{
172
LOG(("curl finali\n"));
173
}
174
 
3616 sourcerer 175
static bool fetch_curl_can_fetch(const nsurl *url)
3584 sourcerer 176
{
177
	LOG(("curl can fetch\n"));
3616 sourcerer 178
	return true; //let's lie a bit
3584 sourcerer 179
}
180
 
181
/**
182
 * Start fetching data for the given URL.
183
 *
184
 * The function returns immediately. The fetch may be queued for later
185
 * processing.
186
 *
187
 * A pointer to an opaque struct curl_fetch_info is returned, which can be
188
 * passed to fetch_abort() to abort the fetch at any time. Returns 0 if memory
189
 * is exhausted (or some other fatal error occurred).
190
 *
191
 * The caller must supply a callback function which is called when anything
192
 * interesting happens. The callback function is first called with msg
193
 * FETCH_HEADER, with the header in data, then one or more times
194
 * with FETCH_DATA with some data for the url, and finally with
195
 * FETCH_FINISHED. Alternatively, FETCH_ERROR indicates an error occurred:
196
 * data contains an error message. FETCH_REDIRECT may replace the FETCH_HEADER,
197
 * FETCH_DATA, FETCH_FINISHED sequence if the server sends a replacement URL.
198
 *
199
 * Some private data can be passed as the last parameter to fetch_start, and
200
 * callbacks will contain this.
201
 */
202
 
3616 sourcerer 203
void * fetch_curl_setup (struct fetch *fetchh,
204
		 nsurl *url,
205
		 bool only_2xx,
206
		 bool downgrade_tls,
207
		 const char *post_urlenc,
3584 sourcerer 208
		 const struct fetch_multipart_data *post_multipart,
209
		 const char **headers)
210
{
211
 
3616 sourcerer 212
	LOG(("curl setup\n"));
213
 
214
	struct fetch_curl_context *ctx;
215
	int i;
3584 sourcerer 216
 
3616 sourcerer 217
	ctx = calloc(1, sizeof(*ctx));
218
	if (ctx == NULL)
219
		return NULL;
3584 sourcerer 220
 
3620 sourcerer 221
	//ctx->path = url_to_path(nsurl_access(url));
222
	char *zz;
223
	int pr;
224
	nsurl_get(url, NSURL_WITH_FRAGMENT, &zz, &pr);
225
 
226
	ctx->path = zz;
3616 sourcerer 227
	if (ctx->path == NULL) {
228
		free(ctx);
229
		return NULL;
230
	}
3584 sourcerer 231
 
3616 sourcerer 232
	ctx->url = nsurl_ref(url);
3584 sourcerer 233
 
234
 
3616 sourcerer 235
	ctx->fetchh = fetchh;
3584 sourcerer 236
 
3616 sourcerer 237
	RING_INSERT(ring, ctx);
3584 sourcerer 238
 
3616 sourcerer 239
	return ctx;
3584 sourcerer 240
}
241
 
242
 
243
/**
3616 sourcerer 244
 * Dispatch a single job
3584 sourcerer 245
 */
3616 sourcerer 246
bool fetch_curl_start(void *vfetch)
3584 sourcerer 247
{
3616 sourcerer 248
LOG(("curl start\n"));
249
	return true;
3584 sourcerer 250
}
251
 
252
 
253
 
254
 
255
 
256
 
257
/**
3616 sourcerer 258
 * Abort a fetch.
3584 sourcerer 259
 */
260
 
3616 sourcerer 261
void fetch_curl_abort(void *ctx)
3584 sourcerer 262
{
3616 sourcerer 263
	struct fetch_curl_context *c = ctx;
264
 
265
	/* To avoid the poll loop having to deal with the fetch context
266
	 * disappearing from under it, we simply flag the abort here.
267
	 * The poll loop itself will perform the appropriate cleanup.
268
	 */
269
	c->aborted = true;
3584 sourcerer 270
}
271
 
272
 
273
/**
3616 sourcerer 274
 * Free a fetch structure and associated resources.
3584 sourcerer 275
 */
276
 
3616 sourcerer 277
void fetch_curl_free(void *ctx)
3584 sourcerer 278
{
3616 sourcerer 279
	struct fetch_curl_context *c = ctx;
280
	nsurl_unref(c->url);
281
	free(c->path);
282
	RING_REMOVE(ring, c);
283
	free(ctx);
3584 sourcerer 284
}
285
 
3616 sourcerer 286
static inline bool fetch_curl_send_callback(const fetch_msg *msg,
287
		struct fetch_curl_context *ctx)
288
{
289
	ctx->locked = true;
290
	fetch_send_callback(msg, ctx->fetchh);
291
	ctx->locked = false;
3584 sourcerer 292
 
3616 sourcerer 293
	return ctx->aborted;
294
}
3584 sourcerer 295
 
3616 sourcerer 296
static bool fetch_curl_send_header(struct fetch_curl_context *ctx,
297
		const char *fmt, ...)
3584 sourcerer 298
{
3616 sourcerer 299
	fetch_msg msg;
300
	char header[64];
301
	va_list ap;
3584 sourcerer 302
 
3616 sourcerer 303
	va_start(ap, fmt);
3584 sourcerer 304
 
3616 sourcerer 305
	vsnprintf(header, sizeof header, fmt, ap);
3584 sourcerer 306
 
3616 sourcerer 307
	va_end(ap);
3584 sourcerer 308
 
3616 sourcerer 309
	msg.type = FETCH_HEADER;
310
	msg.data.header_or_data.buf = (const uint8_t *) header;
311
	msg.data.header_or_data.len = strlen(header);
312
	fetch_curl_send_callback(&msg, ctx);
3584 sourcerer 313
 
3616 sourcerer 314
	return ctx->aborted;
315
}
3584 sourcerer 316
 
3616 sourcerer 317
static void fetch_curl_process_error(struct fetch_curl_context *ctx, int code)
3584 sourcerer 318
{
3616 sourcerer 319
	fetch_msg msg;
320
	char buffer[1024];
321
	const char *title;
322
	char key[8];
3584 sourcerer 323
 
3616 sourcerer 324
	/* content is going to return error code */
325
	fetch_set_http_code(ctx->fetchh, code);
3584 sourcerer 326
 
3616 sourcerer 327
	/* content type */
328
	if (fetch_curl_send_header(ctx, "Content-Type: text/html"))
329
		goto fetch_file_process_error_aborted;
3584 sourcerer 330
 
3616 sourcerer 331
	snprintf(key, sizeof key, "HTTP%03d", code);
332
	title = messages_get(key);
3584 sourcerer 333
 
3616 sourcerer 334
	snprintf(buffer, sizeof buffer, "%s"
335
			"

%s

"
336
			"

Error %d while fetching file %s

",
337
			title, title, code, nsurl_access(ctx->url));
3584 sourcerer 338
 
3616 sourcerer 339
	msg.type = FETCH_DATA;
340
	msg.data.header_or_data.buf = (const uint8_t *) buffer;
341
	msg.data.header_or_data.len = strlen(buffer);
342
	if (fetch_curl_send_callback(&msg, ctx))
343
		goto fetch_file_process_error_aborted;
3584 sourcerer 344
 
3616 sourcerer 345
	msg.type = FETCH_FINISHED;
346
	fetch_curl_send_callback(&msg, ctx);
347
 
348
fetch_file_process_error_aborted:
349
	return;
3584 sourcerer 350
}
351
 
352
 
3620 sourcerer 353
int is_pid(int k)
354
{
355
	int error;
356
asm volatile ("int $0x40":"=a"(error):"a"(18), "b"(21), "c"(k));
357
return error;
358
}
359
 
360
 
361
int kill_pid(int k)
362
{
363
	int error;
364
asm volatile ("int $0x40":"=a"(error):"a"(18), "b"(18), "c"(k));
365
return error;
366
}
367
 
4224 sourcerer 368
 
3616 sourcerer 369
static void fetch_curl_process(struct fetch_curl_context *ctx) {
4224 sourcerer 370
	char ps[96], str[128];
371
	sprintf(ps, "Yay! Path is %s", ctx->path);
372
	execl ("/sys/@notify", ps, 0);
3616 sourcerer 373
 
374
	fetch_msg msg;
3584 sourcerer 375
 
4224 sourcerer 376
 /* ERSATZ DOWNLOADER */
3620 sourcerer 377
 
4224 sourcerer 378
 /*
379
char zapzap[]="

HOOLE!

";
380
size_t file_size=strlen(zapzap);
381
char *buffer = (char*)malloc(file_size * sizeof(char));
382
memcpy(buffer, zapzap, file_size * sizeof(char));
383
*/
384
 
385
 
3620 sourcerer 386
 
387
 
4224 sourcerer 388
 
389
    __menuet__debug_out("AHOY!\n");
390
	struct http_msg *http_ahoy;
391
 
392
	unsigned int wererat = 0;
393
    char * pa=ctx->path;
394
    asm volatile ("pusha");
395
    wererat = http_get(pa);
396
	asm volatile ("popa");
397
	__menuet__debug_out("HTTP GOT!\n");
398
	int result;
399
 
400
    http_ahoy=wererat;
401
 
402
    sprintf (str, "Header %d bytes, content %d bytes, recieved %d bytes\n", http_ahoy->header_length, http_ahoy->content_length, http_ahoy->content_received);
403
    __menuet__debug_out(str);
404
 
405
    asm volatile ("pusha");
406
    result = http_process(wererat);
407
    asm volatile ("popa");
408
    while (result == -1)  {
409
		asm volatile ("pusha");
410
		result = http_process(wererat);
411
		asm volatile ("popa");
412
	}
413
 
414
    http_ahoy=wererat;
415
 
416
    sprintf (str, "Header %d bytes, content %d bytes, recieved %d bytes\n", http_ahoy->header_length, http_ahoy->content_length, http_ahoy->content_received);
417
    __menuet__debug_out(str);
418
 
419
 
420
    __menuet__debug_out("All content is here\n");
421
 
422
	size_t file_size=http_ahoy->content_received;
423
	char *buffer = (char*)malloc(file_size * sizeof(char));
424
	memcpy(buffer, &(http_ahoy->data)+http_ahoy->header_length, file_size);
425
 
426
	// http_free(wererat);
427
    __menuet__debug_out("memcopied\n==\n");
428
 
429
	//__menuet__debug_out(buffer);
430
	//__menuet__debug_out("memcopied\n==\n");
431
 
432
 
433
//char zapzap[]="

HOOLE!

";
434
//file_size=strlen(zapzap);
435
//char *buffer = (char*)malloc(file_size * sizeof(char));
436
//memcpy(buffer, zapzap, file_size * sizeof(char));
437
 
438
 
3616 sourcerer 439
/* fetch is going to be successful */
440
	fetch_set_http_code(ctx->fetchh, 200);
3584 sourcerer 441
 
3616 sourcerer 442
	/* Any callback can result in the fetch being aborted.
443
	 * Therefore, we _must_ check for this after _every_ call to
444
	 * fetch_file_send_callback().
445
	 */
3584 sourcerer 446
 
3624 sourcerer 447
 
448
	if (fetch_curl_send_header(ctx, "Content-Type: %s",
449
			fetch_filetype(ctx->path)))
3616 sourcerer 450
		goto fetch_file_process_aborted;
3584 sourcerer 451
 
3616 sourcerer 452
 
453
	/* main data loop */
3584 sourcerer 454
 
3616 sourcerer 455
		msg.type = FETCH_DATA;
4224 sourcerer 456
		msg.data.header_or_data.buf = (const uint8_t *) buffer;//&(http_ahoy->data) ; //buffer;
3620 sourcerer 457
		msg.data.header_or_data.len = file_size;
3616 sourcerer 458
		fetch_curl_send_callback(&msg, ctx);
459
 
460
 
3584 sourcerer 461
 
3616 sourcerer 462
	if (ctx->aborted == false) {
463
		msg.type = FETCH_FINISHED;
464
		fetch_curl_send_callback(&msg, ctx);
465
	}
3584 sourcerer 466
 
3616 sourcerer 467
fetch_file_process_aborted:
468
return;
3584 sourcerer 469
 
470
}
471
 
3616 sourcerer 472
 
3584 sourcerer 473
/**
3616 sourcerer 474
 * Do some work on current fetches.
3584 sourcerer 475
 *
3616 sourcerer 476
 * Must be called regularly to make progress on fetches.
3584 sourcerer 477
 */
478
 
3616 sourcerer 479
void fetch_curl_poll(lwc_string *scheme_ignored)
3584 sourcerer 480
{
3616 sourcerer 481
	LOG(("curl poll\n"));
482
 
483
	struct fetch_curl_context *c, *next;
3584 sourcerer 484
 
3616 sourcerer 485
	if (ring == NULL) return;
3584 sourcerer 486
 
3616 sourcerer 487
	/* Iterate over ring, processing each pending fetch */
488
	c = ring;
489
	do {
490
		/* Ignore fetches that have been flagged as locked.
491
		 * This allows safe re-entrant calls to this function.
492
		 * Re-entrancy can occur if, as a result of a callback,
493
		 * the interested party causes fetch_poll() to be called
494
		 * again.
495
		 */
496
		if (c->locked == true) {
497
			next = c->r_next;
498
			continue;
499
		}
3584 sourcerer 500
 
3616 sourcerer 501
		/* Only process non-aborted fetches */
502
		if (c->aborted == false) {
503
			/* file fetches can be processed in one go */
504
			fetch_curl_process(c);
505
		}
3584 sourcerer 506
 
3616 sourcerer 507
		/* Compute next fetch item at the last possible moment as
508
		 * processing this item may have added to the ring.
509
		 */
510
		next = c->r_next;
3584 sourcerer 511
 
3616 sourcerer 512
		fetch_remove_from_queues(c->fetchh);
513
		fetch_free(c->fetchh);
514
 
515
		/* Advance to next ring entry, exiting if we've reached
516
		 * the start of the ring or the ring has become empty
517
		 */
518
	} while ( (c = next) != ring && ring != NULL);
519
 
3584 sourcerer 520
}
521