123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- #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;
- }
|