// -------------------- Global Variables // Helper Objects var fs = new ActiveXObject("Scripting.FileSystemObject"); var st = DOpus.Create.StringTools(); // Default example for the mapDirToBrowser setting. var map_dir_to_browser = { "D:\\Bookmarks\\Other\\": "C:\\Bin\\Browser.exe", }; // Columns' Definitions var config = { columns: [ { name: "ToAddress", displayName: "To Address", target: "mail", re: /^To:\s(.*)$/, type: "string", defwidth: 18 }, { name: "FromAddress", displayName: "From Address", target: "mail", re: /^From:\s(.*)$/, type: "string", defwidth: 18 }, { name: "Subject", displayName: "Subject", target: "mail", re: /^Subject:\s(.*)$/, type: "string", defwidth: 20 }, { name: "Newsgroups", displayName: "Newsgroups", target: "mail", re: /^Newsgroups:\s(.*)$/, type: "string", defwidth: 18 }, { name: "Message-ID", displayName: "Message-ID", target: "mail", re: /^Message-ID:\s(.*)$/, type: "string", defwidth: 18 }, { name: "Date", displayName: "Date", target: "mail", re: /^Date:\s(.*)$/, type: "datetime", defwidth: 10 }, { name: "Webpage Address", displayName: "Address", target: "webpage", re: /^Content-Location:\s(.*)$/, type: "string", defwidth: 18 }, { name: "Webpage Domain", displayName: "Domain", target: "webpage", re: /^Content-Location:\s(?:http)s?:\/\/(?:www\.)?(.*?)\/.*$/, type: "string", defwidth: 18 }, { name: "Webpage Source", displayName: "Source", target: "webpage", re: /^From:\s(.*)$/, type: "string", defwidth: 18 }, { name: "Webpage Subject", displayName: "Title", target: "webpage", re: /^Subject:\s(.*)$/, type: "string", defwidth: 20 }, { name: "Webpage Date", displayName: "Visualized On", target: "webpage", re: /^Date:\s(.*)$/, type: "datetime", defwidth: 10 } ] }; // -------------------- Event // Called by Directory Opus to initialize the script. function OnInit(initData) { var uid = ""; var url = ""; initData.url = url; initData.name = "Columns for Electronic Mail Format"; initData.desc = "Columns for displaying e-mail header properties for e-mail and webpage files."; initData.copyright = "Initiated by wowbagger; With contributions from many fellow users; Fork maintened by AndersonNNunes.org"; initData.version = "1.0"; initData.default_enable = true; initData.min_version = "12.0"; // Create a new ScriptCommand object and initialize it to add the command to Opus. var showPreviewCmd = initData.AddCommand(); showPreviewCmd.name = "OpenWebpage"; showPreviewCmd.method = "OnOpenWebpage"; showPreviewCmd.desc = "Open webpage files."; showPreviewCmd.label = "Open Webpage"; showPreviewCmd.template = "MULTI/S,REMOTE/S"; // Helper Function // Easy way to determine settings. // Thanks goes to "tbone". // https://resource.dopus.com/t/helper-confighelper-easier-config-item-handling/19129 function ConfigHelper(data) { var t=this; t.d=data; t.c=data.config; t.cd=DOpus.Create.Map(); t.add=function(name, val, des){ t.l={n:name,ln:name. toLowerCase()}; return t.val(val).des(des);} t.des=function(des){ if (!des) return t; if (t.cd.empty) t.d.config_desc=t.cd; t.cd(t.l.n)=des; return t;} t.val=function(val){ var l=t.l; if (l.v!==l.x&&typeof l.v=="object") l.v.push_back(val);else l.v=t.c[l.n]=val;return t;} t.trn=function(){return t.des(t("script.config."+t.l.ln));} } // Helper object. var cfg = new ConfigHelper(initData); // Configuration. cfg.add("verbose", true, "Enable output of informative log? If set to false, only errors will print messages."); cfg.add("facilitateSubjectGrouping", true, "When enabled, grouping by subject ignores certain prefixes so that all messages from a thread are grouped together."); cfg.add("prefixRegExp", "(RES|ENC|Re|Fwd): ", "RegExp used to identify the prefixes to be ignored if the user enabled the 'facilitateSubjectGrouping' option."); cfg.add("clearOutput", false, "Clear output on run?"); cfg.add("mapDirToBrowser", JSON.stringify(map_dir_to_browser, undefined, 2).replace(/(\n)+/g,"\r\n"), "Specifies which directories have files that should be opened with a given browser. More specific paths should be at the top."); // Temporary variables used to process the script configuration. var labelPrefix; for (i = 0; i < config.columns.length; i++) { // Determine the prefix from the target of the column. if (config.columns[i].target == "mail") { labelPrefix = "(Mail) "; } else if (config.columns[i].target == "webpage") { labelPrefix = "(Webpage) "; } AddNewColumn(initData, config.columns[i].name, config.columns[i].displayName, labelPrefix, config.columns[i].type, config.columns[i].defwidth); } } function OnOpenWebpage(scriptCmdData) { if (Script.config.clearOutput) { DOpus.ClearOutput(); } // Check premisses. if (scriptCmdData.func.sourcetab.selected_files.count == 0) { error("No files are selected."); return; } if (scriptCmdData.func.sourcetab.selected_files.count > 1 && !scriptCmdData.func.args.got_arg.multi) { error("Too many files are selected. Use the MULTI switch if you really want the command to operate on multiple files."); return; } else { var multi = true; } // Adjust command behavior. var cmd = scriptCmdData.func.command; cmd.AddLine("// This line prevents an error when the Run method is executed before the the AddLine method being called at least once."); cmd.deselect = true; cmd.SetQualifiers("none"); cmd.ClearFiles(); if (multi == true) { // Filter selected files to consider only appropriate files. for (var eSel = new Enumerator(scriptCmdData.func.sourcetab.selected_files); !eSel.atEnd(); eSel.moveNext()) { var selectedItem = eSel.item(); for (var i = 0; i < selectedItem.groups.length; i++){ if (selectedItem.groups(i).display_name == "Webpages") { cmd.AddFile(selectedItem); } } } } else { cmd.AddFile(scriptCmdData.func.sourcetab.selected_files(0)); } for (var file_count = cmd.files.count - 1; file_count >= 0; file_count--) { var current_item = cmd.files(file_count); var current_item_path = String(current_item.realpath); if (scriptCmdData.func.args.got_arg.remote) { var item_id = encodeURIComponent("_CEMF_" + current_item_path); if (DOpus.Vars.Exists(item_id)) { var item = JSON.parse(DOpus.Vars.Get(item_id)); var target_uri = item["Webpage Address"]; } else { error("Metadata not cached for \"" + current_item.name + "\"."); return; } } else { var target_uri = current_item_path; } var browser = "default"; map_dir_to_browser = JSON.parse(Script.config.mapDirToBrowser); for (key in map_dir_to_browser) { if (DOpus.FSUtil.ComparePath(current_item_path, key, "cp")) { browser = map_dir_to_browser[key]; break; } } if (browser === "default") { var open_browser_command = quotePath(target_uri); } else { var open_browser_command = quotePath(browser) + " " + quotePath(target_uri); } // Execute command line. var wsh = new ActiveXObject("WScript.Shell"); var run_return_code = wsh.Run(open_browser_command, 1); } } // Helper Function // Add column. function AddNewColumn(initData, name, label, labelPrefix, type, defwidth) { var col; col = initData.AddColumn(); col.name = name; col.label = labelPrefix + label; col.header = label; col.type = type; col.method = "OnValueRequest"; if (name == "Subject" || name == "Webpage Subject") { col.autogroup = false; } else { col.autogroup = true; } col.autorefresh = true; col.justify = "left"; col.multicol = true; col.keyscroll = true; if (defwidth != null && defwidth != 0) { col.defwidth = defwidth; } } // Helper Function // Generate values for columns. function OnValueRequest(scriptColData) { // Check that the target item really exists (sometimes it may be on a collection but may have been deleted already). if (!DOpus.FSUtil.Exists(scriptColData.item) || (!scriptColData.item.is_dir && !fs.FileExists(scriptColData.item.realpath)) || (scriptColData.item.is_dir && !fs.FolderExists(scriptColData.item.realpath))) { // error("Unable to locate \"" + scriptColData.item.realpath + "\"."); return; } if (String(scriptColData.item.realpath).length > 259) { print("Path length is too long for the file \"" + scriptColData.item.realpath + "\". It has been ignored."); return; } if (!inArray(scriptColData.col, config.columns)) return; if (scriptColData.item.is_dir) return; if (isFromGroup(scriptColData.item, "Electronic Mail") || isFromGroup(scriptColData.item, "Webpages")) { // Check the cache first. var item_id = encodeURIComponent("_CEMF_" + scriptColData.item.realpath); if (DOpus.Vars.Exists(item_id)) { var item = JSON.parse(DOpus.Vars.Get(item_id)); if (item["Cache Date"] !== String(scriptColData.item.modify)) { item = null; print("Cached data is stale and will be discarded."); } print("Using 'DOpus.Vars' cache."); } if (!item) { print("Data not found in the cache. Probing..."); var item = ScanFile(scriptColData.item); item["Cache Date"] = String(scriptColData.item.modify); DOpus.Vars.Set(item_id, JSON.stringify(item, undefined, 4).replace(/(\n)+/g,"\r\n")); } if (item) { // Temporary variable that holds a value to be assigned to a column. var iValue; // Iterate over columns and assign values. for (i = 0; i < config.columns.length; i++) { if (!scriptColData.columns.exists(config.columns[i].name)) { continue; } iValue = item[config.columns[i].name]; if (iValue == null) { continue; } // Handle column of type "datetime". if (config.columns[i].type == "datetime") { iValue = new Date(Date.parse(iValue)).getVarDate(); } // Handle other types of column. else { // For the "Subject" column, remove common prefixes of the group value, if the user desires that. if (config.columns[i].name == "Subject" || config.columns[i].name == "Webpage Subject") { if (Script.config.facilitateSubjectGrouping) { scriptColData.columns(config.columns[i].name).group = iValue.replace(new RegExp(Script.config.prefixRegExp, "gi"), "") } } } // Assign computed value. scriptColData.columns(config.columns[i].name).value = iValue; } } } } // Helper Function // Extract values from file. function ScanFile(item, target) { var result = {}; for (i = 0; i < config.columns.length; i++) { // Check premisses; skip column if check fail. if (isFromGroup(item, "Electronic Mail") && config.columns[i].target == "webpage") { continue; } if (isFromGroup(item, "Webpages") && config.columns[i].target == "mail") { continue; } // Open file in read mode. var fn = fs.OpenTextFile(item.realpath, 1); while (!fn.AtEndOfStream) { var textLine = fn.ReadLine(); var match = config.columns[i].re.exec(textLine); if (match != null) { var found_content = match[1]; var subsequentLine = fn.ReadLine(); while (subsequentLine.match(/^(\s|\t).*$/)) { found_content += subsequentLine; subsequentLine = fn.ReadLine(); } result[config.columns[i].name] = decode(found_content); fn.Close(); break; } result[config.columns[i].name] = ""; } fn.Close(); } if (result) return result; else return null; } // Helper Function // Check that a given item is present in an array. function inArray(item, arr) { for (var i = 0; i < arr.length; i++) { if (item == arr[i].name) return true; } } // Helper Function // Decode line of text. function decode(text) { var encoded_multipart_regex_pattern = /\?=\s?\t?(=\?([^?]+)\?([^?]+)\?)/g; text = text.replace(encoded_multipart_regex_pattern, "") var encoded_part_regex_pattern = /(=\?([^?]+)\?([^?]+)\?)([^?]+)\?=/; var match_result = encoded_part_regex_pattern.exec(text); if (match_result != null) { var front = middle = back = ""; var firstIndex = match_result.index; var lastIndex = encoded_part_regex_pattern.lastIndex; encoding_prefix = match_result[1]; if (firstIndex !== 0) { front = text.slice(0, firstIndex); } try { middle = st.Decode(match_result[0].slice(0, -2), "auto"); } catch (err) { if (Script.config.verbose) { return "[Unsupported Encoding]"; } else { return ""; } } if (lastIndex !== text.length - 1) { back = text.slice(lastIndex); } return String(front + middle + back); } return text; } // Helper Function // Print only if requested. function print(text) { if (Script.config.verbose) { DOpus.Output(text); } } // Helper Function // Display error message. function error(text) { DOpus.Output(text, true); } // Helper Function // Return true if 'item' is from file type group 'needle'. function isFromGroup(item, needle) { if (item.groups.length) { for (var i = 0; i < item.groups.length; i++) { if (item.groups(i).display_name === needle) return true; } } return false; } // Helper Function // Return string value path with quotes if all is true or if the path contains a space. // Thanks goes to "spiralx". // https://resource.dopus.com/t/scripts-js-snippet-collection-functions-and-helpers/18387 function quotePath(path, all) { path = String(path); if ((path.indexOf('"') === 0) && (path.lastIndexOf('"') === path.length - 1)) { return path; } else { all = typeof all === "boolean" ? all : false; return all || path.indexOf(' ') !== -1 ? ('"' + path + '"') : path; } }