Skip to content

Instantly share code, notes, and snippets.

@esterTion
Created June 7, 2020 01:22
Show Gist options
  • Save esterTion/bf863ae5e68be12784616e331000f7da to your computer and use it in GitHub Desktop.
Save esterTion/bf863ae5e68be12784616e331000f7da to your computer and use it in GitHub Desktop.
Dump dlst encrypted comic from PFViewer
https://repo.estertion.win/
Package: com.estertion.pfviewer-dumper
Name: PFViewer Dumper
Depends: mobilesubstrate
Version: 1
Architecture: iphoneos-arm
Description: Dump dlst encrypted comic from PFViewer
Maintainer: esterTion
Author: esterTion
Section: Tweaks
include $(THEOS)/makefiles/common.mk
ARCHS = armv7 arm64 arm64e
TWEAK_NAME = PFViewerDumper
PFViewerDumper_FILES = Tweak.xm
PFViewerDumper_CFLAGS = -fobjc-arc
include $(THEOS_MAKE_PATH)/tweak.mk
after-install::
install.exec "killall -9 PFviewer"
{ Filter = { Bundles = ( "red.pfv.pfviewer" ); }; }
@interface ContentReader
-(unsigned long)size;
-(NSData*)wholeData;
@end
@interface PackageFacade
-(unsigned long)pageCount;
-(ContentReader*)contentReaderOnPage:(int)page error:(id)err;
@end
static PackageFacade* pf_ins;
static bool dumping;
static UIWindow* customWin = NULL;
void show_choice();
void dump_content();
void dump_content_work(UIAlertController* alert);
void dump_content_fin(UIAlertController* alert);
%hook PackageFacade
- (id) init {
id instance = %orig;
pf_ins = instance;
dispatch_async(dispatch_get_main_queue(), ^{
show_choice();
});
return instance;
}
%end
void show_choice() {
dumping = false;
if (!customWin) {
customWin = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
customWin.windowLevel = 9999;
customWin.rootViewController = [[UIViewController alloc] init];
}
customWin.hidden = NO;
__block UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"PFViewer Dumper"
message:@"Dump content?"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* action;
action = [UIAlertAction actionWithTitle:@"No" style:UIAlertActionStyleCancel handler:^(UIAlertAction* action) {
pf_ins = nil;
customWin.hidden = YES;
}];
[alert addAction:action];
action = [UIAlertAction actionWithTitle:@"Yes" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action) {
dumping = true;
dump_content();
}];
[alert addAction:action];
[customWin.rootViewController presentViewController:alert animated:YES completion:nil];
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 3);
dispatch_after(delay, dispatch_get_main_queue(), ^(void) {
if (!dumping) pf_ins = nil;
if (alert) {
[alert dismissViewControllerAnimated:YES completion:^() {
customWin.hidden = YES;
}];
}
});
}
void dump_content() {
unsigned long pages = [pf_ins pageCount];
if (pages == 0) {
#ifdef DEBUG
NSLog(@"[PFViewer Dumper] retrying");
#endif
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC / 2);
dispatch_after(delay, dispatch_get_main_queue(), ^(void) {
dump_content();
});
return;
}
__block UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"PFViewer Dumper"
message:@"Dumping"
preferredStyle:UIAlertControllerStyleAlert];
[customWin.rootViewController presentViewController:alert animated:YES completion:nil];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dump_content_work(alert);
});
}
void dump_content_work(UIAlertController* alert) {
unsigned long pages = [pf_ins pageCount];
int pageDigits = 1;
{
unsigned long tmp = pages;
while (tmp >= 10) {
tmp /= 10;
pageDigits++;
}
}
NSFileManager* fm = [NSFileManager defaultManager];
if ([fm fileExistsAtPath:@"/tmp/pfviewer-dumper"]) {
[fm removeItemAtPath:@"/tmp/pfviewer-dumper" error:nil];
}
NSLog(@"[PFViewer Dumper] start, pages %ld", pages);
[fm createDirectoryAtPath:@"/tmp/pfviewer-dumper" withIntermediateDirectories:YES attributes:nil error:nil];
for (int page = 1; page <= pages; page++) {
NSError* error;
#ifdef DEBUG
NSLog(@"[PFViewer Dumper] try page %d", page);
#endif
ContentReader* cr = [pf_ins contentReaderOnPage:page error:error];
if (!cr) {
#ifdef DEBUG
if (error) {
NSLog(@"[PFViewer Dumper] %@", error);
}
#endif
continue;
}
#ifdef DEBUG
NSLog(@"[PFViewer Dumper] page %d", page);
#endif
NSData* data = [cr wholeData];
NSString* path = [NSString stringWithFormat:@"/tmp/pfviewer-dumper/%0*d.jpg", pageDigits, page];
[fm createFileAtPath:path contents:data attributes:nil];
}
__block UIAlertController* alert_b = alert;
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC);
dispatch_after(delay, dispatch_get_main_queue(), ^(void) {
dump_content_fin(alert_b);
});
}
void dump_content_fin(UIAlertController* alert) {
[alert dismissViewControllerAnimated:NO completion:NULL];
alert = [UIAlertController alertControllerWithTitle:@"PFViewer Dumper"
message:@"Dumped to /tmp/pfviewer-dumper"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:[[NSBundle bundleWithIdentifier:@"com.apple.UIKit"] localizedStringForKey:@"Dismiss" value:@"" table:nil]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) { customWin.hidden = YES; }];
[alert addAction:defaultAction];
[customWin.rootViewController presentViewController:alert animated:YES completion:nil];
pf_ins = nil;
dumping = false;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment