diff options
Diffstat (limited to 'WWW/Library/Implementation')
-rw-r--r-- | WWW/Library/Implementation/HTAccess.c | 101 | ||||
-rw-r--r-- | WWW/Library/Implementation/HTAccess.h | 3 | ||||
-rw-r--r-- | WWW/Library/Implementation/HTMIME.c | 7 | ||||
-rw-r--r-- | WWW/Library/Implementation/HTNews.c | 15 | ||||
-rw-r--r-- | WWW/Library/Implementation/HTRules.c | 260 | ||||
-rw-r--r-- | WWW/Library/Implementation/HTRules.h | 27 | ||||
-rw-r--r-- | WWW/Library/Implementation/HTTCP.c | 146 | ||||
-rw-r--r-- | WWW/Library/Implementation/HTTP.c | 1 | ||||
-rw-r--r-- | WWW/Library/Implementation/HTUtils.h | 11 |
9 files changed, 517 insertions, 54 deletions
diff --git a/WWW/Library/Implementation/HTAccess.c b/WWW/Library/Implementation/HTAccess.c index 008d42b7..11dfc5ae 100644 --- a/WWW/Library/Implementation/HTAccess.c +++ b/WWW/Library/Implementation/HTAccess.c @@ -72,6 +72,7 @@ extern HTCJKlang HTCJK; PUBLIC char * HTClientHost = NULL; /* Name of remote login host if any */ PUBLIC FILE * HTlogfile = NULL; /* File to which to output one-liners */ PUBLIC BOOL HTSecure = NO; /* Disable access for telnet users? */ +PUBLIC BOOL HTPermitRedir = NO; /* Always allow redirection in getfile()? */ PUBLIC BOOL using_proxy = NO; /* are we using a proxy gateway? */ @@ -315,6 +316,9 @@ PUBLIC BOOL override_proxy ARGS1( #ifndef DISABLE_FINGER else if (!strcmp(acc_method, "finger")) port = 79; #endif + else if (!strcmp(acc_method, "telnet")) port = 23; + else if (!strcmp(acc_method, "tn3270")) port = 23; + else if (!strcmp(acc_method, "rlogin")) port = 513; FREE(acc_method); } } @@ -379,17 +383,34 @@ PRIVATE int get_physical ARGS2( char * acc_method = NULL; /* Name of access method */ char * physical = NULL; char * Server_addr = NULL; + BOOL override_flag = NO; + + /* + ** Make sure the using_proxy variable is FALSE. + */ + using_proxy = NO; #ifndef NO_RULES physical = HTTranslate(addr); if (!physical) { + if (redirecting_url) { + return HT_REDIRECTING; + } return HT_FORBIDDEN; } if (anchor->isISMAPScript == TRUE) { StrAllocCat(physical, "?0,0"); CTRACE(tfp, "HTAccess: Appending '?0,0' coordinate pair.\n"); } - HTAnchor_setPhysical(anchor, physical); + if (!strncmp(physical, "Proxied=", 8)) { + HTAnchor_setPhysical(anchor, physical + 8); + using_proxy = YES; + } else if (!strncmp(physical, "NoProxy=", 8)) { + HTAnchor_setPhysical(anchor, physical + 8); + override_flag = YES; + } else { + HTAnchor_setPhysical(anchor, physical); + } FREE(physical); /* free our copy */ #else if (anchor->isISMAPScript == TRUE) { @@ -410,53 +431,56 @@ PRIVATE int get_physical ARGS2( ** Check whether gateway access has been set up for this. ** ** This function can be replaced by the rule system above. + ** + ** If the rule system has already determined that we should + ** use a proxy, or that we shouldn't, ignore proxy-related + ** settings, don't use no_proxy either. */ #define USE_GATEWAYS #ifdef USE_GATEWAYS - /* - ** Make sure the using_proxy variable is FALSE. - */ - using_proxy = NO; - if (!strcasecomp(acc_method, "news")) { - /* - ** News is different, so we need to check the name of the server, - ** as well as the default port for selective exclusions. - */ - char *host = NULL; - if ((host = HTParse(addr, "", PARSE_HOST))) { - if (strchr(host, ':') == NULL) { + if (!override_flag && !using_proxy) { /* else ignore no_proxy env var */ + if (!strcasecomp(acc_method, "news")) { + /* + ** News is different, so we need to check the name of the server, + ** as well as the default port for selective exclusions. + */ + char *host = NULL; + if ((host = HTParse(addr, "", PARSE_HOST))) { + if (strchr(host, ':') == NULL) { + StrAllocCopy(Server_addr, "news://"); + StrAllocCat(Server_addr, host); + StrAllocCat(Server_addr, ":119/"); + } + FREE(host); + } else if (getenv("NNTPSERVER") != NULL) { StrAllocCopy(Server_addr, "news://"); - StrAllocCat(Server_addr, host); + StrAllocCat(Server_addr, (char *)getenv("NNTPSERVER")); StrAllocCat(Server_addr, ":119/"); } - FREE(host); - } else if (getenv("NNTPSERVER") != NULL) { - StrAllocCopy(Server_addr, "news://"); - StrAllocCat(Server_addr, (char *)getenv("NNTPSERVER")); - StrAllocCat(Server_addr, ":119/"); - } - } else if (!strcasecomp(acc_method, "wais")) { - /* + } else if (!strcasecomp(acc_method, "wais")) { + /* ** Wais also needs checking of the default port ** for selective exclusions. */ - char *host = NULL; - if ((host = HTParse(addr, "", PARSE_HOST))) { - if (!(strchr(host, ':'))) { - StrAllocCopy(Server_addr, "wais://"); - StrAllocCat(Server_addr, host); - StrAllocCat(Server_addr, ":210/"); + char *host = NULL; + if ((host = HTParse(addr, "", PARSE_HOST))) { + if (!(strchr(host, ':'))) { + StrAllocCopy(Server_addr, "wais://"); + StrAllocCat(Server_addr, host); + StrAllocCat(Server_addr, ":210/"); + } + FREE(host); } - FREE(host); - } - else + else + StrAllocCopy(Server_addr, addr); + } else { StrAllocCopy(Server_addr, addr); - } else { - StrAllocCopy(Server_addr, addr); + } + override_flag = override_proxy(Server_addr); } - if (!override_proxy(Server_addr)) { + if (!override_flag && !using_proxy) { char * gateway_parameter, *gateway, *proxy; /* @@ -641,11 +665,17 @@ PRIVATE int HTLoad ARGS4( HTProtocol *p; int status = get_physical(addr, anchor); if (status == HT_FORBIDDEN) { + /* prevent crash if telnet or similar was forbidden by rule. - kw */ + LYFixCursesOn("show alert:"); return HTLoadError(sink, 500, gettext("Access forbidden by rule")); + } else if (status == HT_REDIRECTING) { + return status; /* fake redirection by rule, to redirecting_url */ } if (status < 0) return status; /* Can't resolve or forbidden */ + /* prevent crash if telnet or similar mapped or proxied by rule. - kw */ + LYFixCursesOnForAccess(addr, HTAnchor_physical(anchor)); p = (HTProtocol *)HTAnchor_protocol(anchor); anchor->underway = TRUE; /* Hack to deal with caching */ status= (*(p->load))(HTAnchor_physical(anchor), @@ -668,6 +698,8 @@ PUBLIC HTStream *HTSaveStream ARGS1( return (*p->saveStream)(anchor); } +PUBLIC int redirection_attempts = 0; /* counter in HTLoadDocument */ + /* Load a document - with logging etc HTLoadDocument() ** ---------------------------------- ** @@ -697,7 +729,6 @@ PRIVATE BOOL HTLoadDocument ARGS4( CONST char * address_to_load = full_address; char *cp; BOOL ForcingNoCache = LYforce_no_cache; - static int redirection_attempts = 0; CTRACE (tfp, "HTAccess: loading document %s\n", address_to_load); diff --git a/WWW/Library/Implementation/HTAccess.h b/WWW/Library/Implementation/HTAccess.h index 2cfd49d5..0c763051 100644 --- a/WWW/Library/Implementation/HTAccess.h +++ b/WWW/Library/Implementation/HTAccess.h @@ -13,6 +13,8 @@ extern char * use_this_url_instead; +extern int redirection_attempts; + /* Definition uses: */ #include <HTAnchor.h> @@ -76,6 +78,7 @@ extern int HTDiag; /* Flag: load source as plain text */ extern char * HTClientHost; /* Name or number of telnetting host */ extern FILE * HTlogfile; /* File to output one-liners to */ extern BOOL HTSecure; /* Disable security holes? */ +extern BOOL HTPermitRedir; /* Special flag for getfile() */ extern HTStream* HTOutputStream; /* For non-interactive, set this */ extern HTFormat HTOutputFormat; /* To convert on load, set this */ diff --git a/WWW/Library/Implementation/HTMIME.c b/WWW/Library/Implementation/HTMIME.c index 65bab4f9..24b42194 100644 --- a/WWW/Library/Implementation/HTMIME.c +++ b/WWW/Library/Implementation/HTMIME.c @@ -1558,6 +1558,13 @@ PRIVATE void HTMIME_put_character ARGS2( if (!strcasecomp(me->value, "YES") || !strcasecomp(me->value, "TRUE")) { me->anchor->safe = TRUE; + } else if (!strcasecomp(me->value, "NO") || + !strcasecomp(me->value, "FALSE")) { + /* + ** If server explicitly tells us that it has changed + ** its mind, reset flag in anchor. - kw + */ + me->anchor->safe = FALSE; } break; case miSERVER: diff --git a/WWW/Library/Implementation/HTNews.c b/WWW/Library/Implementation/HTNews.c index 5b16ee3c..32f4e3a6 100644 --- a/WWW/Library/Implementation/HTNews.c +++ b/WWW/Library/Implementation/HTNews.c @@ -771,8 +771,12 @@ PRIVATE void abort_socket NOARGS { CTRACE(tfp, "HTNews: EOF on read, closing socket %d\n", s); NEWS_NETCLOSE(s); /* End of file, close socket */ - PUTS("Network Error: connection lost"); - PUTC('\n'); + if (rawtext) { + RAW_PUTS("Network Error: connection lost\n"); + } else { + PUTS("Network Error: connection lost"); + PUTC('\n'); + } s = -1; /* End of file on response */ } @@ -1299,7 +1303,7 @@ PRIVATE int read_article ARGS1( if (rawtext) { /* - * No tags - kw + * No tags, and never do a PUTC. - kw */ ; } else if (diagnostic) { @@ -1308,14 +1312,15 @@ PRIVATE int read_article ARGS1( ** as XMP formatted text. - FM */ START(HTML_XMP); + PUTC('\n'); } else { /* ** Read in the BODY of the Article ** as PRE formatted text. - FM */ START(HTML_PRE); + PUTC('\n'); } - PUTC('\n'); p = line; while (!done) { @@ -2783,7 +2788,7 @@ Send_NNTP_command: /* ** This function clears all authorization information by -** invoking the free_HTAAGlobals() function, which normally +** invoking the free_NNTP_AuthInfo() function, which normally ** is invoked at exit. It allows a browser command to do ** this at any time, for example, if the user is leaving ** the terminal for a period of time, but does not want diff --git a/WWW/Library/Implementation/HTRules.c b/WWW/Library/Implementation/HTRules.c index 97df34e6..6140765e 100644 --- a/WWW/Library/Implementation/HTRules.c +++ b/WWW/Library/Implementation/HTRules.c @@ -15,6 +15,7 @@ ** Bug Fix: in case of PASS, only one parameter to printf. ** 19 Sep 93 AL Added Access Authorization stuff. ** 1 Nov 93 AL Added htbin. +** 25 May 99 KW Added redirect for lynx. ** */ @@ -35,10 +36,17 @@ typedef struct _rule { HTRuleOp op; char * pattern; char * equiv; + char * condition_op; /* as strings - may be inefficient, */ + char * condition; /* but this is not for a server - kw */ } rule; #ifndef NO_RULES +#include <HTTP.h> /* for redirecting_url, indirectly HTPermitRedir - kw */ +#include <LYGlobalDefs.h> /* for LYUserSpecifiedURL - kw */ +#include <LYUtils.h> /* for LYFixCursesOn - kw */ +#include <HTAlert.h> + /* Global variables ** ---------------- */ @@ -68,15 +76,17 @@ PRIVATE rule * rule_tail = 0; /* Pointer to last on list */ ** returns 0 if success, -1 if error. */ -PUBLIC int HTAddRule ARGS3( +PUBLIC int HTAddRule ARGS5( HTRuleOp, op, CONST char *, pattern, - CONST char *, equiv) + CONST char *, equiv, + CONST char *, cond_op, + CONST char *, cond) { /* BYTE_ADDRESSING removed and memory check - AS - 1 Sep 93 */ rule * temp; char * pPattern; - temp = (rule *)malloc(sizeof(*temp)); + temp = (rule *)calloc(1, sizeof(*temp)); if (temp==NULL) outofmem(__FILE__, "HTAddRule"); pPattern = (char *)malloc(strlen(pattern)+1); @@ -91,14 +101,23 @@ PUBLIC int HTAddRule ARGS3( } else { temp->equiv = 0; } + if (cond_op) { + StrAllocCopy(temp->condition_op, cond_op); + StrAllocCopy(temp->condition, cond); + } temp->pattern = pPattern; temp->op = op; strcpy(pPattern, pattern); if (equiv) { - CTRACE(tfp, "Rule: For `%s' op %d `%s'\n", pattern, op, equiv); + CTRACE(tfp, "Rule: For `%s' op %d `%s'", pattern, op, equiv); } else { - CTRACE(tfp, "Rule: For `%s' op %d\n", pattern, op); + CTRACE(tfp, "Rule: For `%s' op %d", pattern, op); + } + if (cond_op) { + CTRACE(tfp, "\t%s %s\n", cond_op, cond ? cond : "<null>"); + } else { + CTRACE(tfp, "\n"); } if (!rules) { @@ -137,6 +156,8 @@ void HTClearRules NOARGS rules = temp->next; FREE(temp->pattern); FREE(temp->equiv); + FREE(temp->condition_op); + FREE(temp->condition); FREE(temp); } #ifndef PUT_ON_HEAD @@ -144,7 +165,32 @@ void HTClearRules NOARGS #endif } - +PRIVATE BOOL rule_cond_ok ARGS1( + rule *, r) +{ + BOOL result; + if (!r->condition_op) + return YES; + if (strcmp(r->condition_op, "if") && strcmp(r->condition_op, "unless")) { + CTRACE(tfp, "....... rule ignored, unrecognized `%s'!\n", + r->condition_op); + return NO; + } + if (!strcmp(r->condition, "redirected")) + result = (redirection_attempts > 0); + else if (!strcmp(r->condition, "userspec")) + result = LYUserSpecifiedURL; + else { + CTRACE(tfp, "....... rule ignored, unrecognized `%s %s'!\n", + r->condition_op, r->condition ? r->condition : "<null>"); + return NO; + } + if (!strcmp(r->condition_op, "if")) + return result; + else + return (!result); + +} /* Translate by rules HTTranslate() ** ------------------ ** @@ -169,6 +215,9 @@ char * HTTranslate ARGS1( { rule * r; char *current = NULL; + char *msgtmp = NULL, *pMsg; + int proxy_none_flag = 0; + int permitredir_flag = 0; StrAllocCopy(current, required); HTAA_clearProtections(); /* Reset from previous call -- AL */ @@ -188,6 +237,9 @@ char * HTTranslate ARGS1( } else /* Not wildcard */ if (*p != *q) continue; /* plain mismatch: go to next rule */ + if (!rule_cond_ok(r)) /* check condition, next rule if false - kw */ + continue; + switch (r->op) { /* Perform operation */ #ifdef ACCESS_AUTH @@ -225,14 +277,53 @@ char * HTTranslate ARGS1( break; #endif /* ACCESS_AUTH */ + case HT_UserMsg: /* Produce message immediately */ + LYFixCursesOn("show rule message:"); + HTUserMsg2((r->equiv ? r->equiv : "Rule: %s"), current); + break; + case HT_InfoMsg: /* Produce messages immediately */ + case HT_Progress: + case HT_Alert: + LYFixCursesOn("show rule message:"); /* and fall through */ + case HT_AlwaysAlert: + pMsg = r->equiv ? r->equiv : + (r->op==HT_AlwaysAlert) ? "%s" : "Rule: %s"; + if (strchr(pMsg, '%')) { + HTSprintf0(&msgtmp, pMsg, current); + pMsg = msgtmp; + } + switch (r->op) { /* Actually produce message */ + case HT_InfoMsg: HTInfoMsg(pMsg); break; + case HT_Progress: HTProgress(pMsg); break; + case HT_Alert: HTAlert(pMsg); break; + case HT_AlwaysAlert: HTAlwaysAlert("Rule alert:", pMsg); break; + default: break; + } + FREE(msgtmp); + break; + + case HT_PermitRedir: /* Set special flag */ + permitredir_flag = 1; + CTRACE(tfp, "HTRule: Mark for redirection permitted\n"); + break; + case HT_Pass: /* Authorised */ if (!r->equiv) { + if (proxy_none_flag) { + char * temp = NULL; + StrAllocCopy(temp, "NoProxy="); + StrAllocCat(temp, current); + FREE(current); + current = temp; + } CTRACE(tfp, "HTRule: Pass `%s'\n", current); return current; } /* Else fall through ...to map and pass */ case HT_Map: + case HT_Redirect: + case HT_RedirectPerm: if (*p == *q) { /* End of both strings, no wildcard */ CTRACE(tfp, "For `%s' using `%s'\n", current, r->equiv); StrAllocCopy(current, r->equiv); /* use entire translation */ @@ -264,9 +355,49 @@ char * HTTranslate ARGS1( } /* If no insertion point exists */ } if (r->op == HT_Pass) { + if (proxy_none_flag) { + char * temp = NULL; + StrAllocCopy(temp, "NoProxy="); + StrAllocCat(temp, current); + FREE(current); + current = temp; + } CTRACE(tfp, "HTRule: ...and pass `%s'\n", current); return current; + } else if (r->op == HT_Redirect) { + CTRACE(tfp, "HTRule: ...and redirect to `%s'\n", + current); + redirecting_url = current; + HTPermitRedir = (permitredir_flag == 1); + return (char *)0; + } else if (r->op == HT_RedirectPerm) { + CTRACE(tfp, "HTRule: ...and redirect like 301 to `%s'\n", + current); + redirecting_url = current; + permanent_redirection = TRUE; + HTPermitRedir = (permitredir_flag == 1); + return (char *)0; + } + break; + + case HT_UseProxy: + if (r->equiv && 0==strcasecomp(r->equiv, "none")) { + CTRACE(tfp, "For `%s' will not use proxy\n", current); + proxy_none_flag = 1; + } else if (proxy_none_flag) { + CTRACE(tfp, "For `%s' proxy server ignored: %s\n", + current, + r->equiv ? r->equiv : "<null>"); + } else { + char * temp = NULL; + StrAllocCopy(temp, "Proxied="); + StrAllocCat(temp, r->equiv); + StrAllocCat(temp, current); + CTRACE(tfp, "HTRule: proxy server found: %s\n", + r->equiv ? r->equiv : "<null>"); + FREE(current); + return temp; } break; @@ -280,6 +411,12 @@ char * HTTranslate ARGS1( } /* loop over rules */ + if (proxy_none_flag) { + char * temp = NULL; + StrAllocCopy(temp, "NoProxy="); + StrAllocCat(temp, current); + return temp; + } return current; } @@ -298,6 +435,7 @@ PUBLIC int HTSetConfiguration ARGS1( char * line = NULL; char * pointer = line; char *word1, *word2, *word3; + char *cond_op=NULL, *cond=NULL; float quality, secs, secs_per_byte; int maxbytes; int status; @@ -357,13 +495,121 @@ PUBLIC int HTSetConfiguration ARGS1( op = 0==strcasecomp(word1, "map") ? HT_Map : 0==strcasecomp(word1, "pass") ? HT_Pass : 0==strcasecomp(word1, "fail") ? HT_Fail + : 0==strcasecomp(word1, "redirect") ? HT_Redirect + : 0==strncasecomp(word1, "redirectperm", 12) ? HT_RedirectPerm + : 0==strcasecomp(word1, "redirecttemp") ? HT_Redirect + : 0==strcasecomp(word1, "permitredirection") ? HT_PermitRedir + : 0==strcasecomp(word1, "useproxy") ? HT_UseProxy + : 0==strcasecomp(word1, "alert") ? HT_Alert + : 0==strcasecomp(word1, "alwaysalert") ? HT_AlwaysAlert + : 0==strcasecomp(word1, "progress") ? HT_Progress + : 0==strcasecomp(word1, "usermsg") ? HT_UserMsg + : 0==strcasecomp(word1, "infomsg") ? HT_InfoMsg : 0==strcasecomp(word1, "defprot") ? HT_DefProt : 0==strcasecomp(word1, "protect") ? HT_Protect : HT_Invalid; if (op==HT_Invalid) { fprintf(stderr, "HTRule: %s '%s'\n", RULE_INCORRECT, config); } else { - HTAddRule(op, word2, word3); + switch (op) { + case HT_Fail: /* never a or other 2nd parameter */ + case HT_PermitRedir: + cond_op = word3; + if (cond_op && *cond_op) { + word3 = NULL; + cond = HTNextField(&pointer); + } + break; + + case HT_Pass: /* possibly a URL2 */ + if (word3 && (!strcasecomp(word3, "if") || + !strcasecomp(word3, "unless"))) { + cond_op = word3; + word3 = NULL; + cond = HTNextField(&pointer); + break; + } /* else fall through */ + + case HT_Map: /* always a URL2 (or other 2nd parameter) */ + case HT_Redirect: + case HT_RedirectPerm: + case HT_UseProxy: + cond_op = HTNextField(&pointer); + /* check for extra status word in "Redirect" */ + if (op==HT_Redirect && 0==strcasecomp(word1, "redirect") && + cond_op && + strcasecomp(cond_op, "if") && + strcasecomp(cond_op, "unless")) { + if (0==strcmp(word2, "301") || + 0==strcasecomp(word2, "permanent")) { + op = HT_RedirectPerm; + } else if (!(0==strcmp(word2, "302") || + 0==strcmp(word2, "303") || + 0==strcasecomp(word2, "temp") || + 0==strcasecomp(word2, "seeother"))) { + CTRACE(tfp, "Rule: Ignoring `%s' in Redirect\n", word2); + } + word2 = word3; + word3 = cond_op; /* cond_op isn't condition op after all */ + cond_op = HTNextField(&pointer); + } + if (cond_op && *cond_op) + cond = HTNextField(&pointer); + break; + + case HT_Progress: + case HT_InfoMsg: + case HT_UserMsg: + case HT_Alert: + case HT_AlwaysAlert: + cond_op = HTNextField(&pointer); + if (cond_op && *cond_op) + cond = HTNextField(&pointer); + if (word3) { /* Fix string with too may %s - kw */ + char *cp = word3, *cp1, *cp2; + while ((cp1=strchr(cp, '%'))) { + if (cp1[1] == '\0') { + *cp1 = '\0'; + break; + } else if (cp1[1] == '%') { + cp = cp1 + 2; + continue; + } else while ((cp2=strchr(cp1+2, '%'))) { + if (cp2[1] == '\0') { + *cp2 = '\0'; + break; + } else if (cp2[1] == '%') { + cp1 = cp2; + } else { + *cp2 = '?'; /* replace bad % */ + cp1 = cp2; + } + } + break; + } + } + break; + + default: + break; + } + if (cond_op && cond && *cond && !strcasecomp(cond_op, "unless")) { + cond_op = "unless"; + } else if (cond_op && cond && *cond && + !strcasecomp(cond_op, "if")) { + cond_op = "if"; + } else if (cond_op || cond) { + fprintf(stderr, "HTRule: %s '%s'\n", RULE_INCORRECT, config); + FREE(line); /* syntax error, condition is a mess - kw */ + return -2; /* NB unrecognized cond passes here - kw */ + } + if (cond && !strncasecomp(cond, "redirected", strlen(cond))) { + cond = "redirected"; /* recognized, canonical case - kw */ + } else if (cond && strlen(cond) >= 8 && + !strncasecomp(cond, "userspecified", strlen(cond))) { + cond = "userspec"; /* also allow abbreviation - kw */ + } + HTAddRule(op, word2, word3, cond_op, cond); } } FREE(line); diff --git a/WWW/Library/Implementation/HTRules.h b/WWW/Library/Implementation/HTRules.h index fce782f8..0974bbae 100644 --- a/WWW/Library/Implementation/HTRules.h +++ b/WWW/Library/Implementation/HTRules.h @@ -28,7 +28,16 @@ typedef enum _HTRuleOp { HT_Pass, HT_Fail, HT_DefProt, - HT_Protect + HT_Protect, + HT_Progress, + HT_InfoMsg, + HT_UserMsg, + HT_Alert, + HT_AlwaysAlert, + HT_Redirect, + HT_RedirectPerm, + HT_PermitRedir, + HT_UseProxy } HTRuleOp; #ifndef NO_RULES @@ -57,7 +66,14 @@ HTAddRule: Add rule to the list pattern points to 0-terminated string containing a single "*" equiv points to the equivalent string with * for the place where the - text matched by * goes. + text matched by * goes; or to other 2nd parameter + meaning depends on op). + + cond_op, additional condition for applying rule; cond_op should + cond be either NULL (no additional condition), or one of + the strings "if" or "unless"; if cond_op is not NULL, + cond should point to a recognized condition keyword + (as a string) such as "userspec", "redirected". ON EXIT, @@ -68,7 +84,12 @@ HTAddRule: Add rule to the list large. */ -extern int HTAddRule PARAMS((HTRuleOp op, CONST char * pattern, CONST char * equiv)); +extern int HTAddRule PARAMS(( + HTRuleOp op, + CONST char * pattern, + CONST char * equiv, + CONST char * cond_op, + CONST char * cond)); /* diff --git a/WWW/Library/Implementation/HTTCP.c b/WWW/Library/Implementation/HTTCP.c index 1a6b2621..fdc6b66a 100644 --- a/WWW/Library/Implementation/HTTCP.c +++ b/WWW/Library/Implementation/HTTCP.c @@ -645,7 +645,7 @@ PUBLIC struct hostent * LYGetHostByName ARGS1( struct _statuses { size_t rehostentlen; int h_length; - int child_errno; /* maybe not very useful */ + int child_errno; /* sometimes useful to pass this on */ int child_h_errno; BOOL h_errno_valid; } statuses; @@ -687,7 +687,7 @@ PUBLIC struct hostent * LYGetHostByName ARGS1( CTRACE(tfp, "LYGetHostByName: Calling gethostbyname(%s)\n", host); #endif /* MVS */ - CTRACE_FLUSH(tfp); /* so child messages will not mess parent log */ + CTRACE_FLUSH(tfp); /* so child messages will not mess up parent log */ lynx_nsl_status = HT_INTERNAL; /* should be set to something else below */ @@ -699,6 +699,10 @@ PUBLIC struct hostent * LYGetHostByName ARGS1( */ { int got_rehostent = 0; +#if HAVE_SIGACTION + sigset_t old_sigset; + sigset_t new_sigset; +#endif /* ** Pipe, child pid, status buffers, start time, select() ** control variables. @@ -727,6 +731,32 @@ PUBLIC struct hostent * LYGetHostByName ARGS1( pipe(pfd); +#if HAVE_SIGACTION + /* + * Attempt to prevent a rare situation where the child + * could execute the Lynx signal handlers because it gets + * killed before it even has a chance to reset its handlers, + * resulting in bogus 'Exiting via interrupt' message and + * screen corruption or worse. + * Should that continue to be reported, for systems without + * sigprocmask(), we need to find a different solutions for + * those. - kw 19990430 + */ + sigemptyset(&new_sigset); + sigaddset(&new_sigset, SIGTERM); + sigaddset(&new_sigset, SIGINT); +#ifndef NOSIGHUP + sigaddset(&new_sigset, SIGHUP); +#endif /* NOSIGHUP */ +#ifdef SIGTSTP + sigaddset(&new_sigset, SIGTSTP); +#endif /* SIGTSTP */ +#ifdef SIGWINCH + sigaddset(&new_sigset, SIGWINCH); +#endif /* SIGWINCH */ + sigprocmask(SIG_BLOCK, &new_sigset, &old_sigset); +#endif /* HAVE_SIGACTION */ + if ((fpid = fork()) == 0 ) { struct hostent *phost; /* Pointer to host - See netdb.h */ /* @@ -764,13 +794,26 @@ PUBLIC struct hostent * LYGetHostByName ARGS1( signal(SIGSEGV, SIG_DFL); signal(SIGILL, SIG_DFL); +#if HAVE_SIGACTION + /* Restore signal mask to whatever it was before the fork. -kw */ + sigprocmask(SIG_SETMASK, &old_sigset, NULL); +#endif /* HAVE_SIGACTION */ + /* ** Child won't use read side. -BL */ close(pfd[0]); +#ifdef HAVE_H_ERRNO + /* to detect cases when it doesn't get set although it should */ + h_errno = -2; +#endif + errno = 0; phost = gethostbyname(host); + statuses.child_errno = errno; statuses.child_h_errno = h_errno; +#ifdef HAVE_H_ERRNO statuses.h_errno_valid = YES; +#endif #ifdef MVS CTRACE(tfp, "LYGetHostByName: gethostbyname() returned %d\n", phost); #endif /* MVS */ @@ -790,12 +833,17 @@ PUBLIC struct hostent * LYGetHostByName ARGS1( statuses.h_length = 0; } else { statuses.h_length = ((struct hostent *)rehostent)->h_length; +#ifdef HAVE_H_ERRNO + if (h_errno == -2) /* success, but h_errno unchanged? */ + statuses.h_errno_valid = NO; +#endif } /* ** Send variables indicating status of lookup to parent. ** That includes rehostentlen, which the parent will use ** as the size for the second read (if > 0). */ + if (!statuses.child_errno) statuses.child_errno = errno; statuses.rehostentlen = rehostentlen; write(pfd[1], &statuses, sizeof(statuses)); @@ -815,6 +863,14 @@ PUBLIC struct hostent * LYGetHostByName ARGS1( } } +#if HAVE_SIGACTION + /* + ** (parent) Restore signal mask to whatever it was + ** before the fork. - kw + */ + sigprocmask(SIG_SETMASK, &old_sigset, NULL); +#endif /* HAVE_SIGACTION */ + /* ** (parent) Wait until lookup finishes, or interrupt, ** or cycled too many times (just in case) -BL @@ -871,8 +927,44 @@ PUBLIC struct hostent * LYGetHostByName ARGS1( if (readret == sizeof(statuses)) { h_errno = statuses.child_h_errno; errno = statuses.child_errno; - if (statuses.h_errno_valid) +#ifdef HAVE_H_ERRNO + if (statuses.h_errno_valid) { lynx_nsl_status = HT_H_ERRNO_VALID; + /* + * If something went wrong in the child process + * other than normal lookup errors, and it appears + * that we have enough info to know what went wrong, + * generate diagnostic output. + * ENOMEM observed on linux in processes constrained + * with ulimit. It would be too unkind to abort + * the session, access to local files or through a + * proxy may still work. - kw + */ + if ( +#ifdef NETDB_INTERNAL /* linux glibc: defined in netdb.h */ + (errno && h_errno == NETDB_INTERNAL) || +#endif + (errno == ENOMEM && + statuses.rehostentlen == 0 && + /* should probably be NETDB_INTERNAL if child + memory exhausted, but we may find that + h_errno remains unchanged. - kw */ + h_errno == -2)) { +#ifndef MULTINET + HTInetStatus("CHILD gethostbyname"); +#endif + HTAlert(LYStrerror(statuses.child_errno)); + if (errno == ENOMEM) { + /* + * Not much point in continuing, right? + * Fake a 'z', should shorten pointless + * guessing cycle. - kw + */ + LYFakeZap(YES); + } + } + } +#endif /* HAVE_H_ERRNO */ if (statuses.rehostentlen > sizeof(struct hostent)) { /* ** Then get the full reorganized hostent. -BL, kw @@ -1311,6 +1403,11 @@ PUBLIC CONST char * HTHostName NOARGS return hostname; } +#ifndef MULTINET /* SOCKET_ERRNO != errno ? */ +#if !defined(UCX) || !defined(VAXC) /* errno not modifiable ? */ +#define SOCKET_DEBUG_TRACE /* show errno status after some system calls */ +#endif /* UCX && VAXC */ +#endif /* MULTINET */ /* ** Interruptable connect as implemented for Mosaic by Marc Andreesen ** and hacked in for Lynx years ago by Lou Montulli, and further @@ -1449,6 +1546,13 @@ PUBLIC int HTDoConnect ARGS4( int ret; int tries=0; +#ifdef SOCKET_DEBUG_TRACE + { + int saved_errno = SOCKET_ERRNO; + HTInetStatus("this socket's first connect"); + errno = saved_errno; /* I don't trust HTInetStatus */ + } +#endif /* SOCKET_DEBUG_TRACE */ ret = 0; while (ret <= 0) { fd_set writefds; @@ -1477,6 +1581,13 @@ PUBLIC int HTDoConnect ARGS4( #endif /* SOCKS */ ret = select(FD_SETSIZE, NULL, (void *)&writefds, NULL, &timeout); +#ifdef SOCKET_DEBUG_TRACE + if (tries == 1) { + int saved_errno = SOCKET_ERRNO; + HTInetStatus("this socket's first select"); + errno = saved_errno; /* I don't trust HTInetStatus */ + } +#endif /* SOCKET_DEBUG_TRACE */ /* ** If we suspend, then it is possible that select will be ** interrupted. Allow for this possibility. - JED @@ -1484,6 +1595,13 @@ PUBLIC int HTDoConnect ARGS4( if ((ret == -1) && (errno == EINTR)) continue; +#ifdef SOCKET_DEBUG_TRACE + if (ret < 0) { + int saved_errno = SOCKET_ERRNO; + HTInetStatus("failed select"); + errno = saved_errno; /* I don't trust HTInetStatus */ + } +#endif /* SOCKET_DEBUG_TRACE */ /* ** Again according to the Sun and Motorola man pages for connect: ** EALREADY The socket is non-blocking and a previ- @@ -1527,8 +1645,16 @@ PUBLIC int HTDoConnect ARGS4( if (status && (SOCKET_ERRNO == EALREADY)) /* new stuff LJM */ ret = 0; /* keep going */ - else + else { +#ifdef SOCKET_DEBUG_TRACE + if (status < 0) { + int saved_errno = SOCKET_ERRNO; + HTInetStatus("confirm-ready connect"); + errno = saved_errno; + } +#endif /* SOCKET_DEBUG_TRACE */ break; + } #ifdef SOCKS } #endif /* SOCKS */ @@ -1559,6 +1685,11 @@ PUBLIC int HTDoConnect ARGS4( (SOCKET_ERRNO != 18242) && #endif /* UCX */ (SOCKET_ERRNO != EISCONN)) { +#ifdef SOCKET_DEBUG_TRACE + int saved_errno = SOCKET_ERRNO; + HTInetStatus("confirm-not-ready connect"); + errno = saved_errno; +#endif /* SOCKET_DEBUG_TRACE */ break; } } @@ -1570,6 +1701,13 @@ PUBLIC int HTDoConnect ARGS4( } } } +#ifdef SOCKET_DEBUG_TRACE + else if (status < 0) { + int saved_errno = SOCKET_ERRNO; + HTInetStatus("this socket's first and only connect"); + errno = saved_errno; /* I don't trust HTInetStatus */ + } +#endif /* SOCKET_DEBUG_TRACE */ #endif /* !DJGPP */ if (status < 0) { /* diff --git a/WWW/Library/Implementation/HTTP.c b/WWW/Library/Implementation/HTTP.c index 96067a51..05b3e89c 100644 --- a/WWW/Library/Implementation/HTTP.c +++ b/WWW/Library/Implementation/HTTP.c @@ -918,6 +918,7 @@ try_again: */ HTAlert(line_buffer); HTTP_NETCLOSE(s, handle); + HTNoDataOK = 1; status = HT_NO_DATA; goto clean_up; diff --git a/WWW/Library/Implementation/HTUtils.h b/WWW/Library/Implementation/HTUtils.h index dd5be2dd..dd0a51e7 100644 --- a/WWW/Library/Implementation/HTUtils.h +++ b/WWW/Library/Implementation/HTUtils.h @@ -265,6 +265,17 @@ Macros for declarations /* +OFTEN USED INTEGER MACROS + + Min and Max functions + + */ +#ifndef HTMIN +#define HTMIN(a,b) ((a) <= (b) ? (a) : (b)) +#define HTMAX(a,b) ((a) >= (b) ? (a) : (b)) +#endif +/* + Booleans */ |