File: [local] / OpenXM / src / kan96xx / plugin / oxcgi.c (download)
Revision 1.2, Fri Sep 24 08:35:47 2004 UTC (20 years ago) by takayama
Branch: MAIN
Changes since 1.1: +523 -1
lines
Modules to work for CGI.
URL encoding <---> keyValue pair
( cgiUrlEncodingKeyValuePair, cgiKeyValuePairToUrlEncoding )
HTTP <---> keyValue pair
( cgiHttpToKeyValuePair, cgiKeyValuePairToHttpString )
|
/* $OpenXM: OpenXM/src/kan96xx/plugin/oxcgi.c,v 1.2 2004/09/24 08:35:47 takayama Exp $ */
#include <stdio.h>
#include "datatype.h"
#include "stackm.h"
#include "extern.h"
#include "file2.h"
#include "oxcgi.h"
static int ppp(char *s,int kstart,int kend, int vstart, int vend);
static int cgiHex(int p);
static test1();
static test2();
static test3();
static test4();
/* main() {KSstart();test4();} */
/*
[["URL","http://www.openxm.org"],
["foo","value1"], <--- the first key value.
["hoge","value2"]
]
*/
struct object cgiUrlEncodingToKeyValuePair(char *s) {
int i,n,start;
int kstart,kend; /* start of key, end of key */
int vstart,vend; /* start of value, end of value */
int state;
int nOfPairs;
struct object rob;
struct object ob;
int k;
n = strlen(s); start = -1;
for (i=0; i<n; i++) {
if (s[i] == '?') { start=i+1; break;}
}
for (k=0; k<2; k++) {
/* k==0 path one. Count nOfPairs. */
/* k==1 path two. generate array. */
nOfPairs = 0;
i = start;
/* state 0, 1 : key
=
state 2, 3 : value
&
state 5 : after getting &
state 4 : after getting eof
state 6
*/
state = 0;
while (1) {
switch(state) {
case 0:
kstart = kend = vstart = vend = -1;
if (s[i] <= ' ') {
state=6; break;
} else {
kstart = kend = i;
nOfPairs++;
i++;
state=1;
break;
}
case 1:
if (s[i] <= ' ') {
state=4; break;
}else if (s[i] == '=') {
state=2; i++; break;
}else {
kend = i; i++; break;
}
case 2:
vstart = vend = -1;
if (s[i] <= ' ') {
state=4; break;
}else if (s[i] == '&') {
state=5; break;
}else {
state=3; vstart=vend=i; i++; break;
}
case 3:
if (s[i] <= ' ') {
state=4; break;
}else if (s[i] == '&') {
state=5; break;
}else{
vend=i; i++; break;
}
case 4:
if (k == 1) {
ob = newObjectArray(2);
putoa(ob,0,urlEncodedStringToObj(s,kstart,kend,0));
putoa(ob,1,urlEncodedStringToObj(s,vstart,vend,0));
putoa(rob,nOfPairs,ob);
}
state = -1; break;
case 5:
if (k == 1) {
ob = newObjectArray(2);
putoa(ob,0,urlEncodedStringToObj(s,kstart,kend,0));
putoa(ob,1,urlEncodedStringToObj(s,vstart,vend,0));
putoa(rob,nOfPairs,ob);
}
i++; state = 0; break;
case 6: state = -1; break;
default: break;
}
if (state < 0) break;
/*
if ((state == 4) || (state == 5)) {
ppp(s,kstart,kend,vstart,vend);
}
*/
}
if (k == 0) {
char *stmp; int ii;
rob = newObjectArray(nOfPairs+1);
ob = newObjectArray(2);
putoa(ob,0,KpoString("URL"));
stmp = sGC_malloc(start+2);
if (stmp == NULL) errorKan1("%s\n","No more memory.");
stmp[0] = 0;
for (ii=0; ii<start-1; ii++) {
stmp[ii] = s[ii]; stmp[ii+1] = 0;
}
putoa(ob,1,KpoString(stmp));
putoa(rob,0,ob);
}
}
return rob;
}
/* . - _ A-Z a-z 0-9
space --> +
*/
static int isUrlEncoding3(char s) {
if ((s == '.') || (s == '-') || (s == '_')) return(0);
if ((s >= 'A') && (s <= 'Z')) return(0);
if ((s >= 'a') && (s <= 'z')) return(0);
if ((s >= '0') && (s <= '9')) return(0);
if (s == ' ') return(0);
return(1);
}
char *byteArrayToUrlEncoding(unsigned char *s,int size) {
int n,i,j;
char *r;
n = 0;
/* get Size */
for (i=0; i<size; i++) {
if (isUrlEncoding3((char)s[i])) n += 3;
n++;
}
r = sGC_malloc(n+1);
if (r == NULL) errorKan1("%s\n","No more memory.");
r[0] = 0; r[n] = 0;
i = 0; j = 0;
while ((j < n) && (i<size)) {
if (isUrlEncoding3((char)s[i])) {
sprintf(&(r[j]),"%%%02X",s[i]); j += 3;
}else{
if ((char)s[i] == ' ') r[j]='+';
else r[j] = s[i];
j++; r[j] = 0;
}
i++;
}
return(r);
}
struct object urlEncodedStringToObj(char *s,int vstart,int vend,int mode)
/*
mode == 0. Authmatically choose Sdollar or SbyteArray.
[ not implemented yet. ]
*/
{
struct object rob;
char *ts;
char *ts2;
int i,j;
int p;
if ((s == NULL) || (vstart < 0)) return(NullObject);
if (vend+1-vstart <= 0) return(NullObject);
ts = (char *) malloc(vend-vstart+1);
if (ts == NULL) errorKan1("%s\n","Out of memory.");
j = 0; ts[j] = 0;
for (i=vstart; i<=vend; i++,j++) {
ts[j] = 0;
if (s[i] == '+') {
ts[j] = ' '; ts[j+1] = 0;
}else if (s[i] == '%') {
p = cgiHex(s[i+1])*16+cgiHex(s[i+2]);
i = i+2;
ts[j] = p; ts[j+1] = 0;
}else {
ts[j] = s[i]; ts[j+1] = 0;
}
}
ts2 = (char *)sGC_malloc(j);
if (ts2 == NULL) errorKan1("%s\n","Out of memory.");
for (i=0; i<j; i++) {
ts2[i] = ts[i];
}
return KpoString(ts2);
}
static int cgiHex(int p) {
if (p >= '0' && p <= '9') return (p-'0');
if (p >= 'A' && p <= 'F') return (p-'A'+10);
if (p >= 'a' && p <= 'f') return (p-'a'+10);
errorKan1("%s\n","Invalid argument to cgiHex.");
}
/* for debug */
static int ppp(char *s,int kstart,int kend, int vstart, int vend) {
int i;
printf("%d %d %d %d\n",kstart,kend,vstart,vend);
if (kstart >= 0) {
printf("key=");
for (i=kstart; i<=kend; i++) putchar(s[i]);
printf("\n");
}
if (vstart >= 0) {
printf("value=");
for (i=vstart; i<=vend; i++) putchar(s[i]);
printf("\n");
}
}
static test1() {
char s[1000];
cgiUrlEncodingToKeyValuePair("http://hoge.hoge?name=1231232&hoge=asdfsdf&foo=asdfasdf");
cgiUrlEncodingToKeyValuePair("http://hoge.hoge?name=1231232&hoge=&foo=asdfasdf&");
scanf("%s",s);
cgiUrlEncodingToKeyValuePair(s);
}
static test2() {
char s[1000];
struct object ob;
ob=cgiUrlEncodingToKeyValuePair("http://hoge.hoge?name=1231232&hoge=asdfsdf&foo=asdfasdf");
printObject(ob,1,stdout);
ob=cgiUrlEncodingToKeyValuePair("http://hoge.hoge?name=1231232&hoge=&foo=asdfasdf&hoge=A%41+%42%62y%21");
printObject(ob,1,stdout);
scanf("%s",s);
ob=cgiUrlEncodingToKeyValuePair(s);
printObject(ob,1,stdout);
}
static test4() {
char s[1000];
struct object ob;
char *ts;
int size;
ob=cgiUrlEncodingToKeyValuePair("http://hoge.hoge?name=1231232&hoge=&foo=asdfasdf&hoge=A%41+%42%62y%21");
printObject(ob,1,stdout);
ts = cgiKeyValuePairToUrlEncoding(ob);
printf("result=%s",ts);
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> ";
ob=cgiHttpToKeyValuePair(ts,strlen(ts));
printObject(ob,1,stdout);
ts = cgiKeyValuePairToHttp(ob,&size);
printf("result:\n%s",ts);
}
/* end for debug */
char *cgiKeyValuePairToUrlEncoding(struct object ob) {
FILE2 *fp;
int size;
fp = fp2open(-1);
if (fp == NULL) errorKan1("%s\n","cgiKeyValuePairToUrlEncoding: open error.");
cgiKeyValuePairToUrlEncodingFile2(ob,fp);
return fp2fcloseInString(fp,&size);
}
int checkKeyValuePairFormat(struct object ob,char *msg) {
int i,n;
struct object eob,eob0,eob1;
static char *fmt = NULL;
int size;
char *ss;
size = 1024;
if (fmt == NULL) fmt = sGC_malloc(size);
if (fmt == NULL) errorKan1("%s\n","No more memory.");
for (i=0; i<size; i++) fmt[i]=0;
ss = "%s\n In ";
strcpy(fmt,ss);
strncpy(&(fmt[strlen(ss)]),msg,size-strlen(ss)-2);
if (ob.tag != Sarray) errorKan1(fmt,"checkKeyValuePairFormat: argument must be an array.");
n = getoaSize(ob);
for (i=0; i<n ; i++) {
eob = getoa(ob,i);
if (eob.tag != Sarray) errorKan1(fmt,"checkKeyValuePairFormat: argument must be an array of arrays.");
if (getoaSize(eob) != 2) errorKan1(fmt,"checkKeyValuePairFormat: argument must be an array of arrays of size 2.");
eob0 = getoa(eob,0); eob1 = getoa(eob,1);
if (eob0.tag != Sdollar) errorKan1(fmt,"checkKeyValuePairFormat: the key word must be a string.\n");
}
return 0;
}
int cgiKeyValuePairToUrlEncodingFile2(struct object ob,FILE2 *fp) {
int n,i;
struct object eob,eob0,eob1;
char *key, *s;
checkKeyValuePairFormat(ob,"cgiKeyValuePairToUrlEncodingFile2");
n = getoaSize(ob);
for (i=0; i<n; i++) {
eob = getoa(ob,i);
eob0 = getoa(eob,0); eob1 = getoa(eob,1);
key = KopString(eob0);
if (i == 0) {
if (strcmp(key,"URL") != 0) warningKan("Key word should be URL.\n");
if (eob1.tag != Sdollar) errorKan1("%s\n","URL value must be a string.");
fp2fputs(KopString(eob1),fp);
if ( n > 1 ) fp2fputc('?',fp);
}else{
fp2fputs(key,fp); fp2fputc('=',fp);
if (eob1.tag == Snull) ;
else if (eob1.tag == Sdollar) {
s = KopString(eob1);
fp2fputs(byteArrayToUrlEncoding((unsigned char *)s, strlen(s)),fp);
}else if (eob1.tag == SbyteArray) {
fp2fputs(byteArrayToUrlEncoding(KopByteArray(eob1),getByteArraySize(eob1)),fp);
}else{
errorKan1("%s\n","Value is not string nor byte array.");
}
if (i < n-1) fp2fputc('&',fp);
}
}
return(fp2fflush(fp));
}
static struct object rStringToObj(char *s,int vstart,int vend,int mode) {
/* mode has not yet been used. */
struct object rob;
char *sss; int i;
int bytearray;
bytearray=0;
if (vend < vstart) return NullObject;
for (i=vstart; i<= vend; i++) {
if (s[i] == 0) bytearray=1;
}
if (bytearray) {
rob = newByteArrayFromStr(&(s[vstart]),vend-vstart+1);
return(rob);
}
sss = (char *)sGC_malloc(vend-vstart+1);
if (sss == NULL) errorKan1("%s\n","No more memory.");
for (i=vstart; i<=vend; i++) {
sss[i-vstart] = s[i]; sss[i-vstart+1] = 0;
}
rob = KpoString(sss);
return(rob);
}
/*
[["Content-Body$,"Body"],
["key1","value1"],
["key2","value2"],
...
]
*/
struct object cgiHttpToKeyValuePair(char *s,int size) {
int ssize,i,j,k;
int nOfPairs, startbody,state, kstart,kend,vstart, vend,startline,endline;
int nextstart,path;
struct object rob,ob;
ssize = strlen(s);
nOfPairs = 0; startbody = -1;
/* state==0 : readline and set startline and endline; state = 1;
state==1 : if the line is empty, then state=10;
Determine kstart,kend (key) and vstart,vend (value); state=0;
state==10 : Read the body.
*/
for (path=0; path<2; path++) {
if (path == 1) {
rob = newObjectArray(nOfPairs+1); nOfPairs = 0;
}
i = 0; state=0;
while (i<size) {
if (state == 0) {
/* Read the line */
startline=i; endline= size-1; nextstart = size;
for (j = startline; j<size; j++) {
if (s[j] == 0xd) {
endline = j-1;
if (s[j+1] == 0xa) nextstart = j+2;
else nextstart = j+1;
break;
}else if (s[j] == 0xa) {
endline = j-1; nextstart = j+1; break;
}
}
state = 1; i = nextstart;
}else if (state == 1) {
if (endline <= startline) { state=10; }
else {
kstart=startline; kend = endline;
vstart=endline+1; vend = endline;
for (j=startline; j<=endline; j++) {
if (s[j] > ' ') {kstart = j; break;}
}
for (j=kstart; j<=endline; j++) {
if (s[j] == ':') { kend=j-1; break; }
}
for (j=kend+2; j<=endline; j++) {
if (s[j] > ' ') {vstart = j; break; }
}
for (j=vend; j >= vstart; j--) {
if (s[j] > ' ') { vend=j; break;}
else vend = j-1;
}
/* ppp(s,kstart,kend,vstart,vend); */
nOfPairs++;
if (path == 1) {
ob = newObjectArray(2);
putoa(ob,0,rStringToObj(s,kstart,kend,0));
putoa(ob,1,rStringToObj(s,vstart,vend,0));
putoa(rob,nOfPairs,ob);
}
state = 0;
}
}else {
startbody = i;
if (path == 1) {
ob = newObjectArray(2);
putoa(ob,0,KpoString("Content-Body"));
putoa(ob,1,rStringToObj(s,startbody,size-1,0));
putoa(rob,0,ob);
}
break;
}
}
}
return rob;
}
char *cgiKeyValuePairToHttp(struct object ob,int *sizep) {
char *s;
FILE2 *fp;
int size;
fp=fp2open(-1);
cgiKeyValuePairToHttpFile2(ob,fp);
s = fp2fcloseInString(fp,sizep);
return(s);
}
int cgiKeyValuePairToHttpFile2(struct object ob,FILE2 *fp) {
int n,i;
struct object eob,eob0,eob1;
char *key, *s;
checkKeyValuePairFormat(ob,"cgiKeyValuePairToHttpFile2");
n = getoaSize(ob);
if (n == 0) return(0);
for (i=1; i<n; i++) {
eob = getoa(ob,i);
eob0 = getoa(eob,0); eob1 = getoa(eob,1);
key = KopString(eob0);
fp2fputs(key,fp); fp2fputs(": ",fp);
if (eob1.tag == Snull) ;
else if (eob1.tag == Sdollar) {
s = KopString(eob1);
fp2fputs(s,fp);
}else{
errorKan1("%s\n","Value is not a string.");
}
if (i < n-1) fp2fputc('\n',fp);
else fp2fputs("\n\n",fp);
}
eob = getoa(ob,0);
eob0 = getoa(eob,0); eob1 = getoa(eob,1);
key = KopString(eob0);
if (strcmp(key,"Content-Body") != 0) warningKan("Key word should be Content-Body.\n");
if (eob1.tag == Sdollar) {
fp2fputs(KopString(eob1),fp);
}else if (eob1.tag == SbyteArray) {
fp2write(fp,KopByteArray(eob1),getByteArraySize(eob1));
}else errorKan1("%s\n","BODY must be a string or a byte array.");
return(fp2fflush(fp));
}
static test3() {
char *s;
struct object ob;
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> ";
ob=cgiHttpToKeyValuePair(s,strlen(s));
printObject(ob,1,stdout);
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> ";
ob=cgiHttpToKeyValuePair(s,strlen(s));
printObject(ob,1,stdout);
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> ";
ob=cgiHttpToKeyValuePair(s,strlen(s));
printObject(ob,1,stdout);
{
char *s;
s = "This is a pen.com? !@#0989\n";
printf("\n%s\n",byteArrayToUrlEncoding((unsigned char *)s,strlen(s)));
}
}
struct object cgiKeyValuePairToUrlEncodingString(struct object ob) {
char *s;
s = cgiKeyValuePairToUrlEncoding(ob);
if (s == NULL) return NullObject;
return KpoString(s);
}
struct object cgiKeyValuePairToHttpString(struct object ob) {
int size;
char *s;
s = cgiKeyValuePairToHttp(ob,&size);
if (s == NULL) return NullObject;
return KpoString(s);
}