5using System.Threading.Tasks;
45 private static readonly Dictionary<CaseInsensitiveString, Dictionary<string, Dictionary<string, string>>> functionsPerTabIdPerFqnPerBareJid =
new Dictionary<CaseInsensitiveString, Dictionary<string, Dictionary<string, string>>>();
47 private readonly Dictionary<CaseInsensitiveString, Account> accounts =
new Dictionary<CaseInsensitiveString, Account>();
48 private readonly Dictionary<CaseInsensitiveString, Dictionary<CaseInsensitiveString, RosterItem>> rosters =
new Dictionary<CaseInsensitiveString, Dictionary<CaseInsensitiveString, RosterItem>>();
49 private readonly Dictionary<CaseInsensitiveString, Dictionary<CaseInsensitiveString, Block>> blocks =
new Dictionary<CaseInsensitiveString, Dictionary<CaseInsensitiveString, Block>>();
64 if (this.server is
null)
66 else if (this.server != value)
67 throw new InvalidOperationException(
"Not allowed to change server reference in runtime.");
71 public string Domain => this.server.Domain;
81 internal async Task<ApiKey> GetApiKey(
string ApiKey)
93 return (await this.GetApiKey(
ApiKey))?.Secret;
112 this.accounts[Account.UserName] = Account;
135 return this.
CreateAccount(ApiKey, UserName, Password, EMail, PhoneNr, RemoteEndPoint,
true);
150 public async Task<KeyValuePair<Networking.XMPP.Server.IAccount,
string[]>>
CreateAccount(
153 string RemoteEndPoint,
bool Enabled)
155 ApiKey ApiKeyObject =
null;
158 return new KeyValuePair<Networking.XMPP.Server.IAccount,
string[]>(
null, await GetAlternativeAccountNames(UserName));
162 return new KeyValuePair<Networking.XMPP.Server.IAccount,
string[]>(
null, await GetAlternativeAccountNames(UserName));
168 return new KeyValuePair<Networking.XMPP.Server.IAccount,
string[]>(
null, await GetAlternativeAccountNames(UserName));
176 if (File.Exists(s) || Directory.Exists(s))
177 return new KeyValuePair<Networking.XMPP.Server.IAccount,
string[]>(
null, await GetAlternativeAccountNames(UserName));
184 if (
string.IsNullOrEmpty(
ApiKey))
192 EMailVerified =
null,
194 PhoneNrVerified =
null,
195 Created = DateTime.UtcNow,
206 if (Key.NrCreated - Key.NrDeleted >= Key.MaxAccounts)
207 return new KeyValuePair<Networking.XMPP.Server.IAccount,
string[]>(
null,
null);
217 EMailVerified =
null,
219 PhoneNrVerified =
null,
220 Created = DateTime.UtcNow,
237 return new KeyValuePair<Networking.XMPP.Server.IAccount,
string[]>(
Account,
null);
240 internal static async Task<string[]> GetAlternativeAccountNames(
string UserName)
242 List<string> Suggestions =
new List<string>();
246 while (Suggestions.Count < 3 && NrDigits < 9)
248 string AlternativeName = UserName +
Gateway.
NextInteger(Max).ToString(
"D" + NrDigits.ToString());
253 if (!(AlternativeAccount is
null))
275 if (File.Exists(s) || Directory.Exists(s))
287 Suggestions.Add(AlternativeName);
292 return Suggestions.ToArray();
303 string Domain,
string RemoteEndPoint)
315 new KeyValuePair<string, object>(
"RemoteEndpoint", RemoteEndPoint));
317 StringBuilder sb =
new StringBuilder();
318 string WhoIsInfo =
string.Empty;
320 sb.Append(
"Account created.");
327 StringBuilder Markdown =
new StringBuilder();
329 DateTime UtcNow = DateTime.Now;
331 Markdown.AppendLine(
"XMPP Account created:");
332 Markdown.AppendLine();
333 Markdown.AppendLine(
"| Account Information ||");
334 Markdown.AppendLine(
"|:-----|:------|");
335 Markdown.Append(
"| User Name: | [");
336 Markdown.Append(UserNameEncoded);
337 Markdown.Append(
"](");
338 Markdown.Append(
Gateway.
GetUrl(
"/Account.md?UserName=" + UserNameEncoded));
339 Markdown.AppendLine(
") |");
340 Markdown.Append(
"| JID: | [");
341 Markdown.Append(UserNameEncoded);
342 Markdown.Append(
'@');
344 Markdown.Append(
"](xmpp:");
345 Markdown.Append(UserNameEncoded);
346 Markdown.Append(
'@');
348 Markdown.Append(
")");
349 Markdown.AppendLine(
" |");
353 Markdown.Append(
"| e-Mail: | <mailto:");
355 Markdown.AppendLine(
"> |");
360 Markdown.Append(
"| Phone Nr: | <tel:");
362 Markdown.AppendLine(
"> |");
367 Markdown.Append(
"| Date (UTC) | ");
369 Markdown.AppendLine(
" |");
370 Markdown.Append(
"| Time (UTC) | ");
372 Markdown.AppendLine(
" |");
374 if (!(ApiKeyObject is
null))
376 Markdown.AppendLine();
377 Markdown.AppendLine(
"| API Key information ||");
378 Markdown.AppendLine(
"|:-----|:------|");
379 Markdown.Append(
"| API Key: | [");
380 Markdown.Append(ApiKeyObject.Key);
381 Markdown.Append(
"](");
382 Markdown.Append(
Gateway.
GetUrl(
"/ApiKey.md?Key=" + ApiKeyObject.Key));
383 Markdown.AppendLine(
") |");
384 Markdown.Append(
"| Owner: | ");
386 Markdown.AppendLine(
" |");
387 Markdown.Append(
"| e-Mail: | <");
388 Markdown.Append(ApiKeyObject.EMail.
Value);
389 Markdown.AppendLine(
"> |");
390 Markdown.Append(
"| Accounts created: | ");
391 Markdown.Append(ApiKeyObject.NrCreated.ToString());
392 Markdown.AppendLine(
" |");
393 Markdown.Append(
"| Accounts deleted: | ");
394 Markdown.Append(ApiKeyObject.NrDeleted.ToString());
395 Markdown.AppendLine(
" |");
396 Markdown.Append(
"| Accounts left: | ");
397 Markdown.Append((ApiKeyObject.MaxAccounts - ApiKeyObject.NrCreated + ApiKeyObject.NrDeleted).ToString());
398 Markdown.AppendLine(
" |");
401 if (!
string.IsNullOrEmpty(WhoIsInfo))
403 Markdown.AppendLine();
404 Markdown.AppendLine();
405 Markdown.AppendLine(
"WHOIS Information:");
406 Markdown.AppendLine();
407 Markdown.AppendLine(
"```");
408 Markdown.AppendLine(WhoIsInfo);
409 Markdown.AppendLine(
"```");
424 ApiKey ApiKeyObject =
null;
438 this.accounts.Remove(UserName);
460 new KeyValuePair<string, object>(
"LastLogin",
Login.LastLogin),
462 new KeyValuePair<string, object>(
"RemoteEndpoint",
Login.RemoteEndPoint));
469 StringBuilder Markdown =
new StringBuilder();
471 DateTime UtcNow = DateTime.UtcNow;
473 Markdown.AppendLine(
"XMPP Account deleted:");
474 Markdown.AppendLine();
475 Markdown.AppendLine(
"| Account Information ||");
476 Markdown.AppendLine(
"|:-----|:------|");
477 Markdown.Append(
"| User Name: | ");
478 Markdown.Append(UserNameEncoded);
479 Markdown.AppendLine(
" |");
480 Markdown.Append(
"| JID: | ");
481 Markdown.Append(UserNameEncoded);
482 Markdown.Append(
'@');
483 Markdown.Append(this.server.Domain);
484 Markdown.AppendLine(
" |");
488 Markdown.Append(
"| e-Mail: | <mailto:");
490 Markdown.AppendLine(
"> |");
495 Markdown.Append(
"| Phone Nr: | <tel:");
497 Markdown.AppendLine(
"> |");
502 Markdown.Append(
"| Date (UTC) | ");
504 Markdown.AppendLine(
" |");
505 Markdown.Append(
"| Time (UTC) | ");
507 Markdown.AppendLine(
" |");
509 if (!(ApiKeyObject is
null))
511 Markdown.AppendLine();
512 Markdown.AppendLine(
"| API Key information ||");
513 Markdown.AppendLine(
"|:-----|:------|");
514 Markdown.Append(
"| API Key: | [");
516 Markdown.Append(
"](");
518 Markdown.AppendLine(
") |");
519 Markdown.Append(
"| Owner: | ");
521 Markdown.AppendLine(
" |");
522 Markdown.Append(
"| e-Mail: | <");
523 Markdown.Append(ApiKeyObject.EMail);
524 Markdown.AppendLine(
"> |");
525 Markdown.Append(
"| Accounts created: | ");
526 Markdown.Append(ApiKeyObject.NrCreated.ToString());
527 Markdown.AppendLine(
" |");
528 Markdown.Append(
"| Accounts deleted: | ");
529 Markdown.Append(ApiKeyObject.NrDeleted.ToString());
530 Markdown.AppendLine(
" |");
531 Markdown.Append(
"| Accounts left: | ");
532 Markdown.Append((ApiKeyObject.MaxAccounts - ApiKeyObject.NrCreated + ApiKeyObject.NrDeleted).ToString());
533 Markdown.AppendLine(
" |");
556 Account.Password = Password;
557 Account.Updated = DateTime.UtcNow;
598 Dictionary<CaseInsensitiveString, RosterItem> Roster;
602 if (this.rosters.TryGetValue(UserName, out Roster))
603 return this.ToArrayLocked(Roster);
606 if (await this.GetAccountEx(UserName) is
null)
609 Roster =
new Dictionary<CaseInsensitiveString, RosterItem>();
613 if (Roster.ContainsKey(Item.
BareJid))
621 this.rosters[UserName] = Roster;
622 return this.ToArrayLocked(Roster);
626 private IRosterItem[] ToArrayLocked(Dictionary<CaseInsensitiveString, RosterItem> Roster)
631 int c = Roster.Count;
650 if (this.rosters.TryGetValue(UserName, out Dictionary<CaseInsensitiveString, RosterItem> Roster) &&
657 if (await this.
GetRoster(UserName) is
null)
662 if (this.rosters.TryGetValue(UserName, out Dictionary<CaseInsensitiveString, RosterItem> Roster) &&
685 Dictionary<CaseInsensitiveString, RosterItem> Roster;
691 if (this.rosters.TryGetValue(UserName, out Roster))
693 if (!Roster.TryGetValue(Jid, out Item))
705 if (await this.
GetRoster(UserName) is
null)
710 if (this.rosters.TryGetValue(UserName, out Roster))
712 if (!Roster.TryGetValue(Jid, out Item))
723 Item.Groups = Groups;
734 new KeyValuePair<string, object>(
"Name", Item.
Name),
735 new KeyValuePair<string, object>(
"ObjectId", Item.ObjectId),
737 new KeyValuePair<string, object>(
"Subscription", Item.
Subscription),
738 new KeyValuePair<string, object>(
"NrGroups", Item.
Groups is
null ? 0 : Item.
Groups.Length));
758 new KeyValuePair<string, object>(
"Name", Item.
Name),
759 new KeyValuePair<string, object>(
"ObjectId", Item.ObjectId),
761 new KeyValuePair<string, object>(
"Subscription", Item.
Subscription),
762 new KeyValuePair<string, object>(
"NrGroups", Item.
Groups is
null ? 0 : Item.
Groups.Length));
778 Dictionary<CaseInsensitiveString, RosterItem> Roster;
783 if (this.rosters.TryGetValue(UserName, out Roster))
785 if (Roster.TryGetValue(Jid, out Item))
794 if (await this.
GetRoster(UserName) is
null)
799 if (this.rosters.TryGetValue(UserName, out Roster))
801 if (Roster.TryGetValue(Jid, out Item))
812 new KeyValuePair<string, object>(
"Name", Item.
Name),
813 new KeyValuePair<string, object>(
"ObjectId", Item.ObjectId),
815 new KeyValuePair<string, object>(
"Subscription", Item.
Subscription),
816 new KeyValuePair<string, object>(
"NrGroups", Item.
Groups is
null ? 0 : Item.
Groups.Length));
836 Dictionary<CaseInsensitiveString, Block> Blocks;
843 if (this.blocks.TryGetValue(UserName, out Blocks))
844 Found = Blocks.TryGetValue(
BareJid, out Item);
856 if (this.blocks.TryGetValue(UserName, out Blocks))
857 Found = Blocks.TryGetValue(
BareJid, out Item);
863 if (Found && !(Item is
null))
865 Item.Reason = Reason;
867 Item.Language = TextLanguage;
872 new KeyValuePair<string, object>(
"ObjectId", Item.ObjectId),
873 new KeyValuePair<string, object>(
"Reason", Item.Reason),
874 new KeyValuePair<string, object>(
"Text", Item.Text),
875 new KeyValuePair<string, object>(
"Language", Item.Language));
888 Language = TextLanguage
897 new KeyValuePair<string, object>(
"ObjectId", Item.ObjectId),
898 new KeyValuePair<string, object>(
"Reason", Item.Reason),
899 new KeyValuePair<string, object>(
"Text", Item.Text),
900 new KeyValuePair<string, object>(
"Language", Item.Language));
913 Dictionary<CaseInsensitiveString, Block> Blocks;
918 if (this.blocks.TryGetValue(UserName, out Blocks))
920 if (Blocks.TryGetValue(
BareJid, out Item) && !(Item is
null))
934 if (this.blocks.TryGetValue(UserName, out Blocks))
936 if (Blocks.TryGetValue(
BareJid, out Item) && !(Item is
null))
947 new KeyValuePair<string, object>(
"ObjectId", Item.ObjectId),
948 new KeyValuePair<string, object>(
"Reason", Item.Reason),
949 new KeyValuePair<string, object>(
"Text", Item.Text),
950 new KeyValuePair<string, object>(
"Language", Item.Language));
962 Dictionary<CaseInsensitiveString, Block> Blocks;
966 if (this.blocks.TryGetValue(UserName, out Blocks))
967 this.blocks.Remove(UserName);
977 if (this.blocks.TryGetValue(UserName, out Blocks))
979 if (this.blocks.TryGetValue(UserName, out Blocks))
980 this.blocks.Remove(UserName);
987 foreach (
Block Item
in Blocks.Values)
992 new KeyValuePair<string, object>(
"ObjectId", Item.ObjectId),
993 new KeyValuePair<string, object>(
"Reason", Item.Reason),
994 new KeyValuePair<string, object>(
"Text", Item.Text),
995 new KeyValuePair<string, object>(
"Language", Item.Language));
1008 Dictionary<CaseInsensitiveString, Block> Blocks;
1012 if (this.blocks.TryGetValue(UserName, out Blocks))
1013 return this.ToArrayLocked(Blocks);
1016 if (await this.GetAccountEx(UserName) is
null)
1019 Blocks =
new Dictionary<CaseInsensitiveString, Block>();
1022 Blocks[Item.Jid] = Item;
1026 this.blocks[UserName] = Blocks;
1027 return this.ToArrayLocked(Blocks);
1033 List<CaseInsensitiveString> Result =
new List<CaseInsensitiveString>();
1035 foreach (
Block Item
in Blocks.Values)
1037 if (!(Item is
null))
1038 Result.Add(Item.Jid);
1041 return Result.ToArray();
1048 if (this.blocks.TryGetValue(UserName, out Dictionary<CaseInsensitiveString, Block> Blocks) &&
1049 Blocks.TryGetValue(Jid, out Block Block))
1060 if (this.blocks.TryGetValue(UserName, out Dictionary<CaseInsensitiveString, Block> Blocks))
1062 if (Blocks.TryGetValue(Jid, out Block Block))
1080 int i = ToBareJid.
IndexOf(
'@');
1085 if (!this.server.IsServerDomain(
Domain,
true))
1089 Block Block = await this.GetBlock(ToUserName, FromBareJid);
1091 return !(
Block is
null);
1106 return new Tuple<string, byte[]>(
Avatar.ContentType,
Avatar.Data);
1126 Avatar.ContentType = ContentType;
1132 new KeyValuePair<string, object>(
"ObjectId",
Avatar.ObjectId),
1133 new KeyValuePair<string, object>(
"ContentType",
Avatar.ContentType),
1134 new KeyValuePair<string, object>(
"Bytes",
Avatar.Data.Length));
1141 UserName = UserName,
1142 ContentType = ContentType,
1149 new KeyValuePair<string, object>(
"ObjectId", Avatar2.ObjectId),
1150 new KeyValuePair<string, object>(
"ContentType", Avatar2.ContentType),
1151 new KeyValuePair<string, object>(
"Bytes", Avatar2.Data.Length));
1168 return VCard.VCardXml;
1187 VCard2.VCardXml =
VCard;
1191 new KeyValuePair<string, object>(
"ObjectId", VCard2.ObjectId));
1198 UserName = UserName,
1205 new KeyValuePair<string, object>(
"ObjectId", VCard3.ObjectId));
1233 if (
string.IsNullOrEmpty(s))
1237 s = Convert.ToBase64String(Data, Base64FormattingOptions.None);
1242 return Convert.FromBase64String(s);
1247 #region Offline messages
1274 bool Unregistering =
string.IsNullOrEmpty(
Function);
1276 lock (functionsPerTabIdPerFqnPerBareJid)
1278 if (!functionsPerTabIdPerFqnPerBareJid.TryGetValue(
BareJid, out Dictionary<
string, Dictionary<string, string>> FunctionsPerTabIdPerFqn))
1283 FunctionsPerTabIdPerFqn =
new Dictionary<string, Dictionary<string, string>>();
1284 functionsPerTabIdPerFqnPerBareJid[
BareJid] = FunctionsPerTabIdPerFqn;
1287 if (!FunctionsPerTabIdPerFqn.TryGetValue(Fqn, out Dictionary<string, string> FunctionsPerTabId))
1292 FunctionsPerTabId =
new Dictionary<string, string>();
1293 FunctionsPerTabIdPerFqn[Fqn] = FunctionsPerTabId;
1298 if (!FunctionsPerTabId.Remove(TabId))
1301 if (FunctionsPerTabId.Count > 0)
1304 if (!FunctionsPerTabIdPerFqn.Remove(Fqn))
1307 if (FunctionsPerTabIdPerFqn.Count > 0)
1310 return functionsPerTabIdPerFqnPerBareJid.Remove(
BareJid);
1312 else if (FunctionsPerTabId.TryGetValue(TabId, out
string s) && s ==
Function)
1316 FunctionsPerTabId[TabId] =
Function;
1324 StringBuilder sb =
new StringBuilder();
1328 sb.Append(LocalName);
1332 return sb.ToString();
1358 string Type,
string XmlContent, XmlElement StanzaElement)
1360 lock (functionsPerTabIdPerFqnPerBareJid)
1362 XmlElement FirstContent =
null;
1364 if (!functionsPerTabIdPerFqnPerBareJid.TryGetValue(
BareJid, out Dictionary<
string, Dictionary<string, string>> FunctionsPerTabIdPerFqn))
1367 if (StanzaElement is
null)
1371 StringBuilder Xml =
new StringBuilder();
1373 Xml.Append(
"<message xmlns=\"");
1376 Xml.Append(XmlContent);
1377 Xml.Append(
"</message>");
1380 StanzaElement = Doc.DocumentElement;
1388 Dictionary<string, string> FunctionsPerTabId;
1389 List<ClientPushRecord> Result =
null;
1392 foreach (XmlNode N
in StanzaElement.ChildNodes)
1394 if (N is XmlElement E)
1398 Key = EventHandlerKey(Type, E.LocalName, E.NamespaceURI);
1399 if (FunctionsPerTabIdPerFqn.TryGetValue(Key, out FunctionsPerTabId))
1401 Result ??=
new List<ClientPushRecord>();
1403 foreach (KeyValuePair<string, string> P
in FunctionsPerTabId)
1405 Result.Add(
new ClientPushRecord()
1408 LocalName = E.LocalName,
1417 Key = EventHandlerKey(Type,
string.Empty, E.NamespaceURI);
1418 if (FunctionsPerTabIdPerFqn.TryGetValue(Key, out FunctionsPerTabId))
1420 Result ??=
new List<ClientPushRecord>();
1422 foreach (KeyValuePair<string, string> P
in FunctionsPerTabId)
1424 Result.Add(
new ClientPushRecord()
1427 LocalName =
string.Empty,
1436 Key = EventHandlerKey(
string.Empty,
string.Empty, E.NamespaceURI);
1437 if (FunctionsPerTabIdPerFqn.TryGetValue(Key, out FunctionsPerTabId))
1439 Result ??=
new List<ClientPushRecord>();
1441 foreach (KeyValuePair<string, string> P
in FunctionsPerTabId)
1443 Result.Add(
new ClientPushRecord()
1445 Type =
string.Empty,
1446 LocalName =
string.Empty,
1457 if (!(FirstContent is
null))
1459 Key = EventHandlerKey(
string.Empty,
string.Empty,
string.Empty);
1460 if (FunctionsPerTabIdPerFqn.TryGetValue(Key, out FunctionsPerTabId))
1462 Result ??=
new List<ClientPushRecord>();
1464 foreach (KeyValuePair<string, string> P
in FunctionsPerTabId)
1466 Result.Add(
new ClientPushRecord()
1468 Type =
string.Empty,
1469 LocalName =
string.Empty,
1479 return Result?.ToArray();
1483 internal class ClientPushRecord
1486 public string LocalName;
1489 public string TabId;
1490 public XmlElement Data;
1536 ClientPushRecord[] ClientPushRecords = GetEventTabs(
BareJid, Type, ContentXml,
null);
1538 if (!(ClientPushRecords is
null) && await PushMessageToClients(
BareJid, ClientPushRecords))
1547 From = From.Address,
1548 Language = Language,
1549 ContentXml = ContentXml,
1550 Timestamp = DateTime.UtcNow
1556 if (!(Token is
null))
1559 if (!(Rule is
null))
1561 XmlElement StanzaElement = this.RecreateStanza(ContentXml);
1562 if (!(StanzaElement is
null))
1565 else if (!
string.IsNullOrEmpty(ContentXml))
1567 XmlElement StanzaElement = this.RecreateStanza(ContentXml);
1568 if (!(StanzaElement is
null))
1577 ClientPushRecord[] ClientPushRecords)
1579 if (ClientPushRecords is
null)
1584 foreach (ClientPushRecord Rec
in ClientPushRecords)
1589 UnregisterEventsTab(
BareJid, Rec.Type, Rec.LocalName, Rec.Namespace, Rec.TabId);
1595 private XmlElement RecreateStanza(
string ContentXml)
1597 if (
string.IsNullOrEmpty(ContentXml))
1602 XmlDocument Doc =
XML.
ParseXml(
"<message xmlns='jabber:client'>" + ContentXml +
"</message>");
1603 return Doc.DocumentElement;
1605 catch (Exception ex)
1615 foreach (XmlNode N
in StanzaElement.ChildNodes)
1617 if (N is XmlElement E)
1620 if (!(Rule is
null))
1622 await this.ProcessOfflineRule(Rule, StanzaElement, Token, Type, Id, To, From);
1632 return !(Node is Script.Persistence.Functions.XPath);
1636 string Type,
string Id,
string To,
string From)
1640 if (!
string.IsNullOrEmpty(Type) && !StanzaElement.HasAttribute(
"type"))
1641 StanzaElement.SetAttribute(
"type", Type);
1643 if (!
string.IsNullOrEmpty(Id) && !StanzaElement.HasAttribute(
"id"))
1644 StanzaElement.SetAttribute(
"id", Id);
1646 if (!
string.IsNullOrEmpty(To) && !StanzaElement.HasAttribute(
"to"))
1647 StanzaElement.SetAttribute(
"to", To);
1649 if (!
string.IsNullOrEmpty(From) && !StanzaElement.HasAttribute(
"from"))
1650 StanzaElement.SetAttribute(
"from", From);
1655 bool HasXPath = !((ContentExpression?.
ForAll(this.NoXPath,
null,
SearchMethod.TreeOrder) ??
true) &&
1656 (PatternMatchingExpression?.ForAll(this.NoXPath,
null,
SearchMethod.TreeOrder) ??
true));
1661 if (!(PatternMatchingExpression is
null))
1663 Dictionary<string, IElement> AlreadyFound =
new Dictionary<string, IElement>();
1668 foreach (KeyValuePair<string, IElement> P
in AlreadyFound)
1674 if (ContentExpression is
null)
1675 Content = StanzaElement;
1681 await h(Token, Content);
1685 catch (Exception ex)
1711 if (!(ClientPushRecords is
null) && await PushMessageToClients(
BareJid, ClientPushRecords))
1720 From = From.Address,
1721 Language = Language,
1723 Timestamp = DateTime.UtcNow
1729 if (!(Token is
null))
1732 if (!(Rule is
null))
1758 return await this.GetAccountEx(UserName);
1768 return await this.GetAccountEx(UserName);
1777 lock (this.accounts)
1779 this.accounts.Remove(UserName);
1782 return Task.CompletedTask;
1820 return Account.FtpMaxStorage ?? -1;
1825 #region Dynamic Client Registration
1835 if (!(Result is
null))
1863 Log.
Warning(
"Client registration rejected. Too many clients registered " +
1864 "from same IP address.", RegistrationRequest.RemoteEndPoint,
1865 string.Empty,
"ClientRegistrationRejected",
EventLevel.Minor,
1866 new KeyValuePair<string, object>(
"RemoteEndPoint", RegistrationRequest.RemoteEndPoint),
1867 new KeyValuePair<string, object>(
"Count", Count),
1868 new KeyValuePair<string, object>(
"PublicClient", RegistrationRequest.PublicClient),
1869 new KeyValuePair<string, object>(
"ConfidentialClient", RegistrationRequest.ConfidentialClient),
1870 new KeyValuePair<string, object>(
"ClientName", RegistrationRequest.ClientName),
1871 new KeyValuePair<string, object>(
"SoftwareId", RegistrationRequest.SoftwareId),
1872 new KeyValuePair<string, object>(
"SoftwareVersion", RegistrationRequest.SoftwareVersion),
1873 new KeyValuePair<string, object>(
"ClientUri", RegistrationRequest.ClientUri?.OriginalString),
1874 new KeyValuePair<string, object>(
"LogoUri", RegistrationRequest.LogoUri?.OriginalString),
1875 new KeyValuePair<string, object>(
"TosUri", RegistrationRequest.TosUri?.OriginalString),
1876 new KeyValuePair<string, object>(
"PolicyUri", RegistrationRequest.PolicyUri?.OriginalString));
1881 string EMail =
null;
1882 string PhoneNr =
null;
1886 if (!(RegistrationRequest.Contacts is
null))
1888 foreach (
string Contact
in RegistrationRequest.Contacts)
1890 if (Contact.IndexOf(
'@') >= 0)
1892 if (
string.IsNullOrEmpty(EMail))
1897 if (
string.IsNullOrEmpty(PhoneNr))
1905 UserName = Guid.NewGuid().
ToString();
1906 KeyValuePair<Networking.XMPP.Server.IAccount,
string[]> P =
1907 await this.
CreateAccount(OAuthApiKeyName, UserName, Password, EMail, PhoneNr,
1908 RegistrationRequest.RemoteEndPoint,
false);
1912 if (P.Value is
null)
1916 return new AccountRegistration()
1918 ClientId = UserName,
1919 ClientSecret = Password,
1920 ClientSecretExpiresAt =
null
1929 public string ClientId {
get;
internal set; }
1930 public string ClientSecret {
get;
internal set; }
1931 public DateTime? ClientSecretExpiresAt {
get;
internal set; }
1947 if (!
string.IsNullOrEmpty(UpdateRequest.
ClientSecret) &&
1954 return new AccountRegistration()
1956 ClientId = UserName,
1958 ClientSecretExpiresAt =
null
1968 public async Task<bool>
DeleteUser(
string UserName,
string RemoteEndPoint)
Helps with common JSON-related tasks.
static string Encode(string s)
Encodes a string for inclusion in JSON.
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 ...
Helps with common XML-related tasks.
static XmlDocument ParseXml(string Xml)
Parses an XML Document from its string representation.
Static class managing the application event log. Applications and services log events on this static ...
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 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 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.
The ClientEvents class allows applications to push information asynchronously to web clients connecte...
static Task< int > PushEvent(string[] TabIDs, string Type, object Data)
Puses an event to a set of Tabs, given their Tab IDs.
Static class managing the runtime environment of the IoT Gateway.
static LoginAuditor LoginAuditor
Current Login Auditor. Should be used by modules accepting user logins, to protect the system from un...
static byte[] NextBytes(int NrBytes)
Generates an array of random bytes.
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 int NextInteger(int Max)
Returns a non-negative random integer that is less than the specified maximum.
static string RootFolder
Web root folder.
Returns the Bare JID of a JID.
Creates a random password.
static string CreateRandomPassword(int NrBytes, int NrBuckets)
Creates a random password.
Authentication done by the LOGIN authentication mechanism. https://tools.ietf.org/html/draft-murchiso...
Abstract base class for XMPP client connections
const string C2SNamespace
jabber:client
Push Notification settings.
Expression PatternMatchingExpression
Parsed pattern-matching expression
Expression ContentExpression
Parsed content expression
string MessageVariable
Variable to put the Message XML in, before pattern matching or content script is executed.
Push Notification settings.
Contains information about a stanza.
string Content
Literal XML content.
XmlElement StanzaElement
Stanza element.
bool HasContent
If the stanza has content.
Contains information about one XMPP address.
CaseInsensitiveString Address
XMPP Address
CaseInsensitiveString BareJid
Bare JID
static readonly XmppAddress Empty
Empty address.
CaseInsensitiveString Account
Account
static byte[] GetRandomNumbers(int NrBytes)
Generates a set of random numbers.
static async Task< PushNotificationToken > TryGetPushNotificationToken(CaseInsensitiveString BareJid)
Tries to get a push notification token for a client, if one exists.
static async Task< PushNotificationRule > TryGetPushNotificationRule(CaseInsensitiveString BareJid, string MessageType, string LocalName, string Namespace)
Tries to get a push notification token for a client, if one exists.
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
int IndexOf(CaseInsensitiveString value, StringComparison comparisonType)
Reports the zero-based index of the first occurrence of the specified string in the current System....
static bool IsNullOrEmpty(CaseInsensitiveString value)
Indicates whether the specified string is null or an CaseInsensitiveString.Empty string.
override string ToString()
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 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.
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.
Static class managing persistent counters.
static Task< long > IncrementCounter(CaseInsensitiveString Key)
Increments a counter.
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 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....
bool ForAll(ScriptNodeEventHandler Callback, object State, bool DepthFirst)
Calls the callback method for all script nodes defined for the expression.
Base class for all funcions.
Base class for all nodes in a parsed script tree.
virtual PatternMatchResult PatternMatch(IElement CheckAgainst, Dictionary< string, IElement > AlreadyFound)
Performs a pattern match operation.
Class that monitors login events, and help applications determine malicious intent....
static async Task< string > AppendWhoIsInfo(StringBuilder Markdown, string RemoteEndPoint)
Appends WHOIS information to a Markdown document.
static async Task< KeyValuePair< string, object >[]> Annotate(string RemoteEndPoint, params KeyValuePair< string, object >[] Tags)
Annotates a remote endpoint.
Corresponds to a user in the system.
Maintains the collection of all users in the system.
static IUserSource Source
User source.
Contains information about a broker account.
CaseInsensitiveString EMail
E-mail address associated with account.
CaseInsensitiveString UserName
User Name of account
bool Enabled
If account is enabled
async Task< AccountLogin > GetAccountLogin()
Gets the object with the associated account login status information.
string Password
Password of account
CaseInsensitiveString PhoneNr
Phone number associated with account.
string FtpRootFolder
FTP Root Folder, if account has access to FTP.
const string AccountDeletedCounterName
Name of counter that counts the number of accounts deleted.
const string AccountCreatedCounterName
Name of counter that counts the number of accounts created.
DateTime? Updated
When account was created associated with account holder.
DateTime Created
When account was created associated with account holder.
async Task LoggedIn(string RemoteEndPoint)
Registers a log-in event on the account.
string ApiKey
Reference to API Key used to create object.
static async Task AccountCreated(Account Account, ApiKey ApiKeyObject, string Domain, string RemoteEndPoint)
Notifies operators of a new account being created.
async Task< bool > ClearBlocks(CaseInsensitiveString UserName)
Remove all blocks for an account.
Task AccountUpdated(CaseInsensitiveString UserName)
Called when account has been updated.
async Task< bool > ChangePassword(CaseInsensitiveString UserName, string Password)
Changes the password of an account.
async Task< bool > SetAvatar(CaseInsensitiveString UserName, string ContentType, byte[] Data)
Sets the Avatar of an account.
async Task< byte[]> GetDialbackSecret()
Gets the Dialback secret, as defined in XEP-0185.
async Task< long > GetMaxStorage(string UserName)
Gets the maximum storage allowed for a user.
async Task< IUser > TryGetUser(string UserName)
Tries to get a user with a given user name.
Task< bool > IsPermitted(CaseInsensitiveString BareJid, string Setting)
Checks if a feature is permitted for a Bare JID.
async Task< int > DeleteOfflineMessages(DateTime OlderThan)
Deletes offline messages that are older than a specific timestamp.
async Task< KeyValuePair< Networking.XMPP.Server.IAccount, string[]> > CreateAccount(string ApiKey, CaseInsensitiveString UserName, string Password, CaseInsensitiveString EMail, CaseInsensitiveString PhoneNr, string RemoteEndPoint, bool Enabled)
Creates an account.
async Task< string > GetRootFolder(string UserName)
Gets the root folder of a user.
async Task< IRosterItem > GetRosterItem(CaseInsensitiveString UserName, CaseInsensitiveString Jid)
Gets a roster item for an account.
async Task< IRegistration > RegisterUser(IRegistrationRequest RegistrationRequest)
Registers a new user.
async void AccountLogin(CaseInsensitiveString UserName, string RemoteEndPoint)
Successful login to account registered.
async Task< bool > AddBlock(CaseInsensitiveString UserName, CaseInsensitiveString BareJid, BlockingReason Reason, string Text, string TextLanguage)
Blocks an account.
async Task< int > DeleteOfflineMessages(CaseInsensitiveString ToUserName)
Deletes offline messages for a given account.
async Task< IEnumerable< CaseInsensitiveString > > GetBlockList(CaseInsensitiveString UserName)
Gets the entire block list for an account.
async Task< bool > DeleteUser(string UserName, string RemoteEndPoint)
Deletes an existing user.
async Task< string > GetVCard(CaseInsensitiveString UserName)
Gets the vCard of an account.
async Task< IRosterItem > SetRosterItem(CaseInsensitiveString UserName, CaseInsensitiveString Jid, string Name, SubscriptionStatus? Subscription, bool? PendingSubscription, string[] Groups)
Sets a roster item in a users roster.
const string OAuthApiKeyName
API Key name for clients registered via OAUTH.
PushNotificationEventHandler OnPushNotification
Event raised when a push notification is performed.
string Domain
Current domain.
async Task< bool > StoreOfflineMessage(string Type, string Id, XmppAddress To, XmppAddress From, string Language, Stanza Stanza)
Tries to save an offline message.
async Task DeleteOfflineMessages(IEnumerable< IOfflineMessage > Messages)
Deletes offline messages.
Task< KeyValuePair< Networking.XMPP.Server.IAccount, string[]> > CreateAccount(string ApiKey, CaseInsensitiveString UserName, string Password, CaseInsensitiveString EMail, CaseInsensitiveString PhoneNr, string RemoteEndPoint)
Creates an account.
async Task< bool > Unblock(CaseInsensitiveString UserName, CaseInsensitiveString BareJid)
Unblocks an account.
async Task< bool > DeleteAccount(CaseInsensitiveString UserName, string RemoteEndPoint)
Deletes an account.
async Task< bool > StoreOfflineMessage(string Type, string Id, XmppAddress To, XmppAddress From, string Language, string ContentXml)
Tries to save an offline message.
XmppServer Server
Current XMPP Server.
async Task< IEnumerable< IRosterItem > > GetRoster(CaseInsensitiveString UserName)
Gets the roster of an account.
async Task< IEnumerable< IOfflineMessage > > GetOfflineMessages(CaseInsensitiveString ToUserName, int Max)
Gets the oldest offline messages stored for a given bare JID, up to a maximum count.
async Task< Tuple< string, byte[]> > GetAvatar(CaseInsensitiveString UserName)
Gets the Avatar of an account.
async Task< bool > SetVCard(CaseInsensitiveString UserName, string VCard)
Sets the vCard of an account.
async Task< bool > IsBlocked(CaseInsensitiveString FromBareJid, CaseInsensitiveString ToBareJid)
Checks if a sender is blocked by a receiver.
byte[] GetRandomNumbers(int NrBytes)
Generates a set of random numbers.
async Task< string > GetApiKeySecret(string ApiKey)
Gets the secret for a given API key.
async Task< bool > RemoveRosterItem(CaseInsensitiveString UserName, CaseInsensitiveString Jid)
Removes a roster item.
LoginAuditor Auditor
Login auditor.
async Task< IRegistration > UpdateUser(string UserName, IRegistrationRequest UpdateRequest)
Updates an existing user.
SubscriptionStatus Subscription
Subscription status.
CaseInsensitiveString BareJid
Bare JID.
bool PendingSubscription
If a presence subscription awaits.
string[] Groups
Groups assigned to roster item.
string Name
Name of roster item.
async Task< PubSubNode > GetNodeAsync(CaseInsensitiveString Service, CaseInsensitiveString NodeName, NodeAccessModel? AutoCreateAccess, XmppAddress From, CaseInsensitiveString Domain)
Gets a pubsub node.
Defines a node on which items can be published.
Defines a node subscription.
Provides the user with options to control notifications from the Broker.
bool AccountCreated
If a notification should be sent when a new account is created.
static BrokerNotificationConfiguration Instance
Current instance of configuration.
bool AccountDeleted
If a notification should be sent when a new account is deleted.
Provides the user configuration options regarding use of Push Notification to reach offline clients.
Service Module hosting the XMPP broker and its components.
static async Task AppendRemoteEndPointToTable(StringBuilder Markdown, string RemoteEndPoint)
Appends annotated information about a remote endpoint to a Markdown table.
Persistence layer for FTP servers.
A dynamic user source, supporting registering new users.
Dynamic client registration, as defined in RFC 7591.
Dynamic client registration request, as defined in RFC 7591.
string? ClientSecret
OAuth 2.0 client secret string.
Interface for XMPP Server persistence layers. The persistence layer should implement caching.
Task< IAccount > GetAccount(CaseInsensitiveString UserName)
Method to call to fetch account information.
Interface for roster items.
Interface for XMPP Server persistence layers. The persistence layer should implement caching.
new Task< IAccount > GetAccount(CaseInsensitiveString UserName)
Method to call to fetch account information.
Basic interface for a user.
Task< IUser > TryGetUser(string UserName)
Tries to get a user with a given user name.
SubscriptionStatus
Roster item subscription status enumeration.
BlockingReason
Reason for blocking an account.
MessageType
Type of message received.
PendingSubscription
Pending subscription states.
PatternMatchResult
Status result of a pattern matching operation.
SearchMethod
Method to traverse the expression structure