Files
LIAM/LiamFileshare/C4IT.LIAM.Fileshare.cs
Drechsler, Meik f563d78417 initial
2025-10-15 14:56:07 +02:00

554 lines
16 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using C4IT.Logging;
using static C4IT.Logging.cLogManager;
namespace C4IT.LIAM
{
public static class LiamInitializer
{
static public cLiamProviderBase CreateInstance(cLiamConfiguration LiamConfiguration, cLiamProviderData ProviderData)
{
return new cLiamProviderFileshare(LiamConfiguration, ProviderData);
}
}
public class cLiamProviderFileshare : cLiamProviderBase
{
public readonly cFile MsSharepoint = new cMsGraphSharepoint(new cMsGraphBase());
public Exception LastException { get; private set; } = null;
public string LastErrorMessage { get; private set; } = null;
public bool IsOnline { get; private set; } = false;
public string AccessToken { get; private set; } = null;
public DateTime TokenExpiresIn { get; private set; } = DateTime.MinValue;
private cFileshareLogonInfo privLogonInfo = null;
public cLiamProviderFileshare(cLiamConfiguration LiamConfiguration, cLiamProviderData ProviderData) :
base(LiamConfiguration, ProviderData)
{ }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ResetError()
{
LastException = null;
LastErrorMessage = null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetErrorException(string Action, Exception E, LogLevels lev = LogLevels.Error)
{
LastException = E;
LastErrorMessage = Action + ": " + E.Message;
cLogManager.LogEntry(Action, lev);
}
public override async Task<cLiamDataAreaBase> LoadDataArea(string UID)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
await Task.Delay(0);
try
{
var lstIds = UID.Split('|');
return null;
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
public override async Task<List<cLiamDataAreaBase>> getDataAreasAsync(int Depth = -1)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
if (!await LogonAsync())
return null;
var DataAreas = new List<cLiamDataAreaBase>();
var DAL = await MsSharepoint.RequestTeamsListAsync();
if (DAL == null)
return null;
foreach (var Entry in DAL)
{
if (!string.IsNullOrEmpty(this.DataAreaRegEx) && !Regex.Match(Entry.Key, this.DataAreaRegEx).Success)
continue;
var MsTeam = await MsSharepoint.RequestGroupInfoAsync(Entry.Value);
if (MsTeam == null)
continue;
var Team = new cLiamMsTeamsTeam(this, MsTeam);
DataAreas.Add(Team);
}
if (Depth > 0)
{
var allChilds = new List<cLiamDataAreaBase>();
foreach (var Entry in DataAreas)
{
var entryChilds = await (Entry as cLiamMsTeamsTeam).getChannels(true);
if (entryChilds != null && entryChilds.Count > 0)
allChilds.AddRange(entryChilds);
}
DataAreas.AddRange(allChilds);
}
return DataAreas;
}
catch (Exception E)
{
LogException(E);
}
finally
{
LogMethodEnd(CM);
}
return null;
}
public override async Task<bool> LogonAsync()
{
return await LogonAsync(true);
}
public async Task<bool> LogonAsync(bool force = false)
{
if (!force && IsOnline)
return true;
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
var LI = new cFileshareLogonInfo()
{
Domain = this.Domain,
User = this.Credential?.Identification,
UserSecret = this.Credential?.Secret,
TargetNetworkName = this.RootPath
};
var RetVal = await LogonAsync(LI);
return RetVal;
}
catch (Exception E)
{
LogException(E);
}
finally
{
LogMethodEnd(CM);
}
return false;
}
private async Task<bool> privRelogon()
{
if (DateTime.UtcNow < TokenExpiresIn)
return true;
if (privLogonInfo == null)
return false;
var RetVal = await privLogonAsync(privLogonInfo);
return RetVal;
}
public async Task<bool> LogonAsync(cFileshareLogonInfo LogonInfo)
{
var RetVal = await privLogonAsync(LogonInfo);
if (RetVal == true)
privLogonInfo = LogonInfo;
return RetVal;
}
private async Task<bool> privLogonAsync(cFileshareLogonInfo LogonInfo)
{
//TODO: remove dummy delay?
await Task.Delay(0);
try
{
ResetError();
IsOnline = false;
var netResource = new NetResource()
{
Scope = ResourceScope.GlobalNetwork,
ResourceType = ResourceType.Disk,
DisplayType = ResourceDisplaytype.Share,
RemoteName = LogonInfo.TargetNetworkName
};
var result = WNetAddConnection2(
netResource,
LogonInfo.UserSecret,
LogonInfo.User,
0);
if (result != 0)
{
//DefaultLogger.LogEntry(LogLevels.Debug, $"Error in connect occured ({result}) {new Win32Exception(result).Message}");
//throw new Win32Exception(result);
return false;
}
IsOnline = true;
return true;
}
catch (Exception E)
{
SetErrorException("exception error while network drive login", E, LogLevels.Debug);
cLogManager.LogException(E, LogLevels.Debug);
}
return false;
}
[DllImport("mpr.dll")]
private static extern int WNetAddConnection2(NetResource netResource,
string password, string username, int flags);
}
public class cFileshareLogonInfo
{
public string Domain;
public string User;
public string UserSecret;
public string TargetNetworkName;
}
[StructLayout(LayoutKind.Sequential)]
public class NetResource
{
public ResourceScope Scope;
public ResourceType ResourceType;
public ResourceDisplaytype DisplayType;
public int Usage;
public string LocalName;
public string RemoteName;
public string Comment;
public string Provider;
}
public enum ResourceScope : int
{
Connected = 1,
GlobalNetwork,
Remembered,
Recent,
Context
};
public enum ResourceType : int
{
Any = 0,
Disk = 1,
Print = 2,
Reserved = 8,
}
public enum ResourceDisplaytype : int
{
Generic = 0x0,
Domain = 0x01,
Server = 0x02,
Share = 0x03,
File = 0x04,
Group = 0x05,
Network = 0x06,
Root = 0x07,
Shareadmin = 0x08,
Directory = 0x09,
Tree = 0x0a,
Ndscontainer = 0x0b
}
public enum NetError : uint
{
NERR_Success = 0,
NERR_BASE = 2100,
NERR_UnknownDevDir = (NERR_BASE + 16),
NERR_DuplicateShare = (NERR_BASE + 18),
NERR_BufTooSmall = (NERR_BASE + 23),
}
public enum SHARE_TYPE : uint
{
STYPE_DISKTREE = 0,
STYPE_PRINTQ = 1,
STYPE_DEVICE = 2,
STYPE_IPC = 3,
STYPE_SPECIAL = 0x80000000,
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SHARE_INFO_1
{
public string shi1_netname;
public uint shi1_type;
public string shi1_remark;
public SHARE_INFO_1(string sharename, uint sharetype, string remark)
{
this.shi1_netname = sharename;
this.shi1_type = sharetype;
this.shi1_remark = remark;
}
public override string ToString()
{
return shi1_netname;
}
}
public class cLiamNtfsShare : cLiamDataAreaBase
{
public new readonly cLiamProviderFileshare Provider = null;
private readonly cMsGraphResultGroup MsTeam = null;
public cLiamMsTeamsTeam(cLiamProviderMsTeams Provider, cMsGraphResultGroup MsTeam) :
base(Provider)
{
this.Provider = Provider;
this.MsTeam = MsTeam;
this.TechnicalName = MsTeam.DisplayName;
this.Level = 0;
this.UID = getUID(MsTeam.ID);
this.ParentUID = "";
this.DataType = eLiamDataAreaTypes.MsTeamsTeam;
this.SupportsOwners = true;
this.SupportsPermissions = true;
}
internal static string getUID(string TeamID)
{
return $"{TeamID}";
}
internal async Task<List<cLiamDataAreaBase>> getChannels(bool OnlyPrivate)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
if (MsTeam == null)
return null;
var RegExFilter = this.Provider?.DataAreaRegEx;
var SP = this.Provider?.MsSharepoint;
var WithoutPrivateChannels = this.Provider?.WithoutPrivateChannels ?? false;
if (MsTeam.Channels == null)
if (SP == null || !await MsTeam.ResolveChannels(SP, OnlyPrivate))
return null;
var RetVal = new List<cLiamDataAreaBase>(MsTeam.Channels.Count);
foreach (var Entry in MsTeam.Channels.Values)
{
if (!string.IsNullOrEmpty(RegExFilter) && !Regex.Match(Entry.DisplayName, RegExFilter).Success)
continue;
if (WithoutPrivateChannels && !string.IsNullOrEmpty(Entry.MembershipType) && Entry.MembershipType == "private")
continue;
var DA = new cLiamMsTeamsChannel(Provider, this, Entry);
RetVal.Add(DA);
}
return RetVal;
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
public override async Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
var RetVal = await getChannels(false);
if (RetVal != null)
RetVal.AddRange(await getChildrenFromListAsync(RetVal, Depth));
return RetVal;
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
public static async Task<cLiamMsTeamsTeam> Load(cLiamProviderMsTeams Provider, string UID)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
var arrIDs = UID.Split('|');
if (arrIDs.Length != 1)
return null;
var TeamID = cLiamProviderMsTeams.getUidItem(ref UID);
var T = await Provider.MsSharepoint.RequestGroupInfoAsync(TeamID);
if (T == null)
return null;
var RetVal = new cLiamMsTeamsTeam(Provider, T);
return RetVal;
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
}
public class cNtfsResultBase
{
public string ID { get; private set; } = null;
public string DisplayName { get; private set; } = null;
public dynamic Result { get; private set; } = null;
public cNtfsResultBase(dynamic Result)
{
this.Result = Result;
}
public cNtfsResultBase(cNtfsResultBase Result)
{
if (Result == null)
return;
this.Result = Result.Result;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string GetStringFromDynamic(dynamic O, string ProperyName)
{
try
{
return (string)O[ProperyName];
}
catch { }
return null;
}
}
public class cLiamNtfsFolder : cLiamDataAreaBase
{
public new readonly cLiamProviderFileshare Provider = null;
public readonly cLiamNtfsShare Share = null;
public readonly cMsGraphResultFileObject MsFolder = null;
public override async Task<List<cLiamDataAreaBase>> getChildrenAsync(int Depth = -1)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
if (MsFolder == null)
return null;
var RegExFilter = this.Provider?.DataAreaRegEx;
var SP = this.Provider?.MsSharepoint;
if (MsFolder.Folders == null)
if (SP == null || !await MsFolder.ResolveFolders(SP))
return null;
var DataAreas = new List<cLiamDataAreaBase>();
foreach (var Entry in MsFolder.Folders.Values)
{
if (!string.IsNullOrEmpty(RegExFilter) && !Regex.Match(Entry.DisplayName, RegExFilter).Success)
continue;
var DA = new cLiamMsTeamsFolder(this.Provider, this.Channel, this, Entry, this.ChannelUID);
DataAreas.Add(DA);
}
var CL = await getChildrenFromListAsync(DataAreas, Depth);
if (CL != null)
DataAreas.AddRange(CL);
return DataAreas;
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
public static async Task<cLiamMsTeamsFolder> Load(cLiamProviderMsTeams Provider, string UID)
{
var CM = MethodBase.GetCurrentMethod();
LogMethodBegin(CM);
try
{
var arrIDs = UID.Split('|');
if (arrIDs.Length != 4)
return null;
var FolderID = cLiamProviderMsTeams.getUidItem(ref UID);
var DriveID = cLiamProviderMsTeams.getUidItem(ref UID);
var F = await Provider.MsSharepoint.RequestFileObjectInfo(DriveID, FolderID);
if (F == null)
return null;
var RetVal = new cLiamMsTeamsFolder(Provider, null, null, F, UID);
return RetVal;
}
catch (Exception E)
{
LogException(E);
return null;
}
finally
{
LogMethodEnd(CM);
}
}
}
}