jellyfin/Emby.Common.Implementations/IO/SharpCifs/Netbios/Name.cs
2017-04-01 20:36:06 -04:00

270 lines
6.5 KiB
C#

// 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 System.Text;
using SharpCifs.Util;
using SharpCifs.Util.Sharpen;
namespace SharpCifs.Netbios
{
public class Name
{
private const int TypeOffset = 31;
private const int ScopeOffset = 33;
private static readonly string DefaultScope = Config.GetProperty("jcifs.netbios.scope"
);
internal static readonly string OemEncoding = Config.GetProperty("jcifs.encoding"
, Runtime.GetProperty("file.encoding"));
public string name;
public string Scope;
public int HexCode;
internal int SrcHashCode;
public Name()
{
}
public Name(string name, int hexCode, string scope)
{
if (name.Length > 15)
{
name = Runtime.Substring(name, 0, 15);
}
this.name = name.ToUpper();
this.HexCode = hexCode;
this.Scope = !string.IsNullOrEmpty(scope) ? scope : DefaultScope;
SrcHashCode = 0;
}
internal virtual int WriteWireFormat(byte[] dst, int dstIndex)
{
// write 0x20 in first byte
dst[dstIndex] = unchecked(0x20);
// write name
try
{
byte[] tmp = Runtime.GetBytesForString(name, OemEncoding
);
int i;
for (i = 0; i < tmp.Length; i++)
{
dst[dstIndex + (2 * i + 1)] = unchecked((byte)(((tmp[i] & unchecked(0xF0))
>> 4) + unchecked(0x41)));
dst[dstIndex + (2 * i + 2)] = unchecked((byte)((tmp[i] & unchecked(0x0F))
+ unchecked(0x41)));
}
for (; i < 15; i++)
{
dst[dstIndex + (2 * i + 1)] = unchecked(unchecked(0x43));
dst[dstIndex + (2 * i + 2)] = unchecked(unchecked(0x41));
}
dst[dstIndex + TypeOffset] = unchecked((byte)(((HexCode & unchecked(0xF0)
) >> 4) + unchecked(0x41)));
dst[dstIndex + TypeOffset + 1] = unchecked((byte)((HexCode & unchecked(0x0F)) + unchecked(0x41)));
}
catch (UnsupportedEncodingException)
{
}
return ScopeOffset + WriteScopeWireFormat(dst, dstIndex + ScopeOffset);
}
internal virtual int ReadWireFormat(byte[] src, int srcIndex)
{
byte[] tmp = new byte[ScopeOffset];
int length = 15;
for (int i = 0; i < 15; i++)
{
tmp[i] = unchecked((byte)(((src[srcIndex + (2 * i + 1)] & unchecked(0xFF))
- unchecked(0x41)) << 4));
tmp[i] |= unchecked((byte)(((src[srcIndex + (2 * i + 2)] & unchecked(0xFF)
) - unchecked(0x41)) & unchecked(0x0F)));
if (tmp[i] != unchecked((byte)' '))
{
length = i + 1;
}
}
try
{
name = Runtime.GetStringForBytes(tmp, 0, length, OemEncoding
);
}
catch (UnsupportedEncodingException)
{
}
HexCode = ((src[srcIndex + TypeOffset] & unchecked(0xFF)) - unchecked(0x41)) << 4;
HexCode |= ((src[srcIndex + TypeOffset + 1] & unchecked(0xFF)) - unchecked(
0x41)) & unchecked(0x0F);
return ScopeOffset + ReadScopeWireFormat(src, srcIndex + ScopeOffset);
}
internal int ReadWireFormatDos(byte[] src, int srcIndex)
{
int length = 15;
byte[] tmp = new byte[length];
Array.Copy(src, srcIndex, tmp, 0, length);
try
{
name = Runtime.GetStringForBytes(tmp, 0, length).Trim();
}
catch (Exception ex)
{
}
HexCode = src[srcIndex + length];
return length + 1;
}
internal virtual int WriteScopeWireFormat(byte[] dst, int dstIndex)
{
if (Scope == null)
{
dst[dstIndex] = unchecked(unchecked(0x00));
return 1;
}
// copy new scope in
dst[dstIndex++] = unchecked((byte)('.'));
try
{
Array.Copy(Runtime.GetBytesForString(Scope, OemEncoding
), 0, dst, dstIndex, Scope.Length);
}
catch (UnsupportedEncodingException)
{
}
dstIndex += Scope.Length;
dst[dstIndex++] = unchecked(unchecked(0x00));
// now go over scope backwards converting '.' to label length
int i = dstIndex - 2;
int e = i - Scope.Length;
int c = 0;
do
{
if (dst[i] == '.')
{
dst[i] = unchecked((byte)c);
c = 0;
}
else
{
c++;
}
}
while (i-- > e);
return Scope.Length + 2;
}
internal virtual int ReadScopeWireFormat(byte[] src, int srcIndex)
{
int start = srcIndex;
int n;
StringBuilder sb;
if ((n = src[srcIndex++] & unchecked(0xFF)) == 0)
{
Scope = null;
return 1;
}
try
{
sb = new StringBuilder(Runtime.GetStringForBytes(src, srcIndex, n, OemEncoding));
srcIndex += n;
while ((n = src[srcIndex++] & unchecked(0xFF)) != 0)
{
sb.Append('.').Append(Runtime.GetStringForBytes(src, srcIndex, n, OemEncoding));
srcIndex += n;
}
Scope = sb.ToString();
}
catch (UnsupportedEncodingException)
{
}
return srcIndex - start;
}
public override int GetHashCode()
{
int result;
result = name.GetHashCode();
result += 65599 * HexCode;
result += 65599 * SrcHashCode;
if (Scope != null && Scope.Length != 0)
{
result += Scope.GetHashCode();
}
return result;
}
public override bool Equals(object obj)
{
Name n;
if (!(obj is Name))
{
return false;
}
n = (Name)obj;
if (Scope == null && n.Scope == null)
{
return name.Equals(n.name) && HexCode == n.HexCode;
}
return name.Equals(n.name) && HexCode == n.HexCode && Scope.Equals(n.Scope);
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
//return "";
string n = name;
// fix MSBROWSE name
if (n == null)
{
n = "null";
}
else
{
if (n[0] == unchecked(0x01))
{
char[] c = n.ToCharArray();
c[0] = '.';
c[1] = '.';
c[14] = '.';
n = new string(c);
}
}
sb.Append(n).Append("<").Append(Hexdump.ToHexString(HexCode, 2)).Append(">");
if (Scope != null)
{
sb.Append(".").Append(Scope);
}
return sb.ToString();
}
}
}