RepoFullDownloader/RepoFullDownloader-Core/Program.cs

447 lines
20 KiB
C#
Raw Normal View History

2021-10-17 22:14:26 -07:00
using ICSharpCode.SharpZipLib.BZip2;
using ICSharpCode.SharpZipLib.GZip;
using PlistCS;
2021-10-17 22:14:26 -07:00
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
2022-08-04 11:05:31 -07:00
using System.Text.RegularExpressions;
2021-10-17 22:14:26 -07:00
using System.Threading;
namespace RepoFullDownloader_Core
{
class Program
{
2022-08-04 11:05:31 -07:00
private static List<string> repos = new List<string>();
private static bool originalFilenames;
private static int delayMS;
2021-12-09 19:42:46 -07:00
2021-10-17 22:14:26 -07:00
static void Main(string[] args)
{
Console.WriteLine("RepoFullDownloader by KawaiiZenbo");
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, errors) =>
{
// security
return true;
};
2021-10-17 22:14:26 -07:00
// Initial Checks
if (!Directory.Exists("./output/"))
{
Directory.CreateDirectory("./output/");
}
2022-08-04 11:05:31 -07:00
// Load Options from 'options.ini'
if (!File.Exists("./options.ini"))
{
2022-08-04 11:05:31 -07:00
Console.WriteLine("Could not find options.ini");
Console.WriteLine("Generating example...");
// generate example options
2022-08-04 11:05:31 -07:00
File.WriteAllText("options.ini",
"delayMS=1\n" +
"originalFilenames=false");
}
2022-08-04 11:05:31 -07:00
string[] options = File.ReadAllLines("options.ini");
delayMS = int.Parse(options[0].Split('=')[1]);
originalFilenames = bool.Parse(options[1].Split('=')[1]);
2021-12-10 00:35:54 -07:00
if (args.Length != 0)
2021-10-17 22:14:26 -07:00
{
string url = args[0];
2021-10-18 18:12:12 -07:00
if(!args[0].StartsWith("https://") && !args[0].StartsWith("http://"))
2021-10-17 22:14:26 -07:00
{
url = "http://" + url;
}
if (!args[0].EndsWith("/"))
{
url += "/";
}
try
{
DownloadRepo(url);
2021-10-17 22:14:26 -07:00
}
catch(Exception)
{
Console.WriteLine("No APT repo was found, trying as Installer repo");
DownloadInstallerRepo(url);
}
}
else
{
2022-08-04 11:05:31 -07:00
if (File.Exists("repos.txt"))
2021-10-17 22:14:26 -07:00
{
2022-08-04 11:05:31 -07:00
foreach (string r in File.ReadAllLines("repos.txt"))
{
2022-08-04 11:05:31 -07:00
if (r.StartsWith('#')) continue;
string[] repoWAttributes = r.Split(' ');
try
{
2022-08-04 11:05:31 -07:00
switch (repoWAttributes[1])
{
case "installer":
DownloadInstallerRepo(repoWAttributes[0]);
break;
case "cydia":
DownloadRepo(repoWAttributes[0]);
break;
case "dist":
DownloadDistRepo(repoWAttributes[0], repoWAttributes[2], repoWAttributes[3]);
break;
default:
Console.WriteLine($"Invalid repo type {repoWAttributes[1]} on {repoWAttributes[0]}");
break;
}
}
catch (Exception e)
{
Console.WriteLine($"Invalid formatting on {r}");
Console.WriteLine(e);
}
2021-10-17 22:14:26 -07:00
}
}
2022-08-04 11:05:31 -07:00
else
{
Console.WriteLine("Could not find repos.txt");
Console.WriteLine("Generating example...");
// generate example repo list
File.WriteAllText("repos.txt",
"http://repo.kawaiizenbo.me cydia\n" +
"http://apptapp.saurik.com installer\n" +
"http://apt.saurik.com dist ios/ main"
);
}
2021-10-17 22:14:26 -07:00
}
// this is the part where it is over
Console.WriteLine("done :)");
}
static void DownloadRepo(string link)
2021-10-17 22:14:26 -07:00
{
2021-10-18 18:12:12 -07:00
if (!link.StartsWith("https://") && !link.StartsWith("http://"))
{
link = "http://" + link;
}
if (!link.EndsWith("/"))
{
link += "/";
}
2021-10-22 15:30:51 -07:00
string cleanLink = link.TrimEnd('/').Replace("http://", "").Replace("https://", "").Replace("/", "_").Replace(":", "_");
2021-10-18 18:12:12 -07:00
Directory.CreateDirectory($"./output/{cleanLink}");
HttpClient webClient = new HttpClient();
2021-10-17 22:14:26 -07:00
// headers because some repos are 'interesting'
webClient.DefaultRequestHeaders.Add("X-Machine", "iPod4,1");
webClient.DefaultRequestHeaders.Add("X-Unique-ID", "0000000000000000000000000000000000000000");
webClient.DefaultRequestHeaders.Add("X-Firmware", "6.1");
webClient.DefaultRequestHeaders.Add("User-Agent", "Telesphoreo APT-HTTP/1.0.999");
2021-10-17 22:14:26 -07:00
// Attempt to download packages file (try/catch hell)
try
{
Console.WriteLine("Attempting to download " + link + "Packages.bz2");
Stream packagesBz2 = webClient.GetStreamAsync(link + "Packages.bz2").Result;
2021-10-18 18:12:12 -07:00
FileStream packagesBz2Decompressed = File.Create($"./output/{cleanLink}/Packages");
2021-10-17 22:14:26 -07:00
BZip2.Decompress(packagesBz2, packagesBz2Decompressed, true);
}
catch (Exception e)
{
try
{
Console.WriteLine("Could not download " + link + "Packages.bz2: " + e.Message);
Console.WriteLine("Attempting to download " + link + "Packages.gz");
2022-08-06 10:44:51 -07:00
Stream packagesGz = webClient.GetStreamAsync(link + "Packages.gz").Result;
2021-10-18 18:12:12 -07:00
FileStream packagesGzDecompressed = File.Create($"./output/{cleanLink}/Packages");
2021-10-17 22:18:24 -07:00
GZip.Decompress(packagesGz, packagesGzDecompressed, true);
2021-10-17 22:14:26 -07:00
}
catch (Exception _e)
{
try
{
Console.WriteLine("Could not download " + link + "Packages.gz: " + _e.Message);
Console.WriteLine("Attempting to download " + link + "Packages");
using (StreamWriter outputFile = new StreamWriter($"./output/{cleanLink}/Packages"))
{
outputFile.WriteLine(webClient.GetStreamAsync(link + "Packages").Result);
}
2021-10-17 22:14:26 -07:00
}
catch (Exception __e)
{
Console.WriteLine("Could not download " + link + "Packages: " + __e.Message);
Console.WriteLine("Could not locate packages file in " + link);
Console.WriteLine(__e.Message);
throw;
}
}
}
Thread.Sleep(500);
// Clean list of package links, names, and versions
List<CydiaPackage> packages = new List<CydiaPackage>();
2021-10-18 18:12:12 -07:00
foreach (string s in File.ReadAllText($"./output/{cleanLink}/Packages").Split("\n\n"))
2021-10-17 22:14:26 -07:00
{
string name = "";
string version = "";
string _link = "";
foreach(string s2 in s.Split('\n'))
{
if (s2.StartsWith("Package: "))
{
name = s2.Remove(0, 8).Trim();
}
else if (s2.StartsWith("Version: "))
{
version = s2.Remove(0, 8).Trim();
}
else if (s2.StartsWith("Filename: "))
{
_link = s2.Remove(0, 9).Trim();
}
}
packages.Add(new CydiaPackage(_link, name, version));
}
2021-10-18 18:12:12 -07:00
// remove last one because ????
2021-10-17 22:14:26 -07:00
packages.RemoveAt(packages.Count - 1);
2021-10-22 15:30:51 -07:00
List<string> failed = new List<string>();
2021-10-17 22:14:26 -07:00
foreach(CydiaPackage p in packages)
{
// Download all packages on repo
2021-10-22 15:30:51 -07:00
Random r = new Random();
2021-10-17 22:14:26 -07:00
try
{
2021-10-22 15:30:51 -07:00
string[] choppedUp = p.link.Split('/');
2022-08-04 11:05:31 -07:00
string fileToDownload = originalFilenames ? $"./output/{cleanLink}/" + choppedUp[choppedUp.Length - 1].Replace("/", "_").Replace(":", "_") : $"./output/{cleanLink}/" + p.name.Replace("/", "_").Replace(":", "_") + "-" + p.version.Replace("/", "_").Replace(":", "_") + ".deb";
2021-10-22 15:30:51 -07:00
if (File.Exists(fileToDownload))
2021-10-17 22:14:26 -07:00
{
2021-10-22 15:30:51 -07:00
fileToDownload += "_" + r.Next(0000, 9999);
2021-10-17 22:14:26 -07:00
}
using (WebClient wc = new WebClient())
{
2022-08-01 11:14:37 -07:00
wc.DownloadFile(new Uri(link + p.link), fileToDownload);
}
2021-10-22 15:30:51 -07:00
Console.WriteLine("Successfully downloaded " + link + p.link + " as " + fileToDownload);
2021-10-17 22:14:26 -07:00
}
2021-10-22 15:30:51 -07:00
catch (Exception e)
2021-10-17 22:14:26 -07:00
{
2021-10-22 15:30:51 -07:00
Console.WriteLine("Could not download " + link + p.link);
Console.WriteLine(e.Message);
failed.Add(link + p.link);
2021-10-17 22:14:26 -07:00
}
2022-08-04 11:05:31 -07:00
Thread.Sleep(delayMS);
2021-10-17 22:14:26 -07:00
}
2021-10-22 15:30:51 -07:00
Console.WriteLine("Finished downloading " + link);
if(failed.Count != 0) File.WriteAllLines($"./output/{cleanLink}/failed.txt", failed);
2021-10-17 22:14:26 -07:00
}
static void DownloadInstallerRepo(string link)
{
2021-10-18 18:12:12 -07:00
if (!link.StartsWith("https://") && !link.StartsWith("http://"))
{
link = "http://" + link;
}
if (!link.EndsWith("/"))
{
link += "/";
}
string cleanLink = link.TrimEnd('/').Replace("http://", "").Replace("https://", "").Replace("/", "_").Replace(":", "_");
Directory.CreateDirectory($"./output/{cleanLink}");
2021-10-17 22:14:26 -07:00
WebClient webClient = new WebClient();
webClient.Headers.Add("User-Agent", "AppTapp Installer/3.0 (iPhone/1.1, like CFNetwork/100.0)");
2021-10-17 22:14:26 -07:00
try
{
Console.WriteLine("Attempting to download installer repo " + link);
webClient.DownloadFile(link, $"./output/{cleanLink}/packages.plist");
2021-10-17 22:14:26 -07:00
}
catch (Exception e)
{
Console.WriteLine("Could not download package list from " + link + ": " + e.Message);
return;
}
2022-08-04 11:05:31 -07:00
Dictionary<string, object> plist = (Dictionary<string, object>)Plist.readPlistSource(Regex.Replace(File.ReadAllText($"./output/{cleanLink}/packages.plist"),
"<!--([^|]+)-->", ""));
foreach (Dictionary<string, object> d in (List<object>)plist["packages"])
{
Random r = new Random();
try
{
string[] choppedUp = d["location"].ToString().Split('/');
string fileToDownload = $"./output/{cleanLink}/" + choppedUp[choppedUp.Length - 1];
if (File.Exists(fileToDownload))
{
fileToDownload += "_" + r.Next(0000, 9999);
}
webClient.DownloadFile(new Uri((string)d["location"]), fileToDownload);
Console.WriteLine("Successfully downloaded " + (string)d["location"]);
}
catch (KeyNotFoundException)
{
string[] choppedUp = d["url"].ToString().Split('/');
string fileToDownload = $"./output/{cleanLink}/" + choppedUp[choppedUp.Length - 1];
if (File.Exists(fileToDownload))
{
fileToDownload += "_" + r.Next(0000, 9999);
}
webClient.DownloadFile(new Uri((string)d["url"]), fileToDownload);
Console.WriteLine("Successfully downloaded " + (string)d["url"]);
Dictionary<string, object> pl = (Dictionary<string, object>)Plist.readPlist(fileToDownload);
{
string[] choppedUp2 = pl["location"].ToString().Split('/');
string fileToDownload2 = $"./output/{cleanLink}/" + choppedUp2[choppedUp2.Length - 1];
if (File.Exists(fileToDownload2))
{
fileToDownload2 += "_" + r.Next(0000, 9999);
}
webClient.DownloadFile(new Uri((string)pl["location"]), fileToDownload2);
Console.WriteLine("Successfully downloaded " + (string)pl["location"]);
}
}
catch (Exception e)
{
Console.WriteLine("Could not download " + (string)d["location"]);
Console.WriteLine(e.Message);
}
}
}
2022-08-04 11:05:31 -07:00
static void DownloadDistRepo(string link, string suites, string components)
{
// clean up link so no issues can ever arise
if (!link.StartsWith("https://") && !link.StartsWith("http://"))
{
link = "http://" + link;
}
if (!link.EndsWith("/"))
{
link += "/";
}
// make that good dist path
string distPath;
2022-08-04 11:05:31 -07:00
if(!suites.EndsWith("/"))
{
2022-08-04 11:05:31 -07:00
suites += "/";
}
2022-08-04 11:05:31 -07:00
if (!components.EndsWith("/"))
{
2022-08-04 11:05:31 -07:00
components += "/";
}
2022-08-04 11:05:31 -07:00
distPath = suites + components;
string poolpfLink = link + "dists/" + distPath + "binary-iphoneos-arm/";
string cleanLink = link.TrimEnd('/').Replace("http://", "").Replace("https://", "").Replace("/", "_").Replace(":", "_");
Directory.CreateDirectory($"./output/{cleanLink}-({distPath.Replace("/", "_").Replace(":", "_")})");
HttpClient webClient = new HttpClient();
// headers because some repos are 'interesting'
webClient.DefaultRequestHeaders.Add("X-Machine", "iPod4,1");
webClient.DefaultRequestHeaders.Add("X-Unique-ID", "0000000000000000000000000000000000000000");
webClient.DefaultRequestHeaders.Add("X-Firmware", "6.1");
webClient.DefaultRequestHeaders.Add("User-Agent", "Telesphoreo APT-HTTP/1.0.999");
// Attempt to download packages file (try/catch hell)
try
{
Console.WriteLine("Attempting to download " + poolpfLink + "Packages.bz2");
Stream packagesBz2 = webClient.GetStreamAsync(poolpfLink + "Packages.bz2").Result;
FileStream packagesBz2Decompressed = File.Create($"./output/{cleanLink}-({distPath.Replace("/", "_").Replace(":", "_")})/Packages");
BZip2.Decompress(packagesBz2, packagesBz2Decompressed, true);
}
catch (Exception e)
2021-10-17 22:14:26 -07:00
{
try
2021-10-17 22:14:26 -07:00
{
Console.WriteLine("Could not download " + poolpfLink + "Packages.bz2: " + e.Message);
Console.WriteLine("Attempting to download " + poolpfLink + "Packages.gz");
Stream packagesGz = webClient.GetStreamAsync(poolpfLink + "Packages.gz").Result;
FileStream packagesGzDecompressed = File.Create($"./output/{cleanLink}-({distPath.Replace("/", "_").Replace(":", "_")})/Packages");
GZip.Decompress(packagesGz, packagesGzDecompressed, true);
}
catch (Exception _e)
{
try
{
Console.WriteLine("Could not download " + poolpfLink + "Packages.gz: " + _e.Message);
Console.WriteLine("Attempting to download " + poolpfLink + "Packages");
using (StreamWriter outputFile = new StreamWriter($"./output/{cleanLink}-({distPath.Replace("/", "_").Replace(":", "_")})/Packages"))
{
outputFile.WriteLine(webClient.GetStreamAsync(poolpfLink + "Packages").Result);
}
}
catch (Exception __e)
{
Console.WriteLine("Could not download " + poolpfLink + "Packages: " + __e.Message);
Console.WriteLine("Could not locate packages file in " + poolpfLink);
Console.WriteLine(__e.Message);
throw;
}
2021-10-17 22:14:26 -07:00
}
}
Thread.Sleep(500);
// Clean list of package links, names, and versions
List<CydiaPackage> packages = new List<CydiaPackage>();
foreach (string s in File.ReadAllText($"./output/{cleanLink}-({distPath.Replace("/", "_").Replace(":", "_")})/Packages").Split("\n\n"))
2021-10-17 22:14:26 -07:00
{
string name = "";
string version = "";
string _link = "";
foreach (string s2 in s.Split('\n'))
{
if (s2.StartsWith("Package: "))
{
name = s2.Remove(0, 8).Trim();
}
else if (s2.StartsWith("Version: "))
{
version = s2.Remove(0, 8).Trim();
}
else if (s2.StartsWith("Filename: "))
{
_link = s2.Remove(0, 9).Trim();
}
}
packages.Add(new CydiaPackage(_link, name, version));
}
// remove last one because ????
packages.RemoveAt(packages.Count - 1);
List<string> failed = new List<string>();
foreach (CydiaPackage p in packages)
{
// Download all packages on repo
2021-10-17 22:14:26 -07:00
Random r = new Random();
try
{
string[] choppedUp = p.link.Split('/');
2022-08-04 11:05:31 -07:00
string fileToDownload = originalFilenames ? $"./output/{cleanLink}-({distPath.Replace("/", "_").Replace(":", "_")})/" + choppedUp[choppedUp.Length - 1].Replace("/", "_").Replace(":", "_") : $"./output/{cleanLink}-({distPath.Replace("/", "_").Replace(":", "_")})/" + p.name.Replace("/", "_").Replace(":", "_") + "-" + p.version.Replace("/", "_").Replace(":", "_") + ".deb";
2021-10-17 22:14:26 -07:00
if (File.Exists(fileToDownload))
{
fileToDownload += "_" + r.Next(0000, 9999);
}
using (WebClient wc = new WebClient())
{
wc.DownloadFileAsync(new Uri(link + p.link), fileToDownload);
}
Console.WriteLine("Successfully downloaded " + link + p.link + " as " + fileToDownload);
2021-10-17 22:14:26 -07:00
}
catch (Exception e)
{
Console.WriteLine("Could not download " + link + p.link);
2021-10-17 22:14:26 -07:00
Console.WriteLine(e.Message);
failed.Add(link + p.link);
2021-10-17 22:14:26 -07:00
}
2022-08-04 11:05:31 -07:00
Thread.Sleep(delayMS);
2021-10-17 22:14:26 -07:00
}
Console.WriteLine("Finished downloading " + link);
if (failed.Count != 0) File.WriteAllLines($"./output/{cleanLink}-({distPath.Replace("/", "_").Replace(":", "_")})/failed.txt", failed);
2021-10-17 22:14:26 -07:00
}
}
2022-08-04 11:05:31 -07:00
class CydiaPackage
{
public CydiaPackage(string _link, string _name, string _version)
{
this.link = _link;
this.name = _name;
this.version = _version;
}
public string link { get; set; }
public string name { get; set; }
public string version { get; set; }
}
2021-10-17 22:14:26 -07:00
}