ref: ff0e3e6a00aa5243c401d9e440a19c148c39a3c8
parent: 90b38f03a528f2a1e1b76b69f77bff3cb43b5524
author: cinap_lenrek <[email protected]>
date: Mon Jun 18 04:00:36 EDT 2012
mothra: refactor form submit code
--- a/sys/src/cmd/mothra/forms.c
+++ b/sys/src/cmd/mothra/forms.c
@@ -445,50 +445,7 @@
}
void h_buttoninput(Panel *p, int){
}
-int ulen(char *s){
- int len;
- len=0;
- for(;*s;s++){
- if(strchr("/$-_@.!*'(), ", *s)
- || 'a'<=*s && *s<='z'
- || 'A'<=*s && *s<='Z'
- || '0'<=*s && *s<='9')
- len++;
- else
- len+=3;
- }
- return len;
-}
-int hexdigit(int v){
- return 0<=v && v<=9?'0'+v:'A'+v-10;
-}
-char *ucpy(char *buf, char *s){
- for(;*s;s++){
- if(strchr("/$-_@.!*'(),", *s)
- || 'a'<=*s && *s<='z'
- || 'A'<=*s && *s<='Z'
- || '0'<=*s && *s<='9')
- *buf++=*s;
- else if(*s==' ')
- *buf++='+';
- else{
- *buf++='%';
- *buf++=hexdigit((*s>>4)&15);
- *buf++=hexdigit(*s&15);
- }
- }
- *buf='\0';
- return buf;
-}
-char *runetou(char *buf, Rune r){
- char rbuf[2];
- if(r<=255){
- rbuf[0]=r;
- rbuf[1]='\0';
- buf=ucpy(buf, rbuf);
- }
- return buf;
-}
+
/*
* If there's exactly one button with type=text, then
* a CR in the button is supposed to submit the form.
@@ -505,25 +462,25 @@
void h_submitindex(Panel *p, char *){
h_submitinput(p, 0);
}
-void h_submitinput(Panel *p, int){
- Form *form;
- int size, nrune;
- char *buf, *bufp, sep;
- Rune *rp;
- Field *f;
+
+void
+uencodeform(Form *form, int fd){
+ char *b, *p, *sep;
Option *o;
- form=((Field *)p->userp)->form;
- if(form->method==GET) size=ulen(form->action)+1;
- else size=1;
+ Field *f;
+ Rune *rp;
+ int n;
+
+ sep = "";
for(f=form->fields;f;f=f->next) switch(f->type){
case TYPEIN:
case PASSWD:
- if(f->name==0)
- continue;
- size+=ulen(f->name)+1+ulen(plentryval(f->p))+1;
+ fprint(fd, "%s%U=%U", sep, f->name, plentryval(f->p));
+ sep = "&";
break;
case INDEX:
- size+=ulen(plentryval(f->p))+1;
+ fprint(fd, "%s%U", sep, plentryval(f->p));
+ sep = "&";
break;
case CHECK:
case RADIO:
@@ -531,98 +488,75 @@
case HIDDEN:
if(f->name==0 || f->value==0)
continue;
- size+=ulen(f->name)+1+ulen(f->value)+1;
+ fprint(fd, "%s%U=%U", sep, f->name, f->value);
+ sep = "&";
break;
case SELECT:
if(f->name==0)
continue;
for(o=f->options;o;o=o->next)
- if(o->selected && o->value)
- size+=ulen(f->name)+1+ulen(o->value)+1;
- break;
- case TEXTWIN:
- if(f->name==0)
- continue;
- size+=ulen(f->name)+1+plelen(f->textwin)*3+1;
- break;
- }
- buf=emalloc(size);
- if(form->method==GET){
- strcpy(buf, form->action);
- sep='?';
- }
- else{
- buf[0]='\0';
- sep=0;
- }
- bufp=buf+strlen(buf);
- if(form->method==GET && bufp!=buf && bufp[-1]=='?') *--bufp='\0'; /* spurious ? */
- for(f=form->fields;f;f=f->next) switch(f->type){
- case TYPEIN:
- case PASSWD:
- if(f->name==0)
- continue;
- if(sep) *bufp++=sep;
- sep='&';
- bufp=ucpy(bufp, f->name);
- *bufp++='=';
- bufp=ucpy(bufp, plentryval(f->p));
- break;
- case INDEX:
- if(sep) *bufp++=sep;
- sep='&';
- bufp=ucpy(bufp, plentryval(f->p));
- break;
- case CHECK:
- case RADIO:
- if(!f->state) break;
- case HIDDEN:
- if(f->name==0 || f->value==0)
- continue;
- if(sep) *bufp++=sep;
- sep='&';
- bufp=ucpy(bufp, f->name);
- *bufp++='=';
- bufp=ucpy(bufp, f->value);
- break;
- case SELECT:
- if(f->name==0)
- continue;
- for(o=f->options;o;o=o->next)
if(o->selected && o->value){
- if(sep) *bufp++=sep;
- sep='&';
- bufp=ucpy(bufp, f->name);
- *bufp++='=';
- bufp=ucpy(bufp, o->value);
+ fprint(fd, "%s%U=%U", sep, f->name, o->value);
+ sep = "&";
}
break;
case TEXTWIN:
if(f->name==0)
continue;
- if(sep) *bufp++=sep;
- sep='&';
- bufp=ucpy(bufp, f->name);
- *bufp++='=';
+ n=plelen(f->textwin);
rp=pleget(f->textwin);
- for(nrune=plelen(f->textwin);nrune!=0;--nrune)
- bufp=runetou(bufp, *rp++);
- *bufp='\0';
+ p=b=malloc(UTFmax*n+1);
+ if(b == nil)
+ continue;
+ while(n > 0){
+ p += runetochar(p, rp);
+ rp++;
+ n--;
+ }
+ *p = 0;
+ fprint(fd, "%s%U=%U", sep, f->name, b);
+ sep = "&";
+ free(b);
break;
}
+}
+
+void h_submitinput(Panel *p, int){
+ char buf[NNAME];
+ Form *form;
+ int n, fd;
+
+ form=((Field *)p->userp)->form;
if(form->method==GET){
+ strcpy(buf, "/tmp/mfXXXXXXXXXXX");
+ fd = create(mktemp(buf), ORDWR|ORCLOSE, 0600);
+ if(fd >= 0)
+ fprint(fd, "%s?", form->action);
+ } else
+ fd = urlpost(selurl(form->action), nil);
+ if(fd < 0){
+ message("submit form: %r");
+ return;
+ }
+
+ uencodeform(form, fd);
+
+ if(form->method==GET){
+ seek(fd, 0, 0);
+ n = readn(fd, buf, sizeof(buf));
+ close(fd);
+ if(n < 0 || n >= sizeof(buf)){
+ message("submit form: post data too large");
+ return;
+ }
+ buf[n] = 0;
if(debug)fprint(2, "GET %s\n", buf);
geturl(buf, -1, 0, 0);
}
else{
- int post;
-
- if(debug)fprint(2, "POST %s: %s\n", form->action, buf);
- if((post = urlpost(selurl(form->action), nil)) >= 0)
- write(post, buf, strlen(buf));
- geturl(form->action, post, 0, 0);
+ if(debug)fprint(2, "POST %s\n", form->action);
+ geturl(form->action, fd, 0, 0);
}
- free(buf);
}
void freeform(void *p)
@@ -654,4 +588,21 @@
}
free(form);
}
+}
+
+int
+Ufmt(Fmt *f){
+ char *s = va_arg(f->args, char*);
+ for(; *s; s++){
+ if(strchr("/$-_@.!*'(),", *s)
+ || 'a'<=*s && *s<='z'
+ || 'A'<=*s && *s<='Z'
+ || '0'<=*s && *s<='9')
+ fmtprint(f, "%c", *s);
+ else if(*s==' ')
+ fmtprint(f, "+");
+ else
+ fmtprint(f, "%%%.2X", (unsigned int)*s);
+ }
+ return 0;
}
--- a/sys/src/cmd/mothra/mothra.c
+++ b/sys/src/cmd/mothra/mothra.c
@@ -251,6 +251,8 @@
int i;
quotefmtinstall();
+ fmtinstall('U', Ufmt);
+
ARGBEGIN{
case 'd': debug=1; break;
case 'v': verbose=1; break;
--- a/sys/src/cmd/mothra/mothra.h
+++ b/sys/src/cmd/mothra/mothra.h
@@ -93,6 +93,8 @@
void *emallocz(int, int);
void nstrcpy(char *to, char *from, int len);
void freeform(void *p);
+int Ufmt(Fmt *f);
+#pragma varargck type "U" char*
void message(char *, ...);
int snooptype(int fd);
void mkfieldpanel(Rtext *);
@@ -100,3 +102,4 @@
int urlpost(Url*, char*);
int urlget(Url*, int);
char version[];
+