summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--amiga/Makefile.target2
-rw-r--r--amiga/file.c32
-rwxr-xr-xamiga/save_complete.c116
-rwxr-xr-xamiga/save_complete.h32
-rw-r--r--atari/Makefile.target2
-rwxr-xr-xatari/global_evnt.c2
-rw-r--r--atari/save.c88
-rw-r--r--beos/Makefile.target6
-rw-r--r--beos/save_complete.cpp85
-rw-r--r--cocoa/Makefile.target1
-rw-r--r--cocoa/save.m37
-rw-r--r--desktop/save_complete.c1470
-rw-r--r--desktop/save_complete.h29
-rw-r--r--framebuffer/Makefile.target2
-rw-r--r--framebuffer/save.c48
-rw-r--r--gtk/Makefile.target2
-rw-r--r--gtk/gui.c3
-rw-r--r--gtk/save.c81
-rw-r--r--gtk/scaffolding.c3
-rw-r--r--monkey/utils.c15
-rw-r--r--riscos/save.c67
-rw-r--r--windows/gui.c22
22 files changed, 943 insertions, 1202 deletions
diff --git a/amiga/Makefile.target b/amiga/Makefile.target
index c4db9a373..5b11ec018 100644
--- a/amiga/Makefile.target
+++ b/amiga/Makefile.target
@@ -75,7 +75,7 @@ EXETARGET := NetSurf
S_AMIGA := gui.c tree.c history.c hotlist.c schedule.c file.c \
thumbnail.c misc.c bitmap.c font.c filetype.c utf8.c login.c \
plotters.c object.c menu.c save_pdf.c arexx.c version.c \
- cookies.c context_menu.c clipboard.c save_complete.c \
+ cookies.c context_menu.c clipboard.c \
launch.c search.c history_local.c download.c iff_dr2d.c \
sslcert.c gui_options.c print.c theme.c drag.c icon.c system_colour.c \
datatypes.c dt_picture.c dt_anim.c dt_sound.c plugin_hack.c \
diff --git a/amiga/file.c b/amiga/file.c
index c2e4f13ad..8157180ec 100644
--- a/amiga/file.c
+++ b/amiga/file.c
@@ -99,6 +99,36 @@ void ami_file_open(struct gui_window_2 *gwin)
}
}
+static void ami_file_set_type(const char *path, lwc_string *mime_type)
+{
+ content_type type = content_factory_type_from_mime_type(mime_type);
+ const char *default_type;
+
+ switch(type)
+ {
+ case CONTENT_HTML:
+ default_type = "html";
+ break;
+ case CONTENT_CSS:
+ default_type = "css";
+ break;
+ default:
+ default_type = NULL;
+ break;
+ }
+
+ if (default_type != NULL) {
+ struct DiskObject *dobj = NULL;
+
+ dobj = GetIconTags(NULL,ICONGETA_GetDefaultName,default_type,
+ ICONGETA_GetDefaultType,WBPROJECT,
+ TAG_DONE);
+
+ PutIconTags(path, dobj,
+ ICONPUTA_NotifyWorkbench, TRUE, TAG_DONE);
+ }
+}
+
void ami_file_save(int type, char *fname, struct Window *win,
struct hlcache_handle *object, struct hlcache_handle *favicon,
struct selection *sel)
@@ -134,7 +164,7 @@ void ami_file_save(int type, char *fname, struct Window *win,
if(lock = CreateDir(fname))
{
UnLock(lock);
- save_complete(object, fname);
+ save_complete(object, fname, ami_file_set_type);
amiga_icon_superimpose_favicon(fname, favicon, NULL);
}
break;
diff --git a/amiga/save_complete.c b/amiga/save_complete.c
deleted file mode 100755
index dad952c0b..000000000
--- a/amiga/save_complete.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
- * Copyright 2004-2007 James Bursa <bursa@users.sourceforge.net>
- * Copyright 2008 Chris Young <chris@unsatisfactorysoftware.co.uk>
- * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.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/>.
- */
-
-#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
-#include <libxml/HTMLtree.h>
-#include "desktop/save_complete.h"
-#include "utils/utils.h"
-#include <proto/icon.h>
-#include <workbench/icon.h>
-#include "content/content.h"
-
-/**
-* conducts the filesystem save appropriate to the gui
-* \param path save path
-* \param filename name of file to save
-* \param len data length
-* \param sourcedata pointer to data to save, NULL when all data in c
-* \param type content type
-* \return true for success
-*/
-
-bool save_complete_gui_save(const char *path, const char *filename, size_t len,
- const char *sourcedata, lwc_string *mime_type)
-{
- content_type type = content_factory_type_from_mime_type(mime_type);
- int res;
- int namelen;
- char deftype[5];
- struct DiskObject *dobj = NULL;
- namelen = strlen(path) + strlen(filename) + 2;
- char *fullpath = malloc(namelen);
- if (!fullpath) {
- warn_user("NoMemory", 0);
- return false;
- }
- snprintf(fullpath, namelen, "%s/%s", path, filename);
- FILE *f = fopen(fullpath, "w");
- if (f == NULL)
- return false;
- res = fwrite(sourcedata, len, 1, f);
- fclose(f);
- switch(type)
- {
- case CONTENT_HTML:
- strcpy(deftype,"html");
- break;
- case CONTENT_CSS:
- strcpy(deftype,"css");
- break;
- default:
- free(fullpath);
- return true;
- break;
- }
-
- dobj = GetIconTags(NULL,ICONGETA_GetDefaultName,deftype,
- ICONGETA_GetDefaultType,WBPROJECT,
- TAG_DONE);
-
- PutIconTags(fullpath, dobj,
- ICONPUTA_NotifyWorkbench, TRUE, TAG_DONE);
- free(fullpath);
- if (res != 1)
- return false;
- return true;
-}
-
-/**
-* wrapper for lib function htmlSaveFileFormat; front sets path from
-* path + filename in a filesystem-specific way
-*/
-
-int save_complete_htmlSaveFileFormat(const char *path, const char *filename,
- xmlDocPtr cur, const char *encoding, int format)
-{
- int ret;
- int len = strlen(path) + strlen(filename) + 2;
- struct DiskObject *dobj = NULL;
- char *fullpath = malloc(len);
- if (!fullpath){
- warn_user("NoMemory", 0);
- return -1;
- }
- snprintf(fullpath, len, "%s/%s", path, filename);
- ret = htmlSaveFileFormat(fullpath, cur, encoding, format);
- dobj = GetIconTags(NULL,ICONGETA_GetDefaultName, "html",
- ICONGETA_GetDefaultType,WBPROJECT,
- TAG_DONE);
-
- PutIconTags(fullpath, dobj,
- ICONPUTA_NotifyWorkbench, TRUE, TAG_DONE);
-
- free(fullpath);
- return ret;
-}
-
diff --git a/amiga/save_complete.h b/amiga/save_complete.h
deleted file mode 100755
index cb6c26643..000000000
--- a/amiga/save_complete.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
- * Copyright 2008 Chris Young <chris@unsatisfactorysoftware.co.uk>
- *
- * 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
- * Save HTML document with dependencies (interface).
- */
-
-#ifndef AMIGA_SAVE_COMPLETE_H
-#define AMIGA_SAVE_COMPLETE_H
-
-#include "content/content.h"
-
-void save_complete_init(void);
-bool save_complete(hlcache_handle *c, const char *path);
-
-#endif
diff --git a/atari/Makefile.target b/atari/Makefile.target
index bccb15c48..844abfe31 100644
--- a/atari/Makefile.target
+++ b/atari/Makefile.target
@@ -82,7 +82,7 @@ S_ATARI := gui.c findfile.c filetype.c misc.c bitmap.c schedule.c \
redrawslots.c encoding.c \
browser_win.c toolbar.c statusbar.c browser.c \
global_evnt.c osspec.c dragdrop.c system_colour.c \
- ctxmenu.c save.c settings.c
+ ctxmenu.c settings.c
S_ATARI := $(addprefix atari/,$(S_ATARI))
# This is the final source build list
diff --git a/atari/global_evnt.c b/atari/global_evnt.c
index 0c9dfdc1e..3b15af877 100755
--- a/atari/global_evnt.c
+++ b/atari/global_evnt.c
@@ -176,7 +176,7 @@ static void __CDECL menu_save_page(WINDOW *win, int item, int title, void *data)
} while( !is_folder && path != NULL );
if( path != NULL ){
- save_complete( input_window->browser->bw->current_content, path );
+ save_complete( input_window->browser->bw->current_content, path, NULL );
}
}
diff --git a/atari/save.c b/atari/save.c
deleted file mode 100644
index 83e4e410c..000000000
--- a/atari/save.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.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/>.
- */
-
-#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
-#include <libxml/HTMLtree.h>
-
-#include "content/content.h"
-#include "desktop/save_complete.h"
-#include "utils/utils.h"
-
-/*
- This code was simply taken from GTK frontend. It requires adjustment
- within the core or frontend to work well.
- ( mime type detection fails on load of the saved webpage, that's because
- no file extension is saved. )
-*/
-
-/**
-* conducts the filesystem save appropriate to the gui
-* \param path save path
-* \param filename name of file to save
-* \param len data length
-* \param sourcedata pointer to data to save
-* \param type content type
-* \return true for success
-*/
-
-bool save_complete_gui_save(const char *path, const char *filename,
- size_t len, const char *sourcedata, lwc_string *mime_type)
-{
- int res;
- int namelen;
- namelen = strlen(path) + strlen(filename) + 2; /* '/', '\0' */
- char *fullpath = malloc(namelen);
- if (!fullpath) {
- warn_user("NoMemory", 0);
- return false;
- }
- snprintf(fullpath, namelen, "%s/%s", path, filename);
- FILE *f;
- f = fopen(fullpath, "wb");
- free(fullpath);
- if (f == NULL)
- return false;
- res = fwrite(sourcedata, len, 1, f);
- fclose(f);
- if (res != 1)
- return false;
- return true;
-}
-
-/**
-* wrapper for lib function htmlSaveFileFormat; front sets path from path
-* + filename in a filesystem-specific way
-*/
-
-int save_complete_htmlSaveFileFormat(const char *path, const char *filename,
- xmlDocPtr cur, const char *encoding, int format)
-{
- int ret;
- int len = strlen(path) + strlen(filename) + 2;
- char *fullpath = malloc(len);
- if (fullpath == NULL) {
- warn_user("NoMemory", 0);
- return -1;
- }
- snprintf(fullpath, len, "%s/%s", path, filename);
- ret = htmlSaveFileFormat(fullpath, cur, encoding, format);
- free(fullpath);
- return ret;
-}
diff --git a/beos/Makefile.target b/beos/Makefile.target
index be58be4a7..b1d1eaab5 100644
--- a/beos/Makefile.target
+++ b/beos/Makefile.target
@@ -85,8 +85,8 @@
# S_BEOS are sources purely for the BeOS build
S_BEOS := about.cpp bitmap.cpp fetch_rsrc.cpp \
- filetype.cpp font.cpp gui.cpp login.cpp \
- gui_options.cpp plotters.cpp save_complete.cpp \
+ filetype.cpp font.cpp gui.cpp login.cpp \
+ gui_options.cpp plotters.cpp \
scaffolding.cpp search.cpp schedule.cpp \
thumbnail.cpp treeview.cpp throbber.cpp \
window.cpp system_colour.cpp
@@ -134,4 +134,4 @@ install-beos:
# Package target
# ----------------------------------------------------------------------------
-package-beos: \ No newline at end of file
+package-beos:
diff --git a/beos/save_complete.cpp b/beos/save_complete.cpp
deleted file mode 100644
index 19306dc21..000000000
--- a/beos/save_complete.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2008 Fran├žois Revol <mmu_man@users.sourceforge.net>
- * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.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/>.
- */
-
-#define __STDBOOL_H__ 1
-#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
-#include <libxml/HTMLtree.h>
-extern "C" {
-#include "content/content.h"
-#include "desktop/save_complete.h"
-#include "utils/utils.h"
-}
-
-/**
-* conducts the filesystem save appropriate to the gui
-* \param path save path
-* \param filename name of file to save
-* \param len data length
-* \param sourcedata pointer to data to save
-* \param type content type
-* \return true for success
-*/
-
-bool save_complete_gui_save(const char *path, const char *filename,
- size_t len, const char *sourcedata, lwc_string *mime_type)
-{
- int res;
- int namelen;
- namelen = strlen(path) + strlen(filename) + 2; /* '/', '\0' */
- char *fullpath = (char *)malloc(namelen);
- if (!fullpath) {
- warn_user("NoMemory", 0);
- return false;
- }
- snprintf(fullpath, namelen, "%s/%s", path, filename);
- FILE *f;
- f = fopen(fullpath, "wb");
- free(fullpath);
- if (f == NULL)
- return false;
- res = fwrite(sourcedata, len, 1, f);
- fclose(f);
- if (res != 1)
- return false;
- return true;
-}
-
-/**
-* wrapper for lib function htmlSaveFileFormat; front sets path from path
-* + filename in a filesystem-specific way
-*/
-
-int save_complete_htmlSaveFileFormat(const char *path, const char *filename,
- xmlDocPtr cur, const char *encoding, int format)
-{
- int ret;
- int len = strlen(path) + strlen(filename) + 2;
- char *fullpath = (char *)malloc(len);
- if (fullpath == NULL) {
- warn_user("NoMemory", 0);
- return -1;
- }
- snprintf(fullpath, len, "%s/%s", path, filename);
- ret = htmlSaveFileFormat(fullpath, cur, encoding, format);
- free(fullpath);
- return ret;
-}
-
diff --git a/cocoa/Makefile.target b/cocoa/Makefile.target
index fa1f7a095..fd78e5e11 100644
--- a/cocoa/Makefile.target
+++ b/cocoa/Makefile.target
@@ -95,7 +95,6 @@ S_COCOA := \
font.m \
gui.m \
plotter.m \
- save.m \
schedule.m \
selection.m \
thumbnail.m \
diff --git a/cocoa/save.m b/cocoa/save.m
deleted file mode 100644
index 9ee2f4cd8..000000000
--- a/cocoa/save.m
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2011 Sven Weidauer <sven.weidauer@gmail.com>
- *
- * 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/>.
- */
-
-#import <Cocoa/Cocoa.h>
-
-#import "desktop/save_complete.h"
-
-#define UNIMPL() NSLog( @"Function '%s' unimplemented", __func__ )
-
-bool save_complete_gui_save(const char *path, const char *filename,
- size_t len, const char *sourcedata, lwc_string *mime_type)
-{
- UNIMPL();
- return false;
-}
-
-int save_complete_htmlSaveFileFormat(const char *path, const char *filename,
- xmlDocPtr cur, const char *encoding, int format)
-{
- UNIMPL();
- return 0;
-}
diff --git a/desktop/save_complete.c b/desktop/save_complete.c
index 0ac64b515..42da86752 100644
--- a/desktop/save_complete.c
+++ b/desktop/save_complete.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2004 John M Bell <jmb202@ecs.soton.ac.uk>
+ * Copyright 2012 John-Mark Bell <jmb@netsurf-browser.org>
* Copyright 2004-2007 James Bursa <bursa@users.sourceforge.net>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
@@ -30,548 +30,570 @@
#include <string.h>
#include <sys/types.h>
#include <regex.h>
+
#include <dom/dom.h>
-#include "utils/config.h"
+
#include "content/content.h"
#include "content/hlcache.h"
#include "css/css.h"
-#include "render/box.h"
#include "desktop/save_complete.h"
+#include "render/box.h"
+#include "render/html.h"
#include "utils/log.h"
-#include "utils/url.h"
+#include "utils/nsurl.h"
#include "utils/utils.h"
-#include "render/html.h"
regex_t save_complete_import_re;
/** An entry in save_complete_list. */
-struct save_complete_entry {
+typedef struct save_complete_entry {
hlcache_handle *content;
struct save_complete_entry *next; /**< Next entry in list */
-};
-
-static bool save_complete_html(hlcache_handle *c, const char *path,
- bool index, struct save_complete_entry **list);
-static bool save_imported_sheets(struct nscss_import *imports, uint32_t count,
- const char *path, struct save_complete_entry **list);
-static char * rewrite_stylesheet_urls(const char *source, unsigned int size,
- int *osize, const char *base,
- struct save_complete_entry *list);
-static bool rewrite_document_urls(xmlDoc *doc, const char *base,
- struct save_complete_entry *list);
-static bool rewrite_urls(xmlNode *n, const char *base,
- struct save_complete_entry *list);
-static bool rewrite_url(xmlNode *n, const char *attr, const char *base,
- struct save_complete_entry *list);
-static bool save_complete_list_add(hlcache_handle *content,
- struct save_complete_entry **list);
-static hlcache_handle * save_complete_list_find(const char *url,
- struct save_complete_entry *list);
-static bool save_complete_list_check(hlcache_handle *content,
- struct save_complete_entry *list);
-/* static void save_complete_list_dump(void); */
-static bool save_complete_inventory(const char *path,
- struct save_complete_entry *list);
+} save_complete_entry;
-/**
- * Save an HTML page with all dependencies.
- *
- * \param c CONTENT_HTML to save
- * \param path directory to save to (must exist)
- * \return true on success, false on error and error reported
- */
+typedef struct save_complete_ctx {
+ const char *path;
+ save_complete_entry *list;
+ save_complete_set_type_cb set_type;
+
+ nsurl *base;
+ FILE *fp;
+ enum { STATE_NORMAL, STATE_IN_STYLE } iter_state;
+} save_complete_ctx;
+
+typedef enum {
+ EVENT_ENTER,
+ EVENT_LEAVE
+} save_complete_event_type;
-bool save_complete(hlcache_handle *c, const char *path)
+
+static bool save_complete_save_html(save_complete_ctx *ctx, hlcache_handle *c,
+ bool index);
+static bool save_complete_save_imported_sheets(save_complete_ctx *ctx,
+ struct nscss_import *imports, uint32_t import_count);
+
+
+static void save_complete_ctx_initialise(save_complete_ctx *ctx,
+ const char *path, save_complete_set_type_cb set_type)
{
- bool result;
- struct save_complete_entry *list = NULL;
-
- result = save_complete_html(c, path, true, &list);
+ ctx->path = path;
+ ctx->list = NULL;
+ ctx->set_type = set_type;
+}
- if (result)
- result = save_complete_inventory(path, list);
+static void save_complete_ctx_finalise(save_complete_ctx *ctx)
+{
+ save_complete_entry *list = ctx->list;
- /* free save_complete_list */
- while (list) {
- struct save_complete_entry *next = list->next;
+ while (list != NULL) {
+ save_complete_entry *next = list->next;
free(list);
list = next;
}
-
- return result;
}
-
-/**
- * Save an HTML page with all dependencies, recursing through imported pages.
- *
- * \param c CONTENT_HTML to save
- * \param path directory to save to (must exist)
- * \param index true to save as "index"
- * \return true on success, false on error and error reported
- */
-
-bool save_complete_html(hlcache_handle *c, const char *path, bool index,
- struct save_complete_entry **list)
+static bool save_complete_ctx_add_content(save_complete_ctx *ctx,
+ hlcache_handle *content)
{
- struct html_stylesheet *sheets;
- struct content_html_object *object;
- char filename[256];
- unsigned int i, count;
- xmlDocPtr doc = NULL;
- bool res;
+ save_complete_entry *entry;
- if (content_get_type(c) != CONTENT_HTML)
+ entry = malloc(sizeof (*entry));
+ if (entry == NULL)
return false;
- if (save_complete_list_check(c, *list))
- return true;
+ entry->content = content;
+ entry->next = ctx->list;
+ ctx->list = entry;
- /* save stylesheets, ignoring the base and adblocking sheets */
- sheets = html_get_stylesheets(c, &count);
+ return true;
+}
- for (i = STYLESHEET_START; i != count; i++) {
- hlcache_handle *css;
- const char *css_data;
- unsigned long css_size;
- char *source;
- int source_len;
- struct nscss_import *imports;
- uint32_t import_count;
- lwc_string *type;
-
- if (sheets[i].type == HTML_STYLESHEET_INTERNAL) {
- if (save_imported_sheets(
- sheets[i].data.internal->imports,
- sheets[i].data.internal->import_count,
- path, list) == false)
- return false;
- continue;
- }
+static hlcache_handle *save_complete_ctx_find_content(save_complete_ctx *ctx,
+ const nsurl *url)
+{
+ save_complete_entry *entry;
- css = sheets[i].data.external;
+ for (entry = ctx->list; entry != NULL; entry = entry->next)
+ if (nsurl_compare(url,
+ hlcache_handle_get_url(entry->content),
+ NSURL_COMPLETE))
+ return entry->content;
- if (!css)
- continue;
- if (save_complete_list_check(css, *list))
- continue;
+ return NULL;
+}
- if (!save_complete_list_add(css, list)) {
- warn_user("NoMemory", 0);
- return false;
- }
- imports = nscss_get_imports(css, &import_count);
- if (!save_imported_sheets(imports, import_count, path, list))
- return false;
+static bool save_complete_ctx_has_content(save_complete_ctx *ctx,
+ hlcache_handle *content)
+{
+ save_complete_entry *entry;
- snprintf(filename, sizeof filename, "%p", css);
+ for (entry = ctx->list; entry != NULL; entry = entry->next)
+ if (entry->content == content)
+ return true;
- css_data = content_get_source_data(css, &css_size);
+ return false;
+}
- source = rewrite_stylesheet_urls(css_data, css_size,
- &source_len, nsurl_access(hlcache_handle_get_url(css)),
- *list);
- if (!source) {
- warn_user("NoMemory", 0);
- return false;
- }
+static bool save_complete_save_buffer(save_complete_ctx *ctx,
+ const char *leafname, const char *data, size_t data_len,
+ lwc_string *mime_type)
+{
+ FILE *fp;
+ bool error;
+ char fullpath[PATH_MAX];
- type = content_get_mime_type(css);
- if (type == NULL) {
- free(source);
- return false;
- }
+ strncpy(fullpath, ctx->path, sizeof fullpath);
+ error = path_add_part(fullpath, sizeof fullpath, leafname);
+ if (error == false) {
+ warn_user("NoMemory", NULL);
+ return false;
+ }
- res = save_complete_gui_save(path, filename, source_len,
- source, type);
+ fp = fopen(fullpath, "wb");
+ if (fp == NULL) {
+ LOG(("fopen(): errno = %i", errno));
+ warn_user("SaveError", strerror(errno));
+ return false;
+ }
- lwc_string_unref(type);
- free(source);
+ fwrite(data, sizeof(*data), data_len, fp);
- if (res == false)
- return false;
- }
-
- /* save objects */
- object = html_get_objects(c, &count);
+ fclose(fp);
- for (; object != NULL; object = object->next) {
- hlcache_handle *obj = object->content;
- const char *obj_data;
- unsigned long obj_size;
- lwc_string *type;
+ if (ctx->set_type != NULL)
+ ctx->set_type(fullpath, mime_type);
- if (obj == NULL || content_get_type(obj) == CONTENT_NONE)
- continue;
+ return true;
+}
- obj_data = content_get_source_data(obj, &obj_size);
+/**
+ * Rewrite stylesheet \@import rules for save complete.
+ *
+ * \param source stylesheet source
+ * \param size size of source
+ * \param base url of stylesheet
+ * \param osize updated with the size of the result
+ * \return converted source, or NULL on out of memory
+ */
- if (obj_data == NULL)
- continue;
+static char *save_complete_rewrite_stylesheet_urls(save_complete_ctx *ctx,
+ const char *source, unsigned long size, const nsurl *base,
+ unsigned long *osize)
+{
+ char *rewritten;
+ unsigned long offset = 0;
+ unsigned int imports = 0;
+ nserror error;
- if (save_complete_list_check(obj, *list))
- continue;
+ /* count number occurrences of @import to (over)estimate result size */
+ /* can't use strstr because source is not 0-terminated string */
+ for (offset = 0; SLEN("@import") < size &&
+ offset <= size - SLEN("@import"); offset++) {
+ if (source[offset] == '@' &&
+ tolower(source[offset + 1]) == 'i' &&
+ tolower(source[offset + 2]) == 'm' &&
+ tolower(source[offset + 3]) == 'p' &&
+ tolower(source[offset + 4]) == 'o' &&
+ tolower(source[offset + 5]) == 'r' &&
+ tolower(source[offset + 6]) == 't')
+ imports++;
+ }
- if (!save_complete_list_add(obj, list)) {
- warn_user("NoMemory", 0);
- return false;
- }
+ rewritten = malloc(size + imports * 20);
+ if (rewritten == NULL)
+ return NULL;
+ *osize = 0;
- if (content_get_type(obj) == CONTENT_HTML) {
- if (!save_complete_html(obj, path, false, list))
- return false;
- continue;
+ offset = 0;
+ while (offset < size) {
+ const char *import_url = NULL;
+ char *import_url_copy;
+ int import_url_len = 0;
+ nsurl *url = NULL;
+ regmatch_t match[11];
+ int m = regexec(&save_complete_import_re, source + offset,
+ 11, match, 0);
+ if (m)
+ break;
+
+ if (match[2].rm_so != -1) {
+ import_url = source + offset + match[2].rm_so;
+ import_url_len = match[2].rm_eo - match[2].rm_so;
+ } else if (match[4].rm_so != -1) {
+ import_url = source + offset + match[4].rm_so;
+ import_url_len = match[4].rm_eo - match[4].rm_so;
+ } else if (match[6].rm_so != -1) {
+ import_url = source + offset + match[6].rm_so;
+ import_url_len = match[6].rm_eo - match[6].rm_so;
+ } else if (match[8].rm_so != -1) {
+ import_url = source + offset + match[8].rm_so;
+ import_url_len = match[8].rm_eo - match[8].rm_so;
+ } else if (match[10].rm_so != -1) {
+ import_url = source + offset + match[10].rm_so;
+ import_url_len = match[10].rm_eo - match[10].rm_so;
}
+ assert(import_url != NULL);
- snprintf(filename, sizeof filename, "%p", obj);
+ import_url_copy = strndup(import_url, import_url_len);
+ if (import_url_copy == NULL) {
+ free(rewritten);
+ return NULL;
+ }
- type = content_get_mime_type(obj);
- if (type == NULL)
- return false;
+ error = nsurl_join(base, import_url_copy, &url);
+ free(import_url_copy);
+ if (error == NSERROR_NOMEM) {
+ free(rewritten);
+ return NULL;
+ }
- res = save_complete_gui_save(path, filename,
- obj_size, obj_data, type);
+ /* copy data before match */
+ memcpy(rewritten + *osize, source + offset, match[0].rm_so);
+ *osize += match[0].rm_so;
- lwc_string_unref(type);
+ if (url != NULL) {
+ hlcache_handle *content;
+ content = save_complete_ctx_find_content(ctx, url);
+ if (content != NULL) {
+ /* replace import */
+ char buf[64];
+ snprintf(buf, sizeof buf, "@import '%p'",
+ content);
+ memcpy(rewritten + *osize, buf, strlen(buf));
+ *osize += strlen(buf);
+ } else {
+ /* copy import */
+ memcpy(rewritten + *osize,
+ source + offset + match[0].rm_so,
+ match[0].rm_eo - match[0].rm_so);
+ *osize += match[0].rm_eo - match[0].rm_so;
+ }
+ nsurl_unref(url);
+ } else {
+ /* copy import */
+ memcpy(rewritten + *osize,
+ source + offset + match[0].rm_so,
+ match[0].rm_eo - match[0].rm_so);
+ *osize += match[0].rm_eo - match[0].rm_so;
+ }
- if(res == false)
- return false;
+ assert(0 < match[0].rm_eo);
+ offset += match[0].rm_eo;
}
- /* create shiny XML document from the content source */
-
- {
- unsigned long html_size;
- const char *html_source;
- xmlChar *terminated_html_source;
- html_source = content_get_source_data(c, &html_size);
-
- terminated_html_source = malloc(html_size + 1);
- if (terminated_html_source != NULL) {
- memcpy(terminated_html_source, html_source, html_size);
- terminated_html_source[html_size] = '\0';
- doc = htmlParseDoc(terminated_html_source, NULL);
- free(terminated_html_source);
- }
-
+ /* copy rest of source */
+ if (offset < size) {
+ memcpy(rewritten + *osize, source + offset, size - offset);
+ *osize += size - offset;
}
-
- if (doc == NULL) {
+
+ return rewritten;
+}
+
+static bool save_complete_save_stylesheet(save_complete_ctx *ctx,
+ hlcache_handle *css)
+{
+ const char *css_data;
+ unsigned long css_size;
+ char *source;
+ unsigned long source_len;
+ struct nscss_import *imports;
+ uint32_t import_count;
+ lwc_string *type;
+ char filename[32];
+ bool result;
+
+ if (save_complete_ctx_has_content(ctx, css))
+ return true;
+
+ if (save_complete_ctx_add_content(ctx, css) == false) {
warn_user("NoMemory", 0);
return false;
}
- /* rewrite all urls we know about */
- if (!rewrite_document_urls(doc, nsurl_access(html_get_base_url(c)),
- *list)) {
- xmlFreeDoc(doc);
+ imports = nscss_get_imports(css, &import_count);
+ if (save_complete_save_imported_sheets(ctx,
+ imports, import_count) == false)
+ return false;
+
+ css_data = content_get_source_data(css, &css_size);
+ source = save_complete_rewrite_stylesheet_urls(ctx, css_data, css_size,
+ hlcache_handle_get_url(css), &source_len);
+ if (source == NULL) {
warn_user("NoMemory", 0);
return false;
}
- /* save the html file out last of all */
- if (index)
- snprintf(filename, sizeof filename, "index");
- else
- snprintf(filename, sizeof filename, "%p", c);
+ type = content_get_mime_type(css);
+ if (type == NULL) {
+ free(source);
+ return false;
+ }
- errno = 0;
- if (save_complete_htmlSaveFileFormat(path, filename, doc, 0, 0) == -1) {
- if (errno)
- warn_user("SaveError", strerror(errno));
- else
- warn_user("SaveError", "htmlSaveFileFormat failed");
+ snprintf(filename, sizeof filename, "%p", css);
- xmlFreeDoc(doc);
- return false;
- }
+ result = save_complete_save_buffer(ctx, filename,
+ source, source_len, type);
- xmlFreeDoc(doc);
+ lwc_string_unref(type);
+ free(source);
- return true;
+ return result;
}
-
-/**
- * Save stylesheets imported by a CONTENT_CSS.
- *
- * \param imports Array of imports
- * \param count Number of imports in list
- * \param path Path to save to
- * \return true on success, false on error and error reported
- */
-bool save_imported_sheets(struct nscss_import *imports, uint32_t count,
- const char *path, struct save_complete_entry **list)
+static bool save_complete_save_imported_sheets(save_complete_ctx *ctx,
+ struct nscss_import *imports, uint32_t import_count)
{
- char filename[256];
- unsigned int j;
- char *source;
- int source_len;
- bool res;
-
- for (j = 0; j != count; j++) {
- hlcache_handle *css = imports[j].c;
- const char *css_data;
- unsigned long css_size;
- struct nscss_import *child_imports;
- uint32_t child_import_count;
- lwc_string *type;
-
- if (css == NULL)
- continue;
- if (save_complete_list_check(css, *list))
- continue;
+ uint32_t i;
- if (!save_complete_list_add(css, list)) {
- warn_user("NoMemory", 0);
+ for (i = 0; i < import_count; i++) {
+ if (save_complete_save_stylesheet(ctx, imports[i].c) == false)
return false;
- }
+ }
- child_imports = nscss_get_imports(css, &child_import_count);
- if (!save_imported_sheets(child_imports, child_import_count,
- path, list))
- return false;
+ return true;
+}
- snprintf(filename, sizeof filename, "%p", css);
+static bool save_complete_save_html_stylesheet(save_complete_ctx *ctx,
+ struct html_stylesheet *sheet)
+{
+ if (sheet->type == HTML_STYLESHEET_INTERNAL) {
+ if (save_complete_save_imported_sheets(ctx,
+ sheet->data.internal->imports,
+ sheet->data.internal->import_count) == false)
+ return false;
- css_data = content_get_source_data(css, &css_size);
+ return true;
+ }
- source = rewrite_stylesheet_urls(css_data, css_size,
- &source_len, nsurl_access(hlcache_handle_get_url(css)),
- *list);
- if (!source) {
- warn_user("NoMemory", 0);
- return false;
- }
+ if (sheet->data.external == NULL)
+ return true;
- if (lwc_intern_string("text/css", SLEN("text/css"), &type) !=
- lwc_error_ok) {
- free(source);
- warn_user("NoMemory", 0);
- return false;
- }
+ return save_complete_save_stylesheet(ctx, sheet->data.external);
+}
- res = save_complete_gui_save(path, filename, source_len,
- source, type);
+static bool save_complete_save_html_stylesheets(save_complete_ctx *ctx,
+ hlcache_handle *c)
+{
+ struct html_stylesheet *sheets;
+ unsigned int i, count;
- lwc_string_unref(type);
- free(source);
+ sheets = html_get_stylesheets(c, &count);
- if (res == false)
+ for (i = STYLESHEET_START; i != count; i++) {
+ if (save_complete_save_html_stylesheet(ctx,
+ &sheets[i]) == false)
return false;
}
return true;
}
+static bool save_complete_save_html_object(save_complete_ctx *ctx,
+ hlcache_handle *obj)
+{
+ const char *obj_data;
+ unsigned long obj_size;
+ lwc_string *type;
+ bool result;
+ char filename[32];
-/**
- * Initialise the save_complete module.
- */
+ if (content_get_type(obj) == CONTENT_NONE)
+ return true;
-void save_complete_init(void)
-{
- /* Match an @import rule - see CSS 2.1 G.1. */
- regcomp_wrapper(&save_complete_import_re,
- "@import" /* IMPORT_SYM */
- "[ \t\r\n\f]*" /* S* */
- /* 1 */
- "(" /* [ */
- /* 2 3 */
- "\"(([^\"]|[\\]\")*)\"" /* STRING (approximated) */
- "|"
- /* 4 5 */
- "'(([^']|[\\]')*)'"
- "|" /* | */
- "url\\([ \t\r\n\f]*" /* URI (approximated) */
- /* 6 7 */
- "\"(([^\"]|[\\]\")*)\""
- "[ \t\r\n\f]*\\)"
- "|"
- "url\\([ \t\r\n\f]*"
- /* 8 9 */
- "'(([^']|[\\]')*)'"
- "[ \t\r\n\f]*\\)"
- "|"
- "url\\([ \t\r\n\f]*"
- /* 10 */
- "([^) \t\r\n\f]*)"
- "[ \t\r\n\f]*\\)"
- ")", /* ] */
- REG_EXTENDED | REG_ICASE);
-}
+ obj_data = content_get_source_data(obj, &obj_size);
+ if (obj_data == NULL)
+ return true;
+ if (save_complete_ctx_has_content(ctx, obj))
+ return true;
-/**
- * Rewrite stylesheet \@import rules for save complete.
- *
- * @param source stylesheet source
- * @param size size of source
- * @param osize updated with the size of the result
- * @param base url of stylesheet
- * @return converted source, or 0 on out of memory
- */
+ if (save_complete_ctx_add_content(ctx, obj) == false) {
+ warn_user("NoMemory", 0);
+ return false;
+ }
-char * rewrite_stylesheet_urls(const char *source, unsigned int size,
- int *osize, const char *base,
- struct save_complete_entry *list)
+ if (content_get_type(obj) == CONTENT_HTML) {
+ return save_complete_save_html(ctx, obj, false);
+ }
+
+ snprintf(filename, sizeof filename, "%p", obj);
+
+ type = content_get_mime_type(obj);
+ if (type == NULL)
+ return false;
+
+ result = save_complete_save_buffer(ctx, filename,
+ obj_data, obj_size, type);
+
+ lwc_string_unref(type);
+
+ return result;
+}
+
+static bool save_complete_save_html_objects(save_complete_ctx *ctx,
+ hlcache_handle *c)
{
- char *res;
- const char *url;
- char *url2;
- char buf[20];
- unsigned int offset = 0;
- int url_len = 0;
- hlcache_handle *content;
- int m;
- unsigned int i;
- unsigned int imports = 0;
- regmatch_t match[11];
- url_func_result result;
+ struct content_html_object *object;
+ unsigned int count;
- /* count number occurences of @import to (over)estimate result size */
- /* can't use strstr because source is not 0-terminated string */
- for (i = 0; 7 < size && i != size - 7; i++) {
- if (source[i] == '@' &&
- tolower(source[i + 1]) == 'i' &&
- tolower(source[i + 2]) == 'm' &&
- tolower(source[i + 3]) == 'p' &&
- tolower(source[i + 4]) == 'o' &&
- tolower(source[i + 5]) == 'r' &&
- tolower(source[i + 6]) == 't')
- imports++;
+ object = html_get_objects(c, &count);
+
+ for (; object != NULL; object = object->next) {
+ if (object->content != NULL) {
+ if (save_complete_save_html_object(ctx,
+ object->content) == false)
+ return false;
+ }
}
- res = malloc(size + imports * 20);
- if (!res)
- return 0;
- *osize = 0;
+ return true;
+}
- while (offset < size) {
- m = regexec(&save_complete_import_re, source + offset,
- 11, match, 0);
- if (m)
- break;
+static bool save_complete_libdom_treewalk(dom_node *root,
+ bool (*callback)(dom_node *node,
+ save_complete_event_type event_type, void *ctx),
+ void *ctx)
+{
+ dom_node *node;
- /*for (unsigned int i = 0; i != 11; i++) {
- if (match[i].rm_so == -1)
- continue;
- fprintf(stderr, "%i: '%.*s'\n", i,
- match[i].rm_eo - match[i].rm_so,
- source + offset + match[i].rm_so);
- }*/
+ node = dom_node_ref(root); /* tree root */
- url = 0;
- if (match[2].rm_so != -1) {
- url = source + offset + match[2].rm_so;
- url_len = match[2].rm_eo - match[2].rm_so;
- } else if (match[4].rm_so != -1) {
- url = source + offset + match[4].rm_so;
- url_len = match[4].rm_eo - match[4].rm_so;
- } else if (match[6].rm_so != -1) {
- url = source + offset + match[6].rm_so;
- url_len = match[6].rm_eo - match[6].rm_so;
- } else if (match[8].rm_so != -1) {
- url = source + offset + match[8].rm_so;
- url_len = match[8].rm_eo - match[8].rm_so;
- } else if (match[10].rm_so != -1) {
- url = source + offset + match[10].rm_so;
- url_len = match[10].rm_eo - match[10].rm_so;
- }
- assert(url);
+ while (node != NULL) {
+ dom_node *next = NULL;
+ dom_exception exc;
- url2 = strndup(url, url_len);
- if (!url2) {
- free(res);
- return 0;
- }
- result = url_join(url2, base, (char**)&url);
- free(url2);
- if (result == URL_FUNC_NOMEM) {
- free(res);
- return 0;
+ exc = dom_node_get_first_child(node, &next);
+ if (exc != DOM_NO_ERR) {
+ dom_node_unref(node);
+ break;
}
- /* copy data before match */
- memcpy(res + *osize, source + offset, match[0].rm_so);
- *osize += match[0].rm_so;
+ if (next != NULL) { /* 1. children */
+ dom_node_unref(node);
+ node = next;
+ } else {
+ exc = dom_node_get_next_sibling(node, &next);
+ if (exc != DOM_NO_ERR) {
+ dom_node_unref(node);
+ break;
+ }
- if (result == URL_FUNC_OK) {
- content = save_complete_list_find(url, list);
- if (content) {
- /* replace import */
- snprintf(buf, sizeof buf, "@import '%p'",
- content);
- memcpy(res + *osize, buf, strlen(buf));
- *osize += strlen(buf);
- } else {
- /* copy import */
- memcpy(res + *osize, source + offset + match[0].rm_so,
- match[0].rm_eo - match[0].rm_so);
- *osize += match[0].rm_eo - match[0].rm_so;
+ if (next != NULL) { /* 2. siblings */
+ if (callback(node, EVENT_LEAVE, ctx) == false) {
+ return false;
+ }
+ dom_node_unref(node);
+ node = next;
+ } else { /* 3. ancestor siblings */
+ while (node != NULL) {
+ exc = dom_node_get_next_sibling(node,
+ &next);
+ if (exc != DOM_NO_ERR) {
+ dom_node_unref(node);
+ node = NULL;
+ break;
+ }
+
+ if (next != NULL) {
+ dom_node_unref(next);
+ break;
+ }
+
+ exc = dom_node_get_parent_node(node,
+ &next);
+ if (exc != DOM_NO_ERR) {
+ dom_node_unref(node);
+ node = NULL;
+ break;
+ }
+
+ if (callback(node, EVENT_LEAVE,
+ ctx) == false) {
+ return false;
+ }
+ dom_node_unref(node);
+ node = next;
+ }
+
+ if (node == NULL)
+ break;
+
+ exc = dom_node_get_next_sibling(node, &next);
+ if (exc != DOM_NO_ERR) {
+ dom_node_unref(node);
+ break;
+ }
+
+ if (callback(node, EVENT_LEAVE, ctx) == false) {
+ return false;
+ }
+ dom_node_unref(node);
+ node = next;
}
}
- else {
- /* copy import */
- memcpy(res + *osize, source + offset + match[0].rm_so,
- match[0].rm_eo - match[0].rm_so);
- *osize += match[0].rm_eo - match[0].rm_so;
- }
- assert(0 < match[0].rm_eo);
- offset += match[0].rm_eo;
- }
+ assert(node != NULL);
+
+ if (callback(node, EVENT_ENTER, ctx) == false) {
+ return false; /* callback caused early termination */
+ }
- /* copy rest of source */
- if (offset < size) {
- memcpy(res + *osize, source + offset, size - offset);
- *osize += size - offset;
}
- return res;
+ return true;
}
+static bool save_complete_rewrite_url_value(save_complete_ctx *ctx,
+ const char *value, size_t value_len)
+{
+ nsurl *url;
+ hlcache_handle *content;
+ nserror error;
-/**
- * Rewrite URLs in a HTML document to be relative.
- *
- * \param doc root of the document tree
- * \param base base url of document
- * \return true on success, false on out of memory
- */
+ error = nsurl_join(ctx->base, value, &url);
+ if (error == NSERROR_NOMEM)
+ return false;
-bool rewrite_document_urls(xmlDoc *doc, const char *base,
- struct save_complete_entry *list)
-{
- xmlNode *node;
+ if (url != NULL) {
+ content = save_complete_ctx_find_content(ctx, url);
+ if (content != NULL) {
+ /* found a match */
+ nsurl_unref(url);
- for (node = doc->children; node; node = node->next)
- if (node->type == XML_ELEMENT_NODE)
- if (!rewrite_urls(node, base, list))
- return false;
+ fprintf(ctx->fp, "\"%p\"", content);
+ } else {
+ /* no match found */
+ fprintf(ctx->fp, "\"%s\"", nsurl_access(url));
+ nsurl_unref(url);
+ }
+ } else {
+ fprintf(ctx->fp, "\"%.*s\"", (int) value_len, value);
+ }
return true;
}
+static bool save_complete_write_value(save_complete_ctx *ctx,
+ const char *value, size_t value_len)
+{
+ fprintf(ctx->fp, "\"%.*s\"", (int) value_len, value);
-/**
- * Traverse tree, rewriting URLs as we go.
- *
- * \param n xmlNode of type XML_ELEMENT_NODE to rewrite
- * \param base base url of document
- * \return true on success, false on out of memory
- *
- * URLs in the tree rooted at element n are rewritten.
- */
+ return true;
+}
-bool rewrite_urls(xmlNode *n, const char *base,
- struct save_complete_entry *list)
+static bool save_complete_handle_attr_value(save_complete_ctx *ctx,
+ dom_string *node_name, dom_string *attr_name,
+ dom_string *attr_value)
{
- xmlNode *child;
-
- assert(n->type == XML_ELEMENT_NODE);
+ const char *node_data = dom_string_data(node_name);
+ size_t node_len = dom_string_byte_length(node_name);
+ const char *name_data = dom_string_data(attr_name);
+ size_t name_len = dom_string_byte_length(attr_name);
+ const char *value_data = dom_string_data(attr_value);
+ size_t value_len = dom_string_byte_length(attr_value);
/**
* We only need to consider the following cases:
@@ -581,253 +603,453 @@ bool rewrite_urls(xmlNode *n, const char *base,
* 1) data <object>
* 2) href <a> <area> <link>
* 3) src <script> <input> <frame> <iframe> <img>
- * 4) n/a <style>
- * 5) n/a any <base> tag
- * 6) background any (except those above)
+ * 4) background any (except those above)
*/
- if (!n->name) {
- /* ignore */
- }
/* 1 */
- else if (strcasecmp((const char *) n->name, "object") == 0) {
- if (!rewrite_url(n, "data", base, list))
- return false;
+ if (name_len == SLEN("data") &&
+ strncasecmp(name_data, "data", name_len) == 0) {
+ if (node_len == SLEN("object") &&
+ strncasecmp(node_data,
+ "object", node_len) == 0) {
+ return save_complete_rewrite_url_value(ctx,
+ value_data, value_len);
+ } else {
+ return save_complete_write_value(ctx,
+ value_data, value_len);
+ }
}
/* 2 */
- else if (strcasecmp((const char *) n->name, "a") == 0 ||
- strcasecmp((const char *) n->name, "area") == 0 ||
- strcasecmp((const char *) n->name, "link") == 0) {
- if (!rewrite_url(n, "href", base, list))
- return false;
- }
+ else if (name_len == SLEN("href") &&
+ strncasecmp(name_data, "href", name_len) == 0) {
+ if ((node_len == SLEN("a") &&
+ strncasecmp(node_data, "a", node_len) == 0) ||
+ (node_len == SLEN("area") &&
+ strncasecmp(node_data, "area",
+ node_len) == 0) ||
+ (node_len == SLEN("link") &&
+ strncasecmp(node_data, "link",
+ node_len) == 0)) {
+ return save_complete_rewrite_url_value(ctx,
+ value_data, value_len);
+ } else {
+ return save_complete_write_value(ctx,
+ value_data, value_len);
+ }
+ }
/* 3 */
- else if (strcasecmp((const char *) n->name, "frame") == 0 ||
- strcasecmp((const char *) n->name, "iframe") == 0 ||
- strcasecmp((const char *) n->name, "input") == 0 ||
- strcasecmp((const char *) n->name, "img") == 0 ||
- strcasecmp((const char *) n->name, "script") == 0) {
- if (!rewrite_url(n, "src", base, list))
- return false;
+ else if (name_len == SLEN("src") &&
+ strncasecmp(name_data, "src", name_len) == 0) {
+ if ((node_len == SLEN("frame") &&
+ strncasecmp(node_data, "frame",
+ node_len) == 0) ||
+ (node_len == SLEN("iframe") &&
+ strncasecmp(node_data, "iframe",
+ node_len) == 0) ||
+ (node_len == SLEN("input") &&
+ strncasecmp(node_data, "input",
+ node_len) == 0) ||
+ (node_len == SLEN("img") &&
+ strncasecmp(node_data, "img",
+ node_len) == 0) ||
+ (node_len == SLEN("script") &&
+ strncasecmp(node_data, "script",
+ node_len) == 0)) {
+ return save_complete_rewrite_url_value(ctx,
+ value_data, value_len);
+ } else {
+ return save_complete_write_value(ctx,
+ value_data, value_len);
+ }
}
/* 4 */
- else if (strcasecmp((const char *) n->name, "style") == 0) {
- unsigned int len;
- xmlChar *content;
+ else if (name_len == SLEN("background") &&
+ strncasecmp(name_data, "background", name_len) == 0) {
+ return save_complete_rewrite_url_value(ctx,
+ value_data, value_len);
+ } else {
+ return save_complete_write_value(ctx,
+ value_data, value_len);
+ }
+}
- for (child = n->children; child != 0; child = child->next) {
- char *rewritten;
- /* Get current content */
- content = xmlNodeGetContent(child);
- if (!content)
- /* unfortunately we don't know if this is
- * due to memory exhaustion, or because
- * there is no content for this node */
- continue;
+static bool save_complete_handle_attr(save_complete_ctx *ctx,
+ dom_string *node_name, dom_attr *attr)
+{
+ dom_string *name;
+ const char *name_data;
+ size_t name_len;
+ dom_string *value;
+ dom_exception error;
+
+ error = dom_attr_get_name(attr, &name);
+ if (error != DOM_NO_ERR)
+ return false;
- /* Rewrite @import rules */
- rewritten = rewrite_stylesheet_urls(
- (const char *) content,
- strlen((const char *) content),
- (int *) &len, base, list);
- xmlFree(content);
- if (!rewritten)
- return false;
+ if (name == NULL)
+ return true;
+
+ error = dom_attr_get_value(attr, &value);
+ if (error != DOM_NO_ERR) {
+ dom_string_unref(name);
+ return false;
+ }
- /* set new content */
- xmlNodeSetContentLen(child,
- (const xmlChar*)rewritten,
- len);
+ name_data = dom_string_data(name);
+ name_len = dom_string_byte_length(name);
+
+ fputc(' ', ctx->fp);
+ fwrite(name_data, sizeof(*name_data), name_len, ctx->fp);
+
+ if (value != NULL) {
+ fputc('=', ctx->fp);
+ if (save_complete_handle_attr_value(ctx, node_name,
+ name, value) == false) {
+ dom_string_unref(value);
+ dom_string_unref(name);
+ return false;
}
+ }
- return true;
+ dom_string_unref(name);
+
+ return true;
+}
+
+static bool save_complete_handle_attrs(save_complete_ctx *ctx,
+ dom_string *node_name, dom_namednodemap *attrs)
+{
+ uint32_t length, i;
+ dom_exception error;
+
+ error = dom_namednodemap_get_length(attrs, &length);
+ if (error != DOM_NO_ERR)
+ return false;
+
+ for (i = 0; i < length; i++) {
+ dom_attr *attr;
+
+ error = dom_namednodemap_item(attrs, i, &attr);
+ if (error != DOM_NO_ERR)
+ return false;
+
+ if (attr == NULL)
+ continue;
+
+ if (save_complete_handle_attr(ctx, node_name, attr) == false) {
+ dom_node_unref(attr);
+ return false;
+ }
+
+ dom_node_unref(attr);
}
- /* 5 */
- else if (strcasecmp((const char *) n->name, "base") == 0) {
- /* simply remove any <base> tags from the document */
- xmlUnlinkNode(n);
- xmlFreeNode(n);
- /* base tags have no content, so there's no point recursing
- * additionally, we've just destroyed this node, so trying
- * to recurse would result in bad things happening */
+
+ return true;
+}
+
+static bool save_complete_handle_element(save_complete_ctx *ctx,
+ dom_node *node, save_complete_event_type event_type)
+{
+ dom_string *name;
+ dom_namednodemap *attrs;
+ const char *name_data;
+ size_t name_len;
+ dom_exception error;
+
+ ctx->iter_state = STATE_NORMAL;
+
+ error = dom_node_get_node_name(node, &name);
+ if (error != DOM_NO_ERR)
+ return false;
+
+ if (name == NULL)
+ return true;
+
+ name_data = dom_string_data(name);
+ name_len = dom_string_byte_length(name);
+
+ /* Elide BASE elements from the output */
+ if (name_len == SLEN("base") &&
+ strncasecmp(name_data, "base", name_len) == 0) {
+ dom_string_unref(name);
return true;
}
- /* 6 */
- else {
- if (!rewrite_url(n, "background", base, list))
- return false;
- }
-
- /* now recurse */
- for (child = n->children; child;) {
- /* we must extract the next child now, as if the current
- * child is a <base> element, it will be removed from the
- * tree (see 5, above), thus preventing extraction of the
- * next child */
- xmlNode *next = child->next;
- if (child->type == XML_ELEMENT_NODE) {
- if (!rewrite_urls(child, base, list))
+
+ fputc('<', ctx->fp);
+ if (event_type == EVENT_LEAVE)
+ fputc('/', ctx->fp);
+ fwrite(name_data, sizeof(*name_data), name_len, ctx->fp);
+
+ if (event_type == EVENT_ENTER) {
+ error = dom_node_get_attributes(node, &attrs);
+ if (error != DOM_NO_ERR) {
+ dom_string_unref(name);
+ return false;
+ }
+
+ if (save_complete_handle_attrs(ctx, name, attrs) == false) {
+ dom_namednodemap_unref(attrs);
+ dom_string_unref(name);
+ return false;
+ }
+
+ dom_namednodemap_unref(attrs);
+ }
+
+ fputc('>', ctx->fp);
+
+ /* Rewrite contents of style elements */
+ if (event_type == EVENT_ENTER && name_len == SLEN("style") &&
+ strncasecmp(name_data, "style", name_len) == 0) {
+ dom_string *content;
+
+ error = dom_node_get_text_content(node, &content);
+ if (error != DOM_NO_ERR) {
+ dom_string_unref(name);
+ return false;
+ }
+
+ if (content != NULL) {
+ char *rewritten;
+ unsigned long len;
+
+ /* Rewrite @import rules */
+ rewritten = save_complete_rewrite_stylesheet_urls(
+ ctx,
+ dom_string_data(content),
+ dom_string_byte_length(content),
+ ctx->base,
+ &len);
+ if (rewritten == NULL) {
+ dom_string_unref(content);
+ dom_string_unref(name);
return false;
+ }
+
+ dom_string_unref(content);
+
+ fwrite(rewritten, sizeof(*rewritten), len, ctx->fp);
+
+ free(rewritten);
}
- child = next;
+
+ ctx->iter_state = STATE_IN_STYLE;
}
+ dom_string_unref(name);
+
return true;
}
-
-/**
- * Rewrite an URL in a HTML document.
- *
- * \param n The node to modify
- * \param attr The html attribute to modify
- * \param base base url of document
- * \return true on success, false on out of memory
- */
-
-bool rewrite_url(xmlNode *n, const char *attr, const char *base,
- struct save_complete_entry *list)
+static bool save_complete_node_handler(dom_node *node,
+ save_complete_event_type event_type, void *ctxin)
{
- char *url, *data;
- char rel[20];
- hlcache_handle *content;
- url_func_result res;
+ save_complete_ctx *ctx = ctxin;
+ dom_node_type type;
+ dom_exception error;
- if (!xmlHasProp(n, (const xmlChar *) attr))
- return true;
-
- data = (char *) xmlGetProp(n, (const xmlChar *) attr);
- if (!data)
+ error = dom_node_get_node_type(node, &type);
+ if (error != DOM_NO_ERR)
return false;
- res = url_join(data, base, &url);
- xmlFree(data);
- if (res == URL_FUNC_NOMEM)
- return false;
- else if (res == URL_FUNC_OK) {
- content = save_complete_list_find(url, list);
- if (content) {
- /* found a match */
- free(url);
- snprintf(rel, sizeof rel, "%p", content);
- if (!xmlSetProp(n, (const xmlChar *) attr,
- (xmlChar *) rel))
- return false;
- } else {
- /* no match found */
- if (!xmlSetProp(n, (const xmlChar *) attr,
- (xmlChar *) url)) {
- free(url);
+ if (type == DOM_ELEMENT_NODE) {
+ return save_complete_handle_element(ctx, node, event_type);
+ } else if (type == DOM_TEXT_NODE || type == DOM_COMMENT_NODE) {
+ if (event_type != EVENT_ENTER)
+ return true;
+
+ if (ctx->iter_state != STATE_IN_STYLE) {
+ /* Emit text content */
+ dom_string *text;
+ const char *text_data;
+ size_t text_len;
+
+ error = dom_characterdata_get_data(node, &text);
+ if (error != DOM_NO_ERR) {
return false;
}
- free(url);
+
+ if (text != NULL) {
+ text_data = dom_string_data(text);
+ text_len = dom_string_byte_length(text);
+
+ fwrite(text_data, sizeof(*text_data),
+ text_len, ctx->fp);
+
+ dom_string_unref(text);
+ }
+ }
+ } else if (type == DOM_DOCUMENT_TYPE_NODE) {
+ dom_string *name;
+ const char *name_data;
+ size_t name_len;
+
+ if (event_type != EVENT_ENTER)
+ return true;
+
+ error = dom_document_type_get_name(node, &name);
+ if (error != DOM_NO_ERR)
+ return false;
+
+ if (name == NULL)
+ return true;
+
+ name_data = dom_string_data(name);
+ name_len = dom_string_byte_length(name);
+
+ fputs("<!DOCTYPE ", ctx->fp);
+ fwrite(name_data, sizeof(*name_data), name_len, ctx->fp);
+
+ dom_string_unref(name);
+
+ error = dom_document_type_get_public_id(node, &name);
+ if (error != DOM_NO_ERR)
+ return false;
+
+ if (name != NULL) {
+ name_data = dom_string_data(name);
+ name_len = dom_string_byte_length(name);
+
+ fprintf(ctx->fp, " PUBLIC \"%.*s\"",
+ (int) name_len, name_data);
+
+ dom_string_unref(name);
}
+
+ error = dom_document_type_get_system_id(node, &name);
+ if (error != DOM_NO_ERR)
+ return false;
+
+ if (name != NULL) {
+ name_data = dom_string_data(name);
+ name_len = dom_string_byte_length(name);
+
+ fprintf(ctx->fp, " \"%.*s\"",
+ (int) name_len, name_data);
+
+ dom_string_unref(name);
+ }
+
+ fputc('>', ctx->fp);
+ } else if (type == DOM_DOCUMENT_NODE) {
+ /* Do nothing */
+ } else {
+ LOG(("Unhandled node type: %d", type));
}
return true;
}
+static bool save_complete_save_html_document(save_complete_ctx *ctx,
+ hlcache_handle *c, bool index)
+{
+ bool error;
+ FILE *fp;
+ dom_document *doc;
+ lwc_string *mime_type;
+ char filename[32];
+ char fullpath[PATH_MAX];
-/**
- * Add a content to the save_complete_list.
- *
- * \param content content to add
- * \return true on success, false on out of memory
- */
+ strncpy(fullpath, ctx->path, sizeof fullpath);
-bool save_complete_list_add(hlcache_handle *content,
- struct save_complete_entry **list)
-{
- struct save_complete_entry *entry;
- entry = malloc(sizeof (*entry));
- if (!entry)
+ if (index)
+ snprintf(filename, sizeof filename, "index");
+ else
+ snprintf(filename, sizeof filename, "%p", c);
+
+ error = path_add_part(fullpath, sizeof fullpath, filename);
+ if (error == false) {
+ warn_user("NoMemory", NULL);
return false;
- entry->content = content;
- entry->next = *list;
- *list = entry;
- return true;
-}
+ }
+ fp = fopen(fullpath, "wb");
+ if (fp == NULL) {
+ warn_user("NoMemory", NULL);
+ return false;
+ }
-/**
- * Look up a url in the save_complete_list.
- *
- * \param url url to find
- * \return content if found, 0 otherwise
- */
+ ctx->base = html_get_base_url(c);
+ ctx->fp = fp;
+ ctx->iter_state = STATE_NORMAL;
-hlcache_handle * save_complete_list_find(const char *url,
- struct save_complete_entry *list)
-{
- struct save_complete_entry *entry;
- for (entry = list; entry; entry = entry->next)
- if (strcmp(url, nsurl_access(
- hlcache_handle_get_url(entry->content))) == 0)
- return entry->content;
- return 0;
-}
+ doc = html_get_document(c);
+ if (save_complete_libdom_treewalk((dom_node *) doc,
+ save_complete_node_handler, ctx) == false) {
+ warn_user("NoMemory", 0);
+ fclose(fp);
+ return false;
+ }
-/**
- * Look up a content in the save_complete_list.
- *
- * \param content pointer to content
- * \return true if the content is in the save_complete_list
- */
+ fclose(fp);
-bool save_complete_list_check(hlcache_handle *content,
- struct save_complete_entry *list)
-{
- struct save_complete_entry *entry;
- for (entry = list; entry; entry = entry->next)
- if (entry->content == content)
- return true;
- return false;
-}
+ mime_type = content_get_mime_type(c);
+ if (mime_type != NULL) {
+ if (ctx->set_type != NULL)
+ ctx->set_type(fullpath, mime_type);
+ lwc_string_unref(mime_type);
+ }
+
+ return true;
+}
-#if 0
/**
- * Dump save complete list to stderr
+ * Save an HTML page with all dependencies, recursing through imported pages.
+ *
+ * \param ctx Save complete context
+ * \param c Content to save
+ * \param index true to save as "index"
+ * \return true on success, false on error and error reported
*/
-void save_complete_list_dump(void)
+static bool save_complete_save_html(save_complete_ctx *ctx, hlcache_handle *c,
+ bool index)
{
- struct save_complete_entry *entry;
- for (entry = save_complete_list; entry; entry = entry->next)
- fprintf(stderr, "%p : %s\n", entry->content,
- entry->content->url);
+ if (content_get_type(c) != CONTENT_HTML)
+ return false;
+
+ if (save_complete_ctx_has_content(ctx, c))
+ return true;
+
+ if (save_complete_save_html_stylesheets(ctx, c) == false)
+ return false;
+
+ if (save_complete_save_html_objects(ctx, c) == false)
+ return false;
+
+ return save_complete_save_html_document(ctx, c, index);
}
-#endif
/**
* Create the inventory file listing original URLs.
*/
-bool save_complete_inventory(const char *path,
- struct save_complete_entry *list)
+static bool save_complete_inventory(save_complete_ctx *ctx)
{
- char fullpath[256];
FILE *fp;
- struct save_complete_entry *entry;
bool error;
+ save_complete_entry *entry;
+ char fullpath[PATH_MAX];
- strncpy(fullpath, path, sizeof fullpath);
+ strncpy(fullpath, ctx->path, sizeof fullpath);
error = path_add_part(fullpath, sizeof fullpath, "Inventory");
-
if (error == false) {
- warn_user("NoMemory", 0);
+ warn_user("NoMemory", NULL);
return false;
}
+
fp = fopen(fullpath, "w");
- if (!fp) {
+ if (fp == NULL) {
LOG(("fopen(): errno = %i", errno));
warn_user("SaveError", strerror(errno));
return false;
}
- for (entry = list; entry; entry = entry->next) {
+ for (entry = ctx->list; entry != NULL; entry = entry->next) {
fprintf(fp, "%p %s\n", entry->content,
- nsurl_access(hlcache_handle_get_url(entry->content)));
+ nsurl_access(hlcache_handle_get_url(
+ entry->content)));
}
fclose(fp);
@@ -835,3 +1057,55 @@ bool save_complete_inventory(const char *path,
return true;
}
+/* Documented in save_complete.h */
+void save_complete_init(void)
+{
+ /* Match an @import rule - see CSS 2.1 G.1. */
+ regcomp_wrapper(&save_complete_import_re,
+ "@import" /* IMPORT_SYM */
+ "[ \t\r\n\f]*" /* S* */
+ /* 1 */
+ "(" /* [ */
+ /* 2 3 */
+ "\"(([^\"]|[\\]\")*)\"" /* STRING (approximated) */
+ "|"
+ /* 4 5 */
+ "'(([^']|[\\]')*)'"
+ "|" /* | */
+ "url\\([ \t\r\n\f]*" /* URI (approximated) */
+ /* 6 7 */
+ "\"(([^\"]|[\\]\")*)\""
+ "[ \t\r\n\f]*\\)"
+ "|"
+ "url\\([ \t\r\n\f]*"
+ /* 8 9 */
+ "'(([^']|[\\]')*)'"
+ "[ \t\r\n\f]*\\)"
+ "|"
+ "url\\([ \t\r\n\f]*"
+ /* 10 */
+ "([^) \t\r\n\f]*)"
+ "[ \t\r\n\f]*\\)"
+ ")", /* ] */
+ REG_EXTENDED | REG_ICASE);
+}
+
+/* Documented in save_complete.h */
+bool save_complete(hlcache_handle *c, const char *path,
+ save_complete_set_type_cb set_type)
+{
+ bool result;
+ save_complete_ctx ctx;
+
+ save_complete_ctx_initialise(&ctx, path, set_type);
+
+ result = save_complete_save_html(&ctx, c, true);
+
+ if (result)
+ result = save_complete_inventory(&ctx);
+
+ save_complete_ctx_finalise(&ctx);
+
+ return result;
+}
+
diff --git a/desktop/save_complete.h b/desktop/save_complete.h
index 6970ceaac..3c389a56f 100644
--- a/desktop/save_complete.h
+++ b/desktop/save_complete.h
@@ -25,19 +25,34 @@
#define _NETSURF_DESKTOP_SAVE_COMPLETE_H_
#include <stdbool.h>
-#include <libxml/HTMLtree.h>
#include <libwapcaplet/libwapcaplet.h>
struct hlcache_handle;
-void save_complete_init(void);
-bool save_complete(struct hlcache_handle *c, const char *path);
+/**
+ * Callback to set type of a file
+ *
+ * \param path Native path of file
+ * \param mime_type MIME type of file content
+ */
+typedef void (*save_complete_set_type_cb)(const char *path,
+ lwc_string *mime_type);
-bool save_complete_gui_save(const char *path, const char *filename,
- size_t len, const char *sourcedata, lwc_string *mime_type);
+/**
+ * Initialise save complete module.
+ */
+void save_complete_init(void);
-int save_complete_htmlSaveFileFormat(const char *path, const char *filename,
- xmlDocPtr cur, const char *encoding, int format);
+/**
+ * Save an HTML page with all dependencies.
+ *
+ * \param c CONTENT_HTML to save
+ * \param path Native path to directory to save in to (must exist)
+ * \param set_type Callback to set type of a file, or NULL
+ * \return true on success, false on error and error reported
+ */
+bool save_complete(struct hlcache_handle *c, const char *path,
+ save_complete_set_type_cb set_type);
#endif
diff --git a/framebuffer/Makefile.target b/framebuffer/Makefile.target
index 2a41f4128..e410c36f0 100644
--- a/framebuffer/Makefile.target
+++ b/framebuffer/Makefile.target
@@ -139,7 +139,7 @@ $(eval $(foreach V,$(filter FB_IMAGE_%,$(.VARIABLES)),$(call convert_image,$($(V
# ----------------------------------------------------------------------------
# S_FRAMEBUFFER are sources purely for the framebuffer build
-S_FRAMEBUFFER := gui.c framebuffer.c tree.c save.c schedule.c \
+S_FRAMEBUFFER := gui.c framebuffer.c tree.c schedule.c \
thumbnail.c misc.c bitmap.c filetype.c login.c findfile.c \
localhistory.c system_colour.c clipboard.c
diff --git a/framebuffer/save.c b/framebuffer/save.c
deleted file mode 100644
index 601628ca0..000000000
--- a/framebuffer/save.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2009 John-Mark Bell <jmb@netsurf-browser.org>
- *
- * 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/>.
- */
-
-
-#include "desktop/save_complete.h"
-
-/**
-* conducts the filesystem save appropriate to the gui
-* \param path save path
-* \param filename name of file to save
-* \param len data length
-* \param sourcedata pointer to data to save, NULL when all data in c
-* \param type content type
-* \return true for success
-*/
-
-bool save_complete_gui_save(const char *path, const char *filename, size_t len,
- const char *sourcedata, lwc_string *mime_type)
-{
- return false;
-}
-
-/**
-* wrapper for lib function htmlSaveFileFormat; front sets path from
-* path + filename in a filesystem-specific way
-*/
-
-int save_complete_htmlSaveFileFormat(const char *path, const char *filename,
- xmlDocPtr cur, const char *encoding, int format)
-{
- return -1;
-}
-
diff --git a/gtk/Makefile.target b/gtk/Makefile.target
index c60247392..0018a67d5 100644
--- a/gtk/Makefile.target
+++ b/gtk/Makefile.target
@@ -107,7 +107,7 @@ $(eval $(foreach V,$(filter GTK_IMAGE_%,$(.VARIABLES)),$(call convert_image,$($(
S_GTK := font_pango.c bitmap.c gui.c schedule.c thumbnail.c plotters.c \
treeview.c scaffolding.c gdk.c completion.c login.c throbber.c \
selection.c history.c window.c filetype.c download.c menu.c \
- print.c save.c search.c tabs.c theme.c toolbar.c \
+ print.c search.c tabs.c theme.c toolbar.c \
compat.c cookies.c hotlist.c system_colour.c \
$(addprefix dialogs/,options.c about.c source.c)
diff --git a/gtk/gui.c b/gtk/gui.c
index 891910407..1d15ef743 100644
--- a/gtk/gui.c
+++ b/gtk/gui.c
@@ -51,6 +51,7 @@
#include "desktop/history_global_core.h"
#include "desktop/netsurf.h"
#include "desktop/options.h"
+#include "desktop/save_complete.h"
#include "desktop/save_pdf/pdf_plotters.h"
#include "desktop/searchweb.h"
#include "desktop/sslcert.h"
@@ -417,6 +418,8 @@ static void gui_init(int argc, char** argv, char **respath)
filepath_sfinddef(respath, buf, "mime.types", "/etc/");
gtk_fetch_filetype_init(buf);
+ save_complete_init();
+
urldb_load(nsoption_charp(url_file));
urldb_load_cookies(nsoption_charp(cookie_file));
diff --git a/gtk/save.c b/gtk/save.c
deleted file mode 100644
index fb8f3e0b9..000000000
--- a/gtk/save.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.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/>.
- */
-
-#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "content/content.h"
-#include "desktop/save_complete.h"
-#include "utils/utils.h"
-
-/**
-* conducts the filesystem save appropriate to the gui
-* \param path save path
-* \param filename name of file to save
-* \param len data length
-* \param sourcedata pointer to data to save
-* \param type content type
-* \return true for success
-*/
-
-bool save_complete_gui_save(const char *path, const char *filename,
- size_t len, const char *sourcedata, lwc_string *mime_type)
-{
- int res;
- int namelen;
- namelen = strlen(path) + strlen(filename) + 2; /* '/', '\0' */
- char *fullpath = malloc(namelen);
- if (!fullpath) {
- warn_user("NoMemory", 0);
- return false;
- }
- snprintf(fullpath, namelen, "%s/%s", path, filename);
- FILE *f;
- f = fopen(fullpath, "wb");
- free(fullpath);
- if (f == NULL)
- return false;
- res = fwrite(sourcedata, len, 1, f);
- fclose(f);
- if (res != 1)
- return false;
- return true;
-}
-
-/**
-* wrapper for lib function htmlSaveFileFormat; front sets path from path
-* + filename in a filesystem-specific way
-*/
-
-int save_complete_htmlSaveFileFormat(const char *path, const char *filename,
- xmlDocPtr cur, const char *encoding, int format)
-{
- int ret;
- int len = strlen(path) + strlen(filename) + 2;
- char *fullpath = malloc(len);
- if (fullpath == NULL) {
- warn_user("NoMemory", 0);
- return -1;
- }
- snprintf(fullpath, len, "%s/%s", path, filename);
- ret = htmlSaveFileFormat(fullpath, cur, encoding, format);
- free(fullpath);
- return ret;
-}
-
diff --git a/gtk/scaffolding.c b/gtk/scaffolding.c
index 22816cf89..91288a22e 100644
--- a/gtk/scaffolding.c
+++ b/gtk/scaffolding.c
@@ -668,9 +668,8 @@ MULTIHANDLER(savepage)
return TRUE;
}
closedir(d);
- save_complete_init();
save_complete(nsgtk_get_browser_window(
- g->top_level)->current_content, path);
+ g->top_level)->current_content, path, NULL);
g_free(path);
gtk_widget_destroy(fc);
diff --git a/monkey/utils.c b/monkey/utils.c
index ce67a0c19..886c1ff03 100644
--- a/monkey/utils.c
+++ b/monkey/utils.c
@@ -20,7 +20,6 @@
#include <stdlib.h>
#include <string.h>
-#include "desktop/save_complete.h"
#include "desktop/tree_url_node.h"
#include "utils/utils.h"
@@ -138,20 +137,6 @@ utf8_from_local_encoding(const char *string, size_t len,
return (*result == NULL) ? UTF8_CONVERT_NOMEM : UTF8_CONVERT_OK;
}
-bool
-save_complete_gui_save(const char *path, const char *filename,
- size_t len, const char *sourcedata, lwc_string *mime_type)
-{
- return true;
-}
-
-int
-save_complete_htmlSaveFileFormat(const char *path, const char *filename,
- xmlDocPtr cur, const char *encoding, int format)
-{
- return 0;
-}
-
void
tree_icon_name_from_content_type(char *buffer, content_type type)
{
diff --git a/riscos/save.c b/riscos/save.c
index 064b252d4..f61fd012b 100644
--- a/riscos/save.c
+++ b/riscos/save.c
@@ -975,71 +975,16 @@ void ro_gui_save_done(void)
gui_save_content = 0;
}
-/**
-* conducts the filesystem save appropriate to the gui
-* \param path save path
-* \param filename name of file to save
-* \param len data length
-* \param sourcedata pointer to data to save, NULL when all data in c
-* \param type content type
-* \return true for success
-*/
-
-bool save_complete_gui_save(const char *path, const char *filename, size_t len,
- const char *sourcedata, lwc_string *mime_type)
-{
- char *fullpath;
- os_error *error;
- int namelen = strlen(path) + strlen(filename) + 2;
- int rotype;
- fullpath = malloc(namelen);
- if (fullpath == NULL) {
- warn_user("NoMemory", 0);
- return false;
- }
- snprintf(fullpath, namelen, "%s.%s", path, filename);
- rotype = ro_content_filetype_from_mime_type(mime_type);
- error = xosfile_save_stamped(fullpath, rotype, (byte *) sourcedata,
- (byte *) sourcedata + len);
- free(fullpath);
- if (error) {
- LOG(("xosfile_save_stamped: 0x%x: %s",
- error->errnum, error->errmess));
- warn_user("SaveError", error->errmess);
- return false;
- }
- return true;
-}
-
-/**
-* wrapper for lib function htmlSaveFileFormat; front sets path from
-* path + filename in a filesystem-specific way
-*/
-
-int save_complete_htmlSaveFileFormat(const char *path, const char *filename,
- xmlDocPtr cur, const char *encoding, int format)
+static void ro_gui_save_set_file_type(const char *path, lwc_string *mime_type)
{
+ int rotype = ro_content_filetype_from_mime_type(mime_type);
os_error *error;
- int ret;
- int len = strlen(path) + strlen(filename) + 2;
- char *fullpath = malloc(len);
- if (fullpath == NULL){
- warn_user("NoMemory", 0);
- return -1;
- }
- snprintf(fullpath, len, "%s.%s", path, filename);
-
- ret = htmlSaveFileFormat(fullpath, cur, encoding, format);
- error = xosfile_set_type(fullpath, 0xFAF);
- if (error) {
- LOG(("xosfile_save_stamped: 0x%x: %s",
+ error = xosfile_set_type(path, rotype);
+ if (error != NULL) {
+ LOG(("xosfile_set_type: 0x%x: %s",
error->errnum, error->errmess));
- /* Don't warn the user here -- they probably don't care */
}
-
- free(fullpath);
- return ret;
}
/**
@@ -1130,7 +1075,7 @@ bool ro_gui_save_complete(hlcache_handle *h, char *path)
content_get_title(h), LINK_ANT, buf))
return false;
- return save_complete(h, path);
+ return save_complete(h, path, ro_gui_save_set_file_type);
}
bool ro_gui_save_object_native(hlcache_handle *h, char *path)
diff --git a/windows/gui.c b/windows/gui.c
index 048b50fd5..78c2d1b10 100644
--- a/windows/gui.c
+++ b/windows/gui.c
@@ -38,7 +38,6 @@
#include "desktop/netsurf.h"
#include "desktop/options.h"
#include "desktop/plotters.h"
-#include "desktop/save_complete.h"
#include "desktop/selection.h"
#include "desktop/textinput.h"
#include "render/html.h"
@@ -1691,27 +1690,6 @@ gui_window_set_search_ico(hlcache_handle *ico)
{
}
-bool
-save_complete_gui_save(const char *path,
- const char *filename,
- size_t len,
- const char *sourcedata,
- lwc_string *mime_type)
-{
- return false;
-}
-
-int
-save_complete_htmlSaveFileFormat(const char *path,
- const char *filename,
- xmlDocPtr cur,
- const char *encoding,
- int format)
-{
- return 0;
-}
-
-
void gui_window_new_content(struct gui_window *w)
{
}