// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
namespace WixToolset.Core.CommandLine
{
using System;
using System.IO;
using WixToolset.Data;
using WixToolset.Extensibility.Services;
public class CommandLineHelper
{
///
/// Validates that a string is a valid directory name, and throws appropriate warnings/errors if not
///
/// The commandline switch we're parsing (for error display purposes).
/// The messagehandler to report warnings/errors to.
/// The list of strings to check.
/// The index (in args) of the commandline parameter to be parsed.
/// The string if it is valid, null if it is invalid.
public static string GetDirectory(string commandlineSwitch, IMessaging messageHandler, string[] args, int index)
{
return GetDirectory(commandlineSwitch, messageHandler, args, index, false);
}
///
/// Validates that a string is a valid directory name, and throws appropriate warnings/errors if not
///
/// The commandline switch we're parsing (for error display purposes).
/// The messagehandler to report warnings/errors to.
/// The list of strings to check.
/// The index (in args) of the commandline parameter to be parsed.
/// Indicates if a colon-delimited prefix is allowed.
/// The string if it is valid, null if it is invalid.
public static string GetDirectory(string commandlineSwitch, IMessaging messageHandler, string[] args, int index, bool allowPrefix)
{
commandlineSwitch = String.Concat("-", commandlineSwitch);
if (!IsValidArg(args, index))
{
messageHandler.Write(ErrorMessages.DirectoryPathRequired(commandlineSwitch));
return null;
}
if (File.Exists(args[index]))
{
messageHandler.Write(ErrorMessages.ExpectedDirectoryGotFile(commandlineSwitch, args[index]));
return null;
}
return VerifyPath(messageHandler, args[index], allowPrefix);
}
///
/// Validates that a string is a valid filename, and throws appropriate warnings/errors if not
///
/// The commandline switch we're parsing (for error display purposes).
/// The messagehandler to report warnings/errors to.
/// The list of strings to check.
/// The index (in args) of the commandline parameter to be parsed.
/// The string if it is valid, null if it is invalid.
public static string GetFile(string commandlineSwitch, IMessaging messageHandler, string[] args, int index)
{
commandlineSwitch = String.Concat("-", commandlineSwitch);
if (!IsValidArg(args, index))
{
messageHandler.Write(ErrorMessages.FilePathRequired(commandlineSwitch));
return null;
}
if (Directory.Exists(args[index]))
{
messageHandler.Write(ErrorMessages.ExpectedFileGotDirectory(commandlineSwitch, args[index]));
return null;
}
return VerifyPath(messageHandler, args[index]);
}
///
/// Get a set of files that possibly have a search pattern in the path (such as '*').
///
/// Search path to find files in.
/// Type of file; typically "Source".
/// An array of files matching the search path.
///
/// This method is written in this verbose way because it needs to support ".." in the path.
/// It needs the directory path isolated from the file name in order to use Directory.GetFiles
/// or DirectoryInfo.GetFiles. The only way to get this directory path is manually since
/// Path.GetDirectoryName does not support ".." in the path.
///
/// Throws WixFileNotFoundException if no file matching the pattern can be found.
public static string[] GetFiles(string searchPath, string fileType)
{
if (null == searchPath)
{
throw new ArgumentNullException(nameof(searchPath));
}
// Convert alternate directory separators to the standard one.
string filePath = searchPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
int lastSeparator = filePath.LastIndexOf(Path.DirectorySeparatorChar);
string[] files = null;
try
{
if (0 > lastSeparator)
{
files = Directory.GetFiles(".", filePath);
}
else // found directory separator
{
files = Directory.GetFiles(filePath.Substring(0, lastSeparator + 1), filePath.Substring(lastSeparator + 1));
}
}
catch (DirectoryNotFoundException)
{
// Don't let this function throw the DirectoryNotFoundException. This exception
// occurs for non-existant directories and invalid characters in the searchPattern.
}
catch (ArgumentException)
{
// Don't let this function throw the ArgumentException. This exception
// occurs in certain situations such as when passing a malformed UNC path.
}
catch (IOException)
{
throw new WixFileNotFoundException(searchPath, fileType);
}
if (null == files || 0 == files.Length)
{
throw new WixFileNotFoundException(searchPath, fileType);
}
return files;
}
///
/// Validates that a valid string parameter (without "/" or "-"), and returns a bool indicating its validity
///
/// The list of strings to check.
/// The index (in args) of the commandline parameter to be validated.
/// True if a valid string parameter exists there, false if not.
public static bool IsValidArg(string[] args, int index)
{
if (args.Length <= index || String.IsNullOrEmpty(args[index]) || '/' == args[index][0] || '-' == args[index][0])
{
return false;
}
else
{
return true;
}
}
///
/// Validates that a commandline parameter is a valid file or directory name, and throws appropriate warnings/errors if not
///
/// The messagehandler to report warnings/errors to.
/// The path to test.
/// The string if it is valid, null if it is invalid.
public static string VerifyPath(IMessaging messageHandler, string path)
{
return VerifyPath(messageHandler, path, false);
}
///
/// Validates that a commandline parameter is a valid file or directory name, and throws appropriate warnings/errors if not
///
/// The messagehandler to report warnings/errors to.
/// The path to test.
/// Indicates if a colon-delimited prefix is allowed.
/// The full path if it is valid, null if it is invalid.
public static string VerifyPath(IMessaging messageHandler, string path, bool allowPrefix)
{
string fullPath;
if (0 <= path.IndexOf('\"'))
{
messageHandler.Write(ErrorMessages.PathCannotContainQuote(path));
return null;
}
try
{
string prefix = null;
if (allowPrefix)
{
int prefixLength = path.IndexOf('=') + 1;
if (0 != prefixLength)
{
prefix = path.Substring(0, prefixLength);
path = path.Substring(prefixLength);
}
}
if (String.IsNullOrEmpty(prefix))
{
fullPath = Path.GetFullPath(path);
}
else
{
fullPath = String.Concat(prefix, Path.GetFullPath(path));
}
}
catch (Exception e)
{
messageHandler.Write(ErrorMessages.InvalidCommandLineFileName(path, e.Message));
return null;
}
return fullPath;
}
}
}