2using System.Collections.Generic;
5using System.Threading.Tasks;
31 public const string NamespaceMuc =
"http://jabber.org/protocol/muc";
86 this.
RegisterFeature(
"http://jabber.org/protocol/muc#self-ping-optimization");
107 this.rooms.Dispose();
142 bool RoomCreated =
false;
155 if (Identity is
null)
157 await e.
PresenceErrorNotAllowed(e.
To,
"Only users with approved legal identities on the server can create rooms on the server.",
"en");
173 this.rooms[RoomId] = Room;
177 new KeyValuePair<string, object>(
"Room", RoomId),
178 new KeyValuePair<string, object>(
"Domain", e.
To.
Domain),
179 new KeyValuePair<string, object>(
"Creator", e.
From.
BareJid));
182 if (Room.PasswordProtected)
184 string Password =
null;
186 foreach (XmlNode N
in e.
Content.ChildNodes)
188 if (N is XmlElement E && E.LocalName ==
"password" && E.NamespaceURI ==
NamespaceMuc)
190 Password = E.InnerText;
199 DateTime TP = Next.Value;
200 DateTime Today = DateTime.Today;
202 sb =
new StringBuilder();
204 if (Next.Value == DateTime.MaxValue)
206 sb.Append(
"This endpoint (");
208 sb.Append(
") has been blocked from the system.");
215 sb.Append(
"Too many failed login attempts in a row registered. Try again after ");
216 sb.Append(TP.ToLongTimeString());
218 if (TP.Date != Today)
220 if (TP.Date == Today.AddDays(1))
221 sb.Append(
" tomorrow");
225 sb.Append(TP.ToShortDateString());
229 sb.Append(
". Remote Endpoint: ");
237 if (Password is
null || Room.Password != Password)
244 if (!Room.TryGetOccupantFromNick(NickName, out
MucOccupant Occupant))
251 if (!(Occupant is
null) && !Room.Add(Occupant))
258 if (!(Occupant is
null))
266 if (Occupant.Role is
null)
281 else if (Room.MembersOnly)
298 Persistent = Room.Persistent,
299 Archive = Room.Archive
302 if (!Room.Add(Occupant))
308 if (Occupant.Persistent)
312 await this.OccupantEntered(Room, Occupant, e.
From, RoomCreated, e.
Id, e.
Content);
316 bool RoomCreated,
string Id, XmlElement PresenceContent)
318 Room.RegisterFullJid(Occupant, From);
320 bool CanBroadcastOccupant = Room.CanBroadcastPresence(Occupant);
321 string OccupantXmlNoJid = Occupant.GetUserXml(
null,
null);
322 string OccupantXmlWithJid = Occupant.GetUserXml(From.
Address,
null);
325 bool CanViewJid = Room.CanDiscoverRealJids(Occupant);
327 foreach (
MucOccupant Occupant2
in Room.GetOccupants())
329 if (AreEqual(Occupant2.FullJids, Occupant.FullJids))
332 if (CanGetMembership && Room.CanBroadcastPresence(Occupant2))
336 if (!(Occupant2.FullJids is
null))
338 foreach (
XmppAddress FullJid
in Occupant2.FullJids)
341 string.
Empty, Occupant2.GetUserXml(FullJid.
Address,
null),
this);
348 string.
Empty, Occupant2.GetUserXml(
null,
null),
this);
352 if (CanBroadcastOccupant && (Occupant2.Role?.
ReceiveOccupantPresence ??
false) && Room.CanGetMembership(Occupant2))
354 if (!(Occupant2.FullJids is
null))
356 foreach (
XmppAddress FullJid
in Occupant2.FullJids)
358 await this.
Server.
Presence(
string.Empty, Guid.NewGuid().ToString(), FullJid, OccupantJid,
string.
Empty,
359 Room.CanDiscoverRealJids(Occupant2) ? OccupantXmlWithJid : OccupantXmlNoJid,
this);
365 List<int> StatusCodes =
new List<int>();
367 if (Room.DiscoverRealJids == DiscoverReadJids.Anyone)
368 StatusCodes.Add(100);
370 StatusCodes.Add(110);
373 StatusCodes.Add(170);
376 StatusCodes.Add(201);
378 await this.
Server.
Presence(
string.Empty,
string.IsNullOrEmpty(Id) ? Guid.NewGuid().ToString() : Id, From, OccupantJid,
379 string.Empty, Occupant.GetUserXml(CanViewJid ? From.
Address :
null,
null, StatusCodes.ToArray()),
this);
381 string RoomAddr =
XML.
Encode(Room.Room +
"@" + Room.Domain);
382 bool IncludeJid = Room.CanDiscoverRealJids(Occupant);
384 StringBuilder sb =
new StringBuilder();
386 if (Room.Persistent && (Occupant.Role?.
ReceiveMessages ??
false) && Room.MaxHistoryFetch > 0)
388 List<FilterField> Fields =
new List<FilterField>()
393 int MaxStanzas = Room.MaxHistoryFetch;
394 int MaxSize =
int.MaxValue;
396 if (!(PresenceContent is
null))
398 foreach (XmlNode N
in PresenceContent.ChildNodes)
400 if (N is XmlElement E && E.LocalName ==
"history" && E.NamespaceURI ==
NamespaceMuc)
402 foreach (XmlAttribute Attr
in E.Attributes)
407 if (
int.TryParse(Attr.Value, out
int i))
412 if (
int.TryParse(Attr.Value, out i))
417 if (
int.TryParse(Attr.Value, out i))
431 if (MaxSize > 0 && MaxStanzas > 0)
434 List<MucMessage> Messages =
new List<MucMessage>();
446 sb.Append(
"<delay xmlns='");
448 sb.Append(
"' from='");
450 sb.Append(
"' stamp='");
456 sb.Append(
"<addresses xmlns='");
458 sb.Append(
"'><address type='ofrom' jid='");
460 sb.Append(
"'/></addresses>");
467 if (MaxSize <
int.MaxValue)
472 if (!
string.IsNullOrEmpty(
Message.MessageId))
484 if (!
string.IsNullOrEmpty(
Message.Language))
498 await this.
Server.
Message(
"groupchat", Message.MessageId, From, OccupantJid,
Message.Language, Xml,
this);
503 if (Room.SubjectTimestamp > DateTime.MinValue)
505 sb.Append(
"<subject>");
507 sb.Append(
"</subject>");
508 sb.Append(
"<delay xmlns='");
510 sb.Append(
"' from='");
512 sb.Append(
"' stamp='");
513 sb.Append(
XML.
Encode(Room.SubjectTimestamp));
525 StringBuilder Xml =
new StringBuilder();
527 Xml.Append(
"<x xmlns='");
529 Xml.Append(
"'><item affiliation='none' role='none'><reason>You are not in the room.</reason></item>");
530 Xml.Append(
"<status code='110'/>");
531 Xml.Append(
"<status code='307'/>");
532 Xml.Append(
"<status code='333'/>");
535 await this.
Server.
Presence(
string.Empty,
string.IsNullOrEmpty(e.
Id) ? Guid.NewGuid().ToString() : e.
Id,
541 if (e.
Type ==
"error")
543 Room.Remove(Occupant);
545 StringBuilder Xml =
new StringBuilder();
547 Xml.Append(
"<x xmlns='");
549 Xml.Append(
"'><item affiliation='none' role='none'/>");
550 Xml.Append(
"<status code='333'/>");
553 await this.PresenceXmlToAll(e.
To, Room.GetOccupants(), Xml.ToString());
561 bool Broadcast = Room.CanBroadcastPresence(Occupant);
563 if (e.
Type ==
"unavailable")
565 if (Room.UnregisterFullJid(Occupant, e.
From))
567 Room.Remove(Occupant);
568 Occupant.Role =
new Roles.None();
574 string SuffixWithJid =
null;
575 string SuffixWithoutJid =
null;
578 foreach (
MucOccupant Occupant2
in Room.GetOccupants())
583 if (Room.CanDiscoverRealJids(Occupant2))
585 if (SuffixWithJid is
null)
586 SuffixWithJid = Occupant.GetUserXml(e.
From.
Address,
null);
588 Suffix = SuffixWithJid;
592 if (SuffixWithoutJid is
null)
593 SuffixWithoutJid = Occupant.GetUserXml(
null,
null);
595 Suffix = SuffixWithoutJid;
598 if (!(Occupant2.FullJids is
null))
600 foreach (
XmppAddress FullJid
in Occupant2.FullJids)
609 else if (
string.IsNullOrEmpty(e.
Type))
612 if (!(Occupant2 is
null) && !Occupant2.ContainsFullJid(e.
From))
618 if (!(Occupant.Role?.ChangeRoomNickname ??
false))
626 Room.UnregisterFullJid(Occupant, e.
From);
628 if (Occupant.HasFullJids)
638 Persistent = Room.Persistent,
639 Archive = Room.Archive
642 Occupant.Role = Occupant.Affiliation.GetDefaultRole(Room);
644 if (!(Occupant is
null) && !Room.Add(Occupant))
650 if (Occupant.Persistent)
657 if (Occupant.Persistent)
661 Room.RegisterFullJid(Occupant, e.
From);
664 string OldIncludingJid =
null;
665 string OldExcludingJid =
null;
666 string NewIncludingJid =
null;
667 string NewExcludingJid =
null;
671 foreach (
MucOccupant Occupant3
in Room.GetOccupants())
673 if (Room.CanDiscoverRealJids(Occupant3))
675 if (OldIncludingJid is
null)
676 OldIncludingJid = Occupant.GetUserXml(e.
From.
Address, OldAddr.Resource, 303);
678 OldXml = OldIncludingJid;
682 if (OldExcludingJid is
null)
683 OldExcludingJid = Occupant.GetUserXml(
null, OldAddr.Resource, 303);
685 OldXml = OldExcludingJid;
688 if (Room.CanDiscoverRealJids(Occupant))
690 if (NewIncludingJid is
null)
691 NewIncludingJid = Occupant.GetUserXml(e.
From.
Address, NewAddr.Resource);
693 NewXml = NewIncludingJid;
697 if (NewExcludingJid is
null)
698 NewExcludingJid = Occupant.GetUserXml(
null, NewAddr.Resource);
700 NewXml = NewExcludingJid;
703 if (!(Occupant3.FullJids is
null))
705 foreach (
XmppAddress FullJid
in Occupant3.FullJids)
707 if (FullJid != e.
From)
709 await this.
Server.
Presence(
"unavailable", Guid.NewGuid().ToString(), FullJid, OldAddr,
string.
Empty, OldXml,
this);
717 Occupant.GetUserXml(Room.CanDiscoverRealJids(Occupant) ? e.
From.
Address :
null, OldAddr.Resource, 303, 110),
this);
720 Occupant.GetUserXml(Room.CanDiscoverRealJids(Occupant) ? e.
From.
Address :
null, NewAddr.Resource, 110),
this);
728 if (this.rooms.TryGetValue(RoomId, out
MucRoom Room))
736 this.rooms[RoomId] = Room;
743 if (Room.TryGetOccupantFromBareJid(BareJid, out
MucOccupant Occupant))
751 if (!(Occupant is
null))
759 if (Room.TryGetOccupantFromNick(NickName, out
MucOccupant Occupant))
767 if (!(Occupant is
null))
791 if (e.
Type ==
"error")
793 Room.Remove(Occupant);
795 StringBuilder Xml =
new StringBuilder();
797 Xml.Append(
"<x xmlns='");
799 Xml.Append(
"'><item affiliation='none' role='none'/>");
800 Xml.Append(
"<status code='333'/>");
803 await this.PresenceXmlToAll(e.
To, Room.GetOccupants(), Xml.ToString());
808 string Subject =
null;
809 bool OnlySubject =
true;
811 foreach (XmlNode N
in e.Message.ChildNodes)
813 if (N is XmlElement E)
815 if (E.Name ==
"subject" && E.NamespaceURI == e.Message.NamespaceURI)
816 Subject = E.InnerText;
827 await e.MessageErrorBadRequest(e.To,
"Group chat messages must be addressed to the room JID.",
"en");
831 if (!(Occupant.Role?.SendMessagesToAll ??
false) || !(Occupant.Role?.PresentInRoom ??
false))
833 await e.MessageErrorForbidden(e.To,
"Not allowed to send messages to occupants of room.",
"en");
837 if (!(Subject is
null) && OnlySubject)
839 if ((Room.AllowChangeSubject && (Occupant.Role?.ModifySubject ??
false)) ||
840 Room.IsModerator(Occupant))
842 Room.Subject = Subject;
843 Room.SubjectJid = Occupant.OccupantJid;
844 Room.SubjectTimestamp = DateTime.UtcNow;
851 await e.MessageErrorForbidden(e.To,
"Not allowed to change room subject.",
"en");
856 if (Room.Persistent && Room.Logging && !OnlySubject)
860 Domain = e.To.Domain,
862 NickName = Occupant.NickName,
864 Timestamp = DateTime.UtcNow,
866 Language = e.Language,
868 ArchiveDays = Room.Archive ? Room.ArchiveDays : 0
873 string SenderXml =
null;
875 foreach (
MucOccupant Occupant2
in Room.GetOccupants())
877 if (!(Occupant2.FullJids is
null))
879 bool IncludeJid = Room.CanDiscoverRealJids(Occupant2);
884 if (SenderXml is
null)
886 StringBuilder sb =
new StringBuilder();
888 sb.Append(
"<addresses xmlns='");
890 sb.Append(
"'><address type='ofrom' jid='");
891 sb.Append(
XML.
Encode(e.From.Address.Value));
892 sb.Append(
"'/></addresses>");
894 SenderXml = sb.ToString();
901 await this.
Server.
Message(e.Type, e.Id, To, OccupantJid, e.Language, Xml,
this);
907 await this.SendPrivateMessage(Room, Occupant, e);
920 if (!Room.CanSendPrivateMessage(Occupant))
927 if (Destination is
null)
933 if (!(Destination.FullJids is
null))
967 foreach (XmlNode N
in e.
Content.ChildNodes)
982 if (!(Occupant.Affiliation is Affiliations.Admin))
984 if (!Room.AllowInvites)
990 if (!(Occupant.Role?.InviteOtherUsers ??
false))
997 if (Room.MembersOnly)
999 if (!Room.IsAdmin(Occupant))
1001 await e.
MessageErrorForbidden(e.
To,
"Only room administrators or owners are allowed to invite new members.",
"en");
1015 if (Room.MembersOnly && Room.AddMember(To.
BareJid) && Room.Persistent)
1018 foreach (XmlNode N2
in E.ChildNodes)
1020 if (N2 is XmlElement E2 && E2.LocalName ==
"reason" && E2.NamespaceURI ==
NamespaceMucUser)
1027 StringBuilder Xml =
new StringBuilder();
1029 Xml.Append(
"<x xmlns='");
1031 Xml.Append(
"'><invite from='");
1035 if (!(Reason is
null))
1037 Xml.Append(
"<reason>");
1039 Xml.Append(
"</reason>");
1042 Xml.Append(
"</invite>");
1044 if (Room.PasswordProtected)
1046 Xml.Append(
"<password>");
1048 Xml.Append(
"</password>");
1053 await this.
Server.
Message(
string.Empty, Guid.NewGuid().ToString(), To, e.
To, e.
Language, Xml.ToString(),
this);
1067 if (Room.MembersOnly && Room.RemoveMember(e.
From.
BareJid) && Room.Persistent)
1070 foreach (XmlNode N2
in E.ChildNodes)
1072 if (N2 is XmlElement E2 && E2.LocalName ==
"reason" && E2.NamespaceURI ==
NamespaceMucUser)
1079 Xml =
new StringBuilder();
1081 Xml.Append(
"<x xmlns='");
1083 Xml.Append(
"'><decline from='");
1087 if (!(Reason is
null))
1089 Xml.Append(
"<reason>");
1091 Xml.Append(
"</reason>");
1094 Xml.Append(
"</decline></x>");
1096 await this.
Server.
Message(
string.Empty, Guid.NewGuid().ToString(), To, e.
To, e.
Language, Xml.ToString(),
this);
1109 if (e.
Type ==
"chat")
1110 await this.SendPrivateMessage(Room, Occupant, e);
1116 private async Task RegisterUserGetFormHandler(
object Sender,
IqEventArgs e)
1140 StringBuilder Xml =
new StringBuilder();
1142 if (!(Occupant is
null) && !(Occupant.Role is
null))
1144 Xml.Append(
"<query xmlns='");
1146 Xml.Append(
"'><registered/><username>");
1147 Xml.Append(Occupant.NickName);
1148 Xml.Append(
"</username></query>");
1154 Xml.Append(
"<query xmlns='");
1156 Xml.Append(
"'><instructions>Fill out the form and submit it, to register in the room.</instructions><x xmlns='");
1158 Xml.Append(
"' type='form'><title>");
1159 Xml.Append(
string.IsNullOrEmpty(Room.Name) ?
"Room" : Room.Name);
1160 Xml.Append(
" Registration</title><instructions>Fill out the form and submit it, to register in the room.</instructions>");
1161 Xml.Append(
"<field type='hidden' var='FORM_TYPE'><value>");
1163 Xml.Append(
"</value></field>");
1164 Xml.Append(
"<field label='Given Name' type='text-single' var='muc#register_first'><required/>");
1166 if (!
string.IsNullOrEmpty(Occupant?.FirstName))
1168 Xml.Append(
"<value>");
1169 Xml.Append(
XML.
Encode(Occupant.FirstName));
1170 Xml.Append(
"</value>");
1173 Xml.Append(
"</field>");
1174 Xml.Append(
"<field label='Family Name' type='text-single' var='muc#register_last'><required/>");
1176 if (!
string.IsNullOrEmpty(Occupant?.LastName))
1178 Xml.Append(
"<value>");
1179 Xml.Append(
XML.
Encode(Occupant.LastName));
1180 Xml.Append(
"</value>");
1183 Xml.Append(
"</field>");
1184 Xml.Append(
"<field label='Desired Nickname' type='text-single' var='muc#register_roomnick'><required/>");
1186 if (!
string.IsNullOrEmpty(Occupant?.NickName))
1188 Xml.Append(
"<value>");
1189 Xml.Append(
XML.
Encode(Occupant.NickName));
1190 Xml.Append(
"</value>");
1193 Xml.Append(
"</field>");
1194 Xml.Append(
"<field label='Your URL' type='text-single' var='muc#register_url'>");
1196 if (!
string.IsNullOrEmpty(Occupant?.Url))
1198 Xml.Append(
"<value>");
1200 Xml.Append(
"</value>");
1203 Xml.Append(
"</field>");
1204 Xml.Append(
"<field label='Email Address' type='text-single' var='muc#register_email'>");
1206 if (!
string.IsNullOrEmpty(Occupant?.EMail))
1208 Xml.Append(
"<value>");
1210 Xml.Append(
"</value>");
1213 Xml.Append(
"</field>");
1214 Xml.Append(
"<field label='FAQ Entry' type='text-multi' var='muc#register_faqentry'>");
1216 if (!
string.IsNullOrEmpty(Occupant?.FaqEntry))
1218 Xml.Append(
"<value>");
1219 Xml.Append(
XML.
Encode(Occupant.FaqEntry));
1220 Xml.Append(
"</value>");
1223 Xml.Append(
"</field>");
1224 Xml.Append(
"</x></query>");
1229 private async Task RegisterUserSubmitFormHandler(
object Sender,
IqEventArgs e)
1253 StringBuilder Xml =
new StringBuilder();
1255 if (!(Occupant is
null) && !(Occupant.Role is
null))
1257 Xml.Append(
"<query xmlns='");
1259 Xml.Append(
"'><registered/><username>");
1260 Xml.Append(Occupant.NickName);
1261 Xml.Append(
"</username></query>");
1267 foreach (XmlNode N
in e.
Query.ChildNodes)
1272 if (Type ==
"cancel")
1274 if (!(Occupant is
null))
1276 Room.Remove(Occupant);
1278 if (Occupant.Persistent)
1286 if (Type !=
"submit")
1293 string FirstName =
null;
1294 string LastName =
null;
1295 string NickName =
null;
1296 string Url =
string.Empty;
1297 string EMail =
string.Empty;
1298 string FaqEntry =
string.Empty;
1300 foreach (XmlNode N2
in E.ChildNodes)
1312 case "muc#register_first":
1313 FirstName = GetValue(E2);
1316 case "muc#register_last":
1317 LastName = GetValue(E2);
1320 case "muc#register_roomnick":
1321 NickName = GetValue(E2);
1324 case "muc#register_url":
1328 case "muc#register_email":
1329 EMail = GetValue(E2);
1332 case "muc#register_faqentry":
1333 FaqEntry = GetValue(E2);
1343 if (FormType is
null ||
string.IsNullOrEmpty(FirstName) ||
string.IsNullOrEmpty(LastName) ||
string.IsNullOrEmpty(NickName))
1355 MucOccupant Occupant2 = await this.GetOccupantByNickName(Room, NickName);
1356 if (!(Occupant2 is
null) && Occupant2.BareJid != e.
From.
BareJid)
1362 if (!(Occupant is
null))
1364 bool Changed =
false;
1366 if (Occupant.FirstName != FirstName)
1368 Occupant.FirstName = FirstName;
1372 if (Occupant.LastName != LastName)
1374 Occupant.LastName = LastName;
1378 if (Occupant.NickName != NickName)
1380 Occupant.NickName = NickName;
1384 if (Occupant.Url != Url)
1390 if (Occupant.EMail != EMail)
1392 Occupant.EMail = EMail;
1396 if (Occupant.FaqEntry != FaqEntry)
1398 Occupant.FaqEntry = FaqEntry;
1402 if (Changed && Occupant.Persistent)
1406 Xml.Append(
"<x xmlns='");
1408 Xml.Append(
"' type='form'><title>Registration request</title>");
1409 Xml.Append(
"<instructions>To approve this registration request, select the "Allow this person to register with the room?" checkbox and click OK. To skip this request, click the cancel button.</instructions>");
1410 Xml.Append(
"<field var='FORM_TYPE' type='hidden'><value>");
1412 Xml.Append(
"</value></field>");
1413 Xml.Append(
"<field var='muc#occupant_jid' type='hidden'><value>");
1415 Xml.Append(
"</value></field>");
1416 Xml.Append(
"<field var='muc#register_first' type='text-single' label='Given Name'><value>");
1418 Xml.Append(
"</value></field>");
1419 Xml.Append(
"<field var='muc#register_last' type='text-single' label='Family Name'><value>");
1421 Xml.Append(
"</value></field>");
1422 Xml.Append(
"<field var='muc#register_roomnick' type='text-single' label='Desired Nickname'><value>");
1424 Xml.Append(
"</value></field>");
1425 Xml.Append(
"<field var='muc#register_url' type='text-single' label='User URL'><value>");
1427 Xml.Append(
"</value></field>");
1428 Xml.Append(
"<field var='muc#register_email' type='text-single' label='Email Address'><value>");
1430 Xml.Append(
"</value></field>");
1431 Xml.Append(
"<field var='muc#register_faqentry' type='text-multi' label='FAQ Entry'><value>");
1433 Xml.Append(
"</value></field>");
1434 Xml.Append(
"<field var='muc#register_allow' type='boolean' label='Allow this person to register with the room?'><value>false</value></field></x>");
1436 await this.SendToAdmin(Room,
string.Empty, Xml.ToString());
1446 private async Task SendToAdmin(
MucRoom Room,
string Type,
string Xml)
1448 Dictionary<string, bool> Sent =
new Dictionary<string, bool>();
1451 if (!(Room.Admins is
null))
1455 if (!Sent.ContainsKey(Jid))
1463 if (!(Room.Owners is
null))
1467 if (!Sent.ContainsKey(Jid))
1476 public static async Task<string> GenerateMessageXml(
string Markdown)
1478 StringBuilder sb =
new StringBuilder();
1480 sb.AppendLine(
"BodyOnly: 1");
1482 sb.Append(Markdown);
1490 sb.Append(
"<body>");
1492 sb.Append(
"</body>");
1493 sb.Append(
"<html xmlns='http://jabber.org/protocol/xhtml-im'>");
1494 sb.Append(
"<body xmlns='http://www.w3.org/1999/xhtml'>");
1496 sb.Append(
"</body></html>");
1497 sb.Append(
"<content xmlns='");
1499 sb.Append(
"' type='text/markdown'>");
1501 sb.Append(
"</content>");
1503 return sb.ToString();
1513 XmlElement E = e.
Query;
1517 if (
string.IsNullOrEmpty(Account))
1521 Room = await this.GetRoom(Account, e.
To.
Domain);
1528 if (Room.MembersOnly && !Room.IsMember(e.
From.
BareJid))
1543 if (Occupant is
null)
1550 if (FullJids is
null || FullJids.Length == 0)
1555 else if (FullJids.Length > 1)
1566 await e.
IqError(e2.ErrorTypeString, e2.ErrorElement?.OuterXml ??
string.Empty, e.
To, e2.ErrorText,
string.
Empty);
1574 if (!
string.IsNullOrEmpty(Node) && Node !=
"x-roomuser-item")
1580 StringBuilder Xml =
new StringBuilder();
1582 Xml.Append(
"<query xmlns='");
1586 if (!(Room is
null))
1588 if (
string.IsNullOrEmpty(Node))
1590 if (!
string.IsNullOrEmpty(Account))
1592 Xml.Append(
"<identity category='conference' name='");
1594 Xml.Append(
"' type='text'/>");
1600 if (!(Occupant is
null) && !
string.IsNullOrEmpty(Occupant.NickName))
1602 Xml.Append(
"<identity category='conference' name='");
1603 Xml.Append(
XML.
Encode(Occupant.NickName));
1604 Xml.Append(
"' type='text'/>");
1609 if (
string.IsNullOrEmpty(Account) &&
string.IsNullOrEmpty(Node))
1613 foreach (
string Feature
in this.
features.Keys)
1615 Xml.Append(
"<feature var='");
1622 if (!
string.IsNullOrEmpty(Account) &&
string.IsNullOrEmpty(Node) && !(Room is
null))
1624 Xml.Append(
"<feature var='http://jabber.org/protocol/muc'/>");
1625 Xml.Append(
"<feature var='");
1628 Xml.Append(
"<feature var='");
1631 Xml.Append(
"<feature var='http://jabber.org/protocol/muc#stable_id'/>");
1633 if (Room.MembersOnly)
1634 Xml.Append(
"<feature var='muc_membersonly'/>");
1637 Xml.Append(
"<feature var='muc_moderated'/>");
1639 Xml.Append(
"<feature var='muc_unmoderated'/>");
1641 switch (Room.DiscoverRealJids)
1643 case DiscoverReadJids.Anyone:
1644 Xml.Append(
"<feature var='muc_nonanonymous'/>");
1647 case DiscoverReadJids.Moderators:
1648 Xml.Append(
"<feature var='muc_semianonymous'/>");
1652 if (!Room.MembersOnly)
1653 Xml.Append(
"<feature var='muc_open'/>");
1655 if (Room.PasswordProtected)
1656 Xml.Append(
"<feature var='muc_passwordprotected'/>");
1658 Xml.Append(
"<feature var='muc_unsecured'/>");
1660 if (Room.Persistent)
1661 Xml.Append(
"<feature var='muc_persistent'/>");
1663 Xml.Append(
"<feature var='muc_temporary'/>");
1666 Xml.Append(
"<feature var='muc_hidden'/>");
1668 Xml.Append(
"<feature var='muc_public'/>");
1671 Xml.Append(
"</query>");
1683 XmlElement E = e.
Query;
1687 if (
string.IsNullOrEmpty(Account))
1691 Room = await this.GetRoom(Account, e.
To.
Domain);
1698 if (Room.MembersOnly && !Room.IsMember(e.
From.
BareJid))
1713 if (Occupant is
null)
1720 if (FullJids is
null || FullJids.Length == 0)
1725 else if (FullJids.Length > 1)
1736 await e.
IqError(e2.ErrorTypeString, e2.ErrorElement?.OuterXml ??
string.Empty, e.
To, e2.ErrorText,
string.
Empty);
1744 if (!
string.IsNullOrEmpty(Node) && Node !=
"x-roomuser-item")
1750 StringBuilder Xml =
new StringBuilder();
1752 Xml.Append(
"<query xmlns='");
1756 if (
string.IsNullOrEmpty(Node))
1758 if (
string.IsNullOrEmpty(Account))
1762 if (!this.rooms.ContainsKey(Room2.Room))
1763 this.rooms[Room2.Room] = Room2;
1767 Xml.Append(
"<item jid='");
1771 Xml.Append(
"' name='");
1779 if (!(Room is
null) &&
1781 !Room.MembersOnly &&
1782 !Room.PasswordProtected)
1784 IEnumerable<MucOccupant> Occupants;
1786 if (Room.Persistent)
1793 Occupants = Room.GetOccupants();
1797 Xml.Append(
"<item jid='");
1805 Xml.Append(
"</query>");
1810 private async Task FormSubmissionHandler(
object Sender,
MessageEventArgs e)
1840 if (Type ==
"cancel")
1842 else if (Type !=
"submit")
1849 if (Occupant is
null)
1857 foreach (XmlNode N2
in e.
Content.ChildNodes)
1859 if (N2 is XmlElement E2 &&
1860 E2.LocalName ==
"field" &&
1864 FormType = E2[
"value"]?.InnerText ??
string.Empty;
1873 string NickName =
null;
1876 foreach (XmlNode N2
in e.
Content.ChildNodes)
1881 string Value = E2[
"value"]?.InnerText ??
string.Empty;
1896 case "muc#roomnick":
1900 case "muc#request_allow":
1917 if (
string.IsNullOrEmpty(NickName))
1919 if (
string.IsNullOrEmpty(
Role))
1925 if (
Role !=
"moderator" &&
Role !=
"participant" &&
Role !=
"visitor" &&
Role !=
"none")
1931 StringBuilder sb =
new StringBuilder();
1933 sb.Append(
"<x xmlns='");
1935 sb.Append(
"' type='form'><title>Privileges request</title>");
1936 sb.Append(
"<instructions>To approve this request for privileges, select the ");
1937 sb.Append(
""Grant privileges to this person?" checkbox and click OK. ");
1938 sb.Append(
"To skip this request, click the cancel button.</instructions>");
1939 sb.Append(
"<field var='FORM_TYPE' type='hidden'><value>");
1941 sb.Append(
"</value></field>");
1942 sb.Append(
"<field var='muc#role' type='list-single' label='Requested role'><value>");
1944 sb.Append(
"</value>");
1945 sb.Append(
"<option label='None'><value>none</value></option>");
1946 sb.Append(
"<option label='Visitor'><value>visitor</value></option>");
1947 sb.Append(
"<option label='Participant'><value>participant</value></option>");
1948 sb.Append(
"<option label='Moderator'><value>moderator</value></option></field>");
1949 sb.Append(
"<field var='muc#jid' type='jid-single' label='JID of sender'><value>");
1951 sb.Append(
"</value></field>");
1952 sb.Append(
"<field var='muc#roomnick' type='text-single' label='Room Nickname'><value>");
1953 sb.Append(
XML.
Encode(Occupant.NickName));
1954 sb.Append(
"</value></field>");
1955 sb.Append(
"<field var='muc#request_allow' type='boolean' label='Grant privileges to this person?'><value>false</value></field></x>");
1957 await this.SendToAdmin(Room,
string.Empty, sb.ToString());
1961 if (
string.IsNullOrEmpty(
Role) ||
string.IsNullOrEmpty(NickName) || Jid is
null || !Allow.HasValue)
1969 if (!Room.IsModerator(Occupant))
1975 MucOccupant Occupant2 = await this.GetOccupantByNickName(Room, NickName);
1976 if (Occupant2 is
null)
1982 NickName = NickName,
1985 Persistent = Room.Persistent,
1986 Archive = Room.Archive
1991 if (!Room.Add(Occupant2))
1997 if (Occupant2.Persistent)
2002 if (Occupant2.BareJid != Jid.
BareJid)
2012 Occupant2.Role =
new Roles.None();
2016 Occupant2.Role =
new Visitor();
2032 if (Occupant2.Persistent)
2036 StringBuilder sb =
new StringBuilder();
2041 if (Jids0 is
null || Jids0.Length == 0)
2044 foreach (
MucOccupant Occupant3
in Room.GetOccupants())
2046 if (Room.CanDiscoverRealJids(Occupant3))
2053 sb.Append(
"<x xmlns='");
2055 sb.Append(
"'><item affiliation='");
2056 sb.Append(Occupant2.Affiliation.
Name);
2058 if (!(Jid2 is
null))
2060 sb.Append(
"' jid='");
2064 sb.Append(
"' role='");
2065 sb.Append(Occupant2.Role?.
Name ??
"none");
2066 sb.Append(
"'><actor nick='");
2069 sb.Append(
"</item>");
2075 if (!(Occupant3.FullJids is
null))
2077 foreach (
XmppAddress FullJid
in Occupant3.FullJids)
2078 await this.
Server.
Presence(
string.Empty, Guid.NewGuid().ToString(), FullJid, OccupantJid,
string.Empty, Xml,
this);
2087 string FirstName =
null;
2088 string LastName =
null;
2089 string NickName =
null;
2090 string Url =
string.Empty;
2091 string EMail =
string.Empty;
2092 string FaqEntry =
string.Empty;
2093 string FullJid =
string.
Empty;
2096 foreach (XmlNode N2
in e.
Content.ChildNodes)
2107 case "muc#occupant_jid":
2108 FullJid = GetValue(E2);
2111 case "muc#register_first":
2112 FirstName = GetValue(E2);
2115 case "muc#register_last":
2116 LastName = GetValue(E2);
2119 case "muc#register_roomnick":
2120 NickName = GetValue(E2);
2123 case "muc#register_url":
2127 case "muc#register_email":
2128 EMail = GetValue(E2);
2131 case "muc#register_faqentry":
2132 FaqEntry = GetValue(E2);
2135 case "muc#register_allow":
2152 if (FormType is
null ||
2153 string.IsNullOrEmpty(FirstName) ||
2154 string.IsNullOrEmpty(LastName) ||
2155 string.IsNullOrEmpty(NickName) ||
2156 string.IsNullOrEmpty(FullJid) ||
2163 if (!Room.IsModerator(Occupant))
2174 if (Occupant2 is
null)
2180 NickName = NickName,
2184 Persistent = Room.Persistent,
2185 Archive = Room.Archive,
2186 FirstName = FirstName,
2187 LastName = LastName,
2195 if (!Room.Add(Occupant2))
2201 if (Occupant2.Persistent)
2206 Occupant2.NickName = NickName;
2208 Occupant2.Persistent = Room.Persistent;
2209 Occupant2.Archive = Room.Archive;
2210 Occupant2.FirstName = FirstName;
2211 Occupant2.LastName = LastName;
2212 Occupant2.Url = Url;
2213 Occupant2.EMail = EMail;
2214 Occupant2.FaqEntry = FaqEntry;
2216 if (Occupant2.Role is
null)
2217 Occupant2.Role =
new Visitor();
2219 if (Occupant2.Persistent)
2223 await this.OccupantEntered(Room, Occupant2, From,
false,
string.Empty,
null);
2227 Room.Remove(Occupant2);
2229 if (Occupant2.Persistent)
2240 private async Task AdminCommandHandler(
object Sender,
IqEventArgs e)
2275 foreach (XmlNode N
in e.
Query.ChildNodes)
2280 switch (E.LocalName)
2288 if (!Room.IsModerator(Occupant))
2297 Occupant2 = await this.GetOccupantByNickName(Room, NickName);
2299 Occupant2 = await this.GetOccupantByBareJid(Room, Jid);
2301 if (Occupant2 is
null)
2311 if ((Room.IsAdmin(Occupant2) && !Room.IsAdmin(Occupant)) ||
2312 (Room.IsOwner(Occupant2) && !Room.IsOwner(Occupant)))
2318 bool Kicked =
false;
2320 bool Removed =
false;
2321 bool RoomUpdated =
false;
2322 string Type =
string.Empty;
2324 Occupant2.Reason =
string.Empty;
2326 if (!
string.IsNullOrEmpty(
Role))
2331 if (Occupant.BareJid == Occupant2.BareJid)
2337 Occupant2.Role =
new Roles.None();
2338 Type =
"unavailable";
2343 Occupant2.Role =
new Visitor();
2362 int NrOwnersBefore = Room.Owners.
Length;
2364 if (Room.IsOwner(Occupant2))
2366 if (Occupant.BareJid == Occupant2.BareJid)
2372 Room.RemoveOwner(Occupant2.BareJid);
2376 if (Room.IsAdmin(Occupant2))
2378 Room.RemoveAdmin(Occupant2.BareJid);
2385 if (Occupant.BareJid == Occupant2.BareJid)
2391 Occupant2.Affiliation =
new Affiliations.None();
2393 if (Room.MembersOnly)
2396 Room.Remove(Occupant);
2397 Type =
"unavailable";
2402 Occupant2.Affiliation =
new Member();
2406 Occupant2.Affiliation =
new Affiliations.Admin();
2407 Room.AddAdmin(Occupant2.BareJid);
2412 Occupant2.Affiliation =
new Owner();
2413 Room.AddOwner(Occupant2.BareJid);
2418 Room.Remove(Occupant);
2419 Occupant2.Affiliation =
new Outcast();
2421 Type =
"unavailable";
2429 int NrOwnersAfter = Room.Owners.
Length;
2431 if (NrOwnersAfter == 0 && NrOwnersBefore > 0)
2433 if (Room.Persistent)
2434 this.rooms.Remove(RoomId);
2436 Room.AddOwner(Occupant2.BareJid);
2443 foreach (XmlNode N2
in E.ChildNodes)
2445 if (N2 is XmlElement E2 && E2.LocalName ==
"reason" && E2.NamespaceURI ==
NamespaceMucAdmin)
2447 Occupant2.Reason = E2.InnerText;
2452 if (Occupant2.Persistent)
2455 if (RoomUpdated && Room.Persistent)
2458 StringBuilder Xml =
new StringBuilder();
2462 Xml.Append(
"<x xmlns='");
2464 Xml.Append(
"'><item affiliation='");
2465 Xml.Append(Occupant2.Affiliation.
Name);
2466 Xml.Append(
"' role='");
2467 Xml.Append(Occupant2.Role?.
Name ??
"none");
2468 Xml.Append(
"'><actor nick='");
2469 Xml.Append(
XML.
Encode(Occupant2.NickName));
2472 if (!
string.IsNullOrEmpty(Occupant2.Reason))
2474 Xml.Append(
"<reason>");
2475 Xml.Append(
XML.
Encode(Occupant2.Reason));
2476 Xml.Append(
"</reason>");
2479 Xml.Append(
"</item>");
2482 Xml.Append(
"<status code='301'/>");
2485 Xml.Append(
"<status code='307'/>");
2488 Xml.Append(
"<status code='321'/>");
2490 StringBuilder Xml2 =
new StringBuilder();
2491 Xml2.Append(Xml.ToString());
2492 Xml2.Append(
"</x>");
2495 ToSelf = Xml2.ToString();
2496 ToOthers = Xml.ToString();
2500 foreach (
MucOccupant Occupant3
in Room.GetOccupants())
2502 if (!(Occupant3.FullJids is
null))
2504 foreach (
XmppAddress FullJid
in Occupant3.FullJids)
2506 await this.
Server.
Presence(Type, Guid.NewGuid().ToString(), FullJid, OccupantJid,
string.Empty,
2507 FullJid == e.
From ? ToSelf : ToOthers,
this);
2513 Room.Remove(Occupant2);
2521 private async Task AdminQueryHandler(
object Sender,
IqEventArgs e)
2556 foreach (XmlNode N
in e.
Query.ChildNodes)
2561 switch (E.LocalName)
2567 if (!Room.IsModerator(Occupant))
2573 IEnumerable<MucOccupant> Occupants;
2575 if (!
string.IsNullOrEmpty(
Role))
2577 if (Room.Persistent)
2586 Occupants = from Occupant2 in Room.GetOccupants()
2587 where (Occupant2.Role?.
Name ??
"none") ==
Role
2593 if (Room.Persistent)
2602 Occupants = from Occupant2 in Room.GetOccupants()
2603 where (Occupant2.Affiliation?.
Name ??
"none") ==
Role
2610 StringBuilder Xml =
new StringBuilder();
2613 Xml.Append(
"<query xmlns='");
2619 if (Room.DiscoverRealJids == DiscoverReadJids.None ||
2620 !Room.TryGetOccupantFromNick(Occupant2.NickName, out
MucOccupant Occupant3))
2626 Jids = Occupant3.FullJids;
2627 if (Jids is
null || Jids.Length == 0)
2633 Xml.Append(
"<item affiliation='");
2634 Xml.Append(Occupant2.Affiliation?.
Name ??
"none");
2636 if (Occupant2.Affiliation is
Outcast)
2638 Xml.Append(
"' jid='");
2640 Xml.Append(
XML.
Encode(Occupant2.BareJid));
2648 Xml.Append(
"' jid='");
2652 Xml.Append(
"' nick='");
2653 Xml.Append(
XML.
Encode(Occupant2.NickName));
2654 Xml.Append(
"' role='");
2655 Xml.Append(Occupant2.Role?.
Name ??
"none");
2658 if (
string.IsNullOrEmpty(Occupant2.Reason))
2662 Xml.Append(
"'><reason>");
2663 Xml.Append(
XML.
Encode(Occupant2.Reason));
2664 Xml.Append(
"</reason></item>");
2669 Xml.Append(
"</query>");
2677 private async Task OwnerQueryHandler(
object Sender,
IqEventArgs e)
2706 StringBuilder Xml =
new StringBuilder();
2708 Xml.Append(
"<query xmlns='");
2710 Xml.Append(
"'><x xmlns='jabber:x:data' type='form'>");
2711 Xml.Append(
"<title>Configuration for ");
2713 Xml.Append(
" Room</title>");
2714 Xml.Append(
"<instructions>Enter room configuration below, then click OK.</instructions>");
2715 Xml.Append(
"<field type='hidden' var='FORM_TYPE'><value>");
2717 Xml.Append(
"</value></field>");
2718 Xml.Append(
"<field label='Natural-Language Room Name' type='text-single' var='muc#roomconfig_roomname'><value>");
2720 Xml.Append(
"</value></field>");
2721 Xml.Append(
"<field label='Short Description of Room' type='text-single' var='muc#roomconfig_roomdesc'><value>");
2722 Xml.Append(
XML.
Encode(Room.Description));
2723 Xml.Append(
"</value></field>");
2724 Xml.Append(
"<field label='Natural Language for Room Discussions' type='text-single' var='muc#roomconfig_lang'><value>");
2726 Xml.Append(
"</value></field>");
2727 Xml.Append(
"<field label='Enable Public Logging?' type='boolean' var='muc#roomconfig_enablelogging'><value>");
2728 Xml.Append(Room.Logging ?
"1" :
"0");
2729 Xml.Append(
"</value></field>");
2730 Xml.Append(
"<field label='Allow Occupants to Change Subject?' type='boolean' var='muc#roomconfig_changesubject'><value>");
2731 Xml.Append(Room.AllowChangeSubject ?
"1" :
"0");
2732 Xml.Append(
"</value></field>");
2733 Xml.Append(
"<field label='Allow Occupants to Invite Others?' type='boolean' var='muc#roomconfig_allowinvites'><value>");
2734 Xml.Append(Room.AllowInvites ?
"1" :
"0");
2735 Xml.Append(
"</value></field>");
2736 Xml.Append(
"<field label='Who Can Send Private Messages?' type='list-single' var='muc#roomconfig_allowpm'><value>");
2737 Xml.Append(Room.AllowPrivateMessages.ToString().ToLower());
2738 Xml.Append(
"</value>");
2739 Xml.Append(
"<option label='Anyone'><value>anyone</value></option>");
2740 Xml.Append(
"<option label='Anyone with Voice'><value>participants</value></option>");
2741 Xml.Append(
"<option label='Moderators Only'><value>moderators</value></option>");
2742 Xml.Append(
"<option label='Nobody'><value>none</value></option></field>");
2743 Xml.Append(
"<field label='Maximum Number of Occupants' type='list-single' var='muc#roomconfig_maxusers'><value>");
2744 Xml.Append(Room.MaxHistoryFetch ==
int.MaxValue ?
"none" : Room.MaxHistoryFetch.ToString());
2745 Xml.Append(
"</value>");
2746 Xml.Append(
"<option label='10'><value>10</value></option>");
2747 Xml.Append(
"<option label='20'><value>20</value></option>");
2748 Xml.Append(
"<option label='30'><value>30</value></option>");
2749 Xml.Append(
"<option label='50'><value>50</value></option>");
2750 Xml.Append(
"<option label='100'><value>100</value></option>");
2751 Xml.Append(
"<option label='None'><value>none</value></option></field>");
2752 Xml.Append(
"<field label='Roles for which Presence is Broadcasted' type='list-multi' var='muc#roomconfig_presencebroadcast'>");
2753 if (Room.PresenceBroadcast.HasFlag(BroadcastPresence.Moderator))
2754 Xml.Append(
"<value>moderator</value>");
2755 if (Room.PresenceBroadcast.HasFlag(BroadcastPresence.Participant))
2756 Xml.Append(
"<value>participant</value>");
2757 if (Room.PresenceBroadcast.HasFlag(BroadcastPresence.Visitor))
2758 Xml.Append(
"<value>visitor</value>");
2759 Xml.Append(
"<option label='Moderator'><value>moderator</value></option>");
2760 Xml.Append(
"<option label='Participant'><value>participant</value></option>");
2761 Xml.Append(
"<option label='Visitor'><value>visitor</value></option></field>");
2762 Xml.Append(
"<field label='Roles and Affiliations that May Retrieve Member List' type='list-multi' var='muc#roomconfig_getmemberlist'>");
2763 if (Room.GetMemberList.HasFlag(RetrieveMembershipList.Moderator))
2764 Xml.Append(
"<value>moderator</value>");
2765 if (Room.GetMemberList.HasFlag(RetrieveMembershipList.Participant))
2766 Xml.Append(
"<value>participant</value>");
2767 if (Room.GetMemberList.HasFlag(RetrieveMembershipList.Visitor))
2768 Xml.Append(
"<value>visitor</value>");
2769 Xml.Append(
"<option label='Moderator'><value>moderator</value></option>");
2770 Xml.Append(
"<option label='Participant'><value>participant</value></option>");
2771 Xml.Append(
"<option label='Visitor'><value>visitor</value></option></field>");
2772 Xml.Append(
"<field label='Make Room Publicly Searchable?' type='boolean' var='muc#roomconfig_publicroom'><value>");
2773 Xml.Append(Room.Public ?
"1" :
"0");
2774 Xml.Append(
"</value></field>");
2775 Xml.Append(
"<field label='Make Room Persistent?' type='boolean' var='muc#roomconfig_persistentroom'><value>");
2776 Xml.Append(Room.Persistent ?
"1" :
"0");
2777 Xml.Append(
"</value></field>");
2778 Xml.Append(
"<field label='Make Room Moderated?' type='boolean' var='muc#roomconfig_moderatedroom'><value>");
2779 Xml.Append(Room.Moderated ?
"1" :
"0");
2780 Xml.Append(
"</value></field>");
2781 Xml.Append(
"<field label='Make Room Members-Only?' type='boolean' var='muc#roomconfig_membersonly'><value>");
2782 Xml.Append(Room.MembersOnly ?
"1" :
"0");
2783 Xml.Append(
"</value></field>");
2784 Xml.Append(
"<field label='Password Required to Enter?' type='boolean' var='muc#roomconfig_passwordprotectedroom'><value>");
2785 Xml.Append(Room.PasswordProtected ?
"1" :
"0");
2786 Xml.Append(
"</value></field>");
2787 Xml.Append(
"<field type='fixed'><value>If a password is required to enter this room, you must specify the password below.</value></field>");
2788 Xml.Append(
"<field label='Password' type='text-private' var='muc#roomconfig_roomsecret'><value>");
2790 Xml.Append(
"</value></field>");
2791 Xml.Append(
"<field label='Who May Discover Real JIDs?' type='list-single' var='muc#roomconfig_whois'><value>");
2792 Xml.Append(Room.DiscoverRealJids.ToString().ToLower());
2793 Xml.Append(
"</value>");
2794 Xml.Append(
"<option label='No-one'><value>none</value></option>");
2795 Xml.Append(
"<option label='Moderators Only'><value>moderators</value></option>");
2796 Xml.Append(
"<option label='Anyone'><value>anyone</value></option></field>");
2797 Xml.Append(
"<field label='Maximum Number of History Messages Returned by Room' type='text-single' var='muc#maxhistoryfetch'><value>");
2798 Xml.Append(Room.MaxHistoryFetch.ToString());
2799 Xml.Append(
"</value></field>");
2800 Xml.Append(
"<field type='fixed'><value>You may specify additional people who have admin status in the room. Please provide one Jabber ID per line.</value></field>");
2801 Xml.Append(
"<field label='Room Admins' type='jid-multi' var='muc#roomconfig_roomadmins'>");
2802 if (!(Room.Admins is
null))
2806 Xml.Append(
"<value>");
2808 Xml.Append(
"</value>");
2811 Xml.Append(
"</field>");
2812 Xml.Append(
"<field type='fixed'><value>You may specify additional owners for this room. Please provide one Jabber ID per line.</value></field>");
2813 Xml.Append(
"<field label='Room Owners' type='jid-multi' var='muc#roomconfig_roomowners'>");
2814 if (!(Room.Owners is
null))
2818 Xml.Append(
"<value>");
2820 Xml.Append(
"</value>");
2823 Xml.Append(
"</field></x></query>");
2828 private async Task OwnerCommandHandler(
object Sender,
IqEventArgs e)
2857 foreach (XmlNode N
in e.
Query.ChildNodes)
2859 if (!(N is XmlElement E))
2866 string Password =
null;
2868 foreach (XmlNode N2
in E.ChildNodes)
2870 if (!(N2 is XmlElement E2))
2873 switch (E2.LocalName)
2880 Password = E2.InnerText;
2885 if (Room.PasswordProtected && (Password is
null || Room.Password != Password))
2891 StringBuilder sb =
new StringBuilder();
2893 sb.Append(
"<x xmlns='");
2895 sb.Append(
"'><item affiliation='none' role='none'/><destroy");
2897 if (!
string.IsNullOrEmpty(AlternativeRoomJid))
2899 sb.Append(
" jid='");
2900 sb.Append(
XML.
Encode(AlternativeRoomJid));
2906 if (!
string.IsNullOrEmpty(Reason))
2908 sb.Append(
"<reason>");
2910 sb.Append(
"</reason>");
2913 sb.Append(
"</destroy></x>");
2915 string Xml = sb.ToString();
2920 foreach (
MucOccupant Occupant2
in Room.GetOccupants())
2924 await this.
Server.
Presence(
"unavailable", Guid.NewGuid().ToString(), Jid,
2927 if (Occupant2.Persistent)
2930 Room.Remove(Occupant2);
2934 if (Room.Persistent)
2942 if (Room.Persistent && Room.Logging)
2950 new KeyValuePair<string, object>(
"Room", RoomId),
2951 new KeyValuePair<string, object>(
"Domain", e.
To.
Domain),
2952 new KeyValuePair<string, object>(
"Destroyer", e.
From.
BareJid));
2959 if (Type ==
"submit")
2961 CanSendPrivateMessages? PrivateMessages =
null;
2962 DiscoverReadJids? DiscoverJids =
null;
2963 BroadcastPresence? PresenceBroadcast =
null;
2964 RetrieveMembershipList? GetMemberList =
null;
2966 string RoomName =
null;
2967 string RoomDescription =
null;
2968 string RoomLanguage =
null;
2969 string Password =
null;
2972 int? MaxUsers =
null;
2973 int? MaxHistory =
null;
2974 bool? Logging =
null;
2975 bool? ChangeSubject =
null;
2976 bool? AllowInvites =
null;
2977 bool? Public =
null;
2978 bool? Persist =
null;
2979 bool? Moderated =
null;
2980 bool? MembersOnly =
null;
2981 bool? PasswordProtected =
null;
2982 bool InvalidBoolean =
false;
2983 bool InvalidInt =
false;
2984 bool InvalidEnum =
false;
2986 foreach (XmlNode N2
in E.ChildNodes)
2998 case "muc#roomconfig_roomname":
2999 RoomName = GetValue(E2);
3002 case "muc#roomconfig_roomdesc":
3003 RoomDescription = GetValue(E2);
3006 case "muc#roomconfig_lang":
3007 RoomLanguage = GetValue(E2);
3010 case "muc#roomconfig_enablelogging":
3014 InvalidBoolean =
true;
3017 case "muc#roomconfig_changesubject":
3021 InvalidBoolean =
true;
3024 case "muc#roomconfig_allowinvites":
3028 InvalidBoolean =
true;
3031 case "muc#roomconfig_allowpm":
3032 switch (GetValue(E2))
3035 PrivateMessages = CanSendPrivateMessages.Anyone;
3038 case "participants":
3039 PrivateMessages = CanSendPrivateMessages.Participants;
3043 PrivateMessages = CanSendPrivateMessages.Moderators;
3047 PrivateMessages = CanSendPrivateMessages.None;
3056 case "muc#roomconfig_maxusers":
3057 string s = GetValue(E2);
3058 if (
int.TryParse(s, out
int i))
3060 else if (s ==
"none")
3061 MaxUsers =
int.MaxValue;
3066 case "muc#roomconfig_publicroom":
3070 InvalidBoolean =
true;
3073 case "muc#roomconfig_persistentroom":
3077 InvalidBoolean =
true;
3080 case "muc#roomconfig_moderatedroom":
3084 InvalidBoolean =
true;
3087 case "muc#roomconfig_membersonly":
3091 InvalidBoolean =
true;
3094 case "muc#roomconfig_passwordprotectedroom":
3096 PasswordProtected = b;
3098 InvalidBoolean =
true;
3101 case "muc#roomconfig_roomsecret":
3102 Password = GetValue(E2);
3105 case "muc#roomconfig_presencebroadcast":
3106 PresenceBroadcast = BroadcastPresence.None;
3112 PresenceBroadcast |= BroadcastPresence.Moderator;
3116 PresenceBroadcast |= BroadcastPresence.Participant;
3120 PresenceBroadcast |= BroadcastPresence.Visitor;
3130 case "muc#roomconfig_getmemberlist":
3131 GetMemberList = RetrieveMembershipList.None;
3137 GetMemberList |= RetrieveMembershipList.Moderator;
3141 GetMemberList |= RetrieveMembershipList.Participant;
3145 GetMemberList |= RetrieveMembershipList.Visitor;
3155 case "muc#roomconfig_whois":
3156 switch (GetValue(E2))
3159 DiscoverJids = DiscoverReadJids.Anyone;
3163 DiscoverJids = DiscoverReadJids.Moderators;
3167 DiscoverJids = DiscoverReadJids.None;
3176 case "muc#maxhistoryfetch":
3177 if (
int.TryParse(GetValue(E2), out i))
3183 case "muc#roomconfig_roomadmins":
3184 Administrators = GetValues(E2);
3187 case "muc#roomconfig_roomowners":
3188 Owners = GetValues(E2);
3229 bool NameChanged =
false;
3230 bool DescriptionChanged =
false;
3231 bool LanguageChanged =
false;
3232 bool LoggingChanged =
false;
3233 bool ChangeSubjectChanged =
false;
3234 bool AllowInvitesChanged =
false;
3235 bool PrivateMessagesChanged =
false;
3236 bool MaxOccupantsChanged =
false;
3237 bool PresenceBroadcastChanged =
false;
3238 bool MembershipListChanged =
false;
3239 bool PersistentChanged =
false;
3240 bool ModeratedChanged =
false;
3241 bool MembersOnlyChanged =
false;
3242 bool PublicChanged =
false;
3243 bool PasswordProtectedChanged =
false;
3244 bool PasswordChanged =
false;
3245 bool DiscoverJidsChanged =
false;
3246 bool MaxHistoryChanged =
false;
3247 bool AdminsChanged =
false;
3248 bool OwnersChanged =
false;
3249 SortedDictionary<int, bool> StatusChange =
null;
3251 if (!(RoomName is
null) && Room.Name != RoomName)
3253 Room.Name = RoomName;
3255 this.AddStatus(ref StatusChange, 104);
3258 if (!(RoomDescription is
null) && Room.Description != RoomDescription)
3260 Room.Description = RoomDescription;
3261 DescriptionChanged =
true;
3262 this.AddStatus(ref StatusChange, 104);
3265 if (!(RoomLanguage is
null) && Room.Language != RoomLanguage)
3267 Room.Language = RoomLanguage;
3268 LanguageChanged =
true;
3269 this.AddStatus(ref StatusChange, 104);
3272 if (Logging.HasValue && Logging.Value != Room.Logging)
3274 Room.Logging = Logging.Value;
3275 LoggingChanged =
true;
3276 this.AddStatus(ref StatusChange, Room.Logging ? 170 : 171);
3277 this.AddStatus(ref StatusChange, 104);
3280 if (ChangeSubject.HasValue && ChangeSubject.Value != Room.AllowChangeSubject)
3282 Room.AllowChangeSubject = ChangeSubject.Value;
3283 ChangeSubjectChanged =
true;
3284 this.AddStatus(ref StatusChange, 104);
3287 if (AllowInvites.HasValue && AllowInvites.Value != Room.AllowInvites)
3289 Room.AllowInvites = AllowInvites.Value;
3290 AllowInvitesChanged =
true;
3291 this.AddStatus(ref StatusChange, 104);
3294 if (PrivateMessages.HasValue && PrivateMessages.Value != Room.AllowPrivateMessages)
3296 Room.AllowPrivateMessages = PrivateMessages.Value;
3297 PrivateMessagesChanged =
true;
3298 this.AddStatus(ref StatusChange, 104);
3301 if (MaxUsers.HasValue && MaxUsers.Value != Room.MaxOccupants)
3303 Room.MaxOccupants = MaxUsers.Value;
3304 MaxOccupantsChanged =
true;
3305 this.AddStatus(ref StatusChange, 104);
3308 if (PresenceBroadcast.HasValue && PresenceBroadcast.Value != Room.PresenceBroadcast)
3310 Room.PresenceBroadcast = PresenceBroadcast.Value;
3311 PresenceBroadcastChanged =
true;
3312 this.AddStatus(ref StatusChange, 104);
3315 if (GetMemberList.HasValue && GetMemberList.Value != Room.GetMemberList)
3317 Room.GetMemberList = GetMemberList.Value;
3318 MembershipListChanged =
true;
3319 this.AddStatus(ref StatusChange, 104);
3322 if (Persist.HasValue && Persist.Value != Room.Persistent)
3324 Room.Persistent = Persist.Value;
3325 PersistentChanged =
true;
3326 this.AddStatus(ref StatusChange, 104);
3329 if (Moderated.HasValue && Moderated.Value != Room.Moderated)
3331 Room.Moderated = Moderated.Value;
3332 ModeratedChanged =
true;
3333 this.AddStatus(ref StatusChange, 104);
3336 if (MembersOnly.HasValue && MembersOnly.Value != Room.MembersOnly)
3338 Room.MembersOnly = MembersOnly.Value;
3339 MembersOnlyChanged =
true;
3340 this.AddStatus(ref StatusChange, 104);
3343 if (Public.HasValue && Public.Value != Room.Public)
3345 Room.Public = Public.Value;
3346 PublicChanged =
true;
3347 this.AddStatus(ref StatusChange, 104);
3350 if (PasswordProtected.HasValue && PasswordProtected.Value != Room.PasswordProtected)
3352 Room.PasswordProtected = PasswordProtected.Value;
3353 PasswordProtectedChanged =
true;
3354 this.AddStatus(ref StatusChange, 104);
3357 if (!(Password is
null) && Password != Room.Password)
3359 Room.Password = Password;
3360 PasswordChanged =
true;
3361 this.AddStatus(ref StatusChange, 104);
3364 if (DiscoverJids.HasValue && DiscoverJids.Value != Room.DiscoverRealJids)
3366 Room.DiscoverRealJids = DiscoverJids.Value;
3367 DiscoverJidsChanged =
true;
3368 this.AddStatus(ref StatusChange, 104);
3370 switch (Room.DiscoverRealJids)
3372 case DiscoverReadJids.Anyone:
3373 this.AddStatus(ref StatusChange, 172);
3376 case DiscoverReadJids.Moderators:
3377 this.AddStatus(ref StatusChange, 173);
3382 if (MaxHistory.HasValue && MaxHistory.Value != Room.MaxHistoryFetch)
3384 Room.MaxHistoryFetch = MaxHistory.Value;
3385 MaxHistoryChanged =
true;
3386 this.AddStatus(ref StatusChange, 104);
3389 if (!(Administrators is
null) && !AreEqual(Room.Admins, Administrators))
3391 if (!(Room.Admins is
null))
3395 if (Array.IndexOf(Administrators, Jid) < 0)
3397 MucOccupant Occupant = await this.GetOccupantByBareJid(Room, Jid);
3398 if (!(Occupant is
null))
3400 Occupant.Affiliation =
new Member();
3403 if (Occupant.Persistent)
3406 await this.PresenceUserXmlToAll(Room, Occupant);
3413 Room.Admins = Administrators;
3414 AdminsChanged =
true;
3415 this.AddStatus(ref StatusChange, 104);
3418 if (!(Owners is
null) && !AreEqual(Room.Owners, Owners))
3420 if (!(Room.Owners is
null))
3424 if (Array.IndexOf(Owners, Jid) < 0)
3426 MucOccupant Occupant = await this.GetOccupantByBareJid(Room, Jid);
3427 if (!(Occupant is
null))
3429 Occupant.Affiliation =
new Member();
3432 if (Occupant.Persistent)
3435 await this.PresenceUserXmlToAll(Room, Occupant);
3442 Room.Owners = Owners;
3443 OwnersChanged =
true;
3444 this.AddStatus(ref StatusChange, 104);
3451 if (Array.IndexOf(OldAdmins, Jid) < 0)
3453 MucOccupant Occupant = await this.GetOccupantByBareJid(Room, Jid);
3454 if (!(Occupant is
null))
3456 Occupant.Affiliation =
new Affiliations.Admin();
3459 if (Occupant.Persistent)
3462 await this.PresenceUserXmlToAll(Room, Occupant);
3472 if (Array.IndexOf(OldOwners, Jid) < 0)
3474 MucOccupant Occupant = await this.GetOccupantByBareJid(Room, Jid);
3475 if (!(Occupant is
null))
3477 Occupant.Affiliation =
new Owner();
3480 if (Occupant.Persistent)
3483 await this.PresenceUserXmlToAll(Room, Occupant);
3489 bool Created = Room.Locked;
3490 Room.Locked =
false;
3492 if (Room.Persistent)
3494 if (
string.IsNullOrEmpty(Room.ObjectID))
3501 foreach (
MucOccupant Occupant
in Room.GetOccupants())
3503 if (!Occupant.Persistent)
3505 Occupant.Persistent =
true;
3507 if (
string.IsNullOrEmpty(Occupant.ObjectID))
3518 StringBuilder sb =
new StringBuilder();
3520 if (!(StatusChange is
null))
3522 sb.Append(
"<x xmlns='");
3526 foreach (
int Code
in StatusChange.Keys)
3528 sb.Append(
"<status code='");
3529 sb.Append(Code.ToString());
3535 await this.PresenceXmlToAll(Room, sb.ToString());
3542 sb.Append(
"Room Created");
3544 sb.Append(
"Room Configuration Updated");
3546 sb.AppendLine(
" ||");
3547 sb.AppendLine(
"|:-----|:------|");
3548 sb.Append(
"| Room: | `");
3549 sb.Append(Room.Room);
3550 sb.AppendLine(
"` |");
3551 sb.Append(
"| Domain: | `");
3552 sb.Append(Room.Domain);
3553 sb.AppendLine(
"` |");
3554 sb.Append(
"| Creator: | `");
3555 sb.Append(Room.Creator);
3556 sb.AppendLine(
"` |");
3557 sb.Append(
"| Name: | ");
3559 sb.AppendLine(
" |");
3560 sb.Append(
"| Description: | ");
3562 sb.AppendLine(
" |");
3563 sb.Append(
"| Language: | ");
3565 sb.AppendLine(
" |");
3566 sb.Append(
"| Logging: | ");
3567 sb.Append(BoldIfChanged(OneRow(Room.Logging), LoggingChanged));
3568 sb.AppendLine(
" |");
3569 sb.Append(
"| Allow Change of Subject: | ");
3570 sb.Append(BoldIfChanged(OneRow(Room.AllowChangeSubject), ChangeSubjectChanged));
3571 sb.AppendLine(
" |");
3572 sb.Append(
"| Allow Invites: | ");
3573 sb.Append(BoldIfChanged(OneRow(Room.AllowInvites), AllowInvitesChanged));
3574 sb.AppendLine(
" |");
3575 sb.Append(
"| Private Messages: | ");
3576 sb.Append(BoldIfChanged(OneRow(Room.AllowPrivateMessages), PrivateMessagesChanged));
3577 sb.AppendLine(
" |");
3578 sb.Append(
"| Max Occupants: | ");
3579 sb.Append(BoldIfChanged(Room.MaxOccupants ==
int.MaxValue ?
"No limit" : Room.MaxOccupants.ToString(), MaxOccupantsChanged));
3580 sb.AppendLine(
" |");
3581 sb.Append(
"| Presence Broadcast: | ");
3582 sb.Append(BoldIfChanged(OneRow(Room.PresenceBroadcast), PresenceBroadcastChanged));
3583 sb.AppendLine(
" |");
3584 sb.Append(
"| Membership List: | ");
3585 sb.Append(BoldIfChanged(OneRow(Room.GetMemberList), MembershipListChanged));
3586 sb.AppendLine(
" |");
3587 sb.Append(
"| Persistent: | ");
3588 sb.Append(BoldIfChanged(OneRow(Room.Persistent), PersistentChanged));
3589 sb.AppendLine(
" |");
3590 sb.Append(
"| Moderated: | ");
3591 sb.Append(BoldIfChanged(OneRow(Room.Moderated), ModeratedChanged));
3592 sb.AppendLine(
" |");
3593 sb.Append(
"| Members-Only: | ");
3594 sb.Append(BoldIfChanged(OneRow(Room.MembersOnly), MembersOnlyChanged));
3595 sb.AppendLine(
" |");
3596 sb.Append(
"| Public: | ");
3597 sb.Append(BoldIfChanged(OneRow(Room.Public), PublicChanged));
3598 sb.AppendLine(
" |");
3599 sb.Append(
"| Password protection: | ");
3600 sb.Append(BoldIfChanged(OneRow(Room.PasswordProtected), PasswordProtectedChanged));
3601 sb.AppendLine(
" |");
3602 sb.Append(
"| Password: | ");
3603 sb.Append(BoldIfChanged(OneRow(!
string.IsNullOrEmpty(Room.Password)), PasswordChanged));
3604 sb.AppendLine(
" |");
3605 sb.Append(
"| Discover JIDs: | ");
3606 sb.Append(BoldIfChanged(OneRow(Room.DiscoverRealJids), DiscoverJidsChanged));
3607 sb.AppendLine(
" |");
3608 sb.Append(
"| Max History: | ");
3609 sb.Append(BoldIfChanged(OneRow(Room.MaxHistoryFetch.ToString()), MaxHistoryChanged));
3610 sb.AppendLine(
" |");
3611 sb.Append(
"| Administrators: | ");
3612 sb.Append(BoldIfChanged(OneRow(Room.Admins), AdminsChanged));
3613 sb.AppendLine(
" |");
3614 sb.Append(
"| Owners: | ");
3615 sb.Append(BoldIfChanged(OneRow(Room.Owners), OwnersChanged));
3616 sb.AppendLine(
" |");
3618 await this.SendToAdmin(Room,
"chat", await GenerateMessageXml(sb.ToString()));
3620 else if (Type ==
"cancel")
3623 this.rooms.Remove(RoomId);
3633 private void AddStatus(ref SortedDictionary<int, bool> Codes,
int Code)
3636 Codes =
new SortedDictionary<int, bool>();
3645 foreach (
MucOccupant Occupant2
in Room.GetOccupants())
3647 if (!(Occupant2.FullJids is
null))
3651 if (Room.CanDiscoverRealJids(Occupant2) && !(Occupant.FullJids is
null) && Occupant.FullJids.Length > 0)
3653 foreach (
XmppAddress FullJid
in Occupant.FullJids)
3655 await this.
Server.
Presence(
string.Empty, Guid.NewGuid().ToString(), Jid, From,
string.Empty,
3656 Occupant.GetUserXml(FullJid.
Address, Occupant.NickName),
this);
3661 await this.
Server.
Presence(
string.Empty, Guid.NewGuid().ToString(), Jid, From,
string.Empty,
3662 Occupant.GetUserXml(
null, Occupant.NickName),
this);
3669 private Task PresenceXmlToAll(
MucRoom Room,
string Xml)
3672 return this.PresenceXmlToAll(From, Room.GetOccupants(), Xml);
3679 if (!(Occupant2.FullJids is
null))
3682 await this.
Server.
Presence(
string.Empty, Guid.NewGuid().ToString(), Jid, From,
string.Empty, Xml,
this);
3689 if (Strings is
null)
3690 return string.Empty;
3692 StringBuilder sb =
new StringBuilder();
3707 return sb.ToString();
3710 private static bool AreEqual(Array A1, Array A2)
3712 if ((A1 is
null) ^ (A2 is
null))
3724 for (i = 0; i < c; i++)
3726 if (!A1.GetValue(i).Equals(A2.GetValue(i)))
3733 private static string BoldIfChanged(
string s,
bool Changed)
3735 return Changed ?
"**" + s +
"**" : s;
3738 private static string OneRow(Enum e)
3740 return "`" + e.ToString() +
"`";
3743 private static string OneRow(
bool b)
3745 return b ?
"✔" :
"✗";
3748 private static string OneRow(
string s)
3750 return s.Replace(
"\r\n",
"\n").Replace(
'\r',
'\n').Replace(
'\n',
' ');
3753 private static string GetValue(XmlElement E)
3755 foreach (XmlNode N
in E.ChildNodes)
3757 if (N is XmlElement E2 && E2.LocalName ==
"value" && E.NamespaceURI == E2.NamespaceURI)
3758 return E2.InnerText;
3761 return string.Empty;
3766 List<CaseInsensitiveString> Values =
new List<CaseInsensitiveString>();
3768 foreach (XmlNode N
in E.ChildNodes)
3770 if (N is XmlElement E2 && E2.LocalName ==
"value" && E.NamespaceURI == E2.NamespaceURI)
3771 Values.Add(E2.InnerText);
3774 return Values.ToArray();
3777 private async Task SelfPingHandler(
object Sender,
IqEventArgs e)
Helps with parsing of commong data types.
static bool TryParse(string s, out double Value)
Tries to decode a string encoded double.
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,...
Helps with common XML-related tasks.
static string Attribute(XmlElement E, string Name)
Gets the value of an XML attribute.
static string HtmlValueEncode(string s)
Differs from Encode(String), in that it does not encode the aposotrophe or the quote.
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 class managing the application event log. Applications and services log events on this static ...
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 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...
Base class for components.
bool UnregisterMessageHandler(string LocalName, string Namespace, EventHandlerAsync< MessageEventArgs > Handler, bool RemoveNamespaceAsFeature)
Unregisters a message handler.
void RegisterIqSetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers an IQ-Set handler.
CaseInsensitiveString Subdomain
Subdomain name.
bool UnregisterPresenceHandler(string LocalName, string Namespace, EventHandlerAsync< PresenceEventArgs > Handler, bool RemoveNamespaceAsFeature)
Unregisters a presence handler.
void RegisterIqGetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers an IQ-Get handler.
static string InnerXmlNoJabberNamespace(XmlElement Xml)
Removes the jabber namespace from the outer XML of an element.
void RegisterPresenceHandler(string LocalName, string Namespace, EventHandlerAsync< PresenceEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers a presence handler.
string Name
Component name.
readonly object synchObject
Synchronization object for thread-safe access to internal structures.
async Task< bool > Message(string Type, string Id, XmppAddress To, XmppAddress From, string Language, Stanza Stanza, ISender Sender)
Message stanza.
XmppServer Server
XMPP Server.
bool UnregisterIqGetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool RemoveNamespaceAsFeature)
Unregisters an IQ-Get handler.
bool UnregisterIqSetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool RemoveNamespaceAsFeature)
Unregisters an IQ-Set handler.
void UnregisterFeature(string Namespace)
Unregisters a feature.
void RegisterMessageHandler(string LocalName, string Namespace, EventHandlerAsync< MessageEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers a message handler.
SortedDictionary< string, bool > features
Features supported by component.
void RegisterFeature(string Namespace)
Registers a feature.
Event arguments for IQ queries.
Task IqErrorNotAuthorized(XmppAddress From, string ErrorText, string Language)
Returns a not-authorized error.
XmppAddress From
From address attribute
Task IqErrorNotAcceptable(XmppAddress From, string ErrorText, string Language)
Returns a not-acceptable error.
Task IqResult(string Xml, string From)
Returns a response to the current request.
Task IqErrorItemNotFound(XmppAddress From, string ErrorText, string Language)
Returns a item-not-found error.
XmlElement Query
Query element, if found, null otherwise.
Task IqErrorNotAllowed(XmppAddress From, string ErrorText, string Language)
Returns a not-allowed error.
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 IqErrorServiceUnavailable(XmppAddress From, string ErrorText, string Language)
Returns a service-unavailable error.
Task IqErrorJidMalformed(XmppAddress From, string ErrorText, string Language)
Returns a jid-malformed error.
Task IqErrorConflict(XmppAddress From, string ErrorText, string Language)
Returns a conflict error.
Task IqErrorBadRequest(XmppAddress From, string ErrorText, string Language)
Returns a bad-request error.
Task IqErrorForbidden(XmppAddress From, string ErrorText, string Language)
Returns a forbidden error.
Event arguments for Messages.
Task< bool > MessageErrorServiceUnavailable(XmppAddress From, string ErrorText, string Language)
Sens a message error stanza
Task< bool > MessageErrorItemNotFound(XmppAddress From, string ErrorText, string Language)
Sens a message error stanza
Task< bool > MessageErrorJidMalformed(XmppAddress From, string ErrorText, string Language)
Sens a message error stanza
Task< bool > MessageErrorNotAcceptable(XmppAddress From, string ErrorText, string Language)
Sens a message error stanza
Task< bool > MessageErrorConflict(XmppAddress From, string ErrorText, string Language)
Sens a message error stanza
Task< bool > MessageErrorForbidden(XmppAddress From, string ErrorText, string Language)
Sens a message error stanza
XmppAddress From
From address attribute
XmlElement Message
Message element.
Task< bool > MessageErrorBadRequest(XmppAddress From, string ErrorText, string Language)
Sens a message error stanza
XmppAddress To
To address attribute
string Id
ID of the request.
string Type
Type of request.
XmlElement Content
Content element, if found, null otherwise.
Presence information event arguments.
string Type
Type attribute.
Task PresenceErrorRegistrationRequired(XmppAddress From, string ErrorText, string Language)
Returns an error response to the current request.
string Language
Language attribute.
XmlElement Content
Content element, if found, null otherwise.
Task PresenceErrorServiceUnavailable(XmppAddress From, string ErrorText, string Language)
Returns an error response to the current request.
Task PresenceErrorItemNotFound(XmppAddress From, string ErrorText, string Language)
Returns an error response to the current request.
Task PresenceErrorForbidden(XmppAddress From, string ErrorText, string Language)
Returns an error response to the current request.
Task PresenceErrorNotAcceptable(XmppAddress From, string ErrorText, string Language)
Returns an error response to the current request.
XmppAddress To
To attribute.
Task PresenceErrorNotAllowed(XmppAddress From, string ErrorText, string Language)
Returns an error response to the current request.
Task PresenceErrorJidMalformed(XmppAddress From, string ErrorText, string Language)
Returns an error response to the current request.
Task PresenceErrorConflict(XmppAddress From, string ErrorText, string Language)
Returns an error response to the current request.
Task PresenceErrorNotAuthorized(XmppAddress From, string ErrorText, string Language)
Returns an error response to the current request.
XmppAddress From
From attribute.
XmlElement StanzaElement
Stanza element.
Contains information about one XMPP address.
override string ToString()
object.ToString()
bool IsBareJID
If the address is a Bare JID.
bool HasAccount
If the address has an account part.
CaseInsensitiveString Resource
Resource part.
CaseInsensitiveString Domain
Domain
CaseInsensitiveString Address
XMPP Address
XmppAddress ToBareJID()
Returns the Bare JID as an XmppAddress object.
CaseInsensitiveString BareJid
Bare JID
static readonly XmppAddress Empty
Empty address.
CaseInsensitiveString Account
Account
bool IsFullJID
If the Address is a Full JID.
const string DiscoveryItemsNamespace
http://jabber.org/protocol/disco#items (XEP-0030)
const string ExtendedAddressingNamespace
http://jabber.org/protocol/address (XEP-0033)
const string DiscoveryNamespace
http://jabber.org/protocol/disco#info (XEP-0030)
async Task< bool > Message(string Type, string Id, XmppAddress To, XmppAddress From, string Language, Stanza Stanza, ISender Sender)
Message stanza.
const string ContentNamespace
urn:xmpp:content
Task< bool > SendIqRequest(string Type, string From, string To, string Language, string ContentXml, EventHandlerAsync< IqResultEventArgs > Callback, object State)
Sends an IQ stanza to a recipient.
const string DataFormsNamespace
jabber:x:data (XEP-0004)
const string PingNamespace
urn:xmpp:ping (XEP-0199)
bool IsServerDomain(CaseInsensitiveString Domain, bool IncludeAlternativeDomains)
Checks if a domain is the server domain, or optionally, an alternative domain.
const string RegisterNamespace
jabber:iq:register (XEP-0077)
const string DelayedDeliveryNamespace
urn:xmpp:delay (XEP-0203)
async Task< bool > Presence(string Type, string Id, XmppAddress From, string Language, Stanza Stanza, ISender Sender)
Presence stanza.
Represents a case-insensitive string.
string Value
String-representation of the case-insensitive string. (Representation is case sensitive....
int Length
Gets the number of characters in the current CaseInsensitiveString object.
string LowerCase
Lower-case representation of the case-insensitive string.
static bool IsNullOrEmpty(CaseInsensitiveString value)
Indicates whether the specified string is null or an CaseInsensitiveString.Empty string.
Static interface for database persistence. In order to work, a database provider has to be assigned t...
static Task< IEnumerable< object > > FindDelete(string Collection, params string[] SortOrder)
Finds objects in a given collection and deletes them in the same atomic operation.
static async Task DeleteLazy(object Object)
Deletes an object in the database, if unlocked. If locked, object will be deleted at next opportunity...
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 UpdateLazy(object Object)
Updates an object in the database, if unlocked. If locked, object will be updated at next opportunity...
static Task< IEnumerable< object > > Find(string Collection, params string[] SortOrder)
Finds objects in a given collection.
This filter selects objects that conform to all child-filters provided.
Custom filter used to filter objects using an external expression.
This filter selects objects that have a named field equal to a given value.
This filter selects objects that have a named field greater or equal to a given value.
Implements an in-memory cache.
Abstract base class for MUC affiliations.
abstract Role GetDefaultRole(MucRoom Room)
Gets the default role, given type of room type. If null is returned, entry is not permitted.
abstract string Name
Name of affiliation, in XML.
Represents a member of a room
Represents the owner of a room
Multi-user Chat Room Message
Multi-user Chat Room Occupant
Multi-User-Chat (MUC) Component component, as defined in XEP-0045. https://xmpp.org/extensions/xep-00...
override async Task DiscoveryQueryGet(object Sender, IqEventArgs e)
Get handler for Service Discovery query (XEP-0030).
const string NamespaceMucOwner
http://jabber.org/protocol/muc#owner
MultiUserChatComponent(XmppServer Server, CaseInsensitiveString Subdomain, string Name)
Multi-User-Chat (MUC) Component component, as defined in XEP-0045. https://xmpp.org/extensions/xep-00...
const string FormTypeRoomConfig
http://jabber.org/protocol/muc#roomconfig
override void Dispose()
IDisposable.Dispose
const string NamespaceMucUser
http://jabber.org/protocol/muc#user
override async Task MessageNoHandlerReceived(MessageEventArgs e)
Message without corresponding handler received.
const string NamespaceMuc
http://jabber.org/protocol/muc
const string FormTypeRequest
http://jabber.org/protocol/muc#request
override async Task DiscoveryQueryItemsGet(object Sender, IqEventArgs e)
Get handler for Service Discovery items query (XEP-0030).
override bool SupportsAccounts
If the component supports accounts (true), or if the subdomain name is the only valid address.
override async Task PresenceNoHandlerReceived(PresenceEventArgs e)
Presence stanza without a corresponding handler received.
const string FormTypeRegister
http://jabber.org/protocol/muc#register
const string NamespaceMucAdmin
http://jabber.org/protocol/muc#admin
Abstract base class for MUC roles.
abstract string Name
Name of role, in XML.
abstract bool ReceiveMessages
If user can receive messages
abstract bool ReceiveOccupantPresence
If user can receive presence stanzas from occupants
Service Module hosting the XMPP broker and its components.
Reason
Reason a token is not valid.