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;
2using System.Collections.Generic;
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.Substring(1));
90 }
91 catch (Exception)
92 {
93 throw new BadRequestException("Invalid block digest.");
94 }
95
96 if (this.nlClient.ClientDisposed)
97 throw new ServiceUnavailableException("Service is closing down.");
98
100 ?? throw new NotFoundException("Block not found.");
101
102 if (Ref.AccessDenied && Ref.Creator != this.provider.ExternalIdentity)
103 throw new FailedDependencyException("Access to block was denied by creator or block source.");
104
105 string s = Request.RemoteEndPoint;
106 int i = s.IndexOf('/');
107 if (i > 0)
108 s = s.Substring(0, i);
109
110 RosterItem Item = this.client[s];
111
112 if (Item is null)
113 {
114 string HttpSessionID = GetSessionId(Request, Response);
115
116 if (string.IsNullOrEmpty(HttpSessionID))
117 throw new ForbiddenException("Access to block not granted: Accessing blocks can only be done by approved peers, or via the administrative portal.");
118 else
119 {
120 Variables Session = this.webServer.GetSession(HttpSessionID, false);
121 if (Session is null ||
122 !Session.TryGetVariable(this.userVariable, out Variable v) ||
123 !(v.ValueObject is IUser User))
124 {
125 throw new ForbiddenException("Access to block not granted: User needs to be logged in.");
126 }
127 else
128 {
129 foreach (string Privilege in this.userPrivileges)
130 {
131 if (!User.HasPrivilege(Privilege))
132 throw new ForbiddenException("Access to block not granted: User lacks sufficient privileges.");
133 }
134 }
135 }
136 }
137 else
138 {
139 if (Item.State != SubscriptionState.Both && Item.State != SubscriptionState.From)
140 throw new ForbiddenException("Access to block not granted: Presence subscription not approved.");
141 else if (!Item.IsInGroup(Ref.Collection))
142 throw new ForbiddenException("Access to block not granted: Peer is not authorized to access collection " + Ref.Collection + ".");
143 }
144
145 Task _ = this.ProcessRequest(Request.Header.Accept, Response, Ref);
146 }
147
154 public async Task ProcessRequest(HttpFieldAccept Accept, HttpResponse Response, BlockReference Ref)
155 {
156 try
157 {
158 if (this.nlClient.ClientDisposed)
159 throw new ServiceUnavailableException("Service is closing down.");
160
161 string Alternative = Accept?.GetBestAlternative("binary", "application/octet-stream",
163 JsonCodec.DefaultContentType, "text/x-json") ?? "application/octet-stream";
164
165 string FileName = this.provider.GetFullFileName(Ref.FileName);
166
167 if (string.IsNullOrEmpty(Ref.FileName) || !File.Exists(FileName))
168 {
169 if (!(Ref.Sources is null))
170 {
171 foreach (string Source in Ref.Sources)
172 {
173 if (this.nlClient.ClientDisposed)
174 throw new ServiceUnavailableException("Service is closing down.");
175
176 if (await this.nlClient.RetrieveBlock(Ref, Source, null, true))
177 break;
178 }
179 }
180
181 if (Ref.AccessDenied && Ref.Creator != this.provider.ExternalIdentity)
182 throw new FailedDependencyException("Access to block was denied by creator or block source.");
183
184 FileName = this.provider.GetFullFileName(Ref.FileName);
185 if (string.IsNullOrEmpty(Ref.FileName) || !File.Exists(FileName))
186 {
187 if (Ref.Creator == this.provider.ExternalIdentity)
188 {
189 await Database.Delete(Ref);
191 }
192 else
193 throw new FailedDependencyException("Unable to download block from creator.");
194 }
195 }
196
197 switch (Alternative)
198 {
199 case "binary":
200 case "application/octet-stream":
201 Response.StatusCode = 200;
202 Response.ContentType = Alternative;
203
204 using (Stream f = BlockReader.GetStream(FileName, this.provider))
205 {
206 MemoryStream Header = new MemoryStream();
207 int CollectionLen = f.ReadByte();
208 Header.WriteByte((byte)CollectionLen);
209
210 if (CollectionLen == 0)
211 CollectionLen = 256;
212
213 byte[] CollectionBin = new byte[CollectionLen];
214 await f.ReadAllAsync(CollectionBin, 0, CollectionLen);
215
216 Header.Write(CollectionBin, 0, CollectionLen);
217
218 string CollectionName = Encoding.UTF8.GetString(CollectionBin);
219 Response.SetHeader("X-Collection", CollectionName);
220
221 int SigLen = f.ReadByte();
222 Header.WriteByte((byte)SigLen);
223
224 if (SigLen == 0)
225 SigLen = 256;
226
227 byte[] Signature = new byte[SigLen];
228 await f.ReadAllAsync(Signature, 0, SigLen);
229
230 Header.Write(Signature, 0, SigLen);
231 Response.SetHeader("X-Signature", Convert.ToBase64String(Signature));
232
233 byte[] ContentLen = new byte[8];
234 await f.ReadAllAsync(ContentLen, 0, 8);
235
236 Header.Write(ContentLen, 0, 8);
237
238 long InputLength = BitConverter.ToInt64(ContentLen, 0);
239 byte[] Buf = Header.ToArray();
240
241 Response.ContentLength = Header.Length + InputLength;
242 await Response.Write(Buf, 0, Buf.Length);
243
244 Buf = new byte[(int)Math.Min(32768, InputLength)];
245
246 while (InputLength > 0)
247 {
248 int i = (int)Math.Min(32768, InputLength);
249
250 await f.ReadAllAsync(Buf, 0, i);
251
252 await Response.Write(Buf, 0, i);
253 InputLength -= i;
254 }
255 }
256 break;
257
260 XmlWriterSettings Settings = XML.WriterSettings(true, true);
261 StringBuilder Xml = new StringBuilder();
262 XmlWriter w = XmlWriter.Create(Xml, Settings);
263
264 w.WriteStartDocument();
265 w.WriteStartElement("Block", "http://waher.se/NLB");
266 w.WriteAttributeString("digest", Convert.ToBase64String(Ref.Digest));
267 w.WriteAttributeString("status", Ref.Status.ToString());
268 w.WriteAttributeString("signature", Convert.ToBase64String(Ref.Signature));
269 w.WriteAttributeString("collection", Ref.Collection);
270 w.WriteAttributeString("created", XML.Encode(Ref.Created));
271 w.WriteAttributeString("creator", Ref.Creator);
272
273 if (Ref.Expires != DateTime.MaxValue)
274 w.WriteAttributeString("expires", XML.Encode(Ref.Expires));
275
276 if (Ref.Updated != DateTime.MinValue)
277 w.WriteAttributeString("updated", XML.Encode(Ref.Updated));
278
279 if (!(Ref.Link is null))
280 w.WriteAttributeString("link", Convert.ToBase64String(Ref.Link));
281
282 using (BlockEnumerator TempBlockEnumerator = new BlockEnumerator(Ref, this.provider))
283 {
284 using (ObjectEnumerator<GenericObject> e = await ObjectEnumerator<GenericObject>.Create(TempBlockEnumerator, this.provider))
285 {
286 while (await e.MoveNextAsync())
287 {
288 switch (e.CurrentEntry.Type)
289 {
290 case EntryType.New:
291 w.WriteStartElement("Add");
292 break;
293
294 case EntryType.Update:
295 w.WriteStartElement("Update");
296 break;
297
298 case EntryType.Delete:
299 w.WriteStartElement("Delete");
300 break;
301
302 case EntryType.Clear:
303 w.WriteStartElement("Clear");
304 w.WriteAttributeString("ts", XML.Encode(e.CurrentEntry.Timestamp));
305 w.WriteEndElement();
306 continue;
307
308 default:
309 continue;
310 }
311
312 GenericObject Obj = e.Current;
313
314 w.WriteAttributeString("ts", XML.Encode(e.CurrentEntry.Timestamp));
315 w.WriteAttributeString("type", Obj.TypeName);
316 w.WriteAttributeString("id", Obj.ObjectId.ToString());
317
318 foreach (KeyValuePair<string, object> P in Obj)
319 this.WriteProperty(w, P.Key, P.Value);
320
321 w.WriteEndElement();
322 }
323 }
324 }
325
326 w.WriteEndElement();
327 w.WriteEndDocument();
328 w.Flush();
329
330 Response.StatusCode = 200;
331 Response.ContentType = Alternative;
332 await Response.Write(Xml.ToString());
333 break;
334
336 case "text/x-json":
337 LinkedList<KeyValuePair<string, object>> Result = new LinkedList<KeyValuePair<string, object>>();
338
339 Result.AddLast(new KeyValuePair<string, object>("digest", Convert.ToBase64String(Ref.Digest)));
340 Result.AddLast(new KeyValuePair<string, object>("status", Ref.Status.ToString()));
341 Result.AddLast(new KeyValuePair<string, object>("signature", Convert.ToBase64String(Ref.Signature)));
342 Result.AddLast(new KeyValuePair<string, object>("collection", Ref.Collection));
343 Result.AddLast(new KeyValuePair<string, object>("created", XML.Encode(Ref.Created)));
344 Result.AddLast(new KeyValuePair<string, object>("creator", Ref.Creator));
345
346 if (Ref.Expires != DateTime.MaxValue)
347 Result.AddLast(new KeyValuePair<string, object>("expires", XML.Encode(Ref.Expires)));
348
349 if (Ref.Updated != DateTime.MinValue)
350 Result.AddLast(new KeyValuePair<string, object>("updated", XML.Encode(Ref.Updated)));
351
352 if (!(Ref.Link is null))
353 Result.AddLast(new KeyValuePair<string, object>("link", Convert.ToBase64String(Ref.Link)));
354
355 LinkedList<object> Entries = new LinkedList<object>();
356 Result.AddLast(new KeyValuePair<string, object>("entries", Entries));
357
358 using (BlockEnumerator TempBlockEnumerator = new BlockEnumerator(Ref, this.provider))
359 {
360 using (ObjectEnumerator<GenericObject> e = await ObjectEnumerator<GenericObject>.Create(TempBlockEnumerator, this.provider))
361 {
362 while (await e.MoveNextAsync())
363 {
364 LinkedList<KeyValuePair<string, object>> P1 = new LinkedList<KeyValuePair<string, object>>();
365
366 P1.AddLast(new KeyValuePair<string, object>("type", e.CurrentEntry.Type.ToString()));
367 P1.AddLast(new KeyValuePair<string, object>("ts", XML.Encode(e.CurrentEntry.Timestamp)));
368
369 switch (e.CurrentEntry.Type)
370 {
371 case EntryType.New:
372 case EntryType.Update:
373 case EntryType.Delete:
374 LinkedList<KeyValuePair<string, object>> P2 = new LinkedList<KeyValuePair<string, object>>();
375 GenericObject Obj = e.Current;
376
377 P1.AddLast(new KeyValuePair<string, object>("obj", P2));
378
379 P2.AddLast(new KeyValuePair<string, object>("type", Obj.TypeName));
380 P2.AddLast(new KeyValuePair<string, object>("id", Obj.ObjectId.ToString()));
381
382 foreach (KeyValuePair<string, object> P in Obj)
383 P2.AddLast(new KeyValuePair<string, object>(P.Key, P.Value));
384
385 break;
386 }
387
388 Entries.AddLast(P1);
389 }
390 }
391 }
392
393 Response.StatusCode = 200;
394 Response.ContentType = Alternative;
395 await Response.Write(JSON.Encode(Result, true));
396 break;
397
398 default:
399 throw new NotAcceptableException("Desired format not acceptable. Use the Accept header field to select either text/xml, application/json or application/octet-stream.");
400 }
401
402 await Response.SendResponse();
403 }
404 catch (Exception ex)
405 {
406 await Response.SendResponse(ex);
407 }
408 }
409
410 private void WriteProperty(XmlWriter w, string Name, object Value)
411 {
412 if (Value is null)
413 {
414 w.WriteStartElement("Null");
415 if (!(Name is null))
416 w.WriteAttributeString("n", string.Empty, Name);
417 w.WriteEndElement();
418 }
419 else if (Value is Enum)
420 {
421 w.WriteStartElement("En");
422 if (!(Name is null))
423 w.WriteAttributeString("n", string.Empty, Name);
424 w.WriteAttributeString("v", string.Empty, Value.ToString());
425 w.WriteEndElement();
426 }
427 else
428 {
429 switch (Type.GetTypeCode(Value.GetType()))
430 {
431 case TypeCode.Boolean:
432 w.WriteStartElement("Bl");
433 if (!(Name is null))
434 w.WriteAttributeString("n", string.Empty, Name);
435 w.WriteAttributeString("v", string.Empty, CommonTypes.Encode((bool)Value));
436 w.WriteEndElement();
437 break;
438
439 case TypeCode.Byte:
440 w.WriteStartElement("B");
441 if (!(Name is null))
442 w.WriteAttributeString("n", string.Empty, Name);
443 w.WriteAttributeString("v", string.Empty, Value.ToString());
444 w.WriteEndElement();
445 break;
446
447 case TypeCode.Char:
448 w.WriteStartElement("Ch");
449 if (!(Name is null))
450 w.WriteAttributeString("n", string.Empty, Name);
451 w.WriteAttributeString("v", string.Empty, Value.ToString());
452 w.WriteEndElement();
453 break;
454
455 case TypeCode.DateTime:
456 w.WriteStartElement("DT");
457 if (!(Name is null))
458 w.WriteAttributeString("n", string.Empty, Name);
459 w.WriteAttributeString("v", string.Empty, XML.Encode((DateTime)Value));
460 w.WriteEndElement();
461 break;
462
463 case TypeCode.Decimal:
464 w.WriteStartElement("Dc");
465 if (!(Name is null))
466 w.WriteAttributeString("n", string.Empty, Name);
467 w.WriteAttributeString("v", string.Empty, CommonTypes.Encode((decimal)Value));
468 w.WriteEndElement();
469 break;
470
471 case TypeCode.Double:
472 w.WriteStartElement("Db");
473 if (!(Name is null))
474 w.WriteAttributeString("n", string.Empty, Name);
475 w.WriteAttributeString("v", string.Empty, CommonTypes.Encode((double)Value));
476 w.WriteEndElement();
477 break;
478
479 case TypeCode.Int16:
480 w.WriteStartElement("I2");
481 if (!(Name is null))
482 w.WriteAttributeString("n", string.Empty, Name);
483 w.WriteAttributeString("v", string.Empty, Value.ToString());
484 w.WriteEndElement();
485 break;
486
487 case TypeCode.Int32:
488 w.WriteStartElement("I4");
489 if (!(Name is null))
490 w.WriteAttributeString("n", string.Empty, Name);
491 w.WriteAttributeString("v", string.Empty, Value.ToString());
492 w.WriteEndElement();
493 break;
494
495 case TypeCode.Int64:
496 w.WriteStartElement("I8");
497 if (!(Name is null))
498 w.WriteAttributeString("n", string.Empty, Name);
499 w.WriteAttributeString("v", string.Empty, Value.ToString());
500 w.WriteEndElement();
501 break;
502
503 case TypeCode.SByte:
504 w.WriteStartElement("I1");
505 if (!(Name is null))
506 w.WriteAttributeString("n", string.Empty, Name);
507 w.WriteAttributeString("v", string.Empty, Value.ToString());
508 w.WriteEndElement();
509 break;
510
511 case TypeCode.Single:
512 w.WriteStartElement("Fl");
513 if (!(Name is null))
514 w.WriteAttributeString("n", string.Empty, Name);
515 w.WriteAttributeString("v", string.Empty, CommonTypes.Encode((float)Value));
516 w.WriteEndElement();
517 break;
518
519 case TypeCode.String:
520 string s = Value.ToString();
521 try
522 {
523 XmlConvert.VerifyXmlChars(s);
524 w.WriteStartElement("S");
525 if (!(Name is null))
526 w.WriteAttributeString("n", string.Empty, Name);
527 w.WriteAttributeString("v", string.Empty, s);
528 w.WriteEndElement();
529 }
530 catch (XmlException)
531 {
532 byte[] Bin = Encoding.UTF8.GetBytes(s);
533 s = Convert.ToBase64String(Bin);
534 w.WriteStartElement("S64");
535 if (!(Name is null))
536 w.WriteAttributeString("n", string.Empty, Name);
537 w.WriteAttributeString("v", string.Empty, s);
538 w.WriteEndElement();
539 }
540 break;
541
542 case TypeCode.UInt16:
543 w.WriteStartElement("U2");
544 if (!(Name is null))
545 w.WriteAttributeString("n", string.Empty, Name);
546 w.WriteAttributeString("v", string.Empty, Value.ToString());
547 w.WriteEndElement();
548 break;
549
550 case TypeCode.UInt32:
551 w.WriteStartElement("U4");
552 if (!(Name is null))
553 w.WriteAttributeString("n", string.Empty, Name);
554 w.WriteAttributeString("v", string.Empty, Value.ToString());
555 w.WriteEndElement();
556 break;
557
558 case TypeCode.UInt64:
559 w.WriteStartElement("U8");
560 if (!(Name is null))
561 w.WriteAttributeString("n", string.Empty, Name);
562 w.WriteAttributeString("v", string.Empty, Value.ToString());
563 w.WriteEndElement();
564 break;
565
566 case TypeCode.DBNull:
567 case TypeCode.Empty:
568 w.WriteStartElement("Null");
569 if (!(Name is null))
570 w.WriteAttributeString("n", string.Empty, Name);
571 w.WriteEndElement();
572 break;
573
574 case TypeCode.Object:
575 if (Value is TimeSpan)
576 {
577 w.WriteStartElement("TS");
578 if (!(Name is null))
579 w.WriteAttributeString("n", string.Empty, Name);
580 w.WriteAttributeString("v", string.Empty, Value.ToString());
581 w.WriteEndElement();
582 }
583 else if (Value is DateTimeOffset DTO)
584 {
585 w.WriteStartElement("DTO");
586 if (!(Name is null))
587 w.WriteAttributeString("n", string.Empty, Name);
588 w.WriteAttributeString("v", string.Empty, XML.Encode(DTO));
589 w.WriteEndElement();
590 }
591 else if (Value is CaseInsensitiveString Cis)
592 {
593 s = Cis.Value;
594 try
595 {
596 XmlConvert.VerifyXmlChars(s);
597 w.WriteStartElement("CIS");
598 if (!(Name is null))
599 w.WriteAttributeString("n", string.Empty, Name);
600 w.WriteAttributeString("v", string.Empty, s);
601 w.WriteEndElement();
602 }
603 catch (XmlException)
604 {
605 byte[] Bin = Encoding.UTF8.GetBytes(s);
606 s = Convert.ToBase64String(Bin);
607 w.WriteStartElement("CIS64");
608 if (!(Name is null))
609 w.WriteAttributeString("n", string.Empty, Name);
610 w.WriteAttributeString("v", string.Empty, s);
611 w.WriteEndElement();
612 }
613 }
614 else if (Value is byte[] Bin)
615 {
616 w.WriteStartElement("Bin");
617 if (!(Name is null))
618 w.WriteAttributeString("n", string.Empty, Name);
619
620 byte[] Buf = null;
621 long c = Bin.Length;
622 long i = 0;
623 long d;
624 int j;
625
626 while (i < c)
627 {
628 d = c - i;
629 if (d > 49152)
630 j = 49152;
631 else
632 j = (int)d;
633
634 if (Buf is null)
635 {
636 if (i == 0 && j == c)
637 Buf = Bin;
638 else
639 Buf = new byte[j];
640 }
641
642 if (Buf != Bin)
643 Array.Copy(Bin, i, Buf, 0, j);
644
645 w.WriteElementString("Chunk", Convert.ToBase64String(Buf, 0, j, Base64FormattingOptions.None));
646 i += j;
647 }
648
649 w.WriteEndElement();
650 }
651 else if (Value is Guid)
652 {
653 w.WriteStartElement("ID");
654 if (!(Name is null))
655 w.WriteAttributeString("n", string.Empty, Name);
656 w.WriteAttributeString("v", string.Empty, Value.ToString());
657 w.WriteEndElement();
658 }
659 else if (Value is Array A)
660 {
661 w.WriteStartElement("Array");
662 if (!(Name is null))
663 w.WriteAttributeString("n", string.Empty, Name);
664 w.WriteAttributeString("elementType", string.Empty, Value.GetType().GetElementType().FullName);
665
666 foreach (object Obj in A)
667 this.WriteProperty(w, null, Obj);
668
669 w.WriteEndElement();
670 }
671 else if (Value is GenericObject Obj)
672 {
673 w.WriteStartElement("Obj");
674 if (!(Name is null))
675 w.WriteAttributeString("n", string.Empty, Name);
676 w.WriteAttributeString("type", string.Empty, Obj.TypeName);
677
678 foreach (KeyValuePair<string, object> P in Obj)
679 this.WriteProperty(w, P.Key, P.Value);
680
681 w.WriteEndElement();
682 }
683 else
684 throw new Exception("Unhandled property value type: " + Value.GetType().FullName);
685 break;
686
687 default:
688 throw new Exception("Unhandled property value type: " + Value.GetType().FullName);
689 }
690 }
691 }
692
693 }
694}
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:13
static string Encode(bool x)
Encodes a Boolean for use in XML and other formats.
Definition: CommonTypes.cs:594
Helps with common JSON-related tasks.
Definition: JSON.cs:14
static string Encode(string s)
Encodes a string for inclusion in JSON.
Definition: JSON.cs:507
const string DefaultContentType
application/json
Definition: JsonCodec.cs:19
XML encoder/decoder.
Definition: XmlCodec.cs:16
const string DefaultContentType
Default content type for XML documents.
Definition: XmlCodec.cs:27
const string SchemaContentType
Default content type for XML schema documents.
Definition: XmlCodec.cs:32
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
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:18
HttpRequestHeader Header
Request header.
Definition: HttpRequest.cs:134
string RemoteEndPoint
Remote end-point.
Definition: HttpRequest.cs:195
string SubPath
Sub-path. If a resource is found handling the request, this property contains the trailing sub-path o...
Definition: HttpRequest.cs:146
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:21
async Task SendResponse()
Sends the response back to the client. If the resource is synchronous, there's no need to call this m...
void SetHeader(string FieldName, string Value)
Sets a custom header field value.
async Task Write(byte[] Data)
Returns binary data in the response.
Implements an HTTP server.
Definition: HttpServer.cs:36
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:59
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:19
static async Task Delete(object Object)
Deletes an object in the database.
Definition: Database.cs:717
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
DateTime Timestamp
Timestamp of entry.
Definition: Entry.cs:37
EntryType Type
Entry Type
Definition: Entry.cs:32
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.
T Current
Gets the element in the collection at the current position of the enumerator.
async Task< bool > MoveNextAsync()
Advances the enumerator to the next element of the collection.
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:52
GET Interface for HTTP resources.
Basic interface for a user.
Definition: IUser.cs:7
SubscriptionState
State of a presence subscription.
Definition: RosterItem.cs:16
EntryType
Ledger entry type.
Definition: ILedgerEntry.cs:9