Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
UploadPackage.cs
1using System;
2using System.Collections.Generic;
3using System.Threading.Tasks;
4using Waher.Content;
9using Waher.Script;
10
12{
14 {
15 internal static readonly Dictionary<string, UploadRec> packageFilePerSession = new Dictionary<string, UploadRec>();
16 private static int expectedBlockPackage = 0;
17
18 public UploadPackage()
19 : base("/UploadPackage")
20 {
21 }
22
23 internal class UploadRec
24 {
25 public TemporaryFile File;
26 public bool MakeDownloadable;
27 }
28
29 public override bool HandlesSubPaths => false;
30 public override bool UserSessions => true;
31 public bool AllowsPOST => true;
32
33 public async Task POST(HttpRequest Request, HttpResponse Response)
34 {
35 KeyValuePair<bool, int> P = await Upload(Request, Response, expectedBlockPackage, packageFilePerSession, "package", true);
36 expectedBlockPackage = P.Value;
37 }
38
39 internal static void RemoveFile(string Key, Dictionary<string, UploadRec> Files)
40 {
41 lock (Files)
42 {
43 if (Files.TryGetValue(Key, out UploadRec Rec))
44 {
45 Files.Remove(Key);
46 Rec.File.Dispose();
47 }
48 }
49 }
50
51 internal static async Task<KeyValuePair<bool, int>> Upload(HttpRequest Request, HttpResponse Response, int ExpectedBlockNr,
52 Dictionary<string, UploadRec> Files, string Name, bool PushToClient)
53 {
54 Gateway.AssertUserAuthenticated(Request, "Admin.Software.Upload");
55
56 UploadRec Rec;
57 string TabID;
58 string HttpSessionID;
59 string FileName;
60
61 if (!Request.HasData ||
62 !Request.Header.TryGetHeaderField("X-TabID", out HttpField F) || string.IsNullOrEmpty(TabID = F.Value) ||
63 !Request.Header.TryGetHeaderField("X-BlockNr", out F) || !int.TryParse(F.Value, out int BlockNr) ||
64 !Request.Header.TryGetHeaderField("X-More", out F) || !CommonTypes.TryParse(F.Value, out bool More) ||
65 string.IsNullOrEmpty(HttpSessionID = GetSessionId(Request, Response)))
66 {
67 throw new BadRequestException();
68 }
69
70 if (!Request.Header.TryGetHeaderField("X-Downloadable", out F) || !CommonTypes.TryParse(F.Value, out bool Downloadable))
71 Downloadable = false;
72
73 if (!Request.Header.TryGetHeaderField("X-GenSign", out F) || !CommonTypes.TryParse(F.Value, out bool GenerateSignature))
74 GenerateSignature = false;
75
76 if (BlockNr == 0)
77 {
78 ExpectedBlockNr = 0;
79 RemoveFile(HttpSessionID, Files);
80
81 if (Request.Header.TryGetHeaderField("X-FileName", out F) && !string.IsNullOrEmpty(FileName = F.Value))
82 Request.Session[Name + "FileName"] = F.Value;
83 else
84 throw new BadRequestException();
85 }
86 else if (Request.Session.TryGetVariable(Name + "FileName", out Variable v))
87 FileName = v.ValueObject as string;
88 else
89 throw new BadRequestException();
90
91 if (BlockNr != ExpectedBlockNr)
92 throw new BadRequestException();
93
94 ExpectedBlockNr++;
95
96 lock (Files)
97 {
98 if (!Files.TryGetValue(HttpSessionID, out Rec))
99 {
100 Rec = new UploadRec()
101 {
102 File = new TemporaryFile(),
103 MakeDownloadable = Downloadable
104 };
105
106 Files[HttpSessionID] = Rec;
107 }
108 else
109 Rec.MakeDownloadable |= Downloadable;
110 }
111
112 try
113 {
114 await Request.DataStream.CopyToAsync(Rec.File);
115
116 long FileLength = Rec.File.Length;
117
118 if (!More)
119 {
120 Rec.File.Flush();
121
122 if (GenerateSignature)
123 {
124 Rec.File.Position = 0;
125 byte[] Signature = XmppServerModule.Legal.Sign(Rec.File);
126
127 await UploadSignature.CopyPackage(Rec, Signature, TabID, FileName, Request.RemoteEndPoint);
128
129 RemoveFile(HttpSessionID, Files);
130 }
131 }
132
133 if (PushToClient)
134 {
135 await ClientEvents.PushEvent(new string[] { TabID }, "UpdatePackage",
136 "{\"fileName\":\"" + CommonTypes.JsonStringEncode(FileName) +
137 "\", \"bytes\": \"" + Export.FormatBytes(FileLength) + "\"}", true, "User");
138 }
139
140 Response.StatusCode = 200;
141 }
142 catch (Exception ex)
143 {
144 await ClientEvents.PushEvent(new string[] { TabID }, "UploadFailed",
145 "{\"fileName\":\"" + CommonTypes.JsonStringEncode(FileName) +
146 "\", \"message\": \"" + CommonTypes.JsonStringEncode(ex.Message) +
147 "\", \"remove\": " + CommonTypes.Encode(PushToClient) + "}", true, "User");
148 }
149
150 return new KeyValuePair<bool, int>(!More, ExpectedBlockNr);
151 }
152
153 }
154}
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
static bool TryParse(string s, out double Value)
Tries to decode a string encoded double.
Definition: CommonTypes.cs:46
static string JsonStringEncode(string s)
Encodes a string for inclusion in JSON.
Definition: CommonTypes.cs:803
The ClientEvents class allows applications to push information asynchronously to web clients connecte...
Definition: ClientEvents.cs:51
static Task< int > PushEvent(string[] TabIDs, string Type, object Data)
Puses an event to a set of Tabs, given their Tab IDs.
Static class managing data export.
Definition: Export.cs:19
static string FormatBytes(double Bytes)
Formats a file size using appropriate unit.
Definition: Export.cs:126
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
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repe...
Base class for all HTTP fields.
Definition: HttpField.cs:7
bool TryGetHeaderField(string FieldName, out HttpField Field)
Tries to get a named header field.
Definition: HttpHeader.cs:227
Represents an HTTP request.
Definition: HttpRequest.cs:18
Stream DataStream
Data stream, if data is available, or null if data is not available.
Definition: HttpRequest.cs:139
HttpRequestHeader Header
Request header.
Definition: HttpRequest.cs:134
string RemoteEndPoint
Remote end-point.
Definition: HttpRequest.cs:195
bool HasData
If the request has data.
Definition: HttpRequest.cs:74
Variables Session
Contains session states, if the resource requires sessions, or null otherwise.
Definition: HttpRequest.cs:164
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
Represets a response of an HTTP client request.
Definition: HttpResponse.cs:21
Base class for all synchronous HTTP resources. A synchronous resource responds within the method hand...
Class managing the contents of a temporary file. When the class is disposed, the temporary file is de...
Contains information about a variable.
Definition: Variable.cs:10
virtual bool TryGetVariable(string Name, out Variable Variable)
Tries to get a variable object, given its name.
Definition: Variables.cs:52
async Task POST(HttpRequest Request, HttpResponse Response)
Executes the POST method on the resource.
bool AllowsPOST
If the POST method is allowed.
POST Interface for HTTP resources.