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;
3using System.Threading.Tasks;
4using Waher.Content;
8using Waher.Script;
9
11{
13 {
14 internal static readonly Dictionary<string, UploadRec> packageFilePerSession = new Dictionary<string, UploadRec>();
15 private static int expectedBlockPackage = 0;
16
17 public UploadPackage()
18 : base("/UploadPackage")
19 {
20 }
21
22 internal class UploadRec
23 {
24 public TemporaryFile File;
25 public bool MakeDownloadable;
26 }
27
28 public override bool HandlesSubPaths => false;
29 public override bool UserSessions => true;
30 public bool AllowsPOST => true;
31
32 public async Task POST(HttpRequest Request, HttpResponse Response)
33 {
34 KeyValuePair<bool, int> P = await Upload(Request, Response, expectedBlockPackage, packageFilePerSession, "package", true);
35 expectedBlockPackage = P.Value;
36 }
37
38 internal static void RemoveFile(string Key, Dictionary<string, UploadRec> Files)
39 {
40 lock (Files)
41 {
42 if (Files.TryGetValue(Key, out UploadRec Rec))
43 {
44 Files.Remove(Key);
45 Rec.File.Dispose();
46 }
47 }
48 }
49
50 internal static async Task<KeyValuePair<bool, int>> Upload(HttpRequest Request, HttpResponse Response, int ExpectedBlockNr,
51 Dictionary<string, UploadRec> Files, string Name, bool PushToClient)
52 {
53 Gateway.AssertUserAuthenticated(Request, "Admin.Software.Upload");
54
55 UploadRec Rec;
56 string TabID;
57 string HttpSessionID;
58 string FileName;
59
60 if (!Request.HasData ||
61 !Request.Header.TryGetHeaderField("X-TabID", out HttpField F) || string.IsNullOrEmpty(TabID = F.Value) ||
62 !Request.Header.TryGetHeaderField("X-BlockNr", out F) || !int.TryParse(F.Value, out int BlockNr) ||
63 !Request.Header.TryGetHeaderField("X-More", out F) || !CommonTypes.TryParse(F.Value, out bool More) ||
64 string.IsNullOrEmpty(HttpSessionID = GetSessionId(Request, Response)))
65 {
66 throw new BadRequestException();
67 }
68
69 if (!Request.Header.TryGetHeaderField("X-Downloadable", out F) || !CommonTypes.TryParse(F.Value, out bool Downloadable))
70 Downloadable = false;
71
72 if (!Request.Header.TryGetHeaderField("X-GenSign", out F) || !CommonTypes.TryParse(F.Value, out bool GenerateSignature))
73 GenerateSignature = false;
74
75 if (BlockNr == 0)
76 {
77 ExpectedBlockNr = 0;
78 RemoveFile(HttpSessionID, Files);
79
80 if (Request.Header.TryGetHeaderField("X-FileName", out F) && !string.IsNullOrEmpty(FileName = F.Value))
81 Request.Session[Name + "FileName"] = F.Value;
82 else
83 throw new BadRequestException();
84 }
85 else if (Request.Session.TryGetVariable(Name + "FileName", out Variable v))
86 FileName = v.ValueObject as string;
87 else
88 throw new BadRequestException();
89
90 if (BlockNr != ExpectedBlockNr)
91 throw new BadRequestException();
92
93 ExpectedBlockNr++;
94
95 lock (Files)
96 {
97 if (!Files.TryGetValue(HttpSessionID, out Rec))
98 {
99 Rec = new UploadRec()
100 {
101 File = new TemporaryFile(),
102 MakeDownloadable = Downloadable
103 };
104
105 Files[HttpSessionID] = Rec;
106 }
107 else
108 Rec.MakeDownloadable |= Downloadable;
109 }
110
111 try
112 {
113 await Request.DataStream.CopyToAsync(Rec.File);
114
115 long FileLength = Rec.File.Length;
116
117 if (!More)
118 {
119 Rec.File.Flush();
120
121 if (GenerateSignature)
122 {
123 Rec.File.Position = 0;
124 byte[] Signature = XmppServerModule.Legal.Sign(Rec.File);
125
126 await UploadSignature.CopyPackage(Rec, Signature, TabID, FileName, Request.RemoteEndPoint);
127
128 RemoveFile(HttpSessionID, Files);
129 }
130 }
131
132 if (PushToClient)
133 {
134 await ClientEvents.PushEvent(new string[] { TabID }, "UpdatePackage",
135 "{\"fileName\":\"" + CommonTypes.JsonStringEncode(FileName) +
136 "\", \"bytes\": \"" + Export.FormatBytes(FileLength) + "\"}", true, "User");
137 }
138
139 Response.StatusCode = 200;
140 Response.StatusMessage = "OK";
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:15
static string Encode(bool x)
Encodes a Boolean for use in XML and other formats.
Definition: CommonTypes.cs:596
static bool TryParse(string s, out double Value)
Tries to decode a string encoded double.
Definition: CommonTypes.cs:48
static string JsonStringEncode(string s)
Encodes a string for inclusion in JSON.
Definition: CommonTypes.cs:805
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:18
static string FormatBytes(double Bytes)
Formats a file size using appropriate unit.
Definition: Export.cs:125
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
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:247
Represents an HTTP request.
Definition: HttpRequest.cs:22
Stream DataStream
Data stream, if data is available, or null if data is not available.
Definition: HttpRequest.cs:187
HttpRequestHeader Header
Request header.
Definition: HttpRequest.cs:182
string RemoteEndPoint
Remote end-point.
Definition: HttpRequest.cs:243
bool HasData
If the request has data.
Definition: HttpRequest.cs:113
SessionVariables Session
Contains session states, if the resource requires sessions, or null otherwise.
Definition: HttpRequest.cs:212
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:23
Base class for all synchronous HTTP resources. A synchronous resource responds within the method hand...
override bool TryGetVariable(string Name, out Variable Variable)
Tries to get a variable object, given its name.
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
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.