/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.sshd.common.subsystem.sftp;

import java.io.EOFException;
import java.io.FileNotFoundException;
import java.nio.channels.OverlappingFileLockException;
import java.nio.charset.StandardCharsets;
import java.nio.file.AccessDeniedException;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.InvalidPathException;
import java.nio.file.NoSuchFileException;
import java.nio.file.NotDirectoryException;
import java.nio.file.attribute.AclEntry;
import java.nio.file.attribute.AclEntryFlag;
import java.nio.file.attribute.AclEntryPermission;
import java.nio.file.attribute.AclEntryType;
import java.nio.file.attribute.FileTime;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.nio.file.attribute.UserPrincipal;
import java.nio.file.attribute.UserPrincipalNotFoundException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;

import org.apache.sshd.common.PropertyResolver;
import org.apache.sshd.common.PropertyResolverUtils;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.OsUtils;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.buffer.Buffer;
import org.apache.sshd.common.util.buffer.BufferUtils;
import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
import org.apache.sshd.server.subsystem.sftp.DefaultGroupPrincipal;
import org.apache.sshd.server.subsystem.sftp.InvalidHandleException;
import org.apache.sshd.server.subsystem.sftp.UnixDateFormat;

/**
 * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
 */
public final class SftpHelper {
    /**
     * Used to control whether to append the end-of-list indicator for
     * SSH_FXP_NAME responses via {@link #indicateEndOfNamesList(Buffer, int, PropertyResolver, Boolean)}
     * call, as indicated by <A HREF="https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.4">SFTP v6 - section 9.4</A>
     */
    public static final String APPEND_END_OF_LIST_INDICATOR = "sftp-append-eol-indicator";

    /**
     * Default value for {@link #APPEND_END_OF_LIST_INDICATOR} if none configured
     */
    public static final boolean DEFAULT_APPEND_END_OF_LIST_INDICATOR = true;

    private SftpHelper() {
        throw new UnsupportedOperationException("No instance allowed");
    }

    /**
     * Retrieves the end-of-file indicator for {@code SSH_FXP_DATA} responses, provided
     * the version is at least 6, and the buffer has enough available data
     *
     * @param buffer  The {@link Buffer} to retrieve the data from
     * @param version The SFTP version being used
     * @return The indicator value - {@code null} if none retrieved
     * @see <A HREF="https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.3">SFTP v6 - section 9.3</A>
     */
    public static Boolean getEndOfFileIndicatorValue(Buffer buffer, int version) {
        return (version <  SftpConstants.SFTP_V6) || (buffer.available() < 1) ? null : Boolean.valueOf(buffer.getBoolean());
    }

    /**
     * Retrieves the end-of-list indicator for {@code SSH_FXP_NAME} responses, provided
     * the version is at least 6, and the buffer has enough available data
     *
     * @param buffer  The {@link Buffer} to retrieve the data from
     * @param version The SFTP version being used
     * @return The indicator value - {@code null} if none retrieved
     * @see <A HREF="https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.4">SFTP v6 - section 9.4</A>
     * @see #indicateEndOfNamesList(Buffer, int, PropertyResolver, Boolean)
     */
    public static Boolean getEndOfListIndicatorValue(Buffer buffer, int version) {
        return (version <  SftpConstants.SFTP_V6) || (buffer.available() < 1) ? null : Boolean.valueOf(buffer.getBoolean());
    }

    /**
     * Appends the end-of-list={@code TRUE} indicator for {@code SSH_FXP_NAME} responses, provided
     * the version is at least 6 and the feature is enabled
     *
     * @param buffer   The {@link Buffer} to append the indicator
     * @param version  The SFTP version being used
     * @param resolver The {@link PropertyResolver} to query whether to enable the feature
     * @return The actual indicator value used - {@code null} if none appended
     * @see #indicateEndOfNamesList(Buffer, int, PropertyResolver, Boolean)
     */
    public static Boolean indicateEndOfNamesList(Buffer buffer, int version, PropertyResolver resolver) {
        return indicateEndOfNamesList(buffer, version, resolver, Boolean.TRUE);
    }

    /**
     * Appends the end-of-list indicator for {@code SSH_FXP_NAME} responses, provided the version
     * is at least 6, the feature is enabled and the indicator value is not {@code null}
     *
     * @param buffer         The {@link Buffer} to append the indicator
     * @param version        The SFTP version being used
     * @param resolver       The {@link PropertyResolver} to query whether to enable the feature
     * @param indicatorValue The indicator value - {@code null} means don't append the indicator
     * @return The actual indicator value used - {@code null} if none appended
     * @see <A HREF="https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.4">SFTP v6 - section 9.4</A>
     * @see #APPEND_END_OF_LIST_INDICATOR
     * @see #DEFAULT_APPEND_END_OF_LIST_INDICATOR
     */
    public static Boolean indicateEndOfNamesList(Buffer buffer, int version, PropertyResolver resolver, Boolean indicatorValue) {
        if ((version < SftpConstants.SFTP_V6) || (indicatorValue == null)) {
            return null;
        }

        if (!PropertyResolverUtils.getBooleanProperty(resolver, APPEND_END_OF_LIST_INDICATOR, DEFAULT_APPEND_END_OF_LIST_INDICATOR)) {
            return null;
        }

        buffer.putBoolean(indicatorValue.booleanValue());
        return indicatorValue;
    }

    /**
     * Writes a file / folder's attributes to a buffer
     *
     * @param buffer The target {@link Buffer}
     * @param version The output encoding version
     * @param attributes The {@link Map} of attributes
     * @see #writeAttrsV3(Buffer, int, Map)
     * @see #writeAttrsV4(Buffer, int, Map)
     */
    public static void writeAttrs(Buffer buffer, int version, Map<String, ?> attributes) {
        if (version == SftpConstants.SFTP_V3) {
            writeAttrsV3(buffer, version, attributes);
        } else if (version >= SftpConstants.SFTP_V4) {
            writeAttrsV4(buffer, version, attributes);
        } else {
            throw new IllegalStateException("Unsupported SFTP version: " + version);
        }
    }

    /**
     * Writes the retrieved file / directory attributes in V3 format
     *
     * @param buffer The target {@link Buffer}
     * @param version The actual version - must be {@link SftpConstants#SFTP_V3}
     * @param attributes The {@link Map} of attributes
     */
    public static void writeAttrsV3(Buffer buffer, int version, Map<String, ?> attributes) {
        ValidateUtils.checkTrue(version == SftpConstants.SFTP_V3, "Illegal version: %d", version);

        boolean isReg = getBool((Boolean) attributes.get("isRegularFile"));
        boolean isDir = getBool((Boolean) attributes.get("isDirectory"));
        boolean isLnk = getBool((Boolean) attributes.get("isSymbolicLink"));
        @SuppressWarnings("unchecked")
        Collection<PosixFilePermission> perms = (Collection<PosixFilePermission>) attributes.get("permissions");
        Number size = (Number) attributes.get("size");
        FileTime lastModifiedTime = (FileTime) attributes.get("lastModifiedTime");
        FileTime lastAccessTime = (FileTime) attributes.get("lastAccessTime");
        Map<?, ?> extensions = (Map<?, ?>) attributes.get("extended");
        int flags = ((isReg || isLnk) && (size != null) ? SftpConstants.SSH_FILEXFER_ATTR_SIZE : 0)
                  | (attributes.containsKey("uid") && attributes.containsKey("gid") ? SftpConstants.SSH_FILEXFER_ATTR_UIDGID : 0)
                  | ((perms != null) ? SftpConstants.SSH_FILEXFER_ATTR_PERMISSIONS : 0)
                  | (((lastModifiedTime != null) && (lastAccessTime != null)) ? SftpConstants.SSH_FILEXFER_ATTR_ACMODTIME : 0)
                  | ((extensions != null) ? SftpConstants.SSH_FILEXFER_ATTR_EXTENDED : 0);
        buffer.putInt(flags);
        if ((flags & SftpConstants.SSH_FILEXFER_ATTR_SIZE) != 0) {
            buffer.putLong(size.longValue());
        }
        if ((flags & SftpConstants.SSH_FILEXFER_ATTR_UIDGID) != 0) {
            buffer.putInt(((Number) attributes.get("uid")).intValue());
            buffer.putInt(((Number) attributes.get("gid")).intValue());
        }
        if ((flags & SftpConstants.SSH_FILEXFER_ATTR_PERMISSIONS) != 0) {
            buffer.putInt(attributesToPermissions(isReg, isDir, isLnk, perms));
        }
        if ((flags & SftpConstants.SSH_FILEXFER_ATTR_ACMODTIME) != 0) {
            writeTime(buffer, version, flags, lastAccessTime);
            writeTime(buffer, version, flags, lastModifiedTime);
        }
        if ((flags & SftpConstants.SSH_FILEXFER_ATTR_EXTENDED) != 0) {
            writeExtensions(buffer, extensions);
        }
    }

    /**
     * Writes the retrieved file / directory attributes in V4+ format
     *
     * @param buffer The target {@link Buffer}
     * @param version The actual version - must be at least {@link SftpConstants#SFTP_V4}
     * @param attributes The {@link Map} of attributes
     */
    public static void writeAttrsV4(Buffer buffer, int version, Map<String, ?> attributes) {
        ValidateUtils.checkTrue(version >= SftpConstants.SFTP_V4, "Illegal version: %d", version);

        boolean isReg = getBool((Boolean) attributes.get("isRegularFile"));
        boolean isDir = getBool((Boolean) attributes.get("isDirectory"));
        boolean isLnk = getBool((Boolean) attributes.get("isSymbolicLink"));
        @SuppressWarnings("unchecked")
        Collection<PosixFilePermission> perms = (Collection<PosixFilePermission>) attributes.get("permissions");
        Number size = (Number) attributes.get("size");
        FileTime lastModifiedTime = (FileTime) attributes.get("lastModifiedTime");
        FileTime lastAccessTime = (FileTime) attributes.get("lastAccessTime");
        FileTime creationTime = (FileTime) attributes.get("creationTime");
        @SuppressWarnings("unchecked")
        Collection<AclEntry> acl = (Collection<AclEntry>) attributes.get("acl");
        Map<?, ?> extensions = (Map<?, ?>) attributes.get("extended");
        int flags = (((isReg || isLnk) && (size != null)) ? SftpConstants.SSH_FILEXFER_ATTR_SIZE : 0)
                  | ((attributes.containsKey("owner") && attributes.containsKey("group")) ? SftpConstants.SSH_FILEXFER_ATTR_OWNERGROUP : 0)
                  | ((perms != null) ? SftpConstants.SSH_FILEXFER_ATTR_PERMISSIONS : 0)
                  | ((lastModifiedTime != null) ? SftpConstants.SSH_FILEXFER_ATTR_MODIFYTIME : 0)
                  | ((creationTime != null) ? SftpConstants.SSH_FILEXFER_ATTR_CREATETIME : 0)
                  | ((lastAccessTime != null) ? SftpConstants.SSH_FILEXFER_ATTR_ACCESSTIME : 0)
                  | ((acl != null) ? SftpConstants.SSH_FILEXFER_ATTR_ACL : 0)
                  | ((extensions != null) ? SftpConstants.SSH_FILEXFER_ATTR_EXTENDED : 0);
        buffer.putInt(flags);
        buffer.putByte((byte) (isReg ? SftpConstants.SSH_FILEXFER_TYPE_REGULAR
                : isDir ? SftpConstants.SSH_FILEXFER_TYPE_DIRECTORY
                : isLnk ? SftpConstants.SSH_FILEXFER_TYPE_SYMLINK
                : SftpConstants.SSH_FILEXFER_TYPE_UNKNOWN));
        if ((flags & SftpConstants.SSH_FILEXFER_ATTR_SIZE) != 0) {
            buffer.putLong(size.longValue());
        }
        if ((flags & SftpConstants.SSH_FILEXFER_ATTR_OWNERGROUP) != 0) {
            buffer.putString(Objects.toString(attributes.get("owner"), SftpUniversalOwnerAndGroup.Owner.getName()));
            buffer.putString(Objects.toString(attributes.get("group"), SftpUniversalOwnerAndGroup.Group.getName()));
        }
        if ((flags & SftpConstants.SSH_FILEXFER_ATTR_PERMISSIONS) != 0) {
            buffer.putInt(attributesToPermissions(isReg, isDir, isLnk, perms));
        }

        if ((flags & SftpConstants.SSH_FILEXFER_ATTR_ACCESSTIME) != 0) {
            writeTime(buffer, version, flags, lastAccessTime);
        }

        if ((flags & SftpConstants.SSH_FILEXFER_ATTR_CREATETIME) != 0) {
            writeTime(buffer, version, flags, lastAccessTime);
        }
        if ((flags & SftpConstants.SSH_FILEXFER_ATTR_MODIFYTIME) != 0) {
            writeTime(buffer, version, flags, lastModifiedTime);
        }
        if ((flags & SftpConstants.SSH_FILEXFER_ATTR_ACL) != 0) {
            writeACLs(buffer, version, acl);
        }
        // TODO: ctime
        // TODO: bits
        if ((flags & SftpConstants.SSH_FILEXFER_ATTR_EXTENDED) != 0) {
            writeExtensions(buffer, extensions);
        }
    }

    /**
     * @param bool The {@link Boolean} value
     * @return {@code true} it the argument is non-{@code null} and
     * its {@link Boolean#booleanValue()} is {@code true}
     */
    public static boolean getBool(Boolean bool) {
        return bool != null && bool;
    }

    /**
     * Converts a file / folder's attributes into a mask
     *
     * @param isReg {@code true} if this is a normal file
     * @param isDir {@code true} if this is a directory
     * @param isLnk {@code true} if this is a symbolic link
     * @param perms The file / folder's access {@link PosixFilePermission}s
     * @return A mask encoding the file / folder's attributes
     */
    public static int attributesToPermissions(boolean isReg, boolean isDir, boolean isLnk, Collection<PosixFilePermission> perms) {
        int pf = 0;
        if (perms != null) {
            for (PosixFilePermission p : perms) {
                switch (p) {
                    case OWNER_READ:
                        pf |= SftpConstants.S_IRUSR;
                        break;
                    case OWNER_WRITE:
                        pf |= SftpConstants.S_IWUSR;
                        break;
                    case OWNER_EXECUTE:
                        pf |= SftpConstants.S_IXUSR;
                        break;
                    case GROUP_READ:
                        pf |= SftpConstants.S_IRGRP;
                        break;
                    case GROUP_WRITE:
                        pf |= SftpConstants.S_IWGRP;
                        break;
                    case GROUP_EXECUTE:
                        pf |= SftpConstants.S_IXGRP;
                        break;
                    case OTHERS_READ:
                        pf |= SftpConstants.S_IROTH;
                        break;
                    case OTHERS_WRITE:
                        pf |= SftpConstants.S_IWOTH;
                        break;
                    case OTHERS_EXECUTE:
                        pf |= SftpConstants.S_IXOTH;
                        break;
                    default: // ignored
                }
            }
        }
        pf |= isReg ? SftpConstants.S_IFREG : 0;
        pf |= isDir ? SftpConstants.S_IFDIR : 0;
        pf |= isLnk ? SftpConstants.S_IFLNK : 0;
        return pf;
    }

    /**
     * Converts a POSIX permissions mask to a file type value
     *
     * @param perms The POSIX permissions mask
     * @return The file type - see {@code SSH_FILEXFER_TYPE_xxx} values
     */
    public static int permissionsToFileType(int perms) {
        if ((SftpConstants.S_IFLNK & perms) == SftpConstants.S_IFLNK) {
            return SftpConstants.SSH_FILEXFER_TYPE_SYMLINK;
        } else if ((SftpConstants.S_IFREG & perms) == SftpConstants.S_IFREG) {
            return SftpConstants.SSH_FILEXFER_TYPE_REGULAR;
        } else if ((SftpConstants.S_IFDIR & perms) == SftpConstants.S_IFDIR) {
            return SftpConstants.SSH_FILEXFER_TYPE_DIRECTORY;
        } else if ((SftpConstants.S_IFSOCK & perms) == SftpConstants.S_IFSOCK) {
            return SftpConstants.SSH_FILEXFER_TYPE_SOCKET;
        } else if ((SftpConstants.S_IFBLK & perms) == SftpConstants.S_IFBLK) {
            return SftpConstants.SSH_FILEXFER_TYPE_BLOCK_DEVICE;
        } else if ((SftpConstants.S_IFCHR & perms) == SftpConstants.S_IFCHR) {
            return SftpConstants.SSH_FILEXFER_TYPE_CHAR_DEVICE;
        } else if ((SftpConstants.S_IFIFO & perms) == SftpConstants.S_IFIFO) {
            return SftpConstants.SSH_FILEXFER_TYPE_FIFO;
        } else {
            return SftpConstants.SSH_FILEXFER_TYPE_UNKNOWN;
        }
    }

    /**
     * Converts a file type into a POSIX permission mask value

     * @param type File type - see {@code SSH_FILEXFER_TYPE_xxx} values
     * @return The matching POSIX permission mask value
     */
    public static int fileTypeToPermission(int type) {
        switch (type) {
            case SftpConstants.SSH_FILEXFER_TYPE_REGULAR:
                return SftpConstants.S_IFREG;
            case SftpConstants.SSH_FILEXFER_TYPE_DIRECTORY:
                return SftpConstants.S_IFDIR;
            case SftpConstants.SSH_FILEXFER_TYPE_SYMLINK:
                return SftpConstants.S_IFLNK;
            case SftpConstants.SSH_FILEXFER_TYPE_SOCKET:
                return SftpConstants.S_IFSOCK;
            case SftpConstants.SSH_FILEXFER_TYPE_BLOCK_DEVICE:
                return SftpConstants.S_IFBLK;
            case SftpConstants.SSH_FILEXFER_TYPE_CHAR_DEVICE:
                return SftpConstants.S_IFCHR;
            case SftpConstants.SSH_FILEXFER_TYPE_FIFO:
                return SftpConstants.S_IFIFO;
            default:
                return 0;
        }
    }

    /**
     * Translates a mask of permissions into its enumeration values equivalents
     *
     * @param perms The permissions mask
     * @return A {@link Set} of the equivalent {@link PosixFilePermission}s
     */
    public static Set<PosixFilePermission> permissionsToAttributes(int perms) {
        Set<PosixFilePermission> p = EnumSet.noneOf(PosixFilePermission.class);
        if ((perms & SftpConstants.S_IRUSR) != 0) {
            p.add(PosixFilePermission.OWNER_READ);
        }
        if ((perms & SftpConstants.S_IWUSR) != 0) {
            p.add(PosixFilePermission.OWNER_WRITE);
        }
        if ((perms & SftpConstants.S_IXUSR) != 0) {
            p.add(PosixFilePermission.OWNER_EXECUTE);
        }
        if ((perms & SftpConstants.S_IRGRP) != 0) {
            p.add(PosixFilePermission.GROUP_READ);
        }
        if ((perms & SftpConstants.S_IWGRP) != 0) {
            p.add(PosixFilePermission.GROUP_WRITE);
        }
        if ((perms & SftpConstants.S_IXGRP) != 0) {
            p.add(PosixFilePermission.GROUP_EXECUTE);
        }
        if ((perms & SftpConstants.S_IROTH) != 0) {
            p.add(PosixFilePermission.OTHERS_READ);
        }
        if ((perms & SftpConstants.S_IWOTH) != 0) {
            p.add(PosixFilePermission.OTHERS_WRITE);
        }
        if ((perms & SftpConstants.S_IXOTH) != 0) {
            p.add(PosixFilePermission.OTHERS_EXECUTE);
        }
        return p;
    }

    /**
     * Returns the most adequate sub-status for the provided exception
     *
     * @param t The thrown {@link Throwable}
     * @return The matching sub-status
     */
    public static int resolveSubstatus(Throwable t) {
        if ((t instanceof NoSuchFileException) || (t instanceof FileNotFoundException)) {
            return SftpConstants.SSH_FX_NO_SUCH_FILE;
        } else if (t instanceof InvalidHandleException) {
            return SftpConstants.SSH_FX_INVALID_HANDLE;
        } else if (t instanceof FileAlreadyExistsException) {
            return SftpConstants.SSH_FX_FILE_ALREADY_EXISTS;
        } else if (t instanceof DirectoryNotEmptyException) {
            return SftpConstants.SSH_FX_DIR_NOT_EMPTY;
        } else if (t instanceof NotDirectoryException) {
            return SftpConstants.SSH_FX_NOT_A_DIRECTORY;
        } else if (t instanceof AccessDeniedException) {
            return SftpConstants.SSH_FX_PERMISSION_DENIED;
        } else if (t instanceof EOFException) {
            return SftpConstants.SSH_FX_EOF;
        } else if (t instanceof OverlappingFileLockException) {
            return SftpConstants.SSH_FX_LOCK_CONFLICT;
        } else if (t instanceof UnsupportedOperationException) {
            return SftpConstants.SSH_FX_OP_UNSUPPORTED;
        } else if (t instanceof InvalidPathException) {
            return SftpConstants.SSH_FX_INVALID_FILENAME;
        } else if (t instanceof IllegalArgumentException) {
            return SftpConstants.SSH_FX_INVALID_PARAMETER;
        } else if (t instanceof UnsupportedOperationException) {
            return SftpConstants.SSH_FX_OP_UNSUPPORTED;
        } else if (t instanceof UserPrincipalNotFoundException) {
            return SftpConstants.SSH_FX_UNKNOWN_PRINCIPAL;
        } else if (t instanceof SftpException) {
            return ((SftpException) t).getStatus();
        } else {
            return SftpConstants.SSH_FX_FAILURE;
        }
    }

    public static String resolveStatusMessage(Throwable t) {
        if (t == null) {
            return "";
        } else if (t instanceof SftpException) {
            return t.toString();
        } else {
            return "Internal " + t.getClass().getSimpleName() + ": " + t.getMessage();
        }
    }

    public static Map<String, Object> readAttrs(Buffer buffer, int version) {
        Map<String, Object> attrs = new TreeMap<String, Object>(String.CASE_INSENSITIVE_ORDER);
        int flags = buffer.getInt();
        if (version >= SftpConstants.SFTP_V4) {
            int type = buffer.getUByte();
            switch (type) {
                case SftpConstants.SSH_FILEXFER_TYPE_REGULAR:
                    attrs.put("isRegular", Boolean.TRUE);
                    break;
                case SftpConstants.SSH_FILEXFER_TYPE_DIRECTORY:
                    attrs.put("isDirectory", Boolean.TRUE);
                    break;
                case SftpConstants.SSH_FILEXFER_TYPE_SYMLINK:
                    attrs.put("isSymbolicLink", Boolean.TRUE);
                    break;
                case SftpConstants.SSH_FILEXFER_TYPE_SOCKET:
                case SftpConstants.SSH_FILEXFER_TYPE_CHAR_DEVICE:
                case SftpConstants.SSH_FILEXFER_TYPE_BLOCK_DEVICE:
                case SftpConstants.SSH_FILEXFER_TYPE_FIFO:
                    attrs.put("isOther", Boolean.TRUE);
                    break;
                default:    // ignored
            }
        }

        if ((flags & SftpConstants.SSH_FILEXFER_ATTR_SIZE) != 0) {
            attrs.put("size", buffer.getLong());
        }

        if (version == SftpConstants.SFTP_V3) {
            if ((flags & SftpConstants.SSH_FILEXFER_ATTR_UIDGID) != 0) {
                attrs.put("uid", buffer.getInt());
                attrs.put("gid", buffer.getInt());
            }
        } else {
            if ((version >= SftpConstants.SFTP_V6) && ((flags & SftpConstants.SSH_FILEXFER_ATTR_ALLOCATION_SIZE) != 0)) {
                @SuppressWarnings("unused")
                long allocSize = buffer.getLong();    // TODO handle allocation size
            }

            if ((flags & SftpConstants.SSH_FILEXFER_ATTR_OWNERGROUP) != 0) {
                attrs.put("owner", new DefaultGroupPrincipal(buffer.getString()));
                attrs.put("group", new DefaultGroupPrincipal(buffer.getString()));
            }
        }

        if ((flags & SftpConstants.SSH_FILEXFER_ATTR_PERMISSIONS) != 0) {
            attrs.put("permissions", permissionsToAttributes(buffer.getInt()));
        }

        if (version == SftpConstants.SFTP_V3) {
            if ((flags & SftpConstants.SSH_FILEXFER_ATTR_ACMODTIME) != 0) {
                attrs.put("lastAccessTime", readTime(buffer, version, flags));
                attrs.put("lastModifiedTime", readTime(buffer, version, flags));
            }
        } else if (version >= SftpConstants.SFTP_V4) {
            if ((flags & SftpConstants.SSH_FILEXFER_ATTR_ACCESSTIME) != 0) {
                attrs.put("lastAccessTime", readTime(buffer, version, flags));
            }
            if ((flags & SftpConstants.SSH_FILEXFER_ATTR_CREATETIME) != 0) {
                attrs.put("creationTime", readTime(buffer, version, flags));
            }
            if ((flags & SftpConstants.SSH_FILEXFER_ATTR_MODIFYTIME) != 0) {
                attrs.put("lastModifiedTime", readTime(buffer, version, flags));
            }
            if ((version >= SftpConstants.SFTP_V6) && (flags & SftpConstants.SSH_FILEXFER_ATTR_CTIME) != 0) {
                attrs.put("ctime", readTime(buffer, version, flags));
            }

            if ((flags & SftpConstants.SSH_FILEXFER_ATTR_ACL) != 0) {
                attrs.put("acl", readACLs(buffer, version));
            }

            if ((flags & SftpConstants.SSH_FILEXFER_ATTR_BITS) != 0) {
                @SuppressWarnings("unused")
                int bits = buffer.getInt();
                @SuppressWarnings("unused")
                int valid = 0xffffffff;
                if (version >= SftpConstants.SFTP_V6) {
                    valid = buffer.getInt();
                }
                // TODO: handle attrib bits
            }

            if (version >= SftpConstants.SFTP_V6) {
                if ((flags & SftpConstants.SSH_FILEXFER_ATTR_TEXT_HINT) != 0) {
                    @SuppressWarnings("unused")
                    boolean text = buffer.getBoolean(); // TODO: handle text
                }
                if ((flags & SftpConstants.SSH_FILEXFER_ATTR_MIME_TYPE) != 0) {
                    @SuppressWarnings("unused")
                    String mimeType = buffer.getString(); // TODO: handle mime-type
                }
                if ((flags & SftpConstants.SSH_FILEXFER_ATTR_LINK_COUNT) != 0) {
                    @SuppressWarnings("unused")
                    int nlink = buffer.getInt(); // TODO: handle link-count
                }
                if ((flags & SftpConstants.SSH_FILEXFER_ATTR_UNTRANSLATED_NAME) != 0) {
                    @SuppressWarnings("unused")
                    String untranslated = buffer.getString(); // TODO: handle untranslated-name
                }
            }
        }

        if ((flags & SftpConstants.SSH_FILEXFER_ATTR_EXTENDED) != 0) {
            attrs.put("extended", readExtensions(buffer));
        }

        return attrs;
    }

    public static Map<String, byte[]> readExtensions(Buffer buffer) {
        int count = buffer.getInt();
        // NOTE
        Map<String, byte[]> extended = new TreeMap<String, byte[]>(String.CASE_INSENSITIVE_ORDER);
        for (int i = 0; i < count; i++) {
            String key = buffer.getString();
            byte[] val = buffer.getBytes();
            byte[] prev = extended.put(key, val);
            ValidateUtils.checkTrue(prev == null, "Duplicate values for extended key=%s", key);
        }

        return extended;
    }

    public static void writeExtensions(Buffer buffer, Map<?, ?> extensions) {
        int numExtensions = GenericUtils.size(extensions);
        buffer.putInt(numExtensions);
        if (numExtensions > 0) {
            for (Map.Entry<?, ?> ee : extensions.entrySet()) {
                Object key = ValidateUtils.checkNotNull(ee.getKey(), "No extension type");
                Object value = ValidateUtils.checkNotNull(ee.getValue(), "No extension value");
                buffer.putString(key.toString());
                if (value instanceof byte[]) {
                    buffer.putBytes((byte[]) value);
                } else {
                    buffer.putString(value.toString());
                }
            }
        }
    }

    public static Map<String, String> toStringExtensions(Map<String, ?> extensions) {
        if (GenericUtils.isEmpty(extensions)) {
            return Collections.emptyMap();
        }

        // NOTE: even though extensions are probably case sensitive we do not allow duplicate name that differs only in case
        Map<String, String> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
        for (Map.Entry<String, ?> ee : extensions.entrySet()) {
            String key = ee.getKey();
            Object value = ValidateUtils.checkNotNull(ee.getValue(), "No value for extension=%s", key);
            String prev = map.put(key, (value instanceof byte[]) ? new String((byte[]) value, StandardCharsets.UTF_8) : value.toString());
            ValidateUtils.checkTrue(prev == null, "Multiple values for extension=%s", key);
        }

        return map;
    }

    public static Map<String, byte[]> toBinaryExtensions(Map<String, String> extensions) {
        if (GenericUtils.isEmpty(extensions)) {
            return Collections.emptyMap();
        }

        // NOTE: even though extensions are probably case sensitive we do not allow duplicate name that differs only in case
        Map<String, byte[]> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
        for (Map.Entry<String, String> ee : extensions.entrySet()) {
            String key = ee.getKey();
            String value = ValidateUtils.checkNotNull(ee.getValue(), "No value for extension=%s", key);
            byte[] prev = map.put(key, value.getBytes(StandardCharsets.UTF_8));
            ValidateUtils.checkTrue(prev == null, "Multiple values for extension=%s", key);
        }

        return map;
    }

    // for v4,5 see https://tools.ietf.org/html/draft-ietf-secsh-filexfer-05#page-15
    // for v6 see https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#page-21
    public static List<AclEntry> readACLs(Buffer buffer, int version) {
        int aclSize = buffer.getInt();
        int startPos = buffer.rpos();
        Buffer aclBuffer = new ByteArrayBuffer(buffer.array(), startPos, aclSize, true);
        List<AclEntry> acl = decodeACLs(aclBuffer, version);
        buffer.rpos(startPos + aclSize);
        return acl;
    }

    public static List<AclEntry> decodeACLs(Buffer buffer, int version) {
        @SuppressWarnings("unused")
        int aclFlags = 0;   // TODO handle ACL flags
        if (version >= SftpConstants.SFTP_V6) {
            aclFlags = buffer.getInt();
        }

        int count = buffer.getInt();
        // NOTE: although the value is defined as UINT32 we do not expected a count greater than Integer.MAX_VALUE
        ValidateUtils.checkTrue(count >= 0, "Invalid ACL entries count: %d", count);
        if (count == 0) {
            return Collections.emptyList();
        }

        List<AclEntry> acls = new ArrayList<>(count);
        for (int i = 0; i < count; i++) {
            int aclType = buffer.getInt();
            int aclFlag = buffer.getInt();
            int aclMask = buffer.getInt();
            String aclWho = buffer.getString();
            acls.add(buildAclEntry(aclType, aclFlag, aclMask, aclWho));
        }

        return acls;
    }

    public static AclEntry buildAclEntry(int aclType, int aclFlag, int aclMask, String aclWho) {
        UserPrincipal who = new DefaultGroupPrincipal(aclWho);
        return AclEntry.newBuilder()
                .setType(ValidateUtils.checkNotNull(decodeAclEntryType(aclType), "Unknown ACL type: %d", aclType))
                .setFlags(decodeAclFlags(aclFlag))
                .setPermissions(decodeAclMask(aclMask))
                .setPrincipal(who)
                .build();
    }

    /**
     * @param aclType The {@code ACE4_ACCESS_xxx_ACE_TYPE} value
     * @return The matching {@link AclEntryType} or {@code null} if unknown value
     */
    public static AclEntryType decodeAclEntryType(int aclType) {
        switch (aclType) {
            case SftpConstants.ACE4_ACCESS_ALLOWED_ACE_TYPE:
                return AclEntryType.ALLOW;
            case SftpConstants.ACE4_ACCESS_DENIED_ACE_TYPE:
                return AclEntryType.DENY;
            case SftpConstants.ACE4_SYSTEM_AUDIT_ACE_TYPE:
                return AclEntryType.AUDIT;
            case SftpConstants.ACE4_SYSTEM_ALARM_ACE_TYPE:
                return AclEntryType.ALARM;
            default:
                return null;
        }
    }

    public static Set<AclEntryFlag> decodeAclFlags(int aclFlag) {
        Set<AclEntryFlag> flags = EnumSet.noneOf(AclEntryFlag.class);
        if ((aclFlag & SftpConstants.ACE4_FILE_INHERIT_ACE) != 0) {
            flags.add(AclEntryFlag.FILE_INHERIT);
        }
        if ((aclFlag & SftpConstants.ACE4_DIRECTORY_INHERIT_ACE) != 0) {
            flags.add(AclEntryFlag.DIRECTORY_INHERIT);
        }
        if ((aclFlag & SftpConstants.ACE4_NO_PROPAGATE_INHERIT_ACE) != 0) {
            flags.add(AclEntryFlag.NO_PROPAGATE_INHERIT);
        }
        if ((aclFlag & SftpConstants.ACE4_INHERIT_ONLY_ACE) != 0) {
            flags.add(AclEntryFlag.INHERIT_ONLY);
        }

        return flags;
    }

    public static Set<AclEntryPermission> decodeAclMask(int aclMask) {
        Set<AclEntryPermission> mask = EnumSet.noneOf(AclEntryPermission.class);
        if ((aclMask & SftpConstants.ACE4_READ_DATA) != 0) {
            mask.add(AclEntryPermission.READ_DATA);
        }
        if ((aclMask & SftpConstants.ACE4_LIST_DIRECTORY) != 0) {
            mask.add(AclEntryPermission.LIST_DIRECTORY);
        }
        if ((aclMask & SftpConstants.ACE4_WRITE_DATA) != 0) {
            mask.add(AclEntryPermission.WRITE_DATA);
        }
        if ((aclMask & SftpConstants.ACE4_ADD_FILE) != 0) {
            mask.add(AclEntryPermission.ADD_FILE);
        }
        if ((aclMask & SftpConstants.ACE4_APPEND_DATA) != 0) {
            mask.add(AclEntryPermission.APPEND_DATA);
        }
        if ((aclMask & SftpConstants.ACE4_ADD_SUBDIRECTORY) != 0) {
            mask.add(AclEntryPermission.ADD_SUBDIRECTORY);
        }
        if ((aclMask & SftpConstants.ACE4_READ_NAMED_ATTRS) != 0) {
            mask.add(AclEntryPermission.READ_NAMED_ATTRS);
        }
        if ((aclMask & SftpConstants.ACE4_WRITE_NAMED_ATTRS) != 0) {
            mask.add(AclEntryPermission.WRITE_NAMED_ATTRS);
        }
        if ((aclMask & SftpConstants.ACE4_EXECUTE) != 0) {
            mask.add(AclEntryPermission.EXECUTE);
        }
        if ((aclMask & SftpConstants.ACE4_DELETE_CHILD) != 0) {
            mask.add(AclEntryPermission.DELETE_CHILD);
        }
        if ((aclMask & SftpConstants.ACE4_READ_ATTRIBUTES) != 0) {
            mask.add(AclEntryPermission.READ_ATTRIBUTES);
        }
        if ((aclMask & SftpConstants.ACE4_WRITE_ATTRIBUTES) != 0) {
            mask.add(AclEntryPermission.WRITE_ATTRIBUTES);
        }
        if ((aclMask & SftpConstants.ACE4_DELETE) != 0) {
            mask.add(AclEntryPermission.DELETE);
        }
        if ((aclMask & SftpConstants.ACE4_READ_ACL) != 0) {
            mask.add(AclEntryPermission.READ_ACL);
        }
        if ((aclMask & SftpConstants.ACE4_WRITE_ACL) != 0) {
            mask.add(AclEntryPermission.WRITE_ACL);
        }
        if ((aclMask & SftpConstants.ACE4_WRITE_OWNER) != 0) {
            mask.add(AclEntryPermission.WRITE_OWNER);
        }
        if ((aclMask & SftpConstants.ACE4_SYNCHRONIZE) != 0) {
            mask.add(AclEntryPermission.SYNCHRONIZE);
        }

        return mask;
    }

    public static void writeACLs(Buffer buffer, int version, Collection<? extends AclEntry> acl) {
        int lenPos = buffer.wpos();
        buffer.putInt(0);   // length placeholder
        encodeACLs(buffer, version, acl);
        BufferUtils.updateLengthPlaceholder(buffer, lenPos);
    }

    public static void encodeACLs(Buffer buffer, int version, Collection<? extends AclEntry> acl) {
        ValidateUtils.checkNotNull(acl, "No ACL");
        if (version >= SftpConstants.SFTP_V6) {
            buffer.putInt(0);   // TODO handle ACL flags
        }

        int numEntries = GenericUtils.size(acl);
        buffer.putInt(numEntries);
        if (numEntries > 0) {
            for (AclEntry e : acl) {
                writeAclEntry(buffer, e);
            }
        }
    }

    public static void writeAclEntry(Buffer buffer, AclEntry acl) {
        ValidateUtils.checkNotNull(acl, "No ACL");

        AclEntryType type = acl.type();
        int aclType = encodeAclEntryType(type);
        ValidateUtils.checkTrue(aclType >= 0, "Unknown ACL type: %s", type);
        buffer.putInt(aclType);
        buffer.putInt(encodeAclFlags(acl.flags()));
        buffer.putInt(encodeAclMask(acl.permissions()));

        Principal user = acl.principal();
        buffer.putString(user.getName());
    }

    /**
     * Returns the equivalent SFTP value for the ACL type
     *
     * @param type The {@link AclEntryType}
     * @return The equivalent {@code ACE_SYSTEM_xxx_TYPE} or negative
     * if {@code null} or unknown type
     */
    public static int encodeAclEntryType(AclEntryType type) {
        if (type == null) {
            return Integer.MIN_VALUE;
        }

        switch(type) {
            case ALARM:
                return SftpConstants.ACE4_SYSTEM_ALARM_ACE_TYPE;
            case ALLOW:
                return SftpConstants.ACE4_ACCESS_ALLOWED_ACE_TYPE;
            case AUDIT:
                return SftpConstants.ACE4_SYSTEM_AUDIT_ACE_TYPE;
            case DENY:
                return SftpConstants.ACE4_ACCESS_DENIED_ACE_TYPE;
            default:
                return -1;
        }
    }

    public static long encodeAclFlags(Collection<AclEntryFlag> flags) {
        if (GenericUtils.isEmpty(flags)) {
            return 0L;
        }

        long aclFlag = 0L;
        if (flags.contains(AclEntryFlag.FILE_INHERIT)) {
            aclFlag |= SftpConstants.ACE4_FILE_INHERIT_ACE;
        }
        if (flags.contains(AclEntryFlag.DIRECTORY_INHERIT)) {
            aclFlag |= SftpConstants.ACE4_DIRECTORY_INHERIT_ACE;
        }
        if (flags.contains(AclEntryFlag.NO_PROPAGATE_INHERIT)) {
            aclFlag |= SftpConstants.ACE4_NO_PROPAGATE_INHERIT_ACE;
        }
        if (flags.contains(AclEntryFlag.INHERIT_ONLY)) {
            aclFlag |= SftpConstants.ACE4_INHERIT_ONLY_ACE;
        }

        return aclFlag;
    }

    public static long encodeAclMask(Collection<AclEntryPermission> mask) {
        if (GenericUtils.isEmpty(mask)) {
            return 0L;
        }

        long aclMask = 0L;
        if (mask.contains(AclEntryPermission.READ_DATA)) {
            aclMask |= SftpConstants.ACE4_READ_DATA;
        }
        if (mask.contains(AclEntryPermission.LIST_DIRECTORY)) {
            aclMask |= SftpConstants.ACE4_LIST_DIRECTORY;
        }
        if (mask.contains(AclEntryPermission.WRITE_DATA)) {
            aclMask |= SftpConstants.ACE4_WRITE_DATA;
        }
        if (mask.contains(AclEntryPermission.ADD_FILE)) {
            aclMask |= SftpConstants.ACE4_ADD_FILE;
        }
        if (mask.contains(AclEntryPermission.APPEND_DATA)) {
            aclMask |= SftpConstants.ACE4_APPEND_DATA;
        }
        if (mask.contains(AclEntryPermission.ADD_SUBDIRECTORY)) {
            aclMask |= SftpConstants.ACE4_ADD_SUBDIRECTORY;
        }
        if (mask.contains(AclEntryPermission.READ_NAMED_ATTRS)) {
            aclMask |= SftpConstants.ACE4_READ_NAMED_ATTRS;
        }
        if (mask.contains(AclEntryPermission.WRITE_NAMED_ATTRS)) {
            aclMask |= SftpConstants.ACE4_WRITE_NAMED_ATTRS;
        }
        if (mask.contains(AclEntryPermission.EXECUTE)) {
            aclMask |= SftpConstants.ACE4_EXECUTE;
        }
        if (mask.contains(AclEntryPermission.DELETE_CHILD)) {
            aclMask |= SftpConstants.ACE4_DELETE_CHILD;
        }
        if (mask.contains(AclEntryPermission.READ_ATTRIBUTES)) {
            aclMask |= SftpConstants.ACE4_READ_ATTRIBUTES;
        }
        if (mask.contains(AclEntryPermission.WRITE_ATTRIBUTES)) {
            aclMask |= SftpConstants.ACE4_WRITE_ATTRIBUTES;
        }
        if (mask.contains(AclEntryPermission.DELETE)) {
            aclMask |= SftpConstants.ACE4_DELETE;
        }
        if (mask.contains(AclEntryPermission.READ_ACL)) {
            aclMask |= SftpConstants.ACE4_READ_ACL;
        }
        if (mask.contains(AclEntryPermission.WRITE_ACL)) {
            aclMask |= SftpConstants.ACE4_WRITE_ACL;
        }
        if (mask.contains(AclEntryPermission.WRITE_OWNER)) {
            aclMask |= SftpConstants.ACE4_WRITE_OWNER;
        }
        if (mask.contains(AclEntryPermission.SYNCHRONIZE)) {
            aclMask |= SftpConstants.ACE4_SYNCHRONIZE;
        }

        return aclMask;
    }

    /**
     * Encodes a {@link FileTime} value into a buffer
     *
     * @param buffer The target {@link Buffer}
     * @param version The encoding version
     * @param flags The encoding flags
     * @param time The value to encode
     */
    public static void writeTime(Buffer buffer, int version, int flags, FileTime time) {
        // for v3 see https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#page-8
        // for v6 see https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#page-16
        if (version >= SftpConstants.SFTP_V4) {
            buffer.putLong(time.to(TimeUnit.SECONDS));
            if ((flags & SftpConstants.SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) {
                long nanos = time.to(TimeUnit.NANOSECONDS);
                nanos = nanos % TimeUnit.SECONDS.toNanos(1);
                buffer.putInt((int) nanos);
            }
        } else {
            buffer.putInt(time.to(TimeUnit.SECONDS));
        }
    }

    /**
     * Decodes a {@link FileTime} value from a buffer
     *
     * @param buffer The source {@link Buffer}
     * @param version The encoding version
     * @param flags The encoding flags
     * @return The decoded value
     */
    public static FileTime readTime(Buffer buffer, int version, int flags) {
        // for v3 see https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#page-8
        // for v6 see https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#page-16
        long secs = (version >= SftpConstants.SFTP_V4) ? buffer.getLong() : buffer.getUInt();
        long millis = TimeUnit.SECONDS.toMillis(secs);
        if ((version >= SftpConstants.SFTP_V4) && ((flags & SftpConstants.SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0)) {
            long nanoseconds = buffer.getUInt();
            millis += TimeUnit.NANOSECONDS.toMillis(nanoseconds);
        }
        return FileTime.from(millis, TimeUnit.MILLISECONDS);
    }

    /**
     * Creates an &quot;ls -l&quot; compatible long name string
     *
     * @param shortName The short file name - can also be &quot;.&quot; or &quot;..&quot;
     * @param attributes The file's attributes - e.g., size, owner, permissions, etc.
     * @return A {@link String} representing the &quot;long&quot; file name as per
     * <A HREF="https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02">SFTP version 3 - section 7</A>
     */
    public static String getLongName(String shortName, Map<String, ?> attributes) {
        String owner = Objects.toString(attributes.get("owner"), null);
        String username = OsUtils.getCanonicalUser(owner);
        if (GenericUtils.isEmpty(username)) {
            username = SftpUniversalOwnerAndGroup.Owner.getName();
        }

        String group = Objects.toString(attributes.get("group"), null);
        group = OsUtils.resolveCanonicalGroup(group, owner);
        if (GenericUtils.isEmpty(group)) {
            group = SftpUniversalOwnerAndGroup.Group.getName();
        }

        Number length = (Number) attributes.get("size");
        if (length == null) {
            length = 0L;
        }

        String lengthString = String.format("%1$8s", length);
        String linkCount = Objects.toString(attributes.get("nlink"), null);
        if (GenericUtils.isEmpty(linkCount)) {
            linkCount = "1";
        }

        Boolean isDirectory = (Boolean) attributes.get("isDirectory");
        Boolean isLink = (Boolean) attributes.get("isSymbolicLink");
        @SuppressWarnings("unchecked")
        Set<PosixFilePermission> perms = (Set<PosixFilePermission>) attributes.get("permissions");
        if (perms == null) {
            perms = EnumSet.noneOf(PosixFilePermission.class);
        }
        String permsString = PosixFilePermissions.toString(perms);
        String timeStamp = UnixDateFormat.getUnixDate((FileTime) attributes.get("lastModifiedTime"));
        StringBuilder sb = new StringBuilder(
                GenericUtils.length(linkCount) + GenericUtils.length(username) + GenericUtils.length(group)
              + GenericUtils.length(timeStamp) + GenericUtils.length(lengthString)
              + GenericUtils.length(permsString) + GenericUtils.length(shortName)
              + Integer.SIZE);
        sb.append(SftpHelper.getBool(isDirectory) ? 'd' : (SftpHelper.getBool(isLink) ? 'l' : '-')).append(permsString);

        sb.append(' ');
        for (int index = linkCount.length(); index < 3; index++) {
            sb.append(' ');
        }
        sb.append(linkCount);

        sb.append(' ').append(username);
        for (int index = username.length(); index < 8; index++) {
            sb.append(' ');
        }

        sb.append(' ').append(group);
        for (int index = group.length(); index < 8; index++) {
            sb.append(' ');
        }

        sb.append(' ').append(lengthString).append(' ').append(timeStamp).append(' ').append(shortName);
        return sb.toString();
    }
}
