aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/IO/SharpCifs/Smb/SmbTree.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations/IO/SharpCifs/Smb/SmbTree.cs')
-rw-r--r--Emby.Server.Implementations/IO/SharpCifs/Smb/SmbTree.cs250
1 files changed, 250 insertions, 0 deletions
diff --git a/Emby.Server.Implementations/IO/SharpCifs/Smb/SmbTree.cs b/Emby.Server.Implementations/IO/SharpCifs/Smb/SmbTree.cs
new file mode 100644
index 000000000..8dc068c4c
--- /dev/null
+++ b/Emby.Server.Implementations/IO/SharpCifs/Smb/SmbTree.cs
@@ -0,0 +1,250 @@
+// This code is derived from jcifs smb client library <jcifs at samba dot org>
+// Ported by J. Arturo <webmaster at komodosoft dot net>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+using System;
+using SharpCifs.Util.Sharpen;
+
+namespace SharpCifs.Smb
+{
+ class SmbTree
+ {
+ private static int _treeConnCounter;
+
+ internal int ConnectionState;
+
+ internal int Tid;
+
+ internal string Share;
+
+ internal string Service = "?????";
+
+ internal string Service0;
+
+ internal SmbSession Session;
+
+ internal bool InDfs;
+
+ internal bool InDomainDfs;
+
+ internal int TreeNum;
+
+ internal SmbTree(SmbSession session, string share, string service)
+ {
+ // used by SmbFile.isOpen
+ this.Session = session;
+ this.Share = share.ToUpper();
+ if (service != null && service.StartsWith("??") == false)
+ {
+ this.Service = service;
+ }
+ Service0 = this.Service;
+ ConnectionState = 0;
+ }
+
+ internal virtual bool Matches(string share, string service)
+ {
+ return Runtime.EqualsIgnoreCase(this.Share, share) && (service == null ||
+ service.StartsWith("??") || Runtime.EqualsIgnoreCase(this.Service, service
+ ));
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is SmbTree)
+ {
+ SmbTree tree = (SmbTree)obj;
+ return Matches(tree.Share, tree.Service);
+ }
+ return false;
+ }
+
+ /// <exception cref="SharpCifs.Smb.SmbException"></exception>
+ internal virtual void Send(ServerMessageBlock request, ServerMessageBlock response
+ )
+ {
+ lock (Session.Transport())
+ {
+ if (response != null)
+ {
+ response.Received = false;
+ }
+ TreeConnect(request, response);
+ if (request == null || (response != null && response.Received))
+ {
+ return;
+ }
+ if (Service.Equals("A:") == false)
+ {
+ switch (request.Command)
+ {
+ case ServerMessageBlock.SmbComOpenAndx:
+ case ServerMessageBlock.SmbComNtCreateAndx:
+ case ServerMessageBlock.SmbComReadAndx:
+ case ServerMessageBlock.SmbComWriteAndx:
+ case ServerMessageBlock.SmbComClose:
+ case ServerMessageBlock.SmbComTreeDisconnect:
+ {
+ break;
+ }
+
+ case ServerMessageBlock.SmbComTransaction:
+ case ServerMessageBlock.SmbComTransaction2:
+ {
+ switch (((SmbComTransaction)request).SubCommand & unchecked(0xFF))
+ {
+ case SmbComTransaction.NetShareEnum:
+ case SmbComTransaction.NetServerEnum2:
+ case SmbComTransaction.NetServerEnum3:
+ case SmbComTransaction.TransPeekNamedPipe:
+ case SmbComTransaction.TransWaitNamedPipe:
+ case SmbComTransaction.TransCallNamedPipe:
+ case SmbComTransaction.TransTransactNamedPipe:
+ case SmbComTransaction.Trans2GetDfsReferral:
+ {
+ break;
+ }
+
+ default:
+ {
+ throw new SmbException("Invalid operation for " + Service + " service");
+ }
+ }
+ break;
+ }
+
+ default:
+ {
+ throw new SmbException("Invalid operation for " + Service + " service" + request);
+ }
+ }
+ }
+ request.Tid = Tid;
+ if (InDfs && !Service.Equals("IPC") && !string.IsNullOrEmpty(request.Path))
+ {
+ request.Flags2 = SmbConstants.Flags2ResolvePathsInDfs;
+ request.Path = '\\' + Session.Transport().TconHostName + '\\' + Share + request.Path;
+ }
+ try
+ {
+ Session.Send(request, response);
+ }
+ catch (SmbException se)
+ {
+ if (se.GetNtStatus() == NtStatus.NtStatusNetworkNameDeleted)
+ {
+ TreeDisconnect(true);
+ }
+ throw;
+ }
+ }
+ }
+
+ /// <exception cref="SharpCifs.Smb.SmbException"></exception>
+ internal virtual void TreeConnect(ServerMessageBlock andx, ServerMessageBlock andxResponse
+ )
+ {
+ lock (Session.Transport())
+ {
+ string unc;
+ while (ConnectionState != 0)
+ {
+ if (ConnectionState == 2 || ConnectionState == 3)
+ {
+ // connected or disconnecting
+ return;
+ }
+ try
+ {
+ Runtime.Wait(Session.transport);
+ }
+ catch (Exception ie)
+ {
+ throw new SmbException(ie.Message, ie);
+ }
+ }
+ ConnectionState = 1;
+ // trying ...
+ try
+ {
+ Session.transport.Connect();
+ unc = "\\\\" + Session.transport.TconHostName + '\\' + Share;
+ Service = Service0;
+ if (Session.transport.Log.Level >= 4)
+ {
+ Session.transport.Log.WriteLine("treeConnect: unc=" + unc + ",service=" + Service
+ );
+ }
+ SmbComTreeConnectAndXResponse response = new SmbComTreeConnectAndXResponse(andxResponse
+ );
+ SmbComTreeConnectAndX request = new SmbComTreeConnectAndX(Session, unc, Service,
+ andx);
+ Session.Send(request, response);
+ Tid = response.Tid;
+ Service = response.Service;
+ InDfs = response.ShareIsInDfs;
+ TreeNum = _treeConnCounter++;
+ ConnectionState = 2;
+ }
+ catch (SmbException se)
+ {
+ // connected
+ TreeDisconnect(true);
+ ConnectionState = 0;
+ throw;
+ }
+ }
+ }
+
+ internal virtual void TreeDisconnect(bool inError)
+ {
+ lock (Session.Transport())
+ {
+ if (ConnectionState != 2)
+ {
+ // not-connected
+ return;
+ }
+ ConnectionState = 3;
+ // disconnecting
+ if (!inError && Tid != 0)
+ {
+ try
+ {
+ Send(new SmbComTreeDisconnect(), null);
+ }
+ catch (SmbException se)
+ {
+ if (Session.transport.Log.Level > 1)
+ {
+ Runtime.PrintStackTrace(se, Session.transport.Log);
+ }
+ }
+ }
+ InDfs = false;
+ InDomainDfs = false;
+ ConnectionState = 0;
+ Runtime.NotifyAll(Session.transport);
+ }
+ }
+
+ public override string ToString()
+ {
+ return "SmbTree[share=" + Share + ",service=" + Service + ",tid=" + Tid + ",inDfs="
+ + InDfs + ",inDomainDfs=" + InDomainDfs + ",connectionState=" + ConnectionState
+ + "]";
+ }
+ }
+}