r2641 rjek - /trunk/netsurf/riscos/window.c
by netsurf@semichrome.net
Author: rjek
Date: Fri Jun 23 23:42:31 2006
New Revision: 2641
URL: http://svn.semichrome.net?rev=2641&view=rev
Log:
Add workaround to bug in Pinboard not displaying some windows when iconised
Modified:
trunk/netsurf/riscos/window.c
Modified: trunk/netsurf/riscos/window.c
URL: http://svn.semichrome.net/trunk/netsurf/riscos/window.c?rev=2641&r1=2640&...
==============================================================================
--- trunk/netsurf/riscos/window.c (original)
+++ trunk/netsurf/riscos/window.c Fri Jun 23 23:42:31 2006
@@ -3078,6 +3078,15 @@
strncpy(wi->title, g->title, sizeof(wi->title));
wi->title[sizeof(wi->title) - 1] = '\0';
+ if (wimptextop_string_width(wi->title, 0) > 128) {
+ /* work around bug in Pinboard where it will fail to display
+ * the icon if the text is very wide */
+ if (strlen(wi->title) > 10)
+ wi->title[10] = '\0'; /* pinboard does this anyway */
+ while (wimptextop_string_width(wi->title, 0) > 182)
+ wi->title[strlen(wi->title) - 1] = '\0';
+ }
+
wi->size = sizeof(wimp_full_message_window_info);
wi->your_ref = wi->my_ref;
error = xwimp_send_message(wimp_USER_MESSAGE, (wimp_message*)wi, wi->sender);
16 years, 7 months
r2640 bursa - in /trunk/netsurf/render: box.c box.h
by netsurf@semichrome.net
Author: bursa
Date: Wed Jun 21 03:51:00 2006
New Revision: 2640
URL: http://svn.semichrome.net?rev=2640&view=rev
Log:
Changes to struct box for absolute positioning.
Modified:
trunk/netsurf/render/box.c
trunk/netsurf/render/box.h
Modified: trunk/netsurf/render/box.c
URL: http://svn.semichrome.net/trunk/netsurf/render/box.c?rev=2640&r1=2639&r2=...
==============================================================================
--- trunk/netsurf/render/box.c (original)
+++ trunk/netsurf/render/box.c Wed Jun 21 03:51:00 2006
@@ -84,6 +84,7 @@
box->inline_end = NULL;
box->float_children = NULL;
box->next_float = NULL;
+ box->absolute_children = NULL;
box->col = NULL;
box->gadget = NULL;
box->usemap = NULL;
@@ -117,6 +118,30 @@
}
parent->last = child;
+ child->parent = parent;
+}
+
+
+/**
+ * Add an absolutely positioned child to a box tree node.
+ *
+ * \param parent box giving birth
+ * \param child box to link as last child of parent
+ */
+
+void box_add_absolute_child(struct box *parent, struct box *child)
+{
+ assert(parent);
+ assert(child);
+
+ if (parent->absolute_children != 0) { /* has children already */
+ child->next = parent->absolute_children;
+ parent->absolute_children->prev = child;
+ } else { /* this is the first child */
+ child->next = 0;
+ }
+
+ parent->absolute_children = child;
child->parent = parent;
}
@@ -183,6 +208,11 @@
/* free children first */
for (child = box->children; child; child = next) {
+ next = child->next;
+ box_free(child);
+ }
+
+ for (child = box->absolute_children; child; child = next) {
next = child->next;
box_free(child);
}
@@ -557,4 +587,11 @@
for (c = box->fallback; c; c = c->next)
box_dump(c, depth + 1);
}
-}
+ if (box->absolute_children) {
+ for (i = 0; i != depth; i++)
+ fprintf(stderr, " ");
+ fprintf(stderr, "absolute_children:\n");
+ for (c = box->absolute_children; c; c = c->next)
+ box_dump(c, depth + 1);
+ }
+}
Modified: trunk/netsurf/render/box.h
URL: http://svn.semichrome.net/trunk/netsurf/render/box.h?rev=2640&r1=2639&r2=...
==============================================================================
--- trunk/netsurf/render/box.h (original)
+++ trunk/netsurf/render/box.h Wed Jun 21 03:51:00 2006
@@ -193,6 +193,10 @@
/** Next sibling float box. */
struct box *next_float;
+ /** First absolutely positioned child box, or 0. Absolutely positioned
+ * boxes are linked by next / prev and do not appear under children. */
+ struct box *absolute_children;
+
struct column *col; /**< Array of table column data for TABLE only. */
/** Form control data, or 0 if not a form control. */
@@ -259,6 +263,7 @@
char *href, const char *target, char *title,
char *id, void *context);
void box_add_child(struct box *parent, struct box *child);
+void box_add_absolute_child(struct box *parent, struct box *child);
void box_insert_sibling(struct box *box, struct box *new_box);
void box_unlink_and_free(struct box *box);
void box_free(struct box *box);
16 years, 7 months
r2639 jmb - in /trunk/netsurf: riscos/bitmap.c riscos/gui.c utils/filename.c utils/filename.h
by netsurf@semichrome.net
Author: jmb
Date: Tue Jun 20 23:58:36 2006
New Revision: 2639
URL: http://svn.semichrome.net?rev=2639&view=rev
Log:
Make filename_create_directory check if directory already exists
Constify return of filename_request
Make bitmap save code check for filename_request failure
Update ro_gui_view_source to take account of constification
Modified:
trunk/netsurf/riscos/bitmap.c
trunk/netsurf/riscos/gui.c
trunk/netsurf/utils/filename.c
trunk/netsurf/utils/filename.h
Modified: trunk/netsurf/riscos/bitmap.c
URL: http://svn.semichrome.net/trunk/netsurf/riscos/bitmap.c?rev=2639&r1=2638&...
==============================================================================
--- trunk/netsurf/riscos/bitmap.c (original)
+++ trunk/netsurf/riscos/bitmap.c Tue Jun 20 23:58:36 2006
@@ -252,7 +252,7 @@
assert(sprite_bpp(s) == 8);
if ((unsigned)s->mode & 0x80000000U)
- alpha = true;
+ alpha = true;
error = xosspriteop_read_sprite_info(osspriteop_PTR,
(osspriteop_area *)0x100,
@@ -376,7 +376,7 @@
void bitmap_set_opaque(struct bitmap *bitmap, bool opaque)
{
assert(bitmap);
-
+
if (opaque)
bitmap->state |= BITMAP_OPAQUE;
else
@@ -459,7 +459,7 @@
bitmap->previous = NULL;
bitmap_head = bitmap;
}
-
+
/* dynamically create the buffer */
if (!(bitmap->state & BITMAP_READY)) {
if (!bitmap_initialise(bitmap))
@@ -592,8 +592,8 @@
void (*invalidate)(struct bitmap *bitmap, void *private_word)) {
bitmap->private_word = private_word;
bitmap->invalidate = invalidate;
- bitmap_suspendable++;
-}
+ bitmap_suspendable++;
+}
/**
@@ -644,7 +644,7 @@
bitmap_maintenance_priority = false;
return;
}
-
+
/* the fastest and easiest way to release memory is by suspending
* images. as such, we try to do this first for as many images as
* possible, potentially freeing up large amounts of memory */
@@ -659,7 +659,7 @@
bitmap_direct_used -= 16 + 44 +
bitmap->width * bitmap->height * 4;
bitmap_suspended++;
- }
+ }
}
return;
}
@@ -892,7 +892,7 @@
os_error *error;
struct bitmap_compressed_header *header;
- assert(bitmap->compressed || bitmap->sprite_area);
+ assert(bitmap && (bitmap->compressed || bitmap->sprite_area));
/* unmodified bitmaps will still have their file available */
if ((!(bitmap->state & BITMAP_MODIFIED)) && bitmap->filename[0]) {
@@ -907,6 +907,11 @@
/* dump the data (compressed or otherwise) to disk */
filename = filename_request();
+ if (!filename) {
+ LOG(("filename_request failed"));
+ return;
+ }
+
strcpy(bitmap->filename, filename);
sprintf(bitmap_unixname, "%s/%s", TEMP_FILENAME_PREFIX,
bitmap->filename);
Modified: trunk/netsurf/riscos/gui.c
URL: http://svn.semichrome.net/trunk/netsurf/riscos/gui.c?rev=2639&r1=2638&r2=...
==============================================================================
--- trunk/netsurf/riscos/gui.c (original)
+++ trunk/netsurf/riscos/gui.c Tue Jun 20 23:58:36 2006
@@ -2164,20 +2164,22 @@
message.file_name[211] = '\0';
free(temp_name);
} else {
- /* We cannot release the requested filename until after it has finished
- being used. As we can't easily find out when this is, we simply don't
- bother releasing it and simply allow it to be re-used next time NetSurf
- is started. The memory overhead from doing this is under 1 byte per
- filename. */
- temp_name = filename_request();
- if (!temp_name) {
+ /* We cannot release the requested filename until after it
+ * has finished being used. As we can't easily find out when
+ * this is, we simply don't bother releasing it and simply
+ * allow it to be re-used next time NetSurf is started. The
+ * memory overhead from doing this is under 1 byte per
+ * filename. */
+ const char *filename = filename_request();
+ if (!filename) {
warn_user("NoMemory", 0);
return;
}
- snprintf(full_name, 256, "%s/%s", TEMP_FILENAME_PREFIX, temp_name);
+ snprintf(full_name, 256, "%s/%s", TEMP_FILENAME_PREFIX,
+ filename);
full_name[255] = '\0';
- r = __riscosify(full_name, 0, __RISCOSIFY_NO_SUFFIX, message.file_name,
- 212, 0);
+ r = __riscosify(full_name, 0, __RISCOSIFY_NO_SUFFIX,
+ message.file_name, 212, 0);
if (r == 0) {
LOG(("__riscosify failed"));
return;
@@ -2205,7 +2207,8 @@
message.pos.y = 0;
message.est_size = 0;
message.file_type = 0xfff;
- ro_message_send_message(wimp_USER_MESSAGE_RECORDED, (wimp_message*)&message, 0,
+ ro_message_send_message(wimp_USER_MESSAGE_RECORDED,
+ (wimp_message*)&message, 0,
ro_gui_view_source_bounce);
}
Modified: trunk/netsurf/utils/filename.c
URL: http://svn.semichrome.net/trunk/netsurf/utils/filename.c?rev=2639&r1=2638...
==============================================================================
--- trunk/netsurf/utils/filename.c (original)
+++ trunk/netsurf/utils/filename.c Tue Jun 20 23:58:36 2006
@@ -19,6 +19,7 @@
#include <sys/stat.h>
#include "netsurf/utils/filename.h"
#include "netsurf/utils/log.h"
+#include "netsurf/utils/utils.h"
#define FULL_WORD (unsigned int)4294967295
/* '0' + '0' * 10 */
@@ -44,9 +45,9 @@
/**
* Request a new, unique, filename.
*
- * \return a pointer to a shared buffer containing the new filename
- */
-char *filename_request(void) {
+ * \return a pointer to a shared buffer containing the new filename or NULL on failure
+ */
+const char *filename_request(void) {
struct directory *dir;
int i = -1;
@@ -321,7 +322,8 @@
* Creates a new directory.
*
* \param prefix the prefix to use, or NULL to allocate a new one
- * \return a new directory structure, or NULL on memory exhaustion
+ * \return a new directory structure, or NULL on memory exhaustion or
+ * creation failure
*
* Empty directories are never deleted, except by an explicit call to
* filename_flush().
@@ -384,14 +386,17 @@
TEMP_FILENAME_PREFIX,
new_dir->prefix);
new_dir->prefix[8] = '/';
- if (!mkdir(filename_directory, S_IRWXU))
- return new_dir;
-
- /* the user has probably deleted the parent directory whilst
- * we are running if there is an error, so we don't report
- * this yet and try to create the structure normally. */
- LOG(("Failed to create optimised structure '%s'",
- filename_directory));
+ if (!is_dir(filename_directory)) {
+ if (!mkdir(filename_directory, S_IRWXU))
+ return new_dir;
+
+ /* the user has probably deleted the parent directory
+ * whilst we are running if there is an error, so we
+ * don't report this yet and try to create the
+ * structure normally. */
+ LOG(("Failed to create optimised structure '%s'",
+ filename_directory));
+ }
}
/* create the directory structure */
@@ -405,12 +410,15 @@
*last_1++ = *last_2++;
if (*last_2) {
last_1[0] = '\0';
- if (mkdir(filename_directory, S_IRWXU)) {
- LOG(("Failed to create directory '%s'",
- filename_directory));
- return NULL;
+ if (!is_dir(filename_directory)) {
+ if (mkdir(filename_directory, S_IRWXU)) {
+ LOG(("Failed to create directory '%s'",
+ filename_directory));
+ return NULL;
+ }
}
}
}
+
return new_dir;
}
Modified: trunk/netsurf/utils/filename.h
URL: http://svn.semichrome.net/trunk/netsurf/utils/filename.h?rev=2639&r1=2638...
==============================================================================
--- trunk/netsurf/utils/filename.h (original)
+++ trunk/netsurf/utils/filename.h Tue Jun 20 23:58:36 2006
@@ -16,7 +16,7 @@
#define TEMP_FILENAME_PREFIX "/tmp/WWW/NetSurf/Cache"
#endif
-char *filename_request(void);
+const char *filename_request(void);
bool filename_claim(const char *filename);
void filename_release(const char *filename);
bool filename_initialise(void);
16 years, 7 months
r2638 jmb - in /trunk/netsurf: !NetSurf/Resources/de/Messages riscos/configure.c riscos/configure/con_fonts.c riscos/configure/con_language.c riscos/wimp.c riscos/wimp.h riscos/wimp_event.c
by netsurf@semichrome.net
Author: jmb
Date: Tue Jun 20 22:35:33 2006
New Revision: 2638
URL: http://svn.semichrome.net?rev=2638&view=rev
Log:
Localise configure icon strings when appropriate.
Fix gright menu handling - now writes into display field without
attempting to localise the selection string - it's already localised.
Update German Messages file appropriately.
Modified:
trunk/netsurf/!NetSurf/Resources/de/Messages
trunk/netsurf/riscos/configure.c
trunk/netsurf/riscos/configure/con_fonts.c
trunk/netsurf/riscos/configure/con_language.c
trunk/netsurf/riscos/wimp.c
trunk/netsurf/riscos/wimp.h
trunk/netsurf/riscos/wimp_event.c
Modified: trunk/netsurf/!NetSurf/Resources/de/Messages
URL: http://svn.semichrome.net/trunk/netsurf/%21NetSurf/Resources/de/Messages?...
==============================================================================
--- trunk/netsurf/!NetSurf/Resources/de/Messages (original)
+++ trunk/netsurf/!NetSurf/Resources/de/Messages Tue Jun 20 22:35:33 2006
@@ -871,7 +871,7 @@
con_fonts:Schriftarten
con_home:Homepage
con_image:Bilder
-con_inter:Nützliches
+con_inter:Nützliches
con_lang:Sprachen
con_memory:Speicher
con_secure:Sicherheit
Modified: trunk/netsurf/riscos/configure.c
URL: http://svn.semichrome.net/trunk/netsurf/riscos/configure.c?rev=2638&r1=26...
==============================================================================
--- trunk/netsurf/riscos/configure.c (original)
+++ trunk/netsurf/riscos/configure.c Tue Jun 20 22:35:33 2006
@@ -1,321 +1,404 @@
-/*
- * This file is part of NetSurf, http://netsurf.sourceforge.net/
- * Licensed under the GNU General Public License,
- * http://www.opensource.org/licenses/gpl-license
- * Copyright 2005 Richard Wilson <info(a)tinct.net>
- */
-
-/** \file
- * RISC OS option setting (implemenation).
- */
-
-#include <assert.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include "oslib/os.h"
-#include "oslib/wimp.h"
-#include "netsurf/riscos/dialog.h"
-#include "netsurf/riscos/configure.h"
-#include "netsurf/riscos/wimp_event.h"
-#include "netsurf/riscos/configure/configure.h"
-#include "netsurf/utils/log.h"
-#include "netsurf/utils/utils.h"
-#include "netsurf/utils/messages.h"
-
-#define CONFIGURE_ICON_PADDING_H 32
-#define CONFIGURE_ICON_PADDING_V 32
-
-struct configure_tool {
- const char *name;
- const char *translated;
- char *validation;
- bool (*initialise)(wimp_w w);
- void (*finalise)(wimp_w w);
- wimp_w w;
- wimp_i i;
- bool open;
- struct configure_tool *next;
-};
-
-static wimp_w configure_window;
-static int configure_icons = 0;
-static struct configure_tool *configure_tools = NULL;
-static int configure_icon_width = 68 + CONFIGURE_ICON_PADDING_H;
-static int configure_icon_height = 128 + CONFIGURE_ICON_PADDING_V;
-static int configure_icons_per_line = 0;
-static int configure_width;
-static int configure_height;
-
-static bool ro_gui_configure_click(wimp_pointer *pointer);
-static void ro_gui_configure_open_window(wimp_open *open);
-static void ro_gui_configure_close(wimp_w w);
-
-void ro_gui_configure_initialise(void) {
- /* create our window */
- configure_window = ro_gui_dialog_create("configure");
- ro_gui_wimp_event_register_open_window(configure_window,
- ro_gui_configure_open_window);
- ro_gui_wimp_event_register_mouse_click(configure_window,
- ro_gui_configure_click);
- ro_gui_wimp_event_set_help_prefix(configure_window, "HelpConfigure");
-
- /* add in our option windows */
- ro_gui_configure_register("con_cache",
- ro_gui_options_cache_initialise,
- ro_gui_wimp_event_finalise);
- ro_gui_configure_register("con_connect",
- ro_gui_options_connection_initialise,
- ro_gui_wimp_event_finalise);
- ro_gui_configure_register("con_content",
- ro_gui_options_content_initialise,
- ro_gui_wimp_event_finalise);
- ro_gui_configure_register("con_fonts",
- ro_gui_options_fonts_initialise,
- ro_gui_wimp_event_finalise);
- ro_gui_configure_register("con_home",
- ro_gui_options_home_initialise,
- ro_gui_wimp_event_finalise);
- ro_gui_configure_register("con_image",
- ro_gui_options_image_initialise,
- ro_gui_options_image_finalise);
- ro_gui_configure_register("con_inter",
- ro_gui_options_interface_initialise,
- ro_gui_wimp_event_finalise);
- ro_gui_configure_register("con_lang",
- ro_gui_options_language_initialise,
- ro_gui_wimp_event_finalise);
- ro_gui_configure_register("con_memory",
- ro_gui_options_memory_initialise,
- ro_gui_wimp_event_finalise);
- ro_gui_configure_register("con_theme",
- ro_gui_options_theme_initialise,
- ro_gui_options_theme_finalise);
- ro_gui_configure_register("con_secure",
- ro_gui_options_security_initialise,
- ro_gui_wimp_event_finalise);
-}
-
-void ro_gui_configure_show(void) {
- int width, height;
-
- width = configure_icon_width << 2;
- height = ((configure_icons + 3) >> 2) * configure_icon_height;
- ro_gui_dialog_open_top(configure_window, NULL, width, height);
-}
-
-bool ro_gui_configure_click(wimp_pointer *pointer) {
- struct configure_tool *tool;
-
- if (pointer->buttons == wimp_CLICK_MENU)
- return true;
-
- for (tool = configure_tools; tool; tool = tool->next) {
- if (tool->i == pointer->i) {
- if (!tool->open) {
- tool->open = true;
- if (!tool->initialise(tool->w))
- return false;
- ro_gui_dialog_open_persistent(
- configure_window,
- tool->w, true);
- ro_gui_wimp_event_register_close_window(
- tool->w,
- ro_gui_configure_close);
-
- } else {
- ro_gui_dialog_open_top(tool->w, NULL, 0, 0);
- }
- break;
- }
- }
- return true;
-}
-
-void ro_gui_configure_close(wimp_w w) {
- struct configure_tool *tool;
-
- for (tool = configure_tools; tool; tool = tool->next) {
- if (tool->w == w) {
- tool->open = false;
- if (tool->finalise)
- tool->finalise(w);
- break;
- }
- }
-}
-
-void ro_gui_configure_open_window(wimp_open *open) {
- os_error *error;
- int screen_width, screen_height;
- int height, width;
- int icons_per_line, icon_lines;
- int max_icons_per_line, max_height;
- os_box extent = { 0, 0, 0, 0 };
- int x, y, l;
- struct configure_tool *tool;
-
- width = open->visible.x1 - open->visible.x0;
- height = open->visible.y1 - open->visible.y0;
- icons_per_line = width / configure_icon_width;
- if (icons_per_line < 1)
- icons_per_line = 1;
-
- /* move our icons */
- if (icons_per_line != configure_icons_per_line) {
- configure_icons_per_line = icons_per_line;
- x = CONFIGURE_ICON_PADDING_H / 2;
- y = -configure_icon_height + (CONFIGURE_ICON_PADDING_V / 2);
- l = 0;
- for (tool = configure_tools; tool; tool = tool->next) {
- error = xwimp_resize_icon(configure_window,
- tool->i,
- x,
- y,
- x + configure_icon_width -
- CONFIGURE_ICON_PADDING_H,
- y + configure_icon_height -
- CONFIGURE_ICON_PADDING_V);
- if (error) {
- LOG(("xwimp_resize_icon: 0x%x: %s",
- error->errnum, error->errmess));
- }
- x += configure_icon_width;
- l++;
- if (l >= icons_per_line) {
- x = CONFIGURE_ICON_PADDING_H / 2;
- l = 0;
- y -= configure_icon_height;
- }
- }
- error = xwimp_force_redraw(configure_window,
- 0, -16384, 16384, 0);
- if (error) {
- LOG(("xwimp_force_redraw: 0x%x: %s",
- error->errnum, error->errmess));
- warn_user("WimpError", error->errmess);
- }
- }
-
- /* restrict our height */
- icon_lines = (configure_icons + icons_per_line - 1) /
- icons_per_line;
- max_height = (icon_lines * configure_icon_height);
- if (height > max_height)
- open->visible.y0 = open->visible.y1 - max_height;
-
- /* set the extent */
- if ((configure_height != height) || (configure_width != width)) {
- ro_gui_screen_size(&screen_width, &screen_height);
- max_icons_per_line = screen_width / configure_icon_width;
- if (max_icons_per_line > configure_icons)
- max_icons_per_line = configure_icons;
- extent.x1 = configure_icon_width * max_icons_per_line;
- extent.y0 = -max_height;
- error = xwimp_set_extent(open->w, &extent);
- if (error) {
- LOG(("xwimp_set_extent: 0x%x: %s",
- error->errnum, error->errmess));
- warn_user("WimpError", error->errmess);
- return;
- }
- configure_height = height;
- configure_width = width;
- }
-
- /* open the window */
- error = xwimp_open_window(open);
- if (error) {
- LOG(("xwimp_open_window: 0x%x: %s",
- error->errnum, error->errmess));
- warn_user("WimpError", error->errmess);
- return;
- }
-}
-
-void ro_gui_configure_register(const char *window,
- bool (*initialise)(wimp_w w), void (*finalise)(wimp_w w)) {
- wimp_icon_create new_icon;
- struct configure_tool *tool;
- struct configure_tool *link;
- int icon_width;
- os_error *error;
-
- /* create our tool */
- tool = calloc(sizeof(struct configure_tool), 1);
- if (!tool) {
- LOG(("Insufficient memory for calloc()"));
- die("Insufficient memory");
- }
- tool->name = window;
- tool->translated = messages_get(window);
- tool->validation = malloc(strlen(window) + 2);
- if (!tool->validation) {
- LOG(("Insufficient memory for malloc()"));
- die("Insufficient memory");
- }
- sprintf(tool->validation, "S%s", window);
- tool->initialise = initialise;
- tool->finalise = finalise;
- tool->w = ro_gui_dialog_create(tool->name);
-
- /* update the width */
- error = xwimptextop_string_width(tool->translated,
- strlen(tool->translated), &icon_width);
- if (error) {
- LOG(("xwimptextop_string_width: 0x%x: %s",
- error->errnum, error->errmess));
- die(error->errmess);
- }
- icon_width += CONFIGURE_ICON_PADDING_H;
- if (icon_width > configure_icon_width)
- configure_icon_width = icon_width;
-
- /* create the icon */
- new_icon.w = configure_window;
- new_icon.icon.extent.x0 = 0;
- new_icon.icon.extent.x1 = configure_icon_width;
- new_icon.icon.extent.y1 = 0;
- new_icon.icon.extent.y0 = -configure_icon_height;
- new_icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE |
- wimp_ICON_INDIRECTED | wimp_ICON_HCENTRED |
- (wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT) |
- (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
- (wimp_BUTTON_CLICK << wimp_ICON_BUTTON_TYPE_SHIFT);
- new_icon.icon.data.indirected_text_and_sprite.text =
- tool->translated;
- new_icon.icon.data.indirected_text_and_sprite.validation =
- tool->validation;
- new_icon.icon.data.indirected_text_and_sprite.size =
- strlen(tool->translated);
- error = xwimp_create_icon(&new_icon, &tool->i);
- if (error) {
- LOG(("xwimp_create_icon: 0x%x: %s",
- error->errnum, error->errmess));
- die(error->errmess);
- }
-
- /* link into our list alphabetically */
- if ((!configure_tools) ||
- (strcmp(configure_tools->translated,
- tool->translated) > 0)) {
- tool->next = configure_tools;
- configure_tools = tool;
- } else {
- for (link = configure_tools; link; link = link->next) {
- if (link->next) {
- if (strcmp(link->next->translated,
- tool->translated) > 0) {
- tool->next = link->next;
- link->next = tool;
- break;
- }
- } else {
- link->next = tool;
- break;
- }
- }
- }
- configure_icons++;
-}
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2005 Richard Wilson <info(a)tinct.net>
+ */
+
+/** \file
+ * RISC OS option setting (implementation).
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "oslib/os.h"
+#include "oslib/osbyte.h"
+#include "oslib/territory.h"
+#include "oslib/wimp.h"
+#include "netsurf/riscos/dialog.h"
+#include "netsurf/riscos/configure.h"
+#include "netsurf/riscos/wimp.h"
+#include "netsurf/riscos/wimp_event.h"
+#include "netsurf/riscos/configure/configure.h"
+#include "netsurf/utils/log.h"
+#include "netsurf/utils/utils.h"
+#include "netsurf/utils/messages.h"
+
+#define CONFIGURE_ICON_PADDING_H 32
+#define CONFIGURE_ICON_PADDING_V 32
+#define CONFIGURE_DEFAULT_ICON_WIDTH (68 + CONFIGURE_ICON_PADDING_H)
+#define CONFIGURE_DEFAULT_ICON_HEIGHT (128 + CONFIGURE_ICON_PADDING_V)
+
+struct configure_tool {
+ const char *name;
+#define CONFIGURE_TOOL_TRANSLATED_SIZE 64
+ char translated[CONFIGURE_TOOL_TRANSLATED_SIZE];
+ char *validation;
+ bool (*initialise)(wimp_w w);
+ void (*finalise)(wimp_w w);
+ wimp_w w;
+ wimp_i i;
+ bool open;
+ struct configure_tool *next;
+};
+
+static wimp_w configure_window;
+static int configure_current_encoding;
+static int configure_icons = 0;
+static struct configure_tool *configure_tools = NULL;
+static int configure_icon_width = CONFIGURE_DEFAULT_ICON_WIDTH;
+static int configure_icon_height = CONFIGURE_DEFAULT_ICON_HEIGHT;
+static int configure_icons_per_line = 0;
+static int configure_width;
+static int configure_height;
+
+static bool ro_gui_configure_click(wimp_pointer *pointer);
+static void ro_gui_configure_open_window(wimp_open *open);
+static void ro_gui_configure_close(wimp_w w);
+static bool ro_gui_configure_translate(void);
+
+void ro_gui_configure_initialise(void)
+{
+ /* create our window */
+ configure_window = ro_gui_dialog_create("configure");
+ ro_gui_wimp_event_register_open_window(configure_window,
+ ro_gui_configure_open_window);
+ ro_gui_wimp_event_register_mouse_click(configure_window,
+ ro_gui_configure_click);
+ ro_gui_wimp_event_set_help_prefix(configure_window, "HelpConfigure");
+
+ /* add in our option windows */
+ ro_gui_configure_register("con_cache",
+ ro_gui_options_cache_initialise,
+ ro_gui_wimp_event_finalise);
+ ro_gui_configure_register("con_connect",
+ ro_gui_options_connection_initialise,
+ ro_gui_wimp_event_finalise);
+ ro_gui_configure_register("con_content",
+ ro_gui_options_content_initialise,
+ ro_gui_wimp_event_finalise);
+ ro_gui_configure_register("con_fonts",
+ ro_gui_options_fonts_initialise,
+ ro_gui_wimp_event_finalise);
+ ro_gui_configure_register("con_home",
+ ro_gui_options_home_initialise,
+ ro_gui_wimp_event_finalise);
+ ro_gui_configure_register("con_image",
+ ro_gui_options_image_initialise,
+ ro_gui_options_image_finalise);
+ ro_gui_configure_register("con_inter",
+ ro_gui_options_interface_initialise,
+ ro_gui_wimp_event_finalise);
+ ro_gui_configure_register("con_lang",
+ ro_gui_options_language_initialise,
+ ro_gui_wimp_event_finalise);
+ ro_gui_configure_register("con_memory",
+ ro_gui_options_memory_initialise,
+ ro_gui_wimp_event_finalise);
+ ro_gui_configure_register("con_theme",
+ ro_gui_options_theme_initialise,
+ ro_gui_options_theme_finalise);
+ ro_gui_configure_register("con_secure",
+ ro_gui_options_security_initialise,
+ ro_gui_wimp_event_finalise);
+
+ /* translate the icons */
+ if (!ro_gui_configure_translate())
+ die("ro_gui_configure_translate failed");
+}
+
+void ro_gui_configure_show(void)
+{
+ int width, height;
+
+ width = configure_icon_width << 2;
+ height = ((configure_icons + 3) >> 2) * configure_icon_height;
+ ro_gui_dialog_open_top(configure_window, NULL, width, height);
+}
+
+bool ro_gui_configure_click(wimp_pointer *pointer)
+{
+ struct configure_tool *tool;
+
+ if (pointer->buttons == wimp_CLICK_MENU)
+ return true;
+
+ for (tool = configure_tools; tool; tool = tool->next) {
+ if (tool->i == pointer->i) {
+ if (!tool->open) {
+ tool->open = true;
+ if (!tool->initialise(tool->w))
+ return false;
+ ro_gui_dialog_open_persistent(
+ configure_window,
+ tool->w, true);
+ ro_gui_wimp_event_register_close_window(
+ tool->w,
+ ro_gui_configure_close);
+
+ } else {
+ ro_gui_dialog_open_top(tool->w, NULL, 0, 0);
+ }
+ break;
+ }
+ }
+ return true;
+}
+
+void ro_gui_configure_close(wimp_w w)
+{
+ struct configure_tool *tool;
+
+ for (tool = configure_tools; tool; tool = tool->next) {
+ if (tool->w == w) {
+ tool->open = false;
+ if (tool->finalise)
+ tool->finalise(w);
+ break;
+ }
+ }
+}
+
+void ro_gui_configure_open_window(wimp_open *open)
+{
+ os_error *error;
+ int screen_width, screen_height;
+ int height, width;
+ int icons_per_line, icon_lines;
+ int max_icons_per_line, max_height;
+ os_box extent = { 0, 0, 0, 0 };
+ int x, y, l;
+ struct configure_tool *tool;
+
+ if (!ro_gui_configure_translate()) {
+ warn_user("ro_gui_configure_translate failed", 0);
+ return;
+ }
+
+ width = open->visible.x1 - open->visible.x0;
+ height = open->visible.y1 - open->visible.y0;
+ icons_per_line = width / configure_icon_width;
+ if (icons_per_line < 1)
+ icons_per_line = 1;
+
+ /* move our icons */
+ if (icons_per_line != configure_icons_per_line) {
+ configure_icons_per_line = icons_per_line;
+ x = CONFIGURE_ICON_PADDING_H / 2;
+ y = -configure_icon_height + (CONFIGURE_ICON_PADDING_V / 2);
+ l = 0;
+ for (tool = configure_tools; tool; tool = tool->next) {
+ error = xwimp_resize_icon(configure_window,
+ tool->i,
+ x,
+ y,
+ x + configure_icon_width -
+ CONFIGURE_ICON_PADDING_H,
+ y + configure_icon_height -
+ CONFIGURE_ICON_PADDING_V);
+ if (error) {
+ LOG(("xwimp_resize_icon: 0x%x: %s",
+ error->errnum, error->errmess));
+ }
+ x += configure_icon_width;
+ l++;
+ if (l >= icons_per_line) {
+ x = CONFIGURE_ICON_PADDING_H / 2;
+ l = 0;
+ y -= configure_icon_height;
+ }
+ }
+ error = xwimp_force_redraw(configure_window,
+ 0, -16384, 16384, 0);
+ if (error) {
+ LOG(("xwimp_force_redraw: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+ }
+
+ /* restrict our height */
+ icon_lines = (configure_icons + icons_per_line - 1) /
+ icons_per_line;
+ max_height = (icon_lines * configure_icon_height);
+ if (height > max_height)
+ open->visible.y0 = open->visible.y1 - max_height;
+
+ /* set the extent */
+ if ((configure_height != height) || (configure_width != width)) {
+ ro_gui_screen_size(&screen_width, &screen_height);
+ max_icons_per_line = screen_width / configure_icon_width;
+ if (max_icons_per_line > configure_icons)
+ max_icons_per_line = configure_icons;
+ extent.x1 = configure_icon_width * max_icons_per_line;
+ extent.y0 = -max_height;
+ error = xwimp_set_extent(open->w, &extent);
+ if (error) {
+ LOG(("xwimp_set_extent: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+ configure_height = height;
+ configure_width = width;
+ }
+
+ /* open the window */
+ error = xwimp_open_window(open);
+ if (error) {
+ LOG(("xwimp_open_window: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+}
+
+void ro_gui_configure_register(const char *window,
+ bool (*initialise)(wimp_w w), void (*finalise)(wimp_w w))
+{
+ wimp_icon_create new_icon;
+ struct configure_tool *tool;
+ struct configure_tool *link;
+ os_error *error;
+
+ /* create our tool */
+ tool = calloc(sizeof(struct configure_tool), 1);
+ if (!tool) {
+ LOG(("Insufficient memory for calloc()"));
+ die("Insufficient memory");
+ }
+ tool->name = window;
+ tool->translated[0] = '\0';
+ tool->validation = malloc(strlen(window) + 2);
+ if (!tool->validation) {
+ LOG(("Insufficient memory for malloc()"));
+ die("Insufficient memory");
+ }
+ sprintf(tool->validation, "S%s", window);
+ tool->initialise = initialise;
+ tool->finalise = finalise;
+ tool->w = ro_gui_dialog_create(tool->name);
+
+ /* create the icon */
+ new_icon.w = configure_window;
+ new_icon.icon.extent.x0 = 0;
+ new_icon.icon.extent.x1 = configure_icon_width;
+ new_icon.icon.extent.y1 = 0;
+ new_icon.icon.extent.y0 = -configure_icon_height;
+ new_icon.icon.flags = wimp_ICON_TEXT | wimp_ICON_SPRITE |
+ wimp_ICON_INDIRECTED | wimp_ICON_HCENTRED |
+ (wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT) |
+ (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
+ (wimp_BUTTON_CLICK << wimp_ICON_BUTTON_TYPE_SHIFT);
+ new_icon.icon.data.indirected_text_and_sprite.text =
+ tool->translated;
+ new_icon.icon.data.indirected_text_and_sprite.validation =
+ tool->validation;
+ new_icon.icon.data.indirected_text_and_sprite.size =
+ CONFIGURE_TOOL_TRANSLATED_SIZE;
+ error = xwimp_create_icon(&new_icon, &tool->i);
+ if (error) {
+ LOG(("xwimp_create_icon: 0x%x: %s",
+ error->errnum, error->errmess));
+ die(error->errmess);
+ }
+
+ /* Set the icon's text in current local encoding */
+ ro_gui_set_icon_string(configure_window, tool->i,
+ messages_get(tool->name));
+
+ /* link into our list alphabetically */
+ if ((!configure_tools) ||
+ (strcmp(configure_tools->translated,
+ tool->translated) > 0)) {
+ tool->next = configure_tools;
+ configure_tools = tool;
+ } else {
+ for (link = configure_tools; link; link = link->next) {
+ if (link->next) {
+ if (strcmp(link->next->translated,
+ tool->translated) > 0) {
+ tool->next = link->next;
+ link->next = tool;
+ break;
+ }
+ } else {
+ link->next = tool;
+ break;
+ }
+ }
+ }
+ configure_icons++;
+}
+
+/**
+ * Translate tool icons into the system local encoding.
+ * This will also recalculate the minimum required icon width.
+ *
+ * \return true on success, false on memory exhaustion
+ */
+bool ro_gui_configure_translate(void)
+{
+ int alphabet;
+ struct configure_tool *tool;
+ int icon_width;
+ os_error *error;
+
+ /* read current alphabet */
+ error = xosbyte1(osbyte_ALPHABET_NUMBER, 127, 0,
+ &alphabet);
+ if (error) {
+ LOG(("failed reading alphabet: 0x%x: %s",
+ error->errnum, error->errmess));
+ /* assume Latin1 */
+ alphabet = territory_ALPHABET_LATIN1;
+ }
+
+ if (alphabet == configure_current_encoding)
+ /* text is already in the correct encoding */
+ return true;
+
+ /* reset icon width */
+ configure_icon_width = CONFIGURE_DEFAULT_ICON_WIDTH;
+
+ for (tool = configure_tools; tool; tool = tool->next) {
+ /* re-translate the text */
+ ro_gui_set_icon_string(configure_window, tool->i,
+ messages_get(tool->name));
+
+ /* update the width */
+ error = xwimptextop_string_width(tool->translated,
+ strlen(tool->translated), &icon_width);
+ if (error) {
+ LOG(("xwimptextop_string_width: 0x%x: %s",
+ error->errnum, error->errmess));
+ return false;
+ }
+ icon_width += CONFIGURE_ICON_PADDING_H;
+ if (icon_width > configure_icon_width)
+ configure_icon_width = icon_width;
+
+ error = xwimp_resize_icon(configure_window,
+ tool->i,
+ 0,
+ -configure_icon_height,
+ configure_icon_width,
+ 0);
+ if (error) {
+ LOG(("xwimp_resize_icon: 0x%x: %s",
+ error->errnum, error->errmess));
+ }
+ }
+
+ /* invalidate our global icons_per_line setting
+ * so the icons get reflowed */
+ configure_icons_per_line = 0;
+
+ /* finally, set the current encoding */
+ configure_current_encoding = alphabet;
+
+ return true;
+}
Modified: trunk/netsurf/riscos/configure/con_fonts.c
URL: http://svn.semichrome.net/trunk/netsurf/riscos/configure/con_fonts.c?rev=...
==============================================================================
--- trunk/netsurf/riscos/configure/con_fonts.c (original)
+++ trunk/netsurf/riscos/configure/con_fonts.c Tue Jun 20 22:35:33 2006
@@ -148,7 +148,7 @@
option_font_default = i + 1;
ro_gui_save_options();
- return true;
+ return true;
}
bool ro_gui_options_fonts_init_menu(void)
Modified: trunk/netsurf/riscos/configure/con_language.c
URL: http://svn.semichrome.net/trunk/netsurf/riscos/configure/con_language.c?r...
==============================================================================
--- trunk/netsurf/riscos/configure/con_language.c (original)
+++ trunk/netsurf/riscos/configure/con_language.c Tue Jun 20 22:35:33 2006
@@ -32,8 +32,8 @@
static bool ro_gui_options_language_ok(wimp_w w);
static const char *ro_gui_options_language_name(const char *code);
-bool ro_gui_options_language_initialise(wimp_w w) {
-
+bool ro_gui_options_language_initialise(wimp_w w)
+{
/* set the current values */
ro_gui_set_icon_string(w, LANGUAGE_INTERFACE_FIELD,
ro_gui_options_language_name(option_language ?
@@ -58,9 +58,10 @@
}
-void ro_gui_options_language_default(wimp_pointer *pointer) {
+void ro_gui_options_language_default(wimp_pointer *pointer)
+{
const char *code;
-
+
code = ro_gui_default_language();
ro_gui_set_icon_string(pointer->w, LANGUAGE_INTERFACE_FIELD,
ro_gui_options_language_name(code ?
@@ -70,21 +71,22 @@
code : "en"));
}
-bool ro_gui_options_language_ok(wimp_w w) {
+bool ro_gui_options_language_ok(wimp_w w)
+{
const char *code;
char *temp;
-
+
code = ro_gui_menu_find_menu_entry_key(languages_menu,
ro_gui_get_icon_string(w, LANGUAGE_INTERFACE_FIELD));
if (code) {
- code += 5; /* skip 'lang_' */
+ code += 5; /* skip 'lang_' */
if ((!option_language) || (strcmp(option_language, code))) {
temp = strdup(code);
if (temp) {
- free(option_language);
- option_language = temp;
+ free(option_language);
+ option_language = temp;
} else {
- LOG(("No memory to duplicate language code"));
+ LOG(("No memory to duplicate language code"));
warn_user("NoMemory", 0);
}
}
@@ -92,21 +94,21 @@
code = ro_gui_menu_find_menu_entry_key(languages_menu,
ro_gui_get_icon_string(w, LANGUAGE_WEB_PAGES_FIELD));
if (code) {
- code += 5; /* skip 'lang_' */
+ code += 5; /* skip 'lang_' */
if ((!option_accept_language) ||
(strcmp(option_accept_language, code))) {
temp = strdup(code);
if (temp) {
- free(option_accept_language);
- option_accept_language = temp;
+ free(option_accept_language);
+ option_accept_language = temp;
} else {
- LOG(("No memory to duplicate language code"));
+ LOG(("No memory to duplicate language code"));
warn_user("NoMemory", 0);
}
}
}
ro_gui_save_options();
- return true;
+ return true;
}
@@ -116,9 +118,11 @@
* \param code 2-letter ISO language code
* \return language name, or code if unknown
*/
-const char *ro_gui_options_language_name(const char *code) {
+const char *ro_gui_options_language_name(const char *code)
+{
char key[] = "lang_xx";
key[5] = code[0];
key[6] = code[1];
+
return messages_get(key);
}
Modified: trunk/netsurf/riscos/wimp.c
URL: http://svn.semichrome.net/trunk/netsurf/riscos/wimp.c?rev=2638&r1=2637&r2...
==============================================================================
--- trunk/netsurf/riscos/wimp.c (original)
+++ trunk/netsurf/riscos/wimp.c Tue Jun 20 22:35:33 2006
@@ -284,6 +284,71 @@
/**
+ * Set the contents of an icon to a string.
+ *
+ * \param w window handle
+ * \param i icon handle
+ * \param text string (in local encoding) (copied)
+ */
+void ro_gui_set_icon_string_le(wimp_w w, wimp_i i, const char *text) {
+ wimp_caret caret;
+ wimp_icon_state ic;
+ os_error *error;
+ int old_len, len;
+
+ /* get the icon data */
+ ic.w = w;
+ ic.i = i;
+ error = xwimp_get_icon_state(&ic);
+ if (error) {
+ LOG(("xwimp_get_icon_state: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+
+ /* check that the existing text is not the same as the updated text
+ * to stop flicker */
+ if (ic.icon.data.indirected_text.size &&
+ !strncmp(ic.icon.data.indirected_text.text,
+ text,
+ (unsigned int)ic.icon.data.indirected_text.size - 1))
+ return;
+
+ /* copy the text across */
+ old_len = strlen(ic.icon.data.indirected_text.text);
+ if (ic.icon.data.indirected_text.size) {
+ strncpy(ic.icon.data.indirected_text.text, text,
+ (unsigned int)ic.icon.data.indirected_text.size - 1);
+ ic.icon.data.indirected_text.text[
+ ic.icon.data.indirected_text.size - 1] = '\0';
+ }
+
+ /* handle the caret being in the icon */
+ error = xwimp_get_caret_position(&caret);
+ if (error) {
+ LOG(("xwimp_get_caret_position: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ return;
+ }
+ if ((caret.w == w) && (caret.i == i)) {
+ len = strlen(text);
+ if ((caret.index > len) || (caret.index == old_len))
+ caret.index = len;
+ error = xwimp_set_caret_position(w, i, caret.pos.x, caret.pos.y,
+ -1, caret.index);
+ if (error) {
+ LOG(("xwimp_set_caret_position: 0x%x: %s",
+ error->errnum, error->errmess));
+ warn_user("WimpError", error->errmess);
+ }
+ }
+ ro_gui_redraw_icon(w, i);
+}
+
+
+/**
* Set the contents of an icon to a number.
*
* \param w window handle
@@ -406,7 +471,7 @@
error->errnum, error->errmess));
warn_user("WimpError", error->errmess);
}
- if (!state)
+ if (!state)
return;
/* ensure the caret is not in a shaded icon */
Modified: trunk/netsurf/riscos/wimp.h
URL: http://svn.semichrome.net/trunk/netsurf/riscos/wimp.h?rev=2638&r1=2637&r2...
==============================================================================
--- trunk/netsurf/riscos/wimp.h (original)
+++ trunk/netsurf/riscos/wimp.h Tue Jun 20 22:35:33 2006
@@ -30,6 +30,7 @@
void ro_gui_force_redraw_icon(wimp_w w, wimp_i i);
char *ro_gui_get_icon_string(wimp_w w, wimp_i i);
void ro_gui_set_icon_string(wimp_w w, wimp_i i, const char *text);
+void ro_gui_set_icon_string_le(wimp_w w, wimp_i i, const char *text);
void ro_gui_set_icon_integer(wimp_w w, wimp_i i, int value);
void ro_gui_set_icon_decimal(wimp_w w, wimp_i i, int value, int decimal_places);
Modified: trunk/netsurf/riscos/wimp_event.c
URL: http://svn.semichrome.net/trunk/netsurf/riscos/wimp_event.c?rev=2638&r1=2...
==============================================================================
--- trunk/netsurf/riscos/wimp_event.c (original)
+++ trunk/netsurf/riscos/wimp_event.c Tue Jun 20 22:35:33 2006
@@ -354,7 +354,7 @@
if (menu_entry->menu_flags & wimp_MENU_TICKED)
return true;
- ro_gui_set_icon_string(window->w, event->data.menu_gright.field,
+ ro_gui_set_icon_string_le(window->w, event->data.menu_gright.field,
menu_entry->data.indirected_text.text);
ro_gui_wimp_event_prepare_menu(window->w, event);
if (window->menu_selection)
16 years, 7 months
r2637 jmb - /trunk/netsurf/content/urldb.c
by netsurf@semichrome.net
Author: jmb
Date: Tue Jun 20 13:05:19 2006
New Revision: 2637
URL: http://svn.semichrome.net?rev=2637&view=rev
Log:
Remove assertion of invalid assumption (fixes #1509118)
Modified:
trunk/netsurf/content/urldb.c
Modified: trunk/netsurf/content/urldb.c
URL: http://svn.semichrome.net/trunk/netsurf/content/urldb.c?rev=2637&r1=2636&...
==============================================================================
--- trunk/netsurf/content/urldb.c (original)
+++ trunk/netsurf/content/urldb.c Tue Jun 20 13:05:19 2006
@@ -1080,13 +1080,13 @@
* Set thumbnail for url, replacing any existing thumbnail
*
* \param url Absolute URL to consider
- * \param bitmap Opaque pointer to thumbnail data
+ * \param bitmap Opaque pointer to thumbnail data, or NULL to invalidate
*/
void urldb_set_thumbnail(const char *url, struct bitmap *bitmap)
{
struct path_data *p;
- assert(url && bitmap);
+ assert(url);
p = urldb_find_url(url);
if (!p)
16 years, 7 months
r2636 jmb - /trunk/netsurf/content/urldb.c
by netsurf@semichrome.net
Author: jmb
Date: Tue Jun 20 12:45:41 2006
New Revision: 2636
URL: http://svn.semichrome.net?rev=2636&view=rev
Log:
Make cookie file parser more strict (cookies with spaces in the value
have been seen in the wild).
Fix lookup of cookies for top-level paths (i.e. a path segment of "/")
Modified:
trunk/netsurf/content/urldb.c
Modified: trunk/netsurf/content/urldb.c
URL: http://svn.semichrome.net/trunk/netsurf/content/urldb.c?rev=2636&r1=2635&...
==============================================================================
--- trunk/netsurf/content/urldb.c (original)
+++ trunk/netsurf/content/urldb.c Tue Jun 20 12:45:41 2006
@@ -2334,55 +2334,51 @@
now = time(NULL);
- if (p->prev) {
- for (q = p->prev; q && q->prev; q = q->prev)
- ; /* do nothing */
- } else {
- q = p;
- }
-
- for (; q; q = q->next) {
- if (strcmp(q->segment, p->segment))
- continue;
-
- /* Consider all cookies associated with this exact path */
- for (c = q->cookies; c; c = c->next) {
- if (c->expires != 1 && c->expires < now)
- /* cookie has expired => ignore */
+ if (*(p->segment) != '\0') {
+ /* Match exact path, unless directory, when prefix matching
+ * will handle this case for us. */
+ for (q = p->parent->children; q; q = q->next) {
+ if (strcmp(q->segment, p->segment))
continue;
- if (c->secure && strcasecmp(q->scheme, "https"))
- /* secure cookie for insecure host. ignore */
- continue;
-
- if (!urldb_concat_cookie(c, &ret_used,
- &ret_alloc, &ret)) {
- free(path);
- free(ret);
- return NULL;
+ /* Consider all cookies associated with
+ * this exact path */
+ for (c = q->cookies; c; c = c->next) {
+ if (c->expires != 1 && c->expires < now)
+ /* cookie has expired => ignore */
+ continue;
+
+ if (c->secure && strcasecmp(
+ q->scheme, "https"))
+ /* secure cookie for insecure host.
+ * ignore */
+ continue;
+
+ if (!urldb_concat_cookie(c, &ret_used,
+ &ret_alloc, &ret)) {
+ free(path);
+ free(ret);
+ return NULL;
+ }
+
+ if (c->version < (unsigned int)version)
+ version = c->version;
+
+ c->last_used = now;
+
+ count++;
}
-
- if (c->version < (unsigned int)version)
- version = c->version;
-
- c->last_used = now;
-
- count++;
}
}
// LOG(("%s", ret));
- if (strlen(p->segment) == 0)
- /* We're a directory; skip parent */
- p = p->parent->parent;
-
/* Now consider cookies whose paths prefix-match ours */
- for (; p; p = p->parent) {
- /* Find parent directory's path entry(ies) */
+ for (p = p->parent; p; p = p->parent) {
+ /* Find directory's path entry(ies) */
/* There are potentially multiple due to differing schemes */
for (q = p->children; q; q = q->next) {
- if (strlen(q->segment) > 0)
+ if (*(q->segment) != '\0')
continue;
for (c = q->cookies; c; c = c->next) {
@@ -3024,8 +3020,8 @@
if (!fp)
return;
-#define FIND_WS { \
- for (; *p && !isspace(*p) && !iscntrl(*p); p++) \
+#define FIND_T { \
+ for (; *p && *p != '\t'; p++) \
; /* do nothing */ \
if (p >= end) { \
LOG(("Overran input")); \
@@ -3034,8 +3030,8 @@
*p++ = '\0'; \
}
-#define SKIP_WS { \
- for (; *p && isspace(*p); p++) \
+#define SKIP_T { \
+ for (; *p && *p == '\t'; p++) \
; /* do nothing */ \
if (p >= end) { \
LOG(("Overran input")); \
@@ -3062,7 +3058,7 @@
* (all input is ignored until this is read)
*/
if (strncasecmp(s, "Version:", 8) == 0) {
- FIND_WS; SKIP_WS; file_version = atoi(p);
+ FIND_T; SKIP_T; file_version = atoi(p);
if (file_version != COOKIE_FILE_VERSION) {
LOG(("Unknown Cookie file version"));
@@ -3078,23 +3074,23 @@
/* One cookie/line */
/* Parse input */
- FIND_WS; version = atoi(s);
- SKIP_WS; domain = p; FIND_WS;
- SKIP_WS; domain_specified = atoi(p); FIND_WS;
- SKIP_WS; path = p; FIND_WS;
- SKIP_WS; path_specified = atoi(p); FIND_WS;
- SKIP_WS; secure = atoi(p); FIND_WS;
- SKIP_WS; expires = (time_t)atoi(p); FIND_WS;
- SKIP_WS; last_used = (time_t)atoi(p); FIND_WS;
- SKIP_WS; no_destroy = atoi(p); FIND_WS;
- SKIP_WS; name = p; FIND_WS;
- SKIP_WS; value = p; FIND_WS;
- SKIP_WS; scheme = p; FIND_WS;
- SKIP_WS; url = p; FIND_WS;
+ FIND_T; version = atoi(s);
+ SKIP_T; domain = p; FIND_T;
+ SKIP_T; domain_specified = atoi(p); FIND_T;
+ SKIP_T; path = p; FIND_T;
+ SKIP_T; path_specified = atoi(p); FIND_T;
+ SKIP_T; secure = atoi(p); FIND_T;
+ SKIP_T; expires = (time_t)atoi(p); FIND_T;
+ SKIP_T; last_used = (time_t)atoi(p); FIND_T;
+ SKIP_T; no_destroy = atoi(p); FIND_T;
+ SKIP_T; name = p; FIND_T;
+ SKIP_T; value = p; FIND_T;
+ SKIP_T; scheme = p; FIND_T;
+ SKIP_T; url = p; FIND_T;
/* Comment may have no content, so don't
* use macros as they'll break */
- for (; *p && isspace(*p); p++)
+ for (; *p && *p == '\t'; p++)
; /* do nothing */
comment = p;
@@ -3158,13 +3154,13 @@
"# Lines starting with a '#' are comments, "
"blank lines are ignored.\n"
"#\n"
- "# All lines prior to \"Version: %d\" are discarded.\n"
+ "# All lines prior to \"Version:\t%d\" are discarded.\n"
"#\n"
"# Version\tDomain\tDomain from Set-Cookie\tPath\t"
"Path from Set-Cookie\tSecure\tExpires\tLast used\t"
"No destroy\tName\tValue\tScheme\tURL\tComment\n",
COOKIE_FILE_VERSION);
- fprintf(fp, "Version: %d\n", COOKIE_FILE_VERSION);
+ fprintf(fp, "Version:\t%d\n", COOKIE_FILE_VERSION);
urldb_save_cookie_hosts(fp, &db_root);
16 years, 7 months
r2634 tlsa - in /trunk/netsurfweb: develop.en netsurf.css translations.en
by netsurf@semichrome.net
Author: tlsa
Date: Tue Jun 20 09:36:25 2006
New Revision: 2634
URL: http://svn.semichrome.net?rev=2634&view=rev
Log:
Add translations page.
Added:
trunk/netsurfweb/translations.en
Modified:
trunk/netsurfweb/develop.en
trunk/netsurfweb/netsurf.css
Modified: trunk/netsurfweb/develop.en
URL: http://svn.semichrome.net/trunk/netsurfweb/develop.en?rev=2634&r1=2633&r2...
==============================================================================
--- trunk/netsurfweb/develop.en (original)
+++ trunk/netsurfweb/develop.en Tue Jun 20 09:36:25 2006
@@ -76,9 +76,9 @@
<h2>Translations</h2>
<p>Translations of NetSurf to other languages are welcome. No programming
-knowledge is required, just the ability to use a template editor (for
-example <a href="http://www.linbury.nildram.co.uk/wined.html">WinEd</a>)
-and a text editor.</p>
+knowledge is required, just the ability to use a template editor and a text
+editor. Please see the <a href="translations">translations page</a> for more
+information.</p>
<div class="footer">
Modified: trunk/netsurfweb/netsurf.css
URL: http://svn.semichrome.net/trunk/netsurfweb/netsurf.css?rev=2634&r1=2633&r...
==============================================================================
--- trunk/netsurfweb/netsurf.css (original)
+++ trunk/netsurfweb/netsurf.css Tue Jun 20 09:36:25 2006
@@ -30,6 +30,7 @@
.iconinfo { clear: left; }
.headnote { color: #777; font-style: italic; }
.note { width: 80%; background-color: #d2ffd2; padding: 0.8em; border: 4px ridge #d2ffd2; margin-left: auto; margin-right: auto; }
+.caption { text-align: right; font-style: italic; }
th { font-weight: bold; padding: 3px; text-align: left; }
td { padding: 3px; }
Added: trunk/netsurfweb/translations.en
URL: http://svn.semichrome.net/trunk/netsurfweb/translations.en?rev=2634&view=...
==============================================================================
--- trunk/netsurfweb/translations.en (added)
+++ trunk/netsurfweb/translations.en Tue Jun 20 09:36:25 2006
@@ -1,0 +1,82 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>NetSurf | Development Information</title>
+<link rel="stylesheet" type="text/css" href="netsurf.css">
+</head>
+
+<body>
+<p class="banner"><a href="/"><img src="netsurf.png" alt="NetSurf: Web Browser for RISC OS"></a></p>
+
+<h1>Translations</h1>
+
+<p>This page contains information for anyone interested in translating NetSurf into other languages.</p>
+
+<ul>
+<li><a href="#GettingStarted">Getting started</a>
+<ul>
+<li><a href="#GettingStartedMailingList">Mailing list</a></li>
+<li><a href="#GettingStartedObtainingFiles">Obtaining files</a></li>
+<li><a href="#GettingStartedRequirements">Requirements</a></li>
+</ul></li>
+<li><a href="#FileSubmission">File submission</a></li>
+</ul>
+
+<p class="updated">Last updated 17 June 2006</p>
+
+<h2 id="GettingStarted">Getting started</h2>
+
+<p>Translations of NetSurf into other languages are very welcome. Currently we have the reference version in English and translations into Dutch, French and German.</p>
+
+<h3 id="GettingStartedMailingList">Mailing list</h3>
+
+<p>A <a href="https://lists.sourceforge.net/lists/listinfo/netsurf-translators">mailing list</a> has been set up for NetSurf translators. Please join the mailing list if you would like to translate NetSurf into a new language or help with an exising translation.</p>
+
+<p>The mailing list is for any discussion related to translating NetSurf and will be used to indicate any changes that have been made to NetSurf's interface, web site or documentation.</p>
+
+<h3 id="GettingStartedObtainingFiles">Obtaining files</h3>
+
+<p>There are two types of files that can be translated; those that are part of the web site and those that are part of the NetSurf application.</p>
+
+<p>The documentation is part of the web site and it is copied into the NetSurf application by the autobuilder. The autobuilder automatically makes a few changes to links in the documentation, to ensure they work off line. It is important that it is the web site version of the documentation is translated.</p>
+
+<p>The simplest way to get the latest files is to use Subversion, as follows:</p>
+
+<p><code>*<strong>svn checkout svn://semichrome.net/trunk/netsurf/!NetSurf</strong></code><br><code>*<strong>svn checkout svn://semichrome.net/trunk/netsurfweb</strong></code></p>
+
+<p>The <a href="http://www.cp15.org/versioncontrol/">Subversion client</a> must first have been seen by the filer.</p>
+
+<p>The important files are</p>
+
+<ul>
+<li>!NetSurf.Docs.intro_??</li>
+<li>!NetSurf.Resources.??.Messages</li>
+<li>!NetSurf.Resources.??.Templates</li>
+<li>In netsurfweb: Any file ending in "/??"</li>
+</ul>
+
+<p class="caption">"??" is a two letter country code, such as "de" (Germany) or "fr" (France)</p>
+
+<p>Alternatively, the three files from !NetSurf can be taken from the <a href="http://netsurf.sourceforge.net/builds">latest build</a> and any documentation or web material can be found on the <a href="http://netsurf.sourceforge.net/">web site</a>. Do not be put off by the amount of files that can be translated. A translation of just NetSurf's interface is much better than no translation at all!</p>
+
+<p>Please translate from the English version as this will always be most up to date.</p>
+
+<h3 id="GettingStartedRequirements">Requirements</h3>
+
+<p>No programming knowledge is required, just the ability to use a template editor (for example <a href="http://www.linbury.nildram.co.uk/wined.html">WinEd</a>) and a text editor capable of editing UTF-8 encoded files (for example <a href="http://zap.tartarus.org/">Zap</a>).</p>
+
+<p>NetSurf's Messages files are UTF-8 encoded. In Zap 1.47 Beta, to select UTF-8 mode, click menu over the window and select:</p>
+
+<p><code>Edit > Encoding > UTF8</code></p>
+
+<h2 id="FileSubmission">File submission</h2>
+
+<p>Please send any translated files to Michael <<a href="mailto:tlsa@users.sourceforge.net">tlsa(a)users.sourceforge.net</a>>.</p>
+
+<div class="footer">
+<p class="breadcrumbs"><a href="/">NetSurf</a> » <a href="develop">Development Information</a> » Translations</p> <p class="sourceforge"><a href="http://sourceforge.net/"><img src="http://sourceforge.net/sflogo.php?group_id=51719&type=1" alt="SourceForge.net"></a></p>
+</div>
+
+</body>
+</html>
16 years, 7 months
r2633 jmb - /trunk/netsurf/content/urldb.c
by netsurf@semichrome.net
Author: jmb
Date: Tue Jun 20 00:40:27 2006
New Revision: 2633
URL: http://svn.semichrome.net?rev=2633&view=rev
Log:
Fix handling of broken Expires avpairs
Modified:
trunk/netsurf/content/urldb.c
Modified: trunk/netsurf/content/urldb.c
URL: http://svn.semichrome.net/trunk/netsurf/content/urldb.c?rev=2633&r1=2632&...
==============================================================================
--- trunk/netsurf/content/urldb.c (original)
+++ trunk/netsurf/content/urldb.c Tue Jun 20 00:40:27 2006
@@ -279,7 +279,7 @@
regcomp_wrapper(&expires_re, "[a-zA-Z]{3},[[:space:]]" // "Wdy, "
"[0-9]{2}[[:space:]-]" // "DD[ -]"
"[a-zA-Z]{3}[[:space:]-]" // "MMM[ -]"
- "[0-9]{4}[[:space:]]" // "YYYY "
+ "[0-9]{2,4}[[:space:]]" // "YY(YY)? "
"[0-9]{2}(:[0-9]{2}){2}" // "HH:MM:SS"
"[[:space:]]GMT", // " GMT"
REG_EXTENDED);
@@ -3226,11 +3226,44 @@
}
-#ifdef TEST
+#ifdef TEST_URLDB
+const char *inputs[] = {
+ "day, 16-Jun-2006 01:10:16 GMT",
+ "day, 16 Jun 2006 01:10:16 GMT",
+ "day, 16-Jun-06 01:10:16 GMT",
+ "day, 16 Jun 06 01:10:16 GMT",
+ "Fri, 16-Jun-2006 01:10:16 GMT",
+ "Fri, 16 Jun 2006 01:10:16 GMT",
+ "Fri, 16-Jun-06 01:10:16 GMT",
+ "Fri, 16 Jun 06 01:10:16 GMT"
+};
+#define N_INPUTS (sizeof(inputs) / sizeof(inputs[0]))
+
+int option_expire_url = 0;
+
+void die(const char *error)
+{
+ printf("die: %s\n", error);
+ exit(1);
+}
+
+
+void warn_user(const char *warning, const char *detail)
+{
+ printf("WARNING: %s %s\n", warning, detail);
+}
+
int main(void)
{
struct host_part *h;
struct path_data *p;
+ int i;
+
+ urldb_init();
+
+ for (i = 0; i != N_INPUTS; i++)
+ if (regexec(&expires_re, inputs[i], 0, NULL, 0))
+ LOG(("Failed to match regex %d\n", i));
h = urldb_add_host("127.0.0.1");
if (!h) {
@@ -3246,19 +3279,22 @@
}
/* Get path entry */
- p = urldb_add_path("http", 80, h, "/path/to/resource.htm?a=b", "zz");
+ p = urldb_add_path("http", 80, h, "/path/to/resource.htm?a=b", "zz",
+ "http://netsurf.strcprstskrzkrk.co.uk/path/to/resource.htm?a=b");
if (!p) {
LOG(("failed adding path"));
return 1;
}
- p = urldb_add_path("http", 80, h, "/path/to/resource.htm?a=b", "aa");
+ p = urldb_add_path("http", 80, h, "/path/to/resource.htm?a=b", "aa",
+ "http://netsurf.strcprstskrzkrk.co.uk/path/to/resource.htm?a=b");
if (!p) {
LOG(("failed adding path"));
return 1;
}
- p = urldb_add_path("http", 80, h, "/path/to/resource.htm?a=b", "yy");
+ p = urldb_add_path("http", 80, h, "/path/to/resource.htm?a=b", "yy",
+ "http://netsurf.strcprstskrzkrk.co.uk/path/to/resource.htm?a=b");
if (!p) {
LOG(("failed adding path"));
return 1;
16 years, 7 months
r2632 jmb - in /trunk/netsurf: content/fetch.c content/urldb.c content/urldb.h desktop/netsurf.c riscos/gui.c utils/url.c utils/url.h
by netsurf@semichrome.net
Author: jmb
Date: Mon Jun 19 22:49:25 2006
New Revision: 2632
URL: http://svn.semichrome.net?rev=2632&view=rev
Log:
Merge cookies changes into head - unvalidated transactions and a UI
still need implementing.
Modified:
trunk/netsurf/content/fetch.c
trunk/netsurf/content/urldb.c
trunk/netsurf/content/urldb.h
trunk/netsurf/desktop/netsurf.c
trunk/netsurf/riscos/gui.c
trunk/netsurf/utils/url.c
trunk/netsurf/utils/url.h
Modified: trunk/netsurf/content/fetch.c
URL: http://svn.semichrome.net/trunk/netsurf/content/fetch.c?rev=2632&r1=2631&...
==============================================================================
--- trunk/netsurf/content/fetch.c (original)
+++ trunk/netsurf/content/fetch.c Mon Jun 19 22:49:25 2006
@@ -70,6 +70,7 @@
char *host; /**< Host part of URL. */
char *location; /**< Response Location header, or 0. */
unsigned long content_length; /**< Response Content-Length, or 0. */
+ char *cookie_string; /**< Cookie string for this fetch */
char *realm; /**< HTTP Auth Realm */
char *post_urlenc; /**< Url encoded POST string, or 0. */
struct curl_httppost *post_multipart; /**< Multipart post data, or 0. */
@@ -356,6 +357,7 @@
fetch->host = host;
fetch->location = 0;
fetch->content_length = 0;
+ fetch->cookie_string = 0;
fetch->realm = 0;
fetch->post_urlenc = 0;
fetch->post_multipart = 0;
@@ -635,13 +637,9 @@
SETOPT(CURLOPT_HTTPGET, 1L);
}
if (f->cookies) {
- if (option_cookie_file)
- SETOPT(CURLOPT_COOKIEFILE, option_cookie_file);
- if (option_cookie_jar)
- SETOPT(CURLOPT_COOKIEJAR, option_cookie_jar);
- } else {
- SETOPT(CURLOPT_COOKIEFILE, 0);
- SETOPT(CURLOPT_COOKIEJAR, 0);
+ f->cookie_string = urldb_get_cookie(f->url, f->referer);
+ if (f->cookie_string)
+ SETOPT(CURLOPT_COOKIE, f->cookie_string);
}
#ifdef WITH_AUTH
if ((auth = urldb_get_auth_details(f->url)) != NULL) {
@@ -771,6 +769,7 @@
free(f->host);
free(f->referer);
free(f->location);
+ free(f->cookie_string);
free(f->realm);
if (f->headers)
curl_slist_free_all(f->headers);
@@ -1175,6 +1174,10 @@
f->cachedata.last_modified =
curl_getdate(&data[i], NULL);
}
+ } else if (11 < size && strncasecmp(data, "Set-Cookie:", 11) == 0) {
+ /* extract Set-Cookie header */
+ SKIP_ST(11);
+ urldb_set_cookie(&data[i], f->url);
}
return size;
Modified: trunk/netsurf/content/urldb.c
URL: http://svn.semichrome.net/trunk/netsurf/content/urldb.c?rev=2632&r1=2631&...
==============================================================================
--- trunk/netsurf/content/urldb.c (original)
+++ trunk/netsurf/content/urldb.c Mon Jun 19 22:49:25 2006
@@ -77,6 +77,9 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
+
+#include <curl/curl.h>
+
#include "netsurf/image/bitmap.h"
#include "netsurf/content/urldb.h"
#include "netsurf/desktop/options.h"
@@ -92,7 +95,11 @@
char *name; /**< Cookie name */
char *value; /**< Cookie value */
char *comment; /**< Cookie comment */
- time_t expires; /**< Expiry timestamp, or 0 for session */
+ bool domain_from_set; /**< Domain came from Set-Cookie: header */
+ char *domain; /**< Domain */
+ bool path_from_set; /**< Path came from Set-Cookie: header */
+ char *path; /**< Path */
+ time_t expires; /**< Expiry timestamp, or 1 for session */
time_t last_used; /**< Last used time */
bool secure; /**< Only send for HTTPS requests */
enum { COOKIE_NETSCAPE = 0,
@@ -102,6 +109,7 @@
bool no_destroy; /**< Never destroy this cookie,
* unless it's expired */
+ struct cookie *prev; /**< Previous in list */
struct cookie *next; /**< Next in list */
};
@@ -230,6 +238,17 @@
static int urldb_search_match_prefix(const struct host_part *a,
const char *b);
+/* Cookies */
+static struct cookie *urldb_parse_cookie(const char *url,
+ const char *cookie);
+static bool urldb_insert_cookie(struct cookie *c, const char *scheme,
+ const char *url);
+static void urldb_free_cookie(struct cookie *c);
+static bool urldb_concat_cookie(struct cookie *c, int *used,
+ int *alloc, char **buf);
+static void urldb_save_cookie_hosts(FILE *fp, struct host_part *parent);
+static void urldb_save_cookie_paths(FILE *fp, struct path_data *parent);
+
/** Root database handle */
static struct host_part db_root;
@@ -245,6 +264,27 @@
&empty, &empty, &empty
};
+#define COOKIE_FILE_VERSION 100
+#define URL_FILE_VERSION 106
+
+regex_t expires_re;
+
+/**
+ * Initialise URL database code
+ *
+ * This should be called before any other urldb functions
+ */
+void urldb_init(void)
+{
+ regcomp_wrapper(&expires_re, "[a-zA-Z]{3},[[:space:]]" // "Wdy, "
+ "[0-9]{2}[[:space:]-]" // "DD[ -]"
+ "[a-zA-Z]{3}[[:space:]-]" // "MMM[ -]"
+ "[0-9]{4}[[:space:]]" // "YYYY "
+ "[0-9]{2}(:[0-9]{2}){2}" // "HH:MM:SS"
+ "[[:space:]]GMT", // " GMT"
+ REG_EXTENDED);
+}
+
/**
* Import an URL database from file, replacing any existing database
*
@@ -279,7 +319,7 @@
LOG(("Unsupported URL file version."));
return;
}
- if (version > 106) {
+ if (version > URL_FILE_VERSION) {
LOG(("Unknown URL file version."));
return;
}
@@ -475,7 +515,7 @@
}
/* file format version number */
- fprintf(fp, "106\n");
+ fprintf(fp, "%d\n", URL_FILE_VERSION);
for (i = 0; i != NUM_SEARCH_TREES; i++) {
urldb_save_search_tree(search_trees[i], fp);
@@ -2242,6 +2282,950 @@
return root;
}
+/**
+ * Retrieve cookies for an URL
+ *
+ * \param url URL being fetched
+ * \param referer Referring resource, or NULL
+ * \return Cookies string for libcurl (on heap), or NULL on error/no cookies
+ *
+ * \todo Handle unvalidated fetches
+ */
+char *urldb_get_cookie(const char *url, const char *referer)
+{
+ const struct path_data *p, *q;
+ const struct host_part *h;
+ struct cookie *c;
+ int count = 0, version = COOKIE_RFC2965;
+ int ret_alloc = 4096, ret_used = 1;
+ char *path;
+ char *ret;
+ char *scheme;
+ time_t now;
+ url_func_result res;
+
+ assert(url);
+
+// LOG(("%s : %s", url, referer));
+
+// if (referer)
+// /* No unvalidated fetches for now */
+// return NULL;
+
+ urldb_add_url(url);
+
+ p = urldb_find_url(url);
+ if (!p)
+ return NULL;
+
+ scheme = p->scheme;
+
+ ret = malloc(ret_alloc);
+ if (!ret)
+ return NULL;
+
+ ret[0] = '\0';
+
+ res = url_path(url, &path);
+ if (res != URL_FUNC_OK) {
+ free(ret);
+ return NULL;
+ }
+
+ now = time(NULL);
+
+ if (p->prev) {
+ for (q = p->prev; q && q->prev; q = q->prev)
+ ; /* do nothing */
+ } else {
+ q = p;
+ }
+
+ for (; q; q = q->next) {
+ if (strcmp(q->segment, p->segment))
+ continue;
+
+ /* Consider all cookies associated with this exact path */
+ for (c = q->cookies; c; c = c->next) {
+ if (c->expires != 1 && c->expires < now)
+ /* cookie has expired => ignore */
+ continue;
+
+ if (c->secure && strcasecmp(q->scheme, "https"))
+ /* secure cookie for insecure host. ignore */
+ continue;
+
+ if (!urldb_concat_cookie(c, &ret_used,
+ &ret_alloc, &ret)) {
+ free(path);
+ free(ret);
+ return NULL;
+ }
+
+ if (c->version < (unsigned int)version)
+ version = c->version;
+
+ c->last_used = now;
+
+ count++;
+ }
+ }
+
+// LOG(("%s", ret));
+
+ if (strlen(p->segment) == 0)
+ /* We're a directory; skip parent */
+ p = p->parent->parent;
+
+ /* Now consider cookies whose paths prefix-match ours */
+ for (; p; p = p->parent) {
+ /* Find parent directory's path entry(ies) */
+ /* There are potentially multiple due to differing schemes */
+ for (q = p->children; q; q = q->next) {
+ if (strlen(q->segment) > 0)
+ continue;
+
+ for (c = q->cookies; c; c = c->next) {
+// LOG(("%p: %s=%s", c, c->name, c->value));
+ if (c->expires != 1 && c->expires < now)
+ /* cookie has expired => ignore */
+ continue;
+
+ if (c->secure && strcasecmp(
+ q->scheme, "https"))
+ /* Secure cookie for insecure server
+ * => ignore */
+ continue;
+
+ if (!urldb_concat_cookie(c, &ret_used,
+ &ret_alloc, &ret)) {
+ free(path);
+ free(ret);
+ return NULL;
+ }
+
+ if (c->version < (unsigned int) version)
+ version = c->version;
+
+ c->last_used = now;
+
+ count++;
+ }
+ }
+
+ if (!p->parent) {
+ /* No parent, so bail here. This can't go in the
+ * loop exit condition as we want to process the
+ * top-level node, too */
+ break;
+ }
+ }
+
+// LOG(("%s", ret));
+
+ /* Finally consider domain cookies for hosts which domain match ours */
+ for (h = (const struct host_part *)p; h && h != &db_root;
+ h = h->parent) {
+ for (c = h->paths.cookies; c; c = c->next) {
+ if (c->expires != 1 && c->expires < now)
+ /* cookie has expired => ignore */
+ continue;
+
+ /* Ensure cookie path is a prefix of the resource */
+ if (strncmp(c->path, path, strlen(c->path)) != 0)
+ /* paths don't match => ignore */
+ continue;
+
+ if (c->secure && strcasecmp(scheme, "https"))
+ /* secure cookie for insecure host. ignore */
+ continue;
+
+ if (!urldb_concat_cookie(c, &ret_used, &ret_alloc,
+ &ret)) {
+ free(path);
+ free(ret);
+ return NULL;
+ }
+
+ if (c->version < (unsigned int)version)
+ version = c->version;
+
+ c->last_used = now;
+
+ count++;
+ }
+ }
+
+// LOG(("%s", ret));
+
+ if (count == 0) {
+ /* No cookies found */
+ free(path);
+ free(ret);
+ return NULL;
+ }
+
+ /* and build output string */
+ {
+ char *temp;
+ if (version > 0)
+ temp = malloc(12 + ret_used);
+ else
+ temp = malloc(ret_used);
+ if (!temp) {
+ free(path);
+ free(ret);
+ return NULL;
+ }
+
+ if (version > 0)
+ sprintf(temp, "$Version=%d%s", version, ret);
+ else {
+ /* Old-style cookies => no version & skip "; " */
+ sprintf(temp, "%s", ret + 2);
+ }
+
+ free(path);
+ free(ret);
+ ret = temp;
+ }
+
+ return ret;
+}
+
+/**
+ * Parse Set-Cookie header and insert cookie(s) into database
+ *
+ * \param header Header to parse, with Set-Cookie: stripped
+ * \param url URL being fetched
+ * \return true on success, false otherwise
+ */
+bool urldb_set_cookie(const char *header, const char *url)
+{
+ char cookie[8192];
+ const char *cur = header, *comma, *end;
+ char *path, *host, *scheme, *urlt;
+ url_func_result res;
+
+ assert(url && header);
+
+// LOG(("'%s' : '%s'", url, header));
+
+ /* strip fragment */
+ urlt = strdup(url);
+ scheme = strchr(urlt, '#');
+ if (scheme)
+ *scheme = '\0';
+
+ res = url_scheme(url, &scheme);
+ if (res != URL_FUNC_OK) {
+ free(urlt);
+ return false;
+ }
+
+ res = url_path(url, &path);
+ if (res != URL_FUNC_OK) {
+ free(scheme);
+ free(urlt);
+ return false;
+ }
+
+ res = url_host(url, &host);
+ if (res != URL_FUNC_OK) {
+ free(path);
+ free(scheme);
+ free(urlt);
+ return false;
+ }
+
+ end = cur + strlen(cur) - 2 /* Trailing CRLF */;
+
+ /* Find comma, if any */
+ comma = strchr(cur, ',');
+ if (comma) {
+ /* Check for Expires avpair: Wdy, DD-Mon-YYYY HH:MM:SS GMT */
+ /* Date parts of the form "DD Mon YYYY" have been seen in
+ * the wild, so we accept them too even though they're not
+ * strictly correct - it's more important to match something
+ * that looks like an Expires avpair than be strict here (as
+ * we're simply looking for the end of the cookie
+ * declaration) */
+ if (regexec(&expires_re, comma - 3, 0, NULL, 0) == 0) {
+ /* Part of Expires avpair => look for next comma */
+ comma = strchr(comma + 1, ',');
+ }
+ }
+
+ if (!comma) {/* Yes, if; not else - Expires check may modify comma */
+ /* No comma => 1 cookie in this header */
+ comma = end;
+ }
+
+ do {
+ struct cookie *c;
+ char *dot;
+
+ snprintf(cookie, sizeof cookie, "%.*s", comma - cur, cur);
+
+ c = urldb_parse_cookie(url, cookie);
+ if (!c) {
+ /* failed => stop parsing */
+ goto error;
+ }
+
+ /* validate cookie */
+
+ /* Cookie path must be a prefix of URL path */
+ if (strncmp(c->path, path, strlen(c->path)) != 0 ||
+ strlen(c->path) > strlen(path)) {
+ urldb_free_cookie(c);
+ goto error;
+ }
+
+ /* Cookie domain must contain embedded dots */
+ dot = strchr(c->domain + 1, '.');
+ if (!dot || *(dot + 1) == '\0') {
+ /* no embedded dots */
+ urldb_free_cookie(c);
+ goto error;
+ }
+
+ /* Domain match fetch host with cookie domain */
+ if (strcasecmp(host, c->domain) != 0) {
+ int hlen, dlen;
+
+ if (host[0] >= '0' && host[0] <= '9') {
+ /* IP address, so no partial match */
+ urldb_free_cookie(c);
+ goto error;
+ }
+
+ hlen = strlen(host);
+ dlen = strlen(c->domain);
+
+ if (hlen <= dlen) {
+ /* Partial match not possible */
+ urldb_free_cookie(c);
+ goto error;
+ }
+
+ if (strcasecmp(host + (hlen - dlen), c->domain)) {
+ urldb_free_cookie(c);
+ goto error;
+ }
+
+ /* Ensure H contains no dots */
+ for (int i = 0; i < (hlen - dlen); i++)
+ if (host[i] == '.') {
+ urldb_free_cookie(c);
+ goto error;
+ }
+ }
+
+ /* Now insert into database */
+ if (!urldb_insert_cookie(c, scheme, urlt))
+ goto error;
+
+ cur = comma + 1;
+ if (cur < end) {
+ comma = strchr(cur, ',');
+ if (comma) {
+ /* Check if it's an Expires avpair */
+ if (regexec(&expires_re, comma - 3, 0,
+ NULL, 0) == 0) {
+ /* Part of Expires avpair =>
+ * look for next comma */
+ comma = strchr(comma + 1, ',');
+ }
+ }
+ if (!comma)
+ comma = end;
+ }
+ } while (comma && cur < end);
+
+ free(host);
+ free(path);
+ free(scheme);
+ free(urlt);
+
+ return true;
+
+error:
+ free(host);
+ free(path);
+ free(scheme);
+ free(urlt);
+
+ return false;
+}
+
+/**
+ * Parse a cookie
+ *
+ * \param url URL being fetched
+ * \param cookie Cookie string
+ * \return Pointer to cookie structure (on heap, caller frees) or NULL
+ */
+struct cookie *urldb_parse_cookie(const char *url, const char *cookie)
+{
+ struct cookie *c;
+ char name[1024], value[4096];
+ const char *cur = cookie, *semi, *end;
+ time_t max_age = 0, expires = 0;
+ bool had_max_age = false, had_expires = false;
+ url_func_result res;
+
+ assert(url && cookie);
+
+ c = calloc(1, sizeof(struct cookie));
+ if (!c)
+ return NULL;
+
+ end = cur + strlen(cur);
+
+ /* Find semicolon */
+ semi = strchr(cur, ';');
+ if (!semi)
+ semi = end;
+
+ /* process name-value pairs */
+ do {
+ char *equals = strchr(cur, '=');
+ int vlen;
+
+ name[0] = value[0] = '\0';
+
+ if (equals && equals < semi) {
+ char *n, *v;
+ /* name = value */
+ if (sscanf(cur, "%1023[^=]=%4095[^;]",
+ name, value) != 2)
+ break;
+
+ /* Strip whitespace from start of name */
+ for (n = name; *n; n++) {
+ if (*n != ' ' && *n != '\t')
+ break;
+ }
+
+ /* Strip whitespace from end of name */
+ for (vlen = strlen(name); vlen; vlen--) {
+ if (name[vlen] == ' ' || name[vlen] == '\t')
+ name[vlen] = '\0';
+ else
+ break;
+ }
+
+ /* Strip whitespace from start of value */
+ for (v = value; *v; v++) {
+ if (*v != ' ' && *v != '\t')
+ break;
+ }
+ /* Strip quote from start of value */
+ if (*v == '"')
+ v++;
+
+ /* Strip whitespace from end of value */
+ for (vlen = strlen(value); vlen; vlen--) {
+ if (value[vlen] == ' ' ||
+ value[vlen] == '\t')
+ value[vlen] = '\0';
+ else
+ break;
+ }
+ /* Strip quote from end of value */
+ if (value[vlen] == '"')
+ value[vlen] = '\0';
+
+ if (!c->comment &&
+ strcasecmp(n, "Comment") == 0) {
+ c->comment = strdup(v);
+ if (!c->comment)
+ break;
+ } else if (!c->domain &&
+ strcasecmp(n, "Domain") == 0) {
+ if (v[0] == '.') {
+ /* Domain must start with a dot */
+ c->domain_from_set = true;
+ c->domain = strdup(v);
+ if (!c->domain)
+ break;
+ }
+ } else if (strcasecmp(n, "Max-Age") == 0) {
+ int temp = atoi(v);
+ had_max_age = true;
+ if (temp == 0)
+ /* Special case - 0 means delete */
+ max_age = 0;
+ else
+ max_age = time(NULL) + temp;
+ } else if (!c->path &&
+ strcasecmp(n, "Path") == 0) {
+ c->path_from_set = true;
+ c->path = strdup(v);
+ if (!c->path)
+ break;
+ } else if (strcasecmp(n, "Version") == 0) {
+ c->version = atoi(v);
+ } else if (strcasecmp(n, "Expires") == 0) {
+ had_expires = true;
+ expires = curl_getdate(v, NULL);
+ } else if (!c->name) {
+ c->name = strdup(n);
+ c->value = strdup(v);
+ if (!c->name || !c->value)
+ break;
+ }
+ } else {
+ char *n;
+
+ /* name */
+ if (sscanf(cur, "%1023[^;] ", name) != 1)
+ break;
+
+ /* Strip whitespace from start of name */
+ for (n = name; *n; n++) {
+ if (*n != ' ' && *n != '\t')
+ break;
+ }
+
+ /* Strip whitespace from end of name */
+ for (vlen = strlen(name); vlen; vlen--) {
+ if (name[vlen] == ' ' || name[vlen] == '\t')
+ name[vlen] = '\0';
+ else
+ break;
+ }
+
+ if (strcasecmp(n, "Secure") == 0)
+ c->secure = true;
+ }
+
+ cur = semi + 1;
+ if (cur < end) {
+ semi = strchr(cur, ';');
+ if (!semi)
+ semi = end;
+ }
+ } while(semi && cur < end);
+
+ if (cur < end) {
+ /* parsing failed */
+ urldb_free_cookie(c);
+ return NULL;
+ }
+
+ /* Now fix-up default values */
+ if (!c->domain) {
+ res = url_host(url, &c->domain);
+ if (res != URL_FUNC_OK) {
+ urldb_free_cookie(c);
+ return NULL;
+ }
+ }
+
+ if (!c->path) {
+ res = url_path(url, &c->path);
+ if (res != URL_FUNC_OK) {
+ urldb_free_cookie(c);
+ return NULL;
+ }
+ }
+
+ if (had_max_age && had_expires) {
+ /* Max age takes precedence iff version 1 or later */
+ c->expires =
+ c->version == COOKIE_NETSCAPE ? expires : max_age;
+ } else if (had_max_age) {
+ c->expires = max_age;
+ } else if (had_expires) {
+ c->expires = expires;
+ } else
+ c->expires = 1;
+
+ return c;
+}
+
+/**
+ * Insert a cookie into the database
+ *
+ * \param c The cookie to insert
+ * \param scheme URL scheme associated with cookie path
+ * \param url URL (sans fragment) associated with cookie
+ * \return true on success, false on memory exhaustion (c will be freed)
+ */
+bool urldb_insert_cookie(struct cookie *c, const char *scheme,
+ const char *url)
+{
+ struct cookie *d;
+ const struct host_part *h;
+ struct path_data *p;
+
+ assert(c && scheme && url);
+
+ if (c->domain[0] == '.') {
+ h = urldb_search_find(
+ search_trees[tolower(c->domain[1]) - 'a' + ST_DN],
+ c->domain + 1);
+ if (!h) {
+ h = urldb_add_host(c->domain + 1);
+ if (!h) {
+ urldb_free_cookie(c);
+ return false;
+ }
+ }
+
+ p = &h->paths;
+ } else {
+ if (c->domain[0] >= '0' && c->domain[0] <= '9')
+ h = urldb_search_find(search_trees[ST_IP], c->domain);
+ else
+ h = urldb_search_find(search_trees[
+ tolower(c->domain[0]) - 'a' + ST_DN],
+ c->domain);
+
+ if (!h) {
+ h = urldb_add_host(c->domain);
+ if (!h) {
+ urldb_free_cookie(c);
+ return false;
+ }
+ }
+
+ /* find path */
+ p = urldb_add_path(scheme, 0, h,
+ c->path, NULL, url);
+ if (!p) {
+ urldb_free_cookie(c);
+ return false;
+ }
+ }
+
+ /* add cookie */
+ for (d = p->cookies; d; d = d->next) {
+ if (!strcmp(d->domain, c->domain) &&
+ !strcmp(d->path, c->path) &&
+ !strcmp(d->name, c->name))
+ break;
+ }
+
+ if (d) {
+ if (c->expires == 0) {
+ /* remove cookie */
+ if (d->next)
+ d->next->prev = d->prev;
+ if (d->prev)
+ d->prev->next = d->next;
+ else
+ p->cookies = d->next;
+ urldb_free_cookie(d);
+ urldb_free_cookie(c);
+ } else {
+ /* replace d with c */
+ c->prev = d->prev;
+ c->next = d->next;
+ if (c->next)
+ c->next->prev = c;
+ if (c->prev)
+ c->prev->next = c;
+ else
+ p->cookies = c;
+ urldb_free_cookie(d);
+// LOG(("%p: %s=%s", c, c->name, c->value));
+ }
+ } else {
+ c->prev = NULL;
+ c->next = p->cookies;
+ if (p->cookies)
+ p->cookies->prev = c;
+ p->cookies = c;
+// LOG(("%p: %s=%s", c, c->name, c->value));
+ }
+
+ return true;
+}
+
+/**
+ * Free a cookie
+ *
+ * \param c The cookie to free
+ */
+void urldb_free_cookie(struct cookie *c)
+{
+ assert(c);
+
+ free(c->comment);
+ free(c->domain);
+ free(c->path);
+ free(c->name);
+ free(c->value);
+ free(c);
+}
+
+/**
+ * Concatenate a cookie into the provided buffer
+ *
+ * \param c Cookie to concatenate
+ * \param used Pointer to amount of buffer used (updated)
+ * \param alloc Pointer to allocated size of buffer (updated)
+ * \param buf Pointer to Pointer to buffer (updated)
+ * \return true on success, false on memory exhaustion
+ */
+bool urldb_concat_cookie(struct cookie *c, int *used, int *alloc, char **buf)
+{
+ int clen;
+
+ assert(c && used && alloc && buf && *buf);
+
+ clen = 2 + strlen(c->name) + 1 + strlen(c->value) +
+ (c->path_from_set ?
+ 8 + strlen(c->path) : 0) +
+ (c->domain_from_set ?
+ 10 + strlen(c->domain) : 0);
+
+ if (*used + clen >= *alloc) {
+ char *temp = realloc(*buf, *alloc + 4096);
+ if (!temp) {
+ return false;
+ }
+ *buf = temp;
+ *alloc += 4096;
+ }
+
+ /** \todo Quote value strings iff version > 0 */
+ sprintf(*buf + *used - 1, "; %s=%s%s%s%s%s",
+ c->name, c->value,
+ (c->path_from_set ? "; $Path=" : "" ),
+ (c->path_from_set ? c->path : "" ),
+// (c->path_from_set ? "\"" : ""),
+ (c->domain_from_set ? "; $Domain=" : ""),
+ (c->domain_from_set ? c->domain : "")
+// ,(c->domain_from_set ? "\"" : "")
+ );
+ *used += clen;
+
+ return true;
+}
+
+/**
+ * Load a cookie file into the database
+ *
+ * \param filename File to load
+ */
+void urldb_load_cookies(const char *filename)
+{
+ FILE *fp;
+ char s[16*1024];
+ int file_version = 0;
+
+ assert(filename);
+
+ fp = fopen(filename, "r");
+ if (!fp)
+ return;
+
+#define FIND_WS { \
+ for (; *p && !isspace(*p) && !iscntrl(*p); p++) \
+ ; /* do nothing */ \
+ if (p >= end) { \
+ LOG(("Overran input")); \
+ continue; \
+ } \
+ *p++ = '\0'; \
+}
+
+#define SKIP_WS { \
+ for (; *p && isspace(*p); p++) \
+ ; /* do nothing */ \
+ if (p >= end) { \
+ LOG(("Overran input")); \
+ continue; \
+ } \
+}
+
+ while (fgets(s, sizeof s, fp)) {
+ char *p = s, *end = 0,
+ *domain, *path, *name, *value, *scheme, *url,
+ *comment;
+ int version, domain_specified, path_specified,
+ secure, no_destroy;
+ time_t expires, last_used;
+
+ if(s[0] == 0 || s[0] == '#')
+ /* Skip blank lines or comments */
+ continue;
+
+ s[strlen(s) - 1] = '\0'; /* lose terminating newline */
+ end = s + strlen(s);
+
+ /* Look for file version first
+ * (all input is ignored until this is read)
+ */
+ if (strncasecmp(s, "Version:", 8) == 0) {
+ FIND_WS; SKIP_WS; file_version = atoi(p);
+
+ if (file_version != COOKIE_FILE_VERSION) {
+ LOG(("Unknown Cookie file version"));
+ break;
+ }
+
+ continue;
+ } else if (file_version == 0) {
+ /* Haven't yet seen version; skip this input */
+ continue;
+ }
+
+ /* One cookie/line */
+
+ /* Parse input */
+ FIND_WS; version = atoi(s);
+ SKIP_WS; domain = p; FIND_WS;
+ SKIP_WS; domain_specified = atoi(p); FIND_WS;
+ SKIP_WS; path = p; FIND_WS;
+ SKIP_WS; path_specified = atoi(p); FIND_WS;
+ SKIP_WS; secure = atoi(p); FIND_WS;
+ SKIP_WS; expires = (time_t)atoi(p); FIND_WS;
+ SKIP_WS; last_used = (time_t)atoi(p); FIND_WS;
+ SKIP_WS; no_destroy = atoi(p); FIND_WS;
+ SKIP_WS; name = p; FIND_WS;
+ SKIP_WS; value = p; FIND_WS;
+ SKIP_WS; scheme = p; FIND_WS;
+ SKIP_WS; url = p; FIND_WS;
+
+ /* Comment may have no content, so don't
+ * use macros as they'll break */
+ for (; *p && isspace(*p); p++)
+ ; /* do nothing */
+ comment = p;
+
+ assert(p <= end);
+
+ /* Now create cookie */
+ struct cookie *c = malloc(sizeof(struct cookie));
+ if (!c)
+ break;
+
+ c->name = strdup(name);
+ c->value = strdup(value);
+ c->comment = strdup(comment);
+ c->domain_from_set = domain_specified;
+ c->domain = strdup(domain);
+ c->path_from_set = path_specified;
+ c->path = strdup(path);
+ c->expires = expires;
+ c->last_used = last_used;
+ c->secure = secure;
+ c->version = version;
+ c->no_destroy = no_destroy;
+
+ if (!(c->name && c->value && c->comment &&
+ c->domain && c->path)) {
+ urldb_free_cookie(c);
+ break;
+ }
+
+ /* And insert it into database */
+ if (!urldb_insert_cookie(c, scheme, url)) {
+ /* Cookie freed for us */
+ break;
+ }
+ }
+
+#undef SKIP_WS
+#undef FIND_WS
+
+ fclose(fp);
+}
+
+/**
+ * Save persistent cookies to file
+ *
+ * \param filename Path to save to
+ */
+void urldb_save_cookies(const char *filename)
+{
+ FILE *fp;
+
+ assert(filename);
+
+ fp = fopen(filename, "w");
+ if (!fp)
+ return;
+
+ fprintf(fp, "# >%s\n", filename);
+ fprintf(fp, "# NetSurf cookies file.\n"
+ "#\n"
+ "# Lines starting with a '#' are comments, "
+ "blank lines are ignored.\n"
+ "#\n"
+ "# All lines prior to \"Version: %d\" are discarded.\n"
+ "#\n"
+ "# Version\tDomain\tDomain from Set-Cookie\tPath\t"
+ "Path from Set-Cookie\tSecure\tExpires\tLast used\t"
+ "No destroy\tName\tValue\tScheme\tURL\tComment\n",
+ COOKIE_FILE_VERSION);
+ fprintf(fp, "Version: %d\n", COOKIE_FILE_VERSION);
+
+
+ urldb_save_cookie_hosts(fp, &db_root);
+
+ fclose(fp);
+}
+
+/**
+ * Save a host subtree's cookies
+ *
+ * \param fp File pointer to write to
+ * \param parent Parent host
+ */
+void urldb_save_cookie_hosts(FILE *fp, struct host_part *parent)
+{
+ assert(fp && parent);
+
+ urldb_save_cookie_paths(fp, &parent->paths);
+
+ for (struct host_part *h = parent->children; h; h = h->next)
+ urldb_save_cookie_hosts(fp, h);
+}
+
+/**
+ * Save a path subtree's cookies
+ *
+ * \param fp File pointer to write to
+ * \param parent Parent path
+ */
+void urldb_save_cookie_paths(FILE *fp, struct path_data *parent)
+{
+ time_t now = time(NULL);
+
+ assert(fp && parent);
+
+ if (parent->cookies) {
+ for (struct cookie *c = parent->cookies; c; c = c->next) {
+
+ if (c->expires < now)
+ /* Skip expired cookies */
+ continue;
+
+ fprintf(fp, "%d\t%s\t%d\t%s\t%d\t%d\t%d\t%d\t%d\t"
+ "%s\t%s\t%s\t%s\t%s\n",
+ c->version, c->domain,
+ c->domain_from_set, c->path,
+ c->path_from_set, c->secure,
+ (int)c->expires, (int)c->last_used,
+ c->no_destroy, c->name, c->value,
+ parent->scheme ? parent->scheme
+ : "unused",
+ parent->url ? parent->url : "unused",
+ c->comment ? c->comment : "");
+ }
+ }
+
+ for (struct path_data *p = parent->children; p; p = p->next)
+ urldb_save_cookie_paths(fp, p);
+}
+
+
#ifdef TEST
int main(void)
{
Modified: trunk/netsurf/content/urldb.h
URL: http://svn.semichrome.net/trunk/netsurf/content/urldb.h?rev=2632&r1=2631&...
==============================================================================
--- trunk/netsurf/content/urldb.h (original)
+++ trunk/netsurf/content/urldb.h Mon Jun 19 22:49:25 2006
@@ -24,6 +24,9 @@
};
struct bitmap;
+
+/* Initialisation */
+void urldb_init(void);
/* Persistence support */
void urldb_load(const char *filename);
@@ -66,4 +69,10 @@
/* Debug */
void urldb_dump(void);
+/* Cookies */
+bool urldb_set_cookie(const char *header, const char *url);
+char *urldb_get_cookie(const char *url, const char *referer);
+void urldb_load_cookies(const char *filename);
+void urldb_save_cookies(const char *filename);
+
#endif
Modified: trunk/netsurf/desktop/netsurf.c
URL: http://svn.semichrome.net/trunk/netsurf/desktop/netsurf.c?rev=2632&r1=263...
==============================================================================
--- trunk/netsurf/desktop/netsurf.c (original)
+++ trunk/netsurf/desktop/netsurf.c Mon Jun 19 22:49:25 2006
@@ -15,6 +15,7 @@
#include "netsurf/utils/config.h"
#include "netsurf/content/fetch.h"
#include "netsurf/content/fetchcache.h"
+#include "netsurf/content/urldb.h"
#include "netsurf/desktop/netsurf.h"
#include "netsurf/desktop/browser.h"
#include "netsurf/desktop/gui.h"
@@ -77,6 +78,7 @@
lib_init();
url_init();
+ urldb_init();
gui_init(argc, argv);
setlocale(LC_ALL, "");
fetch_init();
Modified: trunk/netsurf/riscos/gui.c
URL: http://svn.semichrome.net/trunk/netsurf/riscos/gui.c?rev=2632&r1=2631&r2=...
==============================================================================
--- trunk/netsurf/riscos/gui.c (original)
+++ trunk/netsurf/riscos/gui.c Mon Jun 19 22:49:25 2006
@@ -367,6 +367,7 @@
bitmap_initialise_memory();
urldb_load(option_url_path);
+ urldb_load_cookies(option_cookie_file);
nsdir_temp = getenv("NetSurf$Dir");
if (!nsdir_temp)
@@ -724,6 +725,7 @@
void gui_quit(void)
{
bitmap_quit();
+ urldb_save_cookies(option_cookie_jar);
urldb_save(option_url_save);
ro_gui_window_quit();
ro_gui_global_history_save();
Modified: trunk/netsurf/utils/url.c
URL: http://svn.semichrome.net/trunk/netsurf/utils/url.c?rev=2632&r1=2631&r2=2...
==============================================================================
--- trunk/netsurf/utils/url.c (original)
+++ trunk/netsurf/utils/url.c Mon Jun 19 22:49:25 2006
@@ -677,6 +677,58 @@
/**
+ * Extract path segment from an URL
+ *
+ * \param url an absolute URL
+ * \param result pointer to pointer to buffer to hold result
+ * \return URL_FUNC_OK on success
+ */
+
+url_func_result url_path(const char *url, char **result)
+{
+ int m, path_len = 0;
+ regmatch_t match[10];
+
+ (*result) = 0;
+
+ m = regexec(&url_re, url, 10, match, 0);
+ if (m) {
+ LOG(("url '%s' failed to match regex", url));
+ return URL_FUNC_FAILED;
+ }
+ if (match[URL_RE_SCHEME].rm_so == -1 ||
+ match[URL_RE_AUTHORITY].rm_so == -1)
+ return URL_FUNC_FAILED;
+
+ if (match[URL_RE_PATH].rm_so != -1)
+ path_len = match[URL_RE_PATH].rm_eo -
+ match[URL_RE_PATH].rm_so;
+
+ (*result) = malloc((path_len ? path_len : 1) + 1);
+ if (!(*result)) {
+ LOG(("malloc failed"));
+ return URL_FUNC_NOMEM;
+ }
+
+ m = 0;
+ if (path_len > 1) {
+ strncpy((*result), url + match[URL_RE_PATH].rm_so,
+ path_len);
+ for (; path_len != 0 && (*result)[m + path_len - 1] != '/';
+ path_len--)
+ /* do nothing */;
+ m += path_len;
+ }
+ else
+ (*result)[m++] = '/';
+
+ (*result)[m] = '\0';
+
+ return URL_FUNC_OK;
+}
+
+
+/**
* Attempt to find a nice filename for a URL.
*
* \param url an absolute URL
Modified: trunk/netsurf/utils/url.h
URL: http://svn.semichrome.net/trunk/netsurf/utils/url.h?rev=2632&r1=2631&r2=2...
==============================================================================
--- trunk/netsurf/utils/url.h (original)
+++ trunk/netsurf/utils/url.h Mon Jun 19 22:49:25 2006
@@ -30,6 +30,7 @@
url_func_result url_canonical_root(const char *url, char **result);
url_func_result url_strip_lqf(const char *url, char **result);
url_func_result url_plq(const char *url, char **result);
+url_func_result url_path(const char *url, char **result);
char *path_to_url(const char *path);
char *url_to_path(const char *url);
16 years, 7 months