Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
HttpFileUploadComponent.cs
1using System;
3using System.IO;
4using System.Text;
5using System.Threading.Tasks;
6using System.Web;
7using Waher.Content;
9using Waher.Events;
14
16{
22 {
23 private static readonly char[] invalidCharacters = Path.GetInvalidFileNameChars();
24
25 private readonly HttpFileUploadSettings settings;
28
32 public const string Namespace = "urn:xmpp:http:upload:0";
33
37 public const string BackupNamespace = "http://waher.se/Schema/Backups.xsd";
38
42 public const string EncryptedStorageNamespace = "http://waher.se/Schema/EncryptedStorage.xsd";
43
47 public const string PubSubNamespace = "http://waher.se/Schema/PubSub.xsd";
48
52 public const string InternalTransferNamespace = "http://waher.se/Schema/InternalTransfer.xsd";
53
62 : base(Server, Subdomain, "HTTP File Upload")
63 {
64 this.settings = Settings;
65
66 this.DeleteUploadedFiles();
67
68 if (!Directory.Exists(Settings.FileFolder))
69 Directory.CreateDirectory(Settings.FileFolder);
70
71 this.statusByClient = new Cache<CaseInsensitiveString, UploadInformation>(int.MaxValue, TimeSpan.MaxValue, this.settings.FileLifetime, true);
72 this.files = new Cache<CaseInsensitiveString, FileInfo>(int.MaxValue, TimeSpan.MaxValue, this.settings.FileLifetime, true);
73
74 this.files.Removed += this.Files_Removed;
75
76 this.RegisterIqGetHandler("request", Namespace, this.RequestHandler, true);
77 this.RegisterIqSetHandler("prepare", BackupNamespace, this.PrepareBackupHandler, true);
78 this.RegisterIqSetHandler("prepare", EncryptedStorageNamespace, this.PrepareEncryptedStorageHandler, true);
79 this.RegisterIqSetHandler("prepare", PubSubNamespace, this.PreparePubSubStorageHandler, true);
80 this.RegisterIqSetHandler("prepare", InternalTransferNamespace, this.PrepareInternalTransferHandler, true);
81 }
82
83 private void DeleteUploadedFiles()
84 {
85 if (Directory.Exists(this.settings.FileFolder))
86 {
87 try
88 {
89 Directory.Delete(this.settings.FileFolder, true);
90 }
91 catch (Exception ex)
92 {
93 Log.Exception(ex);
94 }
95 }
96 }
97
101 public override void Dispose()
102 {
103 base.Dispose();
104
105 this.UnregisterIqGetHandler("request", Namespace, this.RequestHandler, true);
106 this.UnregisterIqSetHandler("prepare", BackupNamespace, this.PrepareBackupHandler, true);
107 this.UnregisterIqSetHandler("prepare", EncryptedStorageNamespace, this.PrepareEncryptedStorageHandler, true);
108 this.UnregisterIqSetHandler("prepare", PubSubNamespace, this.PreparePubSubStorageHandler, true);
109 this.UnregisterIqSetHandler("prepare", InternalTransferNamespace, this.PrepareInternalTransferHandler, true);
110
111 this.statusByClient?.Dispose();
112 this.statusByClient = null;
113
114 this.files?.Dispose();
115 this.files = null;
116
117 this.DeleteUploadedFiles();
118 }
119
124 public override bool SupportsAccounts => false;
125
129 protected override Task AppendServiceDiscoveryIdentities(StringBuilder Xml, IqEventArgs e, string Node)
130 {
131 Xml.Append("<identity category='store' type='file' name='HTTP File Upload' />");
132
133 return Task.CompletedTask;
134 }
135
139 protected override Task AppendServiceDiscoveryFeatures(StringBuilder Xml, IqEventArgs e, string Node)
140 {
141 Xml.Append("<x type='result' xmlns='jabber:x:data'>");
142 Xml.Append("<field var='FORM_TYPE' type='hidden'>");
143 Xml.Append("<value>");
144 Xml.Append(Namespace);
145 Xml.Append("</value>");
146 Xml.Append("</field>");
147 Xml.Append("<field var='max-file-size'>");
148 Xml.Append("<value>");
149 Xml.Append(this.settings.MaxFileSize.ToString());
150 Xml.Append("</value>");
151 Xml.Append("</field>");
152 Xml.Append("</x>");
153
154 return Task.CompletedTask;
155 }
156
157 private async Task RequestHandler(object Sender, IqEventArgs e)
158 {
159 string FileName = XML.Attribute(e.Query, "filename");
160 string ContentType = XML.Attribute(e.Query, "content-type");
161 long Size = XML.Attribute(e.Query, "size", 0L);
162
163 if (!await this.IsFileOk(FileName, ContentType, Size, e))
164 return;
165
166 if (!e.To.IsDomain)
167 {
168 await e.IqErrorBadRequest(e.To, "Invalid destination address.", "en");
169 return;
170 }
171
172 string Extension = Path.GetExtension(FileName).ToLower();
173 if (Extension.StartsWith('.'))
174 Extension = Extension[1..];
175
176 string BaseContentType = ContentType;
177
178 InternetContent.ParseContentType(ref BaseContentType, out _, out _);
179
180 if (InternetContent.TryGetContentType(Extension, out string ExtensionType))
181 {
182 if (InternetContent.Decodes(ExtensionType, out _, out IContentDecoder ExtensionDecoder) &&
183 InternetContent.Decodes(BaseContentType, out _, out IContentDecoder ContentDecoder) &&
184 ExtensionDecoder.GetType() != ContentDecoder.GetType())
185 {
186 await e.IqErrorBadRequest(e.To, "File extension does not match Content-Type.", "en");
187 return;
188 }
189 }
190 else if (InternetContent.Decodes(BaseContentType, out _, out IContentDecoder ContentDecoder) &&
191 Array.IndexOf(ContentDecoder.FileExtensions, Extension) < 0)
192 {
193 await e.IqErrorBadRequest(e.To, "File extension does not match Content-Type.", "en");
194 return;
195 }
196
198 FilePurpose Purpose;
199
200 if (this.statusByClient.TryGetValue(BareJid, out UploadInformation Status) &&
201 Status.TryGetSpecialFile(FileName, ContentType, Size, out SpecialFile SpecialFile))
202 {
203 Purpose = SpecialFile.Purpose;
204 }
205 else
206 Purpose = FilePurpose.Temporary;
207
208 if (Purpose == FilePurpose.Temporary || Purpose == FilePurpose.InternalTransfer)
209 {
210 int i = BareJid.IndexOf('@');
211 if (i < 0)
212 {
213 await e.IqErrorForbidden(e.To, "Only local clients are allowed to upload content.", "en");
214 return;
215 }
216
217 CaseInsensitiveString Domain = BareJid.Substring(i + 1);
218 if (!this.Server.IsServerDomain(Domain, true))
219 {
220 await e.IqErrorForbidden(e.To, "Only local clients are allowed to upload content.", "en");
221 return;
222 }
223
224 CaseInsensitiveString UserName = BareJid.Substring(0, i);
225 IAccount Account = await this.Server.GetAccount(UserName);
226 if (Account is null)
227 {
228 await e.IqErrorForbidden(e.To, "Only local clients are allowed to upload content.", "en");
229 return;
230 }
231
232 if (Size > this.settings.MaxFileSize)
233 {
234 await e.IqError("modify", "<not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' />" +
235 "<file-too-large xmlns='urn:xmpp:http:upload:0'>" +
236 "<max-file-size>" + this.settings.MaxFileSize.ToString() + "</max-file-size>" +
237 "</file-too-large>", e.To, "File too large. The maximum file size is " + this.settings.MaxFileSize.ToString() +
238 " bytes.", "en");
239 return;
240 }
241 }
242
243 if (!await this.Server.PersistenceLayer.IsPermitted(BareJid, "HTTP.Upload"))
244 {
245 await e.IqErrorNotAllowed(e.To, "You are not allowed to upload files.", "en");
246 return;
247 }
248
249 if (Status is null)
250 {
251 Status = new UploadInformation(BareJid);
252 this.statusByClient[BareJid] = Status;
253 }
254
255 switch (Status.CanUploadFile(Size, Purpose, this.settings))
256 {
257 case CanUploadResult.FileQuotaReached:
258 await e.IqErrorResourceConstraint(e.To, "Quota reached. You can only upload " +
259 this.settings.MaxFilesPerMinute.ToString() + " files per minute.", "en");
260 return;
261
262 case CanUploadResult.ByteQuotaReached:
263 await e.IqErrorResourceConstraint(e.To, "Quota reached. You can only upload " +
264 this.settings.MaxBytesPerMinute.ToString() + " bytes per minute.", "en");
265 return;
266
267 case CanUploadResult.Permitted:
268 StringBuilder Xml = new StringBuilder();
269 string Id = this.Server.NewId(32);
270 string Resource = "/" + Id + "/" + HttpUtility.UrlEncode(FileName);
271 string FilePath;
272 string PutUrl = this.settings.HttpFolder + Resource;
273 string GetUrl = PutUrl;
274 string Key = this.Server.NewId(32);
275
276 switch (Purpose)
277 {
278 case FilePurpose.Temporary:
279 default:
280 FilePath = Path.Combine(this.settings.FileFolder, BareJid, Id + ".bin");
281 break;
282
283 case FilePurpose.Backup:
284 if (FileName.EndsWith(".key", StringComparison.InvariantCultureIgnoreCase))
285 FilePath = Path.Combine(this.settings.KeyFolder, BareJid, FileName);
286 else
287 FilePath = Path.Combine(this.settings.BackupFolder, BareJid, FileName);
288 break;
289
290 case FilePurpose.Encrypted:
291 DateTime Today = DateTime.Today;
292 string EncryptedResource = Path.Combine(Today.Year.ToString("D4"),
293 Today.Month.ToString("D2"), Today.Day.ToString("D2"), Id + ".bin");
294 FilePath = Path.Combine(this.settings.EncryptedStorageFolder, EncryptedResource);
295 GetUrl = this.settings.EncryptedStorageRoot + "/" + EncryptedResource.Replace(Path.DirectorySeparatorChar, '/');
296 break;
297
298 case FilePurpose.PubSub:
299 Today = DateTime.Today;
300 string PubSubResource = Path.Combine(Today.Year.ToString("D4"),
301 Today.Month.ToString("D2"), Today.Day.ToString("D2"), FileName);
302 FilePath = Path.Combine(this.settings.PubSubStorageFolder, PubSubResource);
303 if (File.Exists(FilePath))
304 {
305 await e.IqErrorConflict(e.To, "File already exists.", "en");
306 return;
307 }
308
309 GetUrl = this.settings.PubSubStorageRoot + "/" + PubSubResource.Replace(Path.DirectorySeparatorChar, '/');
310 break;
311
312 case FilePurpose.InternalTransfer:
313 FilePath = Path.Combine(this.settings.InternalTransferFolder, Id + ".bin");
314 break;
315 }
316
317 this.files.Add(Resource, new FileInfo()
318 {
319 Jid = e.From.Address,
320 Resource = Resource,
321 Key = Key,
322 Url = GetUrl,
324 FilePath = FilePath,
325 Size = Size,
326 HasBeenPut = false,
327 Purpose = Purpose
328 });
329
330 Xml.Append("<slot xmlns='urn:xmpp:http:upload:0'>");
331 Xml.Append("<put url='");
332 Xml.Append(XML.Encode(PutUrl));
333 Xml.Append("'><header name='X-Key'>");
334 Xml.Append(Key);
335 Xml.Append("</header></put>");
336 Xml.Append("<get url='");
337 Xml.Append(XML.Encode(GetUrl));
338 Xml.Append("'/></slot>");
339
340 await e.IqResult(Xml.ToString(), e.To);
341 break;
342 }
343 }
344
345 private async Task<bool> IsFileOk(string FileName, string ContentType, long Size, IqEventArgs e)
346 {
347 if (Size < 0)
348 {
349 await e.IqErrorBadRequest(e.To, "Invalid size.", "en");
350 return false;
351 }
352
353 if (string.IsNullOrEmpty(FileName) ||
354 FileName.Contains("\\") ||
355 FileName.Contains("/") ||
356 FileName.Contains("..") ||
357 FileName.IndexOfAny(invalidCharacters) >= 0)
358 {
359 await e.IqErrorBadRequest(e.To, "Invalid file name.", "en");
360 return false;
361 }
362
363 if (string.IsNullOrEmpty(ContentType))
364 {
365 await e.IqErrorBadRequest(e.To, "Invalid content type.", "en");
366 return false;
367 }
368
369 return true;
370 }
371
372 private Task PrepareBackupHandler(object Sender, IqEventArgs e)
373 {
374 return this.Prepare(e, FilePurpose.Backup);
375 }
376
377 private Task PrepareEncryptedStorageHandler(object Sender, IqEventArgs e)
378 {
379 return this.Prepare(e, FilePurpose.Encrypted);
380 }
381
382 private Task PreparePubSubStorageHandler(object Sender, IqEventArgs e)
383 {
384 return this.Prepare(e, FilePurpose.PubSub);
385 }
386
387 private Task PrepareInternalTransferHandler(object Sender, IqEventArgs e)
388 {
389 return this.Prepare(e, FilePurpose.InternalTransfer);
390 }
391
392 private async Task Prepare(IqEventArgs e, FilePurpose Purpose)
393 {
394 CaseInsensitiveString BareJid = e.From.BareJid;
395 string FileName = XML.Attribute(e.Query, "filename");
396 string ContentType = XML.Attribute(e.Query, "content-type");
397 long Size = XML.Attribute(e.Query, "size", 0L);
398
399 if (!await this.IsFileOk(FileName, ContentType, Size, e))
400 return;
401
402 if (!this.statusByClient.TryGetValue(BareJid, out UploadInformation Status))
403 {
404 Status = new UploadInformation(BareJid);
405 this.statusByClient[BareJid] = Status;
406 }
407
408 Status.AddSpecialFile(FileName, ContentType, Size, Purpose);
409
410 await e.IqResult(string.Empty, e.To);
411 }
412
413 private Task Files_Removed(object Sender, CacheItemEventArgs<CaseInsensitiveString, FileInfo> e)
414 {
415 try
416 {
417 if ((e.Value.Purpose == FilePurpose.Temporary ||
418 e.Value.Purpose == FilePurpose.InternalTransfer) &&
419 File.Exists(e.Value.FilePath))
420 {
421 File.Delete(e.Value.FilePath);
422
423 string Folder = Path.GetDirectoryName(e.Value.FilePath);
424
425 if (Directory.GetFiles(Folder, "*.*", SearchOption.AllDirectories).Length == 0)
426 Directory.Delete(Folder);
427 }
428 }
429 catch (Exception ex)
430 {
431 Log.Exception(ex);
432 }
433
434 return Task.CompletedTask;
435 }
436
447 public async Task<bool> DataUploaded(string Resource, string Key, Stream Data,
448 ContentByteRangeInterval Interval, string ContentType, string RemoteEndPoint)
449 {
450 if (!this.files.TryGetValue(Resource, out FileInfo FileInfo))
451 {
452 Log.Error("PUT/PATCH request rejected. Resource slot not found.",
453 new KeyValuePair<string, object>("Resource", Resource),
454 new KeyValuePair<string, object>("RemoteEndPoint", RemoteEndPoint));
455
456 return false;
457 }
458
459 if (Key != FileInfo.Key)
460 {
461 Log.Error("PUT/PATCH request rejected. Invalid key.",
462 new KeyValuePair<string, object>("Resource", Resource),
463 new KeyValuePair<string, object>("Key", Key),
464 new KeyValuePair<string, object>("RemoteEndPoint", RemoteEndPoint));
465
466 return false;
467 }
468
469 if (ContentType != FileInfo.ContentType)
470 {
471 Log.Error("PUT/PATCH request rejected. Invalid Content-Type.",
472 new KeyValuePair<string, object>("Resource", Resource),
473 new KeyValuePair<string, object>("Key", Key),
474 new KeyValuePair<string, object>("RemoteEndPoint", RemoteEndPoint));
475
476 return false;
477 }
478
480 {
481 Log.Error("PUT/PATCH request rejected. File has already been put.",
482 new KeyValuePair<string, object>("Resource", Resource),
483 new KeyValuePair<string, object>("RemoteEndPoint", RemoteEndPoint));
484
485 return false;
486 }
487
488 if (Interval.Last - Interval.First + 1 != Data.Length)
489 {
490 Log.Error("PUT/PATCH request rejected. Range error.",
491 new KeyValuePair<string, object>("Resource", Resource),
492 new KeyValuePair<string, object>("Actual", Data.Length),
493 new KeyValuePair<string, object>("Expected", FileInfo.Size),
494 new KeyValuePair<string, object>("RemoteEndPoint", RemoteEndPoint));
495
496 return false;
497 }
498
499 if (Interval.Last >= FileInfo.Size)
500 {
501 Log.Error("PUT/PATCH request rejected. File size mismatch.",
502 new KeyValuePair<string, object>("Resource", Resource),
503 new KeyValuePair<string, object>("Actual", Data.Length),
504 new KeyValuePair<string, object>("Expected", FileInfo.Size),
505 new KeyValuePair<string, object>("RemoteEndPoint", RemoteEndPoint));
506
507 return false;
508 }
509
510 Data.Position = 0;
511
512 string Folder = Path.GetDirectoryName(FileInfo.FilePath);
513 if (!Directory.Exists(Folder))
514 Directory.CreateDirectory(Folder);
515
516 using FileStream Dest = File.Exists(FileInfo.FilePath)
517 ? File.OpenWrite(FileInfo.FilePath)
518 : File.Create(FileInfo.FilePath);
519
520 if (Interval.First > 0)
521 {
522 if (Dest.Length < Interval.First)
523 {
524 Dest.Position = Dest.Length;
525
526 long Rest = Interval.First - Dest.Length;
527 byte[] Buffer = new byte[Math.Min(Rest, 65536)];
528
529 while (Rest > 0)
530 {
531 int c = (int)Math.Min(Rest, 65536);
532 await Dest.WriteAsync(Buffer, 0, c);
533 Rest -= c;
534 }
535 }
536 else
537 Dest.Position = Interval.First;
538 }
539
540 await Data.CopyToAsync(Dest);
541
542 if (Data.Position >= FileInfo.Size)
543 {
544 FileInfo.HasBeenPut = true;
545
546 if (InternetContent.Decodes(ContentType, out _, out _))
547 {
548 string Error = null;
549
550 try
551 {
552 Dest.Position = 0;
553 byte[] Data2 = await Dest.ReadAllAsync();
554
555 ContentResponse Decoded = await InternetContent.DecodeAsync(ContentType,
556 Data2, new Uri(FileInfo.Url));
557
558 if (Decoded.HasError)
559 Error = Decoded.Error.Message;
560 }
561 catch (Exception ex)
562 {
563 Error = ex.Message;
564 }
565
566 if (!string.IsNullOrEmpty(Error))
567 {
568 Log.Error("PUT/PATCH request rejected. Uploaded content could not be " +
569 "decoded properly: " + Error,
570 new KeyValuePair<string, object>("Resource", Resource),
571 new KeyValuePair<string, object>("RemoteEndPoint", RemoteEndPoint));
572
573 Dest.Close();
574 File.Delete(FileInfo.FilePath);
575 this.files.Remove(Resource);
576
577 return false;
578 }
579 }
580
581 Log.Informational("File uploaded.",
582 new KeyValuePair<string, object>("JID", FileInfo.Jid.Value),
583 new KeyValuePair<string, object>("ContentType", FileInfo.ContentType),
584 new KeyValuePair<string, object>("Path", FileInfo.FilePath),
585 new KeyValuePair<string, object>("Purpose", FileInfo.Purpose),
586 new KeyValuePair<string, object>("Size", Data.Length),
587 new KeyValuePair<string, object>("RemoteEndPoint", RemoteEndPoint));
588 }
589
590 return true;
591 }
592
601 public bool TryGetFile(string Resource, out string FilePath, out string ContentType,
602 out FilePurpose Purpose)
603 {
604 if (this.files.TryGetValue(Resource, out FileInfo FileInfo))
605 {
606 FilePath = FileInfo.FilePath;
607 ContentType = FileInfo.ContentType;
608 Purpose = FileInfo.Purpose;
609 return true;
610 }
611 else
612 {
613 FilePath = null;
614 ContentType = null;
615 Purpose = FilePurpose.Temporary;
616 return false;
617 }
618 }
619
620 }
621}
Contains information about a response to a content request.
bool HasError
If an error occurred.
Exception Error
Error response.
Static class managing encoding and decoding of internet content.
static bool Decodes(string ContentType, out Grade Grade, out IContentDecoder Decoder)
If an object with a given content type can be decoded.
static bool ParseContentType(ref string ContentType, out Encoding Encoding, out KeyValuePair< string, string >[] Fields)
Parses a Content-Type, providing the base Content-Type, character encoding, if any,...
static Task< ContentResponse > DecodeAsync(string ContentType, byte[] Data, Encoding Encoding, KeyValuePair< string, string >[] Fields, Uri BaseUri)
Decodes an object.
static bool TryGetContentType(string FileExtension, out string ContentType)
Tries to get the content type of an item, given its file extension.
Helps with common XML-related tasks.
Definition: XML.cs:21
static string Attribute(XmlElement E, string Name)
Gets the value of an XML attribute.
Definition: XML.cs:1062
static string Encode(string s)
Encodes a string for use in XML.
Definition: XML.cs:29
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:14
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.
Definition: Log.cs:1657
static void Error(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs an error event.
Definition: Log.cs:692
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.
Definition: Log.cs:344
Represents a content range in a ranged HTTP request or response.
long Last
Last byte of interval, inclusive.
Base class for components.
Definition: Component.cs:17
void RegisterIqSetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers an IQ-Set handler.
Definition: Component.cs:162
CaseInsensitiveString Subdomain
Subdomain name.
Definition: Component.cs:77
void RegisterIqGetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool PublishNamespaceAsFeature)
Registers an IQ-Get handler.
Definition: Component.cs:150
XmppServer Server
XMPP Server.
Definition: Component.cs:97
bool UnregisterIqGetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool RemoveNamespaceAsFeature)
Unregisters an IQ-Get handler.
Definition: Component.cs:250
bool UnregisterIqSetHandler(string LocalName, string Namespace, EventHandlerAsync< IqEventArgs > Handler, bool RemoveNamespaceAsFeature)
Unregisters an IQ-Set handler.
Definition: Component.cs:263
Information about a file upload.
Definition: FileInfo.cs:40
string Url
GET URL for uploaded file.
Definition: FileInfo.cs:69
string Key
Key authorizing access to file upload.
Definition: FileInfo.cs:54
string ContentType
Content-Type of uploaded content.
Definition: FileInfo.cs:59
CaseInsensitiveString Jid
JID uploading the file
Definition: FileInfo.cs:44
Implements HTTP File Upload support as an XMPP component: https://xmpp.org/extensions/xep-0363....
const string EncryptedStorageNamespace
http://waher.se/Schema/EncryptedStorage.xsd
override bool SupportsAccounts
If the component supports accounts (true), or if the subdomain name is the only valid address.
const string InternalTransferNamespace
http://waher.se/Schema/InternalTransfer.xsd
HttpFileUploadComponent(XmppServer Server, CaseInsensitiveString Subdomain, HttpFileUploadSettings Settings)
Implements HTTP File Upload support as an XMPP component: https://xmpp.org/extensions/xep-0363....
bool TryGetFile(string Resource, out string FilePath, out string ContentType, out FilePurpose Purpose)
Tries to get a file.
override Task AppendServiceDiscoveryFeatures(StringBuilder Xml, IqEventArgs e, string Node)
Component.AppendServiceDiscoveryFeatures(StringBuilder, IqEventArgs, string)
async Task< bool > DataUploaded(string Resource, string Key, Stream Data, ContentByteRangeInterval Interval, string ContentType, string RemoteEndPoint)
Attempts to put a file in the file folder.
override Task AppendServiceDiscoveryIdentities(StringBuilder Xml, IqEventArgs e, string Node)
Component.AppendServiceDiscoveryIdentities(StringBuilder, IqEventArgs, string)
Event arguments for IQ queries.
Definition: IqEventArgs.cs:12
XmppAddress From
From address attribute
Definition: IqEventArgs.cs:93
Task IqResult(string Xml, string From)
Returns a response to the current request.
Definition: IqEventArgs.cs:113
Task IqErrorResourceConstraint(XmppAddress From, string ErrorText, string Language)
Returns a resource-constraint error.
Definition: IqEventArgs.cs:178
XmlElement Query
Query element, if found, null otherwise.
Definition: IqEventArgs.cs:70
Task IqErrorNotAllowed(XmppAddress From, string ErrorText, string Language)
Returns a not-allowed error.
Definition: IqEventArgs.cs:192
XmppAddress To
To address attribute
Definition: IqEventArgs.cs:88
async Task IqError(string ErrorType, string Xml, XmppAddress From, string ErrorText, string Language)
Returns an error response to the current request.
Definition: IqEventArgs.cs:139
Task IqErrorConflict(XmppAddress From, string ErrorText, string Language)
Returns a conflict error.
Definition: IqEventArgs.cs:262
Task IqErrorBadRequest(XmppAddress From, string ErrorText, string Language)
Returns a bad-request error.
Definition: IqEventArgs.cs:164
Task IqErrorForbidden(XmppAddress From, string ErrorText, string Language)
Returns a forbidden error.
Definition: IqEventArgs.cs:234
override string ToString()
object.ToString()
Definition: XmppAddress.cs:190
CaseInsensitiveString Address
XMPP Address
Definition: XmppAddress.cs:37
bool IsDomain
If the Address is a domain.
Definition: XmppAddress.cs:175
CaseInsensitiveString BareJid
Bare JID
Definition: XmppAddress.cs:45
IXmppServerPersistenceLayer PersistenceLayer
Reference to persistence layer
Definition: XmppServer.cs:982
bool IsServerDomain(CaseInsensitiveString Domain, bool IncludeAlternativeDomains)
Checks if a domain is the server domain, or optionally, an alternative domain.
Definition: XmppServer.cs:898
string NewId(int NrBytes)
Generates a new ID.
Definition: XmppServer.cs:669
Represents a case-insensitive string.
string Value
String-representation of the case-insensitive string. (Representation is case sensitive....
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 ...
Implements an in-memory cache.
Definition: Cache.cs:17
void Dispose()
IDisposable.Dispose
Definition: Cache.cs:99
bool Remove(KeyType Key)
Removes an item from the cache.
Definition: Cache.cs:616
bool TryGetValue(KeyType Key, out ValueType Value)
Tries to get a value from the cache.
Definition: Cache.cs:311
void Add(KeyType Key, ValueType Value)
Adds an item to the cache.
Definition: Cache.cs:446
Event arguments for cache item removal events.
ValueType Value
Value of item that was removed.
Basic interface for Internet Content decoders. A class implementing this interface and having a defau...
Task< bool > IsPermitted(CaseInsensitiveString BareJid, string Setting)
Checks if a feature is permitted for a Bare JID.
Definition: ImplTypes.g.cs:58
FilePurpose
Purpose of file uploaded
Definition: FileInfo.cs:9
ContentType
DTLS Record content type.
Definition: Enumerations.cs:11