Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Initial commit

  • Loading branch information...
commit 115ff0cf272ffe32ec25620fb8563769b99e4dc4 0 parents
Andreas Linde authored

Showing 41 changed files with 5,130 additions and 0 deletions. Show diff stats Hide diff stats

  1. 20  .gitignore
  2. 55  Classes/CNSHockeyManager.h
  3. 104  Classes/CNSHockeyManager.m
  4. 57  Classes/CNSHockeyManagerDelegate.h
  5. 123  Classes/CrashReporting/CNSCrashReportManager.h
  6. 593  Classes/CrashReporting/CNSCrashReportManager.m
  7. 29  Classes/CrashReporting/CNSCrashReportManagerDelegate.h
  8. 64  Classes/CrashReporting/CNSCrashReportTextFormatter.h
  9. 512  Classes/CrashReporting/CNSCrashReportTextFormatter.m
  10. 75  Classes/CrashReporting/CNSCrashReportUI.h
  11. 211  Classes/CrashReporting/CNSCrashReportUI.m
  12. 1,228  Classes/CrashReporting/CNSCrashReportUI.nib/designable.nib
  13. BIN  Classes/CrashReporting/CNSCrashReportUI.nib/keyedobjects.nib
  14. 81  LICENSE.txt
  15. 126  README.md
  16. 30  Resources/HockeySDK-Info.plist
  17. 7  Resources/HockeySDK-Prefix.pch
  18. 2  Resources/en.lproj/InfoPlist.strings
  19. 377  Support/HockeySDK.xcodeproj/project.pbxproj
  20. 7  Support/HockeySDK.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  21. 1  Vendor/CrashReporter.framework/CrashReporter
  22. 1  Vendor/CrashReporter.framework/Headers
  23. 1  Vendor/CrashReporter.framework/Resources
  24. BIN  Vendor/CrashReporter.framework/Versions/A/CrashReporter
  25. 229  Vendor/CrashReporter.framework/Versions/A/Headers/CrashReporter.h
  26. 169  Vendor/CrashReporter.framework/Versions/A/Headers/PLCrashReport.h
  27. 53  Vendor/CrashReporter.framework/Versions/A/Headers/PLCrashReportApplicationInfo.h
  28. 90  Vendor/CrashReporter.framework/Versions/A/Headers/PLCrashReportBinaryImageInfo.h
  29. 65  Vendor/CrashReporter.framework/Versions/A/Headers/PLCrashReportExceptionInfo.h
  30. 51  Vendor/CrashReporter.framework/Versions/A/Headers/PLCrashReportFormatter.h
  31. 73  Vendor/CrashReporter.framework/Versions/A/Headers/PLCrashReportMachineInfo.h
  32. 92  Vendor/CrashReporter.framework/Versions/A/Headers/PLCrashReportProcessInfo.h
  33. 74  Vendor/CrashReporter.framework/Versions/A/Headers/PLCrashReportProcessorInfo.h
  34. 60  Vendor/CrashReporter.framework/Versions/A/Headers/PLCrashReportSignalInfo.h
  35. 142  Vendor/CrashReporter.framework/Versions/A/Headers/PLCrashReportSystemInfo.h
  36. 62  Vendor/CrashReporter.framework/Versions/A/Headers/PLCrashReportTextFormatter.h
  37. 130  Vendor/CrashReporter.framework/Versions/A/Headers/PLCrashReportThreadInfo.h
  38. 97  Vendor/CrashReporter.framework/Versions/A/Headers/PLCrashReporter.h
  39. BIN  Vendor/CrashReporter.framework/Versions/A/Resources/English.lproj/InfoPlist.strings
  40. 38  Vendor/CrashReporter.framework/Versions/A/Resources/Info.plist
  41. 1  Vendor/CrashReporter.framework/Versions/Current
20  .gitignore
... ...
@@ -0,0 +1,20 @@
  1
+# Xcode
  2
+build/*
  3
+*.pbxuser
  4
+!default.pbxuser
  5
+*.mode?v3
  6
+!default.mode?v3
  7
+*.perspective
  8
+*.perspectivev3
  9
+!default.perspectivev3
  10
+!default.xcworkspace
  11
+xcuserdata
  12
+profile
  13
+*.moved-aside
  14
+
  15
+# osx noise
  16
+.DS_Store
  17
+*.ipa
  18
+*.swp
  19
+*~.nib
  20
+profile
55  Classes/CNSHockeyManager.h
... ...
@@ -0,0 +1,55 @@
  1
+//  Copyright 2012 Codenauts UG (haftungsbeschränkt). All rights reserved.
  2
+//  See LICENSE.txt for author information.
  3
+//
  4
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
  5
+//  of this software and associated documentation files (the "Software"), to deal
  6
+//  in the Software without restriction, including without limitation the rights
  7
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8
+//  copies of the Software, and to permit persons to whom the Software is
  9
+//  furnished to do so, subject to the following conditions:
  10
+//
  11
+//  The above copyright notice and this permission notice shall be included in
  12
+//  all copies or substantial portions of the Software.
  13
+//
  14
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20
+//  THE SOFTWARE.
  21
+
  22
+
  23
+#import "CNSHockeyManagerDelegate.h"
  24
+
  25
+@interface CNSHockeyManager : NSObject {
  26
+@private
  27
+  id _delegate;
  28
+  NSString *_appIdentifier;
  29
+  NSString *_companyName;
  30
+  
  31
+  BOOL _loggingEnabled;
  32
+}
  33
+
  34
+#pragma mark - Public Properties
  35
+
  36
+@property (nonatomic, readonly) NSString *appIdentifier;
  37
+
  38
+// Enable debug logging; ONLY ENABLE THIS FOR DEBUGGING!
  39
+//
  40
+// Default: NO
  41
+@property (nonatomic, assign, getter=isLoggingEnabled) BOOL loggingEnabled;
  42
+
  43
+
  44
+#pragma mark - Public Methods
  45
+
  46
+// Returns the shared manager object
  47
++ (CNSHockeyManager *)sharedHockeyManager;
  48
+
  49
+// Configure HockeyApp with a single app identifier and delegate; use this
  50
+// only for debug or beta versions of your app!
  51
+- (void)configureWithIdentifier:(NSString *)newAppIdentifier companyName:(NSString *)newCompanyName delegate:(id)newDelegate;
  52
+
  53
+- (void)configureWithIdentifier:(NSString *)appIdentifier delegate:(id)delegate;
  54
+
  55
+@end
104  Classes/CNSHockeyManager.m
... ...
@@ -0,0 +1,104 @@
  1
+//  Copyright 2012 Codenauts UG (haftungsbeschränkt). All rights reserved.
  2
+//  See LICENSE.txt for author information.
  3
+//
  4
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
  5
+//  of this software and associated documentation files (the "Software"), to deal
  6
+//  in the Software without restriction, including without limitation the rights
  7
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8
+//  copies of the Software, and to permit persons to whom the Software is
  9
+//  furnished to do so, subject to the following conditions:
  10
+//
  11
+//  The above copyright notice and this permission notice shall be included in
  12
+//  all copies or substantial portions of the Software.
  13
+//
  14
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20
+//  THE SOFTWARE.
  21
+
  22
+#import "CNSHockeyManager.h"
  23
+
  24
+#import "CNSCrashReportManager.h"
  25
+#import "CNSCrashReportManagerDelegate.h"
  26
+
  27
+@interface CNSHockeyManager ()
  28
+
  29
+- (void)configureCrashReportManager;
  30
+
  31
+@end
  32
+
  33
+@implementation CNSHockeyManager
  34
+
  35
+@synthesize appIdentifier = _appIdentifier;
  36
+@synthesize loggingEnabled = _loggingEnabled;
  37
+
  38
+#pragma mark - Public Class Methods
  39
+
  40
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_6
  41
++ (CNSHockeyManager *)sharedHockeyManager {   
  42
+  static CNSHockeyManager *sharedInstance = nil;
  43
+  static dispatch_once_t pred;
  44
+  
  45
+  dispatch_once(&pred, ^{
  46
+    sharedInstance = [CNSHockeyManager alloc];
  47
+    sharedInstance = [sharedInstance init];
  48
+  });
  49
+  
  50
+  return sharedInstance;
  51
+}
  52
+#else
  53
++ (CNSHockeyManager *)sharedHockeyManager {
  54
+  static CNSHockeyManager *hockeyManager = nil;
  55
+  
  56
+  if (hockeyManager == nil) {
  57
+    hockeyManager = [[CNSHockeyManager alloc] init];
  58
+  }
  59
+  
  60
+  return hockeyManager;
  61
+}
  62
+#endif
  63
+
  64
+
  65
+- (void)dealloc {
  66
+  [_appIdentifier release], _appIdentifier = nil;
  67
+  _delegate = nil;
  68
+  
  69
+  [super dealloc];
  70
+}
  71
+
  72
+
  73
+#pragma mark - Private Class Methods
  74
+
  75
+
  76
+#pragma mark - Public Instance Methods (Configuration)
  77
+
  78
+- (void)configureWithIdentifier:(NSString *)newAppIdentifier companyName:(NSString *)newCompanyName delegate:(id)newDelegate {
  79
+  _delegate = newDelegate;
  80
+
  81
+  [_appIdentifier release];
  82
+  _appIdentifier = [newAppIdentifier copy];
  83
+
  84
+  [_companyName release];
  85
+  _companyName = [newCompanyName copy];
  86
+
  87
+  [self configureCrashReportManager];
  88
+}
  89
+
  90
+
  91
+- (void)configureWithIdentifier:(NSString *)newAppIdentifier delegate:(id)newDelegate {
  92
+  [self configureWithIdentifier:newAppIdentifier companyName:@"" delegate:newDelegate];
  93
+}
  94
+
  95
+
  96
+#pragma mark - Private Instance Methods
  97
+
  98
+- (void)configureCrashReportManager {
  99
+  [[CNSCrashReportManager sharedCrashReportManager] setAppIdentifier:_appIdentifier];
  100
+  [[CNSCrashReportManager sharedCrashReportManager] setDelegate:_delegate];
  101
+  [[CNSCrashReportManager sharedCrashReportManager] startManager];
  102
+}
  103
+
  104
+@end
57  Classes/CNSHockeyManagerDelegate.h
... ...
@@ -0,0 +1,57 @@
  1
+//
  2
+//  CNSHockeyManagerDelegate.h
  3
+//  HockeySDK
  4
+//
  5
+//  Created by Andreas Linde on 29.03.12.
  6
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
  7
+//
  8
+
  9
+#import <Foundation/Foundation.h>
  10
+
  11
+@protocol CNSHockeyManagerDelegate <NSObject>
  12
+
  13
+@optional
  14
+
  15
+// Invoked when the internet connection is started
  16
+// 
  17
+// Implement to let the delegate enable the activity indicator
  18
+- (void)connectionOpened;
  19
+
  20
+// Invoked when the internet connection is closed
  21
+// 
  22
+// Implement to let the delegate disable the activity indicator
  23
+- (void)connectionClosed;
  24
+
  25
+// Invoked before a crash report will be sent
  26
+// 
  27
+// Return a userid or similar which the crashreport should contain
  28
+// 
  29
+// Maximum length: 255 chars
  30
+// 
  31
+// Default: empty
  32
+- (NSString *)crashReportUserID;
  33
+
  34
+// Invoked before a crash report will be sent
  35
+// 
  36
+// Return contact data, e.g. an email address, for the crash report
  37
+// Maximum length: 255 chars
  38
+// 
  39
+// Default: empty
  40
+-(NSString *)crashReportContact;
  41
+
  42
+// Invoked before a crash report will be sent
  43
+// 
  44
+// Return a the description for the crashreport should contain; the string
  45
+// will automatically be wrapped into <[DATA[ ]]>, so make sure you don't do 
  46
+// that in your string.
  47
+// 
  48
+// Default: empty 
  49
+-(NSString *)crashReportDescription;
  50
+
  51
+// Invoked before the user is asked to send a crash report
  52
+// 
  53
+// Implement to do additional actions, e.g. to make sure to not to ask the 
  54
+// user for an app rating :) 
  55
+- (void)willShowSubmitCrashReportAlert;
  56
+
  57
+@end
123  Classes/CrashReporting/CNSCrashReportManager.h
... ...
@@ -0,0 +1,123 @@
  1
+/*
  2
+ * Author: Andreas Linde <mail@andreaslinde.de>
  3
+ *         Kent Sutherland
  4
+ *
  5
+ * Copyright (c) 2011 Andreas Linde & Kent Sutherland.
  6
+ * All rights reserved.
  7
+ *
  8
+ * Permission is hereby granted, free of charge, to any person
  9
+ * obtaining a copy of this software and associated documentation
  10
+ * files (the "Software"), to deal in the Software without
  11
+ * restriction, including without limitation the rights to use,
  12
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
  13
+ * copies of the Software, and to permit persons to whom the
  14
+ * Software is furnished to do so, subject to the following
  15
+ * conditions:
  16
+ *
  17
+ * The above copyright notice and this permission notice shall be
  18
+ * included in all copies or substantial portions of the Software.
  19
+ *
  20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  22
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  24
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  25
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  26
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  27
+ * OTHER DEALINGS IN THE SOFTWARE.
  28
+ */
  29
+
  30
+#import <Cocoa/Cocoa.h>
  31
+#import "CNSCrashReportManagerDelegate.h"
  32
+
  33
+// flags if the crashlog analyzer is started. since this may theoretically crash we need to track it
  34
+#define kHockeySDKAnalyzerStarted @"HockeySDKCrashReportAnalyzerStarted"
  35
+
  36
+// flags if the QuincyKit is activated at all
  37
+#define kHockeySDKCrashReportActivated @"HockeySDKCrashReportActivated"
  38
+
  39
+// flags if the crashreporter should automatically send crashes without asking the user again
  40
+#define kHockeySDKAutomaticallySendCrashReports @"HockeySDKAutomaticallySendCrashReports"
  41
+
  42
+// stores the set of crashreports that have been approved but aren't sent yet
  43
+#define kHockeySDKApprovedCrashReports @"HockeySDKApprovedCrashReports"
  44
+
  45
+
  46
+typedef enum CrashAlertType {
  47
+  CrashAlertTypeSend = 0,
  48
+  CrashAlertTypeFeedback = 1,
  49
+} CrashAlertType;
  50
+
  51
+typedef enum CrashReportStatus {  
  52
+  CrashReportStatusUnknown = 0,
  53
+  CrashReportStatusAssigned = 1,
  54
+  CrashReportStatusSubmitted = 2,
  55
+  CrashReportStatusAvailable = 3,
  56
+} CrashReportStatus;
  57
+
  58
+typedef enum CrashReportMechanism {
  59
+  CrashReportMechanismPLCrashReporter = 0,
  60
+  CrashReportMechanismMacOSX = 1
  61
+} CrashReportMechanism;
  62
+
  63
+@class CNSCrashReportUI;
  64
+
  65
+@interface CNSCrashReportManager : NSObject
  66
+#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) 
  67
+ <NSXMLParserDelegate>
  68
+#endif
  69
+{
  70
+  NSFileManager *_fileManager;
  71
+
  72
+  BOOL _crashReportActivated;
  73
+  CrashReportMechanism _crashReportMechanism;
  74
+  
  75
+  CrashReportStatus _serverResult;
  76
+  NSInteger         _statusCode;
  77
+    
  78
+  NSMutableString   *_contentOfProperty;
  79
+
  80
+  id<CNSCrashReportManagerDelegate> _delegate;
  81
+
  82
+  NSString   *_appIdentifier;
  83
+  NSString   *_submissionURL;
  84
+  NSString   *_companyName;
  85
+  BOOL       _autoSubmitCrashReport;
  86
+  
  87
+  NSString   *_crashFile;
  88
+  
  89
+  NSMutableArray *_crashFiles;
  90
+  NSString       *_crashesDir;
  91
+  
  92
+  CNSCrashReportUI *_crashReportUI;
  93
+
  94
+  int _analyzerStarted;
  95
+
  96
+}
  97
+
  98
+- (NSString*) modelVersion;
  99
+
  100
++ (CNSCrashReportManager *)sharedCrashReportManager;
  101
+
  102
+// The HockeyApp app identifier (required)
  103
+@property (nonatomic, retain) NSString *appIdentifier;
  104
+
  105
+// submission URL defines where to send the crash reports to (required)
  106
+@property (nonatomic) CrashReportMechanism crashReportMechanism;
  107
+
  108
+// defines the company name to be shown in the crash reporting dialog
  109
+@property (nonatomic, retain) NSString *companyName;
  110
+
  111
+// delegate is required
  112
+@property (nonatomic, assign) id <CNSCrashReportManagerDelegate> delegate;
  113
+
  114
+// if YES, the crash report will be submitted without asking the user
  115
+// if NO, the user will be asked if the crash report can be submitted (default)
  116
+@property (nonatomic, assign, getter=isAutoSubmitCrashReport) BOOL autoSubmitCrashReport;
  117
+
  118
+- (void) startManager;
  119
+
  120
+- (void) cancelReport;
  121
+- (void) sendReportCrash:(NSString*)crashReport crashNotes:(NSString *)crashNotes ;
  122
+
  123
+@end
593  Classes/CrashReporting/CNSCrashReportManager.m
... ...
@@ -0,0 +1,593 @@
  1
+/*
  2
+ * Author: Andreas Linde <mail@andreaslinde.de>
  3
+ *         Kent Sutherland
  4
+ *
  5
+ * Copyright (c) 2011 Andreas Linde & Kent Sutherland.
  6
+ * All rights reserved.
  7
+ *
  8
+ * Permission is hereby granted, free of charge, to any person
  9
+ * obtaining a copy of this software and associated documentation
  10
+ * files (the "Software"), to deal in the Software without
  11
+ * restriction, including without limitation the rights to use,
  12
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
  13
+ * copies of the Software, and to permit persons to whom the
  14
+ * Software is furnished to do so, subject to the following
  15
+ * conditions:
  16
+ *
  17
+ * The above copyright notice and this permission notice shall be
  18
+ * included in all copies or substantial portions of the Software.
  19
+ *
  20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  22
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  24
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  25
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  26
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  27
+ * OTHER DEALINGS IN THE SOFTWARE.
  28
+ */
  29
+
  30
+#import "CNSCrashReportManager.h"
  31
+#import "CNSCrashReportUI.h"
  32
+#import <sys/sysctl.h>
  33
+#import <CrashReporter/CrashReporter.h>
  34
+#import "CNSCrashReportTextFormatter.h"
  35
+
  36
+#define SDK_NAME @"HockeySDK-Mac"
  37
+#define SDK_VERSION @"0.5"
  38
+
  39
+#define CRASHREPORT_MAX_CONSOLE_SIZE 50000
  40
+
  41
+@interface CNSCrashReportManager(private)
  42
+- (NSString *) applicationName;
  43
+- (NSString *) applicationVersionString;
  44
+- (NSString *) applicationVersion;
  45
+
  46
+- (void) handleCrashReport;
  47
+- (BOOL) hasPendingCrashReport;
  48
+- (void)_cleanCrashReports;
  49
+
  50
+- (void) _postXML:(NSString*)xml;
  51
+- (void) searchCrashLogFile:(NSString *)path;
  52
+
  53
+- (void) returnToMainApplication;
  54
+@end
  55
+
  56
+
  57
+@implementation CNSCrashReportManager
  58
+
  59
+@synthesize crashReportMechanism = _crashReportMechanism;
  60
+@synthesize delegate = _delegate;
  61
+@synthesize appIdentifier = _appIdentifier;
  62
+@synthesize companyName = _companyName;
  63
+@synthesize autoSubmitCrashReport = _autoSubmitCrashReport;
  64
+
  65
+#pragma mark - Init
  66
+
  67
++ (CNSCrashReportManager *)sharedCrashReportManager {
  68
+  static CNSCrashReportManager *crashReportManager = nil;
  69
+  
  70
+  if (crashReportManager == nil) {
  71
+    crashReportManager = [[CNSCrashReportManager alloc] init];
  72
+  }
  73
+  
  74
+  return crashReportManager;
  75
+}
  76
+
  77
+- (id) init {
  78
+  if ((self = [super init])) {
  79
+    _crashReportMechanism = CrashReportMechanismPLCrashReporter;
  80
+    _serverResult = CrashReportStatusUnknown;
  81
+    _crashReportUI = nil;
  82
+    _fileManager = [[NSFileManager alloc] init];
  83
+    
  84
+    _submissionURL = @"https://rink.hockeyapp.net/";
  85
+    
  86
+    _crashFile = nil;
  87
+    _crashFiles = nil;
  88
+    
  89
+    self.delegate = nil;
  90
+    self.companyName = @"";
  91
+    
  92
+    NSString *testValue = nil;
  93
+    testValue = [[NSUserDefaults standardUserDefaults] stringForKey:kHockeySDKCrashReportActivated];
  94
+    if (testValue) {
  95
+      _crashReportActivated = [[NSUserDefaults standardUserDefaults] boolForKey:kHockeySDKCrashReportActivated];
  96
+    } else {
  97
+      _crashReportActivated = YES;
  98
+      [[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:YES] forKey:kHockeySDKCrashReportActivated];
  99
+    }
  100
+  }
  101
+  return self;
  102
+}
  103
+
  104
+- (void)dealloc {
  105
+  _delegate = nil;
  106
+
  107
+  [_companyName release]; _companyName = nil;
  108
+
  109
+  [_fileManager release]; _fileManager = nil;
  110
+
  111
+  [_crashFile release]; _crashFile = nil;
  112
+  
  113
+  [_crashFiles release]; _crashFiles = nil;
  114
+  [_crashesDir release]; _crashesDir = nil;
  115
+  
  116
+  [_crashReportUI release]; _crashReportUI= nil;
  117
+  
  118
+  [super dealloc];
  119
+}
  120
+
  121
+
  122
+#pragma mark - Private
  123
+
  124
+- (void)_cleanCrashReports {
  125
+  NSError *error = NULL;
  126
+  
  127
+  for (NSUInteger i=0; i < [_crashFiles count]; i++) {		
  128
+    [_fileManager removeItemAtPath:[_crashFiles objectAtIndex:i] error:&error];
  129
+  }
  130
+  [_crashFiles removeAllObjects];
  131
+  
  132
+  [[NSUserDefaults standardUserDefaults] setObject:nil forKey:kHockeySDKApprovedCrashReports];
  133
+  [[NSUserDefaults standardUserDefaults] synchronize];    
  134
+}
  135
+
  136
+
  137
+- (NSString *) consoleContent {
  138
+  // get the console log
  139
+  NSError* error = nil;
  140
+  NSMutableString *content = [[NSMutableString alloc] initWithString:@""];
  141
+  
  142
+  NSEnumerator *theEnum = [[[NSString stringWithContentsOfFile:@"/private/var/log/system.log" encoding:NSUTF8StringEncoding error:&error] componentsSeparatedByString: @"\n"] objectEnumerator];
  143
+  NSString* currentObject;
  144
+  NSMutableArray* applicationStrings = [NSMutableArray array];
  145
+  
  146
+  NSString* searchString = [[self applicationName] stringByAppendingString:@"["];
  147
+  while ( (currentObject = [theEnum nextObject]) ) {
  148
+    if ([currentObject rangeOfString:searchString].location != NSNotFound)
  149
+      [applicationStrings addObject: currentObject];
  150
+  }
  151
+  
  152
+  NSInteger i;
  153
+  for(i = ((NSInteger)[applicationStrings count])-1; (i>=0 && i>((NSInteger)[applicationStrings count])-100); i--) {
  154
+    [content appendString:[applicationStrings objectAtIndex:i]];
  155
+    [content appendString:@"\n"];
  156
+  }
  157
+  
  158
+  // Now limit the content to CRASHREPORTSENDER_MAX_CONSOLE_SIZE (default: 50kByte)
  159
+  if ([content length] > CRASHREPORT_MAX_CONSOLE_SIZE) {
  160
+    content = (NSMutableString *)[content substringWithRange:NSMakeRange([content length]-CRASHREPORT_MAX_CONSOLE_SIZE-1, CRASHREPORT_MAX_CONSOLE_SIZE)]; 
  161
+  }
  162
+  
  163
+  return [content autorelease];
  164
+}
  165
+
  166
+
  167
+- (NSString *) modelVersion {
  168
+  NSString * modelString  = nil;
  169
+  int        modelInfo[2] = { CTL_HW, HW_MODEL };
  170
+  size_t     modelSize;
  171
+  
  172
+  if (sysctl(modelInfo,
  173
+             2,
  174
+             NULL,
  175
+             &modelSize,
  176
+             NULL, 0) == 0) {
  177
+    void * modelData = malloc(modelSize);
  178
+    
  179
+    if (modelData) {
  180
+      if (sysctl(modelInfo,
  181
+                 2,
  182
+                 modelData,
  183
+                 &modelSize,
  184
+                 NULL, 0) == 0) {
  185
+        modelString = [NSString stringWithUTF8String:modelData];
  186
+      }
  187
+      
  188
+      free(modelData);
  189
+    }
  190
+  }
  191
+  
  192
+  return modelString;
  193
+}
  194
+
  195
+- (void) returnToMainApplication {
  196
+  if ( self.delegate != nil && [self.delegate respondsToSelector:@selector(showMainApplicationWindow)])
  197
+    [self.delegate showMainApplicationWindow];
  198
+}
  199
+
  200
+- (void) startManager {
  201
+  BOOL returnToApp = NO;
  202
+  
  203
+  if ([self hasPendingCrashReport]) {
  204
+    NSError* error = nil;
  205
+    NSString *crashReport = nil;
  206
+    if (_crashReportMechanism == CrashReportMechanismPLCrashReporter) {
  207
+      _crashFile = [_crashFiles lastObject];
  208
+      NSData *crashData = [NSData dataWithContentsOfFile: _crashFile];
  209
+      PLCrashReport *report = [[[PLCrashReport alloc] initWithData:crashData error:&error] autorelease];
  210
+      crashReport = [CNSCrashReportTextFormatter stringValueForCrashReport:report withTextFormat:PLCrashReportTextFormatiOS];
  211
+    } else {
  212
+      NSString *crashLogs = [NSString stringWithContentsOfFile:_crashFile encoding:NSUTF8StringEncoding error:&error];
  213
+      if (!error) {
  214
+        crashReport = [[crashLogs componentsSeparatedByString: @"**********\n\n"] lastObject];
  215
+      }
  216
+    }
  217
+
  218
+    if (crashReport && !error) {        
  219
+      NSString* description = @"";
  220
+    
  221
+      if (_delegate && [_delegate respondsToSelector:@selector(crashReportDescription)]) {
  222
+        description = [_delegate crashReportDescription];
  223
+      }
  224
+
  225
+      if (self.autoSubmitCrashReport) {
  226
+        [self sendReportCrash:crashReport crashNotes:description];
  227
+      } else {
  228
+        _crashReportUI = [[CNSCrashReportUI alloc] initWithManager:self crashReport:crashReport companyName:_companyName applicationName:[self applicationName]];
  229
+        
  230
+        [_crashReportUI askCrashReportDetails];
  231
+      }
  232
+    } else {
  233
+      returnToApp = YES;
  234
+    }
  235
+  } else {
  236
+    returnToApp = YES;
  237
+  }
  238
+  
  239
+  if (returnToApp)
  240
+    [self returnToMainApplication];
  241
+}
  242
+
  243
+
  244
+#pragma mark - Mac OS X based
  245
+
  246
+- (void) searchCrashLogFile:(NSString *)path {  
  247
+  NSError* error;
  248
+  NSMutableArray* filesWithModificationDate = [NSMutableArray array];
  249
+  NSArray* crashLogFiles = [_fileManager contentsOfDirectoryAtPath:path error:&error];
  250
+  NSEnumerator* filesEnumerator = [crashLogFiles objectEnumerator];
  251
+  NSString* crashFile;
  252
+  while((crashFile = [filesEnumerator nextObject])) {
  253
+    NSString* crashLogPath = [path stringByAppendingPathComponent:crashFile];
  254
+    NSDate* modDate = [[_fileManager attributesOfItemAtPath:crashLogPath error:&error] fileModificationDate];
  255
+    [filesWithModificationDate addObject:[NSDictionary dictionaryWithObjectsAndKeys:crashFile,@"name",crashLogPath,@"path",modDate,@"modDate",nil]];
  256
+  }
  257
+  
  258
+  NSSortDescriptor* dateSortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"modDate" ascending:YES] autorelease];
  259
+  NSArray* sortedFiles = [filesWithModificationDate sortedArrayUsingDescriptors:[NSArray arrayWithObject:dateSortDescriptor]];
  260
+  
  261
+  NSPredicate* filterPredicate = [NSPredicate predicateWithFormat:@"name BEGINSWITH %@", [self applicationName]];
  262
+  NSArray* filteredFiles = [sortedFiles filteredArrayUsingPredicate:filterPredicate];
  263
+  
  264
+  _crashFile = [[[filteredFiles valueForKeyPath:@"path"] lastObject] copy];
  265
+}
  266
+
  267
+#pragma mark - setter
  268
+
  269
+- (void)storeLastCrashDate:(NSDate *) date {
  270
+  [[NSUserDefaults standardUserDefaults] setValue:date forKey:@"CrashReportSender.lastCrashDate"];
  271
+  [[NSUserDefaults standardUserDefaults] synchronize];
  272
+}
  273
+
  274
+- (NSDate *)loadLastCrashDate {
  275
+  NSDate *date = [[NSUserDefaults standardUserDefaults] valueForKey:@"CrashReportSender.lastCrashDate"];
  276
+  return date ?: [NSDate distantPast];
  277
+}
  278
+
  279
+- (void)storeAppVersion:(NSString *) version {
  280
+  [[NSUserDefaults standardUserDefaults] setValue:version forKey:@"CrashReportSender.appVersion"];
  281
+  [[NSUserDefaults standardUserDefaults] synchronize];
  282
+}
  283
+
  284
+- (NSString *)loadAppVersion {
  285
+  NSString *appVersion = [[NSUserDefaults standardUserDefaults] valueForKey:@"CrashReportSender.appVersion"];
  286
+  return appVersion ?: nil;
  287
+}
  288
+
  289
+#pragma mark - PLCrashReporter based
  290
+
  291
+#pragma mark - GetCrashData
  292
+
  293
+- (BOOL) hasPendingCrashReport {
  294
+  if (!_crashReportActivated) return NO;
  295
+  
  296
+  if (_crashReportMechanism == CrashReportMechanismPLCrashReporter) {
  297
+    
  298
+    _crashFiles = [[NSMutableArray alloc] init];
  299
+    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
  300
+    _crashesDir = [[NSString stringWithFormat:@"%@", [[paths objectAtIndex:0] stringByAppendingPathComponent:@"/crashes/"]] retain];
  301
+    
  302
+    if (![_fileManager fileExistsAtPath:_crashesDir]) {
  303
+      NSDictionary *attributes = [NSDictionary dictionaryWithObject: [NSNumber numberWithUnsignedLong: 0755] forKey: NSFilePosixPermissions];
  304
+      NSError *theError = NULL;
  305
+      
  306
+      [_fileManager createDirectoryAtPath:_crashesDir withIntermediateDirectories: YES attributes: attributes error: &theError];
  307
+    }
  308
+    
  309
+    PLCrashReporter *crashReporter = [PLCrashReporter sharedReporter];
  310
+    NSError *error = NULL;
  311
+    
  312
+    // Check if we previously crashed
  313
+    if ([crashReporter hasPendingCrashReport]) {
  314
+      [self handleCrashReport];
  315
+    }
  316
+    
  317
+    // Enable the Crash Reporter
  318
+    if (![crashReporter enableCrashReporterAndReturnError: &error])
  319
+      NSLog(@"Warning: Could not enable crash reporter: %@", error);
  320
+    
  321
+    if ([_crashFiles count] == 0 && [_fileManager fileExistsAtPath: _crashesDir]) {
  322
+      NSString *file = nil;
  323
+      NSError *error = NULL;
  324
+      
  325
+      NSDirectoryEnumerator *dirEnum = [_fileManager enumeratorAtPath: _crashesDir];
  326
+      
  327
+      while ((file = [dirEnum nextObject])) {
  328
+        NSDictionary *fileAttributes = [_fileManager attributesOfItemAtPath:[_crashesDir stringByAppendingPathComponent:file] error:&error];
  329
+        if ([[fileAttributes objectForKey:NSFileSize] intValue] > 0 && ![file isEqualToString:@".DS_Store"]) {
  330
+          [_crashFiles addObject:[_crashesDir stringByAppendingPathComponent: file]];
  331
+        }
  332
+      }
  333
+    }
  334
+    
  335
+    if ([_crashFiles count] > 0) {
  336
+      return YES;
  337
+    } else
  338
+      return NO;
  339
+  } else {
  340
+    BOOL returnValue = NO;
  341
+    
  342
+    NSString *appVersion = [self loadAppVersion];
  343
+    NSDate *lastCrashDate = [self loadLastCrashDate];
  344
+    
  345
+    if (!appVersion || ![appVersion isEqualToString:[self applicationVersion]] || [lastCrashDate isEqualToDate:[NSDate distantPast]]) {
  346
+      [self storeAppVersion:[self applicationVersion]];
  347
+      [self storeLastCrashDate:[NSDate date]];
  348
+      return NO;
  349
+    }
  350
+    
  351
+    NSArray* libraryDirectories = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, TRUE);
  352
+    // Snow Leopard is having the log files in another location
  353
+    [self searchCrashLogFile:[[libraryDirectories lastObject] stringByAppendingPathComponent:@"Logs/DiagnosticReports"]];
  354
+    if (_crashFile == nil) {
  355
+      [self searchCrashLogFile:[[libraryDirectories lastObject] stringByAppendingPathComponent:@"Logs/CrashReporter"]];
  356
+      if (_crashFile == nil) {
  357
+        NSString *sandboxFolder = [NSString stringWithFormat:@"/Containers/%@/Data/Library", [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"]];
  358
+        if ([[libraryDirectories lastObject] rangeOfString:sandboxFolder].location != NSNotFound) {
  359
+          NSString *libFolderName = [[libraryDirectories lastObject] stringByReplacingOccurrencesOfString:sandboxFolder withString:@""];
  360
+          [self searchCrashLogFile:[libFolderName stringByAppendingPathComponent:@"Logs/DiagnosticReports"]];
  361
+        }
  362
+      }
  363
+    }
  364
+    
  365
+    if (_crashFile) {
  366
+      NSError* error;
  367
+      
  368
+      NSDate *crashLogModificationDate = [[_fileManager attributesOfItemAtPath:_crashFile error:&error] fileModificationDate];
  369
+      unsigned long long crashLogFileSize = [[_fileManager attributesOfItemAtPath:_crashFile error:&error] fileSize];
  370
+      if ([crashLogModificationDate compare: lastCrashDate] == NSOrderedDescending && crashLogFileSize > 0) {
  371
+        [self storeLastCrashDate:crashLogModificationDate];
  372
+        returnValue = YES;
  373
+      }
  374
+    }
  375
+    
  376
+    return returnValue;
  377
+  }
  378
+}
  379
+
  380
+
  381
+#pragma mark - CNSCrashReportManagerDelegate
  382
+
  383
+- (void) cancelReport {
  384
+  [self _cleanCrashReports];
  385
+  [self returnToMainApplication];
  386
+}
  387
+
  388
+
  389
+- (void) sendReportCrash:(NSString*)crashReport crashNotes:(NSString *)crashNotes {
  390
+  NSString *userid = @"";
  391
+  NSString *contact = @"";
  392
+  
  393
+  if ([self delegate] != nil && [[self delegate] respondsToSelector:@selector(crashReportUserID)]) {
  394
+    userid = [[self delegate] crashReportUserID] ?: @"";
  395
+  }
  396
+  
  397
+  if ([self delegate] != nil && [[self delegate] respondsToSelector:@selector(crashReportContact)]) {
  398
+    contact = [[self delegate] crashReportContact] ?: @"";
  399
+  }
  400
+  
  401
+  SInt32 versionMajor, versionMinor, versionBugFix;
  402
+  if (Gestalt(gestaltSystemVersionMajor, &versionMajor) != noErr) versionMajor = 0;
  403
+  if (Gestalt(gestaltSystemVersionMinor, &versionMinor) != noErr)  versionMinor= 0;
  404
+  if (Gestalt(gestaltSystemVersionBugFix, &versionBugFix) != noErr) versionBugFix = 0;
  405
+  
  406
+  NSString* xml = [NSString stringWithFormat:@"<crash><applicationname>%s</applicationname><bundleidentifier>%s</bundleidentifier><systemversion>%@</systemversion><senderversion>%@</senderversion><version>%@</version><platform>%@</platform><userid>%@</userid><contact>%@</contact><description><![CDATA[%@]]></description><log><![CDATA[%@]]></log></crash>",
  407
+                   [[self applicationName] UTF8String],
  408
+                   [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"] UTF8String],
  409
+                   [NSString stringWithFormat:@"%i.%i.%i", versionMajor, versionMinor, versionBugFix],
  410
+                   [self applicationVersion],
  411
+                   [self applicationVersion],
  412
+                   [self modelVersion],
  413
+                   userid,
  414
+                   contact,
  415
+                   crashNotes,
  416
+                   crashReport
  417
+                   ];
  418
+
  419
+    
  420
+  [self returnToMainApplication];
  421
+  
  422
+  [self _postXML:[NSString stringWithFormat:@"<crashes>%@</crashes>", xml]];
  423
+}
  424
+
  425
+
  426
+#pragma mark - Networking
  427
+
  428
+- (void)_postXML:(NSString*)xml {
  429
+  NSMutableURLRequest *request = nil;
  430
+  NSString *boundary = @"----FOO";
  431
+  
  432
+  request = [NSMutableURLRequest requestWithURL:
  433
+             [NSURL URLWithString:[NSString stringWithFormat:@"%@api/2/apps/%@/crashes?sdk=%@&sdk_version=%@",
  434
+                                   _submissionURL,
  435
+                                   [self.appIdentifier stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
  436
+                                   SDK_NAME,
  437
+                                   SDK_VERSION
  438
+                                   ]
  439
+              ]];
  440
+  
  441
+  [request setValue:@"Quincy/Mac" forHTTPHeaderField:@"User-Agent"];
  442
+  [request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];
  443
+  [request setTimeoutInterval: 15];
  444
+  [request setHTTPMethod:@"POST"];
  445
+  NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
  446
+  [request setValue:contentType forHTTPHeaderField:@"Content-type"];
  447
+  
  448
+  NSMutableData *postBody =  [NSMutableData data];  
  449
+  [postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
  450
+  if (self.appIdentifier) {
  451
+    [postBody appendData:[@"Content-Disposition: form-data; name=\"xml\"; filename=\"crash.xml\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
  452
+    [postBody appendData:[[NSString stringWithFormat:@"Content-Type: text/xml\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
  453
+  } else {
  454
+    [postBody appendData:[@"Content-Disposition: form-data; name=\"xmlstring\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
  455
+  }
  456
+  [postBody appendData:[xml dataUsingEncoding:NSUTF8StringEncoding]];
  457
+  [postBody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
  458
+  [request setHTTPBody:postBody];
  459
+  
  460
+  _serverResult = CrashReportStatusUnknown;
  461
+  _statusCode = 200;
  462
+  
  463
+  NSHTTPURLResponse *response = nil;
  464
+  NSError *error = nil;
  465
+  
  466
+  NSData *responseData = nil;
  467
+  responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
  468
+  _statusCode = [response statusCode];
  469
+  
  470
+  if (_statusCode >= 200 && _statusCode < 400 && responseData != nil && [responseData length] > 0) {
  471
+    [self _cleanCrashReports];
  472
+
  473
+    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:responseData];
  474
+    // Set self as the delegate of the parser so that it will receive the parser delegate methods callbacks.
  475
+    [parser setDelegate:self];
  476
+    // Depending on the XML document you're parsing, you may want to enable these features of NSXMLParser.
  477
+    [parser setShouldProcessNamespaces:NO];
  478
+    [parser setShouldReportNamespacePrefixes:NO];
  479
+    [parser setShouldResolveExternalEntities:NO];
  480
+    
  481
+    [parser parse];
  482
+    
  483
+    [parser release];
  484
+  }
  485
+}
  486
+
  487
+
  488
+#pragma mark - NSXMLParser
  489
+
  490
+- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
  491
+  if (qName) {
  492
+    elementName = qName;
  493
+  }
  494
+  
  495
+  if ([elementName isEqualToString:@"result"]) {
  496
+    _contentOfProperty = [NSMutableString string];
  497
+  }
  498
+}
  499
+
  500
+- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
  501
+  if (qName) {
  502
+    elementName = qName;
  503
+  }
  504
+  
  505
+  if ([elementName isEqualToString:@"result"]) {
  506
+    if ([_contentOfProperty intValue] > _serverResult) {
  507
+      _serverResult = [_contentOfProperty intValue];
  508
+    }
  509
+  }
  510
+}
  511
+
  512
+
  513
+- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
  514
+  if (_contentOfProperty) {
  515
+    // If the current element is one whose content we care about, append 'string'
  516
+    // to the property that holds the content of the current element.
  517
+    if (string != nil) {
  518
+      [_contentOfProperty appendString:string];
  519
+    }
  520
+  }
  521
+}
  522
+
  523
+
  524
+#pragma mark - GetterSetter
  525
+
  526
+- (NSString *) applicationName {
  527
+  NSString *applicationName = [[[NSBundle mainBundle] localizedInfoDictionary] valueForKey: @"CFBundleExecutable"];
  528
+  
  529
+  if (!applicationName)
  530
+    applicationName = [[[NSBundle mainBundle] infoDictionary] valueForKey: @"CFBundleExecutable"];
  531
+  
  532
+  return applicationName;
  533
+}
  534
+
  535
+
  536
+- (NSString*) applicationVersionString {
  537
+  NSString* string = [[[NSBundle mainBundle] localizedInfoDictionary] valueForKey: @"CFBundleShortVersionString"];
  538
+  
  539
+  if (!string)
  540
+    string = [[[NSBundle mainBundle] infoDictionary] valueForKey: @"CFBundleShortVersionString"];
  541
+  
  542
+  return string;
  543
+}
  544
+
  545
+- (NSString *) applicationVersion {
  546
+  NSString* string = [[[NSBundle mainBundle] localizedInfoDictionary] valueForKey: @"CFBundleVersion"];
  547
+  
  548
+  if (!string)
  549
+    string = [[[NSBundle mainBundle] infoDictionary] valueForKey: @"CFBundleVersion"];
  550
+  
  551
+  return string;
  552
+}
  553
+
  554
+
  555
+#pragma mark - PLCrashReporter
  556
+
  557
+//
  558
+// Called to handle a pending crash report.
  559
+//
  560
+- (void) handleCrashReport {
  561
+  PLCrashReporter *crashReporter = [PLCrashReporter sharedReporter];
  562
+  NSError *error = NULL;
  563
+	
  564
+  // check if the next call ran successfully the last time
  565
+  if (_analyzerStarted == 0) {
  566
+    // mark the start of the routine
  567
+    _analyzerStarted = 1;
  568
+    [[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInt:_analyzerStarted] forKey:kHockeySDKAnalyzerStarted];
  569
+    [[NSUserDefaults standardUserDefaults] synchronize];
  570
+    
  571
+    // Try loading the crash report
  572
+    NSData *crashData = [[NSData alloc] initWithData:[crashReporter loadPendingCrashReportDataAndReturnError: &error]];
  573
+    
  574
+    NSString *cacheFilename = [NSString stringWithFormat: @"%.0f", [NSDate timeIntervalSinceReferenceDate]];
  575
+    
  576
+    if (crashData == nil) {
  577
+      NSLog(@"Could not load crash report: %@", error);
  578
+    } else {
  579
+      [crashData writeToFile:[_crashesDir stringByAppendingPathComponent: cacheFilename] atomically:YES];
  580
+    }
  581
+  }
  582
+	
  583
+  // Purge the report
  584
+  // mark the end of the routine
  585
+  _analyzerStarted = 0;
  586
+  [[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInt:_analyzerStarted] forKey:kHockeySDKAnalyzerStarted];
  587
+  [[NSUserDefaults standardUserDefaults] synchronize];
  588
+  
  589
+  [crashReporter purgePendingCrashReport];
  590
+  return;
  591
+}
  592
+
  593
+@end
29  Classes/CrashReporting/CNSCrashReportManagerDelegate.h
... ...
@@ -0,0 +1,29 @@
  1
+//
  2
+//  CNSCrashReportManagerDelegate.h
  3
+//  HockeySDK
  4
+//
  5
+//  Created by Andreas Linde on 29.03.12.
  6
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
  7
+//
  8
+
  9
+#import <Foundation/Foundation.h>
  10
+
  11
+@protocol CNSCrashReportManagerDelegate <NSObject>
  12
+
  13
+@required
  14
+
  15
+// Invoked once the modal sheets are gone
  16
+- (void) showMainApplicationWindow;
  17
+
  18
+@optional
  19
+
  20
+// Return the description the crashreport should contain, empty by default. The string will automatically be wrapped into <[DATA[ ]]>, so make sure you don't do that in your string.
  21
+-(NSString *) crashReportDescription;
  22
+
  23
+// Return the userid the crashreport should contain, empty by default
  24
+-(NSString *) crashReportUserID;
  25
+
  26
+// Return the contact value (e.g. email) the crashreport should contain, empty by default
  27
+-(NSString *) crashReportContact;
  28
+
  29
+@end
64  Classes/CrashReporting/CNSCrashReportTextFormatter.h
... ...
@@ -0,0 +1,64 @@
  1
+/*
  2
+ * Authors:
  3
+ *  Landon Fuller <landonf@plausiblelabs.com>
  4
+ *  Damian Morris <damian@moso.com.au>
  5
+ *  Andreas Linde <mail@andreaslinde.de>
  6
+ *
  7
+ * Copyright (c) 2008-2012 Plausible Labs Cooperative, Inc.
  8
+ * Copyright (c) 2010 MOSO Corporation, Pty Ltd.
  9
+ * Copyright (c) 2012 Codenauts UG (haftungsbeschränkt)
  10
+ * All rights reserved.
  11
+ *
  12
+ * Permission is hereby granted, free of charge, to any person
  13
+ * obtaining a copy of this software and associated documentation
  14
+ * files (the "Software"), to deal in the Software without
  15
+ * restriction, including without limitation the rights to use,
  16
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
  17
+ * copies of the Software, and to permit persons to whom the
  18
+ * Software is furnished to do so, subject to the following
  19
+ * conditions:
  20
+ *
  21
+ * The above copyright notice and this permission notice shall be
  22
+ * included in all copies or substantial portions of the Software.
  23
+ *
  24
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  25
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  26
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  27
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  28
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  29
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  30
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  31
+ * OTHER DEALINGS IN THE SOFTWARE.
  32
+ */
  33
+
  34
+
  35
+#import <Foundation/Foundation.h>
  36
+
  37
+#import "CrashReporter/PLCrashReportFormatter.h"
  38
+
  39
+/**
  40
+ * Supported text output formats.
  41
+ *
  42
+ * @ingroup enums
  43
+ */
  44
+typedef enum {
  45
+    /** An iOS-compatible crash log text format. Compatible with the crash logs generated by the device and available
  46
+     * through iTunes Connect. */
  47
+    CNSCrashReportTextFormatiOS = 0
  48
+} CNSCrashReportTextFormat;
  49
+
  50
+
  51
+@interface CNSCrashReportTextFormatter : NSObject <PLCrashReportFormatter> {
  52
+@private
  53
+    /** Text output format. */
  54
+    CNSCrashReportTextFormat _textFormat;
  55
+
  56
+    /** Encoding to use for string output. */
  57
+    NSStringEncoding _stringEncoding;
  58
+}
  59
+
  60
++ (NSString *) stringValueForCrashReport: (PLCrashReport *) report withTextFormat: (CNSCrashReportTextFormat) textFormat;
  61
+
  62
+- (id) initWithTextFormat: (CNSCrashReportTextFormat) textFormat stringEncoding: (NSStringEncoding) stringEncoding;
  63
+
  64
+@end
512  Classes/CrashReporting/CNSCrashReportTextFormatter.m
... ...
@@ -0,0 +1,512 @@
  1
+/*
  2
+ * Authors:
  3
+ *  Landon Fuller <landonf@plausiblelabs.com>
  4
+ *  Damian Morris <damian@moso.com.au>
  5
+ *  Andreas Linde <mail@andreaslinde.de>
  6
+ *
  7
+ * Copyright (c) 2008-2012 Plausible Labs Cooperative, Inc.
  8
+ * Copyright (c) 2010 MOSO Corporation, Pty Ltd.
  9
+ * Copyright (c) 2012 Codenauts UG (haftungsbeschränkt)
  10
+ * All rights reserved.
  11
+ *
  12
+ * Permission is hereby granted, free of charge, to any person
  13
+ * obtaining a copy of this software and associated documentation
  14
+ * files (the "Software"), to deal in the Software without
  15
+ * restriction, including without limitation the rights to use,
  16
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
  17
+ * copies of the Software, and to permit persons to whom the
  18
+ * Software is furnished to do so, subject to the following
  19
+ * conditions:
  20
+ *
  21
+ * The above copyright notice and this permission notice shall be
  22