--- src/Makefile.orig	Mon Apr 11 14:58:06 1994
+++ src/Makefile	Sat Sep 30 01:39:05 1995
@@ -4,22 +4,26 @@
 LIBXMX_DIR = ../libXmx
 LIBXMX_INC = ../libXmx
 
-PROGRAM_LIBS = $(LIBWWW_DIR)/libwww.a $(LIBHTMLW_DIR)/libhtmlw.a $(LIBXMX_DIR)/libXmx.a
-LIBS = $(PROGRAM_LIBS) $(X_LIBS) $(DTM_LIBS) $(HDF_LIBS) $(WAIS_LIBS) $(MATH_LIB) $(SYS_LIBS)
+PROGRAM_LIBS = $(LIBWWW_DIR)/libwww.a $(LIBHTMLW_DIR)/libhtmlw.a $(LIBXMX_DIR)/libXmx.a 
+LIBS = $(PROGRAM_LIBS) $(X_LIBS) $(DTM_LIBS) $(HDF_LIBS) $(WAIS_LIBS) $(MATH_LIB) ../../regex-0.12/regex.o -L/usr/athena/lib -lhesiod -lresolv $(SYS_LIBS) 
 
 CFILES = main.c gui.c gui-dialogs.c gui-menubar.c gui-documents.c mo-www.c\
   mo-dtm.c hotlist.c whine.c history.c\
   annotate.c pan.c grpan.c grpan-www.c audan.c globalhist.c img.c\
   picread.c xpmhash.c xpmread.c gifread.c pixmaps.c\
-  medcut.c mo-hdf.c
+  medcut.c mo-hdf.c url_translate.c
 OBJS = main.o gui.o gui-dialogs.o gui-menubar.o gui-documents.o mo-www.o\
   mo-dtm.o hotlist.o whine.o history.o\
   annotate.o pan.o grpan.o grpan-www.o audan.o globalhist.o img.o\
   picread.o xpmhash.o xpmread.o gifread.o pixmaps.o\
-  medcut.o mo-hdf.o
+  medcut.o mo-hdf.o url_translate.o
 
 AUXCFILES = hdf-browse.c
 AUXOBJS = hdf-browse.o
+
+url_translate.o: url_translate.c
+	$(CC) -c $(CFLAGS) $(AUX_CFLAGS) -I/usr/athena/include \
+		-I../../regex-0.12 url_translate.c
 
 hdf-browse.o: hdf-browse.c ../libhtmlw/HTML.h
 	$(CC) -c $(CFLAGS) $(AUX_CFLAGS) hdf-browse.c
--- src/mo-www.c.orig	Tue Aug  8 06:14:25 1995
+++ src/mo-www.c	Tue Oct  3 12:49:21 1995
@@ -112,6 +112,8 @@
 extern char *post_content_type;
 extern char *post_data;
 
+extern char *url_translate(char *url, char **redirect);
+
 
 /****************************************************************************
  * name:    hack_htmlsrc (PRIVATE)
@@ -207,7 +209,8 @@
 {
   char *msg;
   int rv;
-  extern char *use_this_url_instead;
+  extern char *use_this_url_instead, *redirecting_url;
+  char *new_url, *translate_redirect = 0;
 
   /* Hmmmmmmm... */
   if (HTMainText)
@@ -216,7 +219,15 @@
       HTMainText = NULL;
     }
 
-  rv = HTLoadAbsolute (url);
+  new_url = url_translate(url, &translate_redirect);
+  rv = HTLoadAbsolute (new_url);
+  if (translate_redirect) {
+	  if (use_this_url_instead == 0) {
+		  use_this_url_instead = translate_redirect;
+		  redirecting_url = translate_redirect;
+	  } else
+		  free(translate_redirect);
+  } 
   if (rv == 1)
     {
       char *txt = hack_htmlsrc ();
@@ -399,7 +410,7 @@
   force_dump_to_file = 1;
   force_dump_filename = fnam;
 
-  rv = HTLoadAbsolute (url);
+  rv = HTLoadAbsolute (url_translate(url, 0));
   if (rv == 1)
     {
       force_dump_to_file = 0;
--- /dev/null	Wed Oct  4 12:51:47 1995
+++ src/url_translate.c	Tue Oct  3 15:00:07 1995
@@ -0,0 +1,362 @@
+/*
+ * url_translate.c --- do URL transmogrifications using regular
+ * expresson matching and replacing
+ */
+
+#define MAX_URL_LEN 2048
+
+#define DEBUG
+#define LOCKER
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <pwd.h>
+#include <ctype.h>
+#include "regex.h"
+#ifdef LOCKER
+#include <hesiod.h>
+#endif
+
+#define LOCAL_TRANSLATION_FILE ".url_translations"
+#define TRANSLATION_FILE "/afs/net/admin/www/lib/url_translations"
+
+struct translate_pat {
+	char	*match;
+	char	*replace;
+	struct translate_pat *next;
+};
+
+struct translate_pat *patterns = NULL;
+
+static int initialized = 0;
+static int do_debug = 0;
+static int notranslate = 0;
+static int nomasterfile = 0;
+
+static int match_replace(char *regex, char *input, char *replace,
+		  char *output, int maxsize)
+{
+	regex_t	re;
+	int	retval;
+	regmatch_t *pmatch;
+	int	i;
+	int	match;
+	char	*p = replace, *q;
+	int	size = maxsize-1;
+	
+	retval = regcomp(&re, regex, REG_EXTENDED);
+	if (retval)
+		return -1;
+	pmatch = malloc(sizeof(regmatch_t) * 10);
+	retval = regexec(&re, input, 10, pmatch, 0);
+	if (retval == REG_NOMATCH) {
+		regfree(&re);
+		free(pmatch);
+		return 0;
+	}
+	if (retval) {
+		regfree(&re);
+		free(pmatch);
+		return -1;
+	}
+	for(p = replace, q=output; *p; p++) {
+		if (*p == '\\' && *(p+1) >= '0' && *(p+1) <= '9') {
+			p++;
+			match = *p - '0';
+			for (i = pmatch[match].rm_so;
+			     i < pmatch[match].rm_eo; i++) {
+				*q++ = input[i];
+				if (!--size)
+					goto finish;
+			}
+		} else {
+			*q++ = *p;
+			if (!--size)
+				goto finish;
+		}
+		
+	}
+finish:
+	regfree(&re);
+	free(pmatch);
+	*q = '\0';
+	return 1;
+}
+
+static char *url_strdup(char *s)
+{
+	char *r;
+
+	r = malloc(strlen(s)+1);
+	if (!r)
+		return NULL;
+	strcpy(r, s);
+	return r;
+}
+
+static void read_translation_patterns(char *filename, FILE *f)
+{
+	char	buf[1024];
+	char	*s;
+	char	*match, *replace;
+	char	*base = 0;
+	struct translate_pat *pat;
+	struct translate_pat *last;
+
+	if (!f)
+		f = fopen(filename, "r");
+	if (!f)
+		return;
+
+	if (do_debug && filename)
+		printf("Reading in translation file %s....\n", filename);
+	
+	for (last = patterns; last && last->next; last = last->next);
+	
+	while (!feof(f)) {
+		if (!fgets(buf, sizeof(buf), f))
+			break;
+		if (buf[0] == '#')
+			continue;
+		s = strchr(buf, '\n');
+		if (s)
+		    *s = '\0';
+		if (buf[0] == 0)
+		    continue;
+		match = &buf[0];
+		s = match;
+		while (*s && !isspace(*s))
+		    s++;
+		if (s == 0) {
+		    printf("Badly formed line in translation file:\n\t%s\n",
+			   buf);
+		    continue;
+		}
+		*s = '\0';
+		do {
+		    s++;
+		} while (*s && isspace(*s));
+		replace = s;
+
+		if (strcmp(match, "base") == 0) {
+		    if (base)
+			free(base);
+		    base = url_strdup(replace);
+		    continue;
+		}
+
+		if (strcmp(match, "debug") == 0) {
+		    do_debug = 1;
+		    continue;
+		}
+		
+		if (strcmp(match, "notranslate") == 0) {
+		    notranslate = 1;
+		    continue;
+		}
+
+		if (strcmp(match, "nomasterfile") == 0) {
+		    nomasterfile = 1;
+		    continue;
+		}
+		
+		pat = malloc(sizeof(struct translate_pat));
+		if (base) {
+		    pat->match = malloc(strlen(base) + strlen(match) + 1);
+		    strcpy(pat->match, base);
+		    strcat(pat->match, match);
+		} else {
+		    pat->match = url_strdup(match);
+		}
+		pat->replace= url_strdup(replace);
+		pat->next = 0;
+#ifdef TESTING
+		printf("match=%s, replace=%s\n", pat->match, pat->replace);
+#endif
+		if (last)
+			last->next = pat;
+		else
+			patterns = pat;
+		last = pat;
+	}
+	if (base)
+	    free(base);
+	fclose(f);
+}
+
+void initialize_url_translations()
+{
+	FILE	*f;
+	struct passwd *pwd;
+	char filename[1024];
+
+	pwd = getpwuid(getuid());
+	if (pwd) {
+		sprintf(filename, "%s/%s", pwd->pw_dir,
+			LOCAL_TRANSLATION_FILE);
+		read_translation_patterns(filename, NULL);
+	}
+	if (!nomasterfile)
+	    read_translation_patterns(TRANSLATION_FILE, NULL);
+	initialized++;
+}
+
+#ifdef LOCKER
+static char* lookup_locker (char* locker)
+{
+    char **cpp, *hesi, *ret = NULL;
+
+    cpp = hes_resolve(locker, "filsys");
+    if (cpp == 0)
+	return NULL;
+    
+    hesi = *cpp;         /* we only look at the first locker entry */
+    if (hesi && !strncmp(hesi,"AFS ",4)) {
+	char *spc;
+
+	hesi += 4;               /* skip "AFS " */
+
+	spc = strchr(hesi, 32);  /* strip the remaining fields */
+	if (spc) *spc='\0';
+
+	ret = (char*)malloc(strlen(hesi)+1);
+
+	if (ret) {
+	    strcpy(ret, hesi);
+	}
+    }
+    while (*cpp) {
+	free(*cpp);
+	cpp++;
+    }
+    return ret;
+}
+
+char *locker_translate(char *orig_url, char *url, char **redirect)
+{
+    char *lockername, *lpath, *end;
+    static char buf[MAX_URL_LEN];
+    
+    if (strncmp(url, "file://localhost/~", 18) == 0)
+	lockername = url_strdup(url+18);
+    else if (strncmp(url, "file:/~", 7))
+	lockername = url_strdup(url+7);
+    else
+	return url;
+    end = strchr(lockername, '/');
+    if (end)
+	*end++ = 0;
+    lpath = lookup_locker(lockername);
+    if (lpath) {
+	sprintf(buf, "file://localhost%s/%s", lpath, end);
+	free(lpath);
+	free(lockername);
+	if (do_debug)
+	    printf("==> %s\n", buf);
+	return buf;
+    }
+    free(lockername);
+    return url;
+}
+#endif
+
+char *regex_translate(char *url, char **redirect)
+{
+	struct translate_pat *p;
+	static char	buf[MAX_URL_LEN];
+	int	retval;
+	
+	for (p = patterns; p; p = p->next) {
+		retval = match_replace(p->match, url, p->replace,
+				       buf, sizeof(buf));
+		if (retval == 1) {
+		    if (do_debug)
+			printf("'%s' --> '%s'\n", url, buf);
+		    return(buf);
+		}
+	}
+	return url;
+}
+
+char *append_list[] = { "/index.html", ".gif", ".jpg", ".jpeg", ".tiff",
+			    ".tif", ".html", ".ps", ".Z", ".gz", 0 };
+
+char *append_translate(char *orig_url, char *url, char **redirect)
+{
+    static char buf[MAX_URL_LEN];
+    struct stat st;
+    char *filepath;
+    char **p;
+    int start = 1;
+
+    if (strncmp(url, "file://localhost/", 17) == 0)
+	filepath = url+16;
+    else if (strncmp(url, "file:/", 6) == 0)
+	filepath = url+5;
+    else
+	return url;
+    if (stat(filepath, &st) == 0) {
+	if (!S_ISDIR(st.st_mode))
+	    return url;
+	start = 0;
+    }
+    for (p = &append_list[start]; *p; p++) {
+	strcpy(buf, filepath);
+	strcat(buf, *p);
+	if (access(buf, F_OK) == 0) {
+	    strcpy(buf, url);
+	    strcat(buf, *p);
+	    if (do_debug)
+		printf("-=-=> %s\n", buf);
+	    if (**p == '/' && redirect) {
+		    if (*redirect)
+			    free(*redirect);
+		    *redirect = malloc(strlen(orig_url)+strlen(*p)+1);
+		    if (*redirect) {
+			    strcpy(*redirect, orig_url);
+			    strcat(*redirect, *p);
+		    }
+	    }
+	    return buf;
+	}
+    }
+    return url;
+}    
+	
+char *url_translate(char *url, char **redirect)
+{
+    char *orig_url = url;
+    
+    if (!initialized)
+	initialize_url_translations();
+	
+    if (notranslate)
+	return url;
+    
+    url = regex_translate(url, redirect);
+    if (url != orig_url) {
+#ifdef LOCKER
+	url = locker_translate(orig_url, url, redirect);
+#endif
+	url = append_translate(orig_url, url, redirect);
+    }
+    return url;
+}
+
+
+#if TESTING
+main(int argc, char **argv)
+{
+	int	retval;
+	char	buff[1024];
+
+	do_debug = 1;
+	printf("%s\n", url_translate(argv[1]));
+	exit(0);
+}
+#endif
+	
