mothra/webfs: multipart/form-data and file upload support
This commit is contained in:
parent
9428062b55
commit
ae311094ad
7 changed files with 221 additions and 130 deletions
|
@ -50,6 +50,7 @@ enum{
|
|||
TEXTWIN,
|
||||
HIDDEN,
|
||||
INDEX,
|
||||
FILE,
|
||||
};
|
||||
struct Option{
|
||||
int selected;
|
||||
|
@ -59,12 +60,13 @@ struct Option{
|
|||
Option *next;
|
||||
};
|
||||
|
||||
#define BOUNDARY "hjdicksHjDiCkSHJDICKS"
|
||||
#define BOUNDARY "nAboJ9uN6ZXsqoVGzLAdjKq97TWDTGjo"
|
||||
|
||||
void h_checkinput(Panel *, int, int);
|
||||
void h_radioinput(Panel *, int, int);
|
||||
void h_submitinput(Panel *, int);
|
||||
void h_buttoninput(Panel *, int);
|
||||
void h_fileinput(Panel *, int);
|
||||
void h_submittype(Panel *, char *);
|
||||
void h_submitindex(Panel *, char *);
|
||||
void h_resetinput(Panel *, int);
|
||||
|
@ -167,14 +169,11 @@ void rdform(Hglob *g){
|
|||
f->type=SUBMIT;
|
||||
else if(cistrcmp(s, "button")==0)
|
||||
f->type=BUTTON;
|
||||
else if(cistrcmp(s, "image")==0){
|
||||
/* presotto's egregious hack to make image submits do something */
|
||||
if(f->name){
|
||||
free(f->name);
|
||||
f->name=0;
|
||||
}
|
||||
f->type=SUBMIT;
|
||||
} else if(cistrcmp(s, "reset")==0)
|
||||
else if(cistrcmp(s, "image")==0)
|
||||
f->type=FILE;
|
||||
else if(cistrcmp(s, "file")==0)
|
||||
f->type=FILE;
|
||||
else if(cistrcmp(s, "reset")==0)
|
||||
f->type=RESET;
|
||||
else if(cistrcmp(s, "hidden")==0)
|
||||
f->type=HIDDEN;
|
||||
|
@ -243,6 +242,8 @@ void rdform(Hglob *g){
|
|||
*g->tp++=' ';
|
||||
o->def=pl_hasattr(g->attr, "selected");
|
||||
o->selected=o->def;
|
||||
if(pl_hasattr(g->attr, "disabled"))
|
||||
o->selected=0;
|
||||
s=pl_getattr(g->attr, "value");
|
||||
if(s==0)
|
||||
o->value=o->label+1;
|
||||
|
@ -369,6 +370,9 @@ void mkfieldpanel(Rtext *t){
|
|||
case BUTTON:
|
||||
f->p=plbutton(0, 0, f->value[0]?f->value:"button", h_buttoninput);
|
||||
break;
|
||||
case FILE:
|
||||
f->p=plbutton(0, 0, f->value[0]?f->value:"file", h_fileinput);
|
||||
break;
|
||||
case SELECT:
|
||||
f->pulldown=plgroup(0,0);
|
||||
scrl=plscrollbar(f->pulldown, PACKW|FILLY);
|
||||
|
@ -453,6 +457,25 @@ void h_resetinput(Panel *p, int){
|
|||
}
|
||||
void h_buttoninput(Panel *p, int){
|
||||
}
|
||||
void h_fileinput(Panel *p, int){
|
||||
char name[NNAME];
|
||||
Field *f;
|
||||
|
||||
f = p->userp;
|
||||
nstrcpy(name, f->value, sizeof(name));
|
||||
free(f->value);
|
||||
f->state=0;
|
||||
for(;;){
|
||||
if(eenter("Upload file", name, sizeof(name), &mouse) <= 0)
|
||||
break;
|
||||
if(access(name, AREAD) == 0){
|
||||
f->state=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
f->value = strdup(name);
|
||||
pldraw(f->p, screen);
|
||||
}
|
||||
|
||||
/*
|
||||
* If there's exactly one button with type=text, then
|
||||
|
@ -478,25 +501,24 @@ void mencodeform(Form *form, int fd){
|
|||
Rune *rp;
|
||||
int n;
|
||||
|
||||
#define SEPS "-----------------------------" BOUNDARY
|
||||
#define NEXT "\r\n" SEPS
|
||||
|
||||
sep = SEPS;
|
||||
for(f=form->fields;f;f=f->next){
|
||||
switch(f->type){
|
||||
sep = "--" BOUNDARY;
|
||||
for(f=form->fields;f;f=f->next)switch(f->type){
|
||||
case TYPEIN:
|
||||
case PASSWD:
|
||||
fprint(fd, "%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n%s",
|
||||
sep, f->name, plentryval(f->p));
|
||||
sep = NEXT;
|
||||
sep = "\r\n--" BOUNDARY;
|
||||
break;
|
||||
case CHECK:
|
||||
case RADIO:
|
||||
if(!f->state) break;
|
||||
case SUBMIT:
|
||||
case HIDDEN:
|
||||
if(f->name==0 || f->value==0)
|
||||
continue;
|
||||
fprint(fd, "%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n%s",
|
||||
sep, f->name, f->value);
|
||||
sep = NEXT;
|
||||
sep = "\r\n--" BOUNDARY;
|
||||
break;
|
||||
case SELECT:
|
||||
if(f->name==0)
|
||||
|
@ -505,7 +527,7 @@ void mencodeform(Form *form, int fd){
|
|||
if(o->selected && o->value){
|
||||
fprint(fd, "%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n%s",
|
||||
sep, f->name, o->value);
|
||||
sep = NEXT;
|
||||
sep = "\r\n--" BOUNDARY;
|
||||
}
|
||||
break;
|
||||
case TEXTWIN:
|
||||
|
@ -524,10 +546,30 @@ void mencodeform(Form *form, int fd){
|
|||
*p = 0;
|
||||
fprint(fd, "%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n%s",
|
||||
sep, f->name, b);
|
||||
sep = NEXT;
|
||||
sep = "\r\n--" BOUNDARY;
|
||||
free(b);
|
||||
break;
|
||||
}
|
||||
for(f=form->fields;f;f=f->next)if(f->type == FILE){
|
||||
char buf[1024];
|
||||
int ifd;
|
||||
|
||||
if(f->name==0 || f->value[0]==0)
|
||||
continue;
|
||||
if(p = strrchr(f->value, '/'))
|
||||
p++;
|
||||
if(p == 0 || *p == 0)
|
||||
p = f->value;
|
||||
if((ifd = open(f->value, OREAD)) < 0)
|
||||
continue;
|
||||
if(filetype(ifd, buf, sizeof(buf)) < 0)
|
||||
strcpy(buf, "application/octet-stream");
|
||||
fprint(fd, "%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\""
|
||||
"\r\nContent-Type: %s\r\n\r\n", sep, f->name, p, buf);
|
||||
while((n = read(ifd, buf, sizeof(buf))) > 0)
|
||||
write(fd, buf, n);
|
||||
close(ifd);
|
||||
sep = "\r\n--" BOUNDARY;
|
||||
}
|
||||
fprint(fd, "%s--\r\n", sep);
|
||||
}
|
||||
|
@ -553,6 +595,7 @@ void uencodeform(Form *form, int fd){
|
|||
case CHECK:
|
||||
case RADIO:
|
||||
if(!f->state) break;
|
||||
case SUBMIT:
|
||||
case HIDDEN:
|
||||
if(f->name==0 || f->value==0)
|
||||
continue;
|
||||
|
|
|
@ -258,6 +258,7 @@ void plegetsel(Panel *p, int *sel0, int *sel1){
|
|||
int plelen(Panel *p){
|
||||
Textwin *t;
|
||||
t=((Edit *)p->data)->t;
|
||||
if(t==0) return 0;
|
||||
return t->etext-t->text;
|
||||
}
|
||||
Rune *pleget(Panel *p){
|
||||
|
|
|
@ -23,7 +23,6 @@ Panel *cururl; /* label giving the url of the visible text */
|
|||
Panel *list; /* list of previously acquired www pages */
|
||||
Panel *msg; /* message display */
|
||||
Panel *menu3; /* button 3 menu */
|
||||
Mouse mouse; /* current mouse data */
|
||||
char mothra[] = "mothra!";
|
||||
Cursor patientcurs={
|
||||
0, 0,
|
||||
|
|
|
@ -96,10 +96,11 @@ void freeform(void *p);
|
|||
int Ufmt(Fmt *f);
|
||||
#pragma varargck type "U" char*
|
||||
void message(char *, ...);
|
||||
int snooptype(int fd);
|
||||
int filetype(int, char *, int);
|
||||
int snooptype(int);
|
||||
void mkfieldpanel(Rtext *);
|
||||
void geturl(char *, int, int, int);
|
||||
int urlpost(Url*, char*);
|
||||
int urlget(Url*, int);
|
||||
char version[];
|
||||
|
||||
Mouse mouse;
|
||||
|
|
|
@ -8,6 +8,32 @@
|
|||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
static void
|
||||
kickwqr(Buq *q, Req *r)
|
||||
{
|
||||
Buf **bb, *b;
|
||||
int l;
|
||||
|
||||
for(bb = &q->bh; q->nwq > 0; bb = &b->next){
|
||||
if((b = *bb) == nil)
|
||||
break;
|
||||
if(b->wreq == nil || (b->wreq != r && r != nil))
|
||||
continue;
|
||||
l = b->ep - b->rp;
|
||||
b = realloc(b, sizeof(*b) + l);
|
||||
*bb = b;
|
||||
if(b->next == nil)
|
||||
q->bt = &b->next;
|
||||
memmove(b->end, b->rp, l);
|
||||
b->rp = b->end;
|
||||
b->ep = b->rp + l;
|
||||
b->wreq->ofcall.count = b->wreq->ifcall.count;
|
||||
respond(b->wreq, q->error);
|
||||
b->wreq = nil;
|
||||
q->nwq--;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
matchreq(Buq *q)
|
||||
{
|
||||
|
@ -47,10 +73,13 @@ matchreq(Buq *q)
|
|||
if(r = b->wreq){
|
||||
r->ofcall.count = r->ifcall.count;
|
||||
respond(r, nil);
|
||||
q->nwq--;
|
||||
}
|
||||
free(b);
|
||||
}
|
||||
}
|
||||
if(q->closed && q->nwq > 0)
|
||||
kickwqr(q, nil);
|
||||
rwakeupall(&q->rz);
|
||||
}
|
||||
|
||||
|
@ -136,8 +165,8 @@ buclose(Buq *q, char *error)
|
|||
if(error)
|
||||
q->error = estrdup9p(error);
|
||||
q->closed = 1;
|
||||
matchreq(q);
|
||||
}
|
||||
matchreq(q);
|
||||
qunlock(q);
|
||||
}
|
||||
|
||||
|
@ -188,7 +217,7 @@ bureq(Buq *q, Req *r)
|
|||
return;
|
||||
case Twrite:
|
||||
l = r->ifcall.count;
|
||||
if((q->size + l) < q->limit){
|
||||
if(!q->closed && (q->size + l) < q->limit){
|
||||
r->ofcall.count = buwrite(q, r->ifcall.data, r->ifcall.count);
|
||||
respond(r, nil);
|
||||
return;
|
||||
|
@ -202,6 +231,7 @@ bureq(Buq *q, Req *r)
|
|||
*q->bt = b;
|
||||
q->bt = &b->next;
|
||||
q->size += l;
|
||||
q->nwq++;
|
||||
break;
|
||||
case Tread:
|
||||
case Topen:
|
||||
|
@ -218,9 +248,7 @@ bureq(Buq *q, Req *r)
|
|||
void
|
||||
buflushreq(Buq *q, Req *r)
|
||||
{
|
||||
Buf **bb, *b;
|
||||
Req **rr;
|
||||
int l;
|
||||
|
||||
switch(r->ifcall.type){
|
||||
default:
|
||||
|
@ -228,23 +256,7 @@ buflushreq(Buq *q, Req *r)
|
|||
return;
|
||||
case Twrite:
|
||||
qlock(q);
|
||||
for(bb = &q->bh; b = *bb; bb = &b->next){
|
||||
if(b->wreq != r)
|
||||
continue;
|
||||
/* fake successfull write */
|
||||
l = b->ep - b->rp;
|
||||
b = realloc(b, sizeof(*b) + l);
|
||||
memmove(b->end, b->rp, l);
|
||||
b->rp = b->end;
|
||||
b->ep = b->rp + l;
|
||||
b->wreq = nil;
|
||||
*bb = b;
|
||||
if(b->next == nil)
|
||||
q->bt = &b->next;
|
||||
r->ofcall.count = r->ifcall.count;
|
||||
respond(r, nil);
|
||||
break;
|
||||
}
|
||||
kickwqr(q, r);
|
||||
break;
|
||||
case Topen:
|
||||
case Tread:
|
||||
|
|
|
@ -51,6 +51,7 @@ struct Buq
|
|||
int closed;
|
||||
int limit;
|
||||
int size;
|
||||
int nwq;
|
||||
|
||||
/* write buffers */
|
||||
Buf *bh;
|
||||
|
|
|
@ -22,6 +22,7 @@ struct Hconn
|
|||
long time;
|
||||
|
||||
int fd;
|
||||
int ctl;
|
||||
int keep;
|
||||
int cancel;
|
||||
int len;
|
||||
|
@ -64,7 +65,7 @@ hdial(Url *u)
|
|||
{
|
||||
char addr[128];
|
||||
Hconn *h, *p;
|
||||
int fd, ofd;
|
||||
int fd, ctl, ofd;
|
||||
|
||||
snprint(addr, sizeof(addr), "tcp!%s!%s", u->host, u->port ? u->port : u->scheme);
|
||||
|
||||
|
@ -85,7 +86,7 @@ hdial(Url *u)
|
|||
if(debug)
|
||||
fprint(2, "hdial [%d] %s\n", hpool.active, addr);
|
||||
|
||||
if((fd = dial(addr, 0, 0, 0)) < 0)
|
||||
if((fd = dial(addr, 0, 0, &ctl)) < 0)
|
||||
return nil;
|
||||
if(strcmp(u->scheme, "https") == 0){
|
||||
TLSconn *tc;
|
||||
|
@ -97,9 +98,11 @@ hdial(Url *u)
|
|||
free(tc->cert);
|
||||
free(tc->sessionID);
|
||||
free(tc);
|
||||
if(fd < 0)
|
||||
if(fd < 0){
|
||||
close(ctl);
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
h = emalloc(sizeof(*h));
|
||||
h->next = nil;
|
||||
|
@ -108,6 +111,7 @@ hdial(Url *u)
|
|||
h->keep = 1;
|
||||
h->len = 0;
|
||||
h->fd = fd;
|
||||
h->ctl = ctl;
|
||||
nstrcpy(h->addr, addr, sizeof(h->addr));
|
||||
|
||||
return h;
|
||||
|
@ -208,11 +212,23 @@ hclose(Hconn *h)
|
|||
if(debug)
|
||||
fprint(2, "hclose [%d] %s\n", hpool.active, h->addr);
|
||||
|
||||
if(h->ctl >= 0)
|
||||
close(h->ctl);
|
||||
if(h->fd >= 0)
|
||||
close(h->fd);
|
||||
free(h);
|
||||
}
|
||||
|
||||
static void
|
||||
hhangup(Hconn *h)
|
||||
{
|
||||
if(debug)
|
||||
fprint(2, "hangup pc=%p: %r\n", getcallerpc(&h));
|
||||
h->keep = 0;
|
||||
if(h->ctl >= 0)
|
||||
hangup(h->ctl);
|
||||
}
|
||||
|
||||
static int
|
||||
hread(Hconn *h, void *data, int len)
|
||||
{
|
||||
|
@ -225,8 +241,10 @@ hread(Hconn *h, void *data, int len)
|
|||
memmove(h->buf, h->buf + len, h->len);
|
||||
return len;
|
||||
}
|
||||
if((len = read(h->fd, data, len)) <= 0)
|
||||
if((len = read(h->fd, data, len)) == 0)
|
||||
h->keep = 0;
|
||||
if(len < 0)
|
||||
hhangup(h);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -234,7 +252,7 @@ static int
|
|||
hwrite(Hconn *h, void *data, int len)
|
||||
{
|
||||
if(write(h->fd, data, len) != len){
|
||||
h->keep = 0;
|
||||
hhangup(h);
|
||||
return -1;
|
||||
}
|
||||
return len;
|
||||
|
@ -281,7 +299,7 @@ hline(Hconn *h, char *data, int len, int cont)
|
|||
if(h->len >= sizeof(h->buf))
|
||||
return 0;
|
||||
if((n = read(h->fd, h->buf + h->len, sizeof(h->buf) - h->len)) <= 0){
|
||||
h->keep = 0;
|
||||
hhangup(h);
|
||||
return -1;
|
||||
}
|
||||
h->len += n;
|
||||
|
@ -431,7 +449,7 @@ catch(void *, char *msg)
|
|||
void
|
||||
http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost)
|
||||
{
|
||||
int i, l, n, try, pid, fd, cfd, chunked, retry, nobody;
|
||||
int i, l, n, try, pid, fd, cfd, needlength, chunked, retry, nobody;
|
||||
char *s, *x, buf[8192+2], status[256], method[16];
|
||||
vlong length, offset;
|
||||
Url ru, tu, *nu;
|
||||
|
@ -470,10 +488,11 @@ http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost)
|
|||
|
||||
h = nil;
|
||||
pid = 0;
|
||||
werrstr("too many errors");
|
||||
needlength = 0;
|
||||
for(try = 0; try < 6; try++){
|
||||
strcpy(status, "0 No status");
|
||||
if(u == nil || (strcmp(u->scheme, "http") && strcmp(u->scheme, "https"))){
|
||||
werrstr("bad url");
|
||||
werrstr("bad url scheme");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -496,6 +515,41 @@ http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost)
|
|||
}
|
||||
qunlock(&authlk);
|
||||
|
||||
length = 0;
|
||||
chunked = 0;
|
||||
if(qpost){
|
||||
/* have to read it to temp file to figure out the length */
|
||||
if(fd >= 0 && needlength && lookkey(shdr, "Content-Length") == nil){
|
||||
seek(fd, 0, 2);
|
||||
while((n = buread(qpost, buf, sizeof(buf))) > 0)
|
||||
write(fd, buf, n);
|
||||
shdr = delkey(shdr, "Transfer-Encoding");
|
||||
}
|
||||
|
||||
qlock(qpost);
|
||||
/* wait until buffer is full, most posts are small */
|
||||
while(!qpost->closed && qpost->size < qpost->limit && qpost->nwq == 0)
|
||||
rsleep(&qpost->rz);
|
||||
|
||||
if(lookkey(shdr, "Content-Length"))
|
||||
chunked = 0;
|
||||
else if(x = lookkey(shdr, "Transfer-Encoding"))
|
||||
chunked = cistrstr(x, "chunked") != nil;
|
||||
else if(chunked = !qpost->closed)
|
||||
shdr = addkey(shdr, "Transfer-Encoding", "chunked");
|
||||
else if(qpost->closed){
|
||||
if(fd >= 0){
|
||||
length = seek(fd, 0, 2);
|
||||
if(length < 0)
|
||||
length = 0;
|
||||
}
|
||||
length += qpost->size;
|
||||
snprint(buf, sizeof(buf), "%lld", length);
|
||||
shdr = addkey(shdr, "Content-Length", buf);
|
||||
}
|
||||
qunlock(qpost);
|
||||
}
|
||||
|
||||
if(proxy){
|
||||
ru = *u;
|
||||
ru.fragment = nil;
|
||||
|
@ -506,42 +560,10 @@ http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost)
|
|||
}
|
||||
n = snprint(buf, sizeof(buf), "%s %U HTTP/1.1\r\nHost: %s%s%s\r\n",
|
||||
method, &ru, u->host, u->port ? ":" : "", u->port ? u->port : "");
|
||||
|
||||
for(k = shdr; k; k = k->next)
|
||||
n += snprint(buf+n, sizeof(buf)-2 - n, "%s: %s\r\n", k->key, k->val);
|
||||
|
||||
if(n >= sizeof(buf)-64){
|
||||
werrstr("request too large");
|
||||
break;
|
||||
}
|
||||
|
||||
nobody = !cistrcmp(method, "HEAD");
|
||||
length = 0;
|
||||
chunked = 0;
|
||||
if(qpost){
|
||||
qlock(qpost);
|
||||
/* wait until buffer is full, most posts are small */
|
||||
while(!qpost->closed && qpost->size < qpost->limit)
|
||||
rsleep(&qpost->rz);
|
||||
|
||||
if(lookkey(shdr, "Content-Length"))
|
||||
chunked = 0;
|
||||
else if(x = lookkey(shdr, "Transfer-Encoding"))
|
||||
chunked = cistrstr(x, "chunked") != nil;
|
||||
else if(chunked = !qpost->closed)
|
||||
n += snprint(buf+n, sizeof(buf)-n, "Transfer-Encoding: chunked\r\n");
|
||||
else if(qpost->closed){
|
||||
if(fd >= 0){
|
||||
length = seek(fd, 0, 2);
|
||||
if(length < 0)
|
||||
length = 0;
|
||||
}
|
||||
length += qpost->size;
|
||||
n += snprint(buf+n, sizeof(buf)-n, "Content-Length: %lld\r\n", length);
|
||||
}
|
||||
qunlock(qpost);
|
||||
}
|
||||
|
||||
if(h == nil){
|
||||
alarm(timeout);
|
||||
if((h = hdial(proxy ? proxy : u)) == nil)
|
||||
|
@ -574,6 +596,8 @@ http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost)
|
|||
}
|
||||
}
|
||||
|
||||
for(k = shdr; k; k = k->next)
|
||||
n += snprint(buf+n, sizeof(buf)-2 - n, "%s: %s\r\n", k->key, k->val);
|
||||
n += snprint(buf+n, sizeof(buf)-n, "\r\n");
|
||||
if(debug)
|
||||
fprint(2, "-> %.*s", n, buf);
|
||||
|
@ -588,10 +612,10 @@ http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost)
|
|||
if((pid = rfork(RFMEM|RFPROC)) <= 0){
|
||||
int ifd;
|
||||
|
||||
alarm(0);
|
||||
if((ifd = fd) >= 0)
|
||||
seek(ifd, 0, 0);
|
||||
while(!h->cancel){
|
||||
alarm(0);
|
||||
if((ifd < 0) || ((n = read(ifd, buf, sizeof(buf)-2)) <= 0)){
|
||||
ifd = -1;
|
||||
if((n = buread(qpost, buf, sizeof(buf)-2)) <= 0)
|
||||
|
@ -600,18 +624,21 @@ http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost)
|
|||
if(write(fd, buf, n) != n)
|
||||
break;
|
||||
}
|
||||
alarm(timeout);
|
||||
if(chunked){
|
||||
char tmp[32];
|
||||
hwrite(h, tmp, snprint(tmp, sizeof(tmp), "%x\r\n", n));
|
||||
if(hwrite(h, tmp, snprint(tmp, sizeof(tmp), "%x\r\n", n)) < 0)
|
||||
break;
|
||||
buf[n++] = '\r';
|
||||
buf[n++] = '\n';
|
||||
}
|
||||
if(hwrite(h, buf, n) != n)
|
||||
break;
|
||||
}
|
||||
if(chunked)
|
||||
if(chunked){
|
||||
alarm(timeout);
|
||||
hwrite(h, "0\r\n\r\n", 5);
|
||||
else
|
||||
}else
|
||||
h->keep = 0;
|
||||
if(pid == 0)
|
||||
exits(0);
|
||||
|
@ -625,7 +652,6 @@ http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost)
|
|||
rhdr = 0;
|
||||
retry = 0;
|
||||
chunked = 0;
|
||||
status[0] = 0;
|
||||
offset = 0;
|
||||
length = NOLENGTH;
|
||||
for(l = 0; hline(h, s = buf, sizeof(buf)-1, 1) > 0; l++){
|
||||
|
@ -640,6 +666,7 @@ http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost)
|
|||
if(cistrcmp(s, "ICY"))
|
||||
break;
|
||||
}
|
||||
if(x[0])
|
||||
nstrcpy(status, x, sizeof(status));
|
||||
continue;
|
||||
}
|
||||
|
@ -671,6 +698,7 @@ http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost)
|
|||
cfd = -1;
|
||||
}
|
||||
|
||||
nobody = !cistrcmp(method, "HEAD");
|
||||
if((i = atoi(status)) < 0)
|
||||
i = 0;
|
||||
Status:
|
||||
|
@ -699,7 +727,14 @@ http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost)
|
|||
case 408: /* Request Timeout */
|
||||
case 409: /* Conflict */
|
||||
case 410: /* Gone */
|
||||
goto Error;
|
||||
case 411: /* Length Required */
|
||||
if(qpost){
|
||||
needlength = 1;
|
||||
h->cancel = 1;
|
||||
retry = 1;
|
||||
break;
|
||||
}
|
||||
case 412: /* Precondition Failed */
|
||||
case 413: /* Request Entity Too Large */
|
||||
case 414: /* Request URI Too Large */
|
||||
|
@ -861,8 +896,7 @@ http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost)
|
|||
h = nil;
|
||||
}
|
||||
alarm(0);
|
||||
|
||||
rerrstr(buf, sizeof(buf));
|
||||
snprint(buf, sizeof(buf), "%s %r", status);
|
||||
buclose(qbody, buf);
|
||||
bufree(qbody);
|
||||
|
||||
|
|
Loading…
Reference in a new issue