Open FawadNL opened 5 years ago
Hello,
Are you getting any error? Also what are you getting in the log?
Hi,
I am not getting any error in Xcode log, but will see the Safari developer console for JS error. Did the plugin work at your end?
Nope, I'm gonna try and fix it this week.
I only see this error in my Safari inspect window - SyntaxError: No identifiers allowed directly after numeric literal
@PeterHdd I am also facing the same issue.
yes IOS part is not working, only android part until now. Still checking the ios part.
Ok, let me know if you need any help in debugging.
If you are able to figure it out also, please commit it, thank you!
OK, so I have been testing and trying to make it work on IOS, but its not working. So, I need either of you to help me(@FawadNL @an-rahulpandey ) as my knowledge in iOS or objective C is null actually.
So here is the thing, the iOS part has not been updated for 4 years, so basically I need to fix everything. To explain how to make it work:
First since ionic webview version 2.0+ works on localhost:8080 server, then the plugin crypto-file
needs to be also on localhost:8080 to work.
Therefore in the javascript part, I did the following if it is platform iOS (it works):
if (platform == 'ios') {
var pluginDir;
console.log(platformInfo);
var iosProject = platformInfo.locations.xcodeCordovaProj;
pluginDir = path.join(iosProject, 'Plugins',context.opts.plugin.id);
replaceCryptKey_ios(pluginDir, key, iv);
var cfg = new ConfigParser(platformInfo.projectConfig.path);
var port = cfg.getGlobalPreference("cryptoPort");
if( port == '')
{
cfg.doc.getroot().getchildren().filter(function(child, idx, arr) {
return (child.tag == 'content');
}).forEach(function(child) {
child.attrib.src = 'http://localhost:8080/' + child.attrib.src;
});
}
else
{
cfg.doc.getroot().getchildren().filter(function(child, idx, arr) {
return (child.tag == 'content');
}).forEach(function(child) {
child.attrib.src = 'http://localhost:' + port + '/' + child.attrib.src;
});
}
cfg.write();
}
cfg.write()
will send http://localhost:8080/index.html
and/or http://localhost:8080/cordova.js
...etc... to the objective c code. So, basically http://localhost:8080/ is the www
in the ionic app and it will send all the decrypted files to the objective c code. (Therefore the javascript part is correct).
Now, the file that needs to be modified is CDVCryptURLProtocol.m
, here is what I did:
#import "CDVCryptURLProtocol.h"
#import <MobileCoreServices/MobileCoreServices.h>
#import <CommonCrypto/CommonCryptor.h>
#import <CommonCrypto/CommonDigest.h>
static NSString* const kCryptKey = @" ";
static NSString* const kCryptIv = @" ";
static int const kIncludeFileLength = 1;
static int const kExcludeFileLength = 0;
static NSString* const kIncludeFiles[] = { @"\\.(htm|html|js|css)$" };
static NSString* const kExcludeFiles[] = { };
NSString *retrievePath;
NSString *wwwPath;
NSString *checkPath;
@implementation CDVCryptURLProtocol
+ (BOOL)canInitWithRequest:(NSURLRequest*)theRequest
{
NSLog(@"the url inside the init request: %@",theRequest);
if ([self checkCryptFile:theRequest.URL]) {
return YES;
}
return [super canInitWithRequest:theRequest];
}
- (void)startLoading
{
NSURL* url = self.request.URL;
wwwPath = [[NSBundle mainBundle].resourcePath stringByAppendingString:@"/www"];
NSString *urling = [@"file://"stringByAppendingString:wwwPath];
NSString *urlings = [urling stringByAppendingString:checkPath];
NSString *finalUrl = [urlings stringByReplacingOccurrencesOfString:@" " withString:@"%20"];
NSURL *urls = [[NSURL alloc] initWithString:finalUrl];
url = urls;
// if ([[self class] checkCryptFile:url]) {
NSString *mimeType = [self getMimeType:url];
NSError* error;
NSString* content = [[NSString alloc] initWithContentsOfFile:url.path encoding:NSUTF8StringEncoding error:&error];
if(error)
{
NSLog(@"the error inside is: %@", error);
}
if (!error) {
NSLog(@"Decrypt: %@",url);
NSData* data = [self decryptAES256WithKey:kCryptKey iv:kCryptIv data:content];
[self sendResponseWithResponseCode:200 data:data mimeType:mimeType];
}
[super startLoading];
}
+ (BOOL)checkCryptFile:(NSURL *)url {
checkPath = [url.path stringByReplacingOccurrencesOfString:@"http://localhost:8080/" withString:@""];//index.html
NSLog(@"the check path: %@", checkPath); //index.html
if (![self hasMatch:checkPath regexArr:kIncludeFiles length:kIncludeFileLength]) {
return NO;
}
if ([self hasMatch:checkPath regexArr:kExcludeFiles length:kExcludeFileLength]) {
return NO;
}
return YES;
}
+ (BOOL)hasMatch:(NSString *)text regexArr:(NSString* const [])regexArr length:(int)length {
for (int i = 0; i < length; i++) {
NSString* const regex = regexArr[i];
if ([self isMatch:text pattern:regex]) {
return YES;
}
}
return NO;
}
+ (BOOL)isMatch:(NSString *)text pattern:(NSString *)pattern {
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];
if (error) {
return NO;
}
if ([regex firstMatchInString:text options:0 range:NSMakeRange(0, text.length)]) {
return YES;
}
return NO;
}
- (NSString*)getMimeType:(NSURL *)url
{
NSString *fullPath = url.path;
NSString *mimeType = nil;
if (fullPath) {
CFStringRef typeId = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[fullPath pathExtension], NULL);
if (typeId) {
mimeType = (__bridge_transfer NSString*)UTTypeCopyPreferredTagWithClass(typeId, kUTTagClassMIMEType);
if (!mimeType) {
// special case for m4a
if ([(__bridge NSString*)typeId rangeOfString : @"m4a-audio"].location != NSNotFound) {
mimeType = @"audio/mp4";
} else if ([[fullPath pathExtension] rangeOfString:@"wav"].location != NSNotFound) {
mimeType = @"audio/wav";
} else if ([[fullPath pathExtension] rangeOfString:@"css"].location != NSNotFound) {
mimeType = @"text/css";
}
}
CFRelease(typeId);
}
}
return mimeType;
}
- (NSData *)decryptAES256WithKey:(NSString *)key iv:(NSString *)iv data:(NSString *)base64String {
NSLog(@"inside decrypt");
NSData *data = [[NSData alloc] initWithBase64EncodedString:base64String options:0];
size_t bufferSize = [data length] + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesDecrypted = 0;
NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
NSData *ivData = [iv dataUsingEncoding:NSUTF8StringEncoding];
CCCryptorStatus status = CCCrypt(kCCDecrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
keyData.bytes,
kCCKeySizeAES256,
ivData.bytes,
data.bytes,
data.length,
buffer,
bufferSize,
&numBytesDecrypted);
if (status == kCCSuccess) {
return [NSData dataWithBytes:buffer length:numBytesDecrypted];
}
free(buffer);
return nil;
}
- (NSString*)getMimeTypeFromPath:(NSString*)fullPath
{
NSString* mimeType = nil;
if (fullPath) {
CFStringRef typeId = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[fullPath pathExtension], NULL);
if (typeId) {
mimeType = (__bridge_transfer NSString*)UTTypeCopyPreferredTagWithClass(typeId, kUTTagClassMIMEType);
if (!mimeType) {
// special case for m4a
if ([(__bridge NSString*)typeId rangeOfString : @"m4a-audio"].location != NSNotFound) {
mimeType = @"audio/mp4";
} else if ([[fullPath pathExtension] rangeOfString:@"wav"].location != NSNotFound) {
mimeType = @"audio/wav";
} else if ([[fullPath pathExtension] rangeOfString:@"css"].location != NSNotFound) {
mimeType = @"text/css";
}
}
CFRelease(typeId);
}
}
return mimeType;
}
- (void)sendResponseWithResponseCode:(NSInteger)statusCode data:(NSData*)data mimeType:(NSString*)mimeType
{
NSLog(@"inside response");
if (mimeType == nil) {
mimeType = @"text/plain";
}
NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc] initWithURL:[[self request] URL] statusCode:statusCode HTTPVersion:@"HTTP/1.1" headerFields:@{@"Content-Type" : mimeType}];
[[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
if (data != nil) {
[[self client] URLProtocol:self didLoadData:data];
}
[[self client] URLProtocolDidFinishLoading:self];
}
+ (NSURLRequest*)canonicalRequestForRequest:(NSURLRequest*)request
{
NSLog(@"%@ received %@", self, NSStringFromSelector(_cmd));
return request;
}
@end
To explain this, the canInitWithRequest
will receive the url "http://localhost:8080/index.html, then the
checkCryptFilemethod will retrieve the extension example "html" and call the
hasMatch` method.
Then in the startLoading
method, I change this url to a valid file directory to be able to decrypt it, or you will get an error file not found. So, the good thing is that it decrypts the files, and in the logs I get:
2019-01-26 20:06:42.976473+0200 myApp[3848:75777] Finished load of: http://localhost:8080/index.html
But the problem is I keep getting a white screen with no data and nothing just a white screen.
So, it is decrypting and you can see in the log when you run it, but in the simulator (iPhone XR), I keep getting white screen after its loaded.
Note:
Also in the config.xml, you need to add <allow-navigation href="http://localhost:8080/*" />
to be able to use localhost:8080.
Also im testing this without cordova-ionic-webview
plugin, as crypto-file
needs to work first, then we add ionic-webview
and debug to check.
Summary:
Good Part:
Javascript part of cordova-crypto-file
is done, files are getting decrypted. The app is being served on localhost:8080.
Bad Part:
After finishing loading, only white screen is appearing in the app, sometimes the design and the data appear in the screen though.
@PeterHdd Thanks for trying. I am also looking it now.
@PeterHdd The plugin works properly, the problem is with the decryption time. If you open the safari inspect window and press reload button you will see that it will work one in five times. The plugins JS files sometimes doesn't get decrypted properly which also gives error.
Also I have noticed that sometimes the files contents are overwritten by other files. See the Resources tab in inspect window and try to see some js files. For e.g device plugin js content will be also shown in splashscreen js file, main.js file content shown in vendor.js file, etc..
@PeterHdd I am seeing same issue with decryption time, however my knowledge of objective-C is also null so I can't help you unfortunately. Hope you find a fix soon.
According to my tests using cordova-plugin-ionic-webview, canInitWithRequest isn't even being instantiated. Something to do with CDVURLProtocol not working with WkWebView I suppose.
Hello, It is not working with iOS. The files are getting encrypted properly, but when I run the app via Xcode, the app gets stuck at splash screen. It shows encrypted content on a white screen. Ios version 12.2
@PeterHdd where is the update? Still ios not working. Nothing there after January
hello any updates ?????????????????????????
If there is an ios developer who is willing to fix this, please let me know (I can help pay for your time and efforts, God willing). Thank you.
@givethanks1 check the forks, maybe someone fixed it there
Hi,
It is not working with iOS. The files are getting encrypted properly, but when I run the app via Xcode, the app gets stuck at splashscreen.