123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.transformList = exports.parseLine = exports.testLine = void 0;
- const FileInfo_1 = require("./FileInfo");
- const JA_MONTH = "\u6708";
- const JA_DAY = "\u65e5";
- const JA_YEAR = "\u5e74";
- /**
- * This parser is based on the FTP client library source code in Apache Commons Net provided
- * under the Apache 2.0 license. It has been simplified and rewritten to better fit the Javascript language.
- *
- * https://github.com/apache/commons-net/blob/master/src/main/java/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java
- *
- * Below is the regular expression used by this parser.
- *
- * Permissions:
- * r the file is readable
- * w the file is writable
- * x the file is executable
- * - the indicated permission is not granted
- * L mandatory locking occurs during access (the set-group-ID bit is
- * on and the group execution bit is off)
- * s the set-user-ID or set-group-ID bit is on, and the corresponding
- * user or group execution bit is also on
- * S undefined bit-state (the set-user-ID bit is on and the user
- * execution bit is off)
- * t the 1000 (octal) bit, or sticky bit, is on [see chmod(1)], and
- * execution is on
- * T the 1000 bit is turned on, and execution is off (undefined bit-
- * state)
- * e z/OS external link bit
- * Final letter may be appended:
- * + file has extended security attributes (e.g. ACL)
- * Note: local listings on MacOSX also use '@'
- * this is not allowed for here as does not appear to be shown by FTP servers
- * {@code @} file has extended attributes
- */
- const RE_LINE = new RegExp("([bcdelfmpSs-])" // file type
- + "(((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-]?)))\\+?" // permissions
- + "\\s*" // separator TODO why allow it to be omitted??
- + "(\\d+)" // link count
- + "\\s+" // separator
- + "(?:(\\S+(?:\\s\\S+)*?)\\s+)?" // owner name (optional spaces)
- + "(?:(\\S+(?:\\s\\S+)*)\\s+)?" // group name (optional spaces)
- + "(\\d+(?:,\\s*\\d+)?)" // size or n,m
- + "\\s+" // separator
- /**
- * numeric or standard format date:
- * yyyy-mm-dd (expecting hh:mm to follow)
- * MMM [d]d
- * [d]d MMM
- * N.B. use non-space for MMM to allow for languages such as German which use
- * diacritics (e.g. umlaut) in some abbreviations.
- * Japanese uses numeric day and month with suffixes to distinguish them
- * [d]dXX [d]dZZ
- */
- + "(" +
- "(?:\\d+[-/]\\d+[-/]\\d+)" + // yyyy-mm-dd
- "|(?:\\S{3}\\s+\\d{1,2})" + // MMM [d]d
- "|(?:\\d{1,2}\\s+\\S{3})" + // [d]d MMM
- "|(?:\\d{1,2}" + JA_MONTH + "\\s+\\d{1,2}" + JA_DAY + ")" +
- ")"
- + "\\s+" // separator
- /**
- * year (for non-recent standard format) - yyyy
- * or time (for numeric or recent standard format) [h]h:mm
- * or Japanese year - yyyyXX
- */
- + "((?:\\d+(?::\\d+)?)|(?:\\d{4}" + JA_YEAR + "))" // (20)
- + "\\s" // separator
- + "(.*)"); // the rest (21)
- /**
- * Returns true if a given line might be a Unix-style listing.
- *
- * - Example: `-rw-r--r--+ 1 patrick staff 1057 Dec 11 14:35 test.txt`
- */
- function testLine(line) {
- return RE_LINE.test(line);
- }
- exports.testLine = testLine;
- /**
- * Parse a single line of a Unix-style directory listing.
- */
- function parseLine(line) {
- const groups = line.match(RE_LINE);
- if (groups === null) {
- return undefined;
- }
- const name = groups[21];
- if (name === "." || name === "..") { // Ignore parent directory links
- return undefined;
- }
- const file = new FileInfo_1.FileInfo(name);
- file.size = parseInt(groups[18], 10);
- file.user = groups[16];
- file.group = groups[17];
- file.hardLinkCount = parseInt(groups[15], 10);
- file.rawModifiedAt = groups[19] + " " + groups[20];
- file.permissions = {
- user: parseMode(groups[4], groups[5], groups[6]),
- group: parseMode(groups[8], groups[9], groups[10]),
- world: parseMode(groups[12], groups[13], groups[14]),
- };
- // Set file type
- switch (groups[1].charAt(0)) {
- case "d":
- file.type = FileInfo_1.FileType.Directory;
- break;
- case "e": // NET-39 => z/OS external link
- file.type = FileInfo_1.FileType.SymbolicLink;
- break;
- case "l":
- file.type = FileInfo_1.FileType.SymbolicLink;
- break;
- case "b":
- case "c":
- file.type = FileInfo_1.FileType.File; // TODO change this if DEVICE_TYPE implemented
- break;
- case "f":
- case "-":
- file.type = FileInfo_1.FileType.File;
- break;
- default:
- // A 'whiteout' file is an ARTIFICIAL entry in any of several types of
- // 'translucent' filesystems, of which a 'union' filesystem is one.
- file.type = FileInfo_1.FileType.Unknown;
- }
- // Separate out the link name for symbolic links
- if (file.isSymbolicLink) {
- const end = name.indexOf(" -> ");
- if (end !== -1) {
- file.name = name.substring(0, end);
- file.link = name.substring(end + 4);
- }
- }
- return file;
- }
- exports.parseLine = parseLine;
- function transformList(files) {
- return files;
- }
- exports.transformList = transformList;
- function parseMode(r, w, x) {
- let value = 0;
- if (r !== "-") {
- value += FileInfo_1.FileInfo.UnixPermission.Read;
- }
- if (w !== "-") {
- value += FileInfo_1.FileInfo.UnixPermission.Write;
- }
- const execToken = x.charAt(0);
- if (execToken !== "-" && execToken.toUpperCase() !== execToken) {
- value += FileInfo_1.FileInfo.UnixPermission.Execute;
- }
- return value;
- }
|