diff --git a/EUExPDFReader/EUExPDFReader.xcodeproj/project.pbxproj b/EUExPDFReader/EUExPDFReader.xcodeproj/project.pbxproj index 1461ffa..14c7955 100644 --- a/EUExPDFReader/EUExPDFReader.xcodeproj/project.pbxproj +++ b/EUExPDFReader/EUExPDFReader.xcodeproj/project.pbxproj @@ -48,6 +48,7 @@ 5A9FF0C71890A84500E16C52 /* ThumbsMainToolbar.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A9FF0B01890A84500E16C52 /* ThumbsMainToolbar.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 5A9FF0C81890A84500E16C52 /* ThumbsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A9FF0B21890A84500E16C52 /* ThumbsViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 5A9FF0C91890A84500E16C52 /* UIXToolbarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A9FF0B41890A84500E16C52 /* UIXToolbarView.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + C628055D2192FAA60033CBDC /* UexPDFGTMBase64.m in Sources */ = {isa = PBXBuildFile; fileRef = C628055B2192FAA60033CBDC /* UexPDFGTMBase64.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -140,6 +141,9 @@ 5A9FF0B21890A84500E16C52 /* ThumbsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ThumbsViewController.m; sourceTree = ""; }; 5A9FF0B31890A84500E16C52 /* UIXToolbarView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIXToolbarView.h; sourceTree = ""; }; 5A9FF0B41890A84500E16C52 /* UIXToolbarView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIXToolbarView.m; sourceTree = ""; }; + C628055A2192FAA60033CBDC /* UexPDFGTMBase64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UexPDFGTMBase64.h; sourceTree = ""; }; + C628055B2192FAA60033CBDC /* UexPDFGTMBase64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UexPDFGTMBase64.m; sourceTree = ""; }; + C628055C2192FAA60033CBDC /* UexEMMGTMDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UexEMMGTMDefines.h; sourceTree = ""; }; FC16252A18AB6BCD00BEF700 /* EUExPDFReader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EUExPDFReader.h; sourceTree = ""; }; /* End PBXFileReference section */ @@ -249,6 +253,7 @@ 5A9FF08A1890A84400E16C52 /* sourceCode */ = { isa = PBXGroup; children = ( + C62805592192FA880033CBDC /* GTMBase64 */, 427A05481EADE91A002BC8DE /* AppCanKit.framework */, 5A9FF08E1890A84500E16C52 /* ReaderViewController.h */, 5A9FF08F1890A84500E16C52 /* ReaderViewController.m */, @@ -300,6 +305,16 @@ path = Sources; sourceTree = ""; }; + C62805592192FA880033CBDC /* GTMBase64 */ = { + isa = PBXGroup; + children = ( + C628055A2192FAA60033CBDC /* UexPDFGTMBase64.h */, + C628055B2192FAA60033CBDC /* UexPDFGTMBase64.m */, + C628055C2192FAA60033CBDC /* UexEMMGTMDefines.h */, + ); + path = GTMBase64; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -415,6 +430,7 @@ 5A9FF0BB1890A84500E16C52 /* ReaderContentTile.m in Sources */, 5A9FF0C71890A84500E16C52 /* ThumbsMainToolbar.m in Sources */, 5A9FF0BA1890A84500E16C52 /* ReaderContentPage.m in Sources */, + C628055D2192FAA60033CBDC /* UexPDFGTMBase64.m in Sources */, 5A9FF0C01890A84500E16C52 /* ReaderThumbCache.m in Sources */, 5A9FF0C21890A84500E16C52 /* ReaderThumbQueue.m in Sources */, 5A9FF0BE1890A84500E16C52 /* ReaderMainPagebar.m in Sources */, diff --git a/EUExPDFReader/EUExPDFReader/EUExPDFReader.h b/EUExPDFReader/EUExPDFReader/EUExPDFReader.h index 225d16e..934c68c 100644 --- a/EUExPDFReader/EUExPDFReader/EUExPDFReader.h +++ b/EUExPDFReader/EUExPDFReader/EUExPDFReader.h @@ -10,6 +10,8 @@ #import +#define kStringWithFormat(object) object?[NSString stringWithFormat:@"%@",object]:nil + @interface EUExPDFReader : EUExBase diff --git a/EUExPDFReader/EUExPDFReader/EUExPDFReader.m b/EUExPDFReader/EUExPDFReader/EUExPDFReader.m index b692492..a279f7c 100644 --- a/EUExPDFReader/EUExPDFReader/EUExPDFReader.m +++ b/EUExPDFReader/EUExPDFReader/EUExPDFReader.m @@ -8,12 +8,15 @@ #import "EUExPDFReader.h" #import "ReaderViewController.h" +#import "UexPDFGTMBase64.h" @interface EUExPDFReader() @property (nonatomic,strong)ReaderViewController *readerController; @property (nonatomic,strong)UIWebView *pdfView; +@property(copy,nonatomic)NSString *filepath; + @end @implementation EUExPDFReader @@ -22,8 +25,8 @@ @implementation EUExPDFReader - (void)openPDFReader:(NSMutableArray *)inArguments{ - ACArgsUnpack(NSString *inPath,ACJSFunctionRef *callback) = inArguments; - + ACArgsUnpack(NSString *inPath,NSString *encryptStr,ACJSFunctionRef *callback) = inArguments; + NSInteger isEncryptValue = [encryptStr integerValue]; if (!inPath) { [callback executeWithArguments: ACArgsPack(@(1))]; @@ -35,7 +38,6 @@ - (void)openPDFReader:(NSMutableArray *)inArguments{ if (self.readerController) { return; } - NSString *absPath = [self absPath:inPath]; NSString *kResScheme = @"res://"; if ([inPath hasPrefix:kResScheme]) { @@ -45,31 +47,168 @@ - (void)openPDFReader:(NSMutableArray *)inArguments{ if([[NSFileManager defaultManager] copyItemAtPath:absPath toPath:copyPath error:nil]){ absPath = copyPath; } - } - + + //判断是否是加密的PDF(isEncryptValue:是否为加密 1:加密 0:非加密) + if (isEncryptValue == 1) { + //将获取到的文件路径放入PreferencePanes目录(临时文件,避免在沙盒中查到) + ReaderDocument *document = [ReaderDocument withDocumentFilePath:absPath password:nil]; + NSString *documentPath2 = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).firstObject; + NSString *fileName = [ReaderDocument GUID]; + NSString *preferencePanesPath = [documentPath2 stringByAppendingPathComponent:fileName]; + NSLog(@"ssssssss === %@",absPath); + [self func_decodeFile:absPath withNewName:preferencePanesPath]; + absPath = preferencePanesPath; + self.filepath = preferencePanesPath; + } + //Document password (for unlocking most encrypted PDF files) NSString *phrase = nil; - ReaderDocument *document = [ReaderDocument withDocumentFilePath:absPath password:phrase]; + ReaderDocument *document = [ReaderDocument withDocumentFilePath:absPath password:phrase]; + if (!document) { [callback executeWithArguments: ACArgsPack(@(1))]; - + NSLog(@"没有PDF文件"); return; } - else + else { [callback executeWithArguments: ACArgsPack(@(0))]; + } - if (!self.readerController) { - self.readerController = [[ReaderViewController alloc] initWithReaderDocument:document]; + self.readerController = [[ReaderViewController alloc] initWithReaderDocument:document withEUExObj:self]; } self.readerController.delegate = self; [[self.webViewEngine viewController] presentViewController:self.readerController animated:YES completion:nil]; +} + + +/** + *文件加密 + \array + \filePath 需要加密的文件路径 + */ +-(void)fileEncrypt:(NSMutableArray *)array{ + @try{ + if ([array isKindOfClass:[NSMutableArray class]] && [array count] > 0) { + NSLog(@"appcan-->uexEMM-->fileEncrypt-->array is %@",array); + NSString *srcPath = [array objectAtIndex:0]; + // srcPath = [NSHomeDirectory() stringByAppendingFormat:@"/Documents/1.mp4"]; + if (![[NSFileManager defaultManager] fileExistsAtPath:srcPath]) { + NSString *jsString = [NSString stringWithFormat:@"uexPDFReader.cbFileEncrypt(\"0\",\"0\",\'');"]; + if ([NSThread isMainThread]) { + // [self.meBrwView stringByEvaluatingJavaScriptFromString:jsString]; + [self.webViewEngine evaluateScript:jsString]; + + }else{ + [self performSelectorOnMainThread:@selector(callBackMethod:) withObject:jsString waitUntilDone:NO]; + } + return; + } + [self func_encodeFile:srcPath withNewName:srcPath]; + NSString *jsString = [NSString stringWithFormat:@"uexPDFReader.cbFileEncrypt(\"0\",\"0\",\"%@\");",srcPath]; + if ([NSThread isMainThread]) { + // [self.meBrwView stringByEvaluatingJavaScriptFromString:jsString]; + [self.webViewEngine evaluateScript:jsString]; + + }else{ + [self performSelectorOnMainThread:@selector(callBackMethod:) withObject:jsString waitUntilDone:NO]; + } + } + }@catch (NSException * e){ + NSLog(@"appcan-->uexEMM-->fileEncrypt-->catch e is %@",e); + } +} + +#define Key_Count (17)//加密字符串长度 +static char arrayForEncode[Key_Count] = "appcan@3g2win.com"; +#pragma mark ----- 解密method +-(BOOL)func_decodeFile:(NSString *)filePath withNewName:(NSString *)newFilePath { + if (nil == filePath || NO == [[NSFileManager defaultManager] fileExistsAtPath:filePath]) { + NSString *jsString = [NSString stringWithFormat:@"uexPDFReader.cbFileDecrypt(\"0\",\"0\",\'');"]; + if ([NSThread isMainThread]) { + // [self.meBrwView stringByEvaluatingJavaScriptFromString:jsString]; + [self.webViewEngine evaluateScript:jsString]; + + }else{ + [self performSelectorOnMainThread:@selector(callBackMethod:) withObject:jsString waitUntilDone:NO]; + } + return NO; + } + @autoreleasepool { + // 读取被加密文件对应的数据 + NSData *dataEncoded = [NSData dataWithContentsOfFile:filePath]; + // 对NSData进行base64解码 + NSData *dataDecode = [UexPDFGTMBase64 decodeData:dataEncoded]; + + // 对前1000位进行异或处理 + unsigned char * cByte = (unsigned char*)[dataDecode bytes]; + for (int index = 0; (index < [dataDecode length]) && (index < Key_Count); index++, cByte++) + { + *cByte = (*cByte) ^ arrayForEncode[index]; + } + NSLog(@"解密成功"); + BOOL yes = [dataDecode writeToFile:newFilePath atomically:NO]; + if (yes) { + NSLog(@"解密文件写入成功"); + }else{ + NSLog(@"解密文件写入失败"); + } + return yes; + } +} + +#pragma mark ----- 加密method(暂时没有被调用到) +-(BOOL)func_encodeFile:(NSString *)filePath withNewName:(NSString*)newFilePath { + if (nil == filePath || NO == [[NSFileManager defaultManager] fileExistsAtPath:filePath]) { + return NO; + } + @autoreleasepool { + //文件路径转换为NSData + NSData *imageDataOrigin = [NSData dataWithContentsOfFile:filePath]; + // 对前1000位进行异或处理 + unsigned char * cByte = (unsigned char*)[imageDataOrigin bytes]; + for (int index = 0; (index < [imageDataOrigin length]) && (index < Key_Count); index++, cByte++) + { + *cByte = (*cByte) ^ arrayForEncode[index]; + } + + //对NSData进行base64编码 + NSData *imageDataEncode = [UexPDFGTMBase64 encodeData:imageDataOrigin]; + NSLog(@"加密成功"); + NSLog(@"=================%@",newFilePath); + return [imageDataEncode writeToFile:newFilePath atomically:YES]; + + + } +} + +/** + *回调方法 + \jsString 回调的js + */ +-(void)callBackMethod:(NSString *)jsString{ + // [self.meBrwView stringByEvaluatingJavaScriptFromString:jsString]; + [self.webViewEngine evaluateScript:jsString]; } +////原生异步回调JS给网页 +//- (void)doCallback:(NSMutableArray *)inArguments{ +// NSDictionary *dict = @{ +// @"key":@"value" +// }; +// //ac_JSONFragment 方法,可以将NSDictionary转换成JSON字符串 +// [self.webViewEngine callbackWithFunctionKeyPath:@"uexPDFReader.cbDoCallback" +// arguments:ACArgsPack(dict.ac_JSONFragment) +// completion:^(JSValue * _Nullable returnValue) { +// if (returnValue) { +// ACLogDebug(@"回调成功!"); +// } +// }]; +//} - (void)openView:(NSMutableArray *)inArguments{ @@ -111,6 +250,7 @@ - (void)openView:(NSMutableArray *)inArguments{ } + - (void)closeView:(NSMutableArray *)inArguments{ [self.pdfView removeFromSuperview]; self.pdfView.delegate = nil; @@ -119,13 +259,15 @@ - (void)closeView:(NSMutableArray *)inArguments{ - (void)dismissReaderViewController:(ReaderViewController *)viewController{ + //MARK:关闭查看PDF时删除解密存储文件。 + NSFileManager *fileManager = [NSFileManager defaultManager]; + [fileManager removeItemAtPath:self.filepath error:nil]; + + NSLog(@"self.filepath =============== %@",self.filepath); [self close:nil]; } - - - - (void)close:(NSMutableArray *)inArguments{ [self.readerController dismissViewControllerAnimated:YES completion:nil]; self.readerController.delegate = nil; diff --git a/EUExPDFReader/EUExPDFReader/sourceCode/GTMBase64/UexEMMGTMDefines.h b/EUExPDFReader/EUExPDFReader/sourceCode/GTMBase64/UexEMMGTMDefines.h new file mode 100644 index 0000000..3c58d1a --- /dev/null +++ b/EUExPDFReader/EUExPDFReader/sourceCode/GTMBase64/UexEMMGTMDefines.h @@ -0,0 +1,252 @@ +// +// GTMDefines.h +// +// Copyright 2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// ============================================================================ + +#include + +// Not all MAC_OS_X_VERSION_10_X macros defined in past SDKs +#ifndef MAC_OS_X_VERSION_10_5 +#define MAC_OS_X_VERSION_10_5 1050 +#endif +#ifndef MAC_OS_X_VERSION_10_6 +#define MAC_OS_X_VERSION_10_6 1060 +#endif + +// ---------------------------------------------------------------------------- +// CPP symbols that can be overridden in a prefix to control how the toolbox +// is compiled. +// ---------------------------------------------------------------------------- + + +// GTMHTTPFetcher will support logging by default but only hook its input +// stream support for logging when requested. You can control the inclusion of +// the code by providing your own definitions for these w/in a prefix header. +// +#ifndef GTM_HTTPFETCHER_ENABLE_LOGGING +#define GTM_HTTPFETCHER_ENABLE_LOGGING 1 +#endif // GTM_HTTPFETCHER_ENABLE_LOGGING +#ifndef GTM_HTTPFETCHER_ENABLE_INPUTSTREAM_LOGGING +#define GTM_HTTPFETCHER_ENABLE_INPUTSTREAM_LOGGING 0 +#endif // GTM_HTTPFETCHER_ENABLE_INPUTSTREAM_LOGGING + +// By setting the GTM_CONTAINERS_VALIDATION_FAILED_LOG and +// GTM_CONTAINERS_VALIDATION_FAILED_ASSERT macros you can control what happens +// when a validation fails. If you implement your own validators, you may want +// to control their internals using the same macros for consistency. +#ifndef GTM_CONTAINERS_VALIDATION_FAILED_ASSERT +#define GTM_CONTAINERS_VALIDATION_FAILED_ASSERT 0 +#endif + +// Give ourselves a consistent way to do inlines. Apple's macros even use +// a few different actual definitions, so we're based off of the foundation +// one. +#if !defined(GTM_INLINE) +#if defined (__GNUC__) && (__GNUC__ == 4) +#define GTM_INLINE static __inline__ __attribute__((always_inline)) +#else +#define GTM_INLINE static __inline__ +#endif +#endif + +// Give ourselves a consistent way of doing externs that links up nicely +// when mixing objc and objc++ +#if !defined (GTM_EXTERN) +#if defined __cplusplus +#define GTM_EXTERN extern "C" +#else +#define GTM_EXTERN extern +#endif +#endif + +// Give ourselves a consistent way of exporting things if we have visibility +// set to hidden. +#if !defined (GTM_EXPORT) +#define GTM_EXPORT __attribute__((visibility("default"))) +#endif + +// _GTMDevLog & _GTMDevAssert +// +// _GTMDevLog & _GTMDevAssert are meant to be a very lightweight shell for +// developer level errors. This implementation simply macros to NSLog/NSAssert. +// It is not intended to be a general logging/reporting system. +// +// Please see http://code.google.com/p/google-toolbox-for-mac/wiki/DevLogNAssert +// for a little more background on the usage of these macros. +// +// _GTMDevLog log some error/problem in debug builds +// _GTMDevAssert assert if conditon isn't met w/in a method/function +// in all builds. +// +// To replace this system, just provide different macro definitions in your +// prefix header. Remember, any implementation you provide *must* be thread +// safe since this could be called by anything in what ever situtation it has +// been placed in. +// + +// We only define the simple macros if nothing else has defined this. +#ifndef _GTMDevLog + +#ifdef DEBUG +#define _GTMDevLog(...) NSLog(__VA_ARGS__) +#else +#define _GTMDevLog(...) do { } while (0) +#endif + +#endif // _GTMDevLog + +// Declared here so that it can easily be used for logging tracking if +// necessary. See GTMUnitTestDevLog.h for details. +@class NSString; +GTM_EXTERN void _GTMUnitTestDevLog(NSString *format, ...); + +#ifndef _GTMDevAssert +// we directly invoke the NSAssert handler so we can pass on the varargs +// (NSAssert doesn't have a macro we can use that takes varargs) +#if !defined(NS_BLOCK_ASSERTIONS) +#define _GTMDevAssert(condition, ...) \ +do { \ +if (!(condition)) { \ +[[NSAssertionHandler currentHandler] \ +handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \ +file:[NSString stringWithUTF8String:__FILE__] \ +lineNumber:__LINE__ \ +description:__VA_ARGS__]; \ +} \ +} while(0) +#else // !defined(NS_BLOCK_ASSERTIONS) +#define _GTMDevAssert(condition, ...) do { } while (0) +#endif // !defined(NS_BLOCK_ASSERTIONS) + +#endif // _GTMDevAssert + +// _GTMCompileAssert +// _GTMCompileAssert is an assert that is meant to fire at compile time if you +// want to check things at compile instead of runtime. For example if you +// want to check that a wchar is 4 bytes instead of 2 you would use +// _GTMCompileAssert(sizeof(wchar_t) == 4, wchar_t_is_4_bytes_on_OS_X) +// Note that the second "arg" is not in quotes, and must be a valid processor +// symbol in it's own right (no spaces, punctuation etc). + +// Wrapping this in an #ifndef allows external groups to define their own +// compile time assert scheme. +#ifndef _GTMCompileAssert +// We got this technique from here: +// http://unixjunkie.blogspot.com/2007/10/better-compile-time-asserts_29.html + +#define _GTMCompileAssertSymbolInner(line, msg) _GTMCOMPILEASSERT ## line ## __ ## msg +#define _GTMCompileAssertSymbol(line, msg) _GTMCompileAssertSymbolInner(line, msg) +#define _GTMCompileAssert(test, msg) \ +typedef char _GTMCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ] +#endif // _GTMCompileAssert + +// Macro to allow fast enumeration when building for 10.5 or later, and +// reliance on NSEnumerator for 10.4. Remember, NSDictionary w/ FastEnumeration +// does keys, so pick the right thing, nothing is done on the FastEnumeration +// side to be sure you're getting what you wanted. +#ifndef GTM_FOREACH_OBJECT +#if defined(TARGET_OS_IPHONE) || (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) +#define GTM_FOREACH_OBJECT(element, collection) \ +for (element in collection) +#define GTM_FOREACH_KEY(element, collection) \ +for (element in collection) +#else +#define GTM_FOREACH_OBJECT(element, collection) \ +for (NSEnumerator * _ ## element ## _enum = [collection objectEnumerator]; \ +(element = [_ ## element ## _enum nextObject]) != nil; ) +#define GTM_FOREACH_KEY(element, collection) \ +for (NSEnumerator * _ ## element ## _enum = [collection keyEnumerator]; \ +(element = [_ ## element ## _enum nextObject]) != nil; ) +#endif +#endif + +// ============================================================================ + +// ---------------------------------------------------------------------------- +// CPP symbols defined based on the project settings so the GTM code has +// simple things to test against w/o scattering the knowledge of project +// setting through all the code. +// ---------------------------------------------------------------------------- + +// Provide a single constant CPP symbol that all of GTM uses for ifdefing +// iPhone code. +#include +#if TARGET_OS_IPHONE // iPhone SDK +// For iPhone specific stuff +#define GTM_IPHONE_SDK 1 +#if TARGET_IPHONE_SIMULATOR +#define GTM_IPHONE_SIMULATOR 1 +#else +#define GTM_IPHONE_DEVICE 1 +#endif // TARGET_IPHONE_SIMULATOR +#else +// For MacOS specific stuff +#define GTM_MACOS_SDK 1 +#endif + +// Provide a symbol to include/exclude extra code for GC support. (This mainly +// just controls the inclusion of finalize methods). +#ifndef GTM_SUPPORT_GC +#if GTM_IPHONE_SDK +// iPhone never needs GC +#define GTM_SUPPORT_GC 0 +#else +// We can't find a symbol to tell if GC is supported/required, so best we +// do on Mac targets is include it if we're on 10.5 or later. +#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 +#define GTM_SUPPORT_GC 0 +#else +#define GTM_SUPPORT_GC 1 +#endif +#endif +#endif + +// To simplify support for 64bit (and Leopard in general), we provide the type +// defines for non Leopard SDKs +#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 +// NSInteger/NSUInteger and Max/Mins +#ifndef NSINTEGER_DEFINED +#if __LP64__ || NS_BUILD_32_LIKE_64 +typedef long NSInteger; +typedef unsigned long NSUInteger; +#else +typedef int NSInteger; +typedef unsigned int NSUInteger; +#endif +#define NSIntegerMax LONG_MAX +#define NSIntegerMin LONG_MIN +#define NSUIntegerMax ULONG_MAX +#define NSINTEGER_DEFINED 1 +#endif // NSINTEGER_DEFINED +// CGFloat +#ifndef CGFLOAT_DEFINED +#if defined(__LP64__) && __LP64__ +// This really is an untested path (64bit on Tiger?) +typedef double CGFloat; +#define CGFLOAT_MIN DBL_MIN +#define CGFLOAT_MAX DBL_MAX +#define CGFLOAT_IS_DOUBLE 1 +#else /* !defined(__LP64__) || !__LP64__ */ +typedef float CGFloat; +#define CGFLOAT_MIN FLT_MIN +#define CGFLOAT_MAX FLT_MAX +#define CGFLOAT_IS_DOUBLE 0 +#endif /* !defined(__LP64__) || !__LP64__ */ +#define CGFLOAT_DEFINED 1 +#endif // CGFLOAT_DEFINED +#endif // MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 \ No newline at end of file diff --git a/EUExPDFReader/EUExPDFReader/sourceCode/GTMBase64/UexPDFGTMBase64.h b/EUExPDFReader/EUExPDFReader/sourceCode/GTMBase64/UexPDFGTMBase64.h new file mode 100644 index 0000000..eb9cc36 --- /dev/null +++ b/EUExPDFReader/EUExPDFReader/sourceCode/GTMBase64/UexPDFGTMBase64.h @@ -0,0 +1,183 @@ +// +// UexEMMGTMBase64.h +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import +#import "UexEMMGTMDefines.h" + +// UexEMMGTMBase64 +// +/// Helper for handling Base64 and WebSafeBase64 encodings +// +/// The webSafe methods use different character set and also the results aren't +/// always padded to a multiple of 4 characters. This is done so the resulting +/// data can be used in urls and url query arguments without needing any +/// encoding. You must use the webSafe* methods together, the data does not +/// interop with the RFC methods. +// +@interface UexPDFGTMBase64 : NSObject + +// +// Standard Base64 (RFC) handling +// + +// encodeData: +// +/// Base64 encodes contents of the NSData object. +// +/// Returns: +/// A new autoreleased NSData with the encoded payload. nil for any error. +// ++(NSData *)encodeData:(NSData *)data; + +// decodeData: +// +/// Base64 decodes contents of the NSData object. +// +/// Returns: +/// A new autoreleased NSData with the decoded payload. nil for any error. +// ++(NSData *)decodeData:(NSData *)data; + +// encodeBytes:length: +// +/// Base64 encodes the data pointed at by |bytes|. +// +/// Returns: +/// A new autoreleased NSData with the encoded payload. nil for any error. +// ++(NSData *)encodeBytes:(const void *)bytes length:(NSUInteger)length; + +// decodeBytes:length: +// +/// Base64 decodes the data pointed at by |bytes|. +// +/// Returns: +/// A new autoreleased NSData with the encoded payload. nil for any error. +// ++(NSData *)decodeBytes:(const void *)bytes length:(NSUInteger)length; + +// stringByEncodingData: +// +/// Base64 encodes contents of the NSData object. +// +/// Returns: +/// A new autoreleased NSString with the encoded payload. nil for any error. +// ++(NSString *)stringByEncodingData:(NSData *)data; + +// stringByEncodingBytes:length: +// +/// Base64 encodes the data pointed at by |bytes|. +// +/// Returns: +/// A new autoreleased NSString with the encoded payload. nil for any error. +// ++(NSString *)stringByEncodingBytes:(const void *)bytes length:(NSUInteger)length; + +// decodeString: +// +/// Base64 decodes contents of the NSString. +// +/// Returns: +/// A new autoreleased NSData with the decoded payload. nil for any error. +// ++(NSData *)decodeString:(NSString *)string; + +// +// Modified Base64 encoding so the results can go onto urls. +// +// The changes are in the characters generated and also allows the result to +// not be padded to a multiple of 4. +// Must use the matching call to encode/decode, won't interop with the +// RFC versions. +// + +// webSafeEncodeData:padded: +// +/// WebSafe Base64 encodes contents of the NSData object. If |padded| is YES +/// then padding characters are added so the result length is a multiple of 4. +// +/// Returns: +/// A new autoreleased NSData with the encoded payload. nil for any error. +// ++(NSData *)webSafeEncodeData:(NSData *)data + padded:(BOOL)padded; + +// webSafeDecodeData: +// +/// WebSafe Base64 decodes contents of the NSData object. +// +/// Returns: +/// A new autoreleased NSData with the decoded payload. nil for any error. +// ++(NSData *)webSafeDecodeData:(NSData *)data; + +// webSafeEncodeBytes:length:padded: +// +/// WebSafe Base64 encodes the data pointed at by |bytes|. If |padded| is YES +/// then padding characters are added so the result length is a multiple of 4. +// +/// Returns: +/// A new autoreleased NSData with the encoded payload. nil for any error. +// ++(NSData *)webSafeEncodeBytes:(const void *)bytes + length:(NSUInteger)length + padded:(BOOL)padded; + +// webSafeDecodeBytes:length: +// +/// WebSafe Base64 decodes the data pointed at by |bytes|. +// +/// Returns: +/// A new autoreleased NSData with the encoded payload. nil for any error. +// ++(NSData *)webSafeDecodeBytes:(const void *)bytes length:(NSUInteger)length; + +// stringByWebSafeEncodingData:padded: +// +/// WebSafe Base64 encodes contents of the NSData object. If |padded| is YES +/// then padding characters are added so the result length is a multiple of 4. +// +/// Returns: +/// A new autoreleased NSString with the encoded payload. nil for any error. +// ++(NSString *)stringByWebSafeEncodingData:(NSData *)data + padded:(BOOL)padded; + +// stringByWebSafeEncodingBytes:length:padded: +// +/// WebSafe Base64 encodes the data pointed at by |bytes|. If |padded| is YES +/// then padding characters are added so the result length is a multiple of 4. +// +/// Returns: +/// A new autoreleased NSString with the encoded payload. nil for any error. +// ++(NSString *)stringByWebSafeEncodingBytes:(const void *)bytes + length:(NSUInteger)length + padded:(BOOL)padded; + +// webSafeDecodeString: +// +/// WebSafe Base64 decodes contents of the NSString. +// +/// Returns: +/// A new autoreleased NSData with the decoded payload. nil for any error. +// ++(NSData *)webSafeDecodeString:(NSString *)string; + +@end diff --git a/EUExPDFReader/EUExPDFReader/sourceCode/GTMBase64/UexPDFGTMBase64.m b/EUExPDFReader/EUExPDFReader/sourceCode/GTMBase64/UexPDFGTMBase64.m new file mode 100644 index 0000000..83851df --- /dev/null +++ b/EUExPDFReader/EUExPDFReader/sourceCode/GTMBase64/UexPDFGTMBase64.m @@ -0,0 +1,695 @@ + +// +// UexEMMGTMBase64.m +// +// Copyright 2006-2008 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +#import "UexPDFGTMBase64.h" +#import "UexEMMGTMDefines.h" + +static const char *kBase64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char *kWebSafeBase64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; +static const char kBase64PaddingChar = '='; +static const char kBase64InvalidChar = 99; + +static const char kBase64DecodeChars[] = { + // This array was generated by the following code: + // #include + // #include + // #include + // main() + // { + // static const char Base64[] = + // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + // char *pos; + // int idx, i, j; + // printf(" "); + // for (i = 0; i < 255; i += 8) { + // for (j = i; j < i + 8; j++) { + // pos = strchr(Base64, j); + // if ((pos == NULL) || (j == 0)) + // idx = 99; + // else + // idx = pos - Base64; + // if (idx == 99) + // printf(" %2d, ", idx); + // else + // printf(" %2d/*%c*/,", idx, j); + // } + // printf("\n "); + // } + // } + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 62/*+*/, 99, 99, 99, 63/*/ */, + 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/, + 60/*8*/, 61/*9*/, 99, 99, 99, 99, 99, 99, + 99, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, + 7/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/, + 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/, + 23/*X*/, 24/*Y*/, 25/*Z*/, 99, 99, 99, 99, 99, + 99, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/, + 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/, + 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/, + 49/*x*/, 50/*y*/, 51/*z*/, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 +}; + +static const char kWebSafeBase64DecodeChars[] = { + // This array was generated by the following code: + // #include + // #include + // #include + // main() + // { + // static const char Base64[] = + // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + // char *pos; + // int idx, i, j; + // printf(" "); + // for (i = 0; i < 255; i += 8) { + // for (j = i; j < i + 8; j++) { + // pos = strchr(Base64, j); + // if ((pos == NULL) || (j == 0)) + // idx = 99; + // else + // idx = pos - Base64; + // if (idx == 99) + // printf(" %2d, ", idx); + // else + // printf(" %2d/*%c*/,", idx, j); + // } + // printf("\n "); + // } + // } + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 62/*-*/, 99, 99, + 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/, + 60/*8*/, 61/*9*/, 99, 99, 99, 99, 99, 99, + 99, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, + 7/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/, + 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/, + 23/*X*/, 24/*Y*/, 25/*Z*/, 99, 99, 99, 99, 63/*_*/, + 99, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/, + 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/, + 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/, + 49/*x*/, 50/*y*/, 51/*z*/, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 +}; + + +// Tests a character to see if it's a whitespace character. +// +// Returns: +// YES if the character is a whitespace character. +// NO if the character is not a whitespace character. +// +GTM_INLINE BOOL IsSpace(unsigned char c) { + // we use our own mapping here because we don't want anything w/ locale + // support. + static BOOL kSpaces[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, // 0-9 + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 10-19 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20-29 + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 30-39 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40-49 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 50-59 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60-69 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 70-79 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80-89 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 90-99 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 100-109 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 110-119 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 120-129 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 130-139 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 140-149 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 150-159 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160-169 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 170-179 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 180-189 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 190-199 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 200-209 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 210-219 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 220-229 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 230-239 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 240-249 + 0, 0, 0, 0, 0, 1, // 250-255 + }; + return kSpaces[c]; +} + +// Calculate how long the data will be once it's base64 encoded. +// +// Returns: +// The guessed encoded length for a source length +// +GTM_INLINE NSUInteger CalcEncodedLength(NSUInteger srcLen, BOOL padded) { + NSUInteger intermediate_result = 8 * srcLen + 5; + NSUInteger len = intermediate_result / 6; + if (padded) { + len = ((len + 3) / 4) * 4; + } + return len; +} + +// Tries to calculate how long the data will be once it's base64 decoded. +// Unlike the above, this is always an upperbound, since the source data +// could have spaces and might end with the padding characters on them. +// +// Returns: +// The guessed decoded length for a source length +// +GTM_INLINE NSUInteger GuessDecodedLength(NSUInteger srcLen) { + return (srcLen + 3) / 4 * 3; +} + + +@interface UexPDFGTMBase64 (PrivateMethods) + ++(NSData *)baseEncode:(const void *)bytes + length:(NSUInteger)length + charset:(const char *)charset + padded:(BOOL)padded; + ++(NSData *)baseDecode:(const void *)bytes + length:(NSUInteger)length + charset:(const char*)charset + requirePadding:(BOOL)requirePadding; + ++(NSUInteger)baseEncode:(const char *)srcBytes + srcLen:(NSUInteger)srcLen + destBytes:(char *)destBytes + destLen:(NSUInteger)destLen + charset:(const char *)charset + padded:(BOOL)padded; + ++(NSUInteger)baseDecode:(const char *)srcBytes + srcLen:(NSUInteger)srcLen + destBytes:(char *)destBytes + destLen:(NSUInteger)destLen + charset:(const char *)charset + requirePadding:(BOOL)requirePadding; + +@end + + +@implementation UexPDFGTMBase64 + +// +// Standard Base64 (RFC) handling +// + ++(NSData *)encodeData:(NSData *)data { + return [self baseEncode:[data bytes] + length:[data length] + charset:kBase64EncodeChars + padded:YES]; +} + ++(NSData *)decodeData:(NSData *)data { + return [self baseDecode:[data bytes] + length:[data length] + charset:kBase64DecodeChars + requirePadding:YES]; +} + ++(NSData *)encodeBytes:(const void *)bytes length:(NSUInteger)length { + return [self baseEncode:bytes + length:length + charset:kBase64EncodeChars + padded:YES]; +} + ++(NSData *)decodeBytes:(const void *)bytes length:(NSUInteger)length { + return [self baseDecode:bytes + length:length + charset:kBase64DecodeChars + requirePadding:YES]; +} + ++(NSString *)stringByEncodingData:(NSData *)data { + NSString *result = nil; + NSData *converted = [self baseEncode:[data bytes] + length:[data length] + charset:kBase64EncodeChars + padded:YES]; + if (converted) { + result = [[[NSString alloc] initWithData:converted + encoding:NSASCIIStringEncoding] autorelease]; + } + return result; +} + ++(NSString *)stringByEncodingBytes:(const void *)bytes length:(NSUInteger)length { + NSString *result = nil; + NSData *converted = [self baseEncode:bytes + length:length + charset:kBase64EncodeChars + padded:YES]; + if (converted) { + result = [[[NSString alloc] initWithData:converted + encoding:NSASCIIStringEncoding] autorelease]; + } + return result; +} + ++(NSData *)decodeString:(NSString *)string { + NSData *result = nil; + NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding]; + if (data) { + result = [self baseDecode:[data bytes] + length:[data length] + charset:kBase64DecodeChars + requirePadding:YES]; + } + return result; +} + +// +// Modified Base64 encoding so the results can go onto urls. +// +// The changes are in the characters generated and also the result isn't +// padded to a multiple of 4. +// Must use the matching call to encode/decode, won't interop with the +// RFC versions. +// + ++(NSData *)webSafeEncodeData:(NSData *)data + padded:(BOOL)padded { + return [self baseEncode:[data bytes] + length:[data length] + charset:kWebSafeBase64EncodeChars + padded:padded]; +} + ++(NSData *)webSafeDecodeData:(NSData *)data { + return [self baseDecode:[data bytes] + length:[data length] + charset:kWebSafeBase64DecodeChars + requirePadding:NO]; +} + ++(NSData *)webSafeEncodeBytes:(const void *)bytes + length:(NSUInteger)length + padded:(BOOL)padded { + return [self baseEncode:bytes + length:length + charset:kWebSafeBase64EncodeChars + padded:padded]; +} + ++(NSData *)webSafeDecodeBytes:(const void *)bytes length:(NSUInteger)length { + return [self baseDecode:bytes + length:length + charset:kWebSafeBase64DecodeChars + requirePadding:NO]; +} + ++(NSString *)stringByWebSafeEncodingData:(NSData *)data + padded:(BOOL)padded { + NSString *result = nil; + NSData *converted = [self baseEncode:[data bytes] + length:[data length] + charset:kWebSafeBase64EncodeChars + padded:padded]; + if (converted) { + result = [[[NSString alloc] initWithData:converted + encoding:NSASCIIStringEncoding] autorelease]; + } + return result; +} + ++(NSString *)stringByWebSafeEncodingBytes:(const void *)bytes + length:(NSUInteger)length + padded:(BOOL)padded { + NSString *result = nil; + NSData *converted = [self baseEncode:bytes + length:length + charset:kWebSafeBase64EncodeChars + padded:padded]; + if (converted) { + result = [[[NSString alloc] initWithData:converted + encoding:NSASCIIStringEncoding] autorelease]; + } + return result; +} + ++(NSData *)webSafeDecodeString:(NSString *)string { + NSData *result = nil; + NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding]; + if (data) { + result = [self baseDecode:[data bytes] + length:[data length] + charset:kWebSafeBase64DecodeChars + requirePadding:NO]; + } + return result; +} + +@end + +@implementation UexPDFGTMBase64 (PrivateMethods) + +// +// baseEncode:length:charset:padded: +// +// Does the common lifting of creating the dest NSData. it creates & sizes the +// data for the results. |charset| is the characters to use for the encoding +// of the data. |padding| controls if the encoded data should be padded to a +// multiple of 4. +// +// Returns: +// an autorelease NSData with the encoded data, nil if any error. +// ++(NSData *)baseEncode:(const void *)bytes + length:(NSUInteger)length + charset:(const char *)charset + padded:(BOOL)padded { + // how big could it be? + NSUInteger maxLength = CalcEncodedLength(length, padded); + // make space + NSMutableData *result = [NSMutableData data]; + [result setLength:maxLength]; + // do it + NSUInteger finalLength = [self baseEncode:bytes + srcLen:length + destBytes:[result mutableBytes] + destLen:[result length] + charset:charset + padded:padded]; + if (finalLength) { + _GTMDevAssert(finalLength == maxLength, @"how did we calc the length wrong?"); + } else { + // shouldn't happen, this means we ran out of space + result = nil; + } + return result; +} + +// +// baseDecode:length:charset:requirePadding: +// +// Does the common lifting of creating the dest NSData. it creates & sizes the +// data for the results. |charset| is the characters to use for the decoding +// of the data. +// +// Returns: +// an autorelease NSData with the decoded data, nil if any error. +// +// ++(NSData *)baseDecode:(const void *)bytes + length:(NSUInteger)length + charset:(const char *)charset + requirePadding:(BOOL)requirePadding { + // could try to calculate what it will end up as + NSUInteger maxLength = GuessDecodedLength(length); + // make space + NSMutableData *result = [NSMutableData data]; + [result setLength:maxLength]; + // do it + NSUInteger finalLength = [self baseDecode:bytes + srcLen:length + destBytes:[result mutableBytes] + destLen:[result length] + charset:charset + requirePadding:requirePadding]; + if (finalLength) { + if (finalLength != maxLength) { + // resize down to how big it was + [result setLength:finalLength]; + } + } else { + // either an error in the args, or we ran out of space + result = nil; + } + return result; +} + +// +// baseEncode:srcLen:destBytes:destLen:charset:padded: +// +// Encodes the buffer into the larger. returns the length of the encoded +// data, or zero for an error. +// |charset| is the characters to use for the encoding +// |padded| tells if the result should be padded to a multiple of 4. +// +// Returns: +// the length of the encoded data. zero if any error. +// ++(NSUInteger)baseEncode:(const char *)srcBytes + srcLen:(NSUInteger)srcLen + destBytes:(char *)destBytes + destLen:(NSUInteger)destLen + charset:(const char *)charset + padded:(BOOL)padded { + if (!srcLen || !destLen || !srcBytes || !destBytes) { + return 0; + } + + char *curDest = destBytes; + const unsigned char *curSrc = (const unsigned char *)(srcBytes); + + // Three bytes of data encodes to four characters of cyphertext. + // So we can pump through three-byte chunks atomically. + while (srcLen > 2) { + // space? + _GTMDevAssert(destLen >= 4, @"our calc for encoded length was wrong"); + curDest[0] = charset[curSrc[0] >> 2]; + curDest[1] = charset[((curSrc[0] & 0x03) << 4) + (curSrc[1] >> 4)]; + curDest[2] = charset[((curSrc[1] & 0x0f) << 2) + (curSrc[2] >> 6)]; + curDest[3] = charset[curSrc[2] & 0x3f]; + + curDest += 4; + curSrc += 3; + srcLen -= 3; + destLen -= 4; + } + + // now deal with the tail (<=2 bytes) + switch (srcLen) { + case 0: + // Nothing left; nothing more to do. + break; + case 1: + // One byte left: this encodes to two characters, and (optionally) + // two pad characters to round out the four-character cypherblock. + _GTMDevAssert(destLen >= 2, @"our calc for encoded length was wrong"); + curDest[0] = charset[curSrc[0] >> 2]; + curDest[1] = charset[(curSrc[0] & 0x03) << 4]; + curDest += 2; + destLen -= 2; + if (padded) { + _GTMDevAssert(destLen >= 2, @"our calc for encoded length was wrong"); + curDest[0] = kBase64PaddingChar; + curDest[1] = kBase64PaddingChar; + curDest += 2; + } + break; + case 2: + // Two bytes left: this encodes to three characters, and (optionally) + // one pad character to round out the four-character cypherblock. + _GTMDevAssert(destLen >= 3, @"our calc for encoded length was wrong"); + curDest[0] = charset[curSrc[0] >> 2]; + curDest[1] = charset[((curSrc[0] & 0x03) << 4) + (curSrc[1] >> 4)]; + curDest[2] = charset[(curSrc[1] & 0x0f) << 2]; + curDest += 3; + destLen -= 3; + if (padded) { + _GTMDevAssert(destLen >= 1, @"our calc for encoded length was wrong"); + curDest[0] = kBase64PaddingChar; + curDest += 1; + } + break; + } + // return the length + return (curDest - destBytes); +} + +// +// baseDecode:srcLen:destBytes:destLen:charset:requirePadding: +// +// Decodes the buffer into the larger. returns the length of the decoded +// data, or zero for an error. +// |charset| is the character decoding buffer to use +// +// Returns: +// the length of the encoded data. zero if any error. +// ++(NSUInteger)baseDecode:(const char *)srcBytes + srcLen:(NSUInteger)srcLen + destBytes:(char *)destBytes + destLen:(NSUInteger)destLen + charset:(const char *)charset + requirePadding:(BOOL)requirePadding { + if (!srcLen || !destLen || !srcBytes || !destBytes) { + return 0; + } + + int decode; + NSUInteger destIndex = 0; + int state = 0; + char ch = 0; + while (srcLen-- && (ch = *srcBytes++) != 0) { + if (IsSpace(ch)) // Skip whitespace + continue; + + if (ch == kBase64PaddingChar) + break; + + decode = charset[(unsigned int)ch]; + if (decode == kBase64InvalidChar) + return 0; + + // Four cyphertext characters decode to three bytes. + // Therefore we can be in one of four states. + switch (state) { + case 0: + // We're at the beginning of a four-character cyphertext block. + // This sets the high six bits of the first byte of the + // plaintext block. + _GTMDevAssert(destIndex < destLen, @"our calc for decoded length was wrong"); + destBytes[destIndex] = decode << 2; + state = 1; + break; + case 1: + // We're one character into a four-character cyphertext block. + // This sets the low two bits of the first plaintext byte, + // and the high four bits of the second plaintext byte. + _GTMDevAssert((destIndex+1) < destLen, @"our calc for decoded length was wrong"); + destBytes[destIndex] |= decode >> 4; + destBytes[destIndex+1] = (decode & 0x0f) << 4; + destIndex++; + state = 2; + break; + case 2: + // We're two characters into a four-character cyphertext block. + // This sets the low four bits of the second plaintext + // byte, and the high two bits of the third plaintext byte. + // However, if this is the end of data, and those two + // bits are zero, it could be that those two bits are + // leftovers from the encoding of data that had a length + // of two mod three. + _GTMDevAssert((destIndex+1) < destLen, @"our calc for decoded length was wrong"); + destBytes[destIndex] |= decode >> 2; + destBytes[destIndex+1] = (decode & 0x03) << 6; + destIndex++; + state = 3; + break; + case 3: + // We're at the last character of a four-character cyphertext block. + // This sets the low six bits of the third plaintext byte. + _GTMDevAssert(destIndex < destLen, @"our calc for decoded length was wrong"); + destBytes[destIndex] |= decode; + destIndex++; + state = 0; + break; + } + } + + // We are done decoding Base-64 chars. Let's see if we ended + // on a byte boundary, and/or with erroneous trailing characters. + if (ch == kBase64PaddingChar) { // We got a pad char + if ((state == 0) || (state == 1)) { + return 0; // Invalid '=' in first or second position + } + if (srcLen == 0) { + if (state == 2) { // We run out of input but we still need another '=' + return 0; + } + // Otherwise, we are in state 3 and only need this '=' + } else { + if (state == 2) { // need another '=' + while ((ch = *srcBytes++) && (srcLen-- > 0)) { + if (!IsSpace(ch)) + break; + } + if (ch != kBase64PaddingChar) { + return 0; + } + } + // state = 1 or 2, check if all remain padding is space + while ((ch = *srcBytes++) && (srcLen-- > 0)) { + if (!IsSpace(ch)) { + return 0; + } + } + } + } else { + // We ended by seeing the end of the string. + + if (requirePadding) { + // If we require padding, then anything but state 0 is an error. + if (state != 0) { + return 0; + } + } else { + // Make sure we have no partial bytes lying around. Note that we do not + // require trailing '=', so states 2 and 3 are okay too. + if (state == 1) { + return 0; + } + } + } + + // If then next piece of output was valid and got written to it means we got a + // very carefully crafted input that appeared valid but contains some trailing + // bits past the real length, so just toss the thing. + if ((destIndex < destLen) && + (destBytes[destIndex] != 0)) { + return 0; + } + + return destIndex; +} + +@end diff --git a/EUExPDFReader/EUExPDFReader/sourceCode/ReaderViewController.h b/EUExPDFReader/EUExPDFReader/sourceCode/ReaderViewController.h index 8a3382d..dd10596 100755 --- a/EUExPDFReader/EUExPDFReader/sourceCode/ReaderViewController.h +++ b/EUExPDFReader/EUExPDFReader/sourceCode/ReaderViewController.h @@ -15,8 +15,10 @@ #import "ReaderMainPagebar.h" #import "ThumbsViewController.h" + @class ReaderViewController; @class ReaderMainToolbar; +@class EUExPDFReader; @protocol ReaderViewControllerDelegate @@ -55,6 +57,9 @@ //@property(nonatomic,weak) EUExPDFReader *uexObj; @property (nonatomic, assign, readwrite) id delegate; -- (id)initWithReaderDocument:(ReaderDocument *)object; + +- (id)initWithReaderDocument:(ReaderDocument *)object withEUExObj:(EUExPDFReader *)euexPDFReader; + +- (instancetype)initWithEUExObj:(EUExPDFReader *)euexPDFReader; @end diff --git a/EUExPDFReader/EUExPDFReader/sourceCode/ReaderViewController.m b/EUExPDFReader/EUExPDFReader/sourceCode/ReaderViewController.m index 3b02237..d72cf36 100755 --- a/EUExPDFReader/EUExPDFReader/sourceCode/ReaderViewController.m +++ b/EUExPDFReader/EUExPDFReader/sourceCode/ReaderViewController.m @@ -10,6 +10,13 @@ #import "ReaderViewController.h" #import "ReaderThumbCache.h" #import "ReaderThumbQueue.h" +#import "EUExPDFReader.h" + +@interface ReaderViewController() + +@property (nonatomic,strong)EUExPDFReader *euexPDFReader; + +@end @implementation ReaderViewController @@ -28,6 +35,16 @@ @implementation ReaderViewController @synthesize delegate; + +- (instancetype)initWithEUExObj:(EUExPDFReader *)euexPDFReader{ + self = [super init]; + if (self) { + _euexPDFReader = euexPDFReader; + } + return self; +} + + #pragma mark Support methods - (void)updateScrollViewContentSize @@ -254,7 +271,7 @@ - (void)showDocument:(id)object #pragma mark UIViewController methods -- (id)initWithReaderDocument:(ReaderDocument *)object +- (id)initWithReaderDocument:(ReaderDocument *)object withEUExObj:(EUExPDFReader *)euexPDFReader { #ifdef DEBUGX NSLog(@"%s", __FUNCTION__); @@ -266,6 +283,7 @@ - (id)initWithReaderDocument:(ReaderDocument *)object { if ((self = [super initWithNibName:nil bundle:nil])) // Designated initializer { + _euexPDFReader = euexPDFReader; NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter addObserver:self selector:@selector(applicationWill:) name:UIApplicationWillTerminateNotification object:nil]; @@ -799,7 +817,7 @@ - (void)tappedInToolbar:(ReaderMainToolbar *)toolbar doneButton:(UIButton *)butt [[ReaderThumbQueue sharedInstance] cancelOperationsWithGUID:document.guid]; [[ReaderThumbCache sharedInstance] removeAllObjects]; // Empty the thumb cache - + if (printInteraction != nil) [printInteraction dismissAnimated:NO]; // Dismiss if ([delegate respondsToSelector:@selector(dismissReaderViewController:)] == YES) @@ -812,6 +830,21 @@ - (void)tappedInToolbar:(ReaderMainToolbar *)toolbar doneButton:(UIButton *)butt NSAssert(NO, @"Delegate must respond to -dismissReaderViewController:"); } + NSDictionary *dict = @{ + @"status":@"1" + }; + //ac_JSONFragment 方法,可以将NSDictionary转换成JSON字符串 + [self.euexPDFReader.webViewEngine callbackWithFunctionKeyPath:@"uexPDFReader.cbDoCallback" + arguments:ACArgsPack(dict.ac_JSONFragment) + completion:^(JSValue * _Nullable returnValue) { + if (returnValue) { + // ACLogDebug(@"回调成功!"); + NSLog(@"回调成功!"); + } + }]; + + + #endif // end of READER_STANDALONE Option } diff --git a/EUExPDFReader/EUExPDFReader/sourceCode/Sources/ReaderDocument.h b/EUExPDFReader/EUExPDFReader/sourceCode/Sources/ReaderDocument.h index 3ec3059..ee89e1b 100755 --- a/EUExPDFReader/EUExPDFReader/sourceCode/Sources/ReaderDocument.h +++ b/EUExPDFReader/EUExPDFReader/sourceCode/Sources/ReaderDocument.h @@ -48,6 +48,8 @@ + (ReaderDocument *)unarchiveFromFileName:(NSString *)filename password:(NSString *)phrase; ++ (NSString *)GUID; + - (id)initWithFilePath:(NSString *)fullFilePath password:(NSString *)phrase; - (void)saveReaderDocument; diff --git a/EUExPDFReader/uexPDFReader/info.xml b/EUExPDFReader/uexPDFReader/info.xml index 53b0e1c..20a2e11 100755 --- a/EUExPDFReader/uexPDFReader/info.xml +++ b/EUExPDFReader/uexPDFReader/info.xml @@ -1,8 +1,11 @@ - 4: 防止重复调用打开pdf页面方法时闪退,但再次调用打开方法时务必要确认上次打开后调用了对应的关闭方法,否则可能会出现打不开的现象 + uexName="uexPDFReader" version="4.0.7" build="2018111301"> + 7: 解决PDF在沙盒能查到的问题 + 6: 打包与emm文件冲突修改 + 5: 添加打开PDF解密定制逻辑 + 4: 防止重复调用打开pdf页面方法时闪退,但再次调用打开方法时务必要确认上次打开后调用了对应的关闭方法,否则可能会出现打不开的现象 3: 适配iPhone X 2: 增加openPDFReader回调 1: 支持view级别的pdf预览 diff --git a/EUExPDFReader/uexPDFReader/libuexPDFReader.a b/EUExPDFReader/uexPDFReader/libuexPDFReader.a index 8537f1c..105fa0c 100644 Binary files a/EUExPDFReader/uexPDFReader/libuexPDFReader.a and b/EUExPDFReader/uexPDFReader/libuexPDFReader.a differ