--- parser3/src/classes/file.C 2026/10/01 14:16:36 1.302 +++ parser3/src/classes/file.C 2026/10/03 14:30:03 1.305 @@ -27,7 +27,7 @@ #include "pa_vregex.h" #include "pa_version.h" -volatile const char * IDENT_FILE_C="$Id: file.C,v 1.302 2026/10/01 14:16:36 moko Exp $"; +volatile const char * IDENT_FILE_C="$Id: file.C,v 1.305 2026/10/03 14:30:03 moko Exp $"; // defines @@ -707,6 +707,7 @@ static void _list(Request& r, MethodPara Value& relative_path=params.as_no_junction(0, "path must not be code"); bool stat=false; + bool fail_on_problem=false; VRegex* vregex=0; VRegexCleaner vrcleaner; @@ -724,6 +725,10 @@ static void _list(Request& r, MethodPara vfilter=value; valid_options++; } + if(Value* vexception=options->get(SUPPRESS_EXCEPTION_NAME)) { + fail_on_problem=r.process(*vexception).as_bool(); + valid_options++; + } if(valid_options!=options->count()) throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION); } else { @@ -745,11 +750,17 @@ static void _list(Request& r, MethodPara } } - const char* absolute_path_cstr=r.full_disk_path(relative_path.as_string()).taint_cstr(String::L_FILE_SPEC); - Table::Action_options table_options; Table& table=*new Table(file_list_table_template(), table_options); + // no exception for a uri or an invalid or tainted file:// + const String* path=fail_on_problem ? &r.full_disk_path(relative_path.as_string()) : r.real_disk_path(relative_path.as_string()); + if(!path) { + r.write(*new VTable(&table)); + return; + } + const char* absolute_path_cstr=path->taint_cstr(String::L_FILE_SPEC); + const int ovector_size=(1/*match*/)*3; int ovector[ovector_size]; @@ -769,6 +780,10 @@ static void _list(Request& r, MethodPara } table+=row; } + , + if(fail_on_problem) + throw Exception(errno==EACCES ? "file.access" : (errno==ENOENT || errno==ENOTDIR) ? "file.missing" : 0, + path, "list failed: %s (%d)%s", strerror(errno), errno, actual_filename(*path, absolute_path_cstr)); ); // write out result @@ -829,7 +844,7 @@ static const String* web_path(Request& r // checking the result is inside document root; // first checking the segment boundary: /root must not match /root-but-longer - return result.first_char()=='/' && !strncmp(disk_path->cstr(), document_root, document_root_length) ? &result : 0; + return result.first_char()=='/' && !path_cmp(disk_path->cstr(), document_root, document_root_length) ? &result : 0; } static void _find(Request& r, MethodParams& params) {