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