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;
3using System.IO;
4using System.IO.Compression;
6using System.Text;
7using System.Threading.Tasks;
8using System.Xml;
9using Waher.Content;
15using Waher.Events;
25
27{
32 {
33 internal static Aes aes = GetCryptoProvider();
34
38 public StartExport()
39 : base("/StartExport")
40 {
41 }
42
43 private static Aes GetCryptoProvider()
44 {
45 Aes Result = Aes.Create();
46
47 Result.BlockSize = 128;
48 Result.KeySize = 256;
49 Result.Mode = CipherMode.CBC;
50 Result.Padding = PaddingMode.None;
51
52 return Result;
53 }
54
58 public override bool HandlesSubPaths => false;
59
63 public override bool UserSessions => true;
64
68 public bool AllowsPOST => true;
69
76 public async Task POST(HttpRequest Request, HttpResponse Response)
77 {
78 try
79 {
80 Gateway.AssertUserAuthenticated(Request, "Admin.Data.Backup");
81
82 if (!Request.HasData)
83 {
84 await Response.SendResponse(new UnsupportedMediaTypeException("Invalid request."));
85 return;
86 }
87
88 ContentResponse Content = await Request.DecodeDataAsync();
89 if (Content.HasError || !(Content.Decoded is Dictionary<string, object> RequestObj))
90 {
91 await Response.SendResponse(new UnsupportedMediaTypeException("Invalid request."));
92 return;
93 }
94
95 if (!RequestObj.TryGetValue("TypeOfFile", out object Obj) || !(Obj is string TypeOfFile))
96 {
97 await Response.SendResponse(new BadRequestException("Missing: TypeOfFile"));
98 return;
99 }
100
101 if (!RequestObj.TryGetValue("Database", out Obj) || !(Obj is bool Database))
102 {
103 await Response.SendResponse(new BadRequestException("Missing: Database"));
104 return;
105 }
106
107 if (!RequestObj.TryGetValue("Ledger", out Obj) || !(Obj is bool Ledger))
108 Ledger = false;
109
110 if (!RequestObj.TryGetValue("WebContent", out Obj) || !(Obj is bool WebContent))
111 {
112 await Response.SendResponse(new BadRequestException("Missing: WebContent"));
113 return;
114 }
115
116 if (!RequestObj.TryGetValue("OnlySelectedCollections", out Obj) || !(Obj is bool OnlySelectedCollections))
117 {
118 await Response.SendResponse(new BadRequestException("Missing: OnlySelectedCollections"));
119 return;
120 }
121
122 if (!RequestObj.TryGetValue("selectedCollections", out Obj) || !(Obj is Array SelectedCollections))
123 {
124 await Response.SendResponse(new BadRequestException("Missing: selectedCollections"));
125 return;
126 }
127
128 if (!RequestObj.TryGetValue("exportOnly", out Obj) || !(Obj is bool ExportOnly))
129 {
130 await Response.SendResponse(new BadRequestException("Missing: exportOnly"));
131 return;
132 }
133
134 ExportInfo ExportInfo = await GetExporter(TypeOfFile, OnlySelectedCollections, SelectedCollections);
135 Task T;
136
137 lock (synchObject)
138 {
139 if (exporting)
140 {
141 Response.StatusCode = 409;
142 Response.StatusMessage = "Conflict";
143 Response.ContentType = PlainTextCodec.DefaultContentType;
144 T = Response.Write("Export is underway.");
145 }
146 else
147 {
148 exporting = true;
149 T = null;
150 }
151 }
152
153 if (!(T is null))
154 {
155 await T;
156 return;
157 }
158
159 if (!ExportOnly)
160 {
161 Export.ExportType = TypeOfFile;
162 Export.ExportDatabase = Database;
163 Export.ExportLedger = Ledger;
164 Export.ExportWebContent = WebContent;
165 }
166
167 List<string> Folders = new List<string>();
168
169 foreach (Export.FolderCategory FolderCategory in Export.GetRegisteredFolders())
170 {
171 if (RequestObj.TryGetValue(FolderCategory.CategoryId, out Obj) && Obj is bool b)
172 {
173 if (!ExportOnly)
174 await Export.SetExportFolderAsync(FolderCategory.CategoryId, b);
175
176 if (b)
177 Folders.AddRange(FolderCategory.Folders);
178 }
179 }
180
181 Task _ = DoExport(ExportInfo, Database, Ledger, WebContent, Folders.ToArray());
182
183 Response.StatusCode = 200;
184 Response.StatusMessage = "OK";
185 Response.ContentType = PlainTextCodec.DefaultContentType;
186
187 await Response.Write(ExportInfo.LocalBackupFileName);
188 }
189 catch (Exception ex)
190 {
191 await Response.SendResponse(ex);
192 }
193 }
194
195 private static bool exporting = false;
196 private static readonly object synchObject = new object();
197
198 internal class ExportInfo
199 {
200 public string LocalBackupFileName;
201 public string LocalKeyFileName;
202 public string FullBackupFileName;
203 public string FullKeyFileName;
204 public string ContentType;
205 public IExportFormat Exporter;
206 }
207
208 internal static async Task<ExportInfo> GetExporter(string TypeOfFile, bool OnlySelectedCollections, Array SelectedCollections)
209 {
210 ExportInfo Result = new ExportInfo();
211 string BasePath = await Export.GetFullExportFolderAsync();
212
213 if (!Directory.Exists(BasePath))
214 Directory.CreateDirectory(BasePath);
215
216 BasePath += Path.DirectorySeparatorChar;
217
218 Result.FullBackupFileName = BasePath + DateTime.Now.ToString("yyyy-MM-dd HH_mm_ss");
219
220 switch (TypeOfFile)
221 {
222 case "XML":
223 Result.FullBackupFileName = await GetUniqueFileName(Result.FullBackupFileName, ".xml");
224 Result.ContentType = XmlCodec.DefaultContentType;
225 FileStream fs = new FileStream(Result.FullBackupFileName, FileMode.Create, FileAccess.Write);
226 DateTime Created = File.GetCreationTime(Result.FullBackupFileName);
227 XmlWriterSettings Settings = XML.WriterSettings(true, false);
228 Settings.Async = true;
229 XmlWriter XmlOutput = XmlWriter.Create(fs, Settings);
230 Result.LocalBackupFileName = Result.FullBackupFileName[BasePath.Length..];
231 Result.Exporter = new XmlExportFormat(Result.LocalBackupFileName, Created, XmlOutput, fs, OnlySelectedCollections, SelectedCollections);
232 break;
233
234 case "Binary":
235 Result.FullBackupFileName = await GetUniqueFileName(Result.FullBackupFileName, ".bin");
236 Result.ContentType = BinaryCodec.DefaultContentType;
237 fs = new FileStream(Result.FullBackupFileName, FileMode.Create, FileAccess.Write);
238 Created = File.GetCreationTime(Result.FullBackupFileName);
239 Result.LocalBackupFileName = Result.FullBackupFileName[BasePath.Length..];
240 Result.Exporter = new BinaryExportFormat(Result.LocalBackupFileName, Created, fs, fs, OnlySelectedCollections, SelectedCollections);
241 break;
242
243 case "Compressed":
244 Result.FullBackupFileName = await GetUniqueFileName(Result.FullBackupFileName, ".gz");
245 Result.ContentType = "application/gzip";
246 fs = new FileStream(Result.FullBackupFileName, FileMode.Create, FileAccess.Write);
247 Created = File.GetCreationTime(Result.FullBackupFileName);
248 Result.LocalBackupFileName = Result.FullBackupFileName[BasePath.Length..];
249 GZipStream gz = new GZipStream(fs, CompressionLevel.Optimal, false);
250 Result.Exporter = new BinaryExportFormat(Result.LocalBackupFileName, Created, gz, fs, OnlySelectedCollections, SelectedCollections);
251 break;
252
253 case "Encrypted":
254 Result.FullBackupFileName = await GetUniqueFileName(Result.FullBackupFileName, ".bak");
255 Result.ContentType = BinaryCodec.DefaultContentType;
256 fs = new FileStream(Result.FullBackupFileName, FileMode.Create, FileAccess.Write);
257 Created = File.GetCreationTime(Result.FullBackupFileName);
258 Result.LocalBackupFileName = Result.FullBackupFileName[BasePath.Length..];
259
260 byte[] Key = Gateway.NextBytes(32);
261 byte[] IV = Gateway.NextBytes(16);
262
263 ICryptoTransform AesTransform = aes.CreateEncryptor(Key, IV);
264 CryptoStream cs = new CryptoStream(fs, AesTransform, CryptoStreamMode.Write);
265
266 gz = new GZipStream(cs, CompressionLevel.Optimal, false);
267 Result.Exporter = new BinaryExportFormat(Result.LocalBackupFileName, Created, gz, fs, cs, 32, OnlySelectedCollections, SelectedCollections);
268
269 string BasePath2 = await Export.GetFullKeyExportFolderAsync();
270
271 if (!Directory.Exists(BasePath2))
272 Directory.CreateDirectory(BasePath2);
273
274 BasePath2 += Path.DirectorySeparatorChar;
275 Result.LocalKeyFileName = Result.LocalBackupFileName.Replace(".bak", ".key");
276 Result.FullKeyFileName = BasePath2 + Result.LocalKeyFileName;
277
278 using (XmlOutput = XmlWriter.Create(Result.FullKeyFileName, XML.WriterSettings(true, false)))
279 {
280 XmlOutput.WriteStartDocument();
281 XmlOutput.WriteStartElement("KeyAes256", XmlFileLedger.Namespace);
282 XmlOutput.WriteAttributeString("key", Convert.ToBase64String(Key));
283 XmlOutput.WriteAttributeString("iv", Convert.ToBase64String(IV));
284 XmlOutput.WriteEndElement();
285 XmlOutput.WriteEndDocument();
286 }
287
288 long Size;
289
290 try
291 {
292 using (fs = File.OpenRead(Result.FullKeyFileName))
293 {
294 Size = fs.Length;
295 }
296 }
297 catch (Exception ex)
298 {
299 Log.Exception(ex);
300 Size = 0;
301 }
302
303 Created = File.GetCreationTime(Result.FullKeyFileName);
304
305 ExportFormat.UpdateClientsFileUpdated(Result.LocalKeyFileName, Size, Created);
306 break;
307
308 default:
309 throw new NotSupportedException("Unsupported file type.");
310 }
311
312 return Result;
313 }
314
321 public static async Task<string> GetUniqueFileName(string Base, string Extension)
322 {
323 using Semaphore Semaphore = await Semaphores.BeginWrite("Export." + Base);
324 string Suffix = string.Empty;
325 string s;
326 int i = 1;
327
328 while (true)
329 {
330 s = Base + Suffix + Extension;
331 if (!File.Exists(s))
332 return s;
333
334 i++;
335 Suffix = " (" + i.ToString() + ")";
336 }
337 }
338
347 internal static async Task DoExport(ExportInfo ExportInfo, bool Database, bool Ledger, bool WebContent, string[] Folders)
348 {
349 Profiler Profiler = new Profiler("Export", ProfilerThreadType.Sequential);
350 Profiler.Start();
351 Profiler.NewState("Start");
352
353 try
354 {
355 List<KeyValuePair<string, object>> Tags = new List<KeyValuePair<string, object>>()
356 {
357 new KeyValuePair<string, object>("Database", Database),
358 new KeyValuePair<string, object>("Ledger", Ledger)
359 };
360
361 foreach (string Folder in Folders)
362 Tags.Add(new KeyValuePair<string, object>(Folder, true));
363
364 Log.Informational("Starting export.", ExportInfo.Exporter.FileName, Tags.ToArray());
365
366 await ExportInfo.Exporter.Start();
367
368 if (Database)
369 {
370 Profiler.NewState("Database");
371
372 StringBuilder Temp = new StringBuilder();
373 string[] RepairedCollections;
374
375 using (XmlWriter w = XmlWriter.Create(Temp, XML.WriterSettings(true, true)))
376 {
377 RepairedCollections = await Persistence.Database.Analyze(w, Path.Combine(Gateway.AppDataFolder,
378 "Transforms", "DbStatXmlToHtml.xslt"), Path.Combine(Gateway.RootFolder, "Data"), false, true,
379 Profiler.CreateThread("Analyze", ProfilerThreadType.Sequential));
380 }
381
382 if (RepairedCollections.Length > 0)
383 {
384 string Xml = Temp.ToString();
385 string ReportFileName = Path.Combine(Path.GetDirectoryName(ExportInfo.FullBackupFileName),
386 "AutoRepair " + DateTime.Now.ToString("yyyy-MM-ddTHH.mm.ss.ffffff") + ".xml");
387 await Files.WriteAllTextAsync(ReportFileName, Xml);
388 }
389
390 SortedDictionary<string, bool> CollectionsToExport = new SortedDictionary<string, bool>();
391
392 if (ExportInfo.Exporter.CollectionNames is null)
393 {
394 foreach (string Collection in await Persistence.Database.GetCollections())
395 CollectionsToExport[Collection] = true;
396 }
397 else
398 {
399 foreach (string Collection in ExportInfo.Exporter.CollectionNames)
400 CollectionsToExport[Collection] = true;
401 }
402
403 foreach (string Collection in Persistence.Database.GetExcludedCollections())
404 CollectionsToExport.Remove(Collection);
405
406 string[] ToExport = new string[CollectionsToExport.Count];
407 CollectionsToExport.Keys.CopyTo(ToExport, 0);
408
409 await Persistence.Database.Export(ExportInfo.Exporter, ToExport,
410 Profiler.CreateThread("Database", ProfilerThreadType.Sequential));
411 }
412
413 if (Ledger && Persistence.Ledger.HasProvider)
414 {
415 Profiler.NewState("Ledger");
416
418 {
419 CollectionNames = ExportInfo.Exporter.CollectionNames
420 };
421
422 await Persistence.Ledger.Export(ExportInfo.Exporter, Restricion,
423 Profiler.CreateThread("Ledger", ProfilerThreadType.Sequential));
424 }
425
426 if (WebContent || Folders.Length > 0)
427 {
428 Profiler.NewState("Files");
429
430 await ExportInfo.Exporter.StartFiles();
431 try
432 {
433 string[] FileNames;
434 string Folder2;
435
436 if (WebContent)
437 {
438 string ConfigFileName = Gateway.ConfigFilePath;
439 if (File.Exists(ConfigFileName))
440 await ExportFile(ConfigFileName, ExportInfo.Exporter);
441
442 FileNames = Directory.GetFiles(Gateway.RootFolder, "*.*", SearchOption.TopDirectoryOnly);
443
444 foreach (string FileName in FileNames)
445 await ExportFile(FileName, ExportInfo.Exporter);
446
448
449 foreach (string Folder in Directory.GetDirectories(Gateway.RootFolder, "*.*", SearchOption.TopDirectoryOnly))
450 {
451 bool IsWebContent = true;
452
453 foreach (Export.FolderCategory FolderCategory in ExportFolders)
454 {
455 foreach (string Folder3 in FolderCategory.Folders)
456 {
457 if (string.Compare(Folder3, Folder, true) == 0)
458 {
459 IsWebContent = false;
460 break;
461 }
462 }
463
464 if (!IsWebContent)
465 break;
466 }
467
468 if (IsWebContent)
469 {
470 FileNames = Directory.GetFiles(Folder, "*.*", SearchOption.AllDirectories);
471
472 foreach (string FileName in FileNames)
473 await ExportFile(FileName, ExportInfo.Exporter);
474 }
475 }
476 }
477
478 foreach (string Folder in Folders)
479 {
480 if (Directory.Exists(Folder2 = Path.Combine(Gateway.RootFolder, Folder)))
481 {
482 FileNames = Directory.GetFiles(Folder2, "*.*", SearchOption.AllDirectories);
483
484 foreach (string FileName in FileNames)
485 await ExportFile(FileName, ExportInfo.Exporter);
486 }
487 }
488 }
489 finally
490 {
491 await ExportInfo.Exporter.EndFiles();
492 }
493 }
494
495 Log.Informational("Export successfully completed.", ExportInfo.Exporter.FileName);
496 }
497 catch (Exception ex)
498 {
500
501 Log.Exception(ex);
502
503 string[] Tabs = ClientEvents.GetTabIDsForLocation("/Settings/Backup.md");
504 await ClientEvents.PushEvent(Tabs, "BackupFailed", "{\"fileName\":\"" + CommonTypes.JsonStringEncode(ExportInfo.Exporter.FileName) +
505 "\", \"message\": \"" + CommonTypes.JsonStringEncode(ex.Message) + "\"}", true, "User");
506 }
507 finally
508 {
509 Profiler.NewState("End");
510
511 try
512 {
513 await ExportInfo.Exporter.End();
514 ExportInfo.Exporter.Dispose();
515 }
516 catch (Exception ex)
517 {
519 Log.Exception(ex);
520 }
521
522 lock (synchObject)
523 {
524 exporting = false;
525 }
526
527 Profiler.NewState("Upload");
528
529 ProfilerThread Thread = Profiler.CreateThread("Upload", ProfilerThreadType.StateMachine);
530
531 await UploadBackupFile(ExportInfo.LocalBackupFileName,
532 ExportInfo.FullBackupFileName, ExportInfo.ContentType,
533 false, Thread);
534
535 if (!string.IsNullOrEmpty(ExportInfo.FullKeyFileName))
536 {
537 await UploadBackupFile(ExportInfo.LocalKeyFileName,
538 ExportInfo.FullKeyFileName, ExportInfo.ContentType,
539 true, Thread);
540 }
541
542 Profiler.Stop();
543
544 //string Uml = Profiler.ExportPlantUml(TimeUnit.DynamicPerProfiling);
545 //string UmlFileName = Path.ChangeExtension(ExportInfo.FullBackupFileName, "uml");
546 //long UmlFileSize;
547 //
548 //await Files.WriteAllTextAsync(UmlFileName, Uml);
549 //
550 //using (FileStream fs = File.OpenRead(UmlFileName))
551 //{
552 // UmlFileSize = fs.Length;
553 //}
554 //
555 //ExportFormat.UpdateClientsFileUpdated(Path.ChangeExtension(ExportInfo.LocalBackupFileName, "uml"), UmlFileSize, DateTime.Now);
556 }
557 }
558
559 private static async Task<bool> ExportFile(string FileName, IExportFormat Output)
560 {
561 using (FileStream fs = File.OpenRead(FileName))
562 {
563 if (FileName.StartsWith(Gateway.AppDataFolder))
564 FileName = FileName[Gateway.AppDataFolder.Length..];
565
566 if (!await Output.ExportFile(FileName, fs))
567 return false;
568 }
569
570 return await Output.UpdateClient(false);
571 }
572
573 private static Task UploadBackupFile(string LocalFileName, string FullFileName,
574 string ContentType, bool IsKey, ProfilerThread Thread)
575 {
576 return UploadBackupFile(new BackupInfo()
577 {
578 LocalFileName = LocalFileName,
579 FullFileName = FullFileName,
581 IsKey = IsKey,
582 Thread = Thread,
583 Rescheduled = false
584 });
585 }
586
587 private class BackupInfo
588 {
589 public string LocalFileName;
590 public string FullFileName;
591 public string ContentType;
592 public bool IsKey;
593 public bool Rescheduled;
594 public Dictionary<string, bool> Recipients = null;
595 public ProfilerThread Thread;
596 }
597
598 private static async Task UploadBackupFile(object State)
599 {
600 BackupInfo BackupInfo = (BackupInfo)State;
601 bool Reschedule = false;
602 string Msg;
603
604 try
605 {
606 if (!File.Exists(BackupInfo.FullFileName))
607 {
608 Log.Warning(Msg = "Backup file has been removed. Upload cancelled.", BackupInfo.LocalFileName);
609
610 if (BackupInfo.Rescheduled)
611 await Gateway.SendNotification(Msg);
612
613 return;
614 }
615 else if (Gateway.XmppClient is null || Gateway.XmppClient.State != XmppState.Connected)
616 Reschedule = true;
617 else
618 {
619 if (BackupInfo.Recipients is null)
620 {
621 BackupInfo.Recipients = new Dictionary<string, bool>();
622
623 string[] Hosts = await Export.GetKeyHostsAsync();
624
625 if (BackupInfo.IsKey && !(Hosts is null))
626 {
627 foreach (string Host in Hosts)
628 BackupInfo.Recipients[Host] = false;
629 }
630
631 Hosts = await Export.GetBackupHostsAsync();
632
633 if (!BackupInfo.IsKey && !(Hosts is null))
634 {
635 foreach (string Host in Hosts)
636 BackupInfo.Recipients[Host] = false;
637 }
638 }
639
640 LinkedList<string> Recipients = new LinkedList<string>();
641 string Recipient;
642
643 foreach (KeyValuePair<string, bool> P in BackupInfo.Recipients)
644 {
645 if (!P.Value)
646 Recipients.AddLast(P.Key);
647 }
648
649 while (!((Recipient = Recipients.First?.Value) is null))
650 {
651 Recipients.RemoveFirst();
652
653 if (Recipient.IndexOf('@') >= 0)
654 {
655 RosterItem Item = Gateway.XmppClient[Recipient];
656 if (Item is null)
657 continue;
658
659 if (!Item.HasLastPresence || !Item.LastPresence.IsOnline)
660 {
661 Reschedule = true;
662 continue;
663 }
664 }
665
666 try
667 {
668 BackupInfo.Thread?.NewState("Discover_" + Recipient);
669
670 using HttpFileUploadClient UploadClient = new HttpFileUploadClient(Gateway.XmppClient, Recipient, null);
671
672 await UploadClient.DiscoverAsync(Recipient);
673
674 if (UploadClient.HasSupport)
675 {
676 using FileStream fs = File.OpenRead(BackupInfo.FullFileName);
677 long FileSize = fs.Length;
678
679 BackupInfo.Thread?.NewState("Prepare_" + Recipient);
680
681 await UploadClient.PrepareFileUpload(BackupInfo.LocalFileName,
682 BackupInfo.ContentType, FileSize, FilePurpose.Backup);
683
684 BackupInfo.Thread?.NewState("Get_Slot_" + Recipient);
685
686 HttpFileUploadEventArgs e2 = await UploadClient.RequestUploadSlotAsync(BackupInfo.LocalFileName,
687 BackupInfo.ContentType, FileSize, false);
688
689 if (!e2.Ok)
690 throw e2.StanzaError ?? new XmppException("Unable to get HTTP upload slot for backup file.");
691
692 BackupInfo.Thread?.NewState("Upload_" + Recipient);
693
694 if (BackupInfo.IsKey)
695 Log.Informational("Uploading key file to " + Recipient + ".", BackupInfo.LocalFileName);
696 else
697 Log.Informational("Uploading backup file to " + Recipient + ".", BackupInfo.LocalFileName);
698
699 await e2.PUT(fs, BackupInfo.ContentType, 60 * 60 * 1000); // 1h timeout
700
701 if (BackupInfo.IsKey)
702 Log.Informational("Key file uploaded to " + Recipient + ".", BackupInfo.LocalFileName);
703 else
704 Log.Informational("Backup file uploaded to " + Recipient + ".", BackupInfo.LocalFileName);
705 }
706 }
707 catch (Exception ex)
708 {
709 BackupInfo.Thread?.Exception(ex, BackupInfo.LocalFileName);
710 Log.Exception(ex);
711 Reschedule = true;
712
713 await Gateway.SendNotification("Unable to upload backup to " + MarkdownDocument.Encode(Recipient) +
714 ".\r\n\r\n" + MarkdownDocument.Encode(ex.Message));
715 }
716 }
717 }
718 }
719 catch (Exception ex)
720 {
721 BackupInfo.Thread?.Exception(ex);
722 Log.Exception(ex);
723 Reschedule = true;
724 }
725 finally
726 {
727 if (Reschedule)
728 {
729 BackupInfo.Thread?.NewState("Reschedule");
730 BackupInfo.Rescheduled = true;
731
732 Gateway.ScheduleEvent(UploadBackupFile, DateTime.Now.AddMinutes(15), BackupInfo);
733 }
734 else if (BackupInfo.Rescheduled)
735 {
736 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.");
737 BackupInfo.Rescheduled = false;
738 }
739
740 BackupInfo.Thread = null;
741 }
742 }
743
744 }
745}
const string DefaultContentType
text/plain
Definition: BinaryCodec.cs:24
Helps with parsing of commong data types.
Definition: CommonTypes.cs:15
static string JsonStringEncode(string s)
Encodes a string for inclusion in JSON.
Definition: CommonTypes.cs:805
Contains information about a response to a content request.
bool HasError
If an error occurred.
object Decoded
Decoded object.
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 ...
Plain text encoder/decoder.
const string DefaultContentType
text/plain
XML encoder/decoder.
Definition: XmlCodec.cs:19
const string DefaultContentType
Default content type for XML documents.
Definition: XmlCodec.cs:30
Helps with common XML-related tasks.
Definition: XML.cs:21
static XmlWriterSettings WriterSettings(bool Indent, bool OmitXmlDeclaration)
Gets an XML writer settings object.
Definition: XML.cs:1351
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 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:576
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
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:559
Static class managing data export.
Definition: Export.cs:18
static async Task< string[]> GetKeyHostsAsync()
Secondary key hosts.
Definition: Export.cs:607
static async Task< string > GetFullExportFolderAsync()
Full path to export folder.
Definition: Export.cs:22
static FolderCategory[] GetRegisteredFolders()
Gets registered exportable folders.
Definition: Export.cs:542
static async Task< string > GetFullKeyExportFolderAsync()
Full path to key folder.
Definition: Export.cs:35
static async Task< string[]> GetBackupHostsAsync()
Secondary backup hosts.
Definition: Export.cs:581
static async Task SetExportFolderAsync(string Value)
Export folder.
Definition: Export.cs:158
Static class managing the runtime environment of the IoT Gateway.
Definition: Gateway.cs:147
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:3868
static string ConfigFilePath
Full path to Gateway.config file.
Definition: Gateway.cs:3181
static byte[] NextBytes(int NrBytes)
Generates an array of random bytes.
Definition: Gateway.cs:4335
static string AppDataFolder
Application data folder.
Definition: Gateway.cs:3132
static Task SendNotification(Graph Graph)
Sends a graph as a notification message to configured notification recipients.
Definition: Gateway.cs:4677
static DateTime ScheduleEvent(Action< object > Callback, DateTime When, object State)
Schedules a one-time event.
Definition: Gateway.cs:4253
static XmppClient XmppClient
XMPP Client connection of gateway.
Definition: Gateway.cs:4038
static string RootFolder
Web root folder.
Definition: Gateway.cs:3142
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:76
override bool UserSessions
If the resource uses user sessions.
Definition: StartExport.cs:63
static async Task< string > GetUniqueFileName(string Base, string Extension)
Gets a unique filename.
Definition: StartExport.cs:321
override bool HandlesSubPaths
If the resource handles sub-paths.
Definition: StartExport.cs:58
bool AllowsPOST
If the POST method is allowed.
Definition: StartExport.cs:68
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:22
bool HasData
If the request has data.
Definition: HttpRequest.cs:113
async Task< ContentResponse > DecodeDataAsync()
Decodes data sent in request.
Definition: HttpRequest.cs:139
Represets a response of an HTTP client request.
Definition: HttpResponse.cs:23
async Task SendResponse()
Sends the response back to the client. If the resource is synchronous, there's no need to call this m...
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).
Class managing HTTP File uploads, as defined in XEP-0363.
Event arguments for HTTP File Upload callback methods.
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
Base class of XMPP exceptions
Static interface for database persistence. In order to work, a database provider has to be assigned t...
Definition: Database.cs:21
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
Contains static methods
Definition: Files.cs:14
static Task WriteAllTextAsync(string FileName, string Text)
Creates a text file asynchronously.
Definition: Files.cs:95
Class that keeps track of events and timing.
Definition: Profiler.cs:68
void Stop()
Stops measuring time.
Definition: Profiler.cs:227
ProfilerThread CreateThread(string Name, ProfilerThreadType Type)
Creates a new profiler thread.
Definition: Profiler.cs:128
void NewState(string State)
Main Thread changes state.
Definition: Profiler.cs:267
void Exception(System.Exception Exception)
Event occurred on main thread
Definition: Profiler.cs:350
void Start()
Starts measuring time.
Definition: Profiler.cs:217
Class that keeps track of events and timing for one thread.
Represents a named semaphore, i.e. an object, identified by a name, that allows single concurrent wri...
Definition: Semaphore.cs:19
Static class of application-wide semaphores that can be used to order access to editable objects.
Definition: Semaphores.cs:17
static async Task< Semaphore > BeginWrite(string Key)
Waits until the semaphore identified by Key is ready for writing. Each call to BeginWrite must be fo...
Definition: Semaphores.cs:91
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.
Definition: ImplTypes.g.cs:58
FilePurpose
Purpose of file uploaded
Definition: FilePurpose.cs:10
XmppState
State of XMPP connection.
Definition: XmppState.cs:7
ProfilerThreadType
Type of profiler thread.
ContentType
DTLS Record content type.
Definition: Enumerations.cs:11