public static InstallerConfiguration CreateDefaultConfiguration() { InstallerConfiguration defaultConfiguration = new InstallerConfiguration (); defaultConfiguration.AutoDiscovery = true; defaultConfiguration.Certificates = new byte[0][]; defaultConfiguration.URIs = new string[0]; defaultConfiguration.Packages = new InstallerPackage[0]; defaultConfiguration.Version = string.Empty; return defaultConfiguration; }
static IDictionary<string, InstallerPackageTuple> MergePackages(InstallerConfiguration localInstallerConfiguration, InstallerConfiguration remoteInstallerConfiguration) { Dictionary<string, InstallerPackageTuple> packages = new Dictionary<string, InstallerPackageTuple> (); foreach (var localPackage in localInstallerConfiguration.Packages) { InstallerPackageTuple packageTuple = new InstallerPackageTuple (); packageTuple.Local = localPackage; packages.Add (localPackage.Name, packageTuple); //duplicate path, boom foreach (var localFile in localPackage.Files) { InstallerFileTuple fileTuple = new InstallerFileTuple (); fileTuple.Local = localFile; packageTuple.files.Add (localFile.Name, fileTuple); } } foreach (var remotePackage in remoteInstallerConfiguration.Packages) { InstallerPackageTuple packageTuple; if (!packages.TryGetValue (remotePackage.Name, out packageTuple)) { packageTuple = new InstallerPackageTuple (); packages.Add (remotePackage.Name, packageTuple); } packageTuple.Remote = remotePackage; foreach (var remoteFile in remotePackage.Files) { InstallerFileTuple fileTuple; if (!packageTuple.files.TryGetValue (remoteFile.Name, out fileTuple)) { fileTuple = new InstallerFileTuple (); packageTuple.files.Add (remoteFile.Name, fileTuple); } fileTuple.Remote = remoteFile; } } foreach (var p in packages) { if ((p.Value.Local == null) ^ (p.Value.Remote == null)) { p.Value.files.Clear (); } } return packages; }
static bool Install(InstallerConfiguration localInstallerConfiguration, Uri uri) { SetCertificate (localInstallerConfiguration.Certificates); Stream manifestStream; string manifestFileName; Stream manifestCopy; Stream manifestSignatureStream; string manifestSignatureFileName; try { manifestStream = Fetch (uri, "manifest.xml"); manifestFileName = Path.GetTempFileName (); manifestCopy = Wack (manifestStream, manifestFileName); manifestSignatureStream = Fetch (uri, "manifest.xml.sig"); manifestSignatureFileName = Path.GetTempFileName (); using (Stream manifestSignatureTempStream = File.OpenWrite (manifestSignatureFileName)) { manifestSignatureStream.CopyTo (manifestSignatureTempStream); } } catch (Exception ex) { Console.Error.WriteLine (ex.Message); Console.Error.WriteLine ("***Error while fetching manifest /sig, ABORTING INSTALLATION FROM {0}***", uri); return false; } try { Process process; process = Process.Start ("gpg", "--verify " + manifestSignatureFileName + " " + manifestFileName); process.WaitForExit (); int ec = process.ExitCode; if (ec != 0) { Console.Error.WriteLine ("***GPG VERIFICATION FAILED. ABORTING INSTALLATION FROM {0}***", uri); return false; } } catch (Exception ex) { Console.WriteLine ("'{{{0}}}:{1}' happneed when I tried to verify the gpg signature, Plesae verify that gpg is installed and all keys belonging to Behrooz0az@gmail are imported.", ex.GetType ().Name, ex.Message); if (Environment.OSVersion.Platform != PlatformID.Win32NT) { //windows users can't care less about security anyways return false; } } if (File.Exists ("manifest.xml")) File.Delete ("manifest.xml"); File.Move (manifestFileName, "manifest.xml"); if (File.Exists ("manifest.xml.sig")) File.Delete ("manifest.xml.sig"); File.Move (manifestSignatureFileName, "manifest.xml.sig"); System.Xml.Serialization.XmlSerializer xmlSerializer = CreateSerializer (); InstallerConfiguration remoteInstallerConfiguration = (InstallerConfiguration)xmlSerializer.Deserialize (manifestCopy); if (string.Compare (remoteInstallerConfiguration.Version, localInstallerConfiguration.Version, StringComparison.Ordinal) < 0) { Console.WriteLine ("remote data too old"); return false; } if (localInstallerConfiguration.Certificates.Length != 0) { List<byte[]> matches = new List<byte[]> (); foreach (var rcert in remoteInstallerConfiguration.Certificates) { foreach (var lcert in localInstallerConfiguration.Certificates) { if (System.Collections.StructuralComparisons.StructuralEqualityComparer.Equals (rcert, lcert)) { matches.Add (lcert); } } } if (matches.Count == 0) { Console.WriteLine ("certificate changed without notice."); return false; } SetCertificate (matches); } Console.WriteLine ("we have {0} packages to check", remoteInstallerConfiguration.Packages.Length); List<InstallerPackage> remotePackages = new List<InstallerPackage> (remoteInstallerConfiguration.Packages); foreach (var package in remoteInstallerConfiguration.Packages) { if (!PlatformSupportsPackage (package)) { Console.WriteLine ("package {0}: Not Supported.", package.Name); remotePackages.Remove (package); } else { Console.WriteLine ("package {0}: OK", package.Name); } } remoteInstallerConfiguration.Packages = remotePackages.ToArray (); Console.WriteLine ("we have {0} packages to install/verify", remoteInstallerConfiguration.Packages.Length); IDictionary<string, InstallerPackageTuple> packages = MergePackages (localInstallerConfiguration, remoteInstallerConfiguration); foreach (var p in packages.Values) { if ((p.Local != null) && (p.Remote == null)) { DeleteEntirePackage (p.Local); } if ((p.Local == null) && (p.Remote != null)) { DownloadEntirePackage (uri, p.Remote); } if ((p.Local != null) && (p.Remote != null)) { DownloadDeltaPackage (uri, p.Local, p.Remote, p.files); } if ((p.Local == null) && (p.Remote == null)) { throw new Exception ("What the f**k"); } } return true; }
static void Configure(Queue<string> queue) { string output = null; InstallerConfiguration installerConfiguration = new InstallerConfiguration (); bool autoDiscovery = false; string version = null; List<string> uris = new List<string> (); List<InstallerPackage> packages = new List<InstallerPackage> (); List<string> certificates = new List<string> (); List<string> ignore = new List<string> (); while (queue.Count > 0) { switch (queue.Dequeue ()) { case "--output": output = queue.Dequeue (); break; case "--auto-discovery": autoDiscovery = true; break; case "--certificate": certificates.Add (queue.Dequeue ()); break; case "--version": version = queue.Dequeue (); break; case "--ignore": while (!queue.Peek ().StartsWith ("--", StringComparison.Ordinal)) { ignore.Add (queue.Dequeue ()); } break; case "--package": InstallerPackage package = new InstallerPackage (); while (queue.Count > 0) { string current = queue.Peek (); if (current.StartsWith ("--", StringComparison.Ordinal)) { break; } queue.Dequeue (); const string name = "name="; if (current.StartsWith (name, StringComparison.Ordinal)) { package.Name = current.Substring (name.Length); } const string platform = "platform="; if (current.StartsWith (platform, StringComparison.Ordinal)) { package.Platform = (Platform)Enum.Parse (typeof(Platform), current.Substring (platform.Length)); } const string bits = "bits="; if (current.StartsWith (bits, StringComparison.Ordinal)) { package.Bits = ushort.Parse (current.Substring (bits.Length)); } const string installPath = "install-path="; if (current.StartsWith (installPath, StringComparison.Ordinal)) { package.InstallPath = current.Substring (installPath.Length); } const string remotePath = "remote-path="; if (current.StartsWith (remotePath, StringComparison.Ordinal)) { package.RemotePath = current.Substring (remotePath.Length); } const string executable = "executable="; if (current.StartsWith (executable, StringComparison.Ordinal)) { package.ExecutableName = current.Substring (executable.Length); } } packages.Add (package); break; case "--uri": uris.Add (queue.Dequeue ()); break; } } Dictionary<string, InstallerPackage> pathes = new Dictionary<string, InstallerPackage> (); foreach (InstallerPackage package in packages) { string prp = package.RemotePath; if (prp == "") prp = "./"; prp = Path.GetFullPath (prp); int packagePathLen = prp.Length; List<InstallerFile> files = new List<InstallerFile> (); foreach (var file in Directory.GetFiles (prp, "*", SearchOption.AllDirectories)) { bool belongsToMe = !pathes.ContainsKey (file); if (!belongsToMe) { continue; } pathes.Add (file, package); string relativePath = file.Substring (packagePathLen); if (ignore.Contains (relativePath)) continue; InstallerFile installerFile = new InstallerFile (); installerFile.Name = relativePath; using (Stream stream = File.OpenRead (file)) { installerFile.SHA256SUM = ComputeHash (stream); } files.Add (installerFile); } package.Files = files.ToArray (); } installerConfiguration.AutoDiscovery = autoDiscovery; installerConfiguration.Version = version; installerConfiguration.Packages = packages.ToArray (); installerConfiguration.URIs = uris.ToArray (); installerConfiguration.Certificates = new byte[certificates.Count][]; for (int i = 0; i != certificates.Count; i++) installerConfiguration.Certificates [i] = File.ReadAllBytes (certificates [i]); var xmlSerializer = CreateSerializer (); using (Stream outputStream = File.Open (output, FileMode.CreateNew)) { xmlSerializer.Serialize (outputStream, installerConfiguration); outputStream.Flush (); } }