#include <u.h>
#include <libc.h>
#include <draw.h>
#include <memdraw.h>
#include <thread.h>
#include <cursor.h>
#include <mouse.h>
#include <keyboard.h>
#include <frame.h>
#include <plumb.h>
#include <html.h>
#include "dat.h"
#include "fns.h"
Url *
urlalloc(Runestr *src, Runestr *post, int m)
{
Url *u;
u = emalloc(sizeof(Url));
copyrunestr(&u->src, src);
if(m==HPost)
copyrunestr(&u->post, post);
u->method = m;
incref(u);
return u;
}
void
urlfree(Url *u)
{
if(u==nil || decref(u) > 0)
return;
closerunestr(&u->src);
closerunestr(&u->act);
closerunestr(&u->post);
closerunestr(&u->ctype);
free(u);
}
Url *
urldup(Url *a)
{
Url *b;
b = emalloc(sizeof(Url));
b->method = a->method;
copyrunestr(&b->src, &a->src);
copyrunestr(&b->act, &a->act);
copyrunestr(&b->post, &a->post);
copyrunestr(&b->ctype, &a->ctype);
return b;
}
static Runestr
getattr(int conn, char *s)
{
char buf[BUFSIZE];
int fd, n;
snprint(buf, sizeof buf, "%s/%d/%s", webmountpt, conn, s);
fd = open(buf, OREAD);
if(fd < 0)
error("can't open attr file");
n = read(fd, buf, sizeof(buf)-1);
if(n < 0)
error("can't read");
close(fd);
buf[n] = '\0';
return (Runestr){runesmprint("%s", buf), n};
}
// tired of typing http://, tired of going to google first.
void
justgoogleit(Url *u)
{
char *s;
s = ucvt(u->src.r+2);
free(u->src.r);
u->src.r = runesmprint("http://www.google.com/search?hl=en&ie=UTF-8&q=%s", s);
free(s);
u->src.nr = runestrlen(u->src.r);
}
void
addhttp(Url *u)
{
Rune *s;
if(validurl(u->src.r))
return;
s = u->src.r;
u->src.r = runesmprint("http://%S", u->src.r);
free(s);
u->src.nr = runestrlen(u->src.r);
}
struct{
void (*f)(Url*);
Rune *lead;
int len;
} ctab[] = {
justgoogleit, L"g ", 2,
addhttp, L"", 0,
};
void
urlconvience(Url *u)
{
int i;
for(i = 0; u->src.nr >= ctab[i].len && runestrncmp(u->src.r, ctab[i].lead, ctab[i].len) != 0; i++)
;
ctab[i].f(u);
}
int
urlopen(Url *u)
{
char buf[BUFSIZE];
int cfd, fd, conn, n;
urlconvience(u);
snprint(buf, sizeof(buf), "%s/clone", webmountpt);
cfd = open(buf, ORDWR);
if(cfd < 0)
error("can't open clone file");
n = read(cfd, buf, sizeof(buf)-1);
if(n <= 0)
error("reading clone");
buf[n] = '\0';
conn = atoi(buf);
snprint(buf, sizeof(buf), "url %S", u->src.r);
if(write(cfd, buf, strlen(buf)) < 0){
// fprint(2, "write: %s: %r\n", buf);
Err:
close(cfd);
return -1;
}
if(u->method==HPost && u->post.r != nil){
snprint(buf, sizeof(buf), "%s/%d/postbody", webmountpt, conn);
fd = open(buf, OWRITE);
if(fd < 0){
// fprint(2, "urlopen: bad query: %s: %r\n", buf);
goto Err;
}
snprint(buf, sizeof(buf), "%S", u->post.r);
if(write(fd, buf, strlen(buf)) < 0)
fprint(2, "urlopen: bad query: %s: %r\n", buf);
close(fd);
}
snprint(buf, sizeof(buf), "%s/%d/body", webmountpt, conn);
fd = open(buf, OREAD);
if(fd < 0){
// fprint(2, "open: %S: %r\n", u->src.r);
goto Err;
}
u->ctype = getattr(conn, "contenttype");
u->act = getattr(conn, "parsed/url");
if(u->act.nr == 0)
copyrunestr(&u->act, &u->src);
close(cfd);
return fd;
}
void
urlcanon(Rune *name)
{
Rune *s, *e, *tail, tailr;
Rune **comp, **p, **q;
int n;
name = runestrstr(name, L"://");
if(name == nil)
return;
name = runestrchr(name+3, '/');
if(name == nil)
return;
if(*name == L'/')
name++;
n = 0;
for(e = name; *e != 0; e++)
if(*e == L'/')
n++;
comp = emalloc((n+2)*sizeof *comp);
/*
* Break the name into a list of components
*/
p = comp;
*p++ = name;
tail = nil;
tailr = L'☺'; /* silence compiler */
for(s = name; *s != 0; s++){
if(*s == '?' || *s == '#'){
tail = s+1;
tailr = *s;
*s = 0;
break;
}
else if(*s == L'/'){
*p++ = s+1;
*s = 0;
}
}
/*
* go through the component list, deleting components that are empty (except
* the last component) or ., and any .. and its predecessor.
*/
for(p = q = comp; *p != nil; p++){
if(runestrcmp(*p, L"") == 0 && p[1] != nil
|| runestrcmp(*p, L".") == 0)
continue;
else if(q>comp && runestrcmp(*p, L"..") == 0 && runestrcmp(q[-1], L"..") != 0)
q--;
else
*q++ = *p;
}
*q = nil;
/*
* rebuild the path name
*/
s = name;
for(p = comp; p<q; p++){
n = runestrlen(*p);
memmove(s, *p, sizeof(Rune)*n);
s += n;
if(p[1] != nil)
*s++ = '/';
}
*s = 0;
if(tail)
runeseprint(s, e+1, "%C%S", tailr, tail);
free(comp);
}
/* this is a HACK */
Rune*
urlcombine(Rune *b, Rune *u)
{
Rune *p, *q, *sep, *s;
Rune endrune[] = { L'?', L'#' };
int i, restore;
if(u == nil)
error("urlcombine: u == nil");
if(validurl(u))
return erunestrdup(u);
if(b==nil || !validurl(b))
error("urlcombine: b==nil || !validurl(b)");
if(runestrncmp(u, L"//", 2) == 0){
q = runestrchr(b, L':');
return runesmprint("%.*S:%S", (int)(q-b), b, u);
}
p = runestrstr(b, L"://");
if(p != nil)
p += 3;
sep = L"";
q = nil;
if(*u ==L'/')
q = runestrchr(p, L'/');
else if(*u==L'#' || *u==L'?'){
for(i=0; i<nelem(endrune); i++)
if(q = runestrchr(p, endrune[i]))
break;
}else if(p != nil){
sep = L"/";
restore = 0;
s = runestrchr(p, L'?');
if(s != nil){
*s = '\0';
restore = 1;
}
q = runestrrchr(p, L'/');
if(restore)
*s = L'?';
}else
sep = L"/";
if(q == nil)
p = runesmprint("%S%S%S", b, sep, u);
else
p = runesmprint("%.*S%S%S", (int)(q-b), b, sep, u);
urlcanon(p);
return p;
}
|