From 87a75e6844b0fbda58342b9dcfbaa7fde184ba52 Mon Sep 17 00:00:00 2001
From: kawaiizenbo <48113593+kawaiizenbo@users.noreply.github.com>
Date: Fri, 10 Dec 2021 09:23:03 -0700
Subject: [PATCH] dist repo support + delay + instalelr repos
---
 RepoFullDownloader-Core/App.config     |  10 +
 RepoFullDownloader-Core/DataClasses.cs |  32 +-
 RepoFullDownloader-Core/Plist.cs       | 961 +++++++++++++++++++++++++
 RepoFullDownloader-Core/Program.cs     | 252 +++++--
 example-options.json                   |  28 +-
 5 files changed, 1231 insertions(+), 52 deletions(-)
 create mode 100644 RepoFullDownloader-Core/App.config
 create mode 100644 RepoFullDownloader-Core/Plist.cs
diff --git a/RepoFullDownloader-Core/App.config b/RepoFullDownloader-Core/App.config
new file mode 100644
index 0000000..082a4aa
--- /dev/null
+++ b/RepoFullDownloader-Core/App.config
@@ -0,0 +1,10 @@
+
+
+	
+		
+			
+		
+	
+
\ No newline at end of file
diff --git a/RepoFullDownloader-Core/DataClasses.cs b/RepoFullDownloader-Core/DataClasses.cs
index 21542a2..22086b2 100644
--- a/RepoFullDownloader-Core/DataClasses.cs
+++ b/RepoFullDownloader-Core/DataClasses.cs
@@ -9,14 +9,42 @@ namespace RepoFullDownloader
     class Options
     {
         public bool originalFilenames { get; set; } = false;
-        public Repo[] repos { get; set; } = { new Repo() { url = "http://cydia.invoxiplaygames.uk/" , isInstaller = false}, new Repo() { url = "http://apptapp.saurik.com/", isInstaller = true } };
+        public Repo[] repos { get; set; } = { 
+            new Repo() 
+            { 
+                url = "http://repo.kawaiizenbo.me/", 
+                type = "cydia"
+            }, 
+            new Repo() 
+            { 
+                url = "http://apptapp.saurik.com/", 
+                type = "installer" 
+            },
+            new Repo()
+            {
+                url = "http://apt.saurik.com/",
+                type = "dist",
+                distAttributes = new DistAttributes()
+                {
+                    suites = "ios/",
+                    components = "main",
+                }
+            }
+        };
         public int delay { get; set; } = 1;
     }
 
     class Repo
     {
         public string url { get; set; }
-        public bool isInstaller { get; set; }
+        public string type { get; set; }
+        public DistAttributes distAttributes { get; set; } = null;
+    }
+
+    class DistAttributes
+    {
+        public string suites { get; set; }
+        public string components { get; set; }
     }
 
     class CydiaPackage
diff --git a/RepoFullDownloader-Core/Plist.cs b/RepoFullDownloader-Core/Plist.cs
new file mode 100644
index 0000000..f52c364
--- /dev/null
+++ b/RepoFullDownloader-Core/Plist.cs
@@ -0,0 +1,961 @@
+//
+//   PlistCS Property List (plist) serialization and parsing library.
+//
+//   https://github.com/animetrics/PlistCS
+//   
+//   Copyright (c) 2011 Animetrics Inc. (marc@animetrics.com)
+//   
+//   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;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml;
+
+namespace PlistCS
+{
+    public static class Plist
+    {
+        private static List offsetTable = new List();
+        private static List objectTable = new List();
+        private static int refCount;
+        private static int objRefSize;
+        private static int offsetByteSize;
+        private static long offsetTableOffset;
+
+        #region Public Functions
+
+        public static object readPlist(string path)
+        {
+            using (FileStream f = new FileStream(path, FileMode.Open, FileAccess.Read))
+            {
+                return readPlist(f, plistType.Auto);
+            }
+        }
+
+        public static object readPlistSource(string source)
+        {
+            return readPlist(System.Text.Encoding.UTF8.GetBytes(source));
+        }
+
+        public static object readPlist(byte[] data)
+        {
+            return readPlist(new MemoryStream(data), plistType.Auto);
+        }
+
+        public static plistType getPlistType(Stream stream)
+        {
+            byte[] magicHeader = new byte[8];
+            stream.Read(magicHeader, 0, 8);
+
+            if (BitConverter.ToInt64(magicHeader, 0) == 3472403351741427810)
+            {
+                return plistType.Binary;
+            }
+            else
+            {
+                return plistType.Xml;
+            }
+        }
+
+        public static object readPlist(Stream stream, plistType type)
+        {
+            if (type == plistType.Auto)
+            {
+                type = getPlistType(stream);
+                stream.Seek(0, SeekOrigin.Begin);
+            }
+
+            if (type == plistType.Binary)
+            {
+                using (BinaryReader reader = new BinaryReader(stream))
+                {
+                    byte[] data = reader.ReadBytes((int)reader.BaseStream.Length);
+                    return readBinary(data);
+                }
+            }
+            else
+            {
+                XmlDocument xml = new XmlDocument();
+                xml.XmlResolver = null;
+                xml.Load(stream);
+                return readXml(xml);
+            }
+        }
+
+        public static void writeXml(object value, string path)
+        {
+            using (StreamWriter writer = new StreamWriter(path))
+            {
+                writer.Write(writeXml(value));
+            }
+        }
+
+        public static void writeXml(object value, Stream stream)
+        {
+            using (StreamWriter writer = new StreamWriter(stream))
+            {
+                writer.Write(writeXml(value));
+            }
+        }
+
+        public static string writeXml(object value)
+        {
+            using (MemoryStream ms = new MemoryStream())
+            {
+                XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
+                xmlWriterSettings.Encoding = new System.Text.UTF8Encoding(false);
+                xmlWriterSettings.ConformanceLevel = ConformanceLevel.Document;
+                xmlWriterSettings.Indent = true;
+
+                using (XmlWriter xmlWriter = XmlWriter.Create(ms, xmlWriterSettings))
+                {
+                    xmlWriter.WriteStartDocument();
+                    //xmlWriter.WriteComment("DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" " + "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"");
+                    xmlWriter.WriteDocType("plist", "-//Apple Computer//DTD PLIST 1.0//EN", "http://www.apple.com/DTDs/PropertyList-1.0.dtd", null);
+                    xmlWriter.WriteStartElement("plist");
+                    xmlWriter.WriteAttributeString("version", "1.0");
+                    compose(value, xmlWriter);
+                    xmlWriter.WriteEndElement();
+                    xmlWriter.WriteEndDocument();
+                    xmlWriter.Flush();
+                    xmlWriter.Close();
+                    return System.Text.Encoding.UTF8.GetString(ms.ToArray());
+                }
+            }
+        }
+
+        public static void writeBinary(object value, string path)
+        {
+            using (BinaryWriter writer = new BinaryWriter(new FileStream(path, FileMode.Create)))
+            {
+                writer.Write(writeBinary(value));
+            }
+        }
+
+        public static void writeBinary(object value, Stream stream)
+        {
+            using (BinaryWriter writer = new BinaryWriter(stream))
+            {
+                writer.Write(writeBinary(value));
+            }
+        }
+
+        public static byte[] writeBinary(object value)
+        {
+            offsetTable.Clear();
+            objectTable.Clear();
+            refCount = 0;
+            objRefSize = 0;
+            offsetByteSize = 0;
+            offsetTableOffset = 0;
+
+            //Do not count the root node, subtract by 1
+            int totalRefs = countObject(value) - 1;
+
+            refCount = totalRefs;
+
+            objRefSize = RegulateNullBytes(BitConverter.GetBytes(refCount)).Length;
+
+            composeBinary(value);
+
+            writeBinaryString("bplist00", false);
+
+            offsetTableOffset = (long)objectTable.Count;
+
+            offsetTable.Add(objectTable.Count - 8);
+
+            offsetByteSize = RegulateNullBytes(BitConverter.GetBytes(offsetTable[offsetTable.Count - 1])).Length;
+
+            List offsetBytes = new List();
+
+            offsetTable.Reverse();
+
+            for (int i = 0; i < offsetTable.Count; i++)
+            {
+                offsetTable[i] = objectTable.Count - offsetTable[i];
+                byte[] buffer = RegulateNullBytes(BitConverter.GetBytes(offsetTable[i]), offsetByteSize);
+                Array.Reverse(buffer);
+                offsetBytes.AddRange(buffer);
+            }
+
+            objectTable.AddRange(offsetBytes);
+
+            objectTable.AddRange(new byte[6]);
+            objectTable.Add(Convert.ToByte(offsetByteSize));
+            objectTable.Add(Convert.ToByte(objRefSize));
+
+            var a = BitConverter.GetBytes((long)totalRefs + 1);
+            Array.Reverse(a);
+            objectTable.AddRange(a);
+
+            objectTable.AddRange(BitConverter.GetBytes((long)0));
+            a = BitConverter.GetBytes(offsetTableOffset);
+            Array.Reverse(a);
+            objectTable.AddRange(a);
+
+            return objectTable.ToArray();
+        }
+
+        #endregion
+
+        #region Private Functions
+
+        private static object readXml(XmlDocument xml)
+        {
+            XmlNode rootNode = xml.DocumentElement.ChildNodes[0];
+            return parse(rootNode);
+        }
+
+        private static object readBinary(byte[] data)
+        {
+            offsetTable.Clear();
+            List offsetTableBytes = new List();
+            objectTable.Clear();
+            refCount = 0;
+            objRefSize = 0;
+            offsetByteSize = 0;
+            offsetTableOffset = 0;
+
+            List bList = new List(data);
+
+            List trailer = bList.GetRange(bList.Count - 32, 32);
+
+            parseTrailer(trailer);
+
+            objectTable = bList.GetRange(0, (int)offsetTableOffset);
+
+            offsetTableBytes = bList.GetRange((int)offsetTableOffset, bList.Count - (int)offsetTableOffset - 32);
+
+            parseOffsetTable(offsetTableBytes);
+
+            return parseBinary(0);
+        }
+
+        private static Dictionary parseDictionary(XmlNode node)
+        {
+            XmlNodeList children = node.ChildNodes;
+            if (children.Count % 2 != 0)
+            {
+                throw new DataMisalignedException("Dictionary elements must have an even number of child nodes");
+            }
+
+            Dictionary dict = new Dictionary();
+
+            for (int i = 0; i < children.Count; i += 2)
+            {
+                XmlNode keynode = children[i];
+                XmlNode valnode = children[i + 1];
+
+                if (keynode.Name != "key")
+                {
+                    throw new ApplicationException("expected a key node");
+                }
+
+                object result = parse(valnode);
+
+                if (result != null)
+                {
+                    dict.Add(keynode.InnerText, result);
+                }
+            }
+
+            return dict;
+        }
+
+        private static List