diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-08-01 11:20:28 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2015-08-01 11:20:28 +0200 |
commit | 815c2ba22ba5d15cdedd39837d4edb4107eb0b32 (patch) | |
tree | 0e99112e36451d449534ed85a99710a43e9e3ff6 /sys | |
parent | f62a2efb7add3ec40ca91adc514d5bdb6b0cd721 (diff) |
mothra: support for inline images and <image> tag
Diffstat (limited to 'sys')
-rw-r--r-- | sys/src/cmd/mothra/forms.c | 8 | ||||
-rw-r--r-- | sys/src/cmd/mothra/getpix.c | 5 | ||||
-rw-r--r-- | sys/src/cmd/mothra/html.h | 9 | ||||
-rw-r--r-- | sys/src/cmd/mothra/html.syntax.c | 1 | ||||
-rw-r--r-- | sys/src/cmd/mothra/mothra.c | 16 | ||||
-rw-r--r-- | sys/src/cmd/mothra/mothra.h | 4 | ||||
-rw-r--r-- | sys/src/cmd/mothra/rdhtml.c | 122 | ||||
-rw-r--r-- | sys/src/cmd/mothra/url.c | 77 |
8 files changed, 184 insertions, 58 deletions
diff --git a/sys/src/cmd/mothra/forms.c b/sys/src/cmd/mothra/forms.c index 90cfe4683..3c8a8fd48 100644 --- a/sys/src/cmd/mothra/forms.c +++ b/sys/src/cmd/mothra/forms.c @@ -129,7 +129,7 @@ void rdform(Hglob *g){ form->method = 0; form->fields = 0; form->efields = 0; - if(g->state->link[0]) + if(g->state->link) form->action = strdup(g->state->link); form->next = g->dst->form; g->dst->form = form; @@ -172,8 +172,10 @@ void rdform(Hglob *g){ else if(cistrcmp(s, "image")==0){ f->type=SUBMIT; s=pl_getattr(g->attr, "src"); - if(s && *s) - nstrcpy(g->state->image, s, sizeof(g->state->image)); + if(s && *s){ + free(g->state->image); + g->state->image = strdup(s); + } s=pl_getattr(g->attr, "width"); if(s && *s) g->state->width=strtolength(g, HORIZ, s); diff --git a/sys/src/cmd/mothra/getpix.c b/sys/src/cmd/mothra/getpix.c index 5dd31bb01..4428959d5 100644 --- a/sys/src/cmd/mothra/getpix.c +++ b/sys/src/cmd/mothra/getpix.c @@ -47,7 +47,7 @@ void getimage(Rtext *t, Www *w){ t->text=strdup(err); w->changed=1; close(fd); - return; + goto Out; } typ = snooptype(fd); if(typ < 0 || typ >= nelem(pixcmd) || pixcmd[typ] == nil){ @@ -81,6 +81,9 @@ void getimage(Rtext *t, Www *w){ w->pix=p; t->b=b; w->changed=1; +Out: + free(url.basename); + free(url.reltext); } void getpix(Rtext *t, Www *w){ diff --git a/sys/src/cmd/mothra/html.h b/sys/src/cmd/mothra/html.h index 242f7947e..b32dd0b5c 100644 --- a/sys/src/cmd/mothra/html.h +++ b/sys/src/cmd/mothra/html.h @@ -4,7 +4,7 @@ #define NSTACK 100 /* html grammar is not recursive, so 30 or so should do */ #define NHBUF 8192 /* Input buffer size */ #define NPEEKC 3 /* Maximum lookahead */ -#define NTOKEN 4096 /* Maximum token length */ +#define NTOKEN 65536 /* Maximum token length */ #define NATTR 512 /* Maximum number of attributes of a tag */ typedef struct Pair Pair; typedef struct Tag Tag; @@ -37,9 +37,9 @@ struct Stack{ int strike; /* flag of <strike> */ int width; /* size of image */ int height; - char image[NNAME]; /* arg of <img> */ - char link[NNAME]; /* arg of <a href=...> */ - char name[NNAME]; /* arg of <a name=...> */ + char *image; /* arg of <img> */ + char *link; /* arg of <a href=...> */ + char *name; /* arg of <a name=...> */ }; /* @@ -169,6 +169,7 @@ enum{ Tag_i, Tag_iframe, Tag_img, + Tag_image, Tag_input, Tag_ins, Tag_isindex, diff --git a/sys/src/cmd/mothra/html.syntax.c b/sys/src/cmd/mothra/html.syntax.c index 98b8dd0af..b2c43ec80 100644 --- a/sys/src/cmd/mothra/html.syntax.c +++ b/sys/src/cmd/mothra/html.syntax.c @@ -47,6 +47,7 @@ Tag tag[]={ [Tag_i] "i", END, [Tag_iframe] "iframe", NOEND, [Tag_img] "img", NOEND, +[Tag_image] "image", NOEND, [Tag_input] "input", NOEND, [Tag_ins] "ins", END, [Tag_isindex] "isindex", NOEND, diff --git a/sys/src/cmd/mothra/mothra.c b/sys/src/cmd/mothra/mothra.c index f58c8bde6..b2713e3e1 100644 --- a/sys/src/cmd/mothra/mothra.c +++ b/sys/src/cmd/mothra/mothra.c @@ -636,9 +636,8 @@ char *urltofile(Url *url){ char *name, *slash; if(url == nil) return nil; - if(url->fullname[0] || url->reltext[0]) - name = urlstr(url); - else + name = urlstr(url); + if(name == nil || name[0] == 0) name = "/"; if(slash = strrchr(name, '/')) name = slash+1; @@ -945,6 +944,9 @@ urlstr(Url *url){ } Url* selurl(char *urlname){ static Url url; + + free(url.reltext); + free(url.basename); seturl(&url, urlname, current ? current->url->fullname : ""); selection=&url; message("selected: %s", urlstr(selection)); @@ -952,8 +954,8 @@ Url* selurl(char *urlname){ return selection; } void seturl(Url *url, char *urlname, char *base){ - nstrcpy(url->reltext, urlname, sizeof(url->reltext)); - nstrcpy(url->basename, base, sizeof(url->basename)); + url->reltext = strdup(urlname); + url->basename = strdup(base); url->fullname[0] = 0; url->tag[0] = 0; url->map = 0; @@ -962,9 +964,13 @@ Url *copyurl(Url *u){ Url *v; v=emalloc(sizeof(Url)); *v=*u; + v->reltext = strdup(u->reltext); + v->basename = strdup(u->basename); return v; } void freeurl(Url *u){ + free(u->reltext); + free(u->basename); free(u); } diff --git a/sys/src/cmd/mothra/mothra.h b/sys/src/cmd/mothra/mothra.h index 665f7084d..80d79269c 100644 --- a/sys/src/cmd/mothra/mothra.h +++ b/sys/src/cmd/mothra/mothra.h @@ -24,9 +24,9 @@ struct Action{ int height; }; struct Url{ + char *basename; + char *reltext; char fullname[NNAME]; - char basename[NNAME]; - char reltext[NNAME]; char tag[NNAME]; int map; /* is this an image map? */ }; diff --git a/sys/src/cmd/mothra/rdhtml.c b/sys/src/cmd/mothra/rdhtml.c index 5f53c8ecf..c347701db 100644 --- a/sys/src/cmd/mothra/rdhtml.c +++ b/sys/src/cmd/mothra/rdhtml.c @@ -62,7 +62,23 @@ void pl_pushstate(Hglob *g, int t){ } g->state[0]=g->state[-1]; g->state->tag=t; + + if(g->state->name) + g->state->name = strdup(g->state->name); + if(g->state->link) + g->state->link = strdup(g->state->link); + if(g->state->image) + g->state->image = strdup(g->state->image); +} +void pl_popstate(Stack *state){ + free(state->name); + state->name=0; + free(state->link); + state->link=0; + free(state->image); + state->image=0; } + void pl_linespace(Hglob *g){ plrtbitmap(&g->dst->text, 1000000, 0, linespace, 0, 0); g->para=0; @@ -110,15 +126,15 @@ void pl_htmloutput(Hglob *g, int nsp, char *s, Field *field){ space=1000000; else if(nsp<=0) space=0; - if(g->state->image[0]==0 && g->state->link[0]==0 && g->state->name[0]==0 && field==0) + if(g->state->image==0 && g->state->link==0 && g->state->name==0 && field==0) ap=0; else{ ap=emalloc(sizeof(Action)); - if(g->state->image[0]) + if(g->state->image) ap->image = strdup(g->state->image); - if(g->state->link[0]) + if(g->state->link) ap->link = strdup(g->state->link); - if(g->state->name[0]) + if(g->state->name) ap->name = strdup(g->state->name); ap->ismap=g->state->ismap; ap->width=g->state->width; @@ -140,7 +156,7 @@ void pl_htmloutput(Hglob *g, int nsp, char *s, Field *field){ } } flags = 0; - if(g->state->link[0]) + if(g->state->link) flags |= PL_HOT; if(g->state->strike) flags |= PL_STR; @@ -652,9 +668,9 @@ void plrdplain(char *name, int fd, Www *dst){ g.state->font=CWIDTH; g.state->size=NORMAL; g.state->pre=0; - g.state->image[0]=0; - g.state->link[0]=0; - g.state->name[0]=0; + g.state->image=0; + g.state->link=0; + g.state->name=0; g.state->margin=0; g.state->indent=20; g.state->ismap=0; @@ -688,9 +704,9 @@ void plrdhtml(char *name, int fd, Www *dst){ g.state->font=ROMAN; g.state->size=NORMAL; g.state->pre=0; - g.state->image[0]=0; - g.state->link[0]=0; - g.state->name[0]=0; + g.state->image=0; + g.state->link=0; + g.state->name=0; g.state->margin=0; g.state->indent=25; g.state->ismap=0; @@ -722,11 +738,13 @@ void plrdhtml(char *name, int fd, Www *dst){ if(sp->tag!=g.tag) pl_pushstate(&g, g.tag); else - for(;g.state!=sp;--g.state) + for(;g.state!=sp;--g.state){ if(tag[g.state->tag].action!=OPTEND) htmlerror(g.name, g.lineno, "end tag </%s> missing", tag[g.state->tag].name); + pl_popstate(g.state); + } break; case END: pl_pushstate(&g, g.tag); @@ -734,12 +752,12 @@ void plrdhtml(char *name, int fd, Www *dst){ } str=pl_getattr(g.attr, "id"); if(str && *str){ - char swap[NNAME]; + char *swap; - nstrcpy(swap, g.state->name, sizeof(swap)); - nstrcpy(g.state->name, str, sizeof(g.state->name)); + swap = g.state->name; + g.state->name = str; pl_htmloutput(&g, 0, "", 0); - nstrcpy(g.state->name, swap, sizeof(g.state->name)); + g.state->name = swap; } switch(g.tag){ default: @@ -749,10 +767,12 @@ void plrdhtml(char *name, int fd, Www *dst){ case Tag_end: /* unrecognized start tag */ break; case Tag_img: + case Tag_image: str=pl_getattr(g.attr, "src"); - if(str && *str) - nstrcpy(g.state->image, str, sizeof(g.state->image)); - else { + if(str && *str){ + free(g.state->image); + g.state->image = strdup(str); + } else { Pair *a; /* @@ -764,8 +784,8 @@ void plrdhtml(char *name, int fd, Www *dst){ if(strcmp(a->name, "longdesc") == 0) continue; if(str = linkify(a->value)){ - nstrcpy(g.state->image, str, sizeof(g.state->image)); - free(str); + free(g.state->image); + g.state->image = str; break; } } @@ -779,13 +799,14 @@ void plrdhtml(char *name, int fd, Www *dst){ g.state->height=strtolength(&g, VERT, str); str=pl_getattr(g.attr, "alt"); if(str==0 || *str == 0){ - if(g.state->image[0]) + if(g.state->image) str=g.state->image; else str="[[image]]"; } pl_htmloutput(&g, 0, str, 0); - g.state->image[0]=0; + free(g.state->image); + g.state->image=0; g.state->ismap=0; g.state->width=0; g.state->height=0; @@ -818,12 +839,16 @@ void plrdhtml(char *name, int fd, Www *dst){ break; case Tag_a: str=pl_getattr(g.attr, "name"); - if(str && *str) - nstrcpy(g.state->name, str, sizeof(g.state->name)); + if(str && *str){ + free(g.state->name); + g.state->name = strdup(str); + } pl_htmloutput(&g, 0, "", 0); str=pl_getattr(g.attr, "href"); - if(str && *str) - nstrcpy(g.state->link, str, sizeof(g.state->link)); + if(str && *str){ + free(g.state->link); + g.state->link = strdup(str); + } break; case Tag_meta: if((str=pl_getattr(g.attr, "http-equiv"))==0) @@ -836,9 +861,10 @@ void plrdhtml(char *name, int fd, Www *dst){ break; str++; pl_htmloutput(&g, 0, "[refresh: ", 0); - str=unquot(g.state->link, str, sizeof(g.state->link)); + free(g.state->link); + g.state->link=unquot(buf, str, sizeof(buf)); pl_htmloutput(&g, 0, str, 0); - g.state->link[0]=0; + g.state->link=0; pl_htmloutput(&g, 0, "]", 0); g.linebrk=1; g.spacc=0; @@ -852,16 +878,21 @@ void plrdhtml(char *name, int fd, Www *dst){ snprint(buf, sizeof(buf), "[%s: ", tag[g.tag].name); pl_htmloutput(&g, 0, buf, 0); str=pl_getattr(g.attr, "src"); - if(str && *str) - nstrcpy(g.state->link, str, sizeof(g.state->link)); + if(str && *str){ + free(g.state->link); + g.state->link = strdup(str); + } str=pl_getattr(g.attr, "name"); - if(str && *str) - nstrcpy(g.state->name, str, sizeof(g.state->name)); - else + if(str && *str){ + free(g.state->name); + g.state->name = strdup(str); + } else str = g.state->link; pl_htmloutput(&g, 0, str, 0); - g.state->link[0]=0; - g.state->name[0]=0; + free(g.state->link); + g.state->link=0; + free(g.state->name); + g.state->name=0; pl_htmloutput(&g, 0, "]", 0); g.linebrk=1; g.spacc=0; @@ -1101,14 +1132,16 @@ void plrdhtml(char *name, int fd, Www *dst){ "end tag mismatch <%s>...</%s>, " "intervening tags popped", tag[g.state->tag].name, tag[g.tag].name); - g.state=sp-1; + + for(--sp; g.state!=sp; --g.state) + pl_popstate(g.state); } } else if(g.state==g.stack) htmlerror(g.name, g.lineno, "end tag </%s> at stack bottom", tag[g.tag].name); else - --g.state; + pl_popstate(g.state--); switch(g.tag){ case Tag_select: case Tag_form: @@ -1148,19 +1181,22 @@ void plrdhtml(char *name, int fd, Www *dst){ case TEXT: if(g.state->isscript) continue; - if(g.state->link[0]==0 && (str = linkify(g.token))){ - nstrcpy(g.state->link, str, sizeof(g.state->link)); + if(g.state->link==0 && (str = linkify(g.token))){ + g.state->link=str; pl_htmloutput(&g, g.nsp, g.token, 0); - g.state->link[0] = 0; - free(str); + free(g.state->link); + g.state->link=0; } else pl_htmloutput(&g, g.nsp, g.token, 0); break; case EOF: - for(;g.state!=g.stack;--g.state) + for(;g.state!=g.stack;--g.state){ if(tag[g.state->tag].action!=OPTEND) htmlerror(g.name, g.lineno, "missing </%s> at EOF", tag[g.state->tag].name); + pl_popstate(g.state); + } + pl_popstate(g.state); *g.tp='\0'; getpix(dst->text, dst); finish(dst); diff --git a/sys/src/cmd/mothra/url.c b/sys/src/cmd/mothra/url.c index dd2ea4ad3..2e0e659ca 100644 --- a/sys/src/cmd/mothra/url.c +++ b/sys/src/cmd/mothra/url.c @@ -6,6 +6,81 @@ #include "mothra.h" static int +hexdigit(int c) +{ + if(c >= '0' && c <= '9') + return c-'0'; + if(c >= 'a' && c <= 'f') + return c-'a'+10; + if(c >= 'A' && c <= 'F') + return c-'A'+10; + return -1; +} + +static int +dechex(uchar *out, int lim, char *in, int n) +{ + uchar *start, *end; + int c; + + start = out; + end = start + lim; + while(n-- > 0 && out < end){ + c = *in++; + if(c == 0) + break; + if(c & 0x80) + return -1; + if(c == '%'){ + n -= 2; + if(n < 0 || (c = hexdigit(*in++)) == -1) + return -1; + if((c = (c << 4) | hexdigit(*in++)) == -1) + return -1; + } + *out++ = c; + } + return out - start; +} + +static int +dataget(Url *url) +{ + int (*decfun)(uchar *, int, char *, int) = dechex; + char *s, *p; + int fd, n, m; + + s = url->reltext; + if(cistrncmp(s, "data:", 5) != 0) + return -1; + s += 5; + if((p = strchr(s, ',')) != nil){ + *p = 0; + if(strstr(s, "base64") != nil) + decfun = dec64; + *p = ','; + s = p+1; + } else + s = strchr(s, 0); + n = strlen(s); + m = n+64; + p = malloc(m); + strcpy(p, "/tmp/duXXXXXXXXXXX"); + if((fd = create(mktemp(p), ORDWR|ORCLOSE, 0600)) < 0){ + free(p); + return -1; + } + if((m = (*decfun)((uchar*)p, m, s, n)) < 0 || write(fd, p, m) != m){ + free(p); + close(fd); + return -1; + } + free(p); + seek(fd, 0, 0); + return fd; +} + +static int fileget(Url *url) { char *rel, *base, *x; @@ -109,6 +184,8 @@ urlget(Url *url, int body) int n, fd; if(body < 0){ + if((fd = dataget(url)) >= 0) + return fd; if((fd = fileget(url)) >= 0) return fd; if((fd = webclone(url, buf, sizeof(buf))) < 0) |