2using System.Collections.Generic;
4using System.Threading.Tasks;
74 int i = FromBareJid.
IndexOf(
'@');
90 List<KeyValuePair<string, object>> Tags =
new List<KeyValuePair<string, object>>();
91 DateTime Timestamp =
XML.
Attribute(E,
"timestamp", DateTime.MinValue);
100 string StackTrace =
string.Empty;
102 foreach (XmlNode N
in E.ChildNodes)
117 TagValueParsed = TagValue;
119 Tags.Add(
new KeyValuePair<string, object>(TagName, TagValueParsed));
123 StackTrace = N.InnerText;
128 if (
string.IsNullOrEmpty(Facility))
129 Facility = FromBareJid;
131 Event Event =
new Event(Timestamp, Type,
Message, Object, Actor, EventId, Level, Facility, Module, StackTrace, Tags.ToArray());
139 private async Task SearchQueryHandler(
object Sender,
IqEventArgs e)
143 await e.
IqErrorForbidden(e.
To,
"Access denied. Not sufficient privileges to perform search.",
"en");
147 StringBuilder Xml =
new StringBuilder();
148 string Instructions =
"Limit the search on events by entering values in one or more fields below. Use asterisks (*) for wildcard searches.";
150 Xml.Append(
"<query xmlns='");
152 Xml.Append(
"'><instructions>");
153 Xml.Append(Instructions);
154 Xml.Append(
"</instructions>");
155 Xml.Append(
"<x xmlns='");
157 Xml.Append(
"' xmlns:xdv='http://jabber.org/protocol/xdata-validate' type='form'><title>Event Log Search</title><instructions>");
158 Xml.Append(Instructions);
159 Xml.Append(
"</instructions><field type='hidden' var='FORM_TYPE'><value>");
161 Xml.Append(
"</value></field>");
163 Xml.Append(
"<field type='text-single' label ='From:' var='From'>");
164 Xml.Append(
"<desc>Search for events newer than this.</desc>");
165 Xml.Append(
"<required/>");
166 Xml.Append(
"<xdv:validate datatype='xs:dateTime'/>");
167 Xml.Append(
"<value>");
168 Xml.Append(
XML.
Encode(DateTime.Now.AddHours(-1)));
169 Xml.Append(
"</value>");
170 Xml.Append(
"</field>");
172 Xml.Append(
"<field type='text-single' label ='To:' var='To'>");
173 Xml.Append(
"<desc>Search for events older than this.</desc>");
174 Xml.Append(
"<required/>");
175 Xml.Append(
"<xdv:validate datatype='xs:dateTime'/>");
176 Xml.Append(
"<value>");
178 Xml.Append(
"</value>");
179 Xml.Append(
"</field>");
181 Xml.Append(
"<field type='list-single' label ='Type:' var='Type'>");
182 Xml.Append(
"<desc>Choose event types.</desc>");
183 Xml.Append(
"<value>All</value>");
184 Xml.Append(
"<option label='All'><value>All</value></option>");
188 Xml.Append(
"<option label='");
190 Xml.Append(
"'><value>");
192 Xml.Append(
"</value></option>");
195 Xml.Append(
"</field>");
197 Xml.Append(
"<field type='list-single' label ='Level:' var='Level'>");
198 Xml.Append(
"<desc>Choose event levels.</desc>");
199 Xml.Append(
"<value>All</value>");
200 Xml.Append(
"<option label='All'><value>All</value></option>");
204 Xml.Append(
"<option label='");
206 Xml.Append(
"'><value>");
208 Xml.Append(
"</value></option>");
211 Xml.Append(
"</field>");
213 Xml.Append(
"<field type='text-single' label ='Message:' var='Message'>");
214 Xml.Append(
"<desc>Search for events containing a specific message text.</desc>");
215 Xml.Append(
"<xdv:validate datatype='xs:string'/>");
216 Xml.Append(
"<value/>");
217 Xml.Append(
"</field>");
219 Xml.Append(
"<field type='text-single' label ='Object:' var='Object'>");
220 Xml.Append(
"<desc>Search for events relating to a specific object.</desc>");
221 Xml.Append(
"<xdv:validate datatype='xs:string'/>");
222 Xml.Append(
"<value/>");
223 Xml.Append(
"</field>");
225 Xml.Append(
"<field type='text-single' label ='Actor:' var='Actor'>");
226 Xml.Append(
"<desc>Search for events relating to a specific actor.</desc>");
227 Xml.Append(
"<xdv:validate datatype='xs:string'/>");
228 Xml.Append(
"<value/>");
229 Xml.Append(
"</field>");
231 Xml.Append(
"<field type='text-single' label ='Event ID:' var='EventId'>");
232 Xml.Append(
"<desc>Search for events having a specific event identity.</desc>");
233 Xml.Append(
"<xdv:validate datatype='xs:string'/>");
234 Xml.Append(
"<value/>");
235 Xml.Append(
"</field>");
237 Xml.Append(
"<field type='text-single' label ='Facility:' var='Facility'>");
238 Xml.Append(
"<desc>Search for events coming from a specific facility.</desc>");
239 Xml.Append(
"<xdv:validate datatype='xs:string'/>");
240 Xml.Append(
"<value/>");
241 Xml.Append(
"</field>");
243 Xml.Append(
"<field type='text-single' label ='Module:' var='Module'>");
244 Xml.Append(
"<desc>Search for events originating in a specific module.</desc>");
245 Xml.Append(
"<xdv:validate datatype='xs:string'/>");
246 Xml.Append(
"<value/>");
247 Xml.Append(
"</field>");
249 Xml.Append(
"<field type='text-single' label ='Stack Trace:' var='StackTrace'>");
250 Xml.Append(
"<desc>Search for events containing a specific stack trace.</desc>");
251 Xml.Append(
"<xdv:validate datatype='xs:string'/>");
252 Xml.Append(
"<value/>");
253 Xml.Append(
"</field>");
255 Xml.Append(
"</x></query>");
260 private async Task SearchHandler(
object Sender,
IqEventArgs e)
264 await e.
IqErrorForbidden(e.
To,
"Access denied. Not sufficient privileges to perform search.",
"en");
268 List<Filter> Filters =
new List<Filter>();
270 foreach (XmlNode N
in e.
Query.ChildNodes)
272 if (N is XmlElement E && E.LocalName ==
"x" && E.NamespaceURI ==
NamespaceDataForm)
274 foreach (XmlNode N2
in E.ChildNodes)
276 if (N2 is XmlElement E2 && E2.LocalName ==
"field")
278 XmlElement Value = E2[
"value"];
287 if (!
XML.
TryParse(Value.InnerText, out DateTime From))
297 if (!
XML.
TryParse(Value.InnerText, out DateTime To))
307 string s = E2.InnerText;
342 if (!
string.IsNullOrEmpty(s))
344 if (s.IndexOf(
'*') >= 0)
358 switch (Filters.Count)
373 StringBuilder Xml =
new StringBuilder();
374 Dictionary<string, string> Headers =
new Dictionary<string, string>();
375 List<KeyValuePair<string, string>> HeadersOrdered =
new List<KeyValuePair<string, string>>()
377 new KeyValuePair<string, string>(
"Timestamp",
"Timestamp"),
378 new KeyValuePair<string, string>(
"Type",
"Type"),
379 new KeyValuePair<string, string>(
"Level",
"Level"),
380 new KeyValuePair<string, string>(
"Message",
"Message"),
381 new KeyValuePair<string, string>(
"Object",
"Object"),
382 new KeyValuePair<string, string>(
"Actor",
"Actor"),
383 new KeyValuePair<string, string>(
"EventId",
"Event ID"),
384 new KeyValuePair<string, string>(
"Facility",
"Facility"),
385 new KeyValuePair<string, string>(
"Module",
"Module"),
386 new KeyValuePair<string, string>(
"StackTrace",
"Stack Trace")
389 foreach (KeyValuePair<string, string> P
in HeadersOrdered)
390 Headers[P.Key] = P.Value;
394 Xml.Append(
"<item>");
396 Xml.Append(
"<field var='Timestamp'><value>");
398 Xml.Append(
"</value></field>");
400 Xml.Append(
"<field var='Type'><value>");
402 Xml.Append(
"</value></field>");
404 Xml.Append(
"<field var='Level'><value>");
406 Xml.Append(
"</value></field>");
408 Xml.Append(
"<field var='Message'><value>");
413 Xml.Append(
"</value></field>");
415 Xml.Append(
"<field var='Object'><value>");
420 Xml.Append(
"</value></field>");
422 Xml.Append(
"<field var='Actor'><value>");
427 Xml.Append(
"</value></field>");
429 Xml.Append(
"<field var='EventId'><value>");
434 Xml.Append(
"</value></field>");
436 Xml.Append(
"<field var='Facility'><value>");
441 Xml.Append(
"</value></field>");
443 Xml.Append(
"<field var='Module'><value>");
448 Xml.Append(
"</value></field>");
449 Xml.Append(
"<field var='StackTrace'><value>");
454 Xml.Append(
"</value></field>");
460 if (!(Tag.
Name is
null))
462 if (!Headers.ContainsKey(Tag.
Name))
465 HeadersOrdered.Add(
new KeyValuePair<string, string>(Tag.
Name, Tag.
Name));
469 Xml.Append(
"<field var='");
471 if (!(Tag.
Name is
null))
474 Xml.Append(
"'><value>");
476 if (!(Tag.
Value is
null))
479 Xml.Append(
"</value></field>");
483 Xml.Append(
"</item>");
486 StringBuilder Xml2 =
new StringBuilder();
488 Xml2.Append(
"<query xmlns='");
490 Xml2.Append(
"'><x xmlns='");
492 Xml2.Append(
"' type='result'><field type='hidden' var='FORM_TYPE'><value>");
494 Xml2.Append(
"</value></field><reported>");
496 foreach (KeyValuePair<string, string> Header
in HeadersOrdered)
498 Xml2.Append(
"<field var='");
500 Xml2.Append(
"' label='");
502 Xml2.Append(
"' type='text-single'/>");
505 Xml2.Append(
"</reported>");
506 Xml2.Append(Xml.ToString());
507 Xml2.Append(
"</x></query>");
Helps with common XML-related tasks.
static string Attribute(XmlElement E, string Name)
Gets the value of an XML attribute.
static string Encode(string s)
Encodes a string for use in XML.
static bool TryParse(string s, out DateTime Value)
Tries to decode a string encoded DateTime.
Class representing an event.
string Message
Free-text event message.
EventType Type
Type of event.
string Object
Object related to the event.
EventLevel Level
Event Level.
string Actor
Actor responsible for the action causing the event.
string Module
Module where the event is reported.
DateTime Timestamp
Timestamp of event.
KeyValuePair< string, object >[] Tags
Variable set of tags providing event-specific information.
string EventId
Computer-readable Event ID identifying type of even.
string Facility
Facility can be either a facility in the network sense or in the system sense.
string StackTrace
Stack Trace of event.
Static class managing the application event log. Applications and services log events on this static ...
static async void Event(Event Event)
Logs an event. It will be distributed to registered event sinks.
Class representing a persisted event.
Class representing a persisted tag.
This class handles incoming events from the XMPP network. The default behaviour is to log incoming ev...
static bool TryParse(string Value, string Type, out object ParsedValue)
Tries to parse a simple value.
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.
void RegisterIqGetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers an IQ-Get handler.
string Name
Component name.
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 RegisterMessageHandler(string LocalName, string Namespace, EventHandlerAsync< MessageEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers a message handler.
Event arguments for IQ queries.
XmppAddress From
From address attribute
Task IqResult(string Xml, string From)
Returns a response to the current request.
XmlElement Query
Query element, if found, null otherwise.
XmppAddress To
To address attribute
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.
XmppAddress From
From address attribute
XmlElement Content
Content element, if found, null otherwise.
CaseInsensitiveString Address
XMPP Address
CaseInsensitiveString BareJid
Bare JID
bool IsServerDomain(CaseInsensitiveString Domain, bool IncludeAlternativeDomains)
Checks if a domain is the server domain, or optionally, an alternative domain.
Represents a 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....
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 string WildcardToRegex(string s, string Wildcard)
Converts a wildcard string to a regular expression string.
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.
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.
This filter selects objects that have a named field lesser or equal to a given value.
This filter selects objects that have a named field matching a given regular expression.
Base class for all filter classes.
Event log component, as defined in XEP-0337. https://xmpp.org/extensions/xep-0337....
const string NamespaceEventLog
urn:xmpp:eventlog
override void Dispose()
IDisposable.Dispose
EventLogComponent(XmppServer Server, CaseInsensitiveString Subdomain, string Name)
Event log component, as defined in XEP-0337. https://xmpp.org/extensions/xep-0337....
override bool SupportsAccounts
If the component supports accounts (true), or if the subdomain name is the only valid address.
const string NamespaceSearch
jabber:iq:search
const string NamespaceDataForm
jabber:x:data
long NrLogMessages
Number of log messages received from this entity.
Service Module hosting the XMPP broker and its components.
Interface for XMPP user accounts.