netsurf: branch master updated. release/3.2-249-g1ccfcfe
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/1ccfcfe953d9a5144746b...
...commit http://git.netsurf-browser.org/netsurf.git/commit/1ccfcfe953d9a5144746bfa...
...tree http://git.netsurf-browser.org/netsurf.git/tree/1ccfcfe953d9a5144746bfafc...
The branch, master has been updated
via 1ccfcfe953d9a5144746bfafcf5d37a8229ca998 (commit)
from b16038cb1ef466c42548534047b02e53b3f87784 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=1ccfcfe953d9a514474...
commit 1ccfcfe953d9a5144746bfafcf5d37a8229ca998
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Remove unused url_path function.
diff --git a/utils/url.c b/utils/url.c
index c7935b2..d1b6805 100644
--- a/utils/url.c
+++ b/utils/url.c
@@ -288,29 +288,6 @@ static void url_destroy_components(const struct url_components *components)
/* exported interface documented in utils/url.h */
-nserror url_path(const char *url, char **result)
-{
- nserror status;
- struct url_components components;
-
- assert(url);
-
- status = url_get_components(url, &components);
- if (status == NSERROR_OK) {
- if (!components.path) {
- status = NSERROR_NOT_FOUND;
- } else {
- *result = strdup(components.path);
- if (!(*result))
- status = NSERROR_NOMEM;
- }
- }
- url_destroy_components(&components);
- return status;
-}
-
-
-/* exported interface documented in utils/url.h */
nserror url_nice(const char *url, char **result,
bool remove_extensions)
{
diff --git a/utils/url.h b/utils/url.h
index d152cc1..9f8de4e 100644
--- a/utils/url.h
+++ b/utils/url.h
@@ -95,14 +95,4 @@ nserror url_escape(const char *unescaped, size_t toskip, bool sptoplus, const ch
*/
nserror url_unescape(const char *str, char **result);
-
-/**
- * Extract path segment from an URL
- *
- * \param url an absolute URL
- * \param result pointer to pointer to buffer to hold result
- * \return NSERROR_OK on success
- */
-nserror url_path(const char *url, char **result);
-
#endif
-----------------------------------------------------------------------
Summary of changes:
utils/url.c | 23 -----------------------
utils/url.h | 10 ----------
2 files changed, 33 deletions(-)
diff --git a/utils/url.c b/utils/url.c
index c7935b2..d1b6805 100644
--- a/utils/url.c
+++ b/utils/url.c
@@ -288,29 +288,6 @@ static void url_destroy_components(const struct url_components *components)
/* exported interface documented in utils/url.h */
-nserror url_path(const char *url, char **result)
-{
- nserror status;
- struct url_components components;
-
- assert(url);
-
- status = url_get_components(url, &components);
- if (status == NSERROR_OK) {
- if (!components.path) {
- status = NSERROR_NOT_FOUND;
- } else {
- *result = strdup(components.path);
- if (!(*result))
- status = NSERROR_NOMEM;
- }
- }
- url_destroy_components(&components);
- return status;
-}
-
-
-/* exported interface documented in utils/url.h */
nserror url_nice(const char *url, char **result,
bool remove_extensions)
{
diff --git a/utils/url.h b/utils/url.h
index d152cc1..9f8de4e 100644
--- a/utils/url.h
+++ b/utils/url.h
@@ -95,14 +95,4 @@ nserror url_escape(const char *unescaped, size_t toskip, bool sptoplus, const ch
*/
nserror url_unescape(const char *str, char **result);
-
-/**
- * Extract path segment from an URL
- *
- * \param url an absolute URL
- * \param result pointer to pointer to buffer to hold result
- * \return NSERROR_OK on success
- */
-nserror url_path(const char *url, char **result);
-
#endif
--
NetSurf Browser
8 years, 3 months
netsurf: branch master updated. release/3.2-248-gb16038c
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/b16038cb1ef466c425485...
...commit http://git.netsurf-browser.org/netsurf.git/commit/b16038cb1ef466c42548534...
...tree http://git.netsurf-browser.org/netsurf.git/tree/b16038cb1ef466c4254853404...
The branch, master has been updated
via b16038cb1ef466c42548534047b02e53b3f87784 (commit)
via d732b0c76950bfdeaa9777bfac0c73517c25a9e0 (commit)
via f7781a877887ca20867fe48b04dbd33e947ab3d0 (commit)
via 87b1da592111c6b30775edcb0a84e38ee26cd520 (commit)
from e39606c411bad57de5891965628f6ac278df42ee (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=b16038cb1ef466c4254...
commit b16038cb1ef466c42548534047b02e53b3f87784
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
We have all the schemes as interned strings, so compare them instead of strncasecmp.
diff --git a/amiga/launch.c b/amiga/launch.c
index c14e2a7..67d74e4 100755
--- a/amiga/launch.c
+++ b/amiga/launch.c
@@ -86,23 +86,31 @@ void ami_openurl_free_list(struct MinList *list)
}while(node=nnode);
}
-BOOL ami_openurl_check_list(struct MinList *list, const char *url)
+BOOL ami_openurl_check_list(struct MinList *list, nsurl *url)
{
struct ami_protocol *node;
struct ami_protocol *nnode;
+ lwc_string *url_scheme;
+ bool match;
if(IsMinListEmpty(list)) return FALSE;
+
+ url_scheme = nsurl_get_component(ns_url, NSURL_SCHEME);
+
node = (struct ami_protocol *)GetHead((struct List *)list);
do
{
nnode=(struct ami_protocol *)GetSucc((struct Node *)node);
- if (!strncasecmp(url, lwc_string_data(node->protocol),
- lwc_string_length(node->protocol)))
+ if (lwc_string_isequal(url_scheme, node->protocol,
+ &match) == NSERROR_OK && match == true) {
+ lwc_string_unref(url_scheme);
return TRUE;
+ }
}while(node=nnode);
+ lwc_string_unref(url_scheme);
return FALSE;
}
@@ -136,7 +144,7 @@ nserror gui_launch_url(struct nsurl *url)
APTR procwin = SetProcWindow((APTR)-1L);
char *launchurl = NULL;
- if(ami_openurl_check_list(&ami_unsupportedprotocols, nsurl_access(url)) == FALSE)
+ if(ami_openurl_check_list(&ami_unsupportedprotocols, url) == FALSE)
{
if(IOpenURL)
{
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=d732b0c76950bfdeaa9...
commit d732b0c76950bfdeaa9777bfac0c73517c25a9e0
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Remove unused url_scheme function.
diff --git a/utils/url.c b/utils/url.c
index 949478e..c7935b2 100644
--- a/utils/url.c
+++ b/utils/url.c
@@ -288,29 +288,6 @@ static void url_destroy_components(const struct url_components *components)
/* exported interface documented in utils/url.h */
-nserror url_scheme(const char *url, char **result)
-{
- nserror status;
- struct url_components components;
-
- assert(url);
-
- status = url_get_components(url, &components);
- if (status == NSERROR_OK) {
- if (!components.scheme) {
- status = NSERROR_NOT_FOUND;
- } else {
- *result = strdup(components.scheme);
- if (!(*result))
- status = NSERROR_NOMEM;
- }
- }
- url_destroy_components(&components);
- return status;
-}
-
-
-/* exported interface documented in utils/url.h */
nserror url_path(const char *url, char **result)
{
nserror status;
diff --git a/utils/url.h b/utils/url.h
index aac4e57..d152cc1 100644
--- a/utils/url.h
+++ b/utils/url.h
@@ -66,18 +66,6 @@ bool url_host_is_ip_address(const char *host);
/**
- * Return the scheme name from an URL.
- *
- * See RFC 3986, 3.1 for reference.
- *
- * \param url an absolute URL
- * \param result pointer to pointer to buffer to hold scheme name
- * \return NSERROR_OK on success
- */
-nserror url_scheme(const char *url, char **result);
-
-
-/**
* Attempt to find a nice filename for a URL.
*
* \param url an absolute URL
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=f7781a877887ca20867...
commit f7781a877887ca20867fe48b04dbd33e947ab3d0
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Don't need url.h
diff --git a/amiga/launch.c b/amiga/launch.c
index e8b64f6..c14e2a7 100755
--- a/amiga/launch.c
+++ b/amiga/launch.c
@@ -32,7 +32,6 @@
#include "utils/nsoption.h"
#include "utils/nsurl.h"
-#include "utils/url.h"
struct Library *OpenURLBase = NULL;
struct OpenURLIFace *IOpenURL = NULL;
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=87b1da592111c6b3077...
commit 87b1da592111c6b30775edcb0a84e38ee26cd520
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Use nsurl to extract scheme.
diff --git a/amiga/launch.c b/amiga/launch.c
index d3c9ff1..e8b64f6 100755
--- a/amiga/launch.c
+++ b/amiga/launch.c
@@ -42,17 +42,25 @@ struct MinList ami_unsupportedprotocols;
struct ami_protocol
{
struct MinNode node;
- char *protocol;
+ lwc_string *protocol;
};
struct ami_protocol *ami_openurl_add_protocol(const char *url)
{
+ nsurl *ns_url
struct ami_protocol *ami_p =
(struct ami_protocol *)AllocVecTagList(sizeof(struct ami_protocol), NULL);
- if(url_scheme(url, &ami_p->protocol) != NSERROR_OK)
+ if (nsurl_create(url, &ns_url) != NSERROR_OK) {
+ FreeVec(ami_p);
+ return NULL;
+ }
+
+ ami_p->protocol = nsurl_get_component(ns_url, NSURL_SCHEME);
+ if (ami_p->protocol == NULL)
{
FreeVec(ami_p);
+ nsurl_unref(ns_url);
return NULL;
}
@@ -73,7 +81,7 @@ void ami_openurl_free_list(struct MinList *list)
nnode=(struct ami_protocol *)GetSucc((struct Node *)node);
Remove((struct Node *)node);
- if(node->protocol) free(node->protocol);
+ if (node->protocol) lwc_string_unref(node->protocol);
FreeVec(node);
node = NULL;
}while(node=nnode);
@@ -91,7 +99,8 @@ BOOL ami_openurl_check_list(struct MinList *list, const char *url)
{
nnode=(struct ami_protocol *)GetSucc((struct Node *)node);
- if(!strncasecmp(url, node->protocol, strlen(node->protocol)))
+ if (!strncasecmp(url, lwc_string_data(node->protocol),
+ lwc_string_length(node->protocol)))
return TRUE;
}while(node=nnode);
-----------------------------------------------------------------------
Summary of changes:
amiga/launch.c | 30 +++++++++++++++++++++++-------
utils/url.c | 23 -----------------------
utils/url.h | 12 ------------
3 files changed, 23 insertions(+), 42 deletions(-)
diff --git a/amiga/launch.c b/amiga/launch.c
index d3c9ff1..67d74e4 100755
--- a/amiga/launch.c
+++ b/amiga/launch.c
@@ -32,7 +32,6 @@
#include "utils/nsoption.h"
#include "utils/nsurl.h"
-#include "utils/url.h"
struct Library *OpenURLBase = NULL;
struct OpenURLIFace *IOpenURL = NULL;
@@ -42,17 +41,25 @@ struct MinList ami_unsupportedprotocols;
struct ami_protocol
{
struct MinNode node;
- char *protocol;
+ lwc_string *protocol;
};
struct ami_protocol *ami_openurl_add_protocol(const char *url)
{
+ nsurl *ns_url
struct ami_protocol *ami_p =
(struct ami_protocol *)AllocVecTagList(sizeof(struct ami_protocol), NULL);
- if(url_scheme(url, &ami_p->protocol) != NSERROR_OK)
+ if (nsurl_create(url, &ns_url) != NSERROR_OK) {
+ FreeVec(ami_p);
+ return NULL;
+ }
+
+ ami_p->protocol = nsurl_get_component(ns_url, NSURL_SCHEME);
+ if (ami_p->protocol == NULL)
{
FreeVec(ami_p);
+ nsurl_unref(ns_url);
return NULL;
}
@@ -73,28 +80,37 @@ void ami_openurl_free_list(struct MinList *list)
nnode=(struct ami_protocol *)GetSucc((struct Node *)node);
Remove((struct Node *)node);
- if(node->protocol) free(node->protocol);
+ if (node->protocol) lwc_string_unref(node->protocol);
FreeVec(node);
node = NULL;
}while(node=nnode);
}
-BOOL ami_openurl_check_list(struct MinList *list, const char *url)
+BOOL ami_openurl_check_list(struct MinList *list, nsurl *url)
{
struct ami_protocol *node;
struct ami_protocol *nnode;
+ lwc_string *url_scheme;
+ bool match;
if(IsMinListEmpty(list)) return FALSE;
+
+ url_scheme = nsurl_get_component(ns_url, NSURL_SCHEME);
+
node = (struct ami_protocol *)GetHead((struct List *)list);
do
{
nnode=(struct ami_protocol *)GetSucc((struct Node *)node);
- if(!strncasecmp(url, node->protocol, strlen(node->protocol)))
+ if (lwc_string_isequal(url_scheme, node->protocol,
+ &match) == NSERROR_OK && match == true) {
+ lwc_string_unref(url_scheme);
return TRUE;
+ }
}while(node=nnode);
+ lwc_string_unref(url_scheme);
return FALSE;
}
@@ -128,7 +144,7 @@ nserror gui_launch_url(struct nsurl *url)
APTR procwin = SetProcWindow((APTR)-1L);
char *launchurl = NULL;
- if(ami_openurl_check_list(&ami_unsupportedprotocols, nsurl_access(url)) == FALSE)
+ if(ami_openurl_check_list(&ami_unsupportedprotocols, url) == FALSE)
{
if(IOpenURL)
{
diff --git a/utils/url.c b/utils/url.c
index 949478e..c7935b2 100644
--- a/utils/url.c
+++ b/utils/url.c
@@ -288,29 +288,6 @@ static void url_destroy_components(const struct url_components *components)
/* exported interface documented in utils/url.h */
-nserror url_scheme(const char *url, char **result)
-{
- nserror status;
- struct url_components components;
-
- assert(url);
-
- status = url_get_components(url, &components);
- if (status == NSERROR_OK) {
- if (!components.scheme) {
- status = NSERROR_NOT_FOUND;
- } else {
- *result = strdup(components.scheme);
- if (!(*result))
- status = NSERROR_NOMEM;
- }
- }
- url_destroy_components(&components);
- return status;
-}
-
-
-/* exported interface documented in utils/url.h */
nserror url_path(const char *url, char **result)
{
nserror status;
diff --git a/utils/url.h b/utils/url.h
index aac4e57..d152cc1 100644
--- a/utils/url.h
+++ b/utils/url.h
@@ -66,18 +66,6 @@ bool url_host_is_ip_address(const char *host);
/**
- * Return the scheme name from an URL.
- *
- * See RFC 3986, 3.1 for reference.
- *
- * \param url an absolute URL
- * \param result pointer to pointer to buffer to hold scheme name
- * \return NSERROR_OK on success
- */
-nserror url_scheme(const char *url, char **result);
-
-
-/**
* Attempt to find a nice filename for a URL.
*
* \param url an absolute URL
--
NetSurf Browser
8 years, 3 months
netsurf: branch master updated. release/3.2-244-ge39606c
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/e39606c411bad57de5891...
...commit http://git.netsurf-browser.org/netsurf.git/commit/e39606c411bad57de589196...
...tree http://git.netsurf-browser.org/netsurf.git/tree/e39606c411bad57de58919656...
The branch, master has been updated
via e39606c411bad57de5891965628f6ac278df42ee (commit)
via df89f689f7ddcb082b4616c6e32cabbb859b3a11 (commit)
from 49873c8bf3e50ba0c7b8d41442ac287ed73e7a47 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=e39606c411bad57de58...
commit e39606c411bad57de5891965628f6ac278df42ee
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
make regex wrapper return errors instead of just aborting
diff --git a/utils/url.c b/utils/url.c
index 37fa939..949478e 100644
--- a/utils/url.c
+++ b/utils/url.c
@@ -44,10 +44,12 @@ struct url_components_internal {
regex_t url_re, url_up_re;
/* exported interface documented in utils/url.h */
-void url_init(void)
+nserror url_init(void)
{
+ nserror ret;
+
/* regex from RFC 2396 */
- regcomp_wrapper(&url_re, "^[[:space:]]*"
+ ret = regcomp_wrapper(&url_re, "^[[:space:]]*"
#define URL_RE_SCHEME 2
"(([a-zA-Z][-a-zA-Z0-9+.]*):)?"
#define URL_RE_AUTHORITY 4
@@ -59,7 +61,11 @@ void url_init(void)
#define URL_RE_FRAGMENT 9
"(#([^[:space:]]*))?"
"[[:space:]]*$", REG_EXTENDED);
- regcomp_wrapper(&url_up_re,
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ return regcomp_wrapper(&url_up_re,
"/([^/]?|[.][^./]|[^./][.]|[^./][^./]|[^/][^/][^/]+)"
"/[.][.](/|$)",
REG_EXTENDED);
diff --git a/utils/url.h b/utils/url.h
index f1aff0e..aac4e57 100644
--- a/utils/url.h
+++ b/utils/url.h
@@ -49,7 +49,7 @@ struct url_components {
*
* Compiles regular expressions required by the url_ functions.
*/
-void url_init(void);
+nserror url_init(void);
/**
diff --git a/utils/utils.c b/utils/utils.c
index 6199a84..6730c9f 100644
--- a/utils/utils.c
+++ b/utils/utils.c
@@ -33,6 +33,7 @@
#include <time.h>
#include "utils/config.h"
+#include "utils/log.h"
#include "utils/messages.h"
#include "utils/utf8.h"
#include "utils/time.h"
@@ -207,18 +208,20 @@ nserror snstrjoin(char **str, size_t *size, char sep, size_t nelm, ...)
/* exported interface documented in utils/utils.h */
-void regcomp_wrapper(regex_t *preg, const char *regex, int cflags)
+nserror regcomp_wrapper(regex_t *preg, const char *regex, int cflags)
{
int r;
r = regcomp(preg, regex, cflags);
if (r) {
char errbuf[200];
regerror(r, preg, errbuf, sizeof errbuf);
- fprintf(stderr, "Failed to compile regexp '%s'\n", regex);
- die(errbuf);
+ LOG(("Failed to compile regexp '%s': %s\n", regex, errbuf));
+ return NSERROR_INIT_FAILED;
}
+ return NSERROR_OK;
}
+
/**
* The size of buffers within human_friendly_bytesize.
*
diff --git a/utils/utils.h b/utils/utils.h
index 80298a4..9be859e 100644
--- a/utils/utils.h
+++ b/utils/utils.h
@@ -163,7 +163,7 @@ bool is_dir(const char *path);
*
* Parameters as for regcomp(), see man regex.
*/
-void regcomp_wrapper(regex_t *preg, const char *regex, int cflags);
+nserror regcomp_wrapper(regex_t *preg, const char *regex, int cflags);
/**
* Create a human redable representation of a size in bytes.
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=df89f689f7ddcb082b4...
commit df89f689f7ddcb082b4616c6e32cabbb859b3a11
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
make the pseudo css fetcher report initialisation errors
diff --git a/render/html_css.c b/render/html_css.c
index 3d9012f..89ab447 100644
--- a/render/html_css.c
+++ b/render/html_css.c
@@ -632,7 +632,9 @@ nserror html_css_init(void)
{
nserror error;
- html_css_fetcher_register();
+ error = html_css_fetcher_register();
+ if (error != NSERROR_OK)
+ return error;
error = nsurl_create("resource:default.css",
&html_default_stylesheet_url);
diff --git a/render/html_css_fetcher.c b/render/html_css_fetcher.c
index 3df1528..8ac9123 100644
--- a/render/html_css_fetcher.c
+++ b/render/html_css_fetcher.c
@@ -274,7 +274,8 @@ static void html_css_fetcher_poll(lwc_string *scheme)
} while ( (c = next) != ring && ring != NULL);
}
-void html_css_fetcher_register(void)
+/* exported interface documented in html_internal.h */
+nserror html_css_fetcher_register(void)
{
lwc_string *scheme;
const struct fetcher_operation_table html_css_fetcher_ops = {
@@ -289,16 +290,17 @@ void html_css_fetcher_register(void)
};
if (lwc_intern_string("x-ns-css", SLEN("x-ns-css"),
- &scheme) != lwc_error_ok) {
- die("Failed to initialise the fetch module "
- "(couldn't intern \"x-ns-css\").");
+ &scheme) != lwc_error_ok) {
+ LOG(("could not intern \"x-ns-css\"."));
+ return NSERROR_INIT_FAILED;
}
- fetcher_add(scheme, &html_css_fetcher_ops);
+ return fetcher_add(scheme, &html_css_fetcher_ops);
}
-nserror html_css_fetcher_add_item(dom_string *data, nsurl *base_url,
- uint32_t *key)
+/* exported interface documented in html_internal.h */
+nserror
+html_css_fetcher_add_item(dom_string *data, nsurl *base_url, uint32_t *key)
{
html_css_fetcher_item *item = malloc(sizeof(*item));
diff --git a/render/html_internal.h b/render/html_internal.h
index 28522dc..b57f240 100644
--- a/render/html_internal.h
+++ b/render/html_internal.h
@@ -293,7 +293,12 @@ nserror html_css_new_selection_context(html_content *c,
css_select_ctx **ret_select_ctx);
/* in render/html_css_fetcher.c */
-void html_css_fetcher_register(void);
+/**
+ * Register the fetcher for the pseudo x-ns-css scheme.
+ *
+ * \return NSERROR_OK on successful registration or error code on failure.
+ */
+nserror html_css_fetcher_register(void);
nserror html_css_fetcher_add_item(dom_string *data, nsurl *base_url,
uint32_t *key);
-----------------------------------------------------------------------
Summary of changes:
render/html_css.c | 4 +++-
render/html_css_fetcher.c | 16 +++++++++-------
render/html_internal.h | 7 ++++++-
utils/url.c | 12 +++++++++---
utils/url.h | 2 +-
utils/utils.c | 9 ++++++---
utils/utils.h | 2 +-
7 files changed, 35 insertions(+), 17 deletions(-)
diff --git a/render/html_css.c b/render/html_css.c
index 3d9012f..89ab447 100644
--- a/render/html_css.c
+++ b/render/html_css.c
@@ -632,7 +632,9 @@ nserror html_css_init(void)
{
nserror error;
- html_css_fetcher_register();
+ error = html_css_fetcher_register();
+ if (error != NSERROR_OK)
+ return error;
error = nsurl_create("resource:default.css",
&html_default_stylesheet_url);
diff --git a/render/html_css_fetcher.c b/render/html_css_fetcher.c
index 3df1528..8ac9123 100644
--- a/render/html_css_fetcher.c
+++ b/render/html_css_fetcher.c
@@ -274,7 +274,8 @@ static void html_css_fetcher_poll(lwc_string *scheme)
} while ( (c = next) != ring && ring != NULL);
}
-void html_css_fetcher_register(void)
+/* exported interface documented in html_internal.h */
+nserror html_css_fetcher_register(void)
{
lwc_string *scheme;
const struct fetcher_operation_table html_css_fetcher_ops = {
@@ -289,16 +290,17 @@ void html_css_fetcher_register(void)
};
if (lwc_intern_string("x-ns-css", SLEN("x-ns-css"),
- &scheme) != lwc_error_ok) {
- die("Failed to initialise the fetch module "
- "(couldn't intern \"x-ns-css\").");
+ &scheme) != lwc_error_ok) {
+ LOG(("could not intern \"x-ns-css\"."));
+ return NSERROR_INIT_FAILED;
}
- fetcher_add(scheme, &html_css_fetcher_ops);
+ return fetcher_add(scheme, &html_css_fetcher_ops);
}
-nserror html_css_fetcher_add_item(dom_string *data, nsurl *base_url,
- uint32_t *key)
+/* exported interface documented in html_internal.h */
+nserror
+html_css_fetcher_add_item(dom_string *data, nsurl *base_url, uint32_t *key)
{
html_css_fetcher_item *item = malloc(sizeof(*item));
diff --git a/render/html_internal.h b/render/html_internal.h
index 28522dc..b57f240 100644
--- a/render/html_internal.h
+++ b/render/html_internal.h
@@ -293,7 +293,12 @@ nserror html_css_new_selection_context(html_content *c,
css_select_ctx **ret_select_ctx);
/* in render/html_css_fetcher.c */
-void html_css_fetcher_register(void);
+/**
+ * Register the fetcher for the pseudo x-ns-css scheme.
+ *
+ * \return NSERROR_OK on successful registration or error code on failure.
+ */
+nserror html_css_fetcher_register(void);
nserror html_css_fetcher_add_item(dom_string *data, nsurl *base_url,
uint32_t *key);
diff --git a/utils/url.c b/utils/url.c
index 37fa939..949478e 100644
--- a/utils/url.c
+++ b/utils/url.c
@@ -44,10 +44,12 @@ struct url_components_internal {
regex_t url_re, url_up_re;
/* exported interface documented in utils/url.h */
-void url_init(void)
+nserror url_init(void)
{
+ nserror ret;
+
/* regex from RFC 2396 */
- regcomp_wrapper(&url_re, "^[[:space:]]*"
+ ret = regcomp_wrapper(&url_re, "^[[:space:]]*"
#define URL_RE_SCHEME 2
"(([a-zA-Z][-a-zA-Z0-9+.]*):)?"
#define URL_RE_AUTHORITY 4
@@ -59,7 +61,11 @@ void url_init(void)
#define URL_RE_FRAGMENT 9
"(#([^[:space:]]*))?"
"[[:space:]]*$", REG_EXTENDED);
- regcomp_wrapper(&url_up_re,
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ return regcomp_wrapper(&url_up_re,
"/([^/]?|[.][^./]|[^./][.]|[^./][^./]|[^/][^/][^/]+)"
"/[.][.](/|$)",
REG_EXTENDED);
diff --git a/utils/url.h b/utils/url.h
index f1aff0e..aac4e57 100644
--- a/utils/url.h
+++ b/utils/url.h
@@ -49,7 +49,7 @@ struct url_components {
*
* Compiles regular expressions required by the url_ functions.
*/
-void url_init(void);
+nserror url_init(void);
/**
diff --git a/utils/utils.c b/utils/utils.c
index 6199a84..6730c9f 100644
--- a/utils/utils.c
+++ b/utils/utils.c
@@ -33,6 +33,7 @@
#include <time.h>
#include "utils/config.h"
+#include "utils/log.h"
#include "utils/messages.h"
#include "utils/utf8.h"
#include "utils/time.h"
@@ -207,18 +208,20 @@ nserror snstrjoin(char **str, size_t *size, char sep, size_t nelm, ...)
/* exported interface documented in utils/utils.h */
-void regcomp_wrapper(regex_t *preg, const char *regex, int cflags)
+nserror regcomp_wrapper(regex_t *preg, const char *regex, int cflags)
{
int r;
r = regcomp(preg, regex, cflags);
if (r) {
char errbuf[200];
regerror(r, preg, errbuf, sizeof errbuf);
- fprintf(stderr, "Failed to compile regexp '%s'\n", regex);
- die(errbuf);
+ LOG(("Failed to compile regexp '%s': %s\n", regex, errbuf));
+ return NSERROR_INIT_FAILED;
}
+ return NSERROR_OK;
}
+
/**
* The size of buffers within human_friendly_bytesize.
*
diff --git a/utils/utils.h b/utils/utils.h
index 80298a4..9be859e 100644
--- a/utils/utils.h
+++ b/utils/utils.h
@@ -163,7 +163,7 @@ bool is_dir(const char *path);
*
* Parameters as for regcomp(), see man regex.
*/
-void regcomp_wrapper(regex_t *preg, const char *regex, int cflags);
+nserror regcomp_wrapper(regex_t *preg, const char *regex, int cflags);
/**
* Create a human redable representation of a size in bytes.
--
NetSurf Browser
8 years, 3 months
netsurf: branch master updated. release/3.2-242-g49873c8
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/49873c8bf3e50ba0c7b8d...
...commit http://git.netsurf-browser.org/netsurf.git/commit/49873c8bf3e50ba0c7b8d41...
...tree http://git.netsurf-browser.org/netsurf.git/tree/49873c8bf3e50ba0c7b8d4144...
The branch, master has been updated
via 49873c8bf3e50ba0c7b8d41442ac287ed73e7a47 (commit)
from d89f654fbe47a3b6f1e517de968f3d0c537df7a6 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=49873c8bf3e50ba0c7b...
commit 49873c8bf3e50ba0c7b8d41442ac287ed73e7a47
Author: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Commit: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Cache size gadget width
diff --git a/amiga/gui.c b/amiga/gui.c
index 131491c..e210c98 100644
--- a/amiga/gui.c
+++ b/amiga/gui.c
@@ -177,6 +177,7 @@ Class *urlStringClass;
BOOL locked_screen = FALSE;
BOOL screen_closed = FALSE;
int screen_signal = -1;
+ULONG sz_gad_width = 0;
struct MsgPort *applibport = NULL;
ULONG applibsig = 0;
@@ -3901,24 +3902,23 @@ static ULONG ami_get_border_gadget_balance(struct gui_window_2 *gwin, ULONG *siz
** Returns the width of the size gadget as a convenience.
*/
- ULONG sz;
ULONG available_width;
float gad1percent;
- struct DrawInfo *dri = GetScreenDrawInfo(scrn);
- GetGUIAttrs(NULL, dri, GUIA_SizeGadgetWidth, &sz, TAG_DONE);
- FreeScreenDrawInfo(scrn, dri);
-
- sz = 24; /* old calculated width on my system */
+ if(sz_gad_width == 0) {
+ struct DrawInfo *dri = GetScreenDrawInfo(scrn);
+ GetGUIAttrs(NULL, dri, GUIA_SizeGadgetWidth, &sz_gad_width, TAG_DONE);
+ FreeScreenDrawInfo(scrn, dri);
+ }
- available_width = gwin->win->Width - scrn->WBorLeft - sz;
+ available_width = gwin->win->Width - scrn->WBorLeft - sz_gad_width;
gad1percent = nsoption_int(toolbar_status_size) / 10000.0;
*size1 = (ULONG)(available_width * gad1percent);
*size2 = (ULONG)(available_width * (1 - gad1percent));
- return sz;
+ return sz_gad_width;
}
void ami_close_all_tabs(struct gui_window_2 *gwin)
-----------------------------------------------------------------------
Summary of changes:
amiga/gui.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/amiga/gui.c b/amiga/gui.c
index 131491c..e210c98 100644
--- a/amiga/gui.c
+++ b/amiga/gui.c
@@ -177,6 +177,7 @@ Class *urlStringClass;
BOOL locked_screen = FALSE;
BOOL screen_closed = FALSE;
int screen_signal = -1;
+ULONG sz_gad_width = 0;
struct MsgPort *applibport = NULL;
ULONG applibsig = 0;
@@ -3901,24 +3902,23 @@ static ULONG ami_get_border_gadget_balance(struct gui_window_2 *gwin, ULONG *siz
** Returns the width of the size gadget as a convenience.
*/
- ULONG sz;
ULONG available_width;
float gad1percent;
- struct DrawInfo *dri = GetScreenDrawInfo(scrn);
- GetGUIAttrs(NULL, dri, GUIA_SizeGadgetWidth, &sz, TAG_DONE);
- FreeScreenDrawInfo(scrn, dri);
-
- sz = 24; /* old calculated width on my system */
+ if(sz_gad_width == 0) {
+ struct DrawInfo *dri = GetScreenDrawInfo(scrn);
+ GetGUIAttrs(NULL, dri, GUIA_SizeGadgetWidth, &sz_gad_width, TAG_DONE);
+ FreeScreenDrawInfo(scrn, dri);
+ }
- available_width = gwin->win->Width - scrn->WBorLeft - sz;
+ available_width = gwin->win->Width - scrn->WBorLeft - sz_gad_width;
gad1percent = nsoption_int(toolbar_status_size) / 10000.0;
*size1 = (ULONG)(available_width * gad1percent);
*size2 = (ULONG)(available_width * (1 - gad1percent));
- return sz;
+ return sz_gad_width;
}
void ami_close_all_tabs(struct gui_window_2 *gwin)
--
NetSurf Browser
8 years, 3 months
netsurf: branch master updated. release/3.2-241-gd89f654
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/d89f654fbe47a3b6f1e51...
...commit http://git.netsurf-browser.org/netsurf.git/commit/d89f654fbe47a3b6f1e517d...
...tree http://git.netsurf-browser.org/netsurf.git/tree/d89f654fbe47a3b6f1e517de9...
The branch, master has been updated
via d89f654fbe47a3b6f1e517de968f3d0c537df7a6 (commit)
from a2e999584cbb7939870700b6b6b62c3da150413f (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=d89f654fbe47a3b6f1e...
commit d89f654fbe47a3b6f1e517de968f3d0c537df7a6
Author: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Commit: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Correct comment
diff --git a/amiga/gui.c b/amiga/gui.c
index 9f4cfee..131491c 100644
--- a/amiga/gui.c
+++ b/amiga/gui.c
@@ -3898,8 +3898,7 @@ static void ami_set_border_gadget_balance(struct gui_window_2 *gwin)
static ULONG ami_get_border_gadget_balance(struct gui_window_2 *gwin, ULONG *size1, ULONG *size2)
{
/* Get the sizes that border gadget 1 (status) and 2 (hscroller) need to be.
- ** Returns the width of the vertical scroller (right-hand window border) as
- ** a convenience.
+ ** Returns the width of the size gadget as a convenience.
*/
ULONG sz;
-----------------------------------------------------------------------
Summary of changes:
amiga/gui.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/amiga/gui.c b/amiga/gui.c
index 9f4cfee..131491c 100644
--- a/amiga/gui.c
+++ b/amiga/gui.c
@@ -3898,8 +3898,7 @@ static void ami_set_border_gadget_balance(struct gui_window_2 *gwin)
static ULONG ami_get_border_gadget_balance(struct gui_window_2 *gwin, ULONG *size1, ULONG *size2)
{
/* Get the sizes that border gadget 1 (status) and 2 (hscroller) need to be.
- ** Returns the width of the vertical scroller (right-hand window border) as
- ** a convenience.
+ ** Returns the width of the size gadget as a convenience.
*/
ULONG sz;
--
NetSurf Browser
8 years, 3 months
netsurf: branch master updated. release/3.2-240-ga2e9995
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/a2e999584cbb793987070...
...commit http://git.netsurf-browser.org/netsurf.git/commit/a2e999584cbb7939870700b...
...tree http://git.netsurf-browser.org/netsurf.git/tree/a2e999584cbb7939870700b6b...
The branch, master has been updated
via a2e999584cbb7939870700b6b6b62c3da150413f (commit)
via 41b08da31a72084cc3af06edda15905f66e6a0bf (commit)
via b2ff4877e43c33cf26de6f9880745259b5237ebb (commit)
from 7e95b7ffb107fb8502aec3fd9eebe64127487a85 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=a2e999584cbb7939870...
commit a2e999584cbb7939870700b6b6b62c3da150413f
Author: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Commit: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Use the correct size gadget width (thx tboeckel)
diff --git a/amiga/gui.c b/amiga/gui.c
index bc46821..9f4cfee 100644
--- a/amiga/gui.c
+++ b/amiga/gui.c
@@ -3906,11 +3906,10 @@ static ULONG ami_get_border_gadget_balance(struct gui_window_2 *gwin, ULONG *siz
ULONG available_width;
float gad1percent;
- /** \TODO sz is supposed to be the width of the window's size gadget,
- possibly + scrn->WBorRight.
- if(gwin->objects[GID_VSCROLL])
- GetAttr(GA_Width, gwin->objects[GID_VSCROLL], (ULONG *)&sz);
- */
+ struct DrawInfo *dri = GetScreenDrawInfo(scrn);
+ GetGUIAttrs(NULL, dri, GUIA_SizeGadgetWidth, &sz, TAG_DONE);
+ FreeScreenDrawInfo(scrn, dri);
+
sz = 24; /* old calculated width on my system */
available_width = gwin->win->Width - scrn->WBorLeft - sz;
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=41b08da31a72084cc3a...
commit 41b08da31a72084cc3af06edda15905f66e6a0bf
Author: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Commit: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Check scroller requirement after a resize
diff --git a/amiga/gui.c b/amiga/gui.c
index 4722b17..bc46821 100644
--- a/amiga/gui.c
+++ b/amiga/gui.c
@@ -1359,6 +1359,102 @@ static void ami_gui_menu_update_all(void)
} while((node = nnode));
}
+static void gui_window_get_dimensions(struct gui_window *g, int *width, int *height,
+ bool scaled)
+{
+ struct IBox *bbox;
+ if(!g) return;
+
+ GetAttr(SPACE_AreaBox, g->shared->objects[GID_BROWSER], (ULONG *)&bbox);
+
+ *width = bbox->Width;
+ *height = bbox->Height;
+
+ if(scaled)
+ {
+ *width /= g->shared->bw->scale;
+ *height /= g->shared->bw->scale;
+ }
+}
+
+/* Add a vertical scroller, if not already present
+ * Returns true if changed, false otherwise */
+static bool ami_gui_vscroll_add(struct gui_window_2 *gwin)
+{
+ struct TagItem attrs[2];
+
+ if(gwin->objects[GID_VSCROLL] != NULL) return false;
+
+ attrs[0].ti_Tag = CHILD_MinWidth;
+ attrs[0].ti_Data = 0;
+ attrs[1].ti_Tag = TAG_DONE;
+ attrs[1].ti_Data = 0;
+
+ gwin->objects[GID_VSCROLL] = ScrollerObject,
+ GA_ID, GID_VSCROLL,
+ GA_RelVerify, TRUE,
+ ICA_TARGET, ICTARGET_IDCMP,
+ ScrollerEnd;
+
+ IDoMethod(gwin->objects[GID_VSCROLLLAYOUT], LM_ADDCHILD,
+ gwin->win, gwin->objects[GID_VSCROLL], attrs);
+
+ return true;
+}
+
+/* Remove the vertical scroller, if present */
+static bool ami_gui_vscroll_remove(struct gui_window_2 *gwin)
+{
+ if(gwin->objects[GID_VSCROLL] == NULL) return false;
+
+ IDoMethod(gwin->objects[GID_VSCROLLLAYOUT], LM_REMOVECHILD,
+ gwin->win, gwin->objects[GID_VSCROLL]);
+
+ gwin->objects[GID_VSCROLL] = NULL;
+
+ return true;
+}
+
+/**
+ * Check the scroll bar requirements for a browser window, and add/remove
+ * the vertical scroller as appropriate. This should be the main entry
+ * point used to perform this task.
+ *
+ * \param gwin "Shared" GUI window to check the state of
+ */
+static void ami_gui_vscroll_update(struct gui_window_2 *gwin)
+{
+ bool rethink = false;
+ browser_scrolling hscroll = BW_SCROLLING_YES;
+ browser_scrolling vscroll = BW_SCROLLING_YES;
+
+ browser_window_get_scrollbar_type(gwin->bw, &hscroll, &vscroll);
+
+ /* We only bother with vscroll, as the hscroller is embedded in the
+ bottom window border with the status bar, so toggling it is pointless */
+
+ if((vscroll == BW_SCROLLING_NO) || browser_window_is_frameset(gwin->bw) == true) {
+ rethink = ami_gui_vscroll_remove(gwin);
+ } else {
+ int h, w, wh, ww;
+ if((browser_window_get_extents(gwin->bw, false, &w, &h) == NSERROR_OK)) {
+ gui_window_get_dimensions(gwin->bw->window, &ww, &wh, false);
+ if (h > wh) rethink = ami_gui_vscroll_add(gwin);
+ else rethink = ami_gui_vscroll_remove(gwin);
+ } else {
+ rethink = ami_gui_vscroll_add(gwin);
+ }
+ }
+
+ if(rethink) {
+ FlushLayoutDomainCache((struct Gadget *)gwin->objects[GID_MAIN]);
+ RethinkLayout((struct Gadget *)gwin->objects[GID_MAIN],
+ gwin->win, NULL, TRUE);
+ browser_window_schedule_reformat(gwin->bw);
+ ami_schedule_redraw(gwin, true);
+ }
+}
+
/**
* function to add retrieved favicon to gui
*/
@@ -2124,6 +2220,7 @@ static void ami_handle_msg(void)
struct browser_window *bw = NULL;
case AMINS_WINDOW:
+ ami_gui_vscroll_update(gwin);
ami_set_border_gadget_balance(gwin);
ami_throbber_redraw_schedule(0, gwin->bw->window);
@@ -2507,102 +2604,6 @@ void ami_get_msg(void)
ami_quit_netsurf_delayed();
}
-static void gui_window_get_dimensions(struct gui_window *g, int *width, int *height,
- bool scaled)
-{
- struct IBox *bbox;
- if(!g) return;
-
- GetAttr(SPACE_AreaBox, g->shared->objects[GID_BROWSER], (ULONG *)&bbox);
-
- *width = bbox->Width;
- *height = bbox->Height;
-
- if(scaled)
- {
- *width /= g->shared->bw->scale;
- *height /= g->shared->bw->scale;
- }
-}
-
-/* Add a vertical scroller, if not already present
- * Returns true if changed, false otherwise */
-static bool ami_gui_vscroll_add(struct gui_window_2 *gwin)
-{
- struct TagItem attrs[2];
-
- if(gwin->objects[GID_VSCROLL] != NULL) return false;
-
- attrs[0].ti_Tag = CHILD_MinWidth;
- attrs[0].ti_Data = 0;
- attrs[1].ti_Tag = TAG_DONE;
- attrs[1].ti_Data = 0;
-
- gwin->objects[GID_VSCROLL] = ScrollerObject,
- GA_ID, GID_VSCROLL,
- GA_RelVerify, TRUE,
- ICA_TARGET, ICTARGET_IDCMP,
- ScrollerEnd;
-
- IDoMethod(gwin->objects[GID_VSCROLLLAYOUT], LM_ADDCHILD,
- gwin->win, gwin->objects[GID_VSCROLL], attrs);
-
- return true;
-}
-
-/* Remove the vertical scroller, if present */
-static bool ami_gui_vscroll_remove(struct gui_window_2 *gwin)
-{
- if(gwin->objects[GID_VSCROLL] == NULL) return false;
-
- IDoMethod(gwin->objects[GID_VSCROLLLAYOUT], LM_REMOVECHILD,
- gwin->win, gwin->objects[GID_VSCROLL]);
-
- gwin->objects[GID_VSCROLL] = NULL;
-
- return true;
-}
-
-/**
- * Check the scroll bar requirements for a browser window, and add/remove
- * the vertical scroller as appropriate. This should be the main entry
- * point used to perform this task.
- *
- * \param gwin "Shared" GUI window to check the state of
- */
-static void ami_gui_vscroll_update(struct gui_window_2 *gwin)
-{
- bool rethink = false;
- browser_scrolling hscroll = BW_SCROLLING_YES;
- browser_scrolling vscroll = BW_SCROLLING_YES;
-
- browser_window_get_scrollbar_type(gwin->bw, &hscroll, &vscroll);
-
- /* We only bother with vscroll, as the hscroller is embedded in the
- bottom window border with the status bar, so toggling it is pointless */
-
- if((vscroll == BW_SCROLLING_NO) || browser_window_is_frameset(gwin->bw) == true) {
- rethink = ami_gui_vscroll_remove(gwin);
- } else {
- int h, w, wh, ww;
- if((browser_window_get_extents(gwin->bw, false, &w, &h) == NSERROR_OK)) {
- gui_window_get_dimensions(gwin->bw->window, &ww, &wh, false);
- if (h > wh) rethink = ami_gui_vscroll_add(gwin);
- else rethink = ami_gui_vscroll_remove(gwin);
- } else {
- rethink = ami_gui_vscroll_add(gwin);
- }
- }
-
- if(rethink) {
- FlushLayoutDomainCache((struct Gadget *)gwin->objects[GID_MAIN]);
- RethinkLayout((struct Gadget *)gwin->objects[GID_MAIN],
- gwin->win, NULL, TRUE);
- browser_window_schedule_reformat(gwin->bw);
- ami_schedule_redraw(gwin, true);
- }
-}
-
void ami_change_tab(struct gui_window_2 *gwin, int direction)
{
struct Node *tab_node = gwin->bw->window->tab_node;
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=b2ff4877e43c33cf26d...
commit b2ff4877e43c33cf26de6f9880745259b5237ebb
Author: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Commit: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Remove the vertical scroll bar if there's nothing to scroll
diff --git a/amiga/gui.c b/amiga/gui.c
index e39d9e7..4722b17 100644
--- a/amiga/gui.c
+++ b/amiga/gui.c
@@ -2507,6 +2507,24 @@ void ami_get_msg(void)
ami_quit_netsurf_delayed();
}
+static void gui_window_get_dimensions(struct gui_window *g, int *width, int *height,
+ bool scaled)
+{
+ struct IBox *bbox;
+ if(!g) return;
+
+ GetAttr(SPACE_AreaBox, g->shared->objects[GID_BROWSER], (ULONG *)&bbox);
+
+ *width = bbox->Width;
+ *height = bbox->Height;
+
+ if(scaled)
+ {
+ *width /= g->shared->bw->scale;
+ *height /= g->shared->bw->scale;
+ }
+}
+
/* Add a vertical scroller, if not already present
* Returns true if changed, false otherwise */
static bool ami_gui_vscroll_add(struct gui_window_2 *gwin)
@@ -2566,7 +2584,14 @@ static void ami_gui_vscroll_update(struct gui_window_2 *gwin)
if((vscroll == BW_SCROLLING_NO) || browser_window_is_frameset(gwin->bw) == true) {
rethink = ami_gui_vscroll_remove(gwin);
} else {
- rethink = ami_gui_vscroll_add(gwin);
+ int h, w, wh, ww;
+ if((browser_window_get_extents(gwin->bw, false, &w, &h) == NSERROR_OK)) {
+ gui_window_get_dimensions(gwin->bw->window, &ww, &wh, false);
+ if (h > wh) rethink = ami_gui_vscroll_add(gwin);
+ else rethink = ami_gui_vscroll_remove(gwin);
+ } else {
+ rethink = ami_gui_vscroll_add(gwin);
+ }
}
if(rethink) {
@@ -4631,24 +4656,6 @@ static void gui_window_set_scroll(struct gui_window *g, int sx, int sy)
// g->shared->new_content = false;
}
-static void gui_window_get_dimensions(struct gui_window *g, int *width, int *height,
- bool scaled)
-{
- struct IBox *bbox;
- if(!g) return;
-
- GetAttr(SPACE_AreaBox, g->shared->objects[GID_BROWSER], (ULONG *)&bbox);
-
- *width = bbox->Width;
- *height = bbox->Height;
-
- if(scaled)
- {
- *width /= g->shared->bw->scale;
- *height /= g->shared->bw->scale;
- }
-}
-
static void gui_window_update_extent(struct gui_window *g)
{
struct IBox *bbox;
-----------------------------------------------------------------------
Summary of changes:
amiga/gui.c | 195 +++++++++++++++++++++++++++++++----------------------------
1 file changed, 101 insertions(+), 94 deletions(-)
diff --git a/amiga/gui.c b/amiga/gui.c
index e39d9e7..9f4cfee 100644
--- a/amiga/gui.c
+++ b/amiga/gui.c
@@ -1359,6 +1359,102 @@ static void ami_gui_menu_update_all(void)
} while((node = nnode));
}
+static void gui_window_get_dimensions(struct gui_window *g, int *width, int *height,
+ bool scaled)
+{
+ struct IBox *bbox;
+ if(!g) return;
+
+ GetAttr(SPACE_AreaBox, g->shared->objects[GID_BROWSER], (ULONG *)&bbox);
+
+ *width = bbox->Width;
+ *height = bbox->Height;
+
+ if(scaled)
+ {
+ *width /= g->shared->bw->scale;
+ *height /= g->shared->bw->scale;
+ }
+}
+
+/* Add a vertical scroller, if not already present
+ * Returns true if changed, false otherwise */
+static bool ami_gui_vscroll_add(struct gui_window_2 *gwin)
+{
+ struct TagItem attrs[2];
+
+ if(gwin->objects[GID_VSCROLL] != NULL) return false;
+
+ attrs[0].ti_Tag = CHILD_MinWidth;
+ attrs[0].ti_Data = 0;
+ attrs[1].ti_Tag = TAG_DONE;
+ attrs[1].ti_Data = 0;
+
+ gwin->objects[GID_VSCROLL] = ScrollerObject,
+ GA_ID, GID_VSCROLL,
+ GA_RelVerify, TRUE,
+ ICA_TARGET, ICTARGET_IDCMP,
+ ScrollerEnd;
+
+ IDoMethod(gwin->objects[GID_VSCROLLLAYOUT], LM_ADDCHILD,
+ gwin->win, gwin->objects[GID_VSCROLL], attrs);
+
+ return true;
+}
+
+/* Remove the vertical scroller, if present */
+static bool ami_gui_vscroll_remove(struct gui_window_2 *gwin)
+{
+ if(gwin->objects[GID_VSCROLL] == NULL) return false;
+
+ IDoMethod(gwin->objects[GID_VSCROLLLAYOUT], LM_REMOVECHILD,
+ gwin->win, gwin->objects[GID_VSCROLL]);
+
+ gwin->objects[GID_VSCROLL] = NULL;
+
+ return true;
+}
+
+/**
+ * Check the scroll bar requirements for a browser window, and add/remove
+ * the vertical scroller as appropriate. This should be the main entry
+ * point used to perform this task.
+ *
+ * \param gwin "Shared" GUI window to check the state of
+ */
+static void ami_gui_vscroll_update(struct gui_window_2 *gwin)
+{
+ bool rethink = false;
+ browser_scrolling hscroll = BW_SCROLLING_YES;
+ browser_scrolling vscroll = BW_SCROLLING_YES;
+
+ browser_window_get_scrollbar_type(gwin->bw, &hscroll, &vscroll);
+
+ /* We only bother with vscroll, as the hscroller is embedded in the
+ bottom window border with the status bar, so toggling it is pointless */
+
+ if((vscroll == BW_SCROLLING_NO) || browser_window_is_frameset(gwin->bw) == true) {
+ rethink = ami_gui_vscroll_remove(gwin);
+ } else {
+ int h, w, wh, ww;
+ if((browser_window_get_extents(gwin->bw, false, &w, &h) == NSERROR_OK)) {
+ gui_window_get_dimensions(gwin->bw->window, &ww, &wh, false);
+ if (h > wh) rethink = ami_gui_vscroll_add(gwin);
+ else rethink = ami_gui_vscroll_remove(gwin);
+ } else {
+ rethink = ami_gui_vscroll_add(gwin);
+ }
+ }
+
+ if(rethink) {
+ FlushLayoutDomainCache((struct Gadget *)gwin->objects[GID_MAIN]);
+ RethinkLayout((struct Gadget *)gwin->objects[GID_MAIN],
+ gwin->win, NULL, TRUE);
+ browser_window_schedule_reformat(gwin->bw);
+ ami_schedule_redraw(gwin, true);
+ }
+}
+
/**
* function to add retrieved favicon to gui
*/
@@ -2124,6 +2220,7 @@ static void ami_handle_msg(void)
struct browser_window *bw = NULL;
case AMINS_WINDOW:
+ ami_gui_vscroll_update(gwin);
ami_set_border_gadget_balance(gwin);
ami_throbber_redraw_schedule(0, gwin->bw->window);
@@ -2507,77 +2604,6 @@ void ami_get_msg(void)
ami_quit_netsurf_delayed();
}
-/* Add a vertical scroller, if not already present
- * Returns true if changed, false otherwise */
-static bool ami_gui_vscroll_add(struct gui_window_2 *gwin)
-{
- struct TagItem attrs[2];
-
- if(gwin->objects[GID_VSCROLL] != NULL) return false;
-
- attrs[0].ti_Tag = CHILD_MinWidth;
- attrs[0].ti_Data = 0;
- attrs[1].ti_Tag = TAG_DONE;
- attrs[1].ti_Data = 0;
-
- gwin->objects[GID_VSCROLL] = ScrollerObject,
- GA_ID, GID_VSCROLL,
- GA_RelVerify, TRUE,
- ICA_TARGET, ICTARGET_IDCMP,
- ScrollerEnd;
-
- IDoMethod(gwin->objects[GID_VSCROLLLAYOUT], LM_ADDCHILD,
- gwin->win, gwin->objects[GID_VSCROLL], attrs);
-
- return true;
-}
-
-/* Remove the vertical scroller, if present */
-static bool ami_gui_vscroll_remove(struct gui_window_2 *gwin)
-{
- if(gwin->objects[GID_VSCROLL] == NULL) return false;
-
- IDoMethod(gwin->objects[GID_VSCROLLLAYOUT], LM_REMOVECHILD,
- gwin->win, gwin->objects[GID_VSCROLL]);
-
- gwin->objects[GID_VSCROLL] = NULL;
-
- return true;
-}
-
-/**
- * Check the scroll bar requirements for a browser window, and add/remove
- * the vertical scroller as appropriate. This should be the main entry
- * point used to perform this task.
- *
- * \param gwin "Shared" GUI window to check the state of
- */
-static void ami_gui_vscroll_update(struct gui_window_2 *gwin)
-{
- bool rethink = false;
- browser_scrolling hscroll = BW_SCROLLING_YES;
- browser_scrolling vscroll = BW_SCROLLING_YES;
-
- browser_window_get_scrollbar_type(gwin->bw, &hscroll, &vscroll);
-
- /* We only bother with vscroll, as the hscroller is embedded in the
- bottom window border with the status bar, so toggling it is pointless */
-
- if((vscroll == BW_SCROLLING_NO) || browser_window_is_frameset(gwin->bw) == true) {
- rethink = ami_gui_vscroll_remove(gwin);
- } else {
- rethink = ami_gui_vscroll_add(gwin);
- }
-
- if(rethink) {
- FlushLayoutDomainCache((struct Gadget *)gwin->objects[GID_MAIN]);
- RethinkLayout((struct Gadget *)gwin->objects[GID_MAIN],
- gwin->win, NULL, TRUE);
- browser_window_schedule_reformat(gwin->bw);
- ami_schedule_redraw(gwin, true);
- }
-}
-
void ami_change_tab(struct gui_window_2 *gwin, int direction)
{
struct Node *tab_node = gwin->bw->window->tab_node;
@@ -3880,11 +3906,10 @@ static ULONG ami_get_border_gadget_balance(struct gui_window_2 *gwin, ULONG *siz
ULONG available_width;
float gad1percent;
- /** \TODO sz is supposed to be the width of the window's size gadget,
- possibly + scrn->WBorRight.
- if(gwin->objects[GID_VSCROLL])
- GetAttr(GA_Width, gwin->objects[GID_VSCROLL], (ULONG *)&sz);
- */
+ struct DrawInfo *dri = GetScreenDrawInfo(scrn);
+ GetGUIAttrs(NULL, dri, GUIA_SizeGadgetWidth, &sz, TAG_DONE);
+ FreeScreenDrawInfo(scrn, dri);
+
sz = 24; /* old calculated width on my system */
available_width = gwin->win->Width - scrn->WBorLeft - sz;
@@ -4631,24 +4656,6 @@ static void gui_window_set_scroll(struct gui_window *g, int sx, int sy)
// g->shared->new_content = false;
}
-static void gui_window_get_dimensions(struct gui_window *g, int *width, int *height,
- bool scaled)
-{
- struct IBox *bbox;
- if(!g) return;
-
- GetAttr(SPACE_AreaBox, g->shared->objects[GID_BROWSER], (ULONG *)&bbox);
-
- *width = bbox->Width;
- *height = bbox->Height;
-
- if(scaled)
- {
- *width /= g->shared->bw->scale;
- *height /= g->shared->bw->scale;
- }
-}
-
static void gui_window_update_extent(struct gui_window *g)
{
struct IBox *bbox;
--
NetSurf Browser
8 years, 3 months
netsurf: branch master updated. release/3.2-237-g7e95b7f
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/7e95b7ffb107fb8502aec...
...commit http://git.netsurf-browser.org/netsurf.git/commit/7e95b7ffb107fb8502aec3f...
...tree http://git.netsurf-browser.org/netsurf.git/tree/7e95b7ffb107fb8502aec3fd9...
The branch, master has been updated
via 7e95b7ffb107fb8502aec3fd9eebe64127487a85 (commit)
via b7b4db8520b803120b9848442be075c4ffc9cc55 (commit)
via d31aa9a95933413b4c51f60689710fd76944b96d (commit)
via 2ad41a78c4501b2b17903bcd259b5b12a85d7dc2 (commit)
via 8d930afb3d6ba353149c31a3520352502eab6c0c (commit)
via 088c03a9b76211b3be39b54c2be9a08089290946 (commit)
via e22273c0ff11e7d457b6cd5c4ba1edd2031fc6d9 (commit)
via 8590780ff5bbdb76a5f77e22f6242491262fc2b0 (commit)
via 90e6cf85b68df8ec84d67bfb5f48b05446142f07 (commit)
via f5d866ab700534e86579952e5f74944bf57aa526 (commit)
via 6034e69ad14b23eb808c713b6e40d4d96609e2f5 (commit)
via 78a8f1d96749b3e3242d03cbafbec708d290ae91 (commit)
via f787b22594c43e1ff786dfe23054aa634547993a (commit)
via f9ed0af8d8551ede4100566f2d49494d68a4c0d6 (commit)
from 53f0f432dd2aa915765e3b2869928a18f09adad8 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=7e95b7ffb107fb8502a...
commit 7e95b7ffb107fb8502aec3fd9eebe64127487a85
Author: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Commit: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Remove some old VertProp tags
diff --git a/amiga/gui.c b/amiga/gui.c
index 1b331c0..e39d9e7 100644
--- a/amiga/gui.c
+++ b/amiga/gui.c
@@ -3514,7 +3514,6 @@ gui_window_create(struct browser_window *bw,
WINDOW_IconifyGadget, iconifygadget,
WINDOW_NewMenu, g->shared->menu,
WINDOW_MenuUserData, WGUD_HOOK,
- //WINDOW_VertProp, 1,
WINDOW_NewPrefsHook, &newprefs_hook,
WINDOW_IDCMPHook, &g->shared->scrollerhook,
WINDOW_IDCMPHookBits, IDCMP_IDCMPUPDATE | IDCMP_REFRESHWINDOW |
@@ -3724,7 +3723,6 @@ gui_window_create(struct browser_window *bw,
IDCMP_GADGETUP | IDCMP_IDCMPUPDATE |
IDCMP_EXTENDEDMOUSE,
WINDOW_HorizProp,1,
- WINDOW_VertProp,1,
WINDOW_IDCMPHook,&g->shared->scrollerhook,
WINDOW_IDCMPHookBits, IDCMP_IDCMPUPDATE |
IDCMP_EXTENDEDMOUSE | IDCMP_REFRESHWINDOW,
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=b7b4db8520b803120b9...
commit b7b4db8520b803120b9848442be075c4ffc9cc55
Merge: 53f0f43 d31aa9a
Author: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Commit: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Merge branch 'chris/shorter-vscrollbar'
Move the vertical scroller into the window area and allow it to be removed when eg. framesets are being displayed.
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=d31aa9a95933413b4c5...
commit d31aa9a95933413b4c51f60689710fd76944b96d
Author: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Commit: Chris Young <chris(a)unsatisfactorysoftware.co.uk>
Use more sensible default value for size gadget width
diff --git a/amiga/gui.c b/amiga/gui.c
index eb55498..939619b 100644
--- a/amiga/gui.c
+++ b/amiga/gui.c
@@ -3882,15 +3882,16 @@ static ULONG ami_get_border_gadget_balance(struct gui_window_2 *gwin, ULONG *siz
** a convenience.
*/
- ULONG sz = 30; /* temporary arbitrary value */
+ ULONG sz;
ULONG available_width;
float gad1percent;
- /**TODO: This is getting the width of the vertical scroll bar, which is not
- necessarily the same as the width of the size gadget that we are
- supposed to be accounting for. */
+ /** \TODO sz is supposed to be the width of the window's size gadget,
+ possibly + scrn->WBorRight.
if(gwin->objects[GID_VSCROLL])
GetAttr(GA_Width, gwin->objects[GID_VSCROLL], (ULONG *)&sz);
+ */
+ sz = 24; /* old calculated width on my system */
available_width = gwin->win->Width - scrn->WBorLeft - sz;
-----------------------------------------------------------------------
Summary of changes:
amiga/gui.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++-------------
amiga/gui.h | 2 +
2 files changed, 107 insertions(+), 28 deletions(-)
diff --git a/amiga/gui.c b/amiga/gui.c
index fb3f8ac..e39d9e7 100644
--- a/amiga/gui.c
+++ b/amiga/gui.c
@@ -61,6 +61,7 @@
#include <proto/chooser.h>
#include <proto/clicktab.h>
#include <proto/layout.h>
+#include <proto/scroller.h>
#include <proto/space.h>
#include <proto/speedbar.h>
#include <proto/string.h>
@@ -2506,6 +2507,77 @@ void ami_get_msg(void)
ami_quit_netsurf_delayed();
}
+/* Add a vertical scroller, if not already present
+ * Returns true if changed, false otherwise */
+static bool ami_gui_vscroll_add(struct gui_window_2 *gwin)
+{
+ struct TagItem attrs[2];
+
+ if(gwin->objects[GID_VSCROLL] != NULL) return false;
+
+ attrs[0].ti_Tag = CHILD_MinWidth;
+ attrs[0].ti_Data = 0;
+ attrs[1].ti_Tag = TAG_DONE;
+ attrs[1].ti_Data = 0;
+
+ gwin->objects[GID_VSCROLL] = ScrollerObject,
+ GA_ID, GID_VSCROLL,
+ GA_RelVerify, TRUE,
+ ICA_TARGET, ICTARGET_IDCMP,
+ ScrollerEnd;
+
+ IDoMethod(gwin->objects[GID_VSCROLLLAYOUT], LM_ADDCHILD,
+ gwin->win, gwin->objects[GID_VSCROLL], attrs);
+
+ return true;
+}
+
+/* Remove the vertical scroller, if present */
+static bool ami_gui_vscroll_remove(struct gui_window_2 *gwin)
+{
+ if(gwin->objects[GID_VSCROLL] == NULL) return false;
+
+ IDoMethod(gwin->objects[GID_VSCROLLLAYOUT], LM_REMOVECHILD,
+ gwin->win, gwin->objects[GID_VSCROLL]);
+
+ gwin->objects[GID_VSCROLL] = NULL;
+
+ return true;
+}
+
+/**
+ * Check the scroll bar requirements for a browser window, and add/remove
+ * the vertical scroller as appropriate. This should be the main entry
+ * point used to perform this task.
+ *
+ * \param gwin "Shared" GUI window to check the state of
+ */
+static void ami_gui_vscroll_update(struct gui_window_2 *gwin)
+{
+ bool rethink = false;
+ browser_scrolling hscroll = BW_SCROLLING_YES;
+ browser_scrolling vscroll = BW_SCROLLING_YES;
+
+ browser_window_get_scrollbar_type(gwin->bw, &hscroll, &vscroll);
+
+ /* We only bother with vscroll, as the hscroller is embedded in the
+ bottom window border with the status bar, so toggling it is pointless */
+
+ if((vscroll == BW_SCROLLING_NO) || browser_window_is_frameset(gwin->bw) == true) {
+ rethink = ami_gui_vscroll_remove(gwin);
+ } else {
+ rethink = ami_gui_vscroll_add(gwin);
+ }
+
+ if(rethink) {
+ FlushLayoutDomainCache((struct Gadget *)gwin->objects[GID_MAIN]);
+ RethinkLayout((struct Gadget *)gwin->objects[GID_MAIN],
+ gwin->win, NULL, TRUE);
+ browser_window_schedule_reformat(gwin->bw);
+ ami_schedule_redraw(gwin, true);
+ }
+}
+
void ami_change_tab(struct gui_window_2 *gwin, int direction)
{
struct Node *tab_node = gwin->bw->window->tab_node;
@@ -2583,6 +2655,7 @@ void ami_switch_tab(struct gui_window_2 *gwin,bool redraw)
browser_window_refresh_url_bar(gwin->bw);
ami_gui_update_hotlist_button(gwin);
+ ami_gui_vscroll_update(gwin);
ami_throbber_redraw_schedule(0, gwin->bw->window);
}
}
@@ -3087,8 +3160,6 @@ static void ami_toggletabbar(struct gui_window_2 *gwin, bool show)
IDoMethod(gwin->objects[GID_TABLAYOUT], LM_REMOVECHILD,
gwin->win, gwin->objects[GID_ADDTAB]);
- /* NB: We are NULLing these, but not disposing them as
- * that causes an Intuition deadlock (TODO) */
gwin->objects[GID_TABS] = NULL;
gwin->objects[GID_ADDTAB] = NULL;
}
@@ -3443,7 +3514,6 @@ gui_window_create(struct browser_window *bw,
WINDOW_IconifyGadget, iconifygadget,
WINDOW_NewMenu, g->shared->menu,
WINDOW_MenuUserData, WGUD_HOOK,
- WINDOW_VertProp, 1,
WINDOW_NewPrefsHook, &newprefs_hook,
WINDOW_IDCMPHook, &g->shared->scrollerhook,
WINDOW_IDCMPHookBits, IDCMP_IDCMPUPDATE | IDCMP_REFRESHWINDOW |
@@ -3615,10 +3685,12 @@ gui_window_create(struct browser_window *bw,
CHILD_WeightedHeight,0,
LayoutEnd,
CHILD_WeightedHeight,0,
- LAYOUT_AddChild, g->shared->objects[GID_BROWSER] = SpaceObject,
- GA_ID,GID_BROWSER,
- SPACE_Transparent,TRUE,
- SpaceEnd,
+ LAYOUT_AddChild, g->shared->objects[GID_VSCROLLLAYOUT] = HGroupObject,
+ LAYOUT_AddChild, g->shared->objects[GID_BROWSER] = SpaceObject,
+ GA_ID,GID_BROWSER,
+ SPACE_Transparent,TRUE,
+ SpaceEnd,
+ EndGroup,
EndGroup,
EndWindow;
}
@@ -3651,15 +3723,14 @@ gui_window_create(struct browser_window *bw,
IDCMP_GADGETUP | IDCMP_IDCMPUPDATE |
IDCMP_EXTENDEDMOUSE,
WINDOW_HorizProp,1,
- WINDOW_VertProp,1,
WINDOW_IDCMPHook,&g->shared->scrollerhook,
WINDOW_IDCMPHookBits, IDCMP_IDCMPUPDATE |
IDCMP_EXTENDEDMOUSE | IDCMP_REFRESHWINDOW,
WINDOW_SharedPort,sport,
WINDOW_UserData,g->shared,
WINDOW_BuiltInScroll,TRUE,
- WINDOW_ParentGroup, g->shared->objects[GID_MAIN] = VGroupObject,
- LAYOUT_SpaceOuter, TRUE,
+ WINDOW_ParentGroup, g->shared->objects[GID_MAIN] = HGroupObject,
+ LAYOUT_SpaceOuter, TRUE,
LAYOUT_AddChild, g->shared->objects[GID_BROWSER] = SpaceObject,
GA_ID,GID_BROWSER,
SPACE_Transparent,TRUE,
@@ -3678,15 +3749,6 @@ gui_window_create(struct browser_window *bw,
return NULL;
}
- GetAttr(WINDOW_VertObject, g->shared->objects[OID_MAIN],
- (ULONG *)&g->shared->objects[OID_VSCROLL]);
-
- RefreshSetGadgetAttrs((struct Gadget *)(APTR)g->shared->objects[OID_VSCROLL],
- g->shared->win, NULL,
- GA_ID, OID_VSCROLL,
- ICA_TARGET, ICTARGET_IDCMP,
- TAG_DONE);
-
if(nsoption_bool(kiosk_mode) == false)
{
ULONG sz, size1, size2;
@@ -3818,7 +3880,12 @@ static ULONG ami_get_border_gadget_balance(struct gui_window_2 *gwin, ULONG *siz
ULONG available_width;
float gad1percent;
- GetAttr(GA_Width, gwin->objects[OID_VSCROLL], (ULONG *)&sz);
+ /** \TODO sz is supposed to be the width of the window's size gadget,
+ possibly + scrn->WBorRight.
+ if(gwin->objects[GID_VSCROLL])
+ GetAttr(GA_Width, gwin->objects[GID_VSCROLL], (ULONG *)&sz);
+ */
+ sz = 24; /* old calculated width on my system */
available_width = gwin->win->Width - scrn->WBorLeft - sz;
@@ -4486,7 +4553,12 @@ void ami_get_hscroll_pos(struct gui_window_2 *gwin, ULONG *xs)
void ami_get_vscroll_pos(struct gui_window_2 *gwin, ULONG *ys)
{
- GetAttr(SCROLLER_Top, gwin->objects[OID_VSCROLL], ys);
+ if(gwin->objects[GID_VSCROLL]) {
+ GetAttr(SCROLLER_Top, gwin->objects[GID_VSCROLL], ys);
+ } else {
+ *ys = 0;
+ }
+
*ys /= gwin->bw->scale;
}
@@ -4525,10 +4597,12 @@ static void gui_window_set_scroll(struct gui_window *g, int sx, int sy)
if((cur_tab == g->tab) || (g->shared->tabs <= 1))
{
- RefreshSetGadgetAttrs((struct Gadget *)(APTR)g->shared->objects[OID_VSCROLL],
- g->shared->win, NULL,
- SCROLLER_Top, (ULONG)(sy * g->shared->bw->scale),
+ if(g->shared->objects[GID_VSCROLL]) {
+ RefreshSetGadgetAttrs((struct Gadget *)(APTR)g->shared->objects[GID_VSCROLL],
+ g->shared->win, NULL,
+ SCROLLER_Top, (ULONG)(sy * g->shared->bw->scale),
TAG_DONE);
+ }
if(g->shared->objects[GID_HSCROLL])
{
@@ -4591,10 +4665,12 @@ static void gui_window_update_extent(struct gui_window *g)
GetAttr(SPACE_AreaBox, g->shared->objects[GID_BROWSER],
(ULONG *)&bbox);
- RefreshSetGadgetAttrs((struct Gadget *)(APTR)g->shared->objects[OID_VSCROLL],g->shared->win,NULL,
- SCROLLER_Total, (ULONG)(content_get_height(g->shared->bw->current_content) * g->shared->bw->scale),
- SCROLLER_Visible, bbox->Height,
+ if(g->shared->objects[GID_VSCROLL]) {
+ RefreshSetGadgetAttrs((struct Gadget *)(APTR)g->shared->objects[GID_VSCROLL],g->shared->win,NULL,
+ SCROLLER_Total, (ULONG)(content_get_height(g->shared->bw->current_content) * g->shared->bw->scale),
+ SCROLLER_Visible, bbox->Height,
TAG_DONE);
+ }
if(g->shared->objects[GID_HSCROLL])
{
@@ -4810,6 +4886,7 @@ static void gui_window_new_content(struct gui_window *g)
ami_plot_release_pens(&g->shared->shared_pens);
ami_menu_update_disabled(g, c);
ami_gui_update_hotlist_button(g->shared);
+ ami_gui_vscroll_update(g->shared);
}
static bool gui_window_drag_start(struct gui_window *g, gui_drag_type type,
@@ -4850,7 +4927,7 @@ void ami_scroller_hook(struct Hook *hook,Object *object,struct IntuiMessage *msg
{
case GID_HSCROLL:
case OID_HSCROLL:
- case OID_VSCROLL:
+ case GID_VSCROLL:
if(nsoption_bool(faster_scroll) == true) gwin->redraw_scroll = true;
else gwin->redraw_scroll = false;
diff --git a/amiga/gui.h b/amiga/gui.h
index 830ac95..ef6ea10 100755
--- a/amiga/gui.h
+++ b/amiga/gui.h
@@ -70,6 +70,8 @@ enum
GID_HOTLISTLAYOUT,
GID_HOTLISTSEPBAR,
GID_HSCROLL,
+ GID_VSCROLL,
+ GID_VSCROLLLAYOUT,
GID_LAST
};
--
NetSurf Browser
8 years, 3 months
netsurf: branch master updated. release/3.2-223-g53f0f43
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/53f0f432dd2aa915765e3...
...commit http://git.netsurf-browser.org/netsurf.git/commit/53f0f432dd2aa915765e3b2...
...tree http://git.netsurf-browser.org/netsurf.git/tree/53f0f432dd2aa915765e3b286...
The branch, master has been updated
via 53f0f432dd2aa915765e3b2869928a18f09adad8 (commit)
via 7cf5cf7cb7797d7f39bb101504822da44ccc3355 (commit)
from 503da8f3f64abdfde62be6018cfb33a36846d363 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=53f0f432dd2aa915765...
commit 53f0f432dd2aa915765e3b2869928a18f09adad8
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
update fetcher registration API to return an error code.
By using an error code return we can gracefully handle fetcher
registration faliures instead of just immediately aborting.
The curl handler was also cleaned up and documentation improved
as a side effect.
diff --git a/content/fetch.c b/content/fetch.c
index 7923e9a..2c326e8 100644
--- a/content/fetch.c
+++ b/content/fetch.c
@@ -287,14 +287,36 @@ static void fetcher_poll(void *unused)
/* exported interface documented in content/fetch.h */
nserror fetcher_init(void)
{
- fetch_curl_register();
- fetch_data_register();
- fetch_file_register();
- fetch_resource_register();
- fetch_about_register();
- fetch_javascript_register();
+ nserror ret;
- return NSERROR_OK;
+ ret = fetch_curl_register();
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ ret = fetch_data_register();
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ ret = fetch_file_register();
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ ret = fetch_resource_register();
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ ret = fetch_about_register();
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ ret = fetch_javascript_register();
+
+ return ret;
}
/* exported interface documented in content/fetchers.h */
diff --git a/content/fetchers/about.h b/content/fetchers/about.h
index 9544971..944f84a 100644
--- a/content/fetchers/about.h
+++ b/content/fetchers/about.h
@@ -23,6 +23,11 @@
#ifndef NETSURF_CONTENT_FETCHERS_FETCH_ABOUT_H
#define NETSURF_CONTENT_FETCHERS_FETCH_ABOUT_H
+/**
+ * Register about scheme handler.
+ *
+ * \return NSERROR_OK on successful registration or error code on failure.
+ */
nserror fetch_about_register(void);
#endif
diff --git a/content/fetchers/curl.c b/content/fetchers/curl.c
index df48d8b..b3a7c69 100644
--- a/content/fetchers/curl.c
+++ b/content/fetchers/curl.c
@@ -18,12 +18,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Fetching of data from an URL (implementation).
+/**
+ * \file
+ * implementation of fetching of data from http and https schemes.
*
* This implementation uses libcurl's 'multi' interface.
*
- *
* The CURL handles are cached in the curl_handle_ring. There are at most
* ::max_cached_fetch_handles in this ring.
*/
@@ -106,193 +106,11 @@ static bool curl_with_openssl;
static char fetch_error_buffer[CURL_ERROR_SIZE]; /**< Error buffer for cURL. */
static char fetch_proxy_userpwd[100]; /**< Proxy authentication details. */
-static bool fetch_curl_initialise(lwc_string *scheme);
-static void fetch_curl_finalise(lwc_string *scheme);
-static bool fetch_curl_can_fetch(const nsurl *url);
-static void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
- bool only_2xx, bool downgrade_tls, const char *post_urlenc,
- const struct fetch_multipart_data *post_multipart,
- const char **headers);
-static bool fetch_curl_start(void *vfetch);
-static bool fetch_curl_initiate_fetch(struct curl_fetch_info *fetch,
- CURL *handle);
-static CURL *fetch_curl_get_handle(lwc_string *host);
-static void fetch_curl_cache_handle(CURL *handle, lwc_string *host);
-static CURLcode fetch_curl_set_options(struct curl_fetch_info *f);
-static CURLcode fetch_curl_sslctxfun(CURL *curl_handle, void *_sslctx,
- void *p);
-static void fetch_curl_abort(void *vf);
-static void fetch_curl_stop(struct curl_fetch_info *f);
-static void fetch_curl_free(void *f);
-static void fetch_curl_poll(lwc_string *scheme_ignored);
-static void fetch_curl_done(CURL *curl_handle, CURLcode result);
-static int fetch_curl_progress(void *clientp, double dltotal, double dlnow,
- double ultotal, double ulnow);
-static int fetch_curl_ignore_debug(CURL *handle,
- curl_infotype type,
- char *data,
- size_t size,
- void *userptr);
-static size_t fetch_curl_data(char *data, size_t size, size_t nmemb,
- void *_f);
-static size_t fetch_curl_header(char *data, size_t size, size_t nmemb,
- void *_f);
-static bool fetch_curl_process_headers(struct curl_fetch_info *f);
-static struct curl_httppost *fetch_curl_post_convert(
- const struct fetch_multipart_data *control);
-static int fetch_curl_verify_callback(int preverify_ok,
- X509_STORE_CTX *x509_ctx);
-static int fetch_curl_cert_verify_callback(X509_STORE_CTX *x509_ctx,
- void *parm);
-
-
-/**
- * Initialise the fetcher.
- *
- * Must be called once before any other function.
- */
-
-void fetch_curl_register(void)
-{
- CURLcode code;
- curl_version_info_data *data;
- int i;
- lwc_string *scheme;
- const struct fetcher_operation_table fetcher_ops = {
- .initialise = fetch_curl_initialise,
- .acceptable = fetch_curl_can_fetch,
- .setup = fetch_curl_setup,
- .start = fetch_curl_start,
- .abort = fetch_curl_abort,
- .free = fetch_curl_free,
- .poll = fetch_curl_poll,
- .finalise = fetch_curl_finalise
- };
-
- LOG(("curl_version %s", curl_version()));
-
- code = curl_global_init(CURL_GLOBAL_ALL);
- if (code != CURLE_OK)
- die("Failed to initialise the fetch module "
- "(curl_global_init failed).");
-
- fetch_curl_multi = curl_multi_init();
- if (!fetch_curl_multi)
- die("Failed to initialise the fetch module "
- "(curl_multi_init failed).");
-
-#if LIBCURL_VERSION_NUM >= 0x071e00
- /* We've been built against 7.30.0 or later: configure caching */
- {
- CURLMcode mcode;
- int maxconnects = nsoption_int(max_fetchers) +
- nsoption_int(max_cached_fetch_handles);
-
-#undef SETOPT
-#define SETOPT(option, value) \
- mcode = curl_multi_setopt(fetch_curl_multi, option, value); \
- if (mcode != CURLM_OK) \
- goto curl_multi_setopt_failed;
-
- SETOPT(CURLMOPT_MAXCONNECTS, maxconnects);
- SETOPT(CURLMOPT_MAX_TOTAL_CONNECTIONS, maxconnects);
- SETOPT(CURLMOPT_MAX_HOST_CONNECTIONS, nsoption_int(max_fetchers_per_host));
- }
-#endif
-
- /* Create a curl easy handle with the options that are common to all
- fetches. */
- fetch_blank_curl = curl_easy_init();
- if (!fetch_blank_curl)
- die("Failed to initialise the fetch module "
- "(curl_easy_init failed).");
-
-#undef SETOPT
-#define SETOPT(option, value) \
- code = curl_easy_setopt(fetch_blank_curl, option, value); \
- if (code != CURLE_OK) \
- goto curl_easy_setopt_failed;
-
- if (verbose_log) {
- SETOPT(CURLOPT_VERBOSE, 1);
- } else {
- SETOPT(CURLOPT_VERBOSE, 0);
- }
- SETOPT(CURLOPT_ERRORBUFFER, fetch_error_buffer);
- if (nsoption_bool(suppress_curl_debug)) {
- SETOPT(CURLOPT_DEBUGFUNCTION, fetch_curl_ignore_debug);
- }
- SETOPT(CURLOPT_WRITEFUNCTION, fetch_curl_data);
- SETOPT(CURLOPT_HEADERFUNCTION, fetch_curl_header);
- SETOPT(CURLOPT_PROGRESSFUNCTION, fetch_curl_progress);
- SETOPT(CURLOPT_NOPROGRESS, 0);
- SETOPT(CURLOPT_USERAGENT, user_agent_string());
- SETOPT(CURLOPT_ENCODING, "gzip");
- SETOPT(CURLOPT_LOW_SPEED_LIMIT, 1L);
- SETOPT(CURLOPT_LOW_SPEED_TIME, 180L);
- SETOPT(CURLOPT_NOSIGNAL, 1L);
- SETOPT(CURLOPT_CONNECTTIMEOUT, 30L);
-
- if (nsoption_charp(ca_bundle) &&
- strcmp(nsoption_charp(ca_bundle), "")) {
- LOG(("ca_bundle: '%s'", nsoption_charp(ca_bundle)));
- SETOPT(CURLOPT_CAINFO, nsoption_charp(ca_bundle));
- }
- if (nsoption_charp(ca_path) && strcmp(nsoption_charp(ca_path), "")) {
- LOG(("ca_path: '%s'", nsoption_charp(ca_path)));
- SETOPT(CURLOPT_CAPATH, nsoption_charp(ca_path));
- }
-
- /* Detect whether the SSL CTX function API works */
- curl_with_openssl = true;
- code = curl_easy_setopt(fetch_blank_curl,
- CURLOPT_SSL_CTX_FUNCTION, NULL);
- if (code != CURLE_OK) {
- curl_with_openssl = false;
- }
-
- LOG(("cURL %slinked against openssl", curl_with_openssl ? "" : "not "));
-
- /* cURL initialised okay, register the fetchers */
-
- data = curl_version_info(CURLVERSION_NOW);
-
- for (i = 0; data->protocols[i]; i++) {
- if (strcmp(data->protocols[i], "http") == 0) {
- scheme = lwc_string_ref(corestring_lwc_http);
-
- } else if (strcmp(data->protocols[i], "https") == 0) {
- scheme = lwc_string_ref(corestring_lwc_https);
-
- } else {
- /* Ignore non-http(s) protocols */
- continue;
- }
-
- if (fetcher_add(scheme, &fetcher_ops) != NSERROR_OK) {
- LOG(("Unable to register cURL fetcher for %s",
- data->protocols[i]));
- }
- }
- return;
-
-curl_easy_setopt_failed:
- die("Failed to initialise the fetch module "
- "(curl_easy_setopt failed).");
-
-#if LIBCURL_VERSION_NUM >= 0x071e00
-curl_multi_setopt_failed:
- die("Failed to initialise the fetch module "
- "(curl_multi_setopt failed).");
-#endif
-}
-
/**
* Initialise a cURL fetcher.
*/
-
-bool fetch_curl_initialise(lwc_string *scheme)
+static bool fetch_curl_initialise(lwc_string *scheme)
{
LOG(("Initialise cURL fetcher for %s", lwc_string_data(scheme)));
curl_fetchers_registered++;
@@ -301,10 +119,11 @@ bool fetch_curl_initialise(lwc_string *scheme)
/**
- * Finalise a cURL fetcher
+ * Finalise a cURL fetcher.
+ *
+ * \param scheme The scheme to finalise.
*/
-
-void fetch_curl_finalise(lwc_string *scheme)
+static void fetch_curl_finalise(lwc_string *scheme)
{
struct cache_handle *h;
@@ -334,19 +153,103 @@ void fetch_curl_finalise(lwc_string *scheme)
}
}
-bool fetch_curl_can_fetch(const nsurl *url)
+
+/**
+ * Check if this fetcher can fetch a url.
+ *
+ * \param url The url to check.
+ * \return true if teh fetcher supports teh url else false.
+ */
+static bool fetch_curl_can_fetch(const nsurl *url)
{
return nsurl_has_component(url, NSURL_HOST);
}
+
+/**
+ * Convert a list of struct ::fetch_multipart_data to a list of
+ * struct curl_httppost for libcurl.
+ */
+static struct curl_httppost *
+fetch_curl_post_convert(const struct fetch_multipart_data *control)
+{
+ struct curl_httppost *post = 0, *last = 0;
+ CURLFORMcode code;
+ nserror ret;
+
+ for (; control; control = control->next) {
+ if (control->file) {
+ char *leafname = NULL;
+ ret = guit->file->basename(control->value, &leafname, NULL);
+ if (ret != NSERROR_OK) {
+ continue;
+ }
+
+ /* We have to special case filenames of "", so curl
+ * a) actually attempts the fetch and
+ * b) doesn't attempt to open the file ""
+ */
+ if (control->value[0] == '\0') {
+ /* dummy buffer - needs to be static so
+ * pointer's still valid when we go out
+ * of scope (not that libcurl should be
+ * attempting to access it, of course).
+ */
+ static char buf;
+
+ code = curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, control->name,
+ CURLFORM_BUFFER, control->value,
+ /* needed, as basename("") == "." */
+ CURLFORM_FILENAME, "",
+ CURLFORM_BUFFERPTR, &buf,
+ CURLFORM_BUFFERLENGTH, 0,
+ CURLFORM_CONTENTTYPE,
+ "application/octet-stream",
+ CURLFORM_END);
+ if (code != CURL_FORMADD_OK)
+ LOG(("curl_formadd: %d (%s)",
+ code, control->name));
+ } else {
+ char *mimetype = guit->fetch->mimetype(control->value);
+ code = curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, control->name,
+ CURLFORM_FILE, control->rawfile,
+ CURLFORM_FILENAME, leafname,
+ CURLFORM_CONTENTTYPE,
+ (mimetype != 0 ? mimetype : "text/plain"),
+ CURLFORM_END);
+ if (code != CURL_FORMADD_OK)
+ LOG(("curl_formadd: %d (%s=%s)",
+ code, control->name,
+ control->value));
+ free(mimetype);
+ }
+ free(leafname);
+ }
+ else {
+ code = curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, control->name,
+ CURLFORM_COPYCONTENTS, control->value,
+ CURLFORM_END);
+ if (code != CURL_FORMADD_OK)
+ LOG(("curl_formadd: %d (%s=%s)", code,
+ control->name,
+ control->value));
+ }
+ }
+
+ return post;
+}
+
/**
* Start fetching data for the given URL.
*
* The function returns immediately. The fetch may be queued for later
* processing.
*
- * A pointer to an opaque struct curl_fetch_info is returned, which can be
- * passed to fetch_abort() to abort the fetch at any time. Returns 0 if memory
+ * A pointer to an opaque struct curl_fetch_info is returned, which can be
+ * passed to fetch_abort() to abort the fetch at any time. Returns 0 if memory
* is exhausted (or some other fatal error occurred).
*
* The caller must supply a callback function which is called when anything
@@ -360,9 +263,12 @@ bool fetch_curl_can_fetch(const nsurl *url)
* Some private data can be passed as the last parameter to fetch_start, and
* callbacks will contain this.
*/
-
-void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
- bool only_2xx, bool downgrade_tls, const char *post_urlenc,
+static void *
+fetch_curl_setup(struct fetch *parent_fetch,
+ nsurl *url,
+ bool only_2xx,
+ bool downgrade_tls,
+ const char *post_urlenc,
const struct fetch_multipart_data *post_multipart,
const char **headers)
{
@@ -420,7 +326,7 @@ void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
* which fails with lighttpd, so disable it (see bug 1429054) */
APPEND(fetch->headers, "Expect:");
- if ((nsoption_charp(accept_language) != NULL) &&
+ if ((nsoption_charp(accept_language) != NULL) &&
(nsoption_charp(accept_language)[0] != '\0')) {
char s[80];
snprintf(s, sizeof s, "Accept-Language: %s, *;q=0.1",
@@ -429,7 +335,7 @@ void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
APPEND(fetch->headers, s);
}
- if (nsoption_charp(accept_charset) != NULL &&
+ if (nsoption_charp(accept_charset) != NULL &&
nsoption_charp(accept_charset)[0] != '\0') {
char s[80];
snprintf(s, sizeof s, "Accept-Charset: %s, *;q=0.1",
@@ -449,6 +355,8 @@ void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
return fetch;
+#undef APPEND
+
failed:
if (fetch->host != NULL)
lwc_string_unref(fetch->host);
@@ -464,126 +372,96 @@ failed:
/**
- * Dispatch a single job
- */
-bool fetch_curl_start(void *vfetch)
-{
- struct curl_fetch_info *fetch = (struct curl_fetch_info*)vfetch;
- return fetch_curl_initiate_fetch(fetch,
- fetch_curl_get_handle(fetch->host));
-}
-
-
-/**
- * Initiate a fetch from the queue.
- *
- * Called with a fetch structure and a CURL handle to be used to fetch the
- * content.
- *
- * This will return whether or not the fetch was successfully initiated.
+ * OpenSSL Certificate verification callback
+ * Stores certificate details in fetch struct.
*/
-
-bool fetch_curl_initiate_fetch(struct curl_fetch_info *fetch, CURL *handle)
+static int
+fetch_curl_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
{
- CURLcode code;
- CURLMcode codem;
-
- fetch->curl_handle = handle;
+ X509 *cert = X509_STORE_CTX_get_current_cert(x509_ctx);
+ int depth = X509_STORE_CTX_get_error_depth(x509_ctx);
+ int err = X509_STORE_CTX_get_error(x509_ctx);
+ struct curl_fetch_info *f = X509_STORE_CTX_get_app_data(x509_ctx);
- /* Initialise the handle */
- code = fetch_curl_set_options(fetch);
- if (code != CURLE_OK) {
- fetch->curl_handle = 0;
- return false;
+ /* save the certificate by incrementing the reference count and
+ * keeping a pointer.
+ */
+ if (depth < MAX_CERTS && !f->cert_data[depth].cert) {
+ f->cert_data[depth].cert = cert;
+ f->cert_data[depth].err = err;
+ cert->references++;
}
- /* add to the global curl multi handle */
- codem = curl_multi_add_handle(fetch_curl_multi, fetch->curl_handle);
- assert(codem == CURLM_OK || codem == CURLM_CALL_MULTI_PERFORM);
-
- return true;
+ return preverify_ok;
}
/**
- * Find a CURL handle to use to dispatch a job
+ * OpenSSL certificate chain verification callback
+ * Verifies certificate chain, setting up context for fetch_curl_verify_callback
*/
-
-CURL *fetch_curl_get_handle(lwc_string *host)
+static int fetch_curl_cert_verify_callback(X509_STORE_CTX *x509_ctx, void *parm)
{
- struct cache_handle *h;
- CURL *ret;
- RING_FINDBYLWCHOST(curl_handle_ring, h, host);
- if (h) {
- ret = h->handle;
- lwc_string_unref(h->host);
- RING_REMOVE(curl_handle_ring, h);
- free(h);
- } else {
- ret = curl_easy_duphandle(fetch_blank_curl);
- }
- return ret;
+ int ok;
+
+ /* Store fetch struct in context for verify callback */
+ ok = X509_STORE_CTX_set_app_data(x509_ctx, parm);
+
+ /* and verify the certificate chain */
+ if (ok)
+ ok = X509_verify_cert(x509_ctx);
+
+ return ok;
}
/**
- * Cache a CURL handle for the provided host (if wanted)
+ * cURL SSL setup callback
+ *
+ * \param curl_handle The curl handle to perform the ssl operation on.
+ * \param _sslctx The ssl context.
+ * \param parm The callback context.
+ * \return A curl result code.
*/
-
-void fetch_curl_cache_handle(CURL *handle, lwc_string *host)
+static CURLcode
+fetch_curl_sslctxfun(CURL *curl_handle, void *_sslctx, void *parm)
{
-#if LIBCURL_VERSION_NUM >= 0x071e00
- /* 7.30.0 or later has its own connection caching; suppress ours */
- curl_easy_cleanup(handle);
- return;
-#else
- struct cache_handle *h = 0;
- int c;
- RING_FINDBYLWCHOST(curl_handle_ring, h, host);
- if (h) {
- /* Already have a handle cached for this hostname */
- curl_easy_cleanup(handle);
- return;
- }
- /* We do not have a handle cached, first up determine if the cache is full */
- RING_GETSIZE(struct cache_handle, curl_handle_ring, c);
- if (c >= nsoption_int(max_cached_fetch_handles)) {
- /* Cache is full, so, we rotate the ring by one and
- * replace the oldest handle with this one. We do this
- * without freeing/allocating memory (except the
- * hostname) and without removing the entry from the
- * ring and then re-inserting it, in order to be as
- * efficient as we can.
- */
- if (curl_handle_ring != NULL) {
- h = curl_handle_ring;
- curl_handle_ring = h->r_next;
- curl_easy_cleanup(h->handle);
- h->handle = handle;
- lwc_string_unref(h->host);
- h->host = lwc_string_ref(host);
- } else {
- /* Actually, we don't want to cache any handles */
- curl_easy_cleanup(handle);
- }
+ struct curl_fetch_info *f = (struct curl_fetch_info *) parm;
+ SSL_CTX *sslctx = _sslctx;
+ long options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
- return;
- }
- /* The table isn't full yet, so make a shiny new handle to add to the ring */
- h = (struct cache_handle*)malloc(sizeof(struct cache_handle));
- h->handle = handle;
- h->host = lwc_string_ref(host);
- RING_INSERT(curl_handle_ring, h);
+ SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, fetch_curl_verify_callback);
+ SSL_CTX_set_cert_verify_callback(sslctx,
+ fetch_curl_cert_verify_callback,
+ parm);
+
+ if (f->downgrade_tls) {
+ /* Disable TLS 1.1/1.2 if the server can't cope with them */
+#ifdef SSL_OP_NO_TLSv1_1
+ options |= SSL_OP_NO_TLSv1_1;
#endif
+#ifdef SSL_OP_NO_TLSv1_2
+ options |= SSL_OP_NO_TLSv1_2;
+#endif
+#ifdef SSL_MODE_SEND_FALLBACK_SCSV
+ /* Ensure server rejects the connection if downgraded too far */
+ SSL_CTX_set_mode(sslctx, SSL_MODE_SEND_FALLBACK_SCSV);
+#endif
+ }
+
+ SSL_CTX_set_options(sslctx, options);
+
+ return CURLE_OK;
}
/**
* Set options specific for a fetch.
+ *
+ * \param f The fetch to set options on.
+ * \return A curl result code.
*/
-
-CURLcode
-fetch_curl_set_options(struct curl_fetch_info *f)
+static CURLcode fetch_curl_set_options(struct curl_fetch_info *f)
{
CURLcode code;
const char *auth;
@@ -631,7 +509,7 @@ fetch_curl_set_options(struct curl_fetch_info *f)
}
/* set up proxy options */
- if (nsoption_bool(http_proxy) &&
+ if (nsoption_bool(http_proxy) &&
(nsoption_charp(http_proxy_host) != NULL) &&
(strncmp(nsurl_access(f->url), "file:", 5) != 0)) {
SETOPT(CURLOPT_PROXY, nsoption_charp(http_proxy_host));
@@ -684,47 +562,122 @@ fetch_curl_set_options(struct curl_fetch_info *f)
return CURLE_OK;
}
+/**
+ * Initiate a fetch from the queue.
+ *
+ * \param fetch fetch to use to fetch content.
+ * \param handle CURL handle to be used to fetch the content.
+ * \return true if the fetch was successfully initiated else false.
+ */
+static bool
+fetch_curl_initiate_fetch(struct curl_fetch_info *fetch, CURL *handle)
+{
+ CURLcode code;
+ CURLMcode codem;
+
+ fetch->curl_handle = handle;
+
+ /* Initialise the handle */
+ code = fetch_curl_set_options(fetch);
+ if (code != CURLE_OK) {
+ fetch->curl_handle = 0;
+ return false;
+ }
+
+ /* add to the global curl multi handle */
+ codem = curl_multi_add_handle(fetch_curl_multi, fetch->curl_handle);
+ assert(codem == CURLM_OK || codem == CURLM_CALL_MULTI_PERFORM);
+
+ return true;
+}
+
/**
- * cURL SSL setup callback
+ * Find a CURL handle to use to dispatch a job
*/
+static CURL *fetch_curl_get_handle(lwc_string *host)
+{
+ struct cache_handle *h;
+ CURL *ret;
+ RING_FINDBYLWCHOST(curl_handle_ring, h, host);
+ if (h) {
+ ret = h->handle;
+ lwc_string_unref(h->host);
+ RING_REMOVE(curl_handle_ring, h);
+ free(h);
+ } else {
+ ret = curl_easy_duphandle(fetch_blank_curl);
+ }
+ return ret;
+}
-CURLcode
-fetch_curl_sslctxfun(CURL *curl_handle, void *_sslctx, void *parm)
+
+/**
+ * Dispatch a single job
+ */
+static bool fetch_curl_start(void *vfetch)
{
- struct curl_fetch_info *f = (struct curl_fetch_info *) parm;
- SSL_CTX *sslctx = _sslctx;
- long options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
+ struct curl_fetch_info *fetch = (struct curl_fetch_info*)vfetch;
+ return fetch_curl_initiate_fetch(fetch,
+ fetch_curl_get_handle(fetch->host));
+}
- SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, fetch_curl_verify_callback);
- SSL_CTX_set_cert_verify_callback(sslctx, fetch_curl_cert_verify_callback,
- parm);
+/**
+ * Cache a CURL handle for the provided host (if wanted)
+ */
- if (f->downgrade_tls) {
- /* Disable TLS 1.1/1.2 if the server can't cope with them */
-#ifdef SSL_OP_NO_TLSv1_1
- options |= SSL_OP_NO_TLSv1_1;
-#endif
-#ifdef SSL_OP_NO_TLSv1_2
- options |= SSL_OP_NO_TLSv1_2;
-#endif
-#ifdef SSL_MODE_SEND_FALLBACK_SCSV
- /* Ensure server rejects the connection if downgraded too far */
- SSL_CTX_set_mode(sslctx, SSL_MODE_SEND_FALLBACK_SCSV);
-#endif
+static void fetch_curl_cache_handle(CURL *handle, lwc_string *host)
+{
+#if LIBCURL_VERSION_NUM >= 0x071e00
+ /* 7.30.0 or later has its own connection caching; suppress ours */
+ curl_easy_cleanup(handle);
+ return;
+#else
+ struct cache_handle *h = 0;
+ int c;
+ RING_FINDBYLWCHOST(curl_handle_ring, h, host);
+ if (h) {
+ /* Already have a handle cached for this hostname */
+ curl_easy_cleanup(handle);
+ return;
}
+ /* We do not have a handle cached, first up determine if the cache is full */
+ RING_GETSIZE(struct cache_handle, curl_handle_ring, c);
+ if (c >= nsoption_int(max_cached_fetch_handles)) {
+ /* Cache is full, so, we rotate the ring by one and
+ * replace the oldest handle with this one. We do this
+ * without freeing/allocating memory (except the
+ * hostname) and without removing the entry from the
+ * ring and then re-inserting it, in order to be as
+ * efficient as we can.
+ */
+ if (curl_handle_ring != NULL) {
+ h = curl_handle_ring;
+ curl_handle_ring = h->r_next;
+ curl_easy_cleanup(h->handle);
+ h->handle = handle;
+ lwc_string_unref(h->host);
+ h->host = lwc_string_ref(host);
+ } else {
+ /* Actually, we don't want to cache any handles */
+ curl_easy_cleanup(handle);
+ }
- SSL_CTX_set_options(sslctx, options);
-
- return CURLE_OK;
+ return;
+ }
+ /* The table isn't full yet, so make a shiny new handle to add to the ring */
+ h = (struct cache_handle*)malloc(sizeof(struct cache_handle));
+ h->handle = handle;
+ h->host = lwc_string_ref(host);
+ RING_INSERT(curl_handle_ring, h);
+#endif
}
/**
* Abort a fetch.
*/
-
-void fetch_curl_abort(void *vf)
+static void fetch_curl_abort(void *vf)
{
struct curl_fetch_info *f = (struct curl_fetch_info *)vf;
assert(f);
@@ -743,8 +696,7 @@ void fetch_curl_abort(void *vf)
*
* Will prod the queue afterwards to allow pending requests to be initiated.
*/
-
-void fetch_curl_stop(struct curl_fetch_info *f)
+static void fetch_curl_stop(struct curl_fetch_info *f)
{
CURLMcode codem;
@@ -768,8 +720,7 @@ void fetch_curl_stop(struct curl_fetch_info *f)
/**
* Free a fetch structure and associated resources.
*/
-
-void fetch_curl_free(void *vf)
+static void fetch_curl_free(void *vf)
{
struct curl_fetch_info *f = (struct curl_fetch_info *)vf;
int i;
@@ -798,41 +749,65 @@ void fetch_curl_free(void *vf)
/**
- * Do some work on current fetches.
+ * Find the status code and content type and inform the caller.
*
- * Must be called regularly to make progress on fetches.
+ * Return true if the fetch is being aborted.
*/
-
-void fetch_curl_poll(lwc_string *scheme_ignored)
+static bool fetch_curl_process_headers(struct curl_fetch_info *f)
{
- int running, queue;
- CURLMcode codem;
- CURLMsg *curl_msg;
-
- /* do any possible work on the current fetches */
- do {
- codem = curl_multi_perform(fetch_curl_multi, &running);
- if (codem != CURLM_OK && codem != CURLM_CALL_MULTI_PERFORM) {
- LOG(("curl_multi_perform: %i %s",
- codem, curl_multi_strerror(codem)));
- warn_user("MiscError", curl_multi_strerror(codem));
- return;
- }
- } while (codem == CURLM_CALL_MULTI_PERFORM);
+ long http_code;
+ CURLcode code;
+ fetch_msg msg;
- /* process curl results */
- curl_msg = curl_multi_info_read(fetch_curl_multi, &queue);
- while (curl_msg) {
- switch (curl_msg->msg) {
- case CURLMSG_DONE:
- fetch_curl_done(curl_msg->easy_handle,
- curl_msg->data.result);
- break;
- default:
- break;
- }
- curl_msg = curl_multi_info_read(fetch_curl_multi, &queue);
+ f->had_headers = true;
+
+ if (!f->http_code)
+ {
+ code = curl_easy_getinfo(f->curl_handle, CURLINFO_HTTP_CODE,
+ &f->http_code);
+ fetch_set_http_code(f->fetch_handle, f->http_code);
+ assert(code == CURLE_OK);
+ }
+ http_code = f->http_code;
+ LOG(("HTTP status code %li", http_code));
+
+ if (http_code == 304 && !f->post_urlenc && !f->post_multipart) {
+ /* Not Modified && GET request */
+ msg.type = FETCH_NOTMODIFIED;
+ fetch_send_callback(&msg, f->fetch_handle);
+ return true;
+ }
+
+ /* handle HTTP redirects (3xx response codes) */
+ if (300 <= http_code && http_code < 400 && f->location != 0) {
+ LOG(("FETCH_REDIRECT, '%s'", f->location));
+ msg.type = FETCH_REDIRECT;
+ msg.data.redirect = f->location;
+ fetch_send_callback(&msg, f->fetch_handle);
+ return true;
}
+
+ /* handle HTTP 401 (Authentication errors) */
+ if (http_code == 401) {
+ msg.type = FETCH_AUTH;
+ msg.data.auth.realm = f->realm;
+ fetch_send_callback(&msg, f->fetch_handle);
+ return true;
+ }
+
+ /* handle HTTP errors (non 2xx response codes) */
+ if (f->only_2xx && strncmp(nsurl_access(f->url), "http", 4) == 0 &&
+ (http_code < 200 || 299 < http_code)) {
+ msg.type = FETCH_ERROR;
+ msg.data.error = messages_get("Not2xx");
+ fetch_send_callback(&msg, f->fetch_handle);
+ return true;
+ }
+
+ if (f->abort)
+ return true;
+
+ return false;
}
@@ -841,8 +816,7 @@ void fetch_curl_poll(lwc_string *scheme_ignored)
*
* \param curl_handle curl easy handle of fetch
*/
-
-void fetch_curl_done(CURL *curl_handle, CURLcode result)
+static void fetch_curl_done(CURL *curl_handle, CURLcode result)
{
fetch_msg msg;
bool finished = false;
@@ -865,14 +839,15 @@ void fetch_curl_done(CURL *curl_handle, CURLcode result)
if (abort_fetch == false && (result == CURLE_OK ||
(result == CURLE_WRITE_ERROR && f->stopped == false))) {
- /* fetch completed normally or the server fed us a junk gzip
- * stream (usually in the form of garbage at the end of the
- * stream). Curl will have fed us all but the last chunk of
- * decoded data, which is sad as, if we'd received the last
+ /* fetch completed normally or the server fed us a junk gzip
+ * stream (usually in the form of garbage at the end of the
+ * stream). Curl will have fed us all but the last chunk of
+ * decoded data, which is sad as, if we'd received the last
* chunk, too, we'd be able to render the whole object.
* As is, we'll just have to accept that the end of the
* object will be truncated in this case and leave it to
- * the content handlers to cope. */
+ * the content handlers to cope.
+ */
if (f->stopped ||
(!f->had_headers &&
fetch_curl_process_headers(f)))
@@ -1008,19 +983,59 @@ void fetch_curl_done(CURL *curl_handle, CURLcode result)
} else {
msg.type = FETCH_SSL_ERR;
}
-
- fetch_send_callback(&msg, f->fetch_handle);
+
+ fetch_send_callback(&msg, f->fetch_handle);
+ }
+
+ fetch_free(f->fetch_handle);
+}
+
+
+/**
+ * Do some work on current fetches.
+ *
+ * Must be called regularly to make progress on fetches.
+ */
+static void fetch_curl_poll(lwc_string *scheme_ignored)
+{
+ int running, queue;
+ CURLMcode codem;
+ CURLMsg *curl_msg;
+
+ /* do any possible work on the current fetches */
+ do {
+ codem = curl_multi_perform(fetch_curl_multi, &running);
+ if (codem != CURLM_OK && codem != CURLM_CALL_MULTI_PERFORM) {
+ LOG(("curl_multi_perform: %i %s",
+ codem, curl_multi_strerror(codem)));
+ warn_user("MiscError", curl_multi_strerror(codem));
+ return;
+ }
+ } while (codem == CURLM_CALL_MULTI_PERFORM);
+
+ /* process curl results */
+ curl_msg = curl_multi_info_read(fetch_curl_multi, &queue);
+ while (curl_msg) {
+ switch (curl_msg->msg) {
+ case CURLMSG_DONE:
+ fetch_curl_done(curl_msg->easy_handle,
+ curl_msg->data.result);
+ break;
+ default:
+ break;
+ }
+ curl_msg = curl_multi_info_read(fetch_curl_multi, &queue);
}
-
- fetch_free(f->fetch_handle);
}
+
+
/**
* Callback function for fetch progress.
*/
-int fetch_curl_progress(void *clientp, double dltotal, double dlnow,
+static int fetch_curl_progress(void *clientp, double dltotal, double dlnow,
double ultotal, double ulnow)
{
static char fetch_progress_buffer[256]; /**< Progress buffer for cURL */
@@ -1061,14 +1076,12 @@ int fetch_curl_progress(void *clientp, double dltotal, double dlnow,
}
-
/**
* Ignore everything given to it.
*
* Used to ignore cURL debug.
*/
-
-int fetch_curl_ignore_debug(CURL *handle,
+static int fetch_curl_ignore_debug(CURL *handle,
curl_infotype type,
char *data,
size_t size,
@@ -1081,9 +1094,7 @@ int fetch_curl_ignore_debug(CURL *handle,
/**
* Callback function for cURL.
*/
-
-size_t fetch_curl_data(char *data, size_t size, size_t nmemb,
- void *_f)
+static size_t fetch_curl_data(char *data, size_t size, size_t nmemb, void *_f)
{
struct curl_fetch_info *f = _f;
CURLcode code;
@@ -1099,7 +1110,8 @@ size_t fetch_curl_data(char *data, size_t size, size_t nmemb,
}
/* ignore body if this is a 401 reply by skipping it and reset
- the HTTP response code to enable follow up fetches */
+ * the HTTP response code to enable follow up fetches.
+ */
if (f->http_code == 401)
{
f->http_code = 0;
@@ -1131,8 +1143,7 @@ size_t fetch_curl_data(char *data, size_t size, size_t nmemb,
*
* See RFC 2616 4.2.
*/
-
-size_t fetch_curl_header(char *data, size_t size, size_t nmemb,
+static size_t fetch_curl_header(char *data, size_t size, size_t nmemb,
void *_f)
{
struct curl_fetch_info *f = _f;
@@ -1211,185 +1222,144 @@ size_t fetch_curl_header(char *data, size_t size, size_t nmemb,
#undef SKIP_ST
}
-/**
- * Find the status code and content type and inform the caller.
- *
- * Return true if the fetch is being aborted.
- */
-bool fetch_curl_process_headers(struct curl_fetch_info *f)
+/* exported function documented in content/fetchers/curl.h */
+nserror fetch_curl_register(void)
{
- long http_code;
CURLcode code;
- fetch_msg msg;
+ curl_version_info_data *data;
+ int i;
+ lwc_string *scheme;
+ const struct fetcher_operation_table fetcher_ops = {
+ .initialise = fetch_curl_initialise,
+ .acceptable = fetch_curl_can_fetch,
+ .setup = fetch_curl_setup,
+ .start = fetch_curl_start,
+ .abort = fetch_curl_abort,
+ .free = fetch_curl_free,
+ .poll = fetch_curl_poll,
+ .finalise = fetch_curl_finalise
+ };
- f->had_headers = true;
+ LOG(("curl_version %s", curl_version()));
- if (!f->http_code)
- {
- code = curl_easy_getinfo(f->curl_handle, CURLINFO_HTTP_CODE,
- &f->http_code);
- fetch_set_http_code(f->fetch_handle, f->http_code);
- assert(code == CURLE_OK);
+ code = curl_global_init(CURL_GLOBAL_ALL);
+ if (code != CURLE_OK) {
+ LOG(("curl_global_init failed."));
+ return NSERROR_INIT_FAILED;
}
- http_code = f->http_code;
- LOG(("HTTP status code %li", http_code));
- if (http_code == 304 && !f->post_urlenc && !f->post_multipart) {
- /* Not Modified && GET request */
- msg.type = FETCH_NOTMODIFIED;
- fetch_send_callback(&msg, f->fetch_handle);
- return true;
+ fetch_curl_multi = curl_multi_init();
+ if (!fetch_curl_multi) {
+ LOG(("curl_multi_init failed."));
+ return NSERROR_INIT_FAILED;
}
- /* handle HTTP redirects (3xx response codes) */
- if (300 <= http_code && http_code < 400 && f->location != 0) {
- LOG(("FETCH_REDIRECT, '%s'", f->location));
- msg.type = FETCH_REDIRECT;
- msg.data.redirect = f->location;
- fetch_send_callback(&msg, f->fetch_handle);
- return true;
- }
+#if LIBCURL_VERSION_NUM >= 0x071e00
+ /* built against 7.30.0 or later: configure caching */
+ {
+ CURLMcode mcode;
+ int maxconnects = nsoption_int(max_fetchers) +
+ nsoption_int(max_cached_fetch_handles);
- /* handle HTTP 401 (Authentication errors) */
- if (http_code == 401) {
- msg.type = FETCH_AUTH;
- msg.data.auth.realm = f->realm;
- fetch_send_callback(&msg, f->fetch_handle);
- return true;
- }
+#undef SETOPT
+#define SETOPT(option, value) \
+ mcode = curl_multi_setopt(fetch_curl_multi, option, value); \
+ if (mcode != CURLM_OK) \
+ goto curl_multi_setopt_failed;
- /* handle HTTP errors (non 2xx response codes) */
- if (f->only_2xx && strncmp(nsurl_access(f->url), "http", 4) == 0 &&
- (http_code < 200 || 299 < http_code)) {
- msg.type = FETCH_ERROR;
- msg.data.error = messages_get("Not2xx");
- fetch_send_callback(&msg, f->fetch_handle);
- return true;
+ SETOPT(CURLMOPT_MAXCONNECTS, maxconnects);
+ SETOPT(CURLMOPT_MAX_TOTAL_CONNECTIONS, maxconnects);
+ SETOPT(CURLMOPT_MAX_HOST_CONNECTIONS, nsoption_int(max_fetchers_per_host));
}
+#endif
- if (f->abort)
- return true;
-
- return false;
-}
-
-
-/**
- * Convert a list of struct ::fetch_multipart_data to a list of
- * struct curl_httppost for libcurl.
- */
-struct curl_httppost *
-fetch_curl_post_convert(const struct fetch_multipart_data *control)
-{
- struct curl_httppost *post = 0, *last = 0;
- CURLFORMcode code;
- nserror ret;
-
- for (; control; control = control->next) {
- if (control->file) {
- char *leafname = NULL;
- ret = guit->file->basename(control->value, &leafname, NULL);
- if (ret != NSERROR_OK) {
- continue;
- }
+ /* Create a curl easy handle with the options that are common to all
+ fetches.
+ */
+ fetch_blank_curl = curl_easy_init();
+ if (!fetch_blank_curl) {
+ LOG(("curl_easy_init failed"));
+ return NSERROR_INIT_FAILED;
+ }
- /* We have to special case filenames of "", so curl
- * a) actually attempts the fetch and
- * b) doesn't attempt to open the file ""
- */
- if (control->value[0] == '\0') {
- /* dummy buffer - needs to be static so
- * pointer's still valid when we go out
- * of scope (not that libcurl should be
- * attempting to access it, of course). */
- static char buf;
+#undef SETOPT
+#define SETOPT(option, value) \
+ code = curl_easy_setopt(fetch_blank_curl, option, value); \
+ if (code != CURLE_OK) \
+ goto curl_easy_setopt_failed;
- code = curl_formadd(&post, &last,
- CURLFORM_COPYNAME, control->name,
- CURLFORM_BUFFER, control->value,
- /* needed, as basename("") == "." */
- CURLFORM_FILENAME, "",
- CURLFORM_BUFFERPTR, &buf,
- CURLFORM_BUFFERLENGTH, 0,
- CURLFORM_CONTENTTYPE,
- "application/octet-stream",
- CURLFORM_END);
- if (code != CURL_FORMADD_OK)
- LOG(("curl_formadd: %d (%s)",
- code, control->name));
- } else {
- char *mimetype = guit->fetch->mimetype(control->value);
- code = curl_formadd(&post, &last,
- CURLFORM_COPYNAME, control->name,
- CURLFORM_FILE, control->rawfile,
- CURLFORM_FILENAME, leafname,
- CURLFORM_CONTENTTYPE,
- (mimetype != 0 ? mimetype : "text/plain"),
- CURLFORM_END);
- if (code != CURL_FORMADD_OK)
- LOG(("curl_formadd: %d (%s=%s)",
- code, control->name,
- control->value));
- free(mimetype);
- }
- free(leafname);
- }
- else {
- code = curl_formadd(&post, &last,
- CURLFORM_COPYNAME, control->name,
- CURLFORM_COPYCONTENTS, control->value,
- CURLFORM_END);
- if (code != CURL_FORMADD_OK)
- LOG(("curl_formadd: %d (%s=%s)", code,
- control->name,
- control->value));
- }
+ if (verbose_log) {
+ SETOPT(CURLOPT_VERBOSE, 1);
+ } else {
+ SETOPT(CURLOPT_VERBOSE, 0);
}
+ SETOPT(CURLOPT_ERRORBUFFER, fetch_error_buffer);
+ if (nsoption_bool(suppress_curl_debug)) {
+ SETOPT(CURLOPT_DEBUGFUNCTION, fetch_curl_ignore_debug);
+ }
+ SETOPT(CURLOPT_WRITEFUNCTION, fetch_curl_data);
+ SETOPT(CURLOPT_HEADERFUNCTION, fetch_curl_header);
+ SETOPT(CURLOPT_PROGRESSFUNCTION, fetch_curl_progress);
+ SETOPT(CURLOPT_NOPROGRESS, 0);
+ SETOPT(CURLOPT_USERAGENT, user_agent_string());
+ SETOPT(CURLOPT_ENCODING, "gzip");
+ SETOPT(CURLOPT_LOW_SPEED_LIMIT, 1L);
+ SETOPT(CURLOPT_LOW_SPEED_TIME, 180L);
+ SETOPT(CURLOPT_NOSIGNAL, 1L);
+ SETOPT(CURLOPT_CONNECTTIMEOUT, 30L);
- return post;
-}
+ if (nsoption_charp(ca_bundle) &&
+ strcmp(nsoption_charp(ca_bundle), "")) {
+ LOG(("ca_bundle: '%s'", nsoption_charp(ca_bundle)));
+ SETOPT(CURLOPT_CAINFO, nsoption_charp(ca_bundle));
+ }
+ if (nsoption_charp(ca_path) && strcmp(nsoption_charp(ca_path), "")) {
+ LOG(("ca_path: '%s'", nsoption_charp(ca_path)));
+ SETOPT(CURLOPT_CAPATH, nsoption_charp(ca_path));
+ }
+ /* Detect whether the SSL CTX function API works */
+ curl_with_openssl = true;
+ code = curl_easy_setopt(fetch_blank_curl,
+ CURLOPT_SSL_CTX_FUNCTION, NULL);
+ if (code != CURLE_OK) {
+ curl_with_openssl = false;
+ }
-/**
- * OpenSSL Certificate verification callback
- * Stores certificate details in fetch struct.
- */
+ LOG(("cURL %slinked against openssl", curl_with_openssl ? "" : "not "));
-int fetch_curl_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
-{
- X509 *cert = X509_STORE_CTX_get_current_cert(x509_ctx);
- int depth = X509_STORE_CTX_get_error_depth(x509_ctx);
- int err = X509_STORE_CTX_get_error(x509_ctx);
- struct curl_fetch_info *f = X509_STORE_CTX_get_app_data(x509_ctx);
+ /* cURL initialised okay, register the fetchers */
- /* save the certificate by incrementing the reference count and
- * keeping a pointer */
- if (depth < MAX_CERTS && !f->cert_data[depth].cert) {
- f->cert_data[depth].cert = cert;
- f->cert_data[depth].err = err;
- cert->references++;
- }
+ data = curl_version_info(CURLVERSION_NOW);
- return preverify_ok;
-}
+ for (i = 0; data->protocols[i]; i++) {
+ if (strcmp(data->protocols[i], "http") == 0) {
+ scheme = lwc_string_ref(corestring_lwc_http);
+ } else if (strcmp(data->protocols[i], "https") == 0) {
+ scheme = lwc_string_ref(corestring_lwc_https);
-/**
- * OpenSSL certificate chain verification callback
- * Verifies certificate chain, setting up context for fetch_curl_verify_callback
- */
+ } else {
+ /* Ignore non-http(s) protocols */
+ continue;
+ }
-int fetch_curl_cert_verify_callback(X509_STORE_CTX *x509_ctx, void *parm)
-{
- int ok;
+ if (fetcher_add(scheme, &fetcher_ops) != NSERROR_OK) {
+ LOG(("Unable to register cURL fetcher for %s",
+ data->protocols[i]));
+ }
+ }
- /* Store fetch struct in context for verify callback */
- ok = X509_STORE_CTX_set_app_data(x509_ctx, parm);
+ return NSERROR_OK;
- /* and verify the certificate chain */
- if (ok)
- ok = X509_verify_cert(x509_ctx);
+curl_easy_setopt_failed:
+ LOG(("curl_easy_setopt failed."));
+ return NSERROR_INIT_FAILED;
- return ok;
+#if LIBCURL_VERSION_NUM >= 0x071e00
+curl_multi_setopt_failed:
+ LOG(("curl_multi_setopt failed."));
+ return NSERROR_INIT_FAILED;
+#endif
}
diff --git a/content/fetchers/curl.h b/content/fetchers/curl.h
index 7ee0963..5f2446a 100644
--- a/content/fetchers/curl.h
+++ b/content/fetchers/curl.h
@@ -25,7 +25,12 @@
#include <curl/curl.h>
-void fetch_curl_register(void);
+/**
+ * Register curl scheme handler.
+ *
+ * \return NSERROR_OK on successful registration or error code on failure.
+ */
+nserror fetch_curl_register(void);
/** Global cURL multi handle. */
extern CURLM *fetch_curl_multi;
diff --git a/content/fetchers/data.h b/content/fetchers/data.h
index f6017e0..2f89ecf 100644
--- a/content/fetchers/data.h
+++ b/content/fetchers/data.h
@@ -16,13 +16,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * data: URL method handler
+/**
+ * \file
+ * data scheme fetch handler interface.
*/
#ifndef NETSURF_CONTENT_FETCHERS_FETCH_DATA_H
#define NETSURF_CONTENT_FETCHERS_FETCH_DATA_H
+/**
+ * Register data scheme handler.
+ *
+ * \return NSERROR_OK on successful registration or error code on failure.
+ */
nserror fetch_data_register(void);
#endif
diff --git a/content/fetchers/file.h b/content/fetchers/file.h
index b3c39db..5a5cfe8 100644
--- a/content/fetchers/file.h
+++ b/content/fetchers/file.h
@@ -16,13 +16,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * file: URL method handler
+/**
+ * \file
+ * file scheme fetcher handler interface.
*/
#ifndef NETSURF_CONTENT_FETCHERS_FETCH_FILE_H
#define NETSURF_CONTENT_FETCHERS_FETCH_FILE_H
+/**
+ * Register file scheme handler.
+ *
+ * \return NSERROR_OK on successful registration or error code on failure.
+ */
nserror fetch_file_register(void);
#endif
diff --git a/content/fetchers/resource.h b/content/fetchers/resource.h
index cf4d6ed..8c7b2d1 100644
--- a/content/fetchers/resource.h
+++ b/content/fetchers/resource.h
@@ -16,8 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * resource: URL method handler.
+/**
+ * \file
+ * resource URL scheme handler interface.
*
* The resource fetcher is intended to provide a flat uniform URL
* space for browser local resources referenced by URL. Using this
@@ -34,6 +35,8 @@
* Register the resource scheme.
*
* should only be called from the fetch initialise
+ *
+ * \return NSERROR_OK on successful registration or error code on failure.
*/
nserror fetch_resource_register(void);
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=7cf5cf7cb7797d7f39b...
commit 7cf5cf7cb7797d7f39bb101504822da44ccc3355
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
fix doc comments
diff --git a/utils/messages.c b/utils/messages.c
index 27038e4..c623297 100644
--- a/utils/messages.c
+++ b/utils/messages.c
@@ -200,79 +200,79 @@ const char *messages_get_errorcode(nserror code)
{
switch (code) {
case NSERROR_OK:
- /**< No error */
+ /* No error */
return messages_get_ctx("OK", messages_hash);
case NSERROR_NOMEM:
- /**< Memory exhaustion */
+ /* Memory exhaustion */
return messages_get_ctx("NoMemory", messages_hash);
case NSERROR_NO_FETCH_HANDLER:
- /**< No fetch handler for URL scheme */
+ /* No fetch handler for URL scheme */
return messages_get_ctx("NoHandler", messages_hash);
case NSERROR_NOT_FOUND:
- /**< Requested item not found */
+ /* Requested item not found */
return messages_get_ctx("NotFound", messages_hash);
case NSERROR_SAVE_FAILED:
- /**< Failed to save data */
+ /* Failed to save data */
return messages_get_ctx("SaveFailed", messages_hash);
case NSERROR_CLONE_FAILED:
- /**< Failed to clone handle */
+ /* Failed to clone handle */
return messages_get_ctx("CloneFailed", messages_hash);
case NSERROR_INIT_FAILED:
- /**< Initialisation failed */
+ /* Initialisation failed */
return messages_get_ctx("InitFailed", messages_hash);
case NSERROR_MNG_ERROR:
- /**< An MNG error occurred */
+ /* An MNG error occurred */
return messages_get_ctx("MNGError", messages_hash);
case NSERROR_BAD_ENCODING:
- /**< The character set is unknown */
+ /* The character set is unknown */
return messages_get_ctx("BadEncoding", messages_hash);
case NSERROR_NEED_DATA:
- /**< More data needed */
+ /* More data needed */
return messages_get_ctx("NeedData", messages_hash);
case NSERROR_ENCODING_CHANGE:
- /**< The character set encoding change was unhandled */
+ /* The character set encoding change was unhandled */
return messages_get_ctx("EncodingChanged", messages_hash);
case NSERROR_BAD_PARAMETER:
- /**< Bad Parameter */
+ /* Bad Parameter */
return messages_get_ctx("BadParameter", messages_hash);
case NSERROR_INVALID:
- /**< Invalid data */
+ /* Invalid data */
return messages_get_ctx("Invalid", messages_hash);
case NSERROR_BOX_CONVERT:
- /**< Box conversion failed */
+ /* Box conversion failed */
return messages_get_ctx("BoxConvert", messages_hash);
case NSERROR_STOPPED:
- /**< Content conversion stopped */
+ /* Content conversion stopped */
return messages_get_ctx("Stopped", messages_hash);
case NSERROR_DOM:
- /**< DOM call returned error */
+ /* DOM call returned error */
return messages_get_ctx("ParsingFail", messages_hash);
case NSERROR_CSS:
- /**< CSS call returned error */
+ /* CSS call returned error */
return messages_get_ctx("CSSGeneric", messages_hash);
case NSERROR_CSS_BASE:
- /**< CSS base sheet failed */
+ /* CSS base sheet failed */
return messages_get_ctx("CSSBase", messages_hash);
case NSERROR_BAD_URL:
- /**< Bad URL */
+ /* Bad URL */
return messages_get_ctx("BadURL", messages_hash);
default:
@@ -280,6 +280,6 @@ const char *messages_get_errorcode(nserror code)
break;
}
- /**< Unknown error */
+ /* Unknown error */
return messages_get_ctx("Unknown", messages_hash);
}
-----------------------------------------------------------------------
Summary of changes:
content/fetch.c | 36 +-
content/fetchers/about.h | 5 +
content/fetchers/curl.c | 1024 +++++++++++++++++++++----------------------
content/fetchers/curl.h | 7 +-
content/fetchers/data.h | 10 +-
content/fetchers/file.h | 10 +-
content/fetchers/resource.h | 7 +-
utils/messages.c | 40 +-
8 files changed, 578 insertions(+), 561 deletions(-)
diff --git a/content/fetch.c b/content/fetch.c
index 7923e9a..2c326e8 100644
--- a/content/fetch.c
+++ b/content/fetch.c
@@ -287,14 +287,36 @@ static void fetcher_poll(void *unused)
/* exported interface documented in content/fetch.h */
nserror fetcher_init(void)
{
- fetch_curl_register();
- fetch_data_register();
- fetch_file_register();
- fetch_resource_register();
- fetch_about_register();
- fetch_javascript_register();
+ nserror ret;
- return NSERROR_OK;
+ ret = fetch_curl_register();
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ ret = fetch_data_register();
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ ret = fetch_file_register();
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ ret = fetch_resource_register();
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ ret = fetch_about_register();
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ ret = fetch_javascript_register();
+
+ return ret;
}
/* exported interface documented in content/fetchers.h */
diff --git a/content/fetchers/about.h b/content/fetchers/about.h
index 9544971..944f84a 100644
--- a/content/fetchers/about.h
+++ b/content/fetchers/about.h
@@ -23,6 +23,11 @@
#ifndef NETSURF_CONTENT_FETCHERS_FETCH_ABOUT_H
#define NETSURF_CONTENT_FETCHERS_FETCH_ABOUT_H
+/**
+ * Register about scheme handler.
+ *
+ * \return NSERROR_OK on successful registration or error code on failure.
+ */
nserror fetch_about_register(void);
#endif
diff --git a/content/fetchers/curl.c b/content/fetchers/curl.c
index df48d8b..b3a7c69 100644
--- a/content/fetchers/curl.c
+++ b/content/fetchers/curl.c
@@ -18,12 +18,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Fetching of data from an URL (implementation).
+/**
+ * \file
+ * implementation of fetching of data from http and https schemes.
*
* This implementation uses libcurl's 'multi' interface.
*
- *
* The CURL handles are cached in the curl_handle_ring. There are at most
* ::max_cached_fetch_handles in this ring.
*/
@@ -106,193 +106,11 @@ static bool curl_with_openssl;
static char fetch_error_buffer[CURL_ERROR_SIZE]; /**< Error buffer for cURL. */
static char fetch_proxy_userpwd[100]; /**< Proxy authentication details. */
-static bool fetch_curl_initialise(lwc_string *scheme);
-static void fetch_curl_finalise(lwc_string *scheme);
-static bool fetch_curl_can_fetch(const nsurl *url);
-static void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
- bool only_2xx, bool downgrade_tls, const char *post_urlenc,
- const struct fetch_multipart_data *post_multipart,
- const char **headers);
-static bool fetch_curl_start(void *vfetch);
-static bool fetch_curl_initiate_fetch(struct curl_fetch_info *fetch,
- CURL *handle);
-static CURL *fetch_curl_get_handle(lwc_string *host);
-static void fetch_curl_cache_handle(CURL *handle, lwc_string *host);
-static CURLcode fetch_curl_set_options(struct curl_fetch_info *f);
-static CURLcode fetch_curl_sslctxfun(CURL *curl_handle, void *_sslctx,
- void *p);
-static void fetch_curl_abort(void *vf);
-static void fetch_curl_stop(struct curl_fetch_info *f);
-static void fetch_curl_free(void *f);
-static void fetch_curl_poll(lwc_string *scheme_ignored);
-static void fetch_curl_done(CURL *curl_handle, CURLcode result);
-static int fetch_curl_progress(void *clientp, double dltotal, double dlnow,
- double ultotal, double ulnow);
-static int fetch_curl_ignore_debug(CURL *handle,
- curl_infotype type,
- char *data,
- size_t size,
- void *userptr);
-static size_t fetch_curl_data(char *data, size_t size, size_t nmemb,
- void *_f);
-static size_t fetch_curl_header(char *data, size_t size, size_t nmemb,
- void *_f);
-static bool fetch_curl_process_headers(struct curl_fetch_info *f);
-static struct curl_httppost *fetch_curl_post_convert(
- const struct fetch_multipart_data *control);
-static int fetch_curl_verify_callback(int preverify_ok,
- X509_STORE_CTX *x509_ctx);
-static int fetch_curl_cert_verify_callback(X509_STORE_CTX *x509_ctx,
- void *parm);
-
-
-/**
- * Initialise the fetcher.
- *
- * Must be called once before any other function.
- */
-
-void fetch_curl_register(void)
-{
- CURLcode code;
- curl_version_info_data *data;
- int i;
- lwc_string *scheme;
- const struct fetcher_operation_table fetcher_ops = {
- .initialise = fetch_curl_initialise,
- .acceptable = fetch_curl_can_fetch,
- .setup = fetch_curl_setup,
- .start = fetch_curl_start,
- .abort = fetch_curl_abort,
- .free = fetch_curl_free,
- .poll = fetch_curl_poll,
- .finalise = fetch_curl_finalise
- };
-
- LOG(("curl_version %s", curl_version()));
-
- code = curl_global_init(CURL_GLOBAL_ALL);
- if (code != CURLE_OK)
- die("Failed to initialise the fetch module "
- "(curl_global_init failed).");
-
- fetch_curl_multi = curl_multi_init();
- if (!fetch_curl_multi)
- die("Failed to initialise the fetch module "
- "(curl_multi_init failed).");
-
-#if LIBCURL_VERSION_NUM >= 0x071e00
- /* We've been built against 7.30.0 or later: configure caching */
- {
- CURLMcode mcode;
- int maxconnects = nsoption_int(max_fetchers) +
- nsoption_int(max_cached_fetch_handles);
-
-#undef SETOPT
-#define SETOPT(option, value) \
- mcode = curl_multi_setopt(fetch_curl_multi, option, value); \
- if (mcode != CURLM_OK) \
- goto curl_multi_setopt_failed;
-
- SETOPT(CURLMOPT_MAXCONNECTS, maxconnects);
- SETOPT(CURLMOPT_MAX_TOTAL_CONNECTIONS, maxconnects);
- SETOPT(CURLMOPT_MAX_HOST_CONNECTIONS, nsoption_int(max_fetchers_per_host));
- }
-#endif
-
- /* Create a curl easy handle with the options that are common to all
- fetches. */
- fetch_blank_curl = curl_easy_init();
- if (!fetch_blank_curl)
- die("Failed to initialise the fetch module "
- "(curl_easy_init failed).");
-
-#undef SETOPT
-#define SETOPT(option, value) \
- code = curl_easy_setopt(fetch_blank_curl, option, value); \
- if (code != CURLE_OK) \
- goto curl_easy_setopt_failed;
-
- if (verbose_log) {
- SETOPT(CURLOPT_VERBOSE, 1);
- } else {
- SETOPT(CURLOPT_VERBOSE, 0);
- }
- SETOPT(CURLOPT_ERRORBUFFER, fetch_error_buffer);
- if (nsoption_bool(suppress_curl_debug)) {
- SETOPT(CURLOPT_DEBUGFUNCTION, fetch_curl_ignore_debug);
- }
- SETOPT(CURLOPT_WRITEFUNCTION, fetch_curl_data);
- SETOPT(CURLOPT_HEADERFUNCTION, fetch_curl_header);
- SETOPT(CURLOPT_PROGRESSFUNCTION, fetch_curl_progress);
- SETOPT(CURLOPT_NOPROGRESS, 0);
- SETOPT(CURLOPT_USERAGENT, user_agent_string());
- SETOPT(CURLOPT_ENCODING, "gzip");
- SETOPT(CURLOPT_LOW_SPEED_LIMIT, 1L);
- SETOPT(CURLOPT_LOW_SPEED_TIME, 180L);
- SETOPT(CURLOPT_NOSIGNAL, 1L);
- SETOPT(CURLOPT_CONNECTTIMEOUT, 30L);
-
- if (nsoption_charp(ca_bundle) &&
- strcmp(nsoption_charp(ca_bundle), "")) {
- LOG(("ca_bundle: '%s'", nsoption_charp(ca_bundle)));
- SETOPT(CURLOPT_CAINFO, nsoption_charp(ca_bundle));
- }
- if (nsoption_charp(ca_path) && strcmp(nsoption_charp(ca_path), "")) {
- LOG(("ca_path: '%s'", nsoption_charp(ca_path)));
- SETOPT(CURLOPT_CAPATH, nsoption_charp(ca_path));
- }
-
- /* Detect whether the SSL CTX function API works */
- curl_with_openssl = true;
- code = curl_easy_setopt(fetch_blank_curl,
- CURLOPT_SSL_CTX_FUNCTION, NULL);
- if (code != CURLE_OK) {
- curl_with_openssl = false;
- }
-
- LOG(("cURL %slinked against openssl", curl_with_openssl ? "" : "not "));
-
- /* cURL initialised okay, register the fetchers */
-
- data = curl_version_info(CURLVERSION_NOW);
-
- for (i = 0; data->protocols[i]; i++) {
- if (strcmp(data->protocols[i], "http") == 0) {
- scheme = lwc_string_ref(corestring_lwc_http);
-
- } else if (strcmp(data->protocols[i], "https") == 0) {
- scheme = lwc_string_ref(corestring_lwc_https);
-
- } else {
- /* Ignore non-http(s) protocols */
- continue;
- }
-
- if (fetcher_add(scheme, &fetcher_ops) != NSERROR_OK) {
- LOG(("Unable to register cURL fetcher for %s",
- data->protocols[i]));
- }
- }
- return;
-
-curl_easy_setopt_failed:
- die("Failed to initialise the fetch module "
- "(curl_easy_setopt failed).");
-
-#if LIBCURL_VERSION_NUM >= 0x071e00
-curl_multi_setopt_failed:
- die("Failed to initialise the fetch module "
- "(curl_multi_setopt failed).");
-#endif
-}
-
/**
* Initialise a cURL fetcher.
*/
-
-bool fetch_curl_initialise(lwc_string *scheme)
+static bool fetch_curl_initialise(lwc_string *scheme)
{
LOG(("Initialise cURL fetcher for %s", lwc_string_data(scheme)));
curl_fetchers_registered++;
@@ -301,10 +119,11 @@ bool fetch_curl_initialise(lwc_string *scheme)
/**
- * Finalise a cURL fetcher
+ * Finalise a cURL fetcher.
+ *
+ * \param scheme The scheme to finalise.
*/
-
-void fetch_curl_finalise(lwc_string *scheme)
+static void fetch_curl_finalise(lwc_string *scheme)
{
struct cache_handle *h;
@@ -334,19 +153,103 @@ void fetch_curl_finalise(lwc_string *scheme)
}
}
-bool fetch_curl_can_fetch(const nsurl *url)
+
+/**
+ * Check if this fetcher can fetch a url.
+ *
+ * \param url The url to check.
+ * \return true if teh fetcher supports teh url else false.
+ */
+static bool fetch_curl_can_fetch(const nsurl *url)
{
return nsurl_has_component(url, NSURL_HOST);
}
+
+/**
+ * Convert a list of struct ::fetch_multipart_data to a list of
+ * struct curl_httppost for libcurl.
+ */
+static struct curl_httppost *
+fetch_curl_post_convert(const struct fetch_multipart_data *control)
+{
+ struct curl_httppost *post = 0, *last = 0;
+ CURLFORMcode code;
+ nserror ret;
+
+ for (; control; control = control->next) {
+ if (control->file) {
+ char *leafname = NULL;
+ ret = guit->file->basename(control->value, &leafname, NULL);
+ if (ret != NSERROR_OK) {
+ continue;
+ }
+
+ /* We have to special case filenames of "", so curl
+ * a) actually attempts the fetch and
+ * b) doesn't attempt to open the file ""
+ */
+ if (control->value[0] == '\0') {
+ /* dummy buffer - needs to be static so
+ * pointer's still valid when we go out
+ * of scope (not that libcurl should be
+ * attempting to access it, of course).
+ */
+ static char buf;
+
+ code = curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, control->name,
+ CURLFORM_BUFFER, control->value,
+ /* needed, as basename("") == "." */
+ CURLFORM_FILENAME, "",
+ CURLFORM_BUFFERPTR, &buf,
+ CURLFORM_BUFFERLENGTH, 0,
+ CURLFORM_CONTENTTYPE,
+ "application/octet-stream",
+ CURLFORM_END);
+ if (code != CURL_FORMADD_OK)
+ LOG(("curl_formadd: %d (%s)",
+ code, control->name));
+ } else {
+ char *mimetype = guit->fetch->mimetype(control->value);
+ code = curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, control->name,
+ CURLFORM_FILE, control->rawfile,
+ CURLFORM_FILENAME, leafname,
+ CURLFORM_CONTENTTYPE,
+ (mimetype != 0 ? mimetype : "text/plain"),
+ CURLFORM_END);
+ if (code != CURL_FORMADD_OK)
+ LOG(("curl_formadd: %d (%s=%s)",
+ code, control->name,
+ control->value));
+ free(mimetype);
+ }
+ free(leafname);
+ }
+ else {
+ code = curl_formadd(&post, &last,
+ CURLFORM_COPYNAME, control->name,
+ CURLFORM_COPYCONTENTS, control->value,
+ CURLFORM_END);
+ if (code != CURL_FORMADD_OK)
+ LOG(("curl_formadd: %d (%s=%s)", code,
+ control->name,
+ control->value));
+ }
+ }
+
+ return post;
+}
+
/**
* Start fetching data for the given URL.
*
* The function returns immediately. The fetch may be queued for later
* processing.
*
- * A pointer to an opaque struct curl_fetch_info is returned, which can be
- * passed to fetch_abort() to abort the fetch at any time. Returns 0 if memory
+ * A pointer to an opaque struct curl_fetch_info is returned, which can be
+ * passed to fetch_abort() to abort the fetch at any time. Returns 0 if memory
* is exhausted (or some other fatal error occurred).
*
* The caller must supply a callback function which is called when anything
@@ -360,9 +263,12 @@ bool fetch_curl_can_fetch(const nsurl *url)
* Some private data can be passed as the last parameter to fetch_start, and
* callbacks will contain this.
*/
-
-void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
- bool only_2xx, bool downgrade_tls, const char *post_urlenc,
+static void *
+fetch_curl_setup(struct fetch *parent_fetch,
+ nsurl *url,
+ bool only_2xx,
+ bool downgrade_tls,
+ const char *post_urlenc,
const struct fetch_multipart_data *post_multipart,
const char **headers)
{
@@ -420,7 +326,7 @@ void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
* which fails with lighttpd, so disable it (see bug 1429054) */
APPEND(fetch->headers, "Expect:");
- if ((nsoption_charp(accept_language) != NULL) &&
+ if ((nsoption_charp(accept_language) != NULL) &&
(nsoption_charp(accept_language)[0] != '\0')) {
char s[80];
snprintf(s, sizeof s, "Accept-Language: %s, *;q=0.1",
@@ -429,7 +335,7 @@ void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
APPEND(fetch->headers, s);
}
- if (nsoption_charp(accept_charset) != NULL &&
+ if (nsoption_charp(accept_charset) != NULL &&
nsoption_charp(accept_charset)[0] != '\0') {
char s[80];
snprintf(s, sizeof s, "Accept-Charset: %s, *;q=0.1",
@@ -449,6 +355,8 @@ void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
return fetch;
+#undef APPEND
+
failed:
if (fetch->host != NULL)
lwc_string_unref(fetch->host);
@@ -464,126 +372,96 @@ failed:
/**
- * Dispatch a single job
- */
-bool fetch_curl_start(void *vfetch)
-{
- struct curl_fetch_info *fetch = (struct curl_fetch_info*)vfetch;
- return fetch_curl_initiate_fetch(fetch,
- fetch_curl_get_handle(fetch->host));
-}
-
-
-/**
- * Initiate a fetch from the queue.
- *
- * Called with a fetch structure and a CURL handle to be used to fetch the
- * content.
- *
- * This will return whether or not the fetch was successfully initiated.
+ * OpenSSL Certificate verification callback
+ * Stores certificate details in fetch struct.
*/
-
-bool fetch_curl_initiate_fetch(struct curl_fetch_info *fetch, CURL *handle)
+static int
+fetch_curl_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
{
- CURLcode code;
- CURLMcode codem;
-
- fetch->curl_handle = handle;
+ X509 *cert = X509_STORE_CTX_get_current_cert(x509_ctx);
+ int depth = X509_STORE_CTX_get_error_depth(x509_ctx);
+ int err = X509_STORE_CTX_get_error(x509_ctx);
+ struct curl_fetch_info *f = X509_STORE_CTX_get_app_data(x509_ctx);
- /* Initialise the handle */
- code = fetch_curl_set_options(fetch);
- if (code != CURLE_OK) {
- fetch->curl_handle = 0;
- return false;
+ /* save the certificate by incrementing the reference count and
+ * keeping a pointer.
+ */
+ if (depth < MAX_CERTS && !f->cert_data[depth].cert) {
+ f->cert_data[depth].cert = cert;
+ f->cert_data[depth].err = err;
+ cert->references++;
}
- /* add to the global curl multi handle */
- codem = curl_multi_add_handle(fetch_curl_multi, fetch->curl_handle);
- assert(codem == CURLM_OK || codem == CURLM_CALL_MULTI_PERFORM);
-
- return true;
+ return preverify_ok;
}
/**
- * Find a CURL handle to use to dispatch a job
+ * OpenSSL certificate chain verification callback
+ * Verifies certificate chain, setting up context for fetch_curl_verify_callback
*/
-
-CURL *fetch_curl_get_handle(lwc_string *host)
+static int fetch_curl_cert_verify_callback(X509_STORE_CTX *x509_ctx, void *parm)
{
- struct cache_handle *h;
- CURL *ret;
- RING_FINDBYLWCHOST(curl_handle_ring, h, host);
- if (h) {
- ret = h->handle;
- lwc_string_unref(h->host);
- RING_REMOVE(curl_handle_ring, h);
- free(h);
- } else {
- ret = curl_easy_duphandle(fetch_blank_curl);
- }
- return ret;
+ int ok;
+
+ /* Store fetch struct in context for verify callback */
+ ok = X509_STORE_CTX_set_app_data(x509_ctx, parm);
+
+ /* and verify the certificate chain */
+ if (ok)
+ ok = X509_verify_cert(x509_ctx);
+
+ return ok;
}
/**
- * Cache a CURL handle for the provided host (if wanted)
+ * cURL SSL setup callback
+ *
+ * \param curl_handle The curl handle to perform the ssl operation on.
+ * \param _sslctx The ssl context.
+ * \param parm The callback context.
+ * \return A curl result code.
*/
-
-void fetch_curl_cache_handle(CURL *handle, lwc_string *host)
+static CURLcode
+fetch_curl_sslctxfun(CURL *curl_handle, void *_sslctx, void *parm)
{
-#if LIBCURL_VERSION_NUM >= 0x071e00
- /* 7.30.0 or later has its own connection caching; suppress ours */
- curl_easy_cleanup(handle);
- return;
-#else
- struct cache_handle *h = 0;
- int c;
- RING_FINDBYLWCHOST(curl_handle_ring, h, host);
- if (h) {
- /* Already have a handle cached for this hostname */
- curl_easy_cleanup(handle);
- return;
- }
- /* We do not have a handle cached, first up determine if the cache is full */
- RING_GETSIZE(struct cache_handle, curl_handle_ring, c);
- if (c >= nsoption_int(max_cached_fetch_handles)) {
- /* Cache is full, so, we rotate the ring by one and
- * replace the oldest handle with this one. We do this
- * without freeing/allocating memory (except the
- * hostname) and without removing the entry from the
- * ring and then re-inserting it, in order to be as
- * efficient as we can.
- */
- if (curl_handle_ring != NULL) {
- h = curl_handle_ring;
- curl_handle_ring = h->r_next;
- curl_easy_cleanup(h->handle);
- h->handle = handle;
- lwc_string_unref(h->host);
- h->host = lwc_string_ref(host);
- } else {
- /* Actually, we don't want to cache any handles */
- curl_easy_cleanup(handle);
- }
+ struct curl_fetch_info *f = (struct curl_fetch_info *) parm;
+ SSL_CTX *sslctx = _sslctx;
+ long options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
- return;
- }
- /* The table isn't full yet, so make a shiny new handle to add to the ring */
- h = (struct cache_handle*)malloc(sizeof(struct cache_handle));
- h->handle = handle;
- h->host = lwc_string_ref(host);
- RING_INSERT(curl_handle_ring, h);
+ SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, fetch_curl_verify_callback);
+ SSL_CTX_set_cert_verify_callback(sslctx,
+ fetch_curl_cert_verify_callback,
+ parm);
+
+ if (f->downgrade_tls) {
+ /* Disable TLS 1.1/1.2 if the server can't cope with them */
+#ifdef SSL_OP_NO_TLSv1_1
+ options |= SSL_OP_NO_TLSv1_1;
#endif
+#ifdef SSL_OP_NO_TLSv1_2
+ options |= SSL_OP_NO_TLSv1_2;
+#endif
+#ifdef SSL_MODE_SEND_FALLBACK_SCSV
+ /* Ensure server rejects the connection if downgraded too far */
+ SSL_CTX_set_mode(sslctx, SSL_MODE_SEND_FALLBACK_SCSV);
+#endif
+ }
+
+ SSL_CTX_set_options(sslctx, options);
+
+ return CURLE_OK;
}
/**
* Set options specific for a fetch.
+ *
+ * \param f The fetch to set options on.
+ * \return A curl result code.
*/
-
-CURLcode
-fetch_curl_set_options(struct curl_fetch_info *f)
+static CURLcode fetch_curl_set_options(struct curl_fetch_info *f)
{
CURLcode code;
const char *auth;
@@ -631,7 +509,7 @@ fetch_curl_set_options(struct curl_fetch_info *f)
}
/* set up proxy options */
- if (nsoption_bool(http_proxy) &&
+ if (nsoption_bool(http_proxy) &&
(nsoption_charp(http_proxy_host) != NULL) &&
(strncmp(nsurl_access(f->url), "file:", 5) != 0)) {
SETOPT(CURLOPT_PROXY, nsoption_charp(http_proxy_host));
@@ -684,47 +562,122 @@ fetch_curl_set_options(struct curl_fetch_info *f)
return CURLE_OK;
}
+/**
+ * Initiate a fetch from the queue.
+ *
+ * \param fetch fetch to use to fetch content.
+ * \param handle CURL handle to be used to fetch the content.
+ * \return true if the fetch was successfully initiated else false.
+ */
+static bool
+fetch_curl_initiate_fetch(struct curl_fetch_info *fetch, CURL *handle)
+{
+ CURLcode code;
+ CURLMcode codem;
+
+ fetch->curl_handle = handle;
+
+ /* Initialise the handle */
+ code = fetch_curl_set_options(fetch);
+ if (code != CURLE_OK) {
+ fetch->curl_handle = 0;
+ return false;
+ }
+
+ /* add to the global curl multi handle */
+ codem = curl_multi_add_handle(fetch_curl_multi, fetch->curl_handle);
+ assert(codem == CURLM_OK || codem == CURLM_CALL_MULTI_PERFORM);
+
+ return true;
+}
+
/**
- * cURL SSL setup callback
+ * Find a CURL handle to use to dispatch a job
*/
+static CURL *fetch_curl_get_handle(lwc_string *host)
+{
+ struct cache_handle *h;
+ CURL *ret;
+ RING_FINDBYLWCHOST(curl_handle_ring, h, host);
+ if (h) {
+ ret = h->handle;
+ lwc_string_unref(h->host);
+ RING_REMOVE(curl_handle_ring, h);
+ free(h);
+ } else {
+ ret = curl_easy_duphandle(fetch_blank_curl);
+ }
+ return ret;
+}
-CURLcode
-fetch_curl_sslctxfun(CURL *curl_handle, void *_sslctx, void *parm)
+
+/**
+ * Dispatch a single job
+ */
+static bool fetch_curl_start(void *vfetch)
{
- struct curl_fetch_info *f = (struct curl_fetch_info *) parm;
- SSL_CTX *sslctx = _sslctx;
- long options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
+ struct curl_fetch_info *fetch = (struct curl_fetch_info*)vfetch;
+ return fetch_curl_initiate_fetch(fetch,
+ fetch_curl_get_handle(fetch->host));
+}
- SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, fetch_curl_verify_callback);
- SSL_CTX_set_cert_verify_callback(sslctx, fetch_curl_cert_verify_callback,
- parm);
+/**
+ * Cache a CURL handle for the provided host (if wanted)
+ */
- if (f->downgrade_tls) {
- /* Disable TLS 1.1/1.2 if the server can't cope with them */
-#ifdef SSL_OP_NO_TLSv1_1
- options |= SSL_OP_NO_TLSv1_1;
-#endif
-#ifdef SSL_OP_NO_TLSv1_2
- options |= SSL_OP_NO_TLSv1_2;
-#endif
-#ifdef SSL_MODE_SEND_FALLBACK_SCSV
- /* Ensure server rejects the connection if downgraded too far */
- SSL_CTX_set_mode(sslctx, SSL_MODE_SEND_FALLBACK_SCSV);
-#endif
+static void fetch_curl_cache_handle(CURL *handle, lwc_string *host)
+{
+#if LIBCURL_VERSION_NUM >= 0x071e00
+ /* 7.30.0 or later has its own connection caching; suppress ours */
+ curl_easy_cleanup(handle);
+ return;
+#else
+ struct cache_handle *h = 0;
+ int c;
+ RING_FINDBYLWCHOST(curl_handle_ring, h, host);
+ if (h) {
+ /* Already have a handle cached for this hostname */
+ curl_easy_cleanup(handle);
+ return;
}
+ /* We do not have a handle cached, first up determine if the cache is full */
+ RING_GETSIZE(struct cache_handle, curl_handle_ring, c);
+ if (c >= nsoption_int(max_cached_fetch_handles)) {
+ /* Cache is full, so, we rotate the ring by one and
+ * replace the oldest handle with this one. We do this
+ * without freeing/allocating memory (except the
+ * hostname) and without removing the entry from the
+ * ring and then re-inserting it, in order to be as
+ * efficient as we can.
+ */
+ if (curl_handle_ring != NULL) {
+ h = curl_handle_ring;
+ curl_handle_ring = h->r_next;
+ curl_easy_cleanup(h->handle);
+ h->handle = handle;
+ lwc_string_unref(h->host);
+ h->host = lwc_string_ref(host);
+ } else {
+ /* Actually, we don't want to cache any handles */
+ curl_easy_cleanup(handle);
+ }
- SSL_CTX_set_options(sslctx, options);
-
- return CURLE_OK;
+ return;
+ }
+ /* The table isn't full yet, so make a shiny new handle to add to the ring */
+ h = (struct cache_handle*)malloc(sizeof(struct cache_handle));
+ h->handle = handle;
+ h->host = lwc_string_ref(host);
+ RING_INSERT(curl_handle_ring, h);
+#endif
}
/**
* Abort a fetch.
*/
-
-void fetch_curl_abort(void *vf)
+static void fetch_curl_abort(void *vf)
{
struct curl_fetch_info *f = (struct curl_fetch_info *)vf;
assert(f);
@@ -743,8 +696,7 @@ void fetch_curl_abort(void *vf)
*
* Will prod the queue afterwards to allow pending requests to be initiated.
*/
-
-void fetch_curl_stop(struct curl_fetch_info *f)
+static void fetch_curl_stop(struct curl_fetch_info *f)
{
CURLMcode codem;
@@ -768,8 +720,7 @@ void fetch_curl_stop(struct curl_fetch_info *f)
/**
* Free a fetch structure and associated resources.
*/
-
-void fetch_curl_free(void *vf)
+static void fetch_curl_free(void *vf)
{
struct curl_fetch_info *f = (struct curl_fetch_info *)vf;
int i;
@@ -798,41 +749,65 @@ void fetch_curl_free(void *vf)
/**
- * Do some work on current fetches.
+ * Find the status code and content type and inform the caller.
*
- * Must be called regularly to make progress on fetches.
+ * Return true if the fetch is being aborted.
*/
-
-void fetch_curl_poll(lwc_string *scheme_ignored)
+static bool fetch_curl_process_headers(struct curl_fetch_info *f)
{
- int running, queue;
- CURLMcode codem;
- CURLMsg *curl_msg;
-
- /* do any possible work on the current fetches */
- do {
- codem = curl_multi_perform(fetch_curl_multi, &running);
- if (codem != CURLM_OK && codem != CURLM_CALL_MULTI_PERFORM) {
- LOG(("curl_multi_perform: %i %s",
- codem, curl_multi_strerror(codem)));
- warn_user("MiscError", curl_multi_strerror(codem));
- return;
- }
- } while (codem == CURLM_CALL_MULTI_PERFORM);
+ long http_code;
+ CURLcode code;
+ fetch_msg msg;
- /* process curl results */
- curl_msg = curl_multi_info_read(fetch_curl_multi, &queue);
- while (curl_msg) {
- switch (curl_msg->msg) {
- case CURLMSG_DONE:
- fetch_curl_done(curl_msg->easy_handle,
- curl_msg->data.result);
- break;
- default:
- break;
- }
- curl_msg = curl_multi_info_read(fetch_curl_multi, &queue);
+ f->had_headers = true;
+
+ if (!f->http_code)
+ {
+ code = curl_easy_getinfo(f->curl_handle, CURLINFO_HTTP_CODE,
+ &f->http_code);
+ fetch_set_http_code(f->fetch_handle, f->http_code);
+ assert(code == CURLE_OK);
+ }
+ http_code = f->http_code;
+ LOG(("HTTP status code %li", http_code));
+
+ if (http_code == 304 && !f->post_urlenc && !f->post_multipart) {
+ /* Not Modified && GET request */
+ msg.type = FETCH_NOTMODIFIED;
+ fetch_send_callback(&msg, f->fetch_handle);
+ return true;
+ }
+
+ /* handle HTTP redirects (3xx response codes) */
+ if (300 <= http_code && http_code < 400 && f->location != 0) {
+ LOG(("FETCH_REDIRECT, '%s'", f->location));
+ msg.type = FETCH_REDIRECT;
+ msg.data.redirect = f->location;
+ fetch_send_callback(&msg, f->fetch_handle);
+ return true;
}
+
+ /* handle HTTP 401 (Authentication errors) */
+ if (http_code == 401) {
+ msg.type = FETCH_AUTH;
+ msg.data.auth.realm = f->realm;
+ fetch_send_callback(&msg, f->fetch_handle);
+ return true;
+ }
+
+ /* handle HTTP errors (non 2xx response codes) */
+ if (f->only_2xx && strncmp(nsurl_access(f->url), "http", 4) == 0 &&
+ (http_code < 200 || 299 < http_code)) {
+ msg.type = FETCH_ERROR;
+ msg.data.error = messages_get("Not2xx");
+ fetch_send_callback(&msg, f->fetch_handle);
+ return true;
+ }
+
+ if (f->abort)
+ return true;
+
+ return false;
}
@@ -841,8 +816,7 @@ void fetch_curl_poll(lwc_string *scheme_ignored)
*
* \param curl_handle curl easy handle of fetch
*/
-
-void fetch_curl_done(CURL *curl_handle, CURLcode result)
+static void fetch_curl_done(CURL *curl_handle, CURLcode result)
{
fetch_msg msg;
bool finished = false;
@@ -865,14 +839,15 @@ void fetch_curl_done(CURL *curl_handle, CURLcode result)
if (abort_fetch == false && (result == CURLE_OK ||
(result == CURLE_WRITE_ERROR && f->stopped == false))) {
- /* fetch completed normally or the server fed us a junk gzip
- * stream (usually in the form of garbage at the end of the
- * stream). Curl will have fed us all but the last chunk of
- * decoded data, which is sad as, if we'd received the last
+ /* fetch completed normally or the server fed us a junk gzip
+ * stream (usually in the form of garbage at the end of the
+ * stream). Curl will have fed us all but the last chunk of
+ * decoded data, which is sad as, if we'd received the last
* chunk, too, we'd be able to render the whole object.
* As is, we'll just have to accept that the end of the
* object will be truncated in this case and leave it to
- * the content handlers to cope. */
+ * the content handlers to cope.
+ */
if (f->stopped ||
(!f->had_headers &&
fetch_curl_process_headers(f)))
@@ -1008,19 +983,59 @@ void fetch_curl_done(CURL *curl_handle, CURLcode result)
} else {
msg.type = FETCH_SSL_ERR;
}
-
- fetch_send_callback(&msg, f->fetch_handle);
+
+ fetch_send_callback(&msg, f->fetch_handle);
+ }
+
+ fetch_free(f->fetch_handle);
+}
+
+
+/**
+ * Do some work on current fetches.
+ *
+ * Must be called regularly to make progress on fetches.
+ */
+static void fetch_curl_poll(lwc_string *scheme_ignored)
+{
+ int running, queue;
+ CURLMcode codem;
+ CURLMsg *curl_msg;
+
+ /* do any possible work on the current fetches */
+ do {
+ codem = curl_multi_perform(fetch_curl_multi, &running);
+ if (codem != CURLM_OK && codem != CURLM_CALL_MULTI_PERFORM) {
+ LOG(("curl_multi_perform: %i %s",
+ codem, curl_multi_strerror(codem)));
+ warn_user("MiscError", curl_multi_strerror(codem));
+ return;
+ }
+ } while (codem == CURLM_CALL_MULTI_PERFORM);
+
+ /* process curl results */
+ curl_msg = curl_multi_info_read(fetch_curl_multi, &queue);
+ while (curl_msg) {
+ switch (curl_msg->msg) {
+ case CURLMSG_DONE:
+ fetch_curl_done(curl_msg->easy_handle,
+ curl_msg->data.result);
+ break;
+ default:
+ break;
+ }
+ curl_msg = curl_multi_info_read(fetch_curl_multi, &queue);
}
-
- fetch_free(f->fetch_handle);
}
+
+
/**
* Callback function for fetch progress.
*/
-int fetch_curl_progress(void *clientp, double dltotal, double dlnow,
+static int fetch_curl_progress(void *clientp, double dltotal, double dlnow,
double ultotal, double ulnow)
{
static char fetch_progress_buffer[256]; /**< Progress buffer for cURL */
@@ -1061,14 +1076,12 @@ int fetch_curl_progress(void *clientp, double dltotal, double dlnow,
}
-
/**
* Ignore everything given to it.
*
* Used to ignore cURL debug.
*/
-
-int fetch_curl_ignore_debug(CURL *handle,
+static int fetch_curl_ignore_debug(CURL *handle,
curl_infotype type,
char *data,
size_t size,
@@ -1081,9 +1094,7 @@ int fetch_curl_ignore_debug(CURL *handle,
/**
* Callback function for cURL.
*/
-
-size_t fetch_curl_data(char *data, size_t size, size_t nmemb,
- void *_f)
+static size_t fetch_curl_data(char *data, size_t size, size_t nmemb, void *_f)
{
struct curl_fetch_info *f = _f;
CURLcode code;
@@ -1099,7 +1110,8 @@ size_t fetch_curl_data(char *data, size_t size, size_t nmemb,
}
/* ignore body if this is a 401 reply by skipping it and reset
- the HTTP response code to enable follow up fetches */
+ * the HTTP response code to enable follow up fetches.
+ */
if (f->http_code == 401)
{
f->http_code = 0;
@@ -1131,8 +1143,7 @@ size_t fetch_curl_data(char *data, size_t size, size_t nmemb,
*
* See RFC 2616 4.2.
*/
-
-size_t fetch_curl_header(char *data, size_t size, size_t nmemb,
+static size_t fetch_curl_header(char *data, size_t size, size_t nmemb,
void *_f)
{
struct curl_fetch_info *f = _f;
@@ -1211,185 +1222,144 @@ size_t fetch_curl_header(char *data, size_t size, size_t nmemb,
#undef SKIP_ST
}
-/**
- * Find the status code and content type and inform the caller.
- *
- * Return true if the fetch is being aborted.
- */
-bool fetch_curl_process_headers(struct curl_fetch_info *f)
+/* exported function documented in content/fetchers/curl.h */
+nserror fetch_curl_register(void)
{
- long http_code;
CURLcode code;
- fetch_msg msg;
+ curl_version_info_data *data;
+ int i;
+ lwc_string *scheme;
+ const struct fetcher_operation_table fetcher_ops = {
+ .initialise = fetch_curl_initialise,
+ .acceptable = fetch_curl_can_fetch,
+ .setup = fetch_curl_setup,
+ .start = fetch_curl_start,
+ .abort = fetch_curl_abort,
+ .free = fetch_curl_free,
+ .poll = fetch_curl_poll,
+ .finalise = fetch_curl_finalise
+ };
- f->had_headers = true;
+ LOG(("curl_version %s", curl_version()));
- if (!f->http_code)
- {
- code = curl_easy_getinfo(f->curl_handle, CURLINFO_HTTP_CODE,
- &f->http_code);
- fetch_set_http_code(f->fetch_handle, f->http_code);
- assert(code == CURLE_OK);
+ code = curl_global_init(CURL_GLOBAL_ALL);
+ if (code != CURLE_OK) {
+ LOG(("curl_global_init failed."));
+ return NSERROR_INIT_FAILED;
}
- http_code = f->http_code;
- LOG(("HTTP status code %li", http_code));
- if (http_code == 304 && !f->post_urlenc && !f->post_multipart) {
- /* Not Modified && GET request */
- msg.type = FETCH_NOTMODIFIED;
- fetch_send_callback(&msg, f->fetch_handle);
- return true;
+ fetch_curl_multi = curl_multi_init();
+ if (!fetch_curl_multi) {
+ LOG(("curl_multi_init failed."));
+ return NSERROR_INIT_FAILED;
}
- /* handle HTTP redirects (3xx response codes) */
- if (300 <= http_code && http_code < 400 && f->location != 0) {
- LOG(("FETCH_REDIRECT, '%s'", f->location));
- msg.type = FETCH_REDIRECT;
- msg.data.redirect = f->location;
- fetch_send_callback(&msg, f->fetch_handle);
- return true;
- }
+#if LIBCURL_VERSION_NUM >= 0x071e00
+ /* built against 7.30.0 or later: configure caching */
+ {
+ CURLMcode mcode;
+ int maxconnects = nsoption_int(max_fetchers) +
+ nsoption_int(max_cached_fetch_handles);
- /* handle HTTP 401 (Authentication errors) */
- if (http_code == 401) {
- msg.type = FETCH_AUTH;
- msg.data.auth.realm = f->realm;
- fetch_send_callback(&msg, f->fetch_handle);
- return true;
- }
+#undef SETOPT
+#define SETOPT(option, value) \
+ mcode = curl_multi_setopt(fetch_curl_multi, option, value); \
+ if (mcode != CURLM_OK) \
+ goto curl_multi_setopt_failed;
- /* handle HTTP errors (non 2xx response codes) */
- if (f->only_2xx && strncmp(nsurl_access(f->url), "http", 4) == 0 &&
- (http_code < 200 || 299 < http_code)) {
- msg.type = FETCH_ERROR;
- msg.data.error = messages_get("Not2xx");
- fetch_send_callback(&msg, f->fetch_handle);
- return true;
+ SETOPT(CURLMOPT_MAXCONNECTS, maxconnects);
+ SETOPT(CURLMOPT_MAX_TOTAL_CONNECTIONS, maxconnects);
+ SETOPT(CURLMOPT_MAX_HOST_CONNECTIONS, nsoption_int(max_fetchers_per_host));
}
+#endif
- if (f->abort)
- return true;
-
- return false;
-}
-
-
-/**
- * Convert a list of struct ::fetch_multipart_data to a list of
- * struct curl_httppost for libcurl.
- */
-struct curl_httppost *
-fetch_curl_post_convert(const struct fetch_multipart_data *control)
-{
- struct curl_httppost *post = 0, *last = 0;
- CURLFORMcode code;
- nserror ret;
-
- for (; control; control = control->next) {
- if (control->file) {
- char *leafname = NULL;
- ret = guit->file->basename(control->value, &leafname, NULL);
- if (ret != NSERROR_OK) {
- continue;
- }
+ /* Create a curl easy handle with the options that are common to all
+ fetches.
+ */
+ fetch_blank_curl = curl_easy_init();
+ if (!fetch_blank_curl) {
+ LOG(("curl_easy_init failed"));
+ return NSERROR_INIT_FAILED;
+ }
- /* We have to special case filenames of "", so curl
- * a) actually attempts the fetch and
- * b) doesn't attempt to open the file ""
- */
- if (control->value[0] == '\0') {
- /* dummy buffer - needs to be static so
- * pointer's still valid when we go out
- * of scope (not that libcurl should be
- * attempting to access it, of course). */
- static char buf;
+#undef SETOPT
+#define SETOPT(option, value) \
+ code = curl_easy_setopt(fetch_blank_curl, option, value); \
+ if (code != CURLE_OK) \
+ goto curl_easy_setopt_failed;
- code = curl_formadd(&post, &last,
- CURLFORM_COPYNAME, control->name,
- CURLFORM_BUFFER, control->value,
- /* needed, as basename("") == "." */
- CURLFORM_FILENAME, "",
- CURLFORM_BUFFERPTR, &buf,
- CURLFORM_BUFFERLENGTH, 0,
- CURLFORM_CONTENTTYPE,
- "application/octet-stream",
- CURLFORM_END);
- if (code != CURL_FORMADD_OK)
- LOG(("curl_formadd: %d (%s)",
- code, control->name));
- } else {
- char *mimetype = guit->fetch->mimetype(control->value);
- code = curl_formadd(&post, &last,
- CURLFORM_COPYNAME, control->name,
- CURLFORM_FILE, control->rawfile,
- CURLFORM_FILENAME, leafname,
- CURLFORM_CONTENTTYPE,
- (mimetype != 0 ? mimetype : "text/plain"),
- CURLFORM_END);
- if (code != CURL_FORMADD_OK)
- LOG(("curl_formadd: %d (%s=%s)",
- code, control->name,
- control->value));
- free(mimetype);
- }
- free(leafname);
- }
- else {
- code = curl_formadd(&post, &last,
- CURLFORM_COPYNAME, control->name,
- CURLFORM_COPYCONTENTS, control->value,
- CURLFORM_END);
- if (code != CURL_FORMADD_OK)
- LOG(("curl_formadd: %d (%s=%s)", code,
- control->name,
- control->value));
- }
+ if (verbose_log) {
+ SETOPT(CURLOPT_VERBOSE, 1);
+ } else {
+ SETOPT(CURLOPT_VERBOSE, 0);
}
+ SETOPT(CURLOPT_ERRORBUFFER, fetch_error_buffer);
+ if (nsoption_bool(suppress_curl_debug)) {
+ SETOPT(CURLOPT_DEBUGFUNCTION, fetch_curl_ignore_debug);
+ }
+ SETOPT(CURLOPT_WRITEFUNCTION, fetch_curl_data);
+ SETOPT(CURLOPT_HEADERFUNCTION, fetch_curl_header);
+ SETOPT(CURLOPT_PROGRESSFUNCTION, fetch_curl_progress);
+ SETOPT(CURLOPT_NOPROGRESS, 0);
+ SETOPT(CURLOPT_USERAGENT, user_agent_string());
+ SETOPT(CURLOPT_ENCODING, "gzip");
+ SETOPT(CURLOPT_LOW_SPEED_LIMIT, 1L);
+ SETOPT(CURLOPT_LOW_SPEED_TIME, 180L);
+ SETOPT(CURLOPT_NOSIGNAL, 1L);
+ SETOPT(CURLOPT_CONNECTTIMEOUT, 30L);
- return post;
-}
+ if (nsoption_charp(ca_bundle) &&
+ strcmp(nsoption_charp(ca_bundle), "")) {
+ LOG(("ca_bundle: '%s'", nsoption_charp(ca_bundle)));
+ SETOPT(CURLOPT_CAINFO, nsoption_charp(ca_bundle));
+ }
+ if (nsoption_charp(ca_path) && strcmp(nsoption_charp(ca_path), "")) {
+ LOG(("ca_path: '%s'", nsoption_charp(ca_path)));
+ SETOPT(CURLOPT_CAPATH, nsoption_charp(ca_path));
+ }
+ /* Detect whether the SSL CTX function API works */
+ curl_with_openssl = true;
+ code = curl_easy_setopt(fetch_blank_curl,
+ CURLOPT_SSL_CTX_FUNCTION, NULL);
+ if (code != CURLE_OK) {
+ curl_with_openssl = false;
+ }
-/**
- * OpenSSL Certificate verification callback
- * Stores certificate details in fetch struct.
- */
+ LOG(("cURL %slinked against openssl", curl_with_openssl ? "" : "not "));
-int fetch_curl_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
-{
- X509 *cert = X509_STORE_CTX_get_current_cert(x509_ctx);
- int depth = X509_STORE_CTX_get_error_depth(x509_ctx);
- int err = X509_STORE_CTX_get_error(x509_ctx);
- struct curl_fetch_info *f = X509_STORE_CTX_get_app_data(x509_ctx);
+ /* cURL initialised okay, register the fetchers */
- /* save the certificate by incrementing the reference count and
- * keeping a pointer */
- if (depth < MAX_CERTS && !f->cert_data[depth].cert) {
- f->cert_data[depth].cert = cert;
- f->cert_data[depth].err = err;
- cert->references++;
- }
+ data = curl_version_info(CURLVERSION_NOW);
- return preverify_ok;
-}
+ for (i = 0; data->protocols[i]; i++) {
+ if (strcmp(data->protocols[i], "http") == 0) {
+ scheme = lwc_string_ref(corestring_lwc_http);
+ } else if (strcmp(data->protocols[i], "https") == 0) {
+ scheme = lwc_string_ref(corestring_lwc_https);
-/**
- * OpenSSL certificate chain verification callback
- * Verifies certificate chain, setting up context for fetch_curl_verify_callback
- */
+ } else {
+ /* Ignore non-http(s) protocols */
+ continue;
+ }
-int fetch_curl_cert_verify_callback(X509_STORE_CTX *x509_ctx, void *parm)
-{
- int ok;
+ if (fetcher_add(scheme, &fetcher_ops) != NSERROR_OK) {
+ LOG(("Unable to register cURL fetcher for %s",
+ data->protocols[i]));
+ }
+ }
- /* Store fetch struct in context for verify callback */
- ok = X509_STORE_CTX_set_app_data(x509_ctx, parm);
+ return NSERROR_OK;
- /* and verify the certificate chain */
- if (ok)
- ok = X509_verify_cert(x509_ctx);
+curl_easy_setopt_failed:
+ LOG(("curl_easy_setopt failed."));
+ return NSERROR_INIT_FAILED;
- return ok;
+#if LIBCURL_VERSION_NUM >= 0x071e00
+curl_multi_setopt_failed:
+ LOG(("curl_multi_setopt failed."));
+ return NSERROR_INIT_FAILED;
+#endif
}
diff --git a/content/fetchers/curl.h b/content/fetchers/curl.h
index 7ee0963..5f2446a 100644
--- a/content/fetchers/curl.h
+++ b/content/fetchers/curl.h
@@ -25,7 +25,12 @@
#include <curl/curl.h>
-void fetch_curl_register(void);
+/**
+ * Register curl scheme handler.
+ *
+ * \return NSERROR_OK on successful registration or error code on failure.
+ */
+nserror fetch_curl_register(void);
/** Global cURL multi handle. */
extern CURLM *fetch_curl_multi;
diff --git a/content/fetchers/data.h b/content/fetchers/data.h
index f6017e0..2f89ecf 100644
--- a/content/fetchers/data.h
+++ b/content/fetchers/data.h
@@ -16,13 +16,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * data: URL method handler
+/**
+ * \file
+ * data scheme fetch handler interface.
*/
#ifndef NETSURF_CONTENT_FETCHERS_FETCH_DATA_H
#define NETSURF_CONTENT_FETCHERS_FETCH_DATA_H
+/**
+ * Register data scheme handler.
+ *
+ * \return NSERROR_OK on successful registration or error code on failure.
+ */
nserror fetch_data_register(void);
#endif
diff --git a/content/fetchers/file.h b/content/fetchers/file.h
index b3c39db..5a5cfe8 100644
--- a/content/fetchers/file.h
+++ b/content/fetchers/file.h
@@ -16,13 +16,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * file: URL method handler
+/**
+ * \file
+ * file scheme fetcher handler interface.
*/
#ifndef NETSURF_CONTENT_FETCHERS_FETCH_FILE_H
#define NETSURF_CONTENT_FETCHERS_FETCH_FILE_H
+/**
+ * Register file scheme handler.
+ *
+ * \return NSERROR_OK on successful registration or error code on failure.
+ */
nserror fetch_file_register(void);
#endif
diff --git a/content/fetchers/resource.h b/content/fetchers/resource.h
index cf4d6ed..8c7b2d1 100644
--- a/content/fetchers/resource.h
+++ b/content/fetchers/resource.h
@@ -16,8 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * resource: URL method handler.
+/**
+ * \file
+ * resource URL scheme handler interface.
*
* The resource fetcher is intended to provide a flat uniform URL
* space for browser local resources referenced by URL. Using this
@@ -34,6 +35,8 @@
* Register the resource scheme.
*
* should only be called from the fetch initialise
+ *
+ * \return NSERROR_OK on successful registration or error code on failure.
*/
nserror fetch_resource_register(void);
diff --git a/utils/messages.c b/utils/messages.c
index 27038e4..c623297 100644
--- a/utils/messages.c
+++ b/utils/messages.c
@@ -200,79 +200,79 @@ const char *messages_get_errorcode(nserror code)
{
switch (code) {
case NSERROR_OK:
- /**< No error */
+ /* No error */
return messages_get_ctx("OK", messages_hash);
case NSERROR_NOMEM:
- /**< Memory exhaustion */
+ /* Memory exhaustion */
return messages_get_ctx("NoMemory", messages_hash);
case NSERROR_NO_FETCH_HANDLER:
- /**< No fetch handler for URL scheme */
+ /* No fetch handler for URL scheme */
return messages_get_ctx("NoHandler", messages_hash);
case NSERROR_NOT_FOUND:
- /**< Requested item not found */
+ /* Requested item not found */
return messages_get_ctx("NotFound", messages_hash);
case NSERROR_SAVE_FAILED:
- /**< Failed to save data */
+ /* Failed to save data */
return messages_get_ctx("SaveFailed", messages_hash);
case NSERROR_CLONE_FAILED:
- /**< Failed to clone handle */
+ /* Failed to clone handle */
return messages_get_ctx("CloneFailed", messages_hash);
case NSERROR_INIT_FAILED:
- /**< Initialisation failed */
+ /* Initialisation failed */
return messages_get_ctx("InitFailed", messages_hash);
case NSERROR_MNG_ERROR:
- /**< An MNG error occurred */
+ /* An MNG error occurred */
return messages_get_ctx("MNGError", messages_hash);
case NSERROR_BAD_ENCODING:
- /**< The character set is unknown */
+ /* The character set is unknown */
return messages_get_ctx("BadEncoding", messages_hash);
case NSERROR_NEED_DATA:
- /**< More data needed */
+ /* More data needed */
return messages_get_ctx("NeedData", messages_hash);
case NSERROR_ENCODING_CHANGE:
- /**< The character set encoding change was unhandled */
+ /* The character set encoding change was unhandled */
return messages_get_ctx("EncodingChanged", messages_hash);
case NSERROR_BAD_PARAMETER:
- /**< Bad Parameter */
+ /* Bad Parameter */
return messages_get_ctx("BadParameter", messages_hash);
case NSERROR_INVALID:
- /**< Invalid data */
+ /* Invalid data */
return messages_get_ctx("Invalid", messages_hash);
case NSERROR_BOX_CONVERT:
- /**< Box conversion failed */
+ /* Box conversion failed */
return messages_get_ctx("BoxConvert", messages_hash);
case NSERROR_STOPPED:
- /**< Content conversion stopped */
+ /* Content conversion stopped */
return messages_get_ctx("Stopped", messages_hash);
case NSERROR_DOM:
- /**< DOM call returned error */
+ /* DOM call returned error */
return messages_get_ctx("ParsingFail", messages_hash);
case NSERROR_CSS:
- /**< CSS call returned error */
+ /* CSS call returned error */
return messages_get_ctx("CSSGeneric", messages_hash);
case NSERROR_CSS_BASE:
- /**< CSS base sheet failed */
+ /* CSS base sheet failed */
return messages_get_ctx("CSSBase", messages_hash);
case NSERROR_BAD_URL:
- /**< Bad URL */
+ /* Bad URL */
return messages_get_ctx("BadURL", messages_hash);
default:
@@ -280,6 +280,6 @@ const char *messages_get_errorcode(nserror code)
break;
}
- /**< Unknown error */
+ /* Unknown error */
return messages_get_ctx("Unknown", messages_hash);
}
--
NetSurf Browser
8 years, 3 months
netsurf: branch master updated. release/3.2-221-g503da8f
by NetSurf Browser Project
Gitweb links:
...log http://git.netsurf-browser.org/netsurf.git/shortlog/503da8f3f64abdfde62be...
...commit http://git.netsurf-browser.org/netsurf.git/commit/503da8f3f64abdfde62be60...
...tree http://git.netsurf-browser.org/netsurf.git/tree/503da8f3f64abdfde62be6018...
The branch, master has been updated
via 503da8f3f64abdfde62be6018cfb33a36846d363 (commit)
from fa7d44702ae74468acd3f4027a8fd5f9ab9d4bc5 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff http://git.netsurf-browser.org/netsurf.git/commit/?id=503da8f3f64abdfde62...
commit 503da8f3f64abdfde62be6018cfb33a36846d363
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Try doxygen todo format.
diff --git a/atari/deskmenu.c b/atari/deskmenu.c
index 427f38a..a9fa648 100644
--- a/atari/deskmenu.c
+++ b/atari/deskmenu.c
@@ -242,12 +242,12 @@ static void __CDECL menu_open_url(short item, short title, void *data)
NULL,
NULL,
&bw);
- /* TODO: Should not be accessing inside bw. */
+ /** \TODO Should not be accessing inside bw. */
gw = bw->window;
}
- /* TODO: Can we do this stuff in gui_window_create, which is called
- * in browser_window_create ? */
+ /** \TODO Can we do this stuff in gui_window_create, which is called
+ * in browser_window_create ? */
/* Loose focus: */
window_set_focus(gw->root, WIDGET_NONE, NULL );
-----------------------------------------------------------------------
Summary of changes:
atari/deskmenu.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/atari/deskmenu.c b/atari/deskmenu.c
index 427f38a..a9fa648 100644
--- a/atari/deskmenu.c
+++ b/atari/deskmenu.c
@@ -242,12 +242,12 @@ static void __CDECL menu_open_url(short item, short title, void *data)
NULL,
NULL,
&bw);
- /* TODO: Should not be accessing inside bw. */
+ /** \TODO Should not be accessing inside bw. */
gw = bw->window;
}
- /* TODO: Can we do this stuff in gui_window_create, which is called
- * in browser_window_create ? */
+ /** \TODO Can we do this stuff in gui_window_create, which is called
+ * in browser_window_create ? */
/* Loose focus: */
window_set_focus(gw->root, WIDGET_NONE, NULL );
--
NetSurf Browser
8 years, 3 months