1
0
mirror of https://github.com/winscp/winscp.git synced 2026-10-24 02:28:55 +03:00
Files
winscp/dotnet/RemotePath.cs
Martin Prikryl 5d67fa58b7 Added method RemotePath.EscapeOperationMask to .NET assembly.
Source commit: fc47b7abc1174fb7cce7df1d3ce75a7bdee44aa3
2020-12-09 00:48:30 +01:00

317 lines
10 KiB
C#

using System;
using System.Globalization;
using System.Reflection;
using System.Runtime.InteropServices;
namespace WinSCP
{
[Guid("70253534-C5DC-4EF3-9C98-65C57D79C324")]
[ClassInterface(Constants.ClassInterface)]
[ComVisible(true)]
public sealed class RemotePath : IReflect
{
public static string EscapeFileMask(string fileMask)
{
if (fileMask == null)
{
throw new ArgumentNullException(nameof(fileMask));
}
int lastSlash = fileMask.LastIndexOf('/');
string path = lastSlash > 0 ? fileMask.Substring(0, lastSlash + 1) : string.Empty;
string mask = lastSlash > 0 ? fileMask.Substring(lastSlash + 1) : fileMask;
// Keep in sync with EscapeFileMask in GenerateUrl.cpp
mask = mask.Replace("[", "[[]").Replace("*", "[*]").Replace("?", "[?]").Replace("<", "<<").Replace(">", ">>");
return path + mask;
}
public static string EscapeOperationMask(string operationMask)
{
if (operationMask == null)
{
throw new ArgumentNullException(nameof(operationMask));
}
int lastSlash = operationMask.LastIndexOf('/');
string path = lastSlash > 0 ? operationMask.Substring(0, lastSlash + 1) : string.Empty;
string mask = lastSlash > 0 ? operationMask.Substring(lastSlash + 1) : operationMask;
mask = mask.Replace("\\", "\\\\").Replace("*", "\\*").Replace("?", "\\?");
return path + mask;
}
[Obsolete("Use RemotePath.Combine method")]
public static string CombinePaths(string path1, string path2)
{
return Combine(path1, path2);
}
public static string Combine(string path1, string path2)
{
if (path1 == null)
{
throw new ArgumentNullException(nameof(path1));
}
if (path2 == null)
{
throw new ArgumentNullException(nameof(path2));
}
string result;
if (path2.StartsWith("/", StringComparison.Ordinal))
{
result = path2;
}
else
{
result =
path1 +
((path1.Length == 0) || (path2.Length == 0) || path1.EndsWith("/", StringComparison.Ordinal) ? string.Empty : "/") +
path2;
}
return result;
}
public static string TranslateRemotePathToLocal(string remotePath, string remoteRoot, string localRoot)
{
if (remotePath == null)
{
throw new ArgumentNullException(nameof(remotePath));
}
if (remoteRoot == null)
{
throw new ArgumentNullException(nameof(remoteRoot));
}
if (localRoot == null)
{
throw new ArgumentNullException(nameof(localRoot));
}
localRoot = AddSeparator(localRoot, @"\");
remoteRoot = AddSeparator(remoteRoot, "/");
string localPath;
// special case
if (AddSeparator(remotePath, "/") == remoteRoot)
{
localPath = localRoot;
}
else
{
if (!remotePath.StartsWith(remoteRoot, StringComparison.Ordinal))
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "{0} does not start with {1}", remotePath, remoteRoot));
}
string subPath = remotePath.Substring(remoteRoot.Length);
// can happen only when remoteRoot is empty
if (subPath.StartsWith("/", StringComparison.Ordinal))
{
subPath = subPath.Substring(1);
}
subPath = subPath.Replace('/', '\\');
localPath = localRoot + subPath;
}
return localPath;
}
private static string AddSeparator(string path, string separator)
{
// not adding to empty root paths, because the path may not even start with slash
if ((path.Length > 0) && !path.EndsWith(separator, StringComparison.Ordinal))
{
path += separator;
}
return path;
}
public static string TranslateLocalPathToRemote(string localPath, string localRoot, string remoteRoot)
{
if (localPath == null)
{
throw new ArgumentNullException(nameof(localPath));
}
if (localRoot == null)
{
throw new ArgumentNullException(nameof(localRoot));
}
if (remoteRoot == null)
{
throw new ArgumentNullException(nameof(remoteRoot));
}
localRoot = AddSeparator(localRoot, @"\");
remoteRoot = AddSeparator(remoteRoot, "/");
string remotePath;
// special case
if (AddSeparator(localPath, @"\") == localRoot)
{
remotePath = remoteRoot;
}
else
{
if (!localPath.StartsWith(localRoot, StringComparison.Ordinal))
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "{0} does not start with {1}", localPath, localRoot));
}
string subPath = localPath.Substring(localRoot.Length);
// can happen only when localRoot is empty
if (subPath.StartsWith("\\", StringComparison.Ordinal))
{
subPath = subPath.Substring(1);
}
subPath = subPath.Replace('\\', '/');
remotePath = remoteRoot + subPath;
}
return remotePath;
}
public static string GetDirectoryName(string path)
{
string result;
if (path == null)
{
result = null;
}
else if (path.Length == 0)
{
throw new ArgumentException("Path cannot be empty", nameof(path));
}
else
{
int i = path.LastIndexOf('/');
if (i < 0)
{
result = string.Empty;
}
else if (i == 0)
{
if (path.Length == 1)
{
result = null;
}
else
{
result = "/";
}
}
else
{
result = path.Substring(0, i);
}
}
return result;
}
public static string AddDirectorySeparator(string path)
{
if (string.IsNullOrEmpty(path))
{
throw new ArgumentException("Path cannot be empty", nameof(path));
}
if (!path.EndsWith("/", StringComparison.Ordinal))
{
path += "/";
}
return path;
}
public static string GetFileName(string path)
{
string result;
if (string.IsNullOrEmpty(path))
{
result = null;
}
else
{
int i = path.LastIndexOf('/');
if (i >= 0)
{
result = path.Substring(i + 1);
}
else
{
result = path;
}
}
return result;
}
FieldInfo IReflect.GetField(string name, BindingFlags bindingAttr)
{
return GetType().GetField(name, bindingAttr);
}
FieldInfo[] IReflect.GetFields(BindingFlags bindingAttr)
{
return GetType().GetFields(bindingAttr);
}
MemberInfo[] IReflect.GetMember(string name, BindingFlags bindingAttr)
{
return GetType().GetMember(name, bindingAttr);
}
MemberInfo[] IReflect.GetMembers(BindingFlags bindingAttr)
{
return GetType().GetMembers(bindingAttr);
}
MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr)
{
return GetType().GetMethod(name, bindingAttr);
}
MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
{
return GetType().GetMethod(name, bindingAttr, binder, types, modifiers);
}
MethodInfo[] IReflect.GetMethods(BindingFlags bindingAttr)
{
return GetType().GetMethods(bindingAttr);
}
PropertyInfo[] IReflect.GetProperties(BindingFlags bindingAttr)
{
return GetType().GetProperties(bindingAttr);
}
PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
{
return GetType().GetProperty(name, bindingAttr, binder, returnType, types, modifiers);
}
PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr)
{
return GetType().GetProperty(name, bindingAttr);
}
object IReflect.InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
{
if (target == null)
{
throw new ArgumentNullException(nameof(target));
}
Type type = target.GetType();
// This trivial implementation allows calling static methods over COM
return type.InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
}
Type IReflect.UnderlyingSystemType
{
get { return GetType(); }
}
}
}