Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
StartExport.cs
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.IO.Compression;
5using System.Security.Cryptography;
6using System.Text;
7using System.Threading.Tasks;
8using System.Xml;
9using Waher.Content;
14using Waher.Events;
22
24{
29 {
30 internal static Aes aes = GetCryptoProvider();
31
35 public StartExport()
36 : base("/StartExport")
37 {
38 }
39
40 private static Aes GetCryptoProvider()
41 {
42 Aes Result = Aes.Create();
43
44 Result.BlockSize = 128;
45 Result.KeySize = 256;
46 Result.Mode = CipherMode.CBC;
47 Result.Padding = PaddingMode.None;
48
49 return Result;
50 }
51
55 public override bool HandlesSubPaths => false;
56
60 public override bool UserSessions => true;
61
65 public bool AllowsPOST => true;
66
73 public async Task POST(HttpRequest Request, HttpResponse Response)
74 {
75 try
76 {
77 Gateway.AssertUserAuthenticated(Request, "Admin.Data.Backup");
78
79 if (!Request.HasData || !(await Request.DecodeDataAsync() is Dictionary<string, object> RequestObj))
80 throw new UnsupportedMediaTypeException("Invalid request.");
81
82 if (!RequestObj.TryGetValue("TypeOfFile", out object Obj) || !(Obj is string TypeOfFile))
83 throw new BadRequestException("Missing: TypeOfFile");
84
85 if (!RequestObj.TryGetValue("Database", out Obj) || !(Obj is bool Database))
86 throw new BadRequestException("Missing: Database");
87
88 if (!RequestObj.TryGetValue("Ledger", out Obj) || !(Obj is bool Ledger))
89 Ledger = false;
90
91 if (!RequestObj.TryGetValue("WebContent", out Obj) || !(Obj is bool WebContent))
92 throw new BadRequestException("Missing: WebContent");
93
94 if (!RequestObj.TryGetValue("OnlySelectedCollections", out Obj) || !(Obj is bool OnlySelectedCollections))
95 throw new BadRequestException("Missing: OnlySelectedCollections");
96
97 if (!RequestObj.TryGetValue("selectedCollections", out Obj) || !(Obj is Array SelectedCollections))
98 throw new BadRequestException("Missing: selectedCollections");
99
100 if (!RequestObj.TryGetValue("exportOnly", out Obj) || !(Obj is bool ExportOnly))
101 throw new BadRequestException("Missing: exportOnly");
102
103 ExportInfo ExportInfo = await GetExporter(TypeOfFile, OnlySelectedCollections, SelectedCollections);
104 Task T;
105
106 lock (synchObject)
107 {
108 if (exporting)
109 {
110 Response.StatusCode = 409;
111 Response.StatusMessage = "Conflict";
112 Response.ContentType = PlainTextCodec.DefaultContentType;
113 T = Response.Write("Export is underway.");
114 }
115 else
116 {
117 exporting = true;
118 T = null;
119 }
120 }
121
122 if (!(T is null))
123 {
124 await T;
125 return;
126 }
127
128 if (!ExportOnly)
129 {
130 Export.ExportType = TypeOfFile;
131 Export.ExportDatabase = Database;
132 Export.ExportLedger = Ledger;
133 Export.ExportWebContent = WebContent;
134 }
135
136 List<string> Folders = new List<string>();
137
138 foreach (Export.FolderCategory FolderCategory in Export.GetRegisteredFolders())
139 {
140 if (RequestObj.TryGetValue(FolderCategory.CategoryId, out Obj) && Obj is bool b)
141 {
142 if (!ExportOnly)
143 await Export.SetExportFolderAsync(FolderCategory.CategoryId, b);
144
145 if (b)
146 Folders.AddRange(FolderCategory.Folders);
147 }
148 }
149
150 Task _ = DoExport(ExportInfo, Database, Ledger, WebContent, Folders.ToArray());
151
152 Response.StatusCode = 200;
153 Response.ContentType = PlainTextCodec.DefaultContentType;
154 await Response.Write(ExportInfo.LocalBackupFileName);
155 }
156 catch (Exception ex)
157 {
158 await Response.SendResponse(ex);
159 }
160 }
161
162 private static bool exporting = false;
163 private static readonly object synchObject = new object();
164
165 internal class ExportInfo
166 {
167 public string LocalBackupFileName;
168 public string LocalKeyFileName;
169 public string FullBackupFileName;
170 public string FullKeyFileName;
171 public IExportFormat Exporter;
172 }
173
174 internal static async Task<ExportInfo> GetExporter(string TypeOfFile, bool OnlySelectedCollections, Array SelectedCollections)
175 {
176 ExportInfo Result = new ExportInfo();
177 string BasePath = await Export.GetFullExportFolderAsync();
178
179 if (!Directory.Exists(BasePath))
180 Directory.CreateDirectory(BasePath);
181
182 BasePath += Path.DirectorySeparatorChar;
183
184 Result.FullBackupFileName = BasePath + DateTime.Now.ToString("yyyy-MM-dd HH_mm_ss");
185
186 switch (TypeOfFile)
187 {
188 case "XML":
189 Result.FullBackupFileName = GetUniqueFileName(Result.FullBackupFileName, ".xml");
190 FileStream fs = new FileStream(Result.FullBackupFileName, FileMode.Create, FileAccess.Write);
191 DateTime Created = File.GetCreationTime(Result.FullBackupFileName);
192 XmlWriterSettings Settings = XML.WriterSettings(true, false);
193 Settings.Async = true;
194 XmlWriter XmlOutput = XmlWriter.Create(fs, Settings);
195 Result.LocalBackupFileName = Result.FullBackupFileName.Substring(BasePath.Length);
196 Result.Exporter = new XmlExportFormat(Result.LocalBackupFileName, Created, XmlOutput, fs, OnlySelectedCollections, SelectedCollections);
197 break;
198
199 case "Binary":
200 Result.FullBackupFileName = GetUniqueFileName(Result.FullBackupFileName, ".bin");
201 fs = new FileStream(Result.FullBackupFileName, FileMode.Create, FileAccess.Write);
202 Created = File.GetCreationTime(Result.FullBackupFileName);
203 Result.LocalBackupFileName = Result.FullBackupFileName.Substring(BasePath.Length);
204 Result.Exporter = new BinaryExportFormat(Result.LocalBackupFileName, Created, fs, fs, OnlySelectedCollections, SelectedCollections);
205 break;
206
207 case "Compressed":
208 Result.FullBackupFileName = GetUniqueFileName(Result.FullBackupFileName, ".gz");
209 fs = new FileStream(Result.FullBackupFileName, FileMode.Create, FileAccess.Write);
210 Created = File.GetCreationTime(Result.FullBackupFileName);
211 Result.LocalBackupFileName = Result.FullBackupFileName.Substring(BasePath.Length);
212 GZipStream gz = new GZipStream(fs, CompressionLevel.Optimal, false);
213 Result.Exporter = new BinaryExportFormat(Result.LocalBackupFileName, Created, gz, fs, OnlySelectedCollections, SelectedCollections);
214 break;
215
216 case "Encrypted":
217 Result.FullBackupFileName = GetUniqueFileName(Result.FullBackupFileName, ".bak");
218 fs = new FileStream(Result.FullBackupFileName, FileMode.Create, FileAccess.Write);
219 Created = File.GetCreationTime(Result.FullBackupFileName);
220 Result.LocalBackupFileName = Result.FullBackupFileName.Substring(BasePath.Length);
221
222 byte[] Key = Gateway.NextBytes(32);
223 byte[] IV = Gateway.NextBytes(16);
224
225 ICryptoTransform AesTransform = aes.CreateEncryptor(Key, IV);
226 CryptoStream cs = new CryptoStream(fs, AesTransform, CryptoStreamMode.Write);
227
228 gz = new GZipStream(cs, CompressionLevel.Optimal, false);
229 Result.Exporter = new BinaryExportFormat(Result.LocalBackupFileName, Created, gz, fs, cs, 32, OnlySelectedCollections, SelectedCollections);
230
231 string BasePath2 = await Export.GetFullKeyExportFolderAsync();
232
233 if (!Directory.Exists(BasePath2))
234 Directory.CreateDirectory(BasePath2);
235
236 BasePath2 += Path.DirectorySeparatorChar;
237 Result.LocalKeyFileName = Result.LocalBackupFileName.Replace(".bak", ".key");
238 Result.FullKeyFileName = BasePath2 + Result.LocalKeyFileName;
239
240 using (XmlOutput = XmlWriter.Create(Result.FullKeyFileName, XML.WriterSettings(true, false)))
241 {
242 XmlOutput.WriteStartDocument();
243 XmlOutput.WriteStartElement("KeyAes256", XmlFileLedger.Namespace);
244 XmlOutput.WriteAttributeString("key", Convert.ToBase64String(Key));
245 XmlOutput.WriteAttributeString("iv", Convert.ToBase64String(IV));
246 XmlOutput.WriteEndElement();
247 XmlOutput.WriteEndDocument();
248 }
249
250 long Size;
251
252 try
253 {
254 using (fs = File.OpenRead(Result.FullKeyFileName))
255 {
256 Size = fs.Length;
257 }
258 }
259 catch (Exception ex)
260 {
261 Log.Exception(ex);
262 Size = 0;
263 }
264
265 Created = File.GetCreationTime(Result.FullKeyFileName);
266
267 ExportFormat.UpdateClientsFileUpdated(Result.LocalKeyFileName, Size, Created);
268 break;
269
270 default:
271 throw new NotSupportedException("Unsupported file type.");
272 }
273
274 return Result;
275 }
276
283 public static string GetUniqueFileName(string Base, string Extension)
284 {
285 string Suffix = string.Empty;
286 string s;
287 int i = 1;
288
289 while (true)
290 {
291 s = Base + Suffix + Extension;
292 if (!File.Exists(s))
293 return s;
294
295 i++;
296 Suffix = " (" + i.ToString() + ")";
297 }
298 }
299
308 internal static async Task DoExport(ExportInfo ExportInfo, bool Database, bool Ledger, bool WebContent, string[] Folders)
309 {
310 Profiler Profiler = new Profiler("Export", ProfilerThreadType.Sequential);
311 Profiler.Start();
312 Profiler.NewState("Start");
313
314 try
315 {
316 List<KeyValuePair<string, object>> Tags = new List<KeyValuePair<string, object>>()
317 {
318 new KeyValuePair<string, object>("Database", Database),
319 new KeyValuePair<string, object>("Ledger", Ledger)
320 };
321
322 foreach (string Folder in Folders)
323 Tags.Add(new KeyValuePair<string, object>(Folder, true));
324
325 Log.Informational("Starting export.", ExportInfo.Exporter.FileName, Tags.ToArray());
326
327 await ExportInfo.Exporter.Start();
328
329 if (Database)
330 {
331 Profiler.NewState("Database");
332
333 StringBuilder Temp = new StringBuilder();
334 string[] RepairedCollections;
335
336 using (XmlWriter w = XmlWriter.Create(Temp, XML.WriterSettings(true, true)))
337 {
338 RepairedCollections = await Persistence.Database.Analyze(w, Path.Combine(Gateway.AppDataFolder,
339 "Transforms", "DbStatXmlToHtml.xslt"), Path.Combine(Gateway.RootFolder, "Data"), false, true,
340 Profiler.CreateThread("Analyze", ProfilerThreadType.Sequential));
341 }
342
343 if (RepairedCollections.Length > 0)
344 {
345 string Xml = Temp.ToString();
346 string ReportFileName = Path.Combine(Path.GetDirectoryName(ExportInfo.FullBackupFileName),
347 "AutoRepair " + DateTime.Now.ToString("yyyy-MM-ddTHH.mm.ss.ffffff") + ".xml");
348 await Resources.WriteAllTextAsync(ReportFileName, Xml);
349 }
350
351 SortedDictionary<string, bool> CollectionsToExport = new SortedDictionary<string, bool>();
352
353 if (ExportInfo.Exporter.CollectionNames is null)
354 {
355 foreach (string Collection in await Persistence.Database.GetCollections())
356 CollectionsToExport[Collection] = true;
357 }
358 else
359 {
360 foreach (string Collection in ExportInfo.Exporter.CollectionNames)
361 CollectionsToExport[Collection] = true;
362 }
363
364 foreach (string Collection in Persistence.Database.GetExcludedCollections())
365 CollectionsToExport.Remove(Collection);
366
367 string[] ToExport = new string[CollectionsToExport.Count];
368 CollectionsToExport.Keys.CopyTo(ToExport, 0);
369
370 await Persistence.Database.Export(ExportInfo.Exporter, ToExport,
371 Profiler.CreateThread("Database", ProfilerThreadType.Sequential));
372 }
373
374 if (Ledger && Persistence.Ledger.HasProvider)
375 {
376 Profiler.NewState("Ledger");
377
379 {
380 CollectionNames = ExportInfo.Exporter.CollectionNames
381 };
382
383 await Persistence.Ledger.Export(ExportInfo.Exporter, Restricion,
384 Profiler.CreateThread("Ledger", ProfilerThreadType.Sequential));
385 }
386
387 if (WebContent || Folders.Length > 0)
388 {
389 Profiler.NewState("Files");
390
391 await ExportInfo.Exporter.StartFiles();
392 try
393 {
394 string[] FileNames;
395 string Folder2;
396
397 if (WebContent)
398 {
399 string ConfigFileName = Gateway.ConfigFilePath;
400 if (File.Exists(ConfigFileName))
401 await ExportFile(ConfigFileName, ExportInfo.Exporter);
402
403 FileNames = Directory.GetFiles(Gateway.RootFolder, "*.*", SearchOption.TopDirectoryOnly);
404
405 foreach (string FileName in FileNames)
406 await ExportFile(FileName, ExportInfo.Exporter);
407
409
410 foreach (string Folder in Directory.GetDirectories(Gateway.RootFolder, "*.*", SearchOption.TopDirectoryOnly))
411 {
412 bool IsWebContent = true;
413
414 foreach (Export.FolderCategory FolderCategory in ExportFolders)
415 {
416 foreach (string Folder3 in FolderCategory.Folders)
417 {
418 if (string.Compare(Folder3, Folder, true) == 0)
419 {
420 IsWebContent = false;
421 break;
422 }
423 }
424
425 if (!IsWebContent)
426 break;
427 }
428
429 if (IsWebContent)
430 {
431 FileNames = Directory.GetFiles(Folder, "*.*", SearchOption.AllDirectories);
432
433 foreach (string FileName in FileNames)
434 await ExportFile(FileName, ExportInfo.Exporter);
435 }
436 }
437 }
438
439 foreach (string Folder in Folders)
440 {
441 if (Directory.Exists(Folder2 = Path.Combine(Gateway.RootFolder, Folder)))
442 {
443 FileNames = Directory.GetFiles(Folder2, "*.*", SearchOption.AllDirectories);
444
445 foreach (string FileName in FileNames)
446 await ExportFile(FileName, ExportInfo.Exporter);
447 }
448 }
449 }
450 finally
451 {
452 await ExportInfo.Exporter.EndFiles();
453 }
454 }
455
456 Log.Informational("Export successfully completed.", ExportInfo.Exporter.FileName);
457 }
458 catch (Exception ex)
459 {
461
462 Log.Exception(ex);
463
464 string[] Tabs = ClientEvents.GetTabIDsForLocation("/Settings/Backup.md");
465 await ClientEvents.PushEvent(Tabs, "BackupFailed", "{\"fileName\":\"" + CommonTypes.JsonStringEncode(ExportInfo.Exporter.FileName) +
466 "\", \"message\": \"" + CommonTypes.JsonStringEncode(ex.Message) + "\"}", true, "User");
467 }
468 finally
469 {
470 Profiler.NewState("End");
471
472 try
473 {
474 await ExportInfo.Exporter.End();
475 ExportInfo.Exporter.Dispose();
476 }
477 catch (Exception ex)
478 {
480 Log.Exception(ex);
481 }
482
483 lock (synchObject)
484 {
485 exporting = false;
486 }
487
488 Profiler.NewState("Upload");
489
490 ProfilerThread Thread = Profiler.CreateThread("Upload", ProfilerThreadType.StateMachine);
491
492 await UploadBackupFile(ExportInfo.LocalBackupFileName, ExportInfo.FullBackupFileName, false, Thread);
493 if (!string.IsNullOrEmpty(ExportInfo.FullKeyFileName))
494 await UploadBackupFile(ExportInfo.LocalKeyFileName, ExportInfo.FullKeyFileName, true, Thread);
495
496 Profiler.Stop();
497
498 //string Uml = Profiler.ExportPlantUml(TimeUnit.DynamicPerProfiling);
499 //string UmlFileName = Path.ChangeExtension(ExportInfo.FullBackupFileName, "uml");
500 //long UmlFileSize;
501 //
502 //await Resources.WriteAllTextAsync(UmlFileName, Uml);
503 //
504 //using (FileStream fs = File.OpenRead(UmlFileName))
505 //{
506 // UmlFileSize = fs.Length;
507 //}
508 //
509 //ExportFormat.UpdateClientsFileUpdated(Path.ChangeExtension(ExportInfo.LocalBackupFileName, "uml"), UmlFileSize, DateTime.Now);
510 }
511 }
512
513 private static async Task<bool> ExportFile(string FileName, IExportFormat Output)
514 {
515 using (FileStream fs = File.OpenRead(FileName))
516 {
517 if (FileName.StartsWith(Gateway.AppDataFolder))
518 FileName = FileName.Substring(Gateway.AppDataFolder.Length);
519
520 if (!await Output.ExportFile(FileName, fs))
521 return false;
522 }
523
524 return await Output.UpdateClient(false);
525 }
526
527 private static Task UploadBackupFile(string LocalFileName, string FullFileName, bool IsKey, ProfilerThread Thread)
528 {
529 return UploadBackupFile(new BackupInfo()
530 {
531 LocalFileName = LocalFileName,
532 FullFileName = FullFileName,
533 IsKey = IsKey,
534 Thread = Thread,
535 Rescheduled = false
536 });
537 }
538
539 private class BackupInfo
540 {
541 public string LocalFileName;
542 public string FullFileName;
543 public bool IsKey;
544 public bool Rescheduled;
545 public Dictionary<string, bool> Recipients = null;
546 public ProfilerThread Thread;
547 }
548
549 private static async Task UploadBackupFile(object State)
550 {
551 BackupInfo BackupInfo = (BackupInfo)State;
552 bool Reschedule = false;
553 string Msg;
554
555 try
556 {
557 if (!File.Exists(BackupInfo.FullFileName))
558 {
559 Log.Warning(Msg = "Backup file has been removed. Upload cancelled.", BackupInfo.LocalFileName);
560
561 if (BackupInfo.Rescheduled)
562 await Gateway.SendNotification(Msg);
563
564 return;
565 }
566 else if (Gateway.XmppClient.State != XmppState.Connected)
567 Reschedule = true;
568 else
569 {
570 if (BackupInfo.Recipients is null)
571 {
572 BackupInfo.Recipients = new Dictionary<string, bool>();
573
574 string[] Hosts = await Export.GetKeyHostsAsync();
575
576 if (BackupInfo.IsKey && !(Hosts is null))
577 {
578 foreach (string Host in Hosts)
579 BackupInfo.Recipients[Host] = false;
580 }
581
582 Hosts = await Export.GetBackupHostsAsync();
583
584 if (!BackupInfo.IsKey && !(Hosts is null))
585 {
586 foreach (string Host in Hosts)
587 BackupInfo.Recipients[Host] = false;
588 }
589 }
590
591 LinkedList<string> Recipients = new LinkedList<string>();
592 string Recipient;
593
594 foreach (KeyValuePair<string, bool> P in BackupInfo.Recipients)
595 {
596 if (!P.Value)
597 Recipients.AddLast(P.Key);
598 }
599
600 while (!((Recipient = Recipients.First?.Value) is null))
601 {
602 Recipients.RemoveFirst();
603
604 if (Recipient.IndexOf('@') >= 0)
605 {
606 RosterItem Item = Gateway.XmppClient[Recipient];
607 if (Item is null)
608 continue;
609
610 if (!Item.HasLastPresence || !Item.LastPresence.IsOnline)
611 {
612 Reschedule = true;
613 continue;
614 }
615 }
616
617 try
618 {
619 BackupInfo.Thread?.NewState("Discover_" + Recipient);
620
621 using (HttpFileUploadClient UploadClient = new HttpFileUploadClient(Gateway.XmppClient, Recipient, null))
622 {
623 await UploadClient.DiscoverAsync(Recipient);
624
625 if (UploadClient.HasSupport)
626 {
627 using (FileStream fs = File.OpenRead(BackupInfo.FullFileName))
628 {
629 BackupInfo.Thread?.NewState("Prepare_" + Recipient);
630
631 StringBuilder Xml = new StringBuilder();
632 long FileSize = fs.Length;
633
634 Xml.Append("<prepare xmlns='http://waher.se/Schema/Backups.xsd' filename='");
635 Xml.Append(XML.Encode(BackupInfo.LocalFileName));
636 Xml.Append("' size='");
637 Xml.Append(FileSize.ToString());
638 Xml.Append("' content-type='application/octet-stream'/>");
639
640 BackupInfo.Thread?.NewState("Get_Slot_" + Recipient);
641
642 await UploadClient.Client.IqSetAsync(UploadClient.FileUploadJid, Xml.ToString());
643 // Empty response expected. Errors cause an exception to be raised.
644
645 HttpFileUploadEventArgs e2 = await UploadClient.RequestUploadSlotAsync(BackupInfo.LocalFileName,
646 BinaryCodec.DefaultContentType, FileSize, false);
647
648 if (!e2.Ok)
649 throw (e2.StanzaError ?? new XmppException("Unable to get HTTP upload slot for backup file."));
650
651 BackupInfo.Thread?.NewState("Upload_" + Recipient);
652
653 if (BackupInfo.IsKey)
654 Log.Informational("Uploading key file to " + Recipient + ".", BackupInfo.LocalFileName);
655 else
656 Log.Informational("Uploading backup file to " + Recipient + ".", BackupInfo.LocalFileName);
657
658 await e2.PUT(fs, BinaryCodec.DefaultContentType, 60 * 60 * 1000); // 1h timeout
659
660 if (BackupInfo.IsKey)
661 Log.Informational("Key file uploaded to " + Recipient + ".", BackupInfo.LocalFileName);
662 else
663 Log.Informational("Backup file uploaded to " + Recipient + ".", BackupInfo.LocalFileName);
664 }
665 }
666 }
667 }
668 catch (Exception ex)
669 {
670 BackupInfo.Thread?.Exception(ex, BackupInfo.LocalFileName);
671 Log.Exception(ex);
672 Reschedule = true;
673
674 await Gateway.SendNotification("Unable to upload backup to " + MarkdownDocument.Encode(Recipient) +
675 ".\r\n\r\n" + MarkdownDocument.Encode(ex.Message));
676 }
677 }
678 }
679 }
680 catch (Exception ex)
681 {
682 BackupInfo.Thread?.Exception(ex);
683 Log.Exception(ex);
684 Reschedule = true;
685 }
686 finally
687 {
688 if (Reschedule)
689 {
690 BackupInfo.Thread?.NewState("Reschedule");
691 BackupInfo.Rescheduled = true;
692
693 Gateway.ScheduleEvent(UploadBackupFile, DateTime.Now.AddMinutes(15), BackupInfo);
694 }
695 else if (BackupInfo.Rescheduled)
696 {
697 await Gateway.SendNotification("Backup file has been successfully been uploaded. The initial attempt to upload the backup file failed, but a sequent rescheduled upload succeeded.");
698 BackupInfo.Rescheduled = false;
699 }
700
701 BackupInfo.Thread = null;
702 }
703 }
704
705 }
706}
const string DefaultContentType
text/plain
Definition: BinaryCodec.cs:24
Helps with parsing of commong data types.
Definition: CommonTypes.cs:13
static string JsonStringEncode(string s)
Encodes a string for inclusion in JSON.
Definition: CommonTypes.cs:803
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 ...
Static class managing loading of resources stored as embedded resources or in content files.
Definition: Resources.cs:15
static Task WriteAllTextAsync(string FileName, string Text)
Creates a text file asynchronously.
Definition: Resources.cs:267
Plain text encoder/decoder.
const string DefaultContentType
text/plain
Helps with common XML-related tasks.
Definition: XML.cs:19
static string Encode(string s)
Encodes a string for use in XML.
Definition: XML.cs:27
static XmlWriterSettings WriterSettings(bool Indent, bool OmitXmlDeclaration)
Gets an XML writer settings object.
Definition: XML.cs:1177
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:13
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:1647
static void Warning(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs a warning event.
Definition: Log.cs:566
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:334
The ClientEvents class allows applications to push information asynchronously to web clients connecte...
Definition: ClientEvents.cs:51
static string[] GetTabIDsForLocation(string Location)
Gets the Tab IDs of all tabs that display a particular resource.
static Task< int > PushEvent(string[] TabIDs, string Type, object Data)
Puses an event to a set of Tabs, given their Tab IDs.
Information about an exportable folder category
Definition: Export.cs:560
Static class managing data export.
Definition: Export.cs:19
static async Task< string[]> GetKeyHostsAsync()
Secondary key hosts.
Definition: Export.cs:608
static async Task< string > GetFullExportFolderAsync()
Full path to export folder.
Definition: Export.cs:23
static FolderCategory[] GetRegisteredFolders()
Gets registered exportable folders.
Definition: Export.cs:543
static async Task< string > GetFullKeyExportFolderAsync()
Full path to key folder.
Definition: Export.cs:36
static async Task< string[]> GetBackupHostsAsync()
Secondary backup hosts.
Definition: Export.cs:582
static async Task SetExportFolderAsync(string Value)
Export folder.
Definition: Export.cs:159
Static class managing the runtime environment of the IoT Gateway.
Definition: Gateway.cs:126
static IUser AssertUserAuthenticated(HttpRequest Request, string Privilege)
Makes sure a request is being made from a session with a successful user login.
Definition: Gateway.cs:3041
static string ConfigFilePath
Full path to Gateway.config file.
Definition: Gateway.cs:2413
static byte[] NextBytes(int NrBytes)
Generates an array of random bytes.
Definition: Gateway.cs:3534
static string AppDataFolder
Application data folder.
Definition: Gateway.cs:2369
static Task SendNotification(Graph Graph)
Sends a graph as a notification message to configured notification recipients.
Definition: Gateway.cs:3826
static DateTime ScheduleEvent(ScheduledEventCallback Callback, DateTime When, object State)
Schedules a one-time event.
Definition: Gateway.cs:3452
static XmppClient XmppClient
XMPP Client connection of gateway.
Definition: Gateway.cs:3187
static string RootFolder
Web root folder.
Definition: Gateway.cs:2379
Abstract base class for export formats.
Definition: ExportFormat.cs:14
static void UpdateClientsFileUpdated(string FileName, long Length, DateTime Created)
Updates the status of a file on all pages viewing backup files
async Task POST(HttpRequest Request, HttpResponse Response)
Executes the POST method on the resource.
Definition: StartExport.cs:73
static string GetUniqueFileName(string Base, string Extension)
Gets a unique filename.
Definition: StartExport.cs:283
override bool UserSessions
If the resource uses user sessions.
Definition: StartExport.cs:60
override bool HandlesSubPaths
If the resource handles sub-paths.
Definition: StartExport.cs:55
bool AllowsPOST
If the POST method is allowed.
Definition: StartExport.cs:65
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repe...
Represents an HTTP request.
Definition: HttpRequest.cs:18
bool HasData
If the request has data.
Definition: HttpRequest.cs:74
async Task< object > DecodeDataAsync()
Decodes data sent in request.
Definition: HttpRequest.cs:95
Represets a response of an HTTP client request.
Definition: HttpResponse.cs:21
async Task SendResponse()
Sends the response back to the client. If the resource is synchronous, there's no need to call this m...
async Task Write(byte[] Data)
Returns binary data in the response.
Base class for all synchronous HTTP resources. A synchronous resource responds within the method hand...
The server is refusing to service the request because the entity of the request is in a format not su...
bool Ok
If the response is an OK result response (true), or an error response (false).
XmppException StanzaError
Any stanza error returned.
Class managing HTTP File uploads, as defined in XEP-0363.
Task DiscoverAsync()
Searches for HTTP File Upload support on the current broker.
Task< HttpFileUploadEventArgs > RequestUploadSlotAsync(string FileName, string ContentType, long ContentSize)
Uploads a file to the upload component.
string FileUploadJid
JID of HTTP File Upload component.
Event arguments for HTTP File Upload callback methods.
async Task PUT(byte[] Content, string ContentType, int Timeout)
Uploads file content to the server.
Maintains information about an item in the roster.
Definition: RosterItem.cs:75
bool HasLastPresence
If the roster item has received presence from an online resource having the given bare JID.
Definition: RosterItem.cs:425
PresenceEventArgs LastPresence
Last presence received from a resource having this bare JID.
Definition: RosterItem.cs:356
XmppState State
Current state of connection.
Definition: XmppClient.cs:985
async Task< XmlElement > IqSetAsync(string To, string Xml)
Performs an asynchronous IQ Set request/response operation.
Definition: XmppClient.cs:4064
Base class of XMPP exceptions
XmppClient Client
XMPP Client.
Static interface for database persistence. In order to work, a database provider has to be assigned t...
Definition: Database.cs:19
Contains basic ledger export restrictions.
Static interface for ledger persistence. In order to work, a ledger provider has to be assigned to it...
Definition: Ledger.cs:14
static bool HasProvider
If a ledger provider is registered.
Definition: Ledger.cs:105
Simple ledger that records anything that happens in the database to XML files in the program data fol...
const string Namespace
http://waher.se/Schema/Export.xsd
Class that keeps track of events and timing.
Definition: Profiler.cs:67
void Stop()
Stops measuring time.
Definition: Profiler.cs:210
ProfilerThread CreateThread(string Name, ProfilerThreadType Type)
Creates a new profiler thread.
Definition: Profiler.cs:127
void NewState(string State)
Main Thread changes state.
Definition: Profiler.cs:247
void Exception(System.Exception Exception)
Event occurred on main thread
Definition: Profiler.cs:330
void Start()
Starts measuring time.
Definition: Profiler.cs:200
Class that keeps track of events and timing for one thread.
Task< bool > ExportFile(string FileName, Stream File)
Export file.
Task< bool > UpdateClient(bool ForceUpdate)
If any clients should be updated about export status.
POST Interface for HTTP resources.
XmppState
State of XMPP connection.
Definition: XmppState.cs:7
ProfilerThreadType
Type of profiler thread.