From 9b86791eef942f8cddf4d170357fae8743f40e74 Mon Sep 17 00:00:00 2001 From: Rohan Kuruvilla Date: Wed, 17 Apr 2013 17:24:59 -0700 Subject: [PATCH] Adding CocosPlayer for iOS --- .../CocosPlayer/Classes/AppDelegate.cpp | 166 +- .../CocosPlayer/Classes/AppDelegate.h | 7 +- .../Classes/CCBDirectoryComparer.h | 21 + .../Classes/CCBDirectoryComparer.m | 109 + ...cocos2dx_cocosplayer_CocosPlayerSocket.cpp | 19 +- ...g_cocos2dx_cocosplayer_CocosPlayerSocket.h | 2 +- .../CocosPlayer/Classes/MainSceneHelper.cpp | 93 +- .../CocosPlayer/Classes/MainSceneHelper.h | 26 +- .../CocosPlayer/Classes/PlayerStatus.cpp | 112 +- .../CocosPlayer/Classes/PlayerStatus.h | 22 +- .../CocosPlayer/Classes/ServerController.h | 99 + .../CocosPlayer/Classes/ServerController.mm | 607 +++++ .../Classes/iOS/CCBDirectoryComparer.h | 21 + .../Classes/iOS/CCBDirectoryComparer.m | 109 + .../Classes/iOS/ServerController.h | 99 + .../Classes/iOS/ServerController.mm | 607 +++++ .../ThoMoClient/ThoMoClientDelegateProtocol.h | 68 + .../ThoMoClient/ThoMoClientStub.m | 407 ++++ .../ThoMoClient/ThoMoClientStub_private.h | 57 + .../iOS/ThoMoNetworking/ThoMoClientStub.h | 111 + .../iOS/ThoMoNetworking/ThoMoNetworkStub.h | 77 + .../iOS/ThoMoNetworking/ThoMoNetworkStub.m | 443 ++++ .../iOS/ThoMoNetworking/ThoMoNetworking.h | 46 + .../ThoMoServer/ThoMoServerDelegateProtocol.h | 68 + .../ThoMoServer/ThoMoServerStub.m | 450 ++++ .../ThoMoServer/ThoMoServerStub_private.h | 54 + .../iOS/ThoMoNetworking/ThoMoServerStub.h | 111 + .../iOS/ThoMoNetworking/ThoMoTCPConnection.h | 88 + .../iOS/ThoMoNetworking/ThoMoTCPConnection.m | 386 +++ .../ThoMoTCPConnectionDelegateProtocol.h | 43 + .../Classes/iOS/ssziparchive/LICENSE | 20 + .../Classes/iOS/ssziparchive/SSZipArchive.h | 45 + .../Classes/iOS/ssziparchive/SSZipArchive.m | 421 ++++ .../Classes/iOS/ssziparchive/minizip/crypt.h | 131 + .../Classes/iOS/ssziparchive/minizip/ioapi.c | 239 ++ .../Classes/iOS/ssziparchive/minizip/ioapi.h | 201 ++ .../iOS/ssziparchive/minizip/mztools.c | 284 +++ .../iOS/ssziparchive/minizip/mztools.h | 31 + .../Classes/iOS/ssziparchive/minizip/unzip.c | 2152 +++++++++++++++++ .../Classes/iOS/ssziparchive/minizip/unzip.h | 437 ++++ .../Classes/iOS/ssziparchive/minizip/zip.c | 2022 ++++++++++++++++ .../Classes/iOS/ssziparchive/minizip/zip.h | 362 +++ .../ccb_btn-play.png.REMOVED.git-id | 1 + .../ccb_btn-run-dis.png.REMOVED.git-id | 1 + .../ccb_btn-run-down.png.REMOVED.git-id | 1 + .../ccb_btn-run.png.REMOVED.git-id | 1 + .../ccb_logo.png.REMOVED.git-id | 1 + .../proj.android/jni/cocosplayer/main.cpp | 1 + .../cocosplayer/CocosPlayerSocket.java | 2 +- .../CocosPlayer/proj.ios/AppController.h | 23 + .../CocosPlayer/proj.ios/AppController.mm | 160 ++ .../project.pbxproj.REMOVED.git-id | 1 + .../Default-568h@2x.png.REMOVED.git-id | 1 + .../proj.ios/Default@2x.png.REMOVED.git-id | 1 + .../CocosPlayer/proj.ios/Prefix.pch | 8 + .../CocosPlayer/proj.ios/RootViewController.h | 33 + .../proj.ios/RootViewController.mm | 66 + .../Javascript/CocosPlayer/proj.ios/main.m | 11 + 58 files changed, 10992 insertions(+), 193 deletions(-) create mode 100644 samples/Javascript/CocosPlayer/Classes/CCBDirectoryComparer.h create mode 100644 samples/Javascript/CocosPlayer/Classes/CCBDirectoryComparer.m create mode 100644 samples/Javascript/CocosPlayer/Classes/ServerController.h create mode 100644 samples/Javascript/CocosPlayer/Classes/ServerController.mm create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/CCBDirectoryComparer.h create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/CCBDirectoryComparer.m create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/ServerController.h create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/ServerController.mm create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoClient/ThoMoClientDelegateProtocol.h create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoClient/ThoMoClientStub.m create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoClient/ThoMoClientStub_private.h create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoClientStub.h create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoNetworkStub.h create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoNetworkStub.m create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoNetworking.h create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoServer/ThoMoServerDelegateProtocol.h create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoServer/ThoMoServerStub.m create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoServer/ThoMoServerStub_private.h create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoServerStub.h create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoTCPConnection.h create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoTCPConnection.m create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoTCPConnectionDelegateProtocol.h create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/LICENSE create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/SSZipArchive.h create mode 100644 samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/SSZipArchive.m create mode 100755 samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/crypt.h create mode 100755 samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/ioapi.c create mode 100755 samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/ioapi.h create mode 100755 samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/mztools.c create mode 100755 samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/mztools.h create mode 100755 samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/unzip.c create mode 100755 samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/unzip.h create mode 100755 samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/zip.c create mode 100755 samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/zip.h create mode 100644 samples/Javascript/CocosPlayer/Resources/Published-iOS/resources-ipadhd/ccb_btn-play.png.REMOVED.git-id create mode 100644 samples/Javascript/CocosPlayer/Resources/Published-iOS/resources-ipadhd/ccb_btn-run-dis.png.REMOVED.git-id create mode 100644 samples/Javascript/CocosPlayer/Resources/Published-iOS/resources-ipadhd/ccb_btn-run-down.png.REMOVED.git-id create mode 100644 samples/Javascript/CocosPlayer/Resources/Published-iOS/resources-ipadhd/ccb_btn-run.png.REMOVED.git-id create mode 100644 samples/Javascript/CocosPlayer/Resources/Published-iOS/resources-ipadhd/ccb_logo.png.REMOVED.git-id create mode 100644 samples/Javascript/CocosPlayer/proj.ios/AppController.h create mode 100644 samples/Javascript/CocosPlayer/proj.ios/AppController.mm create mode 100644 samples/Javascript/CocosPlayer/proj.ios/CocosPlayer.xcodeproj/project.pbxproj.REMOVED.git-id create mode 100644 samples/Javascript/CocosPlayer/proj.ios/Default-568h@2x.png.REMOVED.git-id create mode 100644 samples/Javascript/CocosPlayer/proj.ios/Default@2x.png.REMOVED.git-id create mode 100644 samples/Javascript/CocosPlayer/proj.ios/Prefix.pch create mode 100644 samples/Javascript/CocosPlayer/proj.ios/RootViewController.h create mode 100644 samples/Javascript/CocosPlayer/proj.ios/RootViewController.mm create mode 100644 samples/Javascript/CocosPlayer/proj.ios/main.m diff --git a/samples/Javascript/CocosPlayer/Classes/AppDelegate.cpp b/samples/Javascript/CocosPlayer/Classes/AppDelegate.cpp index 7832606098..d8bf1c89de 100644 --- a/samples/Javascript/CocosPlayer/Classes/AppDelegate.cpp +++ b/samples/Javascript/CocosPlayer/Classes/AppDelegate.cpp @@ -22,8 +22,9 @@ char *_js_log_buf_ccbuilder = NULL; USING_NS_CC; using namespace CocosDenshion; +CCScene *mainScene; -AppDelegate::AppDelegate() +AppDelegate::AppDelegate(): isRetina(false), isIPhone(false) { } @@ -32,6 +33,23 @@ AppDelegate::~AppDelegate() CCScriptEngineManager::sharedManager()->purgeSharedManager(); } + +bool runMainScene() { + /* Push the new scene with a fancy transition. */ + ccColor3B transitionColor; + transitionColor.r = 0; + transitionColor.g = 0; + transitionColor.b = 0; + + mainScene = PlayerStatus::loadMainScene("StatusLayer.ccbi"); + if(CCDirector::sharedDirector()->getRunningScene() != NULL) { + CCDirector::sharedDirector()->replaceScene(CCTransitionFade::create(0.5f, mainScene, transitionColor)); + } else { + CCDirector::sharedDirector()->runWithScene(CCTransitionFade::create(0.5f, mainScene, transitionColor)); + } + return true; +} + void handle_ccb_run() { CCFileUtils::sharedFileUtils()->purgeCachedEntries(); ScriptingCore::getInstance()->runScript("main.js"); @@ -45,21 +63,27 @@ void handle_set_orient(bool isPortrait) { CCLOG("ORIENTATION HALF IMPLEMENTED"); } +void handle_set_message(const char* msg) { + CCBHelper::setInstructionsMessage(msg); +} + +void handle_set_status(const char* msg) { + CCBHelper::setStatusMessage(msg); +} + void handle_disconnected() { CCBHelper::setStatusMessage("Disconnected"); } void handle_ccb_stop() { - CCLOG("STOP UNIMPLEMENTED"); + runMainScene(); } + extern "C" { -bool runMainScene() { - PlayerStatus::loadMainScene("StatusLayer.ccbi"); - return true; -} - +const char * getCCBDirectoryPath(); + bool AppDelegate::applicationDidFinishLaunching() { @@ -68,46 +92,106 @@ bool AppDelegate::applicationDidFinishLaunching() pDirector->setOpenGLView(CCEGLView::sharedOpenGLView()); pDirector->setProjection(kCCDirectorProjection2D); - + CCSize screenSize = CCEGLView::sharedOpenGLView()->getFrameSize(); - + CCSize designSize = CCSizeMake(320, 480); CCSize resourceSize = CCSizeMake(320, 480); + + std::vector resDirOrders; + std::string res; + TargetPlatform platform = CCApplication::sharedApplication()->getTargetPlatform(); + - CCFileUtils* pFileUtils = CCFileUtils::sharedFileUtils(); - std::vector searchResOrder; - string res = "xlarge"; - // if (screenSize.height > 1024) - // { - // resourceSize = CCSizeMake(1280, 1920); - // searchResOrder.push_back("resources-xlarge"); - // res = "xlarge"; - // } - // else - if (screenSize.height > 960) - { - resourceSize = CCSizeMake(640, 960); - searchResOrder.push_back("resources-large"); - res = "large"; - } - else if (screenSize.height > 480) - { - resourceSize = CCSizeMake(480, 720); - searchResOrder.push_back("resources-medium"); - res = "medium"; - } - else - { - resourceSize = CCSizeMake(320, 568); - searchResOrder.push_back("resources-small"); - res = "small"; - } - - pFileUtils->setSearchResolutionsOrder(searchResOrder); - pDirector->setContentScaleFactor(resourceSize.height/designSize.height); + if (platform == kTargetIphone || platform == kTargetIpad) + { + std::vector searchPaths = CCFileUtils::sharedFileUtils()->getSearchPaths(); + searchPaths.insert(searchPaths.begin(), "Published files iOS"); + searchPaths.insert(searchPaths.begin(), getCCBDirectoryPath()); + CCFileUtils::sharedFileUtils()->setSearchPaths(searchPaths); + if (screenSize.height > 1024) + { + res = "iPad"; + designSize = CCSizeMake(360, 480); + resourceSize = CCSizeMake(1536, 2048); + resDirOrders.push_back("resources-ipadhd"); + resDirOrders.push_back("resources-ipad"); + resDirOrders.push_back("resources-iphonehd"); + isIPhone = false; + isRetina = true; + } + else if (screenSize.height > 960) + { + res = "iPad"; + designSize = CCSizeMake(360, 480); + resourceSize = CCSizeMake(768, 1024); + resDirOrders.push_back("resources-ipad"); + resDirOrders.push_back("resources-iphonehd"); + isIPhone = false; + isRetina = false; + } + else if (screenSize.height > 480) + { + res = "iPhone"; + resourceSize = CCSizeMake(640, 960); + resDirOrders.push_back("resources-iphonehd"); + resDirOrders.push_back("resources-iphone"); + isIPhone = true; + isRetina = true; + } + else + { + res = "iPhone"; + resourceSize = CCSizeMake(320, 480); + resDirOrders.push_back("resources-iphone"); + isIPhone = true; + isRetina = false; + } + + } + else if (platform == kTargetAndroid || platform == kTargetWindows) + { + + if (screenSize.height > 960) + { + res = "xlarge"; + resourceSize = CCSizeMake(1280, 1920); + resDirOrders.push_back("resources-xlarge"); + resDirOrders.push_back("resources-large"); + resDirOrders.push_back("resources-medium"); + resDirOrders.push_back("resources-small"); + } + else if (screenSize.height > 720) + { + res = "large"; + resourceSize = CCSizeMake(640, 960); + resDirOrders.push_back("resources-large"); + resDirOrders.push_back("resources-medium"); + resDirOrders.push_back("resources-small"); + } + else if (screenSize.height > 480) + { + res = "medium"; + resourceSize = CCSizeMake(480, 720); + resDirOrders.push_back("resources-medium"); + resDirOrders.push_back("resources-small"); + } + else + { + res = "small"; + resourceSize = CCSizeMake(320, 480); + resDirOrders.push_back("resources-small"); + } + } + + CCFileUtils *pFileUtils = CCFileUtils::sharedFileUtils(); + pFileUtils->setSearchResolutionsOrder(resDirOrders); + + pDirector->setContentScaleFactor(resourceSize.width/designSize.width); + CCEGLView::sharedOpenGLView()->setDesignResolutionSize(designSize.width, designSize.height, kResolutionNoBorder); - + std::vector searchPaths = pFileUtils->getSearchPaths(); searchPaths.insert(searchPaths.begin(), pFileUtils->getWritablePath()); pFileUtils->setSearchPaths(searchPaths); diff --git a/samples/Javascript/CocosPlayer/Classes/AppDelegate.h b/samples/Javascript/CocosPlayer/Classes/AppDelegate.h index 86925ca8a7..3b272ae224 100644 --- a/samples/Javascript/CocosPlayer/Classes/AppDelegate.h +++ b/samples/Javascript/CocosPlayer/Classes/AppDelegate.h @@ -20,7 +20,7 @@ class AppDelegate : private cocos2d::CCApplication { public: - // bool isRetina = false, isIPhone = false; + bool isRetina, isIPhone; AppDelegate(); virtual ~AppDelegate(); @@ -46,11 +46,14 @@ public: }; - +bool runMainScene(); void handle_ccb_run(); void handle_ccb_stop(); void handle_connected(); void handle_disconnected(); void handle_set_orient(bool isPortrait); +void handle_set_message(const char *msg); +void handle_set_status(const char *msg); + #endif // _APP_DELEGATE_H_ diff --git a/samples/Javascript/CocosPlayer/Classes/CCBDirectoryComparer.h b/samples/Javascript/CocosPlayer/Classes/CCBDirectoryComparer.h new file mode 100644 index 0000000000..f351fa7b65 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/CCBDirectoryComparer.h @@ -0,0 +1,21 @@ +// +// CCBDirectoryComparer.h +// CocosBuilder +// +// Created by Viktor Lidholt on 2/5/13. +// +// + +#import + +@interface CCBDirectoryComparer : NSObject +{ +} + +@property (nonatomic,readonly) NSMutableDictionary* files; + +- (void) loadDirectory: (NSString*) dir; + +- (NSArray*) diffWithFiles:(NSDictionary*) diffFiles; + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/CCBDirectoryComparer.m b/samples/Javascript/CocosPlayer/Classes/CCBDirectoryComparer.m new file mode 100644 index 0000000000..e6147c557e --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/CCBDirectoryComparer.m @@ -0,0 +1,109 @@ +// +// CCBDirectoryComparer.m +// CocosBuilder +// +// Created by Viktor Lidholt on 2/5/13. +// +// + +#import "CCBDirectoryComparer.h" + +@implementation CCBDirectoryComparer + +- (id) init +{ + self = [super init]; + if (!self) return NULL; + + _files = [[NSMutableDictionary dictionary] retain]; + + return self; +} + +- (NSDate*) modificationDateForFile:(NSString*)file +{ + NSDictionary* attr = [[NSFileManager defaultManager] attributesOfItemAtPath:file error:NULL]; + return [attr objectForKey:NSFileModificationDate]; +} + +- (void) loadDirectory: (NSString*) dir subDir:(NSString*) subDir +{ + NSFileManager* fm = [NSFileManager defaultManager]; + + NSString* absDir = dir; + if (subDir) absDir = [dir stringByAppendingPathComponent:subDir]; + + NSArray* contents = [fm contentsOfDirectoryAtPath:absDir error:NULL]; + + for (NSString* file in contents) + { + NSString* absFile = [absDir stringByAppendingPathComponent:file]; + NSString* relFile = file; + if (subDir) relFile = [subDir stringByAppendingPathComponent:file]; + + BOOL isDir = NO; + if ([fm fileExistsAtPath:absFile isDirectory:&isDir]) + { + if (isDir) + { + // Go down in sub directory + NSString* subSubDir = file; + if (subDir) subSubDir = [subDir stringByAppendingPathComponent:file]; + [self loadDirectory:dir subDir:subSubDir]; + } + else + { + // Add file + NSDate* date = [self modificationDateForFile:absFile]; + + [_files setObject:date forKey:relFile]; + } + } + } +} + +- (void) loadDirectory: (NSString*) dir +{ + [_files removeAllObjects]; + [self loadDirectory:dir subDir: NULL]; +} + +// More approximate comparison of dates +- (BOOL) isEqualDate:(NSDate*) d1 to:(NSDate*) d2 +{ + NSTimeInterval delta = fabs([d1 timeIntervalSinceDate:d2]); + return (delta < 2.0); +} + +- (NSArray*) diffWithFiles:(NSDictionary*) diffFiles +{ + NSMutableArray* diff = [NSMutableArray array]; + + for (NSString* file in _files) + { + NSDate* fileDate = [_files objectForKey:file]; + + NSDate* diffFileDate = [diffFiles objectForKey:file]; + + if (diffFileDate && [self isEqualDate:fileDate to:diffFileDate]) + { + // Files are equal, there is no diff + continue; + } + + // Add to list of modified files + [diff addObject:file]; + + NSLog(@"MOD: %@ src: %@ dst: %@", file, fileDate, diffFileDate); + } + + return diff; +} + +- (void) dealloc +{ + [super dealloc]; + [_files release]; +} + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/Java_org_cocos2dx_cocosplayer_CocosPlayerSocket.cpp b/samples/Javascript/CocosPlayer/Classes/Java_org_cocos2dx_cocosplayer_CocosPlayerSocket.cpp index cf6f27dc59..b92c8b9c95 100644 --- a/samples/Javascript/CocosPlayer/Classes/Java_org_cocos2dx_cocosplayer_CocosPlayerSocket.cpp +++ b/samples/Javascript/CocosPlayer/Classes/Java_org_cocos2dx_cocosplayer_CocosPlayerSocket.cpp @@ -16,13 +16,19 @@ using namespace cocos2d; using namespace std; extern "C" { - void setPairingCodeJNI(int code) { - JniMethodInfo t; - if (JniHelper::getStaticMethodInfo(t, SOCKET_CLASS_NAME, "setPairingCode", "(I)V")) { + void updatePairing(const char *code) { + int pairingCode = 0; + if(strcmp(code, "Auto") == 0) { + pairingCode = -1; + } else { + pairingCode = atoi(code); + } + JniMethodInfo t; + if (JniHelper::getStaticMethodInfo(t, SOCKET_CLASS_NAME, "setPairingCode", "(I)V")) { t.env->CallStaticVoidMethod(t.classID, t.methodID, code); t.env->DeleteLocalRef(t.classID); - } - } + } + } void cleanCacheDirJNI() { JniMethodInfo t; @@ -41,4 +47,7 @@ extern "C" { t.env->DeleteLocalRef(t.classID); } } + const char *getCCBDirectoryPath() { + return ""; + } } diff --git a/samples/Javascript/CocosPlayer/Classes/Java_org_cocos2dx_cocosplayer_CocosPlayerSocket.h b/samples/Javascript/CocosPlayer/Classes/Java_org_cocos2dx_cocosplayer_CocosPlayerSocket.h index bb70bc9f39..ae833e8ebb 100644 --- a/samples/Javascript/CocosPlayer/Classes/Java_org_cocos2dx_cocosplayer_CocosPlayerSocket.h +++ b/samples/Javascript/CocosPlayer/Classes/Java_org_cocos2dx_cocosplayer_CocosPlayerSocket.h @@ -27,7 +27,7 @@ THE SOFTWARE. #include extern "C" { - extern void setPairingCodeJNI(int code); + extern void updatePairing(const char *code); extern void cleanCacheDirJNI(); extern void setDeviceResolutionJNI(const char* res); } diff --git a/samples/Javascript/CocosPlayer/Classes/MainSceneHelper.cpp b/samples/Javascript/CocosPlayer/Classes/MainSceneHelper.cpp index deef52ebc3..f3a210e9bf 100644 --- a/samples/Javascript/CocosPlayer/Classes/MainSceneHelper.cpp +++ b/samples/Javascript/CocosPlayer/Classes/MainSceneHelper.cpp @@ -4,84 +4,41 @@ CCMenuItemImage * CCBHelper::mBtnRun = NULL; CCMenuItemImage * CCBHelper::mBtnPair = NULL; CCMenuItemImage * CCBHelper::mBtnReset = NULL; -CCLabelTTF * CCBHelper::mLblStatus = NULL; -CCLabelTTF * CCBHelper::mLblPair = NULL; -CCLabelTTF * CCBHelper::mLblInstructions = NULL; - -std::string CCBHelper::mLblStatus_background = ""; -std::string CCBHelper::mLblPair_background = ""; -bool CCBHelper::mLblInstructions_visible = true; - - -void CCBHelper::setStatusObject(CCLabelTTF *status) { - if(mLblStatus == NULL) { - mLblStatus = CCLabelTTF::create(); - } - - status->retain(); - mLblStatus = status; - - if(mLblStatus_background != "") { - status->setString(mLblStatus_background.c_str()); - } -} - +std::string CCBHelper::mLblStatus_prev = ""; +std::string CCBHelper::mLblStatus_str = ""; +std::string CCBHelper::mLblInstructions_prev= ""; +std::string CCBHelper::mLblInstructions_str= ""; +std::string CCBHelper::mLblPair_prev = ""; +std::string CCBHelper::mLblPair_str = ""; +bool CCBHelper::gameAvailable = false; void CCBHelper::setStatusMessage(std::string str) { - if(mLblStatus == NULL) { - mLblStatus_background = str; - } else { - mLblStatus->setString(str.c_str()); - } + if(mLblStatus_prev.compare(str) != 0) { + mLblStatus_prev = str; + mLblStatus_str = str; + } } -void CCBHelper::setInstructionsObject(CCLabelTTF *status) { - if(mLblInstructions == NULL) { - mLblInstructions = CCLabelTTF::create(); - } - status->retain(); - mLblInstructions = status; - if(!mLblInstructions_visible) { - mLblInstructions->setVisible(false); - } +void CCBHelper::setInstructionsMessage(std::string str) { + if(mLblInstructions_prev.compare(str) != 0) { + mLblInstructions_prev = str; + mLblInstructions_str = str; + } } -void CCBHelper::setInstructionsMessage(bool isVisible) { - if(mLblInstructions == NULL) { - mLblInstructions_visible = isVisible; - } else { - mLblInstructions_visible = isVisible; - mLblInstructions->setVisible(isVisible); - } -} - -void CCBHelper::setPairObject(CCLabelTTF *pair) { - - if(mLblPair == NULL) { - mLblPair = CCLabelTTF::create(); - } - pair->retain(); - mLblPair = pair; - if(mLblPair_background != "") { - mLblPair->setString(mLblPair_background.c_str()); - } - -} void CCBHelper::setPairMessage(std::string str) { - if(mLblPair == NULL) { - mLblPair_background = str; - } else { - mLblPair->setString(str.c_str()); - } + if(mLblPair_prev.compare(str) != 0) { + mLblPair_prev = str; + mLblPair_str = str; + } +} + +bool CCBHelper::checkIsMainJSPresent() { + gameAvailable = CCFileUtils::sharedFileUtils()->isFileExist(CCFileUtils::sharedFileUtils()->fullPathForFilename("main.js")); } bool CCBHelper::isMainJSPresent() { - std::string path = CCFileUtils::sharedFileUtils()->fullPathForFilename("main.js"); - CCLOG("PATH RETURNED: %s", path.c_str()); - if(path == "") { - return false; - } - return true; + return gameAvailable; } diff --git a/samples/Javascript/CocosPlayer/Classes/MainSceneHelper.h b/samples/Javascript/CocosPlayer/Classes/MainSceneHelper.h index 3f5e4e717a..6e7f4f33a5 100644 --- a/samples/Javascript/CocosPlayer/Classes/MainSceneHelper.h +++ b/samples/Javascript/CocosPlayer/Classes/MainSceneHelper.h @@ -8,22 +8,16 @@ class CCBHelper { static CCMenuItemImage * mBtnRun; static CCMenuItemImage * mBtnReset; static CCMenuItemImage * mBtnPair; + static bool gameAvailable; + static std::string mLblStatus_prev, mLblStatus_str; + static std::string mLblPair_prev, mLblPair_str; + static std::string mLblInstructions_str, mLblInstructions_prev; - static CCLabelTTF *mLblStatus; - static std::string mLblStatus_background; - static CCLabelTTF *mLblPair; - static std::string mLblPair_background; - static CCLabelTTF *mLblInstructions; - static bool mLblInstructions_visible; - - static void setPairObject(CCLabelTTF *pair); - static void setPairMessage(std::string str); - - static void setInstructionsObject(CCLabelTTF *instr); - static void setInstructionsMessage(bool isVisible); - - static void setStatusObject(CCLabelTTF *status); - static void setStatusMessage(std::string str); - + static void setPairMessage(std::string str); + static void setInstructionsMessage(std::string msg); + static void setStatusMessage(std::string str); static bool isMainJSPresent(); + static bool checkIsMainJSPresent(); + + }; diff --git a/samples/Javascript/CocosPlayer/Classes/PlayerStatus.cpp b/samples/Javascript/CocosPlayer/Classes/PlayerStatus.cpp index db30ab72dd..7582e1ff1d 100644 --- a/samples/Javascript/CocosPlayer/Classes/PlayerStatus.cpp +++ b/samples/Javascript/CocosPlayer/Classes/PlayerStatus.cpp @@ -3,17 +3,18 @@ #include "PlayerStatusLoader.h" #include "MainSceneHelper.h" #include "AppDelegate.h" +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) #include "GUI/CCEditBox/CCEditBox.h" #include "jni/Java_org_cocos2dx_lib_Cocos2dxHelper.h" - +#endif USING_NS_CC; USING_NS_CC_EXT; PlayerStatus::PlayerStatus(): mBtnRun(NULL), mBtnReset(NULL), mBtnPair(NULL), - mLblStatus(NULL), mLblInstructions(NULL), mLblPair(NULL) + mLblStatus(NULL), mLblInstructions(NULL), mLblPair(NULL), editBox(NULL) { - + this->scheduleUpdate(); } PlayerStatus::~PlayerStatus() @@ -46,32 +47,57 @@ SEL_MenuHandler PlayerStatus::onResolveCCBCCMenuItemSelector(CCObject * pTarget, return NULL; } + void PlayerStatus::setDeviceResolution(std::string res) { setDeviceResolutionJNI(res.c_str()); } +void updatePairing(const char *pairing); + void editBoxCallbackFunc(const char* pText, void* ctx) { PlayerStatus *thiz = (PlayerStatus *)ctx; std::string text(pText); if(text == "" || text == " ") { thiz->mLblPair->setString("Auto"); - setPairingCodeJNI(-1); + updatePairing("Auto"); } else { thiz->mLblPair->setString(pText); - setPairingCodeJNI(atoi(pText)); + updatePairing(pText); } } void PlayerStatus::pressedPair(CCObject * pSender, cocos2d::extension::CCControlEvent pCCControlEvent) { - showEditTextDialogJNI("Enter pairing code", "", kEditBoxInputModeNumeric, kEditBoxInputFlagInitialCapsWord, - kKeyboardReturnTypeDone, 4, editBoxCallbackFunc, (void*)this); + TargetPlatform platform = CCApplication::sharedApplication()->getTargetPlatform(); +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + showEditTextDialogJNI("Enter pairing code", "", kEditBoxInputModeNumeric, kEditBoxInputFlagInitialCapsWord, + kKeyboardReturnTypeDone, 4, editBoxCallbackFunc, (void*)this); +#else + if(!this->editBox) { + this->editBox = CCEditBox::create(CCSize(150, 50), CCScale9Sprite::create("green_edit.png")); + PairingDelegate *p = new PairingDelegate(); + p->setTarget(this); + CCPoint visibleOrigin = CCEGLView::sharedOpenGLView()->getVisibleOrigin(); + CCSize visibleSize = CCEGLView::sharedOpenGLView()->getVisibleSize(); + + editBox->setPosition(ccp(visibleOrigin.x+visibleSize.width/2, visibleOrigin.y+visibleSize.height*1/2)); + editBox->setDelegate(p); + editBox->setPlaceHolder("Enter Pairing Code"); + editBox->setPlaceholderFontColor(ccRED); + editBox->setFont("arial", 15); + editBox->setMaxLength(4); + editBox->setReturnType(kKeyboardReturnTypeDone); + this->addChild(editBox); + } else { + this->editBox->setVisible(true); + } +#endif } + void PlayerStatus::pressedReset(CCObject * pSender, cocos2d::extension::CCControlEvent pCCControlEvent) { cleanCacheDirJNI(); - this->mBtnRun->setEnabled(false); - this->mBtnReset->setEnabled(false); + CCBHelper::checkIsMainJSPresent(); } @@ -82,54 +108,33 @@ void PlayerStatus::pressedRun(CCObject * pSender, cocos2d::extension::CCControlE bool PlayerStatus::onAssignCCBMemberVariable(CCObject * pTarget, const char * pMemberVariableName, CCNode * pNode) { + CCB_MEMBERVARIABLEASSIGNER_GLUE(this, "btnRun", CCMenuItemImage *, this->mBtnRun); - if(strcmp(pMemberVariableName, "btnRun")) { - if(this->mBtnRun == NULL) { - this->mBtnRun = CCMenuItemImage::create(); - } - if(CCBHelper::isMainJSPresent()) { - this->mBtnRun->setEnabled(true); - } else { - this->mBtnRun->setEnabled(false); - } - } - - CCB_MEMBERVARIABLEASSIGNER_GLUE(this, "btnReset", CCMenuItemImage *, this->mBtnReset); - - if(strcmp(pMemberVariableName, "btnReset")) { - if(this->mBtnReset == NULL) { - this->mBtnReset = CCMenuItemImage::create(); - } - if(CCBHelper::isMainJSPresent()) { - this->mBtnReset->setEnabled(true); - } else { - this->mBtnReset->setEnabled(false); - } - } - CCB_MEMBERVARIABLEASSIGNER_GLUE(this, "btnPair", CCMenuItemImage *, this->mBtnPair); - CCB_MEMBERVARIABLEASSIGNER_GLUE(this, "lblStatus", CCLabelTTF *, this->mLblStatus); - if(strcmp(pMemberVariableName, "lblStatus") && this->mLblStatus != NULL) { - CCBHelper::setStatusObject(this->mLblStatus); - } - CCB_MEMBERVARIABLEASSIGNER_GLUE(this, "lblPair", CCLabelTTF *, this->mLblPair); - if(strcmp(pMemberVariableName, "lblPair") && this->mLblPair != NULL) { - CCBHelper::setPairObject(this->mLblPair); - } - CCB_MEMBERVARIABLEASSIGNER_GLUE(this, "lblInstructions", CCLabelTTF *, this->mLblInstructions); - if(strcmp(pMemberVariableName, "lblInstructions") && this->mLblInstructions != NULL) { - CCBHelper::setInstructionsObject(this->mLblInstructions); - } - return false; } +void PlayerStatus::update(float dt) { + if(this->mLblInstructions != NULL && CCBHelper::mLblInstructions_str != "") { + this->mLblInstructions->setString(CCBHelper::mLblInstructions_str.c_str()); + } + if(this->mLblStatus != NULL && CCBHelper::mLblStatus_str != "") { + this->mLblStatus->setString(CCBHelper::mLblStatus_str.c_str()); + } + if(CCBHelper::isMainJSPresent() && this->mBtnRun != NULL && this->mBtnReset != NULL) { + this->mBtnRun->setEnabled(true); + this->mBtnReset->setEnabled(true); + } else if(this->mBtnRun != NULL && this->mBtnReset != NULL) { + this->mBtnRun->setEnabled(false); + this->mBtnReset->setEnabled(false); + } +} -void PlayerStatus::loadMainScene(const char *pCCBFileName) { +cocos2d::CCScene* PlayerStatus::loadMainScene(const char *pCCBFileName) { CCNodeLoaderLibrary * ccNodeLoaderLibrary = CCNodeLoaderLibrary::newDefaultCCNodeLoaderLibrary(); ccNodeLoaderLibrary->registerCCNodeLoader("PlayerStatusLayer", PlayerStatusLoader::loader()); @@ -149,12 +154,7 @@ void PlayerStatus::loadMainScene(const char *pCCBFileName) { if(node != NULL) { scene->addChild(node); } - - /* Push the new scene with a fancy transition. */ - ccColor3B transitionColor; - transitionColor.r = 0; - transitionColor.g = 0; - transitionColor.b = 0; - - CCDirector::sharedDirector()->runWithScene(CCTransitionFade::create(0.5f, scene, transitionColor)); -} + CCBHelper::checkIsMainJSPresent(); + return scene; + + } diff --git a/samples/Javascript/CocosPlayer/Classes/PlayerStatus.h b/samples/Javascript/CocosPlayer/Classes/PlayerStatus.h index fe701e878c..5d8948e156 100644 --- a/samples/Javascript/CocosPlayer/Classes/PlayerStatus.h +++ b/samples/Javascript/CocosPlayer/Classes/PlayerStatus.h @@ -16,7 +16,22 @@ * This thread describes the problem: * http://www.cocoabuilder.com/archive/xcode/265549-crash-in-virtual-method-call.html */ +void editBoxCallbackFunc(const char* pText, void* ctx); +class PairingDelegate: public cocos2d::extension::CCEditBoxDelegate { +private: + void *m_Target; +public: + + void setTarget(void *target) { + m_Target = target; + } + + virtual void editBoxReturn(cocos2d::extension::CCEditBox* editBox) { + editBoxCallbackFunc(editBox->getText(), m_Target); + editBox->setVisible(false); + } +}; class PlayerStatus : public cocos2d::CCLayer @@ -30,8 +45,6 @@ public: PlayerStatus(); virtual ~PlayerStatus(); - void openTest(const char * pCCBFileName, const char * pCCNodeName = NULL, cocos2d::extension::CCNodeLoader * pCCNodeLoader = NULL); - virtual cocos2d::SEL_MenuHandler onResolveCCBCCMenuItemSelector(cocos2d::CCObject * pTarget, const char * pSelectorName); virtual cocos2d::extension::SEL_CCControlHandler onResolveCCBCCControlSelector(cocos2d::CCObject * pTarget, const char * pSelectorName); virtual bool onAssignCCBMemberVariable(cocos2d::CCObject * pTarget, const char * pMemberVariableName, cocos2d::CCNode * pNode); @@ -40,7 +53,7 @@ public: void pressedPair(CCObject * pSender, cocos2d::extension::CCControlEvent pCCControlEvent); void pressedReset(CCObject * pSender, cocos2d::extension::CCControlEvent pCCControlEvent); void pressedRun(CCObject * pSender, cocos2d::extension::CCControlEvent pCCControlEvent); - static void loadMainScene(const char *fileName); + static cocos2d::CCScene* loadMainScene(const char *fileName); static void setDeviceResolution(std::string res); cocos2d::CCMenuItemImage* mBtnRun; @@ -50,6 +63,9 @@ public: cocos2d::CCLabelTTF* mLblStatus; cocos2d::CCLabelTTF* mLblInstructions; cocos2d::CCLabelTTF* mLblPair; + virtual void update(float dt); +private: + cocos2d::extension::CCEditBox *editBox; }; diff --git a/samples/Javascript/CocosPlayer/Classes/ServerController.h b/samples/Javascript/CocosPlayer/Classes/ServerController.h new file mode 100644 index 0000000000..d100c16759 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/ServerController.h @@ -0,0 +1,99 @@ +/* + * CocosBuilder: http://www.cocosbuilder.com + * + * Copyright (c) 2012 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import "ThoMoServerStub.h" +#import "cocos2d.h" + +// Network status states +typedef enum { + kCCBNetworkUninitialized = -1, + kCCBNetworkStatusWaiting, + kCCBNetworkStatusTooMany, + kCCBNetworkStatusConnected, + kCCBNetworkStatusShutDown, +} CCBNetworkStatus; + +// Player status states +typedef enum { + kCCBPlayerStatuskUninitialized = -1, + kCCBPlayerStatusIdle, + kCCBPlayerStatusPlay, + kCCBPlayerStatusUnzip, + kCCBPlayerStatusStop, + kCCBPlayerStatusNotConnected, + kCCBPlayerStatusExecuteScript, +} CCBPlayerStatus; + +// Predefined messages +extern NSString *kCCBNetworkStatusStringWaiting; +extern NSString *kCCBNetworkStatusStringTooMany; +extern NSString *kCCBNetworkStatusStringConnected; +extern NSString *kCCBNetworkStatusStringShutDown; + +extern NSString *kCCBPlayerStatusStringNotConnected; +extern NSString *kCCBPlayerStatusStringIdle; +extern NSString *kCCBPlayerStatusStringUnzip; +extern NSString *kCCBPlayerStatusStringStop; +extern NSString *kCCBPlayerStatusStringPlay; +extern NSString *kCCBPlayerStatusStringScript; + +@interface ServerController : NSObject +{ + ThoMoServerStub* server; + + NSMutableSet* connectedClients; + + NSFileHandle* pipeReadHandle; + + CCBNetworkStatus networkStatus; + CCBPlayerStatus playerStatus; + BOOL playerWindowDisplayed; +} + +/** Network status: who is the network connection */ +@property (nonatomic, readwrite) CCBNetworkStatus networkStatus; + +/** State of the player: playing, unzipping, stopping, etc. */ +@property (nonatomic, readwrite) CCBPlayerStatus playerStatus; + +@property (nonatomic, readwrite) BOOL playerWindowDisplayed; +@property (nonatomic, readwrite) BOOL isRetina; +@property (nonatomic, readwrite) BOOL isIPhone; + + +@property (nonatomic,copy) NSString* serverStatus; + +- (void) start; +- (void) stop; +- (void) setPairingCode: (NSString *)code; +- (void) startIfNotStarted; +- (void) updatePairing; + +- (void) sendDeviceName; +- (void) sendResultString:(NSString*) str; +- (void) sendLog:(NSString*)log; +- (void) sendFileList; + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/ServerController.mm b/samples/Javascript/CocosPlayer/Classes/ServerController.mm new file mode 100644 index 0000000000..90dcc0427b --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/ServerController.mm @@ -0,0 +1,607 @@ +/* + * CocosBuilder: http://www.cocosbuilder.com + * + * Copyright (c) 2012 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import "ServerController.h" +#import "js_bindings_core.h" +#import "CCBReader.h" +#include "PlayerStatus.h" +#include "AppDelegate.h" +#import "CCBDirectoryComparer.h" +#import "SSZipArchive.h" + +// Predefined messages +NSString *kCCBNetworkStatusStringWaiting = @"Waiting for connections"; +NSString *kCCBNetworkStatusStringTooMany = @"Too many connections"; +NSString *kCCBNetworkStatusStringConnected = @"Connected"; +NSString *kCCBNetworkStatusStringShutDown = @"Server shut down"; + +NSString *kCCBPlayerStatusStringNotConnected = @"Connect by running CocosBuilder on the same local wireless network as CocosPlayer.\nIf multiple instances of CocosBuilder is run on the same network, use a unique pairing code."; +NSString *kCCBPlayerStatusStringIdle = @"Idle"; +NSString *kCCBPlayerStatusStringUnzip = @"Action: Unzip game"; +NSString *kCCBPlayerStatusStringStop = @"Action: Stop"; +NSString *kCCBPlayerStatusStringPlay = @"Action: Run"; +NSString *kCCBPlayerStatusStringScript = @"Action: Executing script"; + + +@implementation ServerController + +@synthesize networkStatus, playerStatus, playerWindowDisplayed, isRetina, isIPhone; + +#pragma mark Initializers and setup + +- (NSString*) protocolIdentifier +{ + NSString* pairing = [[NSUserDefaults standardUserDefaults] objectForKey:@"pairing"]; + + if (pairing) + { + return [NSString stringWithFormat:@"CocosP-%@",pairing]; + } + else + { + return @"CocosPlayer"; + } +} + +- (id) init +{ + self = [super init]; + if (!self) return NULL; + + connectedClients = [[NSMutableSet alloc] init]; + + server = [[ThoMoServerStub alloc] initWithProtocolIdentifier:[self protocolIdentifier]]; + [server setDelegate:self]; + + networkStatus = kCCBNetworkUninitialized; + playerStatus = kCCBPlayerStatuskUninitialized; + playerWindowDisplayed = YES; + + return self; +} + +#pragma mark Redirection of std out + +- (void) redirectStdErr +{ + NSPipe* pipe = [NSPipe pipe]; + pipeReadHandle = [pipe fileHandleForReading]; + + [pipeReadHandle readInBackgroundAndNotify]; + + int err = dup2([[pipe fileHandleForWriting] fileDescriptor], STDERR_FILENO); + if (!err) NSLog(@"ConsoleWindow: Failed to redirect stderr"); + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(readData:) name:NSFileHandleReadCompletionNotification object:pipeReadHandle]; + + [pipeReadHandle retain]; +} + +- (void) readData:(NSNotification*)notification +{ + [pipeReadHandle readInBackgroundAndNotify] ; + NSString *str = [[NSString alloc] initWithData: [[notification userInfo] objectForKey: NSFileHandleNotificationDataItem] encoding: NSASCIIStringEncoding] ; + [self sendLog:str]; +} + +#pragma mark Control methods + +- (void) start +{ + if (server) + { + [server start]; + + // Redirect std out + [self redirectStdErr]; + } +} + +- (void) startIfNotStarted +{ + if (!server) + { + server = [[ThoMoServerStub alloc] initWithProtocolIdentifier:[self protocolIdentifier]]; + [server setDelegate:self]; + [server start]; + + self.networkStatus = kCCBNetworkStatusWaiting; + } +} + +- (void) stop +{ + if (server) + { + self.networkStatus = kCCBNetworkStatusShutDown; + //[[[PlayerStatusLayer sharedInstance] lblInstructions] setString:kCCBPlayerStatusStringStop]; + handle_ccb_stop(); + [server stop]; + [server release]; + server = NULL; + [connectedClients removeAllObjects]; + } +} + +- (void) updatePairing +{ + // Stop old server + [server stop]; + [server release]; + server = NULL; + [connectedClients removeAllObjects]; + + // Start new server + server = [[ThoMoServerStub alloc] initWithProtocolIdentifier:[self protocolIdentifier]]; + [server setDelegate:self]; + [server start]; + + self.networkStatus = kCCBNetworkStatusWaiting; +} + +#pragma mark Helper methods + +- (void) executeJavaScript:(NSString*)script +{ + self.playerStatus = kCCBPlayerStatusExecuteScript; + +// NSThread *cocos2dThread = [[CCDirector sharedDirector] runningThread]; +// +// [cocos2dThread performBlock:^(void) { +// NSString * string = @"None\n"; +// jsval out; +// BOOL success = [[JSBCore sharedInstance] evalString:script outVal:&out]; +// +// if(success) +// { +// /* +// if(JSVAL_IS_BOOLEAN(out)) +// { +// string = [NSString stringWithFormat:@"Result(bool): %@.\n", (JSVAL_TO_BOOLEAN(out)) ? @"true" : @"false"]; +// } +// else if(JSVAL_IS_INT(out)) +// { +// string = [NSString stringWithFormat:@"Result(int): %i.\n", JSVAL_TO_INT(out)]; +// } +// else if(JSVAL_IS_DOUBLE(out)) +// { +// string = [NSString stringWithFormat:@"Result(double): %d.\n", JSVAL_TO_DOUBLE(out)]; +// } +// else if(JSVAL_IS_STRING(out)) { +// NSString *tmp; +// jsval_to_nsstring( [[ScriptingCore sharedInstance] globalContext], out, &tmp ); +// string = [NSString stringWithFormat:@"Result(string): %d.\n", tmp]; +// } +// else if (JSVAL_IS_VOID(out) ) +// string = @"Result(void):\n"; +// else if (JSVAL_IS_OBJECT(out) ) +// string = @"Result(object):\n"; +// */ +// string = @"Success\n"; +// } +// else +// { +// string = [NSString stringWithFormat:@"Error evaluating script:\n#############################\n%@\n#############################\n", script]; +// } +// +// //[self sendResultString:string]; +// } +// waitUntilDone:NO]; +} + +- (void) listDirectory:(NSString*)dir prefix:(NSString*)prefix +{ + NSArray* files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:dir error:NULL]; + for (NSString* file in files) + { + NSLog(@"%@%@", prefix, file); + + BOOL isDir = NO; + if ([[NSFileManager defaultManager] fileExistsAtPath:[dir stringByAppendingPathComponent:file] isDirectory:&isDir] && isDir) + { + [self listDirectory:[dir stringByAppendingPathComponent:file] prefix:[prefix stringByAppendingString:@" "]]; + } + } +} + +- (void) extractZipData:(NSData*)data +{ + self.playerStatus = kCCBPlayerStatusUnzip; + + id runBlock = ^(void) { + + std::string path = cocos2d::CCFileUtils::sharedFileUtils()->getWritablePath(); + + NSString *writeablePath = [NSString stringWithCString:path.c_str() encoding:NSASCIIStringEncoding]; + + // NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); + NSString* dirPath = [writeablePath stringByAppendingPathComponent:@"ccb"]; + + NSString* zipPath = [dirPath stringByAppendingPathComponent:@"ccb.zip"]; + + BOOL isDirectory = NO; + if (![[NSFileManager defaultManager] fileExistsAtPath:dirPath isDirectory:&isDirectory]) + { + [[NSFileManager defaultManager] createDirectoryAtPath:dirPath withIntermediateDirectories:YES attributes:NULL error:NULL]; + } + + if(![data writeToFile:zipPath atomically:YES]) + { + NSLog(@"CocosPlayer: Failed to write zip file"); + return; + } + + if(![SSZipArchive unzipFileAtPath:zipPath toDestination:dirPath overwrite:YES password:NULL error:NULL]) { + NSLog(@"CocosPlayer: Failed to unzip resources"); + } + + [self listDirectory:dirPath prefix:@""]; + + // Send updated list of files on device + [self sendFileList]; + }; + + double delayInSeconds = 0.01; + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); + dispatch_after(popTime, dispatch_get_main_queue(), runBlock); +} + +-(void) stopJSApp +{ + if( ! playerWindowDisplayed ) { + //[[AppController appController] stopJSApp]; + playerWindowDisplayed = YES; + } +} + +-(void) runJSApp +{ + handle_ccb_run(); + //[[AppController appController] runJSApp]; + playerWindowDisplayed = NO; +} + +- (void) stopMain +{ + if( ! playerWindowDisplayed ) { + self.playerStatus = kCCBPlayerStatusStop; + +// NSThread *cocos2dThread = [[CCDirector sharedDirector] runningThread]; +// +// [cocos2dThread performBlock:^(void) { +// [self stopJSApp]; +// } waitUntilDone:YES]; +// + // Force update network status + + handle_ccb_stop(); + + CCBNetworkStatus tmp = networkStatus; + networkStatus = kCCBNetworkUninitialized; + self.networkStatus = tmp; + } +} + +- (void) runMain +{ + double delayInSeconds = 0.05; + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); + dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ + self.playerStatus = kCCBPlayerStatusPlay; + [self runJSApp]; + }); + +} + +#pragma mark Server callbacks + +- (void) server:(ThoMoServerStub *)theServer acceptedConnectionFromClient:(NSString *)aClientIdString +{ + [connectedClients addObject:aClientIdString]; + + if (connectedClients.count == 1) + { + self.networkStatus = kCCBNetworkStatusConnected; + [self sendDeviceName]; + [self sendFileList]; + } + else + { + self.networkStatus = kCCBNetworkStatusTooMany; + } +} + +- (void)server:(ThoMoServerStub *)theServer lostConnectionToClient:(NSString *)aClientIdString errorMessage:(NSString *)errorMessage +{ + [connectedClients removeObject:aClientIdString]; + + if (connectedClients.count == 0) + { + self.networkStatus = kCCBNetworkStatusWaiting; + } + else if (connectedClients.count == 1) + { + self.networkStatus = kCCBNetworkStatusConnected; + } + else + { + self.networkStatus = kCCBNetworkStatusTooMany; + } +} + +- (void)serverDidShutDown:(ThoMoServerStub *)theServer +{ + self.networkStatus = kCCBNetworkStatusWaiting; + + if( server == theServer || !server) { + [server release]; + server = NULL; + [connectedClients removeAllObjects]; + + [self startIfNotStarted]; + } +} + +- (void)netServiceProblemEncountered:(NSString *)errorMessage onServer:(ThoMoServerStub *)theServer +{ + if( server == theServer ) { + [server stop]; + [server release]; + server = NULL; + [connectedClients removeAllObjects]; + } +} + +- (void) server:(ThoMoServerStub *)theServer didReceiveData:(id)theData fromClient:(NSString *)aClientIdString +{ + if (connectedClients.count != 1) return; + + NSDictionary* msg = theData; + + NSString* cmd = [msg objectForKey:@"cmd"]; + + if ([cmd isEqualToString:@"script"]) + { + NSString* script = [msg objectForKey:@"script"]; + [self executeJavaScript:script]; + } + else if ([cmd isEqualToString:@"run"]) + { + [self runMain]; + } + else if ([cmd isEqualToString:@"stop"]) + { + [self stopMain]; + } + else if ([cmd isEqualToString:@"zip"]) + { + NSData* zipData = [msg objectForKey:@"data"]; + + // Extract zip file received from CocosBuilder + [self extractZipData:zipData]; + } + else if ([cmd isEqualToString:@"settings"]) + { + NSArray* arr = [msg objectForKey:@"orientations"]; + + NSUInteger orientations = 0; + + if ([[arr objectAtIndex:0] boolValue]) orientations |= UIInterfaceOrientationMaskPortrait; + if ([[arr objectAtIndex:1] boolValue]) orientations |= UIInterfaceOrientationMaskPortraitUpsideDown; + if ([[arr objectAtIndex:2] boolValue]) orientations |= UIInterfaceOrientationMaskLandscapeLeft; + if ([[arr objectAtIndex:3] boolValue]) orientations |= UIInterfaceOrientationMaskLandscapeRight; + + //[AppController appController].deviceOrientations = orientations; + } +} + +#pragma mark Server/Player status + +-(void) setNetworkStatus:(CCBNetworkStatus)aNetworkStatus +{ + if( networkStatus != aNetworkStatus ) { + networkStatus = aNetworkStatus; + + //PlayerStatusLayer *statusLayer = [PlayerStatusLayer sharedInstance]; + switch (networkStatus) { + case kCCBNetworkStatusConnected: + if( playerWindowDisplayed) + handle_set_status((const char *)[kCCBNetworkStatusStringConnected cStringUsingEncoding:NSASCIIStringEncoding]); + + self.playerStatus = kCCBPlayerStatusIdle; + break; + case kCCBNetworkStatusShutDown: + if( playerWindowDisplayed) + handle_set_status((const char *)[kCCBNetworkStatusStringShutDown cStringUsingEncoding:NSASCIIStringEncoding]); + + self.playerStatus = kCCBPlayerStatusNotConnected; + break; + case kCCBNetworkStatusTooMany: + if( playerWindowDisplayed) + handle_set_status((const char *)[kCCBNetworkStatusStringWaiting cStringUsingEncoding:NSASCIIStringEncoding]); + + [self stopJSApp]; + self.playerStatus = kCCBPlayerStatusNotConnected; + break; + case kCCBNetworkStatusWaiting: + if( playerWindowDisplayed) + handle_set_status((const char *)[kCCBNetworkStatusStringWaiting cStringUsingEncoding:NSASCIIStringEncoding]); + + self.playerStatus = kCCBPlayerStatusNotConnected; + [self stopJSApp]; + break; + + default: + break; + } + } +} + +-(void) setPlayerStatus:(CCBPlayerStatus)aPlayerStatus +{ + if( playerStatus != aPlayerStatus) { + playerStatus = aPlayerStatus; + + //PlayerStatusLayer *statusLayer = [PlayerStatusLayer sharedInstance]; + + switch (playerStatus) { + case kCCBPlayerStatusExecuteScript: + if( playerWindowDisplayed) { + handle_set_message((const char *)[kCCBPlayerStatusStringScript cStringUsingEncoding:NSASCIIStringEncoding]); + } + break; + case kCCBPlayerStatusPlay: + if( playerWindowDisplayed) + handle_set_message((const char *)[kCCBPlayerStatusStringPlay cStringUsingEncoding:NSASCIIStringEncoding]); + + break; + case kCCBPlayerStatusStop: + if( playerWindowDisplayed) + handle_set_message((const char *)[kCCBPlayerStatusStringStop cStringUsingEncoding:NSASCIIStringEncoding]); + break; + case kCCBPlayerStatusUnzip: + if( playerWindowDisplayed) + handle_set_message((const char *)[kCCBPlayerStatusStringUnzip cStringUsingEncoding:NSASCIIStringEncoding]); + break; + case kCCBPlayerStatusIdle: + if( playerWindowDisplayed) + handle_set_message((const char *)[kCCBPlayerStatusStringIdle cStringUsingEncoding:NSASCIIStringEncoding]); + break; + case kCCBPlayerStatusNotConnected: + if( playerWindowDisplayed) + handle_set_message((const char *)[kCCBPlayerStatusStringNotConnected cStringUsingEncoding:NSASCIIStringEncoding]); + break; + + default: + break; + } + } + +} + +#pragma mark Sending messages + +- (void) sendMessage:(NSDictionary*) msg +{ + if (connectedClients.count == 1) + { + [server sendToAllClients:msg]; + } +} + +- (NSString*) getUUID +{ + // Check user defaults + NSString* uuid = [[NSUserDefaults standardUserDefaults] objectForKey:@"uuid"]; + if (uuid) return uuid; + + // Generate UUID + CFUUIDRef uuidObject = CFUUIDCreate(kCFAllocatorDefault); + uuid = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, uuidObject); + CFRelease(uuidObject); + + // Store generated id + [[NSUserDefaults standardUserDefaults] setObject:uuid forKey:@"uuid"]; + + return uuid; +} + +- (void) sendDeviceName +{ + NSMutableDictionary* msg = [NSMutableDictionary dictionary]; + [msg setObject:@"deviceinfo" forKey:@"cmd"]; + [msg setObject:[[UIDevice currentDevice] name] forKey:@"devicename"]; + //[msg setObject:[AppController appController].deviceType forKey:@"devicetype"]; + if(self.isIPhone) + { + [msg setObject:@"iPhone" forKey:@"devicetype"]; + } + else + { + [msg setObject:@"iPad" forKey:@"devicetype"]; + } + [msg setObject:[NSNumber numberWithBool:self.isRetina] forKey:@"retinadisplay"]; + [msg setObject:[self getUUID] forKey:@"uuid"]; + + [self sendMessage:msg]; + +} + +- (void) sendResultString:(NSString*) str +{ + NSMutableDictionary* msg = [NSMutableDictionary dictionary]; + [msg setObject:@"result" forKey:@"cmd"]; + [msg setObject:str forKey:@"result"]; + + [self sendMessage:msg]; +} + +- (void) sendLog:(NSString*)log +{ + NSMutableDictionary* msg = [NSMutableDictionary dictionary]; + [msg setObject:@"log" forKey:@"cmd"]; + [msg setObject:log forKey:@"string"]; + + [self sendMessage:msg]; +} + +- (void) sendFileList +{ + // Get the contents of the CCB working directory, with files + CCBDirectoryComparer* dc = [[[CCBDirectoryComparer alloc] init] autorelease]; + std::string path = cocos2d::CCFileUtils::sharedFileUtils()->getWritablePath(); + + NSString *writeablePath = [NSString stringWithCString:path.c_str() encoding:NSASCIIStringEncoding]; + + // NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); + NSString* dirPath = [writeablePath stringByAppendingPathComponent:@"ccb"]; + +// NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); +// NSString* dirPath = [[searchPaths objectAtIndex:0] stringByAppendingPathComponent:@"ccb"]; + [dc loadDirectory:dirPath]; + NSDictionary* dirFiles = dc.files; + + // Send message + NSMutableDictionary* msg = [NSMutableDictionary dictionary]; + [msg setObject:@"filelist" forKey:@"cmd"]; + [msg setObject:dirFiles forKey:@"filelist"]; + + [self sendMessage:msg]; + for (id key in msg) { + NSLog(@"key: %@, value: %@", key, [msg objectForKey:key]); + + } +} + +#pragma mark Common + +- (void) dealloc +{ + [server release]; + [connectedClients release]; + + [super dealloc]; +} + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/CCBDirectoryComparer.h b/samples/Javascript/CocosPlayer/Classes/iOS/CCBDirectoryComparer.h new file mode 100644 index 0000000000..f351fa7b65 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/CCBDirectoryComparer.h @@ -0,0 +1,21 @@ +// +// CCBDirectoryComparer.h +// CocosBuilder +// +// Created by Viktor Lidholt on 2/5/13. +// +// + +#import + +@interface CCBDirectoryComparer : NSObject +{ +} + +@property (nonatomic,readonly) NSMutableDictionary* files; + +- (void) loadDirectory: (NSString*) dir; + +- (NSArray*) diffWithFiles:(NSDictionary*) diffFiles; + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/CCBDirectoryComparer.m b/samples/Javascript/CocosPlayer/Classes/iOS/CCBDirectoryComparer.m new file mode 100644 index 0000000000..e6147c557e --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/CCBDirectoryComparer.m @@ -0,0 +1,109 @@ +// +// CCBDirectoryComparer.m +// CocosBuilder +// +// Created by Viktor Lidholt on 2/5/13. +// +// + +#import "CCBDirectoryComparer.h" + +@implementation CCBDirectoryComparer + +- (id) init +{ + self = [super init]; + if (!self) return NULL; + + _files = [[NSMutableDictionary dictionary] retain]; + + return self; +} + +- (NSDate*) modificationDateForFile:(NSString*)file +{ + NSDictionary* attr = [[NSFileManager defaultManager] attributesOfItemAtPath:file error:NULL]; + return [attr objectForKey:NSFileModificationDate]; +} + +- (void) loadDirectory: (NSString*) dir subDir:(NSString*) subDir +{ + NSFileManager* fm = [NSFileManager defaultManager]; + + NSString* absDir = dir; + if (subDir) absDir = [dir stringByAppendingPathComponent:subDir]; + + NSArray* contents = [fm contentsOfDirectoryAtPath:absDir error:NULL]; + + for (NSString* file in contents) + { + NSString* absFile = [absDir stringByAppendingPathComponent:file]; + NSString* relFile = file; + if (subDir) relFile = [subDir stringByAppendingPathComponent:file]; + + BOOL isDir = NO; + if ([fm fileExistsAtPath:absFile isDirectory:&isDir]) + { + if (isDir) + { + // Go down in sub directory + NSString* subSubDir = file; + if (subDir) subSubDir = [subDir stringByAppendingPathComponent:file]; + [self loadDirectory:dir subDir:subSubDir]; + } + else + { + // Add file + NSDate* date = [self modificationDateForFile:absFile]; + + [_files setObject:date forKey:relFile]; + } + } + } +} + +- (void) loadDirectory: (NSString*) dir +{ + [_files removeAllObjects]; + [self loadDirectory:dir subDir: NULL]; +} + +// More approximate comparison of dates +- (BOOL) isEqualDate:(NSDate*) d1 to:(NSDate*) d2 +{ + NSTimeInterval delta = fabs([d1 timeIntervalSinceDate:d2]); + return (delta < 2.0); +} + +- (NSArray*) diffWithFiles:(NSDictionary*) diffFiles +{ + NSMutableArray* diff = [NSMutableArray array]; + + for (NSString* file in _files) + { + NSDate* fileDate = [_files objectForKey:file]; + + NSDate* diffFileDate = [diffFiles objectForKey:file]; + + if (diffFileDate && [self isEqualDate:fileDate to:diffFileDate]) + { + // Files are equal, there is no diff + continue; + } + + // Add to list of modified files + [diff addObject:file]; + + NSLog(@"MOD: %@ src: %@ dst: %@", file, fileDate, diffFileDate); + } + + return diff; +} + +- (void) dealloc +{ + [super dealloc]; + [_files release]; +} + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ServerController.h b/samples/Javascript/CocosPlayer/Classes/iOS/ServerController.h new file mode 100644 index 0000000000..d100c16759 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ServerController.h @@ -0,0 +1,99 @@ +/* + * CocosBuilder: http://www.cocosbuilder.com + * + * Copyright (c) 2012 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import "ThoMoServerStub.h" +#import "cocos2d.h" + +// Network status states +typedef enum { + kCCBNetworkUninitialized = -1, + kCCBNetworkStatusWaiting, + kCCBNetworkStatusTooMany, + kCCBNetworkStatusConnected, + kCCBNetworkStatusShutDown, +} CCBNetworkStatus; + +// Player status states +typedef enum { + kCCBPlayerStatuskUninitialized = -1, + kCCBPlayerStatusIdle, + kCCBPlayerStatusPlay, + kCCBPlayerStatusUnzip, + kCCBPlayerStatusStop, + kCCBPlayerStatusNotConnected, + kCCBPlayerStatusExecuteScript, +} CCBPlayerStatus; + +// Predefined messages +extern NSString *kCCBNetworkStatusStringWaiting; +extern NSString *kCCBNetworkStatusStringTooMany; +extern NSString *kCCBNetworkStatusStringConnected; +extern NSString *kCCBNetworkStatusStringShutDown; + +extern NSString *kCCBPlayerStatusStringNotConnected; +extern NSString *kCCBPlayerStatusStringIdle; +extern NSString *kCCBPlayerStatusStringUnzip; +extern NSString *kCCBPlayerStatusStringStop; +extern NSString *kCCBPlayerStatusStringPlay; +extern NSString *kCCBPlayerStatusStringScript; + +@interface ServerController : NSObject +{ + ThoMoServerStub* server; + + NSMutableSet* connectedClients; + + NSFileHandle* pipeReadHandle; + + CCBNetworkStatus networkStatus; + CCBPlayerStatus playerStatus; + BOOL playerWindowDisplayed; +} + +/** Network status: who is the network connection */ +@property (nonatomic, readwrite) CCBNetworkStatus networkStatus; + +/** State of the player: playing, unzipping, stopping, etc. */ +@property (nonatomic, readwrite) CCBPlayerStatus playerStatus; + +@property (nonatomic, readwrite) BOOL playerWindowDisplayed; +@property (nonatomic, readwrite) BOOL isRetina; +@property (nonatomic, readwrite) BOOL isIPhone; + + +@property (nonatomic,copy) NSString* serverStatus; + +- (void) start; +- (void) stop; +- (void) setPairingCode: (NSString *)code; +- (void) startIfNotStarted; +- (void) updatePairing; + +- (void) sendDeviceName; +- (void) sendResultString:(NSString*) str; +- (void) sendLog:(NSString*)log; +- (void) sendFileList; + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ServerController.mm b/samples/Javascript/CocosPlayer/Classes/iOS/ServerController.mm new file mode 100644 index 0000000000..90dcc0427b --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ServerController.mm @@ -0,0 +1,607 @@ +/* + * CocosBuilder: http://www.cocosbuilder.com + * + * Copyright (c) 2012 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import "ServerController.h" +#import "js_bindings_core.h" +#import "CCBReader.h" +#include "PlayerStatus.h" +#include "AppDelegate.h" +#import "CCBDirectoryComparer.h" +#import "SSZipArchive.h" + +// Predefined messages +NSString *kCCBNetworkStatusStringWaiting = @"Waiting for connections"; +NSString *kCCBNetworkStatusStringTooMany = @"Too many connections"; +NSString *kCCBNetworkStatusStringConnected = @"Connected"; +NSString *kCCBNetworkStatusStringShutDown = @"Server shut down"; + +NSString *kCCBPlayerStatusStringNotConnected = @"Connect by running CocosBuilder on the same local wireless network as CocosPlayer.\nIf multiple instances of CocosBuilder is run on the same network, use a unique pairing code."; +NSString *kCCBPlayerStatusStringIdle = @"Idle"; +NSString *kCCBPlayerStatusStringUnzip = @"Action: Unzip game"; +NSString *kCCBPlayerStatusStringStop = @"Action: Stop"; +NSString *kCCBPlayerStatusStringPlay = @"Action: Run"; +NSString *kCCBPlayerStatusStringScript = @"Action: Executing script"; + + +@implementation ServerController + +@synthesize networkStatus, playerStatus, playerWindowDisplayed, isRetina, isIPhone; + +#pragma mark Initializers and setup + +- (NSString*) protocolIdentifier +{ + NSString* pairing = [[NSUserDefaults standardUserDefaults] objectForKey:@"pairing"]; + + if (pairing) + { + return [NSString stringWithFormat:@"CocosP-%@",pairing]; + } + else + { + return @"CocosPlayer"; + } +} + +- (id) init +{ + self = [super init]; + if (!self) return NULL; + + connectedClients = [[NSMutableSet alloc] init]; + + server = [[ThoMoServerStub alloc] initWithProtocolIdentifier:[self protocolIdentifier]]; + [server setDelegate:self]; + + networkStatus = kCCBNetworkUninitialized; + playerStatus = kCCBPlayerStatuskUninitialized; + playerWindowDisplayed = YES; + + return self; +} + +#pragma mark Redirection of std out + +- (void) redirectStdErr +{ + NSPipe* pipe = [NSPipe pipe]; + pipeReadHandle = [pipe fileHandleForReading]; + + [pipeReadHandle readInBackgroundAndNotify]; + + int err = dup2([[pipe fileHandleForWriting] fileDescriptor], STDERR_FILENO); + if (!err) NSLog(@"ConsoleWindow: Failed to redirect stderr"); + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(readData:) name:NSFileHandleReadCompletionNotification object:pipeReadHandle]; + + [pipeReadHandle retain]; +} + +- (void) readData:(NSNotification*)notification +{ + [pipeReadHandle readInBackgroundAndNotify] ; + NSString *str = [[NSString alloc] initWithData: [[notification userInfo] objectForKey: NSFileHandleNotificationDataItem] encoding: NSASCIIStringEncoding] ; + [self sendLog:str]; +} + +#pragma mark Control methods + +- (void) start +{ + if (server) + { + [server start]; + + // Redirect std out + [self redirectStdErr]; + } +} + +- (void) startIfNotStarted +{ + if (!server) + { + server = [[ThoMoServerStub alloc] initWithProtocolIdentifier:[self protocolIdentifier]]; + [server setDelegate:self]; + [server start]; + + self.networkStatus = kCCBNetworkStatusWaiting; + } +} + +- (void) stop +{ + if (server) + { + self.networkStatus = kCCBNetworkStatusShutDown; + //[[[PlayerStatusLayer sharedInstance] lblInstructions] setString:kCCBPlayerStatusStringStop]; + handle_ccb_stop(); + [server stop]; + [server release]; + server = NULL; + [connectedClients removeAllObjects]; + } +} + +- (void) updatePairing +{ + // Stop old server + [server stop]; + [server release]; + server = NULL; + [connectedClients removeAllObjects]; + + // Start new server + server = [[ThoMoServerStub alloc] initWithProtocolIdentifier:[self protocolIdentifier]]; + [server setDelegate:self]; + [server start]; + + self.networkStatus = kCCBNetworkStatusWaiting; +} + +#pragma mark Helper methods + +- (void) executeJavaScript:(NSString*)script +{ + self.playerStatus = kCCBPlayerStatusExecuteScript; + +// NSThread *cocos2dThread = [[CCDirector sharedDirector] runningThread]; +// +// [cocos2dThread performBlock:^(void) { +// NSString * string = @"None\n"; +// jsval out; +// BOOL success = [[JSBCore sharedInstance] evalString:script outVal:&out]; +// +// if(success) +// { +// /* +// if(JSVAL_IS_BOOLEAN(out)) +// { +// string = [NSString stringWithFormat:@"Result(bool): %@.\n", (JSVAL_TO_BOOLEAN(out)) ? @"true" : @"false"]; +// } +// else if(JSVAL_IS_INT(out)) +// { +// string = [NSString stringWithFormat:@"Result(int): %i.\n", JSVAL_TO_INT(out)]; +// } +// else if(JSVAL_IS_DOUBLE(out)) +// { +// string = [NSString stringWithFormat:@"Result(double): %d.\n", JSVAL_TO_DOUBLE(out)]; +// } +// else if(JSVAL_IS_STRING(out)) { +// NSString *tmp; +// jsval_to_nsstring( [[ScriptingCore sharedInstance] globalContext], out, &tmp ); +// string = [NSString stringWithFormat:@"Result(string): %d.\n", tmp]; +// } +// else if (JSVAL_IS_VOID(out) ) +// string = @"Result(void):\n"; +// else if (JSVAL_IS_OBJECT(out) ) +// string = @"Result(object):\n"; +// */ +// string = @"Success\n"; +// } +// else +// { +// string = [NSString stringWithFormat:@"Error evaluating script:\n#############################\n%@\n#############################\n", script]; +// } +// +// //[self sendResultString:string]; +// } +// waitUntilDone:NO]; +} + +- (void) listDirectory:(NSString*)dir prefix:(NSString*)prefix +{ + NSArray* files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:dir error:NULL]; + for (NSString* file in files) + { + NSLog(@"%@%@", prefix, file); + + BOOL isDir = NO; + if ([[NSFileManager defaultManager] fileExistsAtPath:[dir stringByAppendingPathComponent:file] isDirectory:&isDir] && isDir) + { + [self listDirectory:[dir stringByAppendingPathComponent:file] prefix:[prefix stringByAppendingString:@" "]]; + } + } +} + +- (void) extractZipData:(NSData*)data +{ + self.playerStatus = kCCBPlayerStatusUnzip; + + id runBlock = ^(void) { + + std::string path = cocos2d::CCFileUtils::sharedFileUtils()->getWritablePath(); + + NSString *writeablePath = [NSString stringWithCString:path.c_str() encoding:NSASCIIStringEncoding]; + + // NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); + NSString* dirPath = [writeablePath stringByAppendingPathComponent:@"ccb"]; + + NSString* zipPath = [dirPath stringByAppendingPathComponent:@"ccb.zip"]; + + BOOL isDirectory = NO; + if (![[NSFileManager defaultManager] fileExistsAtPath:dirPath isDirectory:&isDirectory]) + { + [[NSFileManager defaultManager] createDirectoryAtPath:dirPath withIntermediateDirectories:YES attributes:NULL error:NULL]; + } + + if(![data writeToFile:zipPath atomically:YES]) + { + NSLog(@"CocosPlayer: Failed to write zip file"); + return; + } + + if(![SSZipArchive unzipFileAtPath:zipPath toDestination:dirPath overwrite:YES password:NULL error:NULL]) { + NSLog(@"CocosPlayer: Failed to unzip resources"); + } + + [self listDirectory:dirPath prefix:@""]; + + // Send updated list of files on device + [self sendFileList]; + }; + + double delayInSeconds = 0.01; + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); + dispatch_after(popTime, dispatch_get_main_queue(), runBlock); +} + +-(void) stopJSApp +{ + if( ! playerWindowDisplayed ) { + //[[AppController appController] stopJSApp]; + playerWindowDisplayed = YES; + } +} + +-(void) runJSApp +{ + handle_ccb_run(); + //[[AppController appController] runJSApp]; + playerWindowDisplayed = NO; +} + +- (void) stopMain +{ + if( ! playerWindowDisplayed ) { + self.playerStatus = kCCBPlayerStatusStop; + +// NSThread *cocos2dThread = [[CCDirector sharedDirector] runningThread]; +// +// [cocos2dThread performBlock:^(void) { +// [self stopJSApp]; +// } waitUntilDone:YES]; +// + // Force update network status + + handle_ccb_stop(); + + CCBNetworkStatus tmp = networkStatus; + networkStatus = kCCBNetworkUninitialized; + self.networkStatus = tmp; + } +} + +- (void) runMain +{ + double delayInSeconds = 0.05; + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); + dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ + self.playerStatus = kCCBPlayerStatusPlay; + [self runJSApp]; + }); + +} + +#pragma mark Server callbacks + +- (void) server:(ThoMoServerStub *)theServer acceptedConnectionFromClient:(NSString *)aClientIdString +{ + [connectedClients addObject:aClientIdString]; + + if (connectedClients.count == 1) + { + self.networkStatus = kCCBNetworkStatusConnected; + [self sendDeviceName]; + [self sendFileList]; + } + else + { + self.networkStatus = kCCBNetworkStatusTooMany; + } +} + +- (void)server:(ThoMoServerStub *)theServer lostConnectionToClient:(NSString *)aClientIdString errorMessage:(NSString *)errorMessage +{ + [connectedClients removeObject:aClientIdString]; + + if (connectedClients.count == 0) + { + self.networkStatus = kCCBNetworkStatusWaiting; + } + else if (connectedClients.count == 1) + { + self.networkStatus = kCCBNetworkStatusConnected; + } + else + { + self.networkStatus = kCCBNetworkStatusTooMany; + } +} + +- (void)serverDidShutDown:(ThoMoServerStub *)theServer +{ + self.networkStatus = kCCBNetworkStatusWaiting; + + if( server == theServer || !server) { + [server release]; + server = NULL; + [connectedClients removeAllObjects]; + + [self startIfNotStarted]; + } +} + +- (void)netServiceProblemEncountered:(NSString *)errorMessage onServer:(ThoMoServerStub *)theServer +{ + if( server == theServer ) { + [server stop]; + [server release]; + server = NULL; + [connectedClients removeAllObjects]; + } +} + +- (void) server:(ThoMoServerStub *)theServer didReceiveData:(id)theData fromClient:(NSString *)aClientIdString +{ + if (connectedClients.count != 1) return; + + NSDictionary* msg = theData; + + NSString* cmd = [msg objectForKey:@"cmd"]; + + if ([cmd isEqualToString:@"script"]) + { + NSString* script = [msg objectForKey:@"script"]; + [self executeJavaScript:script]; + } + else if ([cmd isEqualToString:@"run"]) + { + [self runMain]; + } + else if ([cmd isEqualToString:@"stop"]) + { + [self stopMain]; + } + else if ([cmd isEqualToString:@"zip"]) + { + NSData* zipData = [msg objectForKey:@"data"]; + + // Extract zip file received from CocosBuilder + [self extractZipData:zipData]; + } + else if ([cmd isEqualToString:@"settings"]) + { + NSArray* arr = [msg objectForKey:@"orientations"]; + + NSUInteger orientations = 0; + + if ([[arr objectAtIndex:0] boolValue]) orientations |= UIInterfaceOrientationMaskPortrait; + if ([[arr objectAtIndex:1] boolValue]) orientations |= UIInterfaceOrientationMaskPortraitUpsideDown; + if ([[arr objectAtIndex:2] boolValue]) orientations |= UIInterfaceOrientationMaskLandscapeLeft; + if ([[arr objectAtIndex:3] boolValue]) orientations |= UIInterfaceOrientationMaskLandscapeRight; + + //[AppController appController].deviceOrientations = orientations; + } +} + +#pragma mark Server/Player status + +-(void) setNetworkStatus:(CCBNetworkStatus)aNetworkStatus +{ + if( networkStatus != aNetworkStatus ) { + networkStatus = aNetworkStatus; + + //PlayerStatusLayer *statusLayer = [PlayerStatusLayer sharedInstance]; + switch (networkStatus) { + case kCCBNetworkStatusConnected: + if( playerWindowDisplayed) + handle_set_status((const char *)[kCCBNetworkStatusStringConnected cStringUsingEncoding:NSASCIIStringEncoding]); + + self.playerStatus = kCCBPlayerStatusIdle; + break; + case kCCBNetworkStatusShutDown: + if( playerWindowDisplayed) + handle_set_status((const char *)[kCCBNetworkStatusStringShutDown cStringUsingEncoding:NSASCIIStringEncoding]); + + self.playerStatus = kCCBPlayerStatusNotConnected; + break; + case kCCBNetworkStatusTooMany: + if( playerWindowDisplayed) + handle_set_status((const char *)[kCCBNetworkStatusStringWaiting cStringUsingEncoding:NSASCIIStringEncoding]); + + [self stopJSApp]; + self.playerStatus = kCCBPlayerStatusNotConnected; + break; + case kCCBNetworkStatusWaiting: + if( playerWindowDisplayed) + handle_set_status((const char *)[kCCBNetworkStatusStringWaiting cStringUsingEncoding:NSASCIIStringEncoding]); + + self.playerStatus = kCCBPlayerStatusNotConnected; + [self stopJSApp]; + break; + + default: + break; + } + } +} + +-(void) setPlayerStatus:(CCBPlayerStatus)aPlayerStatus +{ + if( playerStatus != aPlayerStatus) { + playerStatus = aPlayerStatus; + + //PlayerStatusLayer *statusLayer = [PlayerStatusLayer sharedInstance]; + + switch (playerStatus) { + case kCCBPlayerStatusExecuteScript: + if( playerWindowDisplayed) { + handle_set_message((const char *)[kCCBPlayerStatusStringScript cStringUsingEncoding:NSASCIIStringEncoding]); + } + break; + case kCCBPlayerStatusPlay: + if( playerWindowDisplayed) + handle_set_message((const char *)[kCCBPlayerStatusStringPlay cStringUsingEncoding:NSASCIIStringEncoding]); + + break; + case kCCBPlayerStatusStop: + if( playerWindowDisplayed) + handle_set_message((const char *)[kCCBPlayerStatusStringStop cStringUsingEncoding:NSASCIIStringEncoding]); + break; + case kCCBPlayerStatusUnzip: + if( playerWindowDisplayed) + handle_set_message((const char *)[kCCBPlayerStatusStringUnzip cStringUsingEncoding:NSASCIIStringEncoding]); + break; + case kCCBPlayerStatusIdle: + if( playerWindowDisplayed) + handle_set_message((const char *)[kCCBPlayerStatusStringIdle cStringUsingEncoding:NSASCIIStringEncoding]); + break; + case kCCBPlayerStatusNotConnected: + if( playerWindowDisplayed) + handle_set_message((const char *)[kCCBPlayerStatusStringNotConnected cStringUsingEncoding:NSASCIIStringEncoding]); + break; + + default: + break; + } + } + +} + +#pragma mark Sending messages + +- (void) sendMessage:(NSDictionary*) msg +{ + if (connectedClients.count == 1) + { + [server sendToAllClients:msg]; + } +} + +- (NSString*) getUUID +{ + // Check user defaults + NSString* uuid = [[NSUserDefaults standardUserDefaults] objectForKey:@"uuid"]; + if (uuid) return uuid; + + // Generate UUID + CFUUIDRef uuidObject = CFUUIDCreate(kCFAllocatorDefault); + uuid = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, uuidObject); + CFRelease(uuidObject); + + // Store generated id + [[NSUserDefaults standardUserDefaults] setObject:uuid forKey:@"uuid"]; + + return uuid; +} + +- (void) sendDeviceName +{ + NSMutableDictionary* msg = [NSMutableDictionary dictionary]; + [msg setObject:@"deviceinfo" forKey:@"cmd"]; + [msg setObject:[[UIDevice currentDevice] name] forKey:@"devicename"]; + //[msg setObject:[AppController appController].deviceType forKey:@"devicetype"]; + if(self.isIPhone) + { + [msg setObject:@"iPhone" forKey:@"devicetype"]; + } + else + { + [msg setObject:@"iPad" forKey:@"devicetype"]; + } + [msg setObject:[NSNumber numberWithBool:self.isRetina] forKey:@"retinadisplay"]; + [msg setObject:[self getUUID] forKey:@"uuid"]; + + [self sendMessage:msg]; + +} + +- (void) sendResultString:(NSString*) str +{ + NSMutableDictionary* msg = [NSMutableDictionary dictionary]; + [msg setObject:@"result" forKey:@"cmd"]; + [msg setObject:str forKey:@"result"]; + + [self sendMessage:msg]; +} + +- (void) sendLog:(NSString*)log +{ + NSMutableDictionary* msg = [NSMutableDictionary dictionary]; + [msg setObject:@"log" forKey:@"cmd"]; + [msg setObject:log forKey:@"string"]; + + [self sendMessage:msg]; +} + +- (void) sendFileList +{ + // Get the contents of the CCB working directory, with files + CCBDirectoryComparer* dc = [[[CCBDirectoryComparer alloc] init] autorelease]; + std::string path = cocos2d::CCFileUtils::sharedFileUtils()->getWritablePath(); + + NSString *writeablePath = [NSString stringWithCString:path.c_str() encoding:NSASCIIStringEncoding]; + + // NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); + NSString* dirPath = [writeablePath stringByAppendingPathComponent:@"ccb"]; + +// NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); +// NSString* dirPath = [[searchPaths objectAtIndex:0] stringByAppendingPathComponent:@"ccb"]; + [dc loadDirectory:dirPath]; + NSDictionary* dirFiles = dc.files; + + // Send message + NSMutableDictionary* msg = [NSMutableDictionary dictionary]; + [msg setObject:@"filelist" forKey:@"cmd"]; + [msg setObject:dirFiles forKey:@"filelist"]; + + [self sendMessage:msg]; + for (id key in msg) { + NSLog(@"key: %@, value: %@", key, [msg objectForKey:key]); + + } +} + +#pragma mark Common + +- (void) dealloc +{ + [server release]; + [connectedClients release]; + + [super dealloc]; +} + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoClient/ThoMoClientDelegateProtocol.h b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoClient/ThoMoClientDelegateProtocol.h new file mode 100644 index 0000000000..0a02038fd3 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoClient/ThoMoClientDelegateProtocol.h @@ -0,0 +1,68 @@ +/* + * ThoMoClientDelegateProtocol.h + * ThoMoNetworkingFramework + * + * Created by Thorsten Karrer on 6/8/09. + * Copyright 2010 media computing group - RWTH Aachen University. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +@class ThoMoClientStub; + + + +@protocol ThoMoClientDelegateProtocol + +@optional + +/// Connection notification (optional) +- (void)client:(ThoMoClientStub *)theClient didConnectToServer:(NSString *)aServerIdString; + + +/// Disconnection notification (optional) +- (void)client:(ThoMoClientStub *)theClient didDisconnectFromServer:(NSString *)aServerIdString errorMessage:(NSString *)errorMessage; + + +/// Bonjour problem notification (optional) +- (void)netServiceProblemEncountered:(NSString *)errorMessage onClient:(ThoMoClientStub *)theClient; + + +/// Client shutdown notification (optional) +- (void)clientDidShutDown:(ThoMoClientStub *)theClient; + + + +@required + +/// Data received notification (required) +/** + Sent to its delegate by the client stub on the main thread whenever it received data from a server. + + \param[in] theClient The client stub that received the data. + \param[in] theData The object that was bein received. + \param[in] aServerIdString A string designating the server that sent the data. + */ +-(void)client:(ThoMoClientStub *)theClient didReceiveData:(id)theData fromServer:(NSString *)aServerIdString; + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoClient/ThoMoClientStub.m b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoClient/ThoMoClientStub.m new file mode 100644 index 0000000000..8cce5e58bf --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoClient/ThoMoClientStub.m @@ -0,0 +1,407 @@ +/* + * ThoMoClientStub.m + * ThoMoNetworkingFramework + * + * Created by Thorsten Karrer on 29.6.09. + * Copyright 2010 media computing group - RWTH Aachen University. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import "ThoMoClientStub_private.h" +#import "ThoMoTCPConnection.h" + +// ===================================================================================================================== +#pragma mark - +#pragma mark defines +// --------------------------------------------------------------------------------------------------------------------- + +#define kThoMoNetworkInfoKeyServer kThoMoNetworkInfoKeyRemoteConnectionIdString +#define kThoMoNetworkInfoKeyClient kThoMoNetworkInfoKeyLocalNetworkStub + +// ===================================================================================================================== + + + + + +// ===================================================================================================================== +#pragma mark - +#pragma mark Class Extensions +// --------------------------------------------------------------------------------------------------------------------- + +@interface ThoMoClientStub() + +-(void)netServiceProblemRelayMethod:(NSDictionary *)infoDict; +-(void)didReceiveDataRelayMethod:(NSDictionary *)infoDict; + +-(void)resolveNetService:(NSNetService *)theNetService; + +@end +// ===================================================================================================================== + + + + + +// ===================================================================================================================== +#pragma mark - +#pragma mark ThoMoClientStub implementation +// --------------------------------------------------------------------------------------------------------------------- + +@implementation ThoMoClientStub + + +#pragma mark - +#pragma mark Properties + +@synthesize delegate; +@synthesize offeredNetServices; +@synthesize connectedNetServices; + + +#pragma mark - +#pragma mark Housekeeping + +-(id)initWithProtocolIdentifier:(NSString *)theProtocolIdentifier; +{ + self = [super initWithProtocolIdentifier:theProtocolIdentifier]; + if (self != nil) { + // add inits here + self.offeredNetServices = [[NSMutableArray alloc] init]; + self.connectedNetServices = [[NSMutableDictionary alloc] init]; + } + return self; +} + + +- (void) dealloc +{ + [self stop]; + self.offeredNetServices = nil; + self.connectedNetServices = nil; + [super dealloc]; +} + + + +#pragma mark - +#pragma mark Control + +-(NSArray *)connectedServers; +{ + return [super activeConnections]; +} + +-(void)send:(id)anObject toServer:(NSString *)theServerIdString; +{ + [super send:anObject toConnection:theServerIdString]; +} + +-(void)sendToAllServers:(id)anObject; +{ + for (NSString *aServer in [self connectedServers]) + { + [self send:anObject toServer:aServer]; + } +} + +// DEPRECATED +-(void)sendData:(id)theData toServer:(NSString *)theServerIdString; +{ + [self send:theData toServer:theServerIdString]; +} + +// PRIVATE API +-(void)sendBytes:(NSData *)theBytes toServer:(NSString *)theServerIdString; +{ + [super sendByteData:theBytes toConnection:theServerIdString]; +} + + + +#pragma mark - +#pragma mark Private Methods + +// override +-(BOOL)setup; +{ + if (![super setup]) + return NO; + + //start NSNetServiceBrowser + browser = [[NSNetServiceBrowser alloc] init]; + [browser setDelegate:self]; + [browser searchForServicesOfType:[NSString stringWithFormat:@"_%@._tcp.", protocolIdentifier] inDomain:@"local"]; + + return YES; +} + + +// override +-(void)teardown; +{ + [browser stop]; + [browser release]; + browser = nil; + + [super teardown]; +} + + +// get a key string ("ip_address:port") for a resolved service +-(NSString *)keyStringFromResolvedService:(NSNetService *)theService; +{ + NSData *addr = [[theService addresses] objectAtIndex:0]; + + NSMutableString *peerKey = [[[self keyStringFromAddress:addr] mutableCopy] autorelease]; + + return peerKey; +} + +#pragma mark - +#pragma mark Delegate Methods + +#pragma mark NSNetServiceBrowserDelegate + +// notification when service was found +- (void) netServiceBrowser:(NSNetServiceBrowser*)browser didFindService:(NSNetService*)service moreComing:(BOOL)moreComing +{ + NSLog(@"NetService %@ offered by %@", [service type], [service name]); + + //need to hold a reference to the service + [self.offeredNetServices addObject:service]; + + //resolve net service + [service retain]; // retain - will be released after the resolve comes back! + [service setDelegate:self]; + [service resolveWithTimeout:0.0]; +} + + +//notification when service was removed +- (void) netServiceBrowser:(NSNetServiceBrowser*)browser didRemoveService:(NSNetService*)service moreComing:(BOOL)moreComing +{ + NSLog(@"NetService %@ no longer offered by %@", [service type], [service name]); + + // remove the service from the list + [self.offeredNetServices removeObject:service]; +} + + +#pragma mark NSNetServiceDelegate + +//notification when netservice was resolved +- (void)netServiceDidResolveAddress:(NSNetService *)sender +{ + NSLog(@"Resolved Server Address %@", [sender hostName]); + + // get a key string ("ip_address:port") for the service + NSString *key = [self keyStringFromResolvedService:sender]; + NSAssert(key != nil, @"Could not create key string for resolved service"); + + // Tho 04.01.10: changed. Connections are only established if the service is not present in the connectedNetServices dict. + // This dict should now always contain exactly those services for which we have an open connection + + if (![self.connectedNetServices objectForKey:key]) + { + + //connect to server and cache the NetService if the NetService can build us the I/O-Streams + NSInputStream *istream; + NSOutputStream *ostream; + + // -[NSNetService getInputStream:outputStream:] currently returns the stream + // with a reference that we have to release (something that's counter to the + // standard Cocoa memory management rules ). + BOOL gotStreams = [sender getInputStream:&istream outputStream:&ostream]; + + if (gotStreams) + { + [self openNewConnection:key inputStream:istream outputStream:ostream]; + [istream release]; + [ostream release]; + + [self.connectedNetServices setObject:sender forKey:key]; + } + + } + + // we're done here, stop resolving + [sender stop]; + [sender release]; +} + + +- (void)netService:(NSNetService *)sender didNotResolve:(NSDictionary *)errorDict +{ + NSString *errorString; + switch ([(NSNumber *)[errorDict objectForKey:NSNetServicesErrorCode] intValue]) + { + case NSNetServicesBadArgumentError: + errorString = @"NSNetServicesBadArgumentError"; + break; + case NSNetServicesCancelledError: + errorString = @"NSNetServicesCancelledError"; + break; + case NSNetServicesCollisionError: + errorString = @"NSNetServicesCollisionError"; + break; + case NSNetServicesInvalidError: + errorString = @"NSNetServicesInvalidError"; + break; + case NSNetServicesNotFoundError: + errorString = @"NSNetServicesNotFoundError"; + break; + case NSNetServicesTimeoutError: + errorString = @"NSNetServicesTimeoutError"; + break; + case NSNetServicesUnknownError: + errorString = @"NSNetServicesUnknownError"; + break; + default: + errorString = @"Unknown. Possibly an error on the Mach layer."; + break; + } + + NSLog(@"Could not resolve service %@ because of error %@", sender, errorString); + + // stop the resolve + [sender stop]; + [sender release]; +} + + + +#pragma mark Connection Delegate Methods + +// override +-(void)streamsDidOpenOnConnection:(ThoMoTCPConnection *)theConnection; +{ + // let the super class issue the user notifications on the main thread + [super streamsDidOpenOnConnection:theConnection]; +} + + +// override +-(void)streamEndEncountered:(NSStream *)theStream onConnection:(ThoMoTCPConnection *)theConnection; +{ + NSString *connectionKey = [self keyForConnection:theConnection]; + + // this closes the connection, removes it from the connections array, and schedules the connectionLostRelayMethod selector on the main run loop + [super streamEndEncountered:theStream onConnection:theConnection]; + + // remove the connection's service from the connectedNetServices dict (it may still be contained in the offered array) + NSNetService *connectionNetService = [[self.connectedNetServices objectForKey:connectionKey] retain]; // retain - will be released after the resolve comes back! + [self.connectedNetServices removeObjectForKey:connectionKey]; + + // try to re-resolve the netService if it is still offered by Bonjour + if ([offeredNetServices containsObject:connectionNetService]) + { + [self performSelector:@selector(resolveNetService:) withObject:connectionNetService afterDelay:1]; + } +} + + +// override +-(void)streamErrorEncountered:(NSStream *)theStream onConnection:(ThoMoTCPConnection *)theConnection; +{ + NSString *connectionKey = [self keyForConnection:theConnection]; + + // this closes the connection, removes it from the connections array, and schedules the connectionLostRelayMethod selector on the main run loop + [super streamErrorEncountered:theStream onConnection:theConnection]; + + // remove the connection's service from the connectedNetServices dict (it may still be contained in the offered array) + NSNetService *connectionNetService = [[self.connectedNetServices objectForKey:connectionKey] retain]; // retain - will be released after the resolve comes back! + [self.connectedNetServices removeObjectForKey:connectionKey]; + + // try to re-resolve the netService if it is still offered by Bonjour + if ([offeredNetServices containsObject:connectionNetService]) + { + [self performSelector:@selector(resolveNetService:) withObject:connectionNetService afterDelay:1]; + } +} + +#pragma mark - +#pragma mark Hacking Relays +-(void)resolveNetService:(NSNetService *)theNetService; +{ + [theNetService resolveWithTimeout:5.0]; +} + + +#pragma mark - +#pragma mark Main Thread Relay Methods + +// override +-(void)netWorkStubDidShutDownRelayMethod +{ + if ([delegate respondsToSelector:@selector(clientDidShutDown:)]) + [delegate clientDidShutDown:self]; +} + +// override +-(void)netServiceProblemRelayMethod:(NSDictionary *)infoDict +{ + if ([delegate respondsToSelector:@selector(netServiceProblemEncountered:onClient:)]) + [delegate netServiceProblemEncountered:[infoDict objectForKey:@"kThoMoTCPInfoKeyUserMessage"] onClient:self]; +} + +// required +// override +-(void)didReceiveDataRelayMethod:(NSDictionary *)infoDict; +{ + [delegate client:[infoDict objectForKey:kThoMoNetworkInfoKeyClient] + didReceiveData:[infoDict objectForKey:kThoMoNetworkInfoKeyData] + fromServer:[infoDict objectForKey:kThoMoNetworkInfoKeyServer]]; +} + +// override +-(void)connectionEstablishedRelayMethod:(NSDictionary *)infoDict; +{ + if ([delegate respondsToSelector:@selector(client:didConnectToServer:)]) + [delegate client:[infoDict objectForKey:kThoMoNetworkInfoKeyClient] + didConnectToServer:[infoDict objectForKey:kThoMoNetworkInfoKeyServer]]; +} + +// override +-(void)connectionLostRelayMethod:(NSDictionary *)infoDict; +{ + if ([delegate respondsToSelector:@selector(client:didDisconnectFromServer:errorMessage:)]) + [delegate client:[infoDict objectForKey:kThoMoNetworkInfoKeyClient] + didDisconnectFromServer:[infoDict objectForKey:kThoMoNetworkInfoKeyServer] + errorMessage:[infoDict objectForKey:kThoMoNetworkInfoKeyUserMessage]]; +} + +// override +-(void)connectionClosedRelayMethod:(NSDictionary *)infoDict; +{ + if ([delegate respondsToSelector:@selector(client:didDisconnectFromServer:errorMessage:)]) + [delegate client:[infoDict objectForKey:kThoMoNetworkInfoKeyClient] + didDisconnectFromServer:[infoDict objectForKey:kThoMoNetworkInfoKeyServer] + errorMessage:[infoDict objectForKey:kThoMoNetworkInfoKeyUserMessage]]; +} + + + + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoClient/ThoMoClientStub_private.h b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoClient/ThoMoClientStub_private.h new file mode 100644 index 0000000000..2d674717e1 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoClient/ThoMoClientStub_private.h @@ -0,0 +1,57 @@ +/* + * ThoMoClientStub.h + * ThoMoNetworkingFramework + * + * Created by Thorsten Karrer on 29.6.09. + * Copyright 2010 media computing group - RWTH Aachen University. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import "ThoMoClientDelegateProtocol.h" +#import "ThoMoNetworkStub.h" + +@interface ThoMoClientStub : ThoMoNetworkStub +{ + NSNetServiceBrowser *browser; + + NSMutableArray *offeredNetServices; // offered + NSMutableDictionary *connectedNetServices; // connected + + id delegate; +} + +@property (assign) id delegate; +@property (retain) NSMutableArray *offeredNetServices; +@property (retain) NSMutableDictionary *connectedNetServices; + + +-(NSArray *)connectedServers; + +-(void)sendData:(id)theData toServer:(NSString *)theServerIdString DEPRECATED_ATTRIBUTE; +-(void)sendBytes:(NSData *)theBytes toServer:(NSString *)theServerIdString; + +-(void)send:(id)anObject toServer:(NSString *)theServerIdString; +-(void)sendToAllServers:(id)anObject; + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoClientStub.h b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoClientStub.h new file mode 100644 index 0000000000..0233e27bd2 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoClientStub.h @@ -0,0 +1,111 @@ +/* + * ThoMoClientStub.h + * ThoMoNetworkingFramework + * + * Created by Thorsten Karrer on 28.9.09. + * Copyright 2010 media computing group - RWTH Aachen University. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import "ThoMoClientDelegateProtocol.h" + +@interface ThoMoClientStub : NSObject +{ +} + +/// Delegate accessor +/** + Accessor for the client stubs delegate. Must be compliant to ThoMoClientDelegateProtocol. + */ +@property (assign) id delegate; + + +/// Designated initializer +/** + Initializes the Stub with a protocol identifier string. When started, this client stub will automatically connect to all server stubs (ThoMoServerStub) on the local network that use the same protocol identifier. + + \param[in] theProtocolIdentifier A user-definable string of maximum 14 characters length. Determines which server stubs this client stub connects to. + + \throws ThoMoInvalidArgumentException if theProtocolIdentifier exceeds 14 characters in length. + */ +-(id)initWithProtocolIdentifier:(NSString *)theProtocolIdentifier; + + + +/// Starts the client stub +/** + Starts the client stub on a background thread. The stub will auto-connect to each server with the same protocol identifier. May be called only once during the lifetime of the client stub. + + \throws ThoMoStubAlreadyRunningException if the client stub had already been started before. + */ +-(void) start; + + + +/// Stops the client stub +/** + Stops the client stub and cancels the associated network thread. This will close all open connections. May be called only once during the lifetime of the client stub. + */ +-(void) stop; + + + +/// Returns an array of the connected servers +/** + Returns an array of id-strings for all servers that the client stub is currently connected to. You can use these id-strings to send objects to any of the servers by calling -send:toServer:. + + \returns an array of id-strings for all connected servers. + */ +-(NSArray *)connectedServers; + + + +/// Sends an object to a connected server +/** + Sends anObject to the server designated by theServerIdString. + \note Note that actually a copy of the object is being created on the other side of the connection. Altering the internal state of the object on either side of the connection is not reflected on the other side! + + \param[in] anObject An NSCoding compliant object that will be copied and re-created at the server stub. + \param[in] theServerIdString A string the server to send the object to. Must be taken from the array returned by connectedServers. + + \throws ThoMoInvalidArgumentException if theServerIdString does not designate a server the client stub is connected to. + */ +-(void)send:(id)anObject toServer:(NSString *)theServerIdString; + + + +/// Sends an object to all connected servers +/** + Sends anObject to all servers in the array returned by connectedServers. + \note Note that actually a copy of the object is being created on the other sides of the connections. Altering the internal state of the object on either side of the connections is not reflected on the other sides! + + \param[in] anObject An NSCoding compliant object that will be copied and re-created at the server stubs. + */ +-(void)sendToAllServers:(id)anObject; + + + +-(void)sendData:(id)theData toServer:(NSString *)theServerIdString DEPRECATED_ATTRIBUTE; + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoNetworkStub.h b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoNetworkStub.h new file mode 100644 index 0000000000..9c6eba9a97 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoNetworkStub.h @@ -0,0 +1,77 @@ +/* + * ThoMoNetworkStub.h + * ThoMoNetworkingFramework + * + * Created by Thorsten Karrer on 2.7.09. + * Copyright 2010 media computing group - RWTH Aachen University. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import "ThoMoTCPConnectionDelegateProtocol.h" + + +/// Mixin class that encapsulates the network worker thread and the handling of ThoMoTCPConnections. +/** + You should never instantiate a ThoMoNetworkStub directly. Instead, you should use its subclasses ThoMoServerStub and ThoMoClientStub. + Note: the implementation of this class is Bonjour-agnostic and should remain so. + */ + +@interface ThoMoNetworkStub : NSObject +{ + NSMutableDictionary *connections; + NSString *protocolIdentifier; + NSThread *networkThread; +} + +-(id)initWithProtocolIdentifier:(NSString *)theProtocolIdentifier; + +-(void) start; +-(void) stop; + +-(NSArray *)activeConnections; + +-(void)send:(id)theData toConnection:(NSString *)theConnectionIdString; +-(void)sendByteData:(NSData *)theData toConnection:(NSString *)theConnectionIdString; + + + + + + +// protected +-(BOOL)setup; +-(void)teardown; +-(NSString *)keyStringFromAddress:(NSData *)addr; +/// Returns the key for theConnection from the connections dictionary. +-(NSString *)keyForConnection:(ThoMoTCPConnection *)theConnection; +-(void) openNewConnection:(NSString *)theConnectionKey inputStream:(NSInputStream *)istr outputStream:(NSOutputStream *)ostr; + + + +@end + +NSString *const kThoMoNetworkInfoKeyUserMessage; +NSString *const kThoMoNetworkInfoKeyData; +NSString *const kThoMoNetworkInfoKeyRemoteConnectionIdString; +NSString *const kThoMoNetworkInfoKeyLocalNetworkStub; diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoNetworkStub.m b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoNetworkStub.m new file mode 100644 index 0000000000..ccbe086021 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoNetworkStub.m @@ -0,0 +1,443 @@ +/* + * ThoMoNetworkStub.m + * ThoMoNetworkingFramework + * + * Created by Thorsten Karrer on 2.7.09. + * Copyright 2010 media computing group - RWTH Aachen University. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import "ThoMoNetworkStub.h" +#import +#import "ThoMoTCPConnection.h" +#import + +NSString *const kThoMoNetworkInfoKeyUserMessage = @"kThoMoNetworkInfoKeyUserMessage"; +NSString *const kThoMoNetworkInfoKeyData = @"kThoMoNetworkInfoKeyData"; +NSString *const kThoMoNetworkInfoKeyRemoteConnectionIdString = @"kThoMoNetworkInfoKeyRemoteConnectionIdString"; +NSString *const kThoMoNetworkInfoKeyLocalNetworkStub = @"kThoMoNetworkInfoKeyLocalNetworkStub"; + +NSString *const kThoMoNetworkPrefScopeSpecifierKey = @"kThoMoNetworkPrefScopeSpecifierKey"; + +// interface category for main thread relay methods +@interface ThoMoNetworkStub (RelayMethods) +-(void)netServiceProblemRelayMethod:(NSDictionary *)infoDict; +-(void)didReceiveDataRelayMethod:(NSDictionary *)infoDict; +-(void)connectionEstablishedRelayMethod:(NSDictionary *)infoDict; +-(void)connectionLostRelayMethod:(NSDictionary *)infoDict; +-(void)connectionClosedRelayMethod:(NSDictionary *)infoDict; +@end + +@interface ThoMoNetworkStub () + +-(void)sendDataWithInfoDict:(NSDictionary *)theInfoDict; + +@end + + + + +// ===================================================================================================================== +#pragma mark - +#pragma mark Public Methods +// --------------------------------------------------------------------------------------------------------------------- + +@implementation ThoMoNetworkStub + +#pragma mark Housekeeping + +-(id)initWithProtocolIdentifier:(NSString *)theProtocolIdentifier; +{ + self = [super init]; + if (self != nil) + { + // check if there is a scope specifier present in the user defaults and add it to the protocolId + NSString *scopeSpecifier = [[NSUserDefaults standardUserDefaults] stringForKey:kThoMoNetworkPrefScopeSpecifierKey]; + if (scopeSpecifier) + { + protocolIdentifier = [[scopeSpecifier stringByAppendingFormat:@"-%@", theProtocolIdentifier] retain]; + NSLog(@"Warning: ThoMo Networking Protocol Prefix in effect! If your app cannot connect to its counterpart that may be the reason."); + } + else + { + protocolIdentifier = [theProtocolIdentifier copy]; + } + + if ([protocolIdentifier length] > 14) + { + // clean up internally + [NSException raise:@"ThoMoInvalidArgumentException" + format:@"The protocol identifier plus the optional scoping prefix (\"%@\") exceed" + " Bonjour's maximum allowed length of fourteen characters!", protocolIdentifier]; + } + + connections = [[NSMutableDictionary alloc] init]; + } + return self; +} + +-(id)init; +{ + return [self initWithProtocolIdentifier:@"thoMoNetworkStubDefaultIdentifier"]; +} + +// since the networkThread retains our object while it executes, this method will be called after the thread is done +- (void) dealloc +{ + [connections release]; + [protocolIdentifier release]; + [networkThread release]; + [super dealloc]; +} + +// these methods are called on the main thread +#pragma mark Control + +-(void) start; +{ + if ([networkThread isExecuting]) + { + [NSException raise:@"ThoMoStubAlreadyRunningException" + format:@"The client stub had already been started before and cannot be started twice."]; + } + + // TODO: check if we cannot run a start-stop-start cycle + NSAssert(networkThread == nil, @"Network thread not released properly"); + + networkThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkThreadEntry) object:nil]; + [networkThread start]; +} + +-(void) stop; +{ + [networkThread cancel]; + + // TODO: check if we can release the networkthread here +} + +-(NSArray *)activeConnections; +{ + NSArray *result; + @synchronized(self) + { + result = [[connections allKeys] copy]; + } + return [result autorelease]; +} + +-(void)send:(id)theData toConnection:(NSString *)theConnectionIdString; +{ +// NSData *sendData = [NSKeyedArchiver archivedDataWithRootObject:theData]; + NSString *errorStr; + NSData *sendData = [NSPropertyListSerialization dataWithPropertyList:theData format:NSPropertyListBinaryFormat_v1_0 options:NULL error:&errorStr]; + + [self sendByteData:sendData toConnection:theConnectionIdString]; +} + +-(void)sendByteData:(NSData *)sendData toConnection:(NSString *)theConnectionIdString; +{ + NSDictionary *infoDict = [NSDictionary dictionaryWithObjectsAndKeys: + sendData, @"DATA", + theConnectionIdString, @"ID", + nil]; + + [self performSelector:@selector(sendDataWithInfoDict:) onThread:networkThread withObject:infoDict waitUntilDone:NO]; +} + +#pragma mark Send Data Relay + +// only call on network thread +-(void)sendDataWithInfoDict:(NSDictionary *)theInfoDict; +{ + NSData *sendData = [theInfoDict objectForKey:@"DATA"]; + NSString *theConnectionIdString = [theInfoDict objectForKey:@"ID"]; + + ThoMoTCPConnection *connection = nil; + @synchronized(self) + { + connection = [[connections valueForKey:theConnectionIdString] retain]; + } + + if (!connection) + { + [NSException raise:@"ThoMoInvalidArgumentException" + format:@"No connection found for id %@", theConnectionIdString]; + } + else + { + [connection enqueueNextSendObject:sendData]; + } + [connection release]; +} + + +#pragma mark Threading Methods + +-(void)networkThreadEntry +{ + #ifdef DEBUG + #ifdef THOMO_PTHREAD_NAMING_AVAILABLE + pthread_setname_np("ThoMoNetworking Dispatch Thread"); + #endif + #endif + + NSAutoreleasePool *networkThreadPool = [[NSAutoreleasePool alloc] init]; + + if([self setup]) + { + while (![networkThread isCancelled]) + { + NSDate *inOneSecond = [[NSDate alloc] initWithTimeIntervalSinceNow:1]; + + // catch exceptions and propagate to main thread + @try { + [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:inOneSecond]; + } + @catch (NSException * e) { + [e performSelectorOnMainThread:@selector(raise) withObject:nil waitUntilDone:YES]; + } + + [inOneSecond release]; + } + + [self teardown]; + } + + [self performSelectorOnMainThread:@selector(networkStubDidShutDownRelayMethod) withObject:nil waitUntilDone:NO]; + + [networkThreadPool release]; +} + +#pragma mark - +#pragma mark Connection Delegate Methods + +/// Delegate method that gets called from ThoMoTCPConnections whenever they did receive data. +/** + Takes the received data and relays it to a method on the main thread. + This method is typically overridden in the subclasses of ThoMoNetworkStub and then directly called from there. + + \param[in] theData reference to the received data + \param[in] theConnection reference to the connection that received the data + */ +-(void)didReceiveData:(NSData *)theData onConnection:(ThoMoTCPConnection *)theConnection; +{ + // look up the connection + NSString *connectionKey = [self keyForConnection:theConnection]; + + // unarchive the data + //id receivedData = [NSKeyedUnarchiver unarchiveObjectWithData:theData]; + + NSString *errorStr; + NSDictionary *receivedData = [NSPropertyListSerialization propertyListWithData:theData options:NULL format:NULL error:&errorStr]; + + NSLog(@"DICT: %@", [receivedData description]); + // package the parameters into an info dict and relay them to the main thread + NSDictionary *infoDict = [NSDictionary dictionaryWithObjectsAndKeys: + connectionKey, kThoMoNetworkInfoKeyRemoteConnectionIdString, + self, kThoMoNetworkInfoKeyLocalNetworkStub, + receivedData, kThoMoNetworkInfoKeyData, + nil]; + + [self performSelectorOnMainThread:@selector(didReceiveDataRelayMethod:) withObject:infoDict waitUntilDone:NO]; +} + +-(void)streamsDidOpenOnConnection:(ThoMoTCPConnection *)theConnection; +{ + // look up the connection + NSString *connectionKey = [self keyForConnection:theConnection]; + + // package the parameters into an info dict and relay them to the main thread + NSDictionary *infoDict = [NSDictionary dictionaryWithObjectsAndKeys: + self, kThoMoNetworkInfoKeyLocalNetworkStub, + connectionKey, kThoMoNetworkInfoKeyRemoteConnectionIdString, + nil]; + + [self performSelectorOnMainThread:@selector(connectionEstablishedRelayMethod:) withObject:infoDict waitUntilDone:NO]; +} + +-(void)streamEndEncountered:(NSStream *)theStream onConnection:(ThoMoTCPConnection *)theConnection; +{ + NSString *connectionKey = [self keyForConnection:theConnection]; + + NSString *userMessage = [NSString stringWithFormat:@"Stream end event encountered on stream to %@! Closing connection.", connectionKey]; + + [theConnection close]; + + @synchronized(self) + { + [connections removeObjectForKey:connectionKey]; + } + + NSDictionary *infoDict = [NSDictionary dictionaryWithObjectsAndKeys: + self, kThoMoNetworkInfoKeyLocalNetworkStub, + connectionKey, kThoMoNetworkInfoKeyRemoteConnectionIdString, + userMessage, kThoMoNetworkInfoKeyUserMessage, + nil]; + + [self performSelectorOnMainThread:@selector(connectionClosedRelayMethod:) withObject:infoDict waitUntilDone:NO]; +} + +-(void)streamErrorEncountered:(NSStream *)theStream onConnection:(ThoMoTCPConnection *)theConnection; +{ + NSString *connectionKey = [self keyForConnection:theConnection]; + + NSError *theError = [theStream streamError]; + NSString *userMessage = [NSString stringWithFormat:@"Error %i: \"%@\" on stream to %@! Terminating connection.", (int)[theError code], [theError localizedDescription], connectionKey]; + + [theConnection close]; + + @synchronized(self) + { + [connections removeObjectForKey:connectionKey]; + } + + NSDictionary *infoDict = [NSDictionary dictionaryWithObjectsAndKeys: + self, kThoMoNetworkInfoKeyLocalNetworkStub, + connectionKey, kThoMoNetworkInfoKeyRemoteConnectionIdString, + userMessage, kThoMoNetworkInfoKeyUserMessage, + nil]; + + [self performSelectorOnMainThread:@selector(connectionLostRelayMethod:) withObject:infoDict waitUntilDone:NO]; +} + + + +// ===================================================================================================================== +#pragma mark - +#pragma mark Protected Methods +// --------------------------------------------------------------------------------------------------------------------- + + +-(BOOL)setup +{ + return YES; +} + +-(void)teardown +{ + // close all open connections + @synchronized(self) + { + for (ThoMoTCPConnection *connection in [connections allValues]) { + [connection close]; + } + + [connections removeAllObjects]; + } +} + +-(NSString *)keyStringFromAddress:(NSData *)addr; +{ + // get the peer socket address from the NSData object + // NOTE: there actually is a struct sockaddr in there, NOT a struct sockaddr_in! + // I heard from beej () that they share the same 15 first bytes so casting should not be a problem. + // You've been warned, though... + struct sockaddr_in *peerSocketAddress = (struct sockaddr_in *)[addr bytes]; + + // convert in_addr to ascii (note: returns a pointer to a statically allocated buffer inside inet_ntoa! calling again will overwrite) + char *humanReadableAddress = inet_ntoa(peerSocketAddress->sin_addr); + NSString *peerAddress = [NSString stringWithCString:humanReadableAddress encoding:NSUTF8StringEncoding]; + NSString *peerPort = [NSString stringWithFormat:@"%d", ntohs(peerSocketAddress->sin_port)]; + NSString *peerKey = [NSString stringWithFormat:@"%@:%@", peerAddress, peerPort]; + + return peerKey; +} + +-(NSString *)keyForConnection:(ThoMoTCPConnection *)theConnection; +{ + NSString *connectionKey; + NSArray *keys; + @synchronized(self) + { + keys = [connections allKeysForObject:theConnection]; + NSAssert([keys count] == 1, @"More than one connection record in dict for a single connection."); + connectionKey = [[keys objectAtIndex:0] copy]; + } + + return [connectionKey autorelease]; +} + + +-(void) openNewConnection:(NSString *)theConnectionKey inputStream:(NSInputStream *)istr outputStream:(NSOutputStream *)ostr; +{ + // create a new ThoMoTCPConnection object and set ourselves as the delegate to forward the incoming data to our own delegate + ThoMoTCPConnection *newConnection = [[ThoMoTCPConnection alloc] initWithDelegate:self inputStream:istr outputStream:ostr]; + + // store in our dictionary, open, and release our copy + @synchronized(self) + { + // it should never happen that we overwrite a connection + NSAssert(![connections valueForKey:theConnectionKey], @"ERROR: Tried to create a connection with an IP and port that we already have a connection for."); + + [connections setValue:newConnection forKey:theConnectionKey]; + } + [newConnection open]; + [newConnection release]; +} + +@end + + + +#pragma mark - +#pragma mark Main Thread Relay Methods + +@implementation ThoMoNetworkStub (RelayMethods) + +-(void)networkStubDidShutDownRelayMethod +{ + NSLog(@"%@ :: %@", [self description], NSStringFromSelector(_cmd)); +} + +-(void)netServiceProblemRelayMethod:(NSDictionary *)infoDict +{ + NSLog(@"%@ :: %@", [self description], NSStringFromSelector(_cmd)); +} + +-(void)didReceiveDataRelayMethod:(NSDictionary *)infoDict; +{ + NSLog(@"%@ :: %@", [self description], NSStringFromSelector(_cmd)); +} + +-(void)connectionEstablishedRelayMethod:(NSDictionary *)infoDict; +{ + NSLog(@"%@ :: %@", [self description], NSStringFromSelector(_cmd)); +} + +-(void)connectionLostRelayMethod:(NSDictionary *)infoDict; +{ + NSLog(@"%@ :: %@", [self description], NSStringFromSelector(_cmd)); +} + +-(void)connectionClosedRelayMethod:(NSDictionary *)infoDict; +{ + NSLog(@"%@ :: %@", [self description], NSStringFromSelector(_cmd)); +} + + +#pragma mark - +#pragma mark Debugging + + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoNetworking.h b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoNetworking.h new file mode 100644 index 0000000000..d94664c642 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoNetworking.h @@ -0,0 +1,46 @@ +/* + * ThoMoNetworking.h + * ThoMoNetworkingFramework + * + * Created by Thorsten Karrer on 16.3.10. + * Copyright 2010 media computing group - RWTH Aachen University. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + + + + +#import +#import +#import +#import + +/// Debugging pList key. +/** + If a string is set for this key in the current defaults domain the string will be prepended to the protocol id string. + This can be handy when a fully connected bipartite graph is not desirable, e.g., for debugging purposes. + + \note Note that the prepended string plus a delimiter ('-') both count towards the length limit for protocol identifier strings of 14 characters! + */ +extern NSString *const kThoMoNetworkPrefScopeSpecifierKey; \ No newline at end of file diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoServer/ThoMoServerDelegateProtocol.h b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoServer/ThoMoServerDelegateProtocol.h new file mode 100644 index 0000000000..e184a9b1d3 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoServer/ThoMoServerDelegateProtocol.h @@ -0,0 +1,68 @@ +/* + * ThoMoServerDelegateProtocol.h + * ThoMoNetworkingFramework + * + * Created by Thorsten Karrer on 6/8/09. + * Copyright 2010 media computing group - RWTH Aachen University. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +@class ThoMoServerStub; + + + +@protocol ThoMoServerDelegateProtocol + +@optional + +/// Connection notification (optional) +- (void)server:(ThoMoServerStub *)theServer acceptedConnectionFromClient:(NSString *)aClientIdString; + + +/// Disconnection notification (optional) +- (void)server:(ThoMoServerStub *)theServer lostConnectionToClient:(NSString *)aClientIdString errorMessage:(NSString *)errorMessage; + + +/// Bonjour problem notification (optional) +- (void)netServiceProblemEncountered:(NSString *)errorMessage onServer:(ThoMoServerStub *)theServer; + + +/// Client shutdown notification (optional) +- (void)serverDidShutDown:(ThoMoServerStub *)theServer; + + + +@required + +/// Data received notification (required) +/** + Sent to its delegate by the server stub on the main thread whenever it received data from a client. + + \param[in] theServer The server stub that received the data. + \param[in] theData The object that was bein received. + \param[in] aClientIdString A string designating the client that sent the data. + */ +-(void)server:(ThoMoServerStub *)theServer didReceiveData:(id)theData fromClient:(NSString *)aClientIdString; + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoServer/ThoMoServerStub.m b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoServer/ThoMoServerStub.m new file mode 100644 index 0000000000..77f976026c --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoServer/ThoMoServerStub.m @@ -0,0 +1,450 @@ +/* + * ThoMoServerStub.m + * ThoMoNetworkingFramework + * + * Created by Thorsten Karrer on 29.6.09. + * Copyright 2010 media computing group - RWTH Aachen University. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + + +#import "ThoMoServerStub_private.h" +#import +#import +#import +#import "ThoMoTCPConnection.h" + +#ifdef THOMO_NEEDS_NETWORKING_INCLUDES +#import +#import +#endif + +#define kThoMoNetworkInfoKeyServer kThoMoNetworkInfoKeyLocalNetworkStub +#define kThoMoNetworkInfoKeyClient kThoMoNetworkInfoKeyRemoteConnectionIdString + +#define NO_INFO_RETAIN_CALLBACK NULL +#define NO_INFO_RELEASE_CALLBACK NULL +#define NO_INFO_COPY_DESCRIPTION_CALLBACK NULL +#define APPLE_DEFINED_ZERO 0 +#define SOME_FREE_PORT 0 + + +// ===================================================================================================================== + +#pragma mark - +#pragma mark Private Interfaces +#pragma mark - + +// interface extension for 'private' properties +@interface ThoMoServerStub() +@property (nonatomic, retain) NSNetService *netService; +@property (assign) uint16_t listenPort; +@end + +// interface category for private methods +@interface ThoMoServerStub(Private) +-(void) handleNewConnectionFromAddress:(NSData *)addr inputStream:(NSInputStream *)istr outputStream:(NSOutputStream *)ostr; +@end + +// interface category for main thread relay methods +@interface ThoMoServerStub(RelayMethods) +-(void)netServiceProblemRelayMethod:(NSDictionary *)infoDict; +-(void)didReceiveDataRelayMethod:(NSDictionary *)infoDict; +-(void)clientDidConnectToServerRelayMethod:(NSDictionary *)infoDict; +-(void)clientDidDisconnectFromServerRelayMethod:(NSDictionary *)infoDict; +@end + +// ===================================================================================================================== + + + + + +// ===================================================================================================================== + +#pragma mark - +#pragma mark ServerStub +#pragma mark - + +@implementation ThoMoServerStub + +#pragma mark Properties + +@synthesize delegate; + + +#pragma mark Housekeeping + +-(id)initWithProtocolIdentifier:(NSString *)theProtocolIdentifier andPort:(uint16_t)thePort; +{ + self = [super initWithProtocolIdentifier:theProtocolIdentifier]; + if (self != nil) { + // add inits here + self.listenPort = thePort; + } + return self; +} + + +-(id)initWithProtocolIdentifier:(NSString *)theProtocolIdentifier; +{ + self = [self initWithProtocolIdentifier:theProtocolIdentifier andPort:SOME_FREE_PORT]; + return self; +} + + + +#pragma mark Control + +-(NSArray *)connectedClients; +{ + return [super activeConnections]; +} + +-(void)send:(id)anObject toClient:(NSString *)theClientIdString; +{ + [super send:anObject toConnection:theClientIdString]; +} + +-(void)sendToAllClients:(id)theData; +{ + for (NSString *aClientId in [self connectedClients]) + { + // TODO: this might raise an exception - we should take care to catch and probably re-raise to have the data be sent to at least the rest of the connections + [self send:theData toClient:aClientId]; + } +} + +-(void)sendData:(id)theData toClient:(NSString *)theClientIdString; +{ + [self send:theData toClient:theClientIdString]; +} + +-(void)sendBytes:(NSData *)theBytes toClient:(NSString *)theClientIdString; +{ + [super sendByteData:theBytes toConnection:theClientIdString]; +} + + + + +// --------------------------------------------------------------------------------------------------------------------- +#pragma mark - +#pragma mark Private +// --------------------------------------------------------------------------------------------------------------------- + +#pragma mark Properties + +@synthesize netService; +@synthesize listenPort; + + +#pragma mark Callbacks + +// This function is called by CFSocket when a new connection comes in at our listening socket. +static void ServerStubAcceptCallback(CFSocketRef listenSocket, CFSocketCallBackType callbackType, CFDataRef address, const void *pChildSocketNativeHandle, void *info) +{ + // check if this is the right callback + if (callbackType == kCFSocketAcceptCallBack) { + + // we have packaged up the server object in the info pointer + ThoMoServerStub *server = (ThoMoServerStub *)info; + + // get the BSD child socket for the new connection + CFSocketNativeHandle childSocketNativeHandle = *(CFSocketNativeHandle *)pChildSocketNativeHandle; + + // get the socket address of the peer that connected on our listening socket using the peer's name + uint8_t peerName[SOCK_MAXADDRLEN]; + socklen_t namelength = sizeof(peerName); + NSData *peerSocketAddress = nil; + if (0 == getpeername(childSocketNativeHandle, (struct sockaddr *)peerName, &namelength)) + peerSocketAddress = [NSData dataWithBytes:peerName length:namelength]; + + // create a pair of input and output streams on the child socket + CFReadStreamRef readStream = NULL; + CFWriteStreamRef writeStream = NULL; + CFStreamCreatePairWithSocket(kCFAllocatorDefault, childSocketNativeHandle, &readStream, &writeStream); + + // set the stream properties to close the socket when we're done with the streams + // announce the streams and peer address to the server object (remember, this is just a C callback) + if (readStream && writeStream) + { + CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); + CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); + [server handleNewConnectionFromAddress:peerSocketAddress inputStream:(NSInputStream *)readStream outputStream:(NSOutputStream *)writeStream]; + } + else + { + // on any failure, need to destroy the CFSocketNativeHandle + // since we are not going to use it any more + close(childSocketNativeHandle); + } + + // clean up + if (readStream) CFRelease(readStream); + if (writeStream) CFRelease(writeStream); + } +} + + +#pragma mark Methods + +-(void) handleNewConnectionFromAddress:(NSData *)addr inputStream:(NSInputStream *)istr outputStream:(NSOutputStream *)ostr; +{ + // first convert addr to a key string of format "IP-Address:Port" + // the whole retain thing is because of all the threads bouncing around + NSString *connectionKey = [[[self keyStringFromAddress:addr] retain] autorelease]; + + // now let the superclass create, open, and register a new ThoMoTCPConnection object + [super openNewConnection:connectionKey inputStream:istr outputStream:ostr]; +} + + +-(BOOL)setup; +{ + if (![super setup]) + return NO; + + // ----------- SOCKET STUFF ----------- + + // create socket context. we pass the server object as the info pointer to access it later from the callbacks + CFSocketContext socketContext = {APPLE_DEFINED_ZERO, self, NO_INFO_RETAIN_CALLBACK, NO_INFO_RELEASE_CALLBACK, NO_INFO_COPY_DESCRIPTION_CALLBACK}; + + // create the socket we will use to listen for incoming connections. Here, we can directly install an auto-accepting callback on the socket - handy! + listenSocket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, (CFSocketCallBack)&ServerStubAcceptCallback, &socketContext); + if (NULL == listenSocket) + //TODO: raise exception etc... + return NO; + + // set socket options to reuse socket if the connection breaks + int yes = 1; + setsockopt(CFSocketGetNative(listenSocket), SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes)); + + // fill in the address structure we will use to bind the socket (let the kernel choose the port automatically) + struct sockaddr_in listenSocketAddress; + memset(&listenSocketAddress, 0, sizeof(listenSocketAddress)); + listenSocketAddress.sin_len = sizeof(listenSocketAddress); + listenSocketAddress.sin_family = AF_INET; + listenSocketAddress.sin_port = htons(self.listenPort); // 0 means some free port + listenSocketAddress.sin_addr.s_addr = htonl(INADDR_ANY); // our own address + NSData *listenSocketAddressData = [NSData dataWithBytes:&listenSocketAddress length:sizeof(listenSocketAddress)]; + + // bind & listen (in cocoa this is done via the CFSocketSetAddress call) + if (kCFSocketSuccess != CFSocketSetAddress(listenSocket, (CFDataRef)listenSocketAddressData)) + { + if (listenSocket) CFRelease(listenSocket); + listenSocket = NULL; + //TODO: raise exception etc... + return NO; + } + + // get the port number the kernel chose for us (we need it for bonjour) + listenSocketAddressData = [(NSData *)CFSocketCopyAddress(listenSocket) autorelease]; + memcpy(&listenSocketAddress, [listenSocketAddressData bytes], [listenSocketAddressData length]); + + self.listenPort = ntohs(listenSocketAddress.sin_port); + + // create a RunLoopSource from the socket + CFRunLoopRef runLoop = CFRunLoopGetCurrent(); + CFRunLoopSourceRef listenSocketSource = CFSocketCreateRunLoopSource(kCFAllocatorDefault, listenSocket, 0); + + // add it to the runloop + CFRunLoopAddSource(runLoop, listenSocketSource, kCFRunLoopCommonModes); + CFRelease(listenSocketSource); + + + // ----------- BONJOUR STUFF ----------- + + // use default name and local domain for our bonjour service + NSString *domain = @"local."; + NSString *name = @""; + + // The Bonjour application protocol, which must: + // 1) be no longer than 14 characters + // 2) contain only lower-case letters, digits, and hyphens + // 3) begin and end with lower-case letter or digit + // It should also be descriptive and human-readable + // See the following for more information: + // http://developer.apple.com/networking/bonjour/faq.html + NSString *protocol = [NSString stringWithFormat:@"_%@._tcp.", protocolIdentifier]; + + // create our service object which we want to publish + self.netService = [[[NSNetService alloc] initWithDomain:domain type:protocol name:name port:self.listenPort] autorelease]; + if(nil == self.netService) { + if (listenSocket) CFRelease(listenSocket); + listenSocket = NULL; + //TODO: raise exception etc... + return NO; + } + + // register ourselves as delegate so we know if the publishing did work + [self.netService setDelegate:self]; + + // publish the service + [self.netService scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; + [self.netService publish]; + + return YES; +} + + +-(void)teardown +{ + // disable our bonjour service + if (self.netService) { + [self.netService stop]; + [self.netService removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; + } + + self.netService = nil; + + // invalidate the socket (also removes it from the run loop and releases the socket context structure) + if (listenSocket) { + CFSocketInvalidate(listenSocket); + } + + // release the socket + if (listenSocket) { + CFRelease(listenSocket); + listenSocket = NULL; + } + + [super teardown]; +} + + + +// --------------------------------------------------------------------------------------------------------------------- +#pragma mark - +#pragma mark Delegate Methods +// --------------------------------------------------------------------------------------------------------------------- + +#pragma mark Bonjour + +- (void)netServiceWillPublish:(NSNetService *)sender; +{ + NSLog(@"Netservice is about to be published."); +} + + +- (void)netService:(NSNetService *)sender didNotPublish:(NSDictionary *)errorDict; +{ + if([sender isEqual:netService]) + { + NSString *userMessage = [NSString stringWithFormat:@"Our Netservice did not publish. Error %@", [errorDict objectForKey:NSNetServicesErrorCode]]; + + NSDictionary *infoDict = [NSDictionary dictionaryWithObjectsAndKeys: + self, kThoMoNetworkInfoKeyServer, + userMessage, kThoMoNetworkInfoKeyUserMessage, + nil]; + + [self performSelectorOnMainThread:@selector(netServiceProblemRelayMethod:) withObject:infoDict waitUntilDone:NO]; + } +} + + +- (void)netServiceDidPublish:(NSNetService *)sender; +{ + NSLog(@"Netservice has been published."); +} + + +- (void)netServiceDidStop:(NSNetService *)sender; +{ + if([sender isEqual:netService]) + { + NSString *userMessage = [NSString stringWithFormat:@"Our Netservice did stop!"]; + + NSDictionary *infoDict = [NSDictionary dictionaryWithObjectsAndKeys: + self, kThoMoNetworkInfoKeyServer, + userMessage, kThoMoNetworkInfoKeyUserMessage, + nil]; + + [self performSelectorOnMainThread:@selector(netServiceProblemRelayMethod:) withObject:infoDict waitUntilDone:NO]; + } +} + + + +// --------------------------------------------------------------------------------------------------------------------- +#pragma mark - +#pragma mark Main Thread Relay Methods +// --------------------------------------------------------------------------------------------------------------------- + +-(void)networkStubDidShutDownRelayMethod +{ + if ([delegate respondsToSelector:@selector(serverDidShutDown:)]) + [delegate serverDidShutDown:self]; +} + + +-(void)netServiceProblemRelayMethod:(NSDictionary *)infoDict +{ + if ([delegate respondsToSelector:@selector(netServiceProblemEncountered:onServer:)]) + [delegate netServiceProblemEncountered:[infoDict objectForKey:kThoMoNetworkInfoKeyUserMessage] onServer:self]; +} + + +// required +-(void)didReceiveDataRelayMethod:(NSDictionary *)infoDict; +{ + [delegate server:[infoDict objectForKey:kThoMoNetworkInfoKeyServer] + didReceiveData:[infoDict objectForKey:kThoMoNetworkInfoKeyData] + fromClient:[infoDict objectForKey:kThoMoNetworkInfoKeyClient]]; +} + + +-(void)connectionEstablishedRelayMethod:(NSDictionary *)infoDict; +{ + if ([delegate respondsToSelector:@selector(server:acceptedConnectionFromClient:)]) + [delegate server:[infoDict objectForKey:kThoMoNetworkInfoKeyServer] acceptedConnectionFromClient:[infoDict objectForKey:kThoMoNetworkInfoKeyClient]]; +} + + +-(void)connectionLostRelayMethod:(NSDictionary *)infoDict; +{ + if ([delegate respondsToSelector:@selector(server:lostConnectionToClient:errorMessage:)]) + [delegate server:[infoDict objectForKey:kThoMoNetworkInfoKeyServer] + lostConnectionToClient:[infoDict objectForKey:kThoMoNetworkInfoKeyClient] + errorMessage:[infoDict objectForKey:kThoMoNetworkInfoKeyUserMessage]]; +} + + +-(void)connectionClosedRelayMethod:(NSDictionary *)infoDict; +{ + if ([delegate respondsToSelector:@selector(server:lostConnectionToClient:errorMessage:)]) + [delegate server:[infoDict objectForKey:kThoMoNetworkInfoKeyServer] + lostConnectionToClient:[infoDict objectForKey:kThoMoNetworkInfoKeyClient] + errorMessage:[infoDict objectForKey:kThoMoNetworkInfoKeyUserMessage]]; +} + + +// --------------------------------------------------------------------------------------------------------------------- +#pragma mark - +#pragma mark Debugging +// --------------------------------------------------------------------------------------------------------------------- + +// empty + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoServer/ThoMoServerStub_private.h b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoServer/ThoMoServerStub_private.h new file mode 100644 index 0000000000..48343c2033 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoServer/ThoMoServerStub_private.h @@ -0,0 +1,54 @@ +/* + * ThoMoServerStub.h + * ThoMoNetworkingFramework + * + * Created by Thorsten Karrer on 29.6.09. + * Copyright 2010 media computing group - RWTH Aachen University. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import "ThoMoServerDelegateProtocol.h" +#import "ThoMoNetworkStub.h" + +@interface ThoMoServerStub : ThoMoNetworkStub { + + id delegate; + + uint16_t listenPort; + CFSocketRef listenSocket; + NSNetService *netService; + +} + +@property (assign) id delegate; + +-(NSArray *)connectedClients; + +-(void)sendData:(id)theData toClient:(NSString *)theClientIdString DEPRECATED_ATTRIBUTE; +-(void)sendBytes:(NSData *)theBytes toClient:(NSString *)theClientIdString; + +-(void)send:(id)anObject toClient:(NSString *)theClientIdString; +-(void)sendToAllClients:(id)theData; + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoServerStub.h b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoServerStub.h new file mode 100644 index 0000000000..a40b3f7737 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoServerStub.h @@ -0,0 +1,111 @@ +/* + * ThoMoServerStub.h + * ThoMoNetworkingFramework + * + * Created by Thorsten Karrer on 28.9.09. + * Copyright 2010 media computing group - RWTH Aachen University. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import "ThoMoServerDelegateProtocol.h" + +@interface ThoMoServerStub : NSObject +{ +} + +/// Delegate accessor +/** + Accessor for the server stubs delegate. Must be compliant to ThoMoServerDelegateProtocol. + */ +@property (assign) id delegate; + + + +/// Designated initializer +/** + Initializes the Stub with a protocol identifier string. When started, this server stub will automatically connect to all client stubs (ThoMoClientStub) on the local network that use the same protocol identifier. The server stub will listen on a random free port for client connections. + + \param[in] theProtocolIdentifier A user-definable string of maximum 14 characters length. Determines which client stubs this server stub connects to. + + \throws ThoMoInvalidArgumentException if theProtocolIdentifier exceeds 14 characters in length. + */ +-(id)initWithProtocolIdentifier:(NSString *)theProtocolIdentifier; + + + +/// Starts the server stub +/** + Starts the server stub on a background thread. The stub will auto-connect to each client with the same protocol identifier. May be called only once during the lifetime of the stub. + + \throws ThoMoStubAlreadyRunningException if the server stub had already been started before. + */ +-(void) start; + + + +/// Stops the server stub +/** + Stops the server stub and cancels the associated network thread. This will close all open connections. May be called only once during the lifetime of the stub. + */ +-(void) stop; + + + +/// Returns an array of the connected clients +/** + Returns an array of id-strings for all clients that are currently connected to the server stub. You can use these id-strings to send objects to any of the clients by calling -send:toClient:. + + \returns an array of id-strings for all connected clients. + */ +-(NSArray *)connectedClients; + + + +/// Sends an object to a connected client +/** + Sends anObject to the client designated by theClientIdString. + \note Note that actually a copy of the object is being created on the other side of the connection. Altering the internal state of the object on either side of the connection is not reflected on the other side! + + \param[in] anObject An NSCoding compliant object that will be copied and re-created at the client stub. + \param[in] theServerIdString A string the client to send the object to. Must be taken from the array returned by connectedClients. + + \throws ThoMoInvalidArgumentException if theServerIdString does not designate a client the stub is connected to. + */ +-(void)send:(id)anObject toClient:(NSString *)theClientIdString; + + + +/// Sends an object to all connected clients +/** + Sends anObject to all clients in the array returned by connectedClients. + \note Note that actually a copy of the object is being created on the other sides of the connections. Altering the internal state of the object on either side of the connections is not reflected on the other sides! + + \param[in] anObject An NSCoding compliant object that will be copied and re-created at the client stubs. + */ +-(void)sendToAllClients:(id)theData; + + + +-(void)sendData:(id)theData toClient:(NSString *)theClientIdString DEPRECATED_ATTRIBUTE; +@end diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoTCPConnection.h b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoTCPConnection.h new file mode 100644 index 0000000000..cac649e19a --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoTCPConnection.h @@ -0,0 +1,88 @@ +/* + * ThoMoTCPConnection.h + * ThoMoNetworkingFramework + * + * Created by Thorsten Karrer on 30.6.09. + * Copyright 2010 media computing group - RWTH Aachen University. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import "ThoMoTCPConnectionDelegateProtocol.h" + +typedef enum ServerStubSubPackets { + kServerStubSubPacketHeader, + kServerStubSubPacketData, + kServerStubSubPacketCount +} ServerStubSubPacket; + +@class ThoMoServerStub; + +@interface ThoMoTCPConnection : NSObject +{ + id delegate; + + NSInputStream *inStream; + NSOutputStream *outStream; + + BOOL inReady; + BOOL outReady; + + BOOL streamsCanOpen; + + BOOL openCallbackSent; + + // receiving + ServerStubSubPacket nextExpectedSubpacket; + uint32_t bytesMissingForNextSubpacket; + uint8_t *dataBuffer; + uint8_t *dataBufferCursor; + + //sending + NSMutableArray *sendObjectsQueue; + NSMutableData *currentSendObject; + uint32_t bytesRemainingToSend; + uint8_t *sendBuffer; + uint8_t *sendBufferCursor; + BOOL outStreamHasSpaceAvailableEventIgnored; + + //keepalive + NSTimer *keepaliveSendTimer; + + // reentrancy tracking + BOOL threadIsPresentInMethod; +} + +@property (assign) id delegate; + +-(id)initWithDelegate:(id )theDelegate inputStream:(NSInputStream *)theInStream outputStream:(NSOutputStream *)theOutStream; + +-(void)open; +-(void)close; + +-(void)setupKeepalive; +-(void)teardownKeepalive; + +-(void)enqueueNextSendObject:(NSData *)theData; + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoTCPConnection.m b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoTCPConnection.m new file mode 100644 index 0000000000..a5672ba46d --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoTCPConnection.m @@ -0,0 +1,386 @@ +/* + * ThoMoTCPConnection.m + * ThoMoNetworkingFramework + * + * Created by Thorsten Karrer on 30.6.09. + * Copyright 2010 media computing group - RWTH Aachen University. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#import "ThoMoTCPConnection.h" + +#define HEADERSIZE 4 +#define CHUNKSIZE 1024 + +@implementation ThoMoTCPConnection + +@synthesize delegate; + +- (id) init +{ + return [self initWithDelegate:nil inputStream:nil outputStream:nil]; +} + + +-(id)initWithDelegate:(id )theDelegate inputStream:(NSInputStream *)theInStream outputStream:(NSOutputStream *)theOutStream; +{ + self = [super init]; + if (self != nil) { + + if (theDelegate && theInStream && theOutStream) + { + inReady = NO; + outReady = NO; + streamsCanOpen = YES; + openCallbackSent = NO; + + dataBuffer = (uint8_t *)malloc(HEADERSIZE); + dataBufferCursor = dataBuffer; + bytesMissingForNextSubpacket = HEADERSIZE; + nextExpectedSubpacket = kServerStubSubPacketHeader; + + bytesRemainingToSend = 0; + sendObjectsQueue = [[NSMutableArray alloc] initWithCapacity:5]; + currentSendObject = nil; + + + inStream = [theInStream retain]; + outStream = [theOutStream retain]; + delegate = theDelegate; // do not retain the delegate + + threadIsPresentInMethod = NO; + } + else + { + [self release]; + self = nil; + } + } + return self; +} + +- (void) dealloc +{ + [self close]; + + [inStream release]; + [outStream release]; + + [sendObjectsQueue release]; + + free(dataBuffer); + + if (sendBuffer) + free(sendBuffer); + + [super dealloc]; +} + +-(void)open; +{ + NSAssert(streamsCanOpen, @"Tried to re-open a stream that has already been open at some point - not possible."); + + [inStream setDelegate:self]; + [inStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + [inStream open]; + + [outStream setDelegate:self]; + [outStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + [outStream open]; + + [self setupKeepalive]; + + streamsCanOpen = NO; +} + +-(void)close; +{ + [self teardownKeepalive]; + + // close should also remove it from the runloop - somehow it does not release the runLoop's reference though + [inStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + [inStream close]; + inReady = NO; + + // close should also remove it from the runloop - somehow it does not release the runLoop's reference though + [outStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + [outStream close]; + outReady = NO; +} + +-(void)setupKeepalive; +{ + keepaliveSendTimer = [[NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(sendKeepalive:) userInfo:nil repeats:YES] retain]; +} + +-(void)sendKeepalive:(NSTimer *)theTimer; +{ + NSData *nullData = [[NSData dataWithBytes:NULL length:0] retain]; + [self enqueueNextSendObject:nullData]; + [nullData release]; +} + +-(void)teardownKeepalive; +{ + if (keepaliveSendTimer) { + [keepaliveSendTimer invalidate]; + [keepaliveSendTimer release]; + keepaliveSendTimer = nil; + } +} + +-(void)processBufferAndPrepNextRead +{ + switch (nextExpectedSubpacket) + { + case kServerStubSubPacketHeader: + // parse header and update status + NSAssert(dataBufferCursor == &(dataBuffer[HEADERSIZE]), @"Header expected but wrong number of bytes read into buffer!"); + // ok, because HEADERSIZE == sizeof(bytesMissingForNextSubpacket) + memcpy(&bytesMissingForNextSubpacket, dataBuffer, HEADERSIZE); + uint32_t tmp = ntohl(bytesMissingForNextSubpacket); + bytesMissingForNextSubpacket = tmp; + + //if this is just a keepalive packet it only contains of a header and we can expect another header + if (bytesMissingForNextSubpacket == 0) { + bytesMissingForNextSubpacket = HEADERSIZE; + nextExpectedSubpacket = kServerStubSubPacketHeader; + } + else { + nextExpectedSubpacket = kServerStubSubPacketData; + } + + break; + + case kServerStubSubPacketData: + { + // parse data and update status + NSData *packetData = [[NSData alloc] initWithBytes:dataBuffer length:(dataBufferCursor - dataBuffer)]; + [delegate didReceiveData:packetData onConnection:self]; + [packetData release]; + bytesMissingForNextSubpacket = HEADERSIZE; + nextExpectedSubpacket = kServerStubSubPacketHeader; + break; + } + + default: + NSAssert(NO, @"Packet to process is neither header nor payload"); + break; + } + + // create new receive buffer + free(dataBuffer); + dataBuffer = (uint8_t *)malloc(bytesMissingForNextSubpacket); + + + // reset cursor + dataBufferCursor = dataBuffer; +} + +-(void)dequeueNextSendObject +{ + NSAssert(bytesRemainingToSend == 0, @"Enqueue next send object called although there are still bytes to be sent off"); + + if (sendBuffer) { + free(sendBuffer); + sendBuffer = NULL; + } + + if ([sendObjectsQueue count] > 0) + { + currentSendObject = [[sendObjectsQueue lastObject] retain]; + [sendObjectsQueue removeLastObject]; + + // create new send buffer + uint32_t objectSize = [currentSendObject length]; + uint32_t packetSize = objectSize + HEADERSIZE; + sendBuffer = (uint8_t *)malloc(packetSize); + + // fill it + uint32_t objectSize_n = htonl(objectSize); + memcpy(sendBuffer, &objectSize_n, HEADERSIZE); + memcpy(sendBuffer + HEADERSIZE, [currentSendObject bytes], objectSize); + + // update the cursor and byte counter + sendBufferCursor = sendBuffer; + bytesRemainingToSend = packetSize; + + // release the sendObject + [currentSendObject release]; + } + + // check if we need to re-enable the stream events because we had nothing to send earlier + if (outStreamHasSpaceAvailableEventIgnored && bytesRemainingToSend) + { + // HACK + // this is a hack... not very nice :-/ + [self stream:outStream handleEvent:NSStreamEventHasSpaceAvailable]; + } +} + +-(void)enqueueNextSendObject:(NSData *)theData; +{ + [sendObjectsQueue insertObject:theData atIndex:0]; + + // if we are not sending, trigger a dequeue + if (bytesRemainingToSend == 0) + { + NSAssert([sendObjectsQueue count] == 1, @"We are not sending but the objectSendQueue is not empty!"); + [self dequeueNextSendObject]; + } +} + + +// TODO: READ ME! +// NOTE: This method is NOT safe for reentrancy! +// We have seen in AsyncSocket that a new stream event may be issued during the stream read: and write: calls. +// This, of course, will cause a reentrancy of the same thread into this method which will break things.. badly! +// A solution would be to lock the method conditionally and cache any pending stream events that could not be processed because of the lock. +// For now we only assert that it works. We'll implement the condition if the assertion ever fires... I promise ;) +- (void) stream:(NSStream*)stream handleEvent:(NSStreamEvent)eventCode +{ + NSAssert(!threadIsPresentInMethod, @"We have been caught by the nasty AsyncSocket bug!"); + + threadIsPresentInMethod = YES; + + switch(eventCode) { + case NSStreamEventOpenCompleted: + { + if ([inStream streamStatus] == NSStreamStatusOpen && [outStream streamStatus] == NSStreamStatusOpen && !openCallbackSent) + { + [delegate streamsDidOpenOnConnection:self]; + openCallbackSent = YES; + } + break; + } + case NSStreamEventHasBytesAvailable: + { + //BOOL didCompletePacket = NO; + + while (/*didCompletePacket &&*/ [inStream hasBytesAvailable]) + { + //didCompletePacket = NO; + + // try to read as many bytes as we need for the next subpacket + NSInteger bytesActuallyRead = [inStream read:dataBufferCursor maxLength:bytesMissingForNextSubpacket]; + dataBufferCursor += bytesActuallyRead; + + // if we have enough construct the subpacket and act on it + if (bytesActuallyRead == bytesMissingForNextSubpacket) + { + //didCompletePacket = YES; + [self processBufferAndPrepNextRead]; + } + else if (bytesActuallyRead > 0) + { + bytesMissingForNextSubpacket -= bytesActuallyRead; + //didCompletePacket = NO; + } + else if ([stream streamStatus] == NSStreamStatusAtEnd) + { + // be careful! the delegate might kill us for the bad news... + [delegate streamEndEncountered:stream onConnection:self]; + break; + } + else if ([stream streamStatus] == NSStreamStatusError) + { + // be careful! the delegate might kill us for the bad news... + [delegate streamErrorEncountered:stream onConnection:self]; + break; + } + else + { + NSAssert(NO, @"Could not read bytes from network but stream reports no errors"); + break; + } + + } + + + break; + } + case NSStreamEventHasSpaceAvailable: + { + if (bytesRemainingToSend == 0) + { + outStreamHasSpaceAvailableEventIgnored = YES; + } + else + { + // out stream + outStreamHasSpaceAvailableEventIgnored = NO; + + uint32_t bytesToSend = ((bytesRemainingToSend >= CHUNKSIZE) ? CHUNKSIZE : bytesRemainingToSend); + uint32_t bytesActuallySent = [outStream write:sendBufferCursor maxLength:bytesToSend]; + + bytesRemainingToSend -= bytesActuallySent; + + if (bytesRemainingToSend == 0) + { + // packet has been sent, prepare next + [self dequeueNextSendObject]; + } + else if (bytesActuallySent > 0) + { + // we need to send the rest later + sendBufferCursor += bytesActuallySent; + } + else if ([stream streamStatus] == NSStreamStatusAtEnd) + { + // be careful! the delegate might kill us for the bad news... + [delegate streamEndEncountered:stream onConnection:self]; + } + else if ([stream streamStatus] == NSStreamStatusError || bytesActuallySent == -1) + { + // be careful! the delegate might kill us for the bad news... + [delegate streamErrorEncountered:stream onConnection:self]; + } + else + { + NSAssert(NO, @"Could not write bytes to network but stream reports no errors"); + } + } + + break; + } + case NSStreamEventEndEncountered: + { + // be careful! the delegate might kill us for the bad news... + [delegate streamEndEncountered:stream onConnection:self]; + break; + } + case NSStreamEventErrorOccurred: + { + // be careful! the delegate might kill us for the bad news... + [delegate streamErrorEncountered:stream onConnection:self]; + break; + } + default: + break; + } + + threadIsPresentInMethod = NO; +} + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoTCPConnectionDelegateProtocol.h b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoTCPConnectionDelegateProtocol.h new file mode 100644 index 0000000000..840b79b852 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ThoMoNetworking/ThoMoTCPConnectionDelegateProtocol.h @@ -0,0 +1,43 @@ +/* + * ThoMoTCPConnectionDelegateProtocol.h + * ThoMoNetworkingFramework + * + * Created by Thorsten Karrer on 1.7.09. + * Copyright 2010 media computing group - RWTH Aachen University. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + + +@class ThoMoTCPConnection; + +@protocol ThoMoTCPConnectionDelegateProtocol + +-(void)didReceiveData:(NSData *)theData onConnection:(ThoMoTCPConnection *)theConnection; + +-(void)streamsDidOpenOnConnection:(ThoMoTCPConnection *)theConnection; + +-(void)streamEndEncountered:(NSStream *)theStream onConnection:(ThoMoTCPConnection *)theConnection; +-(void)streamErrorEncountered:(NSStream *)theStream onConnection:(ThoMoTCPConnection *)theConnection; + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/LICENSE b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/LICENSE new file mode 100644 index 0000000000..b904e35840 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2010-2011 Sam Soffes + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/SSZipArchive.h b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/SSZipArchive.h new file mode 100644 index 0000000000..fb8d055aad --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/SSZipArchive.h @@ -0,0 +1,45 @@ +// +// SSZipArchive.h +// SSZipArchive +// +// Created by Sam Soffes on 7/21/10. +// Copyright (c) Sam Soffes 2010-2011. All rights reserved. +// + +#import +#include "minizip/unzip.h" + +@protocol SSZipArchiveDelegate; + +@interface SSZipArchive : NSObject + +// Unzip ++ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination; ++ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error; + ++ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination delegate:(id)delegate; ++ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error delegate:(id)delegate; + +// Zip ++ (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray *)filenames; + +- (id)initWithPath:(NSString *)path; +- (BOOL)open; +- (BOOL)writeFile:(NSString *)path; +- (BOOL)writeData:(NSData *)data filename:(NSString *)filename; +- (BOOL)close; + +@end + + +@protocol SSZipArchiveDelegate + +@optional + +- (void)zipArchiveWillUnzipArchiveAtPath:(NSString *)path zipInfo:(unz_global_info)zipInfo; +- (void)zipArchiveDidUnzipArchiveAtPath:(NSString *)path zipInfo:(unz_global_info)zipInfo unzippedPath:(NSString *)unzippedPath; + +- (void)zipArchiveWillUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath fileInfo:(unz_file_info)fileInfo; +- (void)zipArchiveDidUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath fileInfo:(unz_file_info)fileInfo; + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/SSZipArchive.m b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/SSZipArchive.m new file mode 100644 index 0000000000..93693f52ea --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/SSZipArchive.m @@ -0,0 +1,421 @@ +// +// SSZipArchive.m +// SSZipArchive +// +// Created by Sam Soffes on 7/21/10. +// Copyright (c) Sam Soffes 2010-2011. All rights reserved. +// + +#import "SSZipArchive.h" +#include "minizip/zip.h" +#import "zlib.h" +#import "zconf.h" + +#include + +#define CHUNK 16384 + +@interface SSZipArchive () ++ (NSDate *)_dateWithMSDOSFormat:(UInt32)msdosDateTime; +@end + + +@implementation SSZipArchive { + NSString *_path; + NSString *_filename; + zipFile _zip; +} + + +#pragma mark - Unzipping + ++ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination { + return [self unzipFileAtPath:path toDestination:destination delegate:nil]; +} + + ++ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error { + return [self unzipFileAtPath:path toDestination:destination overwrite:overwrite password:password error:error delegate:nil]; +} + + ++ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination delegate:(id)delegate { + return [self unzipFileAtPath:path toDestination:destination overwrite:YES password:nil error:nil delegate:delegate]; +} + + ++ (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error delegate:(id)delegate { + // Begin opening + zipFile zip = unzOpen((const char*)[path UTF8String]); + if (zip == NULL) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"failed to open zip file" forKey:NSLocalizedDescriptionKey]; + if (error) { + *error = [NSError errorWithDomain:@"SSZipArchiveErrorDomain" code:-1 userInfo:userInfo]; + } + return NO; + } + + unz_global_info globalInfo = {0ul, 0ul}; + unzGetGlobalInfo(zip, &globalInfo); + + // Begin unzipping + if (unzGoToFirstFile(zip) != UNZ_OK) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"failed to open first file in zip file" forKey:NSLocalizedDescriptionKey]; + if (error) { + *error = [NSError errorWithDomain:@"SSZipArchiveErrorDomain" code:-2 userInfo:userInfo]; + } + return NO; + } + + BOOL success = YES; + int ret = 0; + unsigned char buffer[4096] = {0}; + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSMutableSet *directoriesModificationDates = [[NSMutableSet alloc] init]; + + // Message delegate + if ([delegate respondsToSelector:@selector(zipArchiveWillUnzipArchiveAtPath:zipInfo:)]) { + [delegate zipArchiveWillUnzipArchiveAtPath:path zipInfo:globalInfo]; + } + + NSInteger currentFileNumber = 0; + do { + if ([password length] == 0) { + ret = unzOpenCurrentFile(zip); + } else { + ret = unzOpenCurrentFilePassword(zip, [password cStringUsingEncoding:NSASCIIStringEncoding]); + } + + if (ret != UNZ_OK) { + success = NO; + break; + } + + // Reading data and write to file + unz_file_info fileInfo; + memset(&fileInfo, 0, sizeof(unz_file_info)); + + ret = unzGetCurrentFileInfo(zip, &fileInfo, NULL, 0, NULL, 0, NULL, 0); + if (ret != UNZ_OK) { + success = NO; + unzCloseCurrentFile(zip); + break; + } + + // Message delegate + if ([delegate respondsToSelector:@selector(zipArchiveWillUnzipFileAtIndex:totalFiles:archivePath:fileInfo:)]) { + [delegate zipArchiveWillUnzipFileAtIndex:currentFileNumber totalFiles:(NSInteger)globalInfo.number_entry + archivePath:path fileInfo:fileInfo]; + } + + char *filename = (char *)malloc(fileInfo.size_filename + 1); + unzGetCurrentFileInfo(zip, &fileInfo, filename, fileInfo.size_filename + 1, NULL, 0, NULL, 0); + filename[fileInfo.size_filename] = '\0'; + + // + // NOTE + // I used the ZIP spec from here: + // http://www.pkware.com/documents/casestudies/APPNOTE.TXT + // + // ...to deduce this method of detecting whether the file in the ZIP is a symbolic link. + // If it is, it is listed as a directory but has a data size greater than zero (real + // directories have it equal to 0) and the included, uncompressed data is the symbolic link path. + // + // ZIP files did not originally include support for symbolic links so the specification + // doesn't include anything in them that isn't part of a unix extension that isn't being used + // by the archivers we're testing. Most of this is figured out through trial and error and + // reading ZIP headers in hex editors. This seems to do the trick though. + // + + const uLong ZipCompressionMethodStore = 0; + + BOOL fileIsSymbolicLink = NO; + + if((fileInfo.compression_method == ZipCompressionMethodStore) && // Is it compressed? + (S_ISDIR(fileInfo.external_fa)) && // Is it marked as a directory + (fileInfo.compressed_size > 0)) // Is there any data? + { + fileIsSymbolicLink = YES; + } + + // Check if it contains directory + NSString *strPath = [NSString stringWithCString:filename encoding:NSUTF8StringEncoding]; + BOOL isDirectory = NO; + if (filename[fileInfo.size_filename-1] == '/' || filename[fileInfo.size_filename-1] == '\\') { + isDirectory = YES; + } + free(filename); + + // Contains a path + if ([strPath rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"/\\"]].location != NSNotFound) { + strPath = [strPath stringByReplacingOccurrencesOfString:@"\\" withString:@"/"]; + } + + NSString *fullPath = [destination stringByAppendingPathComponent:strPath]; + NSError *err = nil; + NSDate *modDate = [[self class] _dateWithMSDOSFormat:(UInt32)fileInfo.dosDate]; + NSDictionary *directoryAttr = [NSDictionary dictionaryWithObjectsAndKeys:modDate, NSFileCreationDate, modDate, NSFileModificationDate, nil]; + + if (isDirectory) { + [fileManager createDirectoryAtPath:fullPath withIntermediateDirectories:YES attributes:directoryAttr error:&err]; + } else { + [fileManager createDirectoryAtPath:[fullPath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:directoryAttr error:&err]; + } + if (nil != err) { + NSLog(@"[SSZipArchive] Error: %@", err.localizedDescription); + } + + if(!fileIsSymbolicLink) + [directoriesModificationDates addObject: [NSDictionary dictionaryWithObjectsAndKeys:fullPath, @"path", modDate, @"modDate", nil]]; + + if ([fileManager fileExistsAtPath:fullPath] && !isDirectory && !overwrite) { + unzCloseCurrentFile(zip); + ret = unzGoToNextFile(zip); + continue; + } + + if(!fileIsSymbolicLink) + { + FILE *fp = fopen((const char*)[fullPath UTF8String], "wb"); + while (fp) { + int readBytes = unzReadCurrentFile(zip, buffer, 4096); + + if (readBytes > 0) { + fwrite(buffer, readBytes, 1, fp ); + } else { + break; + } + } + + if (fp) { + fclose(fp); + + // Set the original datetime property + if (fileInfo.dosDate != 0) { + NSDate *orgDate = [[self class] _dateWithMSDOSFormat:(UInt32)fileInfo.dosDate]; + NSDictionary *attr = [NSDictionary dictionaryWithObject:orgDate forKey:NSFileModificationDate]; + + if (attr) { + if ([fileManager setAttributes:attr ofItemAtPath:fullPath error:nil] == NO) { + // Can't set attributes + NSLog(@"[SSZipArchive] Failed to set attributes"); + } + } + } + } + } + else + { + // Get the path for the symbolic link + + NSURL* symlinkURL = [NSURL fileURLWithPath:fullPath]; + NSMutableString* destinationPath = [NSMutableString string]; + + int bytesRead = 0; + while((bytesRead = unzReadCurrentFile(zip, buffer, 4096)) > 0) + { + buffer[bytesRead] = 0; + [destinationPath appendString:[NSString stringWithUTF8String:(const char*)buffer]]; + } + + //NSLog(@"Symlinking to: %@", destinationPath); + + NSURL* destinationURL = [NSURL fileURLWithPath:destinationPath]; + + // Create the symbolic link + NSError* symlinkError = nil; + [fileManager createSymbolicLinkAtURL:symlinkURL withDestinationURL:destinationURL error:&symlinkError]; + + if(symlinkError != nil) + { + NSLog(@"Failed to create symbolic link at \"%@\" to \"%@\". Error: %@", symlinkURL.absoluteString, destinationURL.absoluteString, symlinkError.localizedDescription); + } + } + + unzCloseCurrentFile( zip ); + ret = unzGoToNextFile( zip ); + + // Message delegate + if ([delegate respondsToSelector:@selector(zipArchiveDidUnzipFileAtIndex:totalFiles:archivePath:fileInfo:)]) { + [delegate zipArchiveDidUnzipFileAtIndex:currentFileNumber totalFiles:(NSInteger)globalInfo.number_entry + archivePath:path fileInfo:fileInfo]; + } + + currentFileNumber++; + } while(ret == UNZ_OK && UNZ_OK != UNZ_END_OF_LIST_OF_FILE); + + // Close + unzClose(zip); + + // The process of decompressing the .zip archive causes the modification times on the folders + // to be set to the present time. So, when we are done, they need to be explicitly set. + // set the modification date on all of the directories. + NSError * err = nil; + for (NSDictionary * d in directoriesModificationDates) { + if (![[NSFileManager defaultManager] setAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[d objectForKey:@"modDate"], NSFileModificationDate, nil] ofItemAtPath:[d objectForKey:@"path"] error:&err]) { + NSLog(@"[SSZipArchive] Set attributes failed for directory: %@.", [d objectForKey:@"path"]); + } + if (err) { + NSLog(@"[SSZipArchive] Error setting directory file modification date attribute: %@",err.localizedDescription); + } + } + +#if !__has_feature(objc_arc) + [directoriesModificationDates release]; +#endif + + // Message delegate + if (success && [delegate respondsToSelector:@selector(zipArchiveDidUnzipArchiveAtPath:zipInfo:unzippedPath:)]) { + [delegate zipArchiveDidUnzipArchiveAtPath:path zipInfo:globalInfo unzippedPath:destination]; + } + + return success; +} + + +#pragma mark - Zipping + ++ (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray *)paths { + BOOL success = NO; + SSZipArchive *zipArchive = [[SSZipArchive alloc] initWithPath:path]; + if ([zipArchive open]) { + for (NSString *path in paths) { + [zipArchive writeFile:path]; + } + success = [zipArchive close]; + } + +#if !__has_feature(objc_arc) + [zipArchive release]; +#endif + + return success; +} + + +- (id)initWithPath:(NSString *)path { + if ((self = [super init])) { + _path = [path copy]; + } + return self; +} + + +#if !__has_feature(objc_arc) +- (void)dealloc { + [_path release]; + [super dealloc]; +} +#endif + + +- (BOOL)open { + NSAssert((_zip == NULL), @"Attempting open an archive which is already open"); + _zip = zipOpen([_path UTF8String], APPEND_STATUS_CREATE); + return (NULL != _zip); +} + + +- (void)zipInfo:(zip_fileinfo*)zipInfo setDate:(NSDate*)date { + NSCalendar *currentCalendar = [NSCalendar currentCalendar]; + uint flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit; + NSDateComponents *components = [currentCalendar components:flags fromDate:date]; + zipInfo->tmz_date.tm_sec = (unsigned int)components.second; + zipInfo->tmz_date.tm_min = (unsigned int)components.minute; + zipInfo->tmz_date.tm_hour = (unsigned int)components.hour; + zipInfo->tmz_date.tm_mday = (unsigned int)components.day; + zipInfo->tmz_date.tm_mon = (unsigned int)components.month - 1; + zipInfo->tmz_date.tm_year = (unsigned int)components.year; +} + + +- (BOOL)writeFile:(NSString *)path { + NSAssert((_zip != NULL), @"Attempting to write to an archive which was never opened"); + + FILE *input = fopen([path UTF8String], "r"); + if (NULL == input) { + return NO; + } + + zipOpenNewFileInZip(_zip, [[path lastPathComponent] UTF8String], NULL, NULL, 0, NULL, 0, NULL, Z_DEFLATED, + Z_DEFAULT_COMPRESSION); + + void *buffer = malloc(CHUNK); + unsigned int len = 0; + while (!feof(input)) { + len = (unsigned int) fread(buffer, 1, CHUNK, input); + zipWriteInFileInZip(_zip, buffer, len); + } + + zipCloseFileInZip(_zip); + free(buffer); + return YES; +} + + +- (BOOL)writeData:(NSData *)data filename:(NSString *)filename { + if (!_zip) { + return NO; + } + if (!data) { + return NO; + } + zip_fileinfo zipInfo = {{0,0,0,0,0,0},0,0,0}; + [self zipInfo:&zipInfo setDate:[NSDate date]]; + + zipOpenNewFileInZip(_zip, [filename UTF8String], &zipInfo, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION); + + zipWriteInFileInZip(_zip, data.bytes, (unsigned int)data.length); + + zipCloseFileInZip(_zip); + return YES; +} + + +- (BOOL)close { + NSAssert((_zip != NULL), @"[SSZipArchive] Attempting to close an archive which was never opened"); + zipClose(_zip, NULL); + return YES; +} + + +#pragma mark - Private + +// Format from http://newsgroups.derkeiler.com/Archive/Comp/comp.os.msdos.programmer/2009-04/msg00060.html +// Two consecutive words, or a longword, YYYYYYYMMMMDDDDD hhhhhmmmmmmsssss +// YYYYYYY is years from 1980 = 0 +// sssss is (seconds/2). +// +// 3658 = 0011 0110 0101 1000 = 0011011 0010 11000 = 27 2 24 = 2007-02-24 +// 7423 = 0111 0100 0010 0011 - 01110 100001 00011 = 14 33 2 = 14:33:06 ++ (NSDate *)_dateWithMSDOSFormat:(UInt32)msdosDateTime { + static const UInt32 kYearMask = 0xFE000000; + static const UInt32 kMonthMask = 0x1E00000; + static const UInt32 kDayMask = 0x1F0000; + static const UInt32 kHourMask = 0xF800; + static const UInt32 kMinuteMask = 0x7E0; + static const UInt32 kSecondMask = 0x1F; + + NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; + NSDateComponents *components = [[NSDateComponents alloc] init]; + + NSAssert(0xFFFFFFFF == (kYearMask | kMonthMask | kDayMask | kHourMask | kMinuteMask | kSecondMask), @"[SSZipArchive] MSDOS date masks don't add up"); + + [components setYear:1980 + ((msdosDateTime & kYearMask) >> 25)]; + [components setMonth:(msdosDateTime & kMonthMask) >> 21]; + [components setDay:(msdosDateTime & kDayMask) >> 16]; + [components setHour:(msdosDateTime & kHourMask) >> 11]; + [components setMinute:(msdosDateTime & kMinuteMask) >> 5]; + [components setSecond:(msdosDateTime & kSecondMask) * 2]; + + NSDate *date = [NSDate dateWithTimeInterval:0 sinceDate:[gregorian dateFromComponents:components]]; + +#if !__has_feature(objc_arc) + [gregorian release]; + [components release]; +#endif + + return date; +} + +@end diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/crypt.h b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/crypt.h new file mode 100755 index 0000000000..a01d08d932 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/crypt.h @@ -0,0 +1,131 @@ +/* crypt.h -- base code for crypt/uncrypt ZIPfile + + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This code is a modified version of crypting code in Infozip distribution + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + If you don't need crypting in your application, just define symbols + NOCRYPT and NOUNCRYPT. + + This code support the "Traditional PKWARE Encryption". + + The new AES encryption added on Zip format by Winzip (see the page + http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong + Encryption is not supported. +*/ + +#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) + +/*********************************************************************** + * Return the next byte in the pseudo-random sequence + */ +static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) +{ + unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an + * unpredictable manner on 16-bit systems; not a problem + * with any known compiler so far, though */ + + temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; + return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); +} + +/*********************************************************************** + * Update the encryption keys with the next byte of plain text + */ +static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) +{ + (*(pkeys+0)) = CRC32((*(pkeys+0)), c); + (*(pkeys+1)) += (*(pkeys+0)) & 0xff; + (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; + { + register int keyshift = (int)((*(pkeys+1)) >> 24); + (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); + } + return c; +} + + +/*********************************************************************** + * Initialize the encryption keys and the random header according to + * the given password. + */ +static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) +{ + *(pkeys+0) = 305419896L; + *(pkeys+1) = 591751049L; + *(pkeys+2) = 878082192L; + while (*passwd != '\0') { + update_keys(pkeys,pcrc_32_tab,(int)*passwd); + passwd++; + } +} + +#define zdecode(pkeys,pcrc_32_tab,c) \ + (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) + +#define zencode(pkeys,pcrc_32_tab,c,t) \ + (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) + +#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED + +#define RAND_HEAD_LEN 12 + /* "last resort" source for second part of crypt seed pattern */ +# ifndef ZCR_SEED2 +# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ +# endif + +static int crypthead(const char* passwd, /* password string */ + unsigned char* buf, /* where to write header */ + int bufSize, + unsigned long* pkeys, + const unsigned long* pcrc_32_tab, + unsigned long crcForCrypting) +{ + int n; /* index in random header */ + int t; /* temporary */ + int c; /* random byte */ + unsigned char header[RAND_HEAD_LEN-2]; /* random header */ + static unsigned calls = 0; /* ensure different random header each time */ + + if (bufSize> 7) & 0xff; + header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); + } + /* Encrypt random header (last two bytes is high word of crc) */ + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN-2; n++) + { + buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); + } + buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); + buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); + return n; +} + +#endif diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/ioapi.c b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/ioapi.c new file mode 100755 index 0000000000..e0f738297e --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/ioapi.c @@ -0,0 +1,239 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + +*/ + +#if (defined(_WIN32)) + #define _CRT_SECURE_NO_WARNINGS +#endif + +#include "ioapi.h" + +voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode) +{ + if (pfilefunc->zfile_func64.zopen64_file != NULL) + return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode); + else + { + return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode); + } +} + +long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) +{ + if (pfilefunc->zfile_func64.zseek64_file != NULL) + return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin); + else + { + uLong offsetTruncated = (uLong)offset; + if (offsetTruncated != offset) + return -1; + else + return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin); + } +} + +ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream) +{ + if (pfilefunc->zfile_func64.zseek64_file != NULL) + return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream); + else + { + uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream); + if ((tell_uLong) == ((uLong)-1)) + return (ZPOS64_T)-1; + else + return tell_uLong; + } +} + +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32) +{ + p_filefunc64_32->zfile_func64.zopen64_file = NULL; + p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file; + p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; + p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file; + p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file; + p_filefunc64_32->zfile_func64.ztell64_file = NULL; + p_filefunc64_32->zfile_func64.zseek64_file = NULL; + p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file; + +#ifndef __clang_analyzer__ + p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; +#endif + + p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque; + p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file; + p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file; +} + + + +static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode)); +static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size)); +static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream)); +static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream)); +static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream)); + +static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode) +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = fopen(filename, mode_fopen); + return file; +} + +static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode) +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = fopen64((const char*)filename, mode_fopen); + return file; +} + + +static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size) +{ + uLong ret; + ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size) +{ + uLong ret; + ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) +{ + long ret; + ret = ftell((FILE *)stream); + return ret; +} + + +static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream) +{ + ZPOS64_T ret; + ret = ftello64((FILE *)stream); + return ret; +} + +static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin) +{ + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + if (fseek((FILE *)stream, offset, fseek_origin) != 0) + ret = -1; + return ret; +} + +static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) +{ + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + + if(fseeko64((FILE *)stream, offset, fseek_origin) != 0) + ret = -1; + + return ret; +} + + +static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream) +{ + int ret; + ret = fclose((FILE *)stream); + return ret; +} + +static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream) +{ + int ret; + ret = ferror((FILE *)stream); + return ret; +} + +void fill_fopen_filefunc (pzlib_filefunc_def) + zlib_filefunc_def* pzlib_filefunc_def; +{ + pzlib_filefunc_def->zopen_file = fopen_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell_file = ftell_file_func; + pzlib_filefunc_def->zseek_file = fseek_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} + +void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = fopen64_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell64_file = ftell64_file_func; + pzlib_filefunc_def->zseek64_file = fseek64_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/ioapi.h b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/ioapi.h new file mode 100755 index 0000000000..7e20e95130 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/ioapi.h @@ -0,0 +1,201 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + Changes + + Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this) + Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux. + More if/def section may be needed to support other platforms + Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows. + (but you should use iowin32.c for windows instead) + +*/ + +#ifndef _ZLIBIOAPI64_H +#define _ZLIBIOAPI64_H + +#if (!defined(_WIN32)) && (!defined(WIN32)) + + // Linux needs this to support file operation on files larger then 4+GB + // But might need better if/def to select just the platforms that needs them. + + #ifndef __USE_FILE_OFFSET64 + #define __USE_FILE_OFFSET64 + #endif + #ifndef __USE_LARGEFILE64 + #define __USE_LARGEFILE64 + #endif + #ifndef _LARGEFILE64_SOURCE + #define _LARGEFILE64_SOURCE + #endif + #ifndef _FILE_OFFSET_BIT + #define _FILE_OFFSET_BIT 64 + #endif +#endif + +#include +#include +#include "zlib.h" + +#define USE_FILE32API +#if defined(USE_FILE32API) +#define fopen64 fopen +#define ftello64 ftell +#define fseeko64 fseek +#else +#ifdef _MSC_VER + #define fopen64 fopen + #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC))) + #define ftello64 _ftelli64 + #define fseeko64 _fseeki64 + #else // old MSC + #define ftello64 ftell + #define fseeko64 fseek + #endif +#endif +#endif + +/* +#ifndef ZPOS64_T + #ifdef _WIN32 + #define ZPOS64_T fpos_t + #else + #include + #define ZPOS64_T uint64_t + #endif +#endif +*/ + +#ifdef HAVE_MINIZIP64_CONF_H +#include "mz64conf.h" +#endif + +/* a type choosen by DEFINE */ +#ifdef HAVE_64BIT_INT_CUSTOM +typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T; +#else +#ifdef HAS_STDINT_H +#include "stdint.h" +typedef uint64_t ZPOS64_T; +#else + + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef unsigned __int64 ZPOS64_T; +#else +typedef unsigned long long int ZPOS64_T; +#endif +#endif +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define ZLIB_FILEFUNC_SEEK_CUR (1) +#define ZLIB_FILEFUNC_SEEK_END (2) +#define ZLIB_FILEFUNC_SEEK_SET (0) + +#define ZLIB_FILEFUNC_MODE_READ (1) +#define ZLIB_FILEFUNC_MODE_WRITE (2) +#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) + +#define ZLIB_FILEFUNC_MODE_EXISTING (4) +#define ZLIB_FILEFUNC_MODE_CREATE (8) + + +#ifndef ZCALLBACK + #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) + #define ZCALLBACK CALLBACK + #else + #define ZCALLBACK + #endif +#endif + + + + +typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); +typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); +typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); + +typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); + + +/* here is the "old" 32 bits structure structure */ +typedef struct zlib_filefunc_def_s +{ + open_file_func zopen_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell_file_func ztell_file; + seek_file_func zseek_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc_def; + +typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode)); + +typedef struct zlib_filefunc64_def_s +{ + open64_file_func zopen64_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell64_file_func ztell64_file; + seek64_file_func zseek64_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc64_def; + +void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def)); +void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); + +/* now internal definition, only for zip.c and unzip.h */ +typedef struct zlib_filefunc64_32_def_s +{ + zlib_filefunc64_def zfile_func64; + open_file_func zopen32_file; + tell_file_func ztell32_file; + seek_file_func zseek32_file; +} zlib_filefunc64_32_def; + + +#define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) +#define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) +//#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream)) +//#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode)) +#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream)) +#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream)) + +voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)); +long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)); +ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)); + +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32); + +#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode))) +#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream))) +#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode))) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/mztools.c b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/mztools.c new file mode 100755 index 0000000000..80d50e0082 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/mztools.c @@ -0,0 +1,284 @@ +/* + Additional tools for Minizip + Code: Xavier Roche '2004 + License: Same as ZLIB (www.gzip.org) +*/ + +/* Code */ +#include +#include +#include +#include "zlib.h" +#include "unzip.h" +#include "mztools.h" + +#define READ_8(adr) ((unsigned char)*(adr)) +#define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) ) +#define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) ) + +#define WRITE_8(buff, n) do { \ + *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \ +} while(0) +#define WRITE_16(buff, n) do { \ + WRITE_8((unsigned char*)(buff), n); \ + WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \ +} while(0) +#define WRITE_32(buff, n) do { \ + WRITE_16((unsigned char*)(buff), (n) & 0xffff); \ + WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \ +} while(0) + +extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered) +const char* file; +const char* fileOut; +const char* fileOutTmp; +uLong* nRecovered; +uLong* bytesRecovered; +{ + int err = Z_OK; + FILE* fpZip = fopen(file, "rb"); + FILE* fpOut = fopen(fileOut, "wb"); + FILE* fpOutCD = fopen(fileOutTmp, "wb"); + if (fpZip != NULL && fpOut != NULL) { + int entries = 0; + uLong totalBytes = 0; + char header[30]; + char filename[256]; + char extra[1024]; + int offset = 0; + int offsetCD = 0; + while ( fread(header, 1, 30, fpZip) == 30 ) { + int currentOffset = offset; + + /* File entry */ + if (READ_32(header) == 0x04034b50) { + unsigned int version = READ_16(header + 4); + unsigned int gpflag = READ_16(header + 6); + unsigned int method = READ_16(header + 8); + unsigned int filetime = READ_16(header + 10); + unsigned int filedate = READ_16(header + 12); + unsigned int crc = READ_32(header + 14); /* crc */ + unsigned int cpsize = READ_32(header + 18); /* compressed size */ + unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */ + unsigned int fnsize = READ_16(header + 26); /* file name length */ + unsigned int extsize = READ_16(header + 28); /* extra field length */ + filename[0] = extra[0] = '\0'; + + /* Header */ + if (fwrite(header, 1, 30, fpOut) == 30) { + offset += 30; + } else { + err = Z_ERRNO; + break; + } + + /* Filename */ + if (fnsize > 0) { + if (fread(filename, 1, fnsize, fpZip) == fnsize) { + if (fwrite(filename, 1, fnsize, fpOut) == fnsize) { + offset += fnsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_STREAM_ERROR; + break; + } + + /* Extra field */ + if (extsize > 0) { + if (fread(extra, 1, extsize, fpZip) == extsize) { + if (fwrite(extra, 1, extsize, fpOut) == extsize) { + offset += extsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } + + /* Data */ + { + int dataSize = cpsize; + if (dataSize == 0) { + dataSize = uncpsize; + } + if (dataSize > 0) { + char* data = malloc(dataSize); + if (data != NULL) { + if ((int)fread(data, 1, dataSize, fpZip) == dataSize) { + if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) { + offset += dataSize; + totalBytes += dataSize; + } else { + err = Z_ERRNO; + } + } else { + err = Z_ERRNO; + } + free(data); + if (err != Z_OK) { + break; + } + } else { + err = Z_MEM_ERROR; + break; + } + } + } + + /* Central directory entry */ + { + char centralDirectoryEntryHeader[46]; + //char* comment = ""; + //int comsize = (int) strlen(comment); + WRITE_32(centralDirectoryEntryHeader, 0x02014b50); + WRITE_16(centralDirectoryEntryHeader + 4, version); + WRITE_16(centralDirectoryEntryHeader + 6, version); + WRITE_16(centralDirectoryEntryHeader + 8, gpflag); + WRITE_16(centralDirectoryEntryHeader + 10, method); + WRITE_16(centralDirectoryEntryHeader + 12, filetime); + WRITE_16(centralDirectoryEntryHeader + 14, filedate); + WRITE_32(centralDirectoryEntryHeader + 16, crc); + WRITE_32(centralDirectoryEntryHeader + 20, cpsize); + WRITE_32(centralDirectoryEntryHeader + 24, uncpsize); + WRITE_16(centralDirectoryEntryHeader + 28, fnsize); + WRITE_16(centralDirectoryEntryHeader + 30, extsize); + WRITE_16(centralDirectoryEntryHeader + 32, 0 /*comsize*/); + WRITE_16(centralDirectoryEntryHeader + 34, 0); /* disk # */ + WRITE_16(centralDirectoryEntryHeader + 36, 0); /* int attrb */ + WRITE_32(centralDirectoryEntryHeader + 38, 0); /* ext attrb */ + WRITE_32(centralDirectoryEntryHeader + 42, currentOffset); + /* Header */ + if (fwrite(centralDirectoryEntryHeader, 1, 46, fpOutCD) == 46) { + offsetCD += 46; + + /* Filename */ + if (fnsize > 0) { + if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) { + offsetCD += fnsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_STREAM_ERROR; + break; + } + + /* Extra field */ + if (extsize > 0) { + if (fwrite(extra, 1, extsize, fpOutCD) == extsize) { + offsetCD += extsize; + } else { + err = Z_ERRNO; + break; + } + } + + /* Comment field */ + /* + if (comsize > 0) { + if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) { + offsetCD += comsize; + } else { + err = Z_ERRNO; + break; + } + } + */ + + } else { + err = Z_ERRNO; + break; + } + } + + /* Success */ + entries++; + + } else { + break; + } + } + + /* Final central directory */ + { + int entriesZip = entries; + char finalCentralDirectoryHeader[22]; + //char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools"; + //int comsize = (int) strlen(comment); + if (entriesZip > 0xffff) { + entriesZip = 0xffff; + } + WRITE_32(finalCentralDirectoryHeader, 0x06054b50); + WRITE_16(finalCentralDirectoryHeader + 4, 0); /* disk # */ + WRITE_16(finalCentralDirectoryHeader + 6, 0); /* disk # */ + WRITE_16(finalCentralDirectoryHeader + 8, entriesZip); /* hack */ + WRITE_16(finalCentralDirectoryHeader + 10, entriesZip); /* hack */ + WRITE_32(finalCentralDirectoryHeader + 12, offsetCD); /* size of CD */ + WRITE_32(finalCentralDirectoryHeader + 16, offset); /* offset to CD */ + WRITE_16(finalCentralDirectoryHeader + 20, 0 /*comsize*/); /* comment */ + + /* Header */ + if (fwrite(finalCentralDirectoryHeader, 1, 22, fpOutCD) == 22) { + + /* Comment field */ + /* + if (comsize > 0) { + if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) { + err = Z_ERRNO; + } + } + */ + } else { + err = Z_ERRNO; + } + } + + /* Final merge (file + central directory) */ + fclose(fpOutCD); + if (err == Z_OK) { + fpOutCD = fopen(fileOutTmp, "rb"); + if (fpOutCD != NULL) { + int nRead; + char buffer[8192]; + while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) { + if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) { + err = Z_ERRNO; + break; + } + } + fclose(fpOutCD); + } + } + + /* Close */ + fclose(fpZip); + fclose(fpOut); + + /* Wipe temporary file */ + (void)remove(fileOutTmp); + + /* Number of recovered entries */ + if (err == Z_OK) { + if (nRecovered != NULL) { + *nRecovered = entries; + } + if (bytesRecovered != NULL) { + *bytesRecovered = totalBytes; + } + } + } else { + err = Z_STREAM_ERROR; + } + return err; +} diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/mztools.h b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/mztools.h new file mode 100755 index 0000000000..88b34592bf --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/mztools.h @@ -0,0 +1,31 @@ +/* + Additional tools for Minizip + Code: Xavier Roche '2004 + License: Same as ZLIB (www.gzip.org) +*/ + +#ifndef _zip_tools_H +#define _zip_tools_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#include "unzip.h" + +/* Repair a ZIP file (missing central directory) + file: file to recover + fileOut: output file after recovery + fileOutTmp: temporary file name used for recovery +*/ +extern int ZEXPORT unzRepair(const char* file, + const char* fileOut, + const char* fileOutTmp, + uLong* nRecovered, + uLong* bytesRecovered); + +#endif diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/unzip.c b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/unzip.c new file mode 100755 index 0000000000..9cb1743ef4 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/unzip.c @@ -0,0 +1,2152 @@ +/* unzip.c -- IO for uncompress .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + + ------------------------------------------------------------------------------------ + Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of + compatibility with older software. The following is from the original crypt.c. + Code woven in by Terry Thorsen 1/2003. + + Copyright (c) 1990-2000 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 or later + (the contents of which are also included in zip.h) for terms of use. + If, for some reason, all these files are missing, the Info-ZIP license + also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html + + crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + ------------------------------------------------------------------------------------ + + Changes in unzip.c + + 2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos + 2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz* + 2007-2008 - Even Rouault - Remove old C style function prototypes + 2007-2008 - Even Rouault - Add unzip support for ZIP64 + + Copyright (C) 2007-2008 Even Rouault + + + Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again). + Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G + should only read the compressed/uncompressed size from the Zip64 format if + the size from normal header was 0xFFFFFFFF + Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant + Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required) + Patch created by Daniel Borca + + Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer + + Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson + +*/ + + +#include +#include +#include + +//#ifndef NOUNCRYPT +// #define NOUNCRYPT +//#endif + +#include "zlib.h" +#include "unzip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + +#ifndef CASESENSITIVITYDEFAULT_NO +# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) +# define CASESENSITIVITYDEFAULT_NO +# endif +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (16384) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + + +const char unz_copyright[] = + " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info64_internal_s +{ + ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */ +} unz_file_info64_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, + when reading and decompress it */ +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + +#ifdef HAVE_BZIP2 + bz_stream bstream; /* bzLib stream structure for bziped */ +#endif + + ZPOS64_T pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + uLong stream_initialised; /* flag set if stream structure is initialised*/ + + ZPOS64_T offset_local_extrafield;/* offset of the local extra field */ + uInt size_local_extrafield;/* size of the local extra field */ + ZPOS64_T pos_local_extrafield; /* position in the local extra field in read*/ + ZPOS64_T total_out_64; + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */ + ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/ + zlib_filefunc64_32_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + int raw; +} file_in_zip64_read_info_s; + + +/* unz64_s contain internal information about the zipfile +*/ +typedef struct +{ + zlib_filefunc64_32_def z_filefunc; + int is64bitOpenFunction; + voidpf filestream; /* io structore of the zipfile */ + unz_global_info64 gi; /* public global information */ + ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + ZPOS64_T num_file; /* number of the current file in the zipfile*/ + ZPOS64_T pos_in_central_dir; /* pos of the current file in the central dir*/ + ZPOS64_T current_file_ok; /* flag about the usability of the current file*/ + ZPOS64_T central_pos; /* position of the beginning of the central dir*/ + + ZPOS64_T size_central_dir; /* size of the central directory */ + ZPOS64_T offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info64 cur_file_info; /* public info about the current file in zip*/ + unz_file_info64_internal cur_file_info_internal; /* private info about it*/ + file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current + file if we are decompressing it */ + int encrypted; + + int isZip64; + +# ifndef NOUNCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const unsigned long* pcrc_32_tab; +# endif +} unz64_s; + + +#ifndef NOUNCRYPT +#include "crypt.h" +#endif + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ + + +local int unz64local_getByte OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + int *pi)); + +local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi) +{ + unsigned char c; + int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ZERROR64(*pzlib_filefunc_def,filestream)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int unz64local_getShort OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) +{ + uLong x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<8; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unz64local_getLong OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) +{ + uLong x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<8; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<16; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unz64local_getLong64 OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + ZPOS64_T *pX)); + + +local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + ZPOS64_T *pX) +{ + ZPOS64_T x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (ZPOS64_T)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<8; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<16; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<24; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<32; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<40; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<48; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<56; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +/* My own strcmpi / strcasecmp */ +local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2) +{ + for (;;) + { + char c1=*(fileName1++); + char c2=*(fileName2++); + if ((c1>='a') && (c1<='z')) + c1 -= 0x20; + if ((c2>='a') && (c2<='z')) + c2 -= 0x20; + if (c1=='\0') + return ((c2=='\0') ? 0 : -1); + if (c2=='\0') + return 1; + if (c1c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) + +*/ +extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, + const char* fileName2, + int iCaseSensitivity) + +{ + if (iCaseSensitivity==0) + iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity==1) + return strcmp(fileName1,fileName2); + + return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif + +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); +local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + + +/* + Locate the Central directory 64 of a zipfile (at the end, just before + the global comment) +*/ +local ZPOS64_T unz64local_SearchCentralDir64 OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream)); + +local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + uLong uL; + ZPOS64_T relativeOffset; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + if (uPosFound == 0) + return 0; + + /* Zip64 end of central directory locator */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature, already checked */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + + /* number of the disk with the start of the zip64 end of central directory */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + if (uL != 0) + return 0; + + /* relative offset of the zip64 end of central directory record */ + if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK) + return 0; + + /* total number of disks */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + if (uL != 1) + return 0; + + /* Goto end of central directory record */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + + if (uL != 0x06064b50) + return 0; + + return relativeOffset; +} + +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer + "zlib/zlib114.zip". + If the zipfile cannot be opened (file doesn't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ +local unzFile unzOpenInternal (const void *path, + zlib_filefunc64_32_def* pzlib_filefunc64_32_def, + int is64bitOpenFunction) +{ + unz64_s us; + unz64_s *s; + ZPOS64_T central_pos; + uLong uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + ZPOS64_T number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err=UNZ_OK; + + if (unz_copyright[0]!=' ') + return NULL; + + us.z_filefunc.zseek32_file = NULL; + us.z_filefunc.ztell32_file = NULL; + if (pzlib_filefunc64_32_def==NULL) + fill_fopen64_filefunc(&us.z_filefunc.zfile_func64); + else + us.z_filefunc = *pzlib_filefunc64_32_def; + us.is64bitOpenFunction = is64bitOpenFunction; + + + + us.filestream = ZOPEN64(us.z_filefunc, + path, + ZLIB_FILEFUNC_MODE_READ | + ZLIB_FILEFUNC_MODE_EXISTING); + if (us.filestream==NULL) + return NULL; + + central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream); + if (central_pos) + { + uLong uS; + ZPOS64_T uL64; + + us.isZip64 = 1; + + if (ZSEEK64(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* size of zip64 end of central directory record */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK) + err=UNZ_ERRNO; + + /* version made by */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) + err=UNZ_ERRNO; + + /* version needed to extract */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central directory on this disk */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central directory */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + us.gi.size_comment = 0; + } + else + { + central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream); + if (central_pos==0) + err=UNZ_ERRNO; + + us.isZip64 = 0; + + if (ZSEEK64(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.gi.number_entry = uL; + + /* total number of entries in the central dir */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + number_entry_CD = uL; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.size_central_dir = uL; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.offset_central_dir = uL; + + /* zipfile comment length */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) + err=UNZ_ERRNO; + } + + if ((central_pospfile_in_zip_read!=NULL) + unzCloseCurrentFile(file); + + ZCLOSE64(s->z_filefunc, s->filestream); + TRYFREE(s); + return UNZ_OK; +} + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info) +{ + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + *pglobal_info=s->gi; + return UNZ_OK; +} + +extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32) +{ + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + /* to do : check if number_entry is not truncated */ + pglobal_info32->number_entry = (uLong)s->gi.number_entry; + pglobal_info32->size_comment = s->gi.size_comment; + return UNZ_OK; +} +/* + Translate date/time from Dos format to tm_unz (readable more easilty) +*/ +local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm) +{ + ZPOS64_T uDate; + uDate = (ZPOS64_T)(ulDosDate>>16); + ptm->tm_mday = (uInt)(uDate&0x1f) ; + ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; + ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + + ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); + ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; + ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; +} + +/* + Get Info about the current file in the zipfile, with internal only info +*/ +local int unz64local_GetCurrentFileInfoInternal OF((unzFile file, + unz_file_info64 *pfile_info, + unz_file_info64_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +local int unz64local_GetCurrentFileInfoInternal (unzFile file, + unz_file_info64 *pfile_info, + unz_file_info64_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize) +{ + unz64_s* s; + unz_file_info64 file_info; + unz_file_info64_internal file_info_internal; + int err=UNZ_OK; + uLong uMagic; + long lSeek=0; + uLong uL; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (ZSEEK64(s->z_filefunc, s->filestream, + s->pos_in_central_dir+s->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + + /* we check the magic */ + if (err==UNZ_OK) + { + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x02014b50) + err=UNZ_BADZIPFILE; + } + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) + err=UNZ_ERRNO; + + unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info.compressed_size = uL; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info.uncompressed_size = uL; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) + err=UNZ_ERRNO; + + // relative offset of local header + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info_internal.offset_curfile = uL; + + lSeek+=file_info.size_filename; + if ((err==UNZ_OK) && (szFileName!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_filename0) && (fileNameBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek -= uSizeRead; + } + + // Read extrafield + if ((err==UNZ_OK) && (extraField!=NULL)) + { + ZPOS64_T uSizeRead ; + if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + + lSeek += file_info.size_file_extra - (uLong)uSizeRead; + } + else + lSeek += file_info.size_file_extra; + + + if ((err==UNZ_OK) && (file_info.size_file_extra != 0)) + { + uLong acc = 0; + + // since lSeek now points to after the extra field we need to move back + lSeek -= file_info.size_file_extra; + + if (lSeek!=0) + { + if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + while(acc < file_info.size_file_extra) + { + uLong headerId; + uLong dataSize; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK) + err=UNZ_ERRNO; + + /* ZIP64 extra fields */ + if (headerId == 0x0001) + { + uLong uL; + + if(file_info.uncompressed_size == (ZPOS64_T)(unsigned long)-1) + { + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + } + + if(file_info.compressed_size == (ZPOS64_T)(unsigned long)-1) + { + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + } + + if(file_info_internal.offset_curfile == (ZPOS64_T)(unsigned long)-1) + { + /* Relative Header offset */ + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + } + + if(file_info.disk_num_start == (unsigned long)-1) + { + /* Disk Start Number */ + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + } + + } + else + { + if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0) + err=UNZ_ERRNO; + } + + acc += 2 + 2 + dataSize; + } + } + + if ((err==UNZ_OK) && (szComment!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + { +#ifndef __clang_analyzer__ + lSeek=0; +#endif + } + else + err=UNZ_ERRNO; + } + + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; +#ifndef __clang_analyzer__ + lSeek+=file_info.size_file_comment - uSizeRead; +#endif + } +#ifndef __clang_analyzer__ + else + lSeek+=file_info.size_file_comment; +#endif + + + if ((err==UNZ_OK) && (pfile_info!=NULL)) + *pfile_info=file_info; + + if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) + *pfile_info_internal=file_info_internal; + + return err; +} + + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. +*/ +extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file, + unz_file_info64 * pfile_info, + char * szFileName, uLong fileNameBufferSize, + void *extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) +{ + return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); +} + +extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, + unz_file_info * pfile_info, + char * szFileName, uLong fileNameBufferSize, + void *extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) +{ + int err; + unz_file_info64 file_info64; + err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); + if (err==UNZ_OK) + { + pfile_info->version = file_info64.version; + pfile_info->version_needed = file_info64.version_needed; + pfile_info->flag = file_info64.flag; + pfile_info->compression_method = file_info64.compression_method; + pfile_info->dosDate = file_info64.dosDate; + pfile_info->crc = file_info64.crc; + + pfile_info->size_filename = file_info64.size_filename; + pfile_info->size_file_extra = file_info64.size_file_extra; + pfile_info->size_file_comment = file_info64.size_file_comment; + + pfile_info->disk_num_start = file_info64.disk_num_start; + pfile_info->internal_fa = file_info64.internal_fa; + pfile_info->external_fa = file_info64.external_fa; + + pfile_info->tmu_date = file_info64.tmu_date, + + + pfile_info->compressed_size = (uLong)file_info64.compressed_size; + pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size; + + } + return err; +} +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ +extern int ZEXPORT unzGoToFirstFile (unzFile file) +{ + int err=UNZ_OK; + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + s->pos_in_central_dir=s->offset_central_dir; + s->num_file=0; + err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ +extern int ZEXPORT unzGoToNextFile (unzFile file) +{ + unz64_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ + if (s->num_file+1==s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; + s->num_file++; + err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzipStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ +extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity) +{ + unz64_s* s; + int err; + + /* We remember the 'current' position in the file so that we can jump + * back there if we fail. + */ + unz_file_info64 cur_file_infoSaved; + unz_file_info64_internal cur_file_info_internalSaved; + ZPOS64_T num_fileSaved; + ZPOS64_T pos_in_central_dirSaved; + + + if (file==NULL) + return UNZ_PARAMERROR; + + if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + /* Save the current state */ + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + cur_file_infoSaved = s->cur_file_info; + cur_file_info_internalSaved = s->cur_file_info_internal; + + err = unzGoToFirstFile(file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; + err = unzGetCurrentFileInfo64(file,NULL, + szCurrentFileName,sizeof(szCurrentFileName)-1, + NULL,0,NULL,0); + if (err == UNZ_OK) + { + if (unzStringFileNameCompare(szCurrentFileName, + szFileName,iCaseSensitivity)==0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + } + + /* We failed, so restore the state of the 'current file' to where we + * were. + */ + s->num_file = num_fileSaved ; + s->pos_in_central_dir = pos_in_central_dirSaved ; + s->cur_file_info = cur_file_infoSaved; + s->cur_file_info_internal = cur_file_info_internalSaved; + return err; +} + + +/* +/////////////////////////////////////////// +// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) +// I need random access +// +// Further optimization could be realized by adding an ability +// to cache the directory in memory. The goal being a single +// comprehensive file read to put the file I need in a memory. +*/ + +/* +typedef struct unz_file_pos_s +{ + ZPOS64_T pos_in_zip_directory; // offset in file + ZPOS64_T num_of_file; // # of file +} unz_file_pos; +*/ + +extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) +{ + unz64_s* s; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + file_pos->pos_in_zip_directory = s->pos_in_central_dir; + file_pos->num_of_file = s->num_file; + + return UNZ_OK; +} + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos) +{ + unz64_file_pos file_pos64; + int err = unzGetFilePos64(file,&file_pos64); + if (err==UNZ_OK) + { + file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory; + file_pos->num_of_file = (uLong)file_pos64.num_of_file; + } + return err; +} + +extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) +{ + unz64_s* s; + int err; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + + /* jump to the right spot */ + s->pos_in_central_dir = file_pos->pos_in_zip_directory; + s->num_file = file_pos->num_of_file; + + /* set the current file */ + err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + /* return results */ + s->current_file_ok = (err == UNZ_OK); + return err; +} + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos) +{ + unz64_file_pos file_pos64; + if (file_pos == NULL) + return UNZ_PARAMERROR; + + file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory; + file_pos64.num_of_file = file_pos->num_of_file; + return unzGoToFilePos64(file,&file_pos64); +} + +/* +// Unzip Helper Functions - should be here? +/////////////////////////////////////////// +*/ + +/* + Read the local header of the current zipfile + Check the coherency of the local header and info in the end of central + directory about this file + store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) +*/ +local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar, + ZPOS64_T * poffset_local_extrafield, + uInt * psize_local_extrafield) +{ + uLong uMagic,uData,uFlags; + uLong size_filename; + uLong size_extra_field; + int err=UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + + if (err==UNZ_OK) + { + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x04034b50) + err=UNZ_BADZIPFILE; + } + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; +/* + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + err=UNZ_BADZIPFILE; +*/ + if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) + err=UNZ_BADZIPFILE; + + if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && +/* #ifdef HAVE_BZIP2 */ + (s->cur_file_info.compression_method!=Z_BZIP2ED) && +/* #endif */ + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ + err=UNZ_ERRNO; + else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ + err=UNZ_ERRNO; + else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) + err=UNZ_BADZIPFILE; + + *piSizeVar += (uInt)size_filename; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) + err=UNZ_ERRNO; + *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; + + *piSizeVar += (uInt)size_extra_field; + + return err; +} + +/* + Open for reading data the current file in the zipfile. + If there is no error and the file is opened, the return value is UNZ_OK. +*/ +extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, + int* level, int raw, const char* password) +{ + int err=UNZ_OK; + uInt iSizeVar; + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + ZPOS64_T offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ +# ifndef NOUNCRYPT + char source[12]; +# else + if (password != NULL) + return UNZ_PARAMERROR; +# endif + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s)); + if (pfile_in_zip_read_info==NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield=0; + pfile_in_zip_read_info->raw=raw; + + if (pfile_in_zip_read_info->read_buffer==NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised=0; + + if (method!=NULL) + *method = (int)s->cur_file_info.compression_method; + + if (level!=NULL) + { + *level = 6; + switch (s->cur_file_info.flag & 0x06) + { + case 6 : *level = 1; break; + case 4 : *level = 2; break; + case 2 : *level = 9; break; + } + } + + if ((s->cur_file_info.compression_method!=0) && +/* #ifdef HAVE_BZIP2 */ + (s->cur_file_info.compression_method!=Z_BZIP2ED) && +/* #endif */ + (s->cur_file_info.compression_method!=Z_DEFLATED)) + { +#ifndef __clang_analyzer__ + err=UNZ_BADZIPFILE; +#endif + } + + pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; + pfile_in_zip_read_info->crc32=0; + pfile_in_zip_read_info->total_out_64=0; + pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method; + pfile_in_zip_read_info->filestream=s->filestream; + pfile_in_zip_read_info->z_filefunc=s->z_filefunc; +#ifndef __clang_analyzer__ + pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; +#endif + + pfile_in_zip_read_info->stream.total_out = 0; + + if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw)) + { +#ifdef HAVE_BZIP2 + pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0; + pfile_in_zip_read_info->bstream.bzfree = (free_func)0; + pfile_in_zip_read_info->bstream.opaque = (voidpf)0; + pfile_in_zip_read_info->bstream.state = (voidpf)0; + + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = (voidpf)0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } +#else + pfile_in_zip_read_info->raw=1; +#endif + } + else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw)) + { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = 0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=Z_DEFLATED; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + pfile_in_zip_read_info->rest_read_compressed = + s->cur_file_info.compressed_size ; + pfile_in_zip_read_info->rest_read_uncompressed = + s->cur_file_info.uncompressed_size ; + + + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + s->pfile_in_zip_read = pfile_in_zip_read_info; + s->encrypted = 0; + +# ifndef NOUNCRYPT + if (password != NULL) + { + int i; + s->pcrc_32_tab = (const unsigned long*)get_crc_table(); + init_keys(password,s->keys,s->pcrc_32_tab); + if (ZSEEK64(s->z_filefunc, s->filestream, + s->pfile_in_zip_read->pos_in_zipfile + + s->pfile_in_zip_read->byte_before_the_zipfile, + SEEK_SET)!=0) + return UNZ_INTERNALERROR; + if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12) + return UNZ_INTERNALERROR; + + for (i = 0; i<12; i++) + zdecode(s->keys,s->pcrc_32_tab,source[i]); + + s->pfile_in_zip_read->pos_in_zipfile+=12; + s->encrypted=1; + } +# endif + + + return UNZ_OK; +} + +extern int ZEXPORT unzOpenCurrentFile (unzFile file) +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); +} + +extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char* password) +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, password); +} + +extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw) +{ + return unzOpenCurrentFile3(file, method, level, raw, NULL); +} + +/** Addition for GDAL : START */ + +extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + s=(unz64_s*)file; + if (file==NULL) + return 0; //UNZ_PARAMERROR; + pfile_in_zip_read_info=s->pfile_in_zip_read; + if (pfile_in_zip_read_info==NULL) + return 0; //UNZ_PARAMERROR; + return pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile; +} + +/** Addition for GDAL : END */ + +/* + Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ +extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len) +{ + int err=UNZ_OK; + uInt iRead = 0; + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if (pfile_in_zip_read_info->read_buffer == NULL) + return UNZ_END_OF_LIST_OF_FILE; + if (len==0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; + + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + + // NOTE: + // This bit of code seems to try to set the amount of space in the output buffer based on the + // value stored in the headers stored in the .zip file. However, if those values are incorrect + // it may result in a loss of data when uncompresssing that file. The compressed data is still + // legit and will deflate without knowing the uncompressed code so this tidbit is unnecessary and + // may cause issues for some .zip files. + // + // It's removed in here to fix those issues. + // + // See: https://github.com/samsoffes/ssziparchive/issues/16 + // + + /* + if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && + (!(pfile_in_zip_read_info->raw))) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_uncompressed; + */ + + if ((len>pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in) && + (pfile_in_zip_read_info->raw)) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in; + + while (pfile_in_zip_read_info->stream.avail_out>0) + { + if ((pfile_in_zip_read_info->stream.avail_in==0) && + (pfile_in_zip_read_info->rest_read_compressed>0)) + { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + if (ZREAD64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->read_buffer, + uReadThis)!=uReadThis) + return UNZ_ERRNO; + + +# ifndef NOUNCRYPT + if(s->encrypted) + { + uInt i; + for(i=0;iread_buffer[i] = + zdecode(s->keys,s->pcrc_32_tab, + pfile_in_zip_read_info->read_buffer[i]); + } +# endif + + + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed-=uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + } + + if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) + { + uInt uDoCopy,i ; + + if ((pfile_in_zip_read_info->stream.avail_in == 0) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + return (iRead==0) ? UNZ_EOF : iRead; + + if (pfile_in_zip_read_info->stream.avail_out < + pfile_in_zip_read_info->stream.avail_in) + uDoCopy = pfile_in_zip_read_info->stream.avail_out ; + else + uDoCopy = pfile_in_zip_read_info->stream.avail_in ; + + for (i=0;istream.next_out+i) = + *(pfile_in_zip_read_info->stream.next_in+i); + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy; + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED) + { +#ifdef HAVE_BZIP2 + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + + pfile_in_zip_read_info->bstream.next_in = (char*)pfile_in_zip_read_info->stream.next_in; + pfile_in_zip_read_info->bstream.avail_in = pfile_in_zip_read_info->stream.avail_in; + pfile_in_zip_read_info->bstream.total_in_lo32 = pfile_in_zip_read_info->stream.total_in; + pfile_in_zip_read_info->bstream.total_in_hi32 = 0; + pfile_in_zip_read_info->bstream.next_out = (char*)pfile_in_zip_read_info->stream.next_out; + pfile_in_zip_read_info->bstream.avail_out = pfile_in_zip_read_info->stream.avail_out; + pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out; + pfile_in_zip_read_info->bstream.total_out_hi32 = 0; + + uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32; + bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out; + + err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream); + + uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis)); + pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis; + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->bstream.next_in; + pfile_in_zip_read_info->stream.avail_in = pfile_in_zip_read_info->bstream.avail_in; + pfile_in_zip_read_info->stream.total_in = pfile_in_zip_read_info->bstream.total_in_lo32; + pfile_in_zip_read_info->stream.next_out = (Bytef*)pfile_in_zip_read_info->bstream.next_out; + pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out; + pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32; + + if (err==BZ_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=BZ_OK) + break; +#endif + } // end Z_BZIP2ED + else + { + ZPOS64_T uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + ZPOS64_T uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) + err = Z_DATA_ERROR; + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + if (err==Z_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +extern z_off_t ZEXPORT unztell (unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + +extern ZPOS64_T ZEXPORT unztell64 (unzFile file) +{ + + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return (ZPOS64_T)-1; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return (ZPOS64_T)-1; + + return pfile_in_zip_read_info->total_out_64; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +extern int ZEXPORT unzeof (unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* +Read extra field from the current file (opened by unzOpenCurrentFile) +This is the local-header version of the extra field (sometimes, there is +more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field that can be read + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ +extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + uInt read_now; + ZPOS64_T size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf==NULL) + return (int)size_to_read; + + if (len>size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len ; + + if (read_now==0) + return 0; + + if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (ZREAD64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + buf,read_now)!=read_now) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzipOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +extern int ZEXPORT unzCloseCurrentFile (unzFile file) +{ + int err=UNZ_OK; + + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && + (!pfile_in_zip_read_info->raw)) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED) + inflateEnd(&pfile_in_zip_read_info->stream); +#ifdef HAVE_BZIP2 + else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED) + BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream); +#endif + + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + return err; +} + + +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ +extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf) +{ + unz64_s* s; + uLong uReadThis ; + if (file==NULL) + return (int)UNZ_PARAMERROR; + s=(unz64_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} + +/* Additions by RX '2004 */ +extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) +{ + unz64_s* s; + + if (file==NULL) + return 0; //UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return 0; + if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) + if (s->num_file==s->gi.number_entry) + return 0; + return s->pos_in_central_dir; +} + +extern uLong ZEXPORT unzGetOffset (unzFile file) +{ + ZPOS64_T offset64; + + if (file==NULL) + return 0; //UNZ_PARAMERROR; + offset64 = unzGetOffset64(file); + return (uLong)offset64; +} + +extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) +{ + unz64_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + + s->pos_in_central_dir = pos; + s->num_file = s->gi.number_entry; /* hack */ + err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) +{ + return unzSetOffset64(file,pos); +} diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/unzip.h b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/unzip.h new file mode 100755 index 0000000000..3183968b77 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/unzip.h @@ -0,0 +1,437 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + --------------------------------------------------------------------------------- + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + --------------------------------------------------------------------------------- + + Changes + + See header of unzip64.c + +*/ + +#ifndef _unz64_H +#define _unz64_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#ifdef HAVE_BZIP2 +#include "bzlib.h" +#endif + +#define Z_BZIP2ED 12 + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info64_s +{ + ZPOS64_T number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info64; + +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info64_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + ZPOS64_T compressed_size; /* compressed size 8 bytes */ + ZPOS64_T uncompressed_size; /* uncompressed size 8 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info64; + +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +extern unzFile ZEXPORT unzOpen64 OF((const void *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer + "zlib/zlib113.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. + the "64" function take a const void* pointer, because the path is just the + value passed to the open64_file_func callback. + Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path + is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char* + does not describe the reality +*/ + + +extern unzFile ZEXPORT unzOpen2 OF((const char *path, + zlib_filefunc_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unzOpen, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern unzFile ZEXPORT unzOpen2_64 OF((const void *path, + zlib_filefunc64_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unz64Open, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); + +extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file, + unz_global_info64 *pglobal_info)); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +extern int ZEXPORT unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +/* ****************************************** */ +/* Ryan supplied functions */ +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; /* offset in zip file directory */ + uLong num_of_file; /* # of file */ +} unz_file_pos; + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos); + +typedef struct unz64_file_pos_s +{ + ZPOS64_T pos_in_zip_directory; /* offset in zip file directory */ + ZPOS64_T num_of_file; /* # of file */ +} unz64_file_pos; + +extern int ZEXPORT unzGetFilePos64( + unzFile file, + unz64_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos64( + unzFile file, + const unz64_file_pos* file_pos); + +/* ****************************************** */ + +extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file, + unz_file_info64 *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + + +/** Addition for GDAL : START */ + +extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file)); + +/** Addition for GDAL : END */ + + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, + const char* password)); +/* + Open for reading data the current file in the zipfile. + password is a crypting password + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, + int* method, + int* level, + int raw)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + +extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, + int* method, + int* level, + int raw, + const char* password)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); + +extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +/***************************************************************************/ + +/* Get the current file offset */ +extern ZPOS64_T ZEXPORT unzGetOffset64 (unzFile file); +extern uLong ZEXPORT unzGetOffset (unzFile file); + +/* Set the current file offset */ +extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos); +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); + + + +#ifdef __cplusplus +} +#endif + +#endif /* _unz64_H */ diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/zip.c b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/zip.c new file mode 100755 index 0000000000..db501c1885 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/zip.c @@ -0,0 +1,2022 @@ +/* zip.c -- IO on .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + Changes + Oct-2009 - Mathias Svensson - Remove old C style function prototypes + Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives + Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions. + Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data + It is used when recreting zip archive with RAW when deleting items from a zip. + ZIP64 data is automaticly added to items that needs it, and existing ZIP64 data need to be removed. + Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required) + Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer + +*/ + + +#include +#include +#include +#include +#include "zlib.h" +#include "zip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +#ifndef VERSIONMADEBY +# define VERSIONMADEBY (0x0) /* platform depedent */ +#endif + +#ifndef Z_BUFSIZE +#define Z_BUFSIZE (64*1024) //(16384) +#endif + +#ifndef Z_MAXFILENAMEINZIP +#define Z_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +/* +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) +*/ + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + + +// NOT sure that this work on ALL platform +#define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32)) + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +#ifndef DEF_MEM_LEVEL +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +#endif +const char zip_copyright[] =" zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + + +#define SIZEDATA_INDATABLOCK (4096-(4*4)) + +#define LOCALHEADERMAGIC (0x04034b50) +#define CENTRALHEADERMAGIC (0x02014b50) +#define ENDHEADERMAGIC (0x06054b50) +#define ZIP64ENDHEADERMAGIC (0x6064b50) +#define ZIP64ENDLOCHEADERMAGIC (0x7064b50) + +#define FLAG_LOCALHEADER_OFFSET (0x06) +#define CRC_LOCALHEADER_OFFSET (0x0e) + +#define SIZECENTRALHEADER (0x2e) /* 46 */ + +typedef struct linkedlist_datablock_internal_s +{ + struct linkedlist_datablock_internal_s* next_datablock; + uLong avail_in_this_block; + uLong filled_in_this_block; + uLong unused; /* for future use and alignement */ + unsigned char data[SIZEDATA_INDATABLOCK]; +} linkedlist_datablock_internal; + +typedef struct linkedlist_data_s +{ + linkedlist_datablock_internal* first_block; + linkedlist_datablock_internal* last_block; +} linkedlist_data; + + +typedef struct +{ + z_stream stream; /* zLib stream structure for inflate */ +#ifdef HAVE_BZIP2 + bz_stream bstream; /* bzLib stream structure for bziped */ +#endif + + int stream_initialised; /* 1 is stream is initialised */ + uInt pos_in_buffered_data; /* last written byte in buffered_data */ + + ZPOS64_T pos_local_header; /* offset of the local header of the file + currenty writing */ + char* central_header; /* central header data for the current file */ + uLong size_centralExtra; + uLong size_centralheader; /* size of the central header for cur file */ + uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */ + uLong flag; /* flag of the file currently writing */ + + int method; /* compression method of file currenty wr.*/ + int raw; /* 1 for directly writing raw data */ + Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ + uLong dosDate; + uLong crc32; + int encrypt; + int zip64; /* Add ZIP64 extened information in the extra field */ + ZPOS64_T pos_zip64extrainfo; + ZPOS64_T totalCompressedData; + ZPOS64_T totalUncompressedData; +#ifndef NOCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const unsigned long* pcrc_32_tab; + int crypt_header_size; +#endif +} curfile64_info; + +typedef struct +{ + zlib_filefunc64_32_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + linkedlist_data central_dir;/* datablock with central dir in construction*/ + int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ + curfile64_info ci; /* info on the file curretly writing */ + + ZPOS64_T begin_pos; /* position of the beginning of the zipfile */ + ZPOS64_T add_position_when_writting_offset; + ZPOS64_T number_entry; + +#ifndef NO_ADDFILEINEXISTINGZIP + char *globalcomment; +#endif + +} zip64_internal; + + +#ifndef NOCRYPT +#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED +#include "crypt.h" +#endif + +local linkedlist_datablock_internal* allocate_new_datablock() +{ + linkedlist_datablock_internal* ldi; + ldi = (linkedlist_datablock_internal*) + ALLOC(sizeof(linkedlist_datablock_internal)); + if (ldi!=NULL) + { + ldi->next_datablock = NULL ; + ldi->filled_in_this_block = 0 ; + ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; + } + return ldi; +} + +local void free_datablock(linkedlist_datablock_internal* ldi) +{ + while (ldi!=NULL) + { + linkedlist_datablock_internal* ldinext = ldi->next_datablock; + TRYFREE(ldi); + ldi = ldinext; + } +} + +local void init_linkedlist(linkedlist_data* ll) +{ + ll->first_block = ll->last_block = NULL; +} + +local void free_linkedlist(linkedlist_data* ll) +{ + free_datablock(ll->first_block); + ll->first_block = ll->last_block = NULL; +} + + +local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) +{ + linkedlist_datablock_internal* ldi; + const unsigned char* from_copy; + + if (ll==NULL) + return ZIP_INTERNALERROR; + + if (ll->last_block == NULL) + { + ll->first_block = ll->last_block = allocate_new_datablock(); + if (ll->first_block == NULL) + return ZIP_INTERNALERROR; + } + + ldi = ll->last_block; + from_copy = (unsigned char*)buf; + + while (len>0) + { + uInt copy_this; + uInt i; + unsigned char* to_copy; + + if (ldi->avail_in_this_block==0) + { + ldi->next_datablock = allocate_new_datablock(); + if (ldi->next_datablock == NULL) + return ZIP_INTERNALERROR; + ldi = ldi->next_datablock ; + ll->last_block = ldi; + } + + if (ldi->avail_in_this_block < len) + copy_this = (uInt)ldi->avail_in_this_block; + else + copy_this = (uInt)len; + + to_copy = &(ldi->data[ldi->filled_in_this_block]); + + for (i=0;ifilled_in_this_block += copy_this; + ldi->avail_in_this_block -= copy_this; + from_copy += copy_this ; + len -= copy_this; + } + return ZIP_OK; +} + + + +/****************************************************************************/ + +#ifndef NO_ADDFILEINEXISTINGZIP +/* =========================================================================== + Inputs a long in LSB order to the given file + nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T) +*/ + +local int zip64local_putValue OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte)); +local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) +{ + unsigned char buf[8]; + int n; + for (n = 0; n < nbByte; n++) + { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + if (x != 0) + { /* data overflow - hack for ZIP64 (X Roche) */ + for (n = 0; n < nbByte; n++) + { + buf[n] = 0xff; + } + } + + if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte) + return ZIP_ERRNO; + else + return ZIP_OK; +} + +local void zip64local_putValue_inmemory OF((void* dest, ZPOS64_T x, int nbByte)); +local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) +{ + unsigned char* buf=(unsigned char*)dest; + int n; + for (n = 0; n < nbByte; n++) { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + + if (x != 0) + { /* data overflow - hack for ZIP64 */ + for (n = 0; n < nbByte; n++) + { + buf[n] = 0xff; + } + } +} + +/****************************************************************************/ + + +local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) +{ + uLong year = (uLong)ptm->tm_year; + if (year>=1980) + year-=1980; + else if (year>=80) + year-=80; + return + (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | + ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); +} + + +/****************************************************************************/ + +local int zip64local_getByte OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)); + +local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,voidpf filestream,int* pi) +{ + unsigned char c; + int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return ZIP_OK; + } + else + { + if (ZERROR64(*pzlib_filefunc_def,filestream)) + return ZIP_ERRNO; + else + return ZIP_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int zip64local_getShort OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); + +local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) +{ + uLong x ; + int i = 0; + int err; + + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int zip64local_getLong OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); + +local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) +{ + uLong x ; + int i = 0; + int err; + + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<16; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int zip64local_getLong64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)); + + +local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) +{ + ZPOS64_T x; + int i = 0; + int err; + + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (ZPOS64_T)i; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<8; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<16; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<24; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<32; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<40; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<48; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<56; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + + return err; +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local ZPOS64_T zip64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); + +local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + +/* +Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before +the global comment) +*/ +local ZPOS64_T zip64local_SearchCentralDir64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); + +local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + uLong uL; + ZPOS64_T relativeOffset; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + { + // Signature "0x07064b50" Zip64 end of central directory locater + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) + { + uPosFound = uReadPos+i; + break; + } + } + + if (uPosFound!=0) + break; + } + + TRYFREE(buf); + if (uPosFound == 0) + return 0; + + /* Zip64 end of central directory locator */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature, already checked */ + if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) + return 0; + + /* number of the disk with the start of the zip64 end of central directory */ + if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) + return 0; + if (uL != 0) + return 0; + + /* relative offset of the zip64 end of central directory record */ + if (zip64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=ZIP_OK) + return 0; + + /* total number of disks */ + if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) + return 0; + if (uL != 1) + return 0; + + /* Goto Zip64 end of central directory record */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature */ + if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) + return 0; + + if (uL != 0x06064b50) // signature of 'Zip64 end of central directory' + return 0; + + return relativeOffset; +} + +int LoadCentralDirectoryRecord(zip64_internal* pziinit); +int LoadCentralDirectoryRecord(zip64_internal* pziinit) +{ + int err=ZIP_OK; + ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + + ZPOS64_T size_central_dir; /* size of the central directory */ + ZPOS64_T offset_central_dir; /* offset of start of central directory */ + ZPOS64_T central_pos; + uLong uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + ZPOS64_T number_entry; + ZPOS64_T number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + uLong VersionMadeBy; + uLong VersionNeeded; + uLong size_comment; + + int hasZIP64Record = 0; + + // check first if we find a ZIP64 record + central_pos = zip64local_SearchCentralDir64(&pziinit->z_filefunc,pziinit->filestream); + if(central_pos > 0) + { + hasZIP64Record = 1; + } + else if(central_pos == 0) + { + central_pos = zip64local_SearchCentralDir(&pziinit->z_filefunc,pziinit->filestream); + } + +/* disable to allow appending to empty ZIP archive + if (central_pos==0) + err=ZIP_ERRNO; +*/ + + if(hasZIP64Record) + { + ZPOS64_T sizeEndOfCentralDirectory; + if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0) + err=ZIP_ERRNO; + + /* the signature, already checked */ + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) + err=ZIP_ERRNO; + + /* size of zip64 end of central directory record */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &sizeEndOfCentralDirectory)!=ZIP_OK) + err=ZIP_ERRNO; + + /* version made by */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionMadeBy)!=ZIP_OK) + err=ZIP_ERRNO; + + /* version needed to extract */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionNeeded)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of this disk */ + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of the disk with the start of the central directory */ + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central directory on this disk */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &number_entry)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central directory */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&number_entry_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) + err=ZIP_BADZIPFILE; + + /* size of the central directory */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&size_central_dir)!=ZIP_OK) + err=ZIP_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&offset_central_dir)!=ZIP_OK) + err=ZIP_ERRNO; + + // TODO.. + // read the comment from the standard central header. + size_comment = 0; + } + else + { + // Read End of central Directory info + if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=ZIP_ERRNO; + + /* the signature, already checked */ + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of this disk */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of the disk with the start of the central directory */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central dir on this disk */ + number_entry = 0; + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) + err=ZIP_ERRNO; + else + number_entry = uL; + + /* total number of entries in the central dir */ + number_entry_CD = 0; + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) + err=ZIP_ERRNO; + else + number_entry_CD = uL; + + if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) + err=ZIP_BADZIPFILE; + + /* size of the central directory */ + size_central_dir = 0; + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) + err=ZIP_ERRNO; + else + size_central_dir = uL; + + /* offset of start of central directory with respect to the starting disk number */ + offset_central_dir = 0; + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) + err=ZIP_ERRNO; + else + offset_central_dir = uL; + + + /* zipfile global comment length */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &size_comment)!=ZIP_OK) + err=ZIP_ERRNO; + } + + if ((central_posz_filefunc, pziinit->filestream); + return ZIP_ERRNO; + } + + if (size_comment>0) + { + pziinit->globalcomment = (char*)ALLOC(size_comment+1); + if (pziinit->globalcomment) + { + size_comment = ZREAD64(pziinit->z_filefunc, pziinit->filestream, pziinit->globalcomment,size_comment); + pziinit->globalcomment[size_comment]=0; + } + } + + byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir); + pziinit->add_position_when_writting_offset = byte_before_the_zipfile; + + { + ZPOS64_T size_central_dir_to_read = size_central_dir; + size_t buf_size = SIZEDATA_INDATABLOCK; + void* buf_read = (void*)ALLOC(buf_size); + if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0) + err=ZIP_ERRNO; + + while ((size_central_dir_to_read>0) && (err==ZIP_OK)) + { + ZPOS64_T read_this = SIZEDATA_INDATABLOCK; + if (read_this > size_central_dir_to_read) + read_this = size_central_dir_to_read; + + if (ZREAD64(pziinit->z_filefunc, pziinit->filestream,buf_read,(uLong)read_this) != read_this) + err=ZIP_ERRNO; + + if (err==ZIP_OK) + err = add_data_in_datablock(&pziinit->central_dir,buf_read, (uLong)read_this); + + size_central_dir_to_read-=read_this; + } + TRYFREE(buf_read); + } + pziinit->begin_pos = byte_before_the_zipfile; + pziinit->number_entry = number_entry_CD; + + if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET) != 0) + err=ZIP_ERRNO; + + return err; +} + + +#endif /* !NO_ADDFILEINEXISTINGZIP*/ + + +/************************************************************/ +extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def); +extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) +{ + zip64_internal ziinit; + zip64_internal* zi; + int err=ZIP_OK; + + ziinit.z_filefunc.zseek32_file = NULL; + ziinit.z_filefunc.ztell32_file = NULL; + if (pzlib_filefunc64_32_def==NULL) + fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64); + else + ziinit.z_filefunc = *pzlib_filefunc64_32_def; + + ziinit.filestream = ZOPEN64(ziinit.z_filefunc, + pathname, + (append == APPEND_STATUS_CREATE) ? + (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) : + (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING)); + + if (ziinit.filestream == NULL) + return NULL; + + if (append == APPEND_STATUS_CREATEAFTER) + ZSEEK64(ziinit.z_filefunc,ziinit.filestream,0,SEEK_END); + + ziinit.begin_pos = ZTELL64(ziinit.z_filefunc,ziinit.filestream); + ziinit.in_opened_file_inzip = 0; + ziinit.ci.stream_initialised = 0; + ziinit.number_entry = 0; + ziinit.add_position_when_writting_offset = 0; + init_linkedlist(&(ziinit.central_dir)); + + + + zi = (zip64_internal*)ALLOC(sizeof(zip64_internal)); + if (zi==NULL) + { + ZCLOSE64(ziinit.z_filefunc,ziinit.filestream); + return NULL; + } + + /* now we add file in a zipfile */ +# ifndef NO_ADDFILEINEXISTINGZIP + ziinit.globalcomment = NULL; + if (append == APPEND_STATUS_ADDINZIP) + { + // Read and Cache Central Directory Records + err = LoadCentralDirectoryRecord(&ziinit); + } + + if (globalcomment) + { + *globalcomment = ziinit.globalcomment; + } +# endif /* !NO_ADDFILEINEXISTINGZIP*/ + + if (err != ZIP_OK) + { +# ifndef NO_ADDFILEINEXISTINGZIP + TRYFREE(ziinit.globalcomment); +# endif /* !NO_ADDFILEINEXISTINGZIP*/ + TRYFREE(zi); + return NULL; + } + else + { + *zi = ziinit; + return (zipFile)zi; + } +} + +extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) +{ + if (pzlib_filefunc32_def != NULL) + { + zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; + fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def); + return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); + } + else + return zipOpen3(pathname, append, globalcomment, NULL); +} + +extern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) +{ + if (pzlib_filefunc_def != NULL) + { + zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; + zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def; + zlib_filefunc64_32_def_fill.ztell32_file = NULL; + zlib_filefunc64_32_def_fill.zseek32_file = NULL; + return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); + } + else + return zipOpen3(pathname, append, globalcomment, NULL); +} + + + +extern zipFile ZEXPORT zipOpen (const char* pathname, int append) +{ + return zipOpen3((const void*)pathname,append,NULL,NULL); +} + +extern zipFile ZEXPORT zipOpen64 (const void* pathname, int append) +{ + return zipOpen3(pathname,append,NULL,NULL); +} + +int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local); +int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) +{ + /* write the local header */ + int err; + uInt size_filename = (uInt)strlen(filename); + uInt size_extrafield = size_extrafield_local; + + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC, 4); + + if (err==ZIP_OK) + { + if(zi->ci.zip64) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);/* version needed to extract */ + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */ + } + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2); + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2); + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4); + + // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */ + if (err==ZIP_OK) + { + if(zi->ci.zip64) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* compressed size, unknown */ + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */ + } + if (err==ZIP_OK) + { + if(zi->ci.zip64) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* uncompressed size, unknown */ + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */ + } + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2); + + if(zi->ci.zip64) + { + size_extrafield += 20; + } + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield,2); + + if ((err==ZIP_OK) && (size_filename > 0)) + { + if (ZWRITE64(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename) + err = ZIP_ERRNO; + } + + if ((err==ZIP_OK) && (size_extrafield_local > 0)) + { + if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local) + err = ZIP_ERRNO; + } + + + if ((err==ZIP_OK) && (zi->ci.zip64)) + { + // write the Zip64 extended info + short HeaderID = 1; + short DataSize = 16; + ZPOS64_T CompressedSize = 0; + ZPOS64_T UncompressedSize = 0; + + // Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file) + zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream); + +#ifndef __clang_analyzer__ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)HeaderID,2); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)DataSize,2); + + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8); +#endif + } + + return err; +} + +/* + NOTE. + When writing RAW the ZIP64 extended information in extrafield_local and extrafield_global needs to be stripped + before calling this function it can be done with zipRemoveExtraInfoBlock + + It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize + unnecessary allocations. + */ +extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting, + uLong versionMadeBy, uLong flagBase, int zip64) +{ + zip64_internal* zi; + uInt size_filename; + uInt size_comment; + uInt i; + int err = ZIP_OK; + +# ifdef NOCRYPT + if (password != NULL) + return ZIP_PARAMERROR; +# endif + + if (file == NULL) + return ZIP_PARAMERROR; + +#ifdef HAVE_BZIP2 + if ((method!=0) && (method!=Z_DEFLATED) && (method!=Z_BZIP2ED)) + return ZIP_PARAMERROR; +#else + if ((method!=0) && (method!=Z_DEFLATED)) + return ZIP_PARAMERROR; +#endif + + zi = (zip64_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + if (err != ZIP_OK) + return err; + } + + if (filename==NULL) + filename="-"; + + if (comment==NULL) + size_comment = 0; + else + size_comment = (uInt)strlen(comment); + + size_filename = (uInt)strlen(filename); + + if (zipfi == NULL) + zi->ci.dosDate = 0; + else + { + if (zipfi->dosDate != 0) + zi->ci.dosDate = zipfi->dosDate; + else + zi->ci.dosDate = zip64local_TmzDateToDosDate(&zipfi->tmz_date); + } + + zi->ci.flag = flagBase; + if (level==8 || level==9) + zi->ci.flag |= 2; + if (level==2) + zi->ci.flag |= 4; + if (level==1) + zi->ci.flag |= 6; + if (password != NULL) + zi->ci.flag |= 1; + + zi->ci.crc32 = 0; + zi->ci.method = method; + zi->ci.encrypt = 0; + zi->ci.stream_initialised = 0; + zi->ci.pos_in_buffered_data = 0; + zi->ci.raw = raw; + zi->ci.pos_local_header = ZTELL64(zi->z_filefunc,zi->filestream); + + zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment; + zi->ci.size_centralExtraFree = 32; // Extra space we have reserved in case we need to add ZIP64 extra info data + + zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralExtraFree); + + zi->ci.size_centralExtra = size_extrafield_global; + zip64local_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); + /* version info */ + zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)versionMadeBy,2); + zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); + zip64local_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); + zip64local_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); + zip64local_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); + zip64local_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ + zip64local_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ + zip64local_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ + zip64local_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); + zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); + zip64local_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); + zip64local_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ + + if (zipfi==NULL) + zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); + else + zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); + + if (zipfi==NULL) + zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); + else + zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); + + if(zi->ci.pos_local_header >= 0xffffffff) + zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4); + else + zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writting_offset,4); + + for (i=0;ici.central_header+SIZECENTRALHEADER+i) = *(filename+i); + + for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+i) = + *(((const char*)extrafield_global)+i); + + for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+ + size_extrafield_global+i) = *(comment+i); + if (zi->ci.central_header == NULL) + return ZIP_INTERNALERROR; + + zi->ci.zip64 = zip64; + zi->ci.totalCompressedData = 0; + zi->ci.totalUncompressedData = 0; + zi->ci.pos_zip64extrainfo = 0; + + err = Write_LocalFileHeader(zi, filename, size_extrafield_local, extrafield_local); + +#ifdef HAVE_BZIP2 + zi->ci.bstream.avail_in = (uInt)0; + zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; + zi->ci.bstream.total_in_hi32 = 0; + zi->ci.bstream.total_in_lo32 = 0; + zi->ci.bstream.total_out_hi32 = 0; + zi->ci.bstream.total_out_lo32 = 0; +#endif + + zi->ci.stream.avail_in = (uInt)0; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + zi->ci.stream.total_in = 0; + zi->ci.stream.total_out = 0; + zi->ci.stream.data_type = Z_BINARY; + +#ifdef HAVE_BZIP2 + if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED || zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) +#else + if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) +#endif + { + if(zi->ci.method == Z_DEFLATED) + { + zi->ci.stream.zalloc = (alloc_func)0; + zi->ci.stream.zfree = (free_func)0; + zi->ci.stream.opaque = (voidpf)0; + + if (windowBits>0) + windowBits = -windowBits; + + err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy); + + if (err==Z_OK) + zi->ci.stream_initialised = Z_DEFLATED; + } + else if(zi->ci.method == Z_BZIP2ED) + { +#ifdef HAVE_BZIP2 + // Init BZip stuff here + zi->ci.bstream.bzalloc = 0; + zi->ci.bstream.bzfree = 0; + zi->ci.bstream.opaque = (voidpf)0; + + err = BZ2_bzCompressInit(&zi->ci.bstream, level, 0,35); + if(err == BZ_OK) + zi->ci.stream_initialised = Z_BZIP2ED; +#endif + } + + } + +# ifndef NOCRYPT + zi->ci.crypt_header_size = 0; + if ((err==Z_OK) && (password != NULL)) + { + unsigned char bufHead[RAND_HEAD_LEN]; + unsigned int sizeHead; + zi->ci.encrypt = 1; + zi->ci.pcrc_32_tab = (const unsigned long*)get_crc_table(); + /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/ + + sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting); + zi->ci.crypt_header_size = sizeHead; + + if (ZWRITE64(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead) + err = ZIP_ERRNO; + } +# endif + + if (err==Z_OK) + zi->in_opened_file_inzip = 1; + return err; +} + +extern int ZEXPORT zipOpenNewFileInZip4 (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting, + uLong versionMadeBy, uLong flagBase) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, versionMadeBy, flagBase, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip3 (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, VERSIONMADEBY, 0, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting, int zip64) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, VERSIONMADEBY, 0, zip64); +} + +extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, int zip64) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, zip64); +} + +extern int ZEXPORT zipOpenNewFileInZip64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void*extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int zip64) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, 0, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, zip64); +} + +extern int ZEXPORT zipOpenNewFileInZip (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void*extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, 0, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, 0); +} + +local int zip64FlushWriteBuffer(zip64_internal* zi) +{ + int err=ZIP_OK; + + if (zi->ci.encrypt != 0) + { +#ifndef NOCRYPT + uInt i; + int t; + for (i=0;ici.pos_in_buffered_data;i++) + zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i],t); +#endif + } + + if (ZWRITE64(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) != zi->ci.pos_in_buffered_data) + err = ZIP_ERRNO; + + zi->ci.totalCompressedData += zi->ci.pos_in_buffered_data; + +#ifdef HAVE_BZIP2 + if(zi->ci.method == Z_BZIP2ED) + { + zi->ci.totalUncompressedData += zi->ci.bstream.total_in_lo32; + zi->ci.bstream.total_in_lo32 = 0; + zi->ci.bstream.total_in_hi32 = 0; + } + else +#endif + { + zi->ci.totalUncompressedData += zi->ci.stream.total_in; + zi->ci.stream.total_in = 0; + } + + + zi->ci.pos_in_buffered_data = 0; + + return err; +} + +extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned int len) +{ + zip64_internal* zi; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip64_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + + zi->ci.crc32 = crc32(zi->ci.crc32,buf,(uInt)len); + +#ifdef HAVE_BZIP2 + if(zi->ci.method == Z_BZIP2ED && (!zi->ci.raw)) + { + zi->ci.bstream.next_in = (void*)buf; + zi->ci.bstream.avail_in = len; + err = BZ_RUN_OK; + + while ((err==BZ_RUN_OK) && (zi->ci.bstream.avail_in>0)) + { + if (zi->ci.bstream.avail_out == 0) + { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; + } + + + if(err != BZ_RUN_OK) + break; + + if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) + { + uLong uTotalOutBefore_lo = zi->ci.bstream.total_out_lo32; +// uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32; + err=BZ2_bzCompress(&zi->ci.bstream, BZ_RUN); + + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore_lo) ; + } + } + + if(err == BZ_RUN_OK) + err = ZIP_OK; + } + else +#endif + { + zi->ci.stream.next_in = (Bytef*)buf; + zi->ci.stream.avail_in = len; + + while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) + { + if (zi->ci.stream.avail_out == 0) + { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + + + if(err != ZIP_OK) + break; + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + uLong uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_NO_FLUSH); + if(uTotalOutBefore > zi->ci.stream.total_out) + { + int bBreak = 0; + bBreak++; + } + + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + } + else + { + uInt copy_this,i; + if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) + copy_this = zi->ci.stream.avail_in; + else + copy_this = zi->ci.stream.avail_out; + + for (i = 0; i < copy_this; i++) + *(((char*)zi->ci.stream.next_out)+i) = + *(((const char*)zi->ci.stream.next_in)+i); + { + zi->ci.stream.avail_in -= copy_this; + zi->ci.stream.avail_out-= copy_this; + zi->ci.stream.next_in+= copy_this; + zi->ci.stream.next_out+= copy_this; + zi->ci.stream.total_in+= copy_this; + zi->ci.stream.total_out+= copy_this; + zi->ci.pos_in_buffered_data += copy_this; + } + } + }// while(...) + } + + return err; +} + +extern int ZEXPORT zipCloseFileInZipRaw (zipFile file, uLong uncompressed_size, uLong crc32) +{ + return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32); +} + +extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_size, uLong crc32) +{ + zip64_internal* zi; + ZPOS64_T compressed_size; + uLong invalidValue = 0xffffffff; + short datasize = 0; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip64_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + zi->ci.stream.avail_in = 0; + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + while (err==ZIP_OK) + { + uLong uTotalOutBefore; + if (zi->ci.stream.avail_out == 0) + { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + { +#ifndef __clang_analyzer__ + err = ZIP_ERRNO; +#endif + } + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; +#ifndef __clang_analyzer__ + zi->ci.stream.next_out = zi->ci.buffered_data; +#endif + } + uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_FINISH); + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + } + } + else if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) + { +#ifdef HAVE_BZIP2 + err = BZ_FINISH_OK; + while (err==BZ_FINISH_OK) + { + uLong uTotalOutBefore; + if (zi->ci.bstream.avail_out == 0) + { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; + } + uTotalOutBefore = zi->ci.bstream.total_out_lo32; + err=BZ2_bzCompress(&zi->ci.bstream, BZ_FINISH); + if(err == BZ_STREAM_END) + err = Z_STREAM_END; + + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore); + } + + if(err == BZ_FINISH_OK) + err = ZIP_OK; +#endif + } + + if (err==Z_STREAM_END) + err=ZIP_OK; /* this is normal */ + + if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) + { + if (zip64FlushWriteBuffer(zi)==ZIP_ERRNO) + err = ZIP_ERRNO; + } + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + int tmp_err = deflateEnd(&zi->ci.stream); + if (err == ZIP_OK) + err = tmp_err; + zi->ci.stream_initialised = 0; + } +#ifdef HAVE_BZIP2 + else if((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) + { + int tmperr = BZ2_bzCompressEnd(&zi->ci.bstream); + if (err==ZIP_OK) + err = tmperr; + zi->ci.stream_initialised = 0; + } +#endif + + if (!zi->ci.raw) + { + crc32 = (uLong)zi->ci.crc32; + uncompressed_size = zi->ci.totalUncompressedData; + } + compressed_size = zi->ci.totalCompressedData; + +# ifndef NOCRYPT + compressed_size += zi->ci.crypt_header_size; +# endif + + // update Current Item crc and sizes, + if(compressed_size >= 0xffffffff || uncompressed_size >= 0xffffffff || zi->ci.pos_local_header >= 0xffffffff) + { + /*version Made by*/ + zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)45,2); + /*version needed*/ + zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)45,2); + + } + + zip64local_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/ + + + if(compressed_size >= 0xffffffff) + zip64local_putValue_inmemory(zi->ci.central_header+20, invalidValue,4); /*compr size*/ + else + zip64local_putValue_inmemory(zi->ci.central_header+20, compressed_size,4); /*compr size*/ + + /// set internal file attributes field + if (zi->ci.stream.data_type == Z_ASCII) + zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2); + + if(uncompressed_size >= 0xffffffff) + zip64local_putValue_inmemory(zi->ci.central_header+24, invalidValue,4); /*uncompr size*/ + else + zip64local_putValue_inmemory(zi->ci.central_header+24, uncompressed_size,4); /*uncompr size*/ + + // Add ZIP64 extra info field for uncompressed size + if(uncompressed_size >= 0xffffffff) + datasize += 8; + + // Add ZIP64 extra info field for compressed size + if(compressed_size >= 0xffffffff) + datasize += 8; + + // Add ZIP64 extra info field for relative offset to local file header of current file + if(zi->ci.pos_local_header >= 0xffffffff) + datasize += 8; + + if(datasize > 0) + { + char* p = NULL; + + if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree) + { + // we can not write more data to the buffer that we have room for. + return ZIP_BADZIPFILE; + } + + p = zi->ci.central_header + zi->ci.size_centralheader; + + // Add Extra Information Header for 'ZIP64 information' + zip64local_putValue_inmemory(p, 0x0001, 2); // HeaderID + p += 2; + zip64local_putValue_inmemory(p, datasize, 2); // DataSize + p += 2; + + if(uncompressed_size >= 0xffffffff) + { + zip64local_putValue_inmemory(p, uncompressed_size, 8); + p += 8; + } + + if(compressed_size >= 0xffffffff) + { + zip64local_putValue_inmemory(p, compressed_size, 8); + p += 8; + } + + if(zi->ci.pos_local_header >= 0xffffffff) + { + zip64local_putValue_inmemory(p, zi->ci.pos_local_header, 8); +#ifndef __clang_analyzer__ + p += 8; +#endif + } + + // Update how much extra free space we got in the memory buffer + // and increase the centralheader size so the new ZIP64 fields are included + // ( 4 below is the size of HeaderID and DataSize field ) + zi->ci.size_centralExtraFree -= datasize + 4; + zi->ci.size_centralheader += datasize + 4; + + // Update the extra info size field + zi->ci.size_centralExtra += datasize + 4; + zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)zi->ci.size_centralExtra,2); + } + + if (err==ZIP_OK) + err = add_data_in_datablock(&zi->central_dir, zi->ci.central_header, (uLong)zi->ci.size_centralheader); + + free(zi->ci.central_header); + + if (err==ZIP_OK) + { + // Update the LocalFileHeader with the new values. + + ZPOS64_T cur_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); + + if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0) + err = ZIP_ERRNO; + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */ + + if(uncompressed_size >= 0xffffffff) + { + if(zi->ci.pos_zip64extrainfo > 0) + { + // Update the size in the ZIP64 extended field. + if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_zip64extrainfo + 4,ZLIB_FILEFUNC_SEEK_SET)!=0) + err = ZIP_ERRNO; + + if (err==ZIP_OK) /* compressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, uncompressed_size, 8); + + if (err==ZIP_OK) /* uncompressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8); + } + } + else + { + if (err==ZIP_OK) /* compressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4); + + if (err==ZIP_OK) /* uncompressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4); + } + + if (ZSEEK64(zi->z_filefunc,zi->filestream, cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0) + err = ZIP_ERRNO; + } + + zi->number_entry ++; + zi->in_opened_file_inzip = 0; + + return err; +} + +extern int ZEXPORT zipCloseFileInZip (zipFile file) +{ + return zipCloseFileInZipRaw (file,0,0); +} + +int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip); +int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) +{ + int err = ZIP_OK; + ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writting_offset; + + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4); + + /*num disks*/ + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); + + /*relative offset*/ + if (err==ZIP_OK) /* Relative offset to the Zip64EndOfCentralDirectory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream, pos,8); + + /*total disks*/ /* Do not support spawning of disk so always say 1 here*/ + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)1,4); + + return err; +} + +int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip); +int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) +{ + int err = ZIP_OK; + + uLong Zip64DataSize = 44; + + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDHEADERMAGIC,4); + + if (err==ZIP_OK) /* size of this 'zip64 end of central directory' */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)Zip64DataSize,8); // why ZPOS64_T of this ? + + if (err==ZIP_OK) /* version made by */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); + + if (err==ZIP_OK) /* version needed */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); + + if (err==ZIP_OK) /* number of this disk */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); + + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); + + if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); + + if (err==ZIP_OK) /* total number of entries in the central dir */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); + + if (err==ZIP_OK) /* size of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)size_centraldir,8); + + if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ + { + ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; + err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8); + } + return err; +} + +int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip); +int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) +{ + int err = ZIP_OK; + + /*signature*/ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4); + + if (err==ZIP_OK) /* number of this disk */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); + + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); + + if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ + { + { + if(zi->number_entry >= 0xFFFF) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); + } + } + + if (err==ZIP_OK) /* total number of entries in the central dir */ + { + if(zi->number_entry >= 0xFFFF) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); + } + + if (err==ZIP_OK) /* size of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4); + + if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ + { + ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; + if(pos >= 0xffffffff) + { + err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4); + } + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4); + } + + return err; +} + +int Write_GlobalComment(zip64_internal* zi, const char* global_comment); +int Write_GlobalComment(zip64_internal* zi, const char* global_comment) +{ + int err = ZIP_OK; + uInt size_global_comment = 0; + + if(global_comment != NULL) + size_global_comment = (uInt)strlen(global_comment); + + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2); + + if (err == ZIP_OK && size_global_comment > 0) + { + if (ZWRITE64(zi->z_filefunc,zi->filestream, global_comment, size_global_comment) != size_global_comment) + err = ZIP_ERRNO; + } + return err; +} + +extern int ZEXPORT zipClose (zipFile file, const char* global_comment) +{ + zip64_internal* zi; + int err = 0; + uLong size_centraldir = 0; + ZPOS64_T centraldir_pos_inzip; + ZPOS64_T pos; + + if (file == NULL) + return ZIP_PARAMERROR; + + zi = (zip64_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + } + +#ifndef NO_ADDFILEINEXISTINGZIP + if (global_comment==NULL) + global_comment = zi->globalcomment; +#endif + + centraldir_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); + + if (err==ZIP_OK) + { + linkedlist_datablock_internal* ldi = zi->central_dir.first_block; + while (ldi!=NULL) + { + if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) + { + if (ZWRITE64(zi->z_filefunc,zi->filestream, ldi->data, ldi->filled_in_this_block) != ldi->filled_in_this_block) + err = ZIP_ERRNO; + } + + size_centraldir += ldi->filled_in_this_block; + ldi = ldi->next_datablock; + } + } + free_linkedlist(&(zi->central_dir)); + + pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; + if(pos >= 0xffffffff) + { + ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream); + Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); + + Write_Zip64EndOfCentralDirectoryLocator(zi, Zip64EOCDpos); + } + + if (err==ZIP_OK) + err = Write_EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); + + if(err == ZIP_OK) + err = Write_GlobalComment(zi, global_comment); + + if (ZCLOSE64(zi->z_filefunc,zi->filestream) != 0) + if (err == ZIP_OK) + err = ZIP_ERRNO; + +#ifndef NO_ADDFILEINEXISTINGZIP + TRYFREE(zi->globalcomment); +#endif + TRYFREE(zi); + + return err; +} + +extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHeader) +{ + char* p = pData; + int size = 0; + char* pNewHeader; + char* pTmp; + short header; + short dataSize; + + int retVal = ZIP_OK; + + if(pData == NULL || *dataLen < 4) + return ZIP_PARAMERROR; + + pNewHeader = (char*)ALLOC(*dataLen); + pTmp = pNewHeader; + + while(p < (pData + *dataLen)) + { + header = *(short*)p; + dataSize = *(((short*)p)+1); + + if( header == sHeader ) // Header found. + { + p += dataSize + 4; // skip it. do not copy to temp buffer + } + else + { + // Extra Info block should not be removed, So copy it to the temp buffer. + memcpy(pTmp, p, dataSize + 4); + p += dataSize + 4; + size += dataSize + 4; + } + + } + + if(size < *dataLen) + { + // clean old extra info block. + memset(pData,0, *dataLen); + + // copy the new extra info block over the old + if(size > 0) + memcpy(pData, pNewHeader, size); + + // set the new extra info size + *dataLen = size; + + retVal = ZIP_OK; + } + else + retVal = ZIP_ERRNO; + + TRYFREE(pNewHeader); + + return retVal; +} diff --git a/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/zip.h b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/zip.h new file mode 100755 index 0000000000..eec1082b32 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Classes/iOS/ssziparchive/minizip/zip.h @@ -0,0 +1,362 @@ +/* zip.h -- IO on .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + --------------------------------------------------------------------------- + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + --------------------------------------------------------------------------- + + Changes + + See header of zip.h + +*/ + +#ifndef _zip12_H +#define _zip12_H + +#ifdef __cplusplus +extern "C" { +#endif + +//#define HAVE_BZIP2 + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#ifdef HAVE_BZIP2 +#include "bzlib.h" +#endif + +#define Z_BZIP2ED 12 + +#if defined(STRICTZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagzipFile__ { int unused; } zipFile__; +typedef zipFile__ *zipFile; +#else +typedef voidp zipFile; +#endif + +#define ZIP_OK (0) +#define ZIP_EOF (0) +#define ZIP_ERRNO (Z_ERRNO) +#define ZIP_PARAMERROR (-102) +#define ZIP_BADZIPFILE (-103) +#define ZIP_INTERNALERROR (-104) + +#ifndef DEF_MEM_LEVEL +# if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +# else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +# endif +#endif +/* default memLevel */ + +/* tm_zip contain date/time info */ +typedef struct tm_zip_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_zip; + +typedef struct +{ + tm_zip tmz_date; /* date in understandable format */ + uLong dosDate; /* if dos_date == 0, tmu_date is used */ +/* uLong flag; */ /* general purpose bit flag 2 bytes */ + + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ +} zip_fileinfo; + +typedef const char* zipcharpc; + + +#define APPEND_STATUS_CREATE (0) +#define APPEND_STATUS_CREATEAFTER (1) +#define APPEND_STATUS_ADDINZIP (2) + +extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); +extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append)); +/* + Create a zipfile. + pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on + an Unix computer "zlib/zlib113.zip". + if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip + will be created at the end of the file. + (useful if the file contain a self extractor code) + if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will + add files in existing zip (be sure you don't add file that doesn't exist) + If the zipfile cannot be opened, the return value is NULL. + Else, the return value is a zipFile Handle, usable with other function + of this zip package. +*/ + +/* Note : there is no delete function into a zipfile. + If you want delete file into a zipfile, you must open a zipfile, and create another + Of couse, you can use RAW reading and writing to copy the file you did not want delte +*/ + +extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, + int append, + zipcharpc* globalcomment, + zlib_filefunc_def* pzlib_filefunc_def)); + +extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname, + int append, + zipcharpc* globalcomment, + zlib_filefunc64_def* pzlib_filefunc_def)); + +extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level)); + +extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int zip64)); + +/* + Open a file in the ZIP for writing. + filename : the filename in zip (if NULL, '-' without quote will be used + *zipfi contain supplemental information + if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local + contains the extrafield data the the local header + if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global + contains the extrafield data the the local header + if comment != NULL, comment contain the comment string + method contain the compression method (0 for store, Z_DEFLATED for deflate) + level contain the level of compression (can be Z_DEFAULT_COMPRESSION) + zip64 is set to 1 if a zip64 extended information block should be added to the local file header. + this MUST be '1' if the uncompressed size is >= 0xffffffff. + +*/ + + +extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw)); + + +extern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int zip64)); +/* + Same than zipOpenNewFileInZip, except if raw=1, we write raw file + */ + +extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting)); + +extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + int zip64 + )); + +/* + Same than zipOpenNewFileInZip2, except + windowBits,memLevel,,strategy : see parameter strategy in deflateInit2 + password : crypting password (NULL for no crypting) + crcForCrypting : crc of file to compress (needed for crypting) + */ + +extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + uLong versionMadeBy, + uLong flagBase + )); + + +extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + uLong versionMadeBy, + uLong flagBase, + int zip64 + )); +/* + Same than zipOpenNewFileInZip4, except + versionMadeBy : value for Version made by field + flag : value for flag field (compression level info will be added) + */ + + +extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, + const void* buf, + unsigned len)); +/* + Write data in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); +/* + Close the current file in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, + uLong uncompressed_size, + uLong crc32)); + +extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file, + ZPOS64_T uncompressed_size, + uLong crc32)); + +/* + Close the current file in the zipfile, for file opened with + parameter raw=1 in zipOpenNewFileInZip2 + uncompressed_size and crc32 are value for the uncompressed size +*/ + +extern int ZEXPORT zipClose OF((zipFile file, + const char* global_comment)); +/* + Close the zipfile +*/ + + +extern int ZEXPORT zipRemoveExtraInfoBlock OF((char* pData, int* dataLen, short sHeader)); +/* + zipRemoveExtraInfoBlock - Added by Mathias Svensson + + Remove extra information block from a extra information data for the local file header or central directory header + + It is needed to remove ZIP64 extra information blocks when before data is written if using RAW mode. + + 0x0001 is the signature header for the ZIP64 extra information blocks + + usage. + Remove ZIP64 Extra information from a central director extra field data + zipRemoveExtraInfoBlock(pCenDirExtraFieldData, &nCenDirExtraFieldDataLen, 0x0001); + + Remove ZIP64 Extra information from a Local File Header extra field data + zipRemoveExtraInfoBlock(pLocalHeaderExtraFieldData, &nLocalHeaderExtraFieldDataLen, 0x0001); +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _zip64_H */ diff --git a/samples/Javascript/CocosPlayer/Resources/Published-iOS/resources-ipadhd/ccb_btn-play.png.REMOVED.git-id b/samples/Javascript/CocosPlayer/Resources/Published-iOS/resources-ipadhd/ccb_btn-play.png.REMOVED.git-id new file mode 100644 index 0000000000..8cd80b63be --- /dev/null +++ b/samples/Javascript/CocosPlayer/Resources/Published-iOS/resources-ipadhd/ccb_btn-play.png.REMOVED.git-id @@ -0,0 +1 @@ +ba6bcddd1ff6445feb931434c6a04546bc936a4e \ No newline at end of file diff --git a/samples/Javascript/CocosPlayer/Resources/Published-iOS/resources-ipadhd/ccb_btn-run-dis.png.REMOVED.git-id b/samples/Javascript/CocosPlayer/Resources/Published-iOS/resources-ipadhd/ccb_btn-run-dis.png.REMOVED.git-id new file mode 100644 index 0000000000..4c4883b063 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Resources/Published-iOS/resources-ipadhd/ccb_btn-run-dis.png.REMOVED.git-id @@ -0,0 +1 @@ +e386fa2dd33381cb9905ec5472ba7b48bdd60808 \ No newline at end of file diff --git a/samples/Javascript/CocosPlayer/Resources/Published-iOS/resources-ipadhd/ccb_btn-run-down.png.REMOVED.git-id b/samples/Javascript/CocosPlayer/Resources/Published-iOS/resources-ipadhd/ccb_btn-run-down.png.REMOVED.git-id new file mode 100644 index 0000000000..9d76dc4ada --- /dev/null +++ b/samples/Javascript/CocosPlayer/Resources/Published-iOS/resources-ipadhd/ccb_btn-run-down.png.REMOVED.git-id @@ -0,0 +1 @@ +263d1eb95a83c1320c7c988e633f348479d38fb5 \ No newline at end of file diff --git a/samples/Javascript/CocosPlayer/Resources/Published-iOS/resources-ipadhd/ccb_btn-run.png.REMOVED.git-id b/samples/Javascript/CocosPlayer/Resources/Published-iOS/resources-ipadhd/ccb_btn-run.png.REMOVED.git-id new file mode 100644 index 0000000000..4a66e6a540 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Resources/Published-iOS/resources-ipadhd/ccb_btn-run.png.REMOVED.git-id @@ -0,0 +1 @@ +823b99b16a9fdddb84bf8af36e2be53cf928ea04 \ No newline at end of file diff --git a/samples/Javascript/CocosPlayer/Resources/Published-iOS/resources-ipadhd/ccb_logo.png.REMOVED.git-id b/samples/Javascript/CocosPlayer/Resources/Published-iOS/resources-ipadhd/ccb_logo.png.REMOVED.git-id new file mode 100644 index 0000000000..3f37153ef2 --- /dev/null +++ b/samples/Javascript/CocosPlayer/Resources/Published-iOS/resources-ipadhd/ccb_logo.png.REMOVED.git-id @@ -0,0 +1 @@ +7b5dab861d78877bb1354fc832404f9dfb68b0ee \ No newline at end of file diff --git a/samples/Javascript/CocosPlayer/proj.android/jni/cocosplayer/main.cpp b/samples/Javascript/CocosPlayer/proj.android/jni/cocosplayer/main.cpp index 0ab5514f17..5d3e648dfe 100644 --- a/samples/Javascript/CocosPlayer/proj.android/jni/cocosplayer/main.cpp +++ b/samples/Javascript/CocosPlayer/proj.android/jni/cocosplayer/main.cpp @@ -78,6 +78,7 @@ void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv* env, jobject thi { handle_disconnected(); } + void Java_org_cocos2dx_cocosplayer_CocosPlayerSocket_nativeSetOrientation(JNIEnv* env, jobject thiz, jboolean isPortrait) { handle_set_orient((bool)isPortrait); diff --git a/samples/Javascript/CocosPlayer/proj.android/src/org/cocos2dx/cocosplayer/CocosPlayerSocket.java b/samples/Javascript/CocosPlayer/proj.android/src/org/cocos2dx/cocosplayer/CocosPlayerSocket.java index 9cfdbf00f3..4fa661bbb1 100644 --- a/samples/Javascript/CocosPlayer/proj.android/src/org/cocos2dx/cocosplayer/CocosPlayerSocket.java +++ b/samples/Javascript/CocosPlayer/proj.android/src/org/cocos2dx/cocosplayer/CocosPlayerSocket.java @@ -105,7 +105,7 @@ public class CocosPlayerSocket { for(int i =0 ; i < keys.length; ++i ) { } if(cmd.equalsIgnoreCase("zip")) { - //cleanCache(); + // cleanCache(); try { Log.i(TAG, "Size of NSDATA payload: "+((NSData)data.objectForKey("data")).bytes().length); CCBFileUtilsHelper.unzipCCB(((NSData)data.objectForKey("data")).bytes(), cw); diff --git a/samples/Javascript/CocosPlayer/proj.ios/AppController.h b/samples/Javascript/CocosPlayer/proj.ios/AppController.h new file mode 100644 index 0000000000..2488579c0f --- /dev/null +++ b/samples/Javascript/CocosPlayer/proj.ios/AppController.h @@ -0,0 +1,23 @@ +#import "ServerController.h" + + +void startServer(bool isRetina, bool isIPhone); +void cleanCache() { + std::string path = cocos2d::CCFileUtils::sharedFileUtils()->getWritablePath(); + NSString *writeablePath = [NSString stringWithCString:path.c_str() encoding:NSASCIIStringEncoding]; + NSString* dirPath = [writeablePath stringByAppendingPathComponent:@"ccb"]; + + [[NSFileManager defaultManager] removeItemAtPath:dirPath error:NULL]; + [[NSFileManager defaultManager] removeItemAtPath:writeablePath error:NULL]; +} + + +@class RootViewController; + +@interface AppController : NSObject { + UIWindow *window; + RootViewController *viewController; +} + +@end + diff --git a/samples/Javascript/CocosPlayer/proj.ios/AppController.mm b/samples/Javascript/CocosPlayer/proj.ios/AppController.mm new file mode 100644 index 0000000000..d74ce933b5 --- /dev/null +++ b/samples/Javascript/CocosPlayer/proj.ios/AppController.mm @@ -0,0 +1,160 @@ + +#import +#import "AppController.h" +#import "cocos2d.h" +#import "EAGLView.h" +#import "AppDelegate.h" + +#import "RootViewController.h" + +ServerController *server; + +extern "C" { + + + void setDeviceResolutionJNI(const char *text) { + + } + + void cleanCacheDirJNI(){ + cleanCache(); + } + + void updatePairing(const char *pairing) { + NSString *code = [NSString stringWithCString:pairing encoding:NSASCIIStringEncoding]; + if([code isEqual:@"Auto"]) { + [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"pairing"]; + } else { + [[NSUserDefaults standardUserDefaults] setObject:code forKey:@"pairing"]; + } + [[NSUserDefaults standardUserDefaults] synchronize]; + [server updatePairing]; + } + + const char * getCCBDirectoryPath() { + std::string path = cocos2d::CCFileUtils::sharedFileUtils()->getWritablePath(); + NSString *writeablePath = [NSString stringWithCString:path.c_str() encoding:NSASCIIStringEncoding]; + NSString* dirPath = [writeablePath stringByAppendingPathComponent:@"ccb"]; + return [dirPath cStringUsingEncoding:NSASCIIStringEncoding]; + } + +} + +@implementation AppController + +#pragma mark - +#pragma mark Application lifecycle + +// cocos2d application instance +static AppDelegate s_sharedApplication; + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + + // Override point for customization after application launch. + + // Add the view controller's view to the window and display. + window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]]; + EAGLView *__glView = [EAGLView viewWithFrame: [window bounds] + pixelFormat: kEAGLColorFormatRGBA8 + depthFormat: GL_DEPTH_COMPONENT16 //_OES + preserveBackbuffer: NO + sharegroup: nil + multiSampling: NO + numberOfSamples: 0 ]; + + // Use RootViewController manage EAGLView + viewController = [[RootViewController alloc] initWithNibName:nil bundle:nil]; + viewController.wantsFullScreenLayout = YES; + viewController.view = __glView; + + // Set RootViewController to window + if ( [[UIDevice currentDevice].systemVersion floatValue] < 6.0) + { + // warning: addSubView doesn't work on iOS6 + [window addSubview: viewController.view]; + } + else + { + // use this method on ios6 + [window setRootViewController:viewController]; + } + + [window makeKeyAndVisible]; + + [[UIApplication sharedApplication] setStatusBarHidden: YES]; + + cocos2d::CCApplication::sharedApplication()->run(); + + + BOOL isRetina = s_sharedApplication.isRetina; + BOOL isIPhone = s_sharedApplication.isIPhone; + NSLog(@"ISIphone: %d %d", isIPhone, isRetina); + startServer(s_sharedApplication.isRetina, s_sharedApplication.isIPhone); + return YES; +} + + +- (void)applicationWillResignActive:(UIApplication *)application { + /* + Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. + */ + cocos2d::CCDirector::sharedDirector()->pause(); +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + /* + Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + */ + cocos2d::CCDirector::sharedDirector()->resume(); +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + /* + Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + If your application supports background execution, called instead of applicationWillTerminate: when the user quits. + */ + cocos2d::CCApplication::sharedApplication()->applicationDidEnterBackground(); +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + /* + Called as part of transition from the background to the inactive state: here you can undo many of the changes made on entering the background. + */ + cocos2d::CCApplication::sharedApplication()->applicationWillEnterForeground(); +} + +- (void)applicationWillTerminate:(UIApplication *)application { + /* + Called when the application is about to terminate. + See also applicationDidEnterBackground:. + */ +} + + +#pragma mark - +#pragma mark Memory management + +- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { + /* + Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later. + */ + cocos2d::CCDirector::sharedDirector()->purgeCachedData(); +} + +void startServer(bool isRetina, bool isIPhone) { + server = [[ServerController alloc] init]; + server.isIPhone = isIPhone; + server.isRetina = isRetina; + [server start]; + + [server setNetworkStatus:kCCBNetworkStatusWaiting]; +} + +- (void)dealloc { + [super dealloc]; +} + + +@end + diff --git a/samples/Javascript/CocosPlayer/proj.ios/CocosPlayer.xcodeproj/project.pbxproj.REMOVED.git-id b/samples/Javascript/CocosPlayer/proj.ios/CocosPlayer.xcodeproj/project.pbxproj.REMOVED.git-id new file mode 100644 index 0000000000..95247c8767 --- /dev/null +++ b/samples/Javascript/CocosPlayer/proj.ios/CocosPlayer.xcodeproj/project.pbxproj.REMOVED.git-id @@ -0,0 +1 @@ +1ff25700351d8711c5dab5fc4428f896956b1eea \ No newline at end of file diff --git a/samples/Javascript/CocosPlayer/proj.ios/Default-568h@2x.png.REMOVED.git-id b/samples/Javascript/CocosPlayer/proj.ios/Default-568h@2x.png.REMOVED.git-id new file mode 100644 index 0000000000..8f5838f3a8 --- /dev/null +++ b/samples/Javascript/CocosPlayer/proj.ios/Default-568h@2x.png.REMOVED.git-id @@ -0,0 +1 @@ +66c6d1cead373b45218424f6a82f370897e443e4 \ No newline at end of file diff --git a/samples/Javascript/CocosPlayer/proj.ios/Default@2x.png.REMOVED.git-id b/samples/Javascript/CocosPlayer/proj.ios/Default@2x.png.REMOVED.git-id new file mode 100644 index 0000000000..8843505b20 --- /dev/null +++ b/samples/Javascript/CocosPlayer/proj.ios/Default@2x.png.REMOVED.git-id @@ -0,0 +1 @@ +84689888a14a2123d2b39f7f2f61be8c15207479 \ No newline at end of file diff --git a/samples/Javascript/CocosPlayer/proj.ios/Prefix.pch b/samples/Javascript/CocosPlayer/proj.ios/Prefix.pch new file mode 100644 index 0000000000..168ddec406 --- /dev/null +++ b/samples/Javascript/CocosPlayer/proj.ios/Prefix.pch @@ -0,0 +1,8 @@ +// +// Prefix header for all source files of the 'HelloJavascript' target in the 'HelloJavascript' project +// + +#ifdef __OBJC__ + #import + #import +#endif diff --git a/samples/Javascript/CocosPlayer/proj.ios/RootViewController.h b/samples/Javascript/CocosPlayer/proj.ios/RootViewController.h new file mode 100644 index 0000000000..a40c2edd28 --- /dev/null +++ b/samples/Javascript/CocosPlayer/proj.ios/RootViewController.h @@ -0,0 +1,33 @@ +/**************************************************************************** + Copyright (c) 2010-2011 cocos2d-x.org + Copyright (c) 2010 Ricardo Quesada + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#import + + +@interface RootViewController : UIViewController { + +} + +@end diff --git a/samples/Javascript/CocosPlayer/proj.ios/RootViewController.mm b/samples/Javascript/CocosPlayer/proj.ios/RootViewController.mm new file mode 100644 index 0000000000..c6978fb6e4 --- /dev/null +++ b/samples/Javascript/CocosPlayer/proj.ios/RootViewController.mm @@ -0,0 +1,66 @@ + +#import "RootViewController.h" + + +@implementation RootViewController + +/* + // The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad. +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { + if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) { + // Custom initialization + } + return self; +} +*/ + +/* +// Implement loadView to create a view hierarchy programmatically, without using a nib. +- (void)loadView { +} +*/ + +/* +// Implement viewDidLoad to do additional setup after loading the view, typically from a nib. +- (void)viewDidLoad { + [super viewDidLoad]; +} + +*/ +// Override to allow orientations other than the default portrait orientation. +// This method is deprecated on ios6 +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { + return UIInterfaceOrientationIsLandscape( interfaceOrientation ); +} + +// For ios6, use supportedInterfaceOrientations & shouldAutorotate instead +- (NSUInteger) supportedInterfaceOrientations{ +#ifdef __IPHONE_6_0 + return UIInterfaceOrientationMaskAllButUpsideDown; +#endif +} + +- (BOOL) shouldAutorotate { + return YES; +} + +- (void)didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + + // Release any cached data, images, etc that aren't in use. +} + +- (void)viewDidUnload { + [super viewDidUnload]; + // Release any retained subviews of the main view. + // e.g. self.myOutlet = nil; +} + + +- (void)dealloc { + [super dealloc]; +} + + +@end diff --git a/samples/Javascript/CocosPlayer/proj.ios/main.m b/samples/Javascript/CocosPlayer/proj.ios/main.m new file mode 100644 index 0000000000..b1286e31be --- /dev/null +++ b/samples/Javascript/CocosPlayer/proj.ios/main.m @@ -0,0 +1,11 @@ + + +#import + +int main(int argc, char *argv[]) { + + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + int retVal = UIApplicationMain(argc, argv, nil, @"AppController"); + [pool release]; + return retVal; +}