3using System.Collections.Generic;
4using System.Diagnostics;
6using System.IO.Compression;
8using System.Net.Sockets;
9using System.Reflection;
10using System.Runtime.ExceptionServices;
11using System.Security.Cryptography;
13using System.Threading;
14using System.Threading.Tasks;
188 private const string Ip2LocalizationPackageName =
"IP2LOCATION-LITE-DB3.CSV";
191 private static Calibration calibration;
192 private readonly
static Stopwatch clock = CreateWatch();
193 private static readonly
byte[] iotBrokerPackagePublicKey = System.Convert.FromBase64String(
"BRb026TgJ5L1t6T5jWL23m0BQHg1kUNY308V8ixlqmNN8nrPDzB3tTygDylyzjmDCFgWSf7OyUWA");
195 internal const string AutoInstallDelayParameterName =
"Autoinstall.DelayMin";
196 internal const string AutoInstallContentOnlyParameterName =
"Autoinstall.ContentOnly";
197 internal const string AutoInstallTimeParameterName =
"Autoinstall.Time";
199 private readonly Dictionary<CaseInsensitiveString, WebNode> webNodes =
new Dictionary<CaseInsensitiveString, WebNode>();
200 private readonly SortedDictionary<string, LinkedList<IAdminCommand>> adminCommands =
new SortedDictionary<string, LinkedList<IAdminCommand>>();
201 private readonly Dictionary<CaseInsensitiveString, RoomInfo> mucRooms =
new Dictionary<CaseInsensitiveString, RoomInfo>();
203 private Dictionary<string, bool> vulnerableResources =
null;
251 private QR qr =
null;
264 private AddNote addNote =
null;
267 private Buckets statistics =
null;
268 private Timer sampleTimer =
null;
271 private static string appData =
string.Empty;
272 internal static DateTime autoUpdateTP = DateTime.MinValue;
291 DateTime
Now = DateTime.Now;
293 this.statistics =
new Buckets(TP,
new Duration(
false, 0, 0, 0, 0, 1, 0));
296 int UntilNext = (int)((TP.AddSeconds(1) -
Now).TotalMilliseconds + 0.5);
301 this.sampleTimer =
new Timer(this.SampleTimerEventHandler,
null, UntilNext, 1000);
306 LoginAuditor.AnnotateEndpoint += this.LoginAuditor_AnnotateEndpoint;
308 List<string> Ip4DnsBlackLists =
new List<string>();
309 List<string> Ip6DnsBlackLists =
new List<string>();
313 XmlDocument Doc =
new XmlDocument();
314 Doc.Load(Path.Combine(appData,
"DNSBL.xml"));
316 XSL.
Validate(
"DNSBL", Doc,
"BlackLists",
"http://waher.se/Schema/DNSBL.xsd",
319 foreach (XmlNode N
in Doc.DocumentElement.ChildNodes)
321 if (N is XmlElement E && E.LocalName ==
"BlackList")
324 if (!
string.IsNullOrEmpty(s))
325 Ip4DnsBlackLists.Add(s);
328 if (!
string.IsNullOrEmpty(s))
329 Ip6DnsBlackLists.Add(s);
338 List<SpfExpression> SpfExpressions =
new List<SpfExpression>();
342 XmlDocument Doc =
new XmlDocument();
343 Doc.Load(Path.Combine(appData,
"SPF.xml"));
345 XSL.
Validate(
"SPF", Doc,
"SpfRecords",
"http://waher.se/Schema/SPF.xsd",
348 foreach (XmlNode N
in Doc.DocumentElement.ChildNodes)
350 if (N is XmlElement E && E.LocalName ==
"SpfRecord")
354 bool IncludeSubdomains =
XML.
Attribute(E,
"includeSubdomains",
false);
368 XmlDocument Doc =
new XmlDocument();
369 Doc.Load(Path.Combine(appData,
"StopWords.xml"));
371 foreach (XmlNode N
in Doc.DocumentElement.ChildNodes)
373 if (N is XmlElement E && E.LocalName ==
"Language")
375 foreach (XmlNode N2
in E.ChildNodes)
377 if (N2 is XmlElement E2 && E2.LocalName ==
"Stopword")
383 string[] StopWords2 =
new string[StopWords.TokenCounts.Count];
384 StopWords.TokenCounts.Keys.CopyTo(StopWords2, 0);
393 IoTBroker.Legal.Identity.Iso3166.Load();
394 IoTBroker.Legal.Identity.PersonalNumberSchemes.Load();
395 IoTBroker.Legal.Identity.PhoneCountryCodes.Load();
397 Encoding.RegisterProvider(
new CodePages());
401 Ip6DnsBlackLists.ToArray(), SpfExpressions.ToArray());
406 "SMTP Server Log %YEAR%-%MONTH%-%DAY%T%HOUR%.xml", appData +
"Transforms" + Path.DirectorySeparatorChar +
"SnifferXmlToHtml.xslt",
409 this.smtpServer.SmtpSnifferPath = appData +
"SMTP" + Path.DirectorySeparatorChar +
410 "%ENDPOINT%" + Path.DirectorySeparatorChar +
"SMTP Server Log %YEAR%-%MONTH%-%DAY%T%HOUR%.xml";
417 this.httpServer =
null;
426 this.xmppServer.ClientConnectionAdded += this.XmppServer_ClientConnectionAdded;
427 this.xmppServer.ClientConnectionRemoved += this.XmppServer_ClientConnectionRemoved;
428 this.xmppServer.ClientConnectionUpdated += this.XmppServer_ClientConnectionUpdated;
429 this.xmppServer.ServerConnectionAdded += this.XmppServer_ServerConnectionAdded;
430 this.xmppServer.ServerConnectionRemoved += this.XmppServer_ServerConnectionRemoved;
431 this.xmppServer.ServerConnectionUpdated += this.XmppServer_ServerConnectionUpdated;
433 #region Neuro-Foundation V1 handlers
440 #region IEEE V1 handlers
457 this.persistenceLayer.Server = this.xmppServer;
459 this.provisioningComponent =
new ProvisioningComponent(this.xmppServer,
"provisioning",
"Thing Registry and Provisioning Server");
460 this.pubSubComponent = await
PubSubComponent.
Create(this.xmppServer,
"pubsub",
"Publish/Subscribe service");
462 this.eventLogComponent =
new EventLogComponent(this.xmppServer,
"log",
"Event Log");
464 this.legalComponent =
new LegalComponent(this.xmppServer,
"legal",
"Smart Contracts", this.httpServer, Path.Combine(
Gateway.
AppDataFolder,
"Attachments"),
null,
this.pubSubComponent);
465 this.eDalerComponent =
new EDalerComponent(this.xmppServer,
"edaler",
"eDaler", this.legalComponent);
466 this.legalComponent.EDaler = this.eDalerComponent;
470 if (Socks5Ports.Length > 0)
471 this.socks5Component =
new Socks5Component(this.xmppServer,
"socks5", Socks5Ports[0]);
474 if (File.Exists(FileName))
478 s = File.ReadAllText(FileName);
480 Dictionary<string, bool> VulnerableResources =
new Dictionary<string, bool>(StringComparer.InvariantCultureIgnoreCase);
484 if (Resource.StartsWith(
"/"))
485 VulnerableResources[Resource.Substring(1)] =
true;
488 this.vulnerableResources = VulnerableResources;
490 Gateway.Root.FileNotFound += this.Root_FileNotFound;
498 if (!(this.httpServer is
null))
540 this.chatFile = this.httpServer.
Register(
"/ChatFile", this.ChatFileDownload,
false,
true);
541 this.httpxServer =
new HttpxServer(this.xmppServer, this.httpServer, 8192);
546 if (!(this.httpServer.
Sniffers is
null))
549 "XMPP Server Log %YEAR%-%MONTH%-%DAY%T%HOUR%.xml", appData +
"Transforms" + Path.DirectorySeparatorChar +
"SnifferXmlToHtml.xslt",
552 this.xmppServer.ClientSnifferPath = appData +
"XMPP_C2S" + Path.DirectorySeparatorChar +
553 "%ENDPOINT%" + Path.DirectorySeparatorChar +
"XMPP Server Log %YEAR%-%MONTH%-%DAY%T%HOUR%.xml";
556 "XMPP Server Log %YEAR%-%MONTH%-%DAY%T%HOUR%.xml", appData +
"Transforms" + Path.DirectorySeparatorChar +
"SnifferXmlToHtml.xslt",
559 this.xmppServer.DomainSnifferPath = appData +
"XMPP_S2S" + Path.DirectorySeparatorChar +
560 "%DOMAIN%" + Path.DirectorySeparatorChar +
"XMPP Server Log %YEAR%-%MONTH%-%DAY%T%HOUR%.xml";
563 bool Encrypted =
true;
565 if (
Ports.Length == 0)
571 if (
Ports.Length > 0)
573 StringBuilder Url =
new StringBuilder();
587 Url.Append(
Port.ToString());
595 Url.Append(
Port.ToString());
599 string Root = Url.ToString();
601 Url.Append(
"/HttpUpload");
605 MaxFileSize = 1024 * 1024 * 20,
606 MaxFilesPerMinute = 10,
607 MaxBytesPerMinute = 1024 * 1024 * 50,
608 FileLifetime = TimeSpan.FromMinutes(10),
609 FileFolder = Path.Combine(appData,
"HttpUpload"),
610 HttpFolder = Url.ToString(),
613 EncryptedStorageFolder = Path.Combine(appData,
"EncryptedStorage"),
614 EncryptedStorageRoot = Root +
"/EncryptedStorage",
615 PubSubStorageFolder = Path.Combine(appData,
"PubSubStorage"),
616 PubSubStorageRoot = Root +
"/PubSubStorage"
619 this.httpFileUploadComponent =
new HttpFileUploadComponent(this.xmppServer,
"upload", this.httpFileUploadSettings);
620 this.httpFileUploadResource =
new XmppFileUploadResource(
"/HttpUpload", this.httpFileUploadComponent, Encrypted);
623 this.httpServer.
Register(this.httpFileUploadResource);
624 this.httpServer.
Register(this.httpEncryptedFileUploadResource);
625 this.httpServer.
Register(this.httpPubSubFileUploadResource);
627 Export.OnExportFolderUpdated += this.Export_OnExportFolderUpdated;
628 Export.OnExportKeyFolderUpdated += this.Export_OnExportKeyFolderUpdated;
637 if (this.ssoTokens is
null)
638 this.ssoTokens =
new Cache<string, string>(
int.MaxValue, TimeSpan.FromMinutes(30), TimeSpan.FromMinutes(5));
641 ProxyResource.BeforeForwardRequest += this.ProxyResource_AddSsoInformationEncrypted;
643 ProxyResource.BeforeForwardRequest += this.ProxyResource_AddSsoInformationUnencrypted;
648 Gateway.OnNewCertificate += this.Gateway_OnNewCertificate;
671 await this.CheckRegistration();
674 Gateway.ProvisioningClient.ManagePresenceSubscriptionRequests =
false;
678 Gateway.SoftwareUpdateClient.OnSoftwareUpdated += this.SoftwareUpdateClient_OnSoftwareUpdated;
679 Gateway.SoftwareUpdateClient.OnSoftwareValidation += this.SoftwareUpdateClient_OnSoftwareValidation;
680 Gateway.SoftwareUpdateClient.OnSoftwareDownloaded += this.SoftwareUpdateClient_OnSoftwareDownloaded;
681 Gateway.SoftwareUpdateClient.OnSoftwareDeleted += this.SoftwareUpdateClient_OnSoftwareDeleted;
682 Gateway.SoftwareUpdateClient.OnDownloadedSoftwareDeleted += this.SoftwareUpdateClient_OnDownloadedSoftwareDeleted;
685 Gateway.XmppClient.OnStateChanged += this.XmppClient_OnStateChanged;
686 Gateway.XmppClient.OnChatMessage += this.XmppClient_OnChatMessage;
690 Gateway.XmppClient.OnGroupChatMessage += this.XmppClient_OnGroupChatMessage;
691 Gateway.XmppClient.OnValidateSender += this.XmppClient_OnValidateSender;
693 Gateway.MucClient.RoomInvitationReceived += this.MucClient_RoomInvitationReceived;
694 Gateway.MucClient.DirectInvitationReceived += this.MucClient_DirectInvitationReceived;
695 Gateway.MucClient.OccupantPresence += this.MucClient_OccupantPresence;
696 Gateway.MucClient.PrivateMessageReceived += this.MucClient_PrivateMessageReceived;
697 Gateway.MucClient.RoomDestroyed += this.MucClient_RoomDestroyed;
699 await this.LoadPermanentRooms();
705 if (TP > DateTime.MinValue)
708 StringBuilder sb =
new StringBuilder();
709 SortedDictionary<string, bool> AlphabeticalOrder =
new SortedDictionary<string, bool>();
712 AlphabeticalOrder[A.FullName] =
true;
714 foreach (
string Name
in AlphabeticalOrder.Keys)
719 bool Updated = H != H2;
731 sb.Append(
"XMPP server at [`");
733 sb.Append(
"`](http://");
738 sb.Append(
"updated and ");
740 sb.Append(
"restarted at ");
741 sb.Append(
Now.ToShortDateString());
743 sb.Append(
Now.ToLongTimeString());
747 sb.Append(
" [Release Notes](https://lab.tagroot.io/ReleaseNotes)");
762 Gateway.HttpxProxy.PostResource = this.xmppOverHttp;
808 Gateway.OnTerminate += this.Gateway_OnTerminate;
818 private Task Gateway_OnTerminate(
object Sender, EventArgs e)
820 System.Timers.Timer Timer1 =
new System.Timers.Timer(90000);
821 Timer1.Elapsed += this.CloseProcess;
823 System.Timers.Timer Timer2 =
new System.Timers.Timer(110000);
824 Timer1.Elapsed += this.KillProcess;
826 return Task.CompletedTask;
829 private void CloseProcess(
object Sender, System.Timers.ElapsedEventArgs e)
831 Process.GetCurrentProcess().Close();
834 private void KillProcess(
object Sender, System.Timers.ElapsedEventArgs e)
836 Process.GetCurrentProcess().Kill();
845 if (s.StartsWith(
"/"))
848 if (!(this.vulnerableResources?.ContainsKey(s) ??
false))
854 "Scanning for vulnerable web resources.");
857 new KeyValuePair<string, object>(
"Blocked", Blocked));
860 await Task.Delay(60000);
869 if (ContentObject is
null)
871 Content = Encoding.UTF8.GetBytes(ex.Message);
872 ContentType =
"text/plain; charset=utf-8";
883 if (!
string.IsNullOrEmpty(Html))
886 e.Response.StatusMessage = ex.Message;
890 foreach (KeyValuePair<string, string> P
in ex.
HeaderFields)
892 if (
string.Compare(P.Key,
"Content-Type",
true) != 0)
897 e.Response.ContentType =
"text/html; charset=utf-8";
912 private bool subscribingSWUpdates =
false;
913 private bool subscribedToPackages =
false;
915 private async Task XmppClient_OnStateChanged(
object Sender, Networking.XMPP.XmppState NewState)
917 if (NewState == Networking.XMPP.XmppState.Connected)
920 !
this.subscribingSWUpdates &&
923 this.subscribingSWUpdates =
true;
928 if ((DateTime.Now - LastUpdate).TotalDays >= 7 || !
this.subscribedToPackages)
931 this.subscribedToPackages =
true;
934 await this.CheckSoftwarePackage(
Package, (P, MessageId) => Task.FromResult<
string>(MessageId));
945 this.subscribingSWUpdates =
false;
949 await this.RejoinRooms();
953 private Task Gateway_OnNewCertificate(
object Sender, IoTGateway.Events.CertificateEventArgs e)
958 return Task.CompletedTask;
969 if (this.webNodes.ContainsKey(NodeName))
973 this.webNodes[NodeName] =
WebNode;
986 this.webNodes.Remove(NodeName);
994 if (!this.webNodes.TryGetValue(NodeName, out
WebNode))
997 this.webNodes.Remove(NodeName);
1004 public async Task DoImportIpLocalizationDatabase()
1006 string s = Path.Combine(PackagesFolder, Ip2LocalizationPackageName);
1008 this.ImportIpLocalizationDatabase(
null);
1011 private static bool importingIp =
false;
1013 private async
void ImportIpLocalizationDatabase(
object State)
1020 string s = Path.Combine(PackagesFolder, Ip2LocalizationPackageName);
1024 DateTime TP = File.GetLastWriteTime(s);
1029 StringBuilder sb =
new StringBuilder(
"Samples:=[");
1030 DateTime
Start = DateTime.Now;
1044 catch (Exception ex)
1052 using (FileStream fs = File.OpenRead(s))
1054 using (StreamReader r =
new StreamReader(fs))
1056 while (!r.EndOfStream)
1058 string Row = await r.ReadLineAsync();
1059 string[][] Records =
CSV.
Parse(Row);
1061 foreach (
string[] Record
in Records)
1063 if (Record.Length >= 6 &&
1064 uint.TryParse(Record[0], out uint IpRangeFrom) &&
1065 uint.TryParse(Record[1], out uint IpRangeTo))
1071 RangeStart = IpRangeFrom,
1072 RangeEnd = IpRangeTo,
1073 CountryCode = Record[2],
1074 Country = Record[3],
1081 if (Count % 10000 == 0)
1092 sb.Append(Count.ToString());
1115 sb.Append(Count.ToString());
1118 sb.AppendLine(
"]];");
1120 sb.AppendLine(
"Objects:=Samples[0,];");
1121 sb.AppendLine(
"Seconds:=Samples[1,];");
1122 sb.AppendLine(
"ObjOverTime:=plot2dcurve(Seconds,Objects);");
1123 sb.AppendLine(
"ObjOverTime.Title:=\"Objects imported over time\";");
1124 sb.AppendLine(
"ObjOverTime.LabelX:=\"Seconds\";");
1125 sb.AppendLine(
"ObjOverTime.LabelY:=\"#Objects\";");
1127 sb.AppendLine(
"NrSamples:=count(Objects);");
1128 sb.AppendLine(
"DeltaSeconds:=Seconds[1..(NrSamples-1)]-Seconds[0..(NrSamples-2)];");
1129 sb.AppendLine(
"DeltaObjects:=Objects[1..(NrSamples-1)]-Objects[0..(NrSamples-2)];");
1130 sb.AppendLine(
"ObjectsPerSecond:=DeltaObjects./DeltaSeconds;");
1131 sb.AppendLine(
"SpeedOverTime:=plot2dcurve(Seconds[1..(NrSamples-1)],ObjectsPerSecond);");
1132 sb.AppendLine(
"SpeedOverTime.Title:=\"Objects/s imported over time\";");
1133 sb.AppendLine(
"SpeedOverTime.LabelX:=\"Seconds\";");
1134 sb.AppendLine(
"SpeedOverTime.LabelY:=\"#Objects/s\";");
1136 File.WriteAllText(appData +
"ImportTimes.script", sb.ToString());
1139 new KeyValuePair<string, object>(
"NrImported", Count),
1140 new KeyValuePair<string, object>(
"NrSkipped", Skipped));
1145 Count.ToString() +
" records imported. " + Skipped.ToString() +
" " +
1146 (Skipped == 1 ?
"record" :
"records") +
" skipped.");
1161 catch (Exception ex)
1168 catch (Exception ex)
1170 Log.
Error(
"Unable to import IP localization database.\r\n\r\n" + ex.Message, Ip2LocalizationPackageName);
1174 importingIp =
false;
1181 if (this.ip4LocalizationCache is
null)
1190 if (!(Location is
null))
1192 e.
AddTag(
"City", Location.City);
1193 e.
AddTag(
"Region", Location.Region);
1194 e.
AddTag(
"Country", Location.Country);
1195 e.
AddTag(
"Code", Location.CountryCode);
1197 string s =
"flag-" + Location.CountryCode?.ToLower();
1199 e.
AddTag(
"Flag",
":" + s +
":");
1201 e.
AddTag(
"Acknowledgement",
"This site or product includes IP2Location LITE data available from http://www.ip2location.com.");
1213 if (i > 0 &&
int.TryParse(
RemoteEndpoint.Substring(i + 1), out
int _))
1229 if (Addr.AddressFamily != AddressFamily.InterNetwork)
1232 byte[] Bytes = Addr.GetAddressBytes();
1234 uint Value = Bytes[0];
1246 if (Value >= Loc.RangeStart && Value <= Loc.RangeEnd)
1250 catch (Exception ex)
1265 Markdown.Append(
"| Remote Endpoint: | ");
1267 Markdown.AppendLine(
" |");
1271 Markdown.Append(
"| ");
1273 Markdown.Append(
" | ");
1275 Markdown.AppendLine(
" |");
1279 private async
void Service_OnAfterBackup(
object P)
1283 if (!(this.httpServer is
null))
1303 if (!(this.xmppServer is
null))
1326 if (!(this.eventStatistics is
null))
1334 PerType = this.Convert(Stat.
PerType),
1335 PerLevel = this.Convert(Stat.
PerLevel),
1337 PerActor = this.Convert(Stat.
PerActor),
1338 PerModule = this.Convert(Stat.
PerModule),
1346 DateTime TimeLimit = DateTime.Now.AddDays(-30);
1349 if (!(this.persistenceLayer is
null))
1356 if (!(this.xmppServer is
null))
1360 Log.
Informational(
"Mail content from " + Nr.ToString() +
" old messages deleted.");
1363 if (!(this.pubSubComponent is
null))
1367 Log.
Informational(Nr.ToString() +
" pubsub nodes (and " + Nr2.ToString() +
" items) deleted.");
1370 (
int NrTokens,
int NrEvents,
int NrTags) = await
NeuroFeatures.NeuroFeaturesProcessor.DeleteExpiredTokens();
1372 Log.
Informational(NrTokens.ToString() +
" tokens, " + NrTags.ToString() +
" tags and " + NrEvents.ToString() +
" events deleted.");
1374 (
int NrMachines,
int NrEventHandlers,
int NrCurrentStates,
int NrSamples) =
1377 Log.
Informational(NrMachines.ToString() +
" state machines, " + NrEventHandlers.ToString() +
" event handlers and " + NrSamples.ToString() +
" samples deleted.");
1379 catch (Exception ex)
1389 private Sources.PersistedData.Commands.Statistic[] Convert(Dictionary<string, Statistic> Statistics)
1391 List<Sources.PersistedData.Commands.Statistic> Result =
new List<Sources.PersistedData.Commands.Statistic>();
1393 foreach (KeyValuePair<string, Statistic> P
in Statistics)
1395 Result.Add(
new Sources.PersistedData.Commands.Statistic()
1398 Count = P.Value.Count,
1399 First = P.Value.First,
1404 return Result.ToArray();
1414 Gateway.OnNewCertificate -= this.Gateway_OnNewCertificate;
1415 Gateway.OnTerminate -= this.Gateway_OnTerminate;
1419 Gateway.SoftwareUpdateClient.OnSoftwareUpdated -= this.SoftwareUpdateClient_OnSoftwareUpdated;
1420 Gateway.SoftwareUpdateClient.OnSoftwareValidation -= this.SoftwareUpdateClient_OnSoftwareValidation;
1421 Gateway.SoftwareUpdateClient.OnSoftwareDownloaded -= this.SoftwareUpdateClient_OnSoftwareDownloaded;
1422 Gateway.SoftwareUpdateClient.OnSoftwareDeleted -= this.SoftwareUpdateClient_OnSoftwareDeleted;
1423 Gateway.SoftwareUpdateClient.OnDownloadedSoftwareDeleted -= this.SoftwareUpdateClient_OnDownloadedSoftwareDeleted;
1429 Gateway.XmppClient.OnGroupChatMessage -= this.XmppClient_OnGroupChatMessage;
1430 Gateway.XmppClient.OnValidateSender -= this.XmppClient_OnValidateSender;
1432 Gateway.MucClient.RoomInvitationReceived -= this.MucClient_RoomInvitationReceived;
1433 Gateway.MucClient.DirectInvitationReceived -= this.MucClient_DirectInvitationReceived;
1434 Gateway.MucClient.OccupantPresence -= this.MucClient_OccupantPresence;
1435 Gateway.MucClient.PrivateMessageReceived -= this.MucClient_PrivateMessageReceived;
1436 Gateway.MucClient.RoomDestroyed -= this.MucClient_RoomDestroyed;
1439 this.sampleTimer?.Dispose();
1440 this.sampleTimer =
null;
1442 await this.LeaveAllRooms();
1444 LoginAuditor.AnnotateEndpoint -= this.LoginAuditor_AnnotateEndpoint;
1445 this.ip4LocalizationCache?.
Dispose();
1446 this.ip4LocalizationCache =
null;
1448 if (!(this.eventStatistics is
null))
1451 this.eventStatistics.
Dispose();
1452 this.eventStatistics =
null;
1457 if (!(this.vulnerableResources is
null))
1459 this.vulnerableResources =
null;
1462 Gateway.Root.FileNotFound -= this.Root_FileNotFound;
1465 if (!(this.httpServer is
null))
1467 Export.OnExportFolderUpdated -= this.Export_OnExportFolderUpdated;
1468 Export.OnExportKeyFolderUpdated -= this.Export_OnExportKeyFolderUpdated;
1472 this.httpServer.
Unregister(this.webSocketClient);
1473 this.httpServer.
Unregister(this.webHostMetaDataXml);
1474 this.httpServer.
Unregister(this.webHostMetaDataJson);
1476 this.httpServer.
Unregister(this.createApiKey);
1477 this.httpServer.
Unregister(this.updateApiKey);
1478 this.httpServer.
Unregister(this.createAccount);
1479 this.httpServer.
Unregister(this.updateAccount);
1480 this.httpServer.
Unregister(this.deleteAccount);
1481 this.httpServer.
Unregister(this.updatePubSubNode);
1482 this.httpServer.
Unregister(this.deletePubSubNode);
1483 this.httpServer.
Unregister(this.loadMoreItems);
1485 this.httpServer.
Unregister(this.requestAccount);
1486 this.httpServer.
Unregister(this.requestApiKey);
1487 this.httpServer.
Unregister(this.searchEvents);
1488 this.httpServer.
Unregister(this.sendMessage);
1489 this.httpServer.
Unregister(this.setContractState);
1490 this.httpServer.
Unregister(this.publisherAvatar);
1491 this.httpServer.
Unregister(this.legalIdentityStateChanged);
1493 this.httpServer.
Unregister(this.uploadPackage);
1494 this.httpServer.
Unregister(this.uploadSignature);
1495 this.httpServer.
Unregister(this.deletePackage);
1496 this.httpServer.
Unregister(this.installPackage);
1497 this.httpServer.
Unregister(this.uninstallPackage);
1498 this.httpServer.
Unregister(this.dnsOverHttps);
1499 this.httpServer.
Unregister(this.validateLegalId);
1500 this.httpServer.
Unregister(this.validateContract);
1503 this.httpServer.
Unregister(this.whatsMyEndpointResource);
1506 this.httpServer.
Unregister(this.xmppOverHttp);
1509 this.httpxServer =
null;
1511 if (!(this.httpFileUploadResource is
null))
1512 this.httpServer.
Unregister(this.httpFileUploadResource);
1514 if (!(this.httpEncryptedFileUploadResource is
null))
1515 this.httpServer.
Unregister(this.httpEncryptedFileUploadResource);
1517 if (!(this.httpPubSubFileUploadResource is
null))
1518 this.httpServer.
Unregister(this.httpPubSubFileUploadResource);
1520 if (!(this.webNodes is
null))
1524 lock (this.webNodes)
1526 Nodes =
new WebNode[this.webNodes.Count];
1527 this.webNodes.Values.CopyTo(Nodes, 0);
1528 this.webNodes.Clear();
1535 this.webClient1 =
null;
1536 this.webClient2 =
null;
1537 this.webSocketClient =
null;
1538 this.webHostMetaDataXml =
null;
1539 this.webHostMetaDataJson =
null;
1540 this.createApiKey =
null;
1541 this.updateApiKey =
null;
1542 this.createAccount =
null;
1543 this.updateAccount =
null;
1544 this.deleteAccount =
null;
1545 this.updatePubSubNode =
null;
1546 this.deletePubSubNode =
null;
1547 this.loadMoreItems =
null;
1548 this.feedback =
null;
1549 this.requestAccount =
null;
1550 this.requestApiKey =
null;
1551 this.searchEvents =
null;
1552 this.sendMessage =
null;
1553 this.setContractState =
null;
1554 this.publisherAvatar =
null;
1555 this.legalIdentityStateChanged =
null;
1557 this.uploadPackage =
null;
1558 this.uploadSignature =
null;
1559 this.deletePackage =
null;
1560 this.installPackage =
null;
1561 this.uninstallPackage =
null;
1562 this.dnsOverHttps =
null;
1563 this.validateLegalId =
null;
1564 this.validateContract =
null;
1566 this.quickLogin?.Dispose();
1567 this.quickLogin =
null;
1568 this.whatsMyEndpointResource =
null;
1569 this.addNote =
null;
1570 this.chatFile =
null;
1571 this.xmppOverHttp =
null;
1572 this.httpFileUploadResource =
null;
1573 this.httpEncryptedFileUploadResource =
null;
1574 this.httpPubSubFileUploadResource =
null;
1576 this.httpServer =
null;
1579 this.httpFileUploadComponent?.
Dispose();
1580 this.httpFileUploadComponent =
null;
1582 this.socks5Component?.
Dispose();
1583 this.socks5Component =
null;
1585 this.serviceRegistrationComponent?.
Dispose();
1586 this.serviceRegistrationComponent =
null;
1588 this.pubSubComponent?.
Dispose();
1589 this.pubSubComponent =
null;
1592 this.mucComponent =
null;
1594 this.provisioningComponent?.
Dispose();
1595 this.provisioningComponent =
null;
1597 this.legalComponent?.
Dispose();
1598 this.legalComponent =
null;
1600 this.eDalerComponent?.
Dispose();
1601 this.eDalerComponent =
null;
1603 this.eventLogComponent?.
Dispose();
1604 this.eventLogComponent =
null;
1606 if (!(this.xmppServer is
null))
1608 this.xmppServer.ClientConnectionAdded -= this.XmppServer_ClientConnectionAdded;
1609 this.xmppServer.ClientConnectionRemoved -= this.XmppServer_ClientConnectionRemoved;
1610 this.xmppServer.ClientConnectionUpdated -= this.XmppServer_ClientConnectionUpdated;
1611 this.xmppServer.ServerConnectionAdded -= this.XmppServer_ServerConnectionAdded;
1612 this.xmppServer.ServerConnectionRemoved -= this.XmppServer_ServerConnectionRemoved;
1613 this.xmppServer.ServerConnectionUpdated -= this.XmppServer_ServerConnectionUpdated;
1616 this.xmppServer =
null;
1620 this.smtpServer =
null;
1623 this.chatSessions =
null;
1625 this.consolidators?.
Dispose();
1626 this.consolidators =
null;
1629 this.ssoTokens =
null;
1632 this.jwtFactory =
null;
1638 public static XmppServer Server => instance?.xmppServer;
1639 public static SmtpServer MailServer => instance?.smtpServer;
1650 public static string PackagesFolder
1655 public static string DownloadsFolder
1660 public static ApiKey GetApiKey(
string Key)
1662 ApiKey Result = GetApiKeyAsync(Key).Result
1668 public static async Task<ApiKey> GetApiKeyAsync(
string Key)
1670 if (
string.IsNullOrEmpty(Key))
1688 IAccount Result = GetAccountAsync(UserName).Result
1696 if (instance is
null)
1697 return GetAccountAsyncNoInit(UserName);
1712 if (instance is
null)
1713 return GetRosterItemAsyncNoInit(UserName, Jid);
1715 return instance.persistenceLayer.
GetRosterItem(UserName, Jid);
1732 if (instance is
null)
1733 return GetRosterAsyncNoInit(UserName);
1735 return instance.persistenceLayer.
GetRoster(UserName);
1738 private static async Task<IEnumerable<IRosterItem>> GetRosterAsyncNoInit(
CaseInsensitiveString UserName)
1744 private static Stopwatch CreateWatch()
1746 Stopwatch Watch =
new Stopwatch();
1762 private static Calibration
Calibrate(Stopwatch Clock)
1764 DateTime TP = DateTime.Now;
1765 long Ticks = TP.Ticks;
1769 for (i = 0; i < 3; i++)
1771 while ((TP = DateTime.UtcNow).Ticks == Ticks)
1774 HF = Clock.ElapsedTicks;
1778 return new Calibration()
1781 ReferenceHfTick = HF,
1782 TicksTo100Ns = 1e7 / Stopwatch.Frequency
1793 DateTime NowRef = DateTime.UtcNow;
1794 long Ticks = clock.ElapsedTicks;
1795 Calibration Calibration = calibration;
1797 Ticks -= Calibration.ReferenceHfTick;
1799 long Ns100 = (long)(Ticks * Calibration.TicksTo100Ns + 0.5);
1800 long Milliseconds = Ns100 / 10000;
1802 DateTime
Now = Calibration.Reference.AddMilliseconds(Milliseconds);
1804 if ((
Now - NowRef).TotalSeconds >= 1)
1813 return new DateTimeHF(
Now, (
int)(Ns100 / 10), (
int)(Ns100 % 10), Ticks);
1818 private async Task DnsRequest(
object Sender,
IqEventArgs e)
1822 byte[] ReqBin = System.Convert.FromBase64String(e.
Query.InnerText);
1835 RespBin[0] = ReqBin[0];
1836 RespBin[1] = ReqBin[1];
1838 StringBuilder Xml =
new StringBuilder();
1840 Xml.Append(
"<dns xmlns='");
1843 Xml.Append(System.Convert.ToBase64String(RespBin));
1844 Xml.Append(
"</dns>");
1853 catch (Exception ex)
1861 PubSubNode Result = GetPubSubNodeAsync(NodeName).Result
1869 if (instance is
null)
1870 return GetPubSubNodeAsyncNoInit(NodeName);
1914 return IsAdmin(Jid,
null);
1919 Jid = Networking.XMPP.XmppClient.GetBareJID(Jid);
1927 if (
string.Compare(s, Jid,
true) == 0)
1940 public static string DateTimesToHTML(DateTime Created, DateTime Updated)
1942 StringBuilder Result =
new StringBuilder();
1944 Created = Created.ToLocalTime();
1946 if (Updated != DateTime.MinValue)
1947 Updated = Updated.ToLocalTime();
1949 Result.Append(
"<span class=\"ContentItemTimestamp\">");
1950 Result.Append(Created.ToShortDateString());
1951 Result.Append(
", ");
1952 Result.Append(Created.ToLongTimeString());
1953 Result.Append(
"</span>");
1955 if (Updated != Created && Updated != DateTime.MinValue)
1957 Result.Append(
"<span class=\"ContentItemUpdated\">");
1958 Result.Append(Updated.ToShortDateString());
1959 Result.Append(
", ");
1960 Result.Append(Updated.ToLongTimeString());
1961 Result.Append(
"</span>");
1964 return Result.ToString();
1967 private async Task CheckRegistration()
1973 if (this.serviceRegistrationClient is
null)
1986 StringBuilder Xml =
new StringBuilder();
1990 Xml.Append(
"<vCard xmlns='vcard-temp'>");
1991 Xml.Append(
"<FN>XMPP Broker on ");
1993 Xml.Append(
"</FN>");
1994 Xml.Append(
"<URL>");
1996 Xml.Append(
"</URL>");
1997 Xml.Append(
"<JABBERID>");
1999 Xml.Append(
"</JABBERID>");
2000 Xml.Append(
"<PHOTO><TYPE>image/png</TYPE><BINVAL>");
2001 Xml.Append(System.Convert.ToBase64String(
Avatar, Base64FormattingOptions.None));
2002 Xml.Append(
"</BINVAL></PHOTO>");
2003 Xml.Append(
"</vCard>");
2013 catch (Exception ex)
2018 Gateway.
ScheduleEvent((P) => Task.Run(() =>
this.CheckRegistration()), DateTime.Now.AddMinutes(15),
null);
2021 private Task XmppServer_ClientConnectionAdded(
object Sender, Networking.XMPP.Server.ClientConnectionEventArgs e)
2023 return this.connectionsSource?.ClientConnectionAdded(Sender, e) ?? Task.CompletedTask;
2026 private Task XmppServer_ClientConnectionRemoved(
object Sender, Networking.XMPP.Server.ClientConnectionEventArgs e)
2028 return this.connectionsSource?.ClientConnectionRemoved(Sender, e) ?? Task.CompletedTask;
2031 private Task XmppServer_ClientConnectionUpdated(
object Sender, Networking.XMPP.Server.ClientConnectionEventArgs e)
2033 return this.connectionsSource?.ClientConnectionUpdated(Sender, e) ?? Task.CompletedTask;
2036 private Task XmppServer_ServerConnectionAdded(
object Sender, Networking.XMPP.Server.ServerConnectionEventArgs e)
2038 return this.connectionsSource?.ServerConnectionAdded(Sender, e) ?? Task.CompletedTask;
2041 private Task XmppServer_ServerConnectionRemoved(
object Sender, Networking.XMPP.Server.ServerConnectionEventArgs e)
2043 return this.connectionsSource?.ServerConnectionRemoved(Sender, e) ?? Task.CompletedTask;
2046 private Task XmppServer_ServerConnectionUpdated(
object Sender, Networking.XMPP.Server.ServerConnectionEventArgs e)
2048 return this.connectionsSource?.ServerConnectionUpdated(Sender, e) ?? Task.CompletedTask;
2051 internal async Task<bool> CheckSoftwarePackage(Networking.XMPP.Software.Package RemotePackage,
ResponseCallbackHandler ResponseCallback)
2057 if (LocalPackage is
null || LocalPackage.
Published < RemotePackage.Published)
2059 string MessageId = await ResponseCallback(
"Downloading `" + RemotePackage.FileName +
"`",
string.Empty);
2067 catch (Exception ex)
2075 private Task SoftwareUpdateClient_OnSoftwareUpdated(
object Sender, Networking.XMPP.Software.PackageUpdatedEventArgs e)
2077 Log.
Informational(
"New software package available.", PackageTags(e.Package));
2080 return Task.CompletedTask;
2083 private static KeyValuePair<string, object>[] PackageTags(Networking.XMPP.Software.Package
Package)
2085 return new KeyValuePair<string, object>[]
2088 new KeyValuePair<string, object>(
"Bytes",
Package.
Bytes),
2092 new KeyValuePair<string, object>(
"Signature", System.Convert.ToBase64String(
Package.
Signature ??
new byte[0])),
2093 new KeyValuePair<string, object>(
"URL",
Package.
Url)
2097 private async Task SoftwareUpdateClient_OnSoftwareValidation(
object Sender, Networking.XMPP.Software.PackageFileEventArgs e)
2099 string FileName = Path.GetFileName(e.LocalFileName);
2103 if (!ValidateIoTBrokerPackage(e.LocalFileName, e.Package.Signature))
2104 throw new Exception(
"Invalid signature.");
2111 if (!ValidatePackage(e.LocalFileName,
Package.
PublicKey, e.Package.Signature))
2112 throw new Exception(
"Invalid signature.");
2117 internal static bool ValidateIoTBrokerPackage(
string FileName,
byte[] Signature)
2119 Log.
Notice(
"Validating package.", FileName);
2121 using (FileStream f = File.OpenRead(FileName))
2123 bool Result = ValidateIoTBrokerPackage(f, Signature);
2128 Log.
Error(
"Package not valid.", FileName);
2134 internal static bool ValidatePackage(
string FileName,
byte[] PublicKey,
byte[] Signature)
2136 Log.
Notice(
"Validating package.", FileName);
2138 using (FileStream f = File.OpenRead(FileName))
2140 bool Result = ValidatePackage(f, PublicKey, Signature);
2145 Log.
Error(
"Package not valid.", FileName);
2151 internal static bool ValidateIoTBrokerPackage(Stream Data,
byte[] Signature)
2153 return ValidatePackage(Data, iotBrokerPackagePublicKey, Signature);
2156 internal static bool ValidatePackage(Stream Data,
byte[] PublicKey,
byte[] Signature)
2158 return ed448.Verify(Data, PublicKey, Signature);
2161 private Task SoftwareUpdateClient_OnSoftwareDownloaded(
object Sender, Networking.XMPP.Software.PackageFileEventArgs e)
2163 return this.PackageDownloaded(e.Package, e.
From,
string.
Empty, (Markdown, MessageId) => Task.FromResult(MessageId));
2166 private async Task PackageDownloaded(Networking.XMPP.Software.Package DownloadedPackage,
string RemoteEndpoint,
string MessageId,
2169 Log.
Notice(
"New software package downloaded.", PackageTags(DownloadedPackage));
2171 await ResponseCallback(
"Software package downloaded: `" + DownloadedPackage.FileName +
"`", MessageId);
2173 DateTime
Now = DateTime.UtcNow;
2180 FileName = DownloadedPackage.
FileName,
2181 Signature = DownloadedPackage.Signature,
2184 Supersedes = DateTime.MinValue,
2186 Bytes = DownloadedPackage.Bytes,
2188 Installed = DateTime.MinValue,
2190 Downloadable =
false
2197 Package.Signature = DownloadedPackage.Signature;
2200 Package.Published =
Now;
2201 Package.Bytes = DownloadedPackage.Bytes;
2204 Package.ContentOnly = IsContentPackage(
Package);
2209 if (!(this.provisioningComponent is
null))
2210 await this.provisioningComponent.NewPackage(
Package);
2217 else if (
string.Compare(DownloadedPackage.FileName, Ip2LocalizationPackageName,
true) == 0)
2226 StringBuilder Markdown =
new StringBuilder();
2227 DateTime
Now = DateTime.Now;
2242 Markdown.AppendLine(
"New version of installed software has been downloaded");
2243 Markdown.AppendLine(
"==========================================================");
2244 Markdown.AppendLine();
2245 Markdown.AppendLine(
"| Package ||");
2246 Markdown.AppendLine(
"|:------|:-------|");
2247 Markdown.AppendLine(
"| Filename: | `" + DownloadedPackage.
FileName +
"` |");
2252 if (DownloadedPackage.
Supersedes != DateTime.MinValue)
2255 Markdown.AppendLine(
"| Signature: | " + System.Convert.ToBase64String(DownloadedPackage.
Signature) +
" |");
2257 Markdown.Append(
"| Date | ");
2259 Markdown.AppendLine(
" |");
2260 Markdown.Append(
"| Time | ");
2262 Markdown.AppendLine(
" |");
2263 Markdown.AppendLine();
2267 Markdown.AppendLine(
"See [Release Notes](https://lab.tagroot.io/ReleaseNotes) for information about what is new.");
2268 Markdown.AppendLine();
2271 if (DelayMinutes > 0)
2279 await this.UpdateSoftware(DownloadedPackage,
false);
2283 Markdown.AppendLine(
"The new software has been automatically installed.");
2285 catch (Exception ex)
2289 Markdown.AppendLine(
"Unable to install the new software. The following error was reported: ");
2290 Markdown.AppendLine();
2291 Markdown.AppendLine(
"```");
2292 Markdown.AppendLine(ex.Message.Trim());
2293 Markdown.AppendLine(
"```");
2298 if (autoUpdateTP > DateTime.MinValue)
2301 autoUpdateTP = DateTime.MinValue;
2304 DateTime TP =
Now.AddMinutes(DelayMinutes);
2309 Markdown.Append(
"The new software will be automatically installed");
2311 if (DelayMinutes == 1)
2312 Markdown.Append(
" in 1 minute");
2313 else if (DelayMinutes <= 60)
2314 Markdown.Append(
" in " + DelayMinutes.ToString() +
" minutes");
2317 Markdown.Append(
" at ");
2319 if (TP.Date ==
Now.Date)
2320 Markdown.Append(TP.ToShortTimeString());
2323 Markdown.Append(TP.ToShortDateString());
2324 Markdown.Append(
", ");
2325 Markdown.Append(TP.ToShortTimeString());
2329 Markdown.AppendLine(
", unless cancelled from the chat interface.");
2333 Markdown.AppendLine(
"You can update the server with the new package from the chat interface.");
2343 if (!File.Exists(FileName))
2346 StringBuilder sb =
new StringBuilder();
2354 sb.Append(
":Waher.Utility.Install");
2357 byte[] Digest = H.
ComputeVariable(Encoding.UTF8.GetBytes(sb.ToString()));
2358 byte[] AesKey =
new byte[32];
2359 byte[] IV =
new byte[16];
2361 FileStream fs =
null;
2362 ICryptoTransform AesTransform =
null;
2363 CryptoStream Decrypted =
null;
2364 GZipStream Decompressed =
null;
2366 Array.Copy(Digest, 0, AesKey, 0, 32);
2367 Array.Copy(Digest, 32, IV, 0, 16);
2372 Aes.BlockSize = 128;
2374 Aes.Mode = CipherMode.CBC;
2375 Aes.Padding = PaddingMode.Zeros;
2377 fs = File.OpenRead(FileName);
2378 AesTransform = Aes.CreateDecryptor(AesKey, IV);
2379 Decrypted =
new CryptoStream(fs, AesTransform, CryptoStreamMode.Read);
2380 Decompressed =
new GZipStream(Decrypted, CompressionMode.Decompress);
2382 byte b = ReadByte(Decompressed);
2388 Decompressed.ReadAll(Bin, 0, b);
2391 Bin = ReadBin(Decompressed);
2392 if (Encoding.ASCII.GetString(Bin) !=
"IoTGatewayPackage")
2393 throw new Exception(
"Invalid package file.");
2395 while ((b = ReadByte(Decompressed)) != 0)
2397 string RelativeName = Encoding.UTF8.GetString(ReadBin(Decompressed));
2398 ReadVarLenUInt(Decompressed);
2399 ReadVarLenUInt(Decompressed);
2400 ReadVarLenUInt(Decompressed);
2401 ReadVarLenUInt(Decompressed);
2402 ulong Bytes = ReadVarLenUInt(Decompressed);
2407 SkipBytes(Decompressed, Bytes);
2417 SkipBytes(Decompressed, Bytes);
2421 throw new Exception(
"Invalid package file.");
2427 Decompressed?.Dispose();
2428 Decrypted?.Dispose();
2429 AesTransform?.Dispose();
2436 catch (Exception ex)
2443 private static byte[] ReadBin(Stream Input)
2445 ulong Len = ReadVarLenUInt(Input);
2446 if (Len >
int.MaxValue)
2447 throw new Exception(
"Invalid package.");
2450 byte[] Result =
new byte[c];
2452 Input.ReadAll(Result, 0, c);
2457 private static ulong ReadVarLenUInt(Stream Input)
2465 b = ReadByte(Input);
2467 Len |= ((ulong)(b & 127)) << Offset;
2470 while ((b & 0x80) != 0);
2475 private static byte ReadByte(Stream Input)
2477 int i = Input.ReadByte();
2479 throw new EndOfStreamException(
"Reading past end-of-file.");
2484 private static void SkipBytes(Stream Input, ulong Bytes)
2487 if (Bytes < (ulong)c)
2490 byte[] Buffer =
new byte[c];
2492 Input.ReadAll(Buffer, 0, c);
2495 internal async
void UpdateSoftware(
object P)
2500 await this.UpdateSoftware(
Package,
true);
2502 catch (Exception ex)
2513 Folder = PackagesFolder
2516 return this.UpdateSoftware(
Package, State, Backup);
2521 return this.UpdateSoftware(
Package, State, Backup, (Msg, MessageId) => Task.FromResult<
string>(MessageId));
2526 string MessageId =
string.Empty;
2530 MessageId = await ResponseCallback(
"Performing backup.", MessageId);
2534 StringBuilder sb =
new StringBuilder();
2536 bool RestartRequired;
2537 string ServerFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AppDomain.CurrentDomain.FriendlyName +
FileSystem.
ExecutableExtension);
2538 if (!File.Exists(ServerFileName))
2539 ServerFileName = Path.ChangeExtension(ServerFileName,
"dll");
2541 sb.Append(
"Install -d \"");
2543 sb.Append(
"\" -s \"");
2544 sb.Append(ServerFileName);
2548 bool UpdateBroker =
false;
2552 autoUpdateTP = DateTime.MinValue;
2555 if (!File.Exists(BrokerPackageFileName))
2561 UpdateBroker =
true;
2563 List<Package> ToInstall =
new List<Package>();
2565 foreach (
Package Package2
in Packages)
2567 if (Package2.
Installed == DateTime.MinValue)
2578 ToInstall.Add(Package2);
2580 Package2.Installed = Package2.
Published;
2584 ToInstall.Add(Package2);
2587 Packages = ToInstall.ToArray();
2588 RestartRequired =
true;
2605 RestartRequired =
false;
2610 foreach (
Package Package2
in Packages)
2612 string PackageFileName = Path.Combine(PackagesFolder, Package2.
FileName);
2614 if (File.Exists(PackageFileName))
2616 sb.Append(
" -p \"");
2617 sb.Append(PackageFileName.Replace(
"\"",
"\\\""));
2619 if (!(Package2.
AesKey is
null))
2621 sb.Append(
"\" -k \"");
2631 sb.Append(
" -p \"");
2632 sb.Append(BrokerPackageFileName);
2633 sb.Append(
"\" -k \"");
2638 sb.Append(
" -n \"");
2640 sb.Append(
"\" -w 120000 -v -i > install.log");
2642 MessageId = await ResponseCallback(
"Starting update process...", MessageId);
2644 if (await this.ExecuteCommand(State.
To, sb.ToString(), State,
true, ResponseCallback))
2646 if (RestartRequired)
2648 await ResponseCallback(
"Stopping service... Update procedure will continue when service has been stopped. Service will then restart using the updated version.", MessageId);
2654 await ResponseCallback(
"Package installed. No restart required.", MessageId);
2660 internal async Task UninstallSoftware(
string PackageFileName,
byte[] AesKey)
2662 string s = Path.Combine(PackagesFolder, PackageFileName);
2663 if (!File.Exists(s))
2667 if (!File.Exists(s2))
2668 s2 = s2.
Substring(0, s2.Length - 3) +
"dll";
2670 StringBuilder sb =
new StringBuilder();
2672 sb.Append(
"Install -p \"");
2674 sb.Append(
"\" -d \"");
2676 sb.Append(
"\" -s \"");
2679 if (!(AesKey is
null))
2681 sb.Append(
"\" -k \"");
2690 if (!RestartRequired)
2693 sb.Append(
" -n \"");
2695 sb.Append(
"\" -w 120000 -v -u > install.log");
2700 Folder = PackagesFolder
2705 if (await this.ExecuteCommand(
string.Empty, sb.ToString(), State,
true,
2706 (Msg, MessageId) => Task.FromResult<
string>(MessageId)) && RestartRequired)
2712 private Task SoftwareUpdateClient_OnSoftwareDeleted(
object Sender, Networking.XMPP.Software.PackageDeletedEventArgs e)
2714 Log.
Informational(
"Software package deleted on server.", PackageTags(e.Package));
2717 return Task.CompletedTask;
2720 private async Task SoftwareUpdateClient_OnDownloadedSoftwareDeleted(
object Sender, Networking.XMPP.Software.PackageFileEventArgs e)
2722 Log.
Notice(
"Local copy of software package deleted.", PackageTags(e.Package));
2726 if (!(OldPackage is
null))
2730 if (!(this.provisioningComponent is
null))
2731 await this.provisioningComponent.PackageDeleted(OldPackage);
2735 private async Task<(string, string, bool)> GetPlainText(Networking.XMPP.Events.MessageEventArgs e, DateTime OfflineThreshold)
2737 string s = e.Body?.Trim();
2739 string ReplaceObjectId =
string.Empty;
2740 bool IsMarkdown =
false;
2742 foreach (XmlNode N
in e.Message.ChildNodes)
2744 if (N is XmlElement E)
2746 switch (E.LocalName)
2749 if (E.NamespaceURI ==
"urn:xmpp:content" &&
2752 if (
string.IsNullOrEmpty(s))
2764 E.HasAttribute(
"stamp") &&
2765 XML.
TryParse(E.GetAttribute(
"stamp"), out DateTime Timestamp) &&
2766 Timestamp.ToUniversalTime() < OfflineThreshold.ToUniversalTime())
2768 return (
string.Empty,
string.Empty,
false);
2773 if (E.NamespaceURI ==
"urn:xmpp:message-correct:0")
2780 return (s, ReplaceObjectId, IsMarkdown);
2784 private string GetMarkdown(Networking.XMPP.Events.MessageEventArgs e, DateTime OfflineThreshold,
bool EncodeIfText, out
string ReplaceObjectId, out
bool IsMarkdown)
2786 string s = e.Body?.Trim();
2788 ReplaceObjectId =
string.Empty;
2791 foreach (XmlNode N
in e.Message.ChildNodes)
2793 if (N is XmlElement E)
2795 switch (E.LocalName)
2798 if (E.NamespaceURI ==
"urn:xmpp:content" &&
2801 s = E.InnerText.Trim();
2808 E.HasAttribute(
"stamp") &&
2809 XML.
TryParse(E.GetAttribute(
"stamp"), out DateTime Timestamp) &&
2810 Timestamp.ToUniversalTime() < OfflineThreshold.ToUniversalTime())
2812 return string.Empty;
2817 if (E.NamespaceURI ==
"urn:xmpp:message-correct:0")
2827 private async Task XmppClient_OnChatMessage(
object Sender, Networking.XMPP.Events.MessageEventArgs e)
2829 (
string Message,
string _,
bool IsMarkdown) = await this.GetPlainText(e, DateTime.UtcNow.AddMinutes(-1));
2831 Task _ = Task.Run(async () => await this.ProcessChatMessage(Message, e.
From, e.ThreadID, async (Response, MessageId) =>
2833 KeyValuePair<string, string> P = await this.PrepareAdminResponse(Response, MessageId, IsMarkdown);
2835 MessageId = P.Value;
2838 Xml =
"<muteDiff xmlns='http://waher.se/Schema/Editing.xsd'/>";
2840 Xml +=
"<muteDiff xmlns='http://waher.se/Schema/Editing.xsd'/>";
2842 await
Gateway.
XmppClient.SendMessage(Networking.XMPP.QoSLevel.Unacknowledged, Networking.XMPP.MessageType.Chat,
2843 MessageId, e.
From, Xml,
string.
Empty,
string.
Empty,
string.
Empty, e.ThreadID,
string.Empty,
null,
null);
2849 private Task XmppClient_OnValidateSender(
object Sender, Networking.XMPP.Events.ValidateSenderEventArgs e)
2851 if (e.MessageStanza is
null || !e.Rejected)
2852 return Task.CompletedTask;
2854 switch (e.MessageStanza.
Type)
2856 case Networking.XMPP.MessageType.GroupChat:
2859 lock (this.mucRooms)
2861 InRoom = this.mucRooms.ContainsKey(e.FromBareJID);
2871 case Networking.XMPP.MessageType.Normal:
2872 case Networking.XMPP.MessageType.Chat:
2873 foreach (XmlNode N
in e.MessageStanza.Message.ChildNodes)
2875 if (!(N is XmlElement E))
2878 switch (E.NamespaceURI)
2880 case Networking.XMPP.MUC.MultiUserChatClient.NamespaceMuc:
2881 case Networking.XMPP.MUC.MultiUserChatClient.NamespaceMucAdmin:
2882 case Networking.XMPP.MUC.MultiUserChatClient.NamespaceMucOwner:
2883 case Networking.XMPP.MUC.MultiUserChatClient.NamespaceMucUser:
2884 lock (this.mucRooms)
2886 InRoom = this.mucRooms.ContainsKey(e.FromBareJID);
2893 return Task.CompletedTask;
2899 return Task.CompletedTask;
2902 private async Task MucClient_DirectInvitationReceived(
object Sender, Networking.XMPP.MUC.DirectInvitationMessageEventArgs e)
2904 if (await IsAdmin(e.
From))
2906 StringBuilder sb =
new StringBuilder();
2909 if (
string.IsNullOrEmpty(NickName))
2912 sb.Append(
"Accepting an invitation from `");
2913 sb.Append(e.FromBareJID);
2914 sb.Append(
"` to join the room `");
2915 sb.Append(e.RoomId);
2917 sb.Append(e.Domain);
2918 sb.Append(
"` using nick-name `");
2919 sb.Append(NickName);
2922 if (!
string.IsNullOrEmpty(e.Reason))
2925 sb.Append(e.Reason);
2930 await
Enter.
Execute(e.RoomId, e.Domain, NickName, e.Password,
true,
true, (Markdown, MessageId) =>
2932 if (string.IsNullOrEmpty(MessageId))
2933 MessageId = Guid.NewGuid().ToString();
2935 Gateway.SendNotification(Markdown, MessageId);
2936 return Task.FromResult<string>(MessageId);
2941 private Task MucClient_RoomInvitationReceived(
object Sender, Networking.XMPP.MUC.RoomInvitationMessageEventArgs e)
2943 e.Decline(
"Only accepting direct invitations.",
"en");
2944 return Task.CompletedTask;
2947 internal async Task EnterRoom(
string RoomId,
string Domain,
string NickName,
string Password,
bool Permanent)
2950 string Jid = RoomId +
"@" +
Domain;
2953 lock (this.mucRooms)
2955 Changed = (!this.mucRooms.TryGetValue(Jid, out
RoomInfo PrevInfo)) || (PrevInfo.Permanent ^ Permanent);
2956 this.mucRooms[Jid] = Info;
2960 await this.UpdatePermamentRooms();
2963 internal bool TryGetNickName(
string RoomId,
string Domain, out
string NickName)
2965 string Jid = RoomId +
"@" +
Domain;
2967 lock (this.mucRooms)
2976 NickName =
string.Empty;
2982 internal bool TryGetDomainAndNickName(
string RoomId, out
string Domain, out
string NickName)
2986 lock (this.mucRooms)
2996 Domain = NickName =
null;
3006 return !(Result is
null);
3009 internal async Task LeaveRoom(
string RoomId,
string Domain)
3011 string Jid = RoomId +
"@" +
Domain;
3014 lock (this.mucRooms)
3016 Changed = this.mucRooms.TryGetValue(Jid, out
RoomInfo Info) && Info.Permanent;
3017 this.mucRooms.Remove(Jid);
3021 await this.UpdatePermamentRooms();
3024 private async Task UpdatePermamentRooms()
3026 StringBuilder sb =
new StringBuilder();
3028 lock (this.mucRooms)
3030 foreach (
RoomInfo Rec
in this.mucRooms.Values)
3040 if (!
string.IsNullOrEmpty(Rec.
Password))
3054 private async Task LoadPermanentRooms()
3057 string[] Rows = s.Split(
CommonTypes.
CRLF, StringSplitOptions.RemoveEmptyEntries);
3059 lock (this.adminCommands)
3061 foreach (
string Row
in Rows)
3063 string[] Parts = Row.Split(
new string[] {
" | " }, StringSplitOptions.None);
3065 switch (Parts.Length)
3068 this.mucRooms[Parts[0] +
"@" + Parts[1]] =
new RoomInfo(Parts[0], Parts[1], Parts[2],
true);
3072 this.mucRooms[Parts[0] +
"@" + Parts[1]] =
new RoomInfo(Parts[0], Parts[1], Parts[2], Parts[3],
true);
3079 await this.RejoinRooms();
3088 lock (this.mucRooms)
3090 Infos =
new RoomInfo[this.mucRooms.Count];
3091 this.mucRooms.Values.CopyTo(Infos, 0);
3097 private async Task RejoinRooms()
3099 foreach (
RoomInfo Info
in this.GetRooms())
3100 await this.RejoinRoom(Info);
3103 private Task RejoinRoom(
RoomInfo Info)
3108 Gateway.MucClient.SetPresence(Info.RoomId, Info.Domain, Info.NickName, Networking.XMPP.Availability.Chat, null, null);
3110 Gateway.ScheduleEvent((P) => this.RejoinRoom(Info), DateTime.Now.AddMinutes(1), null);
3112 return Task.CompletedTask;
3114 },
null) ?? Task.CompletedTask;
3117 internal void CheckRoomsAlive()
3123 RoomInfo[] Infos = this.GetRooms();
3131 if (e.StanzaError is Networking.XMPP.StanzaErrors.NotAcceptableException)
3133 RoomInfo Info2 = (RoomInfo)e.State;
3134 Gateway.MucClient.EnterRoom(Info2.RoomId, Info2.Domain, Info2.NickName, Info2.Password, async (sender2, e2) =>
3137 await Gateway.MucClient.SetPresence(Info2.RoomId, Info2.Domain, Info2.NickName, Networking.XMPP.Availability.Chat, null, null);
3140 RoomInfo Info3 = (RoomInfo)e2.State;
3142 if (e2.StanzaError is Networking.XMPP.StanzaErrors.ForbiddenException)
3144 await this.LeaveRoom(Info3.RoomId, Info3.Domain);
3145 await Gateway.SendNotification(
"Left room `" + Info3.RoomId +
"@" + Info3.Domain +
"`; forbidden entry (blocked?).");
3147 else if (e2.StanzaError is Networking.XMPP.StanzaErrors.NotAuthorizedException)
3149 await this.LeaveRoom(Info3.RoomId, Info3.Domain);
3150 await Gateway.SendNotification(
"Left room `" + Info3.RoomId +
"@" + Info3.Domain +
"`; password changed.");
3152 else if (e2.StanzaError is Networking.XMPP.StanzaErrors.RegistrationRequiredException)
3154 await this.LeaveRoom(Info3.RoomId, Info3.Domain);
3155 await Gateway.SendNotification(
"Left room `" + Info3.RoomId +
"@" + Info3.Domain +
"`; no longer registered in room.");
3157 else if (e2.StanzaError is Networking.XMPP.StanzaErrors.ItemNotFoundException)
3159 await this.LeaveRoom(Info3.RoomId, Info3.Domain);
3160 await Gateway.SendNotification(
"Left room `" + Info3.RoomId +
"@" + Info3.Domain +
"`; room not found, or is locked for other purposes.");
3162 else if (e2.StanzaError is Networking.XMPP.StanzaErrors.ServiceUnavailableException)
3164 await this.LeaveRoom(Info3.RoomId, Info3.Domain);
3165 await Gateway.SendNotification(
"Left room `" + Info3.RoomId +
"@" + Info3.Domain +
"`; room is full.");
3167 else if (e2.StanzaError is Networking.XMPP.StanzaErrors.ConflictException)
3169 await this.LeaveRoom(Info3.RoomId, Info3.Domain);
3170 await Gateway.SendNotification(
"Left room `" + Info3.RoomId +
"@" + Info3.Domain +
"`; nick-name conflict.");
3177 return Task.CompletedTask;
3182 catch (Exception ex)
3192 private async Task LeaveAllRooms()
3195 int i, c =
Rooms.Length;
3196 TaskCompletionSource<bool>[] TaskCompletionSources =
new TaskCompletionSource<bool>[c];
3197 Task[] Tasks =
new Task[c];
3199 for (i = 0; i < c; i++)
3202 TaskCompletionSources[i] =
new TaskCompletionSource<bool>();
3203 Tasks[i] = TaskCompletionSources[i].Task;
3208 ((TaskCompletionSource<bool>)e.State).TrySetResult(true);
3209 return Task.CompletedTask;
3210 }, TaskCompletionSources[i]);
3213 _ = Task.Delay(5000).ContinueWith((_) =>
3215 foreach (TaskCompletionSource<bool> T
in TaskCompletionSources)
3216 T.TrySetResult(
false);
3217 return Task.CompletedTask;
3220 await Task.WhenAll(Tasks);
3223 private async Task XmppClient_OnGroupChatMessage(
object Sender, Networking.XMPP.Events.MessageEventArgs e)
3229 (
string Message,
string _,
bool IsMarkdown) = await this.GetPlainText(e, DateTime.UtcNow.AddMinutes(-1));
3231 Task _ = Task.Run(async () => await this.ProcessChatMessage(Message, this.GetOccupantRealJid(e), e.ThreadID, async (Response, MessageId) =>
3233 KeyValuePair<string, string> P = await this.PrepareAdminResponse(Response, MessageId, IsMarkdown);
3235 MessageId = P.Value;
3238 Xml =
"<muteDiff xmlns='http://waher.se/Schema/Editing.xsd'/>";
3240 Xml +=
"<muteDiff xmlns='http://waher.se/Schema/Editing.xsd'/>";
3242 await
Gateway.
MucClient.SendCustomPrivateMessage(MessageId, RoomId,
Domain, NickName, Xml,
string.Empty, e.ThreadID,
string.Empty);
3250 if (this.consolidators is
null)
3253 this.consolidators.Removed += this.Consolidators_Removed;
3262 return Task.CompletedTask;
3265 private async Task MucClient_PrivateMessageReceived(
object Sender, Networking.XMPP.MUC.RoomOccupantMessageEventArgs e)
3267 if (!
string.IsNullOrEmpty(e.ThreadID) &&
3268 !(
this.consolidators is
null) &&
3271 string Response = this.GetMarkdown(e, DateTime.UtcNow.AddMinutes(-1),
false, out
string ReplaceObjectId, out
bool IsMarkdown);
3276 if (!
string.IsNullOrEmpty(e.Body))
3284 if (!
string.IsNullOrEmpty(ReplaceObjectId))
3291 if (!
string.IsNullOrEmpty(ReplaceObjectId))
3299 (
string Message,
string _,
bool IsMarkdown) = await this.GetPlainText(e, DateTime.UtcNow.AddMinutes(-1));
3301 Task _ = Task.Run(async () => await this.ProcessChatMessage(Message, this.GetOccupantRealJid(e), e.ThreadID, async (Response, MessageId) =>
3303 KeyValuePair<string, string> P = await this.PrepareAdminResponse(Response, MessageId, IsMarkdown);
3305 MessageId = P.Value;
3308 Xml =
"<muteDiff xmlns='http://waher.se/Schema/Editing.xsd'/>";
3310 Xml +=
"<muteDiff xmlns='http://waher.se/Schema/Editing.xsd'/>";
3312 await
Gateway.
MucClient.SendCustomPrivateMessage(MessageId, e.RoomId, e.Domain, e.NickName, Xml,
string.Empty, e.ThreadID,
string.Empty);
3319 private async Task<KeyValuePair<string, string>> PrepareAdminResponse(
string Response,
string MessageId,
bool IncomingWasMarkdown)
3323 if (IncomingWasMarkdown)
3328 if (
string.IsNullOrEmpty(MessageId))
3329 MessageId = Guid.NewGuid().ToString();
3331 Xml +=
"<replace id='" + MessageId +
"' xmlns='urn:xmpp:message-correct:0'/>";
3333 return new KeyValuePair<string, string>(Xml, MessageId);
3336 private Task MucClient_RoomDestroyed(
object Sender, Networking.XMPP.MUC.UserPresenceEventArgs e)
3338 lock (this.presenceByNickAndRoom)
3340 this.presenceByNickAndRoom.Remove(e.RoomJid);
3343 return Task.CompletedTask;
3346 private Task MucClient_OccupantPresence(
object Sender, Networking.XMPP.MUC.UserPresenceEventArgs e)
3348 lock (this.presenceByNickAndRoom)
3350 if (!this.presenceByNickAndRoom.TryGetValue(e.RoomJid, out SortedDictionary<CaseInsensitiveString, Networking.XMPP.MUC.UserPresenceEventArgs> ByNick))
3352 if (e.Availability == Networking.XMPP.Availability.Offline)
3357 this.presenceByNickAndRoom[e.RoomJid] = ByNick;
3361 if (!(ByNick is
null))
3363 if (e.Availability == Networking.XMPP.Availability.Offline)
3365 if (ByNick.Remove(e.NickName) && ByNick.Count == 0)
3366 this.presenceByNickAndRoom.
Remove(e.RoomId);
3369 ByNick[e.NickName] = e;
3373 return Task.CompletedTask;
3376 internal int GetNrOccupants(
string RoomJid,
string RoomId,
string Domain,
bool ExcludeSelf,
bool ExcludeOffline)
3382 if (!this.TryGetNickName(RoomId,
Domain, out OwnNick))
3388 lock (this.presenceByNickAndRoom)
3390 if (this.presenceByNickAndRoom.TryGetValue(RoomJid, out SortedDictionary<CaseInsensitiveString, Networking.XMPP.MUC.UserPresenceEventArgs> ByNick))
3392 if (!ExcludeSelf && !ExcludeOffline)
3393 return ByNick.Count;
3397 foreach (Networking.XMPP.MUC.UserPresenceEventArgs e in ByNick.Values)
3399 if (ExcludeOffline && !e.IsOnline)
3402 if (ExcludeSelf && !(OwnNick is
null) && Networking.XMPP.XmppClient.GetResource(e.From) == OwnNick)
3415 internal KeyValuePair<
CaseInsensitiveString, Networking.XMPP.MUC.UserPresenceEventArgs>[] GetOccupants(
string RoomJid)
3417 lock (this.presenceByNickAndRoom)
3419 if (!this.presenceByNickAndRoom.TryGetValue(RoomJid, out SortedDictionary<CaseInsensitiveString, Networking.XMPP.MUC.UserPresenceEventArgs> ByNick))
3425 ByNick.
CopyTo(Result, 0);
3431 private string GetOccupantRealJid(Networking.XMPP.Events.MessageEventArgs e)
3433 foreach (XmlNode N
in e.Message.ChildNodes)
3437 foreach (XmlNode N2
in E.ChildNodes)
3439 if (N2 is XmlElement E2 &&
3440 E2.LocalName ==
"address" &&
3441 E2.NamespaceURI == E.NamespaceURI &&
3442 E2.HasAttribute(
"type") &&
3443 E2.GetAttribute(
"type") ==
"ofrom")
3451 string OccupantJid = e.From;
3456 lock (this.presenceByNickAndRoom)
3458 if (this.presenceByNickAndRoom.TryGetValue(RoomJid, out SortedDictionary<CaseInsensitiveString, Networking.XMPP.MUC.UserPresenceEventArgs> ByNick) &&
3459 ByNick.TryGetValue(NickName, out Networking.XMPP.MUC.UserPresenceEventArgs e2))
3461 return string.
IsNullOrEmpty(e2.FullJid) ? OccupantJid : e2.FullJid;
3470 return this.ProcessChatMessage(s, From,
null, ThreadId, ResponseCallback, Channel);
3475 StringBuilder Markdown;
3479 if (
string.IsNullOrEmpty(s))
3481 if (!(Channel is
null))
3482 await Channel.
Information(
"(Ignored, since empty)");
3489 if (
string.IsNullOrEmpty(ThreadId) ||
3490 this.consolidators is
null ||
3493 string Msg =
"Supressing query from self. No outstanding consolidation query registered: " + s;
3495 if (!(Channel is
null))
3502 else if (!await IsAdmin(From,
User))
3504 string Msg =
"Ignoring incoming chat message (sender is not an administrator): " + s;
3506 if (!(Channel is
null))
3513 if (!(Channel is
null))
3514 await Channel.
Information(
"Chat command string accepted.");
3516 if (this.chatSessions is
null)
3519 this.chatSessions.Removed += this.ChatSessions_Removed;
3525 this.chatSessions[From] = Session;
3528 if (!Session.TryGetVariable(
" State ", out
Variable v) || !(v.ValueObject is
ChatState State))
3533 Folder = PackagesFolder
3535 Session[
" State "] = State;
3538 StringBuilder sb =
new StringBuilder();
3539 List<string> ArgumentsList =
new List<string>();
3540 LinkedList<IAdminCommand> Commands;
3544 string CommandName =
null;
3546 bool InQuote =
false;
3547 bool Escape =
false;
3549 foreach (
char ch
in s)
3551 if (
char.IsWhiteSpace(ch) && !InQuote)
3555 if (CommandName is
null)
3556 CommandName = sb.ToString().ToLower();
3558 ArgumentsList.Add(sb.ToString());
3570 else if (ch ==
'\\')
3589 if (CommandName is
null)
3590 CommandName = sb.ToString().ToLower();
3592 ArgumentsList.Add(sb.ToString());
3595 if (CommandName is
null)
3597 if (!(Channel is
null))
3598 await Channel.
Information(
"(Ignored, no command)");
3603 Arguments = ArgumentsList.ToArray();
3605 lock (this.adminCommands)
3607 if (this.adminCommands.Count == 0)
3613 TypeInfo TI = T.GetTypeInfo();
3615 if (TI.IsAbstract || TI.IsInterface || TI.IsGenericTypeDefinition)
3620 string s2 =
Command.Name.ToLower();
3621 if (!this.adminCommands.TryGetValue(s2, out Commands))
3623 Commands =
new LinkedList<IAdminCommand>();
3624 this.adminCommands[s2] = Commands;
3627 Commands.AddLast(Command);
3629 string[] Aliases =
Command.Aliases;
3631 if (!(Aliases is
null))
3633 foreach (
string Alias
in Aliases)
3635 s2 = Alias.ToLower();
3636 if (!this.adminCommands.TryGetValue(s2, out Commands))
3638 Commands =
new LinkedList<IAdminCommand>();
3639 this.adminCommands[s2] = Commands;
3642 Commands.AddLast(Command);
3646 catch (Exception ex)
3657 if (this.adminCommands.TryGetValue(CommandName, out Commands))
3661 if (Alternative.
AppliesTo(s, Arguments, out Details))
3670 if (Command is
null)
3672 if (Arguments.Length == 0 && !(Commands is
null))
3673 await this.ProcessChatMessage(
"help " + s, From,
User, ThreadId, ResponseCallback, Channel);
3674 else if (State.CommandMode)
3676 foreach (
string Row
in s.Split(
CommonTypes.
CRLF, StringSplitOptions.RemoveEmptyEntries))
3677 await this.ExecuteCommand(From, Row.Trim(), State,
false, ResponseCallback);
3681 StringBuilder PrintOutput =
new StringBuilder();
3682 StringWriter PrintWriter =
new StringWriter(PrintOutput);
3683 Session.ConsoleOut = PrintWriter;
3686 AdminScriptRec Rec =
new AdminScriptRec()
3688 ResponseCallback = ResponseCallback
3693 return this.ReturnScriptResult(e.
Preview, Rec);
3696 Session.OnPreview += Preview;
3699 Result = await Exp.
Root.EvaluateAsync(Session);
3705 catch (Exception ex)
3711 Session.OnPreview -= Preview;
3714 Session[
"Ans"] = Result;
3716 string Printed = PrintOutput.ToString().Trim();
3717 PrintOutput.Clear();
3719 if (!
string.IsNullOrEmpty(Printed))
3720 await SendPrinted(Printed,
string.Empty, ResponseCallback);
3722 await this.ReturnScriptResult(Result, Rec);
3726 await
Command.Execute(State, ArgumentsList.ToArray(), s, Details, ResponseCallback);
3728 catch (Exception ex)
3734 Markdown =
new StringBuilder();
3736 Markdown.AppendLine(
"An error occurred when processing request:");
3737 Markdown.AppendLine();
3738 Markdown.AppendLine(
"<font class=\"error\">");
3739 Markdown.AppendLine();
3741 Markdown.AppendLine();
3742 Markdown.AppendLine(
"```");
3744 Markdown.AppendLine(
"```");
3745 Markdown.AppendLine();
3746 Markdown.AppendLine(
"</font>");
3748 await ResponseCallback(Markdown.ToString(),
string.Empty);
3750 catch (Exception ex2)
3757 private class AdminScriptRec
3759 public string MessageId =
string.Empty;
3763 private async Task ReturnScriptResult(
IElement Result, AdminScriptRec Rec)
3765 StringBuilder sb =
new StringBuilder();
3770 if (Result is
Graph G)
3772 sb.AppendLine(
"```Graph");
3775 sb.AppendLine(
"```");
3777 Rec.MessageId = await Rec.ResponseCallback(sb.ToString(), Rec.MessageId);
3781 SKData Data = Img.Encode(SKEncodedImageFormat.Png, 100);
3782 byte[] Bin = Data.ToArray();
3785 sb.Append(
";
3786 sb.Append(System.Convert.ToBase64String(Bin, 0, Bin.Length));
3789 Rec.MessageId = await Rec.ResponseCallback(sb.ToString(), Rec.MessageId);
3795 if (ex is AggregateException ex2)
3799 foreach (Exception ex3
in ex2.InnerExceptions)
3801 sb.AppendLine(ex3.Message);
3805 Rec.MessageId = await SendErrorMessage(
MarkdownDocument.
Encode(sb.ToString()), Rec.MessageId, Rec.ResponseCallback);
3808 Rec.MessageId = await SendErrorMessage(
MarkdownDocument.
Encode(ex.Message), Rec.MessageId, Rec.ResponseCallback);
3814 foreach (
string s3
in M.ColumnNames)
3823 foreach (
string _
in M.ColumnNames)
3830 for (y = 0; y < M.Rows; y++)
3832 for (x = 0; x < M.Columns; x++)
3836 object Item = M.GetElement(x, y).AssociatedObjectValue;
3837 if (!(Item is
null))
3839 if (Item is
string s3)
3846 s3 = s3.Replace(
"\r\n",
"\n").Replace(
"\r",
"\n").Replace(
"\n",
"<br/>");
3855 Rec.MessageId = await Rec.ResponseCallback(sb.ToString(), Rec.MessageId);
3858 Rec.MessageId = await SendResult(
Expression.
ToString(Result), Rec.MessageId, Rec.ResponseCallback);
3861 internal bool TryGetAdminCommand(
string CommandName, out LinkedList<IAdminCommand> Command)
3863 lock (this.adminCommands)
3865 return this.adminCommands.TryGetValue(CommandName, out Command);
3869 internal string[] AdminCommands
3875 lock (this.adminCommands)
3877 Result =
new string[this.adminCommands.Count];
3878 this.adminCommands.Keys.CopyTo(Result, 0);
3885 internal static async Task SendPrinted(
string Msg,
string MessageId,
ResponseCallbackHandler ResponseCallback)
3889 foreach (
string Row
in Msg.Replace(
"\r\n",
"\n").Replace(
'\r',
'\n').Split(
'\n'))
3890 await ResponseCallback(
"<font style=\"color:" + PrintColor +
"\">" + Row +
"</font>", MessageId);
3893 internal static Task<string> SendResult(
string Msg,
string MessageId,
ResponseCallbackHandler ResponseCallback)
3895 StringBuilder sb =
new StringBuilder();
3899 sb.Append(
"<font class=\"result\">`");
3901 sb.Append(
"`</font>");
3905 sb.AppendLine(
"<font class=\"result\">");
3907 sb.AppendLine(
"```");
3910 Msg = Msg.Replace(
"\r\n",
"\n").Replace(
"\r",
"\n");
3911 foreach (
string Row
in Msg.Split(
'\n'))
3914 sb.AppendLine(
"```");
3916 sb.AppendLine(
"</font>");
3919 return ResponseCallback(sb.ToString(), MessageId);
3922 internal static Task<string> SendErrorMessage(
string Msg,
string MessageId,
ResponseCallbackHandler ResponseCallback)
3924 StringBuilder sb =
new StringBuilder();
3926 sb.AppendLine(
"<font class=\"error\">");
3930 sb.AppendLine(
"</font>");
3932 return ResponseCallback(sb.ToString(), MessageId);
3937 if (
string.IsNullOrEmpty(Command))
3946 s = Path.GetFullPath(Path.Combine(State.
Folder, Command));
3947 Exists = File.Exists(s);
3957 if (s.Length < AppDataLen ||
string.Compare(
Gateway.
AppDataFolder, s.Substring(0, AppDataLen),
true) != 0)
3959 await SendErrorMessage(
"Access to files outside of the application data folder not permitted.",
string.Empty, ResponseCallback);
3963 if (!
string.IsNullOrEmpty(To))
3964 await ResponseCallback(this.DownloadableFile(s, State, To),
string.Empty);
3968 int i =
Command.IndexOfAny(
new char[] {
' ',
'\t' });
3978 switch (s.ToLower())
3980 case "analyzeclock":
3989 if (Shell &&
string.Compare(s,
"install",
true) == 0)
4000 s = s.Substring(0, s.Length - 3) +
"dll";
4007 await SendErrorMessage(
"File not found: `" + s.Substring(0, s.Length - 3) +
"exe`. Unable to execute command.",
string.Empty, ResponseCallback);
4092 await SendErrorMessage(
"Command not allowed.",
string.Empty, ResponseCallback);
4097 return ChangeDirectory(State,
".", ResponseCallback);
4100 return ChangeDirectory(State,
"..", ResponseCallback);
4104 return ChangeDirectory(State,
Command.Substring(s.Length).Trim(), ResponseCallback);
4110 string Pattern =
Command.Substring(s.Length).Trim();
4111 if (
string.IsNullOrEmpty(Pattern))
4114 DirectoryInfo Folder =
new DirectoryInfo(State.
Folder);
4115 DirectoryInfo[] Folders;
4116 System.IO.FileInfo[] Files;
4117 StringBuilder Markdown =
new StringBuilder();
4118 Dictionary<string, long> Sizes =
new Dictionary<string, long>();
4119 Dictionary<string, DateTime> DateTimes =
new Dictionary<string, DateTime>();
4120 string MaxSizeFileName =
null;
4121 string MaxDateTimeFileName =
null;
4122 DateTime MaxDateTime = DateTime.MinValue;
4123 long MaxSize =
int.MinValue;
4127 Markdown.AppendLine(
"| Name | Size | Date | Time |");
4128 Markdown.AppendLine(
"|:-----|-----:|:----:|:----:|");
4130 Folders = Folder.GetDirectories(Pattern, SearchOption.TopDirectoryOnly);
4132 foreach (DirectoryInfo DirInfo
in Folders)
4136 DateTimes[DirInfo.Name] = DirInfo.LastWriteTime;
4137 if (DirInfo.LastWriteTime > MaxDateTime)
4139 MaxDateTime = DirInfo.LastWriteTime;
4140 MaxDateTimeFileName = DirInfo.Name;
4149 foreach (DirectoryInfo DirInfo
in Folders)
4151 Markdown.Append(
"| ");
4153 Markdown.Append(
" | \\<DIR\\> | ");
4155 if (DateTimes.TryGetValue(DirInfo.Name, out TP))
4157 if (IsMax = (DirInfo.Name == MaxDateTimeFileName))
4158 Markdown.Append(
"**");
4160 Markdown.Append(TP.ToShortDateString());
4163 Markdown.Append(
"**");
4165 Markdown.Append(
" | ");
4168 Markdown.Append(
"**");
4170 Markdown.Append(TP.ToLongTimeString());
4173 Markdown.Append(
"**");
4175 Markdown.AppendLine(
" |");
4178 Markdown.AppendLine(
"N/A ||");
4181 Files = Folder.GetFiles(Pattern, SearchOption.TopDirectoryOnly);
4183 MaxDateTime = DateTime.MinValue;
4185 foreach (System.IO.FileInfo
FileInfo in Files)
4204 if (
FileInfo.LastWriteTime > MaxDateTime)
4206 MaxDateTime =
FileInfo.LastWriteTime;
4207 MaxDateTimeFileName =
FileInfo.Name;
4216 foreach (System.IO.FileInfo
FileInfo in Files)
4218 Markdown.Append(
"| ");
4219 Markdown.Append(this.DownloadableFile(
FileInfo.Name, State, To));
4220 Markdown.Append(
" | ");
4222 if (Sizes.TryGetValue(
FileInfo.Name, out
long Size))
4224 if (IsMax = (
FileInfo.Name == MaxSizeFileName))
4225 Markdown.Append(
"**");
4230 Markdown.Append(
"**");
4233 Markdown.Append(
"N/A");
4235 Markdown.Append(
" | ");
4237 if (DateTimes.TryGetValue(
FileInfo.Name, out TP))
4239 if (IsMax = (
FileInfo.Name == MaxDateTimeFileName))
4240 Markdown.Append(
"**");
4242 Markdown.Append(TP.ToShortDateString());
4245 Markdown.Append(
"**");
4247 Markdown.Append(
" | ");
4250 Markdown.Append(
"**");
4252 Markdown.Append(TP.ToLongTimeString());
4255 Markdown.Append(
"**");
4257 Markdown.AppendLine(
" |");
4260 Markdown.AppendLine(
"N/A ||");
4263 await ResponseCallback(Markdown.ToString(),
string.Empty);
4273 if (s.StartsWith(
"cd.") || s.StartsWith(
"cd" + Path.DirectorySeparatorChar))
4274 return ChangeDirectory(State,
Command.Substring(2).Trim(), ResponseCallback);
4278 await SendErrorMessage(
"Executing files not allowed.",
string.Empty, ResponseCallback);
4286 ProcessStartInfo StartInfo;
4288 switch (Environment.OSVersion.Platform)
4290 case PlatformID.Win32S:
4291 case PlatformID.Win32Windows:
4292 case PlatformID.Win32NT:
4293 case PlatformID.WinCE:
4294 StartInfo =
new ProcessStartInfo()
4296 FileName =
"cmd.exe",
4297 Arguments =
"/S /C \" " +
Command.Trim() +
" \"",
4298 WorkingDirectory = State.Folder
4302 case PlatformID.Unix:
4303 case PlatformID.MacOSX:
4304 StartInfo =
new ProcessStartInfo()
4306 FileName =
"/bin/zsh",
4307 Arguments =
"-c \" " +
Command.Trim() +
" \"",
4308 WorkingDirectory = State.Folder
4313 await SendErrorMessage(
"Not supported on this operating system.",
string.Empty, ResponseCallback);
4319 StartInfo.UseShellExecute =
true;
4320 StartInfo.WindowStyle = ProcessWindowStyle.Normal;
4324 StartInfo.CreateNoWindow =
true;
4325 StartInfo.ErrorDialog =
false;
4326 StartInfo.RedirectStandardInput =
false;
4327 StartInfo.RedirectStandardError =
true;
4328 StartInfo.RedirectStandardOutput =
true;
4329 StartInfo.UseShellExecute =
false;
4330 StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
4333 Process P =
new Process()
4335 StartInfo = StartInfo
4344 Thread T =
new Thread((e) =>
4350 LinkedListNode<Process> ProcessNode = State.
Processes.AddLast(P);
4356 bool Output =
false;
4358 s = P.StandardOutput.ReadToEnd().Trim();
4360 if (!
string.IsNullOrEmpty(s))
4362 StringBuilder Markdown =
new StringBuilder();
4364 Markdown.AppendLine(
"```");
4365 Markdown.AppendLine(s.Trim());
4366 Markdown.AppendLine(
"```");
4368 ResponseCallback(Markdown.ToString(),
string.Empty);
4372 s = P.StandardError.ReadToEnd().Trim();
4373 if (!
string.IsNullOrEmpty(s))
4375 StringBuilder Markdown =
new StringBuilder();
4377 Markdown.AppendLine(
"<font class=\"error\">");
4378 Markdown.AppendLine();
4379 Markdown.AppendLine(
"```");
4380 Markdown.AppendLine(s.Trim());
4381 Markdown.AppendLine(
"```");
4382 Markdown.AppendLine();
4383 Markdown.AppendLine(
"</font>");
4385 ResponseCallback(Markdown.ToString(),
string.Empty);
4390 ResponseCallback(
"The command executed with no response.",
string.Empty);
4392 while (!P.HasExited);
4401 catch (Exception ex)
4407 IsBackground =
true,
4408 Name =
"CMD Thread",
4409 Priority = ThreadPriority.BelowNormal
4417 internal string DownloadableFile(
string s,
ChatState State,
string To)
4419 if (!File.Exists(s))
4425 using (FileStream fs = File.Open(s, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
4430 FileName = Path.GetFileName(s),
4437 "?jid=" + HttpUtility.UrlEncode(To) +
"&t=" +
Token);
4444 string s = Path.GetFullPath(Path.Combine(State.
Folder, NewFolder)) + Path.DirectorySeparatorChar;
4447 if (s.Length < AppDataLen ||
string.Compare(
Gateway.
AppDataFolder, s.Substring(0, AppDataLen),
true) != 0)
4449 SendErrorMessage(
"Access to folders outside of the application data folder not permitted.",
string.Empty, ResponseCallback);
4452 else if (!Directory.Exists(s))
4454 SendErrorMessage(
"Folder does not exist",
string.Empty, ResponseCallback);
4460 ResponseCallback(
"New folder is `" + s +
"`",
string.Empty);
4473 if (this.chatSessions is
null || !this.chatSessions.
TryGetValue(HttpUtility.UrlDecode(Jid), out
Variables Session))
4476 if (!Session.TryGetVariable(
" State ", out
Variable v) ||
4478 !State.Files.TryGetValue(
Token, out Admin.FileInfo Rec))
4483 if (Rec.FileName != HttpUtility.UrlDecode(Request.
SubPath.Substring(1)))
4486 if (
string.Compare(Path.GetExtension(Rec.FileName),
".xml",
true) == 0)
4488 XmlReaderSettings ReaderSettings =
new XmlReaderSettings()
4491 CheckCharacters =
false,
4492 ConformanceLevel = ConformanceLevel.Document,
4493 DtdProcessing = DtdProcessing.Ignore,
4494 IgnoreComments =
false,
4495 IgnoreProcessingInstructions =
false,
4496 IgnoreWhitespace =
true,
4497 ValidationFlags = System.Xml.Schema.XmlSchemaValidationFlags.None
4499 XmlWriterSettings WriterSettings =
new XmlWriterSettings()
4502 CheckCharacters =
false,
4503 CloseOutput =
false,
4504 ConformanceLevel = ConformanceLevel.Document,
4505 Encoding = Encoding.UTF8,
4508 NamespaceHandling = NamespaceHandling.OmitDuplicates,
4509 NewLineChars =
"\r\n",
4510 NewLineHandling = NewLineHandling.Replace,
4511 NewLineOnAttributes =
false,
4512 OmitXmlDeclaration =
false,
4513 WriteEndDocumentOnClose =
true
4516 using (FileStream fs = File.Open(Rec.Path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
4518 using (XmlReader r = XmlReader.Create(fs, ReaderSettings))
4523 using (XmlWriter w = XmlWriter.Create(TempFile, WriterSettings))
4525 while (await r.ReadAsync())
4529 case XmlNodeType.XmlDeclaration:
4533 case XmlNodeType.ProcessingInstruction:
4534 string Url = r.Value;
4538 if ((i = Url.IndexOf(s =
Gateway.
RootFolder, StringComparison.CurrentCultureIgnoreCase)) >= 0 ||
4541 Url = Url.Remove(i, s.Length - 1);
4543 j = Url.IndexOf(
'"', i);
4545 Url = Url.Remove(i, j - i).Insert(i, Url.Substring(i, j - i).Replace(Path.DirectorySeparatorChar,
'/'));
4548 await w.WriteProcessingInstructionAsync(r.Name, Url);
4551 case XmlNodeType.Attribute:
4552 await w.WriteAttributeStringAsync(r.Prefix, r.LocalName, r.NamespaceURI, r.Value);
4555 case XmlNodeType.CDATA:
4556 await w.WriteCDataAsync(r.Value);
4559 case XmlNodeType.Comment:
4560 await w.WriteCommentAsync(r.Value);
4563 case XmlNodeType.EntityReference:
4564 await w.WriteEntityRefAsync(r.Name);
4567 case XmlNodeType.Text:
4568 case XmlNodeType.SignificantWhitespace:
4569 await w.WriteStringAsync(r.Value);
4572 case XmlNodeType.Whitespace:
4576 case XmlNodeType.Element:
4577 await w.WriteStartElementAsync(r.Prefix, r.LocalName, r.NamespaceURI);
4579 bool IsEmpty = r.IsEmptyElement;
4581 if (r.HasAttributes && r.MoveToFirstAttribute())
4583 await w.WriteAttributeStringAsync(r.Prefix, r.LocalName, r.NamespaceURI, r.Value);
4585 while (r.MoveToNextAttribute())
4586 await w.WriteAttributeStringAsync(r.Prefix, r.LocalName, r.NamespaceURI, r.Value);
4590 w.WriteEndElement();
4593 case XmlNodeType.EndElement:
4594 await w.WriteEndElementAsync();
4597 case XmlNodeType.Document:
4598 case XmlNodeType.DocumentFragment:
4599 case XmlNodeType.DocumentType:
4600 case XmlNodeType.EndEntity:
4601 case XmlNodeType.Entity:
4602 case XmlNodeType.Notation:
4608 catch (XmlException)
4612 catch (Exception ex)
4615 ExceptionDispatchInfo.Capture(ex).Throw();
4618 Response.OnResponseSent += (Sender, e) =>
4621 return Task.CompletedTask;
4624 DateTime LastWriteTime = File.GetLastWriteTime(Rec.Path);
4639 foreach (Process P
in State.Processes)
4645 catch (Exception ex)
4651 State.Processes.Clear();
4654 return Task.CompletedTask;
4665 if (!(Posted is Dictionary<string, string> Form))
4668 if (!Form.TryGetValue(
"g-recaptcha-response", out
string RecaptchaResponse))
4682 return SendMailMessage(To, Subject, Markdown,
new EmbeddedContent[0]);
4699 if (
string.IsNullOrEmpty(From))
4702 return SendMailMessage(From, To, Subject, Markdown, Attachments);
4712 public static Task<bool>
SendMailMessage(
string From,
string To,
string Subject,
string Markdown)
4714 return SendMailMessage(From, To, Subject, Markdown,
new EmbeddedContent[0]);
4729 if (
string.IsNullOrEmpty(From))
4732 return SendMailMessage(
4744 return instance?.xmppServer?.
SendMailMessage(From, To, Subject, Markdown) ?? Task.FromResult(
false);
4759 public static Task<bool>
SendMailMessage(
string SmtpHost,
int SmtpPort,
string UserName,
string Password,
4760 string From,
string To,
string Subject,
string Markdown)
4762 return SendMailMessage(SmtpHost, SmtpPort, UserName, Password, From, To, Subject, Markdown,
new EmbeddedContent[0]);
4778 public static async Task<bool>
SendMailMessage(
string SmtpHost,
int SmtpPort,
string UserName,
string Password,
4779 string From,
string To,
string Subject,
string Markdown, params
EmbeddedContent[] Attachments)
4781 string Styles =
string.Empty;
4783 if (!(Attachments is
null))
4785 List<EmbeddedContent> Attachments2 =
null;
4786 bool Changed =
false;
4802 Styles += CssDocument2.Css;
4808 if (Attachments2 is
null)
4809 Attachments2 =
new List<EmbeddedContent>();
4811 Attachments2.Add(Attachment);
4815 Attachments = Attachments2?.ToArray();
4819 StringBuilder sb =
new StringBuilder();
4821 sb.AppendLine(
"<html>");
4822 sb.AppendLine(
"<head>");
4824 if (!
string.IsNullOrEmpty(Styles))
4826 sb.AppendLine(
"<style>");
4827 sb.AppendLine(Styles);
4828 sb.AppendLine(
"</style>");
4831 sb.AppendLine(
"</head>");
4832 sb.AppendLine(
"<body>");
4834 sb.AppendLine(
"</body>");
4835 sb.AppendLine(
"</html>");
4837 string HTML = sb.ToString();
4843 ContentType =
"text/html; charset=utf-8",
4844 Raw = Encoding.UTF8.GetBytes(HTML)
4848 ContentType =
"text/plain; charset=utf-8",
4849 Raw = Encoding.UTF8.GetBytes(PlainText)
4853 ContentType =
"text/markdown; charset=utf-8",
4854 Raw = Encoding.UTF8.GetBytes(Markdown)
4859 byte[] BodyBin = P.Key;
4860 string ContentType = P.Value;
4862 if (!(Attachments is
null) && Attachments.Length > 0)
4867 ContentType = ContentType,
4870 Array.Copy(Attachments, 0, Mixed, 1, Attachments.Length);
4874 ContentType = P.Value;
4877 KeyValuePair<string, string>[] Headers =
new KeyValuePair<string, string>[]
4879 new KeyValuePair<string, string>(
"MIME-VERSION",
"1.0"),
4880 new KeyValuePair<string, string>(
"FROM", From),
4881 new KeyValuePair<string, string>(
"TO", To),
4882 new KeyValuePair<string, string>(
"SUBJECT", Subject),
4884 new KeyValuePair<string, string>(
"IMPORTANCE",
"normal"),
4885 new KeyValuePair<string, string>(
"X-PRIORITY",
"3"),
4886 new KeyValuePair<string, string>(
"MESSAGE-ID", Guid.NewGuid().ToString()),
4887 new KeyValuePair<string, string>(
"CONTENT-TYPE", ContentType)
4890 int i = To.IndexOf(
'@');
4892 throw new ArgumentException(
"Invalid mail address: " + To, nameof(To));
4894 string Domain = To.Substring(i + 1).Trim();
4896 return await (instance?.smtpServer?.SendMessage(
Domain, SmtpHost, SmtpPort, UserName, Password, From, To, Headers, BodyBin, DateTime.Now) ?? Task.FromResult(
false));
4899 private MethodInfo getCounter2 =
null;
4900 private MethodInfo getCounter3 =
null;
4901 private MethodInfo getCpuValue =
null;
4902 private MethodInfo getFreeMemoryValue =
null;
4903 private object cpuCounter =
null;
4904 private object freeMemoryCounter =
null;
4906 private async
void SampleTimerEventHandler(
object Sender)
4910 if (this.getCounter2 is
null)
4912 Type T =
Types.
GetType(
"Waher.IoTGateway.Svc.PerformanceCounters");
4913 this.getCounter2 = T?.GetMethod(
"GetCounter",
new Type[] { typeof(
string), typeof(
string) });
4914 this.getCounter3 = T?.GetMethod(
"GetCounter",
new Type[] { typeof(
string), typeof(
string), typeof(
string) });
4916 this.cpuCounter = this.getCounter3?.Invoke(
null,
new object[] {
"Processor",
"_Total",
"% Processor Time" });
4917 this.getCpuValue = this.cpuCounter?.GetType()?.GetMethod(
"NextValue",
new Type[0]);
4919 this.freeMemoryCounter = this.getCounter2?.Invoke(
null,
new object[] {
"Memory",
"Available MBytes" });
4920 if (this.freeMemoryCounter is
null)
4921 this.freeMemoryCounter = this.getCounter2?.Invoke(
null,
new object[] {
"Minne",
"Tillgängliga megabyte" });
4923 this.getFreeMemoryValue = this.freeMemoryCounter?.GetType()?.GetMethod(
"NextValue",
new Type[0]);
4927 await this.statistics.
Sample(
"CPU", CPU);
4929 if (this.getFreeMemoryValue?.Invoke(this.freeMemoryCounter,
Types.
NoParameters) is
float FreeMemory)
4930 await this.statistics.
Sample(
"FreeMemory", FreeMemory);
4932 catch (Exception ex)
4966 private async Task Export_OnExportKeyFolderUpdated(
object Sender, EventArgs e)
4972 catch (Exception ex)
4978 private async Task Export_OnExportFolderUpdated(
object Sender, EventArgs e)
4984 catch (Exception ex)
4990 private async Task JwtRequest(
object Sender,
IqEventArgs e)
4997 await e.
IqErrorBadRequest(e.
To,
"Number of seconds token is to be valid must be a positive integer.",
"en");
5004 int IssuedAt = (int)Math.Round(DateTime.UtcNow.Subtract(
JSON.
UnixEpoch).TotalSeconds);
5005 int Expires = IssuedAt + Seconds;
5014 StringBuilder Xml =
new StringBuilder();
5016 Xml.Append(
"<token xmlns='");
5017 Xml.Append(NamespaceJwt);
5020 Xml.Append(
"</token>");
5026 catch (Exception ex)
5032 internal static Task<IClientConnection> JwtAuthenticate(
HttpRequest Request)
5034 return JwtAuthenticate(Request, instance.jwtFactory, instance.xmppServer);
5037 public static async Task<IClientConnection> JwtAuthenticate(
HttpRequest Request,
5041 if (
string.IsNullOrEmpty(TokenStr))
5045 (
bool Found,
IRecipient Recipient) = await HttpxResponse.Server.TryGetRecipient(HttpxResponse.To, HttpxResponse.From);
5057 new KeyValuePair<string, object>(
"Reason",
Reason));
5074 return this.ProxyResource_AddSsoInformation(Sender, e,
true);
5079 return this.ProxyResource_AddSsoInformation(Sender, e,
false);
5089 return Task.CompletedTask;
5092 return this.AddSsoInformation(
User, e, Encrypted);
5094 return this.AddSsoInformation(User2, e, Encrypted);
5096 return Task.CompletedTask;
5101 string EncryptedPrefix = Encrypted ?
"e" :
"u";
5106 if (
string.IsNullOrEmpty(
JwtToken))
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 string EncodeRfc822(DateTime Timestamp)
Encodes a date and time, according to RFC 822 §5.
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 ContentType
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 Task< KeyValuePair< byte[], string > > EncodeAsync(object Object, Encoding Encoding, params string[] AcceptedContentTypes)
Encodes an object.
static Task< object > DecodeAsync(string ContentType, byte[] Data, Encoding Encoding, KeyValuePair< string, string >[] Fields, Uri BaseUri)
Decodes an object.
static string GetContentType(string FileExtension)
Gets the content type of an item, given its file extension. It uses the TryGetContentType to see if a...
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.
string ContentType
Content-Type of embedded object.
object Decoded
Decoded body of embedded object. ContentType defines how TransferDecoded is transformed into Decoded.
byte[] Raw
Raw, untrasnformed body of embedded object.
Represents mixed content, encoded with multipart/mixed
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 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 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.
virtual void Dispose()
IDisposable.Dispose()
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.
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 string InstanceName
Name of the current instance. Default instance=string.Empty
static Task Terminate()
Raises the OnTerminate event handler, letting the container executable know the application needs to ...
static X509Certificate2 Certificate
Domain certificate.
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 Networking.XMPP.Avatar.AvatarClient AvatarClient
XMPP Concentrator Server.
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 async Task< string > GetCustomErrorHtml(HttpRequest Request, string LocalFileName, string ContentType, byte[] Content)
Gets a custom error HTML document.
static DateTime ScheduleEvent(ScheduledEventCallback 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 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.
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 > Query(string Name, QTYPE TYPE, QCLASS CLASS)
Resolves a DNS name.
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...
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, HttpResponse Response)
Sends a file-based response back to the client.
Represents an HTTP request.
HttpRequestHeader Header
Request header.
string RemoteEndPoint
Remote end-point.
Variables 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...
void SetHeader(string FieldName, string Value)
Sets a custom header field value.
TransferEncoding TransferEncoding
Transfer encoding in response.
async Task Write(byte[] Data)
Returns binary data in the 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.
static Variables CreateVariables()
Creates a new collection of variables, that contains access to the global set of variables.
CommunicationStatistics GetCommunicationStatisticsSinceLast()
Gets communication statistics since last call.
HttpResource Register(HttpResource Resource)
Registers a resource with the server.
const int DefaultHttpPort
Default HTTP Port (80).
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.
Abstract base class for XMPP client connections
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 PubSubStorageFolder
Folder where encrypted files reside.
string EncryptedStorageFolder
Folder where encrypted files reside.
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.
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.
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...
CaseInsensitiveString Substring(int startIndex, int length)
Retrieves a substring from this instance. The substring starts at a specified character position and ...
Static interface for database persistence. In order to work, a database provider has to be assigned t...
static Task EndBulk()
Ends bulk-processing of data. Must be called once for every call to StartBulk.
static async Task InsertLazy(object Object)
Inserts an object into the database, if unlocked. If locked, object will be inserted at next opportun...
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.
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...
Static class for access to Full-Text-Search
static void RegisterStopWords(params string[] StopWords)
Registers stop-words with the search-engine. Stop-words are ignored in searches.
Contains information about a tokenization process.
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 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.
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.
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.
Base class for all types of elements.
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 string ToString(double Value)
Converts a value to a string, that can be parsed as part of an expression.
ToMatrix(ScriptNode Operand, bool NullCheck, int Start, int Length, Expression Expression)
To-Matrix operator.
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.
static JwtFactory CreateHmacSha256()
Creates a JWT factory that can create and validate JWT tokens using the HMAC-SHA256 algorithm.
string Create(params KeyValuePair< string, object >[] Claims)
Creates a new JWT token.
void Dispose()
IDisposable.Dispose
Contains information about a Java Web Token (JWT). JWT is defined in RFC 7519: https://tools....
Event arguments for endpoint annotation events.
void AddTag(string Key, object Value)
Adds a tag to the list of tags.
string RemoteEndpoint
Remote endpoint.
Class that monitors login events, and help applications determine malicious intent....
static async void Success(string Message, string UserName, string RemoteEndpoint, string Protocol, params KeyValuePair< string, object >[] Tags)
Handles a successful login attempt.
static async void Fail(string Message, string UserName, string RemoteEndpoint, string Protocol, params KeyValuePair< string, object >[] Tags)
Handles a failed login attempt.
async Task< bool > ProcessLoginFailure(string RemoteEndpoint, string Protocol, DateTime Timestamp, string Reason)
Processes a failed login attempt.
static async Task< KeyValuePair< string, object >[]> Annotate(string RemoteEndpoint, params KeyValuePair< string, object >[] Tags)
Annotates a remote endpoint.
Login state information relating to a remote endpoint
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.
bool HasPrivilege(string Privilege)
If the user has a given privilege.
async Task< string > CreateToken(JwtFactory Factory, bool Encrypted)
Creates a JWT Token referencing the user object.
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.
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.
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
void Dispose()
IDisposable.Dispose
Provisioning and registry 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
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
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.
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
Adds an external note to a token.
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)
Provisioning and registry service component.
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.
bool TryGetBucket(string Id, out Bucket Bucket)
Tries to get a bucket, given its ID.
async Task Sample(string Counter, double Value)
Samples a value
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.
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.
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
const string NamespaceDnsOverXmpp
urn:xmpp:dox:0
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 Task< bool > SendMailMessage(string To, string Subject, string Markdown, params EmbeddedContent[] Attachments)
Sends a mail message
static async Task AppendRemoteEndpointToTable(StringBuilder Markdown, string RemoteEndpoint)
Appends annotated information about a remote endpoint to a Markdown table.
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 Task< IP4Localization > FindIpAddress(string RemoteEndpoint)
Finds locale information about an IP Address.
static DateTimeHF Now
Current high-resolution date and time
static Task< bool > SendMailMessage(string From, string To, string Subject, string Markdown)
Sends a mail message
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< IP4Localization > FindIpAddress(IPAddress Addr)
Finds locale information about an IP Address.
Interface for consolidators.
Task Information(string Comment)
Called to inform the viewer of something.
Task 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 late-bound modules loaded at runtime.
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.
Interface for nodes that are published through the concentrator interface.
HostDomainOptions
Options on how to handle domain names provided in the Host header.
BinaryPresentationMethod
How binary data is to be presented.
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....