aboutsummaryrefslogtreecommitdiffstats
path: root/debian/patches/130_siteconf.patch
diff options
context:
space:
mode:
authorTatsuya Kinoshita <tats@debian.org>2015-01-24 14:36:40 +0000
committerTatsuya Kinoshita <tats@debian.org>2015-01-24 14:37:05 +0000
commit8595cb4102d547388d0d9e699d10a14f8f7aa71c (patch)
treecd27e4b710769000b651b9af4db2704a1cd328dd /debian/patches/130_siteconf.patch
parentUpdate Vcs-Browser (diff)
downloadw3m-8595cb4102d547388d0d9e699d10a14f8f7aa71c.tar.gz
w3m-8595cb4102d547388d0d9e699d10a14f8f7aa71c.zip
Integrate Debian changes into 020_debian.patch (closes: #776112)
(debian/patches/*.patch except 010_upstream.patch are merged)
Diffstat (limited to 'debian/patches/130_siteconf.patch')
-rw-r--r--debian/patches/130_siteconf.patch2065
1 files changed, 0 insertions, 2065 deletions
diff --git a/debian/patches/130_siteconf.patch b/debian/patches/130_siteconf.patch
deleted file mode 100644
index 9f8124f..0000000
--- a/debian/patches/130_siteconf.patch
+++ /dev/null
@@ -1,2065 +0,0 @@
-Subject: New feature: siteconf
-Origin: upstream, http://www.sic.med.tohoku.ac.jp/~satodai/w3m-dev/201206.month/4464.html
-
-Patch to support the siteconf feature, from [w3m-dev 04464]
-on 2012-06-27, provided by AIDA Shinra.
-
-Updated to fix segfault of loadGeneralFile() by Tatsuya Kinoshita.
-
-diff --git a/anchor.c b/anchor.c
-index 27bbd56..39f221d 100644
---- a/anchor.c
-+++ b/anchor.c
-@@ -200,10 +200,11 @@ _put_anchor_news(Buffer *buf, char *p1, char *p2, int line, int pos)
- if (*(p2 - 1) == '>')
- p2--;
- }
-- tmp = wc_Str_conv_strict(Strnew_charp_n(p1, p2 - p1), InnerCharset,
-- buf->document_charset);
-- tmp = Sprintf("news:%s", file_quote(tmp->ptr));
-- return registerHref(buf, tmp->ptr, NULL, NO_REFERER, NULL, '\0', line,
-+ tmp = Strnew_charp("news:");
-+ Strcat_charp_n(tmp, p1, p2 - p1);
-+ return registerHref(buf, url_encode(tmp->ptr, baseURL(buf),
-+ buf->document_charset),
-+ NULL, NO_REFERER, NULL, '\0', line,
- pos);
- }
- #endif /* USE_NNTP */
-@@ -213,9 +214,10 @@ _put_anchor_all(Buffer *buf, char *p1, char *p2, int line, int pos)
- {
- Str tmp;
-
-- tmp = wc_Str_conv_strict(Strnew_charp_n(p1, p2 - p1), InnerCharset,
-- buf->document_charset);
-- return registerHref(buf, url_quote(tmp->ptr), NULL, NO_REFERER, NULL,
-+ tmp = Strnew_charp_n(p1, p2 - p1);
-+ return registerHref(buf, url_encode(tmp->ptr, baseURL(buf),
-+ buf->document_charset),
-+ NULL, NO_REFERER, NULL,
- '\0', line, pos);
- }
-
-@@ -756,7 +758,7 @@ link_list_panel(Buffer *buf)
- p = parsedURL2Str(&pu)->ptr;
- u = html_quote(p);
- if (DecodeURL)
-- p = html_quote(url_unquote_conv(p, buf->document_charset));
-+ p = html_quote(url_decode2(p, buf));
- else
- p = u;
- }
-@@ -787,7 +789,7 @@ link_list_panel(Buffer *buf)
- p = parsedURL2Str(&pu)->ptr;
- u = html_quote(p);
- if (DecodeURL)
-- p = html_quote(url_unquote_conv(p, buf->document_charset));
-+ p = html_quote(url_decode2(p, buf));
- else
- p = u;
- t = getAnchorText(buf, al, a);
-@@ -809,16 +811,13 @@ link_list_panel(Buffer *buf)
- p = parsedURL2Str(&pu)->ptr;
- u = html_quote(p);
- if (DecodeURL)
-- p = html_quote(url_unquote_conv(p, buf->document_charset));
-+ p = html_quote(url_decode2(p, buf));
- else
- p = u;
- if (a->title && *a->title)
- t = html_quote(a->title);
-- else if (DecodeURL)
-- t = html_quote(url_unquote_conv
-- (a->url, buf->document_charset));
- else
-- t = html_quote(a->url);
-+ t = html_quote(url_decode2(a->url, buf));
- Strcat_m_charp(tmp, "<li><a href=\"", u, "\">", t, "</a><br>", p,
- "\n", NULL);
- a = retrieveAnchor(buf->formitem, a->start.line, a->start.pos);
-@@ -842,19 +841,13 @@ link_list_panel(Buffer *buf)
- p = parsedURL2Str(&pu)->ptr;
- u = html_quote(p);
- if (DecodeURL)
-- p = html_quote(url_unquote_conv(p,
-- buf->
-- document_charset));
-+ p = html_quote(url_decode2(p, buf));
- else
- p = u;
- if (m->alt && *m->alt)
- t = html_quote(m->alt);
-- else if (DecodeURL)
-- t = html_quote(url_unquote_conv(m->url,
-- buf->
-- document_charset));
- else
-- t = html_quote(m->url);
-+ t = html_quote(url_decode2(m->url, buf));
- Strcat_m_charp(tmp, "<li><a href=\"", u, "\">", t,
- "</a><br>", p, "\n", NULL);
- }
-diff --git a/config.h.in b/config.h.in
-index 2f41eed..59997b4 100644
---- a/config.h.in
-+++ b/config.h.in
-@@ -25,6 +25,7 @@
-
- #define PASSWD_FILE RC_DIR "/passwd"
- #define PRE_FORM_FILE RC_DIR "/pre_form"
-+#define SITECONF_FILE RC_DIR "/siteconf"
- #define USER_MAILCAP RC_DIR "/mailcap"
- #define SYS_MAILCAP CONF_DIR "/mailcap"
- #define USER_MIMETYPES "~/.mime.types"
-diff --git a/display.c b/display.c
-index e00eb0c..2fe1183 100644
---- a/display.c
-+++ b/display.c
-@@ -257,7 +257,7 @@ make_lastline_link(Buffer *buf, char *title, char *url)
- parseURL2(url, &pu, baseURL(buf));
- u = parsedURL2Str(&pu);
- if (DecodeURL)
-- u = Strnew_charp(url_unquote_conv(u->ptr, buf->document_charset));
-+ u = Strnew_charp(url_decode2(u->ptr, buf));
- #ifdef USE_M17N
- u = checkType(u, &pr, NULL);
- #endif
-diff --git a/doc-jp/README.siteconf b/doc-jp/README.siteconf
-new file mode 100644
-index 0000000..58b51c7
---- /dev/null
-+++ b/doc-jp/README.siteconf
-@@ -0,0 +1,60 @@
-+siteconf: サイト別カスタマイズ
-+
-+siteconf は、 URL のパターンと、それに紐付けられた設定から成ります。
-+siteconf を使うと、サイト毎に文字コードを指定して "decode_url"
-+の出力を改善したり、 Google のリダイレクタを迂回して性能や
-+プライバシーを向上させたりすることができます。
-+
-+デフォルトでは siteconf は ~/.w3m/siteconf から読み込まれます。
-+
-+===== 構文 =====
-+
-+url <url>|/<re-url>/|m@<re-url>@i [exact]
-+substitute_url "<destination-url>"
-+url_charset <charset>
-+no_referer_from on|off
-+no_referer_to on|off
-+
-+後ろの方に書かれたものが優先されます。
-+
-+===== 例 =====
-+
-+url "http://twitter.com/#!/"
-+substitute_url "http://mobile.twitter.com/"
-+
-+twitter.com をモバイルサイトに転送します。
-+
-+url "http://your.bookmark.net/"
-+no_referer_from on
-+
-+your.bookmark.net から張ったリンクを辿る際に、 HTTP referer を
-+送らないようにします。
-+
-+url "http://www.google.com/url?" exact
-+substitute_url "file:///cgi-bin/your-redirector.cgi?"
-+
-+Google のリダイレクタを local CGI に転送します。
-+
-+url /^http:\/\/[a-z]*\.wikipedia\.org\//
-+url_charset utf-8
-+
-+同時に "decode_url" オプションをオンにすると、 Wikipedia への
-+リンクを UTF-8 としてデコードして表示します。
-+
-+===== 正規表現について =====
-+
-+次の正規表現はいずれも同じ意味を表します。
-+
-+/http:\/\/www\.example\.com\//
-+m/http:\/\/www\.example\.com\//
-+m@http://www\.example\.com/@
-+m!http://www\.example\.com/!
-+
-+最後に 'i' 修飾子を付けると、大文字小文字を区別せずに照合を行います。
-+例えば、 m@^http://www\.example\.com/abc/@i は以下のいずれとも一致します。
-+
-+http://www.example.com/abc/
-+http://www.example.com/Abc/
-+http://www.example.com/ABC/
-+
-+ただし、ホスト名の部分は常に小文字に変換してから比較します。
-diff --git a/doc/README.siteconf b/doc/README.siteconf
-new file mode 100644
-index 0000000..f173087
---- /dev/null
-+++ b/doc/README.siteconf
-@@ -0,0 +1,60 @@
-+The siteconf: Site-specific preferences
-+
-+The siteconf consists of URL patterns and preferences associated to them.
-+You can improve "decode_url" feature by giving charsets of URLs site by site,
-+or bypass Google's redirector for performance and your privacy.
-+
-+The siteconf is read from ~/.w3m/siteconf by default.
-+
-+===== The syntax =====
-+
-+url <url>|/<re-url>/|m@<re-url>@i [exact]
-+substitute_url "<destination-url>"
-+url_charset <charset>
-+no_referer_from on|off
-+no_referer_to on|off
-+
-+The last match wins.
-+
-+===== Examples =====
-+
-+url "http://twitter.com/#!/"
-+substitute_url "http://mobile.twitter.com/"
-+
-+This forwards the twitter.com to its mobile site.
-+
-+url "http://your.bookmark.net/"
-+no_referer_from on
-+
-+This prevents HTTP referers from being sent when you follow links
-+at the your.bookmark.net.
-+
-+url "http://www.google.com/url?" exact
-+substitute_url "file:///cgi-bin/your-redirector.cgi?"
-+
-+This forwards the Google's redirector to your local CGI.
-+
-+url /^http:\/\/[a-z]*\.wikipedia\.org\//
-+url_charset utf-8
-+
-+When combinated with "decode_url" option turned on, links to
-+Wikipedia will be human-readable.
-+
-+===== Regular expressions notes =====
-+
-+Following expressions are all equivalent:
-+
-+/http:\/\/www\.example\.com\//
-+m/http:\/\/www\.example\.com\//
-+m@http://www\.example\.com/@
-+m!http://www\.example\.com/!
-+
-+With a trailing 'i' modifier, you can specify a case-insensitive match.
-+For example, m@^http://www\.example\.com/abc/@i matches to:
-+
-+http://www.example.com/abc/
-+http://www.example.com/Abc/
-+http://www.example.com/ABC/
-+
-+Hostnames, however, are always converted to lowercases before compared.
-+
-diff --git a/file.c b/file.c
-index 567d41e..b342de0 100644
---- a/file.c
-+++ b/file.c
-@@ -47,11 +47,11 @@ static JMP_BUF AbortLoading;
- static struct table *tables[MAX_TABLE];
- static struct table_mode table_mode[MAX_TABLE];
-
--#ifdef USE_IMAGE
-+#if defined(USE_M17N) || defined(USE_IMAGE)
- static ParsedURL *cur_baseURL = NULL;
--#ifdef USE_M17N
--static char cur_document_charset;
- #endif
-+#ifdef USE_M17N
-+static wc_ces cur_document_charset = 0;
- #endif
-
- static Str cur_title;
-@@ -215,7 +215,6 @@ currentLn(Buffer *buf)
-
- static Buffer *
- loadSomething(URLFile *f,
-- char *path,
- Buffer *(*loadproc) (URLFile *, Buffer *), Buffer *defaultbuf)
- {
- Buffer *buf;
-@@ -223,17 +222,23 @@ loadSomething(URLFile *f,
- if ((buf = loadproc(f, defaultbuf)) == NULL)
- return NULL;
-
-- buf->filename = path;
- if (buf->buffername == NULL || buf->buffername[0] == '\0') {
- buf->buffername = checkHeader(buf, "Subject:");
-- if (buf->buffername == NULL)
-- buf->buffername = conv_from_system(lastFileName(path));
-+ if (buf->buffername == NULL && buf->filename != NULL)
-+ buf->buffername = conv_from_system(lastFileName(buf->filename));
- }
- if (buf->currentURL.scheme == SCM_UNKNOWN)
- buf->currentURL.scheme = f->scheme;
-- buf->real_scheme = f->scheme;
- if (f->scheme == SCM_LOCAL && buf->sourcefile == NULL)
-- buf->sourcefile = path;
-+ buf->sourcefile = buf->filename;
-+ if (loadproc == loadHTMLBuffer
-+#ifdef USE_IMAGE
-+ || loadproc == loadImageBuffer
-+#endif
-+ )
-+ buf->type = "text/html";
-+ else
-+ buf->type = "text/plain";
- return buf;
- }
-
-@@ -484,28 +489,6 @@ convertLine0(URLFile *uf, Str line, int mode)
- return line;
- }
-
--/*
-- * loadFile: load file to buffer
-- */
--Buffer *
--loadFile(char *path)
--{
-- Buffer *buf;
-- URLFile uf;
-- init_stream(&uf, SCM_LOCAL, NULL);
-- examineFile(path, &uf);
-- if (uf.stream == NULL)
-- return NULL;
-- buf = newBuffer(INIT_BUFFER_WIDTH);
-- current_content_length = 0;
--#ifdef USE_M17N
-- content_charset = 0;
--#endif
-- buf = loadSomething(&uf, path, loadBuffer, buf);
-- UFclose(&uf);
-- return buf;
--}
--
- int
- matchattr(char *p, char *attr, int len, Str *value)
- {
-@@ -1697,13 +1680,15 @@ getLinkNumberStr(int correction)
- /*
- * loadGeneralFile: load file to buffer
- */
-+#define DO_EXTERNAL ((Buffer *(*)(URLFile *, Buffer *))doExternal)
- Buffer *
- loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
- int flag, FormList *volatile request)
- {
- URLFile f, *volatile of = NULL;
- ParsedURL pu;
-- Buffer *b = NULL, *(*volatile proc)() = loadBuffer;
-+ Buffer *b = NULL;
-+ Buffer *(*volatile proc)(URLFile *, Buffer *) = loadBuffer;
- char *volatile tpath;
- char *volatile t = "text/plain", *p, *volatile real_type = NULL;
- Buffer *volatile t_buf = NULL;
-@@ -1730,7 +1715,22 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
- add_auth_cookie_flag = 0;
-
- checkRedirection(NULL);
-+
- load_doc:
-+ {
-+ const char *sc_redirect;
-+ parseURL2(tpath, &pu, current);
-+ sc_redirect = query_SCONF_SUBSTITUTE_URL(&pu);
-+ if (sc_redirect && *sc_redirect && checkRedirection(&pu)) {
-+ tpath = (char *)sc_redirect;
-+ request = NULL;
-+ add_auth_cookie_flag = 0;
-+ current = New(ParsedURL);
-+ *current = pu;
-+ status = HTST_NORMAL;
-+ goto load_doc;
-+ }
-+ }
- TRAP_OFF;
- url_option.referer = referer;
- url_option.flag = flag;
-@@ -1863,7 +1863,7 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
- /* 302: Found */
- /* 303: See Other */
- /* 307: Temporary Redirect (HTTP/1.1) */
-- tpath = url_quote_conv(p, DocumentCharset);
-+ tpath = url_encode(p, NULL, 0);
- request = NULL;
- UFclose(&f);
- current = New(ParsedURL);
-@@ -2022,7 +2022,7 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
- if (f.is_cgi && (p = checkHeader(t_buf, "Location:")) != NULL &&
- checkRedirection(&pu)) {
- /* document moved */
-- tpath = url_quote_conv(remove_space(p), DocumentCharset);
-+ tpath = url_encode(remove_space(p), NULL, 0);
- request = NULL;
- UFclose(&f);
- add_auth_cookie_flag = 0;
-@@ -2123,10 +2123,6 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
- if (real_type == NULL)
- real_type = t;
- proc = loadBuffer;
--#ifdef USE_IMAGE
-- cur_baseURL = New(ParsedURL);
-- copyParsedURL(cur_baseURL, &pu);
--#endif
-
- current_content_length = 0;
- if ((p = checkHeader(t_buf, "Content-Length:")) != NULL)
-@@ -2197,18 +2193,8 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
- #endif
- else if (w3m_backend) ;
- else if (!(w3m_dump & ~DUMP_FRAME) || is_dump_text_type(t)) {
-- if (!do_download && doExternal(f,
-- pu.real_file ? pu.real_file : pu.file,
-- t, &b, t_buf)) {
-- if (b && b != NO_BUFFER) {
-- b->real_scheme = f.scheme;
-- b->real_type = real_type;
-- if (b->currentURL.host == NULL && b->currentURL.file == NULL)
-- copyParsedURL(&b->currentURL, &pu);
-- }
-- UFclose(&f);
-- TRAP_OFF;
-- return b;
-+ if (!do_download && searchExtViewer(t) != NULL) {
-+ proc = DO_EXTERNAL;
- }
- else {
- TRAP_OFF;
-@@ -2232,36 +2218,30 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
- else if (w3m_dump & DUMP_FRAME)
- return NULL;
-
-+ if (t_buf == NULL)
-+ t_buf = newBuffer(INIT_BUFFER_WIDTH);
-+ copyParsedURL(&t_buf->currentURL, &pu);
-+ t_buf->filename = pu.real_file ? pu.real_file :
-+ pu.file ? conv_to_system(pu.file) : NULL;
- if (flag & RG_FRAME) {
-- if (t_buf == NULL)
-- t_buf = newBuffer(INIT_BUFFER_WIDTH);
- t_buf->bufferprop |= BP_FRAME;
- }
- #ifdef USE_SSL
-- if (t_buf)
-- t_buf->ssl_certificate = f.ssl_certificate;
-+ t_buf->ssl_certificate = f.ssl_certificate;
- #endif
- frame_source = flag & RG_FRAME_SRC;
-- b = loadSomething(&f, pu.real_file ? pu.real_file : pu.file, proc, t_buf);
-+ if (proc == DO_EXTERNAL) {
-+ b = doExternal(f, t, t_buf);
-+ } else {
-+ b = loadSomething(&f, proc, t_buf);
-+ }
- UFclose(&f);
- frame_source = 0;
-- if (b) {
-+ if (b && b != NO_BUFFER) {
- b->real_scheme = f.scheme;
- b->real_type = real_type;
-- if (b->currentURL.host == NULL && b->currentURL.file == NULL)
-- copyParsedURL(&b->currentURL, &pu);
-- if (is_html_type(t))
-- b->type = "text/html";
-- else if (w3m_backend) {
-- Str s = Strnew_charp(t);
-- b->type = s->ptr;
-- }
--#ifdef USE_IMAGE
-- else if (proc == loadImageBuffer)
-- b->type = "text/html";
--#endif
-- else
-- b->type = "text/plain";
-+ if (w3m_backend)
-+ b->type = allocStr(t, -1);
- if (pu.label) {
- if (proc == loadHTMLBuffer) {
- Anchor *a;
-@@ -2287,10 +2267,11 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
- if (header_string)
- header_string = NULL;
- #ifdef USE_NNTP
-- if (f.scheme == SCM_NNTP || f.scheme == SCM_NEWS)
-+ if (b && b != NO_BUFFER && (f.scheme == SCM_NNTP || f.scheme == SCM_NEWS))
- reAnchorNewsheader(b);
- #endif
-- preFormUpdateBuffer(b);
-+ if (b && b != NO_BUFFER)
-+ preFormUpdateBuffer(b);
- TRAP_OFF;
- return b;
- }
-@@ -3228,7 +3209,7 @@ process_img(struct parsed_tag *tag, int width)
-
- if (!parsedtag_get_value(tag, ATTR_SRC, &p))
- return tmp;
-- p = remove_space(p);
-+ p = url_encode(remove_space(p), cur_baseURL, cur_document_charset);
- q = NULL;
- parsedtag_get_value(tag, ATTR_ALT, &q);
- if (!pseudoInlines && (q == NULL || (*q == '\0' && ignore_null_img_alt)))
-@@ -3322,12 +3303,7 @@ process_img(struct parsed_tag *tag, int width)
- Image image;
- ParsedURL u;
-
--#ifdef USE_M17N
-- parseURL2(wc_conv(p, InnerCharset, cur_document_charset)->ptr, &u,
-- cur_baseURL);
--#else
- parseURL2(p, &u, cur_baseURL);
--#endif
- image.url = parsedURL2Str(&u)->ptr;
- if (!uncompressed_file_type(u.file, &image.ext))
- image.ext = filename_extension(u.file, TRUE);
-@@ -4084,6 +4060,7 @@ process_form_int(struct parsed_tag *tag, int fid)
- parsedtag_get_value(tag, ATTR_METHOD, &p);
- q = "!CURRENT_URL!";
- parsedtag_get_value(tag, ATTR_ACTION, &q);
-+ q = url_encode(remove_space(q), cur_baseURL, cur_document_charset);
- r = NULL;
- #ifdef USE_M17N
- if (parsedtag_get_value(tag, ATTR_ACCEPT_CHARSET, &r))
-@@ -5067,11 +5044,10 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env)
- }
- return 1;
- case HTML_BASE:
--#ifdef USE_IMAGE
-+#if defined(USE_M17N) || defined(USE_IMAGE)
- p = NULL;
- if (parsedtag_get_value(tag, ATTR_HREF, &p)) {
-- if (!cur_baseURL)
-- cur_baseURL = New(ParsedURL);
-+ cur_baseURL = New(ParsedURL);
- parseURL(p, cur_baseURL, NULL);
- }
- #endif
-@@ -5329,6 +5305,13 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
- #ifdef MENU_SELECT
- Anchor **a_select = NULL;
- #endif
-+#if defined(USE_M17N) || defined(USE_IMAGE)
-+ ParsedURL *base = baseURL(buf);
-+#endif
-+#ifdef USE_M17N
-+ wc_ces name_charset = url_to_charset(NULL, &buf->currentURL,
-+ buf->document_charset);
-+#endif
-
- if (out_size == 0) {
- out_size = LINELEN;
-@@ -5523,16 +5506,17 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
- hseq = 0;
- id = NULL;
- if (parsedtag_get_value(tag, ATTR_NAME, &id)) {
-- id = url_quote_conv(id, buf->document_charset);
-+ id = url_quote_conv(id, name_charset);
- registerName(buf, id, currentLn(buf), pos);
- }
- if (parsedtag_get_value(tag, ATTR_HREF, &p))
-- p = url_quote_conv(remove_space(p),
-- buf->document_charset);
-+ p = url_encode(remove_space(p), base,
-+ buf->document_charset);
- if (parsedtag_get_value(tag, ATTR_TARGET, &q))
- q = url_quote_conv(q, buf->document_charset);
- if (parsedtag_get_value(tag, ATTR_REFERER, &r))
-- r = url_quote_conv(r, buf->document_charset);
-+ r = url_encode(r, base,
-+ buf->document_charset);
- parsedtag_get_value(tag, ATTR_TITLE, &s);
- parsedtag_get_value(tag, ATTR_ACCESSKEY, &t);
- parsedtag_get_value(tag, ATTR_HSEQ, &hseq);
-@@ -5618,7 +5602,7 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
- ParsedURL u;
- Image *image;
-
-- parseURL2(a_img->url, &u, cur_baseURL);
-+ parseURL2(a_img->url, &u, base);
- a_img->image = image = New(Image);
- image->url = parsedURL2Str(&u)->ptr;
- if (!uncompressed_file_type(u.file, &image->ext))
-@@ -5639,7 +5623,7 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
- image->map = q;
- image->ismap = ismap;
- image->touch = 0;
-- image->cache = getImage(image, cur_baseURL,
-+ image->cache = getImage(image, base,
- IMG_FLAG_SKIP);
- }
- else if (iseq < 0) {
-@@ -5761,8 +5745,8 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
- break;
- if (parsedtag_get_value(tag, ATTR_HREF, &p)) {
- MapArea *a;
-- p = url_quote_conv(remove_space(p),
-- buf->document_charset);
-+ p = url_encode(remove_space(p), base,
-+ buf->document_charset);
- t = NULL;
- parsedtag_get_value(tag, ATTR_TARGET, &t);
- q = "";
-@@ -5811,11 +5795,14 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
- break;
- case HTML_BASE:
- if (parsedtag_get_value(tag, ATTR_HREF, &p)) {
-- p = url_quote_conv(remove_space(p),
-- buf->document_charset);
-+ p = url_encode(remove_space(p), NULL,
-+ buf->document_charset);
- if (!buf->baseURL)
- buf->baseURL = New(ParsedURL);
- parseURL(p, buf->baseURL, NULL);
-+#if defined(USE_M17N) || defined(USE_IMAGE)
-+ base = buf->baseURL;
-+#endif
- }
- if (parsedtag_get_value(tag, ATTR_TARGET, &p))
- buf->baseTarget =
-@@ -5830,8 +5817,8 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
- int refresh_interval = getMetaRefreshParam(q, &tmp);
- #ifdef USE_ALARM
- if (tmp) {
-- p = url_quote_conv(remove_space(tmp->ptr),
-- buf->document_charset);
-+ p = url_encode(remove_space(tmp->ptr), base,
-+ buf->document_charset);
- buf->event = setAlarmEvent(buf->event,
- refresh_interval,
- AL_IMPLICIT_ONCE,
-@@ -5844,8 +5831,8 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
- FUNCNAME_reload, NULL);
- #else
- if (tmp && refresh_interval == 0) {
-- p = url_quote_conv(remove_space(tmp->ptr),
-- buf->document_charset);
-+ p = url_encode(remove_space(tmp->ptr), base,
-+ buf->document_charset);
- pushEvent(FUNCNAME_gorURL, p);
- }
- #endif
-@@ -5929,7 +5916,7 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit)
- #ifdef ID_EXT
- id = NULL;
- if (parsedtag_get_value(tag, ATTR_ID, &id)) {
-- id = url_quote_conv(id, buf->document_charset);
-+ id = url_quote_conv(id, name_charset);
- registerName(buf, id, currentLn(buf), pos);
- }
- if (renderFrameSet &&
-@@ -5982,7 +5969,8 @@ addLink(Buffer *buf, struct parsed_tag *tag)
-
- parsedtag_get_value(tag, ATTR_HREF, &href);
- if (href)
-- href = url_quote_conv(remove_space(href), buf->document_charset);
-+ href = url_encode(remove_space(href), baseURL(buf),
-+ buf->document_charset);
- parsedtag_get_value(tag, ATTR_TITLE, &title);
- parsedtag_get_value(tag, ATTR_TYPE, &ctype);
- parsedtag_get_value(tag, ATTR_REL, &rel);
-@@ -6963,8 +6951,6 @@ loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src, int internal)
- image_flag = IMG_FLAG_AUTO;
- else
- image_flag = IMG_FLAG_SKIP;
-- if (newBuf->currentURL.file)
-- cur_baseURL = baseURL(newBuf);
- #endif
-
- if (w3m_halfload) {
-@@ -6987,6 +6973,9 @@ loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src, int internal)
- htmlenv1.f = stdout;
- else
- htmlenv1.buf = newTextLineList();
-+#if defined(USE_M17N) || defined(USE_IMAGE)
-+ cur_baseURL = baseURL(newBuf);
-+#endif
-
- if (SETJMP(AbortLoading) != 0) {
- HTMLlineproc1("<br>Transfer Interrupted!<br>", &htmlenv1);
-@@ -7048,7 +7037,7 @@ loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src, int internal)
- }
- #endif
- lineBuf2 = convertLine(f, lineBuf2, HTML_MODE, &charset, doc_charset);
--#if defined(USE_M17N) && defined(USE_IMAGE)
-+#ifdef USE_M17N
- cur_document_charset = charset;
- #endif
- HTMLlineproc0(lineBuf2->ptr, &htmlenv1, internal);
-@@ -7060,6 +7049,12 @@ loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src, int internal)
- obuf.status = R_ST_NORMAL;
- completeHTMLstream(&htmlenv1, &obuf);
- flushline(&htmlenv1, &obuf, 0, 2, htmlenv1.limit);
-+#if defined(USE_M17N) || defined(USE_IMAGE)
-+ cur_baseURL = NULL;
-+#endif
-+#ifdef USE_M17N
-+ cur_document_charset = 0;
-+#endif
- if (htmlenv1.title)
- newBuf->buffername = htmlenv1.title;
- if (w3m_halfdump) {
-@@ -7207,7 +7202,7 @@ loadGopherDir(URLFile *uf, ParsedURL *pu, wc_ces * charset)
- q = Strnew_m_charp("gopher://", host->ptr, ":", port->ptr,
- "/", file->ptr, NULL)->ptr;
- Strcat_m_charp(tmp, "<a href=\"",
-- html_quote(url_quote_conv(q, *charset)),
-+ html_quote(url_encode(q, NULL, *charset)),
- "\">", p, html_quote(name->ptr + 1), "</a>\n", NULL);
- }
-
-@@ -7331,6 +7326,7 @@ loadImageBuffer(URLFile *uf, Buffer *newBuf)
- URLFile f;
- MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL;
- struct stat st;
-+ const ParsedURL *pu = newBuf ? &newBuf->currentURL : NULL;
-
- loadImage(newBuf, IMG_FLAG_STOP);
- image.url = uf->url;
-@@ -7338,8 +7334,8 @@ loadImageBuffer(URLFile *uf, Buffer *newBuf)
- image.width = -1;
- image.height = -1;
- image.cache = NULL;
-- cache = getImage(&image, cur_baseURL, IMG_FLAG_AUTO);
-- if (!cur_baseURL->is_nocache && cache->loaded & IMG_FLAG_LOADED &&
-+ cache = getImage(&image, (ParsedURL *)pu, IMG_FLAG_AUTO);
-+ if (!(pu && pu->is_nocache) && cache->loaded & IMG_FLAG_LOADED &&
- !stat(cache->file, &st))
- goto image_buffer;
-
-@@ -7580,8 +7576,11 @@ openGeneralPagerBuffer(InputStream stream)
- #ifdef USE_M17N
- content_charset = 0;
- #endif
-+ t_buf = newBuffer(INIT_BUFFER_WIDTH);
-+ copyParsedURL(&t_buf->currentURL, NULL);
-+ t_buf->currentURL.scheme = SCM_LOCAL;
-+ t_buf->currentURL.file = "-";
- if (SearchHeader) {
-- t_buf = newBuffer(INIT_BUFFER_WIDTH);
- readHeader(&uf, t_buf, TRUE, NULL);
- t = checkContentType(t_buf);
- if (t == NULL)
-@@ -7609,14 +7608,13 @@ openGeneralPagerBuffer(InputStream stream)
- #ifdef USE_IMAGE
- else if (activeImage && displayImage && !useExtImageViewer &&
- !(w3m_dump & ~DUMP_FRAME) && !strncasecmp(t, "image/", 6)) {
-- cur_baseURL = New(ParsedURL);
-- parseURL("-", cur_baseURL, NULL);
- buf = loadImageBuffer(&uf, t_buf);
- buf->type = "text/html";
- }
- #endif
- else {
-- if (doExternal(uf, "-", t, &buf, t_buf)) {
-+ if (searchExtViewer(t)) {
-+ buf = doExternal(uf, t, t_buf);
- UFclose(&uf);
- if (buf == NULL || buf == NO_BUFFER)
- return buf;
-@@ -7629,8 +7627,6 @@ openGeneralPagerBuffer(InputStream stream)
- }
- }
- buf->real_type = t;
-- buf->currentURL.scheme = SCM_LOCAL;
-- buf->currentURL.file = "-";
- return buf;
- }
-
-@@ -7823,9 +7819,8 @@ save2tmp(URLFile uf, char *tmpf)
- return 0;
- }
-
--int
--doExternal(URLFile uf, char *path, char *type, Buffer **bufp,
-- Buffer *defaultbuf)
-+Buffer *
-+doExternal(URLFile uf, char *type, Buffer *defaultbuf)
- {
- Str tmpf, command;
- struct mailcap *mcap;
-@@ -7834,7 +7829,7 @@ doExternal(URLFile uf, char *path, char *type, Buffer **bufp,
- char *header, *src = NULL, *ext = uf.ext;
-
- if (!(mcap = searchExtViewer(type)))
-- return 0;
-+ return NULL;
-
- if (mcap->nametemplate) {
- tmpf = unquote_mailcap(mcap->nametemplate, NULL, "", NULL, NULL);
-@@ -7867,15 +7862,13 @@ doExternal(URLFile uf, char *path, char *type, Buffer **bufp,
- UFclose(&uf);
- myExec(command->ptr);
- }
-- *bufp = NO_BUFFER;
-- return 1;
-+ return NO_BUFFER;
- }
- else
- #endif
- {
- if (save2tmp(uf, tmpf->ptr) < 0) {
-- *bufp = NULL;
-- return 1;
-+ return NULL;
- }
- }
- if (mcap->flags & (MAILCAP_HTMLOUTPUT | MAILCAP_COPIOUSOUTPUT)) {
-@@ -7918,14 +7911,13 @@ doExternal(URLFile uf, char *path, char *type, Buffer **bufp,
- buf = NO_BUFFER;
- }
- if (buf && buf != NO_BUFFER) {
-- buf->filename = path;
-- if (buf->buffername == NULL || buf->buffername[0] == '\0')
-- buf->buffername = conv_from_system(lastFileName(path));
-+ if ((buf->buffername == NULL || buf->buffername[0] == '\0') &&
-+ buf->filename)
-+ buf->buffername = conv_from_system(lastFileName(buf->filename));
- buf->edit = mcap->edit;
- buf->mailcap = mcap;
- }
-- *bufp = buf;
-- return 1;
-+ return buf;
- }
-
- static int
-diff --git a/fm.h b/fm.h
-index 8378939..0f56c31 100644
---- a/fm.h
-+++ b/fm.h
-@@ -264,6 +264,18 @@ extern int REV_LB[];
- #define IMG_FLAG_ERROR 2
- #define IMG_FLAG_DONT_REMOVE 4
-
-+#define IS_EMPTY_PARSED_URL(pu) ((pu)->scheme == SCM_UNKNOWN && !(pu)->file)
-+#define SCONF_RESERVED 0
-+#define SCONF_SUBSTITUTE_URL 1
-+#define SCONF_URL_CHARSET 2
-+#define SCONF_NO_REFERER_FROM 3
-+#define SCONF_NO_REFERER_TO 4
-+#define SCONF_N_FIELD 5
-+#define query_SCONF_SUBSTITUTE_URL(pu) ((const char *)querySiteconf(pu, SCONF_SUBSTITUTE_URL))
-+#define query_SCONF_URL_CHARSET(pu) ((const wc_ces *)querySiteconf(pu, SCONF_URL_CHARSET))
-+#define query_SCONF_NO_REFERER_FROM(pu) ((const int *)querySiteconf(pu, SCONF_NO_REFERER_FROM))
-+#define query_SCONF_NO_REFERER_TO(pu) ((const int *)querySiteconf(pu, SCONF_NO_REFERER_TO))
-+
- /*
- * Macros.
- */
-@@ -972,6 +984,7 @@ global int BackgroundExtViewer init(TRUE);
- global int disable_secret_security_check init(FALSE);
- global char *passwd_file init(PASSWD_FILE);
- global char *pre_form_file init(PRE_FORM_FILE);
-+global char *siteconf_file init(SITECONF_FILE);
- global char *ftppasswd init(NULL);
- global int ftppass_hostnamegen init(TRUE);
- global int do_download init(FALSE);
-diff --git a/form.c b/form.c
-index b7556ca..fa17be4 100644
---- a/form.c
-+++ b/form.c
-@@ -787,7 +787,7 @@ struct pre_form {
- static struct pre_form *PreForm = NULL;
-
- static struct pre_form *
--add_pre_form(struct pre_form *prev, char *url, char *name, char *action)
-+add_pre_form(struct pre_form *prev, char *url, Regex *re_url, char *name, char *action)
- {
- ParsedURL pu;
- struct pre_form *new;
-@@ -796,21 +796,13 @@ add_pre_form(struct pre_form *prev, char *url, char *name, char *action)
- new = prev->next = New(struct pre_form);
- else
- new = PreForm = New(struct pre_form);
-- if (url && *url == '/') {
-- int l = strlen(url);
-- if (l > 1 && url[l - 1] == '/')
-- new->url = allocStr(url + 1, l - 2);
-- else
-- new->url = url + 1;
-- new->re_url = newRegex(new->url, FALSE, NULL, NULL);
-- if (!new->re_url)
-- new->url = NULL;
-- }
-- else if (url) {
-+ if (url && !re_url) {
- parseURL2(url, &pu, NULL);
- new->url = parsedURL2Str(&pu)->ptr;
-- new->re_url = NULL;
- }
-+ else
-+ new->url = url;
-+ new->re_url = re_url;
- new->name = (name && *name) ? name : NULL;
- new->action = (action && *action) ? action : NULL;
- new->item = NULL;
-@@ -834,7 +826,7 @@ add_pre_form_item(struct pre_form *pf, struct pre_form_item *prev, int type,
- new->name = name;
- new->value = value;
- if (checked && *checked && (!strcmp(checked, "0") ||
-- strcasecmp(checked, "off")
-+ !strcasecmp(checked, "off")
- || !strcasecmp(checked, "no")))
- new->checked = 0;
- else
-@@ -875,6 +867,7 @@ loadPreForm(void)
- return;
- while (1) {
- char *p, *s, *arg;
-+ Regex *re_arg;
-
- line = Strfgets(fp);
- if (line->length == 0)
-@@ -890,18 +883,20 @@ loadPreForm(void)
- if (*p == '#' || *p == '\0')
- continue; /* comment or empty line */
- s = getWord(&p);
-- arg = getWord(&p);
-
- if (!strcmp(s, "url")) {
-+ arg = getRegexWord((const char **)&p, &re_arg);
- if (!arg || !*arg)
- continue;
- p = getQWord(&p);
-- pf = add_pre_form(pf, arg, NULL, p);
-+ pf = add_pre_form(pf, arg, re_arg, NULL, p);
- pi = pf->item;
- continue;
- }
- if (!pf)
- continue;
-+
-+ arg = getWord(&p);
- if (!strcmp(s, "form")) {
- if (!arg || !*arg)
- continue;
-@@ -913,7 +908,7 @@ loadPreForm(void)
- }
- if (pf->item) {
- struct pre_form *prev = pf;
-- pf = add_pre_form(prev, "", s, p);
-+ pf = add_pre_form(prev, "", NULL, s, p);
- /* copy previous URL */
- pf->url = prev->url;
- pf->re_url = prev->re_url;
-diff --git a/frame.c b/frame.c
-index b431437..48c2d72 100644
---- a/frame.c
-+++ b/frame.c
-@@ -91,7 +91,8 @@ newFrame(struct parsed_tag *tag, Buffer *buf)
- body->baseURL = baseURL(buf);
- if (tag) {
- if (parsedtag_get_value(tag, ATTR_SRC, &p))
-- body->url = url_quote_conv(remove_space(p), buf->document_charset);
-+ body->url = url_encode(remove_space(p), body->baseURL,
-+ buf->document_charset);
- if (parsedtag_get_value(tag, ATTR_NAME, &p) && *p != '_')
- body->name = url_quote_conv(p, buf->document_charset);
- }
-@@ -639,7 +640,7 @@ createFrameFile(struct frameset *f, FILE * f1, Buffer *current, int level,
- case HTML_BASE:
- /* "BASE" is prohibit tag */
- if (parsedtag_get_value(tag, ATTR_HREF, &q)) {
-- q = url_quote_conv(remove_space(q), charset);
-+ q = url_encode(remove_space(q), NULL, charset);
- parseURL(q, &base, NULL);
- }
- if (parsedtag_get_value(tag, ATTR_TARGET, &q)) {
-@@ -768,8 +769,8 @@ createFrameFile(struct frameset *f, FILE * f1, Buffer *current, int level,
- if (!tag->value[j])
- break;
- tag->value[j] =
-- url_quote_conv(remove_space(tag->value[j]),
-- charset);
-+ url_encode(remove_space(tag->value[j]),
-+ &base, charset);
- tag->need_reconstruct = TRUE;
- parseURL2(tag->value[j], &url, &base);
- if (url.scheme == SCM_UNKNOWN ||
-diff --git a/func.c b/func.c
-index f389e00..8b5deac 100644
---- a/func.c
-+++ b/func.c
-@@ -8,6 +8,7 @@
- #include "fm.h"
- #include "func.h"
- #include "myctype.h"
-+#include "regex.h"
-
- #include "funcname.c"
- #include "functable.c"
-@@ -434,6 +435,93 @@ getQWord(char **str)
- return tmp->ptr;
- }
-
-+/* This extracts /regex/i or m@regex@i from the given string.
-+ * Then advances *str to the end of regex.
-+ * If the input does not seems to be a regex, this falls back to getQWord().
-+ *
-+ * Returns a word (no matter whether regex or not) in the give string.
-+ * If regex_ret is non-NULL, compiles the regex and stores there.
-+ *
-+ * XXX: Actually this is unrelated to func.c.
-+ */
-+char *
-+getRegexWord(const char **str, Regex **regex_ret)
-+{
-+ char *word = NULL;
-+ const char *p, *headp, *bodyp, *tailp;
-+ char delimiter;
-+ int esc;
-+ int igncase = 0;
-+
-+ p = *str;
-+ SKIP_BLANKS(p);
-+ headp = p;
-+
-+ /* Get the opening delimiter */
-+ if (p[0] == 'm' && IS_PRINT(p[1]) && !IS_ALNUM(p[1]) && p[1] != '\\') {
-+ delimiter = p[1];
-+ p += 2;
-+ }
-+ else if (p[0] == '/') {
-+ delimiter = '/';
-+ p += 1;
-+ }
-+ else {
-+ goto not_regex;
-+ }
-+ bodyp = p;
-+
-+ /* Scan the end of the expression */
-+ for (esc = 0; *p; ++p) {
-+ if (esc) {
-+ esc = 0;
-+ } else {
-+ if (*p == delimiter)
-+ break;
-+ else if (*p == '\\')
-+ esc = 1;
-+ }
-+ }
-+ if (!*p && *headp == '/')
-+ goto not_regex;
-+ tailp = p;
-+
-+ /* Check the modifiers */
-+ if (*p == delimiter) {
-+ while (*++p && !IS_SPACE(*p)) {
-+ switch (*p) {
-+ case 'i':
-+ igncase = 1;
-+ break;
-+ }
-+ /* ignore unknown modifiers */
-+ }
-+ }
-+
-+ /* Save the expression */
-+ word = allocStr(headp, p - headp);
-+
-+ /* Compile */
-+ if (regex_ret) {
-+ if (*tailp == delimiter)
-+ word[tailp - headp] = 0;
-+ *regex_ret = newRegex(word + (bodyp - headp), igncase, NULL, NULL);
-+ if (*tailp == delimiter)
-+ word[tailp - headp] = delimiter;
-+ }
-+ goto last;
-+
-+not_regex:
-+ p = headp;
-+ word = getQWord((char **)&p);
-+ if (regex_ret)
-+ *regex_ret = NULL;
-+
-+last:
-+ *str = p;
-+ return word;
-+}
-+
- #ifdef USE_MOUSE
- static MouseAction default_mouse_action = {
- NULL,
-diff --git a/history.c b/history.c
-index 951ef83..e9be09b 100644
---- a/history.c
-+++ b/history.c
-@@ -17,7 +17,7 @@ historyBuffer(Hist *hist)
- for (item = hist->list->last; item; item = item->prev) {
- q = html_quote((char *)item->ptr);
- if (DecodeURL)
-- p = html_quote(url_unquote_conv((char *)item->ptr, 0));
-+ p = html_quote(url_decode2((char *)item->ptr, NULL));
- else
- p = q;
- Strcat_charp(src, "<li><a href=\"");
-diff --git a/indep.c b/indep.c
-index 65b04aa..89e86c1 100644
---- a/indep.c
-+++ b/indep.c
-@@ -357,6 +357,20 @@ strcasemstr(char *str, char *srch[], char **ret_ptr)
- return -1;
- }
-
-+int
-+strmatchlen(const char *s1, const char *s2, int maxlen)
-+{
-+ int i;
-+
-+ /* To allow the maxlen to be negatie (infinity),
-+ * compare by "!=" instead of "<=". */
-+ for (i = 0; i != maxlen; ++i) {
-+ if (!s1[i] || !s2[i] || s1[i] != s2[i])
-+ break;
-+ }
-+ return i;
-+}
-+
- char *
- remove_space(char *str)
- {
-diff --git a/indep.h b/indep.h
-index b3819a3..cf566fe 100644
---- a/indep.h
-+++ b/indep.h
-@@ -52,6 +52,7 @@ extern int strncasecmp(const char *s1, const char *s2, size_t n);
- extern char *strcasestr(const char *s1, const char *s2);
- #endif
- extern int strcasemstr(char *str, char *srch[], char **ret_ptr);
-+int strmatchlen(const char *s1, const char *s2, int maxlen);
- extern char *remove_space(char *str);
- extern int non_null(char *s);
- extern void cleanup_line(Str s, int mode);
-diff --git a/linein.c b/linein.c
-index b7e81b6..572b015 100644
---- a/linein.c
-+++ b/linein.c
-@@ -1026,7 +1026,7 @@ _prev(void)
- strCurrentBuf = strBuf;
- }
- if (DecodeURL && (cm_mode & CPL_URL) )
-- p = url_unquote_conv(p, 0);
-+ p = url_decode2(p, NULL);
- strBuf = Strnew_charp(p);
- CLen = CPos = setStrType(strBuf, strProp);
- offset = 0;
-@@ -1045,7 +1045,7 @@ _next(void)
- p = nextHist(hist);
- if (p) {
- if (DecodeURL && (cm_mode & CPL_URL) )
-- p = url_unquote_conv(p, 0);
-+ p = url_decode2(p, NULL);
- strBuf = Strnew_charp(p);
- }
- else {
-diff --git a/main.c b/main.c
-index b421943..a414391 100644
---- a/main.c
-+++ b/main.c
-@@ -894,12 +894,17 @@ main(int argc, char **argv, char **envp)
- if (i >= 0) {
- SearchHeader = search_header;
- DefaultType = default_type;
-+ char *url;
-+
-+ url = load_argv[i];
-+ if (getURLScheme(&url) == SCM_MISSING && !ArgvIsURL)
-+ url = file_to_url(load_argv[i]);
-+ else
-+ url = url_encode(conv_from_system(load_argv[i]), NULL, 0);
- if (w3m_dump == DUMP_HEAD) {
- request = New(FormList);
- request->method = FORM_METHOD_HEAD;
-- newbuf =
-- loadGeneralFile(load_argv[i], NULL, NO_REFERER, 0,
-- request);
-+ newbuf = loadGeneralFile(url, NULL, NO_REFERER, 0, request);
- }
- else {
- if (post_file && i == 0) {
-@@ -928,9 +933,7 @@ main(int argc, char **argv, char **envp)
- else {
- request = NULL;
- }
-- newbuf =
-- loadGeneralFile(load_argv[i], NULL, NO_REFERER, 0,
-- request);
-+ newbuf = loadGeneralFile(url, NULL, NO_REFERER, 0, request);
- }
- if (newbuf == NULL) {
- /* FIXME: gettextize? */
-@@ -945,7 +948,7 @@ main(int argc, char **argv, char **envp)
- break;
- case SCM_LOCAL:
- case SCM_LOCAL_CGI:
-- unshiftHist(LoadHist, conv_from_system(load_argv[i]));
-+ unshiftHist(LoadHist, url);
- default:
- pushHashHist(URLHist, parsedURL2Str(&newbuf->currentURL)->ptr);
- break;
-@@ -1269,15 +1272,12 @@ do_dump(Buffer *buf)
- printf("\nReferences:\n\n");
- for (i = 0; i < buf->href->nanchor; i++) {
- ParsedURL pu;
-- static Str s = NULL;
-+ char *url;
- if (buf->href->anchors[i].slave)
- continue;
- parseURL2(buf->href->anchors[i].url, &pu, baseURL(buf));
-- s = parsedURL2Str(&pu);
-- if (DecodeURL)
-- s = Strnew_charp(url_unquote_conv
-- (s->ptr, Currentbuf->document_charset));
-- printf("[%d] %s\n", buf->href->anchors[i].hseq + 1, s->ptr);
-+ url = url_decode2(parsedURL2Str(&pu)->ptr, Currentbuf);
-+ printf("[%d] %s\n", buf->href->anchors[i].hseq + 1, url);
- }
- }
- }
-@@ -2261,7 +2261,7 @@ DEFUN(movR1, MOVE_RIGHT1,
- static wc_uint32
- getChar(char *p)
- {
-- return wc_any_to_ucs(wtf_parse1(&p));
-+ return wc_any_to_ucs(wtf_parse1((wc_uchar **)&p));
- }
-
- static int
-@@ -2804,12 +2804,15 @@ loadLink(char *url, char *target, char *referer, FormList *request)
- union frameset_element *f_element = NULL;
- int flag = 0;
- ParsedURL *base, pu;
-+ const int *no_referer_ptr;
-
- message(Sprintf("loading %s", url)->ptr, 0, 0);
- refresh();
-
-+ no_referer_ptr = query_SCONF_NO_REFERER_FROM(&Currentbuf->currentURL);
- base = baseURL(Currentbuf);
-- if (base == NULL ||
-+ if ((no_referer_ptr && *no_referer_ptr) ||
-+ base == NULL ||
- base->scheme == SCM_LOCAL || base->scheme == SCM_LOCAL_CGI)
- referer = NO_REFERER;
- if (referer == NULL)
-@@ -4055,6 +4058,7 @@ goURL0(char *prompt, int relative)
- char *url, *referer;
- ParsedURL p_url, *current;
- Buffer *cur_buf = Currentbuf;
-+ const int *no_referer_ptr;
-
- url = searchKeyData();
- if (url == NULL) {
-@@ -4064,11 +4068,8 @@ goURL0(char *prompt, int relative)
- current = baseURL(Currentbuf);
- if (current) {
- char *c_url = parsedURL2Str(current)->ptr;
-- if (DefaultURLString == DEFAULT_URL_CURRENT) {
-- url = c_url;
-- if (DecodeURL)
-- url = url_unquote_conv(url, 0);
-- }
-+ if (DefaultURLString == DEFAULT_URL_CURRENT)
-+ url = url_decode2(c_url, NULL);
- else
- pushHist(hist, c_url);
- }
-@@ -4077,11 +4078,8 @@ goURL0(char *prompt, int relative)
- char *a_url;
- parseURL2(a->url, &p_url, current);
- a_url = parsedURL2Str(&p_url)->ptr;
-- if (DefaultURLString == DEFAULT_URL_LINK) {
-- url = a_url;
-- if (DecodeURL)
-- url = url_unquote_conv(url, Currentbuf->document_charset);
-- }
-+ if (DefaultURLString == DEFAULT_URL_LINK)
-+ url = url_decode2(a_url, Currentbuf);
- else
- pushHist(hist, a_url);
- }
-@@ -4089,15 +4087,22 @@ goURL0(char *prompt, int relative)
- if (url != NULL)
- SKIP_BLANKS(url);
- }
--#ifdef USE_M17N
-- if (url != NULL) {
-- if ((relative || *url == '#') && Currentbuf->document_charset)
-- url = wc_conv_strict(url, InnerCharset,
-- Currentbuf->document_charset)->ptr;
-+ if (relative) {
-+ no_referer_ptr = query_SCONF_NO_REFERER_FROM(&Currentbuf->currentURL);
-+ current = baseURL(Currentbuf);
-+ if ((no_referer_ptr && *no_referer_ptr) ||
-+ current == NULL ||
-+ current->scheme == SCM_LOCAL || current->scheme == SCM_LOCAL_CGI)
-+ referer = NO_REFERER;
- else
-- url = conv_to_system(url);
-+ referer = parsedURL2Str(&Currentbuf->currentURL)->ptr;
-+ url = url_encode(url, current, Currentbuf->document_charset);
-+ }
-+ else {
-+ current = NULL;
-+ referer = NULL;
-+ url = url_encode(url, NULL, 0);
- }
--#endif
- if (url == NULL || *url == '\0') {
- displayBuffer(Currentbuf, B_FORCE_REDRAW);
- return;
-@@ -4106,14 +4111,6 @@ goURL0(char *prompt, int relative)
- gotoLabel(url + 1);
- return;
- }
-- if (relative) {
-- current = baseURL(Currentbuf);
-- referer = parsedURL2Str(&Currentbuf->currentURL)->ptr;
-- }
-- else {
-- current = NULL;
-- referer = NULL;
-- }
- parseURL2(url, &p_url, current);
- pushHashHist(URLHist, parsedURL2Str(&p_url)->ptr);
- cmd_loadURL(url, current, referer, NULL);
-@@ -4510,8 +4507,7 @@ _peekURL(int only_img)
- s = parsedURL2Str(&pu);
- }
- if (DecodeURL)
-- s = Strnew_charp(url_unquote_conv
-- (s->ptr, Currentbuf->document_charset));
-+ s = Strnew_charp(url_decode2(s->ptr, Currentbuf));
- #ifdef USE_M17N
- s = checkType(s, &pp, NULL);
- p = NewAtom_N(Lineprop, s->length);
-@@ -4570,7 +4566,7 @@ DEFUN(curURL, PEEK, "Peek current URL")
- offset = 0;
- s = currentURL();
- if (DecodeURL)
-- s = Strnew_charp(url_unquote_conv(s->ptr, 0));
-+ s = Strnew_charp(url_decode2(s->ptr, NULL));
- #ifdef USE_M17N
- s = checkType(s, &pp, NULL);
- p = NewAtom_N(Lineprop, s->length);
-diff --git a/map.c b/map.c
-index 90aa35a..12701e7 100644
---- a/map.c
-+++ b/map.c
-@@ -279,7 +279,7 @@ follow_map_panel(Buffer *buf, char *name)
- p = parsedURL2Str(&pu)->ptr;
- q = html_quote(p);
- if (DecodeURL)
-- p = html_quote(url_unquote_conv(p, buf->document_charset));
-+ p = html_quote(url_decode2(p, buf));
- else
- p = q;
- Strcat_m_charp(mappage, "<tr valign=top><td><a href=\"", q, "\">",
-@@ -417,10 +417,7 @@ append_map_info(Buffer *buf, Str tmp, FormItemList *fi)
- continue;
- parseURL2(a->url, &pu, baseURL(buf));
- q = html_quote(parsedURL2Str(&pu)->ptr);
-- if (DecodeURL)
-- p = html_quote(url_unquote_conv(a->url, buf->document_charset));
-- else
-- p = html_quote(a->url);
-+ p = html_quote(url_decode2(a->url, buf));
- Strcat_m_charp(tmp, "<tr valign=top><td>&nbsp;&nbsp;<td><a href=\"",
- q, "\">",
- html_quote(*a->alt ? a->alt : mybasename(a->url)),
-@@ -457,10 +454,8 @@ append_link_info(Buffer *buf, Str html, LinkList * link)
- Strcat_charp(html, "[Rev]");
- if (!l->url)
- url = "(empty)";
-- else if (DecodeURL)
-- url = html_quote(url_unquote_conv(l->url, buf->document_charset));
- else
-- url = html_quote(l->url);
-+ url = html_quote(url_decode2(l->url, buf));
- Strcat_m_charp(html, "<td>", url, NULL);
- if (l->ctype)
- Strcat_m_charp(html, " (", html_quote(l->ctype), ")", NULL);
-@@ -498,8 +493,7 @@ append_frame_info(Buffer *buf, Str html, struct frameset *set, int level)
- Strcat_charp(html, p);
- }
- if (DecodeURL)
-- p = html_quote(url_unquote_conv(frame.body->url,
-- buf->document_charset));
-+ p = html_quote(url_decode2(frame.body->url, buf));
- else
- p = q;
- Strcat_m_charp(html, " ", p, "</a></pre_int><br>\n", NULL);
-@@ -550,9 +544,7 @@ page_info_panel(Buffer *buf)
- #ifdef USE_M17N
- Strcat_charp(tmp, "<form method=internal action=charset>");
- #endif
-- p = parsedURL2Str(&buf->currentURL)->ptr;
-- if (DecodeURL)
-- p = url_unquote_conv(p, 0);
-+ p = url_decode2(parsedURL2Str(&buf->currentURL)->ptr, NULL);
- Strcat_m_charp(tmp, "<table cellpadding=0>",
- "<tr valign=top><td nowrap>Title<td>",
- html_quote(buf->buffername),
-@@ -589,7 +581,7 @@ page_info_panel(Buffer *buf)
- p = parsedURL2Str(&pu)->ptr;
- q = html_quote(p);
- if (DecodeURL)
-- p = html_quote(url_unquote_conv(p, buf->document_charset));
-+ p = html_quote(url_decode2(p, buf));
- else
- p = q;
- Strcat_m_charp(tmp,
-@@ -602,7 +594,7 @@ page_info_panel(Buffer *buf)
- p = parsedURL2Str(&pu)->ptr;
- q = html_quote(p);
- if (DecodeURL)
-- p = html_quote(url_unquote_conv(p, buf->document_charset));
-+ p = html_quote(url_decode2(p, buf));
- else
- p = q;
- Strcat_m_charp(tmp,
-@@ -613,10 +605,7 @@ page_info_panel(Buffer *buf)
- if (a != NULL) {
- FormItemList *fi = (FormItemList *)a->url;
- p = form2str(fi);
-- if (DecodeURL)
-- p = html_quote(url_unquote_conv(p, buf->document_charset));
-- else
-- p = html_quote(p);
-+ p = html_quote(url_decode2(p, buf));
- Strcat_m_charp(tmp,
- "<tr valign=top><td nowrap>Method/type of current form&nbsp;<td>",
- p, NULL);
-diff --git a/menu.c b/menu.c
-index 774b1bd..0f66583 100644
---- a/menu.c
-+++ b/menu.c
-@@ -1365,9 +1365,7 @@ initSelectMenu(void)
- break;
- default:
- Strcat_char(str, ' ');
-- p = parsedURL2Str(&buf->currentURL)->ptr;
-- if (DecodeURL)
-- p = url_unquote_conv(p, 0);
-+ p = url_decode2(parsedURL2Str(&buf->currentURL)->ptr, NULL);
- Strcat_charp(str, p);
- break;
- }
-@@ -1513,9 +1511,7 @@ initSelTabMenu(void)
- case SCM_MISSING:
- break;
- default:
-- p = parsedURL2Str(&buf->currentURL)->ptr;
-- if (DecodeURL)
-- p = url_unquote_conv(p, 0);
-+ p = url_decode2(parsedURL2Str(&buf->currentURL)->ptr, NULL);
- Strcat_charp(str, p);
- break;
- }
-@@ -1845,10 +1841,8 @@ link_menu(Buffer *buf)
- Strcat_charp(str, " ");
- if (!l->url)
- p = "";
-- else if (DecodeURL)
-- p = url_unquote_conv(l->url, buf->document_charset);
- else
-- p = l->url;
-+ p = url_decode2(l->url, buf);
- Strcat_charp(str, p);
- label[i] = str->ptr;
- if (len < str->length)
-diff --git a/po/ja.po b/po/ja.po
-index d67c695..947191c 100644
---- a/po/ja.po
-+++ b/po/ja.po
-@@ -407,6 +407,10 @@ msgid "File for setting form on loading"
- msgstr "梧莨惹若荐絎<ゃ"
-
- #: rc.c:149
-+msgid "File for preferences for each site"
-+msgstr "泣ゃヨ┃絎<ゃ"
-+
-+#: rc.c:149
- msgid "Password for anonymous FTP (your mail address)"
- msgstr "FTP鴻若(mail address篏帥)"
-
-diff --git a/proto.h b/proto.h
-index f8a7345..7b1a7a6 100644
---- a/proto.h
-+++ b/proto.h
-@@ -162,6 +162,24 @@ extern Str searchURIMethods(ParsedURL *pu);
- extern void chkExternalURIBuffer(Buffer *buf);
- #endif
- extern ParsedURL *schemeToProxy(int scheme);
-+#ifdef USE_M17N
-+extern wc_ces url_to_charset(const char *url, const ParsedURL *base,
-+ wc_ces doc_charset);
-+extern char *url_encode(const char *url, const ParsedURL *base,
-+ wc_ces doc_charset);
-+#if 0
-+extern char *url_decode(const char *url, const ParsedURL *base,
-+ wc_ces doc_charset);
-+#endif
-+extern char *url_decode2(const char *url, const Buffer *buf);
-+#else /* !defined(USE_M17N) */
-+#define url_encode(url, base, cs) url_quote(url)
-+extern char *url_decode0(const char *url);
-+#if 0
-+#define url_decode(url, base, cs) url_decode0(url)
-+#endif
-+#define url_decode2(url, buf) url_decode0(url)
-+#endif /* !defined(USE_M17N) */
- extern void examineFile(char *path, URLFile *uf);
- extern char *acceptableEncoding();
- extern int dir_exist(char *path);
-@@ -180,7 +198,6 @@ extern void push_symbol(Str str, char symbol, int width, int n);
- #ifdef USE_UNICODE
- extern void update_utf8_symbol(void);
- #endif
--extern Buffer *loadFile(char *path);
- extern Buffer *loadGeneralFile(char *path, ParsedURL *current, char *referer,
- int flag, FormList *request);
- extern int is_boundary(unsigned char *, unsigned char *);
-@@ -249,8 +266,7 @@ extern Buffer *openPagerBuffer(InputStream stream, Buffer *buf);
- extern Buffer *openGeneralPagerBuffer(InputStream stream);
- extern Line *getNextPage(Buffer *buf, int plen);
- extern int save2tmp(URLFile uf, char *tmpf);
--extern int doExternal(URLFile uf, char *path, char *type, Buffer **bufp,
-- Buffer *defaultbuf);
-+extern Buffer *doExternal(URLFile uf, char *type, Buffer *defaultbuf);
- extern int _doFileCopy(char *tmpf, char *defstr, int download);
- #define doFileCopy(tmpf, defstr) _doFileCopy(tmpf, defstr, FALSE);
- extern int doFileMove(char *tmpf, char *defstr);
-@@ -507,7 +523,7 @@ extern ParsedURL *baseURL(Buffer *buf);
- extern int openSocket(char *hostname, char *remoteport_name,
- unsigned short remoteport_num);
- extern void parseURL(char *url, ParsedURL *p_url, ParsedURL *current);
--extern void copyParsedURL(ParsedURL *p, ParsedURL *q);
-+extern void copyParsedURL(ParsedURL *p, const ParsedURL *q);
- extern void parseURL2(char *url, ParsedURL *pu, ParsedURL *current);
- extern Str parsedURL2Str(ParsedURL *pu);
- extern int getURLScheme(char **url);
-@@ -611,6 +627,7 @@ extern char *confFile(char *base);
- extern char *auxbinFile(char *base);
- extern char *libFile(char *base);
- extern char *helpFile(char *base);
-+extern const void *querySiteconf(const ParsedURL *query_pu, int field);
- extern Str localCookie(void);
- extern Str loadLocalDir(char *dirname);
- extern void set_environ(char *var, char *value);
-@@ -723,6 +740,8 @@ extern int getKey(char *s);
- extern char *getKeyData(int key);
- extern char *getWord(char **str);
- extern char *getQWord(char **str);
-+struct regex;
-+extern char *getRegexWord(const char **str, struct regex **regex_ret);
- #ifdef USE_MOUSE
- extern void initMouseAction(void);
- #endif
-diff --git a/rc.c b/rc.c
-index 8441a39..3bf6cea 100644
---- a/rc.c
-+++ b/rc.c
-@@ -9,7 +9,9 @@
- #include <errno.h>
- #include "parsetag.h"
- #include "local.h"
-+#include "regex.h"
- #include <stdlib.h>
-+#include <stddef.h>
-
- struct param_ptr {
- char *name;
-@@ -146,6 +148,7 @@ static int OptionEncode = FALSE;
- #define CMT_DISABLE_SECRET_SECURITY_CHECK N_("Disable secret file security check")
- #define CMT_PASSWDFILE N_("Password file")
- #define CMT_PRE_FORM_FILE N_("File for setting form on loading")
-+#define CMT_SITECONF_FILE N_("File for preferences for each site")
- #define CMT_FTPPASS N_("Password for anonymous FTP (your mail address)")
- #define CMT_FTPPASS_HOSTNAMEGEN N_("Generate domain part of password for FTP")
- #define CMT_USERAGENT N_("User-Agent identification string")
-@@ -619,6 +622,8 @@ struct param_ptr params9[] = {
- CMT_FTPPASS_HOSTNAMEGEN, NULL},
- {"pre_form_file", P_STRING, PI_TEXT, (void *)&pre_form_file,
- CMT_PRE_FORM_FILE, NULL},
-+ {"siteconf_file", P_STRING, PI_TEXT, (void *)&siteconf_file,
-+ CMT_SITECONF_FILE, NULL},
- {"user_agent", P_STRING, PI_TEXT, (void *)&UserAgent, CMT_USERAGENT, NULL},
- {"no_referer", P_INT, PI_ONOFF, (void *)&NoSendReferer, CMT_NOSENDREFERER,
- NULL},
-@@ -1173,6 +1178,8 @@ do_mkdir(const char *dir, long mode)
- #endif /* not __MINW32_VERSION */
- #endif /* not __EMX__ */
-
-+static void loadSiteconf(void);
-+
- void
- sync_with_option(void)
- {
-@@ -1199,6 +1206,7 @@ sync_with_option(void)
- #endif
- loadPasswd();
- loadPreForm();
-+ loadSiteconf();
-
- if (AcceptLang == NULL || *AcceptLang == '\0') {
- /* TRANSLATORS:
-@@ -1556,3 +1564,217 @@ helpFile(char *base)
- return expandPath(Strnew_m_charp(w3m_help_dir(), "/", base, NULL)->ptr);
- }
- #endif
-+
-+/* siteconf */
-+/*
-+ * url "<url>"|/<re-url>/|m@<re-url>@i [exact]
-+ * substitute_url "<destination-url>"
-+ * url_charset <charset>
-+ * no_referer_from on|off
-+ * no_referer_to on|off
-+ *
-+ * The last match wins.
-+ */
-+
-+struct siteconf_rec {
-+ struct siteconf_rec *next;
-+ char *url;
-+ Regex *re_url;
-+ int url_exact;
-+ unsigned char mask[(SCONF_N_FIELD + 7) >> 3];
-+
-+ char *substitute_url;
-+#ifdef USE_M17N
-+ wc_ces url_charset;
-+#endif
-+ int no_referer_from;
-+ int no_referer_to;
-+};
-+#define SCONF_TEST(ent, f) ((ent)->mask[(f)>>3] & (1U<<((f)&7)))
-+#define SCONF_SET(ent, f) ((ent)->mask[(f)>>3] |= (1U<<((f)&7)))
-+#define SCONF_CLEAR(ent, f) ((ent)->mask[(f)>>3] &= ~(1U<<((f)&7)))
-+
-+static struct siteconf_rec *siteconf_head = NULL;
-+static struct siteconf_rec *newSiteconfRec(void);
-+
-+static struct siteconf_rec *
-+newSiteconfRec(void)
-+{
-+ struct siteconf_rec *ent;
-+
-+ ent = New(struct siteconf_rec);
-+ ent->next = NULL;
-+ ent->url = NULL;
-+ ent->re_url = NULL;
-+ ent->url_exact = FALSE;
-+ memset(ent->mask, 0, sizeof(ent->mask));
-+
-+ ent->substitute_url = NULL;
-+#ifdef USE_M17N
-+ ent->url_charset = 0;
-+#endif
-+ return ent;
-+}
-+
-+static void
-+loadSiteconf(void)
-+{
-+ char *efname;
-+ FILE *fp;
-+ Str line;
-+ struct siteconf_rec *ent = NULL;
-+
-+ siteconf_head = NULL;
-+ if (!siteconf_file)
-+ return;
-+ if ((efname = expandPath(siteconf_file)) == NULL)
-+ return;
-+ fp = fopen(efname, "r");
-+ if (fp == NULL)
-+ return;
-+ while (line = Strfgets(fp), line->length > 0) {
-+ char *p, *s;
-+
-+ Strchop(line);
-+ p = line->ptr;
-+ SKIP_BLANKS(p);
-+ if (*p == '#' || *p == '\0')
-+ continue;
-+ s = getWord(&p);
-+
-+ /* The "url" begins a new record. */
-+ if (strcmp(s, "url") == 0) {
-+ char *url, *opt;
-+ struct siteconf_rec *newent;
-+
-+ /* First, register the current record. */
-+ if (ent) {
-+ ent->next = siteconf_head;
-+ siteconf_head = ent;
-+ ent = NULL;
-+ }
-+
-+ /* Second, create a new record. */
-+ newent = newSiteconfRec();
-+ url = getRegexWord((const char **)&p, &newent->re_url);
-+ opt = getWord(&p);
-+ SKIP_BLANKS(p);
-+ if (!newent->re_url) {
-+ ParsedURL pu;
-+ if (!url || !*url)
-+ continue;
-+ parseURL2(url, &pu, NULL);
-+ newent->url = parsedURL2Str(&pu)->ptr;
-+ }
-+ /* If we have an extra or unknown option, ignore this record
-+ * for future extensions. */
-+ if (strcmp(opt, "exact") == 0) {
-+ newent->url_exact = TRUE;
-+ }
-+ else if (*opt != 0)
-+ continue;
-+ if (*p)
-+ continue;
-+ ent = newent;
-+ continue;
-+ }
-+
-+ /* If the current record is broken, skip to the next "url". */
-+ if (!ent)
-+ continue;
-+
-+ /* Fill the new record. */
-+ if (strcmp(s, "substitute_url") == 0) {
-+ ent->substitute_url = getQWord(&p);
-+ SCONF_SET(ent, SCONF_SUBSTITUTE_URL);
-+ }
-+#ifdef USE_M17N
-+ else if (strcmp(s, "url_charset") == 0) {
-+ char *charset = getWord(&p);
-+ ent->url_charset = (charset && *charset) ?
-+ wc_charset_to_ces(charset) : 0;
-+ SCONF_SET(ent, SCONF_URL_CHARSET);
-+ }
-+#endif /* USE_M17N */
-+ else if (strcmp(s, "no_referer_from") == 0) {
-+ ent->no_referer_from = str_to_bool(getWord(&p), 0);
-+ SCONF_SET(ent, SCONF_NO_REFERER_FROM);
-+ }
-+ else if (strcmp(s, "no_referer_to") == 0) {
-+ ent->no_referer_to = str_to_bool(getWord(&p), 0);
-+ SCONF_SET(ent, SCONF_NO_REFERER_TO);
-+ }
-+ }
-+ if (ent) {
-+ ent->next = siteconf_head;
-+ siteconf_head = ent;
-+ ent = NULL;
-+ }
-+ fclose(fp);
-+}
-+
-+const void *
-+querySiteconf(const ParsedURL *query_pu, int field)
-+{
-+ const struct siteconf_rec *ent;
-+ Str u;
-+ char *firstp, *lastp;
-+
-+ if (field < 0 || field >= SCONF_N_FIELD)
-+ return NULL;
-+ if (!query_pu || IS_EMPTY_PARSED_URL(query_pu))
-+ return NULL;
-+ u = parsedURL2Str((ParsedURL *)query_pu);
-+ if (u->length == 0)
-+ return NULL;
-+
-+ for (ent = siteconf_head; ent; ent = ent->next) {
-+ if (!SCONF_TEST(ent, field))
-+ continue;
-+ if (ent->re_url) {
-+ if (RegexMatch(ent->re_url, u->ptr, u->length, 1)) {
-+ MatchedPosition(ent->re_url, &firstp, &lastp);
-+ if (!ent->url_exact)
-+ goto url_found;
-+ if (firstp != u->ptr || lastp == firstp)
-+ continue;
-+ if (*lastp == 0 || *lastp == '?' || *(lastp - 1) == '?' ||
-+ *lastp == '#' || *(lastp - 1) == '#')
-+ goto url_found;
-+ }
-+ } else {
-+ int matchlen = strmatchlen(ent->url, u->ptr, u->length);
-+ if (matchlen == 0 || ent->url[matchlen] != 0)
-+ continue;
-+ firstp = u->ptr;
-+ lastp = u->ptr + matchlen;
-+ if (*lastp == 0 || *lastp == '?' || *(lastp - 1) == '?' ||
-+ *lastp == '#' || *(lastp - 1) == '#')
-+ goto url_found;
-+ if (!ent->url_exact && (*lastp == '/' || *(lastp - 1) == '/'))
-+ goto url_found;
-+ }
-+ }
-+ return NULL;
-+
-+url_found:
-+ switch (field) {
-+ case SCONF_SUBSTITUTE_URL:
-+ if (ent->substitute_url && *ent->substitute_url) {
-+ Str tmp = Strnew_charp_n(u->ptr, firstp - u->ptr);
-+ Strcat_charp(tmp, ent->substitute_url);
-+ Strcat_charp(tmp, lastp);
-+ return tmp->ptr;
-+ }
-+ return NULL;
-+#ifdef USE_M17N
-+ case SCONF_URL_CHARSET:
-+ return &ent->url_charset;
-+#endif
-+ case SCONF_NO_REFERER_FROM:
-+ return &ent->no_referer_from;
-+ case SCONF_NO_REFERER_TO:
-+ return &ent->no_referer_to;
-+ }
-+ return NULL;
-+}
-diff --git a/url.c b/url.c
-index ed6062e..cbb4aab 100644
---- a/url.c
-+++ b/url.c
-@@ -444,6 +444,8 @@ baseURL(Buffer *buf)
- /* <BASE> tag is defined in the document */
- return buf->baseURL;
- }
-+ else if (IS_EMPTY_PARSED_URL(&buf->currentURL))
-+ return NULL;
- else
- return &buf->currentURL;
- }
-@@ -638,16 +640,21 @@ openSocket(char *const hostname,
- #define COPYPATH_SPC_ALLOW 0
- #define COPYPATH_SPC_IGNORE 1
- #define COPYPATH_SPC_REPLACE 2
-+#define COPYPATH_SPC_MASK 3
-+#define COPYPATH_LOWERCASE 4
-
- static char *
- copyPath(char *orgpath, int length, int option)
- {
- Str tmp = Strnew();
-- while (*orgpath && length != 0) {
-- if (IS_SPACE(*orgpath)) {
-- switch (option) {
-+ char ch;
-+ while ((ch = *orgpath) != 0 && length != 0) {
-+ if (option & COPYPATH_LOWERCASE)
-+ ch = TOLOWER(ch);
-+ if (IS_SPACE(ch)) {
-+ switch (option & COPYPATH_SPC_MASK) {
- case COPYPATH_SPC_ALLOW:
-- Strcat_char(tmp, *orgpath);
-+ Strcat_char(tmp, ch);
- break;
- case COPYPATH_SPC_IGNORE:
- /* do nothing */
-@@ -658,7 +665,7 @@ copyPath(char *orgpath, int length, int option)
- }
- }
- else
-- Strcat_char(tmp, *orgpath);
-+ Strcat_char(tmp, ch);
- orgpath++;
- length--;
- }
-@@ -668,22 +675,14 @@ copyPath(char *orgpath, int length, int option)
- void
- parseURL(char *url, ParsedURL *p_url, ParsedURL *current)
- {
-- char *p, *q;
-+ char *p, *q, *qq;
- Str tmp;
-
- url = url_quote(url); /* quote 0x01-0x20, 0x7F-0xFF */
-
- p = url;
-+ copyParsedURL(p_url, NULL);
- p_url->scheme = SCM_MISSING;
-- p_url->port = 0;
-- p_url->user = NULL;
-- p_url->pass = NULL;
-- p_url->host = NULL;
-- p_url->is_nocache = 0;
-- p_url->file = NULL;
-- p_url->real_file = NULL;
-- p_url->query = NULL;
-- p_url->label = NULL;
-
- /* RFC1808: Relative Uniform Resource Locators
- * 4. Resolving Relative URLs
-@@ -694,7 +693,7 @@ parseURL(char *url, ParsedURL *p_url, ParsedURL *current)
- goto do_label;
- }
- #if defined( __EMX__ ) || defined( __CYGWIN__ )
-- if (!strncmp(url, "file://localhost/", 17)) {
-+ if (!strncasecmp(url, "file://localhost/", 17)) {
- p_url->scheme = SCM_LOCAL;
- p += 17 - 1;
- url += 17 - 1;
-@@ -802,19 +801,20 @@ parseURL(char *url, ParsedURL *p_url, ParsedURL *current)
- /* scheme://user:pass@host or
- * scheme://host:port
- */
-- p_url->host = copyPath(q, p - q, COPYPATH_SPC_IGNORE);
-+ qq = q;
- q = ++p;
- while (*p && strchr("@/?#", *p) == NULL)
- p++;
- if (*p == '@') {
- /* scheme://user:pass@... */
-+ p_url->user = copyPath(qq, q - 1 - qq, COPYPATH_SPC_IGNORE);
- p_url->pass = copyPath(q, p - q, COPYPATH_SPC_ALLOW);
- q = ++p;
-- p_url->user = p_url->host;
-- p_url->host = NULL;
- goto analyze_url;
- }
- /* scheme://host:port/ */
-+ p_url->host = copyPath(qq, q - 1 - qq,
-+ COPYPATH_SPC_IGNORE | COPYPATH_LOWERCASE);
- tmp = Strnew_charp_n(q, p - q);
- p_url->port = atoi(tmp->ptr);
- /* *p is one of ['\0', '/', '?', '#'] */
-@@ -829,7 +829,8 @@ parseURL(char *url, ParsedURL *p_url, ParsedURL *current)
- case '/':
- case '?':
- case '#':
-- p_url->host = copyPath(q, p - q, COPYPATH_SPC_IGNORE);
-+ p_url->host = copyPath(q, p - q,
-+ COPYPATH_SPC_IGNORE | COPYPATH_LOWERCASE);
- p_url->port = DefaultPort[p_url->scheme];
- break;
- }
-@@ -956,12 +957,16 @@ parseURL(char *url, ParsedURL *p_url, ParsedURL *current)
- p_url->label = NULL;
- }
-
--#define initParsedURL(p) bzero(p,sizeof(ParsedURL))
- #define ALLOC_STR(s) ((s)==NULL?NULL:allocStr(s,-1))
-
- void
--copyParsedURL(ParsedURL *p, ParsedURL *q)
-+copyParsedURL(ParsedURL *p, const ParsedURL *q)
- {
-+ if (q == NULL) {
-+ memset(p, 0, sizeof(ParsedURL));
-+ p->scheme = SCM_UNKNOWN;
-+ return;
-+ }
- p->scheme = q->scheme;
- p->port = q->port;
- p->is_nocache = q->is_nocache;
-@@ -1283,6 +1288,8 @@ static char *
- otherinfo(ParsedURL *target, ParsedURL *current, char *referer)
- {
- Str s = Strnew();
-+ const int *no_referer_ptr;
-+ int no_referer;
-
- Strcat_charp(s, "User-Agent: ");
- if (UserAgent == NULL || *UserAgent == '\0')
-@@ -1306,7 +1313,12 @@ otherinfo(ParsedURL *target, ParsedURL *current, char *referer)
- Strcat_charp(s, "Pragma: no-cache\r\n");
- Strcat_charp(s, "Cache-control: no-cache\r\n");
- }
-- if (!NoSendReferer) {
-+ no_referer = NoSendReferer;
-+ no_referer_ptr = query_SCONF_NO_REFERER_FROM(current);
-+ no_referer = NoSendReferer || (no_referer_ptr && *no_referer_ptr);
-+ no_referer_ptr = query_SCONF_NO_REFERER_TO(target);
-+ no_referer = no_referer || (no_referer_ptr && *no_referer_ptr);
-+ if (!no_referer) {
- #ifdef USE_SSL
- if (current && current->scheme == SCM_HTTPS && target->scheme != SCM_HTTPS) {
- /* Don't send Referer: if https:// -> http:// */
-@@ -1314,6 +1326,7 @@ otherinfo(ParsedURL *target, ParsedURL *current, char *referer)
- else
- #endif
- if (referer == NULL && current && current->scheme != SCM_LOCAL &&
-+ current->scheme != SCM_LOCAL_CGI &&
- (current->scheme != SCM_FTP ||
- (current->user == NULL && current->pass == NULL))) {
- char *p = current->label;
-@@ -2234,3 +2247,66 @@ schemeToProxy(int scheme)
- }
- return pu;
- }
-+
-+#ifdef USE_M17N
-+wc_ces
-+url_to_charset(const char *url, const ParsedURL *base, wc_ces doc_charset)
-+{
-+ const ParsedURL *pu;
-+ ParsedURL pu_buf;
-+ const wc_ces *csptr;
-+
-+ if (url && *url && *url != '#') {
-+ parseURL2((char *)url, &pu_buf, (ParsedURL *)base);
-+ pu = &pu_buf;
-+ } else {
-+ pu = base;
-+ }
-+ if (pu && (pu->scheme == SCM_LOCAL || pu->scheme == SCM_LOCAL_CGI))
-+ return SystemCharset;
-+ csptr = query_SCONF_URL_CHARSET(pu);
-+ return (csptr && *csptr) ? *csptr :
-+ doc_charset ? doc_charset : DocumentCharset;
-+}
-+
-+char *
-+url_encode(const char *url, const ParsedURL *base, wc_ces doc_charset)
-+{
-+ return url_quote_conv((char *)url,
-+ url_to_charset(url, base, doc_charset));
-+}
-+
-+#if 0 /* unused */
-+char *
-+url_decode(const char *url, const ParsedURL *base, wc_ces doc_charset)
-+{
-+ if (!DecodeURL)
-+ return (char *)url;
-+ return url_unquote_conv((char *)url,
-+ url_to_charset(url, base, doc_charset));
-+}
-+#endif
-+
-+char *
-+url_decode2(const char *url, const Buffer *buf)
-+{
-+ wc_ces url_charset;
-+
-+ if (!DecodeURL)
-+ return (char *)url;
-+ url_charset = buf ?
-+ url_to_charset(url, baseURL((Buffer *)buf), buf->document_charset) :
-+ url_to_charset(url, NULL, 0);
-+ return url_unquote_conv((char *)url, url_charset);
-+}
-+
-+#else /* !defined(USE_M17N) */
-+
-+char *
-+url_decode0(const char *url)
-+{
-+ if (!DecodeURL)
-+ return (char *)url;
-+ return url_unquote_conv((char *)url, 0);
-+}
-+#endif /* !defined(USE_M17N) */