Files
WPinternals/Models/LumiaDownloadModel.cs
T
2018-10-25 22:35:49 +02:00

479 lines
16 KiB
C#

// Copyright (c) 2018, Rene Lergner - wpinternals.net - @Heathcliff74xda
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.IO;
using System.Xml;
namespace WPinternals
{
internal static class LumiaDownloadModel
{
internal static string SearchFFU(string ProductType, string ProductCode, string OperatorCode)
{
string FoundProductType;
return SearchFFU(ProductType, ProductCode, OperatorCode, out FoundProductType);
}
internal static string SearchFFU(string ProductType, string ProductCode, string OperatorCode, out string FoundProductType)
{
if (ProductType == "")
ProductType = null;
if (ProductCode == "")
ProductCode = null;
if (OperatorCode == "")
OperatorCode = null;
if (ProductCode != null)
{
ProductCode = ProductCode.ToUpper();
ProductType = null;
OperatorCode = null;
}
if (ProductType != null)
{
ProductType = ProductType.ToUpper();
if (ProductType.StartsWith("RM") && !ProductType.StartsWith("RM-"))
ProductType = "RM-" + ProductType.Substring(2);
}
if (OperatorCode != null)
OperatorCode = OperatorCode.ToUpper();
DiscoveryQueryParameters DiscoveryQueryParams = new DiscoveryQueryParameters
{
manufacturerName = "Microsoft",
manufacturerProductLine = "Lumia",
packageType = "Firmware",
packageClass = "Public",
manufacturerHardwareModel = ProductType,
manufacturerHardwareVariant = ProductCode,
operatorName = OperatorCode
};
DiscoveryParameters DiscoveryParams = new DiscoveryParameters
{
query = DiscoveryQueryParams
};
DataContractJsonSerializer Serializer1 = new DataContractJsonSerializer(typeof(DiscoveryParameters));
MemoryStream JsonStream1 = new MemoryStream();
Serializer1.WriteObject(JsonStream1, DiscoveryParams);
JsonStream1.Seek(0L, SeekOrigin.Begin);
string JsonContent = new StreamReader(JsonStream1).ReadToEnd();
Uri RequestUri = new Uri("https://api.swrepository.com/rest-api/discovery/1/package");
HttpClient HttpClient = new HttpClient();
HttpClient.DefaultRequestHeaders.UserAgent.TryParseAdd("SoftwareRepository");
HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Task<HttpResponseMessage> HttpPostTask = HttpClient.PostAsync(RequestUri, new StringContent(JsonContent, Encoding.UTF8, "application/json"));
HttpPostTask.Wait();
HttpResponseMessage Response = HttpPostTask.Result;
string JsonResultString = "";
if (Response.StatusCode == HttpStatusCode.OK)
{
Task<string> ReadResponseTask = Response.Content.ReadAsStringAsync();
ReadResponseTask.Wait();
JsonResultString = ReadResponseTask.Result;
}
SoftwarePackage Package = null;
using (MemoryStream JsonStream2 = new MemoryStream(Encoding.UTF8.GetBytes(JsonResultString)))
{
DataContractJsonSerializer Serializer2 = new DataContractJsonSerializer(typeof(SoftwarePackages));
SoftwarePackages SoftwarePackages = (SoftwarePackages)Serializer2.ReadObject(JsonStream2);
if (SoftwarePackages != null)
{
Package = SoftwarePackages.softwarePackages.FirstOrDefault<SoftwarePackage>();
}
}
if (Package == null)
throw new WPinternalsException("FFU not found");
FoundProductType = Package.manufacturerHardwareModel[0];
SoftwareFile FileInfo = Package.files.Where(f => f.fileName.EndsWith(".ffu", StringComparison.OrdinalIgnoreCase)).First();
Uri FileInfoUri = new Uri("https://api.swrepository.com/rest-api/discovery/fileurl/1/" + Package.id + "/" + FileInfo.fileName);
Task<string> GetFileInfoTask = HttpClient.GetStringAsync(FileInfoUri);
GetFileInfoTask.Wait();
string FileInfoString = GetFileInfoTask.Result;
string FfuUrl = "";
FileUrlResult FileUrl = null;
using (MemoryStream JsonStream3 = new MemoryStream(Encoding.UTF8.GetBytes(FileInfoString)))
{
DataContractJsonSerializer Serializer3 = new DataContractJsonSerializer(typeof(FileUrlResult));
FileUrl = (FileUrlResult)Serializer3.ReadObject(JsonStream3);
if (FileUrl != null)
{
FfuUrl = FileUrl.url;
}
}
HttpClient.Dispose();
return FfuUrl;
}
internal static string[] SearchEmergencyFiles(string ProductType)
{
ProductType = ProductType.ToUpper();
if (ProductType.StartsWith("RM") && !ProductType.StartsWith("RM-"))
ProductType = "RM-" + ProductType.Substring(2);
LogFile.Log("Getting Emergency files for: " + ProductType, LogType.FileAndConsole);
if ((ProductType == "RM-1072") || (ProductType == "RM-1073"))
{
LogFile.Log("Due to mix-up in online-repository, redirecting to emergency files of RM-1113", LogType.FileAndConsole);
ProductType = "RM-1113";
}
List<string> Result = new List<string>();
WebClient Client = new WebClient();
string Src;
string FileName;
string Config = null;
try
{
Config = Client.DownloadString(@"https://repairavoidance.blob.core.windows.net/packages/EmergencyFlash/" + ProductType + "/emergency_flash_config.xml");
}
catch
{
LogFile.Log("Emergency files for " + ProductType + " not found", LogType.FileAndConsole);
return null;
}
Client.Dispose();
XmlDocument Doc = new XmlDocument();
Doc.LoadXml(Config);
// Hex
XmlNode Node = Doc.SelectSingleNode("//emergency_flash_config/hex_flasher");
if (Node != null)
{
FileName = Node.Attributes["image_path"].InnerText;
Src = @"https://repairavoidance.blob.core.windows.net/packages/EmergencyFlash/" + ProductType + "/" + FileName;
LogFile.Log("Hex-file: " + Src);
Result.Add(Src);
}
// Mbn
Node = Doc.SelectSingleNode("//emergency_flash_config/mbn_image");
if (Node != null)
{
FileName = Node.Attributes["image_path"].InnerText;
Src = @"https://repairavoidance.blob.core.windows.net/packages/EmergencyFlash/" + ProductType + "/" + FileName;
LogFile.Log("Mbn-file: " + Src);
Result.Add(Src);
}
// Ede
foreach (XmlNode SubNode in Doc.SelectNodes("//emergency_flash_config/first_boot_images/first_boot_image"))
{
FileName = SubNode.Attributes["image_path"].InnerText;
Src = @"https://repairavoidance.blob.core.windows.net/packages/EmergencyFlash/" + ProductType + "/" + FileName;
LogFile.Log("Firehose-programmer-file: " + Src);
Result.Add(Src);
}
// Edp
foreach (XmlNode SubNode in Doc.SelectNodes("//emergency_flash_config/second_boot_firehose_single_image/firehose_image"))
{
FileName = SubNode.Attributes["image_path"].InnerText;
Src = @"https://repairavoidance.blob.core.windows.net/packages/EmergencyFlash/" + ProductType + "/" + FileName;
LogFile.Log("Firehose-payload-file: " + Src);
Result.Add(Src);
}
return Result.ToArray();
}
}
#pragma warning disable 0649
[DataContract]
internal class FileUrlResult
{
[DataMember]
internal string url;
[DataMember]
internal List<string> alternateUrl;
[DataMember]
internal long fileSize;
[DataMember]
internal List<SoftwareFileChecksum> checksum;
}
#pragma warning restore 0649
[DataContract]
public class DiscoveryQueryParameters
{
[DataMember(EmitDefaultValue = false)]
public string customerName;
[DataMember(EmitDefaultValue = false)]
public ExtendedAttributes extendedAttributes;
[DataMember(EmitDefaultValue = false)]
public string manufacturerHardwareModel;
[DataMember(EmitDefaultValue = false)]
public string manufacturerHardwareVariant;
[DataMember(EmitDefaultValue = false)]
public string manufacturerModelName;
[DataMember]
public string manufacturerName;
[DataMember(EmitDefaultValue = false)]
public string manufacturerPackageId;
[DataMember(EmitDefaultValue = false)]
public string manufacturerPlatformId;
[DataMember]
public string manufacturerProductLine;
[DataMember(EmitDefaultValue = false)]
public string manufacturerVariantName;
[DataMember(EmitDefaultValue = false)]
public string operatorName;
[DataMember]
public string packageClass;
[DataMember(EmitDefaultValue = false)]
public string packageRevision;
[DataMember(EmitDefaultValue = false)]
public string packageState;
[DataMember(EmitDefaultValue = false)]
public string packageSubRevision;
[DataMember(EmitDefaultValue = false)]
public string packageSubtitle;
[DataMember(EmitDefaultValue = false)]
public string packageTitle;
[DataMember]
public string packageType;
}
[DataContract]
public class DiscoveryParameters
{
[DataMember(Name = "api-version")]
public string apiVersion;
[DataMember]
public DiscoveryQueryParameters query;
[DataMember]
public List<string> condition;
[DataMember]
public List<string> response;
public DiscoveryParameters(): this(DiscoveryCondition.Default)
{
}
public DiscoveryParameters(DiscoveryCondition Condition)
{
this.apiVersion = "1";
this.query = new DiscoveryQueryParameters();
this.condition = new List<string>();
if (Condition == DiscoveryCondition.All)
{
this.condition.Add("all");
return;
}
if (Condition == DiscoveryCondition.Latest)
{
this.condition.Add("latest");
return;
}
this.condition.Add("default");
}
}
public enum DiscoveryCondition
{
Default,
All,
Latest
}
[Serializable]
public class ExtendedAttributes : ISerializable
{
public Dictionary<string, string> Dictionary;
public ExtendedAttributes()
{
this.Dictionary = new Dictionary<string, string>();
}
protected ExtendedAttributes(SerializationInfo info, StreamingContext context)
{
if (info != null)
{
this.Dictionary = new Dictionary<string, string>();
SerializationInfoEnumerator Enumerator = info.GetEnumerator();
while (Enumerator.MoveNext())
{
this.Dictionary.Add(Enumerator.Current.Name, (string)Enumerator.Current.Value);
}
}
}
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info != null)
{
foreach (string Current in this.Dictionary.Keys)
{
info.AddValue(Current, this.Dictionary[Current]);
}
}
}
}
[DataContract]
public class SoftwareFileChecksum
{
[DataMember]
public string type;
[DataMember]
public string value;
}
[DataContract]
public class SoftwarePackages
{
[DataMember]
public List<SoftwarePackage> softwarePackages;
}
[DataContract]
public class SoftwarePackage
{
[DataMember]
public List<string> customerName;
[DataMember]
public ExtendedAttributes extendedAttributes;
[DataMember]
public List<SoftwareFile> files;
[DataMember]
public string id;
[DataMember]
public List<string> manufacturerHardwareModel;
[DataMember]
public List<string> manufacturerHardwareVariant;
[DataMember]
public List<string> manufacturerModelName;
[DataMember]
public string manufacturerName;
[DataMember]
public string manufacturerPackageId;
[DataMember]
public List<string> manufacturerPlatformId;
[DataMember]
public string manufacturerProductLine;
[DataMember]
public List<string> manufacturerVariantName;
[DataMember]
public List<string> operatorName;
[DataMember]
public List<string> packageClass;
[DataMember]
public string packageDescription;
[DataMember]
public string packageRevision;
[DataMember]
public string packageState;
[DataMember]
public string packageSubRevision;
[DataMember]
public string packageSubtitle;
[DataMember]
public string packageTitle;
[DataMember]
public string packageType;
}
[DataContract]
public class SoftwareFile
{
[DataMember]
public List<SoftwareFileChecksum> checksum;
[DataMember]
public string fileName;
[DataMember]
public long fileSize;
[DataMember]
public string fileType;
}
}