a lot of fixes and updates
This commit is contained in:
parent
fcf6830e2d
commit
323f348410
3 changed files with 83 additions and 21 deletions
|
@ -12,5 +12,11 @@ namespace IPASorter
|
||||||
public string CFBundleIdentifier { get; set; }
|
public string CFBundleIdentifier { get; set; }
|
||||||
public string CFBundleVersion { get; set; }
|
public string CFBundleVersion { get; set; }
|
||||||
public string MinimumOSVersion { get; set; }
|
public string MinimumOSVersion { get; set; }
|
||||||
|
public string CFBundleDisplayName { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AppList
|
||||||
|
{
|
||||||
|
public IPAFile[] apps { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@ using System.IO.Compression;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace IPASorter
|
namespace IPASorter
|
||||||
|
@ -26,16 +28,14 @@ namespace IPASorter
|
||||||
|
|
||||||
// parse filepath if given
|
// parse filepath if given
|
||||||
string argsFilePath = args.Length != 0 ? args[0] : "./";
|
string argsFilePath = args.Length != 0 ? args[0] : "./";
|
||||||
if (!argsFilePath.EndsWith("/") || !argsFilePath.EndsWith("/")) argsFilePath += "/";
|
if (!argsFilePath.EndsWith("/")) argsFilePath += "/";
|
||||||
|
|
||||||
// run steps
|
// run steps
|
||||||
FileScanner(argsFilePath);
|
FileScanner(argsFilePath);
|
||||||
// MD5Eliminator(); obsolete
|
// MD5Eliminator(); obsolete
|
||||||
InfoPlistRenamer();
|
InfoPlistRenamer(argsFilePath);
|
||||||
if(args.Length > 1 && args[1] == "-si")
|
SortByiOSCompatibility(argsFilePath);
|
||||||
{
|
GenerateJson();
|
||||||
SortByiOSCompatibility();
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine("complete :)");
|
Console.WriteLine("complete :)");
|
||||||
}
|
}
|
||||||
|
@ -43,12 +43,14 @@ namespace IPASorter
|
||||||
// step 1
|
// step 1
|
||||||
static void FileScanner(string path)
|
static void FileScanner(string path)
|
||||||
{
|
{
|
||||||
|
Console.WriteLine("Scanning subdirectories for IPA files");
|
||||||
List<string> tmp = Directory.GetFiles(path, "*.ipa", SearchOption.AllDirectories).ToList();
|
List<string> tmp = Directory.GetFiles(path, "*.ipa", SearchOption.AllDirectories).ToList();
|
||||||
foreach (string s in tmp)
|
foreach (string s in tmp)
|
||||||
{
|
{
|
||||||
|
Console.WriteLine($"Found {s}");
|
||||||
files.Add(new IPAFile
|
files.Add(new IPAFile
|
||||||
{
|
{
|
||||||
fileName = s.Split('/')[s.Split('/').Length -1].Split('/')[s.Split('/')[s.Split('/').Length - 1].Split('/').Length - 1],
|
fileName = s.Split('/')[s.Split('/').Length -1],
|
||||||
path = s,
|
path = s,
|
||||||
md5sum = CalculateMD5(s)
|
md5sum = CalculateMD5(s)
|
||||||
}) ;
|
}) ;
|
||||||
|
@ -56,9 +58,10 @@ namespace IPASorter
|
||||||
}
|
}
|
||||||
|
|
||||||
// step 2
|
// step 2
|
||||||
static void InfoPlistRenamer()
|
static void InfoPlistRenamer(string path)
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory("./sortertemp");
|
Directory.CreateDirectory("./sortertemp");
|
||||||
|
Directory.CreateDirectory($"{path}/incomplete");
|
||||||
foreach (IPAFile i in files)
|
foreach (IPAFile i in files)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"fixing name of {i.fileName}");
|
Console.WriteLine($"fixing name of {i.fileName}");
|
||||||
|
@ -66,17 +69,47 @@ namespace IPASorter
|
||||||
// extract ipa
|
// extract ipa
|
||||||
Directory.CreateDirectory($"./sortertemp/{i.fileName}");
|
Directory.CreateDirectory($"./sortertemp/{i.fileName}");
|
||||||
ZipFile.ExtractToDirectory(i.path, $"./sortertemp/{i.fileName}");
|
ZipFile.ExtractToDirectory(i.path, $"./sortertemp/{i.fileName}");
|
||||||
string appPath = $"./sortertemp/{i.fileName}/Payload/{Directory.GetDirectories($"./sortertemp/{i.fileName}/Payload/")[0].Split('/')[Directory.GetDirectories($"./sortertemp/{i.fileName}/Payload/")[0].Split('/').Length - 1]}";
|
|
||||||
|
|
||||||
// parse plist
|
// parse plist
|
||||||
Dictionary<string, object> plist = (Dictionary<string, object>)Plist.readPlist(appPath + "/Info.plist");
|
Dictionary<string, object> plist = new Dictionary<string, object>();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string appPath = $"./sortertemp/{i.fileName}/Payload/{Directory.GetDirectories($"./sortertemp/{i.fileName}/Payload/")[0].Split('/')[Directory.GetDirectories($"./sortertemp/{i.fileName}/Payload/")[0].Split('/').Length - 1]}";
|
||||||
|
plist = (Dictionary<string, object>)Plist.readPlist(appPath + "/Info.plist");
|
||||||
|
}
|
||||||
|
catch(Exception)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{i.fileName} has a missing/damaged Info.plist. moving to the broken directory...");
|
||||||
|
File.Move(i.path, $"{path}/incomplete/{i.fileName.Replace(".ipa", $"-{i.md5sum}.ipa")}", true);
|
||||||
|
i.path = $"{path}/incomplete/{i.fileName.Replace(".ipa", $"-{i.md5sum}.ipa")}";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
Directory.Delete($"./sortertemp/{i.fileName}", true);
|
Directory.Delete($"./sortertemp/{i.fileName}", true);
|
||||||
i.CFBundleIdentifier = plist["CFBundleIdentifier"].ToString();
|
i.CFBundleIdentifier = plist["CFBundleIdentifier"].ToString();
|
||||||
i.CFBundleVersion = plist["CFBundleVersion"].ToString();
|
try
|
||||||
|
{
|
||||||
|
i.CFBundleDisplayName = RemoveIllegalFileNameChars(plist["CFBundleDisplayName"].ToString());
|
||||||
|
}
|
||||||
|
catch (KeyNotFoundException)
|
||||||
|
{
|
||||||
|
i.CFBundleDisplayName = i.CFBundleIdentifier.Split('.')[2];
|
||||||
|
}
|
||||||
|
string whichToUse = "CFBundleVersion";
|
||||||
|
if (plist["CFBundleVersion"].ToString() == "1")
|
||||||
|
{
|
||||||
|
whichToUse = "CFBundleShortVersionString";
|
||||||
|
}
|
||||||
|
i.CFBundleVersion = plist[whichToUse].ToString();
|
||||||
|
try
|
||||||
|
{
|
||||||
i.MinimumOSVersion = plist["MinimumOSVersion"].ToString();
|
i.MinimumOSVersion = plist["MinimumOSVersion"].ToString();
|
||||||
|
}
|
||||||
|
catch (KeyNotFoundException)
|
||||||
|
{
|
||||||
|
i.MinimumOSVersion = "2.0";
|
||||||
|
}
|
||||||
|
|
||||||
// rename file
|
// rename file
|
||||||
string newFileName = $"{plist["CFBundleIdentifier"]}-{plist["CFBundleVersion"]}-(iOS_{plist["MinimumOSVersion"]})-{i.md5sum}.ipa";
|
string newFileName = $"{i.CFBundleDisplayName}-({i.CFBundleIdentifier})-{i.CFBundleVersion}-(iOS_{i.MinimumOSVersion})-{i.md5sum}.ipa";
|
||||||
File.Move(i.path, i.path.Replace(i.fileName, newFileName), true);
|
File.Move(i.path, i.path.Replace(i.fileName, newFileName), true);
|
||||||
i.path = i.path.Replace(i.fileName, newFileName);
|
i.path = i.path.Replace(i.fileName, newFileName);
|
||||||
i.fileName = newFileName;
|
i.fileName = newFileName;
|
||||||
|
@ -84,13 +117,30 @@ namespace IPASorter
|
||||||
Directory.Delete("./sortertemp", true);
|
Directory.Delete("./sortertemp", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional step 3
|
// step 3
|
||||||
static void SortByiOSCompatibility()
|
static void SortByiOSCompatibility(string path)
|
||||||
{
|
{
|
||||||
|
Console.WriteLine("Sorting apps by minimum iOS version");
|
||||||
|
|
||||||
|
foreach(IPAFile i in files)
|
||||||
|
{
|
||||||
|
if (i.path == "DO NOT ENUMERATE") continue;
|
||||||
|
Directory.CreateDirectory($"{path}/iOS{i.MinimumOSVersion.Split('.')[0]}/{i.CFBundleIdentifier}");
|
||||||
|
File.Move(i.path, $"{path}/iOS{i.MinimumOSVersion.Split('.')[0]}/{i.CFBundleIdentifier}/{i.fileName}", true);
|
||||||
|
i.path = $"{path}/iOS{i.MinimumOSVersion.Split('.')[0]}/{i.CFBundleIdentifier}/{i.fileName}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// othet stuff
|
// step 4
|
||||||
|
static void GenerateJson()
|
||||||
|
{
|
||||||
|
AppList apps = new AppList();
|
||||||
|
apps.apps = files.ToArray();
|
||||||
|
string appsJson = JsonSerializer.Serialize(apps);
|
||||||
|
File.WriteAllText("./apps.json", appsJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
// other stuff (hate)
|
||||||
static string CalculateMD5(string fileName)
|
static string CalculateMD5(string fileName)
|
||||||
{
|
{
|
||||||
using (var md5 = MD5.Create())
|
using (var md5 = MD5.Create())
|
||||||
|
@ -102,6 +152,13 @@ namespace IPASorter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string RemoveIllegalFileNameChars(string input, string replacement = "")
|
||||||
|
{
|
||||||
|
var regexSearch = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars());
|
||||||
|
var r = new Regex(string.Format("[{0}]", Regex.Escape(regexSearch)));
|
||||||
|
return r.Replace(input, replacement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,9 @@
|
||||||
Cross platform sorter for iOS app packages (IPAs)
|
Cross platform sorter for iOS app packages (IPAs)
|
||||||
|
|
||||||
## Command line arguments
|
## Command line arguments
|
||||||
`IPASorter <path> <options>`
|
`IPASorter <path>` or
|
||||||
Running with no arguments will sort from the directory the program is in with no sorting options.
|
`dotnet IPASorter.dll <path>`
|
||||||
### Sorting Options
|
Running with no arguments will sort from the directory the program is in.
|
||||||
coming soon
|
|
||||||
|
|
||||||
requires .net core 3.1 or later
|
requires .net core 3.1 or later
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue