Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
BlockResource.cs
1using System;
3using System.IO;
4using System.Text;
5using System.Threading.Tasks;
6using System.Xml;
7using Waher.Content;
18using Waher.Script;
19using Waher.Security;
20
22{
27 {
31 public const string ErrorMsg_BlockFileHasBeenRemoved = "Block file has been removed.";
32
33 private readonly NeuroLedgerProvider provider;
34 private readonly NeuroLedgerClient nlClient;
35 private readonly XmppClient client;
36 private readonly HttpServer webServer;
37 private readonly string userVariable;
38 private readonly string[] userPrivileges;
39
51 HttpServer WebServer, string UserVariable, params string[] UserPrivileges)
52 : base(ResourceName)
53 {
54 this.client = Client;
55 this.nlClient = NLClient;
56 this.provider = Provider;
57 this.webServer = WebServer;
58 this.userVariable = UserVariable;
59 this.userPrivileges = UserPrivileges;
60 }
61
65 public override bool HandlesSubPaths => true;
66
70 public override bool UserSessions => false;
71
75 public bool AllowsGET => true;
76
83 public async Task GET(HttpRequest Request, HttpResponse Response)
84 {
85 byte[] Digest;
86
87 try
88 {
89 Digest = Base64Url.Decode(Request.SubPath[1..]);
90 }
91 catch (Exception)
92 {
93 await Response.SendResponse(new BadRequestException("Invalid block digest."));
94 return;
95 }
96
97 if (this.nlClient.ClientDisposed)
98 {
99 await Response.SendResponse(new ServiceUnavailableException("Service is closing down."));
100 return;
101 }
102
104 if (Ref is null)
105 {
106 await Response.SendResponse(new NotFoundException("Block not found."));
107 return;
108 }
109
110 if (Ref.AccessDenied && Ref.Creator != this.provider.ExternalIdentity)
111 {
112 await Response.SendResponse(new FailedDependencyException("Access to block was denied by creator or block source."));
113 return;
114 }
115
116 string s = Request.RemoteEndPoint;
117 int i = s.IndexOf('/');
118 if (i > 0)
119 s = s[..i];
120
121 RosterItem Item = this.client[s];
122
123 if (Item is null)
124 {
125 string HttpSessionID = GetSessionId(Request, Response);
126
127 if (string.IsNullOrEmpty(HttpSessionID))
128 {
129 await Response.SendResponse(new ForbiddenException(Request, "Access to block not granted: Accessing blocks can only be done by approved peers, or via the administrative portal."));
130 return;
131 }
132 else
133 {
134 Variables Session = this.webServer.GetSession(HttpSessionID, false);
135 if (Session is null ||
136 !Session.TryGetVariable(this.userVariable, out Variable v) ||
137 !(v.ValueObject is IUser User))
138 {
139 await Response.SendResponse(new ForbiddenException(Request, "Access to block not granted: User needs to be logged in."));
140 return;
141 }
142 else
143 {
144 foreach (string Privilege in this.userPrivileges)
145 {
146 if (!User.HasPrivilege(Privilege))
147 {
148 await Response.SendResponse(new ForbiddenException(Request, "Access to block not granted: User lacks sufficient privileges."));
149 return;
150 }
151 }
152 }
153 }
154 }
155 else
156 {
157 if (Item.State != SubscriptionState.Both && Item.State != SubscriptionState.From)
158 {
159 await Response.SendResponse(new ForbiddenException(Request, "Access to block not granted: Presence subscription not approved."));
160 return;
161 }
162 else if (!Item.IsInGroup(Ref.Collection))
163 {
164 await Response.SendResponse(new ForbiddenException(Request, "Access to block not granted: Peer is not authorized to access collection " + Ref.Collection + "."));
165 return;
166 }
167 }
168
169 Task _ = this.ProcessRequest(Request.Header.Accept, Response, Ref);
170 }
171
178 public async Task ProcessRequest(HttpFieldAccept Accept, HttpResponse Response, BlockReference Ref)
179 {
180 try
181 {
182 if (this.nlClient.ClientDisposed)
183 {
184 await Response.SendResponse(new ServiceUnavailableException("Service is closing down."));
185 return;
186 }
187
188 string Alternative = Accept?.GetBestAlternative("binary", "application/octet-stream",
190 JsonCodec.DefaultContentType, "text/x-json") ?? "application/octet-stream";
191
192 string FileName = this.provider.GetFullFileName(Ref.FileName);
193
194 if (string.IsNullOrEmpty(Ref.FileName) || !File.Exists(FileName))
195 {
196 if (!(Ref.Sources is null))
197 {
198 foreach (string Source in Ref.Sources)
199 {
200 if (this.nlClient.ClientDisposed)
201 {
202 await Response.SendResponse(new ServiceUnavailableException("Service is closing down."));
203 return;
204 }
205
206 if (await this.nlClient.RetrieveBlock(Ref, Source, null, true))
207 break;
208 }
209 }
210
211 if (Ref.AccessDenied && Ref.Creator != this.provider.ExternalIdentity)
212 {
213 await Response.SendResponse(new FailedDependencyException("Access to block was denied by creator or block source."));
214 return;
215 }
216
217 FileName = this.provider.GetFullFileName(Ref.FileName);
218 if (string.IsNullOrEmpty(Ref.FileName) || !File.Exists(FileName))
219 {
220 if (Ref.Creator == this.provider.ExternalIdentity)
221 {
222 await Database.Delete(Ref);
224 return;
225 }
226 else
227 {
228 await Response.SendResponse(new FailedDependencyException("Unable to download block from creator."));
229 return;
230 }
231 }
232 }
233
234 switch (Alternative)
235 {
236 case "binary":
237 case "application/octet-stream":
238 Response.StatusCode = 200;
239 Response.StatusMessage = "OK";
240 Response.ContentType = Alternative;
241
242 using (Stream f = BlockReader.GetStream(FileName, this.provider))
243 {
244 MemoryStream Header = new MemoryStream();
245 int CollectionLen = f.ReadByte();
246 Header.WriteByte((byte)CollectionLen);
247
248 if (CollectionLen == 0)
249 CollectionLen = 256;
250
251 byte[] CollectionBin = await f.ReadAllAsync(CollectionLen);
252
253 Header.Write(CollectionBin, 0, CollectionLen);
254
255 string CollectionName = Encoding.UTF8.GetString(CollectionBin);
256 Response.SetHeader("X-Collection", CollectionName);
257
258 int SigLen = f.ReadByte();
259 Header.WriteByte((byte)SigLen);
260
261 if (SigLen == 0)
262 SigLen = 256;
263
264 byte[] Signature = await f.ReadAllAsync(SigLen);
265
266 Header.Write(Signature, 0, SigLen);
267 Response.SetHeader("X-Signature", Convert.ToBase64String(Signature));
268
269 byte[] ContentLen = await f.ReadAllAsync(8);
270
271 Header.Write(ContentLen, 0, 8);
272
273 long InputLength = BitConverter.ToInt64(ContentLen, 0);
274 byte[] Buf = Header.ToArray();
275
276 Response.ContentLength = Header.Length + InputLength;
277 await Response.Write(true, Buf, 0, Buf.Length);
278
279 Buf = new byte[(int)Math.Min(32768, InputLength)];
280
281 while (InputLength > 0)
282 {
283 int i = (int)Math.Min(32768, InputLength);
284
285 await f.ReadAllAsync(Buf, 0, i);
286
287 await Response.Write(false, Buf, 0, i);
288 InputLength -= i;
289 }
290 }
291 break;
292
295 XmlWriterSettings Settings = XML.WriterSettings(true, true);
296 StringBuilder Xml = new StringBuilder();
297 XmlWriter w = XmlWriter.Create(Xml, Settings);
298
299 w.WriteStartDocument();
300 w.WriteStartElement("Block", "http://waher.se/NLB");
301 w.WriteAttributeString("digest", Convert.ToBase64String(Ref.Digest));
302 w.WriteAttributeString("status", Ref.Status.ToString());
303 w.WriteAttributeString("signature", Convert.ToBase64String(Ref.Signature));
304 w.WriteAttributeString("collection", Ref.Collection);
305 w.WriteAttributeString("created", XML.Encode(Ref.Created));
306 w.WriteAttributeString("creator", Ref.Creator);
307
308 if (Ref.Expires != DateTime.MaxValue)
309 w.WriteAttributeString("expires", XML.Encode(Ref.Expires));
310
311 if (Ref.Updated != DateTime.MinValue)
312 w.WriteAttributeString("updated", XML.Encode(Ref.Updated));
313
314 if (!(Ref.Link is null))
315 w.WriteAttributeString("link", Convert.ToBase64String(Ref.Link));
316
317 using (BlockEnumerator TempBlockEnumerator = new BlockEnumerator(Ref, this.provider))
318 {
319 using ObjectEnumerator<GenericObject> e = await ObjectEnumerator<GenericObject>.Create(TempBlockEnumerator, this.provider);
320
321 while (await e.MoveNextAsync())
322 {
323 switch (e.CurrentEntry.Type)
324 {
325 case EntryType.New:
326 w.WriteStartElement("Add");
327 break;
328
329 case EntryType.Update:
330 w.WriteStartElement("Update");
331 break;
332
333 case EntryType.Delete:
334 w.WriteStartElement("Delete");
335 break;
336
337 case EntryType.Clear:
338 w.WriteStartElement("Clear");
339 w.WriteAttributeString("ts", XML.Encode(e.CurrentEntry.Timestamp));
340 w.WriteEndElement();
341 continue;
342
343 default:
344 continue;
345 }
346
347 GenericObject Obj = e.Current;
348
349 w.WriteAttributeString("ts", XML.Encode(e.CurrentEntry.Timestamp));
350 w.WriteAttributeString("type", Obj.TypeName);
351 w.WriteAttributeString("id", Obj.ObjectId.ToString());
352
353 foreach (KeyValuePair<string, object> P in Obj)
354 this.WriteProperty(w, P.Key, P.Value);
355
356 w.WriteEndElement();
357 }
358 }
359
360 w.WriteEndElement();
361 w.WriteEndDocument();
362 w.Flush();
363
364 Response.StatusCode = 200;
365 Response.StatusMessage = "OK";
366 Response.ContentType = Alternative;
367 await Response.Write(Xml.ToString());
368 break;
369
371 case "text/x-json":
372 LinkedList<KeyValuePair<string, object>> Result = new LinkedList<KeyValuePair<string, object>>();
373
374 Result.AddLast(new KeyValuePair<string, object>("digest", Convert.ToBase64String(Ref.Digest)));
375 Result.AddLast(new KeyValuePair<string, object>("status", Ref.Status.ToString()));
376 Result.AddLast(new KeyValuePair<string, object>("signature", Convert.ToBase64String(Ref.Signature)));
377 Result.AddLast(new KeyValuePair<string, object>("collection", Ref.Collection));
378 Result.AddLast(new KeyValuePair<string, object>("created", XML.Encode(Ref.Created)));
379 Result.AddLast(new KeyValuePair<string, object>("creator", Ref.Creator));
380
381 if (Ref.Expires != DateTime.MaxValue)
382 Result.AddLast(new KeyValuePair<string, object>("expires", XML.Encode(Ref.Expires)));
383
384 if (Ref.Updated != DateTime.MinValue)
385 Result.AddLast(new KeyValuePair<string, object>("updated", XML.Encode(Ref.Updated)));
386
387 if (!(Ref.Link is null))
388 Result.AddLast(new KeyValuePair<string, object>("link", Convert.ToBase64String(Ref.Link)));
389
390 LinkedList<object> Entries = new LinkedList<object>();
391 Result.AddLast(new KeyValuePair<string, object>("entries", Entries));
392
393 using (BlockEnumerator TempBlockEnumerator = new BlockEnumerator(Ref, this.provider))
394 {
395 using ObjectEnumerator<GenericObject> e = await ObjectEnumerator<GenericObject>.Create(TempBlockEnumerator, this.provider);
396
397 while (await e.MoveNextAsync())
398 {
399 LinkedList<KeyValuePair<string, object>> P1 = new LinkedList<KeyValuePair<string, object>>();
400
401 P1.AddLast(new KeyValuePair<string, object>("type", e.CurrentEntry.Type.ToString()));
402 P1.AddLast(new KeyValuePair<string, object>("ts", XML.Encode(e.CurrentEntry.Timestamp)));
403
404 switch (e.CurrentEntry.Type)
405 {
406 case EntryType.New:
407 case EntryType.Update:
408 case EntryType.Delete:
409 LinkedList<KeyValuePair<string, object>> P2 = new LinkedList<KeyValuePair<string, object>>();
410 GenericObject Obj = e.Current;
411
412 P1.AddLast(new KeyValuePair<string, object>("obj", P2));
413
414 P2.AddLast(new KeyValuePair<string, object>("type", Obj.TypeName));
415 P2.AddLast(new KeyValuePair<string, object>("id", Obj.ObjectId.ToString()));
416
417 foreach (KeyValuePair<string, object> P in Obj)
418 P2.AddLast(new KeyValuePair<string, object>(P.Key, P.Value));
419
420 break;
421 }
422
423 Entries.AddLast(P1);
424 }
425 }
426
427 Response.StatusCode = 200;
428 Response.StatusMessage = "OK";
429 Response.ContentType = Alternative;
430 await Response.Write(JSON.Encode(Result, true));
431 break;
432
433 default:
434 await Response.SendResponse(new NotAcceptableException("Desired format not acceptable. Use the Accept header field to select either text/xml, application/json or application/octet-stream."));
435 return;
436 }
437
438 await Response.SendResponse();
439 }
440 catch (Exception ex)
441 {
442 await Response.SendResponse(ex);
443 }
444 }
445
446 private void WriteProperty(XmlWriter w, string Name, object Value)
447 {
448 if (Value is null)
449 {
450 w.WriteStartElement("Null");
451 if (!(Name is null))
452 w.WriteAttributeString("n", string.Empty, Name);
453 w.WriteEndElement();
454 }
455 else if (Value is Enum)
456 {
457 w.WriteStartElement("En");
458 if (!(Name is null))
459 w.WriteAttributeString("n", string.Empty, Name);
460 w.WriteAttributeString("v", string.Empty, Value.ToString());
461 w.WriteEndElement();
462 }
463 else
464 {
465 switch (Type.GetTypeCode(Value.GetType()))
466 {
467 case TypeCode.Boolean:
468 w.WriteStartElement("Bl");
469 if (!(Name is null))
470 w.WriteAttributeString("n", string.Empty, Name);
471 w.WriteAttributeString("v", string.Empty, CommonTypes.Encode((bool)Value));
472 w.WriteEndElement();
473 break;
474
475 case TypeCode.Byte:
476 w.WriteStartElement("B");
477 if (!(Name is null))
478 w.WriteAttributeString("n", string.Empty, Name);
479 w.WriteAttributeString("v", string.Empty, Value.ToString());
480 w.WriteEndElement();
481 break;
482
483 case TypeCode.Char:
484 w.WriteStartElement("Ch");
485 if (!(Name is null))
486 w.WriteAttributeString("n", string.Empty, Name);
487 w.WriteAttributeString("v", string.Empty, Value.ToString());
488 w.WriteEndElement();
489 break;
490
491 case TypeCode.DateTime:
492 w.WriteStartElement("DT");
493 if (!(Name is null))
494 w.WriteAttributeString("n", string.Empty, Name);
495 w.WriteAttributeString("v", string.Empty, XML.Encode((DateTime)Value));
496 w.WriteEndElement();
497 break;
498
499 case TypeCode.Decimal:
500 w.WriteStartElement("Dc");
501 if (!(Name is null))
502 w.WriteAttributeString("n", string.Empty, Name);
503 w.WriteAttributeString("v", string.Empty, CommonTypes.Encode((decimal)Value));
504 w.WriteEndElement();
505 break;
506
507 case TypeCode.Double:
508 w.WriteStartElement("Db");
509 if (!(Name is null))
510 w.WriteAttributeString("n", string.Empty, Name);
511 w.WriteAttributeString("v", string.Empty, CommonTypes.Encode((double)Value));
512 w.WriteEndElement();
513 break;
514
515 case TypeCode.Int16:
516 w.WriteStartElement("I2");
517 if (!(Name is null))
518 w.WriteAttributeString("n", string.Empty, Name);
519 w.WriteAttributeString("v", string.Empty, Value.ToString());
520 w.WriteEndElement();
521 break;
522
523 case TypeCode.Int32:
524 w.WriteStartElement("I4");
525 if (!(Name is null))
526 w.WriteAttributeString("n", string.Empty, Name);
527 w.WriteAttributeString("v", string.Empty, Value.ToString());
528 w.WriteEndElement();
529 break;
530
531 case TypeCode.Int64:
532 w.WriteStartElement("I8");
533 if (!(Name is null))
534 w.WriteAttributeString("n", string.Empty, Name);
535 w.WriteAttributeString("v", string.Empty, Value.ToString());
536 w.WriteEndElement();
537 break;
538
539 case TypeCode.SByte:
540 w.WriteStartElement("I1");
541 if (!(Name is null))
542 w.WriteAttributeString("n", string.Empty, Name);
543 w.WriteAttributeString("v", string.Empty, Value.ToString());
544 w.WriteEndElement();
545 break;
546
547 case TypeCode.Single:
548 w.WriteStartElement("Fl");
549 if (!(Name is null))
550 w.WriteAttributeString("n", string.Empty, Name);
551 w.WriteAttributeString("v", string.Empty, CommonTypes.Encode((float)Value));
552 w.WriteEndElement();
553 break;
554
555 case TypeCode.String:
556 string s = Value.ToString();
557 try
558 {
559 XmlConvert.VerifyXmlChars(s);
560 w.WriteStartElement("S");
561 if (!(Name is null))
562 w.WriteAttributeString("n", string.Empty, Name);
563 w.WriteAttributeString("v", string.Empty, s);
564 w.WriteEndElement();
565 }
566 catch (XmlException)
567 {
568 byte[] Bin = Encoding.UTF8.GetBytes(s);
569 s = Convert.ToBase64String(Bin);
570 w.WriteStartElement("S64");
571 if (!(Name is null))
572 w.WriteAttributeString("n", string.Empty, Name);
573 w.WriteAttributeString("v", string.Empty, s);
574 w.WriteEndElement();
575 }
576 break;
577
578 case TypeCode.UInt16:
579 w.WriteStartElement("U2");
580 if (!(Name is null))
581 w.WriteAttributeString("n", string.Empty, Name);
582 w.WriteAttributeString("v", string.Empty, Value.ToString());
583 w.WriteEndElement();
584 break;
585
586 case TypeCode.UInt32:
587 w.WriteStartElement("U4");
588 if (!(Name is null))
589 w.WriteAttributeString("n", string.Empty, Name);
590 w.WriteAttributeString("v", string.Empty, Value.ToString());
591 w.WriteEndElement();
592 break;
593
594 case TypeCode.UInt64:
595 w.WriteStartElement("U8");
596 if (!(Name is null))
597 w.WriteAttributeString("n", string.Empty, Name);
598 w.WriteAttributeString("v", string.Empty, Value.ToString());
599 w.WriteEndElement();
600 break;
601
602 case TypeCode.DBNull:
603 case TypeCode.Empty:
604 w.WriteStartElement("Null");
605 if (!(Name is null))
606 w.WriteAttributeString("n", string.Empty, Name);
607 w.WriteEndElement();
608 break;
609
610 case TypeCode.Object:
611 if (Value is TimeSpan)
612 {
613 w.WriteStartElement("TS");
614 if (!(Name is null))
615 w.WriteAttributeString("n", string.Empty, Name);
616 w.WriteAttributeString("v", string.Empty, Value.ToString());
617 w.WriteEndElement();
618 }
619 else if (Value is DateTimeOffset DTO)
620 {
621 w.WriteStartElement("DTO");
622 if (!(Name is null))
623 w.WriteAttributeString("n", string.Empty, Name);
624 w.WriteAttributeString("v", string.Empty, XML.Encode(DTO));
625 w.WriteEndElement();
626 }
627 else if (Value is CaseInsensitiveString Cis)
628 {
629 s = Cis.Value;
630 try
631 {
632 XmlConvert.VerifyXmlChars(s);
633 w.WriteStartElement("CIS");
634 if (!(Name is null))
635 w.WriteAttributeString("n", string.Empty, Name);
636 w.WriteAttributeString("v", string.Empty, s);
637 w.WriteEndElement();
638 }
639 catch (XmlException)
640 {
641 byte[] Bin = Encoding.UTF8.GetBytes(s);
642 s = Convert.ToBase64String(Bin);
643 w.WriteStartElement("CIS64");
644 if (!(Name is null))
645 w.WriteAttributeString("n", string.Empty, Name);
646 w.WriteAttributeString("v", string.Empty, s);
647 w.WriteEndElement();
648 }
649 }
650 else if (Value is byte[] Bin)
651 {
652 w.WriteStartElement("Bin");
653 if (!(Name is null))
654 w.WriteAttributeString("n", string.Empty, Name);
655
656 byte[] Buf = null;
657 int c = Bin.Length;
658 int i = 0;
659 int d;
660 int j;
661
662 while (i < c)
663 {
664 d = c - i;
665 if (d > 49152)
666 j = 49152;
667 else
668 j = d;
669
670 if (Buf is null)
671 {
672 if (i == 0 && j == c)
673 Buf = Bin;
674 else
675 Buf = new byte[j];
676 }
677
678 if (Buf != Bin)
679 Buffer.BlockCopy(Bin, i, Buf, 0, j);
680
681 w.WriteElementString("Chunk", Convert.ToBase64String(Buf, 0, j, Base64FormattingOptions.None));
682 i += j;
683 }
684
685 w.WriteEndElement();
686 }
687 else if (Value is Guid)
688 {
689 w.WriteStartElement("ID");
690 if (!(Name is null))
691 w.WriteAttributeString("n", string.Empty, Name);
692 w.WriteAttributeString("v", string.Empty, Value.ToString());
693 w.WriteEndElement();
694 }
695 else if (Value is Array A)
696 {
697 w.WriteStartElement("Array");
698 if (!(Name is null))
699 w.WriteAttributeString("n", string.Empty, Name);
700 w.WriteAttributeString("elementType", string.Empty, Value.GetType().GetElementType().FullName);
701
702 foreach (object Obj in A)
703 this.WriteProperty(w, null, Obj);
704
705 w.WriteEndElement();
706 }
707 else if (Value is GenericObject Obj)
708 {
709 w.WriteStartElement("Obj");
710 if (!(Name is null))
711 w.WriteAttributeString("n", string.Empty, Name);
712 w.WriteAttributeString("type", string.Empty, Obj.TypeName);
713
714 foreach (KeyValuePair<string, object> P in Obj)
715 this.WriteProperty(w, P.Key, P.Value);
716
717 w.WriteEndElement();
718 }
719 else
720 throw new Exception("Unhandled property value type: " + Value.GetType().FullName);
721 break;
722
723 default:
724 throw new Exception("Unhandled property value type: " + Value.GetType().FullName);
725 }
726 }
727 }
728
729 }
730}
Static class that does BASE64URL encoding (using URL and filename safe alphabet), as defined in RFC46...
Definition: Base64Url.cs:11
static byte[] Decode(string Base64Url)
Converts a Base64URL-encoded string to its binary representation.
Definition: Base64Url.cs:17
Helps with parsing of commong data types.
Definition: CommonTypes.cs:15
static string Encode(bool x)
Encodes a Boolean for use in XML and other formats.
Definition: CommonTypes.cs:596
Helps with common JSON-related tasks.
Definition: JSON.cs:16
static string Encode(string s)
Encodes a string for inclusion in JSON.
Definition: JSON.cs:537
const string DefaultContentType
application/json
Definition: JsonCodec.cs:20
XML encoder/decoder.
Definition: XmlCodec.cs:19
const string DefaultContentType
Default content type for XML documents.
Definition: XmlCodec.cs:30
const string SchemaContentType
Default content type for XML schema documents.
Definition: XmlCodec.cs:35
Helps with common XML-related tasks.
Definition: XML.cs:21
static string Encode(string s)
Encodes a string for use in XML.
Definition: XML.cs:29
static XmlWriterSettings WriterSettings(bool Indent, bool OmitXmlDeclaration)
Gets an XML writer settings object.
Definition: XML.cs:1351
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repe...
The request failed due to failure of a previous request (e.g., a PROPPATCH).
The server understood the request, but is refusing to fulfill it. Authorization will not help and the...
Accept HTTP Field header. (RFC 2616, §14.1)
string GetBestAlternative(params string[] Alternatives)
Gets the best alternative acceptable to the client.
Base class for all asynchronous HTTP resources. An asynchronous resource responds outside of the meth...
HttpFieldAccept Accept
Accept HTTP Field header. (RFC 2616, §14.1)
Represents an HTTP request.
Definition: HttpRequest.cs:22
HttpRequestHeader Header
Request header.
Definition: HttpRequest.cs:182
string RemoteEndPoint
Remote end-point.
Definition: HttpRequest.cs:243
string SubPath
Sub-path. If a resource is found handling the request, this property contains the trailing sub-path o...
Definition: HttpRequest.cs:194
static string GetSessionId(HttpRequest Request, HttpResponse Response)
Gets the session ID used for a request.
const string HttpSessionID
The Cookie Key for HTTP Session Identifiers: "HttpSessionID"
Definition: HttpResource.cs:27
string ResourceName
Name of resource.
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.
void SetHeader(string FieldName, string Value)
Sets a custom header field value.
Implements an HTTP server.
Definition: HttpServer.cs:41
The resource identified by the request is only capable of generating response entities which have con...
The server has not found anything matching the Request-URI. No indication is given of whether the con...
The server is currently unable to handle the request due to a temporary overloading or maintenance of...
Provides authenticated and authorized clients with binary blocks.
override bool HandlesSubPaths
If the resource handles sub-paths.
async Task GET(HttpRequest Request, HttpResponse Response)
Executes the GET method on the resource.
const string ErrorMsg_BlockFileHasBeenRemoved
Block file has been removed.
bool AllowsGET
If the GET method is allowed.
async Task ProcessRequest(HttpFieldAccept Accept, HttpResponse Response, BlockReference Ref)
Processes a block request.
BlockResource(string ResourceName, NeuroLedgerProvider Provider, XmppClient Client, NeuroLedgerClient NLClient, HttpServer WebServer, string UserVariable, params string[] UserPrivileges)
Provides authenticated and authorized clients with binary blocks.
override bool UserSessions
If the resource uses user sessions.
Maintains information about an item in the roster.
Definition: RosterItem.cs:75
bool IsInGroup(string Group)
Checks if the roster item is in a specific group.
Definition: RosterItem.cs:196
SubscriptionState State
roup Current subscription state.
Definition: RosterItem.cs:268
Manages an XMPP client connection. Implements XMPP, as defined in https://tools.ietf....
Definition: XmppClient.cs:58
Represents a case-insensitive string.
Static interface for database persistence. In order to work, a database provider has to be assigned t...
Definition: Database.cs:21
static async Task Delete(object Object)
Deletes an object in the database.
Definition: Database.cs:1291
byte[] Link
Link to updated block (in case Status shows the block has been updated).
Definition: BlockHeader.cs:120
string Creator
Creator of the block.
Definition: BlockHeader.cs:55
BlockStatus Status
Claimed status of block.
Definition: BlockHeader.cs:108
DateTime Created
When the block was created.
Definition: BlockHeader.cs:75
DateTime Expires
When the block expires.
Definition: BlockHeader.cs:97
DateTime Updated
When the block was updated (in case Status shows the block has been updated or deleted).
Definition: BlockHeader.cs:87
static Stream GetStream(string FileName, NeuroLedgerProvider Provider)
Gets a stream to the contents of the block.
Definition: BlockReader.cs:53
static Task< BlockReference > FindReference(byte[] Digest)
Finds a BlockReference object related to a block, given its digest.
Enumeratres through objects available in a series of blocks.
static async Task< ObjectEnumerator< T > > Create(IAsyncEnumerator< BlockReference > BlockEnumerator, NeuroLedgerProvider Provider)
Creates an object enumerator from a block enumerator.
Contains a reference to a block in the ledger.
bool AccessDenied
If access to the block was denied.
Generic object. Contains a sequence of properties.
Contains information about a variable.
Definition: Variable.cs:10
Collection of variables.
Definition: Variables.cs:25
virtual bool TryGetVariable(string Name, out Variable Variable)
Tries to get a variable object, given its name.
Definition: Variables.cs:56
GET Interface for HTTP resources.
Basic interface for a user.
Definition: IUser.cs:7
Definition: ImplTypes.g.cs:58
SubscriptionState
State of a presence subscription.
Definition: RosterItem.cs:16
EntryType
Ledger entry type.
Definition: ILedgerEntry.cs:9