r13799 mmu_man - /branches/mmu_man/netsurf-gopher-support-v3/content/gopher.c
by netsurf@semichrome.net
Author: mmu_man
Date: Fri Apr 6 14:31:23 2012
New Revision: 13799
URL: http://source.netsurf-browser.org?rev=13799&view=rev
Log:
Apply and merge r12397 from v2 branch: Some cleanup in comments. Added notes on possible issues.
Use html_escape_string() in one more place.
Modified:
branches/mmu_man/netsurf-gopher-support-v3/content/gopher.c
Modified: branches/mmu_man/netsurf-gopher-support-v3/content/gopher.c
URL: http://source.netsurf-browser.org/branches/mmu_man/netsurf-gopher-support...
==============================================================================
--- branches/mmu_man/netsurf-gopher-support-v3/content/gopher.c (original)
+++ branches/mmu_man/netsurf-gopher-support-v3/content/gopher.c Fri Apr 6 14:31:23 2012
@@ -81,6 +81,20 @@
free(s);
}
+/**
+ * Handle incoming data from the fetcher and convert it to HTML.
+ *
+ * \return the amount of consumed data
+ *
+ * This calls of a series of functions. To generate a complete page,
+ * call the following functions in order:
+ *
+ * gopher_generate_top()
+ * gopher_generate_title()
+ * gopher_generate_row() -- call 'n' times for 'n' rows
+ * gopher_generate_bottom()
+ *
+ */
size_t gopher_fetch_data(struct gopher_state *s, char *data, size_t size)
{
@@ -108,6 +122,11 @@
return 0;
}
+ /* XXX: should we loop there until remaining is 0 ? Seems not needed. */
+ /* XXX: note there is a possibility of endless loop if a line is larger
+ * than the input buffer...
+ */
+
fprintf(stderr, "iteration: cached %d remaining %d\n", s->cached, remaining);
p = s->input;
@@ -132,6 +151,9 @@
msg.data.header_or_data.len = strlen(buffer);
fetch_send_callback(&msg, s->fetch_handle);
}
+ /* XXX: should we implement
+ * gopher://gophernicus.org/0/doc/gopher/gopher-title-resource.txt ?
+ */
title = gen_nice_title(nsurl_access(s->url));
if (gopher_generate_title(title, buffer, sizeof(buffer)))
{
@@ -163,7 +185,7 @@
memmove(s->input, s->input + s->cached - left, left);
s->cached = left;
- return size /* - left*/;
+ return size;
}
@@ -218,34 +240,10 @@
int title_length;
/* Convert path for display */
- nice_path = malloc(strlen(path) * SLEN("&") + 1);
+ nice_path = html_escape_string(path);
if (nice_path == NULL) {
return NULL;
}
-
- /* Escape special HTML characters */
- for (cnv = nice_path, tmp = path; *tmp != '\0'; tmp++) {
- if (*tmp == '<') {
- *cnv++ = '&';
- *cnv++ = 'l';
- *cnv++ = 't';
- *cnv++ = ';';
- } else if (*tmp == '>') {
- *cnv++ = '&';
- *cnv++ = 'g';
- *cnv++ = 't';
- *cnv++ = ';';
- } else if (*tmp == '&') {
- *cnv++ = '&';
- *cnv++ = 'a';
- *cnv++ = 'm';
- *cnv++ = 'p';
- *cnv++ = ';';
- } else {
- *cnv++ = *tmp;
- }
- }
- *cnv = '\0';
/* Construct a localised title string */
title_length = (cnv - nice_path) + strlen(messages_get("FileIndex"));
@@ -269,7 +267,6 @@
* Convert the gopher item type to mime type
*
* \return MIME type string
- *
*/
const char *gopher_type_to_mime(char type)
@@ -306,14 +303,6 @@
* Generates the top part of an HTML directory listing page
*
* \return true iff buffer filled without error
- *
- * This is part of a series of functions. To generate a complete page,
- * call the following functions in order:
- *
- * gopher_generate_top()
- * gopher_generate_title()
- * gopher_generate_row() -- call 'n' times for 'n' rows
- * gopher_generate_bottom()
*/
static bool gopher_generate_top(char *buffer, int buffer_length)
@@ -346,14 +335,6 @@
* \param buffer buffer to fill with generated HTML
* \param buffer_length maximum size of buffer
* \return true iff buffer filled without error
- *
- * This is part of a series of functions. To generate a complete page,
- * call the following functions in order:
- *
- * gopher_generate_top()
- * gopher_generate_title()
- * gopher_generate_row() -- call 'n' times for 'n' rows
- * gopher_generate_bottom()
*/
static bool gopher_generate_title(const char *title, char *buffer, int buffer_length)
@@ -585,14 +566,6 @@
* \param buffer buffer to fill with generated HTML
* \param buffer_length maximum size of buffer
* \return true iff buffer filled without error
- *
- * This is part of a series of functions. To generate a complete page,
- * call the following functions in order:
- *
- * gopher_generate_top()
- * gopher_generate_title()
- * gopher_generate_row() -- call 'n' times for 'n' rows
- * gopher_generate_bottom()
*/
static bool gopher_generate_row(const char **data, size_t *size,
@@ -676,14 +649,6 @@
* Generates the bottom part of an HTML directory listing page
*
* \return Bottom of directory listing HTML
- *
- * This is part of a series of functions. To generate a complete page,
- * call the following functions in order:
- *
- * gopher_generate_top()
- * gopher_generate_title()
- * gopher_generate_row() -- call 'n' times for 'n' rows
- * gopher_generate_bottom()
*/
static bool gopher_generate_bottom(char *buffer, int buffer_length)
11 years, 2 months
r13798 mmu_man - in /branches/mmu_man/netsurf-gopher-support-v3: Makefile.sources content/fetchers/curl.c content/gopher.c content/gopher.h
by netsurf@semichrome.net
Author: mmu_man
Date: Fri Apr 6 12:16:37 2012
New Revision: 13798
URL: http://source.netsurf-browser.org?rev=13798&view=rev
Log:
Apply and merge r12396 from v2 branch: Gopher support using the fetcher approach. The curl fetcher gets some minimal changes to avoid replicating it, but most of the work is done in content/gopher.c which maintains its own state including an input buffer for caching unterminated lines. Seems to work so far.
Added:
branches/mmu_man/netsurf-gopher-support-v3/content/gopher.c
branches/mmu_man/netsurf-gopher-support-v3/content/gopher.h
Modified:
branches/mmu_man/netsurf-gopher-support-v3/Makefile.sources
branches/mmu_man/netsurf-gopher-support-v3/content/fetchers/curl.c
Modified: branches/mmu_man/netsurf-gopher-support-v3/Makefile.sources
URL: http://source.netsurf-browser.org/branches/mmu_man/netsurf-gopher-support...
==============================================================================
--- branches/mmu_man/netsurf-gopher-support-v3/Makefile.sources (original)
+++ branches/mmu_man/netsurf-gopher-support-v3/Makefile.sources Fri Apr 6 12:16:37 2012
@@ -4,8 +4,8 @@
# Included by main makefile -- indicates generic sources for every build.
#
-S_CONTENT := content.c content_factory.c dirlist.c fetch.c hlcache.c \
- llcache.c mimesniff.c urldb.c
+S_CONTENT := content.c content_factory.c dirlist.c fetch.c gopher.c \
+ hlcache.c llcache.c mimesniff.c urldb.c
S_FETCHERS := curl.c data.c file.c about.c resource.c
Modified: branches/mmu_man/netsurf-gopher-support-v3/content/fetchers/curl.c
URL: http://source.netsurf-browser.org/branches/mmu_man/netsurf-gopher-support...
==============================================================================
--- branches/mmu_man/netsurf-gopher-support-v3/content/fetchers/curl.c (original)
+++ branches/mmu_man/netsurf-gopher-support-v3/content/fetchers/curl.c Fri Apr 6 12:16:37 2012
@@ -43,6 +43,7 @@
#include <openssl/ssl.h>
#include "content/fetch.h"
#include "content/fetchers/curl.h"
+#include "content/gopher.h"
#include "content/urldb.h"
#include "desktop/netsurf.h"
#include "desktop/options.h"
@@ -91,6 +92,7 @@
#define MAX_CERTS 10
struct cert_info cert_data[MAX_CERTS]; /**< HTTPS certificate data */
unsigned int last_progress_update; /**< Time of last progress update */
+ struct gopher_state *gopher; /**< gopher-specific state */
};
struct cache_handle {
@@ -115,6 +117,10 @@
static void fetch_curl_finalise(lwc_string *scheme);
static bool fetch_curl_can_fetch(const nsurl *url);
static void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
+ bool only_2xx, const char *post_urlenc,
+ const struct fetch_multipart_data *post_multipart,
+ const char **headers);
+static void * fetch_curl_setup_gopher(struct fetch *parent_fetch, nsurl *url,
bool only_2xx, const char *post_urlenc,
const struct fetch_multipart_data *post_multipart,
const char **headers);
@@ -233,6 +239,7 @@
data = curl_version_info(CURLVERSION_NOW);
for (i = 0; data->protocols[i]; i++) {
+ fetcher_setup_fetch setup_hook = fetch_curl_setup;
if (strcmp(data->protocols[i], "http") == 0) {
if (lwc_intern_string("http", SLEN("http"),
&scheme) != lwc_error_ok) {
@@ -247,6 +254,15 @@
"(couldn't intern \"https\").");
}
+ } else if (strcmp(data->protocols[i], "gopher") == 0) {
+ if (lwc_intern_string("gopher", SLEN("gopher"),
+ &scheme) != lwc_error_ok) {
+ die("Failed to initialise the fetch module "
+ "(couldn't intern \"gopher\").");
+ }
+ /* We use a different setup hook */
+ setup_hook = fetch_curl_setup_gopher;
+
} else {
/* Ignore non-http(s) protocols */
continue;
@@ -255,7 +271,7 @@
if (!fetch_add_fetcher(scheme,
fetch_curl_initialise,
fetch_curl_can_fetch,
- fetch_curl_setup,
+ setup_hook,
fetch_curl_start,
fetch_curl_abort,
fetch_curl_free,
@@ -387,6 +403,7 @@
fetch->post_multipart = fetch_curl_post_convert(post_multipart);
memset(fetch->cert_data, 0, sizeof(fetch->cert_data));
fetch->last_progress_update = 0;
+ fetch->gopher = NULL;
if (fetch->host == NULL ||
(post_multipart != NULL && fetch->post_multipart == NULL) ||
@@ -442,6 +459,53 @@
curl_slist_free_all(fetch->headers);
free(fetch);
return NULL;
+}
+
+
+void * fetch_curl_setup_gopher(struct fetch *parent_fetch, nsurl *url,
+ bool only_2xx, const char *post_urlenc,
+ const struct fetch_multipart_data *post_multipart,
+ const char **headers)
+{
+ struct curl_fetch_info *f;
+ const char *mime;
+ char type;
+ f = fetch_curl_setup(parent_fetch, url, only_2xx, post_urlenc,
+ post_multipart, headers);
+
+ f->gopher = gopher_state_create(f->url, f->fetch_handle);
+ if (f->gopher == NULL) {
+ fetch_curl_free(f);
+ return NULL;
+ }
+
+ if (url_gopher_type(nsurl_access(url), &f->gopher->type) != URL_FUNC_OK
+ || type == GOPHER_TYPE_NONE) {
+ f->http_code = 404;
+ fetch_set_http_code(f->fetch_handle, f->http_code);
+ }
+
+ mime = gopher_type_to_mime(f->gopher->type);
+ /* TODO: add a better API,
+ * fetch_filetype() is wrongly assuming unknown files to be HTML.
+ */
+ if (mime == NULL)
+ mime = fetch_filetype(url);
+
+ if (mime) {
+ char s[80];
+ fetch_msg msg;
+
+ fprintf(stderr, "gopher mime is '%s'\n", mime);
+ snprintf(s, sizeof s, "Content-type: %s\r\n", mime);
+ s[sizeof s - 1] = 0;
+ msg.type = FETCH_HEADER;
+ msg.data.header_or_data.buf = (const uint8_t *) s;
+ msg.data.header_or_data.len = strlen(s);
+ fetch_send_callback(&msg, f->fetch_handle);
+ }
+
+ return f;
}
@@ -740,6 +804,9 @@
X509_free(f->cert_data[i].cert);
}
+ if (f->gopher)
+ gopher_state_free(f->gopher);
+
free(f);
}
@@ -818,6 +885,9 @@
if (abort_fetch == false && (result == CURLE_OK ||
(result == CURLE_WRITE_ERROR && f->stopped == false))) {
+ /* handle incoming gopher data */
+ if (f->gopher)
+ gopher_fetch_data(f->gopher, NULL, 0);
/* fetch completed normally or the server fed us a junk gzip
* stream (usually in the form of garbage at the end of the
* stream). Curl will have fed us all but the last chunk of
@@ -1028,6 +1098,25 @@
CURLcode code;
fetch_msg msg;
+ /* gopher data receives special treatment */
+ if (f->gopher && gopher_need_generate(f->gopher->type)) {
+ /* We didn't receive anything yet, check for error.
+ * type 3 items report an error
+ */
+ if (!f->http_code) {
+ if (data[0] == GOPHER_TYPE_ERROR) {
+ /* TODO: try to guess better from the string ?
+ * like "3 '/bcd' doesn't exist!"
+ * TODO: what about other file types ?
+ */
+ f->http_code = 404;
+ } else {
+ f->http_code = 200;
+ }
+ fetch_set_http_code(f->fetch_handle, f->http_code);
+ }
+ }
+
/* ensure we only have to get this information once */
if (!f->http_code)
{
@@ -1048,6 +1137,11 @@
if (f->abort || (!f->had_headers && fetch_curl_process_headers(f))) {
f->stopped = true;
return 0;
+ }
+
+ /* gopher data receives special treatment */
+ if (f->gopher && gopher_need_generate(f->gopher->type)) {
+ return gopher_fetch_data(f->gopher, data, size * nmemb);
}
/* send data to the caller */
Added: branches/mmu_man/netsurf-gopher-support-v3/content/gopher.c
URL: http://source.netsurf-browser.org/branches/mmu_man/netsurf-gopher-support...
==============================================================================
--- branches/mmu_man/netsurf-gopher-support-v3/content/gopher.c (added)
+++ branches/mmu_man/netsurf-gopher-support-v3/content/gopher.c Fri Apr 6 12:16:37 2012
@@ -1,0 +1,703 @@
+/*
+ * Copyright 2011 François Revol <mmu_man(a)users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Generate HTML content for displaying gopher directory listings (implementation).
+ */
+
+#include <errno.h>
+#include <stddef.h>
+#include <string.h>
+#include <strings.h>
+#include <math.h>
+#include <sys/param.h>
+
+#include "content/content_protected.h"
+#include "content/fetch.h"
+#include "content/gopher.h"
+#include "desktop/gui.h"
+#include "desktop/options.h"
+#include "utils/http.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/utils.h"
+
+static char *gen_nice_title(const char *path);
+static bool gopher_generate_top(char *buffer, int buffer_length);
+static bool gopher_generate_title(const char *title, char *buffer,
+ int buffer_length);
+static bool gopher_generate_row(const char **data, size_t *size,
+ char *buffer, int buffer_length);
+static bool gopher_generate_bottom(char *buffer, int buffer_length);
+
+static struct {
+ gopher_item_type type;
+ const char *mime;
+} gopher_type_map[] = {
+ /* these come from http://tools.ietf.org/html/rfc1436 */
+ { GOPHER_TYPE_TEXTPLAIN, "text/plain" },
+ { GOPHER_TYPE_DIRECTORY, "text/html;charset=UTF-8" },
+ { GOPHER_TYPE_QUERY, "text/html;charset=UTF-8" },
+ { GOPHER_TYPE_GIF, "image/gif" },
+ { GOPHER_TYPE_HTML, "text/html" },
+ /* those are not standardized */
+ { GOPHER_TYPE_PDF, "application/pdf" },
+ { GOPHER_TYPE_PNG, "image/png"},
+ { 0, NULL }
+};
+
+struct gopher_state *gopher_state_create(nsurl *url, struct fetch *fetch_handle)
+{
+ struct gopher_state *ctx;
+ ctx = malloc(sizeof(struct gopher_state));
+ if (ctx == NULL)
+ return NULL;
+ /**/
+ ctx->url = nsurl_ref(url);
+ ctx->fetch_handle = fetch_handle;
+ ctx->head_done = false;
+ ctx->cached = 0;
+ return ctx;
+}
+
+void gopher_state_free(struct gopher_state *s)
+{
+ nsurl_unref(s->url);
+ free(s);
+}
+
+
+size_t gopher_fetch_data(struct gopher_state *s, char *data, size_t size)
+{
+ char buffer[1024];
+ char *p = data;
+ size_t remaining = size;
+ size_t left;
+ fetch_msg msg;
+ fprintf(stderr, "%s(,, %d)\n", __FUNCTION__, size);
+
+ /* actually called when done getting it all */
+ if (size == 0)
+ {
+ if (s->type && gopher_need_generate(s->type)) {
+ if (gopher_generate_bottom(buffer, sizeof(buffer)))
+ {
+ /* send data to the caller */
+ /*LOG(("FETCH_DATA"));*/
+ msg.type = FETCH_DATA;
+ msg.data.header_or_data.buf = (const uint8_t *) buffer;
+ msg.data.header_or_data.len = strlen(buffer);
+ fetch_send_callback(&msg, s->fetch_handle);
+ }
+ }
+ return 0;
+ }
+
+ fprintf(stderr, "iteration: cached %d remaining %d\n", s->cached, remaining);
+
+ p = s->input;
+ left = MIN(sizeof(s->input) - s->cached, remaining);
+ memcpy(s->input + s->cached, data, left);
+ remaining -= left;
+ data += left;
+ s->cached += left;
+ left = s->cached;
+
+ fprintf(stderr, "copied: cached %d remaining %d\n", s->cached, remaining);
+
+ if (!s->head_done)
+ {
+ char *title;
+ if (gopher_generate_top(buffer, sizeof(buffer)))
+ {
+ /* send data to the caller */
+ /*LOG(("FETCH_DATA"));*/
+ msg.type = FETCH_DATA;
+ msg.data.header_or_data.buf = (const uint8_t *) buffer;
+ msg.data.header_or_data.len = strlen(buffer);
+ fetch_send_callback(&msg, s->fetch_handle);
+ }
+ title = gen_nice_title(nsurl_access(s->url));
+ if (gopher_generate_title(title, buffer, sizeof(buffer)))
+ {
+ /* send data to the caller */
+ /*LOG(("FETCH_DATA"));*/
+ msg.type = FETCH_DATA;
+ msg.data.header_or_data.buf = (const uint8_t *) buffer;
+ msg.data.header_or_data.len = strlen(buffer);
+ fetch_send_callback(&msg, s->fetch_handle);
+ }
+ free(title);
+ s->head_done = true;
+ }
+
+ while (gopher_generate_row(&p, &left, buffer, sizeof(buffer)))
+ {
+ //fprintf(stderr, "done row, left %d\n", left);
+ /* send data to the caller */
+ /*LOG(("FETCH_DATA"));*/
+ msg.type = FETCH_DATA;
+ msg.data.header_or_data.buf = (const uint8_t *) buffer;
+ msg.data.header_or_data.len = strlen(buffer);
+ fetch_send_callback(&msg, s->fetch_handle);
+ }
+ fprintf(stderr, "last row, left %d\n", left);
+
+ /* move the remainder to the beginning of the buffer */
+ if (left)
+ memmove(s->input, s->input + s->cached - left, left);
+ s->cached = left;
+
+ return size /* - left*/;
+
+}
+
+
+static char *html_escape_string(char *str)
+{
+ char *nice_str, *cnv, *tmp;
+
+ if (str == NULL) {
+ return NULL;
+ }
+
+ /* Convert str for display */
+ nice_str = malloc(strlen(str) * SLEN("&") + 1);
+ if (nice_str == NULL) {
+ return NULL;
+ }
+
+ /* Escape special HTML characters */
+ for (cnv = nice_str, tmp = str; *tmp != '\0'; tmp++) {
+ if (*tmp == '<') {
+ *cnv++ = '&';
+ *cnv++ = 'l';
+ *cnv++ = 't';
+ *cnv++ = ';';
+ } else if (*tmp == '>') {
+ *cnv++ = '&';
+ *cnv++ = 'g';
+ *cnv++ = 't';
+ *cnv++ = ';';
+ } else if (*tmp == '&') {
+ *cnv++ = '&';
+ *cnv++ = 'a';
+ *cnv++ = 'm';
+ *cnv++ = 'p';
+ *cnv++ = ';';
+ } else {
+ *cnv++ = *tmp;
+ }
+ }
+ *cnv = '\0';
+
+ return nice_str;
+}
+
+
+static char *gen_nice_title(const char *path)
+{
+ const char *tmp;
+ char *nice_path, *cnv;
+ char *title;
+ int title_length;
+
+ /* Convert path for display */
+ nice_path = malloc(strlen(path) * SLEN("&") + 1);
+ if (nice_path == NULL) {
+ return NULL;
+ }
+
+ /* Escape special HTML characters */
+ for (cnv = nice_path, tmp = path; *tmp != '\0'; tmp++) {
+ if (*tmp == '<') {
+ *cnv++ = '&';
+ *cnv++ = 'l';
+ *cnv++ = 't';
+ *cnv++ = ';';
+ } else if (*tmp == '>') {
+ *cnv++ = '&';
+ *cnv++ = 'g';
+ *cnv++ = 't';
+ *cnv++ = ';';
+ } else if (*tmp == '&') {
+ *cnv++ = '&';
+ *cnv++ = 'a';
+ *cnv++ = 'm';
+ *cnv++ = 'p';
+ *cnv++ = ';';
+ } else {
+ *cnv++ = *tmp;
+ }
+ }
+ *cnv = '\0';
+
+ /* Construct a localised title string */
+ title_length = (cnv - nice_path) + strlen(messages_get("FileIndex"));
+ title = malloc(title_length + 1);
+
+ if (title == NULL) {
+ free(nice_path);
+ return NULL;
+ }
+
+ /* Set title to localised "Index of <nice_path>" */
+ snprintf(title, title_length, messages_get("FileIndex"), nice_path);
+
+ free(nice_path);
+
+ return title;
+}
+
+
+/**
+ * Convert the gopher item type to mime type
+ *
+ * \return MIME type string
+ *
+ */
+
+const char *gopher_type_to_mime(char type)
+{
+ int i;
+
+ for (i = 0; gopher_type_map[i].type; i++)
+ if (gopher_type_map[i].type == type)
+ return gopher_type_map[i].mime;
+ return NULL;
+}
+
+
+/**
+ * Tells if the gopher item type needs to be converted to html
+ *
+ * \return true iff the item must be converted
+ *
+ */
+
+bool gopher_need_generate(char type)
+{
+ switch (type) {
+ case '1':
+ case '7':
+ return true;
+ default:
+ return false;
+ }
+}
+
+
+/**
+ * Generates the top part of an HTML directory listing page
+ *
+ * \return true iff buffer filled without error
+ *
+ * This is part of a series of functions. To generate a complete page,
+ * call the following functions in order:
+ *
+ * gopher_generate_top()
+ * gopher_generate_title()
+ * gopher_generate_row() -- call 'n' times for 'n' rows
+ * gopher_generate_bottom()
+ */
+
+static bool gopher_generate_top(char *buffer, int buffer_length)
+{
+ int error = snprintf(buffer, buffer_length,
+ "<html>\n"
+ "<head>\n"
+ /*"<!-- base href=\"%s\" -->\n"*//* XXX: needs the content url */
+ /* Don't do that:
+ * seems to trigger a reparsing of the gopher data itself as html...
+ * "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n"
+ */
+ /* TODO: move this to clean CSS in internal.css */
+ "<link rel=\"stylesheet\" title=\"Standard\" "
+ "type=\"text/css\" href=\"resource:internal.css\">\n");
+
+ if (error < 0 || error >= buffer_length)
+ /* Error or buffer too small */
+ return false;
+ else
+ /* OK */
+ return true;
+}
+
+
+/**
+ * Generates the part of an HTML directory listing page that contains the title
+ *
+ * \param title title to use
+ * \param buffer buffer to fill with generated HTML
+ * \param buffer_length maximum size of buffer
+ * \return true iff buffer filled without error
+ *
+ * This is part of a series of functions. To generate a complete page,
+ * call the following functions in order:
+ *
+ * gopher_generate_top()
+ * gopher_generate_title()
+ * gopher_generate_row() -- call 'n' times for 'n' rows
+ * gopher_generate_bottom()
+ */
+
+static bool gopher_generate_title(const char *title, char *buffer, int buffer_length)
+{
+ int error;
+
+ if (title == NULL)
+ title = "";
+
+ error = snprintf(buffer, buffer_length,
+ "<title>%s</title>\n"
+ "</head>\n"
+ "<body id=\"gopher\">\n"
+ "<h1>%s</h1>\n",
+ title, title);
+ if (error < 0 || error >= buffer_length)
+ /* Error or buffer too small */
+ return false;
+ else
+ /* OK */
+ return true;
+}
+
+/**
+ * Internal worker called by gopher_generate_row().
+ */
+
+static bool gopher_generate_row_internal(char type, char *fields[5],
+ char *buffer, int buffer_length)
+{
+ char *nice_text;
+ char *redirect_url = NULL;
+ int error;
+ bool alt_port = false;
+ char *username = NULL;
+
+ if (fields[3] && strcmp(fields[3], "70"))
+ alt_port = true;
+
+ /* escape html special characters */
+ nice_text = html_escape_string(fields[0]);
+
+ /* XXX: outputting \n generates better looking html code,
+ * but currently screws up indentation due to a bug.
+ */
+#define HTML_LF
+/*#define HTML_LF "\n"*/
+
+ switch (type) {
+ case '.':
+ /* end of the page */
+ *buffer = '\0';
+ break;
+ case '0': /* text/plain link */
+ error = snprintf(buffer, buffer_length,
+ "<a href=\"gopher://%s%s%s/%c%s\">"HTML_LF
+ "<span class=\"text\">%s</span></a>"HTML_LF
+ "<br/>"HTML_LF,
+ fields[2],
+ alt_port ? ":" : "",
+ alt_port ? fields[3] : "",
+ type, fields[1], nice_text);
+ break;
+ case '9': /* binary */
+ error = snprintf(buffer, buffer_length,
+ "<a href=\"gopher://%s%s%s/%c%s\">"HTML_LF
+ "<span class=\"binary\">%s</span></a>"HTML_LF
+ "<br/>"HTML_LF,
+ fields[2],
+ alt_port ? ":" : "",
+ alt_port ? fields[3] : "",
+ type, fields[1], nice_text);
+ break;
+ case '1':
+ /*
+ * directory link
+ */
+ error = snprintf(buffer, buffer_length,
+ "<a href=\"gopher://%s%s%s/%c%s\">"HTML_LF
+ "<span class=\"dir\">%s</span></a>"HTML_LF
+ "<br/>"HTML_LF,
+ fields[2],
+ alt_port ? ":" : "",
+ alt_port ? fields[3] : "",
+ type, fields[1], nice_text);
+ break;
+ case '3':
+ /* Error
+ */
+ error = snprintf(buffer, buffer_length,
+ "<span class=\"error\">%s</span><br/>"HTML_LF,
+ nice_text);
+ break;
+ case '7':
+ /* TODO: handle search better.
+ * For now we use an unnamed input field and accept sending ?=foo
+ * as it seems at least Veronica-2 ignores the = but it's unclean.
+ */
+ error = snprintf(buffer, buffer_length,
+ "<form method=\"get\" action=\"gopher://%s%s%s/%c%s\">"HTML_LF
+ "<span class=\"query\">"
+ "<label>%s "
+ "<input name=\"\" type=\"text\" align=\"right\" />"
+ "</label>"
+ "</span></form>"HTML_LF
+ "<br/>"HTML_LF,
+ fields[2],
+ alt_port ? ":" : "",
+ alt_port ? fields[3] : "",
+ type, fields[1], nice_text);
+ break;
+ case '8':
+ /* telnet: links
+ * cf. gopher://78.80.30.202/1/ps3
+ * -> gopher://78.80.30.202:23/8/ps3/new -> new(a)78.80.30.202
+ */
+ alt_port = false;
+ if (fields[3] && strcmp(fields[3], "23"))
+ alt_port = true;
+ username = strrchr(fields[1], '/');
+ if (username)
+ username++;
+ error = snprintf(buffer, buffer_length,
+ "<a href=\"telnet://%s%s%s%s%s\">"HTML_LF
+ "<span class=\"dir\">%s</span></a>"HTML_LF
+ "<br/>"HTML_LF,
+ username ? username : "",
+ username ? "@" : "",
+ fields[2],
+ alt_port ? ":" : "",
+ alt_port ? fields[3] : "",
+ nice_text);
+ break;
+ case 'g':
+ case 'I':
+ case 'p':
+ /* quite dangerous, cf. gopher://namcub.accela-labs.com/1/pics */
+ if (nsoption_bool(gopher_inline_images)) {
+ error = snprintf(buffer, buffer_length,
+ "<a href=\"gopher://%s%s%s/%c%s\">"HTML_LF
+ "<span class=\"img\">%s "HTML_LF /* </span><br/> */
+ //"<span class=\"img\" >"HTML_LF
+ "<img src=\"gopher://%s%s%s/%c%s\" alt=\"%s\"/>"HTML_LF
+ "</span>"
+ "</a>"
+ "<br/>"HTML_LF,
+ fields[2],
+ alt_port ? ":" : "",
+ alt_port ? fields[3] : "",
+ type, fields[1],
+ nice_text,
+ fields[2],
+ alt_port ? ":" : "",
+ alt_port ? fields[3] : "",
+ type, fields[1],
+ nice_text);
+ break;
+ }
+ /* fallback to default, link them */
+ error = snprintf(buffer, buffer_length,
+ "<a href=\"gopher://%s%s%s/%c%s\">"HTML_LF
+ "<span class=\"dir\">%s</span></a>"HTML_LF
+ "<br/>"HTML_LF,
+ fields[2],
+ alt_port ? ":" : "",
+ alt_port ? fields[3] : "",
+ type, fields[1], nice_text);
+ break;
+ case 'h':
+ if (fields[1] && strncmp(fields[1], "URL:", 4) == 0)
+ redirect_url = fields[1] + 4;
+ /* cf. gopher://pineapple.vg/1 */
+ if (fields[1] && strncmp(fields[1], "/URL:", 5) == 0)
+ redirect_url = fields[1] + 5;
+ if (redirect_url) {
+ error = snprintf(buffer, buffer_length,
+ "<a href=\"%s\">"HTML_LF
+ "<span class=\"link\">%s</span></a>"HTML_LF
+ "<br/>"HTML_LF,
+ redirect_url,
+ nice_text);
+ } else {
+ /* cf. gopher://sdf.org/1/sdf/classes/ */
+ error = snprintf(buffer, buffer_length,
+ "<a href=\"gopher://%s%s%s/%c%s\">"HTML_LF
+ "<span class=\"dir\">%s</span></a>"HTML_LF
+ "<br/>"HTML_LF,
+ fields[2],
+ alt_port ? ":" : "",
+ alt_port ? fields[3] : "",
+ type, fields[1], nice_text);
+ }
+ break;
+ case 'i':
+ error = snprintf(buffer, buffer_length,
+ "<span class=\"info\">%s</span><br/>"HTML_LF,
+ nice_text);
+ break;
+ default:
+ LOG(("warning: unknown gopher item type 0x%02x '%c'\n", type, type));
+ error = snprintf(buffer, buffer_length,
+ "<a href=\"gopher://%s%s%s/%c%s\">"HTML_LF
+ "<span class=\"dir\">%s</span></a>"HTML_LF
+ "<br/>"HTML_LF,
+ fields[2],
+ alt_port ? ":" : "",
+ alt_port ? fields[3] : "",
+ type, fields[1], nice_text);
+ break;
+ }
+
+ free(nice_text);
+
+ if (error < 0 || error >= buffer_length)
+ /* Error or buffer too small */
+ return false;
+ else
+ /* OK */
+ return true;
+}
+
+
+/**
+ * Generates the part of an HTML directory listing page that displays a row
+ * of the gopher data
+ *
+ * \param size pointer to the data buffer pointer
+ * \param size pointer to the remaining data size
+ * \param buffer buffer to fill with generated HTML
+ * \param buffer_length maximum size of buffer
+ * \return true iff buffer filled without error
+ *
+ * This is part of a series of functions. To generate a complete page,
+ * call the following functions in order:
+ *
+ * gopher_generate_top()
+ * gopher_generate_title()
+ * gopher_generate_row() -- call 'n' times for 'n' rows
+ * gopher_generate_bottom()
+ */
+
+static bool gopher_generate_row(const char **data, size_t *size,
+ char *buffer, int buffer_length)
+{
+ bool ok = false;
+ char type = 0;
+ int field = 0;
+ /* name, selector, host, port, gopher+ flag */
+ char *fields[5] = { NULL, NULL, NULL, NULL, NULL };
+ const char *s = *data;
+ const char *p = *data;
+ int i;
+ size_t sz = *size;
+
+ for (; sz && *p; p++, sz--) {
+ if (!type) {
+ type = *p;
+ if (!type || type == '\n' || type == '\r') {
+ LOG(("warning: invalid gopher item type 0x%02x\n", type));
+ }
+ s++;
+ continue;
+ }
+ switch (*p) {
+ case '\n':
+ if (field > 0) {
+ LOG(("warning: unterminated gopher item '%c'\n", type));
+ }
+ //FALLTHROUGH
+ case '\r':
+ if (sz < 1 || p[1] != '\n') {
+ LOG(("warning: CR without LF in gopher item '%c'\n", type));
+ }
+ if (field < 3 && type != '.') {
+ LOG(("warning: unterminated gopher item '%c'\n", type));
+ }
+ fields[field] = malloc(p - s + 1);
+ memcpy(fields[field], s, p - s);
+ fields[field][p - s] = '\0';
+ if (type == '.' && field == 0 && p == s) {
+ ;/* XXX: signal end of page? For now we just ignore it. */
+ }
+ ok = gopher_generate_row_internal(type, fields, buffer, buffer_length);
+ for (i = 0; i < 5; i++) {
+ free(fields[i]);
+ fields[i] = NULL;
+ }
+ sz--;
+ p++;
+ if (sz && *p == '\n') {
+ p++;
+ sz--;
+ }
+ *data = p;
+ field = 0;
+ if (ok)
+ *size = sz;
+ return ok;
+ case '\x09':
+ if (field >= 4) {
+ LOG(("warning: extra tab in gopher item '%c'\n", type));
+ break;
+ }
+ fields[field] = malloc(p - s + 1);
+ memcpy(fields[field], s, p - s);
+ fields[field][p - s] = '\0';
+ field++;
+ s = p + 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return false;
+}
+
+
+/**
+ * Generates the bottom part of an HTML directory listing page
+ *
+ * \return Bottom of directory listing HTML
+ *
+ * This is part of a series of functions. To generate a complete page,
+ * call the following functions in order:
+ *
+ * gopher_generate_top()
+ * gopher_generate_title()
+ * gopher_generate_row() -- call 'n' times for 'n' rows
+ * gopher_generate_bottom()
+ */
+
+static bool gopher_generate_bottom(char *buffer, int buffer_length)
+{
+ int error = snprintf(buffer, buffer_length,
+ "</div>\n"
+ "</body>\n"
+ "</html>\n");
+ if (error < 0 || error >= buffer_length)
+ /* Error or buffer too small */
+ return false;
+ else
+ /* OK */
+ return true;
+}
+
+
Added: branches/mmu_man/netsurf-gopher-support-v3/content/gopher.h
URL: http://source.netsurf-browser.org/branches/mmu_man/netsurf-gopher-support...
==============================================================================
--- branches/mmu_man/netsurf-gopher-support-v3/content/gopher.h (added)
+++ branches/mmu_man/netsurf-gopher-support-v3/content/gopher.h Fri Apr 6 12:16:37 2012
@@ -1,0 +1,72 @@
+/*
+ * Copyright 2011 François Revol <mmu_man(a)users.sourceforge.net>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Generate HTML content for displaying gopher directory listings (interface).
+ */
+
+
+#ifndef NETSURF_CONTENT_GOPHER_H
+#define NETSURF_CONTENT_GOPHER_H
+
+#include <stddef.h>
+
+typedef enum {
+ GOPHER_TYPE_NONE = 0, /* none set */
+ /* these come from http://tools.ietf.org/html/rfc1436 */
+ GOPHER_TYPE_TEXTPLAIN = '0',
+ GOPHER_TYPE_DIRECTORY = '1',
+ GOPHER_TYPE_CSO_SEARCH = '2',
+ GOPHER_TYPE_ERROR = '3', /* error message */
+ GOPHER_TYPE_BINHEX = '4', /* binhex encoded text */
+ GOPHER_TYPE_BINARCHIVE = '5', /* binary archive file */
+ GOPHER_TYPE_UUENCODED = '6', /* uuencoded text */
+ GOPHER_TYPE_QUERY = '7', /* search query */
+ GOPHER_TYPE_TELNET = '8', /* telnet link */
+ GOPHER_TYPE_BINARY = '9',
+ GOPHER_TYPE_GIF = 'g', /* GIF image */
+ GOPHER_TYPE_HTML = 'h', /* HTML file or URL */
+ GOPHER_TYPE_INFO = 'i', /* information text */
+ GOPHER_TYPE_IMAGE = 'I', /* image (depends, usually jpeg) */
+ GOPHER_TYPE_AUDIO = 's', /* audio (wav?) */
+ GOPHER_TYPE_TN3270 = 'T', /* tn3270 session */
+ /* those are not standardized */
+ GOPHER_TYPE_PDF = 'd', /* seems to be only for PDF files */
+ GOPHER_TYPE_PNG = 'p' /* cf. gopher://namcub.accelera-labs.com/1/pics */
+} gopher_item_type;
+
+struct gopher_state {
+ char type; /**< Gopher document type */
+ nsurl *url; /**< the fetched URL */
+ struct fetch *fetch_handle; /**< Copy of the fetch handle */
+ bool head_done; /**< We already sent the <head> part */
+ size_t cached; /**< Amount of cached data in the input buffer */
+ char input[2048]; /**< input buffer */
+
+};
+
+struct gopher_state *gopher_state_create(nsurl *url, struct fetch *fetch_handle);
+void gopher_state_free(struct gopher_state *s);
+
+size_t gopher_fetch_data(struct gopher_state *s, char *data, size_t size);
+
+const char *gopher_type_to_mime(char type);
+bool gopher_need_generate(char type);
+
+
+#endif
11 years, 2 months
r13797 chris_y - /trunk/netsurf/amiga/dt_picture.c
by netsurf@semichrome.net
Author: chris_y
Date: Fri Apr 6 12:05:25 2012
New Revision: 13797
URL: http://source.netsurf-browser.org?rev=13797&view=rev
Log:
Convert to use image cache
Modified:
trunk/netsurf/amiga/dt_picture.c
Modified: trunk/netsurf/amiga/dt_picture.c
URL: http://source.netsurf-browser.org/trunk/netsurf/amiga/dt_picture.c?rev=13...
==============================================================================
--- trunk/netsurf/amiga/dt_picture.c (original)
+++ trunk/netsurf/amiga/dt_picture.c Fri Apr 6 12:05:25 2012
@@ -26,6 +26,7 @@
#include "content/content_protected.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
+#include "image/image_cache.h"
#include "render/box.h"
#include "utils/log.h"
#include "utils/messages.h"
@@ -37,45 +38,21 @@
#include <datatypes/pictureclass.h>
#include <intuition/classusr.h>
-typedef struct amiga_dt_picture_content {
- struct content base;
-
- struct bitmap *bitmap; /**< Created NetSurf bitmap */
-
- Object *dto;
- int x;
- int y;
- int w;
- int h;
-} amiga_dt_picture_content;
-
static nserror amiga_dt_picture_create(const content_handler *handler,
lwc_string *imime_type, const http_parameter *params,
llcache_handle *llcache, const char *fallback_charset,
bool quirks, struct content **c);
static bool amiga_dt_picture_convert(struct content *c);
-static void amiga_dt_picture_destroy(struct content *c);
-static bool amiga_dt_picture_redraw(struct content *c,
- struct content_redraw_data *data, const struct rect *clip,
- const struct redraw_context *ctx);
static nserror amiga_dt_picture_clone(const struct content *old, struct content **newc);
-static content_type amiga_dt_picture_content_type(void);
-
-static void *amiga_dt_picture_get_internal(const struct content *c, void *context)
-{
- amiga_dt_picture_content *pic_c = (amiga_dt_picture_content *) c;
-
- return pic_c->bitmap;
-}
static const content_handler amiga_dt_picture_content_handler = {
.create = amiga_dt_picture_create,
.data_complete = amiga_dt_picture_convert,
- .destroy = amiga_dt_picture_destroy,
- .redraw = amiga_dt_picture_redraw,
+ .destroy = image_cache_destroy,
+ .redraw = image_cache_redraw,
.clone = amiga_dt_picture_clone,
- .get_internal = amiga_dt_picture_get_internal,
- .type = amiga_dt_picture_content_type,
+ .get_internal = image_cache_get_internal,
+ .type = image_cache_content_type,
.no_share = false,
};
@@ -125,30 +102,74 @@
llcache_handle *llcache, const char *fallback_charset,
bool quirks, struct content **c)
{
- amiga_dt_picture_content *plugin;
+ struct content *adt;
nserror error;
- plugin = talloc_zero(0, amiga_dt_picture_content);
- if (plugin == NULL)
+ adt = talloc_zero(0, struct content);
+ if (adt == NULL)
return NSERROR_NOMEM;
- error = content__init(&plugin->base, handler, imime_type, params,
+ error = content__init(adt, handler, imime_type, params,
llcache, fallback_charset, quirks);
if (error != NSERROR_OK) {
- talloc_free(plugin);
+ talloc_free(adt);
return error;
}
- *c = (struct content *) plugin;
+ *c = adt;
return NSERROR_OK;
}
+static struct bitmap *amiga_dt_picture_cache_convert(struct content *c)
+{
+ LOG(("amiga_dt_picture_cache_convert"));
+
+ union content_msg_data msg_data;
+ const uint8 *data;
+ UBYTE *bm_buffer;
+ ULONG size;
+ Object *dto;
+ struct bitmap *bitmap;
+ unsigned int bm_flags = BITMAP_NEW;
+ int bm_format = PBPAFMT_RGBA;
+
+ /* This is only relevant for picture datatypes... */
+
+ data = (uint8 *)content__get_source_data(c, &size);
+
+ if(dto = NewDTObject(NULL,
+ DTA_SourceType, DTST_MEMORY,
+ DTA_SourceAddress, data,
+ DTA_SourceSize, size,
+ DTA_GroupID, GID_PICTURE,
+ PDTA_DestMode, PMODE_V43,
+ TAG_DONE))
+ {
+ bitmap = bitmap_create(c->width, c->height, bm_flags);
+ if (!bitmap) {
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return NULL;
+ }
+
+ bm_buffer = bitmap_get_buffer(bitmap);
+
+ IDoMethod(dto, PDTM_READPIXELARRAY,
+ bm_buffer, bm_format, bitmap_get_rowstride(bitmap),
+ 0, 0, c->width, c->height);
+
+ DisposeDTObject(dto);
+ }
+ else return NULL;
+
+ return bitmap;
+}
+
bool amiga_dt_picture_convert(struct content *c)
{
LOG(("amiga_dt_picture_convert"));
- amiga_dt_picture_content *plugin = (amiga_dt_picture_content *) c;
union content_msg_data msg_data;
int width, height;
char title[100];
@@ -164,7 +185,7 @@
data = (uint8 *)content__get_source_data(c, &size);
- if(plugin->dto = NewDTObject(NULL,
+ if(dto = NewDTObject(NULL,
DTA_SourceType, DTST_MEMORY,
DTA_SourceAddress, data,
DTA_SourceSize, size,
@@ -172,30 +193,22 @@
PDTA_DestMode, PMODE_V43,
TAG_DONE))
{
- if(GetDTAttrs(plugin->dto, PDTA_BitMapHeader, &bmh, TAG_DONE))
+ if(GetDTAttrs(dto, PDTA_BitMapHeader, &bmh, TAG_DONE))
{
width = (int)bmh->bmh_Width;
height = (int)bmh->bmh_Height;
-
- plugin->bitmap = bitmap_create(width, height, bm_flags);
- if (!plugin->bitmap) {
- msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
- }
-
- bm_buffer = bitmap_get_buffer(plugin->bitmap);
-
- IDoMethod(plugin->dto, PDTM_READPIXELARRAY,
- bm_buffer, bm_format, bitmap_get_rowstride(plugin->bitmap),
- 0, 0, width, height);
}
else return false;
+
+ DisposeDTObject(dto);
}
else return false;
c->width = width;
c->height = height;
+ c->size = width * height * 4;
+
+ image_cache_add(c, NULL, amiga_dt_picture_cache_convert);
/*
snprintf(title, sizeof(title), "image (%lux%lu, %lu bytes)",
@@ -203,8 +216,6 @@
content__set_title(c, title);
*/
- bitmap_modified(plugin->bitmap);
-
content_set_ready(c);
content_set_done(c);
@@ -212,74 +223,35 @@
return true;
}
-void amiga_dt_picture_destroy(struct content *c)
-{
- amiga_dt_picture_content *plugin = (amiga_dt_picture_content *) c;
-
- LOG(("amiga_dt_picture_destroy"));
-
- if (plugin->bitmap != NULL) {
- bitmap_destroy(plugin->bitmap);
- }
-
- DisposeDTObject(plugin->dto);
-
- return;
-}
-
-bool amiga_dt_picture_redraw(struct content *c,
- struct content_redraw_data *data,
- const struct rect *clip,
- const struct redraw_context *ctx)
-{
- amiga_dt_picture_content *plugin = (amiga_dt_picture_content *) c;
- bitmap_flags_t flags = BITMAPF_NONE;
-
- LOG(("amiga_dt_picture_redraw"));
-
- if (data->repeat_x)
- flags |= BITMAPF_REPEAT_X;
- if (data->repeat_y)
- flags |= BITMAPF_REPEAT_Y;
-
- return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
- plugin->bitmap, data->background_colour, flags);
-}
-
nserror amiga_dt_picture_clone(const struct content *old, struct content **newc)
{
- amiga_dt_picture_content *plugin;
+ struct content *adt;
nserror error;
LOG(("amiga_dt_picture_clone"));
- plugin = talloc_zero(0, amiga_dt_picture_content);
- if (plugin == NULL)
+ adt = talloc_zero(0, struct content);
+ if (adt == NULL)
return NSERROR_NOMEM;
- error = content__clone(old, &plugin->base);
+ error = content__clone(old, adt);
if (error != NSERROR_OK) {
- content_destroy(&plugin->base);
+ content_destroy(adt);
return error;
}
/* We "clone" the old content by replaying conversion */
if ((old->status == CONTENT_STATUS_READY) ||
(old->status == CONTENT_STATUS_DONE)) {
- if (amiga_dt_picture_convert(&plugin->base) == false) {
- content_destroy(&plugin->base);
+ if (amiga_dt_picture_convert(adt) == false) {
+ content_destroy(adt);
return NSERROR_CLONE_FAILED;
}
}
- *newc = (struct content *) plugin;
+ *newc = adt;
return NSERROR_OK;
}
-content_type amiga_dt_picture_content_type(void)
-{
- return CONTENT_IMAGE;
-}
-
#endif
11 years, 2 months
r13796 mmu_man - /branches/mmu_man/netsurf-gopher-support-v3/desktop/options_main.h
by netsurf@semichrome.net
Author: mmu_man
Date: Fri Apr 6 10:58:56 2012
New Revision: 13796
URL: http://source.netsurf-browser.org?rev=13796&view=rev
Log:
Apply and merge r12394 from v2 branch: Add an option to inline images in gopher directories.
Modified:
branches/mmu_man/netsurf-gopher-support-v3/desktop/options_main.h
Modified: branches/mmu_man/netsurf-gopher-support-v3/desktop/options_main.h
URL: http://source.netsurf-browser.org/branches/mmu_man/netsurf-gopher-support...
==============================================================================
--- branches/mmu_man/netsurf-gopher-support-v3/desktop/options_main.h (original)
+++ branches/mmu_man/netsurf-gopher-support-v3/desktop/options_main.h Fri Apr 6 10:58:56 2012
@@ -46,6 +46,8 @@
char *http_proxy_auth_user; \
/** Proxy authentication password */ \
char *http_proxy_auth_pass; \
+ /** Inline images in gopher pages. */ \
+ bool gopher_inline_images; \
/** Default font size / 0.1pt. */ \
int font_size; \
/** Minimum font size. */ \
@@ -205,6 +207,7 @@
.http_proxy_auth = OPTION_HTTP_PROXY_AUTH_NONE, \
.http_proxy_auth_user = NULL, \
.http_proxy_auth_pass = NULL, \
+ .gopher_inline_images = false, \
.font_size = 128, \
.font_min_size = 85, \
.font_sans = NULL, \
@@ -298,6 +301,7 @@
{ "http_proxy_auth", OPTION_INTEGER, &nsoptions.http_proxy_auth }, \
{ "http_proxy_auth_user", OPTION_STRING, &nsoptions.http_proxy_auth_user }, \
{ "http_proxy_auth_pass", OPTION_STRING, &nsoptions.http_proxy_auth_pass }, \
+ { "gopher_inline_images", OPTION_BOOL, &nsoptions.gopher_inline_images }, \
{ "font_size", OPTION_INTEGER, &nsoptions.font_size }, \
{ "font_min_size", OPTION_INTEGER, &nsoptions.font_min_size }, \
{ "font_sans", OPTION_STRING, &nsoptions.font_sans }, \
11 years, 2 months
r13795 mmu_man - in /branches/mmu_man/netsurf-gopher-support-v3/utils: url.c url.h
by netsurf@semichrome.net
Author: mmu_man
Date: Fri Apr 6 10:50:13 2012
New Revision: 13795
URL: http://source.netsurf-browser.org?rev=13795&view=rev
Log:
Apply and merge r12393 from v2 branch: Add url_gopher_type() which extracts the gopher item type from the url.
Modified:
branches/mmu_man/netsurf-gopher-support-v3/utils/url.c
branches/mmu_man/netsurf-gopher-support-v3/utils/url.h
Modified: branches/mmu_man/netsurf-gopher-support-v3/utils/url.c
URL: http://source.netsurf-browser.org/branches/mmu_man/netsurf-gopher-support...
==============================================================================
--- branches/mmu_man/netsurf-gopher-support-v3/utils/url.c (original)
+++ branches/mmu_man/netsurf-gopher-support-v3/utils/url.c Fri Apr 6 10:50:13 2012
@@ -671,6 +671,38 @@
}
/**
+ * Extract the gopher document type from an URL
+ *
+ * \param url an absolute URL
+ * \param result pointer to buffer to hold result
+ * \return URL_FUNC_OK on success
+ */
+
+url_func_result url_gopher_type(const char *url, char *result)
+{
+ url_func_result status;
+ struct url_components components;
+
+ assert(url);
+
+ status = url_get_components(url, &components);
+ if (status == URL_FUNC_OK) {
+ if (!components.path) {
+ status = URL_FUNC_FAILED;
+ } else {
+ if (strlen(components.path) < 2)
+ *result = '1';
+ else if (components.path[0] == '/')
+ *result = components.path[1];
+ else
+ status = URL_FUNC_FAILED;
+ }
+ }
+ url_destroy_components(&components);
+ return status;
+}
+
+/**
* Attempt to find a nice filename for a URL.
*
* \param url an absolute URL
Modified: branches/mmu_man/netsurf-gopher-support-v3/utils/url.h
URL: http://source.netsurf-browser.org/branches/mmu_man/netsurf-gopher-support...
==============================================================================
--- branches/mmu_man/netsurf-gopher-support-v3/utils/url.h (original)
+++ branches/mmu_man/netsurf-gopher-support-v3/utils/url.h Fri Apr 6 10:50:13 2012
@@ -59,6 +59,7 @@
url_func_result url_path(const char *url, char **result);
url_func_result url_leafname(const char *url, char **result);
url_func_result url_fragment(const char *url, char **result);
+url_func_result url_gopher_type(const char *url, char *result);
url_func_result url_compare(const char *url1, const char *url2,
bool nofrag, bool *result);
11 years, 2 months
r13794 mmu_man - /branches/mmu_man/netsurf-gopher-support-v3/Docs/BUILDING-Cocoa
by netsurf@semichrome.net
Author: mmu_man
Date: Fri Apr 6 10:28:15 2012
New Revision: 13794
URL: http://source.netsurf-browser.org?rev=13794&view=rev
Log:
Apply and merge r12392 from v2 branch: Document the MacPorts cURL requirement for gopher.
Not sure it still holds as I do not use a Mac anymore.
Modified:
branches/mmu_man/netsurf-gopher-support-v3/Docs/BUILDING-Cocoa
Modified: branches/mmu_man/netsurf-gopher-support-v3/Docs/BUILDING-Cocoa
URL: http://source.netsurf-browser.org/branches/mmu_man/netsurf-gopher-support...
==============================================================================
--- branches/mmu_man/netsurf-gopher-support-v3/Docs/BUILDING-Cocoa (original)
+++ branches/mmu_man/netsurf-gopher-support-v3/Docs/BUILDING-Cocoa Fri Apr 6 10:28:15 2012
@@ -19,6 +19,16 @@
$ make TARGET=cocoa
In both cases the actual build process is controlled by the Makefile.
+
+ Gopher support requires a recent libcurl from MacPorts since the one Apple
+ ships lacks the gopher handler. Building with MacPorts breaks the self-
+ contained nature of the .app bundle though. Install libcurl with MacPorts:
+
+ $ sudo port install curl
+
+ Then build with:
+
+ $ make TARGET=cocoa WITH_MACPORTS=1
Obtaining NetSurf's build dependencies
========================================
11 years, 2 months
r13793 mmu_man - /branches/mmu_man/netsurf-gopher-support-v3/!NetSurf/Resources/internal.css, f79
by netsurf@semichrome.net
Author: mmu_man
Date: Fri Apr 6 10:23:14 2012
New Revision: 13793
URL: http://source.netsurf-browser.org?rev=13793&view=rev
Log:
Apply and merge r12391 from v2 branch: Some CSS for the html elements generated from gopher directories.
Modified:
branches/mmu_man/netsurf-gopher-support-v3/!NetSurf/Resources/internal.css,f79
Modified: branches/mmu_man/netsurf-gopher-support-v3/!NetSurf/Resources/internal.css,f79
URL: http://source.netsurf-browser.org/branches/mmu_man/netsurf-gopher-support...
==============================================================================
--- branches/mmu_man/netsurf-gopher-support-v3/!NetSurf/Resources/internal.css,f79 (original)
+++ branches/mmu_man/netsurf-gopher-support-v3/!NetSurf/Resources/internal.css,f79 Fri Apr 6 10:23:14 2012
@@ -191,3 +191,40 @@
border: 1px solid #000;
}
+
+/*
+ * gopher listing style
+ */
+
+body#gopher {
+ /* margin: 10px;*/
+ font-size: 100%;
+ padding-bottom: 2em; }
+
+body#gopher h1 {
+ padding: 5mm;
+ margin: 0;
+ border-bottom: 2px solid #777; }
+
+/* XXX: white-space: pre-wrap would be better but is currently buggy */
+body#gopher span {
+ margin-left: 1em;
+ padding-left: 2em;
+ font-family: Courier, monospace;
+ white-space: pre; }
+
+body#gopher span.dir {
+ background-image: url('resource:Icons/directory.png');
+ background-repeat: no-repeat;
+ background-position: bottom left; }
+
+body#gopher span.text {
+ background-image: url('resource:Icons/content.png');
+ background-repeat: no-repeat;
+ background-position: bottom left; }
+
+body#gopher span.query {
+ background-image: url('resource:Icons/search.png');
+ background-repeat: no-repeat;
+ background-position: bottom left; }
+
11 years, 2 months
r13792 mmu_man - in /branches/mmu_man/netsurf-gopher-support-v3: amiga/dist/Install beos/res.rdef cocoa/res/NetSurf-Info.plist
by netsurf@semichrome.net
Author: mmu_man
Date: Fri Apr 6 10:12:16 2012
New Revision: 13792
URL: http://source.netsurf-browser.org?rev=13792&view=rev
Log:
Apply and merge r12390 from v2 branch: Make gopher: URIs known to AmigaOS, BeOS and OSX.
Modified:
branches/mmu_man/netsurf-gopher-support-v3/amiga/dist/Install
branches/mmu_man/netsurf-gopher-support-v3/beos/res.rdef
branches/mmu_man/netsurf-gopher-support-v3/cocoa/res/NetSurf-Info.plist
Modified: branches/mmu_man/netsurf-gopher-support-v3/amiga/dist/Install
URL: http://source.netsurf-browser.org/branches/mmu_man/netsurf-gopher-support...
==============================================================================
--- branches/mmu_man/netsurf-gopher-support-v3/amiga/dist/Install (original)
+++ branches/mmu_man/netsurf-gopher-support-v3/amiga/dist/Install Fri Apr 6 10:12:16 2012
@@ -581,6 +581,10 @@
(p_fitr "ENVARC:launch-handler/URL/FILE.LH" "ClientName=\"NETSURF\" ClientPath=\"APPDIR:NETSURF\" CMDFORMAT=\"URL=*\"file:///%s*\"\"")
)
+ (if (= (p_chk_launch-handler "GOPHER.LH") 0)
+ (p_fitr "ENVARC:launch-handler/URL/GOPHER.LH" "ClientName=\"NETSURF\" ClientPath=\"APPDIR:NETSURF\" CMDFORMAT=\"URL=*\"gopher://%s*\"\"")
+ )
+
(if (= (p_chk_launch-handler "HTTP.LH") 0)
(p_fitr "ENVARC:launch-handler/URL/HTTP.LH" "ClientName=\"NETSURF\" ClientPath=\"APPDIR:NETSURF\" CMDFORMAT=\"URL=*\"http://%s*\"\"")
)
Modified: branches/mmu_man/netsurf-gopher-support-v3/beos/res.rdef
URL: http://source.netsurf-browser.org/branches/mmu_man/netsurf-gopher-support...
==============================================================================
--- branches/mmu_man/netsurf-gopher-support-v3/beos/res.rdef (original)
+++ branches/mmu_man/netsurf-gopher-support-v3/beos/res.rdef Fri Apr 6 10:12:16 2012
@@ -101,6 +101,7 @@
"types" = "application/x-vnd.Be-doc_bookmark",
"types" = "application/x-vnd.Be.URL.file",
"types" = "application/x-vnd.Be.URL.ftp",
+ "types" = "application/x-vnd.Be.URL.gopher",
"types" = "application/x-vnd.Be.URL.http",
"types" = "application/x-vnd.Be.URL.https"
};
Modified: branches/mmu_man/netsurf-gopher-support-v3/cocoa/res/NetSurf-Info.plist
URL: http://source.netsurf-browser.org/branches/mmu_man/netsurf-gopher-support...
==============================================================================
--- branches/mmu_man/netsurf-gopher-support-v3/cocoa/res/NetSurf-Info.plist (original)
+++ branches/mmu_man/netsurf-gopher-support-v3/cocoa/res/NetSurf-Info.plist Fri Apr 6 10:12:16 2012
@@ -44,6 +44,7 @@
<string>org.netsurf-browser.NetSurf.URI</string>
<key>CFBundleURLSchemes</key>
<array>
+ <string>gopher</string>
<string>http</string>
<string>https</string>
</array>
11 years, 2 months
r13790 mono - /trunk/netsurf/atari/gui.c
by netsurf@semichrome.net
Author: mono
Date: Wed Apr 4 16:58:09 2012
New Revision: 13790
URL: http://source.netsurf-browser.org?rev=13790&view=rev
Log:
Removed unused variable.
Modified:
trunk/netsurf/atari/gui.c
Modified: trunk/netsurf/atari/gui.c
URL: http://source.netsurf-browser.org/trunk/netsurf/atari/gui.c?rev=13790&r1=...
==============================================================================
--- trunk/netsurf/atari/gui.c (original)
+++ trunk/netsurf/atari/gui.c Wed Apr 4 16:58:09 2012
@@ -106,7 +106,6 @@
// int timeout; /* timeout in milliseconds */
int flags = MU_MESAG | MU_KEYBD | MU_BUTTON ;
short mx, my, dummy;
- short aestop;
evnt.timer = schedule_run();
@@ -119,7 +118,7 @@
}
} else {
if( input_window != NULL ){
- wind_get( 0, WF_TOP, &aestop, &winloc[1], &winloc[2], &winloc[3]);
+ wind_get( 0, WF_TOP, &winloc[0], &winloc[1], &winloc[2], &winloc[3]);
if( winloc[1] == _AESapid ){
/* only check for mouse move when netsurf is on top: */
// move that into m1 event handler
@@ -309,13 +308,12 @@
if (gw == NULL)
return;
b = gw->browser;
- /* the box values are actually floats */
int x0 = rect->x0 - b->scroll.current.x;
int y0 = rect->y0 - b->scroll.current.y;
int w,h;
w = rect->x1 - rect->x0;
h = rect->y1 - rect->y0;
- browser_schedule_redraw_rect( gw, x0, y0, w,h);
+ browser_schedule_redraw_rect( gw, x0, y0, w, h );
}
bool gui_window_get_scroll(struct gui_window *w, int *sx, int *sy)
11 years, 2 months