diff --git a/.elinks.metadata b/.elinks.metadata new file mode 100644 index 0000000..bcb8f08 --- /dev/null +++ b/.elinks.metadata @@ -0,0 +1 @@ +3517795e8a390cb36ca249a5be6514b9784520a5 SOURCES/elinks-0.12pre6.tar.bz2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..db9c78c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/elinks-0.12pre6.tar.bz2 diff --git a/SOURCES/elinks-0.10.1-utf_8_io-default.patch b/SOURCES/elinks-0.10.1-utf_8_io-default.patch new file mode 100644 index 0000000..8b03026 --- /dev/null +++ b/SOURCES/elinks-0.10.1-utf_8_io-default.patch @@ -0,0 +1,12 @@ +diff -urNp elinks-0.12pre3-orig/src/config/options.inc elinks-0.12pre3/src/config/options.inc +--- elinks-0.12pre3-orig/src/config/options.inc ++++ elinks-0.12pre3/src/config/options.inc +@@ -920,7 +920,7 @@ static struct option_info config_options + * not defined, it should not be possible to set UTF-8 as "codepage"; + * please report any such possibilities as bugs.) */ + INIT_OPT_BOOL("terminal._template_", N_("UTF-8 I/O"), +- "utf_8_io", 0, 0, ++ "utf_8_io", 0, 1, + N_("Enable I/O in UTF-8 for Unicode terminals. " + "Note that currently, only the subset of UTF-8 according to " + "terminal codepage is used. ELinks ignores this option " diff --git a/SOURCES/elinks-0.10.1-xterm.patch b/SOURCES/elinks-0.10.1-xterm.patch new file mode 100644 index 0000000..7475450 --- /dev/null +++ b/SOURCES/elinks-0.10.1-xterm.patch @@ -0,0 +1,18 @@ + src/config/options.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/src/config/options.c b/src/config/options.c +index 925e042..ace1a13 100644 +--- a/src/config/options.c ++++ b/src/config/options.c +@@ -706,8 +706,9 @@ register_autocreated_options(void) + get_opt_bool("terminal.linux.m11_hack") = 1; + get_opt_int("terminal.vt100.type") = TERM_VT100; + get_opt_int("terminal.vt110.type") = TERM_VT100; +- get_opt_int("terminal.xterm.type") = TERM_VT100; ++ get_opt_int("terminal.xterm.type") = 2; + get_opt_bool("terminal.xterm.underline") = 1; ++ get_opt_int("terminal.xterm.colors") = 1; + get_opt_int("terminal.xterm-color.type") = TERM_VT100; + get_opt_int("terminal.xterm-color.colors") = COLOR_MODE_16; + get_opt_bool("terminal.xterm-color.underline") = 1; diff --git a/SOURCES/elinks-0.11.0-getaddrinfo.patch b/SOURCES/elinks-0.11.0-getaddrinfo.patch new file mode 100644 index 0000000..e91bbe4 --- /dev/null +++ b/SOURCES/elinks-0.11.0-getaddrinfo.patch @@ -0,0 +1,25 @@ +--- elinks-0.11.0/src/network/dns.c.getaddrinfo 2006-01-01 17:39:36.000000000 +0100 ++++ elinks-0.11.0/src/network/dns.c 2006-01-10 09:30:56.000000000 +0100 +@@ -157,9 +157,21 @@ do_real_lookup(unsigned char *name, struct sockaddr_storage **addrs, int *addrno + * But we duplicate the code terribly here :|. */ + /* hostent = getipnodebyname(name, AF_INET6, AI_ALL | AI_ADDRCONFIG, NULL); */ + memset(&hint, 0, sizeof(hint)); ++ hint.ai_flags = AI_ADDRCONFIG; + hint.ai_family = AF_UNSPEC; + hint.ai_socktype = SOCK_STREAM; +- if (getaddrinfo(name, NULL, &hint, &ai) != 0) return DNS_ERROR; ++ switch (getaddrinfo(name, NULL, &hint, &ai)) ++ { ++ case 0: ++ break; ++ case EAI_BADFLAGS: ++ hint.ai_flags = 0; ++ if (getaddrinfo(name, NULL, &hint, &ai) == 0) ++ break; ++ /* fall through */ ++ default: ++ return DNS_ERROR; ++ } + + #else + /* Seems there are problems on Mac, so we first need to try diff --git a/SOURCES/elinks-0.11.0-ssl-noegd.patch b/SOURCES/elinks-0.11.0-ssl-noegd.patch new file mode 100644 index 0000000..5818734 --- /dev/null +++ b/SOURCES/elinks-0.11.0-ssl-noegd.patch @@ -0,0 +1,21 @@ +--- elinks-0.11.0/src/network/ssl/ssl.c.noegd 2006-01-10 09:24:50.000000000 +0100 ++++ elinks-0.11.0/src/network/ssl/ssl.c 2006-01-10 09:25:01.000000000 +0100 +@@ -44,18 +44,6 @@ SSL_CTX *context = NULL; + static void + init_openssl(struct module *module) + { +- unsigned char f_randfile[PATH_MAX]; +- +- /* In a nutshell, on OS's without a /dev/urandom, the OpenSSL library +- * cannot initialize the PRNG and so every attempt to use SSL fails. +- * It's actually an OpenSSL FAQ, and according to them, it's up to the +- * application coders to seed the RNG. -- William Yodlowsky */ +- if (RAND_egd(RAND_file_name(f_randfile, sizeof(f_randfile))) < 0) { +- /* Not an EGD, so read and write to it */ +- if (RAND_load_file(f_randfile, -1)) +- RAND_write_file(f_randfile); +- } +- + SSLeay_add_ssl_algorithms(); + context = SSL_CTX_new(SSLv23_client_method()); + SSL_CTX_set_options(context, SSL_OP_ALL); diff --git a/SOURCES/elinks-0.11.0-sysname.patch b/SOURCES/elinks-0.11.0-sysname.patch new file mode 100644 index 0000000..479c1a8 --- /dev/null +++ b/SOURCES/elinks-0.11.0-sysname.patch @@ -0,0 +1,20 @@ +--- elinks-0.11.0/src/osdep/sysname.c.sysname 2006-01-01 17:39:36.000000000 +0100 ++++ elinks-0.11.0/src/osdep/sysname.c 2006-01-10 09:34:14.000000000 +0100 +@@ -26,7 +26,7 @@ + FILE *f; + unsigned char *p; + +- f = popen("uname -srm", "r"); ++ f = popen("uname -s", "r"); + if (!f) return 0; + + if (fread(system_name, 1, sizeof(system_name) - 1, f) <= 0) { +@@ -58,7 +58,7 @@ + + if (!uname(&name)) { + snprintf(system_name, sizeof(system_name), +- "%s %s %s", name.sysname, name.release, name.machine); ++ "%s", name.sysname); + return; + } + #endif diff --git a/SOURCES/elinks-0.11.3-macropen.patch b/SOURCES/elinks-0.11.3-macropen.patch new file mode 100644 index 0000000..a8b7436 --- /dev/null +++ b/SOURCES/elinks-0.11.3-macropen.patch @@ -0,0 +1,16 @@ + src/encoding/encoding.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/src/encoding/encoding.c b/src/encoding/encoding.c +index d019dab..9648da3 100644 +--- a/src/encoding/encoding.c ++++ b/src/encoding/encoding.c +@@ -124,7 +124,7 @@ open_encoded(int fd, enum stream_encoding encoding) + if (!stream) return NULL; + + stream->encoding = encoding; +- if (decoding_backends[stream->encoding]->open(stream, fd) >= 0) ++ if ((decoding_backends[stream->encoding]->open)(stream, fd) >= 0) + return stream; + + mem_free(stream); diff --git a/SOURCES/elinks-0.12pre5-ddg-search.patch b/SOURCES/elinks-0.12pre5-ddg-search.patch new file mode 100644 index 0000000..05d806d --- /dev/null +++ b/SOURCES/elinks-0.12pre5-ddg-search.patch @@ -0,0 +1,51 @@ +From a96d8a17e57343ff29736a2f8d0c954f2c4ba02a Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Tue, 18 Sep 2012 15:32:31 +0200 +Subject: [PATCH] rewrite: add default "ddg" dumb/smart prefixes for DuckDuckGo + +... and mention that URI rewriting rules may leak ELinks' identity +in the documentation of protocol.http.user_agent. + +Originally requested at . +--- + src/protocol/http/http.c | 3 ++- + src/protocol/rewrite/rewrite.c | 2 ++ + 2 files changed, 4 insertions(+), 1 deletions(-) + +diff --git a/src/protocol/http/http.c b/src/protocol/http/http.c +index ce14031..98053c0 100644 +--- a/src/protocol/http/http.c ++++ b/src/protocol/http/http.c +@@ -227,7 +227,8 @@ static union option_info http_options[] = { + "pushing some lite version to them automagically.\n" + "\n" + "Use \" \" if you don't want any User-Agent header to be sent " +- "at all.\n" ++ "at all. URI rewriting rules may still include parameters " ++ "that reveal you are using ELinks.\n" + "\n" + "%v in the string means ELinks version,\n" + "%s in the string means system identification,\n" +diff --git a/src/protocol/rewrite/rewrite.c b/src/protocol/rewrite/rewrite.c +index dd5c7ab..e01da74 100644 +--- a/src/protocol/rewrite/rewrite.c ++++ b/src/protocol/rewrite/rewrite.c +@@ -121,6 +121,7 @@ static union option_info uri_rewrite_options[] = { + INIT_OPT_DUMB_PREFIX("cia", "http://cia.navi.cx/"), + INIT_OPT_DUMB_PREFIX("b", "http://babelfish.altavista.com/babelfish/tr"), + INIT_OPT_DUMB_PREFIX("d", "http://www.dict.org"), ++ INIT_OPT_DUMB_PREFIX("ddg", "http://duckduckgo.com/?t=elinks"), + INIT_OPT_DUMB_PREFIX("g", "http://www.google.com/"), + INIT_OPT_DUMB_PREFIX("gg", "http://www.google.com/"), + INIT_OPT_DUMB_PREFIX("go", "http://www.google.com/"), +@@ -158,6 +159,7 @@ static union option_info uri_rewrite_options[] = { + INIT_OPT_SMART_PREFIX("cambridge", "http://dictionary.cambridge.org/results.asp?searchword=%s"), + INIT_OPT_SMART_PREFIX("cliki", "http://www.cliki.net/admin/search?words=%s"), + INIT_OPT_SMART_PREFIX("d", "http://www.dict.org/bin/Dict?Query=%s&Form=Dict1&Strategy=*&Database=*&submit=Submit+query"), ++ INIT_OPT_SMART_PREFIX("ddg", "http://duckduckgo.com/?q=%s&t=elinks"), + INIT_OPT_SMART_PREFIX("dmoz", "http://search.dmoz.org/cgi-bin/search?search=%s"), + INIT_OPT_SMART_PREFIX("foldoc", "http://wombat.doc.ic.ac.uk/foldoc/foldoc.cgi?%s"), + INIT_OPT_SMART_PREFIX("g", "http://www.google.com/search?q=%s&btnG=Google+Search"), +-- +1.7.1 + diff --git a/SOURCES/elinks-0.12pre5-js185.patch b/SOURCES/elinks-0.12pre5-js185.patch new file mode 100644 index 0000000..2d19ba0 --- /dev/null +++ b/SOURCES/elinks-0.12pre5-js185.patch @@ -0,0 +1,2350 @@ +From a3f59264b9504e8bf3d0ac70b99a237bc964089d Mon Sep 17 00:00:00 2001 +From: Miciah Dashiel Butler Masters +Date: Sat, 18 Jul 2009 23:41:01 +0000 +Subject: [PATCH 1/4] Heartbeat code using JS_TriggerOperationCallback + +Implement new heartbeat code to catch runaway execution of document +ECMAScript code. The old code uses JS_SetBranchCallback which is +deprecated in new versions of SpiderMonkey. The new code uses setitimer(2) +and the JS_SetOperationCallback and JS_TriggerOperationCallback interfaces, +introduced in SpiderMonkey 1.8.1. Compatibility with both the old +JS_SetBranchCallback and the new interfaces is maintained. + +Signed-off-by: Kamil Dudka +--- + Makefile.config.in | 1 + + configure.in | 12 +++ + src/ecmascript/ecmascript.h | 4 + + src/ecmascript/spidermonkey.c | 38 ++++++++- + src/ecmascript/spidermonkey/Makefile | 2 + + src/ecmascript/spidermonkey/heartbeat.c | 125 +++++++++++++++++++++++++++++++ + src/ecmascript/spidermonkey/heartbeat.h | 24 ++++++ + 7 files changed, 201 insertions(+), 5 deletions(-) + create mode 100644 src/ecmascript/spidermonkey/heartbeat.c + create mode 100644 src/ecmascript/spidermonkey/heartbeat.h + +diff --git a/Makefile.config.in b/Makefile.config.in +index c463868..40a8cd7 100644 +--- a/Makefile.config.in ++++ b/Makefile.config.in +@@ -115,6 +115,7 @@ CONFIG_DOC = @CONFIG_DOC@ + CONFIG_DOM = @CONFIG_DOM@ + CONFIG_ECMASCRIPT = @CONFIG_ECMASCRIPT@ + CONFIG_ECMASCRIPT_SMJS = @CONFIG_ECMASCRIPT_SMJS@ ++CONFIG_ECMASCRIPT_SMJS_HEARTBEAT = @CONFIG_ECMASCRIPT_SMJS@ + CONFIG_EXMODE = @CONFIG_EXMODE@ + CONFIG_FASTMEM = @CONFIG_FASTMEM@ + CONFIG_FINGER = @CONFIG_FINGER@ +diff --git a/configure.in b/configure.in +index f3e3d77..f79ca78 100644 +--- a/configure.in ++++ b/configure.in +@@ -283,6 +283,7 @@ AC_CHECK_FUNCS(snprintf vsnprintf asprintf vasprintf) + AC_CHECK_FUNCS(getifaddrs getpwnam inet_pton inet_ntop) + AC_CHECK_FUNCS(fflush fsync fseeko ftello sigaction) + AC_CHECK_FUNCS(gettimeofday clock_gettime) ++AC_CHECK_FUNCS(setitimer, HAVE_SETITIMER=yes) + + AC_CHECK_FUNCS([cygwin_conv_to_full_win32_path]) + +@@ -603,6 +604,8 @@ AC_MSG_RESULT($cf_result) + CONFIG_SPIDERMONKEY="$cf_result" + if test "$cf_result" = "yes"; then + AC_CHECK_FUNCS([[JS_ReportAllocationOverflow]]) ++ AC_CHECK_FUNCS(JS_SetBranchCallback) ++ AC_CHECK_FUNCS(JS_TriggerOperationCallback, HAVE_JS_TRIGGEROPERATIONCALLBACK=yes) + fi + EL_RESTORE_FLAGS + +@@ -615,6 +618,15 @@ fi + EL_CONFIG_DEPENDS(CONFIG_ECMASCRIPT, [CONFIG_ECMASCRIPT_SMJS], [ECMAScript (JavaScript)]) + AC_SUBST(CONFIG_ECMASCRIPT_SMJS) + ++if test "x$CONFIG_ECMASCRIPT_SMJS" = xyes && ++ test "x$HAVE_JS_TRIGGEROPERATIONCALLBACK" = xyes && ++ test "x$HAVE_SETITIMER" = xyes; then ++ EL_CONFIG(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT, [ECMAScript heartbeat support]) ++else ++ CONFIG_ECMASCRIPT_SMJS_HEARTBEAT=no ++fi ++AC_SUBST(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT) ++ + + # =================================================================== + # Optional Spidermonkey-based ECMAScript browser scripting +diff --git a/src/ecmascript/ecmascript.h b/src/ecmascript/ecmascript.h +index e8d84b5..8613b34 100644 +--- a/src/ecmascript/ecmascript.h ++++ b/src/ecmascript/ecmascript.h +@@ -33,7 +33,11 @@ struct ecmascript_interpreter { + /* The code evaluated by setTimeout() */ + struct string code; + ++#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT) ++ struct heartbeat *heartbeat; ++#elif defined(HAVE_JS_SETBRANCHCALLBACK) + time_t exec_start; ++#endif + + /* This is a cross-rerenderings accumulator of + * @document.onload_snippets (see its description for juicy details). +diff --git a/src/ecmascript/spidermonkey.c b/src/ecmascript/spidermonkey.c +index 78c3bca..16fb0a4 100644 +--- a/src/ecmascript/spidermonkey.c ++++ b/src/ecmascript/spidermonkey.c +@@ -25,6 +25,7 @@ + #include "ecmascript/spidermonkey.h" + #include "ecmascript/spidermonkey/document.h" + #include "ecmascript/spidermonkey/form.h" ++#include "ecmascript/spidermonkey/heartbeat.h" + #include "ecmascript/spidermonkey/location.h" + #include "ecmascript/spidermonkey/navigator.h" + #include "ecmascript/spidermonkey/unibar.h" +@@ -109,6 +110,7 @@ reported: + JS_ClearPendingException(ctx); + } + ++#if !defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT) && defined(HAVE_JS_SETBRANCHCALLBACK) + static JSBool + safeguard(JSContext *ctx, JSScript *script) + { +@@ -132,6 +134,7 @@ setup_safeguard(struct ecmascript_interpreter *interpreter, + interpreter->exec_start = time(NULL); + JS_SetBranchCallback(ctx, safeguard); + } ++#endif + + + static void +@@ -172,6 +175,9 @@ spidermonkey_get_interpreter(struct ecmascript_interpreter *interpreter) + * some kind of bytecode cache. (If we will ever do that.) */ + JS_SetOptions(ctx, JSOPTION_VAROBJFIX | JSOPTION_COMPILE_N_GO); + JS_SetErrorReporter(ctx, error_reporter); ++#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT) ++ JS_SetOperationCallback(ctx, heartbeat_callback); ++#endif + + window_obj = JS_NewObject(ctx, (JSClass *) &window_class, NULL, NULL); + if (!window_obj) goto release_and_fail; +@@ -263,10 +269,17 @@ spidermonkey_eval(struct ecmascript_interpreter *interpreter, + assert(interpreter); + if (!js_module_init_ok) return; + ctx = interpreter->backend_data; ++#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT) ++ interpreter->heartbeat = add_heartbeat(interpreter); ++#elif defined(HAVE_JS_SETBRANCHCALLBACK) + setup_safeguard(interpreter, ctx); ++#endif + interpreter->ret = ret; + JS_EvaluateScript(ctx, JS_GetGlobalObject(ctx), + code->source, code->length, "", 0, &rval); ++#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT) ++ done_heartbeat(interpreter->heartbeat); ++#endif + } + + +@@ -274,17 +287,25 @@ unsigned char * + spidermonkey_eval_stringback(struct ecmascript_interpreter *interpreter, + struct string *code) + { ++ JSBool ret; + JSContext *ctx; + jsval rval; + + assert(interpreter); + if (!js_module_init_ok) return NULL; + ctx = interpreter->backend_data; +- setup_safeguard(interpreter, ctx); + interpreter->ret = NULL; +- if (JS_EvaluateScript(ctx, JS_GetGlobalObject(ctx), +- code->source, code->length, "", 0, &rval) +- == JS_FALSE) { ++#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT) ++ interpreter->heartbeat = add_heartbeat(interpreter); ++#elif defined(HAVE_JS_SETBRANCHCALLBACK) ++ setup_safeguard(interpreter, ctx); ++#endif ++ ret = JS_EvaluateScript(ctx, JS_GetGlobalObject(ctx), ++ code->source, code->length, "", 0, &rval); ++#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT) ++ done_heartbeat(interpreter->heartbeat); ++#endif ++ if (ret == JS_FALSE) { + return NULL; + } + if (JSVAL_IS_VOID(rval)) { +@@ -308,14 +329,21 @@ spidermonkey_eval_boolback(struct ecmascript_interpreter *interpreter, + assert(interpreter); + if (!js_module_init_ok) return 0; + ctx = interpreter->backend_data; +- setup_safeguard(interpreter, ctx); + interpreter->ret = NULL; + fun = JS_CompileFunction(ctx, NULL, "", 0, NULL, code->source, + code->length, "", 0); + if (!fun) + return -1; + ++#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT) ++ interpreter->heartbeat = add_heartbeat(interpreter); ++#elif defined(HAVE_JS_SETBRANCHCALLBACK) ++ setup_safeguard(interpreter, ctx); ++#endif + ret = JS_CallFunction(ctx, NULL, fun, 0, NULL, &rval); ++#if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT) ++ done_heartbeat(interpreter->heartbeat); ++#endif + if (ret == 2) { /* onClick="history.back()" */ + return 0; + } +diff --git a/src/ecmascript/spidermonkey/Makefile b/src/ecmascript/spidermonkey/Makefile +index f1c0fef..377ca80 100644 +--- a/src/ecmascript/spidermonkey/Makefile ++++ b/src/ecmascript/spidermonkey/Makefile +@@ -2,6 +2,8 @@ top_builddir=../../.. + include $(top_builddir)/Makefile.config + INCLUDES += $(SPIDERMONKEY_CFLAGS) + ++OBJS-$(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT) += heartbeat.o ++ + OBJS = document.o form.o location.o navigator.o unibar.o window.o + + include $(top_srcdir)/Makefile.lib +diff --git a/src/ecmascript/spidermonkey/heartbeat.c b/src/ecmascript/spidermonkey/heartbeat.c +new file mode 100644 +index 0000000..bf95d92 +--- /dev/null ++++ b/src/ecmascript/spidermonkey/heartbeat.c +@@ -0,0 +1,125 @@ ++/* The SpiderMonkey ECMAScript backend heartbeat fuctionality. */ ++ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include /* setitimer(2) */ ++ ++#include "elinks.h" ++ ++#include "ecmascript/spidermonkey/util.h" ++ ++#include "config/options.h" ++#include "document/view.h" ++#include "ecmascript/ecmascript.h" ++#include "ecmascript/spidermonkey.h" ++#include "ecmascript/spidermonkey/heartbeat.h" ++#include "osdep/signals.h" ++#include "session/session.h" ++#include "util/lists.h" ++#include "util/math.h" /* int_upper_bound */ ++#include "util/memory.h" ++#include "viewer/text/vs.h" ++ ++ ++ ++static INIT_LIST_OF(struct heartbeat, heartbeats); ++ ++static struct itimerval heartbeat_timer = { { 1, 0 }, { 1, 0 } }; ++ ++ ++/* This callback is installed by JS_SetOperationCallback and triggered ++ * by JS_TriggerOperationCallback in the heartbeat code below. Returning ++ * JS_FALSE terminates script execution immediately. */ ++JSBool ++heartbeat_callback(JSContext *ctx) ++{ ++ return JS_FALSE; ++} ++ ++/* Callback for SIGVTALRM. Go through all heartbeats, decrease each ++ * one's TTL, and call JS_TriggerOperationCallback if a heartbeat's TTL ++ * goes to 0. */ ++static void ++check_heartbeats(void *data) ++{ ++ struct heartbeat *hb; ++ ++ foreach (hb, heartbeats) { ++ assert(hb->interpreter); ++ ++ --hb->ttl; ++ ++ if (hb->ttl <= 0) { ++ if (hb->interpreter->vs ++ && hb->interpreter->vs->doc_view ++ && hb->interpreter->vs->doc_view->session ++ && hb->interpreter->vs->doc_view->session->tab ++ && hb->interpreter->vs->doc_view->session->tab->term) { ++ struct session *ses = hb->interpreter->vs->doc_view->session; ++ struct terminal *term = ses->tab->term; ++ int max_exec_time = get_opt_int("ecmascript.max_exec_time"); ++ ++ ecmascript_timeout_dialog(term, max_exec_time); ++ } ++ ++ JS_TriggerOperationCallback(hb->interpreter->backend_data); ++ } ++ } ++ ++ install_signal_handler(SIGVTALRM, check_heartbeats, NULL, 1); ++} ++ ++/* Create a new heartbeat for the given interpreter. */ ++struct heartbeat * ++add_heartbeat(struct ecmascript_interpreter *interpreter) ++{ ++ struct session *ses; ++ struct heartbeat *hb; ++ ++ assert(interpreter); ++ ++ if (!interpreter->vs || !interpreter->vs->doc_view) ++ ses = NULL; ++ else ++ ses = interpreter->vs->doc_view->session; ++ ++ hb = mem_alloc(sizeof(struct heartbeat)); ++ if (!hb) return NULL; ++ ++ hb->ttl = get_opt_int("ecmascript.max_exec_time"); ++ hb->interpreter = interpreter; ++ ++ add_to_list(heartbeats, hb); ++ ++ /* Update the heartbeat timer. */ ++ if (list_is_singleton(*hb)) { ++ heartbeat_timer.it_value.tv_sec = 1; ++ setitimer(ITIMER_VIRTUAL, &heartbeat_timer, NULL); ++ } ++ ++ /* We install the handler every call to add_heartbeat instead of only on ++ * module initialisation because other code may set other handlers for ++ * the signal. */ ++ install_signal_handler(SIGVTALRM, check_heartbeats, NULL, 1); ++ ++ return hb; ++} ++ ++/* Destroy the given heartbeat. */ ++void ++done_heartbeat(struct heartbeat *hb) ++{ ++ assert(hb->interpreter); ++ ++ /* Stop the heartbeat timer if this heartbeat is the only one. */ ++ if (list_is_singleton(*hb)) { ++ heartbeat_timer.it_value.tv_sec = 0; ++ setitimer(ITIMER_VIRTUAL, &heartbeat_timer, NULL); ++ } ++ ++ del_from_list(hb); ++ hb->interpreter->heartbeat = NULL; ++ mem_free(hb); ++} +diff --git a/src/ecmascript/spidermonkey/heartbeat.h b/src/ecmascript/spidermonkey/heartbeat.h +new file mode 100644 +index 0000000..f7c8b12 +--- /dev/null ++++ b/src/ecmascript/spidermonkey/heartbeat.h +@@ -0,0 +1,24 @@ ++#ifndef EL__ECMASCRIPT_SPIDERMONKEY_HEARTBEAT_H ++#define EL__ECMASCRIPT_SPIDERMONKEY_HEARTBEAT_H ++ ++#include "ecmascript/spidermonkey/util.h" ++ ++#include "ecmascript/spidermonkey.h" ++ ++struct heartbeat { ++ LIST_HEAD(struct heartbeat); ++ ++ int ttl; /* Time to live. This value is assigned when the ++ * script begins execution and is decremented every ++ * second. When it reaches 0, script execution is ++ * terminated. */ ++ ++ struct ecmascript_interpreter *interpreter; ++}; ++ ++struct heartbeat *add_heartbeat(struct ecmascript_interpreter *interpreter); ++void done_heartbeat(struct heartbeat *hb); ++ ++JSBool heartbeat_callback(JSContext *ctx); ++ ++#endif +-- +1.7.4.2 + + +From dcaff5d937d63888c560727dda5f5348fa59a366 Mon Sep 17 00:00:00 2001 +From: witekfl +Date: Tue, 19 Apr 2011 22:41:05 +0200 +Subject: [PATCH 2/4] JS_VERSION at least 185 is required for ECMASCript + (xulrunner-2.0 or later) + +The code wasn't tested. It compiles + +Signed-off-by: Kamil Dudka +--- + configure.in | 10 ++- + src/ecmascript/spidermonkey-shared.h | 13 ++- + src/ecmascript/spidermonkey.c | 11 +-- + src/ecmascript/spidermonkey/document.c | 44 ++++---- + src/ecmascript/spidermonkey/form.c | 192 +++++++++++++++++++++---------- + src/ecmascript/spidermonkey/location.c | 42 ++++--- + src/ecmascript/spidermonkey/navigator.c | 10 +- + src/ecmascript/spidermonkey/unibar.c | 16 ++-- + src/ecmascript/spidermonkey/window.c | 57 ++++++---- + src/scripting/smjs/action_object.c | 29 +++-- + src/scripting/smjs/bookmarks.c | 24 ++-- + src/scripting/smjs/cache_object.c | 18 ++-- + src/scripting/smjs/core.c | 11 +- + src/scripting/smjs/elinks_object.c | 26 +++-- + src/scripting/smjs/global_object.c | 6 +- + src/scripting/smjs/globhist.c | 22 ++-- + src/scripting/smjs/hooks.c | 4 +- + src/scripting/smjs/keybinding.c | 12 +- + src/scripting/smjs/load_uri.c | 10 +- + src/scripting/smjs/view_state_object.c | 16 ++-- + 20 files changed, 344 insertions(+), 229 deletions(-) + +diff --git a/configure.in b/configure.in +index f79ca78..64faf85 100644 +--- a/configure.in ++++ b/configure.in +@@ -593,7 +593,15 @@ if test -z "$disable_spidermonkey"; then + CPPFLAGS="$CPPFLAGS_X $SPIDERMONKEY_CFLAGS" + + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#define XP_UNIX +- #include ]], [[JS_GetReservedSlot(NULL, NULL, 0, NULL)]])],[cf_result=yes],[cf_result=no]) ++ #define XP_UNIX ++ #include ]], [[ ++ #ifndef JS_VERSION ++ #error JS_VERSION ++ #endif ++ #if JS_VERSION < 185 ++ #error too old ++ #endif]])], ++ [cf_result=yes],[cf_result=no]) + fi + done + done +diff --git a/src/ecmascript/spidermonkey-shared.h b/src/ecmascript/spidermonkey-shared.h +index 4cc0eeb..98bfe31 100644 +--- a/src/ecmascript/spidermonkey-shared.h ++++ b/src/ecmascript/spidermonkey-shared.h +@@ -50,6 +50,7 @@ JSObject *spidermonkey_InitClass(JSContext *cx, JSObject *obj, + + static void undef_to_jsval(JSContext *ctx, jsval *vp); + static unsigned char *jsval_to_string(JSContext *ctx, jsval *vp); ++static unsigned char *jsid_to_string(JSContext *ctx, jsid *id); + + /* Inline functions */ + +@@ -68,7 +69,17 @@ jsval_to_string(JSContext *ctx, jsval *vp) + return ""; + } + +- return empty_string_or_(JS_GetStringBytes(JS_ValueToString(ctx, val))); ++ return empty_string_or_(JS_EncodeString(ctx, JS_ValueToString(ctx, val))); ++} ++ ++static inline unsigned char * ++jsid_to_string(JSContext *ctx, jsid *id) ++{ ++ jsval v; ++ ++ /* TODO: check returned value */ ++ JS_IdToValue(ctx, *id, &v); ++ return jsval_to_string(ctx, &v); + } + + #endif +diff --git a/src/ecmascript/spidermonkey.c b/src/ecmascript/spidermonkey.c +index 16fb0a4..021e6bd 100644 +--- a/src/ecmascript/spidermonkey.c ++++ b/src/ecmascript/spidermonkey.c +@@ -167,19 +167,14 @@ spidermonkey_get_interpreter(struct ecmascript_interpreter *interpreter) + return NULL; + interpreter->backend_data = ctx; + JS_SetContextPrivate(ctx, interpreter); +- /* TODO: Make JSOPTION_STRICT and JSOPTION_WERROR configurable. */ +-#ifndef JSOPTION_COMPILE_N_GO +-#define JSOPTION_COMPILE_N_GO 0 /* Older SM versions don't have it. */ +-#endif +- /* XXX: JSOPTION_COMPILE_N_GO will go (will it?) when we implement +- * some kind of bytecode cache. (If we will ever do that.) */ +- JS_SetOptions(ctx, JSOPTION_VAROBJFIX | JSOPTION_COMPILE_N_GO); ++ JS_SetOptions(ctx, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT); ++ JS_SetVersion(ctx, JSVERSION_LATEST); + JS_SetErrorReporter(ctx, error_reporter); + #if defined(CONFIG_ECMASCRIPT_SMJS_HEARTBEAT) + JS_SetOperationCallback(ctx, heartbeat_callback); + #endif + +- window_obj = JS_NewObject(ctx, (JSClass *) &window_class, NULL, NULL); ++ window_obj = JS_NewCompartmentAndGlobalObject(ctx, (JSClass *) &window_class, NULL); + if (!window_obj) goto release_and_fail; + if (!JS_InitStandardClasses(ctx, window_obj)) goto release_and_fail; + if (!JS_DefineProperties(ctx, window_obj, (JSPropertySpec *) window_props)) +diff --git a/src/ecmascript/spidermonkey/document.c b/src/ecmascript/spidermonkey/document.c +index 8f7bb92..dd72aae 100644 +--- a/src/ecmascript/spidermonkey/document.c ++++ b/src/ecmascript/spidermonkey/document.c +@@ -47,8 +47,8 @@ + #include "viewer/text/vs.h" + + +-static JSBool document_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp); +-static JSBool document_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp); ++static JSBool document_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp); ++static JSBool document_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp); + + /* Each @document_class object must have a @window_class parent. */ + const JSClass document_class = { +@@ -81,7 +81,7 @@ const JSPropertySpec document_props[] = { + + /* @document_class.getProperty */ + static JSBool +-document_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++document_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) + { + JSObject *parent_win; /* instance of @window_class */ + struct view_state *vs; +@@ -104,9 +104,9 @@ document_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + document = doc_view->document; + ses = doc_view->session; + +- if (JSVAL_IS_STRING(id)) { ++ if (JSID_IS_STRING(id)) { + struct form *form; +- unsigned char *string = jsval_to_string(ctx, &id); ++ unsigned char *string = jsid_to_string(ctx, &id); + + #ifdef CONFIG_COOKIES + if (!strcmp(string, "cookie")) { +@@ -135,12 +135,12 @@ document_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + return JS_TRUE; + } + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_TRUE; + + undef_to_jsval(ctx, vp); + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case JSP_DOC_LOC: + JS_GetProperty(ctx, parent_win, "location", vp); + break; +@@ -188,7 +188,7 @@ document_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + + /* @document_class.setProperty */ + static JSBool +-document_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++document_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) + { + JSObject *parent_win; /* instance of @window_class */ + struct view_state *vs; +@@ -209,9 +209,9 @@ document_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + doc_view = vs->doc_view; + document = doc_view->document; + +- if (JSVAL_IS_STRING(id)) { ++ if (JSID_IS_STRING(id)) { + #ifdef CONFIG_COOKIES +- if (!strcmp(jsval_to_string(ctx, &id), "cookie")) { ++ if (!strcmp(jsid_to_string(ctx, &id), "cookie")) { + set_cookie(vs->uri, jsval_to_string(ctx, vp)); + /* Do NOT touch our .cookie property, evil + * SpiderMonkey!! */ +@@ -221,10 +221,10 @@ document_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + return JS_TRUE; + } + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_TRUE; + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case JSP_DOC_TITLE: + mem_free_set(&document->title, stracpy(jsval_to_string(ctx, vp))); + print_screen_status(doc_view->session); +@@ -242,8 +242,8 @@ document_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + return JS_TRUE; + } + +-static JSBool document_write(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); +-static JSBool document_writeln(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); ++static JSBool document_write(JSContext *ctx, uintN argc, jsval *rval); ++static JSBool document_writeln(JSContext *ctx, uintN argc, jsval *rval); + + const spidermonkeyFunctionSpec document_funcs[] = { + { "write", document_write, 1 }, +@@ -252,11 +252,12 @@ const spidermonkeyFunctionSpec document_funcs[] = { + }; + + static JSBool +-document_write_do(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, +- jsval *rval, int newline) ++document_write_do(JSContext *ctx, uintN argc, jsval *rval, int newline) + { ++ jsval val; + struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx); + struct string *ret = interpreter->ret; ++ jsval *argv = JS_ARGV(ctx, rval); + + if (argc >= 1 && ret) { + int i = 0; +@@ -281,22 +282,23 @@ document_write_do(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, + set_led_value(interpreter->vs->doc_view->session->status.ecmascript_led, 'J'); + #endif + +- boolean_to_jsval(ctx, rval, 0); ++ boolean_to_jsval(ctx, &val, 0); ++ JS_SET_RVAL(ctx, rval, val); + + return JS_TRUE; + } + + /* @document_funcs{"write"} */ + static JSBool +-document_write(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++document_write(JSContext *ctx, uintN argc, jsval *rval) + { + +- return document_write_do(ctx, obj, argc, argv, rval, 0); ++ return document_write_do(ctx, argc, rval, 0); + } + + /* @document_funcs{"writeln"} */ + static JSBool +-document_writeln(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++document_writeln(JSContext *ctx, uintN argc, jsval *rval) + { +- return document_write_do(ctx, obj, argc, argv, rval, 1); ++ return document_write_do(ctx, argc, rval, 1); + } +diff --git a/src/ecmascript/spidermonkey/form.c b/src/ecmascript/spidermonkey/form.c +index ff436a1..824b170 100644 +--- a/src/ecmascript/spidermonkey/form.c ++++ b/src/ecmascript/spidermonkey/form.c +@@ -55,8 +55,8 @@ static const JSClass form_class; /* defined below */ + * HTMLInputElement. The difference could be spotted only by some clever tricky + * JS code, but I hope it doesn't matter anywhere. --pasky */ + +-static JSBool input_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp); +-static JSBool input_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp); ++static JSBool input_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp); ++static JSBool input_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp); + static void input_finalize(JSContext *ctx, JSObject *obj); + + /* Each @input_class object must have a @form_class parent. */ +@@ -116,10 +116,10 @@ static const JSPropertySpec input_props[] = { + { NULL } + }; + +-static JSBool input_blur(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); +-static JSBool input_click(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); +-static JSBool input_focus(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); +-static JSBool input_select(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); ++static JSBool input_blur(JSContext *ctx, uintN argc, jsval *rval); ++static JSBool input_click(JSContext *ctx, uintN argc, jsval *rval); ++static JSBool input_focus(JSContext *ctx, uintN argc, jsval *rval); ++static JSBool input_select(JSContext *ctx, uintN argc, jsval *rval); + + static const spidermonkeyFunctionSpec input_funcs[] = { + { "blur", input_blur, 0 }, +@@ -150,7 +150,7 @@ input_get_form_state(JSContext *ctx, JSObject *jsinput) + + /* @input_class.getProperty */ + static JSBool +-input_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++input_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) + { + JSObject *parent_form; /* instance of @form_class */ + JSObject *parent_doc; /* instance of @document_class */ +@@ -189,7 +189,7 @@ input_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + assert(fc); + assert(fc->form && fs); + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_TRUE; + + linknum = get_form_control_link(document, fc); +@@ -198,7 +198,7 @@ input_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + + undef_to_jsval(ctx, vp); + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case JSP_INPUT_ACCESSKEY: + { + JSString *keystr; +@@ -301,7 +301,7 @@ input_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + + /* @input_class.setProperty */ + static JSBool +-input_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++input_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) + { + JSObject *parent_form; /* instance of @form_class */ + JSObject *parent_doc; /* instance of @document_class */ +@@ -341,14 +341,14 @@ input_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + assert(fc); + assert(fc->form && fs); + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_TRUE; + + linknum = get_form_control_link(document, fc); + /* Hiddens have no link. */ + if (linknum >= 0) link = &document->links[linknum]; + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case JSP_INPUT_ACCESSKEY: + accesskey = jsval_to_accesskey(ctx, vp); + if (accesskey == UCS_NO_CHAR) +@@ -422,7 +422,7 @@ input_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + + /* @input_funcs{"blur"} */ + static JSBool +-input_blur(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++input_blur(JSContext *ctx, uintN argc, jsval *rval) + { + /* We are a text-mode browser and there *always* has to be something + * selected. So we do nothing for now. (That was easy.) */ +@@ -431,11 +431,14 @@ input_blur(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) + + /* @input_funcs{"click"} */ + static JSBool +-input_click(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++input_click(JSContext *ctx, uintN argc, jsval *rval) + { ++ jsval val; + JSObject *parent_form; /* instance of @form_class */ + JSObject *parent_doc; /* instance of @document_class */ + JSObject *parent_win; /* instance of @window_class */ ++ JSObject *obj = JS_THIS_OBJECT(ctx, rval); ++ jsval *argv = JS_ARGV(ctx, rval); + struct view_state *vs; + struct document_view *doc_view; + struct document *document; +@@ -479,17 +482,21 @@ input_click(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) + else + print_screen_status(ses); + +- boolean_to_jsval(ctx, rval, 0); ++ boolean_to_jsval(ctx, &val, 0); ++ JS_SET_RVAL(ctx, rval, val); + return JS_TRUE; + } + + /* @input_funcs{"focus"} */ + static JSBool +-input_focus(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++input_focus(JSContext *ctx, uintN argc, jsval *rval) + { ++ jsval val; + JSObject *parent_form; /* instance of @form_class */ + JSObject *parent_doc; /* instance of @document_class */ + JSObject *parent_win; /* instance of @window_class */ ++ JSObject *obj = JS_THIS_OBJECT(ctx, rval); ++ jsval *argv = JS_ARGV(ctx, rval); + struct view_state *vs; + struct document_view *doc_view; + struct document *document; +@@ -528,13 +535,14 @@ input_focus(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) + + jump_to_link_number(ses, doc_view, linknum); + +- boolean_to_jsval(ctx, rval, 0); ++ boolean_to_jsval(ctx, &val, 0); ++ JS_SET_RVAL(ctx, rval, val); + return JS_TRUE; + } + + /* @input_funcs{"select"} */ + static JSBool +-input_select(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++input_select(JSContext *ctx, uintN argc, jsval *rval) + { + /* We support no text selecting yet. So we do nothing for now. + * (That was easy, too.) */ +@@ -662,19 +670,22 @@ get_form_control_object(JSContext *ctx, JSObject *jsform, + + + static struct form_view *form_get_form_view(JSContext *ctx, JSObject *jsform, jsval *argv); +-static JSBool form_elements_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp); ++static JSBool form_elements_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp); + + /* Each @form_elements_class object must have a @form_class parent. */ + static const JSClass form_elements_class = { + "elements", + JSCLASS_HAS_PRIVATE, + JS_PropertyStub, JS_PropertyStub, +- form_elements_get_property, JS_PropertyStub, ++ form_elements_get_property, JS_StrictPropertyStub, + JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub + }; + +-static JSBool form_elements_item(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); +-static JSBool form_elements_namedItem(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); ++static JSBool form_elements_item2(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); ++static JSBool form_elements_namedItem2(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); ++static JSBool form_elements_item(JSContext *ctx, uintN argc, jsval *rval); ++static JSBool form_elements_namedItem(JSContext *ctx, uintN argc, jsval *rval); ++ + + static const spidermonkeyFunctionSpec form_elements_funcs[] = { + { "item", form_elements_item, 1 }, +@@ -696,8 +707,9 @@ static const JSPropertySpec form_elements_props[] = { + + /* @form_elements_class.getProperty */ + static JSBool +-form_elements_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++form_elements_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) + { ++ jsval idval; + JSObject *parent_form; /* instance of @form_class */ + JSObject *parent_doc; /* instance of @document_class */ + JSObject *parent_win; /* instance of @window_class */ +@@ -730,32 +742,46 @@ form_elements_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + if (!form_view) return JS_FALSE; /* detached */ + form = find_form_by_form_view(document, form_view); + +- if (JSVAL_IS_STRING(id)) { +- form_elements_namedItem(ctx, obj, 1, &id, vp); ++ if (JSID_IS_STRING(id)) { ++ JS_IdToValue(ctx, id, &idval); ++ form_elements_namedItem2(ctx, obj, 1, &idval, vp); + return JS_TRUE; + } + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_TRUE; + + undef_to_jsval(ctx, vp); + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case JSP_FORM_ELEMENTS_LENGTH: + int_to_jsval(ctx, vp, list_size(&form->items)); + break; + default: + /* Array index. */ +- form_elements_item(ctx, obj, 1, &id, vp); ++ JS_IdToValue(ctx, id, &idval); ++ form_elements_item2(ctx, obj, 1, &idval, vp); + break; + } + + return JS_TRUE; + } + ++static JSBool ++form_elements_item(JSContext *ctx, uintN argc, jsval *rval) ++{ ++ jsval val; ++ JSObject *obj = JS_THIS_OBJECT(ctx, rval); ++ jsval *argv = JS_ARGV(ctx, rval); ++ JSBool ret = form_elements_item2(ctx, obj, argc, argv, &val); ++ ++ JS_SET_RVAL(ctx, rval, val); ++ return ret; ++} ++ + /* @form_elements_funcs{"item"} */ + static JSBool +-form_elements_item(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++form_elements_item2(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) + { + JSObject *parent_form; /* instance of @form_class */ + JSObject *parent_doc; /* instance of @document_class */ +@@ -813,9 +839,21 @@ form_elements_item(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval + return JS_TRUE; + } + ++static JSBool ++form_elements_namedItem(JSContext *ctx, uintN argc, jsval *rval) ++{ ++ jsval val; ++ JSObject *obj = JS_THIS_OBJECT(ctx, rval); ++ jsval *argv = JS_ARGV(ctx, rval); ++ JSBool ret = form_elements_namedItem2(ctx, obj, argc, argv, &val); ++ ++ JS_SET_RVAL(ctx, rval, val); ++ return ret; ++} ++ + /* @form_elements_funcs{"namedItem"} */ + static JSBool +-form_elements_namedItem(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++form_elements_namedItem2(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) + { + JSObject *parent_form; /* instance of @form_class */ + JSObject *parent_doc; /* instance of @document_class */ +@@ -876,8 +914,8 @@ form_elements_namedItem(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, + + + +-static JSBool form_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp); +-static JSBool form_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp); ++static JSBool form_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp); ++static JSBool form_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp); + static void form_finalize(JSContext *ctx, JSObject *obj); + + /* Each @form_class object must have a @document_class parent. */ +@@ -914,8 +952,8 @@ static const JSPropertySpec form_props[] = { + { NULL } + }; + +-static JSBool form_reset(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); +-static JSBool form_submit(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); ++static JSBool form_reset(JSContext *ctx, uintN argc, jsval *rval); ++static JSBool form_submit(JSContext *ctx, uintN argc, jsval *rval); + + static const spidermonkeyFunctionSpec form_funcs[] = { + { "reset", form_reset, 0 }, +@@ -940,7 +978,7 @@ form_get_form_view(JSContext *ctx, JSObject *jsform, jsval *argv) + + /* @form_class.getProperty */ + static JSBool +-form_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++form_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) + { + /* DBG("doc %p %s\n", parent_doc, JS_GetStringBytes(JS_ValueToString(ctx, OBJECT_TO_JSVAL(parent_doc)))); */ + JSObject *parent_doc; /* instance of @document_class */ +@@ -971,11 +1009,11 @@ form_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + + assert(form); + +- if (JSVAL_IS_STRING(id)) { ++ if (JSID_IS_STRING(id)) { + struct form_control *fc; + unsigned char *string; + +- string = jsval_to_string(ctx, &id); ++ string = jsid_to_string(ctx, &id); + foreach (fc, form->items) { + JSObject *fcobj = NULL; + struct form_state *fs; +@@ -996,12 +1034,12 @@ form_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + return JS_TRUE; + } + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_TRUE; + + undef_to_jsval(ctx, vp); + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case JSP_FORM_ACTION: + string_to_jsval(ctx, vp, form->action); + break; +@@ -1076,7 +1114,7 @@ form_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + + /* @form_class.setProperty */ + static JSBool +-form_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++form_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) + { + JSObject *parent_doc; /* instance of @document_class */ + JSObject *parent_win; /* instance of @window_class */ +@@ -1107,10 +1145,10 @@ form_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + + assert(form); + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_TRUE; + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case JSP_FORM_ACTION: + string = stracpy(jsval_to_string(ctx, vp)); + if (form->action) { +@@ -1162,10 +1200,13 @@ form_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + + /* @form_funcs{"reset"} */ + static JSBool +-form_reset(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++form_reset(JSContext *ctx, uintN argc, jsval *rval) + { ++ jsval val; + JSObject *parent_doc; /* instance of @document_class */ + JSObject *parent_win; /* instance of @window_class */ ++ JSObject *obj = JS_THIS_OBJECT(ctx, rval); ++ jsval *argv = JS_ARGV(ctx, rval); + struct view_state *vs; + struct document_view *doc_view; + struct form_view *fv; +@@ -1191,17 +1232,21 @@ form_reset(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) + do_reset_form(doc_view, form); + draw_forms(doc_view->session->tab->term, doc_view); + +- boolean_to_jsval(ctx, rval, 0); ++ boolean_to_jsval(ctx, &val, 0); ++ JS_SET_RVAL(ctx, rval, val); + + return JS_TRUE; + } + + /* @form_funcs{"submit"} */ + static JSBool +-form_submit(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++form_submit(JSContext *ctx, uintN argc, jsval *rval) + { ++ jsval val; + JSObject *parent_doc; /* instance of @document_class */ + JSObject *parent_win; /* instance of @window_class */ ++ JSObject *obj = JS_THIS_OBJECT(ctx, rval); ++ jsval *argv = JS_ARGV(ctx, rval); + struct view_state *vs; + struct document_view *doc_view; + struct session *ses; +@@ -1227,7 +1272,8 @@ form_submit(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) + assert(form); + submit_given_form(ses, doc_view, form, 0); + +- boolean_to_jsval(ctx, rval, 0); ++ boolean_to_jsval(ctx, &val, 0); ++ JS_SET_RVAL(ctx, rval, val); + + return JS_TRUE; + } +@@ -1308,19 +1354,20 @@ spidermonkey_detach_form_view(struct form_view *fv) + } + + +-static JSBool forms_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp); ++static JSBool forms_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp); + + /* Each @forms_class object must have a @document_class parent. */ + const JSClass forms_class = { + "forms", + JSCLASS_HAS_PRIVATE, + JS_PropertyStub, JS_PropertyStub, +- forms_get_property, JS_PropertyStub, ++ forms_get_property, JS_StrictPropertyStub, + JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub + }; + +-static JSBool forms_item(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); +-static JSBool forms_namedItem(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); ++static JSBool forms_item(JSContext *ctx, uintN argc, jsval *rval); ++static JSBool forms_item2(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); ++static JSBool forms_namedItem(JSContext *ctx, uintN argc, jsval *rval); + + const spidermonkeyFunctionSpec forms_funcs[] = { + { "item", forms_item, 1 }, +@@ -1365,8 +1412,9 @@ find_form_by_name(JSContext *ctx, JSObject *jsdoc, + + /* @forms_class.getProperty */ + static JSBool +-forms_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++forms_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) + { ++ jsval idval; + JSObject *parent_doc; /* instance of @document_class */ + JSObject *parent_win; /* instance of @window_class */ + struct view_state *vs; +@@ -1390,36 +1438,50 @@ forms_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + doc_view = vs->doc_view; + document = doc_view->document; + +- if (JSVAL_IS_STRING(id)) { ++ if (JSID_IS_STRING(id)) { + /* When SMJS evaluates forms.namedItem("foo"), it first + * calls forms_get_property with id = JSString "namedItem" + * and *vp = JSObject JSFunction forms_namedItem. + * If we don't find a form whose name is id, + * we must leave *vp unchanged here, to avoid + * "TypeError: forms.namedItem is not a function". */ +- find_form_by_name(ctx, parent_doc, doc_view, id, vp); ++ JS_IdToValue(ctx, id, &idval); ++ find_form_by_name(ctx, parent_doc, doc_view, idval, vp); + return JS_TRUE; + } + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_TRUE; + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case JSP_FORMS_LENGTH: + int_to_jsval(ctx, vp, list_size(&document->forms)); + break; + default: + /* Array index. */ +- forms_item(ctx, obj, 1, &id, vp); ++ JS_IdToValue(ctx, id, &idval); ++ forms_item2(ctx, obj, 1, &idval, vp); + break; + } + + return JS_TRUE; + } + ++static JSBool ++forms_item(JSContext *ctx, uintN argc, jsval *rval) ++{ ++ jsval val; ++ JSObject *obj = JS_THIS_OBJECT(ctx, rval); ++ jsval *argv = JS_ARGV(ctx, rval); ++ JSBool ret = forms_item2(ctx, obj, argc, argv, &val); ++ ++ JS_SET_RVAL(ctx, rval, val); ++ return ret; ++} ++ + /* @forms_funcs{"item"} */ + static JSBool +-forms_item(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++forms_item2(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) + { + JSObject *parent_doc; /* instance of @document_class */ + JSObject *parent_win; /* instance of @window_class */ +@@ -1459,10 +1521,13 @@ forms_item(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) + + /* @forms_funcs{"namedItem"} */ + static JSBool +-forms_namedItem(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++forms_namedItem(JSContext *ctx, uintN argc, jsval *rval) + { ++ jsval val; + JSObject *parent_doc; /* instance of @document_class */ + JSObject *parent_win; /* instance of @window_class */ ++ JSObject *obj = JS_THIS_OBJECT(ctx, rval); ++ jsval *argv = JS_ARGV(ctx, rval); + struct view_state *vs; + struct document_view *doc_view; + +@@ -1481,8 +1546,9 @@ forms_namedItem(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *r + if (argc != 1) + return JS_TRUE; + +- undef_to_jsval(ctx, rval); +- find_form_by_name(ctx, parent_doc, doc_view, argv[0], rval); ++ undef_to_jsval(ctx, &val); ++ find_form_by_name(ctx, parent_doc, doc_view, argv[0], &val); ++ JS_SET_RVAL(ctx, rval, val); + return JS_TRUE; + } + +@@ -1519,13 +1585,13 @@ static unicode_val_T + jsval_to_accesskey(JSContext *ctx, jsval *vp) + { + size_t len; +- const jschar *chr; ++ const char *chr; + + /* Convert the value in place, to protect the result from GC. */ + if (JS_ConvertValue(ctx, *vp, JSTYPE_STRING, vp) == JS_FALSE) + return UCS_NO_CHAR; +- len = JS_GetStringLength(JSVAL_TO_STRING(*vp)); +- chr = JS_GetStringChars(JSVAL_TO_STRING(*vp)); ++ len = JS_GetStringEncodingLength(ctx, JSVAL_TO_STRING(*vp)); ++ chr = JS_EncodeString(ctx, JSVAL_TO_STRING(*vp)); + + /* This implementation ignores extra characters in the string. */ + if (len < 1) +diff --git a/src/ecmascript/spidermonkey/location.c b/src/ecmascript/spidermonkey/location.c +index dd5b40b..752a890 100644 +--- a/src/ecmascript/spidermonkey/location.c ++++ b/src/ecmascript/spidermonkey/location.c +@@ -45,15 +45,15 @@ + #include "viewer/text/vs.h" + + +-static JSBool history_back(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); +-static JSBool history_forward(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); +-static JSBool history_go(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); ++static JSBool history_back(JSContext *ctx, uintN argc, jsval *rval); ++static JSBool history_forward(JSContext *ctx, uintN argc, jsval *rval); ++static JSBool history_go(JSContext *ctx, uintN argc, jsval *rval); + + const JSClass history_class = { + "history", + JSCLASS_HAS_PRIVATE, + JS_PropertyStub, JS_PropertyStub, +- JS_PropertyStub, JS_PropertyStub, ++ JS_PropertyStub, JS_StrictPropertyStub, + JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub + }; + +@@ -66,7 +66,7 @@ const spidermonkeyFunctionSpec history_funcs[] = { + + /* @history_funcs{"back"} */ + static JSBool +-history_back(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++history_back(JSContext *ctx, uintN argc, jsval *rval) + { + struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx); + struct document_view *doc_view = interpreter->vs->doc_view; +@@ -83,7 +83,7 @@ history_back(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval + + /* @history_funcs{"forward"} */ + static JSBool +-history_forward(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++history_forward(JSContext *ctx, uintN argc, jsval *rval) + { + struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx); + struct document_view *doc_view = interpreter->vs->doc_view; +@@ -96,11 +96,12 @@ history_forward(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *r + + /* @history_funcs{"go"} */ + static JSBool +-history_go(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++history_go(JSContext *ctx, uintN argc, jsval *rval) + { + struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx); + struct document_view *doc_view = interpreter->vs->doc_view; + struct session *ses = doc_view->session; ++ jsval *argv = JS_ARGV(ctx, rval); + int index; + struct location *loc; + +@@ -124,8 +125,8 @@ history_go(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) + } + + +-static JSBool location_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp); +-static JSBool location_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp); ++static JSBool location_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp); ++static JSBool location_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp); + + /* Each @location_class object must have a @window_class parent. */ + const JSClass location_class = { +@@ -150,7 +151,7 @@ const JSPropertySpec location_props[] = { + + /* @location_class.getProperty */ + static JSBool +-location_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++location_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) + { + JSObject *parent_win; /* instance of @window_class */ + struct view_state *vs; +@@ -167,12 +168,12 @@ location_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + vs = JS_GetInstancePrivate(ctx, parent_win, + (JSClass *) &window_class, NULL); + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_TRUE; + + undef_to_jsval(ctx, vp); + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case JSP_LOC_HREF: + astring_to_jsval(ctx, vp, get_uri_string(vs->uri, URI_ORIGINAL)); + break; +@@ -191,7 +192,7 @@ location_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + + /* @location_class.setProperty */ + static JSBool +-location_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++location_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) + { + JSObject *parent_win; /* instance of @window_class */ + struct view_state *vs; +@@ -210,10 +211,10 @@ location_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + (JSClass *) &window_class, NULL); + doc_view = vs->doc_view; + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_TRUE; + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case JSP_LOC_HREF: + location_goto(doc_view, jsval_to_string(ctx, vp)); + break; +@@ -222,7 +223,7 @@ location_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + return JS_TRUE; + } + +-static JSBool location_toString(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); ++static JSBool location_toString(JSContext *ctx, uintN argc, jsval *rval); + + const spidermonkeyFunctionSpec location_funcs[] = { + { "toString", location_toString, 0 }, +@@ -232,7 +233,12 @@ const spidermonkeyFunctionSpec location_funcs[] = { + + /* @location_funcs{"toString"}, @location_funcs{"toLocaleString"} */ + static JSBool +-location_toString(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++location_toString(JSContext *ctx, uintN argc, jsval *rval) + { +- return JS_GetProperty(ctx, obj, "href", rval); ++ jsval val; ++ JSObject *obj = JS_THIS_OBJECT(ctx, rval); ++ JSBool ret = JS_GetProperty(ctx, obj, "href", &val); ++ ++ JS_SET_RVAL(ctx, rval, val); ++ return ret; + } +diff --git a/src/ecmascript/spidermonkey/navigator.c b/src/ecmascript/spidermonkey/navigator.c +index a009d62..e08a224 100644 +--- a/src/ecmascript/spidermonkey/navigator.c ++++ b/src/ecmascript/spidermonkey/navigator.c +@@ -44,13 +44,13 @@ + #include "viewer/text/vs.h" + + +-static JSBool navigator_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp); ++static JSBool navigator_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp); + + const JSClass navigator_class = { + "navigator", + JSCLASS_HAS_PRIVATE, + JS_PropertyStub, JS_PropertyStub, +- navigator_get_property, JS_PropertyStub, ++ navigator_get_property, JS_StrictPropertyStub, + JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub + }; + +@@ -81,14 +81,14 @@ const JSPropertySpec navigator_props[] = { + + /* @navigator_class.getProperty */ + static JSBool +-navigator_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++navigator_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) + { +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_TRUE; + + undef_to_jsval(ctx, vp); + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case JSP_NAVIGATOR_APP_CODENAME: + string_to_jsval(ctx, vp, "Mozilla"); /* More like a constant nowadays. */ + break; +diff --git a/src/ecmascript/spidermonkey/unibar.c b/src/ecmascript/spidermonkey/unibar.c +index 3c290a3..576c0a7 100644 +--- a/src/ecmascript/spidermonkey/unibar.c ++++ b/src/ecmascript/spidermonkey/unibar.c +@@ -45,8 +45,8 @@ + #include "viewer/text/vs.h" + + +-static JSBool unibar_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp); +-static JSBool unibar_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp); ++static JSBool unibar_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp); ++static JSBool unibar_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp); + + /* Each @menubar_class object must have a @window_class parent. */ + const JSClass menubar_class = { +@@ -80,7 +80,7 @@ const JSPropertySpec unibar_props[] = { + + /* @menubar_class.getProperty, @statusbar_class.getProperty */ + static JSBool +-unibar_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++unibar_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) + { + JSObject *parent_win; /* instance of @window_class */ + struct view_state *vs; +@@ -104,10 +104,10 @@ unibar_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + status = &doc_view->session->status; + bar = JS_GetPrivate(ctx, obj); /* from @menubar_class or @statusbar_class */ + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_TRUE; + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case JSP_UNIBAR_VISIBLE: + #define unibar_fetch(bar) \ + boolean_to_jsval(ctx, vp, status->force_show_##bar##_bar >= 0 \ +@@ -139,7 +139,7 @@ unibar_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + + /* @menubar_class.setProperty, @statusbar_class.setProperty */ + static JSBool +-unibar_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++unibar_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) + { + JSObject *parent_win; /* instance of @window_class */ + struct view_state *vs; +@@ -163,10 +163,10 @@ unibar_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + status = &doc_view->session->status; + bar = JS_GetPrivate(ctx, obj); /* from @menubar_class or @statusbar_class */ + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_TRUE; + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case JSP_UNIBAR_VISIBLE: + switch (*bar) { + case 's': +diff --git a/src/ecmascript/spidermonkey/window.c b/src/ecmascript/spidermonkey/window.c +index 5e93a6f..9bc8dd9 100644 +--- a/src/ecmascript/spidermonkey/window.c ++++ b/src/ecmascript/spidermonkey/window.c +@@ -44,12 +44,12 @@ + #include "viewer/text/vs.h" + + +-static JSBool window_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp); +-static JSBool window_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp); ++static JSBool window_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp); ++static JSBool window_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp); + + const JSClass window_class = { + "window", +- JSCLASS_HAS_PRIVATE, /* struct view_state * */ ++ JSCLASS_HAS_PRIVATE | JSCLASS_GLOBAL_FLAGS, /* struct view_state * */ + JS_PropertyStub, JS_PropertyStub, + window_get_property, window_set_property, + JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub +@@ -122,7 +122,7 @@ find_child_frame(struct document_view *doc_view, struct frame_desc *tframe) + + /* @window_class.getProperty */ + static JSBool +-window_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++window_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) + { + struct view_state *vs; + +@@ -138,11 +138,11 @@ window_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + * location is then evaluated in string context, toString() + * is called which we overrode for that class below, so + * everything's fine. */ +- if (JSVAL_IS_STRING(id)) { ++ if (JSID_IS_STRING(id)) { + struct document_view *doc_view = vs->doc_view; + JSObject *obj; + +- obj = try_resolve_frame(doc_view, jsval_to_string(ctx, &id)); ++ obj = try_resolve_frame(doc_view, jsid_to_string(ctx, &id)); + /* TODO: Try other lookups (mainly element lookup) until + * something yields data. */ + if (obj) { +@@ -151,12 +151,12 @@ window_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + return JS_TRUE; + } + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_TRUE; + + undef_to_jsval(ctx, vp); + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case JSP_WIN_CLOSED: + /* TODO: It will be a major PITA to implement this properly. + * Well, perhaps not so much if we introduce reference tracking +@@ -252,7 +252,7 @@ found_parent: + + /* @window_class.setProperty */ + static JSBool +-window_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++window_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) + { + struct view_state *vs; + +@@ -264,8 +264,8 @@ window_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + + vs = JS_GetInstancePrivate(ctx, obj, (JSClass *) &window_class, NULL); + +- if (JSVAL_IS_STRING(id)) { +- if (!strcmp(jsval_to_string(ctx, &id), "location")) { ++ if (JSID_IS_STRING(id)) { ++ if (!strcmp(jsid_to_string(ctx, &id), "location")) { + struct document_view *doc_view = vs->doc_view; + + location_goto(doc_view, jsval_to_string(ctx, vp)); +@@ -276,10 +276,10 @@ window_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + return JS_TRUE; + } + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_TRUE; + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case JSP_WIN_STATUS: + mem_free_set(&vs->doc_view->session->status.window_status, stracpy(jsval_to_string(ctx, vp))); + print_screen_status(vs->doc_view->session); +@@ -296,9 +296,9 @@ window_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + } + + +-static JSBool window_alert(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); +-static JSBool window_open(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); +-static JSBool window_setTimeout(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); ++static JSBool window_alert(JSContext *ctx, uintN argc, jsval *rval); ++static JSBool window_open(JSContext *ctx, uintN argc, jsval *rval); ++static JSBool window_setTimeout(JSContext *ctx, uintN argc, jsval *rval); + + const spidermonkeyFunctionSpec window_funcs[] = { + { "alert", window_alert, 1 }, +@@ -309,8 +309,11 @@ const spidermonkeyFunctionSpec window_funcs[] = { + + /* @window_funcs{"alert"} */ + static JSBool +-window_alert(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++window_alert(JSContext *ctx, uintN argc, jsval *rval) + { ++ jsval val; ++ JSObject *obj = JS_THIS_OBJECT(ctx, rval); ++ jsval *argv = JS_ARGV(ctx, rval); + struct view_state *vs; + unsigned char *string; + +@@ -328,14 +331,18 @@ window_alert(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval + info_box(vs->doc_view->session->tab->term, MSGBOX_FREE_TEXT, + N_("JavaScript Alert"), ALIGN_CENTER, stracpy(string)); + +- undef_to_jsval(ctx, rval); ++ undef_to_jsval(ctx, &val); ++ JS_SET_RVAL(ctx, rval, val); + return JS_TRUE; + } + + /* @window_funcs{"open"} */ + static JSBool +-window_open(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++window_open(JSContext *ctx, uintN argc, jsval *rval) + { ++ jsval val; ++ JSObject *obj = JS_THIS_OBJECT(ctx, rval); ++ jsval *argv = JS_ARGV(ctx, rval); + struct view_state *vs; + struct document_view *doc_view; + struct session *ses; +@@ -405,7 +412,7 @@ window_open(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) + deo->uri = get_uri_reference(uri); + deo->target = stracpy(frame); + register_bottom_half(delayed_goto_uri_frame, deo); +- boolean_to_jsval(ctx, rval, 1); ++ boolean_to_jsval(ctx, &val, 1); + goto end; + } + } +@@ -416,7 +423,7 @@ window_open(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) + && can_open_in_new(ses->tab->term)) { + open_uri_in_new_window(ses, uri, NULL, ENV_ANY, + CACHE_MODE_NORMAL, TASK_NONE); +- boolean_to_jsval(ctx, rval, 1); ++ boolean_to_jsval(ctx, &val, 1); + } else { + /* When opening a new tab, we might get rerendered, losing our + * context and triggerring a disaster, so postpone that. */ +@@ -426,9 +433,9 @@ window_open(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) + deo->ses = ses; + deo->uri = get_uri_reference(uri); + register_bottom_half(delayed_open, deo); +- boolean_to_jsval(ctx, rval, 1); ++ boolean_to_jsval(ctx, &val, 1); + } else { +- undef_to_jsval(ctx, rval); ++ undef_to_jsval(ctx, &val); + } + } + +@@ -436,13 +443,15 @@ end: + done_uri(uri); + mem_free_if(frame); + ++ JS_SET_RVAL(ctx, rval, val); + return JS_TRUE; + } + + /* @window_funcs{"setTimeout"} */ + static JSBool +-window_setTimeout(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++window_setTimeout(JSContext *ctx, uintN argc, jsval *rval) + { ++ jsval *argv = JS_ARGV(ctx, rval); + struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx); + unsigned char *code; + int timeout; +diff --git a/src/scripting/smjs/action_object.c b/src/scripting/smjs/action_object.c +index d95564d..d0379e0 100644 +--- a/src/scripting/smjs/action_object.c ++++ b/src/scripting/smjs/action_object.c +@@ -42,25 +42,31 @@ smjs_action_fn_finalize(JSContext *ctx, JSObject *obj) + + /* @action_fn_class.call */ + static JSBool +-smjs_action_fn_callback(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, +- jsval *rval) ++smjs_action_fn_callback(JSContext *ctx, uintN argc, jsval *rval) + { ++ jsval value; ++ jsval *argv = JS_ARGV(ctx, rval); + struct smjs_action_fn_callback_hop *hop; + JSObject *fn_obj; + + assert(smjs_ctx); + if_assert_failed return JS_FALSE; + +- *rval = JS_FALSE; ++ value = JS_FALSE; + +- if (JS_TRUE != JS_ValueToObject(ctx, argv[-2], &fn_obj)) ++ if (JS_TRUE != JS_ValueToObject(ctx, argv[-2], &fn_obj)) { ++ JS_SET_RVAL(ctx, rval, value); + return JS_TRUE; ++ } + assert(JS_InstanceOf(ctx, fn_obj, (JSClass *) &action_fn_class, NULL)); + if_assert_failed return JS_FALSE; + + hop = JS_GetInstancePrivate(ctx, fn_obj, + (JSClass *) &action_fn_class, NULL); +- if (!hop) return JS_TRUE; ++ if (!hop) { ++ JS_SET_RVAL(ctx, rval, value); ++ return JS_TRUE; ++ } + + if (!would_window_receive_keypresses(hop->ses->tab)) { + /* The user cannot run actions in this tab by pressing +@@ -98,7 +104,8 @@ smjs_action_fn_callback(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, + + do_action(hop->ses, hop->action_id, 1); + +- *rval = JS_TRUE; ++ value = JS_TRUE; ++ JS_SET_RVAL(ctx, rval, value); + + return JS_TRUE; + } +@@ -107,7 +114,7 @@ static const JSClass action_fn_class = { + "action_fn", + JSCLASS_HAS_PRIVATE, /* struct smjs_action_fn_callback_hop * */ + JS_PropertyStub, JS_PropertyStub, +- JS_PropertyStub, JS_PropertyStub, ++ JS_PropertyStub, JS_StrictPropertyStub, + JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, + smjs_action_fn_finalize, + NULL, NULL, +@@ -152,14 +159,16 @@ smjs_get_action_fn_object(unsigned char *action_str) + + /* @action_class.getProperty */ + static JSBool +-action_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++action_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) + { ++ jsval val; + JSObject *action_fn; + unsigned char *action_str; + + *vp = JSVAL_NULL; + +- action_str = JS_GetStringBytes(JS_ValueToString(ctx, id)); ++ JS_IdToValue(ctx, id, &val); ++ action_str = JS_EncodeString(ctx, JS_ValueToString(ctx, val)); + if (!action_str) return JS_TRUE; + + action_fn = smjs_get_action_fn_object(action_str); +@@ -174,7 +183,7 @@ static const JSClass action_class = { + "action", + 0, + JS_PropertyStub, JS_PropertyStub, +- action_get_property, JS_PropertyStub, ++ action_get_property, JS_StrictPropertyStub, + JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, + }; + +diff --git a/src/scripting/smjs/bookmarks.c b/src/scripting/smjs/bookmarks.c +index f12f84b..6c8b7fa 100644 +--- a/src/scripting/smjs/bookmarks.c ++++ b/src/scripting/smjs/bookmarks.c +@@ -113,29 +113,29 @@ jsval_to_bookmark_string(JSContext *ctx, jsval val, unsigned char **result) + unsigned char *str; + + /* jsstring_to_utf8() might GC; protect the string to come. */ +- if (!JS_AddNamedRoot(ctx, &jsstr, "jsval_to_bookmark_string")) ++ if (!JS_AddNamedStringRoot(ctx, &jsstr, "jsval_to_bookmark_string")) + return JS_FALSE; + + jsstr = JS_ValueToString(ctx, val); + if (jsstr == NULL) { +- JS_RemoveRoot(ctx, &jsstr); ++ JS_RemoveStringRoot(ctx, &jsstr); + return JS_FALSE; + } + + str = jsstring_to_utf8(ctx, jsstr, NULL); + if (str == NULL) { +- JS_RemoveRoot(ctx, &jsstr); ++ JS_RemoveStringRoot(ctx, &jsstr); + return JS_FALSE; + } + +- JS_RemoveRoot(ctx, &jsstr); ++ JS_RemoveStringRoot(ctx, &jsstr); + mem_free_set(result, str); + return JS_TRUE; + } + + /* @bookmark_class.getProperty */ + static JSBool +-bookmark_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++bookmark_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) + { + struct bookmark *bookmark; + +@@ -152,10 +152,10 @@ bookmark_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + + undef_to_jsval(ctx, vp); + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_FALSE; + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case BOOKMARK_TITLE: + return bookmark_string_to_jsval(ctx, bookmark->title, vp); + case BOOKMARK_URL: +@@ -177,7 +177,7 @@ bookmark_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + + /* @bookmark_class.setProperty */ + static JSBool +-bookmark_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++bookmark_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) + { + struct bookmark *bookmark; + unsigned char *title = NULL; +@@ -195,10 +195,10 @@ bookmark_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + + if (!bookmark) return JS_FALSE; + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_FALSE; + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case BOOKMARK_TITLE: + if (!jsval_to_bookmark_string(ctx, *vp, &title)) + return JS_FALSE; +@@ -250,7 +250,7 @@ smjs_get_bookmark_object(struct bookmark *bookmark) + + /* @bookmark_folder_class.getProperty */ + static JSBool +-bookmark_folder_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++bookmark_folder_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) + { + struct bookmark *bookmark; + struct bookmark *folder; +@@ -283,7 +283,7 @@ static const JSClass bookmark_folder_class = { + "bookmark_folder", + JSCLASS_HAS_PRIVATE, /* struct bookmark * */ + JS_PropertyStub, JS_PropertyStub, +- bookmark_folder_get_property, JS_PropertyStub, ++ bookmark_folder_get_property, JS_StrictPropertyStub, + JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, bookmark_finalize, + }; + +diff --git a/src/scripting/smjs/cache_object.c b/src/scripting/smjs/cache_object.c +index cd23842..0bdb563 100644 +--- a/src/scripting/smjs/cache_object.c ++++ b/src/scripting/smjs/cache_object.c +@@ -40,7 +40,7 @@ static const JSPropertySpec cache_entry_props[] = { + + /* @cache_entry_class.getProperty */ + static JSBool +-cache_entry_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++cache_entry_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) + { + struct cache_entry *cached; + JSBool ret; +@@ -66,9 +66,9 @@ cache_entry_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + + undef_to_jsval(ctx, vp); + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + ret = JS_FALSE; +- else switch (JSVAL_TO_INT(id)) { ++ else switch (JSID_TO_INT(id)) { + case CACHE_ENTRY_CONTENT: { + struct fragment *fragment = get_cache_fragment(cached); + +@@ -121,7 +121,7 @@ cache_entry_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + + /* @cache_entry_class.setProperty */ + static JSBool +-cache_entry_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++cache_entry_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) + { + struct cache_entry *cached; + JSBool ret; +@@ -145,12 +145,12 @@ cache_entry_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + * eventually unlock the object. */ + object_lock(cached); + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + ret = JS_FALSE; +- else switch (JSVAL_TO_INT(id)) { ++ else switch (JSID_TO_INT(id)) { + case CACHE_ENTRY_CONTENT: { + JSString *jsstr = JS_ValueToString(smjs_ctx, *vp); +- unsigned char *str = JS_GetStringBytes(jsstr); ++ unsigned char *str = JS_EncodeString(smjs_ctx, jsstr); + size_t len = JS_GetStringLength(jsstr); + + add_fragment(cached, 0, str, len); +@@ -161,7 +161,7 @@ cache_entry_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + } + case CACHE_ENTRY_TYPE: { + JSString *jsstr = JS_ValueToString(smjs_ctx, *vp); +- unsigned char *str = JS_GetStringBytes(jsstr); ++ unsigned char *str = JS_EncodeString(smjs_ctx, jsstr); + + mem_free_set(&cached->content_type, stracpy(str)); + +@@ -170,7 +170,7 @@ cache_entry_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + } + case CACHE_ENTRY_HEAD: { + JSString *jsstr = JS_ValueToString(smjs_ctx, *vp); +- unsigned char *str = JS_GetStringBytes(jsstr); ++ unsigned char *str = JS_EncodeString(smjs_ctx, jsstr); + + mem_free_set(&cached->head, stracpy(str)); + +diff --git a/src/scripting/smjs/core.c b/src/scripting/smjs/core.c +index 2493904..ced28b0 100644 +--- a/src/scripting/smjs/core.c ++++ b/src/scripting/smjs/core.c +@@ -94,11 +94,11 @@ smjs_do_file(unsigned char *path) + } + + static JSBool +-smjs_do_file_wrapper(JSContext *ctx, JSObject *obj, uintN argc, +- jsval *argv, jsval *rval) ++smjs_do_file_wrapper(JSContext *ctx, uintN argc, jsval *rval) + { ++ jsval *argv = JS_ARGV(ctx, rval); + JSString *jsstr = JS_ValueToString(smjs_ctx, *argv); +- unsigned char *path = JS_GetStringBytes(jsstr); ++ unsigned char *path = JS_EncodeString(smjs_ctx, jsstr); + + if (smjs_do_file(path)) + return JS_TRUE; +@@ -136,6 +136,9 @@ init_smjs(struct module *module) + return; + } + ++ JS_SetOptions(smjs_ctx, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT); ++ JS_SetVersion(smjs_ctx, JSVERSION_LATEST); ++ + JS_SetErrorReporter(smjs_ctx, error_reporter); + + smjs_init_global_object(); +@@ -308,7 +311,7 @@ jsstring_to_utf8(JSContext *ctx, JSString *jsstr, int *length) + struct string utf8; + + utf16_len = JS_GetStringLength(jsstr); +- utf16 = JS_GetStringChars(jsstr); /* stays owned by jsstr */ ++ utf16 = JS_GetStringCharsZ(ctx, jsstr); /* stays owned by jsstr */ + if (utf16 == NULL) { + /* JS_GetStringChars doesn't have a JSContext * + * parameter so it can't report the error +diff --git a/src/scripting/smjs/elinks_object.c b/src/scripting/smjs/elinks_object.c +index 5a9b394..3c51ec9 100644 +--- a/src/scripting/smjs/elinks_object.c ++++ b/src/scripting/smjs/elinks_object.c +@@ -27,7 +27,7 @@ + + + static JSBool +-elinks_get_home(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++elinks_get_home(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) + { + *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx, elinks_home)); + +@@ -35,7 +35,7 @@ elinks_get_home(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + } + + static JSBool +-elinks_get_location(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++elinks_get_location(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) + { + struct uri *uri; + +@@ -51,7 +51,7 @@ elinks_get_location(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + } + + static JSBool +-elinks_set_location(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++elinks_set_location(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) + { + JSString *jsstr; + unsigned char *url; +@@ -61,7 +61,7 @@ elinks_set_location(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + jsstr = JS_ValueToString(smjs_ctx, *vp); + if (!jsstr) return JS_FALSE; + +- url = JS_GetStringBytes(jsstr); ++ url = JS_EncodeString(smjs_ctx, jsstr); + if (!url) return JS_FALSE; + + goto_url(smjs_ses, url); +@@ -71,8 +71,10 @@ elinks_set_location(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + + /* @elinks_funcs{"alert"} */ + static JSBool +-elinks_alert(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++elinks_alert(JSContext *ctx, uintN argc, jsval *rval) + { ++ jsval val; ++ jsval *argv = JS_ARGV(ctx, rval); + unsigned char *string; + + if (argc != 1) +@@ -85,15 +87,18 @@ elinks_alert(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval + info_box(smjs_ses->tab->term, MSGBOX_NO_TEXT_INTL, + N_("User script alert"), ALIGN_LEFT, string); + +- undef_to_jsval(ctx, rval); ++ undef_to_jsval(ctx, &val); ++ JS_SET_RVAL(ctx, rval, val); + + return JS_TRUE; + } + + /* @elinks_funcs{"execute"} */ + static JSBool +-elinks_execute(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) ++elinks_execute(JSContext *ctx, uintN argc, jsval *rval) + { ++ jsval val; ++ jsval *argv = JS_ARGV(ctx, rval); + unsigned char *string; + + if (argc != 1) +@@ -104,8 +109,9 @@ elinks_execute(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rv + return JS_TRUE; + + exec_on_terminal(smjs_ses->tab->term, string, "", TERM_EXEC_BG); +- undef_to_jsval(ctx, rval); + ++ undef_to_jsval(ctx, &val); ++ JS_SET_RVAL(ctx, rval, val); + return JS_TRUE; + } + +@@ -113,7 +119,7 @@ static const JSClass elinks_class = { + "elinks", + 0, + JS_PropertyStub, JS_PropertyStub, +- JS_PropertyStub, JS_PropertyStub, ++ JS_PropertyStub, JS_StrictPropertyStub, + JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub + }; + +@@ -142,7 +148,7 @@ smjs_get_elinks_object(void) + return NULL; + + if (!JS_DefineProperty(smjs_ctx, jsobj, "home", JSVAL_NULL, +- elinks_get_home, JS_PropertyStub, ++ elinks_get_home, JS_StrictPropertyStub, + JSPROP_ENUMERATE + | JSPROP_PERMANENT + | JSPROP_READONLY)) +diff --git a/src/scripting/smjs/global_object.c b/src/scripting/smjs/global_object.c +index 3a59782..0976f8a 100644 +--- a/src/scripting/smjs/global_object.c ++++ b/src/scripting/smjs/global_object.c +@@ -16,9 +16,9 @@ JSObject *smjs_global_object; + + + static const JSClass global_class = { +- "global", 0, +- JS_PropertyStub, JS_PropertyStub, ++ "global", JSCLASS_GLOBAL_FLAGS, + JS_PropertyStub, JS_PropertyStub, ++ JS_PropertyStub, JS_StrictPropertyStub, + JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub + }; + +@@ -29,7 +29,7 @@ smjs_get_global_object(void) + + assert(smjs_ctx); + +- jsobj = JS_NewObject(smjs_ctx, (JSClass *) &global_class, NULL, NULL); ++ jsobj = JS_NewCompartmentAndGlobalObject(smjs_ctx, (JSClass *) &global_class, NULL); + + if (!jsobj) return NULL; + +diff --git a/src/scripting/smjs/globhist.c b/src/scripting/smjs/globhist.c +index 0ab6938..376c44e 100644 +--- a/src/scripting/smjs/globhist.c ++++ b/src/scripting/smjs/globhist.c +@@ -51,7 +51,7 @@ static const JSPropertySpec smjs_globhist_item_props[] = { + + /* @smjs_globhist_item_class.getProperty */ + static JSBool +-smjs_globhist_item_get_property(JSContext *ctx, JSObject *obj, jsval id, ++smjs_globhist_item_get_property(JSContext *ctx, JSObject *obj, jsid id, + jsval *vp) + { + struct global_history_item *history_item; +@@ -70,10 +70,10 @@ smjs_globhist_item_get_property(JSContext *ctx, JSObject *obj, jsval id, + + undef_to_jsval(ctx, vp); + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_FALSE; + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case GLOBHIST_TITLE: + *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx, + history_item->title)); +@@ -117,7 +117,7 @@ smjs_globhist_item_get_property(JSContext *ctx, JSObject *obj, jsval id, + + /* @smjs_globhist_item_class.setProperty */ + static JSBool +-smjs_globhist_item_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++smjs_globhist_item_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) + { + struct global_history_item *history_item; + +@@ -133,13 +133,13 @@ smjs_globhist_item_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval * + + if (!history_item) return JS_FALSE; + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_FALSE; + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case GLOBHIST_TITLE: { + JSString *jsstr = JS_ValueToString(smjs_ctx, *vp); +- unsigned char *str = JS_GetStringBytes(jsstr); ++ unsigned char *str = JS_EncodeString(smjs_ctx, jsstr); + + mem_free_set(&history_item->title, stracpy(str)); + +@@ -147,7 +147,7 @@ smjs_globhist_item_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval * + } + case GLOBHIST_URL: { + JSString *jsstr = JS_ValueToString(smjs_ctx, *vp); +- unsigned char *str = JS_GetStringBytes(jsstr); ++ unsigned char *str = JS_EncodeString(smjs_ctx, jsstr); + + mem_free_set(&history_item->url, stracpy(str)); + +@@ -201,13 +201,13 @@ smjs_get_globhist_item_object(struct global_history_item *history_item) + + /* @smjs_globhist_class.getProperty */ + static JSBool +-smjs_globhist_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++smjs_globhist_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) + { + JSObject *jsobj; + unsigned char *uri_string; + struct global_history_item *history_item; + +- uri_string = JS_GetStringBytes(JS_ValueToString(ctx, id)); ++ uri_string = JS_EncodeString(ctx, JS_ValueToString(ctx, id)); + if (!uri_string) goto ret_null; + + history_item = get_global_history_item(uri_string); +@@ -229,7 +229,7 @@ ret_null: + static const JSClass smjs_globhist_class = { + "global_history", 0, + JS_PropertyStub, JS_PropertyStub, +- smjs_globhist_get_property, JS_PropertyStub, ++ smjs_globhist_get_property, JS_StrictPropertyStub, + JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, + }; + +diff --git a/src/scripting/smjs/hooks.c b/src/scripting/smjs/hooks.c +index 291039c..d69daf6 100644 +--- a/src/scripting/smjs/hooks.c ++++ b/src/scripting/smjs/hooks.c +@@ -41,7 +41,7 @@ script_hook_url(va_list ap, void *data) + ret = EVENT_HOOK_STATUS_LAST; + } else { + JSString *jsstr = JS_ValueToString(smjs_ctx, rval); +- unsigned char *str = JS_GetStringBytes(jsstr); ++ unsigned char *str = JS_EncodeString(smjs_ctx, jsstr); + + mem_free_set(url, stracpy(str)); + } +@@ -58,7 +58,7 @@ script_hook_pre_format_html(va_list ap, void *data) + struct session *ses = va_arg(ap, struct session *); + struct cache_entry *cached = va_arg(ap, struct cache_entry *); + enum evhook_status ret = EVENT_HOOK_STATUS_NEXT; +- JSObject *cache_entry_object, *view_state_object = JSVAL_NULL; ++ JSObject *cache_entry_object, *view_state_object = NULL; + jsval args[2], rval; + + evhook_use_params(ses && cached); +diff --git a/src/scripting/smjs/keybinding.c b/src/scripting/smjs/keybinding.c +index 2b35477..b452298 100644 +--- a/src/scripting/smjs/keybinding.c ++++ b/src/scripting/smjs/keybinding.c +@@ -17,7 +17,7 @@ static const JSClass keymap_class; /* defined below */ + + /* @keymap_class.getProperty */ + static JSBool +-keymap_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++keymap_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) + { + unsigned char *action_str; + const unsigned char *keystroke_str; +@@ -32,7 +32,7 @@ keymap_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + data = JS_GetInstancePrivate(ctx, obj, + (JSClass *) &keymap_class, NULL); + +- keystroke_str = JS_GetStringBytes(JS_ValueToString(ctx, id)); ++ keystroke_str = JS_EncodeString(ctx, JS_ValueToString(ctx, id)); + if (!keystroke_str) goto ret_null; + + action_str = get_action_name_from_keystroke((enum keymap_id) *data, +@@ -70,7 +70,7 @@ smjs_keybinding_action_callback(va_list ap, void *data) + + /* @keymap_class.setProperty */ + static JSBool +-keymap_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++keymap_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) + { + int *data; + unsigned char *keymap_str; +@@ -90,13 +90,13 @@ keymap_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + keymap_str = get_keymap_name((enum keymap_id) *data); + if (!keymap_str) return JS_FALSE; + +- keystroke_str = JS_GetStringBytes(JS_ValueToString(ctx, id)); ++ keystroke_str = JS_EncodeString(ctx, JS_ValueToString(ctx, id)); + if (!keystroke_str) return JS_FALSE; + + if (JSVAL_IS_STRING(*vp)) { + unsigned char *action_str; + +- action_str = JS_GetStringBytes(JS_ValueToString(ctx, *vp)); ++ action_str = JS_EncodeString(ctx, JS_ValueToString(ctx, *vp)); + if (!action_str) return JS_FALSE; + + if (bind_do(keymap_str, keystroke_str, action_str, 0)) +@@ -203,7 +203,7 @@ static const JSClass keymaps_hash_class = { + "keymaps_hash", + JSCLASS_HAS_PRIVATE, + JS_PropertyStub, JS_PropertyStub, +- JS_PropertyStub, JS_PropertyStub, ++ JS_PropertyStub, JS_StrictPropertyStub, + JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, + }; + +diff --git a/src/scripting/smjs/load_uri.c b/src/scripting/smjs/load_uri.c +index 4f2dcf2..7e3881c 100644 +--- a/src/scripting/smjs/load_uri.c ++++ b/src/scripting/smjs/load_uri.c +@@ -56,7 +56,7 @@ smjs_loading_callback(struct download *download, void *data) + end: + if (download->cached) + object_unlock(download->cached); +- JS_RemoveRoot(smjs_ctx, &hop->callback); ++ JS_RemoveValueRoot(smjs_ctx, &hop->callback); + mem_free(download->data); + mem_free(download); + +@@ -64,9 +64,9 @@ end: + } + + static JSBool +-smjs_load_uri(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, +- jsval *rval) ++smjs_load_uri(JSContext *ctx, uintN argc, jsval *rval) + { ++ jsval *argv = JS_ARGV(ctx, rval); + struct smjs_load_uri_hop *hop; + struct download *download; + JSString *jsstr; +@@ -76,7 +76,7 @@ smjs_load_uri(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, + if (argc < 2) return JS_FALSE; + + jsstr = JS_ValueToString(smjs_ctx, argv[0]); +- uri_string = JS_GetStringBytes(jsstr); ++ uri_string = JS_EncodeString(smjs_ctx, jsstr); + + uri = get_uri(uri_string, 0); + if (!uri) return JS_FALSE; +@@ -96,7 +96,7 @@ smjs_load_uri(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, + + hop->callback = argv[1]; + hop->ses = smjs_ses; +- if (!JS_AddNamedRoot(smjs_ctx, &hop->callback, ++ if (!JS_AddNamedValueRoot(smjs_ctx, &hop->callback, + "smjs_load_uri_hop.callback")) { + mem_free(hop); + mem_free(download); +diff --git a/src/scripting/smjs/view_state_object.c b/src/scripting/smjs/view_state_object.c +index 64f43ca..636b37b 100644 +--- a/src/scripting/smjs/view_state_object.c ++++ b/src/scripting/smjs/view_state_object.c +@@ -39,7 +39,7 @@ static const JSPropertySpec view_state_props[] = { + + /* @view_state_class.getProperty */ + static JSBool +-view_state_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++view_state_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) + { + struct view_state *vs; + +@@ -54,10 +54,10 @@ view_state_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + + undef_to_jsval(ctx, vp); + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_FALSE; + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case VIEW_STATE_PLAIN: + *vp = INT_TO_JSVAL(vs->plain); + +@@ -80,7 +80,7 @@ view_state_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + + /* @view_state_class.setProperty */ + static JSBool +-view_state_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++view_state_set_property(JSContext *ctx, JSObject *obj, jsid id, JSBool strict, jsval *vp) + { + struct view_state *vs; + +@@ -93,10 +93,10 @@ view_state_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) + vs = JS_GetInstancePrivate(ctx, obj, + (JSClass *) &view_state_class, NULL); + +- if (!JSVAL_IS_INT(id)) ++ if (!JSID_IS_INT(id)) + return JS_FALSE; + +- switch (JSVAL_TO_INT(id)) { ++ switch (JSID_TO_INT(id)) { + case VIEW_STATE_PLAIN: { + vs->plain = atol(jsval_to_string(ctx, vp)); + +@@ -143,7 +143,7 @@ smjs_get_view_state_object(struct view_state *vs) + } + + static JSBool +-smjs_elinks_get_view_state(JSContext *ctx, JSObject *obj, jsval id, jsval *vp) ++smjs_elinks_get_view_state(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) + { + JSObject *vs_obj; + struct view_state *vs; +@@ -170,6 +170,6 @@ smjs_init_view_state_interface(void) + return; + + JS_DefineProperty(smjs_ctx, smjs_elinks_object, "vs", JSVAL_NULL, +- smjs_elinks_get_view_state, JS_PropertyStub, ++ smjs_elinks_get_view_state, JS_StrictPropertyStub, + JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY); + } +-- +1.7.4.2 + +From 32109054ce40067b8c55837fb69f1bc1249e38fd Mon Sep 17 00:00:00 2001 +From: witekfl +Date: Mon, 25 Apr 2011 21:04:03 +0200 +Subject: [PATCH 3/4] SpiderMonkey: fix issue with javascript:history.back() + +In history.back() and others set rval to NULL. +Do not convert NULL to string in spidermoney_eval_stringback. + +Signed-off-by: Kamil Dudka +--- + src/ecmascript/spidermonkey.c | 2 +- + src/ecmascript/spidermonkey/location.c | 3 +++ + 2 files changed, 4 insertions(+), 1 deletions(-) + +diff --git a/src/ecmascript/spidermonkey.c b/src/ecmascript/spidermonkey.c +index 021e6bd..5360455 100644 +--- a/src/ecmascript/spidermonkey.c ++++ b/src/ecmascript/spidermonkey.c +@@ -303,7 +303,7 @@ spidermonkey_eval_stringback(struct ecmascript_interpreter *interpreter, + if (ret == JS_FALSE) { + return NULL; + } +- if (JSVAL_IS_VOID(rval)) { ++ if (JSVAL_IS_VOID(rval) || JSVAL_IS_NULL(rval)) { + /* Undefined value. */ + return NULL; + } +diff --git a/src/ecmascript/spidermonkey/location.c b/src/ecmascript/spidermonkey/location.c +index 752a890..d1fbdfb 100644 +--- a/src/ecmascript/spidermonkey/location.c ++++ b/src/ecmascript/spidermonkey/location.c +@@ -78,6 +78,7 @@ history_back(JSContext *ctx, uintN argc, jsval *rval) + * and return non zero for to prevent + * "calculating" new link. Returned value 2 is changed to 0 in function + * spidermonkey_eval_boolback */ ++ JS_SET_RVAL(ctx, rval, JSVAL_NULL); + return 2; + } + +@@ -91,6 +92,7 @@ history_forward(JSContext *ctx, uintN argc, jsval *rval) + + go_unback(ses); + ++ JS_SET_RVAL(ctx, rval, JSVAL_NULL); + return 2; + } + +@@ -121,6 +123,7 @@ history_go(JSContext *ctx, uintN argc, jsval *rval) + index += index > 0 ? -1 : 1; + } + ++ JS_SET_RVAL(ctx, rval, JSVAL_NULL); + return 2; + } + +-- +1.7.4.4 + + +From 725e389837d565cc3f9e787bd268fa5933c7bbb6 Mon Sep 17 00:00:00 2001 +From: witekfl +Date: Sun, 4 Mar 2012 18:20:48 +0100 +Subject: [PATCH 4/4] Check if hb is NULL. + +Signed-off-by: Kamil Dudka +--- + src/ecmascript/spidermonkey/heartbeat.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/src/ecmascript/spidermonkey/heartbeat.c b/src/ecmascript/spidermonkey/heartbeat.c +index bf95d92..b3dff58 100644 +--- a/src/ecmascript/spidermonkey/heartbeat.c ++++ b/src/ecmascript/spidermonkey/heartbeat.c +@@ -111,6 +111,7 @@ add_heartbeat(struct ecmascript_interpreter *interpreter) + void + done_heartbeat(struct heartbeat *hb) + { ++ if (!hb) return; /* add_heartbeat returned NULL */ + assert(hb->interpreter); + + /* Stop the heartbeat timer if this heartbeat is the only one. */ +-- +1.7.9.1 + diff --git a/SOURCES/elinks-0.12pre6-autoconf.patch b/SOURCES/elinks-0.12pre6-autoconf.patch new file mode 100644 index 0000000..c9be0a2 --- /dev/null +++ b/SOURCES/elinks-0.12pre6-autoconf.patch @@ -0,0 +1,35 @@ +From d7380abead73dc753023ef598b87944756c08d40 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Mon, 25 Feb 2013 15:31:07 +0100 +Subject: [PATCH] configure.in: add missing AC_LANG_PROGRAM + +... around the first argument of AC_COMPILE_IFELSE +--- + configure.in | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/configure.in b/configure.in +index 2629ac3..4290e45 100644 +--- a/configure.in ++++ b/configure.in +@@ -220,7 +220,7 @@ AC_STRUCT_TM + AC_C_CONST + AC_C_INLINE + AC_MSG_CHECKING([[for C99-conforming inline]]) +-AC_COMPILE_IFELSE([[ ++AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + int add(int change); + + static int sum; +@@ -236,7 +236,7 @@ AC_COMPILE_IFELSE([[ + sub(int change) + { + return add(-change); +- }]], ++ }]])], + [AC_MSG_RESULT([[yes]]) + AC_DEFINE([NONSTATIC_INLINE], [inline], + [Define as inline if the compiler lets you declare a function without inline, then define it with inline, and have that definition refer to identifiers with internal linkage. This is allowed by C99 6.7.4p6 and 6.7.4p3 together. Otherwise define as nothing.])], +-- +1.7.1 + diff --git a/SOURCES/elinks-nss-inc.patch b/SOURCES/elinks-nss-inc.patch new file mode 100644 index 0000000..666fc6b --- /dev/null +++ b/SOURCES/elinks-nss-inc.patch @@ -0,0 +1,69 @@ + src/network/ssl/ssl.c | 33 ++++++++++++++++++++++++++++++++- + 1 files changed, 32 insertions(+), 1 deletions(-) + +diff --git a/src/network/ssl/ssl.c b/src/network/ssl/ssl.c +index 73446b5..eadff7f 100644 +--- a/src/network/ssl/ssl.c ++++ b/src/network/ssl/ssl.c +@@ -48,10 +48,20 @@ SSL_CTX *context = NULL; + static void + init_openssl(struct module *module) + { ++ unsigned char *ca_file; + SSLeay_add_ssl_algorithms(); + context = SSL_CTX_new(SSLv23_client_method()); + SSL_CTX_set_options(context, SSL_OP_ALL); ++#ifdef CONFIG_NSS_COMPAT_OSSL ++ ca_file = get_opt_str("connection.ssl.trusted_ca_file"); ++ if (*ca_file) ++ SSL_CTX_load_verify_locations(context, ca_file, NULL); ++ else ++ SSL_CTX_set_default_verify_paths(context); ++#else ++ (void) ca_file; + SSL_CTX_set_default_verify_paths(context); ++#endif + } + + static void +@@ -61,10 +71,30 @@ done_openssl(struct module *module) + } + + static union option_info openssl_options[] = { ++#ifdef CONFIG_NSS_COMPAT_OSSL ++ INIT_OPT_BOOL("connection.ssl", N_("Verify certificates"), ++ "cert_verify", 0, 0, ++ N_("Verify the peer's SSL certificate.")), ++ ++ INIT_OPT_STRING("connection.ssl", N_("Trusted CA file"), ++ "trusted_ca_file", 0, "/etc/pki/tls/certs/ca-bundle.crt", ++ N_("The location of a file containing certificates of " ++ "trusted certification authorities in PEM format. " ++ "ELinks then trusts certificates issued by these CAs.\n" ++ "\n" ++ "If you set this option to an empty string, default NSS root" ++ "certificates are loaded.\n" ++ "\n" ++ "If you change this option or the file, you must " ++ "restart ELinks for the changes to take effect. " ++ "This option affects GnuTLS and nss_compat_ossl but not " ++ "OpenSSL.")), ++#else + INIT_OPT_BOOL("connection.ssl", N_("Verify certificates"), + "cert_verify", 0, 0, + N_("Verify the peer's SSL certificate. Note that this " + "needs extensive configuration of OpenSSL by the user.")), ++#endif + + INIT_OPT_TREE("connection.ssl", N_("Client Certificates"), + "client_cert", OPT_SORT, +@@ -187,7 +217,8 @@ static union option_info gnutls_options[] = { + "\n" + "If you change this option or the file, you must " + "restart ELinks for the changes to take effect. " +- "This option affects GnuTLS but not OpenSSL.")), ++ "This option affects GnuTLS and nss_compat_ossl but not " ++ "OpenSSL.")), + + NULL_OPTION_INFO, + }; diff --git a/SOURCES/elinks-nss.patch b/SOURCES/elinks-nss.patch new file mode 100644 index 0000000..893505c --- /dev/null +++ b/SOURCES/elinks-nss.patch @@ -0,0 +1,265 @@ + configure.in | 34 +++++++++++++++++++++++++++++++++- + src/network/ssl/socket.c | 28 ++++++++++++++++++++++------ + src/network/ssl/ssl.c | 32 ++++++++++++++++++++++++++------ + src/network/ssl/ssl.h | 2 +- + 4 files changed, 82 insertions(+), 14 deletions(-) + +diff --git a/configure.in b/configure.in +index 0e534db..972a305 100644 +--- a/configure.in ++++ b/configure.in +@@ -970,6 +970,37 @@ AC_ARG_WITH(openssl, [[ --with-openssl[=DIR] enable OpenSSL support (default + *) chosen_ssl_library="OpenSSL" ;; + esac]) + ++AC_ARG_WITH(nss_compat_ossl, [[ --with-nss_compat_ossl[=DIR] ++ NSS compatibility SSL libraries/include files]]) ++ ++# nss_compat_ossl ++if test -n "$with_nss_compat_ossl" && test "$with_nss_compat_ossl" != "no"; then ++ EL_SAVE_FLAGS ++ if test "$with_nss_compat_ossl" = yes; then ++ if pkg-config nss; then ++ CFLAGS="$CFLAGS_X `pkg-config --cflags nss`" ++ LIBS="$LIBS_X `pkg-config --libs nss`" ++ else ++ with_nss_compat_ossl=no ++ fi ++ else ++ # Without pkg-config, we'll kludge in some defaults ++ CFLAGS="$CFLAGS_X -I$with_nss_compat_ossl/include -I/usr/include/nss3 -I/usr/include/nspr4" ++ LIBS="$LIBS_X -L$with_nss_compat_ossl/lib -lssl3 -lsmime3 -lnss3 -lplds4 -lplc4 -lnspr4 -lpthread -ldl" ++ fi ++ AC_CHECK_HEADERS(nss_compat_ossl/nss_compat_ossl.h,, [with_nss_compat_ossl=no], [#define NSS_COMPAT_OSSL_H]) ++ AC_CHECK_LIB(nss_compat_ossl, X509_free,, [with_nss_compat_ossl=no]) ++ ++ if test "$with_nss_compat_ossl" = "no"; then ++ EL_RESTORE_FLAGS ++ else ++ LIBS="$LIBS -lnss_compat_ossl" ++ EL_CONFIG(CONFIG_NSS_COMPAT_OSSL, [nss_compat_ossl]) ++ disable_openssl="yes" ++ disable_gnutls="yes" ++ fi ++fi ++ + # ---- OpenSSL + + AC_MSG_CHECKING([for OpenSSL]) +@@ -1092,10 +1123,11 @@ fi + + # Final SSL setup + +-EL_CONFIG_DEPENDS(CONFIG_SSL, [CONFIG_OPENSSL CONFIG_GNUTLS], [SSL]) ++EL_CONFIG_DEPENDS(CONFIG_SSL, [CONFIG_OPENSSL CONFIG_GNUTLS CONFIG_NSS_COMPAT_OSSL], [SSL]) + AC_SUBST(CONFIG_GNUTLS_OPENSSL_COMPAT) + AC_SUBST(CONFIG_OPENSSL) + AC_SUBST(CONFIG_GNUTLS) ++AC_SUBST(CONFIG_NSS_COMPAT_OSSL) + + #endif + +diff --git a/src/network/ssl/socket.c b/src/network/ssl/socket.c +index 45b4b4a..3265107 100644 +--- a/src/network/ssl/socket.c ++++ b/src/network/ssl/socket.c +@@ -6,6 +6,10 @@ + + #ifdef CONFIG_OPENSSL + #include ++#define USE_OPENSSL ++#elif defined(CONFIG_NSS_COMPAT_OSSL) ++#include ++#define USE_OPENSSL + #elif defined(CONFIG_GNUTLS) + #include + #else +@@ -26,7 +30,7 @@ + + + /* SSL errors */ +-#ifdef CONFIG_OPENSSL ++#ifdef USE_OPENSSL + #define SSL_ERROR_WANT_READ2 9999 /* XXX */ + #define SSL_ERROR_WANT_WRITE2 SSL_ERROR_WANT_WRITE + #define SSL_ERROR_SYSCALL2 SSL_ERROR_SYSCALL +@@ -40,7 +44,7 @@ + #define SSL_ERROR_SYSCALL2 GNUTLS_E_PULL_ERROR + #endif + +-#ifdef CONFIG_OPENSSL ++#ifdef USE_OPENSSL + + #define ssl_do_connect(socket) SSL_get_error(socket->ssl, SSL_connect(socket->ssl)) + #define ssl_do_write(socket, data, len) SSL_write(socket->ssl, data, len) +@@ -126,7 +130,7 @@ ssl_connect(struct socket *socket) + if (socket->no_tls) + ssl_set_no_tls(socket); + +-#ifdef CONFIG_OPENSSL ++#ifdef USE_OPENSSL + SSL_set_fd(socket->ssl, socket->fd); + + if (get_opt_bool("connection.ssl.cert_verify")) +@@ -137,7 +141,13 @@ ssl_connect(struct socket *socket) + if (get_opt_bool("connection.ssl.client_cert.enable")) { + unsigned char *client_cert; + +- client_cert = get_opt_str("connection.ssl.client_cert.file"); ++#ifdef CONFIG_NSS_COMPAT_OSSL ++ client_cert = get_opt_str( ++ "connection.ssl.client_cert.nickname"); ++#else ++ client_cert = get_opt_str( ++ "connection.ssl.client_cert.file"); ++#endif + if (!*client_cert) { + client_cert = getenv("X509_CLIENT_CERT"); + if (client_cert && !*client_cert) +@@ -145,11 +155,17 @@ ssl_connect(struct socket *socket) + } + + if (client_cert) { ++#ifdef CONFIG_NSS_COMPAT_OSSL ++ SSL_CTX_use_certificate_chain_file( ++ (SSL *) socket->ssl, ++ client_cert); ++#else + SSL_CTX *ctx = ((SSL *) socket->ssl)->ctx; + + SSL_CTX_use_certificate_chain_file(ctx, client_cert); + SSL_CTX_use_PrivateKey_file(ctx, client_cert, + SSL_FILETYPE_PEM); ++#endif + } + } + +@@ -206,7 +222,7 @@ ssl_write(struct socket *socket, unsigned char *data, int len) + ssize_t wr = ssl_do_write(socket, data, len); + + if (wr <= 0) { +-#ifdef CONFIG_OPENSSL ++#ifdef USE_OPENSSL + int err = SSL_get_error(socket->ssl, wr); + #elif defined(CONFIG_GNUTLS) + int err = wr; +@@ -235,7 +251,7 @@ ssl_read(struct socket *socket, unsigned char *data, int len) + ssize_t rd = ssl_do_read(socket, data, len); + + if (rd <= 0) { +-#ifdef CONFIG_OPENSSL ++#ifdef USE_OPENSSL + int err = SSL_get_error(socket->ssl, rd); + #elif defined(CONFIG_GNUTLS) + int err = rd; +diff --git a/src/network/ssl/ssl.c b/src/network/ssl/ssl.c +index 685c31e..73446b5 100644 +--- a/src/network/ssl/ssl.c ++++ b/src/network/ssl/ssl.c +@@ -7,6 +7,10 @@ + #ifdef CONFIG_OPENSSL + #include + #include ++#define USE_OPENSSL ++#elif defined(CONFIG_NSS_COMPAT_OSSL) ++#include ++#define USE_OPENSSL + #elif defined(CONFIG_GNUTLS) + #include + #include +@@ -33,7 +37,7 @@ + /* FIXME: As you can see, SSL is currently implemented in very, erm, + * decentralized manner. */ + +-#ifdef CONFIG_OPENSSL ++#ifdef USE_OPENSSL + + #ifndef PATH_MAX + #define PATH_MAX 256 /* according to my /usr/include/bits/posix1_lim.h */ +@@ -71,12 +75,28 @@ static union option_info openssl_options[] = { + N_("Enable or not the sending of X509 client certificates " + "to servers which request them.")), + ++#ifdef CONFIG_NSS_COMPAT_OSSL ++ INIT_OPT_STRING("connection.ssl.client_cert", N_("Certificate nickname"), ++ "nickname", 0, "", ++ N_("The nickname of the client certificate stored in NSS " ++ "database. If this value is unset, the nickname from " ++ "the X509_CLIENT_CERT variable is used instead. If you " ++ "have a PKCS#12 file containing client certificate, you " ++ "can import it into your NSS database with:\n" ++ "\n" ++ "$ pk12util -i mycert.p12 -d /path/to/database\n" ++ "\n" ++ "The NSS database location can be changed by SSL_DIR " ++ "environment variable. The database can be also shared " ++ "with Mozilla browsers.")), ++#else + INIT_OPT_STRING("connection.ssl.client_cert", N_("Certificate File"), + "file", 0, "", + N_("The location of a file containing the client certificate " + "and unencrypted private key in PEM format. If unset, the " + "file pointed to by the X509_CLIENT_CERT variable is used " + "instead.")), ++#endif + + NULL_OPTION_INFO, + }; +@@ -182,7 +202,7 @@ static struct module gnutls_module = struct_module( + /* done: */ done_gnutls + ); + +-#endif /* CONFIG_OPENSSL or CONFIG_GNUTLS */ ++#endif /* USE_OPENSSL or CONFIG_GNUTLS */ + + static union option_info ssl_options[] = { + INIT_OPT_TREE("connection", N_("SSL"), +@@ -193,7 +213,7 @@ static union option_info ssl_options[] = { + }; + + static struct module *ssl_modules[] = { +-#ifdef CONFIG_OPENSSL ++#ifdef USE_OPENSSL + &openssl_module, + #elif defined(CONFIG_GNUTLS) + &gnutls_module, +@@ -214,7 +234,7 @@ struct module ssl_module = struct_module( + int + init_ssl_connection(struct socket *socket) + { +-#ifdef CONFIG_OPENSSL ++#ifdef USE_OPENSSL + socket->ssl = SSL_new(context); + if (!socket->ssl) return S_SSL_ERROR; + #elif defined(CONFIG_GNUTLS) +@@ -271,7 +291,7 @@ done_ssl_connection(struct socket *socket) + ssl_t *ssl = socket->ssl; + + if (!ssl) return; +-#ifdef CONFIG_OPENSSL ++#ifdef USE_OPENSSL + SSL_free(ssl); + #elif defined(CONFIG_GNUTLS) + gnutls_deinit(*ssl); +@@ -288,7 +308,7 @@ get_ssl_connection_cipher(struct socket *socket) + + if (!init_string(&str)) return NULL; + +-#ifdef CONFIG_OPENSSL ++#ifdef USE_OPENSSL + add_format_to_string(&str, "%ld-bit %s %s", + SSL_get_cipher_bits(ssl, NULL), + SSL_get_cipher_version(ssl), +diff --git a/src/network/ssl/ssl.h b/src/network/ssl/ssl.h +index 7c54a7a..21ca142 100644 +--- a/src/network/ssl/ssl.h ++++ b/src/network/ssl/ssl.h +@@ -22,7 +22,7 @@ unsigned char *get_ssl_connection_cipher(struct socket *socket); + + /* Internal type used in ssl module. */ + +-#ifdef CONFIG_OPENSSL ++#if defined(CONFIG_OPENSSL) || defined(CONFIG_NSS_COMPAT_OSSL) + #define ssl_t SSL + #elif defined(CONFIG_GNUTLS) + #define ssl_t gnutls_session_t diff --git a/SOURCES/elinks-scroll.patch b/SOURCES/elinks-scroll.patch new file mode 100644 index 0000000..a652093 --- /dev/null +++ b/SOURCES/elinks-scroll.patch @@ -0,0 +1,861 @@ +From f513964579f72fc77eea6e0961e49cc8299bf204 Mon Sep 17 00:00:00 2001 +From: Witold Filipczyk +Date: Sun, 31 Aug 2008 14:23:28 +0200 +Subject: [PATCH] Use real_box in dialog.c. + +Signed-off-by: Kamil Dudka +--- + src/bfu/button.c | 32 +++++++++++++------------- + src/bfu/button.h | 3 +- + src/bfu/checkbox.c | 13 +++++----- + src/bfu/checkbox.h | 3 +- + src/bfu/dialog.c | 59 ++++++++++++++++++++++++++++++++++------------- + src/bfu/dialog.h | 2 + + src/bfu/group.c | 18 +++++++------- + src/bfu/group.h | 2 +- + src/bfu/inpfield.c | 10 ++++---- + src/bfu/inpfield.h | 2 +- + src/bfu/listbox.c | 3 +- + src/bfu/listbox.h | 2 +- + src/bfu/text.c | 16 +++++++----- + src/bfu/text.h | 5 ++- + src/dialogs/download.c | 12 +++++----- + src/terminal/draw.c | 36 +++++++++++++++++++++++++++++ + src/terminal/draw.h | 10 ++++++++ + src/terminal/window.c | 15 ++++++++++++ + src/terminal/window.h | 2 + + 19 files changed, 170 insertions(+), 75 deletions(-) + +diff --git a/src/bfu/button.c b/src/bfu/button.c +index 8267c94..8e6ac62 100644 +--- a/src/bfu/button.c ++++ b/src/bfu/button.c +@@ -115,7 +115,7 @@ buttons_width(struct widget_data *widget_data, int n, + } + + void +-dlg_format_buttons(struct terminal *term, ++dlg_format_buttons(struct terminal *term, struct dialog_data *dlg_data, + struct widget_data *widget_data, int n, + int x, int *y, int w, int *rw, enum format_align align, int format_only) + { +@@ -212,7 +212,7 @@ display_button(struct dialog_data *dlg_data, struct widget_data *widget_data) + } + + +- draw_text(term, pos->x, pos->y, BUTTON_LEFT, BUTTON_LEFT_LEN, 0, color); ++ draw_text2(term, dlg_data, pos->x, pos->y, BUTTON_LEFT, BUTTON_LEFT_LEN, 0, color); + if (len > 0) { + unsigned char *text = widget_data->widget->text; + int hk_pos = widget_data->widget->info.button.hotkey_pos; +@@ -236,15 +236,15 @@ display_button(struct dialog_data *dlg_data, struct widget_data *widget_data) + NULL); + + if (hk_pos) +- draw_text(term, x, pos->y, ++ draw_text2(term, dlg_data, x, pos->y, + text, hk_pos, 0, color); + +- draw_text(term, x + cells_to_hk, pos->y, ++ draw_text2(term, dlg_data, x + cells_to_hk, pos->y, + &text[hk_pos + 1], hk_bytes, + attr, shortcut_color); + + if (right > 1) +- draw_text(term, x+cells_to_hk+hk_cells, ++ draw_text2(term, dlg_data, x+cells_to_hk+hk_cells, + pos->y, + &text[hk_pos + hk_bytes + 1], + right - 1, 0, color); +@@ -257,11 +257,11 @@ display_button(struct dialog_data *dlg_data, struct widget_data *widget_data) + len - hk_width, + NULL); + +- draw_text(term, x, pos->y, ++ draw_text2(term, dlg_data, x, pos->y, + text, hk_len, + attr, shortcut_color); + +- draw_text(term, x + hk_width, pos->y, ++ draw_text2(term, dlg_data, x + hk_width, pos->y, + &text[hk_len], len_to_display, + 0, color); + } +@@ -271,18 +271,18 @@ display_button(struct dialog_data *dlg_data, struct widget_data *widget_data) + int right = widget_data->widget->info.button.truetextlen - hk_pos - 1; + + if (hk_pos) { +- draw_text(term, x, pos->y, text, hk_pos, 0, color); ++ draw_text2(term, dlg_data, x, pos->y, text, hk_pos, 0, color); + } +- draw_text(term, x + hk_pos, pos->y, ++ draw_text2(term, dlg_data, x + hk_pos, pos->y, + &text[hk_pos + 1], 1, attr, shortcut_color); + if (right > 1) { +- draw_text(term, x + hk_pos + 1, pos->y, ++ draw_text2(term, dlg_data, x + hk_pos + 1, pos->y, + &text[hk_pos + 2], right - 1, 0, color); + } + + } else { +- draw_text(term, x, pos->y, text, 1, attr, shortcut_color); +- draw_text(term, x + 1, pos->y, &text[1], len - 1, 0, color); ++ draw_text2(term, dlg_data, x, pos->y, text, 1, attr, shortcut_color); ++ draw_text2(term, dlg_data, x + 1, pos->y, &text[1], len - 1, 0, color); + } + } + #ifdef CONFIG_UTF8 +@@ -290,15 +290,15 @@ display_button(struct dialog_data *dlg_data, struct widget_data *widget_data) + int text_cells = utf8_ptr2cells(widget_data->widget->text, NULL); + int hk = (widget_data->widget->info.button.hotkey_pos >= 0); + +- draw_text(term, x + text_cells - hk, pos->y, ++ draw_text2(term, dlg_data, x + text_cells - hk, pos->y, + BUTTON_RIGHT, BUTTON_RIGHT_LEN, 0, color); + } else + #endif /* CONFIG_UTF8 */ +- draw_text(term, x + len, pos->y, BUTTON_RIGHT, ++ draw_text2(term, dlg_data, x + len, pos->y, BUTTON_RIGHT, + BUTTON_RIGHT_LEN, 0, color); + if (sel) { +- set_cursor(term, x, pos->y, 1); +- set_window_ptr(dlg_data->win, pos->x, pos->y); ++ set_cursor2(term, dlg_data, x, pos->y, 1); ++ set_window_ptr2(dlg_data, dlg_data->win, pos->x, pos->y); + } + return EVENT_PROCESSED; + } +diff --git a/src/bfu/button.h b/src/bfu/button.h +index e6e907d..de986c8 100644 +--- a/src/bfu/button.h ++++ b/src/bfu/button.h +@@ -5,6 +5,7 @@ + #include "util/align.h" + + struct dialog; ++struct dialog_data; + struct terminal; + struct widget_data; + +@@ -89,6 +90,6 @@ void add_dlg_button_do(struct dialog *dlg, unsigned char *text, int flags, widge + #endif + + extern const struct widget_ops button_ops; +-void dlg_format_buttons(struct terminal *, struct widget_data *, int, int, int *, int, int *, enum format_align, int); ++void dlg_format_buttons(struct terminal *, struct dialog_data *, struct widget_data *, int, int, int *, int, int *, enum format_align, int); + + #endif +diff --git a/src/bfu/checkbox.c b/src/bfu/checkbox.c +index 7ed97e0..d7c974b 100644 +--- a/src/bfu/checkbox.c ++++ b/src/bfu/checkbox.c +@@ -36,7 +36,7 @@ add_dlg_radio_do(struct dialog *dlg, unsigned char *text, + } + + void +-dlg_format_checkbox(struct terminal *term, ++dlg_format_checkbox(struct terminal *term, struct dialog_data *dlg_data, + struct widget_data *widget_data, + int x, int *y, int w, int *rw, + enum format_align align, int format_only) +@@ -49,7 +49,7 @@ dlg_format_checkbox(struct terminal *term, + + if (text && *text) { + if (rw) *rw -= CHECKBOX_LS; +- dlg_format_text_do(term, text, x + CHECKBOX_LS, y, ++ dlg_format_text_do(term, dlg_data, text, x + CHECKBOX_LS, y, + w - CHECKBOX_LS, rw, + get_bfu_color(term, "dialog.checkbox-label"), + align, format_only); +@@ -78,11 +78,11 @@ display_checkbox(struct dialog_data *dlg_data, struct widget_data *widget_data) + else + text = widget_data->widget->info.checkbox.gid ? "( )" : "[ ]"; + +- draw_text(term, pos->x, pos->y, text, CHECKBOX_LEN, 0, color); ++ draw_text2(term, dlg_data, pos->x, pos->y, text, CHECKBOX_LEN, 0, color); + + if (selected) { +- set_cursor(term, pos->x + 1, pos->y, 1); +- set_window_ptr(dlg_data->win, pos->x, pos->y); ++ set_cursor2(term, dlg_data, pos->x + 1, pos->y, 1); ++ set_window_ptr2(dlg_data, dlg_data->win, pos->x, pos->y); + } + + return EVENT_PROCESSED; +@@ -128,7 +128,6 @@ mouse_checkbox(struct dialog_data *dlg_data, struct widget_data *widget_data) + static widget_handler_status_T + select_checkbox(struct dialog_data *dlg_data, struct widget_data *widget_data) + { +- + if (!widget_data->widget->info.checkbox.gid) { + /* Checkbox. */ + int *cdata = (int *) widget_data->cdata; +@@ -159,8 +158,8 @@ select_checkbox(struct dialog_data *dlg_data, struct widget_data *widget_data) + } + widget_data->info.checkbox.checked = 1; + } +- + display_widget(dlg_data, widget_data); ++ + return EVENT_PROCESSED; + } + +diff --git a/src/bfu/checkbox.h b/src/bfu/checkbox.h +index 573f1d2..b4e65ce 100644 +--- a/src/bfu/checkbox.h ++++ b/src/bfu/checkbox.h +@@ -2,6 +2,7 @@ + #define EL__BFU_CHECKBOX_H + + struct dialog; ++struct dialog_data; + struct terminal; + struct widget_data; + +@@ -30,7 +31,7 @@ void add_dlg_radio_do(struct dialog *dlg, unsigned char *text, int groupid, int + extern const struct widget_ops checkbox_ops; + + void +-dlg_format_checkbox(struct terminal *term, ++dlg_format_checkbox(struct terminal *term, struct dialog_data *dlg_data, + struct widget_data *widget_data, + int x, int *y, int w, int *rw, + enum format_align align, int format_only); +diff --git a/src/bfu/dialog.c b/src/bfu/dialog.c +index b2df9f8..414283f 100644 +--- a/src/bfu/dialog.c ++++ b/src/bfu/dialog.c +@@ -82,20 +82,18 @@ redraw_dialog(struct dialog_data *dlg_data, int layout) + } + + if (!dlg_data->dlg->layout.only_widgets) { +- struct box box; +- +- set_box(&box, ++ set_box(&dlg_data->real_box, + dlg_data->box.x + (DIALOG_LEFT_BORDER + 1), + dlg_data->box.y + (DIALOG_TOP_BORDER + 1), + dlg_data->box.width - 2 * (DIALOG_LEFT_BORDER + 1), + dlg_data->box.height - 2 * (DIALOG_TOP_BORDER + 1)); + +- draw_border(term, &box, get_bfu_color(term, "dialog.frame"), DIALOG_FRAME); ++ draw_border(term, &dlg_data->real_box, get_bfu_color(term, "dialog.frame"), DIALOG_FRAME); + + assert(dlg_data->dlg->title); + + title_color = get_bfu_color(term, "dialog.title"); +- if (title_color && box.width > 2) { ++ if (title_color && dlg_data->real_box.width > 2) { + unsigned char *title = dlg_data->dlg->title; + int titlelen = strlen(title); + int titlecells = titlelen; +@@ -107,7 +105,7 @@ redraw_dialog(struct dialog_data *dlg_data, int layout) + &title[titlelen]); + #endif /* CONFIG_UTF8 */ + +- titlecells = int_min(box.width - 2, titlecells); ++ titlecells = int_min(dlg_data->real_box.width - 2, titlecells); + + #ifdef CONFIG_UTF8 + if (term->utf8_cp) +@@ -115,13 +113,13 @@ redraw_dialog(struct dialog_data *dlg_data, int layout) + NULL); + #endif /* CONFIG_UTF8 */ + +- x = (box.width - titlecells) / 2 + box.x; +- y = box.y - 1; ++ x = (dlg_data->real_box.width - titlecells) / 2 + dlg_data->real_box.x; ++ y = dlg_data->real_box.y - 1; + + +- draw_text(term, x - 1, y, " ", 1, 0, title_color); +- draw_text(term, x, y, title, titlelen, 0, title_color); +- draw_text(term, x + titlecells, y, " ", 1, 0, ++ draw_text2(term, dlg_data, x - 1, y, " ", 1, 0, title_color); ++ draw_text2(term, dlg_data, x, y, title, titlelen, 0, title_color); ++ draw_text2(term, dlg_data, x + titlecells, y, " ", 1, 0, + title_color); + } + } +@@ -181,6 +179,23 @@ init_widget(struct dialog_data *dlg_data, int i) + return widget_data; + } + ++static int ++check_range(struct dialog_data *dlg_data, struct widget_data *widget_data) ++{ ++ if (!dlg_data->dlg->layout.only_widgets) { ++ struct box *box = &widget_data->box; ++ struct box *dlgbox = &dlg_data->real_box; ++ int y = box->y - dlgbox->y; ++ ++ if ((y < dlg_data->y) || (y >= dlg_data->y + dlgbox->height)) { ++ dlg_data->y = y / dlgbox->height * dlgbox->height; ++ redraw_dialog(dlg_data, 0); ++ return 1; ++ } ++ } ++ return 0; ++} ++ + void + select_widget(struct dialog_data *dlg_data, struct widget_data *widget_data) + { +@@ -190,6 +205,9 @@ select_widget(struct dialog_data *dlg_data, struct widget_data *widget_data) + + dlg_data->selected_widget_id = widget_data - dlg_data->widgets_data; + ++ if (check_range(dlg_data, widget_data)) ++ return; ++ + display_widget(dlg_data, previously_selected_widget); + display_widget(dlg_data, widget_data); + } +@@ -228,6 +246,11 @@ cycle_widget_focus(struct dialog_data *dlg_data, int direction) + } while (!widget_is_focusable(selected_widget(dlg_data)) + && dlg_data->selected_widget_id != prev_selected); + ++ if (check_range(dlg_data, selected_widget(dlg_data))) { ++ redraw_from_window(dlg_data->win); ++ return; ++ } ++ + display_widget(dlg_data, previously_selected_widget); + display_widget(dlg_data, selected_widget(dlg_data)); + redraw_from_window(dlg_data->win); +@@ -238,6 +261,7 @@ dialog_ev_init(struct dialog_data *dlg_data) + { + int i; + ++ dlg_data->y = 0; + /* TODO: foreachback_widget() */ + for (i = dlg_data->number_of_widgets - 1; i >= 0; i--) { + struct widget_data *widget_data; +@@ -421,6 +445,7 @@ dialog_ev_abort(struct dialog_data *dlg_data) + } + + freeml(dlg_data->ml); ++ dlg_data->y = 0; + } + + /* TODO: use EVENT_PROCESSED/EVENT_NOT_PROCESSED. */ +@@ -554,17 +579,17 @@ format_widgets(struct terminal *term, struct dialog_data *dlg_data, + switch (wdata->widget->type) { + case WIDGET_FIELD_PASS: + case WIDGET_FIELD: +- dlg_format_field(term, wdata, x, y, w, rw, ALIGN_LEFT, ++ dlg_format_field(term, dlg_data, wdata, x, y, w, rw, ALIGN_LEFT, + format_only); + break; + + case WIDGET_LISTBOX: +- dlg_format_listbox(term, wdata, x, y, w, h, rw, ++ dlg_format_listbox(term, dlg_data, wdata, x, y, w, h, rw, + ALIGN_LEFT, format_only); + break; + + case WIDGET_TEXT: +- dlg_format_text(term, wdata, x, y, w, rw, h, ++ dlg_format_text(term, dlg_data, wdata, x, y, w, rw, h, + format_only); + break; + +@@ -583,7 +608,7 @@ format_widgets(struct terminal *term, struct dialog_data *dlg_data, + break; + } + +- dlg_format_group(term, wdata, size, x, y, w, rw, ++ dlg_format_group(term, dlg_data, wdata, size, x, y, w, rw, + format_only); + wdata += size - 1; + +@@ -591,7 +616,7 @@ format_widgets(struct terminal *term, struct dialog_data *dlg_data, + + /* No horizontal space between checkboxes belonging to + * the same group. */ +- dlg_format_checkbox(term, wdata, x, y, w, rw, ++ dlg_format_checkbox(term, dlg_data, wdata, x, y, w, rw, + ALIGN_LEFT, format_only); + if (widgets > 1 + && group == widget_has_group(&wdata[1])) +@@ -603,7 +628,7 @@ format_widgets(struct terminal *term, struct dialog_data *dlg_data, + /* We assume that the buttons are all stuffed at the very end + * of the dialog. */ + case WIDGET_BUTTON: +- dlg_format_buttons(term, wdata, widgets, ++ dlg_format_buttons(term, dlg_data, wdata, widgets, + x, y, w, rw, ALIGN_CENTER, format_only); + return; + } +diff --git a/src/bfu/dialog.h b/src/bfu/dialog.h +index b0cde3b..bec914c 100644 +--- a/src/bfu/dialog.h ++++ b/src/bfu/dialog.h +@@ -100,6 +100,8 @@ struct dialog_data { + struct memory_list *ml; + + struct box box; ++ struct box real_box; ++ int y; + int number_of_widgets; + int selected_widget_id; + struct term_event *term_event; +diff --git a/src/bfu/group.c b/src/bfu/group.c +index cc4c6d8..15bd827 100644 +--- a/src/bfu/group.c ++++ b/src/bfu/group.c +@@ -20,7 +20,7 @@ + #define CHECKBOX_LEN 3 /* "[X]" or "(X)" */ + + void +-dlg_format_group(struct terminal *term, ++dlg_format_group(struct terminal *term, struct dialog_data *dlg_data, + struct widget_data *widget_data, + int n, int x, int *y, int w, int *rw, int format_only) + { +@@ -87,14 +87,14 @@ dlg_format_group(struct terminal *term, + text, + label_length, + NULL); +- draw_text(term, xpos + width ++ draw_text2(term, dlg_data, xpos + width + + label_padding, + *y, text, lb, 0, + color); + } else + #endif /* CONFIG_UTF8 */ + { +- draw_text(term, xpos + width ++ draw_text2(term, dlg_data, xpos + width + + label_padding, + *y, text, + label_length, 0, +@@ -113,12 +113,12 @@ dlg_format_group(struct terminal *term, + text, + label_length, + NULL); +- draw_text(term, xpos, *y, ++ draw_text2(term, dlg_data, xpos, *y, + text, lb, 0, color); + } else + #endif /* CONFIG_UTF8 */ + { +- draw_text(term, xpos, *y, ++ draw_text2(term, dlg_data, xpos, *y, + text, label_length, + 0, color); + } +@@ -155,11 +155,11 @@ group_layouter(struct dialog_data *dlg_data) + #endif /* CONFIG_UTF8 */ + rw = int_min(w, strlen(dlg_data->dlg->title)); + +- dlg_format_group(term, dlg_data->widgets_data, n, ++ dlg_format_group(term, dlg_data, dlg_data->widgets_data, n, + 0, &y, w, &rw, 1); + + y++; +- dlg_format_buttons(term, dlg_data->widgets_data + n, 2, 0, &y, w, ++ dlg_format_buttons(term, dlg_data, dlg_data->widgets_data + n, 2, 0, &y, w, + &rw, ALIGN_CENTER, 1); + + w = rw; +@@ -167,10 +167,10 @@ group_layouter(struct dialog_data *dlg_data) + draw_dialog(dlg_data, w, y); + + y = dlg_data->box.y + DIALOG_TB + 1; +- dlg_format_group(term, dlg_data->widgets_data, n, ++ dlg_format_group(term, dlg_data, dlg_data->widgets_data, n, + dlg_data->box.x + DIALOG_LB, &y, w, NULL, 0); + + y++; +- dlg_format_buttons(term, dlg_data->widgets_data + n, 2, ++ dlg_format_buttons(term, dlg_data, dlg_data->widgets_data + n, 2, + dlg_data->box.x + DIALOG_LB, &y, w, &rw, ALIGN_CENTER, 0); + } +diff --git a/src/bfu/group.h b/src/bfu/group.h +index 0de645d..9b92c2a 100644 +--- a/src/bfu/group.h ++++ b/src/bfu/group.h +@@ -5,7 +5,7 @@ struct dialog_data; + struct terminal; + struct widget_data; + +-void dlg_format_group(struct terminal *term, ++void dlg_format_group(struct terminal *term, struct dialog_data *dlg_data, + struct widget_data *widget_data, + int n, int x, int *y, int w, int *rw, int format_only); + +diff --git a/src/bfu/inpfield.c b/src/bfu/inpfield.c +index 4c0dcd2..0a9c63e 100644 +--- a/src/bfu/inpfield.c ++++ b/src/bfu/inpfield.c +@@ -103,7 +103,7 @@ check_nonempty(struct dialog_data *dlg_data, struct widget_data *widget_data) + } + + void +-dlg_format_field(struct terminal *term, ++dlg_format_field(struct terminal *term, struct dialog_data *dlg_data, + struct widget_data *widget_data, + int x, int *y, int w, int *rw, enum format_align align, int format_only) + { +@@ -132,7 +132,7 @@ dlg_format_field(struct terminal *term, + if (label && *label) { + if (!format_only) text_color = get_bfu_color(term, "dialog.text"); + +- dlg_format_text_do(term, label, x, y, w, rw, text_color, ALIGN_LEFT, format_only); ++ dlg_format_text_do(term, dlg_data, label, x, y, w, rw, text_color, ALIGN_LEFT, format_only); + } + + /* XXX: We want the field and label on the same line if the terminal +@@ -140,7 +140,7 @@ dlg_format_field(struct terminal *term, + if (label && *label && float_label) { + if (widget_data->widget->info.field.flags & INPFIELD_FLOAT) { + (*y) -= INPUTFIELD_HEIGHT; +- dlg_format_text_do(term, INPUTFIELD_FLOAT_SEPARATOR, ++ dlg_format_text_do(term, dlg_data, INPUTFIELD_FLOAT_SEPARATOR, + x + label_width, y, w, rw, + text_color, ALIGN_LEFT, format_only); + w -= INPUTFIELD_FLOAT_SEPARATOR_LEN + INPUTFIELD_FLOATLABEL_PADDING; +@@ -312,7 +312,7 @@ display_field_do(struct dialog_data *dlg_data, struct widget_data *widget_data, + if (term->utf8_cp) + w = utf8_cells2bytes(text, w, NULL); + #endif /* CONFIG_UTF8 */ +- draw_text(term, widget_data->box.x, widget_data->box.y, ++ draw_text2(term, dlg_data, widget_data->box.x, widget_data->box.y, + text, w, 0, color); + } else { + struct box box; +@@ -763,7 +763,7 @@ input_line_layouter(struct dialog_data *dlg_data) + - ses->status.show_status_bar + - ses->status.show_tabs_bar; + +- dlg_format_field(win->term, dlg_data->widgets_data, 0, ++ dlg_format_field(win->term, dlg_data, dlg_data->widgets_data, 0, + &y, win->term->width, NULL, ALIGN_LEFT, 0); + } + +diff --git a/src/bfu/inpfield.h b/src/bfu/inpfield.h +index d45a902..fb2270e 100644 +--- a/src/bfu/inpfield.h ++++ b/src/bfu/inpfield.h +@@ -62,7 +62,7 @@ extern const struct widget_ops field_pass_ops; + widget_handler_status_T check_number(struct dialog_data *, struct widget_data *); + widget_handler_status_T check_nonempty(struct dialog_data *, struct widget_data *); + +-void dlg_format_field(struct terminal *, struct widget_data *, int, int *, int, int *, enum format_align, int format_only); ++void dlg_format_field(struct terminal *, struct dialog_data *, struct widget_data *, int, int *, int, int *, enum format_align, int format_only); + + void input_field(struct terminal *, struct memory_list *, int, unsigned char *, + unsigned char *, unsigned char *, unsigned char *, void *, +diff --git a/src/bfu/listbox.c b/src/bfu/listbox.c +index 7ec1b66..e4de12f 100644 +--- a/src/bfu/listbox.c ++++ b/src/bfu/listbox.c +@@ -41,7 +41,8 @@ get_listbox_widget_data(struct widget_data *widget_data) + + /* Layout for generic boxes */ + void +-dlg_format_listbox(struct terminal *term, struct widget_data *widget_data, ++dlg_format_listbox(struct terminal *term, struct dialog_data *dlg_data, ++ struct widget_data *widget_data, + int x, int *y, int w, int max_height, int *rw, + enum format_align align, int format_only) + { +diff --git a/src/bfu/listbox.h b/src/bfu/listbox.h +index c3599e5..63b8be4 100644 +--- a/src/bfu/listbox.h ++++ b/src/bfu/listbox.h +@@ -133,7 +133,7 @@ struct listbox_item { + + extern const struct widget_ops listbox_ops; + +-void dlg_format_listbox(struct terminal *, struct widget_data *, int, int *, int, int, int *, enum format_align, int format_only); ++void dlg_format_listbox(struct terminal *, struct dialog_data *, struct widget_data *, int, int *, int, int, int *, enum format_align, int format_only); + + struct listbox_item *traverse_listbox_items_list(struct listbox_item *, struct listbox_data *, int, int, int (*)(struct listbox_item *, void *, int *), void *); + +diff --git a/src/bfu/text.c b/src/bfu/text.c +index e8be019..3d2895e 100644 +--- a/src/bfu/text.c ++++ b/src/bfu/text.c +@@ -211,7 +211,8 @@ split_lines(struct widget_data *widget_data, int max_width) + + /* Format text according to dialog box and alignment. */ + void +-dlg_format_text_do(struct terminal *term, unsigned char *text, ++dlg_format_text_do(struct terminal *term, struct dialog_data *dlg_data, ++ unsigned char *text, + int x, int *y, int width, int *real_width, + struct color_pair *color, enum format_align align, + int format_only) +@@ -255,12 +256,13 @@ dlg_format_text_do(struct terminal *term, unsigned char *text, + + assert(cells <= width && shift < width); + +- draw_text(term, x + shift, *y, text, line_width, 0, color); ++ draw_text2(term, dlg_data, x + shift, *y, text, line_width, 0, color); + } + } + + void +-dlg_format_text(struct terminal *term, struct widget_data *widget_data, ++dlg_format_text(struct terminal *term, struct dialog_data *dlg_data, ++ struct widget_data *widget_data, + int x, int *y, int width, int *real_width, int max_height, + int format_only) + { +@@ -335,7 +337,7 @@ dlg_format_text(struct terminal *term, struct widget_data *widget_data, + widget_data->info.text.current = 0; + } + +- dlg_format_text_do(term, text, ++ dlg_format_text_do(term, dlg_data, text, + x, y, width, real_width, + get_bfu_color(term, "dialog.text"), + widget_data->widget->info.text.align, format_only); +@@ -395,8 +397,8 @@ display_text(struct dialog_data *dlg_data, struct widget_data *widget_data) + + /* Hope this is at least a bit reasonable. Set cursor + * and window pointer to start of the first text line. */ +- set_cursor(win->term, widget_data->box.x, widget_data->box.y, 1); +- set_window_ptr(win, widget_data->box.x, widget_data->box.y); ++ set_cursor2(win->term, dlg_data, widget_data->box.x, widget_data->box.y, 1); ++ set_window_ptr2(dlg_data, win, widget_data->box.x, widget_data->box.y); + + return EVENT_PROCESSED; + } +@@ -423,7 +425,7 @@ format_and_display_text(struct widget_data *widget_data, + draw_box(term, &widget_data->box, ' ', 0, + get_bfu_color(term, "dialog.generic")); + +- dlg_format_text(term, widget_data, ++ dlg_format_text(term, dlg_data, widget_data, + widget_data->box.x, &y, widget_data->box.width, NULL, + height, 0); + +diff --git a/src/bfu/text.h b/src/bfu/text.h +index 8dd3365..b181c1a 100644 +--- a/src/bfu/text.h ++++ b/src/bfu/text.h +@@ -4,6 +4,7 @@ + #include "util/color.h" + + struct dialog; ++struct dialog_data; + struct terminal; + + struct widget_info_text { +@@ -45,12 +46,12 @@ void add_dlg_text(struct dialog *dlg, unsigned char *text, + enum format_align align, int bottom_pad); + + extern const struct widget_ops text_ops; +-void dlg_format_text_do(struct terminal *term, ++void dlg_format_text_do(struct terminal *term, struct dialog_data *dlg_data, + unsigned char *text, int x, int *y, int w, int *rw, + struct color_pair *scolor, enum format_align align, int format_only); + + void +-dlg_format_text(struct terminal *term, struct widget_data *widget_data, ++dlg_format_text(struct terminal *term, struct dialog_data *dlg_data, struct widget_data *widget_data, + int x, int *y, int dlg_width, int *real_width, int height, int format_only); + + #define text_is_scrollable(widget_data) \ +diff --git a/src/dialogs/download.c b/src/dialogs/download.c +index 0116578..b90f047 100644 +--- a/src/dialogs/download.c ++++ b/src/dialogs/download.c +@@ -157,7 +157,7 @@ download_dialog_layouter(struct dialog_data *dlg_data) + int_lower_bound(&w, DOWN_DLG_MIN); + } + +- dlg_format_text_do(term, url, 0, &y, w, &rw, ++ dlg_format_text_do(term, dlg_data, url, 0, &y, w, &rw, + dialog_text_color, ALIGN_LEFT, 1); + + y++; +@@ -166,11 +166,11 @@ download_dialog_layouter(struct dialog_data *dlg_data) + #if CONFIG_BITTORRENT + if (bittorrent) y += 2; + #endif +- dlg_format_text_do(term, msg, 0, &y, w, &rw, ++ dlg_format_text_do(term, dlg_data, msg, 0, &y, w, &rw, + dialog_text_color, ALIGN_LEFT, 1); + + y++; +- dlg_format_buttons(term, dlg_data->widgets_data, ++ dlg_format_buttons(term, dlg_data, dlg_data->widgets_data, + dlg_data->number_of_widgets, 0, &y, w, + &rw, ALIGN_CENTER, 1); + +@@ -190,7 +190,7 @@ download_dialog_layouter(struct dialog_data *dlg_data) + + y = dlg_data->box.y + DIALOG_TB + 1; + x = dlg_data->box.x + DIALOG_LB; +- dlg_format_text_do(term, url, x, &y, w, NULL, ++ dlg_format_text_do(term, dlg_data, url, x, &y, w, NULL, + dialog_text_color, ALIGN_LEFT, 0); + + if (show_meter) { +@@ -207,11 +207,11 @@ download_dialog_layouter(struct dialog_data *dlg_data) + } + #endif + y++; +- dlg_format_text_do(term, msg, x, &y, w, NULL, ++ dlg_format_text_do(term, dlg_data, msg, x, &y, w, NULL, + dialog_text_color, ALIGN_LEFT, 0); + + y++; +- dlg_format_buttons(term, dlg_data->widgets_data, ++ dlg_format_buttons(term, dlg_data, dlg_data->widgets_data, + dlg_data->number_of_widgets, x, &y, w, + NULL, ALIGN_CENTER, 0); + +diff --git a/src/terminal/draw.c b/src/terminal/draw.c +index b3b3706..267d9ac 100644 +--- a/src/terminal/draw.c ++++ b/src/terminal/draw.c +@@ -7,6 +7,7 @@ + + #include "elinks.h" + ++#include "bfu/dialog.h" + #include "config/options.h" + #include "intl/charsets.h" + #include "terminal/color.h" +@@ -559,6 +560,23 @@ draw_text(struct terminal *term, int x, int y, + } + + void ++draw_text2(struct terminal *term, struct dialog_data *dlg_data, int x, int y, ++ unsigned char *text, int length, ++ enum screen_char_attr attr, struct color_pair *color) ++{ ++ struct box *box = &dlg_data->real_box; ++ ++ if (box->height) { ++ int y_max = box->y + box->height; ++ ++ y -= dlg_data->y; ++ if (y < box->y || y >= y_max) return; ++ } ++ draw_text(term, x, y, text, length, attr, color); ++} ++ ++ ++void + set_cursor(struct terminal *term, int x, int y, int blockable) + { + assert(term && term->screen); +@@ -580,6 +598,24 @@ set_cursor(struct terminal *term, int x, int y, int blockable) + } + + void ++set_cursor2(struct terminal *term, struct dialog_data *dlg_data, int x, int y, int blockable) ++{ ++ struct box *box = &dlg_data->real_box; ++ ++ assert(term && term->screen); ++ if_assert_failed return; ++ ++ if (box->height) { ++ int y_max = box->y + box->height; ++ ++ y -= dlg_data->y; ++ if (y < box->y || y >= y_max) return; ++ } ++ set_cursor(term, x, y, blockable); ++} ++ ++ ++void + clear_terminal(struct terminal *term) + { + struct box box; +diff --git a/src/terminal/draw.h b/src/terminal/draw.h +index 6dcd31a..20fba4e 100644 +--- a/src/terminal/draw.h ++++ b/src/terminal/draw.h +@@ -4,6 +4,7 @@ + #include "intl/charsets.h" /* unicode_val_T */ + + struct color_pair; ++struct dialog_data; + struct box; + struct terminal; + +@@ -280,6 +281,12 @@ void draw_text(struct terminal *term, int x, int y, + enum screen_char_attr attr, + struct color_pair *color); + ++/** Draws text for dialogs. */ ++void draw_text2(struct terminal *term, struct dialog_data *dlg_data, int x, int y, ++ unsigned char *text, int length, ++ enum screen_char_attr attr, struct color_pair *color); ++ ++ + /** Draws @a length chars from @a line on the screen. */ + void draw_line(struct terminal *term, int x, int y, int length, + struct screen_char *line); +@@ -289,6 +296,9 @@ void draw_line(struct terminal *term, int x, int y, int length, + * bottom right corner of the screen. */ + void set_cursor(struct terminal *term, int x, int y, int blockable); + ++/* set cursor for dialogs */ ++void set_cursor2(struct terminal *term, struct dialog_data *dlg_data, int x, int y, int blockable); ++ + /** Blanks the screen. */ + void clear_terminal(struct terminal *); + +diff --git a/src/terminal/window.c b/src/terminal/window.c +index 9ac7191..934207d 100644 +--- a/src/terminal/window.c ++++ b/src/terminal/window.c +@@ -7,6 +7,7 @@ + + #include "elinks.h" + ++#include "bfu/dialog.h" + #include "bfu/menu.h" + #include "terminal/event.h" + #include "terminal/tab.h" +@@ -227,3 +228,17 @@ would_window_receive_keypresses(const struct window *win) + return 1; + } + #endif /* CONFIG_SCRIPTING_SPIDERMONKEY */ ++ ++void ++set_window_ptr2(struct dialog_data *dlg_data, struct window *window, int x, int y) ++{ ++ struct box *box = &dlg_data->real_box; ++ ++ if (box->height) { ++ int y_max = box->y + box->height; ++ ++ y -= dlg_data->y; ++ if (y < box->y || y >= y_max) return; ++ } ++ set_window_ptr(window, x, y); ++} +diff --git a/src/terminal/window.h b/src/terminal/window.h +index 8bb329d..c8250ac 100644 +--- a/src/terminal/window.h ++++ b/src/terminal/window.h +@@ -3,6 +3,7 @@ + + #include "util/lists.h" + ++struct dialog_data; + struct term_event; + struct terminal; + struct window; +@@ -73,6 +74,7 @@ void add_window(struct terminal *, window_handler_T, void *); + void delete_window(struct window *); + void delete_window_ev(struct window *, struct term_event *ev); + #define set_window_ptr(window, x_, y_) do { (window)->x = (x_); (window)->y = (y_); } while (0) ++void set_window_ptr2(struct dialog_data *dlg_data, struct window *window, int x, int y); + void get_parent_ptr(struct window *, int *, int *); + + void add_empty_window(struct terminal *, void (*)(void *), void *); +-- +1.7.1 + diff --git a/SOURCES/elinks.conf b/SOURCES/elinks.conf new file mode 100644 index 0000000..1175846 --- /dev/null +++ b/SOURCES/elinks.conf @@ -0,0 +1,29 @@ +## ELinks 0.12pre3 configuration file + +## This is ELinks global configuration file. You can keep global ELinks +## configuration here. Each user can also save its own ELinks configuration +## to ~/.elinks/elinks.conf. The per user configuration file can be edited +## by ELinks when you save options through UI. + +## connection +# Connection options. + + ## connection.ssl + # SSL options. + + ## connection.ssl.cert_verify [0|1] + # Verify the peer's SSL certificate. + set connection.ssl.cert_verify = 1 + + ## connection.ssl.trusted_ca_file + # The location of a file containing certificates of trusted certification + # authorities in PEM format. ELinks then trusts certificates issued by + # these CAs. + # + # If you set this option to an empty string, default NSS root certificates + # are loaded. + # + # If you change this option or the file, you must restart ELinks for the + # changes to take effect. This option affects GnuTLS and nss_compat_ossl + # but not OpenSSL. + set connection.ssl.trusted_ca_file = "/etc/pki/tls/certs/ca-bundle.crt" diff --git a/SPECS/elinks.spec b/SPECS/elinks.spec new file mode 100644 index 0000000..f9ea5f4 --- /dev/null +++ b/SPECS/elinks.spec @@ -0,0 +1,572 @@ +%global prerel pre6 + +Name: elinks +Summary: A text-mode Web browser +Version: 0.12 +Release: 0.37.%{prerel}%{?dist} +License: GPLv2 +URL: http://elinks.or.cz +Group: Applications/Internet +Source: http://elinks.or.cz/download/elinks-%{version}%{prerel}.tar.bz2 +Source2: elinks.conf + +BuildRequires: automake +BuildRequires: bzip2-devel +BuildRequires: expat-devel +BuildRequires: gpm-devel +BuildRequires: js-devel +BuildRequires: krb5-devel +BuildRequires: libidn-devel +BuildRequires: nss_compat_ossl-devel +BuildRequires: pkgconfig +BuildRequires: zlib-devel +Requires(preun): %{_sbindir}/alternatives +Requires(post): coreutils +Requires(post): %{_sbindir}/alternatives +Requires(postun): coreutils +Requires(postun): %{_sbindir}/alternatives +Provides: webclient +Obsoletes: links < 1:0.97 +Provides: links = 1:0.97-1 +Provides: text-www-browser + +Patch0: elinks-0.11.0-ssl-noegd.patch +Patch1: elinks-0.10.1-utf_8_io-default.patch +Patch3: elinks-0.11.0-getaddrinfo.patch +Patch4: elinks-0.11.0-sysname.patch +Patch5: elinks-0.10.1-xterm.patch +Patch7: elinks-0.11.3-macropen.patch +Patch8: elinks-scroll.patch +Patch9: elinks-nss.patch +Patch10: elinks-nss-inc.patch +Patch11: elinks-0.12pre5-js185.patch +Patch12: elinks-0.12pre5-ddg-search.patch +Patch13: elinks-0.12pre6-autoconf.patch + +%description +Elinks is a text-based Web browser. Elinks does not display any images, +but it does support frames, tables and most other HTML tags. Elinks' +advantage over graphical browsers is its speed--Elinks starts and exits +quickly and swiftly displays Web pages. + +%prep +%setup -q -n %{name}-%{version}%{prerel} + +# Prevent crash when HOME is unset (bug #90663). +%patch0 -p1 + +# UTF-8 by default +%patch1 -p1 + +# Make getaddrinfo call use AI_ADDRCONFIG. +%patch3 -p1 + +# Don't put so much information in the user-agent header string (bug #97273). +%patch4 -p1 + +# Fix xterm terminal: "Linux" driver seems better than "VT100" (#128105) +%patch5 -p1 + +# fix for open macro in new glibc +%patch7 -p1 + +#upstream fix for out of screen dialogs +%patch8 -p1 + +# Port elinks to use NSS library for cryptography (#346861) - accepted upstream +%patch9 -p1 + +# Port elinks to use NSS library for cryptography (#346861) - incremental patch +%patch10 -p1 + +# backported upstream commits f31cf6f, 2844f8b, 218a225, and 12803e4 +%patch11 -p1 + +# add default "ddg" dumb/smart rewrite prefixes for DuckDuckGo (#856348) +%patch12 -p1 + +# add missing AC_LANG_PROGRAM around the first argument of AC_COMPILE_IFELSE +%patch13 -p1 + +# remove bogus serial numbers +sed -i 's/^# *serial [AM0-9]*$//' acinclude.m4 config/m4/*.m4 + +# we need to recreate autotools files because of the NSS patch +aclocal -I config/m4 +autoconf +autoheader + +%build +export CFLAGS="$RPM_OPT_FLAGS $(getconf LFS_CFLAGS) -D_GNU_SOURCE" +%configure %{?rescue:--without-gpm} --without-x --with-gssapi \ + --enable-bittorrent --with-nss_compat_ossl --enable-256-colors \ + --without-openssl --without-gnutls + +# uncomment to turn off optimizations +#sed -i 's/-O2/-O0/' Makefile.config + +MOPTS="V=1" +if tty >/dev/null 2>&1; then + # turn on fancy colorized output only when we have a TTY device + MOPTS= +fi +make %{?_smp_mflags} $MOPTS + +%install +make install DESTDIR=$RPM_BUILD_ROOT V=1 +rm -f $RPM_BUILD_ROOT%{_datadir}/locale/locale.alias +mkdir -p $RPM_BUILD_ROOT%{_sysconfdir} +install -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/elinks.conf +touch $RPM_BUILD_ROOT%{_bindir}/links +true | gzip -c > $RPM_BUILD_ROOT%{_mandir}/man1/links.1.gz +%find_lang elinks + +%postun +if [ "$1" -ge "1" ]; then + links=`readlink %{_sysconfdir}/alternatives/links` + if [ "$links" == "%{_bindir}/elinks" ]; then + %{_sbindir}/alternatives --set links %{_bindir}/elinks + fi +fi +exit 0 + +%post +#Set up alternatives files for links +%{_sbindir}/alternatives --install %{_bindir}/links links %{_bindir}/elinks 90 \ + --slave %{_mandir}/man1/links.1.gz links-man %{_mandir}/man1/elinks.1.gz +links=`readlink %{_sysconfdir}/alternatives/links` +if [ "$links" == "%{_bindir}/elinks" ]; then + %{_sbindir}/alternatives --set links %{_bindir}/elinks +fi + + +%preun +if [ $1 = 0 ]; then + %{_sbindir}/alternatives --remove links %{_bindir}/elinks +fi +exit 0 + +%files -f elinks.lang +%doc README SITES TODO COPYING +%ghost %verify(not md5 size mtime) %{_bindir}/links +%{_bindir}/elinks +%ghost %verify(not md5 size mtime) %{_mandir}/man1/links.1.gz +%config(noreplace) %{_sysconfdir}/elinks.conf +%{_mandir}/man1/elinks.1* +%{_mandir}/man5/* + +%changelog +* Tue Sep 19 2017 Kamil Dudka - 0.12-0.37.pre6 +- Rebuilt for js 48-bit VA support (#1439479) + +* Fri Jan 24 2014 Daniel Mach - 0.12-0.36.pre6 +- Mass rebuild 2014-01-24 + +* Fri Dec 27 2013 Daniel Mach - 0.12-0.35.pre6 +- Mass rebuild 2013-12-27 + +* Mon Feb 25 2013 Kamil Dudka - 0.12-0.34.pre6 +- update to latest upstream pre-release +- drop unneeded patches +- fix autoconf warnings +- explicitly disable using OpenSSL and GnuTLS + +* Wed Feb 13 2013 Fedora Release Engineering - 0.12-0.33.pre5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Fri Jan 04 2013 Kamil Dudka - 0.12-0.32.pre5 +- do not delegate GSSAPI credentials (CVE-2012-4545) + +* Mon Oct 08 2012 Kamil Dudka - 0.12-0.31.pre5 +- add default "ddg" dumb/smart rewrite prefixes for DuckDuckGo (#856348) + +* Tue Aug 28 2012 Kamil Dudka - 0.12-0.30.pre5 +- fix specfile issues reported by the fedora-review script + +* Wed Jul 18 2012 Fedora Release Engineering - 0.12-0.29.pre5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Fri Mar 09 2012 Kamil Dudka - 0.12-0.28.pre5 +- do not crash if add_heartbeat() returned NULL (#798103) + +* Fri Jan 13 2012 Fedora Release Engineering - 0.12-0.27.pre5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Fri May 06 2011 Kamil Dudka - 0.12-0.26.pre5 +- improve the js-1.8.5 patch (upstream commit 218a225) + +* Thu Apr 21 2011 Kamil Dudka - 0.12-0.25.pre5 +- port to js-1.8.5 API (upstream commits f31cf6f and 2844f8b) + +* Tue Feb 08 2011 Fedora Release Engineering - 0.12-0.24.pre5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Wed Apr 07 2010 Kamil Dudka - 0.12-0.23.pre5 +- do not print control characters to build logs +- avoid aclocal warnings + +* Thu Jan 07 2010 Kamil Dudka - 0.12-0.22.pre5 +- remove patch for configure script to find OpenSSL (we use NSS now) +- remove buildrequires for nss-devel (#550770) + +* Sun Dec 27 2009 Kamil Dudka 0.12-0.21.pre5 +- add buildrequires for js-devel (#550717) and zlib-devel +- build support for 256 color terminal + +* Mon Dec 14 2009 Ondrej Vasik 0.12-0.20.pre5 +- Add buildrequires for gpm-devel to enable gpm support(#547064) + +* Fri Aug 14 2009 Orion Poplawski 0.12-0.19.pre5 +- Add Requires(post/postun): coreutils for readlink + +* Fri Jul 24 2009 Fedora Release Engineering - 0.12-0.18.pre5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Wed Jul 08 2009 Ondrej Vasik 0.12-0.17.pre5 +- new upstream bugfix prerelease + +* Mon Jun 01 2009 Ondrej Vasik 0.12-0.16.pre4 +- new upstream bugfix prerelease +- defuzz patches + +* Wed Apr 29 2009 Kamil Dudka 0.12-0.15.pre3 +- try to load default NSS root certificates if the configuration option + connection.ssl.trusted_ca_file is set to an empty string (#497788) + +* Tue Apr 28 2009 Ondrej Vasik 0.12-0.14.pre3 +- enable certificate verification by default via configuration + file(#495532) + +* Tue Apr 28 2009 Kamil Dudka 0.12-0.13.pre3 +- use appropriate BuildRequires for nss_compat_ossl (#495532) +- support for trusted CA certificates loading from file in PEM format + +* Fri Apr 03 2009 Ondrej Vasik 0.12-0.12.pre3 +- use word Elinks instead of Links in package description + +* Mon Mar 30 2009 Ondrej Vasik 0.12-0.11.pre3 +- new upstream bugfix prerelease +- defuzz patches + +* Wed Mar 25 2009 Ondrej Vasik 0.12-0.10.pre2 +- use better obsoletes/provides for links, use alternatives for + links manpage and binary(#470703) + +* Tue Feb 24 2009 Fedora Release Engineering - 0.12-0.9.pre2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Fri Jan 16 2009 Tomas Mraz 0.12-0.8.pre2 +- rebuild with new openssl + +* Wed Jan 14 2009 Ondrej Vasik 0.12-0.7.pre2 +- versioned obsoletes and provides for links + +* Wed Oct 1 2008 Kamil Dudka 0.12-0.6.pre2 +- port elinks to use NSS library for cryptography (#346861) + +* Mon Sep 29 2008 Ondrej Vasik 0.12-0.5.pre2 +- new upstream bugfix prerelease +- Removed already applied patches for tabreload and bittorrent + +* Mon Sep 1 2008 Ondrej Vasik 0.12-0.4.pre1 +- upstream fix for bittorrent protocol +- upstream fix for out of screen bittorrent dialog texts + +* Tue Jul 15 2008 Ondrej Vasik 0.12-0.3.pre1 +- get rid off fuzz in patches + +* Tue Jul 15 2008 Ondrej Vasik 0.12-0.2.pre1 +- fix a crash when opening tab during page reload + +* Tue Jul 1 2008 Ondrej Vasik 0.12-0.1.pre1 +- unstable elinks-0.12 pre1, solves several long-term issues + unsolvable (or very hard to solve) in 0.11.4 (like #173411), + in general is elinks-0.12pre1 considered better than 0.11.4 +- dropped patches negotiate-auth, chunkedgzip - included in 0.12pre1, + modified few others due source code changes + +* Sat Jun 21 2008 Ondrej Vasik 0.11.4-1 +- new stable upstream release + +* Thu Mar 6 2008 Ondrej Vasik 0.11.4-0.4.rc1 +- new upstream release candidate marked stable + +* Thu Feb 21 2008 Ondrej Vasik 0.11.4-0.3.rc0 +- fixed broken output for gzipped chunked pages(#410801) + +* Thu Feb 07 2008 Ondrej Vasik 0.11.4-0.2.rc0 +- used -D_GNU_SOURCE instead of ugly hack/patch to + have NI_MAXPATH defined + +* Wed Feb 06 2008 Ondrej Vasik 0.11.4-0.1.rc0 +- new version marked stable by upstream 0.11.4rc0 +- enabled experimental bittorent support(#426702) + +* Wed Dec 05 2007 Ondrej Vasik 0.11.3-7 +- rebuilt because of new OpenSSL + +* Thu Oct 11 2007 Ondrej Vasik 0.11.3-6 +- generalized text-www-browser requirements(#174566) + +* Tue Aug 28 2007 Ondrej Vasik 0.11.3-5 +- rebuilt because of expat 2.0 + +* Wed Aug 22 2007 Ondrej Vasik 0.11.3-4 +- rebuilt for F8 +- changed license tag to GPLv2 + +* Thu Aug 9 2007 Ondrej Vasik 0.11.3-3 +- fix of open macro(new glibc) by Joe Orton + +* Fri Jul 27 2007 Ondrej Vasik 0.11.3-2 +- cleanup of duplicates in buildreq, added license file to doc +- (package review by Tyler Owen(#225725)) + +* Tue Jun 5 2007 Ondrej Vasik 0.11.3-1 +- update to new upstream version +- removed patch for #210103 , included in upstream release +- updated patch elinks-0.11.1-negotiate.patch to pass build + +* Mon Mar 26 2007 Karel Zak 0.11.2-1 +- update to new upstream version +- cleanup spec file + +* Wed Oct 11 2006 Karel Zak 0.11.1-5 +- fix #210103 - elinks crashes when given bad HTTP_PROXY + +* Wed Jul 12 2006 Jesse Keating - 0.11.1-4.1 +- rebuild + +* Mon Jun 12 2006 Karel Zak 0.11.1-4 +- improved negotiate-auth patch (faster now) + +* Fri Jun 9 2006 Karel Zak 0.11.1-3 +- added negotiate-auth (GSSAPI) support -- EXPERIMENTAL! + +* Mon May 29 2006 Karel Zak 0.11.1-2 +- update to new upstream version + +* Wed May 17 2006 Karsten Hopp 0.11.0-3 +- add buildrequires bzip2-devel, expat-devel,libidn-devel + +* Fri Feb 10 2006 Jesse Keating - 0.11.0-2.2 +- bump again for double-long bug on ppc(64) + +* Tue Feb 07 2006 Jesse Keating - 0.11.0-2.1 +- rebuilt for new gcc4.1 snapshot and glibc changes + +* Tue Jan 10 2006 Karel Zak 0.11.0-2 +- use upstream version of srcdir.patch + +* Tue Jan 10 2006 Karel Zak 0.11.0-1 +- update to new upstream version +- fix 0.11.0 build system (srcdir.patch) +- regenerate patches: + elinks-0.11.0-getaddrinfo.patch, + elinks-0.11.0-ssl-noegd.patch, + elinks-0.11.0-sysname.patch, + elinks-0.11.0-union.patch + +* Fri Dec 09 2005 Jesse Keating 0.10.6-2.1 +- rebuilt + +* Wed Nov 9 2005 Karel Zak 0.10.6-2 +- rebuild (against new openssl) + +* Thu Sep 29 2005 Karel Zak 0.10.6-1 +- update to new upstream version + +* Tue May 17 2005 Karel Zak 0.10.3-3 +- fix #157300 - Strange behavior on ppc64 (patch by Miloslav Trmac) + +* Tue May 10 2005 Miloslav Trmac - 0.10.3-2 +- Fix checking for numeric command prefix (#152953, patch by Jonas Fonseca) +- Fix invalid C causing assertion errors on ppc and ia64 (#156647) + +* Mon Mar 21 2005 Karel Zak 0.10.3-1 +- sync with upstream; stable 0.10.3 + +* Sat Mar 5 2005 Karel Zak 0.10.2-2 +- rebuilt + +* Tue Feb 8 2005 Karel Zak 0.10.2-1 +- sync with upstream; stable 0.10.2 + +* Fri Jan 28 2005 Karel Zak 0.10.1-1 +- sync with upstream; stable 0.10.1 + +* Thu Oct 14 2004 Karel Zak 0.9.2-2 +- the "Linux" driver seems better than "VT100" for xterm (#128105) + +* Wed Oct 6 2004 Karel Zak 0.9.2-1 +- upload new upstream tarball with stable 0.9.2 release + +* Mon Sep 20 2004 Jindrich Novy 0.9.2-0.rc7.4 +- 0.9.2rc7. +- changed summary in spec to get rid of #41732, #61499 + +* Mon Sep 13 2004 Tim Waugh 0.9.2-0.rc4.3 +- Avoid symbol clash (bug #131170). + +* Fri Aug 6 2004 Tim Waugh 0.9.2-0.rc4.2 +- 0.9.2rc4. + +* Mon Jul 12 2004 Tim Waugh 0.9.2-0.rc2.2 +- Fix elinks -dump -stdin (bug #127624). + +* Thu Jul 1 2004 Tim Waugh 0.9.2-0.rc2.1 +- 0.9.2rc2. + +* Tue Jun 15 2004 Elliot Lee +- rebuilt + +* Wed Jun 2 2004 Tim Waugh 0.9.1-3 +- Build with LFS support (bug #125064). + +* Fri May 28 2004 Tim Waugh 0.9.1-2 +- Use UTF-8 by default (bug #76445). + +* Thu Mar 11 2004 Tim Waugh 0.9.1-1 +- 0.9.1. +- Use %%find_lang. + +* Fri Feb 13 2004 Elliot Lee +- rebuilt + +* Mon Dec 8 2003 Tim Waugh 0.4.3-1 +- 0.4.3. +- Updated pkgconfig patch. + +* Mon Aug 11 2003 Tim Waugh 0.4.2-7.1 +- Rebuilt. + +* Mon Aug 11 2003 Tim Waugh 0.4.2-7 +- Don't require XFree86-libs (bug #102072). + +* Tue Jul 22 2003 Nalin Dahyabhai 0.4.2-6.2 +- rebuild + +* Thu Jun 12 2003 Tim Waugh 0.4.2-6.1 +- Rebuilt. + +* Thu Jun 12 2003 Tim Waugh 0.4.2-6 +- Make getaddrinfo call use AI_ADDRCONFIG. +- Don't put so much information in the user-agent header string (bug #97273). + +* Wed Jun 04 2003 Elliot Lee +- rebuilt + +* Mon Jun 2 2003 Tim Waugh 0.4.2-4.1 +- Rebuild again. + +* Mon Jun 2 2003 Tim Waugh 0.4.2-4 +- Rebuild. + +* Mon May 12 2003 Tim Waugh 0.4.2-3 +- Prevent crash when HOME is unset (bug #90663). + +* Sun May 04 2003 Florian La Roche 0.4.2-2 +- use relative symlinks to elinks + +* Wed Feb 5 2003 Tim Waugh 0.4.2-1 +- 0.4.2 (bug #83273). + +* Wed Jan 22 2003 Tim Powers 0.3.2-5 +- rebuilt + +* Thu Jan 16 2003 Tim Waugh +- Fix URL (bug #81987). + +* Tue Jan 7 2003 Nalin Dahyabhai 0.3.2-4 +- rebuild + +* Mon Dec 23 2002 Tim Waugh 0.3.2-3 +- Fix bug #62368. + +* Thu Dec 12 2002 Nalin Dahyabhai +- use openssl's pkg-config data, if available + +* Wed Nov 20 2002 Tim Powers 0.3.2-2 +- rebuild on all arches + +* Tue Aug 20 2002 Jakub Jelinek 0.3.2-1 +- update to 0.3.2 to fix the DNS Ctrl-C segfaults +- update URLs, the project moved +- include man page + +* Fri Jun 21 2002 Tim Powers +- automated rebuild + +* Thu May 23 2002 Tim Powers +- automated rebuild + +* Thu Jan 24 2002 Tim Powers +- rebuilt against new openssl + +* Wed Jan 09 2002 Tim Powers +- automated rebuild + +* Wed Jan 2 2002 Preston Brown 0.96-4 +- cookie fix + +* Thu Sep 13 2001 Bernhard Rosenkraenzer 0.96-3 +- Save some more space in rescue mode + +* Wed Jul 18 2001 Bernhard Rosenkraenzer 0.96-2 +- Add the links manual from links.sourceforge.net (RFE #49228) + +* Tue Jul 3 2001 Bernhard Rosenkraenzer 0.96-1 +- update to 0.96 + +* Fri Jun 22 2001 Nalin Dahyabhai +- actually run make in build phase + +* Tue Jun 12 2001 Nalin Dahyabhai +- rebuild in new environment + +* Fri Mar 2 2001 Nalin Dahyabhai +- rebuild in new environment + +* Tue Jan 9 2001 Bernhard Rosenkraenzer +- 0.95 + +* Mon Jan 1 2001 Bernhard Rosenkraenzer +- 0.94 final + +* Sun Dec 24 2000 Bernhard Rosenkraenzer +- pre9 + +* Mon Dec 10 2000 Preston Brown +- Upgraded to pre8. + +* Tue Dec 5 2000 Bernhard Rosenkraenzer +- 0.94pre7 +- Minor fixes to the specfile (s/Copyright:/License:/) +- merge rescue stuff + +* Fri Nov 24 2000 Bernhard Rosenkraenzer +- 0.94pre5 + +* Wed Nov 15 2000 Bernhard Rosenkraenzer +- 0.94pre4 + +* Tue Oct 24 2000 Bernhard Rosenkraenzer +- 0.94pre1 + +* Wed Aug 2 2000 Bernhard Rosenkraenzer +- 0.92 (needed - prior versions won't display XHTML properly) + +* Thu Jul 20 2000 Nalin Dahyabhai +- rebuild in new environment to work around bugs + +* Wed Jul 12 2000 Prospector +- automatic rebuild + +* Thu Jun 15 2000 Bernhard Rosenkraenzer +- 0.84 + +* Sun Jun 11 2000 Preston Brown +- provides virtual package webclient. + +* Thu Jan 6 2000 Bernhard Rosenkraenzer +- initial RPM