5using System.Diagnostics;
7using System.IO.Compression;
10using System.Reflection;
11using System.Runtime.ExceptionServices;
14using System.Threading;
15using System.Threading.Tasks;
219 private const string Ip2LocalizationPackageName =
"IP2LOCATION-LITE-DB5.CSV";
222 private static Calibration calibration;
223 private readonly
static Stopwatch clock = CreateWatch();
224 private static readonly
byte[] iotBrokerPackagePublicKey =
System.Convert.FromBase64String(
"BRb026TgJ5L1t6T5jWL23m0BQHg1kUNY308V8ixlqmNN8nrPDzB3tTygDylyzjmDCFgWSf7OyUWA");
227 internal const string AutoInstallDelayParameterName =
"Autoinstall.DelayMin";
228 internal const string AutoInstallContentOnlyParameterName =
"Autoinstall.ContentOnly";
229 internal const string AutoInstallTimeParameterName =
"Autoinstall.Time";
231 private readonly Dictionary<CaseInsensitiveString, WebNode> webNodes =
new Dictionary<CaseInsensitiveString, WebNode>();
232 private readonly SortedDictionary<string, LinkedList<IAdminCommand>> adminCommands =
new SortedDictionary<string, LinkedList<IAdminCommand>>();
233 private readonly Dictionary<CaseInsensitiveString, RoomInfo> mucRooms =
new Dictionary<CaseInsensitiveString, RoomInfo>();
237 private Dictionary<string, bool> vulnerableResources =
null;
288 private QR qr =
null;
302 private AddNote addNote =
null;
306 private Vault vault =
null;
311 private Buckets performanceStatistics =
null;
312 private Timer sampleTimer =
null;
314 private static string appData =
string.Empty;
315 private static string appDataDrive =
null;
316 internal static DateTime autoUpdateTP = DateTime.MinValue;
333 if (!
string.IsNullOrEmpty(appData))
334 appDataDrive = Path.GetPathRoot(appData);
338 OsTime.AssociatedObjectValue is TimeSpan TimeSinceOsStart)
341 double CurrentOsStartTime = TimeSinceOsStart.TotalSeconds;
343 if (CurrentOsStartTime < LastOsStartTime)
345 string Unit =
"seconds";
346 double d = CurrentOsStartTime;
374 Log.
Alert(
"Operating System restarted " +
384 DateTime
Now = DateTime.Now;
386 this.performanceStatistics =
new Buckets(TP,
new Duration(
false, 0, 0, 0, 0, 1, 0),
false,
true,
true);
389 int UntilNext = (int)((TP.AddSeconds(1) -
Now).TotalMilliseconds + 0.5);
394 this.sampleTimer =
new Timer(this.SampleTimerEventHandler,
null, UntilNext, 1000);
403 LoginAuditor.AnnotateEndpoint += this.LoginAuditor_AnnotateEndpoint;
405 List<string> Ip4DnsBlackLists =
new List<string>();
406 List<string> Ip6DnsBlackLists =
new List<string>();
410 XmlDocument Doc =
XML.
LoadFromFile(Path.Combine(appData,
"DNSBL.xml"));
412 XSL.
Validate(
"DNSBL", Doc,
"BlackLists",
"http://waher.se/Schema/DNSBL.xsd",
415 foreach (XmlNode N
in Doc.DocumentElement.ChildNodes)
417 if (N is XmlElement E && E.LocalName ==
"BlackList")
420 if (!
string.IsNullOrEmpty(s))
421 Ip4DnsBlackLists.Add(s);
424 if (!
string.IsNullOrEmpty(s))
425 Ip6DnsBlackLists.Add(s);
434 List<SpfExpression> SpfExpressions =
new List<SpfExpression>();
440 XSL.
Validate(
"SPF", Doc,
"SpfRecords",
"http://waher.se/Schema/SPF.xsd",
443 foreach (XmlNode N
in Doc.DocumentElement.ChildNodes)
445 if (N is XmlElement E && E.LocalName ==
"SpfRecord")
449 bool IncludeSubdomains =
XML.
Attribute(E,
"includeSubdomains",
false);
463 XmlDocument Doc =
XML.
LoadFromFile(Path.Combine(appData,
"StopWords.xml"));
465 foreach (XmlNode N
in Doc.DocumentElement.ChildNodes)
467 if (N is XmlElement E && E.LocalName ==
"Language")
469 foreach (XmlNode N2
in E.ChildNodes)
471 if (N2 is XmlElement E2 && E2.LocalName ==
"Stopword")
477 string[] StopWords2 =
new string[StopWords.TokenCounts.Count];
478 StopWords.TokenCounts.Keys.CopyTo(StopWords2, 0);
487 IoTBroker.Legal.Identity.Iso3166.Load();
488 IoTBroker.Legal.Identity.PersonalNumberSchemes.Load();
489 IoTBroker.Legal.Identity.PhoneCountryCodes.Load();
491 Encoding.RegisterProvider(
new CodePages());
493 #region Upgrading internal database
501 Log.
Notice(
"Upgrading to DB Generation " + DbGen.ToString() +
".");
511 object[] FindParameters =
new object[] { 0,
int.MaxValue,
new FilterAnd(), Array.Empty<
string>() };
513 object Obj = MI.Invoke(
null, FindParameters);
516 if (Obj is IEnumerable Objects)
521 foreach (
object Object in Objects)
547 Ip6DnsBlackLists.ToArray(), SpfExpressions.ToArray());
552 "SMTP Server Log %YEAR%-%MONTH%-%DAY%T%HOUR%.xml", appData +
"Transforms" + Path.DirectorySeparatorChar +
"SnifferXmlToHtml.xslt",
555 this.smtpServer.SmtpSnifferPath = appData +
"SMTP" + Path.DirectorySeparatorChar +
556 "%ENDPOINT%" + Path.DirectorySeparatorChar +
"SMTP Server Log %YEAR%-%MONTH%-%DAY%T%HOUR%.xml";
565 Dictionary<int, KeyValuePair<ClientCertificates, bool>> PortSpecificMTlsSettings =
new Dictionary<int, KeyValuePair<ClientCertificates, bool>>();
570 foreach (
int Port in FtpPorts.Join(FtpsPorts).Join(FtpDataPorts))
573 PortSpecificMTlsSettings[
Port] =
new KeyValuePair<ClientCertificates, bool>(ClientCertificate, TrustClientCertificates);
579 this.persistenceLayer);
584 "FTP Server Log %YEAR%-%MONTH%-%DAY%T%HOUR%.xml", appData +
"Transforms" + Path.DirectorySeparatorChar +
"SnifferXmlToHtml.xslt",
594 Gateway.
Certificate, !(Gateway.Certificate is
null), this.persistenceLayer, this.smtpServer, this.httpServer);
596 this.xmppServer.GetParentConnection += (sender, e) =>
599 return Task.CompletedTask;
604 this.xmppServer.ClientConnectionAdded += this.XmppServer_ClientConnectionAdded;
605 this.xmppServer.ClientConnectionRemoved += this.XmppServer_ClientConnectionRemoved;
606 this.xmppServer.ClientConnectionUpdated += this.XmppServer_ClientConnectionUpdated;
607 this.xmppServer.ServerConnectionAdded += this.XmppServer_ServerConnectionAdded;
608 this.xmppServer.ServerConnectionRemoved += this.XmppServer_ServerConnectionRemoved;
609 this.xmppServer.ServerConnectionUpdated += this.XmppServer_ServerConnectionUpdated;
611 Gateway.ConcentratorServer.SensorServer.AssignAuthority += this.SensorServer_AssignAuthority;
614 ContractsClient.GetLocalSchema += this.ContractsClient_GetLocalSchema;
615 ContractsClient.ValidateLocalSignature += this.ContractsClient_ValidateLocalSignature;
616 ContractsClient.GetLocalPublicKey += this.ContractsClient_GetLocalPublicKey;
618 #region Neuro-Foundation V1 handlers
625 #region IEEE V1 handlers
640 this.persistenceLayer.Server = this.xmppServer;
642 this.pubSubComponent = await
PubSubComponent.
Create(this.xmppServer,
"pubsub",
"Publish/Subscribe service");
644 this.eventLogComponent =
new EventLogComponent(this.xmppServer,
"log",
"Event Log");
646 this.geoComponent =
new GeoSpatialComponent(this.xmppServer,
"geo",
"Geo-Spatial information");
647 this.provisioningComponent =
new ProvisioningComponent(this.xmppServer,
"provisioning",
"Thing Registry and Provisioning Server", this.geoComponent);
648 this.legalComponent =
new LegalComponent(this.xmppServer,
"legal",
"Smart Contracts", this.httpServer, Path.Combine(
Gateway.
AppDataFolder,
"Attachments"),
null,
this.pubSubComponent,
this.geoComponent);
649 this.eDalerComponent =
new EDalerComponent(this.xmppServer,
"edaler",
"eDaler", this.legalComponent);
650 this.legalComponent.EDaler = this.eDalerComponent;
652 await this.geoComponent.Load();
656 if (Socks5Ports.Length > 0)
657 this.socks5Component =
new Socks5Component(this.xmppServer,
"socks5", Socks5Ports[0]);
660 if (File.Exists(FileName))
664 s = File.ReadAllText(FileName);
666 Dictionary<string, bool> VulnerableResources =
new Dictionary<string, bool>(StringComparer.InvariantCultureIgnoreCase);
670 if (Resource.StartsWith(
"/"))
671 VulnerableResources[Resource[1..]] =
true;
674 this.vulnerableResources = VulnerableResources;
676 Gateway.Root.FileNotFound += this.CheckForHoneyPotResources;
688 if (!(this.httpServer is
null))
737 TimeSpan.FromSeconds(30),
false,
739 this.chatFile = this.httpServer.
Register(
"/ChatFile", this.ChatFileDownload,
false,
true);
740 this.httpxServer =
new HttpxServer(this.xmppServer, this.httpServer, 8192);
745 if (!(this.httpServer.
Sniffers is
null))
748 "XMPP Server Log %YEAR%-%MONTH%-%DAY%T%HOUR%.xml", appData +
"Transforms" + Path.DirectorySeparatorChar +
"SnifferXmlToHtml.xslt",
751 this.xmppServer.ClientSnifferPath = appData +
"XMPP_C2S" + Path.DirectorySeparatorChar +
752 "%ENDPOINT%" + Path.DirectorySeparatorChar +
"XMPP Server Log %YEAR%-%MONTH%-%DAY%T%HOUR%.xml";
755 "XMPP Server Log %YEAR%-%MONTH%-%DAY%T%HOUR%.xml", appData +
"Transforms" + Path.DirectorySeparatorChar +
"SnifferXmlToHtml.xslt",
758 this.xmppServer.DomainSnifferPath = appData +
"XMPP_S2S" + Path.DirectorySeparatorChar +
759 "%DOMAIN%" + Path.DirectorySeparatorChar +
"XMPP Server Log %YEAR%-%MONTH%-%DAY%T%HOUR%.xml";
762 bool Encrypted =
true;
764 if (
Ports.Length == 0)
770 if (
Ports.Length > 0)
772 StringBuilder Url =
new StringBuilder();
786 Url.Append(
Port.ToString());
794 Url.Append(
Port.ToString());
798 string Root = Url.ToString();
800 Url.Append(
"/HttpUpload");
804 MaxFileSize = 1024 * 1024 * 20,
805 MaxFilesPerMinute = 10,
806 MaxBytesPerMinute = 1024 * 1024 * 50,
807 FileLifetime = TimeSpan.FromMinutes(10),
808 FileFolder = Path.Combine(appData,
"HttpUpload"),
809 HttpFolder = Url.ToString(),
812 EncryptedStorageFolder = Path.Combine(appData,
"EncryptedStorage"),
813 EncryptedStorageRoot = Root +
"/EncryptedStorage",
814 InternalTransferFolder = Path.Combine(appData,
"InternalTransfer"),
815 InternalTransferRoot = Root +
"/InternalTransfer",
816 PubSubStorageFolder = Path.Combine(appData,
"PubSubStorage"),
817 PubSubStorageRoot = Root +
"/PubSubStorage"
820 this.httpFileUploadComponent =
new HttpFileUploadComponent(this.xmppServer,
"upload", this.httpFileUploadSettings);
821 this.httpFileUploadResource =
new XmppFileUploadResource(
"/HttpUpload", this.httpFileUploadComponent, Encrypted);
825 this.httpServer.
Register(this.httpFileUploadResource);
826 this.httpServer.
Register(this.httpEncryptedFileUploadResource);
827 this.httpServer.
Register(this.httpPubSubFileUploadResource);
828 this.httpServer.
Register(this.httpInternalTransferUploadResource);
830 Export.OnExportFolderUpdated += this.Export_OnExportFolderUpdated;
831 Export.OnExportKeyFolderUpdated += this.Export_OnExportKeyFolderUpdated;
840 this.ssoTokens ??=
new Cache<string, string>(
int.MaxValue, TimeSpan.FromMinutes(30), TimeSpan.FromMinutes(5));
843 ProxyResource.BeforeForwardRequest += this.ProxyResource_AddSsoInformationEncrypted;
845 ProxyResource.BeforeForwardRequest += this.ProxyResource_AddSsoInformationUnencrypted;
850 await this.DeleteOldItems();
852 Gateway.OnNewCertificate += this.Gateway_OnNewCertificate;
873 await this.CheckRegistration();
876 Gateway.ProvisioningClient.ManagePresenceSubscriptionRequests =
false;
880 Gateway.SoftwareUpdateClient.OnSoftwareUpdated += this.SoftwareUpdateClient_OnSoftwareUpdated;
881 Gateway.SoftwareUpdateClient.OnSoftwareValidation += this.SoftwareUpdateClient_OnSoftwareValidation;
882 Gateway.SoftwareUpdateClient.OnSoftwareDownloaded += this.SoftwareUpdateClient_OnSoftwareDownloaded;
883 Gateway.SoftwareUpdateClient.OnSoftwareDeleted += this.SoftwareUpdateClient_OnSoftwareDeleted;
884 Gateway.SoftwareUpdateClient.OnDownloadedSoftwareDeleted += this.SoftwareUpdateClient_OnDownloadedSoftwareDeleted;
887 Gateway.XmppClient.OnStateChanged += this.XmppClient_OnStateChanged;
888 Gateway.XmppClient.OnChatMessage += this.XmppClient_OnChatMessage;
892 Gateway.XmppClient.OnGroupChatMessage += this.XmppClient_OnGroupChatMessage;
893 Gateway.XmppClient.OnValidateSender += this.XmppClient_OnValidateSender;
895 Gateway.MucClient.RoomInvitationReceived += this.MucClient_RoomInvitationReceived;
896 Gateway.MucClient.DirectInvitationReceived += this.MucClient_DirectInvitationReceived;
897 Gateway.MucClient.OccupantPresence += this.MucClient_OccupantPresence;
898 Gateway.MucClient.PrivateMessageReceived += this.MucClient_PrivateMessageReceived;
899 Gateway.MucClient.RoomDestroyed += this.MucClient_RoomDestroyed;
901 await this.LoadPermanentRooms();
907 if (TP > DateTime.MinValue)
910 StringBuilder sb =
new StringBuilder();
911 SortedDictionary<string, bool> AlphabeticalOrder =
new SortedDictionary<string, bool>();
914 AlphabeticalOrder[A.FullName] =
true;
916 foreach (
string Name
in AlphabeticalOrder.Keys)
921 bool Updated = H != H2;
929 sb.Append(
"XMPP server at [`");
931 sb.Append(
"`](http://");
936 sb.Append(
"updated and ");
938 sb.Append(
"restarted at ");
939 sb.Append(
Now.ToShortDateString());
941 sb.Append(
Now.ToLongTimeString());
945 sb.Append(
" [Release Notes](https://lab.tagroot.io/ReleaseNotes)");
960 Gateway.HttpxProxy.PostResource = this.xmppOverHttp;
1006 Gateway.OnTerminate += this.Gateway_OnTerminate;
1008 await CheckFullTestSearchIndices();
1012 catch (Exception ex)
1038 private static async Task CheckFullTestSearchIndices()
1041 "FTS_Identities",
"LegalIdentities");
1046 ReindexIdentities =
true;
1050 "FTS_Contracts",
"Contracts");
1057 ReindexContracts =
true;
1061 "FTS_Tokens",
"NeuroFeatureTokens");
1068 ReindexTokens =
true;
1072 "FTS_Accounts",
"BrokerAccounts");
1089 ReindexAccounts =
true;
1092 if (ReindexIdentities)
1093 await ReindexFullTextSearchIndex(
"FTS_Identities",
"LegalIdentities");
1095 if (ReindexContracts)
1096 await ReindexFullTextSearchIndex(
"FTS_Contracts",
"Contracts");
1099 await ReindexFullTextSearchIndex(
"FTS_Tokens",
"NeuroFeatureTokens");
1101 if (ReindexAccounts)
1102 await ReindexFullTextSearchIndex(
"FTS_Accounts",
"BrokerAccounts");
1105 private static async Task ReindexFullTextSearchIndex(
string IndexName,
string CollectionName)
1109 Log.
Notice(
"Full Text Search Index regenerated.", IndexName,
1110 new KeyValuePair<string, object>(
"Collection", CollectionName),
1111 new KeyValuePair<string, object>(
"Index", IndexName),
1112 new KeyValuePair<string, object>(
"NrObjects", NrObjects));
1115 private async Task SensorServer_AssignAuthority(
object Sender, Networking.XMPP.Events.AuthorityEventArgs e)
1117 if (await IsAdmin(e.BareJid))
1128 private Task Gateway_OnTerminate(
object Sender, EventArgs e)
1130 System.Timers.Timer CheckTimer =
new System.Timers.Timer(80000);
1131 CheckTimer.Elapsed += this.CheckRunningTasks;
1133 System.Timers.Timer CloseTimer =
new System.Timers.Timer(90000);
1134 CloseTimer.Elapsed += this.CloseProcess;
1136 System.Timers.Timer KillTimer =
new System.Timers.Timer(110000);
1137 CloseTimer.Elapsed += this.KillProcess;
1139 return Task.CompletedTask;
1142 private void CheckRunningTasks(
object Sender,
System.Timers.ElapsedEventArgs e)
1147 StringBuilder sb =
new StringBuilder();
1149 sb.AppendLine(
"Active asynchronous processors stopping the service shutdown:");
1164 private void CloseProcess(
object Sender,
System.Timers.ElapsedEventArgs e)
1166 Process.GetCurrentProcess().Close();
1169 private void KillProcess(
object Sender,
System.Timers.ElapsedEventArgs e)
1171 Process.GetCurrentProcess().Kill();
1183 if (s.StartsWith(
"/"))
1186 if (!(this.vulnerableResources?.ContainsKey(s) ??
false))
1192 "Scanning for vulnerable web resources.");
1195 new KeyValuePair<string, object>(
"Blocked", Blocked));
1198 await Task.Delay(60000);
1203 if (Content is
null)
1207 if (ContentObject is
null)
1209 Content = Encoding.UTF8.GetBytes(ex.Message);
1227 if (!
string.IsNullOrEmpty(Html))
1230 e.Response.StatusMessage = ex.Message;
1234 foreach (KeyValuePair<string, string> P
in ex.
HeaderFields)
1236 if (
string.Compare(P.Key,
"Content-Type",
true) != 0)
1241 e.Response.ContentType =
"text/html; charset=utf-8";
1250 catch (Exception ex2)
1256 private bool subscribingSWUpdates =
false;
1257 private bool subscribedToPackages =
false;
1259 private async Task XmppClient_OnStateChanged(
object Sender, Networking.XMPP.XmppState NewState)
1261 if (NewState == Networking.XMPP.XmppState.Connected)
1264 !
this.subscribingSWUpdates &&
1267 this.subscribingSWUpdates =
true;
1272 if ((DateTime.Now - LastUpdate).TotalDays >= 7 || !
this.subscribedToPackages)
1275 this.subscribedToPackages =
true;
1278 await this.CheckSoftwarePackage(
Package, (P, MessageId) => Task.FromResult<
string>(MessageId));
1283 catch (Exception ex)
1289 this.subscribingSWUpdates =
false;
1293 await this.RejoinRooms();
1297 private Task Gateway_OnNewCertificate(
object Sender, IoTGateway.Events.CertificateEventArgs e)
1303 return Task.CompletedTask;
1312 lock (this.webNodes)
1314 if (this.webNodes.ContainsKey(NodeName))
1318 this.webNodes[NodeName] =
WebNode;
1325 catch (Exception ex)
1329 lock (this.webNodes)
1331 this.webNodes.Remove(NodeName);
1337 lock (this.webNodes)
1339 if (!this.webNodes.TryGetValue(NodeName, out
WebNode))
1342 this.webNodes.Remove(NodeName);
1349 public async Task DoImportIpLocalizationDatabase()
1351 string s = Path.Combine(PackagesFolder, Ip2LocalizationPackageName);
1353 this.ImportIpLocalizationDatabase(
null);
1356 private static bool importingIp =
false;
1358 private async
void ImportIpLocalizationDatabase(
object State)
1365 string s = Path.Combine(PackagesFolder, Ip2LocalizationPackageName);
1369 DateTime TP = File.GetLastWriteTimeUtc(s);
1374 StringBuilder sb =
new StringBuilder(
"Samples:=[");
1375 DateTime
Start = DateTime.Now;
1389 catch (Exception ex)
1397 using FileStream fs = File.OpenRead(s);
1398 using StreamReader r =
new StreamReader(fs);
1400 while (!r.EndOfStream)
1402 string Row = await r.ReadLineAsync();
1403 string[][] Records =
CSV.
Parse(Row);
1405 foreach (
string[]
Record in Records)
1407 if (
Record.Length >= 8 &&
1408 uint.TryParse(
Record[0], out uint IpRangeFrom) &&
1409 uint.TryParse(
Record[1], out uint IpRangeTo) &&
1417 RangeStart = IpRangeFrom,
1418 RangeEnd = IpRangeTo,
1423 Latitude = Latitude,
1424 Longitude = Longitude
1429 if (Count % 10000 == 0)
1440 sb.Append(Count.ToString());
1460 sb.Append(Count.ToString());
1463 sb.AppendLine(
"]];");
1465 sb.AppendLine(
"Objects:=Samples[0,];");
1466 sb.AppendLine(
"Seconds:=Samples[1,];");
1467 sb.AppendLine(
"ObjOverTime:=plot2dcurve(Seconds,Objects);");
1468 sb.AppendLine(
"ObjOverTime.Title:=\"Objects imported over time\";");
1469 sb.AppendLine(
"ObjOverTime.LabelX:=\"Seconds\";");
1470 sb.AppendLine(
"ObjOverTime.LabelY:=\"#Objects\";");
1472 sb.AppendLine(
"NrSamples:=count(Objects);");
1473 sb.AppendLine(
"DeltaSeconds:=Seconds[1..(NrSamples-1)]-Seconds[0..(NrSamples-2)];");
1474 sb.AppendLine(
"DeltaObjects:=Objects[1..(NrSamples-1)]-Objects[0..(NrSamples-2)];");
1475 sb.AppendLine(
"ObjectsPerSecond:=DeltaObjects./DeltaSeconds;");
1476 sb.AppendLine(
"SpeedOverTime:=plot2dcurve(Seconds[1..(NrSamples-1)],ObjectsPerSecond);");
1477 sb.AppendLine(
"SpeedOverTime.Title:=\"Objects/s imported over time\";");
1478 sb.AppendLine(
"SpeedOverTime.LabelX:=\"Seconds\";");
1479 sb.AppendLine(
"SpeedOverTime.LabelY:=\"#Objects/s\";");
1481 File.WriteAllText(appData +
"ImportTimes.script", sb.ToString());
1484 new KeyValuePair<string, object>(
"NrImported", Count),
1485 new KeyValuePair<string, object>(
"NrSkipped", Skipped));
1490 Count.ToString() +
" records imported. " + Skipped.ToString() +
" " +
1491 (Skipped == 1 ?
"record" :
"records") +
" skipped.");
1506 catch (Exception ex)
1513 catch (Exception ex)
1515 Log.
Error(
"Unable to import IP localization database.\r\n\r\n" + ex.Message, Ip2LocalizationPackageName);
1519 importingIp =
false;
1526 if (this.ip4LocalizationCache is
null)
1535 if (!(Location is
null))
1537 e.
AddTag(
"City", Location.City);
1538 e.
AddTag(
"Region", Location.Region);
1539 e.
AddTag(
"Country", Location.Country);
1540 e.
AddTag(
"Code", Location.CountryCode);
1542 string s =
"flag-" + Location.CountryCode?.ToLower();
1544 e.
AddTag(
"Flag",
":" + s +
":");
1546 e.
AddTag(
"Latitude", Location.Latitude);
1547 e.
AddTag(
"Longitude", Location.Longitude);
1548 e.
AddTag(
"Acknowledgement",
"This site or product includes IP2Location LITE data available from http://www.ip2location.com.");
1559 RemoteEndPoint = RemoteEndPoint.RemovePortNumber();
1561 if (!IPAddress.TryParse(RemoteEndPoint, out IPAddress Addr))
1574 if (Addr.AddressFamily != AddressFamily.InterNetwork)
1577 byte[] Bytes = Addr.GetAddressBytes();
1579 uint Value = Bytes[0];
1591 if (Value >= Loc.RangeStart && Value <= Loc.RangeEnd)
1595 catch (Exception ex)
1610 Markdown.Append(
"| Remote Endpoint: | ");
1611 Markdown.Append(RemoteEndPoint);
1612 Markdown.AppendLine(
" |");
1616 Markdown.Append(
"| ");
1618 Markdown.Append(
" | ");
1620 Markdown.AppendLine(
" |");
1624 private async
void Service_NewDay(
object P)
1628 if (!(this.httpServer is
null))
1648 if (!(this.xmppServer is
null))
1671 if (!(this.eventStatistics is
null))
1679 PerType = this.Convert(Stat.
PerType),
1680 PerLevel = this.Convert(Stat.
PerLevel),
1682 PerActor = this.Convert(Stat.
PerActor),
1683 PerModule = this.Convert(Stat.
PerModule),
1691 await this.DeleteOldItems();
1693 catch (Exception ex)
1703 private async Task DeleteOldItems()
1707 DateTime TimeLimit = DateTime.Now.AddDays(-30);
1710 if (!(this.persistenceLayer is
null))
1718 catch (Exception ex)
1720 Log.
Error(
"Unable to delete old offline messages.\r\n\r\n" + ex.Message,
1721 string.Empty,
string.Empty,
string.Empty,
EventLevel.Medium,
1722 string.Empty,
string.Empty, ex.StackTrace);
1726 if (!(this.xmppServer is
null))
1732 Log.
Informational(
"Mail content from " + Nr.ToString() +
" old messages deleted.");
1734 catch (Exception ex)
1736 Log.
Error(
"Unable to delete old e-mail messages.\r\n\r\n" + ex.Message,
1737 string.Empty,
string.Empty,
string.Empty,
EventLevel.Medium,
1738 string.Empty,
string.Empty, ex.StackTrace);
1742 if (!(this.pubSubComponent is
null))
1748 Log.
Informational(Nr.ToString() +
" pubsub nodes (and " + Nr2.ToString() +
" items) deleted.");
1750 catch (Exception ex)
1752 Log.
Error(
"Unable to delete expired pubsub nodes.\r\n\r\n" + ex.Message,
1753 string.Empty,
string.Empty,
string.Empty,
EventLevel.Medium,
1754 string.Empty,
string.Empty, ex.StackTrace);
1760 (
int NrTokens,
int NrEvents,
int NrTags) = await
NeuroFeatures.NeuroFeaturesProcessor.DeleteExpiredTokens(
this.eDalerComponent);
1762 Log.
Informational(NrTokens.ToString() +
" tokens, " + NrTags.ToString() +
" tags and " + NrEvents.ToString() +
" events deleted.");
1764 catch (Exception ex)
1766 Log.
Error(
"Unable to delete expired tokens.\r\n\r\n" + ex.Message,
1767 string.Empty,
string.Empty,
string.Empty,
EventLevel.Medium,
1768 string.Empty,
string.Empty, ex.StackTrace);
1773 (
int NrMachines,
int NrEventHandlers,
int NrCurrentStates,
int NrSamples) =
1776 Log.
Informational(NrMachines.ToString() +
" state machines, " + NrEventHandlers.ToString() +
" event handlers and " + NrSamples.ToString() +
" samples deleted.");
1778 catch (Exception ex)
1780 Log.
Error(
"Unable to delete expired state machines.\r\n\r\n" + ex.Message,
1781 string.Empty,
string.Empty,
string.Empty,
EventLevel.Medium,
1782 string.Empty,
string.Empty, ex.StackTrace);
1788 if (NrAttachments > 0)
1789 Log.
Informational(NrAttachments.ToString() +
" cached attachments deleted.");
1791 catch (Exception ex)
1793 Log.
Error(
"Unable to delete old cached attachments.\r\n\r\n" + ex.Message,
1794 string.Empty,
string.Empty,
string.Empty,
EventLevel.Medium,
1795 string.Empty,
string.Empty, ex.StackTrace);
1800 int Count = await (this.legalComponent?.DeleteOldPreviewApplications(14) ?? Task.FromResult(0));
1805 catch (Exception ex)
1807 Log.
Error(
"Unable to delete old preview files.\r\n\r\n" + ex.Message,
1808 string.Empty,
string.Empty,
string.Empty,
EventLevel.Medium,
1809 string.Empty,
string.Empty, ex.StackTrace);
1814 catch (Exception ex)
1820 private Sources.Reports.Events.Commands.Statistic[] Convert(Dictionary<string, Waher.Events.Statistics.Statistic> Statistics)
1822 List<Sources.Reports.Events.Commands.Statistic> Result =
new List<Sources.Reports.Events.Commands.Statistic>();
1824 foreach (KeyValuePair<string, Waher.Events.Statistics.Statistic> P
in Statistics)
1826 Result.Add(
new Sources.Reports.Events.Commands.Statistic()
1829 Count = P.Value.Count,
1830 First = P.Value.First,
1835 return Result.ToArray();
1845 Gateway.OnNewCertificate -= this.Gateway_OnNewCertificate;
1846 Gateway.OnTerminate -= this.Gateway_OnTerminate;
1850 Gateway.SoftwareUpdateClient.OnSoftwareUpdated -= this.SoftwareUpdateClient_OnSoftwareUpdated;
1851 Gateway.SoftwareUpdateClient.OnSoftwareValidation -= this.SoftwareUpdateClient_OnSoftwareValidation;
1852 Gateway.SoftwareUpdateClient.OnSoftwareDownloaded -= this.SoftwareUpdateClient_OnSoftwareDownloaded;
1853 Gateway.SoftwareUpdateClient.OnSoftwareDeleted -= this.SoftwareUpdateClient_OnSoftwareDeleted;
1854 Gateway.SoftwareUpdateClient.OnDownloadedSoftwareDeleted -= this.SoftwareUpdateClient_OnDownloadedSoftwareDeleted;
1860 Gateway.XmppClient.OnGroupChatMessage -= this.XmppClient_OnGroupChatMessage;
1861 Gateway.XmppClient.OnValidateSender -= this.XmppClient_OnValidateSender;
1863 Gateway.MucClient.RoomInvitationReceived -= this.MucClient_RoomInvitationReceived;
1864 Gateway.MucClient.DirectInvitationReceived -= this.MucClient_DirectInvitationReceived;
1865 Gateway.MucClient.OccupantPresence -= this.MucClient_OccupantPresence;
1866 Gateway.MucClient.PrivateMessageReceived -= this.MucClient_PrivateMessageReceived;
1867 Gateway.MucClient.RoomDestroyed -= this.MucClient_RoomDestroyed;
1870 this.sampleTimer?.Dispose();
1871 this.sampleTimer =
null;
1873 await this.LeaveAllRooms();
1875 LoginAuditor.AnnotateEndpoint -= this.LoginAuditor_AnnotateEndpoint;
1876 this.ip4LocalizationCache?.
Dispose();
1877 this.ip4LocalizationCache =
null;
1879 if (!(this.eventStatistics is
null))
1883 this.eventStatistics =
null;
1888 if (!(this.vulnerableResources is
null))
1890 this.vulnerableResources =
null;
1893 Gateway.Root.FileNotFound -= this.CheckForHoneyPotResources;
1896 if (!(this.httpServer is
null))
1898 Export.OnExportFolderUpdated -= this.Export_OnExportFolderUpdated;
1899 Export.OnExportKeyFolderUpdated -= this.Export_OnExportKeyFolderUpdated;
1903 this.httpServer.
Unregister(this.webSocketClient);
1904 this.httpServer.
Unregister(this.webHostMetaDataXml);
1905 this.httpServer.
Unregister(this.webHostMetaDataJson);
1907 this.httpServer.
Unregister(this.createApiKey);
1908 this.httpServer.
Unregister(this.updateApiKey);
1909 this.httpServer.
Unregister(this.createAccount);
1910 this.httpServer.
Unregister(this.updateAccount);
1911 this.httpServer.
Unregister(this.deleteAccount);
1912 this.httpServer.
Unregister(this.updatePubSubNode);
1913 this.httpServer.
Unregister(this.deletePubSubNode);
1914 this.httpServer.
Unregister(this.loadMoreItems);
1916 this.httpServer.
Unregister(this.requestAccount);
1917 this.httpServer.
Unregister(this.requestApiKey);
1918 this.httpServer.
Unregister(this.searchEvents);
1919 this.httpServer.
Unregister(this.sendMessage);
1920 this.httpServer.
Unregister(this.setContractState);
1921 this.httpServer.
Unregister(this.publisherAvatar);
1922 this.httpServer.
Unregister(this.legalIdentityStateChanged);
1924 this.httpServer.
Unregister(this.uploadPackage);
1925 this.httpServer.
Unregister(this.uploadSignature);
1926 this.httpServer.
Unregister(this.deletePackage);
1927 this.httpServer.
Unregister(this.installPackage);
1928 this.httpServer.
Unregister(this.uninstallPackage);
1929 this.httpServer.
Unregister(this.dnsOverHttps);
1930 this.httpServer.
Unregister(this.validateLegalId);
1931 this.httpServer.
Unregister(this.validateContract);
1934 this.httpServer.
Unregister(this.remoteLogin);
1935 this.httpServer.
Unregister(this.whatsMyEndpointResource);
1937 this.httpServer.
Unregister(this.publicTokenView);
1938 this.httpServer.
Unregister(this.publicTokenHistoryView);
1939 this.httpServer.
Unregister(this.publicNodes);
1941 this.httpServer.
Unregister(this.killMachine);
1944 this.httpServer.
Unregister(this.xmppOverHttp);
1947 this.httpxServer =
null;
1949 if (!(this.httpFileUploadResource is
null))
1950 this.httpServer.
Unregister(this.httpFileUploadResource);
1952 if (!(this.httpEncryptedFileUploadResource is
null))
1953 this.httpServer.
Unregister(this.httpEncryptedFileUploadResource);
1955 if (!(this.httpPubSubFileUploadResource is
null))
1956 this.httpServer.
Unregister(this.httpPubSubFileUploadResource);
1958 if (!(this.httpInternalTransferUploadResource is
null))
1959 this.httpServer.
Unregister(this.httpInternalTransferUploadResource);
1961 if (!(this.webNodes is
null))
1965 lock (this.webNodes)
1967 Nodes =
new WebNode[this.webNodes.Count];
1968 this.webNodes.Values.CopyTo(Nodes, 0);
1969 this.webNodes.Clear();
1976 this.webClient1 =
null;
1977 this.webClient2 =
null;
1978 this.webSocketClient =
null;
1979 this.webHostMetaDataXml =
null;
1980 this.webHostMetaDataJson =
null;
1981 this.createApiKey =
null;
1982 this.updateApiKey =
null;
1983 this.createAccount =
null;
1984 this.updateAccount =
null;
1985 this.deleteAccount =
null;
1986 this.updatePubSubNode =
null;
1987 this.deletePubSubNode =
null;
1988 this.loadMoreItems =
null;
1989 this.feedback =
null;
1990 this.requestAccount =
null;
1991 this.requestApiKey =
null;
1992 this.searchEvents =
null;
1993 this.sendMessage =
null;
1994 this.setContractState =
null;
1995 this.publisherAvatar =
null;
1996 this.legalIdentityStateChanged =
null;
1998 this.uploadPackage =
null;
1999 this.uploadSignature =
null;
2000 this.deletePackage =
null;
2001 this.installPackage =
null;
2002 this.uninstallPackage =
null;
2003 this.dnsOverHttps =
null;
2004 this.validateLegalId =
null;
2005 this.validateContract =
null;
2007 this.quickLogin?.Dispose();
2008 this.quickLogin =
null;
2009 this.remoteLogin =
null;
2010 this.whatsMyEndpointResource =
null;
2011 this.addNote =
null;
2012 this.publicTokenView =
null;
2013 this.publicTokenHistoryView =
null;
2014 this.publicNodes =
null;
2016 this.killMachine =
null;
2017 this.httpProxy =
null;
2018 this.chatFile =
null;
2019 this.xmppOverHttp =
null;
2020 this.httpFileUploadResource =
null;
2021 this.httpEncryptedFileUploadResource =
null;
2022 this.httpPubSubFileUploadResource =
null;
2023 this.httpInternalTransferUploadResource =
null;
2025 this.httpServer =
null;
2028 this.httpFileUploadComponent?.
Dispose();
2029 this.httpFileUploadComponent =
null;
2031 this.socks5Component?.
Dispose();
2032 this.socks5Component =
null;
2034 this.serviceRegistrationComponent?.
Dispose();
2035 this.serviceRegistrationComponent =
null;
2037 this.pubSubComponent?.
Dispose();
2038 this.pubSubComponent =
null;
2041 this.mucComponent =
null;
2043 this.provisioningComponent?.
Dispose();
2044 this.provisioningComponent =
null;
2046 this.legalComponent?.
Dispose();
2047 this.legalComponent =
null;
2049 this.eDalerComponent?.
Dispose();
2050 this.eDalerComponent =
null;
2053 this.geoComponent =
null;
2055 this.eventLogComponent?.
Dispose();
2056 this.eventLogComponent =
null;
2058 if (!(this.xmppServer is
null))
2060 this.xmppServer.ClientConnectionAdded -= this.XmppServer_ClientConnectionAdded;
2061 this.xmppServer.ClientConnectionRemoved -= this.XmppServer_ClientConnectionRemoved;
2062 this.xmppServer.ClientConnectionUpdated -= this.XmppServer_ClientConnectionUpdated;
2063 this.xmppServer.ServerConnectionAdded -= this.XmppServer_ServerConnectionAdded;
2064 this.xmppServer.ServerConnectionRemoved -= this.XmppServer_ServerConnectionRemoved;
2065 this.xmppServer.ServerConnectionUpdated -= this.XmppServer_ServerConnectionUpdated;
2068 this.xmppServer =
null;
2072 this.smtpServer =
null;
2075 this.ftpServer =
null;
2078 this.chatSessions =
null;
2080 this.consolidators?.
Dispose();
2081 this.consolidators =
null;
2084 this.ssoTokens =
null;
2093 public static SmtpServer MailServer => instance?.smtpServer;
2094 public static FtpServer FileServer => instance?.ftpServer;
2110 if (!(instance is
null))
2111 return instance.xmppServer;
2123 public static string PackagesFolder
2128 public static string DownloadsFolder
2133 public static string InternalTransfersFolder
2138 public static ApiKey GetApiKey(
string Key)
2140 ApiKey Result = GetApiKeyAsync(Key).Result
2146 public static async Task<ApiKey> GetApiKeyAsync(
string Key)
2148 if (
string.IsNullOrEmpty(Key))
2166 IAccount Result = GetAccountAsync(UserName).Result
2174 if (instance is
null)
2175 return GetAccountAsyncNoInit(UserName);
2190 if (instance is
null)
2191 return GetRosterItemAsyncNoInit(UserName, Jid);
2193 return instance.persistenceLayer.
GetRosterItem(UserName, Jid);
2210 if (instance is
null)
2211 return GetRosterAsyncNoInit(UserName);
2213 return instance.persistenceLayer.
GetRoster(UserName);
2216 private static async Task<IEnumerable<IRosterItem>> GetRosterAsyncNoInit(
CaseInsensitiveString UserName)
2222 private static Stopwatch CreateWatch()
2224 Stopwatch Watch =
new Stopwatch();
2240 private static Calibration
Calibrate(Stopwatch Clock)
2242 DateTime TP = DateTime.Now;
2243 long Ticks = TP.Ticks;
2247 for (i = 0; i < 3; i++)
2249 while ((TP = DateTime.UtcNow).Ticks == Ticks)
2252 HF = Clock.ElapsedTicks;
2256 return new Calibration()
2259 ReferenceHfTick = HF,
2260 TicksTo100Ns = 1e7 / Stopwatch.Frequency
2271 DateTime NowRef = DateTime.UtcNow;
2272 long Ticks = clock.ElapsedTicks;
2273 Calibration Calibration = calibration;
2275 Ticks -= Calibration.ReferenceHfTick;
2277 long Ns100 = (long)(Ticks * Calibration.TicksTo100Ns + 0.5);
2278 long Milliseconds = Ns100 / 10000;
2280 DateTime
Now = Calibration.Reference.AddMilliseconds(Milliseconds);
2282 if ((
Now - NowRef).TotalSeconds >= 1)
2291 return new DateTimeHF(
Now, (
int)(Ns100 / 10), (
int)(Ns100 % 10), Ticks);
2296 private async Task DnsRequest(
object Sender,
IqEventArgs e)
2300 byte[] ReqBin =
System.Convert.FromBase64String(e.
Query.InnerText);
2313 RespBin[0] = ReqBin[0];
2314 RespBin[1] = ReqBin[1];
2316 StringBuilder Xml =
new StringBuilder();
2318 Xml.Append(
"<dns xmlns='");
2321 Xml.Append(
System.Convert.ToBase64String(RespBin));
2322 Xml.Append(
"</dns>");
2331 catch (Exception ex)
2339 PubSubNode Result = GetPubSubNodeAsync(NodeName).Result
2347 if (instance is
null)
2348 return GetPubSubNodeAsyncNoInit(NodeName);
2392 return IsAdmin(Jid,
null);
2397 Jid = Networking.XMPP.XmppClient.GetBareJID(Jid);
2405 if (
string.Compare(s, Jid,
true) == 0)
2416 public static string DateTimesToHTML(DateTime Created, DateTime Updated)
2418 StringBuilder Result =
new StringBuilder();
2420 Created = Created.ToLocalTime();
2422 if (Updated != DateTime.MinValue)
2423 Updated = Updated.ToLocalTime();
2425 Result.Append(
"<span class=\"ContentItemTimestamp\">");
2426 Result.Append(Created.ToShortDateString());
2427 Result.Append(
", ");
2428 Result.Append(Created.ToLongTimeString());
2429 Result.Append(
"</span>");
2431 if (Updated != Created && Updated != DateTime.MinValue)
2433 Result.Append(
"<span class=\"ContentItemUpdated\">");
2434 Result.Append(Updated.ToShortDateString());
2435 Result.Append(
", ");
2436 Result.Append(Updated.ToLongTimeString());
2437 Result.Append(
"</span>");
2440 return Result.ToString();
2443 private async Task CheckRegistration()
2460 StringBuilder Xml =
new StringBuilder();
2464 Xml.Append(
"<vCard xmlns='vcard-temp'>");
2465 Xml.Append(
"<FN>XMPP Broker on ");
2467 Xml.Append(
"</FN>");
2468 Xml.Append(
"<URL>");
2470 Xml.Append(
"</URL>");
2471 Xml.Append(
"<JABBERID>");
2473 Xml.Append(
"</JABBERID>");
2474 Xml.Append(
"<PHOTO><TYPE>image/png</TYPE><BINVAL>");
2475 Xml.Append(
System.Convert.ToBase64String(
Avatar, Base64FormattingOptions.None));
2476 Xml.Append(
"</BINVAL></PHOTO>");
2477 Xml.Append(
"</vCard>");
2487 catch (Exception ex)
2492 Gateway.
ScheduleEvent((P) => Task.Run(() =>
this.CheckRegistration()), DateTime.Now.AddMinutes(15),
null);
2495 private Task XmppServer_ClientConnectionAdded(
object Sender, Networking.XMPP.Server.ClientConnectionEventArgs e)
2497 return this.connectionsSource?.ClientConnectionAdded(Sender, e) ?? Task.CompletedTask;
2500 private Task XmppServer_ClientConnectionRemoved(
object Sender, Networking.XMPP.Server.ClientConnectionEventArgs e)
2502 return this.connectionsSource?.ClientConnectionRemoved(Sender, e) ?? Task.CompletedTask;
2505 private Task XmppServer_ClientConnectionUpdated(
object Sender, Networking.XMPP.Server.ClientConnectionEventArgs e)
2507 return this.connectionsSource?.ClientConnectionUpdated(Sender, e) ?? Task.CompletedTask;
2510 private Task XmppServer_ServerConnectionAdded(
object Sender, Networking.XMPP.Server.ServerConnectionEventArgs e)
2512 return this.connectionsSource?.ServerConnectionAdded(Sender, e) ?? Task.CompletedTask;
2515 private Task XmppServer_ServerConnectionRemoved(
object Sender, Networking.XMPP.Server.ServerConnectionEventArgs e)
2517 return this.connectionsSource?.ServerConnectionRemoved(Sender, e) ?? Task.CompletedTask;
2520 private Task XmppServer_ServerConnectionUpdated(
object Sender, Networking.XMPP.Server.ServerConnectionEventArgs e)
2522 return this.connectionsSource?.ServerConnectionUpdated(Sender, e) ?? Task.CompletedTask;
2525 internal async Task<bool> CheckSoftwarePackage(Networking.XMPP.Software.Package RemotePackage,
ResponseCallbackHandler ResponseCallback)
2531 if (LocalPackage is
null ||
2532 LocalPackage.
Published < RemotePackage.Published ||
2533 !CheckPackageSize(LocalPackage.
FileName, RemotePackage.Bytes))
2535 string MessageId = await ResponseCallback(
"Downloading `" + RemotePackage.FileName +
"`",
string.Empty);
2537 DateTime Last = DateTime.UtcNow;
2538 long BytesDownloaded = 0;
2540 Destination.OnWrite += async (Sender, e) =>
2542 DateTime TP = DateTime.UtcNow;
2544 BytesDownloaded = e.Total;
2546 if (TP.Second != Last.Second)
2549 await ResponseCallback(
"Downloading `" + RemotePackage.FileName +
"`: " + BytesDownloaded.ToString() +
" bytes downloaded.", MessageId);
2560 catch (Exception ex)
2562 await ReturnError(ex, ResponseCallback);
2568 private static bool CheckPackageSize(
string FileName,
long ExpectedSize)
2570 string FullPath = Path.Combine(PackagesFolder, FileName);
2572 if (!File.Exists(FullPath))
2575 System.IO.FileInfo Info =
new System.IO.FileInfo(FullPath);
2577 return Info.Length == ExpectedSize;
2580 private Task SoftwareUpdateClient_OnSoftwareUpdated(
object Sender, Networking.XMPP.Software.PackageUpdatedEventArgs e)
2582 Log.
Informational(
"New software package available.", PackageTags(e.Package));
2585 return Task.CompletedTask;
2588 private static KeyValuePair<string, object>[] PackageTags(Networking.XMPP.Software.Package
Package)
2590 return new KeyValuePair<string, object>[]
2593 new KeyValuePair<string, object>(
"Bytes",
Package.
Bytes),
2597 new KeyValuePair<string, object>(
"Signature",
System.Convert.ToBase64String(
Package.
Signature ?? Array.Empty<
byte>())),
2598 new KeyValuePair<string, object>(
"URL",
Package.
Url)
2602 private async Task SoftwareUpdateClient_OnSoftwareValidation(
object Sender, Networking.XMPP.Software.PackageFileEventArgs e)
2604 string FileName = Path.GetFileName(e.LocalFileName);
2608 if (!ValidateIoTBrokerPackage(e.LocalFileName, e.Package.Signature))
2609 throw new Exception(
"Invalid signature.");
2619 if (!ValidatePackage(e.LocalFileName,
Package.
PublicKey, e.Package.Signature))
2620 throw new Exception(
"Invalid signature.");
2625 internal static bool ValidateIoTBrokerPackage(
string FileName,
byte[]
Signature)
2627 Log.
Notice(
"Validating package.", FileName);
2629 using FileStream f = File.OpenRead(FileName);
2630 bool Result = ValidateIoTBrokerPackage(f,
Signature);
2635 Log.
Error(
"Package not valid.", FileName);
2640 internal static bool ValidatePackage(
string FileName,
byte[] PublicKey,
byte[]
Signature)
2642 Log.
Notice(
"Validating package.", FileName);
2644 using FileStream f = File.OpenRead(FileName);
2645 bool Result = ValidatePackage(f, PublicKey,
Signature);
2650 Log.
Error(
"Package not valid.", FileName);
2655 internal static bool ValidateIoTBrokerPackage(Stream Data,
byte[]
Signature)
2657 return ValidatePackage(Data, iotBrokerPackagePublicKey,
Signature);
2660 internal static bool ValidatePackage(Stream Data,
byte[] PublicKey,
byte[]
Signature)
2662 return ed448.Verify(Data, PublicKey,
Signature);
2665 private Task SoftwareUpdateClient_OnSoftwareDownloaded(
object Sender, Networking.XMPP.Software.PackageFileEventArgs e)
2667 return this.PackageDownloaded(e.Package, e.
From,
string.
Empty,
2668 (Markdown, MessageId) => Task.FromResult(MessageId));
2671 private async Task PackageDownloaded(Networking.XMPP.Software.Package DownloadedPackage,
2674 Log.
Notice(
"New software package downloaded.", PackageTags(DownloadedPackage));
2676 await ResponseCallback(
"Software package downloaded: `" + DownloadedPackage.FileName +
"`", MessageId);
2678 DateTime
Now = DateTime.UtcNow;
2685 FileName = DownloadedPackage.
FileName,
2686 Signature = DownloadedPackage.Signature,
2687 RemoteEndPoint = RemoteEndPoint,
2689 Supersedes = DateTime.MinValue,
2691 Bytes = DownloadedPackage.Bytes,
2693 Installed = DateTime.MinValue,
2695 Downloadable =
false
2702 Package.Signature = DownloadedPackage.Signature;
2703 Package.RemoteEndPoint = RemoteEndPoint;
2705 Package.Published =
Now;
2706 Package.Bytes = DownloadedPackage.Bytes;
2717 StringBuilder sb =
new StringBuilder();
2719 sb.AppendLine(
"<?xml version=\"1.0\" encoding=\"utf-8\"?>");
2720 sb.AppendLine(
"<Signatures xmlns=\"http://waher.se/Schema/Signatures.xsd\">");
2721 sb.Append(
"\t<Signature fileName=\"");
2725 sb.AppendLine(
"</Signature>");
2726 sb.AppendLine(
"</Signatures>");
2728 File.WriteAllText(SignatureFile, sb.ToString(), Encoding.UTF8);
2730 if (!(this.provisioningComponent is
null))
2731 await this.provisioningComponent.NewPackage(
Package);
2736 await this.NewSoftwareAvailable(
Package, RemoteEndPoint);
2738 else if (
string.Compare(DownloadedPackage.FileName, Ip2LocalizationPackageName,
true) == 0)
2745 internal async Task NewSoftwareAvailable(
Package DownloadedPackage,
string RemoteEndPoint)
2747 StringBuilder Markdown =
new StringBuilder();
2748 DateTime
Now = DateTime.Now;
2763 Markdown.AppendLine(
"New version of installed software has been downloaded");
2764 Markdown.AppendLine(
"==========================================================");
2765 Markdown.AppendLine();
2766 Markdown.AppendLine(
"| Package ||");
2767 Markdown.AppendLine(
"|:------|:-------|");
2768 Markdown.AppendLine(
"| Filename: | `" + DownloadedPackage.
FileName +
"` |");
2770 Markdown.AppendLine(
"| From: | `" + RemoteEndPoint +
"` |");
2773 if (DownloadedPackage.
Supersedes != DateTime.MinValue)
2776 Markdown.AppendLine(
"| Signature: | " +
System.Convert.ToBase64String(DownloadedPackage.
Signature) +
" |");
2778 Markdown.Append(
"| Date | ");
2780 Markdown.AppendLine(
" |");
2781 Markdown.Append(
"| Time | ");
2783 Markdown.AppendLine(
" |");
2784 Markdown.AppendLine();
2788 Markdown.AppendLine(
"See [Release Notes](https://lab.tagroot.io/ReleaseNotes) for information about what is new.");
2789 Markdown.AppendLine();
2792 if (DelayMinutes > 0)
2800 await this.UpdateSoftware(DownloadedPackage,
false);
2804 Markdown.AppendLine(
"The new software has been automatically installed.");
2806 catch (Exception ex)
2810 Markdown.AppendLine(
"Unable to install the new software. The following error was reported: ");
2811 Markdown.AppendLine();
2812 Markdown.AppendLine(
"```");
2813 Markdown.AppendLine(ex.Message.Trim());
2814 Markdown.AppendLine(
"```");
2819 if (autoUpdateTP > DateTime.MinValue)
2822 autoUpdateTP = DateTime.MinValue;
2825 DateTime TP =
Now.AddMinutes(DelayMinutes);
2830 Markdown.Append(
"The new software will be automatically installed");
2832 if (DelayMinutes == 1)
2833 Markdown.Append(
" in 1 minute");
2834 else if (DelayMinutes <= 60)
2835 Markdown.Append(
" in " + DelayMinutes.ToString() +
" minutes");
2838 Markdown.Append(
" at ");
2840 if (TP.Date ==
Now.Date)
2841 Markdown.Append(TP.ToShortTimeString());
2844 Markdown.Append(TP.ToShortDateString());
2845 Markdown.Append(
", ");
2846 Markdown.Append(TP.ToShortTimeString());
2850 Markdown.AppendLine(
", unless cancelled from the chat interface.");
2854 Markdown.AppendLine(
"You can update the server with the new package from the chat interface.");
2869 if (!File.Exists(FileName))
2872 StringBuilder sb =
new StringBuilder();
2882 sb.Append(
":Waher.Utility.Install");
2885 byte[] Digest = H.
ComputeVariable(Encoding.UTF8.GetBytes(sb.ToString()));
2886 byte[] AesKey =
new byte[32];
2887 byte[] IV =
new byte[16];
2889 FileStream fs =
null;
2890 ICryptoTransform AesTransform =
null;
2891 CryptoStream Decrypted =
null;
2892 GZipStream Decompressed =
null;
2894 Buffer.BlockCopy(Digest, 0, AesKey, 0, 32);
2895 Buffer.BlockCopy(Digest, 32, IV, 0, 16);
2900 Aes.BlockSize = 128;
2902 Aes.Mode = CipherMode.CBC;
2903 Aes.Padding = PaddingMode.Zeros;
2905 fs = File.OpenRead(FileName);
2906 AesTransform = Aes.CreateDecryptor(AesKey, IV);
2907 Decrypted =
new CryptoStream(fs, AesTransform, CryptoStreamMode.Read);
2908 Decompressed =
new GZipStream(Decrypted, CompressionMode.Decompress);
2910 byte b = ReadByte(Decompressed);
2916 Decompressed.ReadAll(Bin, 0, b);
2919 Bin = ReadBin(Decompressed);
2920 if (Encoding.ASCII.GetString(Bin) !=
"IoTGatewayPackage")
2921 throw new Exception(
"Invalid package file.");
2923 while ((b = ReadByte(Decompressed)) != 0)
2925 string RelativeName = Encoding.UTF8.GetString(ReadBin(Decompressed));
2926 ReadVarLenUInt(Decompressed);
2927 ReadVarLenUInt(Decompressed);
2928 ReadVarLenUInt(Decompressed);
2929 ReadVarLenUInt(Decompressed);
2930 ulong Bytes = ReadVarLenUInt(Decompressed);
2935 SkipBytes(Decompressed, Bytes);
2945 SkipBytes(Decompressed, Bytes);
2949 throw new Exception(
"Invalid package file.");
2955 Decompressed?.Dispose();
2956 Decrypted?.Dispose();
2957 AesTransform?.Dispose();
2964 catch (Exception ex)
2971 private static byte[] ReadBin(Stream Input)
2973 ulong Len = ReadVarLenUInt(Input);
2974 if (Len >
int.MaxValue)
2975 throw new Exception(
"Invalid package.");
2978 byte[] Result =
new byte[c];
2980 Input.ReadAll(Result, 0, c);
2985 private static ulong ReadVarLenUInt(Stream Input)
2993 b = ReadByte(Input);
2995 Len |= ((ulong)(b & 127)) << Offset;
2998 while ((b & 0x80) != 0);
3003 private static byte ReadByte(Stream Input)
3005 int i = Input.ReadByte();
3007 throw new EndOfStreamException(
"Reading past end-of-file.");
3012 private static void SkipBytes(Stream Input, ulong Bytes)
3018 byte[] Buffer =
new byte[c];
3022 Input.ReadAll(Buffer, 0, (
int)c);
3029 internal async
void UpdateSoftware(
object P)
3034 await this.UpdateSoftware(
Package,
true);
3036 catch (Exception ex)
3047 Folder = PackagesFolder
3050 return this.UpdateSoftware(
Package, State, Backup);
3055 return this.UpdateSoftware(
Package, State, Backup, (Msg, MessageId) => Task.FromResult<
string>(MessageId));
3060 string MessageId =
string.Empty;
3064 MessageId = await ResponseCallback(
"Performing backup.", MessageId);
3068 StringBuilder sb =
new StringBuilder();
3070 bool RestartRequired;
3071 string ServerFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AppDomain.CurrentDomain.FriendlyName +
FileSystem.
ExecutableExtension);
3072 if (!File.Exists(ServerFileName))
3073 ServerFileName = Path.ChangeExtension(ServerFileName,
"dll");
3075 sb.Append(
"Install -d \"");
3077 sb.Append(
"\" -s \"");
3078 sb.Append(ServerFileName);
3082 bool UpdateBroker =
false;
3086 autoUpdateTP = DateTime.MinValue;
3089 if (!File.Exists(BrokerPackageFileName))
3095 UpdateBroker =
true;
3097 List<Package> ToInstall =
new List<Package>();
3099 foreach (
Package Package2
in Packages)
3101 if (Package2.
Installed == DateTime.MinValue)
3112 ToInstall.Add(Package2);
3114 Package2.Installed = Package2.
Published;
3118 ToInstall.Add(Package2);
3121 Packages = ToInstall.ToArray();
3122 RestartRequired =
true;
3139 RestartRequired =
false;
3144 foreach (
Package Package2
in Packages)
3146 string PackageFileName = Path.Combine(PackagesFolder, Package2.
FileName);
3148 if (File.Exists(PackageFileName))
3150 sb.Append(
" -p \"");
3151 sb.Append(PackageFileName.Replace(
"\"",
"\\\""));
3153 if (!(Package2.
AesKey is
null))
3155 sb.Append(
"\" -k \"");
3165 sb.Append(
" -p \"");
3166 sb.Append(BrokerPackageFileName);
3167 sb.Append(
"\" -k \"");
3172 !
string.IsNullOrEmpty(ServiceName))
3174 sb.Append(
" -sn \"");
3175 sb.Append(ServiceName);
3180 sb.Append(
" -n \"");
3182 sb.Append(
"\" -w 120000 -v -i > install.log");
3184 MessageId = await ResponseCallback(
"Starting update process...", MessageId);
3186 if (await this.ExecuteCommand(State.
To, sb.ToString(), State,
true, ResponseCallback))
3188 if (RestartRequired)
3190 await ResponseCallback(
"Stopping service... Update procedure will continue when service has been stopped. Service will then restart using the updated version.", MessageId);
3196 await ResponseCallback(
"Package installed. No restart required.", MessageId);
3202 internal async Task UninstallSoftware(
string PackageFileName,
byte[] AesKey)
3204 string s = Path.Combine(PackagesFolder, PackageFileName);
3205 if (!File.Exists(s))
3209 if (!File.Exists(s2))
3210 s2 = s2[..^3] +
"dll";
3212 StringBuilder sb =
new StringBuilder();
3214 sb.Append(
"Install -p \"");
3216 sb.Append(
"\" -d \"");
3218 sb.Append(
"\" -s \"");
3221 if (!(AesKey is
null))
3223 sb.Append(
"\" -k \"");
3232 if (!RestartRequired)
3235 sb.Append(
" -n \"");
3237 sb.Append(
"\" -w 120000 -v -u > install.log");
3242 Folder = PackagesFolder
3247 if (await this.ExecuteCommand(
string.Empty, sb.ToString(), State,
true,
3248 (Msg, MessageId) => Task.FromResult<
string>(MessageId)) && RestartRequired)
3254 private Task SoftwareUpdateClient_OnSoftwareDeleted(
object Sender, Networking.XMPP.Software.PackageDeletedEventArgs e)
3256 Log.
Informational(
"Software package deleted on server.", PackageTags(e.Package));
3259 return Task.CompletedTask;
3262 private async Task SoftwareUpdateClient_OnDownloadedSoftwareDeleted(
object Sender, Networking.XMPP.Software.PackageFileEventArgs e)
3264 Log.
Notice(
"Local copy of software package deleted.", PackageTags(e.Package));
3268 if (!(OldPackage is
null))
3272 if (!(this.provisioningComponent is
null))
3273 await this.provisioningComponent.PackageDeleted(OldPackage);
3277 private async Task<(string, string, bool)> GetPlainText(Networking.XMPP.Events.MessageEventArgs e, DateTime OfflineThreshold)
3279 string s = e.Body?.Trim();
3281 string ReplaceObjectId =
string.Empty;
3282 bool IsMarkdown =
false;
3284 foreach (XmlNode N
in e.Message.ChildNodes)
3286 if (N is XmlElement E)
3288 switch (E.LocalName)
3291 if (E.NamespaceURI ==
"urn:xmpp:content" &&
3294 if (
string.IsNullOrEmpty(s))
3306 E.HasAttribute(
"stamp") &&
3307 XML.
TryParse(E.GetAttribute(
"stamp"), out DateTime Timestamp) &&
3308 Timestamp.ToUniversalTime() < OfflineThreshold.ToUniversalTime())
3310 return (
string.Empty,
string.Empty,
false);
3315 if (E.NamespaceURI ==
"urn:xmpp:message-correct:0")
3322 return (s, ReplaceObjectId, IsMarkdown);
3326 private string GetMarkdown(Networking.XMPP.Events.MessageEventArgs e, DateTime OfflineThreshold,
bool EncodeIfText, out
string ReplaceObjectId, out
bool IsMarkdown)
3328 string s = e.Body?.Trim();
3330 ReplaceObjectId =
string.Empty;
3333 foreach (XmlNode N
in e.Message.ChildNodes)
3335 if (N is XmlElement E)
3337 switch (E.LocalName)
3340 if (E.NamespaceURI ==
"urn:xmpp:content" &&
3343 s = E.InnerText.Trim();
3350 E.HasAttribute(
"stamp") &&
3351 XML.
TryParse(E.GetAttribute(
"stamp"), out DateTime Timestamp) &&
3352 Timestamp.ToUniversalTime() < OfflineThreshold.ToUniversalTime())
3354 return string.Empty;
3359 if (E.NamespaceURI ==
"urn:xmpp:message-correct:0")
3369 private async Task XmppClient_OnChatMessage(
object Sender, Networking.XMPP.Events.MessageEventArgs e)
3371 (
string Message,
string _,
bool IsMarkdown) = await this.GetPlainText(e, DateTime.UtcNow.AddMinutes(-1));
3373 Task
_ = Task.Run(async () => await this.ProcessChatMessage(
Message, e.
From, e.ThreadID, async (Response, MessageId) =>
3375 KeyValuePair<string, string> P = await this.PrepareAdminResponse(Response, MessageId, IsMarkdown);
3377 MessageId = P.Value;
3380 Xml =
"<muteDiff xmlns='http://waher.se/Schema/Editing.xsd'/>";
3382 Xml +=
"<muteDiff xmlns='http://waher.se/Schema/Editing.xsd'/>";
3384 await
Gateway.
XmppClient.SendMessage(Networking.XMPP.QoSLevel.Unacknowledged, Networking.XMPP.MessageType.Chat,
3385 MessageId, e.
From, Xml,
string.
Empty,
string.
Empty,
string.
Empty, e.ThreadID,
string.Empty,
null,
null);
3391 private Task XmppClient_OnValidateSender(
object Sender, Networking.XMPP.Events.ValidateSenderEventArgs e)
3393 if (e.MessageStanza is
null || !e.Rejected)
3394 return Task.CompletedTask;
3396 switch (e.MessageStanza.
Type)
3398 case Networking.XMPP.MessageType.GroupChat:
3401 lock (this.mucRooms)
3403 InRoom = this.mucRooms.ContainsKey(e.FromBareJID);
3413 case Networking.XMPP.MessageType.Normal:
3414 case Networking.XMPP.MessageType.Chat:
3415 foreach (XmlNode N
in e.MessageStanza.Message.ChildNodes)
3417 if (!(N is XmlElement E))
3420 switch (E.NamespaceURI)
3422 case Networking.XMPP.MUC.MultiUserChatClient.NamespaceMuc:
3423 case Networking.XMPP.MUC.MultiUserChatClient.NamespaceMucAdmin:
3424 case Networking.XMPP.MUC.MultiUserChatClient.NamespaceMucOwner:
3425 case Networking.XMPP.MUC.MultiUserChatClient.NamespaceMucUser:
3426 lock (this.mucRooms)
3428 InRoom = this.mucRooms.ContainsKey(e.FromBareJID);
3435 return Task.CompletedTask;
3441 return Task.CompletedTask;
3444 private async Task MucClient_DirectInvitationReceived(
object Sender, Networking.XMPP.MUC.DirectInvitationMessageEventArgs e)
3446 if (await IsAdmin(e.
From))
3448 StringBuilder sb =
new StringBuilder();
3451 if (
string.IsNullOrEmpty(NickName))
3454 sb.Append(
"Accepting an invitation from `");
3455 sb.Append(e.FromBareJID);
3456 sb.Append(
"` to join the room `");
3457 sb.Append(e.RoomId);
3459 sb.Append(e.Domain);
3460 sb.Append(
"` using nick-name `");
3461 sb.Append(NickName);
3464 if (!
string.IsNullOrEmpty(e.Reason))
3467 sb.Append(e.Reason);
3472 await
Enter.
Execute(e.RoomId, e.Domain, NickName, e.Password,
true,
true, (Markdown, MessageId) =>
3474 if (string.IsNullOrEmpty(MessageId))
3475 MessageId = Guid.NewGuid().ToString();
3477 Gateway.SendNotification(Markdown, MessageId);
3478 return Task.FromResult<string>(MessageId);
3483 private Task MucClient_RoomInvitationReceived(
object Sender, Networking.XMPP.MUC.RoomInvitationMessageEventArgs e)
3485 e.Decline(
"Only accepting direct invitations.",
"en");
3486 return Task.CompletedTask;
3489 internal async Task EnterRoom(
string RoomId,
string Domain,
string NickName,
string Password,
bool Permanent)
3492 string Jid = RoomId +
"@" +
Domain;
3495 lock (this.mucRooms)
3497 Changed = (!this.mucRooms.TryGetValue(Jid, out
RoomInfo PrevInfo)) || (PrevInfo.Permanent ^ Permanent);
3498 this.mucRooms[Jid] = Info;
3502 await this.UpdatePermamentRooms();
3505 internal bool TryGetNickName(
string RoomId,
string Domain, out
string NickName)
3507 string Jid = RoomId +
"@" +
Domain;
3509 lock (this.mucRooms)
3518 NickName =
string.Empty;
3524 internal bool TryGetDomainAndNickName(
string RoomId, out
string Domain, out
string NickName)
3528 lock (this.mucRooms)
3538 Domain = NickName =
null;
3548 return !(Result is
null);
3551 internal async Task LeaveRoom(
string RoomId,
string Domain)
3553 string Jid = RoomId +
"@" +
Domain;
3556 lock (this.mucRooms)
3558 Changed = this.mucRooms.TryGetValue(Jid, out
RoomInfo Info) && Info.Permanent;
3559 this.mucRooms.Remove(Jid);
3563 await this.UpdatePermamentRooms();
3566 private async Task UpdatePermamentRooms()
3568 StringBuilder sb =
new StringBuilder();
3570 lock (this.mucRooms)
3572 foreach (
RoomInfo Rec
in this.mucRooms.Values)
3582 if (!
string.IsNullOrEmpty(Rec.
Password))
3596 private async Task LoadPermanentRooms()
3599 string[] Rows = s.Split(
CommonTypes.
CRLF, StringSplitOptions.RemoveEmptyEntries);
3601 lock (this.adminCommands)
3603 foreach (
string Row
in Rows)
3605 string[] Parts = Row.Split(
new string[] {
" | " }, StringSplitOptions.None);
3607 switch (Parts.Length)
3610 this.mucRooms[Parts[0] +
"@" + Parts[1]] =
new RoomInfo(Parts[0], Parts[1], Parts[2],
true);
3614 this.mucRooms[Parts[0] +
"@" + Parts[1]] =
new RoomInfo(Parts[0], Parts[1], Parts[2], Parts[3],
true);
3621 await this.RejoinRooms();
3630 lock (this.mucRooms)
3632 Infos =
new RoomInfo[this.mucRooms.Count];
3633 this.mucRooms.Values.CopyTo(Infos, 0);
3639 private async Task RejoinRooms()
3641 foreach (
RoomInfo Info
in this.GetRooms())
3642 await this.RejoinRoom(Info);
3645 private Task RejoinRoom(
RoomInfo Info)
3650 Gateway.MucClient.SetPresence(Info.RoomId, Info.Domain, Info.NickName, Networking.XMPP.Availability.Chat, null, null);
3652 Gateway.ScheduleEvent((P) => this.RejoinRoom(Info), DateTime.Now.AddMinutes(1), null);
3654 return Task.CompletedTask;
3656 },
null) ?? Task.CompletedTask;
3659 internal void CheckRoomsAlive()
3665 RoomInfo[] Infos = this.GetRooms();
3673 if (e.StanzaError is Networking.XMPP.StanzaErrors.NotAcceptableException)
3675 RoomInfo Info2 = (RoomInfo)e.State;
3676 Gateway.MucClient.EnterRoom(Info2.RoomId, Info2.Domain, Info2.NickName, Info2.Password, async (sender2, e2) =>
3679 await Gateway.MucClient.SetPresence(Info2.RoomId, Info2.Domain, Info2.NickName, Networking.XMPP.Availability.Chat, null, null);
3682 RoomInfo Info3 = (RoomInfo)e2.State;
3684 if (e2.StanzaError is Networking.XMPP.StanzaErrors.ForbiddenException)
3686 await this.LeaveRoom(Info3.RoomId, Info3.Domain);
3687 await Gateway.SendNotification(
"Left room `" + Info3.RoomId +
"@" + Info3.Domain +
"`; forbidden entry (blocked?).");
3689 else if (e2.StanzaError is Networking.XMPP.StanzaErrors.NotAuthorizedException)
3691 await this.LeaveRoom(Info3.RoomId, Info3.Domain);
3692 await Gateway.SendNotification(
"Left room `" + Info3.RoomId +
"@" + Info3.Domain +
"`; password changed.");
3694 else if (e2.StanzaError is Networking.XMPP.StanzaErrors.RegistrationRequiredException)
3696 await this.LeaveRoom(Info3.RoomId, Info3.Domain);
3697 await Gateway.SendNotification(
"Left room `" + Info3.RoomId +
"@" + Info3.Domain +
"`; no longer registered in room.");
3699 else if (e2.StanzaError is Networking.XMPP.StanzaErrors.ItemNotFoundException)
3701 await this.LeaveRoom(Info3.RoomId, Info3.Domain);
3702 await Gateway.SendNotification(
"Left room `" + Info3.RoomId +
"@" + Info3.Domain +
"`; room not found, or is locked for other purposes.");
3704 else if (e2.StanzaError is Networking.XMPP.StanzaErrors.ServiceUnavailableException)
3706 await this.LeaveRoom(Info3.RoomId, Info3.Domain);
3707 await Gateway.SendNotification(
"Left room `" + Info3.RoomId +
"@" + Info3.Domain +
"`; room is full.");
3709 else if (e2.StanzaError is Networking.XMPP.StanzaErrors.ConflictException)
3711 await this.LeaveRoom(Info3.RoomId, Info3.Domain);
3712 await Gateway.SendNotification(
"Left room `" + Info3.RoomId +
"@" + Info3.Domain +
"`; nick-name conflict.");
3719 return Task.CompletedTask;
3724 catch (Exception ex)
3734 private async Task LeaveAllRooms()
3737 int i, c =
Rooms.Length;
3738 TaskCompletionSource<bool>[] TaskCompletionSources =
new TaskCompletionSource<bool>[c];
3739 Task[] Tasks =
new Task[c];
3741 for (i = 0; i < c; i++)
3744 TaskCompletionSources[i] =
new TaskCompletionSource<bool>();
3745 Tasks[i] = TaskCompletionSources[i].Task;
3750 ((TaskCompletionSource<bool>)e.State)?.TrySetResult(true);
3751 return Task.CompletedTask;
3752 }, TaskCompletionSources[i]);
3755 _ = Task.Delay(5000).ContinueWith((
_) =>
3757 foreach (TaskCompletionSource<bool> T
in TaskCompletionSources)
3758 T.TrySetResult(
false);
3759 return Task.CompletedTask;
3762 await Task.WhenAll(Tasks);
3765 private async Task XmppClient_OnGroupChatMessage(
object Sender, Networking.XMPP.Events.MessageEventArgs e)
3771 (
string Message,
string _,
bool IsMarkdown) = await this.GetPlainText(e, DateTime.UtcNow.AddMinutes(-1));
3773 Task
_ = Task.Run(async () => await this.ProcessChatMessage(
Message, this.GetOccupantRealJid(e), e.ThreadID, async (Response, MessageId) =>
3775 KeyValuePair<string, string> P = await this.PrepareAdminResponse(Response, MessageId, IsMarkdown);
3777 MessageId = P.Value;
3780 Xml =
"<muteDiff xmlns='http://waher.se/Schema/Editing.xsd'/>";
3782 Xml +=
"<muteDiff xmlns='http://waher.se/Schema/Editing.xsd'/>";
3784 await
Gateway.
MucClient.SendCustomPrivateMessage(MessageId, RoomId,
Domain, NickName, Xml,
string.Empty, e.ThreadID,
string.Empty);
3792 if (this.consolidators is
null)
3795 this.consolidators.Removed += this.Consolidators_Removed;
3803 return e.
Value.DisposeAsync();
3806 private async Task MucClient_PrivateMessageReceived(
object Sender, Networking.XMPP.MUC.RoomOccupantMessageEventArgs e)
3808 if (!
string.IsNullOrEmpty(e.ThreadID) &&
3809 !(
this.consolidators is
null) &&
3812 string Response = this.GetMarkdown(e, DateTime.UtcNow.AddMinutes(-1),
false, out
string ReplaceObjectId, out
bool IsMarkdown);
3817 if (!
string.IsNullOrEmpty(e.Body))
3825 if (!
string.IsNullOrEmpty(ReplaceObjectId))
3832 if (!
string.IsNullOrEmpty(ReplaceObjectId))
3840 (
string Message,
string _,
bool IsMarkdown) = await this.GetPlainText(e, DateTime.UtcNow.AddMinutes(-1));
3842 Task
_ = Task.Run(async () => await this.ProcessChatMessage(
Message, this.GetOccupantRealJid(e), e.ThreadID, async (Response, MessageId) =>
3844 KeyValuePair<string, string> P = await this.PrepareAdminResponse(Response, MessageId, IsMarkdown);
3846 MessageId = P.Value;
3849 Xml =
"<muteDiff xmlns='http://waher.se/Schema/Editing.xsd'/>";
3851 Xml +=
"<muteDiff xmlns='http://waher.se/Schema/Editing.xsd'/>";
3853 await
Gateway.
MucClient.SendCustomPrivateMessage(MessageId, e.RoomId, e.Domain, e.NickName, Xml,
string.Empty, e.ThreadID,
string.Empty);
3860 private async Task<KeyValuePair<string, string>> PrepareAdminResponse(
string Response,
string MessageId,
bool IncomingWasMarkdown)
3864 if (IncomingWasMarkdown)
3869 if (
string.IsNullOrEmpty(MessageId))
3870 MessageId = Guid.NewGuid().ToString();
3872 Xml +=
"<replace id='" + MessageId +
"' xmlns='urn:xmpp:message-correct:0'/>";
3874 return new KeyValuePair<string, string>(Xml, MessageId);
3877 private Task MucClient_RoomDestroyed(
object Sender, Networking.XMPP.MUC.UserPresenceEventArgs e)
3879 lock (this.presenceByNickAndRoom)
3881 this.presenceByNickAndRoom.Remove(e.RoomJid);
3884 return Task.CompletedTask;
3887 private Task MucClient_OccupantPresence(
object Sender, Networking.XMPP.MUC.UserPresenceEventArgs e)
3889 lock (this.presenceByNickAndRoom)
3891 if (!this.presenceByNickAndRoom.TryGetValue(e.RoomJid, out SortedDictionary<CaseInsensitiveString, Networking.XMPP.MUC.UserPresenceEventArgs> ByNick))
3893 if (e.Availability == Networking.XMPP.Availability.Offline)
3898 this.presenceByNickAndRoom[e.RoomJid] = ByNick;
3902 if (!(ByNick is
null))
3904 if (e.Availability == Networking.XMPP.Availability.Offline)
3906 if (ByNick.Remove(e.NickName) && ByNick.Count == 0)
3907 this.presenceByNickAndRoom.
Remove(e.RoomId);
3910 ByNick[e.NickName] = e;
3914 return Task.CompletedTask;
3917 internal int GetNrOccupants(
string RoomJid,
string RoomId,
string Domain,
bool ExcludeSelf,
bool ExcludeOffline)
3923 if (!this.TryGetNickName(RoomId,
Domain, out OwnNick))
3929 lock (this.presenceByNickAndRoom)
3931 if (this.presenceByNickAndRoom.TryGetValue(RoomJid, out SortedDictionary<CaseInsensitiveString, Networking.XMPP.MUC.UserPresenceEventArgs> ByNick))
3933 if (!ExcludeSelf && !ExcludeOffline)
3934 return ByNick.Count;
3938 foreach (Networking.XMPP.MUC.UserPresenceEventArgs e in ByNick.Values)
3940 if (ExcludeOffline && !e.IsOnline)
3943 if (ExcludeSelf && !(OwnNick is
null) && Networking.XMPP.XmppClient.GetResource(e.From) == OwnNick)
3956 internal KeyValuePair<
CaseInsensitiveString, Networking.XMPP.MUC.UserPresenceEventArgs>[] GetOccupants(
string RoomJid)
3958 lock (this.presenceByNickAndRoom)
3960 if (!this.presenceByNickAndRoom.TryGetValue(RoomJid, out SortedDictionary<CaseInsensitiveString, Networking.XMPP.MUC.UserPresenceEventArgs> ByNick))
3966 ByNick.
CopyTo(Result, 0);
3972 private string GetOccupantRealJid(Networking.XMPP.Events.MessageEventArgs e)
3974 foreach (XmlNode N
in e.Message.ChildNodes)
3978 foreach (XmlNode N2
in E.ChildNodes)
3980 if (N2 is XmlElement E2 &&
3981 E2.LocalName ==
"address" &&
3982 E2.NamespaceURI == E.NamespaceURI &&
3983 E2.HasAttribute(
"type") &&
3984 E2.GetAttribute(
"type") ==
"ofrom")
3992 string OccupantJid = e.From;
3997 lock (this.presenceByNickAndRoom)
3999 if (this.presenceByNickAndRoom.TryGetValue(RoomJid, out SortedDictionary<CaseInsensitiveString, Networking.XMPP.MUC.UserPresenceEventArgs> ByNick) &&
4000 ByNick.TryGetValue(NickName, out Networking.XMPP.MUC.UserPresenceEventArgs e2))
4002 return string.
IsNullOrEmpty(e2.FullJid) ? OccupantJid : e2.FullJid;
4011 return this.ProcessChatMessage(s, From,
null, ThreadId, ResponseCallback, Channel);
4018 if (
string.IsNullOrEmpty(s))
4026 if (
string.IsNullOrEmpty(ThreadId) ||
4027 this.consolidators is
null ||
4030 string Msg =
"Supressing query from self. No outstanding consolidation query registered: " + s;
4038 else if (!await IsAdmin(From,
User))
4040 string Msg =
"Ignoring incoming chat message (sender is not an administrator): " + s;
4048 Channel?.
Information(
"Chat command string accepted.");
4050 if (this.chatSessions is
null)
4053 this.chatSessions.Removed += this.ChatSessions_Removed;
4059 this.chatSessions[From] = Session;
4062 if (!Session.TryGetVariable(
" State ", out
Variable v) || !(v.ValueObject is
ChatState State))
4067 Folder = PackagesFolder
4069 Session[
" State "] = State;
4072 StringBuilder sb =
new StringBuilder();
4073 List<string> ArgumentsList =
new List<string>();
4074 LinkedList<IAdminCommand> Commands;
4078 string CommandName =
null;
4080 bool InQuote =
false;
4081 bool Escape =
false;
4083 foreach (
char ch
in s)
4085 if (
char.IsWhiteSpace(ch) && !InQuote)
4089 if (CommandName is
null)
4090 CommandName = sb.ToString().ToLower();
4092 ArgumentsList.Add(sb.ToString());
4104 else if (ch ==
'\\')
4123 if (CommandName is
null)
4124 CommandName = sb.ToString().ToLower();
4126 ArgumentsList.Add(sb.ToString());
4129 if (CommandName is
null)
4135 Arguments = ArgumentsList.ToArray();
4137 lock (this.adminCommands)
4139 if (this.adminCommands.Count == 0)
4145 TypeInfo TI = T.GetTypeInfo();
4147 if (TI.IsAbstract || TI.IsInterface || TI.IsGenericTypeDefinition)
4152 string s2 =
Command.Name.ToLower();
4153 if (!this.adminCommands.TryGetValue(s2, out Commands))
4155 Commands =
new LinkedList<IAdminCommand>();
4156 this.adminCommands[s2] = Commands;
4159 Commands.AddLast(Command);
4161 string[] Aliases =
Command.Aliases;
4163 if (!(Aliases is
null))
4165 foreach (
string Alias
in Aliases)
4167 s2 = Alias.ToLower();
4168 if (!this.adminCommands.TryGetValue(s2, out Commands))
4170 Commands =
new LinkedList<IAdminCommand>();
4171 this.adminCommands[s2] = Commands;
4174 Commands.AddLast(Command);
4178 catch (Exception ex)
4189 if (this.adminCommands.TryGetValue(CommandName, out Commands))
4193 if (Alternative.
AppliesTo(s, Arguments, out Details))
4202 if (Command is
null)
4204 if (Arguments.Length == 0 && !(Commands is
null))
4205 await this.ProcessChatMessage(
"help " + s, From,
User, ThreadId, ResponseCallback, Channel);
4206 else if (State.CommandMode)
4208 foreach (
string Row
in s.Split(
CommonTypes.
CRLF, StringSplitOptions.RemoveEmptyEntries))
4209 await this.ExecuteCommand(From, Row.Trim(), State,
false, ResponseCallback);
4213 StringBuilder PrintOutput =
new StringBuilder();
4214 StringWriter PrintWriter =
new StringWriter(PrintOutput);
4215 Session.ConsoleOut = PrintWriter;
4218 AdminScriptRec Rec =
new AdminScriptRec()
4220 ResponseCallback = ResponseCallback
4225 return this.ReturnScriptResult(e.
Preview, Rec);
4229 Session.OnPreview += Preview;
4249 catch (Exception ex)
4255 Session.OnPreview -= Preview;
4258 Session[
"Ans"] = Result;
4260 string Printed = PrintOutput.ToString().Trim();
4261 PrintOutput.Clear();
4263 if (!
string.IsNullOrEmpty(Printed))
4264 await SendPrinted(Printed,
string.Empty, ResponseCallback);
4266 await this.ReturnScriptResult(Result, Rec);
4270 await
Command.Execute(State, ArgumentsList.ToArray(), s, Details, ResponseCallback);
4272 catch (Exception ex)
4274 await ReturnError(ex, ResponseCallback);
4283 StringBuilder Markdown =
new StringBuilder();
4285 Markdown.AppendLine(
"An error occurred when processing request:");
4286 Markdown.AppendLine();
4287 Markdown.AppendLine(
"<font class=\"error\">");
4288 Markdown.AppendLine();
4290 Markdown.AppendLine();
4291 Markdown.AppendLine(
"```");
4293 Markdown.AppendLine(
"```");
4294 Markdown.AppendLine();
4295 Markdown.AppendLine(
"</font>");
4297 await ResponseCallback(Markdown.ToString(),
string.Empty);
4299 catch (Exception ex2)
4305 private class AdminScriptRec
4307 public string MessageId =
string.Empty;
4311 private async Task ReturnScriptResult(
IElement Result, AdminScriptRec Rec)
4313 StringBuilder sb =
new StringBuilder();
4318 if (Result is
Graph G)
4320 sb.AppendLine(
"```Graph");
4323 sb.AppendLine(
"```");
4325 Rec.MessageId = await Rec.ResponseCallback(sb.ToString(), Rec.MessageId);
4329 SKData Data = Img.Encode(SKEncodedImageFormat.Png, 100);
4330 byte[] Bin = Data.ToArray();
4333 sb.Append(
";
4334 sb.Append(
System.Convert.ToBase64String(Bin, 0, Bin.Length));
4337 Rec.MessageId = await Rec.ResponseCallback(sb.ToString(), Rec.MessageId);
4343 if (ex is AggregateException ex2)
4347 foreach (Exception ex3
in ex2.InnerExceptions)
4349 sb.AppendLine(ex3.Message);
4353 Rec.MessageId = await SendErrorMessage(
MarkdownDocument.
Encode(sb.ToString()), Rec.MessageId, Rec.ResponseCallback);
4356 Rec.MessageId = await SendErrorMessage(
MarkdownDocument.
Encode(ex.Message), Rec.MessageId, Rec.ResponseCallback);
4362 foreach (
string s3
in M.ColumnNames)
4371 foreach (
string _ in M.ColumnNames)
4378 for (y = 0; y < M.Rows; y++)
4380 for (x = 0; x < M.Columns; x++)
4384 object Item = M.GetElement(x, y).AssociatedObjectValue;
4385 if (!(Item is
null))
4387 if (Item is
string s3)
4394 s3 = s3.Replace(
"\r\n",
"\n").Replace(
"\r",
"\n").Replace(
"\n",
"<br/>");
4403 Rec.MessageId = await Rec.ResponseCallback(sb.ToString(), Rec.MessageId);
4409 internal bool TryGetAdminCommand(
string CommandName, out LinkedList<IAdminCommand> Command)
4411 lock (this.adminCommands)
4413 return this.adminCommands.TryGetValue(CommandName, out Command);
4417 internal string[] AdminCommands
4423 lock (this.adminCommands)
4425 Result =
new string[this.adminCommands.Count];
4426 this.adminCommands.Keys.CopyTo(Result, 0);
4433 internal static async Task SendPrinted(
string Msg,
string MessageId,
ResponseCallbackHandler ResponseCallback)
4437 foreach (
string Row
in Msg.Replace(
"\r\n",
"\n").Replace(
'\r',
'\n').Split(
'\n'))
4438 await ResponseCallback(
"<font style=\"color:" + PrintColor +
"\">" + Row +
"</font>", MessageId);
4441 internal static Task<string> SendResult(
string Msg,
string MessageId,
ResponseCallbackHandler ResponseCallback)
4443 StringBuilder sb =
new StringBuilder();
4447 sb.Append(
"<font class=\"result\">`");
4449 sb.Append(
"`</font>");
4453 sb.AppendLine(
"<font class=\"result\">");
4455 sb.AppendLine(
"```");
4458 Msg = Msg.Replace(
"\r\n",
"\n").Replace(
"\r",
"\n");
4459 foreach (
string Row
in Msg.Split(
'\n'))
4462 sb.AppendLine(
"```");
4464 sb.AppendLine(
"</font>");
4467 return ResponseCallback(sb.ToString(), MessageId);
4470 internal static Task<string> SendErrorMessage(
string Msg,
string MessageId,
ResponseCallbackHandler ResponseCallback)
4472 StringBuilder sb =
new StringBuilder();
4474 sb.AppendLine(
"<font class=\"error\">");
4478 sb.AppendLine(
"</font>");
4480 return ResponseCallback(sb.ToString(), MessageId);
4485 if (
string.IsNullOrEmpty(Command))
4494 s = Path.GetFullPath(Path.Combine(State.
Folder, Command));
4495 Exists = File.Exists(s);
4505 if (s.Length < AppDataLen ||
string.Compare(
Gateway.
AppDataFolder, s[..AppDataLen],
true) != 0)
4507 await SendErrorMessage(
"Access to files outside of the application data folder not permitted.",
string.Empty, ResponseCallback);
4511 if (!
string.IsNullOrEmpty(To))
4512 await ResponseCallback(this.DownloadableFile(s, State, To),
string.Empty);
4516 int i =
Command.IndexOfAny(
new char[] {
' ',
'\t' });
4526 switch (s.ToLower())
4528 case "analyzeclock":
4537 if (Shell &&
string.Compare(s,
"install",
true) == 0)
4548 s = s[..^3] +
"dll";
4555 await SendErrorMessage(
"File not found: `" + s[..^3] +
"exe`. Unable to execute command.",
string.Empty, ResponseCallback);
4640 await SendErrorMessage(
"Command not allowed.",
string.Empty, ResponseCallback);
4645 return ChangeDirectory(State,
".", ResponseCallback);
4648 return ChangeDirectory(State,
"..", ResponseCallback);
4652 return ChangeDirectory(State, Command[s.Length..].Trim(), ResponseCallback);
4658 string Pattern =
Command[s.Length..].Trim();
4659 if (
string.IsNullOrEmpty(Pattern))
4662 DirectoryInfo Folder =
new DirectoryInfo(State.
Folder);
4663 DirectoryInfo[] Folders;
4665 StringBuilder Markdown =
new StringBuilder();
4666 Dictionary<string, long> Sizes =
new Dictionary<string, long>();
4667 Dictionary<string, DateTime> DateTimes =
new Dictionary<string, DateTime>();
4668 string MaxSizeFileName =
null;
4669 string MaxDateTimeFileName =
null;
4670 DateTime MaxDateTime = DateTime.MinValue;
4671 long MaxSize =
int.MinValue;
4675 Markdown.AppendLine(
"| Name | Size | Date | Time |");
4676 Markdown.AppendLine(
"|:-----|-----:|:----:|:----:|");
4678 Folders = Folder.GetDirectories(Pattern, SearchOption.TopDirectoryOnly);
4680 foreach (DirectoryInfo DirInfo
in Folders)
4684 DateTimes[DirInfo.Name] = DirInfo.LastWriteTime;
4685 if (DirInfo.LastWriteTime > MaxDateTime)
4687 MaxDateTime = DirInfo.LastWriteTime;
4688 MaxDateTimeFileName = DirInfo.Name;
4697 foreach (DirectoryInfo DirInfo
in Folders)
4699 Markdown.Append(
"| ");
4701 Markdown.Append(
" | \\<DIR\\> | ");
4703 if (DateTimes.TryGetValue(DirInfo.Name, out TP))
4705 if (IsMax = (DirInfo.Name == MaxDateTimeFileName))
4706 Markdown.Append(
"**");
4708 Markdown.Append(TP.ToShortDateString());
4711 Markdown.Append(
"**");
4713 Markdown.Append(
" | ");
4716 Markdown.Append(
"**");
4718 Markdown.Append(TP.ToLongTimeString());
4721 Markdown.Append(
"**");
4723 Markdown.AppendLine(
" |");
4726 Markdown.AppendLine(
"N/A ||");
4729 Files = Folder.GetFiles(Pattern, SearchOption.TopDirectoryOnly);
4731 MaxDateTime = DateTime.MinValue;
4752 if (
FileInfo.LastWriteTime > MaxDateTime)
4754 MaxDateTime =
FileInfo.LastWriteTime;
4755 MaxDateTimeFileName =
FileInfo.Name;
4766 Markdown.Append(
"| ");
4767 Markdown.Append(this.DownloadableFile(
FileInfo.Name, State, To));
4768 Markdown.Append(
" | ");
4770 if (Sizes.TryGetValue(
FileInfo.Name, out
long Size))
4772 if (IsMax = (
FileInfo.Name == MaxSizeFileName))
4773 Markdown.Append(
"**");
4778 Markdown.Append(
"**");
4781 Markdown.Append(
"N/A");
4783 Markdown.Append(
" | ");
4785 if (DateTimes.TryGetValue(
FileInfo.Name, out TP))
4787 if (IsMax = (
FileInfo.Name == MaxDateTimeFileName))
4788 Markdown.Append(
"**");
4790 Markdown.Append(TP.ToShortDateString());
4793 Markdown.Append(
"**");
4795 Markdown.Append(
" | ");
4798 Markdown.Append(
"**");
4800 Markdown.Append(TP.ToLongTimeString());
4803 Markdown.Append(
"**");
4805 Markdown.AppendLine(
" |");
4808 Markdown.AppendLine(
"N/A ||");
4811 await ResponseCallback(Markdown.ToString(),
string.Empty);
4821 if (s.StartsWith(
"cd.") || s.StartsWith(
"cd" + Path.DirectorySeparatorChar))
4822 return ChangeDirectory(State, Command[2..].Trim(), ResponseCallback);
4826 await SendErrorMessage(
"Executing files not allowed.",
string.Empty, ResponseCallback);
4834 ProcessStartInfo StartInfo;
4836 switch (Environment.OSVersion.Platform)
4838 case PlatformID.Win32S:
4839 case PlatformID.Win32Windows:
4840 case PlatformID.Win32NT:
4841 case PlatformID.WinCE:
4842 StartInfo =
new ProcessStartInfo()
4844 FileName =
"cmd.exe",
4845 Arguments =
"/S /C \" " +
Command.Trim() +
" \"",
4846 WorkingDirectory = State.Folder
4850 case PlatformID.Unix:
4851 case PlatformID.MacOSX:
4852 StartInfo =
new ProcessStartInfo()
4854 FileName =
"/bin/zsh",
4855 Arguments =
"-c \" " +
Command.Trim() +
" \"",
4856 WorkingDirectory = State.Folder
4861 await SendErrorMessage(
"Not supported on this operating system.",
string.Empty, ResponseCallback);
4867 StartInfo.UseShellExecute =
true;
4868 StartInfo.WindowStyle = ProcessWindowStyle.Normal;
4872 StartInfo.CreateNoWindow =
true;
4873 StartInfo.ErrorDialog =
false;
4874 StartInfo.RedirectStandardInput =
false;
4875 StartInfo.RedirectStandardError =
true;
4876 StartInfo.RedirectStandardOutput =
true;
4877 StartInfo.UseShellExecute =
false;
4878 StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
4882 new KeyValuePair<string, object>(
"FileName", StartInfo.FileName),
4883 new KeyValuePair<string, object>(
"Arguments", StartInfo.Arguments),
4884 new KeyValuePair<string, object>(
"WorkingDirectory", StartInfo.WorkingDirectory),
4885 new KeyValuePair<string, object>(
"UseShellExecute", StartInfo.UseShellExecute),
4886 new KeyValuePair<string, object>(
"WindowStyle", StartInfo.WindowStyle),
4887 new KeyValuePair<string, object>(
"CreateNoWindow", StartInfo.CreateNoWindow),
4888 new KeyValuePair<string, object>(
"ErrorDialog", StartInfo.ErrorDialog),
4889 new KeyValuePair<string, object>(
"RedirectStandardInput", StartInfo.RedirectStandardInput),
4890 new KeyValuePair<string, object>(
"RedirectStandardError", StartInfo.RedirectStandardError),
4891 new KeyValuePair<string, object>(
"RedirectStandardOutput", StartInfo.RedirectStandardOutput));
4893 Process P =
new Process()
4895 StartInfo = StartInfo
4904 Thread T =
new Thread((e) =>
4910 LinkedListNode<Process> ProcessNode = State.
Processes.AddLast(P);
4916 bool Output =
false;
4918 s = P.StandardOutput.ReadToEnd().Trim();
4920 if (!
string.IsNullOrEmpty(s))
4922 StringBuilder Markdown =
new StringBuilder();
4924 Markdown.AppendLine(
"```");
4925 Markdown.AppendLine(s.Trim());
4926 Markdown.AppendLine(
"```");
4928 ResponseCallback(Markdown.ToString(),
string.Empty);
4932 s = P.StandardError.ReadToEnd().Trim();
4933 if (!
string.IsNullOrEmpty(s))
4935 StringBuilder Markdown =
new StringBuilder();
4937 Markdown.AppendLine(
"<font class=\"error\">");
4938 Markdown.AppendLine();
4939 Markdown.AppendLine(
"```");
4940 Markdown.AppendLine(s.Trim());
4941 Markdown.AppendLine(
"```");
4942 Markdown.AppendLine();
4943 Markdown.AppendLine(
"</font>");
4945 ResponseCallback(Markdown.ToString(),
string.Empty);
4950 ResponseCallback(
"The command executed with no response.",
string.Empty);
4952 while (!P.HasExited);
4961 catch (Exception ex)
4967 IsBackground =
true,
4968 Name =
"CMD Thread",
4969 Priority = ThreadPriority.BelowNormal
4977 internal string DownloadableFile(
string s,
ChatState State,
string To)
4979 if (!File.Exists(s))
4985 using (FileStream fs = File.Open(s, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
4990 FileName = Path.GetFileName(s),
4997 "?jid=" + HttpUtility.UrlEncode(To) +
"&t=" +
Token);
5004 string s = Path.GetFullPath(Path.Combine(State.
Folder, NewFolder)) + Path.DirectorySeparatorChar;
5007 if (s.Length < AppDataLen ||
string.Compare(
Gateway.
AppDataFolder, s[..AppDataLen],
true) != 0)
5009 SendErrorMessage(
"Access to folders outside of the application data folder not permitted.",
string.Empty, ResponseCallback);
5012 else if (!Directory.Exists(s))
5014 SendErrorMessage(
"Folder does not exist",
string.Empty, ResponseCallback);
5020 ResponseCallback(
"New folder is `" + s +
"`",
string.Empty);
5033 if (this.chatSessions is
null || !this.chatSessions.
TryGetValue(HttpUtility.UrlDecode(Jid), out
Variables Session))
5036 if (!Session.TryGetVariable(
" State ", out
Variable v) ||
5038 !State.Files.TryGetValue(
Token, out Admin.FileInfo Rec))
5043 if (Rec.FileName != HttpUtility.UrlDecode(Request.
SubPath[1..]))
5046 if (
string.Compare(Path.GetExtension(Rec.FileName),
".xml",
true) == 0)
5048 XmlReaderSettings ReaderSettings =
new XmlReaderSettings()
5051 CheckCharacters =
false,
5052 ConformanceLevel = ConformanceLevel.Document,
5053 DtdProcessing = DtdProcessing.Ignore,
5054 IgnoreComments =
false,
5055 IgnoreProcessingInstructions =
false,
5056 IgnoreWhitespace =
true,
5057 ValidationFlags = System.Xml.Schema.XmlSchemaValidationFlags.None
5059 XmlWriterSettings WriterSettings =
new XmlWriterSettings()
5062 CheckCharacters =
false,
5063 CloseOutput =
false,
5064 ConformanceLevel = ConformanceLevel.Document,
5065 Encoding = Encoding.UTF8,
5068 NamespaceHandling = NamespaceHandling.OmitDuplicates,
5069 NewLineChars =
"\r\n",
5070 NewLineHandling = NewLineHandling.Replace,
5071 NewLineOnAttributes =
false,
5072 OmitXmlDeclaration =
false,
5073 WriteEndDocumentOnClose =
true
5076 using FileStream fs = File.Open(Rec.Path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
5077 using XmlReader r = XmlReader.Create(fs, ReaderSettings);
5081 using XmlWriter w = XmlWriter.Create(TempFile, WriterSettings);
5083 while (await r.ReadAsync())
5087 case XmlNodeType.XmlDeclaration:
5091 case XmlNodeType.ProcessingInstruction:
5092 string Url = r.Value;
5096 if ((i = Url.IndexOf(s =
Gateway.
RootFolder, StringComparison.CurrentCultureIgnoreCase)) >= 0 ||
5099 Url = Url.Remove(i, s.Length - 1);
5101 j = Url.IndexOf(
'"', i);
5103 Url = Url.Remove(i, j - i).Insert(i, Url[i..j].Replace(Path.DirectorySeparatorChar,
'/'));
5106 await w.WriteProcessingInstructionAsync(r.Name, Url);
5109 case XmlNodeType.Attribute:
5110 await w.WriteAttributeStringAsync(r.Prefix, r.LocalName, r.NamespaceURI, r.Value);
5113 case XmlNodeType.CDATA:
5114 await w.WriteCDataAsync(r.Value);
5117 case XmlNodeType.Comment:
5118 await w.WriteCommentAsync(r.Value);
5121 case XmlNodeType.EntityReference:
5122 await w.WriteEntityRefAsync(r.Name);
5125 case XmlNodeType.Text:
5126 case XmlNodeType.SignificantWhitespace:
5127 await w.WriteStringAsync(r.Value);
5130 case XmlNodeType.Whitespace:
5134 case XmlNodeType.Element:
5135 await w.WriteStartElementAsync(r.Prefix, r.LocalName, r.NamespaceURI);
5137 bool IsEmpty = r.IsEmptyElement;
5139 if (r.HasAttributes && r.MoveToFirstAttribute())
5141 await w.WriteAttributeStringAsync(r.Prefix, r.LocalName, r.NamespaceURI, r.Value);
5143 while (r.MoveToNextAttribute())
5144 await w.WriteAttributeStringAsync(r.Prefix, r.LocalName, r.NamespaceURI, r.Value);
5148 w.WriteEndElement();
5151 case XmlNodeType.EndElement:
5152 await w.WriteEndElementAsync();
5155 case XmlNodeType.Document:
5156 case XmlNodeType.DocumentFragment:
5157 case XmlNodeType.DocumentType:
5158 case XmlNodeType.EndEntity:
5159 case XmlNodeType.Entity:
5160 case XmlNodeType.Notation:
5165 catch (XmlException)
5169 catch (Exception ex)
5172 ExceptionDispatchInfo.Capture(ex).Throw();
5175 Response.OnResponseSent += (Sender, e) =>
5178 return Task.CompletedTask;
5181 DateTime LastWriteTime = File.GetLastWriteTimeUtc(Rec.Path);
5183 Rec.ETag, LastWriteTime,
false, Response);
5188 File.GetLastWriteTimeUtc(Rec.Path),
false, Response);
5196 foreach (Process P
in State.Processes)
5202 catch (Exception ex)
5208 State.Processes.Clear();
5211 return Task.CompletedTask;
5222 if (!(Posted is Dictionary<string, string> Form))
5225 if (!Form.TryGetValue(
"g-recaptcha-response", out
string RecaptchaResponse))
5239 return SendMailMessage(To, Subject, Markdown, Array.Empty<
EmbeddedContent>());
5256 if (
string.IsNullOrEmpty(From))
5259 return SendMailMessage(From, To, Subject, Markdown, Attachments);
5269 public static Task<bool>
SendMailMessage(
string From,
string To,
string Subject,
string Markdown)
5271 return SendMailMessage(From, To, Subject, Markdown, Array.Empty<
EmbeddedContent>());
5286 if (
string.IsNullOrEmpty(From))
5289 return SendMailMessage(
5301 return instance?.xmppServer?.
SendMailMessage(From, To, Subject, Markdown) ?? Task.FromResult(
false);
5316 public static Task<bool>
SendMailMessage(
string SmtpHost,
int SmtpPort,
string UserName,
string Password,
5317 string From,
string To,
string Subject,
string Markdown)
5319 return SendMailMessage(SmtpHost, SmtpPort, UserName, Password, From, To, Subject, Markdown, Array.Empty<
EmbeddedContent>());
5335 public static async Task<bool>
SendMailMessage(
string SmtpHost,
int SmtpPort,
string UserName,
string Password,
5336 string From,
string To,
string Subject,
string Markdown, params
EmbeddedContent[] Attachments)
5338 string Styles =
string.Empty;
5340 if (!(Attachments is
null))
5342 List<EmbeddedContent> Attachments2 =
null;
5343 bool Changed =
false;
5362 Styles += CssDocument2.Css;
5368 Attachments2 ??=
new List<EmbeddedContent>();
5373 Attachments = Attachments2?.ToArray();
5377 StringBuilder sb =
new StringBuilder();
5379 sb.AppendLine(
"<html>");
5380 sb.AppendLine(
"<head>");
5382 if (!
string.IsNullOrEmpty(Styles))
5384 sb.AppendLine(
"<style>");
5385 sb.AppendLine(Styles);
5386 sb.AppendLine(
"</style>");
5389 sb.AppendLine(
"</head>");
5390 sb.AppendLine(
"<body>");
5392 sb.AppendLine(
"</body>");
5393 sb.AppendLine(
"</html>");
5395 string HTML = sb.ToString();
5401 ContentType =
"text/html; charset=utf-8",
5402 Raw = Encoding.UTF8.GetBytes(HTML)
5406 ContentType =
"text/plain; charset=utf-8",
5407 Raw = Encoding.UTF8.GetBytes(PlainText)
5411 ContentType =
"text/markdown; charset=utf-8",
5412 Raw = Encoding.UTF8.GetBytes(Markdown)
5422 if (!(Attachments is
null) && Attachments.Length > 0)
5427 ContentType = ContentType,
5430 Array.Copy(Attachments, 0, Mixed, 1, Attachments.Length);
5439 KeyValuePair<string, string>[] Headers =
new KeyValuePair<string, string>[]
5441 new KeyValuePair<string, string>(
"MIME-VERSION",
"1.0"),
5442 new KeyValuePair<string, string>(
"FROM", From),
5443 new KeyValuePair<string, string>(
"TO", To),
5444 new KeyValuePair<string, string>(
"SUBJECT", Subject),
5446 new KeyValuePair<string, string>(
"IMPORTANCE",
"normal"),
5447 new KeyValuePair<string, string>(
"X-PRIORITY",
"3"),
5448 new KeyValuePair<string, string>(
"MESSAGE-ID", Guid.NewGuid().ToString()),
5449 new KeyValuePair<string, string>(
"CONTENT-TYPE", ContentType)
5452 int i = To.IndexOf(
'@');
5454 throw new ArgumentException(
"Invalid mail address: " + To, nameof(To));
5456 string Domain = To[(i + 1)..].Trim();
5458 return await (instance?.smtpServer?.SendMessage(
Domain, SmtpHost, SmtpPort, UserName, Password, From, To, Headers, BodyBin, DateTime.Now) ?? Task.FromResult(
false));
5462 "CPU usage is above 75% for 10 minutes.",
5463 "CPU usage is below 75% for 10 minutes.",
5464 "CPU usage is above 90% for 30 minutes.",
5465 "CPU usage is below 90% for 30 minutes.");
5467 "Free Memory available is below 1000 MB for 30 seconds.",
5468 "Free Memory available is above 1000 MB for 30 seconds.",
5469 "Free Memory available is below 200 MB for 30 seconds.",
5470 "Free Memory available is above 200 MB for 30 seconds.");
5472 "Free Hard Disk available is below 10 GB for 30 seconds.",
5473 "Free Hard Disk available is above 10 GB for 30 seconds.",
5474 "Free Hard Disk available is below 2 GB for 30 seconds.",
5475 "Free Hard Disk available is above 2 GB for 30 seconds.");
5477 "Allocated Memory is above 1500 MB for 30 seconds.",
5478 "Allocated Memory is below 1500 MB for 30 seconds.",
5479 "Allocated Memory is above 1900 MB for 30 seconds.",
5480 "Allocated Memory is below 1900 MB for 30 seconds.");
5481 private MethodInfo getCounter2 =
null;
5482 private MethodInfo getCounter3 =
null;
5483 private MethodInfo getCpuValue =
null;
5484 private MethodInfo getFreeMemoryValue =
null;
5485 private object cpuCounter =
null;
5486 private object freeMemoryCounter =
null;
5488 private async
void SampleTimerEventHandler(
object Sender)
5492 if (this.getCounter2 is
null)
5494 Type T =
Types.
GetType(
"Waher.IoTGateway.Svc.PerformanceCounters");
5495 this.getCounter2 = T?.GetMethod(
"GetCounter",
new Type[] { typeof(
string), typeof(
string) });
5496 this.getCounter3 = T?.GetMethod(
"GetCounter",
new Type[] { typeof(
string), typeof(
string), typeof(
string) });
5498 this.cpuCounter = this.getCounter3?.Invoke(
null,
new object[] {
"Processor",
"_Total",
"% Processor Time" });
5499 this.getCpuValue = this.cpuCounter?.GetType()?.GetMethod(
"NextValue", Array.Empty<Type>());
5501 this.freeMemoryCounter = this.getCounter2?.Invoke(
null,
new object[] {
"Memory",
"Available MBytes" });
5502 this.freeMemoryCounter ??= this.getCounter2?.Invoke(
null,
new object[] {
"Minne",
"Tillgängliga megabyte" });
5504 this.getFreeMemoryValue = this.freeMemoryCounter?.GetType()?.GetMethod(
"NextValue", Array.Empty<Type>());
5509 await this.performanceStatistics.
Sample(
"CPU", CPU);
5510 cpuMonitor.Sample(CPU);
5523 if (!
string.IsNullOrEmpty(appDataDrive))
5525 DriveInfo Drive =
new DriveInfo(appDataDrive);
5526 double FreeHD = Drive.AvailableFreeSpace / 1073741824.0;
5527 await this.performanceStatistics.
Sample(
"FreeHD",
FreeHD);
5528 freeHDMonitor.Sample(
FreeHD);
5531 catch (Exception ex)
5593 private async Task Export_OnExportKeyFolderUpdated(
object Sender, EventArgs e)
5599 catch (Exception ex)
5605 private async Task Export_OnExportFolderUpdated(
object Sender, EventArgs e)
5611 catch (Exception ex)
5617 private async Task JwtRequest(
object Sender,
IqEventArgs e)
5624 await e.
IqErrorBadRequest(e.
To,
"Number of seconds token is to be valid must be a positive integer.",
"en");
5637 int IssuedAt = (int)Math.Round(DateTime.UtcNow.Subtract(
JSON.
UnixEpoch).TotalSeconds);
5638 int Expires = IssuedAt + Seconds;
5647 StringBuilder Xml =
new StringBuilder();
5649 Xml.Append(
"<token xmlns='");
5650 Xml.Append(NamespaceJwt);
5653 Xml.Append(
"</token>");
5659 catch (Exception ex)
5670 internal string CreateJwtToken(params KeyValuePair<string, object>[] Claims)
5672 return this.CreateJwtToken((IEnumerable<KeyValuePair<string, object>>)Claims);
5680 internal string CreateJwtToken(IEnumerable<KeyValuePair<string, object>> Claims)
5691 internal bool ValidateJwtToken(
string Token)
5693 return this.ValidateJwtToken(
Token,
false);
5703 internal bool ValidateJwtToken(
string Token,
bool CheckIssuer)
5705 return this.ValidateJwtToken(
Token, CheckIssuer, out
_);
5716 internal bool ValidateJwtToken(
string Token,
bool CheckIssuer, out
JwtToken ParsedToken)
5721 return this.ValidateJwtToken(ParsedToken, CheckIssuer);
5732 return this.ValidateJwtToken(
Token,
false);
5742 internal bool ValidateJwtToken(
JwtToken Token,
bool CheckIssuer)
5750 internal static Task<IClientConnection> JwtAuthenticate(
HttpRequest Request)
5755 public static async Task<IClientConnection> JwtAuthenticate(
HttpRequest Request,
5759 if (
string.IsNullOrEmpty(TokenStr))
5763 IRecipient Recipient = await HttpxResponse.Server.TryGetRecipient(HttpxResponse.To, HttpxResponse.From);
5777 new KeyValuePair<string, object>(
"Reason",
Reason));
5786 throw new ForbiddenException(Request,
"JWT token obsoleted, due to XMPP disconnect.");
5794 return this.ProxyResource_AddSsoInformation(Sender, e,
true);
5799 return this.ProxyResource_AddSsoInformation(Sender, e,
false);
5809 return Task.CompletedTask;
5812 return this.AddSsoInformation(
User, e, Encrypted);
5814 return this.AddSsoInformation(User2, e, Encrypted);
5816 return Task.CompletedTask;
5821 string EncryptedPrefix = Encrypted ?
"e" :
"u";
5826 if (
string.IsNullOrEmpty(
JwtToken))
5846 private static async Task TransferIdDelivered(
object Sender, Networking.XMPP.Events.MessageEventArgs e)
5850 if (e.From != OnboardingNeuron)
5854 bool Deleted =
XML.
Attribute(e.Content,
"deleted",
false);
5859 await WebServices.Agent.Account.Transfer.TransferCodeDelivered(Code);
5862 private async Task ContractsClient_GetLocalSchema(
object Sender, Networking.XMPP.Contracts.EventArguments.SchemaReferenceEventArgs e)
5866 if (e.SchemaDigest is
null)
5883 private async Task ContractsClient_ValidateLocalSignature(
object Sender, Networking.XMPP.Contracts.EventArguments.ValidateSignatureEventArgs e)
5890 if (!(Identity is
null))
5892 e.Valid = Identity.ValidateSignature(e.Data, e.Signature);
5896 StringBuilder Xml =
new StringBuilder();
5897 Identity.Serialize(Xml,
true,
true,
true,
true,
true,
true,
true,
null, this.legalComponent);
5905 private Task ContractsClient_GetLocalPublicKey(
object Sender, Networking.XMPP.Contracts.EventArguments.PublicKeyEventArgs e)
5909 Tuple<Networking.XMPP.IE2eEndpoint, DateTime?, DateTime?> P =
5912 if (!(P.Item1 is
null) && P.Item2.HasValue)
5913 e.ReturnKey(P.Item1, P.Item2.Value, P.Item3);
5916 return Task.CompletedTask;
5919 #region Encrypted files
5929 return LoadEncryptedFile(FileName, Salt,
null);
5941 using FileStream File =
System.IO.File.OpenRead(FileName);
5942 Aes Aes = Aes.Create();
5944 Aes.BlockSize = 128;
5946 Aes.Mode = CipherMode.CBC;
5947 Aes.Padding = PaddingMode.Zeros;
5949 byte[] Key =
new byte[32];
5950 byte[] IV =
new byte[16];
5952 Buffer.BlockCopy(Salt, 0, Key, 0, 32);
5953 Buffer.BlockCopy(Salt, 32, IV, 0, 16);
5955 using ICryptoTransform Decryptor = Aes.CreateDecryptor(Key, IV);
5956 using CryptoStream DecryptedFile =
new CryptoStream(File, Decryptor, CryptoStreamMode.Read);
5960 long c = Size.Value;
5961 if (c >
int.MaxValue)
5962 throw new IOException(
"File too large.");
5965 byte[] Bin = await DecryptedFile.ReadAllAsync(c0);
5971 using MemoryStream ms =
new MemoryStream();
5972 await DecryptedFile.CopyToAsync(ms);
5973 return ms.ToArray();
5985 using MemoryStream ms =
new MemoryStream(Data);
5986 return SaveEncryptedFile(FileName, Salt, ms);
5997 using FileStream File =
System.IO.File.Create(FileName);
5998 Aes Aes = Aes.Create();
6000 Aes.BlockSize = 128;
6002 Aes.Mode = CipherMode.CBC;
6003 Aes.Padding = PaddingMode.Zeros;
6005 byte[] Key =
new byte[32];
6006 byte[] IV =
new byte[16];
6008 Buffer.BlockCopy(Salt, 0, Key, 0, 32);
6009 Buffer.BlockCopy(Salt, 32, IV, 0, 16);
6011 using ICryptoTransform Encryptor = Aes.CreateEncryptor(Key, IV);
6012 using CryptoStream EncryptedFile =
new CryptoStream(File, Encryptor, CryptoStreamMode.Write);
6015 await Data.CopyToAsync(EncryptedFile);
6016 EncryptedFile.FlushFinalBlock();
6027 long Len = Data.Length;
6033 byte b = (byte)(Len & 127);
6045 await Data.CopyToAsync(Blob);
6066 b = Data.ReadByte();
6067 Len |= ((long)b & 127) << Offset;
6070 while ((b & 0x80) != 0);
6073 byte[] Buf =
new byte[65536];
6078 c = (int)Math.Min(65536, Len);
6079 i = await Data.ReadAsync(Buf, 0, c);
6082 await Blob.DisposeAsync();
6094 internal static async Task<byte[]> CreateSalt(
string Key,
byte[] AdditionalData)
6100 int c = AdditionalData?.Length ?? 0;
6103 byte[] Data =
new byte[48 + c];
6105 Buffer.BlockCopy(Salt, 0, Data, 0, 48);
6107 Buffer.BlockCopy(AdditionalData, 0, Data, 48, c);
6117 internal static async Task<KeyValuePair<byte[], byte[]>> GetSaltWithAdditionalData(
string Key)
6124 if (!P.Key || !(P.Value is
byte[] Data) || (c = Data.Length - 48) < 0)
6125 return new KeyValuePair<byte[], byte[]>(
null,
null);
6127 byte[] Salt =
new byte[48];
6128 byte[] AdditionalData =
new byte[c];
6130 Buffer.BlockCopy(Data, 0, Salt, 0, 48);
6132 Buffer.BlockCopy(Data, 48, AdditionalData, 0, c);
6134 return new KeyValuePair<byte[], byte[]>(Salt, AdditionalData);
6137 internal static async Task<bool> RemoveSalt(
string Key)
Helps with common CSV-related tasks. (CSV=Comma Separated Values)
static string[][] Parse(string Csv)
Parses a CSV string.
Helps with parsing of commong data types.
static string Encode(bool x)
Encodes a Boolean for use in XML and other formats.
static readonly char[] CRLF
Contains the CR LF character sequence.
static bool TryParse(string s, out double Value)
Tries to decode a string encoded double.
static string EncodeRfc822(DateTime Timestamp)
Encodes a date and time, according to RFC 822 §5.
Contains information about a response to a content request.
byte[] Encoded
Encoded object.
string ContentType
Internet Content-Type of encoded object.
bool HasError
If an error occurred.
object Decoded
Decoded object.
Exception Error
Error response.
void AssertOk()
Asserts response is OK.
Contains information about an emoji.
Static class that provide methods for managing emojis.
static bool TryGetEmoji(string ShortName, out EmojiInfo Emoji)
Tries to get information about an emoji, given its short name.
const string DefaultContentType
Content-Type for CSS files.
Encapsulates a CSS Document
static string GetBody(string Html)
Extracts the contents of the BODY element in a HTML string.
JavaScript encoder/decoder.
const string DefaultContentType
application/javascript
Static class managing encoding and decoding of internet content.
static string GetContentType(string FileExtension)
Gets the content type of an item, given its file extension. It uses the TryGetContentType to see if a...
static Task< ContentResponse > EncodeAsync(object Object, Encoding Encoding, params string[] AcceptedContentTypes)
Encodes an object.
static Task< ContentResponse > DecodeAsync(string ContentType, byte[] Data, Encoding Encoding, KeyValuePair< string, string >[] Fields, Uri BaseUri)
Decodes an object.
Helps with common JSON-related tasks.
static readonly DateTime UnixEpoch
Unix Date and Time epoch, starting at 1970-01-01T00:00:00Z
Consolidates Markdown from multiple sources, sharing the same thread.
Task< bool > Update(string Source, MarkdownDocument Markdown, string Id)
Updates incoming markdown information.
Task< bool > Add(string Source, MarkdownDocument Markdown)
Adds incoming markdown information.
const string ContentType
Markdown content type.
Contains a markdown document. This markdown document class supports original markdown,...
static string Encode(string s)
Encodes all special characters in a string so that it can be included in a markdown document without ...
async Task< string > GeneratePlainText()
Generates Plain Text from the markdown text.
async Task< string > GenerateHTML()
Generates HTML from the markdown text.
static Task< MarkdownDocument > CreateAsync(string MarkdownText, params Type[] TransparentExceptionTypes)
Contains a markdown document. This markdown document class supports original markdown,...
Abstract base class for all markdown elements.
Represents alternative versions of the same content, encoded with multipart/alternative
Represents content embedded in other content.
Represents mixed content, encoded with multipart/mixed
Static class helping modules to find files installed on the system.
static string ExecutableExtension
Extension used by executable files on the platform.
Plain text encoder/decoder.
const string DefaultContentType
text/plain
Helps with common XML-related tasks.
static string Attribute(XmlElement E, string Name)
Gets the value of an XML attribute.
static XmlDocument LoadFromFile(string FileName)
Loads an XML document from a file.
static string Encode(string s)
Encodes a string for use in XML.
static bool TryParse(string s, out DateTime Value)
Tries to decode a string encoded DateTime.
static string HtmlAttributeEncode(string s)
Differs from Encode(String), in that it does not encode the aposotrophe.
Static class managing loading of XSL resources stored as embedded resources or in content files.
static XmlSchema LoadSchema(string ResourceName)
Loads an XML schema from an embedded resource.
static void Validate(string ObjectID, XmlDocument Xml, params XmlSchema[] Schemas)
Validates an XML document given a set of XML schemas.
Static class managing the application event log. Applications and services log events on this static ...
static string CleanStackTrace(string StackTrace)
Cleans a Stack Trace string, removing entries from the asynchronous execution model,...
static void Register(IEventSink EventSink)
Registers an event sink with the event log. Call Unregister(IEventSink) to unregister it,...
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
static void Warning(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs a warning event.
static void Error(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs an error event.
static void Informational(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs an informational event.
static Exception UnnestException(Exception Exception)
Unnests an exception, to extract the relevant inner exception.
static bool Unregister(IEventSink EventSink)
Unregisters an event sink from the event log.
static void Notice(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs a notice event.
static void Alert(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs an alert event.
virtual Task DisposeAsync()
IDisposableAsync.DisposeAsync()
Contains event statistics.
Dictionary< string, Statistic > PerEventId
Number of events, per actor.
Dictionary< string, Statistic > PerFacility
Number of events, per actor.
Dictionary< string, Statistic > PerType
Number of events, per actor.
Dictionary< string, Statistic > PerActor
Number of events, per actor.
DateTime CurrentStat
Timestamp of current statistics.
Dictionary< string, Statistic > PerStackTrace
Number of events, per stack trace (Only of type Critical, Alert and Emergency).
DateTime LastStat
Timestamp of last statistics. If DateTime.MinValue, no statistics has been retrieved since restart of...
Dictionary< string, Statistic > PerLevel
Number of events, per actor.
Dictionary< string, Statistic > PerModule
Number of events, per actor.
Calculates statistics on incoming events.
EventStatistics GetStatisticsSinceLast()
Gets statistics of events logged since last call to GetStatisticsSinceLast.
Converts CSSX-files to CSS, by evaluating emebedded script and replacing it with results.
static string ColorToCss(SKColor Color)
Converts a color to its CSS representation.
Static class managing data export.
static async Task< string > GetFullExportFolderAsync()
Full path to export folder.
static async Task< string > GetFullKeyExportFolderAsync()
Full path to key folder.
static string FormatBytes(double Bytes)
Formats a file size using appropriate unit.
Static class managing the runtime environment of the IoT Gateway.
static CaseInsensitiveString Domain
Domain name.
static HttpServer HttpServer
HTTP Server
static string InstanceName
Name of the current instance. Default instance=string.Empty
static OAuth2Environment OAuthEnvironment
OAUTH2 environment reference.
static Task Terminate()
Raises the OnTerminate event handler, letting the container executable know the application needs to ...
static bool IsDomain(string DomainOrHost, bool IncludeAlternativeDomains)
If a domain or host name represents the gateway.
static AvatarClient AvatarClient
XMPP Concentrator Server.
static X509Certificate2 Certificate
Domain certificate.
static void DeleteOldFiles(string Path, long KeepDays)
Deletes old files in a folder.
static Task< string > GetMultiFormatChatMessageXml(string Markdown)
Gets XML for a multi-formatted chat message.
static async Task DoBackup()
Performs a backup of the system.
static LoginAuditor LoginAuditor
Current Login Auditor. Should be used by modules accepting user logins, to protect the system from un...
static Task< int > ProcessNewServiceConfigurations()
Processes new Service Configuration Files. This method should be called after installation of new ser...
static byte[] NextBytes(int NrBytes)
Generates an array of random bytes.
static string AppDataFolder
Application data folder.
static int[] GetConfigPorts(string Protocol)
Gets the port numbers defined for a given protocol in the configuration file.
static CaseInsensitiveString[] AlternativeDomains
Alternative domain names
static Task SendNotification(Graph Graph)
Sends a graph as a notification message to configured notification recipients.
static string GetUrl(string LocalResource)
Gets a URL for a resource.
static MultiUserChatClient MucClient
XMPP Multi-User Chat Protocol (MUC) Client.
static JwtFactory JwtFactory
JWT Factory, used to create and validate JWT tokens.
static async Task< string > GetCustomErrorHtml(HttpRequest Request, string LocalFileName, string ContentType, byte[] Content)
Gets a custom error HTML document.
static DateTime ScheduleEvent(Action< object > Callback, DateTime When, object State)
Schedules a one-time event.
static CaseInsensitiveString[] GetNotificationAddresses()
Returns configured notification addresses.
static XmppClient XmppClient
XMPP Client connection of gateway.
static string RootFolder
Web root folder.
static bool HasDomain
If a domain name is configured.
static bool CancelScheduledEvent(DateTime When)
Cancels a scheduled event.
static SoftwareUpdateClient SoftwareUpdateClient
XMPP Software Updates Client, if such a compoent is available on the XMPP broker.
static ProvisioningClient ProvisioningClient
XMPP Provisioning Client.
static HttpFolderResource Root
Root folder resource.
Domain constant, contains the value of the gateway domain.
static ThemeDefinition CurrentTheme
Current theme.
static DomainConfiguration Instance
Current instance of configuration.
bool UseEncryption
If the server uses server-side encryption.
SKColor LinkColorUnvisited
Color of unvisited links.
string Account
XMPP Account
static XmppConfiguration Instance
Current instance of configuration.
Tokenizes contents defined in a Markdown document.
Represents a file-based resource that can have custom values depending on what domain the resource is...
ISniffer[] Sniffers
Registered sniffers.
virtual void Add(ISniffer Sniffer)
ICommunicationLayer.Add
Question[] Questions
Question section
byte[] Raw
Raw DNS message
Contains information about a DNS Question
DNS resolver, as defined in:
static Task< DnsResponse > TryQuery(string Name, QTYPE TYPE, QCLASS CLASS)
Tries to query a DNS name.
Implements a simple FTP Server, as defined in:
CommunicationLayer ExternalSniffers
External Sniffers for FTP communication.
void Dispose()
IDisposable.Dispose
void UpdateCertificate(X509Certificate ServerCertificate)
Updates the server certificate
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repe...
Contains communication statistics.
Dictionary< string, Statistic > CallsPerFrom
Calls per From header value.
long NrBytesTx
Number of bytes transmitted.
long NrCalls
Number of method calls.
long NrBytesRx
Number of bytes received.
Dictionary< string, Statistic > CallsPerResource
Calls per resource.
DateTime CurrentStat
Timestamp of current statistics.
Dictionary< string, Statistic > CallsPerMethod
Calls per method.
DateTime LastStat
Timestamp of last statistics. If DateTime.MinValue, no statistics has been retrieved since restart of...
Dictionary< string, Statistic > CallsPerUserAgent
Calls per User Agent header value.
Event arguments for file not found events.
HttpResponse Response
Current response object.
HttpRequest Request
Current request object.
NotFoundException Exception
Exception that will be returned to client. Change, if a custom exception is to be returned....
The server understood the request, but is refusing to fulfill it. Authorization will not help and the...
Base class for all HTTP authentication schemes, as defined in RFC-7235: https://datatracker....
KeyValuePair< string, string >[] HeaderFields
HTTP Header fields to include in the response.
async Task< object > GetContentObjectAsync()
Any content object to return. The object will be encoded before being sent.
string ContentType
The content type of Content, if provided.
int StatusCode
HTTP Status Code.
byte[] Content
Any encoded content to return.
Publishes a folder with all its files and subfolders through HTTP GET, with optional support for PUT,...
static Task SendResponse(string FullPath, string ContentType, string ETag, DateTime LastModified, bool LastModifiedUpdated, HttpResponse Response)
Sends a file-based response back to the client.
Represents an HTTP request.
HttpRequestHeader Header
Request header.
string RemoteEndPoint
Remote end-point.
SessionVariables Session
Contains session states, if the resource requires sessions, or null otherwise.
string SubPath
Sub-path. If a resource is found handling the request, this property contains the trailing sub-path o...
HttpResponse Response
HTTP Response object, if one has been assigned to the request.
Base class for all HTTP resources.
string ComputeETag(Stream fs)
Computes an ETag value for a resource.
Represets a response of an HTTP client request.
async Task DisposeAsync()
Closes the connection and disposes of all resources.
async Task SendResponse()
Sends the response back to the client. If the resource is synchronous, there's no need to call this m...
Task Write(byte[] Data)
Returns binary data in the response.
void SetHeader(string FieldName, string Value)
Sets a custom header field value.
TransferEncoding TransferEncoding
Transfer encoding in response.
An HTTP Reverse proxy resource. Incoming requests are reverted to a another web server for processing...
Implements an HTTP server.
int[] OpenHttpPorts
HTTP Ports successfully opened.
CommunicationStatistics GetCommunicationStatisticsSinceLast()
Gets communication statistics since last call.
static SessionVariables CreateSessionVariables()
Creates a new collection of variables, that contains access to the global set of variables.
HttpResource Register(HttpResource Resource)
Registers a resource with the server.
const int DefaultHttpPort
Default HTTP Port (80).
void GetMTlsSettings(int Port, out ClientCertificates ClientCertificates, out bool TrustClientCertificates)
Gets mTLS settings for a given port number.
int[] OpenHttpsPorts
HTTPS Ports successfully opened.
bool Unregister(HttpResource Resource)
Unregisters a resource from the server.
const int DefaultHttpsPort
Default HTTPS port (443).
The server has not found anything matching the Request-URI. No indication is given of whether the con...
Event arguments for proxy request events.
HttpRequest Request
Current request object.
HttpRequestMessage Message
Message being forwarded.
Similar to 403 Forbidden, but specifically for use when authentication is required and has failed or ...
Implements a simple SMTP Server, as defined in:
CommunicationLayer ExternalSniffers
External Sniffers for SMTP communication.
void UpdateCertificate(X509Certificate ServerCertificate)
Updates the server certificate
void Dispose()
IDisposable.Dispose
Outputs sniffed data to an XML file.
Implements an XMPP concentrator server interface.
Task< bool > Register(IDataSource DataSource)
Registers a new data source with the concentrator.
Contains a reference to an attachment assigned to a legal object.
string ContentType
Internet Content Type of binary attachment.
Adds support for legal identities, smart contracts and signatures to an XMPP client.
const string NamespaceOnboarding
http://waher.se/schema/Onboarding/v1.xsd
static LegalIdentity Parse(string Xml)
Parses an identity from its XML representation
Abstract base class of signatures
Abstract base class for XMPP client connections
bool IsComponentDomain(CaseInsensitiveString Domain, bool IncludeAlternativeDomains)
Checks if a domain is the component domain, or optionally, an alternative component domain.
Information about a file upload.
Implements HTTP File Upload support as an XMPP component: https://xmpp.org/extensions/xep-0363....
override void Dispose()
IDisposable.Dispose
HTTP File Upload settings.
string InternalTransferFolder
Folder where files for internal transfer are stored.
string PubSubStorageFolder
Folder where encrypted files reside.
string EncryptedStorageFolder
Folder where encrypted files reside.
Access scheme used for internal transfer of files between client and server.
HTTP Resource managing HTTP Uploads, and access to uploaded files.
Event arguments for IQ queries.
string Type
Type attribute in IQ stanza.
XmppAddress From
From address attribute
Task IqResult(string Xml, string From)
Returns a response to the current request.
XmlElement Query
Query element, if found, null otherwise.
XmppAddress To
To address attribute
async Task IqError(string ErrorType, string Xml, XmppAddress From, string ErrorText, string Language)
Returns an error response to the current request.
Task IqErrorBadRequest(XmppAddress From, string ErrorText, string Language)
Returns a bad-request error.
Task IqErrorForbidden(XmppAddress From, string ErrorText, string Language)
Returns a forbidden error.
Implements SOCKS5 Byte streams support as an XMPP component: https://xmpp.org/extensions/xep-0065....
override void Dispose()
IDisposable.Dispose
Contains communication statistics.
Dictionary< string, Statistic > StanzasPerFromDomain
Stanzas per domain of sender
long NrBytesTx
Number of bytes transmitted.
Dictionary< string, Statistic > StanzasPerStanzaType
Stanzas per stanza and type.
DateTime LastStat
Timestamp of last statistics. If DateTime.MinValue, no statistics has been retrieved since restart of...
Dictionary< string, Statistic > StanzasPerToDomain
Stanzas per domain of receiver
Dictionary< string, Statistic > StanzasPerToBareJid
Stanzas per bare JID of receiver
Dictionary< string, Statistic > StanzasPerNamespace
Stanzas per namespace
long NrStanzas
Number of stanzas.
long NrBytesRx
Number of bytes received.
Dictionary< string, Statistic > StanzasPerFqn
Stanzas per fully qualified name (namespace::localName)
DateTime CurrentStat
Timestamp of current statistics.
Dictionary< string, Statistic > StanzasPerFromBareJid
Stanzas per bare JID of sender
Mainstains information about connectivity from a specific s2s endpoint.
Web Socket client interface
Contains information about one XMPP address.
CaseInsensitiveString Resource
Resource part.
CaseInsensitiveString Domain
Domain
CaseInsensitiveString Address
XMPP Address
CaseInsensitiveString BareJid
Bare JID
static readonly XmppAddress Empty
Empty address.
CaseInsensitiveString Account
Account
const string ExtendedAddressingNamespace
http://jabber.org/protocol/address (XEP-0033)
IClientConnection[] GetClientConnections()
Get active client connections
void UpdateCertificate(X509Certificate ServerCertificate)
Updates the server certificate
CommunicationLayer S2sSniffers
Sniffers for XMPP S2S communication.
S2sEndpointStatistics[] GetServerConnectionStatistics()
Gets S2S connection statistics.
bool TryGetClientConnection(string FullJID, out IClientConnection Connection)
Tries to get an active client connection.
CommunicationLayer C2sSniffers
Sniffers for XMPP C2S communication.
bool IsServerDomain(CaseInsensitiveString Domain, bool IncludeAlternativeDomains)
Checks if a domain is the server domain, or optionally, an alternative domain.
void RegisterIqGetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers an IQ-Get handler.
bool TryGetS2sEndpoint(string RemoteDomain, out IS2SEndpoint Endpoint)
Tries to get a server-to-server connection state object.
void Dispose()
IDisposable.Dispose
static Task< XmppServer > Create(CaseInsensitiveString Domain, CaseInsensitiveString[] AlternativeDomains, X509Certificate ServerCertificate, bool EncryptionRequired, IXmppServerPersistenceLayer PersistenceLayer)
Creates an instance of an XMPP server.
Statistics.CommunicationStatistics GetCommunicationStatisticsSinceLast()
Gets communication statistics since last call.
const string DelayedDeliveryNamespace
urn:xmpp:delay (XEP-0203)
async Task< bool > SendMailMessage(CaseInsensitiveString From, CaseInsensitiveString To, string Subject, string Markdown)
Sends a mail message
async Task< int > DeleteOldMailContent(DateTime OlderThan)
Deletes old mail content.
Represents a case-insensitive string.
string Value
String-representation of the case-insensitive string. (Representation is case sensitive....
static readonly CaseInsensitiveString Empty
Empty case-insensitive string
static bool IsNullOrEmpty(CaseInsensitiveString value)
Indicates whether the specified string is null or an CaseInsensitiveString.Empty string.
void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count)
Copies a specified number of characters from a specified position in this instance to a specified pos...
CaseInsensitiveString Remove(int startIndex)
Returns a new string in which all the characters in the current instance, beginning at a specified po...
Static interface for database persistence. In order to work, a database provider has to be assigned t...
static Task< IPersistentDictionary > GetDictionary(string Collection)
Gets a persistent dictionary containing objects in a collection.
static Task EndBulk()
Ends bulk-processing of data. Must be called once for every call to StartBulk.
static Task StartBulk()
Starts bulk-proccessing of data. Must be followed by a call to EndBulk.
static async Task Update(object Object)
Updates an object in the database.
static async Task Delete(object Object)
Deletes an object in the database.
static Task< IEnumerable< object > > Find(string Collection, params string[] SortOrder)
Finds objects in a given collection.
static async Task Insert(object Object)
Inserts an object into the default collection of the database.
static async Task Clear(string CollectionName)
Clears a collection of all objects.
Persists objects into binary files.
This filter selects objects that conform to all child-filters provided.
This filter selects objects that have a named field equal to a given value.
This filter selects objects that have a named field lesser or equal to a given value.
Full-text search module, controlling the life-cycle of the full-text-search engine.
static async Task< TokenCount[]> Tokenize(IEnumerable< object > Objects)
Tokenizes a set of objects using available tokenizers. Tokenizers are classes with a default contruct...
Defines an indexable property.
Static class for access to Full-Text-Search
static Task< bool > AddFullTextSearch(string CollectionName, params PropertyDefinition[] Properties)
Adds properties for full-text-search indexation.
static void RegisterStopWords(params string[] StopWords)
Registers stop-words with the search-engine. Stop-words are ignored in searches.
static Task< bool > SetFullTextSearchIndexCollection(string IndexCollection, string CollectionName)
Defines the Full-text-search index collection name, for objects in a given collection.
static Task< long > ReindexCollection(string IndexCollectionName)
Reindexes the full-text-search index for a database collection.
Contains information about a tokenization process.
Provides a Serializer context for full serialization.
Implements an in-memory cache.
bool ContainsKey(KeyType Key)
Checks if a key is available in the cache.
void Dispose()
IDisposable.Dispose
bool TryGetValue(KeyType Key, out ValueType Value)
Tries to get a value from the cache.
void Add(KeyType Key, ValueType Value)
Adds an item to the cache.
Event arguments for cache item removal events.
ValueType Value
Value of item that was removed.
Static class managing loading of resources stored as embedded resources or in content files.
static byte[] LoadResource(string ResourceName)
Loads a resource from an embedded resource.
Static class that dynamically manages types and interfaces available in the runtime environment.
static void SetModuleParameter(string Name, object Value)
Sets a module parameter. This parameter value will be accessible to modules when they are loaded.
static Type GetType(string FullName)
Gets a type, given its full name.
static bool TryGetModuleParameter(string Name, out object Value)
Tries to get a module parameter value.
static Assembly[] Assemblies
Assemblies in the inventory.
static object[] NoParameters
Contains an empty array of parameter values.
static object Instantiate(Type Type, params object[] Arguments)
Returns an instance of the type Type . If one needs to be created, it is. If the constructor requires...
static Type[] GetTypesImplementingInterface(string InterfaceFullName)
Gets all types implementing a given interface.
Processes work tasks, in an asynchronous manner.
string Name
Name of processor.
Maintains a record of active processors.
static IAsyncProcessor[] GetActiveProcessors()
Gets an array of all active processors.
static Task CloseAllProcessorsForTermination()
Closes all active processors for new items.
static bool HasActiveProcessors
If there are active processors.
XMPP-based Service Registration Client.
async Task CheckRegistration(params Annotation[] Annotations)
Checks if the software needs to be registered.
Static class managing persistent settings.
static async Task< string > GetAsync(string Key, string DefaultValue)
Gets a string-valued setting.
static async Task< bool > SetAsync(string Key, string Value)
Sets a string-valued setting.
bool TryGetBucket(string Id, out Bucket Bucket)
Tries to get a bucket, given its ID.
async Task< SampleStatistic > Sample(string Counter, double Value)
Samples a value
Class managing the contents of a temporary file. When the class is disposed, the temporary file is de...
override void Dispose(bool disposing)
Disposes of the object, and deletes the temporary file.
string FileName
File Name.
Class managing the contents of a temporary stream. When the class is disposed, any temporary file is ...
Manages a temporary stream. Contents is kept in-memory, if below a memory threshold,...
override void WriteByte(byte value)
Writes a byte to the current position in the stream and advances the position within the stream by on...
override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
Asynchronously writes a sequence of bytes to the current stream, advances the current position within...
Represents a named semaphore, i.e. an object, identified by a name, that allows single concurrent wri...
Static class of application-wide semaphores that can be used to order access to editable objects.
static async Task< Semaphore > BeginWrite(string Key)
Waits until the semaphore identified by Key is ready for writing. Each call to BeginWrite must be fo...
Base class for all types of elements.
Exception used to break a loop.
Exception used to continue a loop.
Script runtime exception.
IElement ReturnValue
Return value.
Class managing a script expression.
ScriptNode Root
Root script node.
async Task< object > EvaluateAsync(Variables Variables)
Evaluates the expression, using the variables provided in the Variables collection....
static bool TryGetConstant(string Name, Variables Variables, out IElement ValueElement)
Tries to get a constant value, given its name.
static string ToExpressionString(object Value)
Converts an object to a string, that can be parsed as part of an expression.
Base class for all nodes in a parsed script tree.
static async Task< object > WaitPossibleTask(object Result)
Waits for any asynchronous process to terminate.
virtual Task< IElement > EvaluateAsync(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection. This method should be ...
static readonly ObjectValue Null
Null value.
ToMatrix(ScriptNode Operand, bool NullCheck, int Start, int Length, Expression Expression)
To-Matrix operator.
Data Source defined by a type definition
static MethodInfo FindMethod
Generic object database Find method: Database.Find<T>(int, int, Filter, string[])
Event arguments for preview events.
IElement Preview
Preview of result.
Contains information about a variable.
virtual Variable Add(string Name, object Value)
Adds a variable to the collection.
virtual bool TryGetVariable(string Name, out Variable Variable)
Tries to get a variable object, given its name.
Edwards448 Elliptic Curve, as defined in RFC7748 and RFC8032: https://tools.ietf.org/html/rfc7748 htt...
Contains methods for simple hash calculations.
static string ComputeSHA256HashString(byte[] Data)
Computes the SHA-256 hash of a block of binary data.
static string BinaryToString(byte[] Data)
Converts an array of bytes to a string with their hexadecimal representations (in lower case).
Use JWT tokens for authentication. The Bearer scheme defined in RFC 6750 is used: https://tools....
static string GetAccessToken(HttpRequest Request)
Gets the access token from an HTTP request.
Static class containing predefined JWT claim names.
const string Issuer
Issuer of the JWT
const string IssueTime
Time at which the JWT was issued; can be used to determine age of the JWT
const string JwtId
Unique identifier; can be used to prevent the JWT from being replayed (allows a token to be used only...
const string Subject
Subject of the JWT (the user)
const string ExpirationTime
Time after which the JWT expires
A factory that can create and validate JWT tokens.
bool IsValid(JwtToken Token)
Checks if a token is valid and signed by the factory.
string Create(params KeyValuePair< string, object >[] Claims)
Creates a new JWT token.
Contains information about a Java Web Token (JWT). JWT is defined in RFC 7519: https://tools....
static bool TryParse(string Token, out JwtToken ParsedToken)
Tries to parse a JWT token.
Event arguments for endpoint annotation events.
string RemoteEndPoint
Remote endpoint.
void AddTag(string Key, object Value)
Adds a tag to the list of tags.
Class that monitors login events, and help applications determine malicious intent....
static async Task< KeyValuePair< string, object >[]> Annotate(string RemoteEndPoint, params KeyValuePair< string, object >[] Tags)
Annotates a remote endpoint.
static async void Success(string Message, string UserName, string RemoteEndPoint, string Protocol, params KeyValuePair< string, object >[] Tags)
Handles a successful login attempt.
async Task< bool > ProcessLoginFailure(string RemoteEndPoint, string Protocol, DateTime Timestamp, string Reason)
Processes a failed login attempt.
static void Fail(string Message, string UserName, string RemoteEndPoint, string Protocol)
Handles a failed login attempt.
byte[] ComputeVariable(byte[] N)
Computes the SPONGE function, as defined in section 4 of NIST FIPS 202.
Implements the SHA3 SHAKE256 extendable-output functions, as defined in section 6....
Contains information about a SPF string.
Corresponds to a user in the system.
async Task< string > CreateToken(JwtFactory Factory, bool Encrypted, params KeyValuePair< string, object >[] AdditionalClaims)
Creates a JWT Token referencing the user object.
bool HasPrivilege(string Privilege)
If the user has a given privilege.
Maintains the collection of all users in the system.
static async Task< User > GetUser(string UserName, bool CreateIfNew)
Gets the User object corresponding to a User Name.
static IUserSource Source
User source.
readonly Dictionary< string, FileInfo > Files
Currently accesible files
readonly LinkedList< Process > Processes
Current processes related to session
string Folder
Current folder
Information about a file accessible through admin command interface
Asks the broker to enter a room.
override async Task Execute(ChatState State, string[] Arguments, string OrgMessage, ResponseCallbackHandler ResponseCallback)
Executes the command.
Multi-User Chat Room information
string NickName
Nick-name to use in room.
bool Permanent
If room association should be persisted.
string Password
Password to use to enter room.
Lists rooms currently entered by the neuron.
Consolidates responses from occupants in a MUC room.
Identity of the IoT Broker package.
const string Key
Key for decrypting the contents of the package.
const string FileName
IoTBroker.package
Contains information about a broker account.
async Task< IRosterItem > GetRosterItem(CaseInsensitiveString UserName, CaseInsensitiveString Jid)
Gets a roster item for an account.
async Task DeleteOfflineMessages(IEnumerable< IOfflineMessage > Messages)
Deletes offline messages.
async Task< IEnumerable< IRosterItem > > GetRoster(CaseInsensitiveString UserName)
Gets the roster of an account.
Tokenizes (for full-text-search) a broker account.
Manages eDaler on accounts connected to the broker.
override void Dispose()
IDisposable.Dispose
Event log component, as defined in XEP-0337. https://xmpp.org/extensions/xep-0337....
override void Dispose()
IDisposable.Dispose
override void Dispose()
IDisposable.Dispose
void Dispose()
IDisposable.Dispose
static async Task< int > DeleteOldAttachments()
Deletes old attachments from the cache and database.
Tokenizes a set of human readable texts.
Tokenizes a set of parameters.
Tokenizes a set of roles.
byte[] XmlSchema
XML Schema
Legal (digital identities, smart contracts) service component.
const string NamespaceSmartContractsNeuroFoundationV1
urn:nf:iot:leg:sc:1.0
const string NamespaceLegalIdentityIeeeV1
urn:ieee:iot:leg:id:1.0
const string NamespaceLegalIdentityNeuroFoundationV1
urn:nf:iot:leg:id:1.0
static Task< string > GetOnboardingNeuronDomainName()
Gets the domain name of the Nnboarding Neuron.
const string NamespaceE2ENeuroFoundationV1
urn:nf:iot:e2e:1.0
const string NamespaceSmartContractsIeeeV1
urn:ieee:iot:leg:sc:1.0
const string NamespaceE2EIeeeV1
urn:ieee:iot:e2e:1.0
static Tuple< IE2eEndpoint, DateTime?, DateTime?> GetPublicKey(DateTime? Timestamp)
Returns the public key of the legal component, optionally, for a given point in time....
override void Dispose()
IDisposable.Dispose
Web resource that allows calling applications to enable Multi-Factor Authentication using legal ident...
Web resource that allows calling applications to enable Quick-Login using legal identities.
const string UserVariableName
QuickLoginUser
Web resource that permits authentication of users into their remote systems, by triggering a digital ...
Marketplace processor, brokering sales of items via tenders and offers defined in smart contracts.
Multi-User-Chat (MUC) Component component, as defined in XEP-0045. https://xmpp.org/extensions/xep-00...
override void Dispose()
IDisposable.Dispose
Tokenizes (for full-text-search) a Neuro-Feature token.
Adds an external note to a token.
Public token history view.
Paiwise processor, processing payment instructions defined in smart contracts.
Provisioning and registry service component.
const string NamespaceProvisioningOwnerIeeeV1
urn:ieee:iot:prov:o:1.0
const string NamespaceSoftwareUpdatesNeuroFoundationV1
urn:nf:iot:swu:1.0
const string NamespaceProvisioningTokenNeuroFoundationV1
urn:nf:iot:prov:t:1.0
const string NamespaceIoTDiscoveryNeuroFoundationV1
urn:nf:iot:disco:1.0
const string NamespaceProvisioningTokenIeeeV1
urn:ieee:iot:prov:t:1.0
const string NamespaceProvisioningDeviceIeeeV1
urn:ieee:iot:prov:d:1.0
const string NamespaceIoTDiscoveryIeeeV1
urn:ieee:iot:disco:1.0
override void Dispose()
IDisposable.Dispose
const string NamespaceIoTDiscoveryXsfV0
urn:xmpp:iot:discovery
const string NamespaceProvisioningOwnerNeuroFoundationV1
urn:nf:iot:prov:o:1.0
const string NamespaceSoftwareUpdatesIeeeV1
urn:ieee:iot:swu:1.0
const string NamespaceProvisioningDeviceNeuroFoundationV1
urn:nf:iot:prov:d:1.0
Contains information about a software package.
byte[] PublicKey
Public key of issuer, used to create signature.
byte[] Signature
Cryptographic signature of package, as calculated by the issuer of the package.
DateTime Installed
When package was installed (if installed).
bool ContentOnly
If package only contains content (i.e. no assemblies and executable files).
CaseInsensitiveString FileName
Filename of package.
DateTime Published
When package was published.
string Url
URL of package.
byte[] AesKey
Symmetric cipher used to encrypt package file.
long Bytes
Number of bytes of package.
DateTime Supersedes
Timestamp of superceded package.
DateTime Created
When package record was created
PubSub component, as defined in XEP-0060. https://xmpp.org/extensions/xep-0060.html
async Task<(int, int)> DeleteExpiredNodes()
Deletes expired nodes
async Task< PubSubNode > GetNodeAsync(CaseInsensitiveString Service, CaseInsensitiveString NodeName, NodeAccessModel? AutoCreateAccess, XmppAddress From, CaseInsensitiveString Domain)
Gets a pubsub node.
override void Dispose()
IDisposable.Dispose
static async Task< PubSubComponent > Create(XmppServer Server, CaseInsensitiveString Subdomain, string Name)
PubSub component, as defined in XEP-0060.
Defines a node on which items can be published.
CaseInsensitiveString Name
Name of node.
bool PublishOnWeb
If the items published to the node should be available on the web or not.
override void Dispose()
IDisposable.Dispose
Provides the user configuration options regarding use of SMTP Relay server to send mail.
static RelayConfiguration Instance
Current instance of configuration.
override Task ConfigureSystem()
Is called during startup to configure the system.
Data source mirroring the Gateway.config file.
References a port number.
Root node of port numbers to use.
Defines a proxy resource to act as a reverse proxy.
bool Encrypted
If forwarded requests are encrypted (HTTPS) or not (HTTP).
Data source mirroring the ProgramData folder for the broker.
Root node of Events report folder.
static async Task RegisterReports()
Registers protocol reports.
static async Task RegisterReports()
Registers protocol reports.
Service helping services synchronize their clocks over the Internet.
Component that synchronizes content in the federated network, by sending synchronization messages and...
Date and Time value based on the intenal high-frequency timer.
Gets information about the domain.
DomainInfo()
Gets information about the domain.
HttpAuthenticationScheme[] CreateAuthenticationSchemes(IUserSource Users)
Creates a set of authentication schemes for the resource.
HttpAuthenticationScheme[] AuthenticationSchemes
Array of authentication schemes used for the resource.
static async Task< bool > SiteVerify(string RecaptchaResponse, string RemoteEndPoint)
Allows web pages and web services to verify that Google reCaptcha responses are valid.
Web Service, generating QR-codes based on URI input.
Access to secured vault storage via signed URLs.
Provides IP information about the caller.
Allows senders to send XMPP stanzas over HTTP POST.
Service Module hosting the XMPP broker and its components.
static Task< bool > SendMailMessage(string To, string Subject, string Markdown)
Sends a mail message
const string NamespaceSynchronizationNeuroFoundationV1
urn:nf:iot:synchronization:1.0
const string NamespaceSynchronizationIeeeV1
urn:ieee:iot:synchronization:1.0
HttpAuthenticationScheme[] DefaultAuthenticationSchemesXmpp
Default HTTP Authentication schemes for XMPP-authenticated resources.
HttpAuthenticationScheme[] DefaultAuthenticationSchemesAdmin
Default HTTP Authentication schemes for administrative resources.
const string NamespaceDnsOverXmpp
urn:xmpp:dox:0
const int DB_Generation
Current Database generation. Used for upgrading the internal database.
async Task Stop()
Stops the module.
static void Calibrate()
Calibrates the internal clock with the high frequency timer.
async Task Start()
Starts the module.
static async Task< byte[]> LoadEncryptedFile(string FileName, byte[] Salt, long? Size)
Loads an encrypted file.
static Task< bool > SendMailMessage(string To, string Subject, string Markdown, params EmbeddedContent[] Attachments)
Sends a mail message
static async Task SaveEncryptedFile(string FileName, byte[] Salt, Stream Data)
Saves an encrypted file.
static Task< IP4Localization > FindIpAddress(string RemoteEndPoint)
Finds locale information about an IP Address.
static async Task< bool > SendMailMessage(string SmtpHost, int SmtpPort, string UserName, string Password, string From, string To, string Subject, string Markdown, params EmbeddedContent[] Attachments)
Sends a mail message
const string NamespaceJwt
urn:xmpp:jwt:0
static string NamespaceSynchronization(NamespaceSet Version)
Returns the namespace for IoT Clock Synchronization.
static NamespaceSet GetVersion(string Namespace)
Gets the namespace set version corresponding to a given a namespace.
bool AuthenticateJwtToken(JwtToken Token, out Reason Reason)
Validates a JWT token against the JWT factory defined for the XMPP Server.
static Task< bool > SendMailMessage(string SmtpHost, int SmtpPort, string UserName, string Password, string From, string To, string Subject, string Markdown)
Sends a mail message
static bool IsContentPackage(Package Package)
Checks if a Package is a Content-Only package.
static async Task< Stream > EncodeBlob(Stream Data)
Encodes a variable-length BLOB by prefixing it with its length. This permits the BLOB to be safely en...
static Task SaveEncryptedFile(string FileName, byte[] Salt, byte[] Data)
Saves an encrypted file.
static ISerializerContext NormalizedSerialization
Serialization context for normalized serialization.
static DateTimeHF Now
Current high-resolution date and time
static async Task AppendRemoteEndPointToTable(StringBuilder Markdown, string RemoteEndPoint)
Appends annotated information about a remote endpoint to a Markdown table.
static Task< bool > SendMailMessage(string From, string To, string Subject, string Markdown)
Sends a mail message
static Task< byte[]> LoadEncryptedFile(string FileName, byte[] Salt)
Loads an encrypted file.
static bool VerifyRecaptcha(object Posted, string RemoteEndPoint)
Method that can be used by web pages to verify Recaptcha responses.
static Task< bool > SendMailMessage(string From, string To, string Subject, string Markdown, params EmbeddedContent[] Attachments)
Sends a mail message
static async Task< Stream > DecodeBlob(Stream Data)
Decodes a variable-length BLOB encoded by the EncodeBlob method. The length prefix is read first,...
static async Task< IP4Localization > FindIpAddress(IPAddress Addr)
Finds locale information about an IP Address.
Origin of request has maximum authority.
Origin of request has no authority.
static HttpAuthenticationScheme[] GetAuthenticationSchemes()
Gets an array of authentication schemes available to authorize access to a web resource.
Module for semantic things.
Interface for consolidators.
void Information(string Comment)
Called to inform the viewer of something.
void Warning(string Warning)
Called to inform the viewer of a warning state.
Interface for observable classes implementing communication protocols.
Interface for XMPP user accounts.
Interface for client connections.
Interface for recipients of stanzas.
Interface for XMPP S2S endpoints
Interface for XMPP Server persistence layers. The persistence layer should implement caching.
Interface for objects containing encrypted properties. Mark the properties that are encrypted with th...
Persistent dictionary that can contain more entries than possible in the internal memory.
Task< KeyValuePair< bool, object > > TryGetValueAsync(string key)
Gets the value associated with the specified key.
Task< bool > ContainsKeyAsync(string key)
Determines whether the System.Collections.Generic.IDictionary{string,object} contains an element with...
Task< bool > RemoveAsync(string key)
Removes the element with the specified key from the System.Collections.IDictionary object.
Task AddAsync(string key, object value)
Adds an element with the provided key and value to the System.Collections.Generic....
Interface for late-bound modules loaded at runtime.
Interface for AsyncProcessor<T> instances.
Basic interface for all types of elements.
object AssociatedObjectValue
Associated object value.
Interface for objects that can be converted into matrices.
Basic interface for a user.
A User that can participate in distributed operations, where the user is identified using a JWT token...
Basic interface for administration commands
bool AppliesTo(string CommandLine, string[] Arguments, out object Details)
If the command is applicable to the given command line.
class CountryCode(ScriptNode Argument, int Start, int Length, Expression Expression)
Looks up a Country Name and returns the corresponding Country Code.
HostDomainOptions
Options on how to handle domain names provided in the Host header.
Priority
Priority of message
BinaryPresentationMethod
How binary data is to be presented.
ClientCertificates
Client Certificate Options
ContentType
DTLS Record content type.
Reason
Reason a token is not valid.
delegate Task< string > ResponseCallbackHandler(string Markdown, string MessageId)
Delegate for response callback handler methods.
NamespaceSet
Namespace versions
Represents a duration value, as defined by the xsd:duration data type: http://www....