152 lines
5.7 KiB
Objective-C
152 lines
5.7 KiB
Objective-C
#import <SafariServices/SafariServices.h>
|
|
|
|
#include "jni.h"
|
|
#include <dlfcn.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
#include "utils.h"
|
|
|
|
CFTypeRef SecTaskCopyValueForEntitlement(void* task, NSString* entitlement, CFErrorRef _Nullable *error);
|
|
void* SecTaskCreateFromSelf(CFAllocatorRef allocator);
|
|
|
|
BOOL getEntitlementValue(NSString *key) {
|
|
void *secTask = SecTaskCreateFromSelf(NULL);
|
|
CFTypeRef value = SecTaskCopyValueForEntitlement(SecTaskCreateFromSelf(NULL), key, nil);
|
|
if (value != nil) {
|
|
CFRelease(value);
|
|
}
|
|
CFRelease(secTask);
|
|
|
|
return value != nil && [(__bridge id)value boolValue];
|
|
}
|
|
|
|
BOOL isJITEnabled(BOOL checkCSFlags) {
|
|
if (!checkCSFlags && (getEntitlementValue(@"dynamic-codesigning") || isJailbroken)) {
|
|
return YES;
|
|
}
|
|
|
|
int flags;
|
|
csops(getpid(), 0, &flags, sizeof(flags));
|
|
return (flags & CS_DEBUGGED) != 0;
|
|
}
|
|
|
|
void openLink(UIViewController* sender, NSURL* link) {
|
|
if (NSClassFromString(@"SFSafariViewController") == nil) {
|
|
NSData *data = [link.absoluteString dataUsingEncoding:NSUTF8StringEncoding];
|
|
CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
|
|
[filter setValue:data forKey:@"inputMessage"];
|
|
UIImage *image = [UIImage imageWithCIImage:filter.outputImage scale:1.0 orientation:UIImageOrientationUp];
|
|
UIGraphicsBeginImageContextWithOptions(CGSizeMake(300, 300), NO, 0.0);
|
|
CGRect frame = CGRectMake(0, 0, 300, 300);
|
|
[image drawInRect:frame];
|
|
UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
|
|
imageView.image = UIGraphicsGetImageFromCurrentImageContext();
|
|
UIGraphicsEndImageContext();
|
|
|
|
UIAlertController* alert = [UIAlertController alertControllerWithTitle:nil
|
|
message:link.absoluteString
|
|
preferredStyle:UIAlertControllerStyleAlert];
|
|
|
|
UIViewController *vc = UIViewController.new;
|
|
vc.view = imageView;
|
|
[alert setValue:vc forKey:@"contentViewController"];
|
|
|
|
UIAlertAction* doneAction = [UIAlertAction actionWithTitle:localize(@"Done", nil) style:UIAlertActionStyleCancel handler:nil];
|
|
[alert addAction:doneAction];
|
|
[sender presentViewController:alert animated:YES completion:nil];
|
|
} else {
|
|
SFSafariViewController *vc = [[SFSafariViewController alloc] initWithURL:link];
|
|
[sender presentViewController:vc animated:YES completion:nil];
|
|
}
|
|
}
|
|
|
|
NSMutableDictionary* parseJSONFromFile(NSString *path) {
|
|
NSError *error;
|
|
|
|
NSString *content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
|
|
if (content == nil) {
|
|
NSLog(@"[ParseJSON] Error: could not read %@: %@", path, error.localizedDescription);
|
|
return @{@"NSErrorObject": error}.mutableCopy;
|
|
}
|
|
|
|
NSData* data = [content dataUsingEncoding:NSUTF8StringEncoding];
|
|
NSMutableDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
|
|
if (error) {
|
|
NSLog(@"[ParseJSON] Error: could not parse JSON: %@", error.localizedDescription);
|
|
return @{@"NSErrorObject": error}.mutableCopy;
|
|
}
|
|
return dict;
|
|
}
|
|
|
|
NSError* saveJSONToFile(NSDictionary *dict, NSString *path) {
|
|
// TODO: handle rename
|
|
NSError *error;
|
|
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:&error];
|
|
if (jsonData == nil) {
|
|
return error;
|
|
}
|
|
BOOL success = [jsonData writeToFile:path options:NSDataWritingAtomic error:&error];
|
|
if (!success) {
|
|
return error;
|
|
}
|
|
return nil;
|
|
}
|
|
|
|
NSString* localize(NSString* key, NSString* comment) {
|
|
NSString *value = NSLocalizedString(key, nil);
|
|
if (![NSLocale.preferredLanguages[0] isEqualToString:@"en"] && [value isEqualToString:key]) {
|
|
NSString* path = [NSBundle.mainBundle pathForResource:@"en" ofType:@"lproj"];
|
|
NSBundle* languageBundle = [NSBundle bundleWithPath:path];
|
|
value = [languageBundle localizedStringForKey:key value:nil table:nil];
|
|
|
|
if ([value isEqualToString:key]) {
|
|
value = [[NSBundle bundleWithIdentifier:@"com.apple.UIKit"] localizedStringForKey:key value:nil table:nil];
|
|
}
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
void customNSLog(const char *file, int lineNumber, const char *functionName, NSString *format, ...)
|
|
{
|
|
va_list ap;
|
|
va_start (ap, format);
|
|
NSString *body = [[NSString alloc] initWithFormat:format arguments:ap];
|
|
printf("%s", [body UTF8String]);
|
|
if (![format hasSuffix:@"\n"]) {
|
|
printf("\n");
|
|
}
|
|
va_end (ap);
|
|
}
|
|
|
|
CGFloat MathUtils_dist(CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2) {
|
|
const CGFloat x = (x2 - x1);
|
|
const CGFloat y = (y2 - y1);
|
|
return (CGFloat) hypot(x, y);
|
|
}
|
|
|
|
//Ported from https://www.arduino.cc/reference/en/language/functions/math/map/
|
|
CGFloat MathUtils_map(CGFloat x, CGFloat in_min, CGFloat in_max, CGFloat out_min, CGFloat out_max) {
|
|
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
|
}
|
|
|
|
CGFloat dpToPx(CGFloat dp) {
|
|
CGFloat screenScale = [[UIScreen mainScreen] scale];
|
|
return dp * screenScale;
|
|
}
|
|
|
|
CGFloat pxToDp(CGFloat px) {
|
|
CGFloat screenScale = [[UIScreen mainScreen] scale];
|
|
return px / screenScale;
|
|
}
|
|
|
|
void setButtonPointerInteraction(UIButton *button) {
|
|
button.pointerInteractionEnabled = YES;
|
|
button.pointerStyleProvider = ^ UIPointerStyle* (UIButton* button, UIPointerEffect* proposedEffect, UIPointerShape* proposedShape) {
|
|
UITargetedPreview *preview = [[UITargetedPreview alloc] initWithView:button];
|
|
return [NSClassFromString(@"UIPointerStyle") styleWithEffect:[NSClassFromString(@"UIPointerHighlightEffect") effectWithPreview:preview] shape:proposedShape];
|
|
};
|
|
}
|