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

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.3     ! paf         6:        $Id: pa_vform.C,v 1.2 2001/03/14 17:09:21 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) {
        !           235:        String& sname=*NEW String(pool());
        !           236:        sname.APPEND_CONST(name);
        !           237: 
        !           238:        Value *value;
        !           239:        if(file_name)
        !           240:                value=0; //TODO NEW VFile(...)
        !           241:        else {
        !           242:                String& string=*NEW String(pool());
        !           243:                string.APPEND_TAINTED(value_ptr, value_size, "form", 0);
        !           244:                value=NEW VString(string);
        !           245:        }
        !           246: 
        !           247:        fields.put(sname, value);
        !           248: }
1.1       paf       249: 
                    250: void VForm::fill_fields(
                    251:                                                Request& request,
1.3     ! paf       252:                                                int post_max_size
1.1       paf       253:                                                )
                    254: {
1.3     ! paf       255:        // parsing QS [GET and ?name=value from uri rewrite)]
        !           256:        if(request.info.query_string)
        !           257:                ParseGetFormInput(request.info.query_string);
        !           258:        // parsing POSTed data
        !           259:        if(request.info.request_method) {
        !           260:                if(const char *content_type=request.info.content_type)
        !           261:                        if(StrEqNc(request.info.request_method, "post",true)) {
        !           262:                                int post_size=max(0, min(request.info.content_length, post_max_size));
        !           263:                                if(StrEqNc(content_type, "application/x-www-form-urlencoded",true)) 
        !           264:                                        ParsePostFormInput(content_type, post_size, false);
        !           265:                                else if(StrEqNc(content_type, "multipart/form-data",0))
        !           266:                                        ParsePostFormInput(content_type, post_size, true);
        !           267:                        }
        !           268:        } else
        !           269:                ; // TODO: разобрать пришедшее письмо, если какой ключик выставлен?
1.1       paf       270: }

E-mail: