mirror of
https://github.com/zhigang1992/iOS-6-Advanced-Cookbook.git
synced 2026-01-12 17:23:08 +08:00
Bringin' home another little lost lamb - this time from C13
This commit is contained in:
BIN
C13 - Push/02 - pushutil/.DS_Store
vendored
Normal file
BIN
C13 - Push/02 - pushutil/.DS_Store
vendored
Normal file
Binary file not shown.
262
C13 - Push/02 - pushutil/pushutil.xcodeproj/project.pbxproj
Normal file
262
C13 - Push/02 - pushutil/pushutil.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,262 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
8E4B3D021427B24C00CE678C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E4B3D011427B24C00CE678C /* Foundation.framework */; };
|
||||
8E4B3D051427B24C00CE678C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E4B3D041427B24C00CE678C /* main.m */; };
|
||||
8E4B3D141427B2A100CE678C /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E4B3D131427B2A100CE678C /* CoreFoundation.framework */; };
|
||||
8E4B3D171427B2A500CE678C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E4B3D161427B2A500CE678C /* Security.framework */; };
|
||||
8E4B3D201427B2C100CE678C /* ioSock.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E4B3D1C1427B2C100CE678C /* ioSock.c */; };
|
||||
8E4B3D211427B2C100CE678C /* APNSHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E4B3D1F1427B2C100CE678C /* APNSHelper.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
8E4B3CFB1427B24C00CE678C /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
8E4B3CFD1427B24C00CE678C /* pushutil */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = pushutil; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8E4B3D011427B24C00CE678C /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
8E4B3D041427B24C00CE678C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
8E4B3D071427B24C00CE678C /* pushutil-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "pushutil-Prefix.pch"; sourceTree = "<group>"; };
|
||||
8E4B3D131427B2A100CE678C /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
|
||||
8E4B3D161427B2A500CE678C /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
|
||||
8E4B3D1C1427B2C100CE678C /* ioSock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioSock.c; sourceTree = "<group>"; };
|
||||
8E4B3D1D1427B2C100CE678C /* ioSock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ioSock.h; sourceTree = "<group>"; };
|
||||
8E4B3D1E1427B2C100CE678C /* APNSHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APNSHelper.h; sourceTree = "<group>"; };
|
||||
8E4B3D1F1427B2C100CE678C /* APNSHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = APNSHelper.m; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
8E4B3CFA1427B24C00CE678C /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8E4B3D171427B2A500CE678C /* Security.framework in Frameworks */,
|
||||
8E4B3D141427B2A100CE678C /* CoreFoundation.framework in Frameworks */,
|
||||
8E4B3D021427B24C00CE678C /* Foundation.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
8E4B3CF21427B24C00CE678C = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8E4B3D031427B24C00CE678C /* pushutil */,
|
||||
8E4B3D001427B24C00CE678C /* Frameworks */,
|
||||
8E4B3CFE1427B24C00CE678C /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8E4B3CFE1427B24C00CE678C /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8E4B3CFD1427B24C00CE678C /* pushutil */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8E4B3D001427B24C00CE678C /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8E4B3D161427B2A500CE678C /* Security.framework */,
|
||||
8E4B3D131427B2A100CE678C /* CoreFoundation.framework */,
|
||||
8E4B3D011427B24C00CE678C /* Foundation.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8E4B3D031427B24C00CE678C /* pushutil */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8E4B3D041427B24C00CE678C /* main.m */,
|
||||
8E4B3D1C1427B2C100CE678C /* ioSock.c */,
|
||||
8E4B3D1D1427B2C100CE678C /* ioSock.h */,
|
||||
8E4B3D1E1427B2C100CE678C /* APNSHelper.h */,
|
||||
8E4B3D1F1427B2C100CE678C /* APNSHelper.m */,
|
||||
8E4B3D061427B24C00CE678C /* Supporting Files */,
|
||||
);
|
||||
path = pushutil;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8E4B3D061427B24C00CE678C /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8E4B3D071427B24C00CE678C /* pushutil-Prefix.pch */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
8E4B3CFC1427B24C00CE678C /* pushutil */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 8E4B3D0C1427B24C00CE678C /* Build configuration list for PBXNativeTarget "pushutil" */;
|
||||
buildPhases = (
|
||||
8E4B3CF91427B24C00CE678C /* Sources */,
|
||||
8E4B3CFA1427B24C00CE678C /* Frameworks */,
|
||||
8E4B3CFB1427B24C00CE678C /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = pushutil;
|
||||
productName = pushutil;
|
||||
productReference = 8E4B3CFD1427B24C00CE678C /* pushutil */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
8E4B3CF41427B24C00CE678C /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0460;
|
||||
ORGANIZATIONNAME = "Up To No Good, Inc.";
|
||||
};
|
||||
buildConfigurationList = 8E4B3CF71427B24C00CE678C /* Build configuration list for PBXProject "pushutil" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 8E4B3CF21427B24C00CE678C;
|
||||
productRefGroup = 8E4B3CFE1427B24C00CE678C /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
8E4B3CFC1427B24C00CE678C /* pushutil */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
8E4B3CF91427B24C00CE678C /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8E4B3D051427B24C00CE678C /* main.m in Sources */,
|
||||
8E4B3D201427B2C100CE678C /* ioSock.c in Sources */,
|
||||
8E4B3D211427B2C100CE678C /* APNSHelper.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
8E4B3D0A1427B24C00CE678C /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
8E4B3D0B1427B24C00CE678C /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
8E4B3D0D1427B24C00CE678C /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "pushutil/pushutil-Prefix.pch";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
8E4B3D0E1427B24C00CE678C /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "pushutil/pushutil-Prefix.pch";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
8E4B3CF71427B24C00CE678C /* Build configuration list for PBXProject "pushutil" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
8E4B3D0A1427B24C00CE678C /* Debug */,
|
||||
8E4B3D0B1427B24C00CE678C /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
8E4B3D0C1427B24C00CE678C /* Build configuration list for PBXNativeTarget "pushutil" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
8E4B3D0D1427B24C00CE678C /* Debug */,
|
||||
8E4B3D0E1427B24C00CE678C /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 8E4B3CF41427B24C00CE678C /* Project object */;
|
||||
}
|
||||
7
C13 - Push/02 - pushutil/pushutil.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
C13 - Push/02 - pushutil/pushutil.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:pushutil.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
Binary file not shown.
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges</key>
|
||||
<true/>
|
||||
<key>SnapshotAutomaticallyBeforeSignificantChanges</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0460"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "8E4B3CFC1427B24C00CE678C"
|
||||
BuildableName = "pushutil"
|
||||
BlueprintName = "pushutil"
|
||||
ReferencedContainer = "container:pushutil.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
buildConfiguration = "Debug">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "8E4B3CFC1427B24C00CE678C"
|
||||
BuildableName = "pushutil"
|
||||
BlueprintName = "pushutil"
|
||||
ReferencedContainer = "container:pushutil.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Debug"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "8E4B3CFC1427B24C00CE678C"
|
||||
BuildableName = "pushutil"
|
||||
BlueprintName = "pushutil"
|
||||
ReferencedContainer = "container:pushutil.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
buildConfiguration = "Release"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "8E4B3CFC1427B24C00CE678C"
|
||||
BuildableName = "pushutil"
|
||||
BlueprintName = "pushutil"
|
||||
ReferencedContainer = "container:pushutil.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>pushutil.xcscheme</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
<dict>
|
||||
<key>8E4B3CFC1427B24C00CE678C</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
17
C13 - Push/02 - pushutil/pushutil/APNSHelper.h
Normal file
17
C13 - Push/02 - pushutil/pushutil/APNSHelper.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
Erica Sadun, http://ericasadun.com
|
||||
iPhone Developer's Cookbook, 3.0 Edition
|
||||
BSD License, Use at your own risk
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface APNSHelper : NSObject
|
||||
@property (nonatomic, strong) NSString *deviceTokenID;
|
||||
@property (nonatomic, strong) NSData *certificateData;
|
||||
@property (assign) BOOL useSandboxServer;
|
||||
|
||||
+ (APNSHelper *) sharedInstance;
|
||||
- (BOOL) push: (NSString *) payload;
|
||||
- (NSArray *) fetchFeedback;
|
||||
@end
|
||||
353
C13 - Push/02 - pushutil/pushutil/APNSHelper.m
Normal file
353
C13 - Push/02 - pushutil/pushutil/APNSHelper.m
Normal file
@@ -0,0 +1,353 @@
|
||||
/*
|
||||
Erica Sadun, http://ericasadun.com
|
||||
iPhone Developer's Cookbook, 3.0 Edition
|
||||
BSD License, Use at your own risk
|
||||
*/
|
||||
|
||||
#import "APNSHelper.h"
|
||||
#import "ioSock.h"
|
||||
|
||||
@implementation APNSHelper
|
||||
@synthesize certificateData;
|
||||
@synthesize deviceTokenID;
|
||||
@synthesize useSandboxServer;
|
||||
|
||||
static APNSHelper *sharedInstance = nil;
|
||||
|
||||
+(APNSHelper *) sharedInstance {
|
||||
if(!sharedInstance) {
|
||||
sharedInstance = [[self alloc] init];
|
||||
}
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if (!(self = [super init])) return self;
|
||||
self.certificateData = nil;
|
||||
self.deviceTokenID = nil;
|
||||
return self;
|
||||
}
|
||||
|
||||
// Adapted from code by Stefan Hafeneger
|
||||
- (BOOL) push: (NSString *) payload
|
||||
{
|
||||
otSocket socket;
|
||||
SSLContextRef context;
|
||||
SecKeychainRef keychain;
|
||||
SecIdentityRef identity;
|
||||
SecCertificateRef certificate;
|
||||
OSStatus result;
|
||||
|
||||
// Ensure device token
|
||||
if (!self.deviceTokenID)
|
||||
{
|
||||
printf("Error: Device Token is nil\n");
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Ensure certificate
|
||||
if (!self.certificateData)
|
||||
{
|
||||
printf("Error: Certificate Data is nil\n");
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Establish connection to server.
|
||||
PeerSpec peer;
|
||||
if (self.useSandboxServer)
|
||||
{
|
||||
printf("Sending message via sandbox\n");
|
||||
result = MakeServerConnection("gateway.sandbox.push.apple.com", 2195, &socket, &peer);
|
||||
}
|
||||
else
|
||||
result = MakeServerConnection("gateway.push.apple.com", 2195, &socket, &peer);
|
||||
if (result)
|
||||
{
|
||||
printf("Error creating server connection\n");
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Create new SSL context.
|
||||
result = SSLNewContext(false, &context);
|
||||
if (result)
|
||||
{
|
||||
printf("Error creating SSL context\n");
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Set callback functions for SSL context.
|
||||
result = SSLSetIOFuncs(context, SocketRead, SocketWrite);
|
||||
if (result)
|
||||
{
|
||||
printf("Error setting SSL context callback functions\n");
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Set SSL context connection.
|
||||
result = SSLSetConnection(context, socket);
|
||||
if (result)
|
||||
{
|
||||
printf("Error setting the SSL context connection\n");
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Set server domain name.
|
||||
result = SSLSetPeerDomainName(context, "gateway.sandbox.push.apple.com", 30);
|
||||
if (result)
|
||||
{
|
||||
printf("Error setting the server domain name\n");
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Open keychain.
|
||||
result = SecKeychainCopyDefault(&keychain);
|
||||
if (result)
|
||||
{
|
||||
printf("Error accessing keychain\n");
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Create certificate from data
|
||||
CFDataRef data = (__bridge CFDataRef) self.certificateData;
|
||||
certificate = SecCertificateCreateWithData(kCFAllocatorDefault, data);
|
||||
if (!certificate)
|
||||
{
|
||||
printf("Error creating certificate from data\n");
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Create identity.
|
||||
result = SecIdentityCreateWithCertificate(keychain, certificate, &identity);
|
||||
if (result)
|
||||
{
|
||||
printf("Error creating identity from certificate: %d\n", result);
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Disable Verify
|
||||
result = SSLSetEnableCertVerify(context, NO);
|
||||
if (result)
|
||||
{
|
||||
printf("Error disabling cert verify\n");
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Set client certificate.
|
||||
CFArrayRef certificates = CFArrayCreate(NULL, (const void **)&identity, 1, NULL);
|
||||
result = SSLSetCertificate(context, certificates);
|
||||
if (result)
|
||||
{
|
||||
printf("Error setting the client certificate\n");
|
||||
CFRelease(certificates);
|
||||
return NO;
|
||||
}
|
||||
|
||||
CFRelease(certificates);
|
||||
|
||||
// Perform SSL handshake.
|
||||
do {result = SSLHandshake(context);} while(result == errSSLWouldBlock);
|
||||
|
||||
// Convert string into device token data.
|
||||
NSMutableData *deviceToken = [NSMutableData data];
|
||||
unsigned value;
|
||||
NSScanner *scanner = [NSScanner scannerWithString:self.deviceTokenID];
|
||||
while(![scanner isAtEnd]) {
|
||||
[scanner scanHexInt:&value];
|
||||
value = htonl(value);
|
||||
[deviceToken appendBytes:&value length:sizeof(value)];
|
||||
}
|
||||
|
||||
// Create C input variables.
|
||||
char *deviceTokenBinary = (char *)[deviceToken bytes];
|
||||
char *payloadBinary = (char *)[payload UTF8String];
|
||||
size_t payloadLength = strlen(payloadBinary);
|
||||
|
||||
// Prepare message
|
||||
uint8_t command = 0;
|
||||
char message[293];
|
||||
char *pointer = message;
|
||||
uint16_t networkTokenLength = htons(32);
|
||||
uint16_t networkPayloadLength = htons(payloadLength);
|
||||
|
||||
// Compose message.
|
||||
memcpy(pointer, &command, sizeof(uint8_t));
|
||||
pointer += sizeof(uint8_t);
|
||||
memcpy(pointer, &networkTokenLength, sizeof(uint16_t));
|
||||
pointer += sizeof(uint16_t);
|
||||
memcpy(pointer, deviceTokenBinary, 32);
|
||||
pointer += 32;
|
||||
memcpy(pointer, &networkPayloadLength, sizeof(uint16_t));
|
||||
pointer += sizeof(uint16_t);
|
||||
memcpy(pointer, payloadBinary, payloadLength);
|
||||
pointer += payloadLength;
|
||||
|
||||
// Send message over SSL.
|
||||
size_t processed = 0;
|
||||
result = SSLWrite(context, &message, (pointer - message), &processed);
|
||||
if (result)
|
||||
{
|
||||
printf("Error sending message via SSL.\n");
|
||||
return NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Message sent.\n");
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *) fetchFeedback
|
||||
{
|
||||
otSocket socket;
|
||||
SSLContextRef context;
|
||||
SecKeychainRef keychain;
|
||||
SecIdentityRef identity;
|
||||
SecCertificateRef certificate;
|
||||
OSStatus result;
|
||||
|
||||
// Ensure device token
|
||||
if (!self.deviceTokenID)
|
||||
{
|
||||
printf("Error: Device Token is nil\n");
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Ensure certificate
|
||||
if (!self.certificateData)
|
||||
{
|
||||
printf("Error: Certificate Data is nil\n");
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Establish connection to server.
|
||||
PeerSpec peer;
|
||||
if (self.useSandboxServer)
|
||||
{
|
||||
printf("Recovering feedback via sandbox\n");
|
||||
result = MakeServerConnection("feedback.sandbox.push.apple.com", 2196, &socket, &peer);
|
||||
}
|
||||
else
|
||||
result = MakeServerConnection("feedback.push.apple.com", 2196, &socket, &peer);
|
||||
if (result)
|
||||
{
|
||||
printf("Error creating server connection\n");
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Create new SSL context.
|
||||
result = SSLNewContext(false, &context);
|
||||
if (result)
|
||||
{
|
||||
printf("Error creating SSL context\n");
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Set callback functions for SSL context.
|
||||
result = SSLSetIOFuncs(context, SocketRead, SocketWrite);
|
||||
if (result)
|
||||
{
|
||||
printf("Error setting SSL context callback functions\n");
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Set SSL context connection.
|
||||
result = SSLSetConnection(context, socket);
|
||||
if (result)
|
||||
{
|
||||
printf("Error setting the SSL context connection\n");
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Set server domain name.
|
||||
result = SSLSetPeerDomainName(context, "gateway.sandbox.push.apple.com", 30);
|
||||
if (result)
|
||||
{
|
||||
printf("Error setting the server domain name\n");
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Open keychain.
|
||||
result = SecKeychainCopyDefault(&keychain);
|
||||
if (result)
|
||||
{
|
||||
printf("Error accessing keychain\n");
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Create certificate from data
|
||||
CFDataRef data = (__bridge CFDataRef) self.certificateData;
|
||||
certificate = SecCertificateCreateWithData(kCFAllocatorDefault, data);
|
||||
if (!certificate)
|
||||
{
|
||||
printf("Error creating certificate from data\n");
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Create identity.
|
||||
result = SecIdentityCreateWithCertificate(keychain, certificate, &identity);
|
||||
if (result)
|
||||
{
|
||||
printf("Error creating identity from certificate\n");
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Disable Verify
|
||||
result = SSLSetEnableCertVerify(context, NO);
|
||||
if (result)
|
||||
{
|
||||
printf("Error disabling cert verify\n");
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Set client certificate.
|
||||
CFArrayRef certificates = CFArrayCreate(NULL, (const void **)&identity, 1, NULL);
|
||||
result = SSLSetCertificate(context, certificates);
|
||||
if (result)
|
||||
{
|
||||
printf("Error setting the client certificate\n");
|
||||
CFRelease(certificates);
|
||||
return nil;
|
||||
}
|
||||
CFRelease(certificates);
|
||||
|
||||
// Perform SSL handshake.
|
||||
do {result = SSLHandshake(context);} while(result == errSSLWouldBlock);
|
||||
if (result)
|
||||
{
|
||||
cssmPerror("Error", result);
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSMutableArray *results = [NSMutableArray array];
|
||||
|
||||
// 4 big endian bytes for time_t
|
||||
// 2 big endian bytes for token length (always 0, 32)
|
||||
// 32 bytes for device token
|
||||
|
||||
// Retrieve message from SSL.
|
||||
size_t processed = 0;
|
||||
char buffer[38];
|
||||
do
|
||||
{
|
||||
result = SSLRead(context, buffer, 38, &processed);
|
||||
if (result) break;
|
||||
|
||||
// Recover Date
|
||||
char *b = buffer;
|
||||
NSTimeInterval ti = ((unsigned char)b[0] << 24) + ((unsigned char)b[1] << 16) + ((unsigned char)b[2] << 8) + (unsigned char)b[3];
|
||||
NSDate *date = [NSDate dateWithTimeIntervalSince1970:ti];
|
||||
|
||||
// Recover Device ID
|
||||
NSMutableString *deviceID = [NSMutableString string];
|
||||
b += 6;
|
||||
for (int i = 0; i < 32; i++) [deviceID appendFormat:@"%02x", (unsigned char)b[i]];
|
||||
|
||||
// Add dictionary to results
|
||||
[results addObject:@{deviceID: date}];
|
||||
|
||||
} while (processed > 0);
|
||||
|
||||
return results;
|
||||
}
|
||||
@end
|
||||
444
C13 - Push/02 - pushutil/pushutil/ioSock.c
Normal file
444
C13 - Push/02 - pushutil/pushutil/ioSock.c
Normal file
@@ -0,0 +1,444 @@
|
||||
/*
|
||||
File: ioSock.h
|
||||
|
||||
Contains: SecureTransport sample I/O module, X sockets version
|
||||
|
||||
Copyright: © Copyright 2002 Apple Computer, Inc. All rights reserved.
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
|
||||
("Apple") in consideration of your agreement to the following terms, and your
|
||||
use, installation, modification or redistribution of this Apple software
|
||||
constitutes acceptance of these terms. If you do not agree with these terms,
|
||||
please do not use, install, modify or redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and subject
|
||||
to these terms, Apple grants you a personal, non-exclusive license, under Apple's
|
||||
copyrights in this original Apple software (the "Apple Software"), to use,
|
||||
reproduce, modify and redistribute the Apple Software, with or without
|
||||
modifications, in source and/or binary forms; provided that if you redistribute
|
||||
the Apple Software in its entirety and without modifications, you must retain
|
||||
this notice and the following text and disclaimers in all such redistributions of
|
||||
the Apple Software. Neither the name, trademarks, service marks or logos of
|
||||
Apple Computer, Inc. may be used to endorse or promote products derived from the
|
||||
Apple Software without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or implied,
|
||||
are granted by Apple herein, including but not limited to any patent rights that
|
||||
may be infringed by your derivative works or by other works in which the Apple
|
||||
Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
|
||||
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
|
||||
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
|
||||
COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
|
||||
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
|
||||
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Change History (most recent first):
|
||||
11/4/02 1.0d1
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "ioSock.h"
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
|
||||
#include <time.h>
|
||||
#include <strings.h>
|
||||
|
||||
/* debugging for this module */
|
||||
#define SSL_OT_DEBUG 1
|
||||
|
||||
/* log errors to stdout */
|
||||
#define SSL_OT_ERRLOG 1
|
||||
|
||||
/* trace all low-level network I/O */
|
||||
#define SSL_OT_IO_TRACE 0
|
||||
|
||||
/* if SSL_OT_IO_TRACE, only log non-zero length transfers */
|
||||
#define SSL_OT_IO_TRACE_NZ 1
|
||||
|
||||
/* pause after each I/O (only meaningful if SSL_OT_IO_TRACE == 1) */
|
||||
#define SSL_OT_IO_PAUSE 0
|
||||
|
||||
/* print a stream of dots while I/O pending */
|
||||
#define SSL_OT_DOT 1
|
||||
|
||||
/* dump some bytes of each I/O (only meaningful if SSL_OT_IO_TRACE == 1) */
|
||||
#define SSL_OT_IO_DUMP 0
|
||||
#define SSL_OT_IO_DUMP_SIZE 256
|
||||
|
||||
/* general, not-too-verbose debugging */
|
||||
#if SSL_OT_DEBUG
|
||||
#define dprintf(s) printf s
|
||||
#else
|
||||
#define dprintf(s)
|
||||
#endif
|
||||
|
||||
/* errors --> stdout */
|
||||
#if SSL_OT_ERRLOG
|
||||
#define eprintf(s) printf s
|
||||
#else
|
||||
#define eprintf(s)
|
||||
#endif
|
||||
|
||||
/* enable nonblocking I/O - maybe should be an arg to MakeServerConnection() */
|
||||
#define NON_BLOCKING 0
|
||||
|
||||
/* trace completion of every r/w */
|
||||
#if SSL_OT_IO_TRACE
|
||||
static void tprintf(
|
||||
const char *str,
|
||||
UInt32 req,
|
||||
UInt32 act,
|
||||
const UInt8 *buf)
|
||||
{
|
||||
#if SSL_OT_IO_TRACE_NZ
|
||||
if(act == 0) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
printf("%s(%d): moved (%d) bytes\n", str, req, act);
|
||||
#if SSL_OT_IO_DUMP
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<act; i++) {
|
||||
printf("%02X ", buf[i]);
|
||||
if(i >= (SSL_OT_IO_DUMP_SIZE - 1)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
#if SSL_OT_IO_PAUSE
|
||||
{
|
||||
char instr[20];
|
||||
printf("CR to continue: ");
|
||||
gets(instr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
#define tprintf(str, req, act, buf)
|
||||
#endif /* SSL_OT_IO_TRACE */
|
||||
|
||||
/*
|
||||
* If SSL_OT_DOT, output a '.' every so often while waiting for
|
||||
* connection. This gives user a chance to do something else with the
|
||||
* UI.
|
||||
*/
|
||||
|
||||
#if SSL_OT_DOT
|
||||
|
||||
static time_t lastTime = (time_t)0;
|
||||
#define TIME_INTERVAL 3
|
||||
|
||||
static void outputDot()
|
||||
{
|
||||
time_t thisTime = time(0);
|
||||
|
||||
if((thisTime - lastTime) >= TIME_INTERVAL) {
|
||||
printf("."); fflush(stdout);
|
||||
lastTime = thisTime;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define outputDot()
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Connect to server.
|
||||
*/
|
||||
OSStatus MakeServerConnection(
|
||||
const char *hostName,
|
||||
int port,
|
||||
otSocket *socketNo, // RETURNED
|
||||
PeerSpec *peer) // RETURNED
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
struct hostent *ent;
|
||||
struct in_addr host;
|
||||
int sock = 0;
|
||||
|
||||
*socketNo = NULL;
|
||||
if (hostName[0] >= '0' && hostName[0] <= '9')
|
||||
{
|
||||
host.s_addr = inet_addr(hostName);
|
||||
}
|
||||
else
|
||||
{ ent = gethostbyname(hostName);
|
||||
if (!ent)
|
||||
{ printf("gethostbyname failed\n");
|
||||
return ioErr;
|
||||
}
|
||||
memcpy(&host, ent->h_addr, sizeof(struct in_addr));
|
||||
}
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
addr.sin_addr = host;
|
||||
addr.sin_port = htons((u_short)port);
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
if (connect(sock, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) != 0)
|
||||
{ printf("connect returned error\n");
|
||||
return ioErr;
|
||||
}
|
||||
|
||||
#if NON_BLOCKING
|
||||
/* OK to do this after connect? */
|
||||
{
|
||||
int rtn = fcntl(sock, F_SETFL, O_NONBLOCK);
|
||||
if(rtn == -1) {
|
||||
perror("fctnl(O_NONBLOCK)");
|
||||
return ioErr;
|
||||
}
|
||||
}
|
||||
#endif /* NON_BLOCKING*/
|
||||
|
||||
peer->ipAddr = addr.sin_addr.s_addr;
|
||||
peer->port = htons((u_short)port);
|
||||
*socketNo = (otSocket)sock;
|
||||
return noErr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up an otSocket to listen for client connections. Call once, then
|
||||
* use multiple AcceptClientConnection calls.
|
||||
*/
|
||||
OSStatus ListenForClients(
|
||||
int port,
|
||||
otSocket *socketNo) // RETURNED
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
struct hostent *ent;
|
||||
int len;
|
||||
int sock;
|
||||
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(sock < 1) {
|
||||
perror("socket");
|
||||
return ioErr;
|
||||
}
|
||||
|
||||
ent = gethostbyname("localhost");
|
||||
if (!ent) {
|
||||
perror("gethostbyname");
|
||||
return ioErr;
|
||||
}
|
||||
memcpy(&addr.sin_addr, ent->h_addr, sizeof(struct in_addr));
|
||||
|
||||
addr.sin_port = htons((u_short)port);
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
addr.sin_family = AF_INET;
|
||||
len = sizeof(struct sockaddr_in);
|
||||
if (bind(sock, (struct sockaddr *) &addr, len)) {
|
||||
perror("bind");
|
||||
return ioErr;
|
||||
}
|
||||
if (listen(sock, 1)) {
|
||||
perror("listen");
|
||||
return ioErr;
|
||||
}
|
||||
*socketNo = (otSocket)sock;
|
||||
return noErr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Accept a client connection.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Currently we always get back a different peer port number on successive
|
||||
* connections, no matter what the client is doing. To test for resumable
|
||||
* session support, force peer port = 0.
|
||||
*/
|
||||
#define FORCE_ACCEPT_PEER_PORT_ZERO 1
|
||||
|
||||
OSStatus AcceptClientConnection(
|
||||
otSocket listenSock, // obtained from ListenForClients
|
||||
otSocket *acceptSock, // RETURNED
|
||||
PeerSpec *peer) // RETURNED
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
int sock;
|
||||
uint len;
|
||||
|
||||
len = sizeof(struct sockaddr_in);
|
||||
sock = accept((int)listenSock, (struct sockaddr *) &addr, &len);
|
||||
if (sock < 0) {
|
||||
perror("accept");
|
||||
return ioErr;
|
||||
}
|
||||
*acceptSock = (otSocket)sock;
|
||||
peer->ipAddr = addr.sin_addr.s_addr;
|
||||
#if FORCE_ACCEPT_PEER_PORT_ZERO
|
||||
peer->port = 0;
|
||||
#else
|
||||
peer->port = ntohs(addr.sin_port);
|
||||
#endif
|
||||
return noErr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Shut down a connection.
|
||||
*/
|
||||
void endpointShutdown(
|
||||
otSocket socket)
|
||||
{
|
||||
close((int)socket);
|
||||
}
|
||||
|
||||
/*
|
||||
* R/W. Called out from SSL.
|
||||
*/
|
||||
OSStatus SocketRead(
|
||||
SSLConnectionRef connection,
|
||||
void *data, /* owned by
|
||||
* caller, data
|
||||
* RETURNED */
|
||||
size_t *dataLength) /* IN/OUT */
|
||||
{
|
||||
UInt32 bytesToGo = (UInt32) *dataLength;
|
||||
UInt32 initLen = bytesToGo;
|
||||
UInt8 *currData = (UInt8 *)data;
|
||||
int sock = (int)connection;
|
||||
OSStatus rtn = noErr;
|
||||
UInt32 bytesRead = 0;
|
||||
int rrtn;
|
||||
|
||||
*dataLength = 0;
|
||||
|
||||
for(;;) {
|
||||
// bytesRead = 0;
|
||||
rrtn = (int) read(sock, currData, bytesToGo);
|
||||
if (rrtn <= 0) {
|
||||
/* this is guesswork... */
|
||||
int theErr = errno;
|
||||
dprintf(("SocketRead: read(%d) error %d\n", (int)bytesToGo, theErr));
|
||||
#if !NON_BLOCKING
|
||||
if((rrtn == 0) && (theErr == 0)) {
|
||||
/* try fix for iSync */
|
||||
rtn = errSSLClosedGraceful;
|
||||
//rtn = errSSLClosedAbort;
|
||||
}
|
||||
else /* do the switch */
|
||||
#endif
|
||||
switch(theErr) {
|
||||
case ENOENT:
|
||||
/* connection closed */
|
||||
rtn = errSSLClosedGraceful;
|
||||
break;
|
||||
case ECONNRESET:
|
||||
rtn = errSSLClosedAbort;
|
||||
break;
|
||||
#if NON_BLOCKING
|
||||
case EAGAIN:
|
||||
#else
|
||||
case 0: /* ??? */
|
||||
#endif
|
||||
rtn = errSSLWouldBlock;
|
||||
break;
|
||||
default:
|
||||
dprintf(("SocketRead: read(%d) error %d\n",
|
||||
(int)bytesToGo, theErr));
|
||||
rtn = ioErr;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else {
|
||||
bytesRead = rrtn;
|
||||
}
|
||||
bytesToGo -= bytesRead;
|
||||
currData += bytesRead;
|
||||
|
||||
if(bytesToGo == 0) {
|
||||
/* filled buffer with incoming data, done */
|
||||
break;
|
||||
}
|
||||
}
|
||||
*dataLength = initLen - bytesToGo;
|
||||
tprintf("SocketRead", initLen, *dataLength, (UInt8 *)data);
|
||||
|
||||
#if SSL_OT_DOT || (SSL_OT_DEBUG && !SSL_OT_IO_TRACE)
|
||||
if((rtn == 0) && (*dataLength == 0)) {
|
||||
/* keep UI alive */
|
||||
outputDot();
|
||||
}
|
||||
#endif
|
||||
return rtn;
|
||||
}
|
||||
|
||||
int oneAtATime = 0;
|
||||
|
||||
OSStatus SocketWrite(
|
||||
SSLConnectionRef connection,
|
||||
const void *data,
|
||||
size_t *dataLength) /* IN/OUT */
|
||||
{
|
||||
UInt32 bytesSent = 0;
|
||||
int sock = (int)connection;
|
||||
int length;
|
||||
UInt32 dataLen = (UInt32) *dataLength;
|
||||
const UInt8 *dataPtr = (UInt8 *)data;
|
||||
OSStatus ortn;
|
||||
|
||||
if(oneAtATime && (*dataLength > 1)) {
|
||||
UInt32 i;
|
||||
UInt32 outLen;
|
||||
size_t thisMove;
|
||||
|
||||
outLen = 0;
|
||||
for(i=0; i<dataLen; i++) {
|
||||
thisMove = 1;
|
||||
ortn = SocketWrite(connection, dataPtr, &thisMove);
|
||||
outLen += thisMove;
|
||||
dataPtr++;
|
||||
if(ortn) {
|
||||
return ortn;
|
||||
}
|
||||
}
|
||||
return noErr;
|
||||
}
|
||||
*dataLength = 0;
|
||||
|
||||
do {
|
||||
length = (int) write(sock,
|
||||
(char*)dataPtr + bytesSent,
|
||||
dataLen - bytesSent);
|
||||
} while ((length > 0) &&
|
||||
( (bytesSent += length) < dataLen) );
|
||||
|
||||
if(length <= 0) {
|
||||
if(errno == EAGAIN) {
|
||||
ortn = errSSLWouldBlock;
|
||||
}
|
||||
else {
|
||||
ortn = ioErr;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ortn = noErr;
|
||||
}
|
||||
tprintf("SocketWrite", dataLen, bytesSent, dataPtr);
|
||||
*dataLength = bytesSent;
|
||||
return ortn;
|
||||
}
|
||||
129
C13 - Push/02 - pushutil/pushutil/ioSock.h
Normal file
129
C13 - Push/02 - pushutil/pushutil/ioSock.h
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
File: ioSock.h
|
||||
|
||||
Contains: SecureTransport sample I/O module, X sockets version
|
||||
|
||||
Copyright: © Copyright 2002 Apple Computer, Inc. All rights reserved.
|
||||
|
||||
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
|
||||
("Apple") in consideration of your agreement to the following terms, and your
|
||||
use, installation, modification or redistribution of this Apple software
|
||||
constitutes acceptance of these terms. If you do not agree with these terms,
|
||||
please do not use, install, modify or redistribute this Apple software.
|
||||
|
||||
In consideration of your agreement to abide by the following terms, and subject
|
||||
to these terms, Apple grants you a personal, non-exclusive license, under Apple's
|
||||
copyrights in this original Apple software (the "Apple Software"), to use,
|
||||
reproduce, modify and redistribute the Apple Software, with or without
|
||||
modifications, in source and/or binary forms; provided that if you redistribute
|
||||
the Apple Software in its entirety and without modifications, you must retain
|
||||
this notice and the following text and disclaimers in all such redistributions of
|
||||
the Apple Software. Neither the name, trademarks, service marks or logos of
|
||||
Apple Computer, Inc. may be used to endorse or promote products derived from the
|
||||
Apple Software without specific prior written permission from Apple. Except as
|
||||
expressly stated in this notice, no other rights or licenses, express or implied,
|
||||
are granted by Apple herein, including but not limited to any patent rights that
|
||||
may be infringed by your derivative works or by other works in which the Apple
|
||||
Software may be incorporated.
|
||||
|
||||
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
|
||||
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
|
||||
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
|
||||
COMBINATION WITH YOUR PRODUCTS.
|
||||
|
||||
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
|
||||
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
|
||||
(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Change History (most recent first):
|
||||
11/4/02 1.0d1
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _IO_SOCK_H_
|
||||
#define _IO_SOCK_H_
|
||||
|
||||
#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h>
|
||||
#include <Security/SecureTransport.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Opaque reference to an Open Transport connection.
|
||||
*/
|
||||
typedef void *otSocket;
|
||||
|
||||
/*
|
||||
* info about a peer returned from MakeServerConnection() and
|
||||
* AcceptClientConnection().
|
||||
*/
|
||||
typedef struct
|
||||
{ UInt32 ipAddr;
|
||||
int port;
|
||||
} PeerSpec;
|
||||
|
||||
/*
|
||||
* Ont-time only init.
|
||||
*/
|
||||
void initSslOt();
|
||||
|
||||
/*
|
||||
* Connect to server.
|
||||
*/
|
||||
extern OSStatus MakeServerConnection(
|
||||
const char *hostName,
|
||||
int port,
|
||||
otSocket *socketNo, // RETURNED
|
||||
PeerSpec *peer); // RETURNED
|
||||
|
||||
/*
|
||||
* Set up an otSocket to listen for client connections. Call once, then
|
||||
* use multiple AcceptClientConnection calls.
|
||||
*/
|
||||
OSStatus ListenForClients(
|
||||
int port,
|
||||
otSocket *socketNo); // RETURNED
|
||||
|
||||
/*
|
||||
* Accept a client connection. Call endpointShutdown() for each successful;
|
||||
* return from this function.
|
||||
*/
|
||||
OSStatus AcceptClientConnection(
|
||||
otSocket listenSock, // obtained from ListenForClients
|
||||
otSocket *acceptSock, // RETURNED
|
||||
PeerSpec *peer); // RETURNED
|
||||
|
||||
/*
|
||||
* Shut down a connection.
|
||||
*/
|
||||
void endpointShutdown(
|
||||
otSocket socket);
|
||||
|
||||
/*
|
||||
* R/W. Called out from SSL.
|
||||
*/
|
||||
OSStatus SocketRead(
|
||||
SSLConnectionRef connection,
|
||||
void *data, /* owned by
|
||||
* caller, data
|
||||
* RETURNED */
|
||||
size_t *dataLength); /* IN/OUT */
|
||||
|
||||
OSStatus SocketWrite(
|
||||
SSLConnectionRef connection,
|
||||
const void *data,
|
||||
size_t *dataLength); /* IN/OUT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _IO_SOCK_H_ */
|
||||
516
C13 - Push/02 - pushutil/pushutil/main.m
Normal file
516
C13 - Push/02 - pushutil/pushutil/main.m
Normal file
@@ -0,0 +1,516 @@
|
||||
//
|
||||
// main.m
|
||||
// pushutil
|
||||
//
|
||||
// Created by Erica Sadun on 9/19/11.
|
||||
// Copyright (c) 2011 Up To No Good, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "APNSHelper.h"
|
||||
void usage(void);
|
||||
NSString *workingDir(void);
|
||||
NSString *deviceFile(void);
|
||||
NSString *cert(void);
|
||||
NSData *apnsCert(void);
|
||||
void checkCert(void);
|
||||
|
||||
void usage()
|
||||
{
|
||||
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
printf("Usage: pushutil options\n");
|
||||
printf("-help Print this usage message\n");
|
||||
printf("-cwd Use the current directory\n");
|
||||
printf("-pwd Print the active directory\n");
|
||||
printf("-devices List the available devices\n");
|
||||
printf("-add name Add a device name (one per execution)\n");
|
||||
printf("-token devicetoken Use with -add for device token\n");
|
||||
printf("-remove name Remove a device\n");
|
||||
printf("-use name Set this device as default\n");
|
||||
printf("-badge number Badge the application\n");
|
||||
printf("-sound soundfile Play this sound\n");
|
||||
printf("-msg message Set the alert message\n");
|
||||
printf("-okay Use one OK button on the alert\n");
|
||||
printf("-button text Use custom button text\n");
|
||||
printf("-feedback Request feedback report\n");
|
||||
printf("-sandbox Use the sandbox (not the production) server\n");
|
||||
printf("Note: This utility does not support custom payload entries at this time\n");
|
||||
}
|
||||
|
||||
// Return the current working directory for the utility.
|
||||
// This dir stores the .cer and .devices files. It need not be the folder
|
||||
// from which this utility is run
|
||||
NSString *workingDir()
|
||||
{
|
||||
return [[NSUserDefaults standardUserDefaults] objectForKey:@"cwd"];
|
||||
}
|
||||
|
||||
// Attempt to retrieve the device file path from the cwd.
|
||||
// If one does not exist, it creates one.
|
||||
NSString *deviceFile()
|
||||
{
|
||||
NSString *cwd = workingDir();
|
||||
if (!cwd) return nil;
|
||||
|
||||
NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:cwd error:nil];
|
||||
if (!contents) return nil;
|
||||
|
||||
NSArray *dfiles = [contents pathsMatchingExtensions:@[@"devices"]];
|
||||
|
||||
if (![dfiles count])
|
||||
{
|
||||
NSDictionary *dict = @{};
|
||||
NSString *path = [cwd stringByAppendingPathComponent:@"apns.devices"];
|
||||
[dict writeToFile:path atomically:YES];
|
||||
return path;
|
||||
}
|
||||
|
||||
return [cwd stringByAppendingPathComponent:[dfiles lastObject]];
|
||||
}
|
||||
|
||||
// Return the file name (without path) for the certificate
|
||||
NSString *cert()
|
||||
{
|
||||
NSString *cwd = workingDir();
|
||||
if (!cwd) return nil;
|
||||
|
||||
NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:cwd error:nil];
|
||||
if (!contents) return nil;
|
||||
|
||||
NSArray *certs = [contents pathsMatchingExtensions:@[@"cer"]];
|
||||
if (!certs.count) return nil;
|
||||
|
||||
return [certs lastObject];
|
||||
}
|
||||
|
||||
// Return the apns certificate data, which must be stored in the working directory
|
||||
NSData *apnsCert()
|
||||
{
|
||||
NSString *dcert = cert();
|
||||
if (!dcert) return nil;
|
||||
|
||||
NSString *path = [workingDir() stringByAppendingPathComponent:dcert];
|
||||
return [NSData dataWithContentsOfFile:path];
|
||||
}
|
||||
|
||||
// Check whether a .cer file is located in the working directory or not
|
||||
void checkCert()
|
||||
{
|
||||
NSString *cer = cert();
|
||||
if (!cer)
|
||||
printf("Warning: No certificates found in the working directory\n");
|
||||
else
|
||||
printf("The default certificate is %s\n", [cer UTF8String]);
|
||||
}
|
||||
|
||||
int main (int argc, const char * argv[])
|
||||
{
|
||||
if (argc == 1)
|
||||
{
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@autoreleasepool {
|
||||
// Gather command line arguments
|
||||
NSArray *args = [[NSProcessInfo processInfo] arguments];
|
||||
NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF beginswith '-'"];
|
||||
NSArray *dashedArgs = [args filteredArrayUsingPredicate:pred];
|
||||
|
||||
// Prepare the main, payload, and alert dictionaries
|
||||
NSMutableDictionary *mainDict = [NSMutableDictionary dictionary];
|
||||
NSMutableDictionary *payloadDict = [NSMutableDictionary dictionary];
|
||||
NSMutableDictionary *alertDict = [NSMutableDictionary dictionary];
|
||||
payloadDict[@"alert"] = alertDict;
|
||||
mainDict[@"aps"] = payloadDict;
|
||||
|
||||
// Scan for device adds
|
||||
NSString *deviceName = nil;
|
||||
NSString *token = nil;
|
||||
|
||||
for (NSString *darg in dashedArgs)
|
||||
{
|
||||
if (([darg caseInsensitiveCompare:@"-help"] == NSOrderedSame) ||
|
||||
([darg caseInsensitiveCompare:@"-usage"] == NSOrderedSame))
|
||||
{
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ([darg caseInsensitiveCompare:@"-badge"] == NSOrderedSame)
|
||||
{
|
||||
NSString *badge = [[NSUserDefaults standardUserDefaults] objectForKey:@"badge"];
|
||||
if (!badge)
|
||||
{
|
||||
fprintf(stderr, "Error: Supply badge number with -badge\n");
|
||||
continue;
|
||||
}
|
||||
payloadDict[@"badge"] = @([badge intValue]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (([darg caseInsensitiveCompare:@"-sound"] == NSOrderedSame) ||
|
||||
([darg caseInsensitiveCompare:@"-snd"] == NSOrderedSame))
|
||||
{
|
||||
NSString *sound = [[NSUserDefaults standardUserDefaults] objectForKey:@"sound"];
|
||||
if (!sound) sound = [[NSUserDefaults standardUserDefaults] objectForKey:@"snd"];
|
||||
if (!sound)
|
||||
{
|
||||
fprintf(stderr, "Error: Supply file name with -sound\n");
|
||||
continue;
|
||||
}
|
||||
payloadDict[@"sound"] = sound;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (([darg caseInsensitiveCompare:@"-okay"] == NSOrderedSame) ||
|
||||
([darg caseInsensitiveCompare:@"-ok"] == NSOrderedSame))
|
||||
{
|
||||
alertDict[@"action-loc-key"] = [NSNull null];
|
||||
continue;
|
||||
}
|
||||
|
||||
if ([darg caseInsensitiveCompare:@"-button"] == NSOrderedSame)
|
||||
{
|
||||
NSString *button = [[NSUserDefaults standardUserDefaults] objectForKey:@"button"];
|
||||
if (!button)
|
||||
{
|
||||
fprintf(stderr, "Error: Supply text with -button\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
alertDict[@"action-loc-key"] = button;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (([darg caseInsensitiveCompare:@"-msg"] == NSOrderedSame) ||
|
||||
([darg caseInsensitiveCompare:@"-message"] == NSOrderedSame))
|
||||
{
|
||||
NSString *msg = [[NSUserDefaults standardUserDefaults] objectForKey:@"msg"];
|
||||
if (!msg) msg = [[NSUserDefaults standardUserDefaults] objectForKey:@"message"];
|
||||
if (!msg)
|
||||
{
|
||||
fprintf(stderr, "Error: Supply text with -msg\n");
|
||||
continue;
|
||||
}
|
||||
alertDict[@"body"] = msg;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (([darg caseInsensitiveCompare:@"-add"] == NSOrderedSame) ||
|
||||
([darg caseInsensitiveCompare:@"-device"] == NSOrderedSame))
|
||||
{
|
||||
deviceName = [[NSUserDefaults standardUserDefaults] objectForKey:@"add"];
|
||||
if (!deviceName) deviceName = [[NSUserDefaults standardUserDefaults] objectForKey:@"device"];
|
||||
if (!deviceName)
|
||||
{
|
||||
fprintf(stderr, "Error: Supply device name with -add\n");
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ([darg caseInsensitiveCompare:@"-token"] == NSOrderedSame)
|
||||
{
|
||||
token = [[NSUserDefaults standardUserDefaults] objectForKey:@"token"];
|
||||
if (!token)
|
||||
{
|
||||
fprintf(stderr, "Error: Supply token id with -token\n");
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ([darg caseInsensitiveCompare:@"-use"] == NSOrderedSame)
|
||||
{
|
||||
NSString *use = [[NSUserDefaults standardUserDefaults] objectForKey:@"use"];
|
||||
if (!use)
|
||||
{
|
||||
fprintf(stderr, "Error: supply a device name with -use\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfFile:deviceFile()];
|
||||
if (!dict)
|
||||
{
|
||||
fprintf(stderr, "Error: token not found for device %s.\n", [use UTF8String]);
|
||||
continue;
|
||||
}
|
||||
|
||||
NSString *usetoken = dict[[use uppercaseString]];
|
||||
if (!usetoken)
|
||||
{
|
||||
fprintf(stderr, "Error: token not found for device %s.\n", [use UTF8String]);
|
||||
continue;
|
||||
}
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setObject:usetoken forKey:@"defaultToken"];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
printf("Default token set for device %s\n", [use UTF8String]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ([darg caseInsensitiveCompare:@"-sandbox"] == NSOrderedSame)
|
||||
{
|
||||
[APNSHelper sharedInstance].useSandboxServer = YES;
|
||||
printf("Will use sandbox (not production) sever.\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ((token && !deviceName) || (deviceName && !token))
|
||||
{
|
||||
fprintf(stderr, "Error: Supply both a device name with -add and a device token with -token\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (token && deviceName)
|
||||
{
|
||||
if (!workingDir())
|
||||
{
|
||||
fprintf(stderr, "Error: You must set up a working directory before adding devices\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if ([token length] != 71)
|
||||
{
|
||||
fprintf(stderr, "Error: Supply the token using the following format\n");
|
||||
printf("-token \"xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx\"\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfFile:deviceFile()];
|
||||
dict[[deviceName uppercaseString]] = token;
|
||||
[dict writeToFile:deviceFile() atomically:YES];
|
||||
printf("Added %s to device list\n", [deviceName UTF8String]);
|
||||
}
|
||||
|
||||
// Scan for actions
|
||||
for (NSString *darg in dashedArgs)
|
||||
{
|
||||
if ([darg caseInsensitiveCompare:@"-cwd"] == NSOrderedSame)
|
||||
{
|
||||
char wd[256];
|
||||
getwd(wd);
|
||||
|
||||
NSString *cwd = @(wd);
|
||||
[[NSUserDefaults standardUserDefaults] setObject:cwd forKey:@"cwd"];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
printf("Updated working directory:\n %s\n", [cwd UTF8String]);
|
||||
checkCert();
|
||||
continue;
|
||||
}
|
||||
|
||||
if ([darg caseInsensitiveCompare:@"-pwd"] == NSOrderedSame)
|
||||
{
|
||||
NSString *cwd = workingDir();
|
||||
if (!cwd)
|
||||
printf("The working directory has not yet been set. Use -cwd to set it here.\n");
|
||||
else
|
||||
printf("Working directory: %s\n", [cwd UTF8String]);
|
||||
checkCert();
|
||||
continue;
|
||||
}
|
||||
|
||||
if ([darg caseInsensitiveCompare:@"-clearwd"] == NSOrderedSame) // undocumented
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"cwd"];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
printf("Cleared working directory\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if ([darg caseInsensitiveCompare:@"-cleartoken"] == NSOrderedSame) // undocumented
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"defaultToken"];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
printf("Cleared default token\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if ([darg caseInsensitiveCompare:@"-devices"] == NSOrderedSame)
|
||||
{
|
||||
if (!workingDir())
|
||||
{
|
||||
printf("You must set up a working directory before checking for devices\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
NSString *dfile = deviceFile();
|
||||
if (!dfile)
|
||||
{
|
||||
printf("No devices have been set up yet\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:dfile];
|
||||
if (!dict)
|
||||
printf("No devices have been set up yet\n");
|
||||
else
|
||||
{
|
||||
printf("There are %d available devices\n", (int) dict.allKeys.count);
|
||||
for (NSString *key in [dict allKeys])
|
||||
printf(" %s\n", [key UTF8String]);
|
||||
}
|
||||
|
||||
NSString *dtok = [[NSUserDefaults standardUserDefaults] objectForKey:@"defaultToken"];
|
||||
if (!dtok) continue;
|
||||
NSArray *keys = [dict allKeysForObject:dtok];
|
||||
if (keys && ([keys count] > 0)) printf("Default device is %s\n", [[keys lastObject] UTF8String]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ([darg caseInsensitiveCompare:@"-remove"] == NSOrderedSame)
|
||||
{
|
||||
NSString *key = [[NSUserDefaults standardUserDefaults] objectForKey:@"remove"];
|
||||
if (!key)
|
||||
{
|
||||
fprintf(stderr, "Error: Supply a device name to -remove. Use -devices to list.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfFile:deviceFile()];
|
||||
if (!dict)
|
||||
{
|
||||
fprintf(stderr, "Error: device not found\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!dict[key])
|
||||
{
|
||||
fprintf(stderr, "Error: device not found\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
[dict removeObjectForKey:key];
|
||||
[dict writeToFile:deviceFile() atomically:YES];
|
||||
printf("Device %s removed from list.\n", [key UTF8String]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ([darg caseInsensitiveCompare:@"-kvpairs"] == NSOrderedSame) // undocumented
|
||||
{
|
||||
NSString *kvstring = [[NSUserDefaults standardUserDefaults] objectForKey:@"kvpairs"];
|
||||
NSArray *kvarray = [kvstring componentsSeparatedByString:@" "];
|
||||
for (NSString *item in kvarray)
|
||||
{
|
||||
NSArray *pair = [item componentsSeparatedByString:@":"];
|
||||
if ([pair count] != 2) continue;
|
||||
mainDict[pair[0]] = [pair lastObject];
|
||||
}
|
||||
|
||||
printf("Custom key value pairs added to dictionary\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if ([darg caseInsensitiveCompare:@"-feedback"] == NSOrderedSame)
|
||||
{
|
||||
NSString *dToken = [[NSUserDefaults standardUserDefaults] objectForKey:@"defaultToken"];
|
||||
if (!dToken)
|
||||
{
|
||||
fprintf(stderr, "Error: Device token has not been set.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
NSData *dCert = apnsCert();
|
||||
if (!dCert)
|
||||
{
|
||||
fprintf(stderr, "Error retrieving apns certificate\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
[APNSHelper sharedInstance].deviceTokenID = dToken;
|
||||
[APNSHelper sharedInstance].certificateData = dCert;
|
||||
NSArray *resultsArray = [[APNSHelper sharedInstance] fetchFeedback];
|
||||
|
||||
if (resultsArray.count == 0)
|
||||
{
|
||||
printf("No feedback results at this time.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
NSString *path = [workingDir() stringByAppendingPathComponent:@"feedback.txt"];
|
||||
FILE *fp;
|
||||
if ((fp = fopen([path UTF8String], "a")) == NULL)
|
||||
{
|
||||
printf("Cannot open feedback.txt for output\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
printf("APNS has encountered the following delivery failures:\n\n");
|
||||
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
|
||||
formatter.dateFormat = @"MM/dd/YY h:mm:ss a";
|
||||
|
||||
for (NSDictionary *dict in resultsArray)
|
||||
{
|
||||
NSString *deviceid = [[dict allKeys] lastObject];
|
||||
NSDate *date = dict[deviceid];
|
||||
NSString *timestamp = [formatter stringFromDate:date];
|
||||
fprintf(fp, "%s %s\n", [timestamp UTF8String], [deviceid UTF8String]);
|
||||
printf("TIMESTAMP: %s\n", [timestamp UTF8String]);
|
||||
printf("DEVICE ID: %s\n\n", [deviceid UTF8String]);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
printf("Wrote %d events to feedback.txt\n", (int) resultsArray.count);
|
||||
}
|
||||
|
||||
exit(1); // successful exit
|
||||
}
|
||||
|
||||
if ([darg caseInsensitiveCompare:@"-undoc"] == NSOrderedSame) // undocumented
|
||||
{
|
||||
printf("-undoc print this message\n");
|
||||
printf("-usage synonym for -help\n");
|
||||
printf("-snd synonym for -sound\n");
|
||||
printf("-ok synonym for -okay\n");
|
||||
printf("-message synonym for -msg\n");
|
||||
printf("-device synonym for -add\n");
|
||||
printf("-clearwd clear the current working directory from memory\n");
|
||||
printf("-cleartoken remove the active token setting\n");
|
||||
printf("-kvpairs manually add custom k/v pairs, string-to-string only\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine whether to continue with sending alert
|
||||
|
||||
BOOL goOn = (payloadDict[@"sound"] || payloadDict[@"badge"]);
|
||||
goOn = goOn || alertDict[@"body"];
|
||||
goOn = goOn || ([[mainDict allKeys] count] > 1);
|
||||
if (!goOn)
|
||||
{
|
||||
printf("No message to send.\nDone.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
NSString *dToken = [[NSUserDefaults standardUserDefaults] objectForKey:@"defaultToken"];
|
||||
if (!dToken)
|
||||
{
|
||||
fprintf(stderr, "Error: Device token has not been set.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
NSData *dCert = apnsCert();
|
||||
if (!dCert)
|
||||
{
|
||||
fprintf(stderr, "Error retrieving apns certificate\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
printf("Preparing to send message\n");
|
||||
|
||||
[APNSHelper sharedInstance].deviceTokenID = dToken;
|
||||
[APNSHelper sharedInstance].certificateData = dCert;
|
||||
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:mainDict options:0 error:nil];
|
||||
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
BOOL success = [[APNSHelper sharedInstance] push:jsonString];
|
||||
|
||||
if (success) printf("Done.\n");
|
||||
else fprintf(stderr, "Errors encountered during send.\n");
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
7
C13 - Push/02 - pushutil/pushutil/pushutil-Prefix.pch
Normal file
7
C13 - Push/02 - pushutil/pushutil/pushutil-Prefix.pch
Normal file
@@ -0,0 +1,7 @@
|
||||
//
|
||||
// Prefix header for all source files of the 'pushutil' target in the 'pushutil' project
|
||||
//
|
||||
|
||||
#ifdef __OBJC__
|
||||
#import <Foundation/Foundation.h>
|
||||
#endif
|
||||
Reference in New Issue
Block a user