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