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 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> getDataAreasAsync(int Depth = -1) { var CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); try { if (!await LogonAsync()) return null; var DataAreas = new List(); 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(); 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 LogonAsync() { return await LogonAsync(true); } public async Task 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 privRelogon() { if (DateTime.UtcNow < TokenExpiresIn) return true; if (privLogonInfo == null) return false; var RetVal = await privLogonAsync(privLogonInfo); return RetVal; } public async Task LogonAsync(cFileshareLogonInfo LogonInfo) { var RetVal = await privLogonAsync(LogonInfo); if (RetVal == true) privLogonInfo = LogonInfo; return RetVal; } private async Task 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> 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(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> 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 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> 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(); 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 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); } } } }