Annotation of parser3/src/types/pa_vform.C, revision 1.5

1.1       paf         1: /*
                      2:        Parser
1.3       paf         3:        Copyright(c) 2001 ArtLebedev Group(http://www.artlebedev.com)
                      4:        Author: Alexander Petrosyan <paf@design.ru>(http://design.ru/paf)
1.1       paf         5: 
1.5     ! paf         6:        $Id: pa_vform.C,v 1.4 2001/03/16 12:30:26 paf Exp $
1.1       paf         7: */
                      8: 
1.3       paf         9: /*
                     10:        based on cgic by TODO:?
                     11: */
                     12: 
                     13: #include <ctype.h>
                     14: #include <string.h>
                     15: 
1.1       paf        16: #include "pa_vform.h"
                     17: #include "pa_vstring.h"
1.3       paf        18: #include "pa_globals.h"
                     19: #include "pa_common.h"
                     20: #include "pa_request.h"
                     21: 
                     22: // parse helper funcs
                     23: 
                     24: static bool StrEqNc(const char *s1, const char *s2, bool strict) {
                     25:        while(true) {
                     26:                if(!(*s1)) {
                     27:                        if(!(*s2))
                     28:                                return true;
                     29:                        else
                     30:                                return !strict;
                     31:                } else if(!(*s2))
                     32:                        return !strict;
                     33:                if(isalpha(*s1)) {
                     34:                        if(tolower(*s1) !=tolower(*s2))
                     35:                                return false;
                     36:                } else if((*s1) !=(*s2))
                     37:                        return false;
                     38:                s1++;
                     39:                s2++;
                     40:        }
                     41: }
                     42: 
                     43: static int getHeader(const char *data,int len){
                     44:     int i,enter=-1;
                     45:     if (data)
                     46:        for (i=0;i<len;i++)
                     47:            if (data[i]=='\n'){
                     48:                if (enter>=0) enter++;
                     49:                if (enter>1) return i;
                     50:            } else if (data[i]!='\r') enter=0;
                     51:     return 0;
                     52: }
                     53: 
                     54: static const char *searchAttribute(const char *data,const char *attr,int len){
                     55:     int i;
                     56:     if (data)
                     57:        for (i=0;i<len;i++)
                     58:            if (tolower(data[i])==*attr){
                     59:                int j;
                     60:                for (j=i+1;j<=len;j++)
                     61:                    if (!attr[j-i]) return &data[j];
                     62:                    else {
                     63:                        if (j==len) break;
                     64:                        if (attr[j-i]!=tolower(data[j])) break;
                     65:                    }
                     66:            }
                     67:     return NULL;
                     68: }
                     69: 
                     70: // VForm
                     71: 
                     72: char *VForm::strpart(const char *str, int len) {
                     73:     char *result=(char *)malloc(len+1); // TODO
                     74:     if (!result) return NULL;
                     75:     memcpy(result,str,len);
                     76:     result[len]=0;
                     77:     return result;
                     78: }
                     79: 
                     80: char *VForm::getAttributeValue(const char *data,char *attr,int len) {
                     81:     const char *value=searchAttribute(data,attr,len);
                     82:     if (value){
                     83:        int i;
                     84:        if (!(len-=value-data)) return NULL;
                     85:        if (*value=='"') {
                     86:            for (i=1;i<len;i++) if (value[i]=='"') break;
                     87:            return strpart(&value[1],i-1);
                     88:        } else {
                     89:            for (i=0;i<len;i++) if (strchr(" ;\"\n\r",value[i])) break;
                     90:            return strpart(value,i);
                     91:        }
                     92:     }
                     93:     return NULL;
                     94: }
                     95: 
                     96: void VForm::UnescapeChars(char **sp, const char *cp, int len) {
                     97:        char *s;
                     98:        EscapeState escapeState=EscapeRest;
                     99:        int escapedValue=0;
                    100:        int srcPos=0;
                    101:        int dstPos=0;
                    102:        s=(char *) malloc(len + 1);
                    103:        while(srcPos < len) {
                    104:                int ch=cp[srcPos];
                    105:                switch(escapeState) {
                    106:                        case EscapeRest:
                    107:                        if(ch=='%') {
                    108:                                escapeState=EscapeFirst;
                    109:                        } else if(ch=='+') {
                    110:                                s[dstPos++]=' ';
                    111:                        } else {
                    112:                                s[dstPos++]=ch; 
                    113:                        }
                    114:                        break;
                    115:                        case EscapeFirst:
                    116:                        escapedValue=hex_value[ch] << 4;        
                    117:                        escapeState=EscapeSecond;
                    118:                        break;
                    119:                        case EscapeSecond:
                    120:                        escapedValue +=hex_value[ch];
                    121:                        s[dstPos++]=escapedValue;
                    122:                        escapeState=EscapeRest;
                    123:                        break;
                    124:                }
                    125:                srcPos++;
                    126:        }
                    127:        s[dstPos]=0;
                    128:        *sp=s;
                    129: }              
                    130:        
                    131: 
                    132: void VForm::ParseGetFormInput(const char *query_string) {
                    133:        ParseFormInput(query_string, strlen(query_string));
                    134: }
                    135: 
                    136: void VForm::ParsePostFormInput(const char *content_type, int post_size, 
                    137:                                                           bool mime_mode) {
                    138:        char *input;
                    139:        if(!post_size) 
                    140:                return;
                    141: 
                    142:        input=(char *) malloc(post_size);
                    143:        int read_size=(*service_funcs.read_post)(input, post_size);
                    144:        if(read_size !=post_size)
                    145:                THROW(0, 0,
                    146:                        0,
                    147:                        "ParsePostFormInput: post_size(%d)!=read_size(%d)", 
                    148:                                post_size, read_size);
                    149: 
                    150:        if(mime_mode)
                    151:                ParseMimeInput(content_type, input, post_size);
                    152:        else
                    153:                ParseFormInput(input, post_size);
                    154:        //free(input);
                    155: }
                    156: 
                    157: void VForm::ParseFormInput(const char *data, int length) {
                    158:                /* Scan for pairs, unescaping and storing them as they are found. */
                    159:        int pos=0;
                    160:        while(pos !=length) {
                    161:                int foundEq=0;
                    162:                int foundAmp=0;
                    163:                int start=pos;
                    164:                int len=0;
                    165:                char *attr;
                    166:                char *value;
                    167:                while(pos !=length) {
                    168:                        if(data[pos]=='=') {
                    169:                                foundEq=1;
                    170:                                pos++;
                    171:                                break;
                    172:                        }
                    173:                        pos++;
                    174:                        len++;
                    175:                }
                    176:                if(!foundEq)
                    177:                        break;
                    178:                UnescapeChars(&attr, data+start, len);
                    179:                start=pos;
                    180:                len=0;
                    181:                while(pos !=length) {
                    182:                        if(data[pos]=='&') {
                    183:                                foundAmp=1;
                    184:                                pos++;
                    185:                                break;
                    186:                        }
                    187:                        pos++;
                    188:                        len++;
                    189:                }
                    190:                /* The last pair probably won't be followed by a &, but
                    191:                        that's fine, so check for that after accepting it */
                    192:                UnescapeChars(&value, data+start, len);
                    193:                /* OK, we have a new pair, add it to the list. */
                    194:                AppendFormEntry(attr, value);
                    195:                if(!foundAmp)
                    196:                        break;
                    197:        }
                    198: }
                    199: 
                    200: void VForm::ParseMimeInput(const char *content_type, 
                    201:                                                                          const char *data, int length) {
                    202: /* Scan for mime-presented pairs, storing them as they are found. */
                    203:        const char 
                    204:                *boundary=getAttributeValue(content_type,"boundary=",strlen(content_type)),
                    205:            *lastData=&data[length];
                    206:        if(!boundary) 
                    207:                THROW(0,0,
                    208:                        0,
                    209:                        "VForm::ParseMimeInput no boundary attribute of Content-Type");
                    210: 
                    211:        while(true) {
                    212:                const char 
                    213:                        *dataStart=searchAttribute(data,boundary,lastData-data),
                    214:                        *dataEnd=searchAttribute(dataStart,boundary,lastData-dataStart);
                    215:                int headerSize=getHeader(dataStart,lastData-dataStart);
                    216: 
                    217:                if(!dataStart|!dataEnd|!headerSize) break;
                    218:                if(searchAttribute(dataStart,"content-disposition: form-data",headerSize)){
                    219:                        int valueSize=(dataEnd-dataStart)-headerSize-5-strlen(boundary);
                    220:                        char *attr=getAttributeValue(dataStart," name=",headerSize),
                    221:                             *fName=getAttributeValue(dataStart," filename=",headerSize);
                    222: 
                    223:                        if(attr && valueSize){
                    224:                                /* OK, we have a new pair, add it to the list. */
                    225:                                AppendFormEntry(attr, &dataStart[headerSize+1], valueSize, fName);
                    226:                        }
                    227:                }
                    228:                data=(dataEnd-strlen(boundary));
                    229:        }
                    230: }
                    231: 
                    232: void VForm::AppendFormEntry(const char *name, 
                    233:                                                        const char *value_ptr, int value_size,
                    234:                                                        const char *file_name) {
1.5     ! paf       235:        String& sname=*NEW String(pool(), name);
1.3       paf       236: 
                    237:        Value *value;
                    238:        if(file_name)
                    239:                value=0; //TODO NEW VFile(...)
                    240:        else {
                    241:                String& string=*NEW String(pool());
                    242:                string.APPEND_TAINTED(value_ptr, value_size, "form", 0);
                    243:                value=NEW VString(string);
                    244:        }
                    245: 
                    246:        fields.put(sname, value);
                    247: }
1.1       paf       248: 
                    249: void VForm::fill_fields(
                    250:                                                Request& request,
1.3       paf       251:                                                int post_max_size
1.1       paf       252:                                                )
                    253: {
1.3       paf       254:        // parsing QS [GET and ?name=value from uri rewrite)]
                    255:        if(request.info.query_string)
                    256:                ParseGetFormInput(request.info.query_string);
                    257:        // parsing POSTed data
1.4       paf       258:        if(request.info.method) {
1.3       paf       259:                if(const char *content_type=request.info.content_type)
1.4       paf       260:                        if(StrEqNc(request.info.method, "post",true)) {
1.3       paf       261:                                int post_size=max(0, min(request.info.content_length, post_max_size));
                    262:                                if(StrEqNc(content_type, "application/x-www-form-urlencoded",true)) 
                    263:                                        ParsePostFormInput(content_type, post_size, false);
                    264:                                else if(StrEqNc(content_type, "multipart/form-data",0))
                    265:                                        ParsePostFormInput(content_type, post_size, true);
                    266:                        }
                    267:        } else
                    268:                ; // TODO: разобрать пришедшее письмо, если какой ключик выставлен?
1.1       paf       269: }

E-mail: