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