// Copyright 2014 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 static org.junit.Assert.*;

import com.google.common.base.Preconditions;
import com.google.enterprise.adaptor.fs.WinApi.Netapi32Ex;
import com.google.enterprise.adaptor.fs.WinApi.Shlwapi;
import com.google.enterprise.adaptor.fs.WindowsAclFileAttributeViews.Mpr;

import org.junit.*;
import org.junit.rules.TemporaryFolder;

import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.Advapi32;
import com.sun.jna.platform.win32.Advapi32Util.Account;
import com.sun.jna.platform.win32.Kernel32;
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 java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;

/**
 * Base class that provides mechanisms for faking JNA ACL access.
 * Tests that wish to fake JNA calls to access ACLs should extend this.
 */
public class TestWindowsAclViews {

  @Rule
  public final TemporaryFolder temp = new TemporaryFolder();

  protected final Path newTempDir(String name) throws IOException {
    return temp.newFolder(name).toPath().toRealPath();
  }

  protected final Path newTempFile(String name) throws IOException {
    return temp.newFile(name).toPath().toRealPath();
  }

  protected final Path newTempFile(Path parent, String name)
      throws IOException {
    Preconditions.checkArgument(parent.startsWith(getTempRoot()));
    return Files.createFile(parent.resolve(name));
  }

  protected final Path getTempRoot() throws IOException {
    return temp.getRoot().getCanonicalFile().toPath();
  }

  /**
   * Serializes an WinNT ACEs into a byte buffer representing a DACL.
   * This byte buffer is suitable for reading back via 
   * <code>new WinNT.SECURITY_DESCRIPTOR_RELATIVE(Memory)</code>.
   */
  protected static final byte[] buildDaclMemory(
      WinNT.ACCESS_ACEStructure... aces) throws Exception {
    WinNT.ACL acl = new WinNT.ACL();
    WinNT.SECURITY_DESCRIPTOR_RELATIVE securityDescriptor =
        new WinNT.SECURITY_DESCRIPTOR_RELATIVE();
    int totalSize = securityDescriptor.size() + acl.size();
    for (WinNT.ACCESS_ACEStructure ace : aces) {
      totalSize += ace.AceSize;
    }

    // Serialize the structures into a buffer.
    final byte[] buffer = new byte[totalSize];
    int offset = 0;
    // The start of the ACL follows the securityDescriptor in memory.
    securityDescriptor.Dacl = securityDescriptor.size();
    securityDescriptor.write();
    securityDescriptor.getPointer().read(0, buffer, offset,
                                         securityDescriptor.size());
    offset += securityDescriptor.size();
    acl.AceCount = (short) aces.length;
    acl.write();
    acl.getPointer().read(0, buffer, offset, acl.size());
    offset += acl.size();
    for (WinNT.ACCESS_ACEStructure ace : aces) {
      ace.write();
      ace.getPointer().read(0, buffer, offset, ace.AceSize);
      offset += ace.AceSize;
    }
    return buffer;
  }

  /**
   * A convenient Ace Builder. Only AccountSid SIDs are supported.
   */
  public static class AceBuilder {
    private byte type;
    private byte flags;
    private int perms;
    private AccountSid sid;

    public AceBuilder setType(byte type) {
      this.type = type;
      return this;
    }

    public AceBuilder setFlags(byte... flags) {
      for (byte flag : flags) {
        this.flags |= flag;
      }
      return this;
    }

    public AceBuilder setPerms(int... perms) {
      for (int perm : perms) {
        this.perms |= perm;
      }
      return this;
    }

    public AceBuilder setSid(AccountSid sid) {
      this.sid = sid;
      return this;
    }

    public WinNT.ACCESS_ACEStructure build() {
      // Because ACCESS_ACEStructure does not allow me to set the SID
      // directly, I must create a serialized ACE containing a Pointer
      // to my AccountSid, then create a new ACE from that memory.
      WinNT.ACCESS_ACEStructure ace = new Ace();
      ace.AceType = type;
      ace.AceFlags = flags;
      ace.Mask = perms;
      ace.AceSize = (short)(ace.size() + Pointer.SIZE);
      ace.write();
      byte[] buffer = new byte[ace.AceSize];
      ace.getPointer().read(0, buffer, 0, ace.size());
      Memory memory = new Memory(buffer.length);
      memory.write(0, buffer, 0, ace.size());
      sid.write();
      // See ACCESS_ACEStructure(Pointer p) constructor for mystery offsets.
      memory.setPointer(4 + 4, sid.getPointer());
      ace = new Ace(memory);
      assertEquals(ace.getSID().sid, sid.getPointer());
      return ace;
    }
  }

  /**
   * A subclass of WinNT.ACCESS_ACEStructure that avoids using
   * Advapi32Util to get the string SID.
   */
  public static class Ace extends WinNT.ACCESS_ACEStructure {
    public Ace() {
    }

    public Ace(Pointer p) {
      super(p);
    }

    @Override
    public String getSidString() {
      return new AccountSid(getSID().sid).toString();
    }
  }

  /**
   * A SID structure that encapsulates the <code>Advapi32Util.Account</code>
   * information, avoiding network lookups to in <code>getAccountBySid</code>.
   */
  public static class AccountSid extends Structure {

    public static AccountSid user(String name, String domain) {
      return new AccountSid(SID_NAME_USE.SidTypeUser, name, domain);
    }

    public static AccountSid group(String name, String domain) {
      return new AccountSid(SID_NAME_USE.SidTypeGroup, name, domain);
    }

    @Override
    protected List getFieldOrder() {
      return Arrays.asList(new String[] { "type", "name", "domain" });
    }

    public int type;
    public String name;
    public String domain;

    public AccountSid() {
    }

    public AccountSid(Pointer p) {
      super(p);
      read();
    }

    public AccountSid(int type, String name, String domain) {
      this.type = type;
      this.name = name;
      this.domain = domain;
    }

    public Account getAccount() throws Win32Exception {
      if (name == null && domain == null) {
        throw new Win32Exception(WinError.ERROR_NONE_MAPPED);
      } else {
        Account account = new Account();
        account.accountType = type;
        account.name = name;
        account.domain = domain;
        return account;
      }
    }

    @Override
    public String toString() {
      if (name == null && domain == null) {
        return "null";
      } else {
        return (domain == null) ? name : domain + "\\" + name;
      }
    }
  }

  /**
   * An subclass of {@link WindowsAclFileAttributeViews} that avoids making
   * actual Windows API calls by using faked JNA implementations.
   */
  public static class TestAclFileAttributeViews
      extends WindowsAclFileAttributeViews {

    public TestAclFileAttributeViews() {
      super(null, null, null, null, null);
    }

    public TestAclFileAttributeViews(Advapi32 advapi32, Kernel32 kernel32,
      Mpr mpr, Netapi32Ex netapi32, Shlwapi shlwapi) {
      super(advapi32, kernel32, mpr, netapi32, shlwapi);
    }

    @Override
    Account getAccountBySid(WinNT.PSID sid) throws Win32Exception {
      return new AccountSid(sid.sid).getAccount();
    }
  }
}
