--- parser3/src/classes/file.C 2006/10/31 17:16:10 1.145 +++ parser3/src/classes/file.C 2007/02/07 15:50:32 1.151 @@ -5,7 +5,7 @@ Author: Alexandr Petrosian (http://paf.design.ru) */ -static const char * const IDENT_FILE_C="$Date: 2006/10/31 17:16:10 $"; +static const char * const IDENT_FILE_C="$Date: 2007/02/07 15:50:32 $"; #include "pa_config_includes.h" @@ -25,6 +25,7 @@ static const char * const IDENT_FILE_C=" #include "pa_charset.h" #include "pa_charsets.h" #include "pa_sql_connection.h" +#include "pa_md5.h" // defines @@ -149,6 +150,47 @@ static void _move(Request& r, MethodPara r.absolute(vto_file_name.as_string())); } +static void copy_process_source( + struct stat& , + int from_file, + const String& , const char* /*fname*/, bool, + void *context) { + int& to_file=*static_cast(context); + + int nCount=0; + do { + unsigned char buffer[FILE_BUFFER_SIZE]; + nCount = file_block_read(from_file, buffer, sizeof(buffer)); + int written=write(to_file, buffer, nCount); + if( written < 0 ) + throw Exception(0, + 0, + "write failed: %s (%d)", strerror(errno), errno); + + } while(nCount > 0); +} + +static void copy_open_target(int f, void *from_spec) { + String& file_spec=*static_cast(from_spec); + file_read_action_under_lock(file_spec, "copy", copy_process_source, &f); +}; + +static void _copy(Request& r, MethodParams& params) { + Value& vfrom_file_name=params.as_no_junction(0, "from file name must not be code"); + Value& vto_file_name=params.as_no_junction(1, "to file name must not be code"); + + String from_spec = r.absolute(vfrom_file_name.as_string()); + const String& to_spec = r.absolute(vto_file_name.as_string()); + + create_dir_for_file(to_spec); + + file_write_action_under_lock( + to_spec, + "copy", + copy_open_target, + &from_spec); +} + static void _load_pass_param( HashStringValue::key_type key, HashStringValue::value_type value, @@ -795,6 +837,8 @@ static void _sql(Request& r, MethodParam } static void _base64(Request& r, MethodParams& params) { + bool dynamic = !(&r.get_self() == file_class); + if ( dynamic ){ VFile& self=GET_SELF(r, VFile); if(params.count()) { // decode @@ -809,39 +853,128 @@ static void _base64(Request& r, MethodPa const char* encoded=pa_base64_encode(self.value_ptr(), self.value_size()); r.write_assign_lang(*new String(encoded, 0, true/*once ?param=base64(something) was needed*/)); } + } else { + // encode + const String& file_spec=params.as_string(0, "file name must be string"); + const char* encoded=pa_base64_encode(r.absolute(file_spec)); + r.write_assign_lang(*new String(encoded, 0, true/*once ?param=base64(something) was needed*/)); + } +} + +static void _crc32(Request& r, MethodParams& params) { + unsigned long crc32 = 0; + if(&r.get_self() == file_class) { + // ^file:crc32[file-name] + if(params.count()) { + const String& file_spec=params.as_string(0, "file name must be string"); + crc32=pa_crc32(r.absolute(file_spec)); + } else { + throw Exception("parser.runtime", + 0, + "file name must be defined"); + } + } else { + // ^file.crc32[] + VFile& self=GET_SELF(r, VFile); + crc32=pa_crc32(self.value_ptr(), self.value_size()); + } + r.write_no_lang(*new VInt(crc32)); +} + + +static void file_md5_file_action( + struct stat& finfo, + int f, + const String& , const char* /*fname*/, bool, + void *context) +{ + PA_MD5_CTX& md5context=*static_cast(context); + if(finfo.st_size) { + int nCount=0; + do { + unsigned char buffer[FILE_BUFFER_SIZE]; + nCount = file_block_read(f, buffer, sizeof(buffer)); + if ( nCount ){ + pa_MD5Update(&md5context, (const unsigned char*)buffer, nCount); + } + } while(nCount > 0); + } +} + +const char* pa_md5(const String& file_spec) +{ + PA_MD5_CTX context; + unsigned char digest[16]; + pa_MD5Init(&context); + file_read_action_under_lock(file_spec, "md5", file_md5_file_action, &context); + pa_MD5Final(digest, &context); + + return hex_string(digest, sizeof(digest), false); +} + +const char* pa_md5(const char *in, size_t in_size) +{ + PA_MD5_CTX context; + unsigned char digest[16]; + pa_MD5Init(&context); + pa_MD5Update(&context, (const unsigned char*)in, in_size); + pa_MD5Final(digest, &context); + + return hex_string(digest, sizeof(digest), false); +} + +static void _md5(Request& r, MethodParams& params) { + const char* md5; + if(&r.get_self() == file_class) { + // ^file:md5[file-name] + if(params.count()) { + const String& file_spec=params.as_string(0, "file name must be string"); + md5=pa_md5(r.absolute(file_spec)); + } else { + throw Exception("parser.runtime", + 0, + "file name must be defined"); + } + } else { + // ^file.md5[] + VFile& self=GET_SELF(r, VFile); + md5=pa_md5(self.value_ptr(), self.value_size()); + + } + r.write_no_lang(*new String(md5)); } // constructor MFile::MFile(): Methoded("file") { - // ^create[text;user-name;string] - // ^create[binary;user-name;SOMEDAY SOMETHING] + // ^file::create[text;user-name;string] + // ^file::create[binary;user-name;SOMEDAY SOMETHING] add_native_method("create", Method::CT_DYNAMIC, _create, 3, 3); - // ^save[mode;file-name] + // ^file.save[mode;file-name] add_native_method("save", Method::CT_DYNAMIC, _save, 2, 2); - // ^delete[file-name] + // ^file:delete[file-name] add_native_method("delete", Method::CT_STATIC, _delete, 1, 1); - // ^move[from-file-name;to-file-name] + // ^file:move[from-file-name;to-file-name] add_native_method("move", Method::CT_STATIC, _move, 2, 2); - // ^load[mode;disk-name] - // ^load[mode;disk-name;user-name] + // ^file::load[mode;disk-name] + // ^file::load[mode;disk-name;user-name] add_native_method("load", Method::CT_DYNAMIC, _load, 2, 3); - // ^stat[disk-name] + // ^file::stat[disk-name] add_native_method("stat", Method::CT_DYNAMIC, _stat, 1, 1); - // ^cgi[file-name] - // ^cgi[file-name;env hash] - // ^cgi[file-name;env hash;1cmd;2line;3ar;4g;5s] + // ^file::cgi[file-name] + // ^file::cgi[file-name;env hash] + // ^file::cgi[file-name;env hash;1cmd;2line;3ar;4g;5s] add_native_method("cgi", Method::CT_DYNAMIC, _cgi, 1, 2+50); - // ^exec[file-name] - // ^exec[file-name;env hash] - // ^exec[file-name;env hash;1cmd;2line;3ar;4g;5s] + // ^file::exec[file-name] + // ^file::exec[file-name;env hash] + // ^file::exec[file-name;env hash;1cmd;2line;3ar;4g;5s] add_native_method("exec", Method::CT_DYNAMIC, _exec, 1, 2+50); // ^file:list[path] @@ -851,8 +984,8 @@ MFile::MFile(): Methoded("file") { // ^file:lock[path]{code} add_native_method("lock", Method::CT_STATIC, _lock, 2, 2); - // ^find[file-name] - // ^find[file-name]{when-not-found} + // ^file:find[file-name] + // ^file:find[file-name]{when-not-found} add_native_method("find", Method::CT_STATIC, _find, 1, 2); // ^file:dirname[/a/some.tar.gz]=/a @@ -873,7 +1006,19 @@ MFile::MFile(): Methoded("file") { // ^file::sql[[alt_name]]{} add_native_method("sql", Method::CT_DYNAMIC, _sql, 1, 2); - // ^file.base64[] << encode // ^file::base64[string] << decode - add_native_method("base64", Method::CT_DYNAMIC, _base64, 0, 1); + // ^file.base64[] << encode + // ^file:base64[file-name] << encode + add_native_method("base64", Method::CT_ANY, _base64, 0, 1); + + // ^file.crc32[] + // ^file:crc32[file-name] + add_native_method("crc32", Method::CT_ANY, _crc32, 0, 1); + + // ^file.md5[] + // ^file:md5[file-name] + add_native_method("md5", Method::CT_ANY, _md5, 0, 1); + + // ^file:copy[from-file-name;to-file-name] + add_native_method("copy", Method::CT_STATIC, _copy, 2, 2); }