diff options
author | Phil Mellor <phil@monkeyson.info> | 2002-09-11 14:24:02 +0000 |
---|---|---|
committer | Phil Mellor <phil@monkeyson.info> | 2002-09-11 14:24:02 +0000 |
commit | 811106028fd050cdee11fbc8732ba39f2de5e12a (patch) | |
tree | 0194609193dc142881958ff81bef57f07da71b54 /desktop/fetch.c | |
parent | a46eef0002d061c3363756182a592be7646ae79b (diff) | |
download | netsurf-811106028fd050cdee11fbc8732ba39f2de5e12a.tar.gz netsurf-811106028fd050cdee11fbc8732ba39f2de5e12a.tar.bz2 |
[project @ 2002-09-11 14:24:02 by monkeyson]
RISC OS Wimp GUI.
svn path=/import/netsurf/; revision=33
Diffstat (limited to 'desktop/fetch.c')
-rw-r--r-- | desktop/fetch.c | 344 |
1 files changed, 344 insertions, 0 deletions
diff --git a/desktop/fetch.c b/desktop/fetch.c new file mode 100644 index 000000000..a7881fcc2 --- /dev/null +++ b/desktop/fetch.c @@ -0,0 +1,344 @@ +/** + * $Id: fetch.c,v 1.1 2002/09/11 14:24:02 monkeyson Exp $ + */ + +#include "libxml/HTMLparser.h" +#include "netsurf/render/box.h" +#include "netsurf/render/css.h" +#include "netsurf/desktop/browser.h" +#include "netsurf/desktop/netsurf.h" +#include "netsurf/desktop/fetch.h" +#include "netsurf/render/utils.h" +#include "curl/curl.h" +#include <time.h> +#include <string.h> +#include <stdio.h> + +void fetch_identify_location(struct fetch* f, char* location, char* previous) +{ + FILE* ff = fopen("identify", "a"); + fprintf(ff, "identify: '%s' '%s'", location, previous); + if (f->location != NULL) + fprintf(ff, " '%s'\n", f->location); + else + fprintf(ff, "\n"); + fclose(ff); + + if (f->location != NULL) + xfree(f->location); + + if (strspn(location, "http://") == strlen("http://")) + { + f->location = xstrdup(location); + f->type = fetch_CURL; + return; + } + else if (strspn(location, "file:/") == strlen("file:/")) + { + f->location = xstrdup(location); + f->type = fetch_FILE; + return; + } + else if (previous != NULL) + { + char* ext = strrchr(previous, '/'); + + if (ext != NULL && ext != previous) + { + int len = (int)(ext - previous) + strlen(location) + 2; + char* combined = xcalloc(len, sizeof(char)); + strncpy(combined, previous, (int)(ext - previous)); + strcpy(combined + (ext - previous), "/"); + strcpy(combined + (ext - previous) + 1, location); + fetch_identify_location(f, combined, NULL); + xfree(combined); + return; + } + } + + f->location = xcalloc(strlen(location) + strlen("http://") + 1, sizeof(char)); + sprintf(f->location, "http://%s", location); + f->type = fetch_CURL; + return; +} + +struct fetch* create_fetch(char* location, char* previous, fetch_flags f, struct fetch_request* r) +{ + struct fetch* fetch = (struct fetch*) xcalloc(1, sizeof(struct fetch)); + + fetch_identify_location(fetch, location, previous); + + fetch->flags = f; + + fetch->status = fetch_STATUS_WAIT; + fetch->bytes_fetched = 0; + fetch->bytes_total = -1; + + fetch->request = r; + + fetch->start_time = time(&fetch->start_time); + + fetch->next = netsurf_fetches; + netsurf_fetches = fetch; + + return fetch; +} + +void fetch_destroy(struct fetch* f) +{ + if (f == NULL) + return; + + if (netsurf_fetches == f) + netsurf_fetches = f->next; + else + { + struct fetch* ff = netsurf_fetches; + while (ff->next != f && ff->next != NULL) + ff = ff->next; + if (ff->next == f) + ff->next = f->next; + } + + xfree(f->location); + xfree(f->request); + xfree(f); +} + +struct fetch* fetch_cancel(struct fetch* f) +{ + if (f == NULL) + return NULL; + + /* may need to contact server here */ + + f->status = fetch_DELETED; + /* fetch may not necessarily be destroyed if the cancelling can't be done + instantly */ + return f; +} + +void fetch_receive(struct fetch* f, int amount, char* bytes) +{ + struct browser_message msg; + + f->bytes_fetched = f->bytes_fetched + amount; + + switch (f->request->type) + { + case REQUEST_FROM_BROWSER: + msg.type = msg_FETCH_DATA; + msg.f = f; + msg.data.fetch_data.block = bytes; + msg.data.fetch_data.block_size = amount; + if (browser_window_message(f->request->requestor.browser, &msg) != 0) + { + fetch_cancel(f); + return; + } + break; + default: + break; + } + + if (f->bytes_fetched >= f->bytes_total && f->bytes_total != -1) + { + msg.type = msg_FETCH_FINISHED; + msg.f = f; + browser_window_message(f->request->requestor.browser, &msg); + fetch_destroy(f); + } + + return; +} + +size_t fetch_curl_data(void * data, size_t size, size_t nmemb, struct fetch* f) +{ + struct browser_message msg; + msg.type = msg_FETCH_DATA; + msg.f = f; + msg.data.fetch_data.block = data; + msg.data.fetch_data.block_size = size * nmemb; + Log("fetch_poll","sending curl's FETCH_DATA to browser"); + browser_window_message(f->request->requestor.browser, &msg); + return size * nmemb; +} + +struct fetch* fetch_poll(struct fetch* f) +{ + struct fetch* ret = f; + + Log("fetch_poll","polling..."); + + if (f == NULL) + { + Log("fetch_poll","null fetch; returning"); + return f; + } + + if (f->type == fetch_DELETED) + { + ret = f->next; + Log("fetch_poll", "deleting marked fetch"); + fetch_destroy(f); + Log("fetch_poll", "moving on..."); + return fetch_poll(ret); + } + else if (f->type == fetch_CURL && f->status == fetch_STATUS_WAIT) + { + struct browser_message msg; + CURL* curl; + + Log("fetch_poll","init curl"); + curl = curl_easy_init(); + Log("fetch_poll","init curl returned"); + if (curl != 0) + { + Log("fetch_poll","init curl OK"); + /* shouldn't assume this! somehow work it out instead. */ + msg.type = msg_FETCH_FETCH_INFO; + msg.f = f; + msg.data.fetch_info.type = type_HTML; + msg.data.fetch_info.total_size = -1; + + if (browser_window_message(f->request->requestor.browser, &msg) == 0) + { + Log("fetch_poll","about to set options"); + curl_easy_setopt(curl, CURLOPT_URL, f->location); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fetch_curl_data); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, f); + Log("fetch_poll","about to perform"); + curl_easy_perform(curl); + Log("fetch_poll","about to cleanup"); + curl_easy_cleanup(curl); + + Log("fetch_poll","cleanup finished"); + msg.type = msg_FETCH_FINISHED; + msg.f = f; + Log("fetch_poll","sending FETCH_FINISHED to browser"); + browser_window_message(f->request->requestor.browser, &msg); + Log("fetch_poll","FETCH_FINISHED accepted"); + + ret = f->next; + Log("fetch_poll","Destroying f"); + fetch_destroy(f); + Log("fetch_poll","Moving on..."); + return fetch_poll(ret); + } + Log("fetch_poll","about to cleanup since requestor went funny"); + curl_easy_cleanup(curl); + + Log("fetch_poll","Requesting browser didn't like something"); + ret = f->next; + Log("fetch_poll","Cancelling fetch"); + f = fetch_cancel(f); + return fetch_poll(ret); + } + + Log("fetch_poll","we are aborting the mission"); + msg.type = msg_FETCH_ABORT; + msg.f = f; + browser_window_message(f->request->requestor.browser, &msg); + Log("fetch_poll","ABORT message sent to browser"); + + ret = f->next; + fetch_destroy(f); + return fetch_poll(ret); /* carry on polling */ + } + else if (f->type == fetch_FILE && f->status == fetch_STATUS_WAIT) + { + struct browser_message msg; + char actual_filename[1024]; + FILE* in; + + gui_file_to_filename(f->location, actual_filename, 1024); + in = fopen("files","a"); + fprintf(in, "%s\n%s\n\n",f->location, actual_filename); + fclose(in); + in = fopen(actual_filename, "r"); + + if (in == NULL) + { + /* can't open file -- send abort to requestor, then destroy */ + Log("fetch_poll","can't open file"); + msg.type = msg_FETCH_ABORT; + msg.f = f; + browser_window_message(f->request->requestor.browser, &msg); + Log("fetch_poll","ABORT message sent to browser"); + + ret = f->next; + fetch_destroy(f); + Log("fetch_poll","destroyed f; moving on"); + + return fetch_poll(ret); /* carry on polling */ + } + else + { + /* file opened successfully. now to send size and type to requestor, + then the data, then finish. */ + int size; + + /* calculate size */ + Log("fetch_poll","calculating file size"); + fseek(in, 0, SEEK_END); + size = (int) ftell(in); + fclose(in); + + /* send file info. (assuming HTML at the mo, but should work out + what it is, somehow) */ + msg.type = msg_FETCH_FETCH_INFO; + msg.f = f; + msg.data.fetch_info.type = type_HTML; + msg.data.fetch_info.total_size = size; + + Log("fetch_poll","sending FETCH_INFO to browser"); + if (browser_window_message(f->request->requestor.browser, &msg) == 0) + { + /* file info accepted. can now load the data and send it */ + Log("fetch_poll","FETCH_INFO accepted"); + f->status = fetch_STATUS_FETCH; + + /* load and send data */ + msg.type = msg_FETCH_DATA; + msg.f = f; + msg.data.fetch_data.block = load(actual_filename); + msg.data.fetch_data.block_size = size; + Log("fetch_poll","sending FETCH_DATA to browser"); + if (browser_window_message(f->request->requestor.browser, &msg) == 0) + { + xfree(msg.data.fetch_data.block); + /* data accepted. no more data, so finish */ + Log("fetch_poll","FETCH_DATA accepted"); + f->status = fetch_STATUS_FINISH; + + /* send finish */ + msg.type = msg_FETCH_FINISHED; + msg.f = f; + Log("fetch_poll","sending FETCH_FINISHED to browser"); + browser_window_message(f->request->requestor.browser, &msg); + Log("fetch_poll","FETCH_FINISHED accepted"); + + ret = f->next; + Log("fetch_poll","Destroying f"); + fetch_destroy(f); + Log("fetch_poll","Moving on..."); + return fetch_poll(ret); + /* destroy this fetch, then move on to next fetch to poll */ + } + xfree(msg.data.fetch_data.block); + } + + /* requestor didn't like something, and wants the fetch cancelled */ + Log("fetch_poll","Requesting browser didn't like something"); + ret = f->next; + Log("fetch_poll","Cancelling fetch"); + f = fetch_cancel(f); + return fetch_poll(ret); + } + } + + Log("fetch_poll","Moving on (at end of function with f->next)"); + f->next = fetch_poll(f->next); + return f; +} + |