Annotation of parser3/src/types/pa_vfile.C, revision 1.55

1.34      paf         1: 
1.5       paf         2: /** @file
1.14      paf         3:        Parser: @b file parser type.
1.3       paf         4: 
1.51      moko        5:        Copyright (c) 2001-2012 Art. Lebedev Studio (http://www.artlebedev.com)
1.26      paf         6:        Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.30      paf         7: */
1.3       paf         8: 
1.37      paf         9: #include "classes.h"
1.1       paf        10: #include "pa_vfile.h"
                     11: #include "pa_vstring.h"
1.3       paf        12: #include "pa_vint.h"
1.50      misha      13: #include "pa_request.h"
1.1       paf        14: 
1.55    ! moko       15: volatile const char * IDENT_PA_VFILE_C="$Id: pa_vfile.C,v 1.54 2012-06-15 11:54:18 moko Exp $" IDENT_PA_VFILE_H;
1.51      moko       16: 
1.37      paf        17: // externs
                     18: 
                     19: extern Methoded* file_class;
                     20: 
                     21: // defines for statics
                     22: 
                     23: #define SIZE_NAME "size"
                     24: #define TEXT_NAME "text"
                     25: 
1.50      misha      26: #define MODE_VALUE_TEXT "text"
                     27: #define MODE_VALUE_BINARY "binary"
                     28: 
1.37      paf        29: // statics
                     30: 
                     31: static const String size_name(SIZE_NAME);
                     32: static const String text_name(TEXT_NAME);
1.50      misha      33: 
                     34: static const String mode_value_text(MODE_VALUE_TEXT);
                     35: static const String mode_value_binary(MODE_VALUE_BINARY);
1.37      paf        36: 
                     37: // methods
                     38: 
                     39: VStateless_class *VFile::get_class() { return file_class; }
                     40: 
1.54      moko       41: void VFile::set(bool atainted, const char* avalue_ptr, size_t avalue_size, const String* afile_name, Value* acontent_type, Request* r) {
1.8       paf        42:        fvalue_ptr=avalue_ptr;
                     43:        fvalue_size=avalue_size;
1.53      misha      44: 
1.43      misha      45:        ftext_tainted=atainted;
1.8       paf        46: 
1.10      paf        47:        ffields.clear();
1.43      misha      48: 
1.53      misha      49:        // $.size
1.50      misha      50:        ffields.put(size_name, new VInt(fvalue_size));
                     51: 
1.53      misha      52:        // $.name
1.50      misha      53:        set_name(afile_name);
                     54: 
                     55:        // $mime-type
                     56:        set_content_type(acontent_type, afile_name, r);
1.54      moko       57: }
1.53      misha      58: 
1.54      moko       59: void VFile::set(bool atainted, bool ais_text_mode, char* avalue_ptr, size_t avalue_size, const String* afile_name, Value* acontent_type, Request* r) {
                     60:        if(ais_text_mode && avalue_ptr && avalue_size) {
                     61:                fix_line_breaks(avalue_ptr, avalue_size);
                     62:        }
                     63:        set(atainted, avalue_ptr, avalue_size, afile_name, acontent_type, r);
                     64:        // $.mode
                     65:        set_mode(ais_text_mode);
                     66:        fis_text_content=ais_text_mode;
1.50      misha      67: }
                     68: 
1.54      moko       69: void VFile::set_binary(bool atainted, const char* avalue_ptr, size_t avalue_size, const String* afile_name, Value* acontent_type, Request* r) {
                     70:        set(atainted, avalue_ptr, avalue_size, afile_name, acontent_type, r);
                     71:        // $.mode
                     72:        set_mode(false);
                     73:        fis_text_content=false;
                     74: }
1.53      misha      75: 
1.54      moko       76: void VFile::set(VFile& avfile, bool ais_text_mode, const String* afile_name, Value* acontent_type, Request* r) {
                     77:        set(avfile.ftext_tainted, avfile.fvalue_ptr, avfile.fvalue_size, afile_name, acontent_type, r);
1.53      misha      78: 
                     79:        ffields.clear();
1.50      misha      80:        for(HashStringValue::Iterator i(avfile.ffields); i; i.next())
1.53      misha      81:                if(i.key() != text_name) // do not copy cached .text value
                     82:                        ffields.put_dont_replace(*new String(i.key(), String::L_TAINTED), i.value());
1.54      moko       83: 
                     84:        // $.mode
                     85:        set_mode(ais_text_mode);
                     86:        fis_text_content= avfile.fis_text_content;
1.53      misha      87: }
                     88: 
                     89: const char* VFile::text_cstr() {
                     90:        const char* p=value_ptr();
1.54      moko       91:        if(fis_text_content)
1.53      misha      92:                return p;
                     93: 
                     94:        size_t size=fvalue_size;
                     95: 
                     96:        if(const char *premature_zero_pos=(const char *)memchr(p, 0, size))
                     97:                size=premature_zero_pos-p;
                     98: 
                     99:        char *copy_ptr=size?strdup(p, size):0;
1.54      moko      100:        // text mode but binary content
1.53      misha     101:        if(fis_text_mode && size)
                    102:                fix_line_breaks(copy_ptr, size);
                    103:        return copy_ptr;
1.50      misha     104: }
                    105: 
1.53      misha     106: void VFile::set_mode(bool ais_text_mode){
                    107:        fis_text_mode=ais_text_mode;
                    108:        ffields.put(mode_name, new VString(ais_text_mode? mode_value_text : mode_value_binary ));
1.50      misha     109: }
                    110: 
                    111: void VFile::set_name(const String* afile_name){
1.14      paf       112:        char *lfile_name;
1.50      misha     113:        if(afile_name) {
                    114:                lfile_name=strdup(afile_name->taint_cstr(String::L_FILE_SPEC));
1.10      paf       115:                if(char *after_slash=rsplit(lfile_name, '\\'))
                    116:                        lfile_name=after_slash;
                    117:                if(char *after_slash=rsplit(lfile_name, '/'))
                    118:                        lfile_name=after_slash;
1.14      paf       119:        } else
1.54      moko      120:                lfile_name=(char *)NONAME_DAT;
1.50      misha     121: 
1.53      misha     122:        ffields.put(name_name, new VString(*new String(lfile_name, String::L_FILE_SPEC)));
1.50      misha     123: }
1.43      misha     124: 
1.50      misha     125: void VFile::set_content_type(Value* acontent_type, const String* afile_name, Request* r){
                    126:        if(!acontent_type && afile_name && r)
                    127:                acontent_type=new VString(r->mime_type_of(afile_name));
1.43      misha     128: 
                    129:        if(acontent_type)
                    130:                ffields.put(content_type_name, acontent_type);
                    131: }
                    132: 
1.46      misha     133: void VFile::save(Request_charsets& charsets, const String& file_spec, bool is_text, Charset* asked_charset) {
                    134:        if(fvalue_ptr)
                    135:                file_write(charsets, file_spec, fvalue_ptr, fvalue_size, is_text, false/*do_append*/, asked_charset);
                    136:        else
                    137:                throw Exception(PARSER_RUNTIME,
                    138:                        &file_spec,
                    139:                        "saving stat-ed file");
                    140: }
                    141: 
1.50      misha     142: bool VFile::is_text_mode(const String& mode) {
                    143:        if(mode==mode_value_text)
                    144:                return true;
                    145:        if(mode==mode_value_binary)
                    146:                return false;
                    147:        throw Exception(PARSER_RUNTIME,
                    148:                &mode,
                    149:                "is invalid mode, must be either '"MODE_VALUE_TEXT"' or '"MODE_VALUE_BINARY"'");
                    150: }
                    151:        
                    152: bool VFile::is_valid_mode (const String& mode) {
                    153:        return (mode==mode_value_text || mode==mode_value_binary);
                    154: }
                    155: 
1.45      misha     156: Value* VFile::get_element(const String& aname) {
1.43      misha     157:        Value* result;
                    158: 
                    159:        // $method
1.45      misha     160:        if(result=VStateless_object::get_element(aname))
1.43      misha     161:                return result;
                    162: 
                    163:        // $field
                    164:        if(result=ffields.get(aname))
                    165:                return result;
                    166: 
                    167:        // $text - if not cached
1.53      misha     168:        if(aname == text_name && fvalue_ptr && fvalue_size) {
1.43      misha     169:                // assigned file have ptr and we really have some bytes
1.42      misha     170: 
1.53      misha     171:                result=new VString(*new String(text_cstr(), ftext_tainted ? String::L_TAINTED : String::L_AS_IS));
1.42      misha     172: 
1.53      misha     173:                // cache it
1.43      misha     174:                ffields.put(text_name, result);
1.35      paf       175: 
                    176:                return result;
1.43      misha     177:        }
1.35      paf       178: 
1.43      misha     179:        return 0;
1.3       paf       180: }
1.48      misha     181: 
1.52      moko      182: const String* VFile::get_json_string(Json_options& options){
1.49      moko      183:        String& result=*new String("{\n", String::L_AS_IS);
                    184:        
                    185:        String * indent=NULL;
                    186: 
1.52      moko      187:        if (options.indent){
                    188:                indent = new String(",\n\t", String::L_AS_IS); *indent << options.indent << "\"";
                    189:                result << "\t" << options.indent;
1.49      moko      190:        }
                    191: 
                    192:        result << "\"class\":\"file\"";
1.48      misha     193: 
                    194:        for(HashStringValue::Iterator i(ffields); i; i.next() ){
                    195:                String::Body key=i.key();
                    196:                if(key != text_name){
1.49      moko      197:                        indent ? result << *indent : result << ",\n\"";
                    198:                        result << String(key, String::L_JSON) << "\":" << *i.value()->get_json_string(options);
1.48      misha     199:                }
                    200:        }
                    201: 
                    202:        if(fvalue_ptr){
1.52      moko      203:                switch(options.file){
1.48      misha     204:                        case Json_options::F_BASE64:
                    205:                                {
1.49      moko      206:                                        indent ? result << *indent : result << ",\n\"";
                    207:                                        result << "base64\":\"";
1.48      misha     208:                                        const char* encoded=pa_base64_encode(fvalue_ptr, fvalue_size);
1.55    ! moko      209:                                        result.append_help_length(encoded, 0, String::L_JSON);
1.49      moko      210:                                        result << "\"";
1.48      misha     211:                                        break;
                    212:                                }
                    213:                        case Json_options::F_TEXT:
                    214:                                {
1.49      moko      215:                                        indent ? result << *indent : result << ",\n\"";
                    216:                                        result << "text\":\"";
1.55    ! moko      217:                                        result.append_help_length(text_cstr(), 0, String::L_JSON);
1.49      moko      218:                                        result << "\"";
1.48      misha     219:                                        break;
                    220:                                }
                    221:                }
                    222:        }
                    223: 
1.52      moko      224:        result << "\n" << options.indent << "}";
1.49      moko      225:        return &result;
1.48      misha     226: }

E-mail: