Annotation of OpenXM/src/kan96xx/plugin/oxcgi.c, Revision 1.3
1.3 ! takayama 1: /* $OpenXM: OpenXM/src/kan96xx/plugin/oxcgi.c,v 1.2 2004/09/24 08:35:47 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: }
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:
1.3 ! takayama 524: struct object KooStringToUrlEncoding(struct object sob) {
! 525: unsigned char *s;
! 526: char *rs;
! 527: int n;
! 528: if (sob.tag == Sdollar) {
! 529: s = (unsigned char *) KopString(sob);
! 530: n = strlen((char *)s);
! 531: }else if (sob.tag == SbyteArray) {
! 532: s = KopByteArray(sob);
! 533: n = getByteArraySize(sob);
! 534: }else errorKan1("%s\n","KooStringToUrlEncoding: argument must be a string or a bytearray.");
! 535: rs = byteArrayToUrlEncoding(s,n);
! 536: return KpoString(rs);
! 537: }
! 538:
! 539: struct object KooUrlEncodedStringToObj(struct object sob) {
! 540: char *s;
! 541: int n;
! 542: if (sob.tag == Sdollar) {
! 543: s = KopString(sob);
! 544: n = strlen((char *)s);
! 545: }else if (sob.tag == SbyteArray) {
! 546: s = KopByteArray(sob);
! 547: n = getByteArraySize(sob);
! 548: }else errorKan1("%s\n","KooUrlEncodedStringToObj: argument must be a string.");
! 549: return urlEncodedStringToObj(s,0,n-1,0);
! 550: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>