Annotation of OpenXM/src/kan96xx/plugin/oxcgi.c, Revision 1.2
1.2 ! takayama 1: /* $OpenXM: OpenXM/src/kan96xx/plugin/oxcgi.c,v 1.1 2004/09/21 12:52:01 takayama Exp $ */
! 2: #include <stdio.h>
! 3: #include "datatype.h"
! 4: #include "stackm.h"
! 5: #include "extern.h"
! 6: #include "file2.h"
! 7: #include "oxcgi.h"
! 8:
! 9: static int ppp(char *s,int kstart,int kend, int vstart, int vend);
! 10: static int cgiHex(int p);
! 11:
! 12: static test1();
! 13: static test2();
! 14: static test3();
! 15: static test4();
! 16:
! 17: /* main() {KSstart();test4();} */
! 18:
! 19: /*
! 20: [["URL","http://www.openxm.org"],
! 21: ["foo","value1"], <--- the first key value.
! 22: ["hoge","value2"]
! 23: ]
! 24: */
! 25: struct object cgiUrlEncodingToKeyValuePair(char *s) {
! 26: int i,n,start;
! 27: int kstart,kend; /* start of key, end of key */
! 28: int vstart,vend; /* start of value, end of value */
! 29: int state;
! 30: int nOfPairs;
! 31: struct object rob;
! 32: struct object ob;
! 33: int k;
! 34: n = strlen(s); start = -1;
! 35: for (i=0; i<n; i++) {
! 36: if (s[i] == '?') { start=i+1; break;}
! 37: }
! 38: for (k=0; k<2; k++) {
! 39: /* k==0 path one. Count nOfPairs. */
! 40: /* k==1 path two. generate array. */
! 41: nOfPairs = 0;
! 42: i = start;
! 43: /* state 0, 1 : key
! 44: =
! 45: state 2, 3 : value
! 46: &
! 47: state 5 : after getting &
! 48: state 4 : after getting eof
! 49: state 6
! 50: */
! 51: state = 0;
! 52: while (1) {
! 53: switch(state) {
! 54: case 0:
! 55: kstart = kend = vstart = vend = -1;
! 56: if (s[i] <= ' ') {
! 57: state=6; break;
! 58: } else {
! 59: kstart = kend = i;
! 60: nOfPairs++;
! 61: i++;
! 62: state=1;
! 63: break;
! 64: }
! 65: case 1:
! 66: if (s[i] <= ' ') {
! 67: state=4; break;
! 68: }else if (s[i] == '=') {
! 69: state=2; i++; break;
! 70: }else {
! 71: kend = i; i++; break;
! 72: }
! 73: case 2:
! 74: vstart = vend = -1;
! 75: if (s[i] <= ' ') {
! 76: state=4; break;
! 77: }else if (s[i] == '&') {
! 78: state=5; break;
! 79: }else {
! 80: state=3; vstart=vend=i; i++; break;
! 81: }
! 82: case 3:
! 83: if (s[i] <= ' ') {
! 84: state=4; break;
! 85: }else if (s[i] == '&') {
! 86: state=5; break;
! 87: }else{
! 88: vend=i; i++; break;
! 89: }
! 90: case 4:
! 91: if (k == 1) {
! 92: ob = newObjectArray(2);
! 93: putoa(ob,0,urlEncodedStringToObj(s,kstart,kend,0));
! 94: putoa(ob,1,urlEncodedStringToObj(s,vstart,vend,0));
! 95: putoa(rob,nOfPairs,ob);
! 96: }
! 97: state = -1; break;
! 98: case 5:
! 99: if (k == 1) {
! 100: ob = newObjectArray(2);
! 101: putoa(ob,0,urlEncodedStringToObj(s,kstart,kend,0));
! 102: putoa(ob,1,urlEncodedStringToObj(s,vstart,vend,0));
! 103: putoa(rob,nOfPairs,ob);
! 104: }
! 105: i++; state = 0; break;
! 106: case 6: state = -1; break;
! 107: default: break;
! 108: }
! 109: if (state < 0) break;
! 110: /*
! 111: if ((state == 4) || (state == 5)) {
! 112: ppp(s,kstart,kend,vstart,vend);
! 113: }
! 114: */
! 115: }
! 116: if (k == 0) {
! 117: char *stmp; int ii;
! 118: rob = newObjectArray(nOfPairs+1);
! 119: ob = newObjectArray(2);
! 120: putoa(ob,0,KpoString("URL"));
! 121: stmp = sGC_malloc(start+2);
! 122: if (stmp == NULL) errorKan1("%s\n","No more memory.");
! 123: stmp[0] = 0;
! 124: for (ii=0; ii<start-1; ii++) {
! 125: stmp[ii] = s[ii]; stmp[ii+1] = 0;
! 126: }
! 127: putoa(ob,1,KpoString(stmp));
! 128: putoa(rob,0,ob);
! 129: }
! 130: }
! 131: return rob;
! 132: }
! 133:
! 134: /* . - _ A-Z a-z 0-9
! 135: space --> +
! 136: */
! 137: static int isUrlEncoding3(char s) {
! 138: if ((s == '.') || (s == '-') || (s == '_')) return(0);
! 139: if ((s >= 'A') && (s <= 'Z')) return(0);
! 140: if ((s >= 'a') && (s <= 'z')) return(0);
! 141: if ((s >= '0') && (s <= '9')) return(0);
! 142: if (s == ' ') return(0);
! 143: return(1);
! 144: }
! 145:
! 146: char *byteArrayToUrlEncoding(unsigned char *s,int size) {
! 147: int n,i,j;
! 148: char *r;
! 149: n = 0;
! 150: /* get Size */
! 151: for (i=0; i<size; i++) {
! 152: if (isUrlEncoding3((char)s[i])) n += 3;
! 153: n++;
! 154: }
! 155: r = sGC_malloc(n+1);
! 156: if (r == NULL) errorKan1("%s\n","No more memory.");
! 157: r[0] = 0; r[n] = 0;
! 158: i = 0; j = 0;
! 159: while ((j < n) && (i<size)) {
! 160: if (isUrlEncoding3((char)s[i])) {
! 161: sprintf(&(r[j]),"%%%02X",s[i]); j += 3;
! 162: }else{
! 163: if ((char)s[i] == ' ') r[j]='+';
! 164: else r[j] = s[i];
! 165: j++; r[j] = 0;
! 166: }
! 167: i++;
! 168: }
! 169: return(r);
! 170: }
! 171: struct object urlEncodedStringToObj(char *s,int vstart,int vend,int mode)
! 172: /*
! 173: mode == 0. Authmatically choose Sdollar or SbyteArray.
! 174: [ not implemented yet. ]
! 175: */
! 176: {
! 177: struct object rob;
! 178: char *ts;
! 179: char *ts2;
! 180: int i,j;
! 181: int p;
! 182: if ((s == NULL) || (vstart < 0)) return(NullObject);
! 183: if (vend+1-vstart <= 0) return(NullObject);
! 184: ts = (char *) malloc(vend-vstart+1);
! 185: if (ts == NULL) errorKan1("%s\n","Out of memory.");
! 186: j = 0; ts[j] = 0;
! 187: for (i=vstart; i<=vend; i++,j++) {
! 188: ts[j] = 0;
! 189: if (s[i] == '+') {
! 190: ts[j] = ' '; ts[j+1] = 0;
! 191: }else if (s[i] == '%') {
! 192: p = cgiHex(s[i+1])*16+cgiHex(s[i+2]);
! 193: i = i+2;
! 194: ts[j] = p; ts[j+1] = 0;
! 195: }else {
! 196: ts[j] = s[i]; ts[j+1] = 0;
! 197: }
! 198: }
! 199: ts2 = (char *)sGC_malloc(j);
! 200: if (ts2 == NULL) errorKan1("%s\n","Out of memory.");
! 201: for (i=0; i<j; i++) {
! 202: ts2[i] = ts[i];
! 203: }
! 204: return KpoString(ts2);
! 205: }
! 206:
! 207: static int cgiHex(int p) {
! 208: if (p >= '0' && p <= '9') return (p-'0');
! 209: if (p >= 'A' && p <= 'F') return (p-'A'+10);
! 210: if (p >= 'a' && p <= 'f') return (p-'a'+10);
! 211: errorKan1("%s\n","Invalid argument to cgiHex.");
! 212: }
! 213:
! 214: /* for debug */
! 215: static int ppp(char *s,int kstart,int kend, int vstart, int vend) {
! 216: int i;
! 217: printf("%d %d %d %d\n",kstart,kend,vstart,vend);
! 218: if (kstart >= 0) {
! 219: printf("key=");
! 220: for (i=kstart; i<=kend; i++) putchar(s[i]);
! 221: printf("\n");
! 222: }
! 223: if (vstart >= 0) {
! 224: printf("value=");
! 225: for (i=vstart; i<=vend; i++) putchar(s[i]);
! 226: printf("\n");
! 227: }
! 228: }
! 229: static test1() {
! 230: char s[1000];
! 231: cgiUrlEncodingToKeyValuePair("http://hoge.hoge?name=1231232&hoge=asdfsdf&foo=asdfasdf");
! 232: cgiUrlEncodingToKeyValuePair("http://hoge.hoge?name=1231232&hoge=&foo=asdfasdf&");
! 233: scanf("%s",s);
! 234: cgiUrlEncodingToKeyValuePair(s);
! 235: }
! 236: static test2() {
! 237: char s[1000];
! 238: struct object ob;
! 239: ob=cgiUrlEncodingToKeyValuePair("http://hoge.hoge?name=1231232&hoge=asdfsdf&foo=asdfasdf");
! 240: printObject(ob,1,stdout);
! 241: ob=cgiUrlEncodingToKeyValuePair("http://hoge.hoge?name=1231232&hoge=&foo=asdfasdf&hoge=A%41+%42%62y%21");
! 242: printObject(ob,1,stdout);
! 243: scanf("%s",s);
! 244: ob=cgiUrlEncodingToKeyValuePair(s);
! 245: printObject(ob,1,stdout);
! 246: }
! 247:
! 248: static test4() {
! 249: char s[1000];
! 250: struct object ob;
! 251: char *ts;
! 252: int size;
! 253: ob=cgiUrlEncodingToKeyValuePair("http://hoge.hoge?name=1231232&hoge=&foo=asdfasdf&hoge=A%41+%42%62y%21");
! 254: printObject(ob,1,stdout);
! 255: ts = cgiKeyValuePairToUrlEncoding(ob);
! 256: printf("result=%s",ts);
! 257:
! 258:
! 259: ts = "Pragma: no-cache\nContent-Length: 2915\nContent-Type: text/html\nConnection: close\n\n <DIV class=Section1> \n <P class=MsoNormal \n style=\"mso-list: none; mso-list-ins: \" 19991102T2025\"> \n </P> ";
! 260:
! 261: ob=cgiHttpToKeyValuePair(ts,strlen(ts));
! 262: printObject(ob,1,stdout);
! 263: ts = cgiKeyValuePairToHttp(ob,&size);
! 264: printf("result:\n%s",ts);
! 265:
! 266: }
! 267: /* end for debug */
! 268:
! 269:
! 270: char *cgiKeyValuePairToUrlEncoding(struct object ob) {
! 271: FILE2 *fp;
! 272: int size;
! 273: fp = fp2open(-1);
! 274: if (fp == NULL) errorKan1("%s\n","cgiKeyValuePairToUrlEncoding: open error.");
! 275: cgiKeyValuePairToUrlEncodingFile2(ob,fp);
! 276: return fp2fcloseInString(fp,&size);
! 277: }
! 278: int checkKeyValuePairFormat(struct object ob,char *msg) {
! 279: int i,n;
! 280: struct object eob,eob0,eob1;
! 281: static char *fmt = NULL;
! 282: int size;
! 283: char *ss;
! 284: size = 1024;
! 285: if (fmt == NULL) fmt = sGC_malloc(size);
! 286: if (fmt == NULL) errorKan1("%s\n","No more memory.");
! 287: for (i=0; i<size; i++) fmt[i]=0;
! 288: ss = "%s\n In ";
! 289: strcpy(fmt,ss);
! 290: strncpy(&(fmt[strlen(ss)]),msg,size-strlen(ss)-2);
! 291:
! 292: if (ob.tag != Sarray) errorKan1(fmt,"checkKeyValuePairFormat: argument must be an array.");
! 293: n = getoaSize(ob);
! 294: for (i=0; i<n ; i++) {
! 295: eob = getoa(ob,i);
! 296: if (eob.tag != Sarray) errorKan1(fmt,"checkKeyValuePairFormat: argument must be an array of arrays.");
! 297: if (getoaSize(eob) != 2) errorKan1(fmt,"checkKeyValuePairFormat: argument must be an array of arrays of size 2.");
! 298: eob0 = getoa(eob,0); eob1 = getoa(eob,1);
! 299: if (eob0.tag != Sdollar) errorKan1(fmt,"checkKeyValuePairFormat: the key word must be a string.\n");
! 300: }
! 301: return 0;
! 302: }
! 303:
! 304: int cgiKeyValuePairToUrlEncodingFile2(struct object ob,FILE2 *fp) {
! 305: int n,i;
! 306: struct object eob,eob0,eob1;
! 307: char *key, *s;
! 308: checkKeyValuePairFormat(ob,"cgiKeyValuePairToUrlEncodingFile2");
! 309: n = getoaSize(ob);
! 310: for (i=0; i<n; i++) {
! 311: eob = getoa(ob,i);
! 312: eob0 = getoa(eob,0); eob1 = getoa(eob,1);
! 313: key = KopString(eob0);
! 314: if (i == 0) {
! 315: if (strcmp(key,"URL") != 0) warningKan("Key word should be URL.\n");
! 316: if (eob1.tag != Sdollar) errorKan1("%s\n","URL value must be a string.");
! 317: fp2fputs(KopString(eob1),fp);
! 318: if ( n > 1 ) fp2fputc('?',fp);
! 319: }else{
! 320: fp2fputs(key,fp); fp2fputc('=',fp);
! 321: if (eob1.tag == Snull) ;
! 322: else if (eob1.tag == Sdollar) {
! 323: s = KopString(eob1);
! 324: fp2fputs(byteArrayToUrlEncoding((unsigned char *)s, strlen(s)),fp);
! 325: }else if (eob1.tag == SbyteArray) {
! 326: fp2fputs(byteArrayToUrlEncoding(KopByteArray(eob1),getByteArraySize(eob1)),fp);
! 327: }else{
! 328: errorKan1("%s\n","Value is not string nor byte array.");
! 329: }
! 330: if (i < n-1) fp2fputc('&',fp);
! 331: }
! 332: }
! 333: return(fp2fflush(fp));
! 334: }
! 335:
! 336: static struct object rStringToObj(char *s,int vstart,int vend,int mode) {
! 337: /* mode has not yet been used. */
! 338: struct object rob;
! 339: char *sss; int i;
! 340: int bytearray;
! 341: bytearray=0;
! 342: if (vend < vstart) return NullObject;
! 343: for (i=vstart; i<= vend; i++) {
! 344: if (s[i] == 0) bytearray=1;
! 345: }
! 346: if (bytearray) {
! 347: rob = newByteArrayFromStr(&(s[vstart]),vend-vstart+1);
! 348: return(rob);
! 349: }
! 350: sss = (char *)sGC_malloc(vend-vstart+1);
! 351: if (sss == NULL) errorKan1("%s\n","No more memory.");
! 352: for (i=vstart; i<=vend; i++) {
! 353: sss[i-vstart] = s[i]; sss[i-vstart+1] = 0;
! 354: }
! 355: rob = KpoString(sss);
! 356: return(rob);
! 357: }
! 358:
! 359: /*
! 360: [["Content-Body$,"Body"],
! 361: ["key1","value1"],
! 362: ["key2","value2"],
! 363: ...
! 364: ]
! 365: */
! 366: struct object cgiHttpToKeyValuePair(char *s,int size) {
! 367: int ssize,i,j,k;
! 368: int nOfPairs, startbody,state, kstart,kend,vstart, vend,startline,endline;
! 369: int nextstart,path;
! 370: struct object rob,ob;
! 371: ssize = strlen(s);
! 372: nOfPairs = 0; startbody = -1;
! 373: /* state==0 : readline and set startline and endline; state = 1;
! 374: state==1 : if the line is empty, then state=10;
! 375: Determine kstart,kend (key) and vstart,vend (value); state=0;
! 376: state==10 : Read the body.
! 377: */
! 378: for (path=0; path<2; path++) {
! 379: if (path == 1) {
! 380: rob = newObjectArray(nOfPairs+1); nOfPairs = 0;
! 381: }
! 382: i = 0; state=0;
! 383: while (i<size) {
! 384: if (state == 0) {
! 385: /* Read the line */
! 386: startline=i; endline= size-1; nextstart = size;
! 387: for (j = startline; j<size; j++) {
! 388: if (s[j] == 0xd) {
! 389: endline = j-1;
! 390: if (s[j+1] == 0xa) nextstart = j+2;
! 391: else nextstart = j+1;
! 392: break;
! 393: }else if (s[j] == 0xa) {
! 394: endline = j-1; nextstart = j+1; break;
! 395: }
! 396: }
! 397: state = 1; i = nextstart;
! 398: }else if (state == 1) {
! 399: if (endline <= startline) { state=10; }
! 400: else {
! 401: kstart=startline; kend = endline;
! 402: vstart=endline+1; vend = endline;
! 403: for (j=startline; j<=endline; j++) {
! 404: if (s[j] > ' ') {kstart = j; break;}
! 405: }
! 406: for (j=kstart; j<=endline; j++) {
! 407: if (s[j] == ':') { kend=j-1; break; }
! 408: }
! 409: for (j=kend+2; j<=endline; j++) {
! 410: if (s[j] > ' ') {vstart = j; break; }
! 411: }
! 412: for (j=vend; j >= vstart; j--) {
! 413: if (s[j] > ' ') { vend=j; break;}
! 414: else vend = j-1;
! 415: }
! 416: /* ppp(s,kstart,kend,vstart,vend); */
! 417: nOfPairs++;
! 418: if (path == 1) {
! 419: ob = newObjectArray(2);
! 420: putoa(ob,0,rStringToObj(s,kstart,kend,0));
! 421: putoa(ob,1,rStringToObj(s,vstart,vend,0));
! 422: putoa(rob,nOfPairs,ob);
! 423: }
! 424: state = 0;
! 425: }
! 426: }else {
! 427: startbody = i;
! 428: if (path == 1) {
! 429: ob = newObjectArray(2);
! 430: putoa(ob,0,KpoString("Content-Body"));
! 431: putoa(ob,1,rStringToObj(s,startbody,size-1,0));
! 432: putoa(rob,0,ob);
! 433: }
! 434: break;
! 435: }
! 436: }
! 437: }
! 438: return rob;
! 439: }
! 440:
! 441: char *cgiKeyValuePairToHttp(struct object ob,int *sizep) {
! 442: char *s;
! 443: FILE2 *fp;
! 444: int size;
! 445: fp=fp2open(-1);
! 446: cgiKeyValuePairToHttpFile2(ob,fp);
! 447: s = fp2fcloseInString(fp,sizep);
! 448: return(s);
! 449: }
! 450:
! 451: int cgiKeyValuePairToHttpFile2(struct object ob,FILE2 *fp) {
! 452: int n,i;
! 453: struct object eob,eob0,eob1;
! 454: char *key, *s;
! 455: checkKeyValuePairFormat(ob,"cgiKeyValuePairToHttpFile2");
! 456: n = getoaSize(ob);
! 457: if (n == 0) return(0);
! 458: for (i=1; i<n; i++) {
! 459: eob = getoa(ob,i);
! 460: eob0 = getoa(eob,0); eob1 = getoa(eob,1);
! 461: key = KopString(eob0);
! 462: fp2fputs(key,fp); fp2fputs(": ",fp);
! 463: if (eob1.tag == Snull) ;
! 464: else if (eob1.tag == Sdollar) {
! 465: s = KopString(eob1);
! 466: fp2fputs(s,fp);
! 467: }else{
! 468: errorKan1("%s\n","Value is not a string.");
! 469: }
! 470: if (i < n-1) fp2fputc('\n',fp);
! 471: else fp2fputs("\n\n",fp);
! 472: }
! 473: eob = getoa(ob,0);
! 474: eob0 = getoa(eob,0); eob1 = getoa(eob,1);
! 475: key = KopString(eob0);
! 476: if (strcmp(key,"Content-Body") != 0) warningKan("Key word should be Content-Body.\n");
! 477: if (eob1.tag == Sdollar) {
! 478: fp2fputs(KopString(eob1),fp);
! 479: }else if (eob1.tag == SbyteArray) {
! 480: fp2write(fp,KopByteArray(eob1),getByteArraySize(eob1));
! 481: }else errorKan1("%s\n","BODY must be a string or a byte array.");
! 482:
! 483: return(fp2fflush(fp));
! 484: }
! 485:
! 486:
! 487: static test3() {
! 488: char *s;
! 489: struct object ob;
! 490: s = "Pragma: no-cache\nContent-Length: 2915\nContent-Type: text/html\nConnection: close\n\n <DIV class=Section1> \n <P class=MsoNormal \n style=\"mso-list: none; mso-list-ins: \" 19991102T2025\"> \n </P> ";
! 491:
! 492: ob=cgiHttpToKeyValuePair(s,strlen(s));
! 493: printObject(ob,1,stdout);
! 494:
! 495: s = "Pragma:\nContent-Length: 2915\r\nContent-Type: text/html\nConnection: close\n\n <DIV class=Section1> \n <P class=MsoNormal \n style=\"mso-list: none; mso-list-ins: \" 19991102T2025\"> \n </P> ";
! 496: ob=cgiHttpToKeyValuePair(s,strlen(s));
! 497: printObject(ob,1,stdout);
! 498:
! 499: s = "Pragma\nContent-Length 2915\r\nContent-Type text/html\nConnection: close\n\n <DIV class=Section1> \n <P class=MsoNormal \n style=\"mso-list: none; mso-list-ins: \" 19991102T2025\"> \n </P> ";
! 500: ob=cgiHttpToKeyValuePair(s,strlen(s));
! 501: printObject(ob,1,stdout);
! 502:
! 503: {
! 504: char *s;
! 505: s = "This is a pen.com? !@#0989\n";
! 506: printf("\n%s\n",byteArrayToUrlEncoding((unsigned char *)s,strlen(s)));
! 507: }
! 508: }
! 509:
! 510: struct object cgiKeyValuePairToUrlEncodingString(struct object ob) {
! 511: char *s;
! 512: s = cgiKeyValuePairToUrlEncoding(ob);
! 513: if (s == NULL) return NullObject;
! 514: return KpoString(s);
! 515: }
! 516: struct object cgiKeyValuePairToHttpString(struct object ob) {
! 517: int size;
! 518: char *s;
! 519: s = cgiKeyValuePairToHttp(ob,&size);
! 520: if (s == NULL) return NullObject;
! 521: return KpoString(s);
! 522: }
! 523:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>