// Copyright 2013 Google Inc. All Rights Reserved.
//
// Licensed 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 com.google.enterprise.adaptor.fs;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import com.google.enterprise.adaptor.fs.WinApi.Netapi32Ex;
import com.google.enterprise.adaptor.fs.WinApi.Shlwapi;

import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.Advapi32;
import com.sun.jna.platform.win32.Advapi32Util;
import com.sun.jna.platform.win32.Advapi32Util.Account;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.LMErr;
import com.sun.jna.platform.win32.W32Errors;
import com.sun.jna.platform.win32.Win32Exception;
import com.sun.jna.platform.win32.WinError;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.platform.win32.WinNT.SID_NAME_USE;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;

import java.io.IOException;
import java.nio.file.LinkOption;
import java.nio.file.Path;
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.AclFileAttributeView;
import java.nio.file.attribute.GroupPrincipal;
import java.nio.file.attribute.UserPrincipal;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Generate various {@link AclFileAttributeView}s for Windows files.
 */
class WindowsAclFileAttributeViews {

  private static final Logger log = 
      Logger.getLogger(WindowsAclFileAttributeViews.class.getName());

  private static final Kernel32 KERNEL32 = Kernel32.INSTANCE;
  private static final Advapi32 ADVAPI32 = Advapi32.INSTANCE; 

  /** This pattern parses a UNC path to get the host and share details. */
  private static final Pattern UNC_PATTERN =
      Pattern.compile("^\\\\\\\\([^\\\\]+)\\\\([^\\\\]+)");

  /** The set of SID_NAME_USE which are groups and not users. */
  private static final Set<Integer> GROUP_SID_TYPES =
      Collections.unmodifiableSet(Sets.newHashSet(
        SID_NAME_USE.SidTypeAlias, SID_NAME_USE.SidTypeGroup,
            SID_NAME_USE.SidTypeWellKnownGroup));

  /** The set of SID_NAME_USE which are user and not groups. */
  private static final Set<Integer> USER_SID_TYPES =
      Collections.unmodifiableSet(Sets.newHashSet(SID_NAME_USE.SidTypeUser));

  /** Map of NT GENERIC permissions to NT FILE permissions. */
  private static final Map<Integer, Integer> GENERIC_PERMS_MAP = 
      Collections.unmodifiableMap(new HashMap<Integer, Integer>() {
          {
            put(WinNT.GENERIC_READ, WinNT.FILE_GENERIC_READ);
            put(WinNT.GENERIC_WRITE, WinNT.FILE_GENERIC_WRITE);
            put(WinNT.GENERIC_EXECUTE, WinNT.FILE_GENERIC_EXECUTE);
            put(WinNT.GENERIC_ALL, WinNT.FILE_ALL_ACCESS);
          }
      });

  /** The map of Acl permissions from NT to AclEntryPermission. */
  private static final Map<Integer, AclEntryPermission> ACL_PERMS_MAP =
      Collections.unmodifiableMap(new HashMap<Integer, AclEntryPermission>() {
          {
            put(WinNT.FILE_READ_DATA, AclEntryPermission.READ_DATA);
            put(WinNT.FILE_READ_ATTRIBUTES,
                AclEntryPermission.READ_ATTRIBUTES);
            put(WinNT.FILE_READ_EA, AclEntryPermission.READ_NAMED_ATTRS);
            put(WinNT.READ_CONTROL, AclEntryPermission.READ_ACL);
            put(WinNT.FILE_WRITE_DATA, AclEntryPermission.WRITE_DATA);
            put(WinNT.FILE_APPEND_DATA, AclEntryPermission.APPEND_DATA);
            put(WinNT.FILE_WRITE_ATTRIBUTES,
                AclEntryPermission.WRITE_ATTRIBUTES);
            put(WinNT.FILE_WRITE_EA, AclEntryPermission.WRITE_NAMED_ATTRS);
            put(WinNT.WRITE_DAC, AclEntryPermission.WRITE_ACL);
            put(WinNT.WRITE_OWNER, AclEntryPermission.WRITE_OWNER);
            put(WinNT.DELETE, AclEntryPermission.DELETE);
            put(WinNT.FILE_DELETE_CHILD, AclEntryPermission.DELETE_CHILD);
            put(WinNT.SYNCHRONIZE, AclEntryPermission.SYNCHRONIZE);
            put(WinNT.FILE_EXECUTE, AclEntryPermission.EXECUTE);
          }
      });

  /** The map of Acl entry flags from NT to AclEntryFlag. */
  private static final Map<Byte, AclEntryFlag> ACL_FLAGS_MAP =
      Collections.unmodifiableMap(new HashMap<Byte, AclEntryFlag>() {
          {
            put(WinNT.OBJECT_INHERIT_ACE, AclEntryFlag.FILE_INHERIT);
            put(WinNT.CONTAINER_INHERIT_ACE, AclEntryFlag.DIRECTORY_INHERIT);
            put(WinNT.INHERIT_ONLY_ACE, AclEntryFlag.INHERIT_ONLY);
            put(WinNT.NO_PROPAGATE_INHERIT_ACE,
                AclEntryFlag.NO_PROPAGATE_INHERIT);
          }
      });

  /** The map of Acl entry type from NT to AclEntryType. */
  private static final Map<Byte, AclEntryType> ACL_TYPE_MAP =
      Collections.unmodifiableMap(new HashMap<Byte, AclEntryType>() {
          {
            put(WinNT.ACCESS_ALLOWED_ACE_TYPE, AclEntryType.ALLOW);
            put(WinNT.ACCESS_DENIED_ACE_TYPE, AclEntryType.DENY);
          }
      });


  /**
   * Returns a container for the direct and inherited ACLs for
   * the supplied file.
   *
   * @param path The file/folder to get the {@link AclFileAttributeViews} for
   * @return AclFileAttributeViews of direct and inherited ACL entries
   */
  public AclFileAttributeViews getAclViews(Path path) throws IOException {
    String pathname = path.toRealPath(LinkOption.NOFOLLOW_LINKS).toString();
    WinNT.ACCESS_ACEStructure[] aces = getFileSecurity(pathname, 
        WinNT.DACL_SECURITY_INFORMATION |
        WinNT.PROTECTED_DACL_SECURITY_INFORMATION |
        WinNT.UNPROTECTED_DACL_SECURITY_INFORMATION);
    ImmutableList.Builder<AclEntry> inherited = ImmutableList.builder();
    ImmutableList.Builder<AclEntry> direct = ImmutableList.builder();

    for (WinNT.ACCESS_ACEStructure ace : aces) {
      AclEntry aclEntry = newAclEntry(ace);      
      if (aclEntry != null) {
        if ((ace.AceFlags & WinNT.INHERITED_ACE) == WinNT.INHERITED_ACE) {
          inherited.add(aclEntry);
        } else {
          direct.add(aclEntry);
        }
      }
    }

    List<AclEntry> inheritedAcl = inherited.build();
    log.log(Level.FINEST, "Inherited ACL for {0}: {1}",
        new Object[] { pathname, inheritedAcl });

    List<AclEntry> directAcl = direct.build();
    log.log(Level.FINEST, "Direct ACL for {0}: {1}",
        new Object[] { pathname, directAcl });

    return new AclFileAttributeViews(
        new SimpleAclFileAttributeView(directAcl),
        new SimpleAclFileAttributeView(inheritedAcl));
  }

  /**
   * Returns the access control list for the file share which contains
   * the supplied file.
   *
   * @param path The file/folder to get the {@link AclFileAttributeView} for
   * @return AclFileAttributeView of ACL entries imposed by the share
   */
  public AclFileAttributeView getShareAclView(Path path)
      throws IOException, UnsupportedOperationException {
    if (Shlwapi.INSTANCE.PathIsUNC(path.toString())) {
      log.log(Level.FINEST, "Using a UNC path.");
      return getUncShareAclView(path.toString());
    } else if (Shlwapi.INSTANCE.PathIsNetworkPath(path.toString())) {
      log.log(Level.FINEST, "Using a mapped drive.");
      // Call WNetGetUniversalNameW with the size needed for 
      // UNIVERSAL_NAME_INFO. If WNetGetUniversalNameW returns ERROR_MORE_DATA
      // that indicates that a larger buffer is needed. If this happens, make
      // a second call to WNetGetUniversalNameW with a buffer big enough.
      Mpr mprlib = Mpr.INSTANCE;
      Memory buf = new Memory(1024);
      IntByReference bufSize = new IntByReference((int) buf.size());
      int result = mprlib.WNetGetUniversalNameW(path.getRoot().toString(),
          Mpr.UNIVERSAL_NAME_INFO_LEVEL, buf, bufSize);
      if (result == WinNT.ERROR_MORE_DATA) {
        buf = new Memory(bufSize.getValue());
        result = Mpr.INSTANCE.WNetGetUniversalNameW(path.getRoot().toString(),
            Mpr.UNIVERSAL_NAME_INFO_LEVEL, buf, bufSize);
      }
      if (result != WinNT.NO_ERROR) {
        throw new IOException("Unable to get UNC path for the mapped path " +
            path + ". Result: " + result);
      }

      Mpr.UNIVERSAL_NAME_INFO info = new Mpr.UNIVERSAL_NAME_INFO(buf);
      return getUncShareAclView(info.lpUniversalName);
    } else {
      log.log(Level.FINEST, "Using a local drive.");
      return new SimpleAclFileAttributeView(Collections.<AclEntry>emptyList());
    }
    // TODO(mifern): For a local drive, mapped and UNC the share Acl must also
    // include the Acls from the config point to the root.
  }

  private AclFileAttributeView getUncShareAclView(String uncPath)
      throws IOException {
    Matcher match = UNC_PATTERN.matcher(uncPath);
    if (!match.find()) {
      throw new IOException("The UNC path " + uncPath + " is not valid. "
          + "A UNC path of the form \\\\<host>\\<share> is required.");
    }
    String host = match.group(1);
    String share = match.group(2);
    log.log(Level.FINEST, "UNC: host: {0}, share: {1}.",
        new Object[] { host, share });
    return getShareAclView(host, share);
  }
  
  private AclFileAttributeView getShareAclView(String host, String share)
      throws IOException {
    Netapi32Ex netapi32 = Netapi32Ex.INSTANCE;
    PointerByReference buf = new PointerByReference();
    
    // Call NetShareGetInfo with a 502 to get the security descriptor of the
    // share. The security descriptor contains the Acl details for the share
    // that the adaptor needs.
    int result = netapi32.NetShareGetInfo(host, share, 502, buf);
    if (result != WinError.ERROR_SUCCESS) {
      if (result == WinError.ERROR_ACCESS_DENIED) {
        throw new IOException(
            "The user does not have access to the share Acl information.");
      } else if (result == WinError.ERROR_INVALID_LEVEL) {
        throw new IOException(
            "The value specified for the level parameter is not valid.");
      } else if (result == WinError.ERROR_INVALID_PARAMETER) {
        throw new IOException("A specified parameter is not valid.");
      } else if (result == WinError.ERROR_NOT_ENOUGH_MEMORY) {
        throw new IOException("Insufficient memory is available.");
      } else if (result == LMErr.NERR_NetNameNotFound) {
        throw new IOException("The share name does not exist.");
      } else {
        throw new IOException("Unable to the read share Acl. Error: " +
            result);
      }
    }

    Netapi32Ex.SHARE_INFO_502 info =
        new Netapi32Ex.SHARE_INFO_502(buf.getValue());
    netapi32.NetApiBufferFree(buf.getValue());

    WinNT.SECURITY_DESCRIPTOR_RELATIVE sdr =
        new WinNT.SECURITY_DESCRIPTOR_RELATIVE(info.shi502_security_descriptor);
    WinNT.ACL dacl = sdr.getDiscretionaryACL();

    ImmutableList.Builder<AclEntry> builder = ImmutableList.builder();
    for (WinNT.ACCESS_ACEStructure ace : dacl.getACEStructures()) {
      AclEntry entry = newAclEntry(ace);
      if (entry != null) {
        builder.add(entry);
      }
    }

    List<AclEntry> acl = builder.build();
    if (log.isLoggable(Level.FINEST)) {
      log.log(Level.FINEST, "Share ACL for \\\\{0}\\{1}: {2}",
          new Object[] { host, share, acl.toString() });
    }
    return new SimpleAclFileAttributeView(acl);
  }

  /**
   * Creates an {@link AclEntry} from a {@code WinNT.ACCESS_ACEStructure}.
   *
   * @param ace Windows ACE returned by JNA
   * @return AclEntry representing the ace, or {@code null} if a valid
   *         AclEntry could not be created from the ace.
   */
  public static AclEntry newAclEntry(WinNT.ACCESS_ACEStructure ace) {
    // Map the type.
    AclEntryType aclType = ACL_TYPE_MAP.get(ace.AceType);
    if (aclType == null) {
      log.log(Level.FINEST, "Skipping ACE with unsupported access type: {0}.",
          ace.AceType);
      return null;
    }

    // Map the user.
    Account account;
    try {
      account = Advapi32Util.getAccountBySid(ace.getSID());
    } catch (Win32Exception e) {
      // Only the least significant 16-bits signifies the HR code.
      if ((e.getHR().intValue() & 0xFFFF) == WinError.ERROR_NONE_MAPPED) {
        log.log(Level.WARNING, "Skipping ACE with unresolvable SID: {0}.",
            ace.getSidString());
        return null;
      } else {
        throw e;
      }
    }
    String accountName = (account.domain == null ?
        account.name : account.domain + "\\" + account.name);
    UserPrincipal aclPrincipal;
    String accountType = getSidTypeString(account.accountType);
    if (USER_SID_TYPES.contains(account.accountType)) {
      aclPrincipal = new User(accountName, accountType);
    } else if (GROUP_SID_TYPES.contains(account.accountType)) {
      aclPrincipal = new Group(accountName, accountType);
    } else {
      log.log(Level.FINEST,
          "Skipping ACE with unsupported account type {0} ({1}).",
          new Object[] { accountName, accountType });
      return null;
    }
    
    // Expand NT GENERIC_* permissions to their FILE_GENERIC_* equivalents.
    int aceMask = ace.Mask;
    for (Map.Entry<Integer, Integer> e : GENERIC_PERMS_MAP.entrySet()) {
      if ((ace.Mask & e.getKey()) == e.getKey()) {
        aceMask |= e.getValue();
      }
    }

    // Map the permissions.
    Set<AclEntryPermission> aclPerms = EnumSet.noneOf(AclEntryPermission.class);
    for (Map.Entry<Integer, AclEntryPermission> e : ACL_PERMS_MAP.entrySet()) {
      if ((aceMask & e.getKey()) == e.getKey()) {
        aclPerms.add(e.getValue());
      }
    }
    
    // Map the flags.
    Set<AclEntryFlag> aclFlags = EnumSet.noneOf(AclEntryFlag.class);
    for (Map.Entry<Byte, AclEntryFlag> e : ACL_FLAGS_MAP.entrySet()) {
      if ((ace.AceFlags & e.getKey()) == e.getKey()) {
        aclFlags.add(e.getValue());
      }
    }

    return AclEntry.newBuilder()
        .setType(aclType)
        .setPrincipal(aclPrincipal)
        .setPermissions(aclPerms)
        .setFlags(aclFlags)
        .build();
  }

  // One-to-one corresponance to WinNT.SID_NAME_USE "enumeration".
  private static final List<String> SID_TYPE_NAMES = ImmutableList.of(
      "Unknown", "User", "Group", "Domain", "Alias", "Well-known Group",
      "Deleted", "Invalid", "Computer");

  private static String getSidTypeString(int sidType) {
    if (sidType < 0 || sidType > SID_TYPE_NAMES.size()) {
      return SID_TYPE_NAMES.get(0);
    } else {
      return SID_TYPE_NAMES.get(sidType);
    }
  }

  private static class User implements UserPrincipal {
    private final String accountName;
    private final String accountType;

    User(String accountName, String accountType) {
      this.accountName = accountName;
      this.accountType = accountType;
    }

    @Override
    public String getName() {
      return accountName;
    }

    @Override
    public String toString() {
      return accountName + " (" + accountType + ")";
    }
  }

  private static class Group extends User implements GroupPrincipal {
    Group(String accountName, String accountType) {
      super(accountName, accountType);
    }
  }

  private interface Mpr extends StdCallLibrary {
    Mpr INSTANCE = (Mpr) Native.loadLibrary("Mpr", Mpr.class,
        W32APIOptions.UNICODE_OPTIONS);

    public final int UNIVERSAL_NAME_INFO_LEVEL = 1;

    int WNetGetUniversalNameW(String lpLocalPath, int dwInfoLevel,
        Pointer lpBuffer, IntByReference lpBufferSize);

    public static class UNIVERSAL_NAME_INFO extends Structure {
      public String lpUniversalName;

      public UNIVERSAL_NAME_INFO() {
        super();
      }

      public UNIVERSAL_NAME_INFO(Pointer memory) {
        useMemory(memory);
        read();
      }

      @Override
      protected List<String> getFieldOrder() {
        return Arrays.asList(new String[] { "lpUniversalName" });
      }
    }
  }

  /** Uses JNA to call native Windows {@code GetFileSecurity} function. */
  private WinNT.ACCESS_ACEStructure[] getFileSecurity(String pathname,
      int daclType) throws IOException {
    WString wpath = new WString(pathname);
    IntByReference lengthNeeded = new IntByReference();

    if (ADVAPI32.GetFileSecurity(wpath, daclType, null, 0, lengthNeeded)) {
      throw new RuntimeException("GetFileSecurity was expected to fail with "
          + "ERROR_INSUFFICIENT_BUFFER");
    }

    int rc = KERNEL32.GetLastError();
    if (rc != W32Errors.ERROR_INSUFFICIENT_BUFFER) {
      throw new IOException("Failed GetFileSecurity", new Win32Exception(rc));
    }

    Memory memory = new Memory(lengthNeeded.getValue());
    if (!ADVAPI32.GetFileSecurity(wpath, daclType, memory, (int) memory.size(),
                                  lengthNeeded)) {
      throw new IOException("Failed GetFileSecurity",
          new Win32Exception(KERNEL32.GetLastError()));
    }

    WinNT.SECURITY_DESCRIPTOR_RELATIVE securityDescriptor =
        new WinNT.SECURITY_DESCRIPTOR_RELATIVE(memory);
    return securityDescriptor.getDiscretionaryACL().getACEStructures();
  }
}
