Plan 9 from Bell Labs’s /usr/web/sources/patch/applied/httpd-host-port/redirect.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <bio.h>
#include "httpd.h"
#include "httpsrv.h"

enum
{
	HASHSIZE = 1019,
};

typedef struct Redir	Redir;
struct Redir
{
	Redir	*next;
	char	*pat;
	char	*repl;
};

static Redir *redirtab[HASHSIZE];
static Redir *vhosttab[HASHSIZE];
static char emptystring[1];

static int 
hashasu(char *key, int n)
{
        ulong h;

	h = 0;
        while(*key != 0)
                h = 65599*h + *(uchar*)key++;
        return h % n;
}

static void
insert(Redir **tab, char *pat, char *repl)
{
	Redir **l;
	Redir *srch;
	ulong hash;

	hash = hashasu(pat, HASHSIZE);
	for(l = &tab[hash]; *l; l = &(*l)->next)
		;
	*l = srch = ezalloc(sizeof(Redir));
	srch->pat = pat;
	srch->repl = repl;
	srch->next = 0;
}

static void
cleartab(Redir **tab)
{	
	Redir *t;
	int i;

	for(i = 0; i < HASHSIZE; i++){
		while((t = tab[i]) != nil){
			tab[i] = t->next;
			free(t->pat);
			free(t->repl);
			free(t);
		}
	}
}

void
redirectinit(void)
{
	static Biobuf *b = nil;
	static Qid qid;
	char *file, *line, *s, *host, *field[3];

	file = "/sys/lib/httpd.rewrite";
	if(b != nil){
		if(updateQid(Bfildes(b), &qid) == 0)
			return;
		Bterm(b);
	}
	b = Bopen(file, OREAD);
	if(b == nil)
		sysfatal("can't read from %s", file);
	updateQid(Bfildes(b), &qid);

	cleartab(redirtab);
	cleartab(vhosttab);

	while((line = Brdline(b, '\n')) != nil){
		line[Blinelen(b)-1] = 0;
		s = strchr(line, '#');
		if(s != nil)
			*s = '\0'; 	/* chop comment */
		if(tokenize(line, field, nelem(field)) == 2){
			if(strncmp(field[0], "http://", STRLEN("http://")) == 0 &&
					strncmp(field[1], "http://", STRLEN("http://")) != 0){
				host = field[0]+STRLEN("http://");
				s = strpbrk(host, "/");
				if(s)
					*s = 0;  /* chop trailing slash */
				
				insert(vhosttab, estrdup(host), estrdup(field[1]));
			}else{
				insert(redirtab, estrdup(field[0]), estrdup(field[1]));
			}
		}
	}
	syslog(0, HTTPLOG, "redirectinit pid=%d", getpid());
}

static Redir*
lookup(Redir **tab, char *pat)
{
	Redir *srch;
	ulong hash;

	hash = hashasu(pat,HASHSIZE);
	for(srch = tab[hash]; srch != nil; srch = srch->next)
		if(strcmp(pat, srch->pat) == 0)
			return srch;
	return nil;
}

static char*
prevslash(char *p, char *s)
{
	while(--s > p)
		if(*s == '/')
			break;
	return s;
}

char*
redirect(HConnect *hc, char *path)
{
	Redir *redir;
	char *s, *newpath;
	int c, n;

	for(s = strchr(path, '\0'); s > path; s = prevslash(path, s)){
		c = *s;
		*s = '\0';
		redir = lookup(redirtab, path);
		*s = c;
		if(redir != nil){
			n = strlen(redir->repl) + strlen(s) + 2 + UTFmax;
			newpath = halloc(hc, n);
			snprint(newpath, n, "%s%s", redir->repl, s);
			return newpath;
		}
	}
	return nil;
}

// if host is virtual, return implicit prefix for URI within webroot.
// if not, return empty string
// return value should not be freed by caller
char*
masquerade(char *host)
{
	Redir *redir;

	redir = lookup(vhosttab, host);
	if(redir != nil)
		return redir->repl;
	return emptystring;
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.