From 0891cd824249ed15cb2c53e35329b0591398d8f5 Mon Sep 17 00:00:00 2001 From: NightBits Date: Wed, 19 Dec 2018 20:42:46 +0100 Subject: [PATCH] Initial commit --- .DS_Store | Bin 0 -> 6148 bytes EonaCatTools.xcodeproj/project.pbxproj | 636 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + EonaCatTools/.DS_Store | Bin 0 -> 6148 bytes EonaCatTools/AppDelegate.h | 16 + EonaCatTools/AppDelegate.m | 55 ++ EonaCatTools/Base.lproj/Main_iPad.storyboard | 114 ++++ .../Base.lproj/Main_iPhone.storyboard | 114 ++++ EonaCatTools/EonaCatTools-Info.plist | 49 ++ EonaCatTools/EonaCatTools-Prefix.pch | 16 + .../AppIcon.appiconset/Contents.json | 48 ++ .../LaunchImage.launchimage/Contents.json | 51 ++ EonaCatTools/Images/toast.png | Bin 0 -> 17067 bytes EonaCatTools/Tools/.DS_Store | Bin 0 -> 6148 bytes EonaCatTools/Tools/ExceptionsLogger/.DS_Store | Bin 0 -> 6148 bytes .../Dutch.lproj/ExceptionsLogger.strings | 5 + .../English.lproj/ExceptionsLogger.strings | 5 + .../Tools/ExceptionsLogger/ExceptionHandler.h | 20 + .../Tools/ExceptionsLogger/ExceptionHandler.m | 359 ++++++++++ .../ExceptionsLogger/ExceptionLogger-iPad.xib | 46 ++ .../Tools/ExceptionsLogger/ExceptionLogger.h | 24 + .../Tools/ExceptionsLogger/ExceptionLogger.m | 226 +++++++ .../ExceptionsLogger/ExceptionLogger.png | Bin 0 -> 15163 bytes .../ExceptionsLogger/ExceptionLogger.xib | 47 ++ EonaCatTools/Tools/Lockscreen/.DS_Store | Bin 0 -> 6148 bytes .../Dutch.lproj/LockController.strings | 6 + .../English.lproj/LockController.strings | 6 + .../Tools/Lockscreen/LockController.h | 73 ++ .../Tools/Lockscreen/LockController.m | 444 ++++++++++++ EonaCatTools/Tools/Popup/.DS_Store | Bin 0 -> 6148 bytes EonaCatTools/Tools/Popup/Popup.h | 25 + EonaCatTools/Tools/Popup/Popup.m | 83 +++ EonaCatTools/Tools/Toast/Toast.h | 27 + EonaCatTools/Tools/Toast/Toast.m | 375 +++++++++++ EonaCatTools/Tools/Toast/toast.wav | Bin 0 -> 114760 bytes .../Tools/uniqueIdentifier/DeviceIdentifier.h | 21 + .../Tools/uniqueIdentifier/DeviceIdentifier.m | 101 +++ EonaCatTools/Tools/uniqueIdentifier/SHA1.h | 13 + EonaCatTools/Tools/uniqueIdentifier/SHA1.m | 29 + EonaCatTools/ViewController.h | 18 + EonaCatTools/ViewController.m | 89 +++ EonaCatTools/en.lproj/InfoPlist.strings | 2 + EonaCatTools/main.m | 17 + EonaCatToolsTests/.DS_Store | Bin 0 -> 6148 bytes .../EonaCatToolsTests-Info.plist | 22 + EonaCatToolsTests/EonaCatToolsTests.m | 35 + EonaCatToolsTests/en.lproj/InfoPlist.strings | 2 + README.md | 12 +- 48 files changed, 3236 insertions(+), 2 deletions(-) create mode 100644 .DS_Store create mode 100644 EonaCatTools.xcodeproj/project.pbxproj create mode 100644 EonaCatTools.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 EonaCatTools/.DS_Store create mode 100644 EonaCatTools/AppDelegate.h create mode 100644 EonaCatTools/AppDelegate.m create mode 100644 EonaCatTools/Base.lproj/Main_iPad.storyboard create mode 100644 EonaCatTools/Base.lproj/Main_iPhone.storyboard create mode 100644 EonaCatTools/EonaCatTools-Info.plist create mode 100644 EonaCatTools/EonaCatTools-Prefix.pch create mode 100644 EonaCatTools/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 EonaCatTools/Images.xcassets/LaunchImage.launchimage/Contents.json create mode 100644 EonaCatTools/Images/toast.png create mode 100644 EonaCatTools/Tools/.DS_Store create mode 100644 EonaCatTools/Tools/ExceptionsLogger/.DS_Store create mode 100644 EonaCatTools/Tools/ExceptionsLogger/Dutch.lproj/ExceptionsLogger.strings create mode 100644 EonaCatTools/Tools/ExceptionsLogger/English.lproj/ExceptionsLogger.strings create mode 100644 EonaCatTools/Tools/ExceptionsLogger/ExceptionHandler.h create mode 100644 EonaCatTools/Tools/ExceptionsLogger/ExceptionHandler.m create mode 100644 EonaCatTools/Tools/ExceptionsLogger/ExceptionLogger-iPad.xib create mode 100644 EonaCatTools/Tools/ExceptionsLogger/ExceptionLogger.h create mode 100644 EonaCatTools/Tools/ExceptionsLogger/ExceptionLogger.m create mode 100644 EonaCatTools/Tools/ExceptionsLogger/ExceptionLogger.png create mode 100644 EonaCatTools/Tools/ExceptionsLogger/ExceptionLogger.xib create mode 100644 EonaCatTools/Tools/Lockscreen/.DS_Store create mode 100644 EonaCatTools/Tools/Lockscreen/Dutch.lproj/LockController.strings create mode 100644 EonaCatTools/Tools/Lockscreen/English.lproj/LockController.strings create mode 100644 EonaCatTools/Tools/Lockscreen/LockController.h create mode 100644 EonaCatTools/Tools/Lockscreen/LockController.m create mode 100644 EonaCatTools/Tools/Popup/.DS_Store create mode 100644 EonaCatTools/Tools/Popup/Popup.h create mode 100644 EonaCatTools/Tools/Popup/Popup.m create mode 100644 EonaCatTools/Tools/Toast/Toast.h create mode 100644 EonaCatTools/Tools/Toast/Toast.m create mode 100644 EonaCatTools/Tools/Toast/toast.wav create mode 100644 EonaCatTools/Tools/uniqueIdentifier/DeviceIdentifier.h create mode 100644 EonaCatTools/Tools/uniqueIdentifier/DeviceIdentifier.m create mode 100644 EonaCatTools/Tools/uniqueIdentifier/SHA1.h create mode 100644 EonaCatTools/Tools/uniqueIdentifier/SHA1.m create mode 100644 EonaCatTools/ViewController.h create mode 100644 EonaCatTools/ViewController.m create mode 100644 EonaCatTools/en.lproj/InfoPlist.strings create mode 100644 EonaCatTools/main.m create mode 100644 EonaCatToolsTests/.DS_Store create mode 100644 EonaCatToolsTests/EonaCatToolsTests-Info.plist create mode 100644 EonaCatToolsTests/EonaCatToolsTests.m create mode 100644 EonaCatToolsTests/en.lproj/InfoPlist.strings diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..7de3dccb7ce61652181da76908d3139444ced035 GIT binary patch literal 6148 zcmeHKOG*Pl5PcN`M%-j0h^sk)kiEzd#uH2qpk^dNC+U!nx||z$GtcC!?jj^ai3Aam zDyV+lHC6q2J<~k}K>Dky2Xp~+sEVx<7N3YdSKX18S&oSk`v`bJi81al-0^n9Ut~b{ zu4{W%VRQeUFkm~N#-dsb>-!LDUBJaYXI$cy+aFNj0W-{5d#p#jau_DF$biV(q5Vuk zQBo6TLo*xp<_HsNRw+k${w?>C| zaR!_LXW%;w=ut!IoF??r8E^)ifi(kqK4etI+^|U)j}8_w1t7L*j>5X;5*m{k=7vo| zKA}hoC8kiZ6hl%t?V0)IhE2j04zc7zY-F(vMdIk}Ka1{=JfWA)fHSboz)@;;_5Q#4 zI{)7e@|H8;4E!qwq+OInpG&g4b!TyU*JjjPs*3tG3D+U4#H*OTdKI5jqtKpdg_s*Q S32CADk3gis3uoY08TbGL$Z6C7 literal 0 HcmV?d00001 diff --git a/EonaCatTools.xcodeproj/project.pbxproj b/EonaCatTools.xcodeproj/project.pbxproj new file mode 100644 index 0000000..50ff3b6 --- /dev/null +++ b/EonaCatTools.xcodeproj/project.pbxproj @@ -0,0 +1,636 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + EC760B97178E976E00095B31 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC760B96178E976E00095B31 /* Foundation.framework */; }; + EC760B99178E976E00095B31 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC760B98178E976E00095B31 /* CoreGraphics.framework */; }; + EC760B9B178E976E00095B31 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC760B9A178E976E00095B31 /* UIKit.framework */; }; + EC760BA1178E976E00095B31 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = EC760B9F178E976E00095B31 /* InfoPlist.strings */; }; + EC760BA3178E976E00095B31 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = EC760BA2178E976E00095B31 /* main.m */; }; + EC760BA7178E976E00095B31 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EC760BA6178E976E00095B31 /* AppDelegate.m */; }; + EC760BAA178E976E00095B31 /* Main_iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EC760BA8178E976E00095B31 /* Main_iPhone.storyboard */; }; + EC760BAD178E976E00095B31 /* Main_iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EC760BAB178E976E00095B31 /* Main_iPad.storyboard */; }; + EC760BB0178E976E00095B31 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EC760BAF178E976E00095B31 /* ViewController.m */; }; + EC760BB2178E976E00095B31 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EC760BB1178E976E00095B31 /* Images.xcassets */; }; + EC760BB9178E976E00095B31 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC760BB8178E976E00095B31 /* XCTest.framework */; }; + EC760BBA178E976E00095B31 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC760B96178E976E00095B31 /* Foundation.framework */; }; + EC760BBB178E976E00095B31 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC760B9A178E976E00095B31 /* UIKit.framework */; }; + EC760BC3178E976E00095B31 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = EC760BC1178E976E00095B31 /* InfoPlist.strings */; }; + EC760BC5178E976E00095B31 /* EonaCatToolsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EC760BC4178E976E00095B31 /* EonaCatToolsTests.m */; }; + EC760BEC178E97CB00095B31 /* ExceptionsLogger.strings in Resources */ = {isa = PBXBuildFile; fileRef = EC760BE2178E97CB00095B31 /* ExceptionsLogger.strings */; }; + EC760BED178E97CB00095B31 /* ExceptionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = EC760BE6178E97CB00095B31 /* ExceptionHandler.m */; }; + EC760BEE178E97CB00095B31 /* ExceptionLogger-iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = EC760BE7178E97CB00095B31 /* ExceptionLogger-iPad.xib */; }; + EC760BEF178E97CB00095B31 /* ExceptionLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = EC760BE9178E97CB00095B31 /* ExceptionLogger.m */; }; + EC760BF0178E97CB00095B31 /* ExceptionLogger.png in Resources */ = {isa = PBXBuildFile; fileRef = EC760BEA178E97CB00095B31 /* ExceptionLogger.png */; }; + EC760BF1178E97CB00095B31 /* ExceptionLogger.xib in Resources */ = {isa = PBXBuildFile; fileRef = EC760BEB178E97CB00095B31 /* ExceptionLogger.xib */; }; + EC760BF7178E989000095B31 /* DeviceIdentifier.m in Sources */ = {isa = PBXBuildFile; fileRef = EC760BF4178E989000095B31 /* DeviceIdentifier.m */; }; + EC760BF8178E989000095B31 /* SHA1.m in Sources */ = {isa = PBXBuildFile; fileRef = EC760BF6178E989000095B31 /* SHA1.m */; }; + EC760C05178EB5FB00095B31 /* LockController.strings in Resources */ = {isa = PBXBuildFile; fileRef = EC760BFA178EB5FB00095B31 /* LockController.strings */; }; + EC760C06178EB5FB00095B31 /* LockController.m in Sources */ = {isa = PBXBuildFile; fileRef = EC760BFE178EB5FB00095B31 /* LockController.m */; }; + EC760C07178EB5FB00095B31 /* Popup.m in Sources */ = {isa = PBXBuildFile; fileRef = EC760C01178EB5FB00095B31 /* Popup.m */; }; + EC760C08178EB5FB00095B31 /* Toast.m in Sources */ = {isa = PBXBuildFile; fileRef = EC760C04178EB5FB00095B31 /* Toast.m */; }; + EC760C0B178EB9C800095B31 /* toast.png in Resources */ = {isa = PBXBuildFile; fileRef = EC760C0A178EB9C800095B31 /* toast.png */; }; + EC760C0D178EBBE300095B31 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC760C0C178EBBE300095B31 /* AudioToolbox.framework */; }; + EC760C0F178EBCD200095B31 /* toast.wav in Resources */ = {isa = PBXBuildFile; fileRef = EC760C0E178EBCD200095B31 /* toast.wav */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + EC760BBC178E976E00095B31 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = EC760B8B178E976E00095B31 /* Project object */; + proxyType = 1; + remoteGlobalIDString = EC760B92178E976E00095B31; + remoteInfo = EonaCatTools; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + EC760B93178E976E00095B31 /* EonaCatTools.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EonaCatTools.app; sourceTree = BUILT_PRODUCTS_DIR; }; + EC760B96178E976E00095B31 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + EC760B98178E976E00095B31 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + EC760B9A178E976E00095B31 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + EC760B9E178E976E00095B31 /* EonaCatTools-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "EonaCatTools-Info.plist"; sourceTree = ""; }; + EC760BA0178E976E00095B31 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + EC760BA2178E976E00095B31 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + EC760BA4178E976E00095B31 /* EonaCatTools-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "EonaCatTools-Prefix.pch"; sourceTree = ""; }; + EC760BA5178E976E00095B31 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + EC760BA6178E976E00095B31 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + EC760BA9178E976E00095B31 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main_iPhone.storyboard; sourceTree = ""; }; + EC760BAC178E976E00095B31 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main_iPad.storyboard; sourceTree = ""; }; + EC760BAE178E976E00095B31 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + EC760BAF178E976E00095B31 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; + EC760BB1178E976E00095B31 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + EC760BB7178E976E00095B31 /* EonaCatToolsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = EonaCatToolsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + EC760BB8178E976E00095B31 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + EC760BC0178E976E00095B31 /* EonaCatToolsTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "EonaCatToolsTests-Info.plist"; sourceTree = ""; }; + EC760BC2178E976E00095B31 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + EC760BC4178E976E00095B31 /* EonaCatToolsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EonaCatToolsTests.m; sourceTree = ""; }; + EC760BE3178E97CB00095B31 /* Dutch */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Dutch; path = Dutch.lproj/ExceptionsLogger.strings; sourceTree = ""; }; + EC760BE4178E97CB00095B31 /* English */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/ExceptionsLogger.strings; sourceTree = ""; }; + EC760BE5178E97CB00095B31 /* ExceptionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExceptionHandler.h; sourceTree = ""; }; + EC760BE6178E97CB00095B31 /* ExceptionHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExceptionHandler.m; sourceTree = ""; }; + EC760BE7178E97CB00095B31 /* ExceptionLogger-iPad.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "ExceptionLogger-iPad.xib"; sourceTree = ""; }; + EC760BE8178E97CB00095B31 /* ExceptionLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExceptionLogger.h; sourceTree = ""; }; + EC760BE9178E97CB00095B31 /* ExceptionLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExceptionLogger.m; sourceTree = ""; }; + EC760BEA178E97CB00095B31 /* ExceptionLogger.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ExceptionLogger.png; sourceTree = ""; }; + EC760BEB178E97CB00095B31 /* ExceptionLogger.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ExceptionLogger.xib; sourceTree = ""; }; + EC760BF3178E989000095B31 /* DeviceIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeviceIdentifier.h; sourceTree = ""; }; + EC760BF4178E989000095B31 /* DeviceIdentifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DeviceIdentifier.m; sourceTree = ""; }; + EC760BF5178E989000095B31 /* SHA1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHA1.h; sourceTree = ""; }; + EC760BF6178E989000095B31 /* SHA1.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHA1.m; sourceTree = ""; }; + EC760BFB178EB5FB00095B31 /* Dutch */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Dutch; path = Dutch.lproj/LockController.strings; sourceTree = ""; }; + EC760BFC178EB5FB00095B31 /* English */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/LockController.strings; sourceTree = ""; }; + EC760BFD178EB5FB00095B31 /* LockController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LockController.h; sourceTree = ""; }; + EC760BFE178EB5FB00095B31 /* LockController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LockController.m; sourceTree = ""; }; + EC760C00178EB5FB00095B31 /* Popup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Popup.h; sourceTree = ""; }; + EC760C01178EB5FB00095B31 /* Popup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Popup.m; sourceTree = ""; }; + EC760C03178EB5FB00095B31 /* Toast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Toast.h; sourceTree = ""; }; + EC760C04178EB5FB00095B31 /* Toast.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Toast.m; sourceTree = ""; }; + EC760C0A178EB9C800095B31 /* toast.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = toast.png; sourceTree = ""; }; + EC760C0C178EBBE300095B31 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; + EC760C0E178EBCD200095B31 /* toast.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = toast.wav; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + EC760B90178E976E00095B31 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + EC760C0D178EBBE300095B31 /* AudioToolbox.framework in Frameworks */, + EC760B99178E976E00095B31 /* CoreGraphics.framework in Frameworks */, + EC760B9B178E976E00095B31 /* UIKit.framework in Frameworks */, + EC760B97178E976E00095B31 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EC760BB4178E976E00095B31 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + EC760BB9178E976E00095B31 /* XCTest.framework in Frameworks */, + EC760BBB178E976E00095B31 /* UIKit.framework in Frameworks */, + EC760BBA178E976E00095B31 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + EC760B8A178E976E00095B31 = { + isa = PBXGroup; + children = ( + EC760B9C178E976E00095B31 /* EonaCatTools */, + EC760BBE178E976E00095B31 /* EonaCatToolsTests */, + EC760B95178E976E00095B31 /* Frameworks */, + EC760B94178E976E00095B31 /* Products */, + ); + sourceTree = ""; + }; + EC760B94178E976E00095B31 /* Products */ = { + isa = PBXGroup; + children = ( + EC760B93178E976E00095B31 /* EonaCatTools.app */, + EC760BB7178E976E00095B31 /* EonaCatToolsTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + EC760B95178E976E00095B31 /* Frameworks */ = { + isa = PBXGroup; + children = ( + EC760C0C178EBBE300095B31 /* AudioToolbox.framework */, + EC760B96178E976E00095B31 /* Foundation.framework */, + EC760B98178E976E00095B31 /* CoreGraphics.framework */, + EC760B9A178E976E00095B31 /* UIKit.framework */, + EC760BB8178E976E00095B31 /* XCTest.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + EC760B9C178E976E00095B31 /* EonaCatTools */ = { + isa = PBXGroup; + children = ( + EC760C09178EB9C800095B31 /* Images */, + EC760BE0178E97CB00095B31 /* Tools */, + EC760BA5178E976E00095B31 /* AppDelegate.h */, + EC760BA6178E976E00095B31 /* AppDelegate.m */, + EC760BA8178E976E00095B31 /* Main_iPhone.storyboard */, + EC760BAB178E976E00095B31 /* Main_iPad.storyboard */, + EC760BAE178E976E00095B31 /* ViewController.h */, + EC760BAF178E976E00095B31 /* ViewController.m */, + EC760BB1178E976E00095B31 /* Images.xcassets */, + EC760B9D178E976E00095B31 /* Supporting Files */, + ); + path = EonaCatTools; + sourceTree = ""; + }; + EC760B9D178E976E00095B31 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + EC760B9E178E976E00095B31 /* EonaCatTools-Info.plist */, + EC760B9F178E976E00095B31 /* InfoPlist.strings */, + EC760BA2178E976E00095B31 /* main.m */, + EC760BA4178E976E00095B31 /* EonaCatTools-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + EC760BBE178E976E00095B31 /* EonaCatToolsTests */ = { + isa = PBXGroup; + children = ( + EC760BC4178E976E00095B31 /* EonaCatToolsTests.m */, + EC760BBF178E976E00095B31 /* Supporting Files */, + ); + path = EonaCatToolsTests; + sourceTree = ""; + }; + EC760BBF178E976E00095B31 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + EC760BC0178E976E00095B31 /* EonaCatToolsTests-Info.plist */, + EC760BC1178E976E00095B31 /* InfoPlist.strings */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + EC760BE0178E97CB00095B31 /* Tools */ = { + isa = PBXGroup; + children = ( + EC760BF9178EB5FB00095B31 /* Lockscreen */, + EC760BFF178EB5FB00095B31 /* Popup */, + EC760C02178EB5FB00095B31 /* Toast */, + EC760BF2178E989000095B31 /* uniqueIdentifier */, + EC760BE1178E97CB00095B31 /* ExceptionsLogger */, + ); + path = Tools; + sourceTree = ""; + }; + EC760BE1178E97CB00095B31 /* ExceptionsLogger */ = { + isa = PBXGroup; + children = ( + EC760BE2178E97CB00095B31 /* ExceptionsLogger.strings */, + EC760BE5178E97CB00095B31 /* ExceptionHandler.h */, + EC760BE6178E97CB00095B31 /* ExceptionHandler.m */, + EC760BE7178E97CB00095B31 /* ExceptionLogger-iPad.xib */, + EC760BE8178E97CB00095B31 /* ExceptionLogger.h */, + EC760BE9178E97CB00095B31 /* ExceptionLogger.m */, + EC760BEA178E97CB00095B31 /* ExceptionLogger.png */, + EC760BEB178E97CB00095B31 /* ExceptionLogger.xib */, + ); + path = ExceptionsLogger; + sourceTree = ""; + }; + EC760BF2178E989000095B31 /* uniqueIdentifier */ = { + isa = PBXGroup; + children = ( + EC760BF3178E989000095B31 /* DeviceIdentifier.h */, + EC760BF4178E989000095B31 /* DeviceIdentifier.m */, + EC760BF5178E989000095B31 /* SHA1.h */, + EC760BF6178E989000095B31 /* SHA1.m */, + ); + path = uniqueIdentifier; + sourceTree = ""; + }; + EC760BF9178EB5FB00095B31 /* Lockscreen */ = { + isa = PBXGroup; + children = ( + EC760BFA178EB5FB00095B31 /* LockController.strings */, + EC760BFD178EB5FB00095B31 /* LockController.h */, + EC760BFE178EB5FB00095B31 /* LockController.m */, + ); + path = Lockscreen; + sourceTree = ""; + }; + EC760BFF178EB5FB00095B31 /* Popup */ = { + isa = PBXGroup; + children = ( + EC760C00178EB5FB00095B31 /* Popup.h */, + EC760C01178EB5FB00095B31 /* Popup.m */, + ); + path = Popup; + sourceTree = ""; + }; + EC760C02178EB5FB00095B31 /* Toast */ = { + isa = PBXGroup; + children = ( + EC760C03178EB5FB00095B31 /* Toast.h */, + EC760C0E178EBCD200095B31 /* toast.wav */, + EC760C04178EB5FB00095B31 /* Toast.m */, + ); + path = Toast; + sourceTree = ""; + }; + EC760C09178EB9C800095B31 /* Images */ = { + isa = PBXGroup; + children = ( + EC760C0A178EB9C800095B31 /* toast.png */, + ); + name = Images; + path = EonaCatTools/Images; + sourceTree = SOURCE_ROOT; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + EC760B92178E976E00095B31 /* EonaCatTools */ = { + isa = PBXNativeTarget; + buildConfigurationList = EC760BC8178E976E00095B31 /* Build configuration list for PBXNativeTarget "EonaCatTools" */; + buildPhases = ( + EC760B8F178E976E00095B31 /* Sources */, + EC760B90178E976E00095B31 /* Frameworks */, + EC760B91178E976E00095B31 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = EonaCatTools; + productName = EonaCatTools; + productReference = EC760B93178E976E00095B31 /* EonaCatTools.app */; + productType = "com.apple.product-type.application"; + }; + EC760BB6178E976E00095B31 /* EonaCatToolsTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = EC760BCB178E976E00095B31 /* Build configuration list for PBXNativeTarget "EonaCatToolsTests" */; + buildPhases = ( + EC760BB3178E976E00095B31 /* Sources */, + EC760BB4178E976E00095B31 /* Frameworks */, + EC760BB5178E976E00095B31 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + EC760BBD178E976E00095B31 /* PBXTargetDependency */, + ); + name = EonaCatToolsTests; + productName = EonaCatToolsTests; + productReference = EC760BB7178E976E00095B31 /* EonaCatToolsTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + EC760B8B178E976E00095B31 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + ORGANIZATIONNAME = EonaCat; + TargetAttributes = { + EC760BB6178E976E00095B31 = { + TestTargetID = EC760B92178E976E00095B31; + }; + }; + }; + buildConfigurationList = EC760B8E178E976E00095B31 /* Build configuration list for PBXProject "EonaCatTools" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + Dutch, + English, + ); + mainGroup = EC760B8A178E976E00095B31; + productRefGroup = EC760B94178E976E00095B31 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + EC760B92178E976E00095B31 /* EonaCatTools */, + EC760BB6178E976E00095B31 /* EonaCatToolsTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + EC760B91178E976E00095B31 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EC760BAD178E976E00095B31 /* Main_iPad.storyboard in Resources */, + EC760C05178EB5FB00095B31 /* LockController.strings in Resources */, + EC760BB2178E976E00095B31 /* Images.xcassets in Resources */, + EC760BEC178E97CB00095B31 /* ExceptionsLogger.strings in Resources */, + EC760BF1178E97CB00095B31 /* ExceptionLogger.xib in Resources */, + EC760BF0178E97CB00095B31 /* ExceptionLogger.png in Resources */, + EC760C0F178EBCD200095B31 /* toast.wav in Resources */, + EC760BEE178E97CB00095B31 /* ExceptionLogger-iPad.xib in Resources */, + EC760BAA178E976E00095B31 /* Main_iPhone.storyboard in Resources */, + EC760BA1178E976E00095B31 /* InfoPlist.strings in Resources */, + EC760C0B178EB9C800095B31 /* toast.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EC760BB5178E976E00095B31 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EC760BC3178E976E00095B31 /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + EC760B8F178E976E00095B31 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EC760C06178EB5FB00095B31 /* LockController.m in Sources */, + EC760BB0178E976E00095B31 /* ViewController.m in Sources */, + EC760BA7178E976E00095B31 /* AppDelegate.m in Sources */, + EC760C07178EB5FB00095B31 /* Popup.m in Sources */, + EC760BF7178E989000095B31 /* DeviceIdentifier.m in Sources */, + EC760C08178EB5FB00095B31 /* Toast.m in Sources */, + EC760BED178E97CB00095B31 /* ExceptionHandler.m in Sources */, + EC760BEF178E97CB00095B31 /* ExceptionLogger.m in Sources */, + EC760BA3178E976E00095B31 /* main.m in Sources */, + EC760BF8178E989000095B31 /* SHA1.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EC760BB3178E976E00095B31 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EC760BC5178E976E00095B31 /* EonaCatToolsTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + EC760BBD178E976E00095B31 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = EC760B92178E976E00095B31 /* EonaCatTools */; + targetProxy = EC760BBC178E976E00095B31 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + EC760B9F178E976E00095B31 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + EC760BA0178E976E00095B31 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + EC760BA8178E976E00095B31 /* Main_iPhone.storyboard */ = { + isa = PBXVariantGroup; + children = ( + EC760BA9178E976E00095B31 /* Base */, + ); + name = Main_iPhone.storyboard; + sourceTree = ""; + }; + EC760BAB178E976E00095B31 /* Main_iPad.storyboard */ = { + isa = PBXVariantGroup; + children = ( + EC760BAC178E976E00095B31 /* Base */, + ); + name = Main_iPad.storyboard; + sourceTree = ""; + }; + EC760BC1178E976E00095B31 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + EC760BC2178E976E00095B31 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + EC760BE2178E97CB00095B31 /* ExceptionsLogger.strings */ = { + isa = PBXVariantGroup; + children = ( + EC760BE3178E97CB00095B31 /* Dutch */, + EC760BE4178E97CB00095B31 /* English */, + ); + name = ExceptionsLogger.strings; + sourceTree = ""; + }; + EC760BFA178EB5FB00095B31 /* LockController.strings */ = { + isa = PBXVariantGroup; + children = ( + EC760BFB178EB5FB00095B31 /* Dutch */, + EC760BFC178EB5FB00095B31 /* English */, + ); + name = LockController.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + EC760BC6178E976E00095B31 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + EC760BC7178E976E00095B31 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + EC760BC9178E976E00095B31 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "EonaCatTools/EonaCatTools-Prefix.pch"; + INFOPLIST_FILE = "EonaCatTools/EonaCatTools-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + EC760BCA178E976E00095B31 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "EonaCatTools/EonaCatTools-Prefix.pch"; + INFOPLIST_FILE = "EonaCatTools/EonaCatTools-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; + EC760BCC178E976E00095B31 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/EonaCatTools.app/EonaCatTools"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + "$(SYSTEM_APPS_DIR)/Xcode5-DP3.app/Contents/Developer/Library/Frameworks", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "EonaCatTools/EonaCatTools-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "EonaCatToolsTests/EonaCatToolsTests-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUNDLE_LOADER)"; + WRAPPER_EXTENSION = xctest; + }; + name = Debug; + }; + EC760BCD178E976E00095B31 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/EonaCatTools.app/EonaCatTools"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + "$(SYSTEM_APPS_DIR)/Xcode5-DP3.app/Contents/Developer/Library/Frameworks", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "EonaCatTools/EonaCatTools-Prefix.pch"; + INFOPLIST_FILE = "EonaCatToolsTests/EonaCatToolsTests-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUNDLE_LOADER)"; + WRAPPER_EXTENSION = xctest; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + EC760B8E178E976E00095B31 /* Build configuration list for PBXProject "EonaCatTools" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EC760BC6178E976E00095B31 /* Debug */, + EC760BC7178E976E00095B31 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + EC760BC8178E976E00095B31 /* Build configuration list for PBXNativeTarget "EonaCatTools" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EC760BC9178E976E00095B31 /* Debug */, + EC760BCA178E976E00095B31 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; + EC760BCB178E976E00095B31 /* Build configuration list for PBXNativeTarget "EonaCatToolsTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EC760BCC178E976E00095B31 /* Debug */, + EC760BCD178E976E00095B31 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = EC760B8B178E976E00095B31 /* Project object */; +} diff --git a/EonaCatTools.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/EonaCatTools.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..651a506 --- /dev/null +++ b/EonaCatTools.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/EonaCatTools/.DS_Store b/EonaCatTools/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 + +@interface AppDelegate : UIResponder + +#define Delegate ((AppDelegate *)[[UIApplication sharedApplication] delegate]) + +@property (strong, nonatomic) UIWindow *window; +@property (nonatomic, assign) BOOL iPad; + +@end diff --git a/EonaCatTools/AppDelegate.m b/EonaCatTools/AppDelegate.m new file mode 100644 index 0000000..eb36295 --- /dev/null +++ b/EonaCatTools/AppDelegate.m @@ -0,0 +1,55 @@ +// +// AppDelegate.m +// Created by EonaCat +// Copyright 2013 EonaCat. All rights reserved. +// + +#import "AppDelegate.h" +#import "ExceptionHandler.h" + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + + self.iPad = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad); + + // Create the exceptionHandler + [self performSelector:@selector(setExceptionHandler) withObject:nil afterDelay:0]; + + return YES; +} + +- (void)setExceptionHandler +{ + createExceptionHandler(@"YOUREMAILADDRESS", @""); +} + +- (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. +} + +- (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, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (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. +} + +- (void)applicationWillTerminate:(UIApplication *)application +{ + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/EonaCatTools/Base.lproj/Main_iPad.storyboard b/EonaCatTools/Base.lproj/Main_iPad.storyboard new file mode 100644 index 0000000..d185ea0 --- /dev/null +++ b/EonaCatTools/Base.lproj/Main_iPad.storyboard @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EonaCatTools/Base.lproj/Main_iPhone.storyboard b/EonaCatTools/Base.lproj/Main_iPhone.storyboard new file mode 100644 index 0000000..9e8307e --- /dev/null +++ b/EonaCatTools/Base.lproj/Main_iPhone.storyboard @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EonaCatTools/EonaCatTools-Info.plist b/EonaCatTools/EonaCatTools-Info.plist new file mode 100644 index 0000000..ede82dd --- /dev/null +++ b/EonaCatTools/EonaCatTools-Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + nl.EonaCat.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + UIMainStoryboardFile + Main_iPhone + UIMainStoryboardFile~ipad + Main_iPad + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/EonaCatTools/EonaCatTools-Prefix.pch b/EonaCatTools/EonaCatTools-Prefix.pch new file mode 100644 index 0000000..82a2bb4 --- /dev/null +++ b/EonaCatTools/EonaCatTools-Prefix.pch @@ -0,0 +1,16 @@ +// +// Prefix header +// +// The contents of this file are implicitly included at the beginning of every source file. +// + +#import + +#ifndef __IPHONE_5_0 +#warning "This project uses features only available in iOS SDK 5.0 and later." +#endif + +#ifdef __OBJC__ + #import + #import +#endif diff --git a/EonaCatTools/Images.xcassets/AppIcon.appiconset/Contents.json b/EonaCatTools/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..1189d95 --- /dev/null +++ b/EonaCatTools/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,48 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "50x50", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "50x50", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "72x72", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "72x72", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/EonaCatTools/Images.xcassets/LaunchImage.launchimage/Contents.json b/EonaCatTools/Images.xcassets/LaunchImage.launchimage/Contents.json new file mode 100644 index 0000000..6f870a4 --- /dev/null +++ b/EonaCatTools/Images.xcassets/LaunchImage.launchimage/Contents.json @@ -0,0 +1,51 @@ +{ + "images" : [ + { + "orientation" : "portrait", + "idiom" : "iphone", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "subtype" : "retina4", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/EonaCatTools/Images/toast.png b/EonaCatTools/Images/toast.png new file mode 100644 index 0000000000000000000000000000000000000000..a8c4593b47c35e79b49970795b643240837d21c5 GIT binary patch literal 17067 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 CH$5u= literal 0 HcmV?d00001 diff --git a/EonaCatTools/Tools/.DS_Store b/EonaCatTools/Tools/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..e6cc851acbd8d4f957c84a5af64c6714a9d9c675 GIT binary patch literal 6148 zcmeHK%}T>S5T3PF6I94W=yCB}q}pN?JcLj|Z$b+_SkZ)38YoF^QhKP-;4}ChzKzf0 z%iKgOx%RUOMwC5Bk}29FlRb>WY;xx`R;zaBtSOH> zCwWt@y4_Y&cG{N0El&TD?yvy5>z7%x&{l47(o%b6j7H7 z^TZIk9R1Sdxdsc3x*UX>8OJd*e?4A=njQU8rGs!aa?1=b17!wky6e#We}SJ&Y4xJ+n71VJ_Hs-ko3ym}i S`Bgb0{|G2TxM2oH1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 +#import +#import + +#define exceptionDelegate [[UIApplication sharedApplication] delegate] + +@interface ExceptionHandler : UIViewController +{ + BOOL dismissed; +} + +@end + +void createExceptionHandler(NSString *emailAddress,NSString *BCCemailAddress); \ No newline at end of file diff --git a/EonaCatTools/Tools/ExceptionsLogger/ExceptionHandler.m b/EonaCatTools/Tools/ExceptionsLogger/ExceptionHandler.m new file mode 100644 index 0000000..fee0e16 --- /dev/null +++ b/EonaCatTools/Tools/ExceptionsLogger/ExceptionHandler.m @@ -0,0 +1,359 @@ +// +// ExceptionHandler.m +// Created by EonaCat +// Copyright 2013 EonaCat. All rights reserved. +// + +// The ExceptionHandler needs to be imported in the ApplicationDelegate by using the #import "ExceptionHandler.h"; statement in de .m file +// The following functions need to be created in the ApplicationDelegate.m file + +// - (void)setExceptionHandler +// { +// createExceptionHandler(@"YOUREMAILADDRESS", @""); +// } + +// In the ApplicationDelegate file the method +// - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { +// need to be created inside this method you will need to implement the following code: +// + +// //Create the exceptionHandler +// [self performSelector:@selector(setExceptionHandler) withObject:nil afterDelay:0]; +// +// +// You will need to implement the application delegate of the application before you can use the Email function. +// So be sure to import the applications's delegate headerfile and change the following line: +// (Located in the - (void) displayComposerSheet:(NSString *)body method) +// +// [self presentViewController: tempMailCompose animated:YES completion:nil]; +// +// into +// +// [root.navigationController presentViewController: tempMailCompose animated:YES completion:nil]; +// +// Be sure that the following line is present in your core or appdelegate file +// #define Delegate ((yourAppDelegateFileName*)[UIApplication sharedApplication].delegate) + + + +#import "ExceptionHandler.h" +#import "DeviceIdentifier.h" +#include +#include +#import "ExceptionLogger.h" + +const NSString *ExceptionName = @"ExceptionName"; +const NSString *ExceptionKey = @"ExceptionKey"; +const NSString *ExceptionAddresses = @"ExceptionAddresses"; + +NSString *ExceptionTitle = @"iPhone Exception"; +NSString *ExceptionEmail = @""; +NSString *ExceptionBCCEmail = @""; +NSString *ExceptionMessage = @""; +NSInteger ExceptionShown = 0; +BOOL ExceptionAlert = true; + +volatile int32_t ExceptionCount = 0; +const int32_t ExceptionMaximum = 5; + +const NSInteger ExceptionHandlerSkipAddressCount = 4; +const NSInteger ExceptionHandlerReportAddressCount = 5; + +@implementation ExceptionHandler + ++ (NSArray *)backtrace +{ + void *callstack[128]; + int frames = backtrace(callstack, 128); + char **stringSymbols = backtrace_symbols(callstack, frames); + + int i; + NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames]; + + for (i = ExceptionHandlerSkipAddressCount; i < ExceptionHandlerSkipAddressCount + ExceptionHandlerReportAddressCount; i++) + { + [backtrace addObject:[NSString stringWithUTF8String:stringSymbols[i]]]; + } + free(stringSymbols); + + return backtrace; +} + +- (void)alertView:(UIAlertView *)anAlertView clickedButtonAtIndex:(NSInteger)Index +{ + if (Index == 0) // Quit button clicked + { + ExceptionShown = 0; + dismissed = YES; + } + else if (Index == 1) // Continue button clicked + { + ExceptionShown = 0; + } + else if (Index == 2) // Email button clicked + { + // Create the email that needs to be send + [self performSelector:@selector(showComposer:) withObject:ExceptionMessage afterDelay:0.1]; + } +} + + +// Displays an email composition interface inside the application. Populates all the Mail fields. +- (void) displayComposerSheet:(NSString *)body +{ + MFMailComposeViewController *mailController = [[MFMailComposeViewController alloc] init]; + mailController.mailComposeDelegate = self; + + NSArray *toRecipient = [[NSArray alloc] initWithObjects:ExceptionEmail,nil]; + [mailController setToRecipients:toRecipient]; + + if (ExceptionBCCEmail.length > 0) + { + NSArray *bccRecipient = [[NSArray alloc] initWithObjects:ExceptionBCCEmail,nil]; + [mailController setBccRecipients:bccRecipient]; + } + [mailController setSubject:ExceptionTitle]; + [mailController setMessageBody:body isHTML:NO]; + + UIWindow* window = [[UIApplication sharedApplication] keyWindow]; + [window addSubview:mailController.view]; +} + +// Dismisses the email composition interface when users tap Cancel or Send. Proceeds to update the message field with the result of the operation. +- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error +{ + // Notifies users about errors associated with the interface + switch (result) + { + case MFMailComposeResultCancelled: + NSLog(@"Result: canceled"); + break; + case MFMailComposeResultSaved: + NSLog(@"Result: saved"); + break; + case MFMailComposeResultSent: + NSLog(@"Result: sent"); + break; + case MFMailComposeResultFailed: + NSLog(@"Result: failed"); + break; + default: + NSLog(@"Result: not sent"); + break; + } + [self dismissViewControllerAnimated:YES completion:nil]; +} + +// Launches the Mail application on the device. Workaround +-(void)launchMailAppOnDevice:(NSString *)body +{ + NSString *recipients; + + if ([ExceptionEmail isEqualToString:@"YOUREMAILADDRESS"]) + { + NSLog(@"Could not send email (default values where detected!)"); + return; + } + + if (ExceptionBCCEmail.length > 0) + { + recipients = [NSString stringWithFormat:@"mailto:%@?bcc=%@?subject=%@", ExceptionEmail, ExceptionBCCEmail, ExceptionTitle]; + } + else + { + recipients = [NSString stringWithFormat:@"mailto:%@?subject=%@", ExceptionEmail, ExceptionTitle]; + } + + NSString *mailBody = [NSString stringWithFormat:@"&body=%@", body]; + + NSString *email = [NSString stringWithFormat:@"%@%@", recipients, mailBody]; + email = [email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:email]]; +} + +// Call this method and pass parameters +-(void) showComposer:(id)sender +{ + Class mailClass = (NSClassFromString(@"MFMailComposeViewController")); + + if (mailClass != nil) + { + // We must always check whether the current device is configured for sending emails + if ([mailClass canSendMail]) + { + [self displayComposerSheet:sender]; + } + else + { + [self launchMailAppOnDevice:sender]; + } + } + else + { + [self launchMailAppOnDevice:sender]; + } +} + + +- (void)saveAndQuit +{ + +} + +- (void)checkForExceptions:(NSException *)exception +{ + if (ExceptionShown == 0) + { + ExceptionShown = 1; + [self saveAndQuit]; + + /* + // Set the IMEI Number + // Check if you got iOS5 + NSString *IMEI; + float version = [[[UIDevice currentDevice] systemVersion] floatValue]; + if (version >= 5.0) + { + IMEI = [[NSString alloc] initWithString:[[UIDevice currentDevice] deviceIdentifier]]; + } + else + { + IMEI = [[NSString alloc] initWithString:[[UIDevice currentDevice] uniqueIdentifier]]; + } + */ + + NSDate *currentTime = [NSDate date]; + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setDateFormat:@"YYYY-MM-dd hh-mm"]; + NSString *resultString = [dateFormatter stringFromDate: currentTime]; + + ExceptionMessage = [NSString stringWithFormat: + @"iPhone exception information:\n\n" + @"Date: %@\n" + @"Application Name: %@\n" + @"Localized Application Name: %@\n" + @"Devicetype: %@\n" + @"============================= \n" + @"Reason: %@\n" + @"============================= \n\n" + @"***************************** \n\n" + @"Exception: %@\n\n" + @"***************************** \n", + resultString, [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"], + [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"], [UIDevice currentDevice].model, + [exception reason],[[exception userInfo] objectForKey:ExceptionAddresses]]; + + if (ExceptionAlert) + { + UIAlertView *alert = + [[UIAlertView alloc] + initWithTitle:@"You have found an error" + message:[NSString stringWithFormat: @"You can try continuing using the application " + @"but it may become unstable after a while.\n" + @"Please send us an email with the error report " + @"by clicking on the send report button."] + delegate:self + cancelButtonTitle:@"Quit" + otherButtonTitles:@"Continue", @"Send report",nil]; + [alert show]; + } + else + { + [[ExceptionLogger instance] log:ExceptionMessage]; + } + + CFRunLoopRef runLoop = CFRunLoopGetCurrent(); + CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop); + + while (!dismissed) + { + for (NSString *mode in (__bridge NSArray *)allModes) + { + CFRunLoopRunInMode((__bridge CFStringRef)mode, 0.001, false); + } + } + + CFRelease(allModes); + + NSSetUncaughtExceptionHandler(NULL); + signal(SIGABRT, SIG_DFL); + signal(SIGILL, SIG_DFL); + signal(SIGSEGV, SIG_DFL); + signal(SIGFPE, SIG_DFL); + signal(SIGBUS, SIG_DFL); + signal(SIGPIPE, SIG_DFL); + + if ([[exception name] isEqual:ExceptionName]) + { + kill(getpid(), [[[exception userInfo] objectForKey:ExceptionKey] intValue]); + } + else + { + [exception raise]; + } + } +} + +@end + +void checkForExceptions(NSException *exception) +{ + int32_t exceptionCount = OSAtomicIncrement32(&ExceptionCount); + if (exceptionCount > ExceptionMaximum) + { + NSLog(@"Maximum amount of exceptions where raised !"); + return; + } + + NSArray *callStack = [ExceptionHandler backtrace]; + NSMutableDictionary *userInfo = + [NSMutableDictionary dictionaryWithDictionary:[exception userInfo]]; + [userInfo + setObject:callStack + forKey:ExceptionAddresses]; + + [[[ExceptionHandler alloc] init] + performSelectorOnMainThread:@selector(checkForExceptions:) + withObject: + [NSException + exceptionWithName:[exception name] + reason:[exception reason] + userInfo:userInfo] + waitUntilDone:YES]; +} + +void ExceptionCounter(int exception) +{ + int32_t exceptionCount = OSAtomicIncrement32(&ExceptionCount); + + if (exceptionCount > ExceptionMaximum) + { + return; + } + + NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:exception] forKey:ExceptionKey]; + + NSArray *callStack = [ExceptionHandler backtrace]; + [userInfo setObject:callStack forKey:ExceptionAddresses]; + + [[[ExceptionHandler alloc] init] performSelectorOnMainThread:@selector(checkForExceptions:) + withObject: [NSException exceptionWithName:[NSString stringWithFormat:@"%@",ExceptionTitle] + reason: [NSString stringWithFormat: NSLocalizedString(@"Signal %d was raised.", nil), signal] + userInfo: [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:exception] forKey:ExceptionKey]] + waitUntilDone:YES]; +} + +void createExceptionHandler(NSString *emailAddress,NSString *BCCemailAddress) +{ + NSSetUncaughtExceptionHandler(&checkForExceptions); + signal(SIGABRT, ExceptionCounter); + signal(SIGILL, ExceptionCounter); + signal(SIGSEGV, ExceptionCounter); + signal(SIGFPE, ExceptionCounter); + signal(SIGBUS, ExceptionCounter); + signal(SIGPIPE, ExceptionCounter); + + ExceptionEmail = emailAddress; + ExceptionBCCEmail = BCCemailAddress; +} \ No newline at end of file diff --git a/EonaCatTools/Tools/ExceptionsLogger/ExceptionLogger-iPad.xib b/EonaCatTools/Tools/ExceptionsLogger/ExceptionLogger-iPad.xib new file mode 100644 index 0000000..6ba67e2 --- /dev/null +++ b/EonaCatTools/Tools/ExceptionsLogger/ExceptionLogger-iPad.xib @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EonaCatTools/Tools/ExceptionsLogger/ExceptionLogger.h b/EonaCatTools/Tools/ExceptionsLogger/ExceptionLogger.h new file mode 100644 index 0000000..bc19908 --- /dev/null +++ b/EonaCatTools/Tools/ExceptionsLogger/ExceptionLogger.h @@ -0,0 +1,24 @@ +// +// ExceptionLogger.h +// Created by EonaCat +// Copyright 2013 EonaCat. All rights reserved. +// + +#import + +@interface ExceptionLogger : UIViewController +{ + IBOutlet UINavigationItem *navigationBar; + NSString *path; + IBOutlet UITextView *textView; +} + +@property (nonatomic, strong) IBOutlet UINavigationItem *navigationBar; +@property (nonatomic, strong) IBOutlet UITextView *textView; + ++(ExceptionLogger*)instance; +-(IBAction)updateLog:(id)sender; +-(IBAction)Clear:(id)sender; +-(void)log:(NSString*)exception; + +@end diff --git a/EonaCatTools/Tools/ExceptionsLogger/ExceptionLogger.m b/EonaCatTools/Tools/ExceptionsLogger/ExceptionLogger.m new file mode 100644 index 0000000..baa5bbe --- /dev/null +++ b/EonaCatTools/Tools/ExceptionsLogger/ExceptionLogger.m @@ -0,0 +1,226 @@ +// +// ExceptionLogger.m +// Created by EonaCat +// Copyright 2013 EonaCat. All rights reserved. +// + +// The ExceptionLogger needs to be imported in a view by using the #import "ExceptionLogger.h"; statement in de .m file +// The following functions need to be created in the view.m file + +// - (void)swipedScreen:(UISwipeGestureRecognizer*)swipeGesture +// { +// // Show ExceptionLogger (Check for iPhone or iPad) +// ExceptionLogger* exceptionLogger = nil; +// if (iPad) +// { +// exceptionLogger = [[ExceptionLogger alloc] initWithNibName:@"ExceptionLogger-iPad" bundle:nil]; +// } +// else +// { +// exceptionLogger = [[ExceptionLogger alloc] initWithNibName:@"ExceptionLogger" bundle:nil]; +// } +// [self.navigationController pushViewController:exceptionLogger animated:YES completion:nil]; +// [exceptionLogger release]; +// } + +// Add these line to your ViewDidLoad method: +// +// // Add the ExceptionLogger Swipe Gesture +// UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipedScreen:)]; +// swipeRight.direction = UISwipeGestureRecognizerDirectionRight; +// [self.view addGestureRecognizer:swipeRight]; + +// In your delegate file you need to write the following lines: +// +// +// + +// Be sure that the following line is present in your core or delegate file +// #define Delegate ((yourAppDelegateFileName*)[UIApplication sharedApplication].delegate) + +#import "ExceptionLogger.h" + +@implementation ExceptionLogger +static ExceptionLogger* _instance = nil; + +@synthesize textView; +@synthesize navigationBar; + ++(ExceptionLogger*)instance +{ + @synchronized([ExceptionLogger class]) + { + if (!_instance) + { + [self alloc]; + } + return _instance; + } + return nil; +} + ++(id)alloc +{ + @synchronized([ExceptionLogger class]) + { + _instance = [super alloc]; + return _instance; + } + return nil; +} + +- (void)viewDidLoad +{ + @try + { + [super viewDidLoad]; + self.navigationBar.title = NSLocalizedStringFromTable(@"Exceptions", @"ExceptionsLogger", @"Exceptions"); + navigationBar.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle: NSLocalizedStringFromTable(@"Back", @"ExceptionsLogger", @"Back") + style: UIBarButtonItemStyleBordered + target: self + action: @selector(Back:)]; + + navigationBar.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle: NSLocalizedStringFromTable(@"Clear", @"ExceptionsLogger", @"Clear") +style: UIBarButtonItemStyleBordered + target: self + action: @selector(Clear:)]; + textView.editable = false; + textView.text = @""; + [self updateLog:self]; + textView.hidden = false; + + [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(updateLog:) userInfo:nil repeats:YES]; + } + @catch(NSException* exception) + { + NSLog(@"Exception: ExceptionLogger > viewDidLoad\n%@",exception); + } +} + +- (IBAction)Back:(id)sender +{ + [self dismissViewControllerAnimated:YES completion:nil]; +} + +-(void)log:(NSString*)exception +{ + @try + { + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setDateFormat:@"dd-MM-YYYY HH:mm:ss"]; + NSString *stringFromDate = [dateFormatter stringFromDate:[NSDate date]]; + NSString* stringData = [[NSString alloc] initWithFormat:@"\n%@\n\n %@", stringFromDate, exception]; + NSData *dataToWrite = [stringData dataUsingEncoding:NSUTF8StringEncoding]; + + NSString *docsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; + path = [docsDirectory stringByAppendingPathComponent:@"Exceptions.log"]; + + NSFileManager *fileManager = [NSFileManager defaultManager]; + + if (![fileManager fileExistsAtPath:path]) + { + [fileManager createFileAtPath:path contents:nil attributes:nil]; + } + + NSDictionary* attributes = [fileManager attributesOfItemAtPath:path error:nil]; + NSNumber* fileSize = [attributes objectForKey:NSFileSize]; + // Check if the logfile exceeds 10 MB + + if ([fileSize intValue] > 10 * 1024) + { + [fileManager removeItemAtPath:path error:nil]; + [fileManager createFileAtPath:path contents:nil attributes:nil]; + } + + NSMutableData *concatenatedData = [[NSMutableData alloc] init]; + [concatenatedData appendData: dataToWrite]; + NSData *fileData = [[NSData alloc] initWithContentsOfFile:(NSString *)path]; + [concatenatedData appendData: fileData]; + NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:path]; + [fileHandle seekToFileOffset:0]; + [fileHandle writeData:concatenatedData]; + } + @catch(NSException* exception) + { + NSLog(@"Exception: ExceptionLogger > log\n%@",exception); + } +} + +- (BOOL)canBecomeFirstResponder +{ + return NO; +} + +-(IBAction)updateLog:(id)sender +{ + @try + { + NSString *docsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; + path = [docsDirectory stringByAppendingPathComponent:@"Exceptions.log"]; + + NSFileManager *fileManager = [NSFileManager defaultManager]; + if ([fileManager fileExistsAtPath:path]) + { + textView.text = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];[NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; + } + } + @catch(NSException* exception) + { + NSLog(@"Exception: ExceptionLogger > updateLog\n%@",exception); + } +} + +-(IBAction)Clear:(id)sender +{ + @try + { + NSString *docsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; + + path = [docsDirectory stringByAppendingPathComponent:@"Exceptions.log"]; + + NSFileManager *fileManager = [NSFileManager defaultManager]; + if ([fileManager fileExistsAtPath:path]) + { + [fileManager removeItemAtPath:path error:nil]; + [fileManager createFileAtPath:path contents:nil attributes:nil ]; + } + + [self updateLog:self]; + } + @catch(NSException* exception) + { + NSLog(@"Exception: ExceptionLogger > Clear\n%@",exception); + } +} + +- (void)viewWillAppear:(BOOL)animated +{ + @try + { + [super viewWillAppear:animated]; + } + @catch(NSException* exception) + { + NSLog(@"Exception: ExceptionLogger > viewWillAppear\n%@",exception); + } +} + + +- (void)viewDidAppear:(BOOL)animated +{ + [super viewDidAppear:animated]; +} + +// Rotate application view +-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + return YES; +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; +} + + +@end \ No newline at end of file diff --git a/EonaCatTools/Tools/ExceptionsLogger/ExceptionLogger.png b/EonaCatTools/Tools/ExceptionsLogger/ExceptionLogger.png new file mode 100644 index 0000000000000000000000000000000000000000..213252727473480e0e4af504df1db32bfc0f7894 GIT binary patch literal 15163 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 O08(P|qP4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EonaCatTools/Tools/Lockscreen/.DS_Store b/EonaCatTools/Tools/Lockscreen/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 + +// +// LockController.h +// Created by EonaCat +// Copyright 2013 EonaCat. All rights reserved. +// + +typedef enum +{ + AUTHENTICATE, + SET +} STYLE; + +@protocol LockControllerDelegate + +@required +//- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +- (void)lockControllerDidFinish:(NSString*)passcode tag:(NSInteger)tag; +- (void)lockControllerIncorrectPassword:(NSString*)incorrectPassword tag:(NSInteger)tag; +- (void)lockControllerDidCancel:(NSInteger)tag; + +@end + + +@interface LockController : UIViewController +{ + //Public + STYLE style; + NSString *passcode; + NSString *givenPasscode; + NSString *title; + UILabel *promptLabel; + UILabel *subPromptLabel; + UILabel *hintLabel; + UIAlertView *alert; + int _deviceWidth; + + id __weak delegate; + BOOL hideCode; + + //Private + BOOL _iPad; + BOOL retry; + NSMutableString *tempString; + + UITextField *hiddenField; + UINavigationItem *navigationItem; + NSMutableArray *textFieldArray; +} + +@property (nonatomic, weak) id delegate; +@property (nonatomic, copy) NSString *title; +@property (nonatomic) STYLE style; +@property (nonatomic, strong) UIColor *color; +@property (nonatomic, strong) UIColor *color2; +@property (nonatomic, strong) NSString *passcode; +@property (nonatomic, strong) NSString *prompt; +@property (nonatomic, strong) NSString *subPrompt; +@property (nonatomic, strong) NSString *hint; +@property (nonatomic, strong) NSString *correct; +@property (nonatomic) NSInteger tag; +@property (nonatomic) BOOL cancel; +@property (nonatomic) NSInteger fieldsAmount; +@property (nonatomic) BOOL hideCode; +@property (nonatomic) BOOL waitingAlert; + +- (id)initWithTitle:(NSString*)newTitle prompt:(NSString*)newPrompt errorMessage:(NSString*)newSubPrompt correctMessage:(NSString*)newCorrectMessage passCode:(NSString*)newPasscode hint:(NSString*)newHint color:(UIColor*)newColor color2:(UIColor*)newColor2 fieldAmount:(NSInteger)newFieldAmount style:(STYLE)newStyle delegate:(id)newDelegate tag:(NSInteger)newTag cancelButton:(BOOL)cancelButton; + +- (void)incorrect; +- (void)finished; + +@end diff --git a/EonaCatTools/Tools/Lockscreen/LockController.m b/EonaCatTools/Tools/Lockscreen/LockController.m new file mode 100644 index 0000000..b66f7cb --- /dev/null +++ b/EonaCatTools/Tools/Lockscreen/LockController.m @@ -0,0 +1,444 @@ +#import "LockController.h" +#import + +// +// LockController.m +// Created by EonaCat +// Copyright 2013 EonaCat. All rights reserved. +// + +//private methods +@interface LockController() + +- (void)setupSubviews; +- (void)setupNavigationBar; +- (void)setupTextFields; +- (void)resetFields; +- (void)passcodeDidNotMatch:(NSString*)incorrectPassword; +- (void)dissmissView; + +@property (nonatomic, strong) NSMutableString *tempString; +@property (nonatomic, strong) UITextField *hiddenField; +@property (nonatomic, strong) UINavigationItem *navigationItem; + +@end + +@implementation LockController + +@synthesize delegate; +@synthesize style; +@synthesize passcode; +@synthesize prompt; +@synthesize subPrompt; +@synthesize hint; +@synthesize hiddenField; +@synthesize navigationItem; +@synthesize tempString; +@synthesize title; +@synthesize hideCode; +@synthesize waitingAlert; + +- (id)initWithTitle:(NSString*)newTitle prompt:(NSString*)newPrompt errorMessage:(NSString*)newSubPrompt correctMessage:(NSString*)newCorrectMessage passCode:(NSString*)newPasscode hint:(NSString*)newHint color:(UIColor*)newColor color2:(UIColor*)newColor2 fieldAmount:(NSInteger)newFieldAmount style:(STYLE)newStyle delegate:(id)newDelegate tag:(NSInteger)newTag cancelButton:(BOOL)cancelButton +{ + if (self = [super init]) + { + _iPad = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad; + + if (_iPad) + { + _deviceWidth = 768; + } + else + { + _deviceWidth = 320; + } + + newTitle == nil ? [NSString stringWithFormat:@"Security"] : newTitle; + newPrompt == nil ? [NSString stringWithFormat:@"Insert pincode"] : newPrompt; + newSubPrompt == nil ? [NSString stringWithFormat:@"Invalid code"] : newSubPrompt; + newHint == nil ? [NSString stringWithFormat:@"As a security you need to supply a pincode"] : newHint; + newColor == nil ? [UIColor whiteColor] : newColor; + newColor2 == nil ? [UIColor whiteColor] : newColor2; + //newFieldAmount == 0 ? 4 : newFieldAmount; + newCorrectMessage == nil ? [NSString stringWithFormat:@"Code is valid"] : newCorrectMessage; + newPasscode == nil ? [NSString stringWithFormat:@"0000"] : newCorrectMessage; + + self.cancel = cancelButton; + self.tag = newTag; + self.title = newTitle; + self.prompt = newPrompt; + self.subPrompt = newSubPrompt; + self.hint = newHint; + self.color = newColor; + self.color2 = newColor2; + self.correct = newCorrectMessage; + self.passcode = newPasscode; + self.style = newStyle; + self.fieldsAmount = newFieldAmount; + self.delegate = newDelegate; + + self.tempString = [NSMutableString string]; + self.hideCode = true; + self.waitingAlert = false; + } + + return self; +} + + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + //needs a delegate + assert (delegate != nil); + + //check if passcode is set for AUTHENTICATION + if (style == AUTHENTICATE) + { + assert (passcode != nil); + } + + [self setupSubviews]; + +} + +-(void)handleSingleTap:(UITapGestureRecognizer *)sender +{ + [alert dismissWithClickedButtonIndex:0 animated:YES]; +} + +- (void)setupSubviews +{ + self.view.backgroundColor = [UIColor groupTableViewBackgroundColor]; + + if (self.waitingAlert) + { + //Alert + alert = [[UIAlertView alloc] initWithTitle:NSLocalizedStringFromTable(@"Status", @"LockController", @"Status") + message:NSLocalizedStringFromTable(@"Please wait", @"LockController", @"Please wait") + delegate:self + cancelButtonTitle:nil + otherButtonTitles:nil, nil]; + + UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)]; + [alert addGestureRecognizer:singleTap]; + } + + //main prompt + promptLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 70, _deviceWidth, 25)]; + promptLabel.textAlignment = NSTextAlignmentCenter; + promptLabel.backgroundColor = [UIColor clearColor]; + promptLabel.shadowColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:.50]; + promptLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize]]; + promptLabel.shadowOffset = CGSizeMake(0, -0.75); + promptLabel.textColor = [UIColor blackColor]; + promptLabel.text = prompt; + [self.view addSubview:promptLabel]; + + //subPrompt + subPromptLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 90, _deviceWidth, 25)]; + subPromptLabel.textAlignment = NSTextAlignmentCenter; + subPromptLabel.backgroundColor = [UIColor clearColor]; + subPromptLabel.textColor = [UIColor redColor]; + subPromptLabel.font = [UIFont systemFontOfSize:14]; + subPromptLabel.text = subPrompt; + subPromptLabel.hidden = true; + [self.view addSubview:subPromptLabel]; + + // hint + hintLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 160, _deviceWidth, 100)]; + hintLabel.textAlignment = NSTextAlignmentCenter; + hintLabel.backgroundColor = [UIColor clearColor]; + hintLabel.shadowColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:.50]; + hintLabel.font = [UIFont systemFontOfSize:14]; + hintLabel.shadowOffset = CGSizeMake(0, -0.75); + hintLabel.numberOfLines = 2; + hintLabel.textColor = [UIColor blackColor]; + hintLabel.text = hint; + [self.view addSubview:hintLabel]; + + //bar + [self setupNavigationBar]; + + //text fields + [self setupTextFields]; +} + +- (void)setupNavigationBar +{ + UINavigationBar *navBar; + + navBar = [[UINavigationBar alloc]initWithFrame:CGRectMake(0,0,_deviceWidth,50)]; + navBar.barStyle = UIBarStyleBlack; + [self.view addSubview:navBar]; + navigationItem = [[UINavigationItem alloc]init]; + + if (self.cancel) + { + [navigationItem setRightBarButtonItem:[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemCancel + target:self + action:@selector(userDidCancel:)] + animated:NO]; + } + + [navBar pushNavigationItem:navigationItem animated:NO]; + + navigationItem.title = title; + + if (self.color) + { + CAGradientLayer *gradient = [CAGradientLayer layer]; + gradient.frame = self.view.bounds; + gradient.colors = @[(id)[self.color CGColor], (id)[self.color2 CGColor],(id)[self.color CGColor], (id)[self.color CGColor]]; + [self.view.layer insertSublayer:gradient atIndex:0]; + + if ([[[UIDevice currentDevice] systemVersion] floatValue] < 7.0) + { + [navBar setTintColor:self.color]; + } + else + { + [navBar setBarTintColor:self.color]; + } + } +} + +- (void)setupTextFields +{ + int toppadding; + int leftpadding; + int width; + int height; + int padding; + CGFloat fontsize; + + + if (_iPad) + { + if (_fieldsAmount == 4) + { + leftpadding = 150; + } + else + { + leftpadding = 130; + } + + width = 100; + height = 100; + toppadding = 250; + padding = 60; + fontsize = 64; + } + else + { + if (_fieldsAmount == 4) + { + leftpadding = 40; + } + else + { + leftpadding = 20; + } + width = 50; + height = 50; + toppadding = 125; + padding = 30; + fontsize = 32; + } + + // Initialise the textField array + textFieldArray = [NSMutableArray array]; + + for (int i = 0; i < self.fieldsAmount; i++) + { + UITextField *textField; + + textField = [[UITextField alloc]initWithFrame:CGRectMake(leftpadding + width*i + padding,toppadding,width,height)]; + + textField.backgroundColor = [UIColor whiteColor]; + textField.borderStyle = UITextBorderStyleBezel; + textField.secureTextEntry = self.hideCode; + textField.font = [UIFont systemFontOfSize:fontsize]; + textField.textAlignment = NSTextAlignmentCenter; + textField.tag = i; + textField.enabled = false; + + [self.view addSubview:textField]; + [textFieldArray addObject:textField]; + } + + hiddenField = [[UITextField alloc]initWithFrame:CGRectMake(0,0,500,500)]; + hiddenField.text = @""; + hiddenField.keyboardType = UIKeyboardTypeNumberPad; + hiddenField.keyboardAppearance = UIKeyboardAppearanceAlert; + hiddenField.delegate = self; + hiddenField.hidden = true; + [hiddenField becomeFirstResponder]; + [self.view setBackgroundColor:[UIColor whiteColor]]; + [self.view addSubview:hiddenField]; +} + +-(BOOL)checkDecimal:(NSString *)string +{ + NSNumberFormatter *numberFormat = [[NSNumberFormatter alloc] init]; + BOOL isDecimal = [numberFormat numberFromString:string] != nil; + + if (!isDecimal) + { + UIAlertView * decimalAlert = [[UIAlertView alloc] initWithTitle:NSLocalizedStringFromTable(@"Decimal title", @"LockController", @"Decimal title") + message:NSLocalizedStringFromTable(@"Decimal message", @"LockController", @"Decimal message") + delegate:self + cancelButtonTitle:@"OK" + otherButtonTitles:nil, nil]; + [decimalAlert show]; + } + return isDecimal; +} + +- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string +{ + @try + { + if ([string isEqualToString:@""] || [self checkDecimal:string]) + { + UITextField *currentTextField; + + // Check if the backSpace was pressed + if ([string isEqualToString:@""]) + { + [self.tempString setString:[self.tempString substringToIndex:[self.tempString length]-1]]; + currentTextField = textFieldArray[[self.tempString length]]; + } + else + { + [self.tempString appendString:string]; + currentTextField = textFieldArray[[self.tempString length] -1]; + } + + currentTextField.text = string; + + // we have reached the maximum characters + if ([self.tempString length] == [textFieldArray count]) + { + if (self.style == SET) + { + if (passcode == nil) + { + //empty tempstring to passcode string + passcode = [self.tempString copy]; + + self.tempString = [NSMutableString string]; + + //reset fields + [self resetFields]; + textField.text = @""; + } + else + { + //check if confirm matches first + givenPasscode = [self.tempString copy]; + if ([passcode isEqualToString:self.tempString]) + { + subPromptLabel.textColor = [UIColor greenColor]; + subPromptLabel.text = self.correct; + [delegate lockControllerDidFinish:givenPasscode tag:self.tag]; + [self dissmissView]; + } + else + { + [self passcodeDidNotMatch:givenPasscode]; + } + } + } + else if(self.style == AUTHENTICATE) + { + givenPasscode = [self.tempString copy]; + if ([passcode isEqualToString:self.tempString]) + { + subPromptLabel.textColor = [UIColor greenColor]; + subPromptLabel.text = self.correct; + [delegate lockControllerDidFinish:givenPasscode tag:self.tag]; + [self dissmissView]; + } + else + { + [self passcodeDidNotMatch:givenPasscode]; + } + return false; + } + } + return true; + } + return false; + } + @catch (NSException *exception) + { + // Do nothing + } +} + +- (void)passcodeDidNotMatch:(NSString*)incorrectPassword +{ + if (self.waitingAlert) + { + [alert show]; + } + + self.tempString = [NSMutableString string]; + + subPromptLabel.textColor = [UIColor redColor]; + subPromptLabel.text = self.subPrompt; + subPromptLabel.hidden = false; + + [self resetFields]; + [delegate lockControllerIncorrectPassword:incorrectPassword tag:self.tag]; +} + +- (void)resetFields +{ + for (UITextField *textField in textFieldArray) + { + textField.text = @""; + } + hiddenField.text = @""; +} + +- (void)incorrect +{ + if (self.waitingAlert) + { + [alert dismissWithClickedButtonIndex:0 animated:true]; + } +} + + +- (void)finished +{ + if (self.waitingAlert) + { + [alert dismissWithClickedButtonIndex:0 animated:true]; + } + + subPromptLabel.textColor = [UIColor greenColor]; + subPromptLabel.text = self.correct; +} + +- (void)dissmissView +{ + [self dismissViewControllerAnimated:TRUE completion:nil]; +} + +- (void)userDidCancel:(id)sender +{ + [delegate lockControllerDidCancel:self.tag]; + [self dissmissView]; +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; +} + +@end diff --git a/EonaCatTools/Tools/Popup/.DS_Store b/EonaCatTools/Tools/Popup/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..4ff8c89d51ce81e71b142e04a98b9231ed3ab338 GIT binary patch literal 6148 zcmeHKO-sW-5Pe$FsZ=|F6C7Pu3jX-}(>_)%WBKI0MeW9}KW&i%d=x-8uu#fHTlBAn%7r z6-?~qG2*@73rY_O(kk-uofd|I_IOsCBs%x(-Exs2)1&t z4khH(dHFOe+Xn6+&BY!W#9|qFiTtj literal 0 HcmV?d00001 diff --git a/EonaCatTools/Tools/Popup/Popup.h b/EonaCatTools/Tools/Popup/Popup.h new file mode 100644 index 0000000..86518df --- /dev/null +++ b/EonaCatTools/Tools/Popup/Popup.h @@ -0,0 +1,25 @@ +// +// Popup.h +// Created by EonaCat +// Copyright 2013 EonaCat. All rights reserved. +// + +#import + +@interface Popup : NSObject +{ + NSTimer *_notificationTimer; + UILabel *_target; + UIColor *_targetOldBackgroundColor; + UIColor *_targetOldTextColor; + NSString *_targetText; + UIAlertView *_alert; +} + +-(void)showAlert:(NSString*)title message:(NSString*)message delegate:(id)delegate cancelButtonText:(NSString*)cancelButtonText otherButtonText:(NSString*)otherButtonText tag:(NSInteger)tag; +-(void)showDebugNotification:(NSString*)message textColor:(UIColor*)textColor backgroundColor:(UIColor*)backgroundColor target:(UILabel*)target; +-(void)dismiss; + ++ (id)getInstance; + +@end diff --git a/EonaCatTools/Tools/Popup/Popup.m b/EonaCatTools/Tools/Popup/Popup.m new file mode 100644 index 0000000..1c00b1b --- /dev/null +++ b/EonaCatTools/Tools/Popup/Popup.m @@ -0,0 +1,83 @@ +// +// Popup.m +// Created by EonaCat +// Copyright 2013 EonaCat. All rights reserved. +// + +#import "Popup.h" + +@implementation Popup + +static Popup *_instance; + ++ (id)getInstance +{ + @synchronized(self) + { + if (_instance == nil) + { + _instance = [[self alloc] init]; + } + } + return _instance; +} + +-(void)showAlert:(NSString *)title message:(NSString *)message delegate:(id)delegate cancelButtonText:(NSString *)cancelButtonText otherButtonText:(NSString *)otherButtonText tag:(NSInteger)tag +{ + _alert = [[UIAlertView alloc] initWithTitle:title + message:message + delegate:delegate + cancelButtonTitle:[cancelButtonText length] == 0 ? nil : cancelButtonText + otherButtonTitles:[otherButtonText length] == 0 ? nil : otherButtonText,nil]; + _alert.tag = tag; + [_alert show]; + + + UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)]; + [_alert addGestureRecognizer:singleTap]; +} + +-(void)handleSingleTap:(UITapGestureRecognizer *)sender +{ + [_alert dismissWithClickedButtonIndex:0 animated:YES]; +} + +-(void)dismiss +{ + [_alert dismissWithClickedButtonIndex:0 animated:true]; +} + +-(void)showDebugNotification:(NSString *)message textColor:(UIColor *)textColor backgroundColor:(UIColor *)backgroundColor target:(UILabel *)target +{ + _target = target; + _targetOldBackgroundColor = target.backgroundColor; + _targetOldTextColor = target.textColor; + _targetText = target.text; + + + target.textColor = textColor; + target.backgroundColor = backgroundColor; + target.text = message; + _notificationTimer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(debugNotificationTimeElapsed:) userInfo:nil repeats:NO]; +} + +- (void)debugNotificationTimeElapsed:(NSTimer*)timer +{ + @try + { + UILabel *target = _target; + target.backgroundColor = _targetOldBackgroundColor; + target.textColor = _targetOldTextColor; + target.text = _targetText; + + + [_notificationTimer invalidate]; + } + @catch (NSException *exception) + { + NSLog(@"DebugNotificationError: %@",exception.description); + } +} + + +@end diff --git a/EonaCatTools/Tools/Toast/Toast.h b/EonaCatTools/Tools/Toast/Toast.h new file mode 100644 index 0000000..d520186 --- /dev/null +++ b/EonaCatTools/Tools/Toast/Toast.h @@ -0,0 +1,27 @@ +// +// Toast.h +// Created by EonaCat +// Copyright 2013 EonaCat. All rights reserved. +// + +#import + +@interface UIView (Toast) + +// each makeToast method creates a view and displays it as toast +- (void)makeToast:(NSString *)message; +- (void)makeToast:(NSString *)message duration:(CGFloat)interval position:(id)position; +- (void)makeToast:(NSString *)message duration:(CGFloat)interval position:(id)position title:(NSString *)title; +- (void)makeToast:(NSString *)message duration:(CGFloat)interval position:(id)position title:(NSString *)title image:(UIImage *)image; +- (void)makeToast:(NSString *)message duration:(CGFloat)interval position:(id)position image:(UIImage *)image; + +// displays toast with an activity spinner +- (void)makeToastActivity; +- (void)makeToastActivity:(id)position; +- (void)hideToastActivity; + +// the showToast methods display any view as toast +- (void)showToast:(UIView *)toast; +- (void)showToast:(UIView *)toast duration:(CGFloat)interval position:(id)point; + +@end diff --git a/EonaCatTools/Tools/Toast/Toast.m b/EonaCatTools/Tools/Toast/Toast.m new file mode 100644 index 0000000..2776893 --- /dev/null +++ b/EonaCatTools/Tools/Toast/Toast.m @@ -0,0 +1,375 @@ +// +// Toast.m +// Created by EonaCat +// Copyright 2013 EonaCat. All rights reserved. +// + +#import "Toast.h" +#import +#import +#import + +#define kMaxWidth 0.8 +#define kMaxHeight 0.8 + +#define kHorizontalPadding 10.0 +#define kVerticalPadding 10.0 +#define kCornerRadius 10.0 +#define kOpacity 0.8 +#define kFontSize 16.0 +#define kMaxTitleLines 999 +#define kMaxMessageLines 999 +#define kFadeDuration 0.2 +#define kDisplayShadow YES + +#define kDefaultLength 3.0 +#define kDefaultPosition @"bottom" + +#define kImageWidth 80.0 +#define kImageHeight 80.0 + +#define kActivityWidth 100.0 +#define kActivityHeight 100.0 +#define kActivityDefaultPosition @"center" +#define kActivityTag 91325 + +static NSString *kDurationKey = @"CSToastDurationKey"; + + +@interface UIView (ToastPrivate) + +- (CGPoint)getPositionFor:(id)position toast:(UIView *)toast; +- (UIView *)makeViewForMessage:(NSString *)message title:(NSString *)title image:(UIImage *)image; + +@end + + +@implementation UIView (Toast) + +#pragma mark - Toast Methods + +- (void)makeToast:(NSString *)message { + [self makeToast:message duration:kDefaultLength position:kDefaultPosition]; +} + +- (void)makeToast:(NSString *)message duration:(CGFloat)interval position:(id)position { + UIView *toast = [self makeViewForMessage:message title:nil image:nil]; + [self showToast:toast duration:interval position:position]; +} + +- (void)makeToast:(NSString *)message duration:(CGFloat)interval position:(id)position title:(NSString *)title { + UIView *toast = [self makeViewForMessage:message title:title image:nil]; + [self showToast:toast duration:interval position:position]; +} + +- (void)makeToast:(NSString *)message duration:(CGFloat)interval position:(id)position image:(UIImage *)image { + UIView *toast = [self makeViewForMessage:message title:nil image:image]; + [self showToast:toast duration:interval position:position]; +} + +- (void)makeToast:(NSString *)message duration:(CGFloat)interval position:(id)position title:(NSString *)title image:(UIImage *)image { + UIView *toast = [self makeViewForMessage:message title:title image:image]; + [self showToast:toast duration:interval position:position]; +} + +- (void)showToast:(UIView *)toast { + [self showToast:toast duration:kDefaultLength position:kDefaultPosition]; +} + +- (void)showToast:(UIView *)toast duration:(CGFloat)interval position:(id)point { + // Display a view for a given duration & position. + + CGPoint toastPoint = [self getPositionFor:point toast:toast]; + + // use an associative reference to associate the toast view with the display interval + objc_setAssociatedObject (toast, &kDurationKey, [NSNumber numberWithFloat:interval], OBJC_ASSOCIATION_RETAIN); + + [toast setCenter:toastPoint]; + [toast setAlpha:0.0]; + [self addSubview:toast]; + +#if !__has_feature(objc_arc) + [UIView beginAnimations:@"fade_in" context:toast]; +#else + [UIView beginAnimations:@"fade_in" context:(__bridge void*)toast]; +#endif + [UIView setAnimationDuration:kFadeDuration]; + + SystemSoundID mySound = [self createSoundID: @"toast.wav"]; + AudioServicesPlaySystemSound(mySound); + + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseOut]; + [toast setAlpha:1.0]; + [UIView commitAnimations]; + +} + +-(SystemSoundID) createSoundID: (NSString*)name +{ + NSString *path = [NSString stringWithFormat: @"%@/%@", + [[NSBundle mainBundle] resourcePath], name]; + + NSURL* filePath = [NSURL fileURLWithPath: path isDirectory: NO]; + SystemSoundID soundID; + AudioServicesCreateSystemSoundID((__bridge CFURLRef)filePath, &soundID); + NSLog(@"%@, %@", path, filePath); + return soundID; +} + +#pragma mark - Toast Activity Methods + +- (void)makeToastActivity { + [self makeToastActivity:kActivityDefaultPosition]; +} + +- (void)makeToastActivity:(id)position { + // prevent more than one activity view + UIView *existingToast = [self viewWithTag:kActivityTag]; + if (existingToast != nil) { + [existingToast removeFromSuperview]; + } + + UIView *activityContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kActivityWidth, kActivityHeight)]; +#if !__has_feature(objc_arc) + [activityContainer autorelease]; +#endif + [activityContainer setCenter:[self getPositionFor:position toast:activityContainer]]; + [activityContainer setBackgroundColor:[[UIColor blackColor] colorWithAlphaComponent:kOpacity]]; + [activityContainer setAlpha:0.0]; + [activityContainer setTag:kActivityTag]; + [activityContainer setAutoresizingMask:(UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin)]; + [activityContainer.layer setCornerRadius:kCornerRadius]; + if (kDisplayShadow) { + [activityContainer.layer setShadowColor:[UIColor blackColor].CGColor]; + [activityContainer.layer setShadowOpacity:0.8]; + [activityContainer.layer setShadowRadius:6.0]; + [activityContainer.layer setShadowOffset:CGSizeMake(4.0, 4.0)]; + } + + UIActivityIndicatorView *activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; +#if !__has_feature(objc_arc) + [activityView autorelease]; +#endif + [activityView setCenter:CGPointMake(activityContainer.bounds.size.width / 2, activityContainer.bounds.size.height / 2)]; + [activityContainer addSubview:activityView]; + [activityView startAnimating]; + + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:kFadeDuration]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseOut]; + [activityContainer setAlpha:1.0]; + [UIView commitAnimations]; + + [self addSubview:activityContainer]; +} + +- (void)hideToastActivity { + UIView *existingToast = [self viewWithTag:kActivityTag]; + if (existingToast != nil) { + [UIView beginAnimations:nil context:nil]; + [UIView setAnimationDuration:kFadeDuration]; + [UIView setAnimationDelegate:existingToast]; + [UIView setAnimationDidStopSelector:@selector(removeFromSuperview)]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseIn]; + [existingToast setAlpha:0.0]; + [UIView commitAnimations]; + } +} + +#pragma mark - Animation Delegate Method + +- (void)animationDidStop:(NSString*)animationID finished:(BOOL)finished context:(void *)context { +#if !__has_feature(objc_arc) + UIView *toast = (UIView *)context; +#else + UIView *toast = (UIView *)(__bridge id)context; +#endif + + // retrieve the display interval associated with the view + CGFloat interval = [(NSNumber *)objc_getAssociatedObject(toast, &kDurationKey) floatValue]; + + if([animationID isEqualToString:@"fade_in"]) { + +#if !__has_feature(objc_arc) + [UIView beginAnimations:@"fade_out" context:toast]; +#else + [UIView beginAnimations:@"fade_out" context:(__bridge void*)toast]; +#endif + [UIView setAnimationDelay:interval]; + [UIView setAnimationDuration:kFadeDuration]; + [UIView setAnimationDelegate:self]; + [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)]; + [UIView setAnimationCurve:UIViewAnimationCurveEaseIn]; + [toast setAlpha:0.0]; + [UIView commitAnimations]; + + } else if ([animationID isEqualToString:@"fade_out"]) { + + [toast removeFromSuperview]; + + } + +} + +#pragma mark - Private Methods + +- (CGPoint)getPositionFor:(id)point toast:(UIView *)toast { + // Convert string literals @"top", @"bottom", @"center", or any point wrapped in an + // NSValue object into a CGPoint + + if([point isKindOfClass:[NSString class]]) { + + if( [point caseInsensitiveCompare:@"top"] == NSOrderedSame ) { + return CGPointMake(self.bounds.size.width/2, (toast.frame.size.height / 2) + kVerticalPadding); + } else if( [point caseInsensitiveCompare:@"bottom"] == NSOrderedSame ) { + return CGPointMake(self.bounds.size.width/2, (self.bounds.size.height - (toast.frame.size.height / 2)) - kVerticalPadding); + } else if( [point caseInsensitiveCompare:@"center"] == NSOrderedSame ) { + return CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2); + } + + } else if ([point isKindOfClass:[NSValue class]]) { + return [point CGPointValue]; + } + + NSLog(@"Error: Invalid position for toast."); + return [self getPositionFor:kDefaultPosition toast:toast]; +} + +- (UIView *)makeViewForMessage:(NSString *)message title:(NSString *)title image:(UIImage *)image { + // sanity + if((message == nil) && (title == nil) && (image == nil)) return nil; + + // Dynamically build a toast view with any combination of message, title, & image. + UILabel *messageLabel = nil; + UILabel *titleLabel = nil; + UIImageView *imageView = nil; + + // create the parent view + UIView *wrapperView = [[UIView alloc] init]; +#if !__has_feature(objc_arc) + [wrapperView autorelease]; +#endif + [wrapperView setAutoresizingMask:(UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin)]; + [wrapperView.layer setCornerRadius:kCornerRadius]; + if (kDisplayShadow) { + [wrapperView.layer setShadowColor:[UIColor blackColor].CGColor]; + [wrapperView.layer setShadowOpacity:0.8]; + [wrapperView.layer setShadowRadius:6.0]; + [wrapperView.layer setShadowOffset:CGSizeMake(4.0, 4.0)]; + } + + [wrapperView setBackgroundColor:[[UIColor blackColor] colorWithAlphaComponent:kOpacity]]; + + if(image != nil) { + imageView = [[UIImageView alloc] initWithImage:image]; +#if !__has_feature(objc_arc) + [imageView autorelease]; +#endif + [imageView setContentMode:UIViewContentModeScaleAspectFit]; + [imageView setFrame:CGRectMake(kHorizontalPadding, kVerticalPadding, kImageWidth, kImageHeight)]; + } + + CGFloat imageWidth, imageHeight, imageLeft; + + // the imageView frame values will be used to size & position the other views + if(imageView != nil) { + imageWidth = imageView.bounds.size.width; + imageHeight = imageView.bounds.size.height; + imageLeft = kHorizontalPadding; + } else { + imageWidth = imageHeight = imageLeft = 0.0; + } + + if (title != nil) { + titleLabel = [[UILabel alloc] init]; +#if !__has_feature(objc_arc) + [titleLabel autorelease]; +#endif + [titleLabel setNumberOfLines:kMaxTitleLines]; + [titleLabel setFont:[UIFont boldSystemFontOfSize:kFontSize]]; + [titleLabel setTextAlignment:NSTextAlignmentLeft]; + [titleLabel setLineBreakMode:NSLineBreakByWordWrapping]; + [titleLabel setTextColor:[UIColor whiteColor]]; + [titleLabel setBackgroundColor:[UIColor clearColor]]; + [titleLabel setAlpha:1.0]; + [titleLabel setText:title]; + + // size the title label according to the length of the text + CGSize maxSizeTitle = CGSizeMake((self.bounds.size.width * kMaxWidth) - imageWidth, self.bounds.size.height * kMaxHeight); + CGSize expectedSizeTitle = [title sizeWithFont:titleLabel.font constrainedToSize:maxSizeTitle lineBreakMode:titleLabel.lineBreakMode]; + [titleLabel setFrame:CGRectMake(0.0, 0.0, expectedSizeTitle.width, expectedSizeTitle.height)]; + } + + if (message != nil) { + messageLabel = [[UILabel alloc] init]; +#if !__has_feature(objc_arc) + [messageLabel autorelease]; +#endif + [messageLabel setNumberOfLines:kMaxMessageLines]; + [messageLabel setFont:[UIFont systemFontOfSize:kFontSize]]; + [messageLabel setLineBreakMode:NSLineBreakByWordWrapping]; + [messageLabel setTextColor:[UIColor whiteColor]]; + [messageLabel setBackgroundColor:[UIColor clearColor]]; + [messageLabel setAlpha:1.0]; + [messageLabel setText:message]; + + // size the message label according to the length of the text + CGSize maxSizeMessage = CGSizeMake((self.bounds.size.width * kMaxWidth) - imageWidth, self.bounds.size.height * kMaxHeight); + CGSize expectedSizeMessage = [message sizeWithFont:messageLabel.font constrainedToSize:maxSizeMessage lineBreakMode:messageLabel.lineBreakMode]; + [messageLabel setFrame:CGRectMake(0.0, 0.0, expectedSizeMessage.width, expectedSizeMessage.height)]; + } + + // titleLabel frame values + CGFloat titleWidth, titleHeight, titleTop, titleLeft; + + if(titleLabel != nil) { + titleWidth = titleLabel.bounds.size.width; + titleHeight = titleLabel.bounds.size.height; + titleTop = kVerticalPadding; + titleLeft = imageLeft + imageWidth + kHorizontalPadding; + } else { + titleWidth = titleHeight = titleTop = titleLeft = 0.0; + } + + // messageLabel frame values + CGFloat messageWidth, messageHeight, messageLeft, messageTop; + + if(messageLabel != nil) { + messageWidth = messageLabel.bounds.size.width; + messageHeight = messageLabel.bounds.size.height; + messageLeft = imageLeft + imageWidth + kHorizontalPadding; + messageTop = titleTop + titleHeight + kVerticalPadding; + } else { + messageWidth = messageHeight = messageLeft = messageTop = 0.0; + } + + + CGFloat longerWidth = MAX(titleWidth, messageWidth); + CGFloat longerLeft = MAX(titleLeft, messageLeft); + + // wrapper width uses the longerWidth or the image width, whatever is larger. same logic applies to the wrapper height + CGFloat wrapperWidth = MAX((imageWidth + (kHorizontalPadding * 2)), (longerLeft + longerWidth + kHorizontalPadding)); + CGFloat wrapperHeight = MAX((messageTop + messageHeight + kVerticalPadding), (imageHeight + (kVerticalPadding * 2))); + + [wrapperView setFrame:CGRectMake(0.0, 0.0, wrapperWidth, wrapperHeight)]; + + if(titleLabel != nil) { + [titleLabel setFrame:CGRectMake(titleLeft, titleTop, titleWidth, titleHeight)]; + [wrapperView addSubview:titleLabel]; + } + + if(messageLabel != nil) { + [messageLabel setFrame:CGRectMake(messageLeft, messageTop, messageWidth, messageHeight)]; + [wrapperView addSubview:messageLabel]; + } + + if(imageView != nil) { + [wrapperView addSubview:imageView]; + } + + return wrapperView; +} + +@end diff --git a/EonaCatTools/Tools/Toast/toast.wav b/EonaCatTools/Tools/Toast/toast.wav new file mode 100644 index 0000000000000000000000000000000000000000..ae55a36ad1b7962f6c0e7d2db0d5e4280ea959e0 GIT binary patch literal 114760 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 T&R@P<`|JPsk6-`$zYYC2f(Nyn literal 0 HcmV?d00001 diff --git a/EonaCatTools/Tools/uniqueIdentifier/DeviceIdentifier.h b/EonaCatTools/Tools/uniqueIdentifier/DeviceIdentifier.h new file mode 100644 index 0000000..ad61d66 --- /dev/null +++ b/EonaCatTools/Tools/uniqueIdentifier/DeviceIdentifier.h @@ -0,0 +1,21 @@ +// +// DeviceIdentifier.h +// Created by EonaCat +// Copyright 2013 EonaCat. All rights reserved. +// + +#import + + +@interface UIDevice (IdentifierAddition) + +// Generate a sha1 hash of your MAC address with your bundle app identifier +- (NSString*) appIdentifier; + +// Generate a sha1 hash of your MAC address +- (NSString*) deviceIdentifier; + +// Get the MAC address +- (NSString*) macAddress; + +@end diff --git a/EonaCatTools/Tools/uniqueIdentifier/DeviceIdentifier.m b/EonaCatTools/Tools/uniqueIdentifier/DeviceIdentifier.m new file mode 100644 index 0000000..d0abe5e --- /dev/null +++ b/EonaCatTools/Tools/uniqueIdentifier/DeviceIdentifier.m @@ -0,0 +1,101 @@ +// +// DeviceIdentifier.m +// Created by EonaCat +// Copyright 2013 EonaCat. All rights reserved. +// + +#import "DeviceIdentifier.h" +#import "SHA1.h" + +#include +#include +#include +#include + +@interface UIDevice(Private) + +- (NSString*) macaddress; + +@end + +@implementation UIDevice (IdentifierAddition) + +// Get the local macaddress +- (NSString*) macaddress +{ + int mib[6]; + size_t len; + char *buf; + unsigned char *ptr; + struct if_msghdr *ifm; + struct sockaddr_dl *sdl; + + mib[0] = CTL_NET; + mib[1] = AF_ROUTE; + mib[2] = 0; + mib[3] = AF_LINK; + mib[4] = NET_RT_IFLIST; + + if ((mib[5] = if_nametoindex("en0")) == 0) + { + printf("Error: if_nametoindex error\n"); + return NULL; + } + + if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) + { + printf("Error: sysctl, take 1\n"); + return NULL; + } + + if ((buf = malloc(len)) == NULL) + { + printf("Could not allocate memory. error!\n"); + return NULL; + } + + if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) + { + printf("Error: sysctl, take 2"); + free(buf); + return NULL; + } + + ifm = (struct if_msghdr *)buf; + sdl = (struct sockaddr_dl *)(ifm + 1); + ptr = (unsigned char *)LLADDR(sdl); + NSString *outstring = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X", + *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)]; + free(buf); + + return outstring; +} + +// Get the appIdentifier +- (NSString*) appIdentifier +{ + NSString *macaddress = [[UIDevice currentDevice] macaddress]; + NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; + + NSString *stringToHash = [NSString stringWithFormat:@"%@%@",macaddress,bundleIdentifier]; + NSString *uniqueIdentifier = [stringToHash stringFromSHA1:stringToHash]; + + return uniqueIdentifier; +} + +// Get the deviceIdentifier +- (NSString*) deviceIdentifier +{ + NSString *macaddress = [[UIDevice currentDevice] macaddress]; + NSString *uniqueIdentifier = [macaddress stringFromSHA1:macaddress]; + + return uniqueIdentifier; +} + +// Get the macAddress +- (NSString*) macAddress +{ + return [[UIDevice currentDevice] macaddress]; +} + +@end \ No newline at end of file diff --git a/EonaCatTools/Tools/uniqueIdentifier/SHA1.h b/EonaCatTools/Tools/uniqueIdentifier/SHA1.h new file mode 100644 index 0000000..ea7e4fa --- /dev/null +++ b/EonaCatTools/Tools/uniqueIdentifier/SHA1.h @@ -0,0 +1,13 @@ +// +// SHA1.h +// Created by EonaCat +// Copyright 2013 EonaCat. All rights reserved. +// + +#import + +@interface NSString(SHA1) + +-(NSString*) stringFromSHA1:(NSString*)input; + +@end diff --git a/EonaCatTools/Tools/uniqueIdentifier/SHA1.m b/EonaCatTools/Tools/uniqueIdentifier/SHA1.m new file mode 100644 index 0000000..dccb382 --- /dev/null +++ b/EonaCatTools/Tools/uniqueIdentifier/SHA1.m @@ -0,0 +1,29 @@ +// +// SHA1.m +// Created by EonaCat +// Copyright 2013 EonaCat. All rights reserved. +// + +#import "SHA1.h" +#import + +@implementation NSString(SHA1) + +-(NSString*) stringFromSHA1:(NSString*)input +{ + const char *charString = [input cStringUsingEncoding:NSUTF8StringEncoding]; + NSData *data = [NSData dataWithBytes:charString length:input.length]; + + uint8_t digest[CC_SHA1_DIGEST_LENGTH]; + + CC_SHA1(data.bytes, data.length, digest); + + NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2]; + + for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) + { + [output appendFormat:@"%02x", digest[i]]; + } + return output; +} +@end \ No newline at end of file diff --git a/EonaCatTools/ViewController.h b/EonaCatTools/ViewController.h new file mode 100644 index 0000000..5e0e226 --- /dev/null +++ b/EonaCatTools/ViewController.h @@ -0,0 +1,18 @@ +// +// ViewController.h +// Created by EonaCat +// Copyright 2013 EonaCat. All rights reserved. +// + +#import +#import "LockController.h" + +@interface ViewController : UIViewController + +@property (weak, nonatomic) IBOutlet UIButton *showExceptionsButton; +@property (weak, nonatomic) IBOutlet UIButton *throwException; +@property (weak, nonatomic) IBOutlet UIButton *showToastButton; +@property (weak, nonatomic) IBOutlet UIButton *showPopupButton; +@property (weak, nonatomic) IBOutlet UIButton *showLockScreenButton; + +@end diff --git a/EonaCatTools/ViewController.m b/EonaCatTools/ViewController.m new file mode 100644 index 0000000..8b05273 --- /dev/null +++ b/EonaCatTools/ViewController.m @@ -0,0 +1,89 @@ +// +// ViewController.m +// Created by EonaCat +// Copyright 2013 EonaCat. All rights reserved. +// + +#import "ViewController.h" +#import "AppDelegate.h" +#import "Toast.h" +#import "Popup.h" +#import "LockController.h" +#import "ExceptionLogger.h" + +@interface ViewController () + +@end + +@implementation ViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + // Do any additional setup after loading the view, typically from a nib. +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (IBAction)showExceptionsAction:(UIButton *)sender +{ + // Show ExceptionLogger (Check for iPhone or iPad) + ExceptionLogger* exceptionLogger; + + if (Delegate.iPad) + { + exceptionLogger = [[ExceptionLogger alloc] initWithNibName:@"ExceptionLogger-iPad" bundle:nil]; + } + else + { + exceptionLogger = [[ExceptionLogger alloc] initWithNibName:@"ExceptionLogger" bundle:nil]; + } + exceptionLogger.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; + [self presentViewController:exceptionLogger animated:YES completion:nil]; +} + +- (void)lockControllerIncorrectPassword:(NSString*)incorrectPassword tag:(NSInteger)tag +{ + [[Popup getInstance] showAlert:@"Incorrect" message:@"All your base are belong to us" delegate:self cancelButtonText:@"OK" otherButtonText:nil tag:0]; + +} + +-(void)lockControllerDidFinish:(NSString *)passcode tag:(NSInteger)tag +{ + [[Popup getInstance] showAlert:@"Correct!" message:@"All your base belongs to you" delegate:self cancelButtonText:@"OK" otherButtonText:nil tag:0]; +} + +- (IBAction)throwExceptionAction:(UIButton *)sender +{ + @throw [[NSException alloc] initWithName:@"NSException thrown!" reason:@"Testing" userInfo:nil]; +} + +- (IBAction)showToastAction:(UIButton *)sender +{ + //[self.view makeToast:[NSString stringWithFormat:@"Toasted!"] duration:3.0 position:@"top"]; + [self.view makeToast:@"EonaCat Toast!" duration:3.0 position:@"top" title:@"Toasted!" image:[UIImage imageNamed:@"toast.png"]]; +} + +- (IBAction)showPopupAction:(UIButton *)sender +{ + [[Popup getInstance] showAlert:@"Popup!" message:@"EonaCat Popup" delegate:self cancelButtonText:@"OK" otherButtonText:nil tag:0]; +} + +- (IBAction)showLockScreenAction:(UIButton *)sender +{ + LockController *lockController = [[LockController alloc] init]; + + [lockController setDelegate:self]; + [lockController setTitle:@"EonaCat LOCK!"]; + [lockController setSubPrompt:@"Passcode => 0000"]; + [lockController setPasscode:@"0000"]; + + // [self presentViewController:lockController animated:true completion:nil]; + [[Popup getInstance] showAlert:@"Lock!" message:@"Doesn't work on iOS7 yet!" delegate:self cancelButtonText:@"OK" otherButtonText:nil tag:0]; +} + +@end diff --git a/EonaCatTools/en.lproj/InfoPlist.strings b/EonaCatTools/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/EonaCatTools/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/EonaCatTools/main.m b/EonaCatTools/main.m new file mode 100644 index 0000000..02e8ba3 --- /dev/null +++ b/EonaCatTools/main.m @@ -0,0 +1,17 @@ +// +// main.m +// Created by EonaCat +// Copyright 2013 EonaCat. All rights reserved. +// + + +#import + +#import "AppDelegate.h" + +int main(int argc, char * argv[]) +{ + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/EonaCatToolsTests/.DS_Store b/EonaCatToolsTests/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..d5a14b17cb02d1d1c0df50e8c48930fdc8e2cbe2 GIT binary patch literal 6148 zcmeHKyGjH>5Ukb<7ECTQoG%dkgW)*8z#llyGm*m;#eAdtEg9xU2Rz~#H#mOh z@5k}CcP!tmtQ3#}Qa}nw0V%MgfcIY7aFwVi1*Cu!_)@^X4~_2F3#Y{RbTGsSKwL2$ z#&ygR#O4WNFPsvYp;=OiNwpd=Ea}X*s_TVQV$xwXd{{l%YC^GiI`3~$4(o}EQa}ov zD{z_HwfFx!`VaH}IY~PyAO-%F0=C-TZ#R6U>aDYv^IqHNJG$3=(A~HW3PZGGVzgs! gyd7UhQPwqI^Sl>Mi9u&R=tTVtxGpj&@Yf1_0wzNhaR2}S literal 0 HcmV?d00001 diff --git a/EonaCatToolsTests/EonaCatToolsTests-Info.plist b/EonaCatToolsTests/EonaCatToolsTests-Info.plist new file mode 100644 index 0000000..f01e55e --- /dev/null +++ b/EonaCatToolsTests/EonaCatToolsTests-Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + nl.EonaCat.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/EonaCatToolsTests/EonaCatToolsTests.m b/EonaCatToolsTests/EonaCatToolsTests.m new file mode 100644 index 0000000..b2ca2f1 --- /dev/null +++ b/EonaCatToolsTests/EonaCatToolsTests.m @@ -0,0 +1,35 @@ +// +// EonaCatToolsTest.m +// Created by EonaCat +// Copyright 2013 EonaCat. All rights reserved. +// + + +#import + +@interface EonaCatToolsTests : XCTestCase + +@end + +@implementation EonaCatToolsTests + +- (void)setUp +{ + [super setUp]; + + // Set-up code here. +} + +- (void)tearDown +{ + // Tear-down code here. + + [super tearDown]; +} + +- (void)testExample +{ + XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); +} + +@end diff --git a/EonaCatToolsTests/en.lproj/InfoPlist.strings b/EonaCatToolsTests/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/EonaCatToolsTests/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/README.md b/README.md index 3c437e7..82b58a2 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,11 @@ -# EonaCat-Tools +EonaCat-Tools +================= -EonaCat-Tools Objective-c \ No newline at end of file +This xcode project consist out of the following classes: + +Popup (Wrapper) +Toast +Exceptionslogger +Exceptionshandler + +These tools can be useful for anyone developing for the iOS devices.