Skip to content
Snippets Groups Projects
Select Git revision
  • slyedit_quote_line_wrap_user_toggle_option
  • dd_msg_area_chooser_coloring_fix_and_separator_char_fix
  • master default protected
  • dailybuild_linux-x64
  • dailybuild_win32
  • sqlite
  • rip_abstraction
  • dailybuild_macos-armv8
  • dd_file_lister_filanem_in_desc_color
  • mode7
  • dd_msg_reader_are_you_there_warning_improvement
  • c23-playing
  • syncterm-1.3
  • syncterm-1.2
  • test-build
  • hide_remote_connection_with_telgate
  • 638-can-t-control-c-during-a-file-search
  • add_body_to_pager_email
  • mingw32-build
  • cryptlib-3.4.7
  • sbbs320d
  • syncterm-1.6
  • syncterm-1.5
  • syncterm-1.4
  • sbbs320b
  • syncterm-1.3
  • syncterm-1.2
  • syncterm-1.2rc6
  • syncterm-1.2rc5
  • push
  • syncterm-1.2rc4
  • syncterm-1.2rc2
  • syncterm-1.2rc1
  • sbbs319b
  • sbbs318b
  • goodbuild_linux-x64_Sep-01-2020
  • goodbuild_win32_Sep-01-2020
  • goodbuild_linux-x64_Aug-31-2020
  • goodbuild_win32_Aug-31-2020
  • goodbuild_win32_Aug-30-2020
40 results

filelist.js

Blame
  • filelist.js 12.24 KiB
    // List files in one or more Synchronet v3.19 file base directories
    // Note: '-strip' option requires v3.20 or later
    
    load("file_size.js");
    load("string.js");
    
    "use strict";
    
    function datestr(t)
    {
    	if(date_fmt)
    		return strftime(date_fmt, t);
    	return system.datestr(t);
    }
    
    function archive_date(file)
    {
    	try {
    		var list = Archive(file).list();
    	} catch(e) {
    		return file_date(file);
    	}
    	var t = 0;
    	for(var i = 0; i < list.length; i++)
    		t = Math.max(list[i].time, t);
    	return t;
    }
    
    function is_user_accessible_dir(dir)
    {
    	if(user.number === 0)
    		return true;
    	return user.compare_ars(file_area.dir[dir].ars)
    		&& user.compare_ars(file_area.dir[dir].download_ars);
    }
    
    var out = js.global.stdout ? stdout : console;
    var sort_prop;
    var exclude_list = [];
    var options = { sort: false, case_sensitive: true };
    var json_space;
    var detail = -1;
    var dir_list = [];
    var filespec = "";
    var extdesc_prefix;
    var both_desc = false;
    var since = 0;
    var props = [];
    var fmt;
    var name_len = 12;
    var date_fmt;
    var size_fmt = 2;
    var size_fmts = [
    //	 bytes,		precision,	minlen
    	[undefined, undefined,	10 	],
    	[false,		0,			5 ],
    	[false,		1,			6 ],
    	[false,		2,			7 ],
    	[1024,		0,			5 ],
    	[1024,		1,			6 ],
    	[1024,		2,			7 ],
    	[1024*1024,	0,			5 ],
    	[1024*1024,	1,			6 ],
    	[1024*1024,	2,			7 ],
    	[1024*1024,	3,			8 ],
    	[true,		undefined,	7 ],
    	[false,		undefined,	7 ],
    	];
    for(var i = 0; i < argc; i++) {
    	var arg = argv[i];
    	if(arg[0] == '-') {
    		var opt = arg;
    		while(opt[0] == '-')
    			opt = opt.slice(1);
    		if(opt == '?' || opt.toLowerCase() == "help") {
    			writeln("usage: [-options] [dir-code [...]] [include-filespec=*]");
    			writeln("options:");
    			writeln("  -all            list files in all libraries/directories");
    			writeln("  -lib=<name>     list files in all directories of specified library");
    			writeln("  -ex=<filespec>  add filename or spec to excluded filename list");
    			writeln("  -hdr            include header for each directory");
    			writeln("  -sort[=prop]    enable/configure file sorting");
    			writeln("  -i              perform case-insensitive global sorting");
    			writeln("  -reverse        reverse the sort order");
    			writeln("  -out=<file>     write output to specified filename (rather than stdout)");
    			writeln("  -json[=spaces]  use JSON formatted output");
    			writeln("  -utf8           use UTF-8 encoded output (instead of CP437)");
    			writeln("  -strip          strip Ctrl-A (attribute) sequences from output");
    			writeln("  -user=<name>    specify user to use for directory access checks");
    			writeln("  -new=<days>     include new files uploaded in past <days>");
    			writeln("  -p=<list>       specify comma-separated list of property names to print");
    			writeln("  -cdt            include credit value instead of file size");
    			writeln("  -desc           include file summary / description");
    			writeln("  -ext            include extended file descriptions");
    			writeln("  -ext=<prefix>   specify extended file description prefix");
    			writeln("  -fmt=<fmt>      specify output format string (printf syntax)");
    			writeln("  -date=<fmt>     specify date/time display format (strftime syntax)");
    			writeln("  -size=<fmt>     specify size/byte display format (0-" + (size_fmts.length - 1) + ")");
    			writeln("  -name=<len>     specify filename length (default: 12)");
    			writeln("  -pad            pad filename with spaces");
    			writeln("  -adate          use latest archived file date/time instead of file time");
    			writeln("  -v              increase verbosity (detail) of output");
    			exit(0);
    		}
    		if(opt.indexOf("ex=") == 0) {
    			exclude_list.push(opt.slice(3));
    			continue;
    		}
    		if(opt.indexOf("lib=") == 0) {
    			var lib = opt.slice(4);
    			if(!file_area.lib[lib]) {
    				alert("Library not found: " + lib);
    				exit(1);
    			}
    			for(var j = 0; j < file_area.lib[lib].dir_list.length; j++) {
    				var dir = file_area.lib[lib].dir_list[j].code;
    				if(is_user_accessible_dir(dir))
    					dir_list.push(dir);
    			}
    			options.auto = true;
    			continue;
    		}
    		if(opt.indexOf("new=") == 0) {
    			var days  = parseInt(opt.slice(4), 10);
    			since = time() - (days * (24 * 60 * 60));
    			continue;
    		}
    		if(opt.indexOf("pre=") == 0) {
    			precision = parseInt(opt.slice(4), 10);
    			continue;
    		}
    		if(opt.indexOf("date=") == 0) {
    			date_fmt = opt.slice(5);
    			continue;
    		}
    		if(opt.indexOf("name=") == 0) {
    			name_len = parseInt(opt.slice(5), 10);
    			continue;
    		}
    		if(opt.indexOf("sort=") == 0) {
    			sort_prop = opt.slice(5);
    			options.sort = true;
    			continue;
    		}
    		if(opt.indexOf("user=") == 0) {
    			user.number = system.matchuser(opt.slice(5));
    			if(user.number < 1)
    				alert("Invalid user specified: " + opt.slice(5));
    			continue;
    		}
    		if(opt.indexOf("out=") == 0) {
    			out = new File(opt.slice(4));
    			if(!out.open("w")) {
    				alert("Error " + out.error + " opening " + out.name);
    				exit(1);
    			}
    			continue;
    		}
    		if(opt == "i") {
    			options.case_sensitive = false;
    			continue;
    		}
    		if(opt[0] == 'v') {
    			var j = 0;
    			while(opt[j++] == 'v')
    				detail++;
    			continue;
    		}
    		if(opt.indexOf("ext=") == 0) {
    			extdesc_prefix = opt.slice(4);
    			detail = FileBase.DETAIL.EXTENDED;
    			continue;
    		}
    		if(opt == "ext") {
    			if(detail == FileBase.DETAIL.NORM)
    				both_desc = true;
    			detail = FileBase.DETAIL.EXTENDED;
    			continue;
    		}
    		if(opt == "desc") {
    			if(detail >= FileBase.DETAIL.EXTENDED)
    				both_desc = true;
    			else
    				detail = FileBase.DETAIL.NORM;
    			continue;
    		}
    		if(opt.indexOf("p=") == 0) {
    			props = props.concat(opt.slice(2).split(','));
    			continue;
    		}
    		if(opt == "json") {
    			fmt = "json";
    			json_space = 4;
    			continue;
    		}
    		if(opt.indexOf("json=") == 0) {
    			fmt = "json";
    			json_space = parseInt(opt.slice(5), 10);
    			continue;
    		}
    		if(opt.indexOf("fmt=") == 0) {
    			fmt = opt.slice(4);
    			continue;
    		}
    		if(opt.indexOf("size=") == 0) {
    			opt = opt.slice(5);
    			size_fmt = parseInt(opt, 10);
    			if(isNaN(size_fmt))
    				size_fmt = opt;
    			else if(size_fmt >= size_fmts.length)
    				size_fmt = 0;
    			continue;
    		}
    		if(opt == "all") {
    			for(var dir in file_area.dir) {
    				if(is_user_accessible_dir(dir))
    					dir_list.push(dir);
    			}
    			continue;
    		}
    		options[opt] = true;
    		continue;
    	}
    	if(file_area.dir[arg])
    		dir_list.push(arg);
    	else
    		filespec = arg;
    }
    if(fmt != "json") {
    
    	if(options.hdr || props.length)
    		detail = Math.max(FileBase.DETAIL.MIN, detail);
    
    	if(!props.length) {
    		var f = "%-" + name_len + "s";
    		var offset = name_len;
    		props.push("name");
    		if(detail >= FileBase.DETAIL.MIN) {
    			props.push("size");
    			if(typeof size_fmt == 'string')
    				f += size_fmt;
    			else {
    				f += " %" + size_fmts[size_fmt][2] + "s";
    				offset += size_fmts[size_fmt][2] + 1;
    			}
    		}
    		if(detail > FileBase.DETAIL.EXTENDED) {
    			props.push("time");
    			f += " %-8s";
    			offset += 9;
    		}
    		if(detail >= FileBase.DETAIL.NORM) {
    			props.push("desc");
    			f += " %-58s";
    		}
    		if(detail >= FileBase.DETAIL.EXTENDED) {
    			props.push("extdesc");
    			if(extdesc_prefix === undefined)
    				extdesc_prefix = format("%*s| ", offset - 1, "");
    			if(both_desc)
    				f += "%s";
    		}
    		if(!fmt)
    			fmt = f;
    	}
    	if(!fmt)
    		fmt = "%s ".repeat(props.length);
    }
    
    if(!dir_list.length) {
    	var code;
    	while(!file_area.dir[code] && !js.terminated) {
    		for(var d in file_area.dir)
    			writeln(d);
    		code = prompt("Directory code");
    	}
    	dir_list.push(code);
    }
    
    log("Reading " + dir_list.length + " file areas...");
    var dir_code;
    var file_list = [];
    for(var i = 0; i < dir_list.length; i++) {
    	dir_code = dir_list[i];
    	var base = new FileBase(dir_code);
    	if(!base.open())
    		throw new Error(base.last_error);
    	if(detail < 0)
    		file_list = file_list.concat(base.get_names(filespec, since, options.sort));
    	else {
    		var list = base.get_list(filespec, detail, since, options.sort);
    		for(var j = 0; j < list.length; j++) {
    			list[j].dir = dir_code;
    			if(list[j].extdesc) {
    				list[j].extdesc = "\n" + truncsp(list[j].extdesc);
    				js.flatten_string(list[j].extdesc);
    			}
    			if(options.adate)
    				list[j].time = archive_date(base.get_path(list[j]));
    			if(options.cdt)
    				list[j].size = list[j].cost;
    		}
    		file_list = file_list.concat(list);
    	}
    	base.close();
    }
    
    if(!file_list.length)
    	exit(0);
    
    if(!options.hdr && options.sort && sort_prop !== undefined) {
    	if(!options.case_sensitive) {
    		log("Sorting " + file_list.length + " files...");
    		if(typeof file_list[0] == "string")
    			file_list.sort(
    				function(a, b) {
    					if (a.toLowerCase() < b.toLowerCase()) return -1;
    					if (a.toLowerCase() > b.toLowerCase()) return 1;
    					return 0;
    				}
    			);
    		else {
    			file_list.sort(
    				function(a, b) {
    					var a = a[sort_prop];
    					var b = b[sort_prop];
    					if(typeof a == "string") {
    						var a = a.toLowerCase();
    						var b = b.toLowerCase();
    					}
    					if (a < b) return -1;
    					if (a > b) return 1;
    					return 0;
    				}
    			);
    		}
    	}
    	else {
    		log("Sorting " + file_list.length + " files...");
    		if(typeof file_list[0] == "string")
    			file_list.sort();
    		else {
    			file_list.sort(
    				function(a, b) {
    					if (a[sort_prop] < b[sort_prop]) return -1;
    					if (a[sort_prop] > b[sort_prop]) return 1;
    					return 0;
    				}
    			);
    		}
    	}
    }
    if(options.reverse)
    	file_list.reverse();
    
    log("Formatting " + file_list.length + " files for output...");
    if(fmt == "json") {
    	out.writeln(JSON.stringify(file_list, null, json_space));
    	exit(0);
    }
    var total_files = 0;
    var bytes = 0;
    var output = [];
    dir_code = undefined;
    for(var i = 0; i < file_list.length; i++) {
    	var file = file_list[i];
    	switch(typeof file) {
    		case "string":
    			if(excluded(file))
    				continue;
    			break;
    		case "object":
    			if(excluded(file.name))
    				continue;
    			bytes += file.size;
    			break;
    		default:
    			throw new Error(typeof file);
    			break;
    	}
    	if(typeof file == "object" && options.hdr && dir_code != file.dir) {
    		dir_code = file.dir;
    		var dir = file_area.dir[dir_code];
    		if(i)
    			output.push("");
    		var hdr = format("%-15s %-40s Files: %d", dir.lib_name, dir.description, dir.files);
    		output.push(hdr);
    		output.push(format("%.*s", hdr.length
    			, "-------------------------------------------------------------------------------"));
    	}
    	output.push(list_file(file, fmt, props));
    	++total_files;
    }
    
    for(var i in output) {
    	if(options.utf8)
    		output[i] = utf8_encode(output[i]);
    	if(options.strip)
    		output[i] = strip_ctrl_a(output[i]);
    	out.writeln(output[i]);
    }
    if(bytes)
    	out.writeln(format("%s bytes in %u files", file_size_str(bytes), total_files));
    else if(total_files)
    	out.writeln(format("%u files", total_files));
    
    function archive_contents(path, list)
    {
    	var output = [];
    	for(var i = 0; i < list.length; i++) {
    		var fname = path + list[i];
    		writeln(fname);
    		output.push(fname);
    		var contents;
    		try {
    			contents = Archive(fname).list();
    		} catch(e) {
    //			alert(e);
    			continue;
    		}
    		for(var j = 0; j < contents.length; j++)
    			output.push(contents[j].name + " " + contents[j].size);
    	}
    	return output;
    }
    
    function list_file(file, fmt, props)
    {
    	if(typeof file == 'string')
    		return file;
    	if(fmt === undefined)
    		fmt = "%s";
    	var a = [fmt];
    	for(var i in props) {
    		var name = props[i];
    		var p = file[name];
    		switch(typeof p) {
    			case "undefined":
    				if(name == 'desc')
    					a.push(file.name);
    				else
    					a.push('');
    				break;
    			case "string":
    				if(name == 'name')
    					a.push(FileBase().format_name(p, name_len, options.pad));
    				else if(name == 'extdesc') {
    					p = p.replace(/\r/g, '');
    					if(both_desc)
    						a.push(p.replace(/([^\n]+)/g, (extdesc_prefix + "$&")).trimRight());
    					else
    						a.push(p.trim().replace(/\n/g, '\n' + extdesc_prefix).trimRight());
    				}
    				else if(both_desc || name !== 'desc' || !file.extdesc)
    					a.push(p);
    				break;
    			case "number":
    				switch(name) {
    					case 'time':
    					case 'added':
    					case 'last_downloaded':
    						a.push(datestr(p));
    						break;
    					case 'crc32':
    						a.push(format("%08lx", p));
    						break;
    					case 'crc16':
    						a.push(format("%04lx", p));
    						break;
    					case 'size':
    					case 'cost':
    						if(typeof size_fmt == 'string') {
    							a.push(format(size_fmt, p));
    							break;
    						}
    						if(size_fmts[size_fmt][0] !== undefined
    							|| size_fmts[size_fmt][1] !== undefined) {
    							a.push(file_size_str(p
    								,/* unit: */ size_fmts[size_fmt][0]
    								,/* precision: */ size_fmts[size_fmt][1]));
    							break;
    						}
    					default:
    						a.push(p);
    						break;
    				}
    				break;
    		}
    	}
    	return format.apply(this, a);
    }
    
    function excluded(fname)
    {
    	for(var i = 0; i < exclude_list.length; i++)
    		if(wildmatch(fname, exclude_list[i]))
    			return true;
    	return false;
    }