mirror of
https://github.com/ReneLergner/WPinternals.git
synced 2026-06-14 03:16:40 +10:00
479 lines
16 KiB
C#
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;
|
|
}
|
|
}
|