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