Annotation of parser3/src/types/pa_vfile.C, revision 1.53
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.53 ! misha 15: volatile const char * IDENT_PA_VFILE_C="$Id: pa_vfile.C,v 1.52 2012-05-28 19:47:52 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:
41: void VFile::set(
1.43 misha 42: bool atainted,
1.53 ! misha 43: bool ais_text_mode,
! 44: char* avalue_ptr,
1.50 misha 45: size_t avalue_size,
46: const String* afile_name,
47: Value* acontent_type,
48: Request* r) {
1.53 ! misha 49:
1.8 paf 50: fvalue_ptr=avalue_ptr;
51: fvalue_size=avalue_size;
1.53 ! misha 52:
1.43 misha 53: ftext_tainted=atainted;
1.53 ! misha 54: feols_normalized=false;
1.8 paf 55:
1.10 paf 56: ffields.clear();
1.43 misha 57:
1.53 ! misha 58: // $.size
1.50 misha 59: ffields.put(size_name, new VInt(fvalue_size));
60:
1.53 ! misha 61: // $.mode
! 62: set_mode(ais_text_mode);
! 63:
! 64: // $.name
1.50 misha 65: set_name(afile_name);
66:
67: // $mime-type
68: set_content_type(acontent_type, afile_name, r);
1.53 ! misha 69:
! 70: fix_line_breaks_set();
1.50 misha 71: }
72:
1.53 ! misha 73: void VFile::set(VFile& avfile) {
! 74: fvalue_ptr=avfile.fvalue_ptr;
! 75: fvalue_size=avfile.fvalue_size;
! 76:
! 77: ftext_tainted=avfile.ftext_tainted;
! 78: fis_text_mode=avfile.fis_text_mode;
! 79: feols_normalized=avfile.feols_normalized;
! 80:
! 81: fix_line_breaks_set();
! 82:
! 83: ffields.clear();
1.50 misha 84:
85: for(HashStringValue::Iterator i(avfile.ffields); i; i.next())
1.53 ! misha 86: if(i.key() != text_name) // do not copy cached .text value
! 87: ffields.put_dont_replace(*new String(i.key(), String::L_TAINTED), i.value());
! 88: }
! 89:
! 90: const char* VFile::text_cstr() {
! 91: const char* p=value_ptr();
! 92: if(feols_normalized)
! 93: return p;
! 94:
! 95: size_t size=fvalue_size;
! 96:
! 97: // have to check for "text" files as well because mode could be changed after creation by set_mode()
! 98: if(const char *premature_zero_pos=(const char *)memchr(p, 0, size))
! 99: size=premature_zero_pos-p;
! 100:
! 101: char *copy_ptr=size?strdup(p, size):0;
! 102: if(fis_text_mode && size)
! 103: fix_line_breaks(copy_ptr, size);
! 104:
! 105: return copy_ptr;
1.50 misha 106: }
107:
1.53 ! misha 108: void VFile::set_mode(bool ais_text_mode){
! 109: fis_text_mode=ais_text_mode;
! 110: ffields.put(mode_name, new VString(ais_text_mode? mode_value_text : mode_value_binary ));
1.50 misha 111: }
112:
113: void VFile::set_name(const String* afile_name){
1.14 paf 114: char *lfile_name;
1.50 misha 115: if(afile_name) {
116: lfile_name=strdup(afile_name->taint_cstr(String::L_FILE_SPEC));
1.10 paf 117: if(char *after_slash=rsplit(lfile_name, '\\'))
118: lfile_name=after_slash;
119: if(char *after_slash=rsplit(lfile_name, '/'))
120: lfile_name=after_slash;
1.14 paf 121: } else
1.16 paf 122: lfile_name=NONAME_DAT;
1.50 misha 123:
1.53 ! misha 124: ffields.put(name_name, new VString(*new String(lfile_name, String::L_FILE_SPEC)));
1.50 misha 125: }
1.43 misha 126:
1.50 misha 127: void VFile::set_content_type(Value* acontent_type, const String* afile_name, Request* r){
128: if(!acontent_type && afile_name && r)
129: acontent_type=new VString(r->mime_type_of(afile_name));
1.43 misha 130:
131: if(acontent_type)
132: ffields.put(content_type_name, acontent_type);
133: }
134:
1.46 misha 135: void VFile::save(Request_charsets& charsets, const String& file_spec, bool is_text, Charset* asked_charset) {
136: if(fvalue_ptr)
137: file_write(charsets, file_spec, fvalue_ptr, fvalue_size, is_text, false/*do_append*/, asked_charset);
138: else
139: throw Exception(PARSER_RUNTIME,
140: &file_spec,
141: "saving stat-ed file");
142: }
143:
1.50 misha 144: bool VFile::is_text_mode(const String& mode) {
145: if(mode==mode_value_text)
146: return true;
147: if(mode==mode_value_binary)
148: return false;
149: throw Exception(PARSER_RUNTIME,
150: &mode,
151: "is invalid mode, must be either '"MODE_VALUE_TEXT"' or '"MODE_VALUE_BINARY"'");
152: }
153:
154: bool VFile::is_valid_mode (const String& mode) {
155: return (mode==mode_value_text || mode==mode_value_binary);
156: }
157:
1.53 ! misha 158: void VFile::fix_line_breaks_set() {
! 159: if(!feols_normalized && fis_text_mode && fvalue_ptr && fvalue_size) {
! 160: fix_line_breaks(fvalue_ptr, fvalue_size);
! 161: feols_normalized=true;
! 162: }
! 163: }
! 164:
1.45 misha 165: Value* VFile::get_element(const String& aname) {
1.43 misha 166: Value* result;
167:
168: // $method
1.45 misha 169: if(result=VStateless_object::get_element(aname))
1.43 misha 170: return result;
171:
172: // $field
173: if(result=ffields.get(aname))
174: return result;
175:
176: // $text - if not cached
1.53 ! misha 177: if(aname == text_name && fvalue_ptr && fvalue_size) {
1.43 misha 178: // assigned file have ptr and we really have some bytes
1.42 misha 179:
1.53 ! misha 180: result=new VString(*new String(text_cstr(), ftext_tainted ? String::L_TAINTED : String::L_AS_IS));
1.42 misha 181:
1.53 ! misha 182: // cache it
1.43 misha 183: ffields.put(text_name, result);
1.35 paf 184:
185: return result;
1.43 misha 186: }
1.35 paf 187:
1.43 misha 188: return 0;
1.3 paf 189: }
1.48 misha 190:
1.52 moko 191: const String* VFile::get_json_string(Json_options& options){
1.49 moko 192: String& result=*new String("{\n", String::L_AS_IS);
193:
194: String * indent=NULL;
195:
1.52 moko 196: if (options.indent){
197: indent = new String(",\n\t", String::L_AS_IS); *indent << options.indent << "\"";
198: result << "\t" << options.indent;
1.49 moko 199: }
200:
201: result << "\"class\":\"file\"";
1.48 misha 202:
203: for(HashStringValue::Iterator i(ffields); i; i.next() ){
204: String::Body key=i.key();
205: if(key != text_name){
1.49 moko 206: indent ? result << *indent : result << ",\n\"";
207: result << String(key, String::L_JSON) << "\":" << *i.value()->get_json_string(options);
1.48 misha 208: }
209: }
210:
211: if(fvalue_ptr){
1.52 moko 212: switch(options.file){
1.48 misha 213: case Json_options::F_BASE64:
214: {
1.49 moko 215: indent ? result << *indent : result << ",\n\"";
216: result << "base64\":\"";
1.48 misha 217: const char* encoded=pa_base64_encode(fvalue_ptr, fvalue_size);
1.49 moko 218: result.append_help_length(encoded, strlen(encoded), String::L_JSON);
219: result << "\"";
1.48 misha 220: break;
221: }
222: case Json_options::F_TEXT:
223: {
1.49 moko 224: indent ? result << *indent : result << ",\n\"";
225: result << "text\":\"";
226: result.append(get_element(text_name)->as_string(), String::L_JSON, true/*forced lang*/);
227: result << "\"";
1.48 misha 228: break;
229: }
230: }
231: }
232:
1.52 moko 233: result << "\n" << options.indent << "}";
1.49 moko 234: return &result;
1.48 misha 235: }
E-mail: