Support the siteconf feature

Patch to support the siteconf feature, from [w3m-dev 04463]
on 2012-06-27, provided by AIDA Shinra.
This commit is contained in:
Tatsuya Kinoshita
2013-04-08 21:48:49 +09:00
parent dbd52ac2ca
commit a32bf68c85
21 changed files with 781 additions and 263 deletions

222
rc.c
View File

@@ -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;
}