diff options
Diffstat (limited to 'MediaBrowser.Networking')
| -rw-r--r-- | MediaBrowser.Networking/Management/NativeMethods.cs | 72 | ||||
| -rw-r--r-- | MediaBrowser.Networking/Management/NetworkManager.cs | 265 | ||||
| -rw-r--r-- | MediaBrowser.Networking/Management/NetworkShares.cs | 638 | ||||
| -rw-r--r-- | MediaBrowser.Networking/MediaBrowser.Networking.csproj | 14 |
4 files changed, 989 insertions, 0 deletions
diff --git a/MediaBrowser.Networking/Management/NativeMethods.cs b/MediaBrowser.Networking/Management/NativeMethods.cs new file mode 100644 index 000000000..9a888fab2 --- /dev/null +++ b/MediaBrowser.Networking/Management/NativeMethods.cs @@ -0,0 +1,72 @@ +using System; +using System.Runtime.InteropServices; +using System.Security; + +namespace MediaBrowser.Networking.Management +{ + /// <summary> + /// Class NativeMethods + /// </summary> + [SuppressUnmanagedCodeSecurity] + public static class NativeMethods + { + //declare the Netapi32 : NetServerEnum method import + /// <summary> + /// Nets the server enum. + /// </summary> + /// <param name="ServerName">Name of the server.</param> + /// <param name="dwLevel">The dw level.</param> + /// <param name="pBuf">The p buf.</param> + /// <param name="dwPrefMaxLen">The dw pref max len.</param> + /// <param name="dwEntriesRead">The dw entries read.</param> + /// <param name="dwTotalEntries">The dw total entries.</param> + /// <param name="dwServerType">Type of the dw server.</param> + /// <param name="domain">The domain.</param> + /// <param name="dwResumeHandle">The dw resume handle.</param> + /// <returns>System.Int32.</returns> + [DllImport("Netapi32", CharSet = CharSet.Auto, SetLastError = true), + SuppressUnmanagedCodeSecurityAttribute] + + public static extern int NetServerEnum( + string ServerName, // must be null + int dwLevel, + ref IntPtr pBuf, + int dwPrefMaxLen, + out int dwEntriesRead, + out int dwTotalEntries, + int dwServerType, + string domain, // null for login domain + out int dwResumeHandle + ); + + //declare the Netapi32 : NetApiBufferFree method import + /// <summary> + /// Nets the API buffer free. + /// </summary> + /// <param name="pBuf">The p buf.</param> + /// <returns>System.Int32.</returns> + [DllImport("Netapi32", SetLastError = true), + SuppressUnmanagedCodeSecurityAttribute] + + public static extern int NetApiBufferFree( + IntPtr pBuf); + } + + //create a _SERVER_INFO_100 STRUCTURE + /// <summary> + /// Struct _SERVER_INFO_100 + /// </summary> + [StructLayout(LayoutKind.Sequential)] + public struct _SERVER_INFO_100 + { + /// <summary> + /// The sv100_platform_id + /// </summary> + internal int sv100_platform_id; + /// <summary> + /// The sv100_name + /// </summary> + [MarshalAs(UnmanagedType.LPWStr)] + internal string sv100_name; + } +} diff --git a/MediaBrowser.Networking/Management/NetworkManager.cs b/MediaBrowser.Networking/Management/NetworkManager.cs new file mode 100644 index 000000000..fcead43d3 --- /dev/null +++ b/MediaBrowser.Networking/Management/NetworkManager.cs @@ -0,0 +1,265 @@ +using MediaBrowser.Common.Net; +using MediaBrowser.Model.Net; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Management; +using System.Net; +using System.Net.Sockets; +using System.Runtime.InteropServices; + +namespace MediaBrowser.Networking.Management +{ + /// <summary> + /// Class NetUtils + /// </summary> + public class NetworkManager : INetworkManager + { + /// <summary> + /// Gets the machine's local ip address + /// </summary> + /// <returns>IPAddress.</returns> + public string GetLocalIpAddress() + { + var host = Dns.GetHostEntry(Dns.GetHostName()); + + var ip = host.AddressList.FirstOrDefault(i => i.AddressFamily == AddressFamily.InterNetwork); + + if (ip == null) + { + return null; + } + + return ip.ToString(); + } + + /// <summary> + /// Gets a random port number that is currently available + /// </summary> + /// <returns>System.Int32.</returns> + public int GetRandomUnusedPort() + { + var listener = new TcpListener(IPAddress.Any, 0); + listener.Start(); + var port = ((IPEndPoint)listener.LocalEndpoint).Port; + listener.Stop(); + return port; + } + + /// <summary> + /// Creates the netsh URL registration. + /// </summary> + public void AuthorizeHttpListening(string url) + { + var startInfo = new ProcessStartInfo + { + FileName = "netsh", + Arguments = string.Format("http add urlacl url={0} user=\"NT AUTHORITY\\Authenticated Users\"", url), + CreateNoWindow = true, + WindowStyle = ProcessWindowStyle.Hidden, + Verb = "runas", + ErrorDialog = false + }; + + using (var process = Process.Start(startInfo)) + { + process.WaitForExit(); + } + } + + /// <summary> + /// Adds the windows firewall rule. + /// </summary> + /// <param name="port">The port.</param> + /// <param name="protocol">The protocol.</param> + public void AddSystemFirewallRule(int port, NetworkProtocol protocol) + { + // First try to remove it so we don't end up creating duplicates + RemoveSystemFirewallRule(port, protocol); + + var args = string.Format("advfirewall firewall add rule name=\"Port {0}\" dir=in action=allow protocol={1} localport={0}", port, protocol); + + RunNetsh(args); + } + + /// <summary> + /// Removes the windows firewall rule. + /// </summary> + /// <param name="port">The port.</param> + /// <param name="protocol">The protocol.</param> + public void RemoveSystemFirewallRule(int port, NetworkProtocol protocol) + { + var args = string.Format("advfirewall firewall delete rule name=\"Port {0}\" protocol={1} localport={0}", port, protocol); + + RunNetsh(args); + } + + /// <summary> + /// Runs the netsh. + /// </summary> + /// <param name="args">The args.</param> + private void RunNetsh(string args) + { + var startInfo = new ProcessStartInfo + { + FileName = "netsh", + Arguments = args, + CreateNoWindow = true, + WindowStyle = ProcessWindowStyle.Hidden, + Verb = "runas", + ErrorDialog = false + }; + + using (var process = new Process { StartInfo = startInfo }) + { + process.Start(); + process.WaitForExit(); + } + } + + /// <summary> + /// Returns MAC Address from first Network Card in Computer + /// </summary> + /// <returns>[string] MAC Address</returns> + public string GetMacAddress() + { + var mc = new ManagementClass("Win32_NetworkAdapterConfiguration"); + var moc = mc.GetInstances(); + var macAddress = String.Empty; + foreach (ManagementObject mo in moc) + { + if (macAddress == String.Empty) // only return MAC Address from first card + { + try + { + if ((bool)mo["IPEnabled"]) macAddress = mo["MacAddress"].ToString(); + } + catch + { + mo.Dispose(); + return ""; + } + } + mo.Dispose(); + } + + return macAddress.Replace(":", ""); + } + + /// <summary> + /// Uses the DllImport : NetServerEnum with all its required parameters + /// (see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netmgmt/netmgmt/netserverenum.asp + /// for full details or method signature) to retrieve a list of domain SV_TYPE_WORKSTATION + /// and SV_TYPE_SERVER PC's + /// </summary> + /// <returns>Arraylist that represents all the SV_TYPE_WORKSTATION and SV_TYPE_SERVER + /// PC's in the Domain</returns> + public IEnumerable<string> GetNetworkDevices() + { + //local fields + const int MAX_PREFERRED_LENGTH = -1; + var SV_TYPE_WORKSTATION = 1; + var SV_TYPE_SERVER = 2; + var buffer = IntPtr.Zero; + var tmpBuffer = IntPtr.Zero; + var entriesRead = 0; + var totalEntries = 0; + var resHandle = 0; + var sizeofINFO = Marshal.SizeOf(typeof(_SERVER_INFO_100)); + + try + { + //call the DllImport : NetServerEnum with all its required parameters + //see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netmgmt/netmgmt/netserverenum.asp + //for full details of method signature + var ret = NativeMethods.NetServerEnum(null, 100, ref buffer, MAX_PREFERRED_LENGTH, out entriesRead, out totalEntries, SV_TYPE_WORKSTATION | SV_TYPE_SERVER, null, out resHandle); + + //if the returned with a NERR_Success (C++ term), =0 for C# + if (ret == 0) + { + //loop through all SV_TYPE_WORKSTATION and SV_TYPE_SERVER PC's + for (var i = 0; i < totalEntries; i++) + { + //get pointer to, Pointer to the buffer that received the data from + //the call to NetServerEnum. Must ensure to use correct size of + //STRUCTURE to ensure correct location in memory is pointed to + tmpBuffer = new IntPtr((int)buffer + (i * sizeofINFO)); + //Have now got a pointer to the list of SV_TYPE_WORKSTATION and + //SV_TYPE_SERVER PC's, which is unmanaged memory + //Needs to Marshal data from an unmanaged block of memory to a + //managed object, again using STRUCTURE to ensure the correct data + //is marshalled + var svrInfo = (_SERVER_INFO_100)Marshal.PtrToStructure(tmpBuffer, typeof(_SERVER_INFO_100)); + + //add the PC names to the ArrayList + if (!string.IsNullOrEmpty(svrInfo.sv100_name)) + { + yield return svrInfo.sv100_name; + } + } + } + } + finally + { + //The NetApiBufferFree function frees + //the memory that the NetApiBufferAllocate function allocates + NativeMethods.NetApiBufferFree(buffer); + } + } + + + /// <summary> + /// Gets the network shares. + /// </summary> + /// <param name="path">The path.</param> + /// <returns>IEnumerable{NetworkShare}.</returns> + public IEnumerable<NetworkShare> GetNetworkShares(string path) + { + return new ShareCollection(path).OfType<Share>().Select(ToNetworkShare); + } + + /// <summary> + /// To the network share. + /// </summary> + /// <param name="share">The share.</param> + /// <returns>NetworkShare.</returns> + private NetworkShare ToNetworkShare(Share share) + { + return new NetworkShare + { + Name = share.NetName, + Path = share.Path, + Remark = share.Remark, + Server = share.Server, + ShareType = ToNetworkShareType(share.ShareType) + }; + } + + /// <summary> + /// To the type of the network share. + /// </summary> + /// <param name="shareType">Type of the share.</param> + /// <returns>NetworkShareType.</returns> + /// <exception cref="System.ArgumentException">Unknown share type</exception> + private NetworkShareType ToNetworkShareType(ShareType shareType) + { + switch (shareType) + { + case ShareType.Device: + return NetworkShareType.Device; + case ShareType.Disk : + return NetworkShareType.Disk; + case ShareType.IPC : + return NetworkShareType.Ipc; + case ShareType.Printer : + return NetworkShareType.Printer; + case ShareType.Special: + return NetworkShareType.Special; + default: + throw new ArgumentException("Unknown share type"); + } + } + } + +} diff --git a/MediaBrowser.Networking/Management/NetworkShares.cs b/MediaBrowser.Networking/Management/NetworkShares.cs new file mode 100644 index 000000000..0239ddead --- /dev/null +++ b/MediaBrowser.Networking/Management/NetworkShares.cs @@ -0,0 +1,638 @@ +using System; +using System.IO; +using System.Collections; +using System.Runtime.InteropServices; + +namespace MediaBrowser.Networking.Management +{ + /// <summary> + /// Type of share + /// </summary> + [Flags] + public enum ShareType + { + /// <summary>Disk share</summary> + Disk = 0, + /// <summary>Printer share</summary> + Printer = 1, + /// <summary>Device share</summary> + Device = 2, + /// <summary>IPC share</summary> + IPC = 3, + /// <summary>Special share</summary> + Special = -2147483648, // 0x80000000, + } + + #region Share + + /// <summary> + /// Information about a local share + /// </summary> + public class Share + { + #region Private data + + private string _server; + private string _netName; + private string _path; + private ShareType _shareType; + private string _remark; + + #endregion + + #region Constructor + + /// <summary> + /// Constructor + /// </summary> + /// <param name="Server"></param> + /// <param name="shi"></param> + public Share(string server, string netName, string path, ShareType shareType, string remark) + { + if (ShareType.Special == shareType && "IPC$" == netName) + { + shareType |= ShareType.IPC; + } + + _server = server; + _netName = netName; + _path = path; + _shareType = shareType; + _remark = remark; + } + + #endregion + + #region Properties + + /// <summary> + /// The name of the computer that this share belongs to + /// </summary> + public string Server + { + get { return _server; } + } + + /// <summary> + /// Share name + /// </summary> + public string NetName + { + get { return _netName; } + } + + /// <summary> + /// Local path + /// </summary> + public string Path + { + get { return _path; } + } + + /// <summary> + /// Share type + /// </summary> + public ShareType ShareType + { + get { return _shareType; } + } + + /// <summary> + /// Comment + /// </summary> + public string Remark + { + get { return _remark; } + } + + /// <summary> + /// Returns true if this is a file system share + /// </summary> + public bool IsFileSystem + { + get + { + // Shared device + if (0 != (_shareType & ShareType.Device)) return false; + // IPC share + if (0 != (_shareType & ShareType.IPC)) return false; + // Shared printer + if (0 != (_shareType & ShareType.Printer)) return false; + + // Standard disk share + if (0 == (_shareType & ShareType.Special)) return true; + + // Special disk share (e.g. C$) + return ShareType.Special == _shareType && !string.IsNullOrEmpty(_netName); + } + } + + /// <summary> + /// Get the root of a disk-based share + /// </summary> + public DirectoryInfo Root + { + get + { + if (IsFileSystem) + { + if (string.IsNullOrEmpty(_server)) + if (string.IsNullOrEmpty(_path)) + return new DirectoryInfo(ToString()); + else + return new DirectoryInfo(_path); + return new DirectoryInfo(ToString()); + } + return null; + } + } + + #endregion + + /// <summary> + /// Returns the path to this share + /// </summary> + /// <returns></returns> + public override string ToString() + { + if (string.IsNullOrEmpty(_server)) + { + return string.Format(@"\\{0}\{1}", Environment.MachineName, _netName); + } + return string.Format(@"\\{0}\{1}", _server, _netName); + } + + /// <summary> + /// Returns true if this share matches the local path + /// </summary> + /// <param name="path"></param> + /// <returns></returns> + public bool MatchesPath(string path) + { + if (!IsFileSystem) return false; + if (string.IsNullOrEmpty(path)) return true; + + return path.ToLower().StartsWith(_path.ToLower()); + } + } + + #endregion + + /// <summary> + /// A collection of shares + /// </summary> + public class ShareCollection : ReadOnlyCollectionBase + { + #region Platform + + /// <summary> + /// Is this an NT platform? + /// </summary> + protected static bool IsNT + { + get { return (PlatformID.Win32NT == Environment.OSVersion.Platform); } + } + + /// <summary> + /// Returns true if this is Windows 2000 or higher + /// </summary> + protected static bool IsW2KUp + { + get + { + OperatingSystem os = Environment.OSVersion; + if (PlatformID.Win32NT == os.Platform && os.Version.Major >= 5) + return true; + else + return false; + } + } + + #endregion + + #region Interop + + #region Constants + + /// <summary>Maximum path length</summary> + protected const int MAX_PATH = 260; + /// <summary>No error</summary> + protected const int NO_ERROR = 0; + /// <summary>Access denied</summary> + protected const int ERROR_ACCESS_DENIED = 5; + /// <summary>Access denied</summary> + protected const int ERROR_WRONG_LEVEL = 124; + /// <summary>More data available</summary> + protected const int ERROR_MORE_DATA = 234; + /// <summary>Not connected</summary> + protected const int ERROR_NOT_CONNECTED = 2250; + /// <summary>Level 1</summary> + protected const int UNIVERSAL_NAME_INFO_LEVEL = 1; + /// <summary>Max extries (9x)</summary> + protected const int MAX_SI50_ENTRIES = 20; + + #endregion + + #region Structures + + /// <summary>Unc name</summary> + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + protected struct UNIVERSAL_NAME_INFO + { + [MarshalAs(UnmanagedType.LPTStr)] + public string lpUniversalName; + } + + /// <summary>Share information, NT, level 2</summary> + /// <remarks> + /// Requires admin rights to work. + /// </remarks> + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + protected struct SHARE_INFO_2 + { + [MarshalAs(UnmanagedType.LPWStr)] + public string NetName; + public ShareType ShareType; + [MarshalAs(UnmanagedType.LPWStr)] + public string Remark; + public int Permissions; + public int MaxUsers; + public int CurrentUsers; + [MarshalAs(UnmanagedType.LPWStr)] + public string Path; + [MarshalAs(UnmanagedType.LPWStr)] + public string Password; + } + + /// <summary>Share information, NT, level 1</summary> + /// <remarks> + /// Fallback when no admin rights. + /// </remarks> + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + protected struct SHARE_INFO_1 + { + [MarshalAs(UnmanagedType.LPWStr)] + public string NetName; + public ShareType ShareType; + [MarshalAs(UnmanagedType.LPWStr)] + public string Remark; + } + + /// <summary>Share information, Win9x</summary> + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + protected struct SHARE_INFO_50 + { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 13)] + public string NetName; + + public byte bShareType; + public ushort Flags; + + [MarshalAs(UnmanagedType.LPTStr)] + public string Remark; + [MarshalAs(UnmanagedType.LPTStr)] + public string Path; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)] + public string PasswordRW; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)] + public string PasswordRO; + + public ShareType ShareType + { + get { return (ShareType)((int)bShareType & 0x7F); } + } + } + + /// <summary>Share information level 1, Win9x</summary> + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + protected struct SHARE_INFO_1_9x + { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 13)] + public string NetName; + public byte Padding; + + public ushort bShareType; + + [MarshalAs(UnmanagedType.LPTStr)] + public string Remark; + + public ShareType ShareType + { + get { return (ShareType)((int)bShareType & 0x7FFF); } + } + } + + #endregion + + #region Functions + + /// <summary>Get a UNC name</summary> + [DllImport("mpr", CharSet = CharSet.Auto)] + protected static extern int WNetGetUniversalName(string lpLocalPath, + int dwInfoLevel, ref UNIVERSAL_NAME_INFO lpBuffer, ref int lpBufferSize); + + /// <summary>Get a UNC name</summary> + [DllImport("mpr", CharSet = CharSet.Auto)] + protected static extern int WNetGetUniversalName(string lpLocalPath, + int dwInfoLevel, IntPtr lpBuffer, ref int lpBufferSize); + + /// <summary>Enumerate shares (NT)</summary> + [DllImport("netapi32", CharSet = CharSet.Unicode)] + protected static extern int NetShareEnum(string lpServerName, int dwLevel, + out IntPtr lpBuffer, int dwPrefMaxLen, out int entriesRead, + out int totalEntries, ref int hResume); + + /// <summary>Enumerate shares (9x)</summary> + [DllImport("svrapi", CharSet = CharSet.Ansi)] + protected static extern int NetShareEnum( + [MarshalAs(UnmanagedType.LPTStr)] string lpServerName, int dwLevel, + IntPtr lpBuffer, ushort cbBuffer, out ushort entriesRead, + out ushort totalEntries); + + /// <summary>Free the buffer (NT)</summary> + [DllImport("netapi32")] + protected static extern int NetApiBufferFree(IntPtr lpBuffer); + + #endregion + + #region Enumerate shares + + /// <summary> + /// Enumerates the shares on Windows NT + /// </summary> + /// <param name="server">The server name</param> + /// <param name="shares">The ShareCollection</param> + protected static void EnumerateSharesNT(string server, ShareCollection shares) + { + int level = 2; + int entriesRead, totalEntries, nRet, hResume = 0; + IntPtr pBuffer = IntPtr.Zero; + + try + { + nRet = NetShareEnum(server, level, out pBuffer, -1, + out entriesRead, out totalEntries, ref hResume); + + if (ERROR_ACCESS_DENIED == nRet) + { + //Need admin for level 2, drop to level 1 + level = 1; + nRet = NetShareEnum(server, level, out pBuffer, -1, + out entriesRead, out totalEntries, ref hResume); + } + + if (NO_ERROR == nRet && entriesRead > 0) + { + Type t = (2 == level) ? typeof(SHARE_INFO_2) : typeof(SHARE_INFO_1); + int offset = Marshal.SizeOf(t); + + for (int i = 0, lpItem = pBuffer.ToInt32(); i < entriesRead; i++, lpItem += offset) + { + IntPtr pItem = new IntPtr(lpItem); + if (1 == level) + { + SHARE_INFO_1 si = (SHARE_INFO_1)Marshal.PtrToStructure(pItem, t); + shares.Add(si.NetName, string.Empty, si.ShareType, si.Remark); + } + else + { + SHARE_INFO_2 si = (SHARE_INFO_2)Marshal.PtrToStructure(pItem, t); + shares.Add(si.NetName, si.Path, si.ShareType, si.Remark); + } + } + } + + } + finally + { + // Clean up buffer allocated by system + if (IntPtr.Zero != pBuffer) + NetApiBufferFree(pBuffer); + } + } + + /// <summary> + /// Enumerates the shares on Windows 9x + /// </summary> + /// <param name="server">The server name</param> + /// <param name="shares">The ShareCollection</param> + protected static void EnumerateShares9x(string server, ShareCollection shares) + { + int level = 50; + int nRet = 0; + ushort entriesRead, totalEntries; + + Type t = typeof(SHARE_INFO_50); + int size = Marshal.SizeOf(t); + ushort cbBuffer = (ushort)(MAX_SI50_ENTRIES * size); + //On Win9x, must allocate buffer before calling API + IntPtr pBuffer = Marshal.AllocHGlobal(cbBuffer); + + try + { + nRet = NetShareEnum(server, level, pBuffer, cbBuffer, + out entriesRead, out totalEntries); + + if (ERROR_WRONG_LEVEL == nRet) + { + level = 1; + t = typeof(SHARE_INFO_1_9x); + size = Marshal.SizeOf(t); + + nRet = NetShareEnum(server, level, pBuffer, cbBuffer, + out entriesRead, out totalEntries); + } + + if (NO_ERROR == nRet || ERROR_MORE_DATA == nRet) + { + for (int i = 0, lpItem = pBuffer.ToInt32(); i < entriesRead; i++, lpItem += size) + { + IntPtr pItem = new IntPtr(lpItem); + + if (1 == level) + { + SHARE_INFO_1_9x si = (SHARE_INFO_1_9x)Marshal.PtrToStructure(pItem, t); + shares.Add(si.NetName, string.Empty, si.ShareType, si.Remark); + } + else + { + SHARE_INFO_50 si = (SHARE_INFO_50)Marshal.PtrToStructure(pItem, t); + shares.Add(si.NetName, si.Path, si.ShareType, si.Remark); + } + } + } + else + Console.WriteLine(nRet); + + } + finally + { + //Clean up buffer + Marshal.FreeHGlobal(pBuffer); + } + } + + /// <summary> + /// Enumerates the shares + /// </summary> + /// <param name="server">The server name</param> + /// <param name="shares">The ShareCollection</param> + protected static void EnumerateShares(string server, ShareCollection shares) + { + if (null != server && 0 != server.Length && !IsW2KUp) + { + server = server.ToUpper(); + + // On NT4, 9x and Me, server has to start with "\\" + if (!('\\' == server[0] && '\\' == server[1])) + server = @"\\" + server; + } + + if (IsNT) + EnumerateSharesNT(server, shares); + else + EnumerateShares9x(server, shares); + } + + #endregion + + #endregion + + #region Static methods + + /// <summary> + /// Returns true if fileName is a valid local file-name of the form: + /// X:\, where X is a drive letter from A-Z + /// </summary> + /// <param name="fileName">The filename to check</param> + /// <returns></returns> + public static bool IsValidFilePath(string fileName) + { + if (null == fileName || 0 == fileName.Length) return false; + + char drive = char.ToUpper(fileName[0]); + if ('A' > drive || drive > 'Z') + return false; + + else if (Path.VolumeSeparatorChar != fileName[1]) + return false; + else if (Path.DirectorySeparatorChar != fileName[2]) + return false; + else + return true; + } + + #endregion + + /// <summary>The name of the server this collection represents</summary> + private string _server; + + #region Constructor + + /// <summary> + /// Default constructor - local machine + /// </summary> + public ShareCollection() + { + _server = string.Empty; + EnumerateShares(_server, this); + } + + /// <summary> + /// Constructor + /// </summary> + /// <param name="Server"></param> + public ShareCollection(string server) + { + _server = server; + EnumerateShares(_server, this); + } + + #endregion + + #region Add + + protected void Add(Share share) + { + InnerList.Add(share); + } + + protected void Add(string netName, string path, ShareType shareType, string remark) + { + InnerList.Add(new Share(_server, netName, path, shareType, remark)); + } + + #endregion + + #region Properties + + /// <summary> + /// Returns the name of the server this collection represents + /// </summary> + public string Server + { + get { return _server; } + } + + /// <summary> + /// Returns the <see cref="Share"/> at the specified index. + /// </summary> + public Share this[int index] + { + get { return (Share)InnerList[index]; } + } + + /// <summary> + /// Returns the <see cref="Share"/> which matches a given local path + /// </summary> + /// <param name="path">The path to match</param> + public Share this[string path] + { + get + { + if (null == path || 0 == path.Length) return null; + + path = Path.GetFullPath(path); + if (!IsValidFilePath(path)) return null; + + Share match = null; + + for (int i = 0; i < InnerList.Count; i++) + { + Share s = (Share)InnerList[i]; + + if (s.IsFileSystem && s.MatchesPath(path)) + { + //Store first match + if (null == match) + match = s; + + // If this has a longer path, + // and this is a disk share or match is a special share, + // then this is a better match + else if (match.Path.Length < s.Path.Length) + { + if (ShareType.Disk == s.ShareType || ShareType.Disk != match.ShareType) + match = s; + } + } + } + + return match; + } + } + + #endregion + + /// <summary> + /// Copy this collection to an array + /// </summary> + /// <param name="array"></param> + /// <param name="index"></param> + public void CopyTo(Share[] array, int index) + { + InnerList.CopyTo(array, index); + } + } +}
\ No newline at end of file diff --git a/MediaBrowser.Networking/MediaBrowser.Networking.csproj b/MediaBrowser.Networking/MediaBrowser.Networking.csproj index 40ec81db3..194f9e400 100644 --- a/MediaBrowser.Networking/MediaBrowser.Networking.csproj +++ b/MediaBrowser.Networking/MediaBrowser.Networking.csproj @@ -32,6 +32,7 @@ <ItemGroup> <Reference Include="System" /> <Reference Include="System.Core" /> + <Reference Include="System.Management" /> <Reference Include="System.Xml.Linq" /> <Reference Include="System.Data.DataSetExtensions" /> <Reference Include="Microsoft.CSharp" /> @@ -42,8 +43,21 @@ <Compile Include="..\SharedVersion.cs"> <Link>Properties\SharedVersion.cs</Link> </Compile> + <Compile Include="Management\NativeMethods.cs" /> + <Compile Include="Management\NetworkManager.cs" /> + <Compile Include="Management\NetworkShares.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj"> + <Project>{9142eefa-7570-41e1-bfcc-468bb571af2f}</Project> + <Name>MediaBrowser.Common</Name> + </ProjectReference> + <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj"> + <Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project> + <Name>MediaBrowser.Model</Name> + </ProjectReference> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <PropertyGroup> <PostBuildEvent>xcopy "$(TargetPath)" "$(SolutionDir)\Nuget\dlls\" /y /d /r /i</PostBuildEvent> |
