2using System.Collections.Generic;
4using System.Runtime.ExceptionServices;
5using System.Threading.Tasks;
20 private static int expectedBlockSignature = 0;
23 : base(
"/UploadSignature")
27 public override bool HandlesSubPaths =>
false;
28 public override bool UserSessions =>
true;
33 KeyValuePair<bool, int> P = await
UploadPackage.Upload(Request, Response, expectedBlockSignature, signatureFilePerSession,
"signature",
false);
34 expectedBlockSignature = P.Value;
38 UploadPackage.UploadRec PackageRec;
39 UploadPackage.UploadRec SignatureRec;
50 SignatureRec = GetAndRemoveFile(
HttpSessionID, signatureFilePerSession);
52 CopyPackage(PackageRec, SignatureRec, TabID, Request.
Session[
"packageFileName"]?.ToString(), Request.
RemoteEndPoint);
56 private static UploadPackage.UploadRec GetAndRemoveFile(
string SessionID, Dictionary<string, UploadPackage.UploadRec> Files)
62 Files.Remove(SessionID);
70 private static async
void CopyPackage(UploadPackage.UploadRec PackageRec, UploadPackage.UploadRec SignatureRec,
string TabID,
71 string PackageFileName,
string RemoteEndpoint)
75 if (PackageRec.File.Length >
int.MaxValue)
76 throw new Exception(
"Package file too large.");
78 XmlDocument Doc =
new XmlDocument()
80 PreserveWhitespace =
true
82 SignatureRec.File.Position = 0;
83 Doc.Load(SignatureRec.File);
85 if (Doc.DocumentElement is
null ||
86 Doc.DocumentElement.LocalName !=
"Signatures" ||
87 Doc.DocumentElement.NamespaceURI !=
"http://waher.se/Schema/Signatures.xsd")
89 throw new Exception(
"Invalid signature file.");
92 byte[] Signature =
null;
94 foreach (XmlNode N
in Doc.DocumentElement.ChildNodes)
96 if (N is XmlElement E && E.LocalName ==
"Signature" &&
XML.
Attribute(E,
"fileName") == PackageFileName)
100 Signature = Convert.FromBase64String(E.InnerText);
104 throw new Exception(
"Invalid signature.");
110 if (Signature is
null)
111 throw new Exception(
"Signature for corresponding package file not included in uploaded signature file.");
113 await CopyPackage(PackageRec, Signature, TabID, PackageFileName, RemoteEndpoint);
123 PackageRec.File.Dispose();
124 SignatureRec.File.Dispose();
128 internal static async Task CopyPackage(UploadPackage.UploadRec PackageRec,
byte[] Signature,
string TabID,
129 string PackageFileName,
string RemoteEndpoint)
131 DateTime Now = DateTime.UtcNow;
132 Package Package = await Provisioning.ProvisioningComponent.GetPackage(PackageFileName);
133 long Size = PackageRec.File.Length;
134 bool PrevDownloadable;
135 bool Downloadable = PackageRec.MakeDownloadable;
139 PrevDownloadable =
false;
143 FileName = PackageFileName,
144 Signature = Signature,
145 RemoteEndpoint = RemoteEndpoint,
147 Supersedes = DateTime.MinValue,
151 Installed = DateTime.MinValue,
162 Package.Signature = Signature;
163 Package.RemoteEndpoint = RemoteEndpoint;
165 Package.Published = Now;
166 Package.Bytes = Size;
167 Package.Downloadable = Downloadable;
176 bool InstallPackage = Package.Installed > DateTime.MinValue;
182 PackageRec.File.Position = 0;
184 throw new Exception(
"Invalid IoT Broker package. Signature invalid.");
187 using (FileStream f = File.Create(Path.Combine(
XmppServerModule.PackagesFolder, PackageFileName)))
189 PackageRec.File.Position = 0;
190 await PackageRec.File.CopyToAsync(f);
193 if (PackageRec.MakeDownloadable)
197 if (!Directory.Exists(DownloadsFolder))
198 Directory.CreateDirectory(DownloadsFolder);
200 using (FileStream f = File.Create(Path.Combine(DownloadsFolder, PackageFileName)))
202 PackageRec.File.Position = 0;
203 await PackageRec.File.CopyToAsync(f);
210 ExceptionDispatchInfo.Capture(ex).Throw();
213 if (PrevDownloadable && !Downloadable)
217 if (File.Exists(FullPath))
218 File.Delete(FullPath);
227 "\", \"supersedes\": \"" + (Package.Supersedes == DateTime.MinValue ? string.Empty :
Package.
Supersedes.ToString()) +
230 "\", \"signature\": \"<a href='javascript:window.alert(\\\"" + s +
"\\\")'>" + s.Substring(0, 10) +
"...</a>" +
231 "\", \"button\": \"<button class='negButtonSm' onclick='DeletePackage(\\\"" +
Package.
FileName.
Replace(
"\"",
"\\\"") +
"\\\")'>Delete</button>" +
232 "\", \"message\": \"Package successfully uploaded.\"}",
true,
"User");
236 if (NewSoftware || InstallPackage)
Helps with parsing of commong data types.
static string JsonStringEncode(string s)
Encodes a string for inclusion in JSON.
Helps with common XML-related tasks.
static string Attribute(XmlElement E, string Name)
Gets the value of an XML attribute.
The ClientEvents class allows applications to push information asynchronously to web clients connecte...
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.
static string FormatBytes(double Bytes)
Formats a file size using appropriate unit.
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repe...
Base class for all HTTP fields.
Represents an HTTP request.
HttpRequestHeader Header
Request header.
string RemoteEndPoint
Remote end-point.
Variables Session
Contains session states, if the resource requires sessions, or null otherwise.
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"
Represets a response of an HTTP client request.
Base class for all synchronous HTTP resources. A synchronous resource responds within the method hand...
CaseInsensitiveString Replace(CaseInsensitiveString oldValue, CaseInsensitiveString newValue)
Returns a new string in which all occurrences of a specified string in the current instance are repla...
Static interface for database persistence. In order to work, a database provider has to be assigned t...
static async Task Update(object Object)
Updates an object in the database.
static async Task Delete(object Object)
Deletes an object in the database.
static async Task Insert(object Object)
Inserts an object into the default collection of the database.
Identity of the IoT Broker package.
const string FileName
IoTBroker.package
Contains information about a software package.
bool Downloadable
If package should be made downloadable via web interface.
byte[] Signature
Cryptographic signature of package, as calculated by the issuer of the package.
CaseInsensitiveString FileName
Filename of package.
DateTime Published
When package was published.
byte[] AesKey
Symmetric cipher used to encrypt package file.
long Bytes
Number of bytes of package.
DateTime Supersedes
Timestamp of superceded package.
string RemoteEndpoint
Remote Endpoint from where the package was downloaded or uploaded.
string RelativeUrl
Relative URL of package.
DateTime Created
When package record was created
bool AllowsPOST
If the POST method is allowed.
async Task POST(HttpRequest Request, HttpResponse Response)
Executes the POST method on the resource.
Service Module hosting the XMPP broker and its components.
POST Interface for HTTP resources.