about summary refs log tree commit diff stats
path: root/WWW/Library/Implementation/HTRules.c
diff options
context:
space:
mode:
Diffstat (limited to 'WWW/Library/Implementation/HTRules.c')
-rw-r--r--WWW/Library/Implementation/HTRules.c260
1 files changed, 253 insertions, 7 deletions
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);