From a1a0aabd60d933dc021e411c966e3490317690cf Mon Sep 17 00:00:00 2001 From: Daniel Weck Date: Wed, 10 Dec 2014 02:14:51 +0000 Subject: [PATCH 01/13] initial commit, bindings work but the widget EPUB3 demo file from the Google Code samples does not resolve relative file paths correctly (moon-phase.xml data) so there is a TODO: pass absolute path to iframe src query parameter, not just the filename (otherwise the plugin XHTML cannot figure-out the base href). --- .../Core/Responses/HTTPFileResponse.m | 3 + LauncherOSX/LOXAppDelegate.mm | 3 + LauncherOSX/LOXPackage.mm | 5 +- LauncherOSX/LOXWebViewController.h | 4 + LauncherOSX/LOXWebViewController.mm | 88 ++++++++++++++++++- LauncherOSX/PackageResourceServer.mm | 28 ++---- readium-sdk | 2 +- 7 files changed, 109 insertions(+), 24 deletions(-) diff --git a/LauncherOSX/CocoaHTTPServer/Core/Responses/HTTPFileResponse.m b/LauncherOSX/CocoaHTTPServer/Core/Responses/HTTPFileResponse.m index 0e4a219..e7489ce 100755 --- a/LauncherOSX/CocoaHTTPServer/Core/Responses/HTTPFileResponse.m +++ b/LauncherOSX/CocoaHTTPServer/Core/Responses/HTTPFileResponse.m @@ -32,6 +32,9 @@ - (NSDictionary *)httpHeaders { else if([ext isEqualToString:@"css"]) { return [NSDictionary dictionaryWithObject:@"text/css" forKey:@"Content-Type"]; } + else if([ext isEqualToString:@"xml"]) { + return [NSDictionary dictionaryWithObject:@"application/xml" forKey:@"Content-Type"]; + } else if([ext isEqualToString:@"xhtml"] || [ext isEqualToString:@"html"]) { return [NSDictionary dictionaryWithObject:@"application/xhtml+xml" forKey:@"Content-Type"]; } diff --git a/LauncherOSX/LOXAppDelegate.mm b/LauncherOSX/LOXAppDelegate.mm index 2922c51..5d2635c 100644 --- a/LauncherOSX/LOXAppDelegate.mm +++ b/LauncherOSX/LOXAppDelegate.mm @@ -37,6 +37,7 @@ #import "LOXUtil.h" #import "LOXMediaOverlay.h" #import "LOXMediaOverlayController.h" +#import "LOXWebViewController.h" using namespace ePub3; @@ -88,6 +89,8 @@ - (id)init -(void) awakeFromNib { + [NSURLProtocol registerClass:[Epub3URLProtocol class]]; + _epubApi = [[LOXePubSdkApi alloc] init]; self.spineViewController.currentPagesInfo = _currentPagesInfo; diff --git a/LauncherOSX/LOXPackage.mm b/LauncherOSX/LOXPackage.mm index b085dbd..810e1e4 100644 --- a/LauncherOSX/LOXPackage.mm +++ b/LauncherOSX/LOXPackage.mm @@ -114,8 +114,11 @@ - (RDPackageResource *)resourceAtRelativePath:(NSString *)relativePath { return nil; } + NSRange range2 = [relativePath rangeOfString:@"?"]; + if (range2.location != NSNotFound) { + relativePath = [relativePath substringToIndex:range2.location]; + } NSRange range = [relativePath rangeOfString:@"#"]; - if (range.location != NSNotFound) { relativePath = [relativePath substringToIndex:range.location]; } diff --git a/LauncherOSX/LOXWebViewController.h b/LauncherOSX/LOXWebViewController.h index 724945f..e9ddd7d 100644 --- a/LauncherOSX/LOXWebViewController.h +++ b/LauncherOSX/LOXWebViewController.h @@ -39,6 +39,10 @@ @class WebView; @class PackageResourceServer; +@interface Epub3URLProtocol : NSURLProtocol + +@end + @interface LOXWebViewController : NSObject { @private diff --git a/LauncherOSX/LOXWebViewController.mm b/LauncherOSX/LOXWebViewController.mm index 8cd6340..69dacd0 100644 --- a/LauncherOSX/LOXWebViewController.mm +++ b/LauncherOSX/LOXWebViewController.mm @@ -33,8 +33,63 @@ #import "PackageResourceServer.h" #import "RDPackageResource.h" #import +#import +@interface Epub3URLProtocol () +@property (nonatomic, strong) NSURLConnection *connection; ++(NSString *)scheme; +@end +@implementation Epub3URLProtocol + +static NSString* EPUB3 = [NSString stringWithUTF8String:ePub3::IRI::gEPUBScheme.c_str()]; + ++(NSString *)scheme;{ + return EPUB3; +} + ++ (BOOL)canInitWithRequest:(NSURLRequest *)request +{ + NSURL* requestURI = [request URL]; + if(NSOrderedSame == [[requestURI scheme] caseInsensitiveCompare:EPUB3]){ + return YES; + } + + return NO; +} ++ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request +{ + return request; +} +- (void)startLoading +{ + NSMutableURLRequest *newRequest = [self.request mutableCopy]; + self.connection = [NSURLConnection connectionWithRequest:newRequest delegate:self]; +} +- (void)stopLoading +{ + [self.connection cancel]; +} +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data +{ + [self.client URLProtocol:self didLoadData:data]; +} +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error +{ + [self.client URLProtocol:self didFailWithError:error]; + self.connection = nil; +} +- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response +{ + [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed]; +} +- (void)connectionDidFinishLoading:(NSURLConnection *)connection +{ + [self.client URLProtocolDidFinishLoading:self]; + self.connection = nil; +} +@end + @interface LOXWebViewController () -(void)onPageChanged:(NSNotification*) notification; @@ -133,7 +188,6 @@ - (NSURLRequest *)webView:(WebView *)sender //NSString * prefix2 = [NSString stringWithFormat:@"%@%@", prefix1, folder]; //[path substringFromIndex: [path rangeOfString:prefix1].location] - if (schemeFile != NSOrderedSame && [path hasPrefix:folder]) { NSString * str = [[NSString stringWithFormat:@"file://%@", path] stringByAddingPercentEscapesUsingEncoding : NSUTF8StringEncoding]; NSURL *url = [NSURL URLWithString:str]; @@ -144,7 +198,12 @@ - (NSURLRequest *)webView:(WebView *)sender return newRequest; } - if (schemeFile != NSOrderedSame) + // ObjectPreprocessor and ContentHandler with epub3:// URI protocol + // See [NSURLProtocol registerClass:[Epub3URLProtocol class]]; + //NSString* EPUB3 = [NSString stringWithUTF8String:ePub3::IRI::gEPUBScheme.c_str()]; + NSComparisonResult schemeEPUB = [scheme caseInsensitiveCompare: [Epub3URLProtocol scheme]]; + + if (schemeFile != NSOrderedSame && schemeEPUB != NSOrderedSame) { return request; } @@ -154,10 +213,35 @@ - (NSURLRequest *)webView:(WebView *)sender return request; } + if (schemeEPUB == NSOrderedSame) + { + NSString* BASE = [NSString stringWithUTF8String:_package.sdkPackage->BasePath().c_str()]; + if (![BASE hasPrefix:@"/"]) { + BASE = [NSString stringWithFormat:@"/%@", BASE]; + } + if ([path hasPrefix:BASE]) + { + path = [path substringFromIndex:[BASE length]]; + + schemeFile == NSOrderedSame; + } + } + if ([path hasPrefix:@"/"]) { path = [path substringFromIndex:1]; } + NSString *query = request.URL.query; + if (query != nil) + { + path = [NSString stringWithFormat:@"%@?%@", path, query]; + } + NSString *fragment = request.URL.fragment; + if (fragment != nil) + { + path = [NSString stringWithFormat:@"%@#%@", path, fragment]; + } + NSString * str = [[NSString stringWithFormat:@"%@/%@/%@", prefix1, _package.packageUUID, path] stringByAddingPercentEscapesUsingEncoding : NSUTF8StringEncoding]; NSURL *url = [NSURL URLWithString:str]; diff --git a/LauncherOSX/PackageResourceServer.mm b/LauncherOSX/PackageResourceServer.mm index 2aa45c0..cf0b1d2 100644 --- a/LauncherOSX/PackageResourceServer.mm +++ b/LauncherOSX/PackageResourceServer.mm @@ -59,17 +59,11 @@ @implementation PackageResourceConnection bool isHTML = [ext isEqualToString:@"xhtml"] || [ext isEqualToString:@"html"]; //[path hasSuffix:@".html"] || [path hasSuffix:@".xhtml"]; - if([ext isEqualToString:@"svg"]) { - contentType = @"image/svg+xml"; - } - else if([ext isEqualToString:@"js"]) { - contentType = @"text/javascript"; - } - else if([ext isEqualToString:@"css"]) { - contentType = @"text/css"; + if([ext isEqualToString:@"xml"]) { + contentType = @"application/xml"; // FORCE } else if(isHTML) { - contentType = @"application/xhtml+xml"; + contentType = @"application/xhtml+xml"; // FORCE } if (contentType == nil) @@ -262,18 +256,12 @@ - (NSDictionary *)httpHeaders { if(m_resource.relativePath) { NSString* ext = [[m_resource.relativePath pathExtension] lowercaseString]; - - if([ext isEqualToString:@"svg"]) { - return [NSDictionary dictionaryWithObject:@"image/svg+xml" forKey:@"Content-Type"]; - } - else if([ext isEqualToString:@"js"]) { - return [NSDictionary dictionaryWithObject:@"text/javascript" forKey:@"Content-Type"]; - } - else if([ext isEqualToString:@"css"]) { - return [NSDictionary dictionaryWithObject:@"text/css" forKey:@"Content-Type"]; + + if([ext isEqualToString:@"xhtml"] || [ext isEqualToString:@"html"]) { + return [NSDictionary dictionaryWithObject:@"application/xhtml+xml" forKey:@"Content-Type"]; // FORCE } - else if([ext isEqualToString:@"xhtml"] || [ext isEqualToString:@"html"]) { - return [NSDictionary dictionaryWithObject:@"application/xhtml+xml" forKey:@"Content-Type"]; + else if([ext isEqualToString:@"xml"]) { + return [NSDictionary dictionaryWithObject:@"application/xml" forKey:@"Content-Type"]; // FORCE } else { diff --git a/readium-sdk b/readium-sdk index 5d099de..2b8a384 160000 --- a/readium-sdk +++ b/readium-sdk @@ -1 +1 @@ -Subproject commit 5d099ded268b155a8d7d119687ca6bc2ababc905 +Subproject commit 2b8a3849265f3e362ca2291317d121d7db39deb7 From 02bc359a95e323dcc552074ee6483f6a43686a7e Mon Sep 17 00:00:00 2001 From: Daniel Weck Date: Fri, 12 Dec 2014 19:23:55 +0000 Subject: [PATCH 02/13] EPUB3 Bindings work, but there are bug fixes I need to backport to the develop branch --- LauncherOSX/LOXPackage.mm | 28 +++--- LauncherOSX/LOXWebViewController.mm | 134 ++++++++++++++++++++------- LauncherOSX/PackageResourceServer.mm | 44 +++++---- LauncherOSX/RDPackageResource.mm | 4 +- readium-sdk | 2 +- 5 files changed, 144 insertions(+), 68 deletions(-) diff --git a/LauncherOSX/LOXPackage.mm b/LauncherOSX/LOXPackage.mm index 810e1e4..eb8d0f3 100644 --- a/LauncherOSX/LOXPackage.mm +++ b/LauncherOSX/LOXPackage.mm @@ -105,7 +105,18 @@ - (NSString *) resourceRelativePath:(NSString *)urlAbsolutePath return nil; } - return [urlAbsolutePath substringFromIndex:NSMaxRange(range)]; + NSString * relativePath = [urlAbsolutePath substringFromIndex:NSMaxRange(range)]; + + NSRange rangeQ = [relativePath rangeOfString:@"?"]; + if (rangeQ.location != NSNotFound) { + relativePath = [relativePath substringToIndex:rangeQ.location]; + } + NSRange rangeH = [relativePath rangeOfString:@"#"]; + if (rangeH.location != NSNotFound) { + relativePath = [relativePath substringToIndex:rangeH.location]; + } + + return relativePath; } - (RDPackageResource *)resourceAtRelativePath:(NSString *)relativePath { @@ -114,27 +125,18 @@ - (RDPackageResource *)resourceAtRelativePath:(NSString *)relativePath { return nil; } - NSRange range2 = [relativePath rangeOfString:@"?"]; - if (range2.location != NSNotFound) { - relativePath = [relativePath substringToIndex:range2.location]; - } - NSRange range = [relativePath rangeOfString:@"#"]; - if (range.location != NSNotFound) { - relativePath = [relativePath substringToIndex:range.location]; - } - ePub3::string s = ePub3::string(relativePath.UTF8String); //ConstManifestItemPtr std::shared_ptr manItem = _sdkPackage->ManifestItemAtRelativePath(s); if (manItem == nullptr) { - NSLog(@"Relative path '%@' does not have a manifest item!", relativePath); + NSLog(@"Relative path '%@' does not have a manifest item! (resourceAtRelativePath)", relativePath); //return nil; } std::unique_ptr byteStream = _sdkPackage->ReadStreamForRelativePath(s); if (byteStream == nullptr) { - NSLog(@"Relative path '%@' does not have an archive byte stream!", relativePath); + NSLog(@"Relative path '%@' does not have an archive byte stream! (resourceAtRelativePath)", relativePath); return nil; } @@ -160,7 +162,7 @@ - (void *)getProperByteStream:(NSString *)relativePath currentByteStream:(ePub3: ePub3::ConstManifestItemPtr manifestItem = _sdkPackage->ManifestItemAtRelativePath(s); if (manifestItem == nullptr) { - NSLog(@"Relative path '%@' does not have a manifest item!", relativePath); + NSLog(@"Relative path '%@' does not have a manifest item! (getProperByteStream)", relativePath); //return nil; return currentByteStream; } diff --git a/LauncherOSX/LOXWebViewController.mm b/LauncherOSX/LOXWebViewController.mm index 69dacd0..c8312e2 100644 --- a/LauncherOSX/LOXWebViewController.mm +++ b/LauncherOSX/LOXWebViewController.mm @@ -36,8 +36,8 @@ #import -@interface Epub3URLProtocol () -@property (nonatomic, strong) NSURLConnection *connection; +@interface Epub3URLProtocol () // +//@property (nonatomic, strong) NSURLConnection *connection; +(NSString *)scheme; @end @implementation Epub3URLProtocol @@ -47,47 +47,109 @@ @implementation Epub3URLProtocol +(NSString *)scheme;{ return EPUB3; } +// +//- (id)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id)client { +// +// if ((self = [super initWithRequest:request cachedResponse:cachedResponse client:client])) { +// +// } +// +// return self; +//} +//- (void)dealloc { +// +// if (self.connection != nil) +// { +// self.connection.cancel; +// } +//} + (BOOL)canInitWithRequest:(NSURLRequest *)request { NSURL* requestURI = [request URL]; - if(NSOrderedSame == [[requestURI scheme] caseInsensitiveCompare:EPUB3]){ + if (requestURI == nil) + { + return NO; + } + if (NSOrderedSame == [[requestURI scheme] caseInsensitiveCompare:EPUB3]) + { + if ([NSURLProtocol propertyForKey:@"Epub3URLProtocol_Handled" inRequest:request]) + { + return NO; + } + return YES; } return NO; } + + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { return request; } + - (void)startLoading { NSMutableURLRequest *newRequest = [self.request mutableCopy]; - self.connection = [NSURLConnection connectionWithRequest:newRequest delegate:self]; -} -- (void)stopLoading -{ - [self.connection cancel]; -} -- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data -{ - [self.client URLProtocol:self didLoadData:data]; -} -- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error -{ - [self.client URLProtocol:self didFailWithError:error]; - self.connection = nil; + + [NSURLProtocol setProperty:@YES forKey:@"Epub3URLProtocol_Handled" inRequest:newRequest]; + + NSString * str = [NSURLProtocol propertyForKey:@"URLSTR" inRequest:newRequest]; + NSURL *url = [NSURL URLWithString:[str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + [newRequest setURL: url]; + + NSURL* originalURL = [self.request URL]; + + NSURLResponse *response = [[NSURLResponse alloc] initWithURL:originalURL MIMEType:nil expectedContentLength:0 textEncodingName:nil]; + [self.client URLProtocol:self wasRedirectedToRequest:newRequest redirectResponse:response]; + [self.client URLProtocolDidFinishLoading:self]; + + //self.connection = [NSURLConnection connectionWithRequest:newRequest delegate:self]; } -- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response -{ - [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed]; + ++ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b { + return [super requestIsCacheEquivalent:a toRequest:b]; } -- (void)connectionDidFinishLoading:(NSURLConnection *)connection + +- (void)stopLoading { - [self.client URLProtocolDidFinishLoading:self]; - self.connection = nil; +// if (self.connection != nil) +// { +// [self.connection cancel]; +// } +// self.connection = nil; } + +//-(NSURLRequest *)connection:(NSURLConnection *)connection +// willSendRequest:(NSURLRequest *)request +// redirectResponse:(NSURLResponse *)redirectResponse +// +//{ +// NSURLRequest *newRequest = request; +// if (redirectResponse) { +// newRequest = nil; +// } +// return newRequest; +//} +//- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data +//{ +// [self.client URLProtocol:self didLoadData:data]; +//} +//- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error +//{ +// [self.client URLProtocol:self didFailWithError:error]; +// self.connection = nil; +//} +//- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response +//{ +// [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed]; +//} +//- (void)connectionDidFinishLoading:(NSURLConnection *)connection +//{ +// [self.client URLProtocolDidFinishLoading:self]; +// self.connection = nil; +//} @end @interface LOXWebViewController () @@ -158,8 +220,8 @@ - (NSURLRequest *)webView:(WebView *)sender NSString * math = @"/readium_MathJax.js"; if ([path hasPrefix:math]) { NSString *filePath = [[NSBundle mainBundle] pathForResource:@"MathJax" ofType:@"js" inDirectory:@"Scripts/mathjax"]; - NSString * str = [[NSString stringWithFormat:@"file://%@", filePath] stringByAddingPercentEscapesUsingEncoding : NSUTF8StringEncoding]; - NSURL *url = [NSURL URLWithString:str]; + NSString * str = [NSString stringWithFormat:@"file://%@", filePath]; + NSURL *url = [NSURL URLWithString: [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; NSMutableURLRequest *newRequest = [request mutableCopy]; [newRequest setURL: url]; @@ -170,8 +232,8 @@ - (NSURLRequest *)webView:(WebView *)sender NSString * annotationsCSS = @"/readium_Annotations.css"; if ([path hasPrefix:annotationsCSS]) { NSString *filePath = [[NSBundle mainBundle] pathForResource:@"annotations" ofType:@"css" inDirectory:@"Scripts"]; - NSString * str = [[NSString stringWithFormat:@"file://%@", filePath] stringByAddingPercentEscapesUsingEncoding : NSUTF8StringEncoding]; - NSURL *url = [NSURL URLWithString:str]; + NSString * str = [NSString stringWithFormat:@"file://%@", filePath]; + NSURL *url = [NSURL URLWithString: [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; NSMutableURLRequest *newRequest = [request mutableCopy]; [newRequest setURL: url]; @@ -189,8 +251,8 @@ - (NSURLRequest *)webView:(WebView *)sender //[path substringFromIndex: [path rangeOfString:prefix1].location] if (schemeFile != NSOrderedSame && [path hasPrefix:folder]) { - NSString * str = [[NSString stringWithFormat:@"file://%@", path] stringByAddingPercentEscapesUsingEncoding : NSUTF8StringEncoding]; - NSURL *url = [NSURL URLWithString:str]; + NSString * str = [NSString stringWithFormat:@"file://%@", path]; + NSURL *url = [NSURL URLWithString: [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; NSMutableURLRequest *newRequest = [request mutableCopy]; [newRequest setURL: url]; @@ -222,9 +284,9 @@ - (NSURLRequest *)webView:(WebView *)sender if ([path hasPrefix:BASE]) { path = [path substringFromIndex:[BASE length]]; - - schemeFile == NSOrderedSame; } + + //prefix1 = [NSString stringWithFormat:@"%@://", [Epub3URLProtocol scheme]]; } if ([path hasPrefix:@"/"]) { @@ -242,12 +304,16 @@ - (NSURLRequest *)webView:(WebView *)sender path = [NSString stringWithFormat:@"%@#%@", path, fragment]; } - NSString * str = [[NSString stringWithFormat:@"%@/%@/%@", prefix1, _package.packageUUID, path] stringByAddingPercentEscapesUsingEncoding : NSUTF8StringEncoding]; - NSURL *url = [NSURL URLWithString:str]; + NSString * str = [NSString stringWithFormat:@"%@/%@/%@", prefix1, _package.packageUUID, path]; + if (schemeEPUB == NSOrderedSame) { + [NSURLProtocol setProperty:[NSString stringWithString:str] forKey:@"URLSTR" inRequest:request]; + return request; + } + + NSURL *url = [NSURL URLWithString: [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; NSMutableURLRequest *newRequest = [request mutableCopy]; [newRequest setURL: url]; - return newRequest; } diff --git a/LauncherOSX/PackageResourceServer.mm b/LauncherOSX/PackageResourceServer.mm index cf0b1d2..b081992 100644 --- a/LauncherOSX/PackageResourceServer.mm +++ b/LauncherOSX/PackageResourceServer.mm @@ -54,6 +54,11 @@ @implementation PackageResourceConnection @synchronized ([PackageResourceServer resourceLock]) { RDPackageResource *resource = [m_package resourceAtRelativePath:path]; + if (resource == nil) { + NSLog(@"No resource found! (%@)", path); + return nil; + } + NSString* ext = [[path pathExtension] lowercaseString]; NSString* contentType = nil; @@ -78,35 +83,39 @@ @implementation PackageResourceConnection } } } - - if (resource == nil) { - NSLog(@"No resource found! (%@)", path); + + if (contentType == nil) + { + NSLog(@"No contentType?! (%@)", path); } - else { - if (!isHTML) { - ePub3::string s = ePub3::string(path.UTF8String); - ePub3::ManifestTable manifest = [m_package sdkPackage]->Manifest(); - for (auto i = manifest.begin(); i != manifest.end(); i++) { - std::shared_ptr item = i->second; - if (item->Href() == s) { - if (item->MediaType() == "application/xhtml+xml") { - isHTML = true; - } - break; - } - } + + if (!isHTML) { + if (contentType != nil && (contentType == @"application/xhtml+xml" || contentType == @"text/html")) { + isHTML = true; } + } + if (isHTML) { NSData *data = [resource readDataFull]; if (data != nil) { - BOOL ok = NO; +// NSString * dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; +// NSLog(@"XHTML SOURCE: %@", dataStr); +// data = [dataStr dataUsingEncoding:NSUTF8StringEncoding]; + + BOOL ok = YES; @try { NSXMLParser *xmlparser = [[NSXMLParser alloc] initWithData:data]; //[xmlparser setDelegate:self]; [xmlparser setShouldResolveExternalEntities:NO]; ok = [xmlparser parse]; + + if (ok == NO) + { + NSError * error = [xmlparser parserError]; + NSLog(@"XHTML PARSE ERROR: %@", error); + } } @catch (NSException *ex) { @@ -182,7 +191,6 @@ @implementation PackageResourceConnection // if (data != nil) { // return [[HTTPDataResponse alloc] initWithData:data contentType:contentType]; // } - } } return nil; diff --git a/LauncherOSX/RDPackageResource.mm b/LauncherOSX/RDPackageResource.mm index 5430019..198b798 100644 --- a/LauncherOSX/RDPackageResource.mm +++ b/LauncherOSX/RDPackageResource.mm @@ -50,8 +50,6 @@ - (NSData *)readDataFull { } else { - NSMutableData *md = [[NSMutableData alloc] initWithCapacity: m_bytesCount]; - if (!m_hasProperStream) { ePub3::ByteStream *byteStream = m_byteStream.release(); @@ -60,6 +58,8 @@ - (NSData *)readDataFull { m_hasProperStream = YES; } + NSMutableData *md = [[NSMutableData alloc] initWithCapacity: m_bytesCount]; + while (YES) { std::size_t count = m_byteStream->ReadBytes(m_buffer, sizeof(m_buffer)); diff --git a/readium-sdk b/readium-sdk index 2b8a384..5ebca44 160000 --- a/readium-sdk +++ b/readium-sdk @@ -1 +1 @@ -Subproject commit 2b8a3849265f3e362ca2291317d121d7db39deb7 +Subproject commit 5ebca44fa0f744fb5f6c50f017245eb47c11d904 From 47b7b2f0f4a6299e9d1a3ce3d42ad5469959bebe Mon Sep 17 00:00:00 2001 From: Daniel Weck Date: Fri, 12 Dec 2014 21:42:34 +0000 Subject: [PATCH 03/13] submodule --- readium-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readium-sdk b/readium-sdk index 3de04c1..fbbb9d3 160000 --- a/readium-sdk +++ b/readium-sdk @@ -1 +1 @@ -Subproject commit 3de04c18ad03e9da17fd5ad2eebfbbac0899d8e8 +Subproject commit fbbb9d3f06de8b193f15a5ccb34f38f6c2adc546 From d0a71e590b6231a7fab21b24795021589d7d0903 Mon Sep 17 00:00:00 2001 From: Daniel Weck Date: Fri, 12 Dec 2014 23:04:19 +0000 Subject: [PATCH 04/13] submodule --- readium-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readium-sdk b/readium-sdk index fbbb9d3..499c07f 160000 --- a/readium-sdk +++ b/readium-sdk @@ -1 +1 @@ -Subproject commit fbbb9d3f06de8b193f15a5ccb34f38f6c2adc546 +Subproject commit 499c07f9d2848c6ab933f1f0e30cda2fd9aba5a0 From 17388b39a4455ce874a9089e8c1af904a9ae3e3c Mon Sep 17 00:00:00 2001 From: Daniel Weck Date: Sat, 13 Dec 2014 01:14:33 +0000 Subject: [PATCH 05/13] Switch + Bindings works, also epubReadingSystem injection in subframes --- LauncherOSX/LOXWebViewController.mm | 2 +- LauncherOSX/PackageResourceServer.mm | 2 +- readium-sdk | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/LauncherOSX/LOXWebViewController.mm b/LauncherOSX/LOXWebViewController.mm index c8312e2..d45b1c6 100644 --- a/LauncherOSX/LOXWebViewController.mm +++ b/LauncherOSX/LOXWebViewController.mm @@ -206,7 +206,7 @@ - (NSURLRequest *)webView:(WebView *)sender // NSString *code = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; // Iterate top-level iframes, inject global window.navigator.epubReadingSystem if the expected hook function exists ( readium_set_epubReadingSystem() ). - NSString* cmd = @"for (var i = 0; i < window.frames.length; i++) { var iframe = window.frames[i]; if (iframe.readium_set_epubReadingSystem) { iframe.readium_set_epubReadingSystem(window.navigator.epubReadingSystem); }}"; + NSString* cmd = @"var epubRSInject = function(win) { if (win.frames) { for (var i = 0; i < win.frames.length; i++) { var iframe = win.frames[i]; if (iframe.readium_set_epubReadingSystem) { iframe.readium_set_epubReadingSystem(window.navigator.epubReadingSystem); } epubRSInject(iframe); } } }; epubRSInject(window);"; // does not work as expected: // WebScriptObject* script = [sender windowScriptObject]; diff --git a/LauncherOSX/PackageResourceServer.mm b/LauncherOSX/PackageResourceServer.mm index 65aa7e3..15cf69e 100644 --- a/LauncherOSX/PackageResourceServer.mm +++ b/LauncherOSX/PackageResourceServer.mm @@ -161,7 +161,7 @@ @implementation PackageResourceConnection NSString *inject_epubReadingSystem2 = @""; NSString *inject_mathJax = @""; - if ([source rangeOfString:@" ", m_baseUrlPath]; inject_mathJax = @""; diff --git a/readium-sdk b/readium-sdk index 499c07f..ccff7d4 160000 --- a/readium-sdk +++ b/readium-sdk @@ -1 +1 @@ -Subproject commit 499c07f9d2848c6ab933f1f0e30cda2fd9aba5a0 +Subproject commit ccff7d408ba250e710562ce7334edf6738afbbec From 9a7e460cca4acc9f6adc50c5be6d245028ae5f08 Mon Sep 17 00:00:00 2001 From: Daniel Weck Date: Tue, 16 Dec 2014 20:54:00 +0000 Subject: [PATCH 06/13] fixed detection of EOF in HTTP response implementation, 50kB buffers for testing small resources such as encrypted images --- .../CocoaHTTPServer/Core/HTTPConnection.m | 2 +- LauncherOSX/PackageResourceServer.h | 2 + LauncherOSX/PackageResourceServer.mm | 215 ++++++++++-------- LauncherOSX/RDPackageResource.h | 4 +- LauncherOSX/RDPackageResource.mm | 195 +++++++++------- readium-sdk | 2 +- 6 files changed, 246 insertions(+), 174 deletions(-) diff --git a/LauncherOSX/CocoaHTTPServer/Core/HTTPConnection.m b/LauncherOSX/CocoaHTTPServer/Core/HTTPConnection.m index d4ac82f..fc86e13 100755 --- a/LauncherOSX/CocoaHTTPServer/Core/HTTPConnection.m +++ b/LauncherOSX/CocoaHTTPServer/Core/HTTPConnection.m @@ -25,7 +25,7 @@ #if TARGET_OS_IPHONE #define READ_CHUNKSIZE (1024 * 256) #else - #define READ_CHUNKSIZE (1024 * 512) + #define READ_CHUNKSIZE (1024 * 50) #endif // Define chunk size used to read in POST upload data diff --git a/LauncherOSX/PackageResourceServer.h b/LauncherOSX/PackageResourceServer.h index a7c4d94..0d79d52 100644 --- a/LauncherOSX/PackageResourceServer.h +++ b/LauncherOSX/PackageResourceServer.h @@ -22,6 +22,8 @@ @interface PackageResourceResponse : NSObject { @private UInt64 m_offset; +@private UInt64 m_offsetInitial; +//@private bool m_isDone; @private RDPackageResource *m_resource; @private BOOL m_isRangeRequest; } diff --git a/LauncherOSX/PackageResourceServer.mm b/LauncherOSX/PackageResourceServer.mm index 15cf69e..914f773 100644 --- a/LauncherOSX/PackageResourceServer.mm +++ b/LauncherOSX/PackageResourceServer.mm @@ -95,98 +95,103 @@ @implementation PackageResourceConnection } } - if (isHTML) { - NSData *data = [resource readDataFull]; - if (data != nil) { - - // Can be used to check / debug encoding issues - // NSString * dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - // NSLog(@"XHTML SOURCE: %@", dataStr); - // data = [dataStr dataUsingEncoding:NSUTF8StringEncoding]; - - BOOL ok = YES; - @try - { - NSXMLParser *xmlparser = [[NSXMLParser alloc] initWithData:data]; - //[xmlparser setDelegate:self]; - [xmlparser setShouldResolveExternalEntities:NO]; - ok = [xmlparser parse]; - - if (ok == NO) - { - NSError * error = [xmlparser parserError]; - NSLog(@"XHTML PARSE ERROR: %@", error); - } - } - @catch (NSException *ex) - { - NSLog(@"XHTML parse exception: %@", ex); - ok = NO; - } - - if (ok == NO) - { - //contentType = @"application/xhtml+xml"; - contentType = @"text/html"; - - //TODO: resource.contentType = contentType; - } - - NSString* source = [self htmlFromData:data]; - if (source != nil) { - NSString *pattern = @"()"; - NSError *error = nil; - NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error]; - if(error != nil) { - NSLog(@"RegEx error: %@", error); - } else { - //NSString *filePath = [[NSBundle mainBundle] pathForResource:@"epubReadingSystem_inject" ofType:@"js" inDirectory:@"Scripts"]; - //NSString *code = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; - //NSString *inject_epubReadingSystem = [NSString stringWithFormat:@"", code]; - - //NSString *inject_epubReadingSystem1 = [NSString stringWithFormat:@"", m_baseUrlPath]; - - // Installs "hook" function so that top-level window (application) can later inject the window.navigator.epubReadingSystem into this HTML document's iframe - NSString *inject_epubReadingSystem1 = [NSString stringWithFormat:@"", - @"window.readium_set_epubReadingSystem = function (obj) {\ - \nwindow.navigator.epubReadingSystem = obj;\ - \nwindow.readium_set_epubReadingSystem = undefined;\ - \nvar el1 = document.getElementById(\"readium_epubReadingSystem_inject1\");\ - \nif (el1 && el1.parentNode) { el1.parentNode.removeChild(el1); }\ - \nvar el2 = document.getElementById(\"readium_epubReadingSystem_inject2\");\ - \nif (el2 && el2.parentNode) { el2.parentNode.removeChild(el2); }\ - \n};"]; - - // Fake script, generates HTTP request => triggers the push of window.navigator.epubReadingSystem into this HTML document's iframe (see LOXWebViewController.mm where the "readium_epubReadingSystem_inject" UIWebView URI query is handled) - NSString *inject_epubReadingSystem2 = @""; - - NSString *inject_mathJax = @""; - if ([source rangeOfString:@" ", m_baseUrlPath]; - inject_mathJax = @""; - - //NSString *filePath = [[NSBundle mainBundle] pathForResource:@"MathJax" ofType:@"js" inDirectory:@"Scripts/mathjax"]; - //NSString *code = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; - //inject_mathJax = [NSString stringWithFormat:@"", code]; - //inject_mathJax = [NSString stringWithFormat:@"", code]; - //inject_mathJax = [NSString stringWithFormat:@"", code]; - } - - NSString *newSource = [regex stringByReplacingMatchesInString:source options:0 range:NSMakeRange(0, [source length]) withTemplate: - [NSString stringWithFormat:@"%@\n%@\n%@\n%@", @"$1", inject_epubReadingSystem1, inject_epubReadingSystem2, inject_mathJax]]; - if (newSource != nil && newSource.length > 0) { - NSData * newData = [newSource dataUsingEncoding:NSUTF8StringEncoding]; - if (newData != nil) { - return [[HTTPDataResponse alloc] initWithData:newData contentType:contentType]; - } - } - } - } + if (isHTML) { + NSString * FALLBACK_HTML = @"HTML READ ERRORERROR READING HTML BYTES!"; + NSData *data = [resource readDataFull]; + if (data == nil || data.length == 0) + { + data = [FALLBACK_HTML dataUsingEncoding:NSUTF8StringEncoding]; + } + + BOOL ok = YES; + @try + { + NSXMLParser *xmlparser = [[NSXMLParser alloc] initWithData:data]; + //[xmlparser setDelegate:self]; + [xmlparser setShouldResolveExternalEntities:NO]; + ok = [xmlparser parse]; + + if (ok == NO) + { + NSError * error = [xmlparser parserError]; + NSLog(@"XHTML PARSE ERROR: %@", error); + + // Can be used to check / debug encoding issues + NSString * dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + NSLog(@"XHTML SOURCE: %@", dataStr); } } + @catch (NSException *ex) + { + NSLog(@"XHTML parse exception: %@", ex); + ok = NO; + } + + if (ok == NO) + { + //contentType = @"application/xhtml+xml"; + contentType = @"text/html"; - return [[PackageResourceResponse alloc] initWithResource:resource]; + //TODO: resource.contentType = contentType; + } + + NSString* source = [self htmlFromData:data]; + if (source == nil || source.length == 0) + { + source = FALLBACK_HTML; + } + + NSString *pattern = @"(]*>)"; + NSError *error = nil; + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error]; + if(error != nil) { + NSLog(@"RegEx error: %@", error); + } else { + //NSString *filePath = [[NSBundle mainBundle] pathForResource:@"epubReadingSystem_inject" ofType:@"js" inDirectory:@"Scripts"]; + //NSString *code = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; + //NSString *inject_epubReadingSystem = [NSString stringWithFormat:@"", code]; + + //NSString *inject_epubReadingSystem1 = [NSString stringWithFormat:@"", m_baseUrlPath]; + + // Installs "hook" function so that top-level window (application) can later inject the window.navigator.epubReadingSystem into this HTML document's iframe + NSString *inject_epubReadingSystem1 = [NSString stringWithFormat:@"", + @"window.readium_set_epubReadingSystem = function (obj) {\ + \nwindow.navigator.epubReadingSystem = obj;\ + \nwindow.readium_set_epubReadingSystem = undefined;\ + \nvar el1 = document.getElementById(\"readium_epubReadingSystem_inject1\");\ + \nif (el1 && el1.parentNode) { el1.parentNode.removeChild(el1); }\ + \nvar el2 = document.getElementById(\"readium_epubReadingSystem_inject2\");\ + \nif (el2 && el2.parentNode) { el2.parentNode.removeChild(el2); }\ + \n};"]; + + // Fake script, generates HTTP request => triggers the push of window.navigator.epubReadingSystem into this HTML document's iframe (see LOXWebViewController.mm where the "readium_epubReadingSystem_inject" UIWebView URI query is handled) + NSString *inject_epubReadingSystem2 = @""; + + NSString *inject_mathJax = @""; + if ([source rangeOfString:@" ", m_baseUrlPath]; + inject_mathJax = @""; + + //NSString *filePath = [[NSBundle mainBundle] pathForResource:@"MathJax" ofType:@"js" inDirectory:@"Scripts/mathjax"]; + //NSString *code = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; + //inject_mathJax = [NSString stringWithFormat:@"", code]; + //inject_mathJax = [NSString stringWithFormat:@"", code]; + //inject_mathJax = [NSString stringWithFormat:@"", code]; + } + + NSString *newSource = [regex stringByReplacingMatchesInString:source options:0 range:NSMakeRange(0, [source length]) withTemplate: + [NSString stringWithFormat:@"%@\n%@\n%@\n%@", @"$1", inject_epubReadingSystem1, inject_epubReadingSystem2, inject_mathJax]]; + if (newSource != nil && newSource.length > 0) { + NSData * newData = [newSource dataUsingEncoding:NSUTF8StringEncoding]; + if (newData != nil) { + return [[HTTPDataResponse alloc] initWithData:newData contentType:contentType]; + } + } + } + } + + return [[PackageResourceResponse alloc] initWithResource:resource]; // // NSData *data = resource.data; // if (data != nil) { @@ -289,7 +294,14 @@ - (NSDictionary *)httpHeaders { return [NSDictionary new]; } +//- (BOOL)isChunked +//{ +// return YES; // we do not know the content length in advance +//} + - (UInt64)contentLength { + printf("contentLength: %d (%s)\n", m_resource.bytesCount, [m_resource.relativePath UTF8String]); + return m_resource.bytesCount; } @@ -302,6 +314,7 @@ - (id)initWithResource:(RDPackageResource *)resource { if (self = [super init]) { m_resource = resource; m_isRangeRequest = NO; + //m_isDone = false; } return self; @@ -309,8 +322,13 @@ - (id)initWithResource:(RDPackageResource *)resource { - (BOOL)isDone { - bool isDone = m_offset >= m_resource.bytesCount; -//printf("is DONE: %d\n", isDone); + + bool isDone = !m_isRangeRequest + ? (m_offset >= m_resource.bytesCount) + : (m_offset >= (m_offsetInitial + m_resource.bytesCountCheck)); + +printf("is DONE: %d (%s)\n", isDone, [m_resource.relativePath UTF8String]); + return isDone; } @@ -323,8 +341,10 @@ - (UInt64)offset { - (NSData *)readDataOfLength:(NSUInteger)length { NSData *data = nil; + //printf("readDataOfLength 1 %s (%d)\n", [m_resource.relativePath UTF8String], length); @synchronized ([PackageResourceServer resourceLock]) { + printf("readDataOfLength %s (%d)\n", [m_resource.relativePath UTF8String], length); data = [m_resource readDataOfLength:length offset:m_offset isRangeRequest:m_isRangeRequest]; } @@ -332,12 +352,25 @@ - (NSData *)readDataOfLength:(NSUInteger)length { m_offset += data.length; } + if (data == nil || data.length == 0) + { + printf("readDataOfLength NO DATA %s (%d)\n", [m_resource.relativePath UTF8String], length); + //m_isDone = true; + } + + if (data == nil) + { + data = [NSData data]; + } + return data; } - (void)setOffset:(UInt64)offset { + printf("setOffset: %d (%s)\n", offset, [m_resource.relativePath UTF8String]); m_offset = offset; + m_offsetInitial = offset; m_isRangeRequest = YES; } diff --git a/LauncherOSX/RDPackageResource.h b/LauncherOSX/RDPackageResource.h index 9869736..e1f657b 100644 --- a/LauncherOSX/RDPackageResource.h +++ b/LauncherOSX/RDPackageResource.h @@ -10,7 +10,8 @@ #import #import -#define kSDKLauncherPackageResourceBufferSize 4096 +// Same as HTTPConnection.m (to avoid unnecessary intermediary buffer iterations) +#define READ_CHUNKSIZE (1024 * 50) @class RDPackageResource; @class LOXPackage; @@ -23,6 +24,7 @@ //@property (nonatomic, readonly) ePub3::ByteStream* byteStream; @property (nonatomic, readonly) std::size_t bytesCount; +@property (nonatomic, readonly) std::size_t bytesCountCheck; @property (nonatomic, readonly) LOXPackage *package; diff --git a/LauncherOSX/RDPackageResource.mm b/LauncherOSX/RDPackageResource.mm index 198b798..09edbca 100644 --- a/LauncherOSX/RDPackageResource.mm +++ b/LauncherOSX/RDPackageResource.mm @@ -23,7 +23,8 @@ @interface RDPackageResource() { @private NSString *m_relativePath; @private BOOL m_hasProperStream; @private std::size_t m_bytesCount; -@private UInt8 m_buffer[kSDKLauncherPackageResourceBufferSize]; +@private std::size_t m_bytesCountCheck; +@private UInt8 m_buffer[READ_CHUNKSIZE]; //@private NSData *m_data; } @@ -34,6 +35,7 @@ @implementation RDPackageResource //@synthesize byteStream = m_byteStream; @synthesize bytesCount = m_bytesCount; +@synthesize bytesCountCheck = m_bytesCountCheck; @synthesize relativePath = m_relativePath; @synthesize package = m_package; @@ -50,26 +52,36 @@ - (NSData *)readDataFull { } else { - if (!m_hasProperStream) - { - ePub3::ByteStream *byteStream = m_byteStream.release(); - m_byteStream.reset((ePub3::ByteStream *)[m_package getProperByteStream:m_relativePath currentByteStream:byteStream isRangeRequest:NO]); - m_bytesCount = [RDPackageResource bytesAvailable:m_byteStream.get() pack:m_package path:m_relativePath]; - m_hasProperStream = YES; - } + if (!m_hasProperStream) + { + ePub3::ByteStream *byteStream = m_byteStream.release(); + m_byteStream.reset((ePub3::ByteStream *)[m_package getProperByteStream:m_relativePath currentByteStream:byteStream isRangeRequest:NO]); + m_bytesCount = [RDPackageResource bytesAvailable:m_byteStream.get() pack:m_package path:m_relativePath]; + m_hasProperStream = YES; + } - NSMutableData *md = [[NSMutableData alloc] initWithCapacity: m_bytesCount]; + m_bytesCountCheck = 0; - while (YES) { - std::size_t count = m_byteStream->ReadBytes(m_buffer, sizeof(m_buffer)); + NSMutableData *md = [[NSMutableData alloc] initWithCapacity: m_bytesCount]; - if (count == 0) { - break; - } + while (YES) { + std::size_t count = m_byteStream->ReadBytes(m_buffer, sizeof(m_buffer)); - [md appendBytes:m_buffer length:count]; + if (count == 0) { + break; } + m_bytesCountCheck += count; + [md appendBytes:m_buffer length:count]; + } + + + if (m_bytesCount != m_bytesCountCheck) + { + printf("BYTE COUNT UPDATE (readDataFull): %d -> %d (%s)\n", m_bytesCount, m_bytesCountCheck, [m_relativePath UTF8String]); + m_bytesCount = m_bytesCountCheck; + } + m_data = md; } } @@ -84,67 +96,65 @@ - (NSData *)readDataFull { { NSLog(@"BYTESTREAM zero BytesAvailable!"); } - else - { - return size; - } - - //std::unique_ptr reader = _sdkPackage->ReaderForRelativePath(s); - //reader->read(<#(void*)p#>, <#(size_t)len#>) - - std::shared_ptr archive = [package sdkPackage]->Archive(); - - try - { - //ZipItemInfo - ePub3::ArchiveItemInfo info = archive->InfoAtPath([package sdkPackage]->BasePath() + [relPath UTF8String]); - size = info.UncompressedSize(); - } - catch (std::exception& e) - { - auto msg = e.what(); - NSLog(@"!!! [ArchiveItemInfo] ZIP file not found (corrupted archive?): %@ (%@)", relPath, [NSString stringWithUTF8String:msg]); - } - catch (...) { - throw; - } - - archive = nullptr; - - - - std::string s = [relPath UTF8String]; - std::unique_ptr reader = [package sdkPackage]->ReaderForRelativePath(s); - - if (reader == nullptr) - { - NSLog(@"!!! [ArchiveReader] ZIP file not found (corrupted archive?): %@", relPath); - } - else - { - UInt8 buffer[kSDKLauncherPackageResourceBufferSize]; - std::size_t total = 0; - std::size_t count = 0; - while ((count = reader->read(buffer, sizeof(buffer))) > 0) - { - total += count; - } - - if (total > 0) - { - // ByteStream bug??! zip_fread works with ArchiveReader, why not ByteStream? - NSLog(@"WTF??!"); - - if (total != size) - { - NSLog(@"Oh dear..."); - } - } - } - - reader = nullptr; return size; + +// //std::unique_ptr reader = _sdkPackage->ReaderForRelativePath(s); +// //reader->read(<#(void*)p#>, <#(size_t)len#>) +// +// std::shared_ptr archive = [package sdkPackage]->Archive(); +// +// try +// { +// //ZipItemInfo +// ePub3::ArchiveItemInfo info = archive->InfoAtPath([package sdkPackage]->BasePath() + [relPath UTF8String]); +// size = info.UncompressedSize(); +// } +// catch (std::exception& e) +// { +// auto msg = e.what(); +// NSLog(@"!!! [ArchiveItemInfo] ZIP file not found (corrupted archive?): %@ (%@)", relPath, [NSString stringWithUTF8String:msg]); +// } +// catch (...) { +// throw; +// } +// +// archive = nullptr; +// +// +// +// std::string s = [relPath UTF8String]; +// std::unique_ptr reader = [package sdkPackage]->ReaderForRelativePath(s); +// +// if (reader == nullptr) +// { +// NSLog(@"!!! [ArchiveReader] ZIP file not found (corrupted archive?): %@", relPath); +// } +// else +// { +// UInt8 buffer[READ_CHUNKSIZE]; +// std::size_t total = 0; +// std::size_t count = 0; +// while ((count = reader->read(buffer, sizeof(buffer))) > 0) +// { +// total += count; +// } +// +// if (total > 0) +// { +// // ByteStream bug??! zip_fread works with ArchiveReader, why not ByteStream? +// NSLog(@"WTF??!"); +// +// if (total != size) +// { +// NSLog(@"Oh dear..."); +// } +// } +// } +// +// reader = nullptr; +// +// return size; } - (NSData *)readDataOfLength:(NSUInteger)length offset:(UInt64)offset isRangeRequest:(BOOL)isRangeRequest { @@ -179,16 +189,26 @@ - (NSData *)readDataOfLength:(NSUInteger)length offset:(UInt64)offset isRangeReq std::size_t count = filterStream->ReadBytes(m_buffer, sizeof(m_buffer), range); - if (count <= 0) break; + if (count <= 0) { + break; + } [md appendBytes:m_buffer length:count]; + m_bytesCountCheck += count; totalRead += count; //printf("+++++ readDataOfLength SO FAR: %d / %d (%s)\n", totalRead, length, [m_relativePath UTF8String]); range.Location(range.Location() + count); } +// +// if (m_bytesCount != m_bytesCountCheck) +// { +// printf("BYTE COUNT UPDATE (FilterChainByteStreamRange): %d -> %d (%s) %d\n", m_bytesCount, m_bytesCountCheck, [m_relativePath UTF8String], offset); +// m_bytesCount = m_bytesCountCheck; +// } + if (totalRead != length) { //NSLog(@"1) Did not read the expected number of bytes! (%lu %lu / %lu %@)", totalRead, length, m_bytesCount, m_relativePath); //printf("1) Did not read the expected number of bytes! (%d %d / %d %s)\n", totalRead, length, m_bytesCount, [m_relativePath UTF8String]); @@ -206,7 +226,7 @@ - (NSData *)readDataOfLength:(NSUInteger)length offset:(UInt64)offset isRangeReq } else { //NSLog(@"1) Correct: (%lu %lu / %lu %@)", totalRead, length, m_bytesCount, m_relativePath); - printf("1) Correct: (%d %d / %d %s)\n", totalRead, length, m_bytesCount, [m_relativePath UTF8String]); + printf("2) Korrect: (%d %d / %d %s %d)\n", totalRead, length, m_bytesCount, [m_relativePath UTF8String], offset); } @@ -215,8 +235,11 @@ - (NSData *)readDataOfLength:(NSUInteger)length offset:(UInt64)offset isRangeReq ePub3::SeekableByteStream *seekableByteStream = dynamic_cast(m_byteStream.get()); if (seekableByteStream != nullptr - || (m_bytesCount - m_byteStream->BytesAvailable()) == offset) //not-seek-able-ByteStream does not expose its internal position! m_byteStream->Position() + || true) { + //ASSERT (m_bytesCount - m_byteStream->BytesAvailable()) == offset + // (does not work because underlying raw byte stream may not map 1-1 to output ranges) + // ... we assume that this is part of a series of contiguous subsequent buffer requests from the HTTP chunking. NSMutableData *md = [[NSMutableData alloc] initWithCapacity:length]; @@ -236,10 +259,21 @@ - (NSData *)readDataOfLength:(NSUInteger)length offset:(UInt64)offset isRangeReq std::size_t count = m_byteStream->ReadBytes(m_buffer, toRead); - if (count <= 0) break; + if (count <= 0) { + + + if (m_bytesCount != m_bytesCountCheck) + { + printf("BYTE COUNT UPDATE: %d -> %d (%s) %d\n", m_bytesCount, m_bytesCountCheck, [m_relativePath UTF8String], offset); + m_bytesCount = m_bytesCountCheck; + } + + break; + } [md appendBytes:m_buffer length:count]; + m_bytesCountCheck += count; totalRead += count; //printf("+++++ readDataOfLength SO FAR: %d / %d (%s)\n", totalRead, length, [m_relativePath UTF8String]); @@ -247,7 +281,7 @@ - (NSData *)readDataOfLength:(NSUInteger)length offset:(UInt64)offset isRangeReq if (totalRead != length) { //NSLog(@"1) Did not read the expected number of bytes! (%lu %lu / %lu %@)", totalRead, length, m_bytesCount, m_relativePath); - //printf("1) Did not read the expected number of bytes! (%d %d / %d %s)\n", totalRead, length, m_bytesCount, [m_relativePath UTF8String]); + printf("BYTE Partial: (%d %d / %d %s %d)\n", totalRead, length, m_bytesCount, [m_relativePath UTF8String], offset); if (totalRead == 0){ @@ -262,7 +296,7 @@ - (NSData *)readDataOfLength:(NSUInteger)length offset:(UInt64)offset isRangeReq } else { //NSLog(@"1) Correct: (%lu %lu / %lu %@)", totalRead, length, m_bytesCount, m_relativePath); - printf("1) Correct: (%d %d / %d %s)\n", totalRead, length, m_bytesCount, [m_relativePath UTF8String]); + printf("BYTE Correct: (%d %d / %d %s %d)\n", totalRead, length, m_bytesCount, [m_relativePath UTF8String], offset); } @@ -307,6 +341,7 @@ - (void)dealloc { m_byteStream.reset(byteStream); m_bytesCount = [RDPackageResource bytesAvailable:m_byteStream.get() pack:package path:m_relativePath]; + m_bytesCountCheck = 0; m_hasProperStream = NO; diff --git a/readium-sdk b/readium-sdk index 1c100f2..da8e291 160000 --- a/readium-sdk +++ b/readium-sdk @@ -1 +1 @@ -Subproject commit 1c100f2edaffb2936794e522c82959bbe12fa24d +Subproject commit da8e29131bf031e6b28708acabc94e582505fa62 From e32082a28939c79e315bdc469bc4466a19357711 Mon Sep 17 00:00:00 2001 From: Daniel Weck Date: Wed, 17 Dec 2014 16:24:37 +0000 Subject: [PATCH 07/13] minor: log message relocated --- LauncherOSX/PackageResourceServer.mm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/LauncherOSX/PackageResourceServer.mm b/LauncherOSX/PackageResourceServer.mm index 914f773..79aeedc 100644 --- a/LauncherOSX/PackageResourceServer.mm +++ b/LauncherOSX/PackageResourceServer.mm @@ -115,10 +115,6 @@ @implementation PackageResourceConnection { NSError * error = [xmlparser parserError]; NSLog(@"XHTML PARSE ERROR: %@", error); - - // Can be used to check / debug encoding issues - NSString * dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - NSLog(@"XHTML SOURCE: %@", dataStr); } } @catch (NSException *ex) @@ -129,6 +125,10 @@ @implementation PackageResourceConnection if (ok == NO) { + // Can be used to check / debug encoding issues + NSString * dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + NSLog(@"XHTML SOURCE: %@", dataStr); + //contentType = @"application/xhtml+xml"; contentType = @"text/html"; From 1298972ad509f1afdbaac91dac3f52c28b2666cb Mon Sep 17 00:00:00 2001 From: Daniel Weck Date: Wed, 17 Dec 2014 16:29:32 +0000 Subject: [PATCH 08/13] code cleanup, removed log messages --- LauncherOSX/PackageResourceServer.h | 1 - LauncherOSX/PackageResourceServer.mm | 24 +++++++++--------------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/LauncherOSX/PackageResourceServer.h b/LauncherOSX/PackageResourceServer.h index 0d79d52..22194de 100644 --- a/LauncherOSX/PackageResourceServer.h +++ b/LauncherOSX/PackageResourceServer.h @@ -23,7 +23,6 @@ @interface PackageResourceResponse : NSObject { @private UInt64 m_offset; @private UInt64 m_offsetInitial; -//@private bool m_isDone; @private RDPackageResource *m_resource; @private BOOL m_isRangeRequest; } diff --git a/LauncherOSX/PackageResourceServer.mm b/LauncherOSX/PackageResourceServer.mm index 79aeedc..15d7b36 100644 --- a/LauncherOSX/PackageResourceServer.mm +++ b/LauncherOSX/PackageResourceServer.mm @@ -33,11 +33,6 @@ @implementation PackageResourceConnection return nil; } - // See: - // ConstManifestItemPtr PackageBase::ManifestItemAtRelativePath(const string& path) const - // which compares with non-escaped source (OPF original manifest>item@src attribute value) - //path = [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - // // if (path != nil && [path hasPrefix:@"/"]) { // path = [path substringFromIndex:1]; @@ -300,7 +295,7 @@ - (NSDictionary *)httpHeaders { //} - (UInt64)contentLength { - printf("contentLength: %d (%s)\n", m_resource.bytesCount, [m_resource.relativePath UTF8String]); +// printf("contentLength: %d (%s)\n", m_resource.bytesCount, [m_resource.relativePath UTF8String]); return m_resource.bytesCount; } @@ -314,7 +309,6 @@ - (id)initWithResource:(RDPackageResource *)resource { if (self = [super init]) { m_resource = resource; m_isRangeRequest = NO; - //m_isDone = false; } return self; @@ -327,7 +321,7 @@ - (BOOL)isDone { ? (m_offset >= m_resource.bytesCount) : (m_offset >= (m_offsetInitial + m_resource.bytesCountCheck)); -printf("is DONE: %d (%s)\n", isDone, [m_resource.relativePath UTF8String]); +//printf("is DONE: %d (%s)\n", isDone, [m_resource.relativePath UTF8String]); return isDone; } @@ -341,21 +335,21 @@ - (UInt64)offset { - (NSData *)readDataOfLength:(NSUInteger)length { NSData *data = nil; - //printf("readDataOfLength 1 %s (%d)\n", [m_resource.relativePath UTF8String], length); +//printf("readDataOfLength 1 %s (%d)\n", [m_resource.relativePath UTF8String], length); @synchronized ([PackageResourceServer resourceLock]) { - printf("readDataOfLength %s (%d)\n", [m_resource.relativePath UTF8String], length); +//printf("readDataOfLength %s (%d)\n", [m_resource.relativePath UTF8String], length); data = [m_resource readDataOfLength:length offset:m_offset isRangeRequest:m_isRangeRequest]; } - if (data != nil) { + if (data != nil) + { m_offset += data.length; } if (data == nil || data.length == 0) { printf("readDataOfLength NO DATA %s (%d)\n", [m_resource.relativePath UTF8String], length); - //m_isDone = true; } if (data == nil) @@ -368,7 +362,7 @@ - (NSData *)readDataOfLength:(NSUInteger)length { - (void)setOffset:(UInt64)offset { - printf("setOffset: %d (%s)\n", offset, [m_resource.relativePath UTF8String]); +//printf("setOffset: %d (%s)\n", offset, [m_resource.relativePath UTF8String]); m_offset = offset; m_offsetInitial = offset; m_isRangeRequest = YES; @@ -409,8 +403,8 @@ - (id)initWithPackage:(LOXPackage *)package baseUrlPath:(NSString*)baseUrlPath { m_resourceLock = [[NSObject alloc] init]; -// NSString * port = [NSString stringWithFormat:@"%d", kSDKLauncherPackageResourceServerPort]; -// NSString * address = [@"localhost:" stringByAppendingString:port]; +// NSString * port = [NSString stringWithFormat:@"%d", kSDKLauncherPackageResourceServerPort]; +// NSString * address = [@"localhost:" stringByAppendingString:port]; NSString * address = @"localhost"; NSURL * url = [NSURL fileURLWithPath: [@"file:///" stringByAppendingString:[m_package packageUUID]]]; From 29461d6d2d23d535b105155df0f125c4c64e46eb Mon Sep 17 00:00:00 2001 From: Daniel Weck Date: Wed, 17 Dec 2014 16:35:50 +0000 Subject: [PATCH 09/13] commented log messages --- LauncherOSX/RDPackageResource.mm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/LauncherOSX/RDPackageResource.mm b/LauncherOSX/RDPackageResource.mm index 09edbca..764e094 100644 --- a/LauncherOSX/RDPackageResource.mm +++ b/LauncherOSX/RDPackageResource.mm @@ -78,7 +78,7 @@ - (NSData *)readDataFull { if (m_bytesCount != m_bytesCountCheck) { - printf("BYTE COUNT UPDATE (readDataFull): %d -> %d (%s)\n", m_bytesCount, m_bytesCountCheck, [m_relativePath UTF8String]); +// printf("BYTE COUNT UPDATE (readDataFull): %d -> %d (%s)\n", m_bytesCount, m_bytesCountCheck, [m_relativePath UTF8String]); m_bytesCount = m_bytesCountCheck; } @@ -226,7 +226,7 @@ - (NSData *)readDataOfLength:(NSUInteger)length offset:(UInt64)offset isRangeReq } else { //NSLog(@"1) Correct: (%lu %lu / %lu %@)", totalRead, length, m_bytesCount, m_relativePath); - printf("2) Korrect: (%d %d / %d %s %d)\n", totalRead, length, m_bytesCount, [m_relativePath UTF8String], offset); +// printf("2) Korrect: (%d %d / %d %s %d)\n", totalRead, length, m_bytesCount, [m_relativePath UTF8String], offset); } @@ -264,7 +264,7 @@ - (NSData *)readDataOfLength:(NSUInteger)length offset:(UInt64)offset isRangeReq if (m_bytesCount != m_bytesCountCheck) { - printf("BYTE COUNT UPDATE: %d -> %d (%s) %d\n", m_bytesCount, m_bytesCountCheck, [m_relativePath UTF8String], offset); +// printf("BYTE COUNT UPDATE: %d -> %d (%s) %d\n", m_bytesCount, m_bytesCountCheck, [m_relativePath UTF8String], offset); m_bytesCount = m_bytesCountCheck; } @@ -281,7 +281,7 @@ - (NSData *)readDataOfLength:(NSUInteger)length offset:(UInt64)offset isRangeReq if (totalRead != length) { //NSLog(@"1) Did not read the expected number of bytes! (%lu %lu / %lu %@)", totalRead, length, m_bytesCount, m_relativePath); - printf("BYTE Partial: (%d %d / %d %s %d)\n", totalRead, length, m_bytesCount, [m_relativePath UTF8String], offset); +// printf("BYTE Partial: (%d %d / %d %s %d)\n", totalRead, length, m_bytesCount, [m_relativePath UTF8String], offset); if (totalRead == 0){ @@ -296,7 +296,7 @@ - (NSData *)readDataOfLength:(NSUInteger)length offset:(UInt64)offset isRangeReq } else { //NSLog(@"1) Correct: (%lu %lu / %lu %@)", totalRead, length, m_bytesCount, m_relativePath); - printf("BYTE Correct: (%d %d / %d %s %d)\n", totalRead, length, m_bytesCount, [m_relativePath UTF8String], offset); +// printf("BYTE Correct: (%d %d / %d %s %d)\n", totalRead, length, m_bytesCount, [m_relativePath UTF8String], offset); } From 0c28f0f91441470056f81f78fdf9a1430ab3d12e Mon Sep 17 00:00:00 2001 From: Daniel Weck Date: Wed, 17 Dec 2014 16:37:03 +0000 Subject: [PATCH 10/13] restored 512kB buffer (was smaller to test for small resource decryption) --- LauncherOSX/CocoaHTTPServer/Core/HTTPConnection.m | 2 +- LauncherOSX/RDPackageResource.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LauncherOSX/CocoaHTTPServer/Core/HTTPConnection.m b/LauncherOSX/CocoaHTTPServer/Core/HTTPConnection.m index fc86e13..d4ac82f 100755 --- a/LauncherOSX/CocoaHTTPServer/Core/HTTPConnection.m +++ b/LauncherOSX/CocoaHTTPServer/Core/HTTPConnection.m @@ -25,7 +25,7 @@ #if TARGET_OS_IPHONE #define READ_CHUNKSIZE (1024 * 256) #else - #define READ_CHUNKSIZE (1024 * 50) + #define READ_CHUNKSIZE (1024 * 512) #endif // Define chunk size used to read in POST upload data diff --git a/LauncherOSX/RDPackageResource.h b/LauncherOSX/RDPackageResource.h index e1f657b..d8a3f87 100644 --- a/LauncherOSX/RDPackageResource.h +++ b/LauncherOSX/RDPackageResource.h @@ -11,7 +11,7 @@ #import // Same as HTTPConnection.m (to avoid unnecessary intermediary buffer iterations) -#define READ_CHUNKSIZE (1024 * 50) +#define READ_CHUNKSIZE (1024 * 512) @class RDPackageResource; @class LOXPackage; From a83a914c4352ead53b37c6249036157745ff9657 Mon Sep 17 00:00:00 2001 From: Daniel Weck Date: Wed, 17 Dec 2014 21:36:28 +0000 Subject: [PATCH 11/13] submodule --- readium-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readium-sdk b/readium-sdk index da8e291..1412a7b 160000 --- a/readium-sdk +++ b/readium-sdk @@ -1 +1 @@ -Subproject commit da8e29131bf031e6b28708acabc94e582505fa62 +Subproject commit 1412a7b26e28107d92e42eeb8af7cc8ec2ca36da From 19ee89b91560799300c1d3d0165b78857897b899 Mon Sep 17 00:00:00 2001 From: Daniel Weck Date: Wed, 17 Dec 2014 22:25:13 +0000 Subject: [PATCH 12/13] submodule --- readium-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readium-sdk b/readium-sdk index 1412a7b..cfdda31 160000 --- a/readium-sdk +++ b/readium-sdk @@ -1 +1 @@ -Subproject commit 1412a7b26e28107d92e42eeb8af7cc8ec2ca36da +Subproject commit cfdda3182d9cab21ddb48e45dedcfa1d336103b0 From 91b3fb1a441d02dc332102f98aa79f40df138cb8 Mon Sep 17 00:00:00 2001 From: Daniel Weck Date: Tue, 27 Jan 2015 08:21:42 +0000 Subject: [PATCH 13/13] subomdules --- readium-sdk | 2 +- readium-shared-js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/readium-sdk b/readium-sdk index cfdda31..f0b366e 160000 --- a/readium-sdk +++ b/readium-sdk @@ -1 +1 @@ -Subproject commit cfdda3182d9cab21ddb48e45dedcfa1d336103b0 +Subproject commit f0b366e2edead42263f8de6e5ed9a1490b82ac95 diff --git a/readium-shared-js b/readium-shared-js index dc921ee..8303a0b 160000 --- a/readium-shared-js +++ b/readium-shared-js @@ -1 +1 @@ -Subproject commit dc921ee4cb95ea9c3b87c593639320e202a1ef66 +Subproject commit 8303a0bc1ebc00aceb0c8246a225c436d4e18a3c