diff --git a/Gemfile.lock b/Gemfile.lock index c58a26a6b..a26d67633 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ GEM remote: https://rubygems.org/ specs: - CFPropertyList (2.3.5) + CFPropertyList (2.3.6) activesupport (4.2.10) i18n (~> 0.7) minitest (~> 5.1) @@ -9,32 +9,33 @@ GEM tzinfo (~> 1.1) addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) + atomos (0.1.2) babosa (1.0.2) claide (1.0.2) - cocoapods (1.3.1) + cocoapods (1.4.0) activesupport (>= 4.0.2, < 5) claide (>= 1.0.2, < 2.0) - cocoapods-core (= 1.3.1) - cocoapods-deintegrate (>= 1.0.1, < 2.0) + cocoapods-core (= 1.4.0) + cocoapods-deintegrate (>= 1.0.2, < 2.0) cocoapods-downloader (>= 1.1.3, < 2.0) cocoapods-plugins (>= 1.0.0, < 2.0) cocoapods-search (>= 1.0.0, < 2.0) cocoapods-stats (>= 1.0.0, < 2.0) - cocoapods-trunk (>= 1.2.0, < 2.0) + cocoapods-trunk (>= 1.3.0, < 2.0) cocoapods-try (>= 1.1.0, < 2.0) colored2 (~> 3.1) escape (~> 0.0.4) fourflusher (~> 2.0.1) gh_inspector (~> 1.0) - molinillo (~> 0.5.7) + molinillo (~> 0.6.4) nap (~> 1.0) ruby-macho (~> 1.1) - xcodeproj (>= 1.5.1, < 2.0) - cocoapods-core (1.3.1) + xcodeproj (>= 1.5.4, < 2.0) + cocoapods-core (1.4.0) activesupport (>= 4.0.2, < 6) fuzzy_match (~> 2.0.4) nap (~> 1.0) - cocoapods-deintegrate (1.0.1) + cocoapods-deintegrate (1.0.2) cocoapods-downloader (1.1.3) cocoapods-plugins (1.0.0) nap @@ -46,37 +47,38 @@ GEM cocoapods-try (1.1.0) colored (1.2) colored2 (3.1.2) - commander-fastlane (4.4.5) + commander-fastlane (4.4.6) highline (~> 1.7.2) + concurrent-ruby (1.0.5) declarative (0.0.10) declarative-option (0.1.0) domain_name (0.5.20170404) unf (>= 0.0.5, < 1.0.0) dotenv (2.2.1) escape (0.0.4) - excon (0.59.0) - faraday (0.13.1) + excon (0.60.0) + faraday (0.14.0) multipart-post (>= 1.2, < 3) faraday-cookie_jar (0.0.6) faraday (>= 0.7.4) http-cookie (~> 1.0.0) faraday_middleware (0.12.2) faraday (>= 0.7.4, < 1.0) - fastimage (2.1.0) - fastlane (2.60.1) - CFPropertyList (>= 2.3, < 3.0.0) + fastimage (2.1.1) + fastlane (2.84.0) + CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.3, < 3.0.0) babosa (>= 1.0.2, < 2.0.0) bundler (>= 1.12.0, < 2.0.0) colored - commander-fastlane (>= 4.4.5, < 5.0.0) + commander-fastlane (>= 4.4.6, < 5.0.0) dotenv (>= 2.1.1, < 3.0.0) excon (>= 0.45.0, < 1.0.0) faraday (~> 0.9) faraday-cookie_jar (~> 0.0.6) faraday_middleware (~> 0.9) fastimage (>= 2.1.0, < 3.0.0) - gh_inspector (>= 1.0.1, < 2.0.0) + gh_inspector (>= 1.1.2, < 2.0.0) google-api-client (>= 0.13.1, < 0.14.0) highline (>= 1.7.2, < 2.0.0) json (< 3.0.0) @@ -88,17 +90,18 @@ GEM public_suffix (~> 2.0.0) rubyzip (>= 1.1.0, < 2.0.0) security (= 0.1.3) - slack-notifier (>= 1.3, < 2.0.0) + slack-notifier (>= 2.0.0, < 3.0.0) terminal-notifier (>= 1.6.2, < 2.0.0) terminal-table (>= 1.4.5, < 2.0.0) - tty-screen (~> 0.5.0) + tty-screen (>= 0.6.3, < 1.0.0) + tty-spinner (>= 0.8.0, < 1.0.0) word_wrap (~> 1.0.0) - xcodeproj (>= 1.5.0, < 2.0.0) + xcodeproj (>= 1.5.2, < 2.0.0) xcpretty (>= 0.2.4, < 1.0.0) xcpretty-travis-formatter (>= 0.0.3) fourflusher (2.0.1) fuzzy_match (2.0.4) - gh_inspector (1.0.3) + gh_inspector (1.1.2) google-api-client (0.13.6) addressable (~> 2.5, >= 2.5.1) googleauth (~> 0.5) @@ -106,21 +109,22 @@ GEM mime-types (~> 3.0) representable (~> 3.0) retriable (>= 2.0, < 4.0) - googleauth (0.5.3) + googleauth (0.6.2) faraday (~> 0.12) - jwt (~> 1.4) + jwt (>= 1.4, < 3.0) logging (~> 2.0) memoist (~> 0.12) multi_json (~> 1.11) os (~> 0.9) signet (~> 0.7) - highline (1.7.8) + highline (1.7.10) http-cookie (1.0.3) domain_name (~> 0.5) httpclient (2.8.3) - i18n (0.8.6) + i18n (0.9.5) + concurrent-ruby (~> 1.0) json (2.1.0) - jwt (1.5.6) + jwt (2.1.0) little-plugger (1.1.4) logging (2.2.2) little-plugger (~> 1.1) @@ -130,16 +134,16 @@ GEM mime-types-data (~> 3.2015) mime-types-data (3.2016.0521) mini_magick (4.5.1) - minitest (5.10.3) - molinillo (0.5.7) - multi_json (1.12.2) + minitest (5.11.3) + molinillo (0.6.4) + multi_json (1.13.1) multi_xml (0.6.0) multipart-post (2.0.0) nanaimo (0.2.3) nap (1.1.0) netrc (0.11.0) os (0.9.6) - plist (3.3.0) + plist (3.4.0) public_suffix (2.0.5) representable (3.0.4) declarative (< 0.1.0) @@ -150,33 +154,37 @@ GEM ruby-macho (1.1.0) rubyzip (1.2.1) security (0.1.3) - signet (0.7.3) + signet (0.8.1) addressable (~> 2.3) faraday (~> 0.9) - jwt (~> 1.5) + jwt (>= 1.5, < 3.0) multi_json (~> 1.10) - slack-notifier (1.5.1) + slack-notifier (2.3.2) terminal-notifier (1.8.0) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) thread_safe (0.3.6) - tty-screen (0.5.0) - tzinfo (1.2.3) + tty-cursor (0.5.0) + tty-screen (0.6.4) + tty-spinner (0.8.0) + tty-cursor (>= 0.5.0) + tzinfo (1.2.5) thread_safe (~> 0.1) uber (0.1.0) unf (0.1.4) unf_ext - unf_ext (0.0.7.4) + unf_ext (0.0.7.5) unicode-display_width (1.3.0) word_wrap (1.0.0) - xcodeproj (1.5.2) + xcodeproj (1.5.6) CFPropertyList (~> 2.3.3) + atomos (~> 0.1.2) claide (>= 1.0.2, < 2.0) colored2 (~> 3.1) nanaimo (~> 0.2.3) xcpretty (0.2.8) rouge (~> 2.0.7) - xcpretty-travis-formatter (0.0.4) + xcpretty-travis-formatter (1.0.0) xcpretty (~> 0.2, >= 0.0.7) PLATFORMS @@ -187,4 +195,4 @@ DEPENDENCIES fastlane BUNDLED WITH - 1.14.6 + 1.16.1 diff --git a/Podfile.lock b/Podfile.lock index 793848dc7..c63050ed2 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -211,7 +211,7 @@ SPEC CHECKSUMS: PureLayout: 4d550abe49a94f24c2808b9b95db9131685fe4cd Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96 SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c - SignalServiceKit: c639443811f2670986006f5b661cb1a862de66ab + SignalServiceKit: 5cc6e8e249f381c5eaee8693c0dff20fc1a3eee0 SocketRocket: dbb1554b8fc288ef8ef370d6285aeca7361be31e SQLCipher: f9fcf29b2e59ced7defc2a2bdd0ebe79b40d4990 SSZipArchive: 14401ade5f8e82aba1ff03e9f88e9de60937ae60 @@ -222,4 +222,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 66db99df53e7593362ebb004bea5d2215ca00e8e -COCOAPODS: 1.3.1 +COCOAPODS: 1.4.0 diff --git a/Pods b/Pods index 29babe215..e028d806f 160000 --- a/Pods +++ b/Pods @@ -1 +1 @@ -Subproject commit 29babe215072d52688ea5b18592f308bfc190612 +Subproject commit e028d806f2e2054658e53c4b3c696c2bef8e5755 diff --git a/Scripts/debug_log_upload.py b/Scripts/debug_log_upload.py new file mode 100755 index 000000000..0c26aafb4 --- /dev/null +++ b/Scripts/debug_log_upload.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +import sys +import os +import re +import commands +import subprocess +import argparse +import inspect +import urllib2 +import json + +def fail(message): + file_name = __file__ + current_line_no = inspect.stack()[1][2] + current_function_name = inspect.stack()[1][3] + print 'Failure in:', file_name, current_line_no, current_function_name + print message + sys.exit(1) + + +def execute_command(command): + try: + print ' '.join(command) + output = subprocess.check_output(command) + if output: + print output + except subprocess.CalledProcessError as e: + print e.output + sys.exit(1) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Precommit cleanup script.') + parser.add_argument('--file', help='used for starting a new version.') + + args = parser.parse_args() + + params_response = urllib2.urlopen("https://debuglogs.org/").read() + + params = json.loads(params_response) + + upload_url = params['url'] + upload_fields = params['fields'] + upload_key = upload_fields['key'] + upload_key = upload_key + os.path.splitext(args.file)[1] + upload_fields['key'] = upload_key + + download_url = 'https://debuglogs.org/' + upload_key + print 'download_url:', download_url + + curl_command = ['curl', '-v', '-i', '-X', 'POST'] + for field_name in upload_fields: + field_value = upload_fields[field_name] + curl_command.append('-F') + curl_command.append("'%s=%s'" % (field_name, field_value, )) + curl_command.append('-F') + curl_command.append("'file=@%s'" % (args.file,)) + curl_command.append(upload_url) + + # execute_command(curl_command) + print ' '.join(curl_command) + + print 'download_url:', download_url + \ No newline at end of file diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index 4de216e56..254dc626d 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -46,6 +46,7 @@ #import #import #import +#import @import WebRTC; @import Intents; @@ -324,7 +325,7 @@ static NSString *const kURLHostVerifyPrefix = @"verify"; [controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"SETTINGS_ADVANCED_SUBMIT_DEBUGLOG", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *_Nonnull action) { - [Pastelog submitLogsWithShareCompletion:^{ + [Pastelog submitLogsWithCompletion:^{ DDLogInfo( @"%@ exiting after sharing debug logs.", self.logTag); [DDLog flushLog]; @@ -396,6 +397,15 @@ static NSString *const kURLHostVerifyPrefix = @"verify"; if (languageCode.length > 0) { DDLogInfo(@"Language Code: %@", languageCode); } + + size_t size; + sysctlbyname("hw.machine", NULL, &size, NULL, 0); + char *machine = malloc(size); + sysctlbyname("hw.machine", machine, &size, NULL, 0); + NSString *platform = [NSString stringWithUTF8String:machine]; + free(machine); + + DDLogInfo(@"iPhone Version: %@", platform); } - (UIViewController *)loadingRootViewController diff --git a/Signal/src/ViewControllers/DebugUI/DebugUIMessages.m b/Signal/src/ViewControllers/DebugUI/DebugUIMessages.m index dde2caf40..53f33f172 100644 --- a/Signal/src/ViewControllers/DebugUI/DebugUIMessages.m +++ b/Signal/src/ViewControllers/DebugUI/DebugUIMessages.m @@ -7,7 +7,6 @@ #import "OWSTableViewController.h" #import "Signal-Swift.h" #import "ThreadUtil.h" -#import #import #import #import diff --git a/Signal/src/ViewControllers/DebugUI/DebugUIMisc.m b/Signal/src/ViewControllers/DebugUI/DebugUIMisc.m index 41ecfa7e9..40eb0cce6 100644 --- a/Signal/src/ViewControllers/DebugUI/DebugUIMisc.m +++ b/Signal/src/ViewControllers/DebugUI/DebugUIMisc.m @@ -10,7 +10,6 @@ #import "RegistrationViewController.h" #import "Signal-Swift.h" #import "ThreadUtil.h" -#import #import #import #import diff --git a/Signal/src/ViewControllers/DebugUI/DebugUISyncMessages.m b/Signal/src/ViewControllers/DebugUI/DebugUISyncMessages.m index 51cb890db..dd033379a 100644 --- a/Signal/src/ViewControllers/DebugUI/DebugUISyncMessages.m +++ b/Signal/src/ViewControllers/DebugUI/DebugUISyncMessages.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "DebugUISyncMessages.h" @@ -7,7 +7,6 @@ #import "OWSTableViewController.h" #import "Signal-Swift.h" #import "ThreadUtil.h" -#import #import #import #import diff --git a/Signal/src/util/Pastelog.h b/Signal/src/util/Pastelog.h index 99356aa0e..0d46da066 100644 --- a/Signal/src/util/Pastelog.h +++ b/Signal/src/util/Pastelog.h @@ -2,14 +2,17 @@ // Copyright (c) 2018 Open Whisper Systems. All rights reserved. // +NS_ASSUME_NONNULL_BEGIN + +typedef void (^SubmitDebugLogsCompletion)(void); + @interface Pastelog : NSObject -typedef void (^DebugLogsUploadedBlock)(NSError *error, NSString *urlString); -typedef void (^DebugLogsSharedBlock)(void); +- (instancetype)init NS_UNAVAILABLE; -+(void)submitLogs; -+ (void)submitLogsWithShareCompletion:(nullable DebugLogsSharedBlock)block; -+ (void)submitLogsWithUploadCompletion:(DebugLogsUploadedBlock)block; -+ (void)submitLogsWithUploadCompletion:(DebugLogsUploadedBlock)block forFileLogger:(DDFileLogger *)fileLogger; ++ (void)submitLogs; ++ (void)submitLogsWithCompletion:(nullable SubmitDebugLogsCompletion)completion; @end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/util/Pastelog.m b/Signal/src/util/Pastelog.m index d6dc5b7cb..17dda81a0 100644 --- a/Signal/src/util/Pastelog.m +++ b/Signal/src/util/Pastelog.m @@ -5,6 +5,10 @@ #import "Pastelog.h" #import "Signal-Swift.h" #import "ThreadUtil.h" +#import "zlib.h" +#import +#import +#import #import #import #import @@ -12,251 +16,472 @@ #import #import #import -#import -@interface Pastelog () +NS_ASSUME_NONNULL_BEGIN -@property (nonatomic) UIAlertController *loadingAlert; -@property (nonatomic) NSMutableData *responseData; -@property (nonatomic) DebugLogsUploadedBlock block; +typedef void (^UploadDebugLogsSuccess)(NSURL *url); +typedef void (^UploadDebugLogsFailure)(NSString *localizedErrorMessage); + +#pragma mark - + +@class DebugLogUploader; + +typedef void (^DebugLogUploadSuccess)(DebugLogUploader *uploader, NSURL *url); +typedef void (^DebugLogUploadFailure)(DebugLogUploader *uploader, NSError *error); + +@interface DebugLogUploader : NSObject + +@property (nonatomic) NSURL *fileUrl; +@property (nonatomic) NSString *mimeType; +@property (nonatomic, nullable) DebugLogUploadSuccess success; +@property (nonatomic, nullable) DebugLogUploadFailure failure; @end #pragma mark - -@implementation Pastelog +@implementation DebugLogUploader -+(void)submitLogs { - [self submitLogsWithShareCompletion:nil]; +- (void)dealloc +{ + DDLogVerbose(@"Dealloc: %@", self.logTag); } -+ (void)submitLogsWithShareCompletion:(nullable DebugLogsSharedBlock)shareCompletionParam +- (void)uploadFileWithURL:(NSURL *)fileUrl + mimeType:(NSString *)mimeType + success:(DebugLogUploadSuccess)success + failure:(DebugLogUploadFailure)failure { - DebugLogsSharedBlock shareCompletion = ^{ - if (shareCompletionParam) { - // Wait a moment. If PasteLog opens a URL, it needs a moment to complete. - dispatch_after( - dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), shareCompletionParam); + OWSAssert(fileUrl); + OWSAssert(mimeType.length > 0); + OWSAssert(success); + OWSAssert(failure); + + self.fileUrl = fileUrl; + self.mimeType = mimeType; + self.success = success; + self.failure = failure; + + [self getUploadParameters]; +} + +- (void)getUploadParameters +{ + __weak DebugLogUploader *weakSelf = self; + + NSURLSessionConfiguration *sessionConf = NSURLSessionConfiguration.ephemeralSessionConfiguration; + AFHTTPSessionManager *sessionManager = + [[AFHTTPSessionManager alloc] initWithBaseURL:nil sessionConfiguration:sessionConf]; + sessionManager.requestSerializer = [AFHTTPRequestSerializer serializer]; + sessionManager.responseSerializer = [AFJSONResponseSerializer serializer]; + NSString *urlString = @"https://debuglogs.org/"; + [sessionManager GET:urlString + parameters:nil + progress:nil + success:^(NSURLSessionDataTask *task, id _Nullable responseObject) { + if (![responseObject isKindOfClass:[NSDictionary class]]) { + DDLogError(@"%@ Invalid response: %@, %@", weakSelf.logTag, urlString, responseObject); + [weakSelf + failWithError:OWSErrorWithCodeDescription(OWSErrorCodeDebugLogUploadFailed, @"Invalid response")]; + return; + } + NSString *uploadUrl = responseObject[@"url"]; + if (![uploadUrl isKindOfClass:[NSString class]] || uploadUrl.length < 1) { + DDLogError(@"%@ Invalid response: %@, %@", weakSelf.logTag, urlString, responseObject); + [weakSelf + failWithError:OWSErrorWithCodeDescription(OWSErrorCodeDebugLogUploadFailed, @"Invalid response")]; + return; + } + NSDictionary *fields = responseObject[@"fields"]; + if (![fields isKindOfClass:[NSDictionary class]] || fields.count < 1) { + DDLogError(@"%@ Invalid response: %@, %@", weakSelf.logTag, urlString, responseObject); + [weakSelf + failWithError:OWSErrorWithCodeDescription(OWSErrorCodeDebugLogUploadFailed, @"Invalid response")]; + return; + } + for (NSString *fieldName in fields) { + NSString *fieldValue = fields[fieldName]; + if (![fieldName isKindOfClass:[NSString class]] || fieldName.length < 1 + || ![fieldValue isKindOfClass:[NSString class]] || fieldValue.length < 1) { + DDLogError(@"%@ Invalid response: %@, %@", weakSelf.logTag, urlString, responseObject); + [weakSelf failWithError:OWSErrorWithCodeDescription( + OWSErrorCodeDebugLogUploadFailed, @"Invalid response")]; + return; + } + } + NSString *_Nullable uploadKey = fields[@"key"]; + if (![uploadKey isKindOfClass:[NSString class]] || uploadKey.length < 1) { + DDLogError(@"%@ Invalid response: %@, %@", weakSelf.logTag, urlString, responseObject); + [weakSelf + failWithError:OWSErrorWithCodeDescription(OWSErrorCodeDebugLogUploadFailed, @"Invalid response")]; + return; + } + + // Add a file extension to the upload's key. + NSString *fileExtension = weakSelf.fileUrl.lastPathComponent.pathExtension; + uploadKey = [uploadKey stringByAppendingPathExtension:fileExtension]; + NSMutableDictionary *updatedFields = [fields mutableCopy]; + updatedFields[@"key"] = uploadKey; + + [weakSelf uploadFileWithUploadUrl:uploadUrl fields:updatedFields uploadKey:uploadKey]; } - }; + failure:^(NSURLSessionDataTask *_Nullable task, NSError *error) { + DDLogError(@"%@ failed: %@", weakSelf.logTag, urlString); + [weakSelf failWithError:error]; + }]; +} - [self submitLogsWithUploadCompletion:^(NSError *error, NSString *urlString) { - if (!error) { - UIAlertController *alert = [UIAlertController - alertControllerWithTitle:NSLocalizedString(@"DEBUG_LOG_ALERT_TITLE", @"Title of the debug log alert.") - message:NSLocalizedString( - @"DEBUG_LOG_ALERT_MESSAGE", @"Message of the debug log alert.") - preferredStyle:UIAlertControllerStyleAlert]; - [alert - addAction:[UIAlertAction - actionWithTitle:NSLocalizedString(@"DEBUG_LOG_ALERT_OPTION_EMAIL", - @"Label for the 'email debug log' option of the the debug log alert.") - style:UIAlertActionStyleDefault - handler:^(UIAlertAction *_Nonnull action) { - [Pastelog.sharedManager submitEmail:urlString]; - - shareCompletion(); - }]]; - [alert addAction:[UIAlertAction - actionWithTitle:NSLocalizedString(@"DEBUG_LOG_ALERT_OPTION_COPY_LINK", - @"Label for the 'copy link' option of the the debug log alert.") - style:UIAlertActionStyleDefault - handler:^(UIAlertAction *_Nonnull action) { - UIPasteboard *pb = [UIPasteboard generalPasteboard]; - [pb setString:urlString]; - - shareCompletion(); - }]]; -#ifdef DEBUG - [alert addAction:[UIAlertAction - actionWithTitle:NSLocalizedString(@"DEBUG_LOG_ALERT_OPTION_SEND_TO_SELF", - @"Label for the 'send to self' option of the the debug log alert.") - style:UIAlertActionStyleDefault - handler:^(UIAlertAction *_Nonnull action) { - [Pastelog.sharedManager sendToSelf:urlString]; - }]]; - [alert addAction:[UIAlertAction - actionWithTitle: - NSLocalizedString(@"DEBUG_LOG_ALERT_OPTION_SEND_TO_LAST_THREAD", - @"Label for the 'send to last thread' option of the the debug log alert.") - style:UIAlertActionStyleDefault - handler:^(UIAlertAction *_Nonnull action) { - [Pastelog.sharedManager sendToMostRecentThread:urlString]; - }]]; -#endif - [alert addAction: - [UIAlertAction - actionWithTitle:NSLocalizedString(@"DEBUG_LOG_ALERT_OPTION_BUG_REPORT", - @"Label for the 'Open a Bug Report' option of the the debug log alert.") - style:UIAlertActionStyleCancel - handler:^(UIAlertAction *_Nonnull action) { - [Pastelog.sharedManager prepareRedirection:urlString - shareCompletion:shareCompletion]; - }]]; - UIViewController *presentingViewController - = UIApplication.sharedApplication.frontmostViewControllerIgnoringAlerts; - [presentingViewController presentViewController:alert animated:NO completion:nil]; - } else{ - UIAlertView *alertView = - [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"DEBUG_LOG_FAILURE_ALERT_TITLE", - @"Title of the alert indicating the debug log upload failed.") - message:error.localizedDescription - delegate:nil - cancelButtonTitle:@"OK" - otherButtonTitles:nil, nil]; - [alertView show]; +- (void)uploadFileWithUploadUrl:(NSString *)uploadUrl fields:(NSDictionary *)fields uploadKey:(NSString *)uploadKey +{ + OWSAssert(uploadUrl.length > 0); + OWSAssert(fields); + OWSAssert(uploadKey.length > 0); + + __weak DebugLogUploader *weakSelf = self; + NSURLSessionConfiguration *sessionConf = NSURLSessionConfiguration.ephemeralSessionConfiguration; + AFHTTPSessionManager *sessionManager = + [[AFHTTPSessionManager alloc] initWithBaseURL:nil sessionConfiguration:sessionConf]; + sessionManager.requestSerializer = [AFHTTPRequestSerializer serializer]; + sessionManager.responseSerializer = [AFHTTPResponseSerializer serializer]; + [sessionManager POST:uploadUrl + parameters:@{} + constructingBodyWithBlock:^(id formData) { + for (NSString *fieldName in fields) { + NSString *fieldValue = fields[fieldName]; + [formData appendPartWithFormData:[fieldValue dataUsingEncoding:NSUTF8StringEncoding] name:fieldName]; + } + NSError *error; + BOOL success = [formData appendPartWithFileURL:weakSelf.fileUrl + name:@"file" + fileName:weakSelf.fileUrl.lastPathComponent + mimeType:weakSelf.mimeType + error:&error]; + if (!success || error) { + DDLogError(@"%@ failed: %@, error: %@", weakSelf.logTag, uploadUrl, error); + } } - }]; + progress:nil + success:^(NSURLSessionDataTask *task, id _Nullable responseObject) { + DDLogVerbose(@"%@ Response: %@, %@", weakSelf.logTag, uploadUrl, responseObject); + + NSString *urlString = [NSString stringWithFormat:@"https://debuglogs.org/%@", uploadKey]; + [self succeedWithUrl:[NSURL URLWithString:urlString]]; + } + failure:^(NSURLSessionDataTask *_Nullable task, NSError *error) { + DDLogError(@"%@ failed: %@", weakSelf.logTag, uploadUrl); + [weakSelf failWithError:error]; + }]; } -+ (void)submitLogsWithUploadCompletion:(DebugLogsUploadedBlock)block +- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { - [self submitLogsWithUploadCompletion:block forFileLogger:[[DDFileLogger alloc] init]]; + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; + + NSInteger statusCode = httpResponse.statusCode; + // We'll accept any 2xx status code. + NSInteger statusCodeClass = statusCode - (statusCode % 100); + if (statusCodeClass != 200) { + DDLogError(@"%@ statusCode: %zd, %zd", self.logTag, statusCode, statusCodeClass); + DDLogError(@"%@ headers: %@", self.logTag, httpResponse.allHeaderFields); + [self failWithError:[NSError errorWithDomain:@"PastelogKit" + code:10001 + userInfo:@{ NSLocalizedDescriptionKey : @"Invalid response code." }]]; + } } -+ (void)submitLogsWithUploadCompletion:(DebugLogsUploadedBlock)block forFileLogger:(DDFileLogger *)fileLogger +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { + DDLogVerbose(@"%@ %s", self.logTag, __PRETTY_FUNCTION__); - [self sharedManager].block = block; + [self failWithError:error]; +} - [self sharedManager].loadingAlert = - [UIAlertController alertControllerWithTitle:NSLocalizedString(@"DEBUG_LOG_ACTIVITY_INDICATOR", - @"Message indicating that the debug log is being uploaded.") - message:nil - preferredStyle:UIAlertControllerStyleAlert]; - UIViewController *presentingViewController = UIApplication.sharedApplication.frontmostViewControllerIgnoringAlerts; - [presentingViewController presentViewController:[self sharedManager].loadingAlert animated:NO completion:nil]; +- (void)failWithError:(NSError *)error +{ + OWSAssert(error); - NSArray *logFilePaths = DebugLogger.sharedLogger.allLogFilePaths; + DDLogError(@"%@ %s %@", self.logTag, __PRETTY_FUNCTION__, error); - NSMutableDictionary *gistFiles = [NSMutableDictionary new]; + DispatchMainThreadSafe(^{ + // Call the completions exactly once. + if (self.failure) { + self.failure(self, error); + } + self.success = nil; + self.failure = nil; + }); +} - for (NSString *logFilePath in logFilePaths) { - NSError *error; - NSString *logContents = - [NSString stringWithContentsOfFile:logFilePath encoding:NSUTF8StringEncoding error:&error]; - if (error) { - OWSFail(@"%@ Error loading log file contents: %@", self.logTag, error); - continue; +- (void)succeedWithUrl:(NSURL *)url +{ + OWSAssert(url); + + DDLogVerbose(@"%@ %s %@", self.logTag, __PRETTY_FUNCTION__, url); + + DispatchMainThreadSafe(^{ + // Call the completions exactly once. + if (self.success) { + self.success(self, url); } - gistFiles[logFilePath.lastPathComponent] = @{ - @"content" : logContents, - }; - } + self.success = nil; + self.failure = nil; + }); +} - NSDictionary *gistDict = @{@"description":[self gistDescription], @"files":gistFiles}; +@end - NSData *postData = [NSJSONSerialization dataWithJSONObject:gistDict options:0 error:nil]; +#pragma mark - - NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[[NSURL alloc] initWithString:@"https://api.github.com/gists"] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:30]; +@interface Pastelog () - [[self sharedManager] setResponseData:[NSMutableData data]]; - [[self sharedManager] setBlock:block]; +@property (nonatomic) UIAlertController *loadingAlert; - [request setHTTPMethod:@"POST"]; - [request setHTTPBody:postData]; +@property (nonatomic) DebugLogUploader *currentUploader; - NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:[self sharedManager]]; +@end - [connection start]; +#pragma mark - -} +@implementation Pastelog -+(Pastelog*)sharedManager { ++ (instancetype)sharedManager +{ static Pastelog *sharedMyManager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - sharedMyManager = [[self alloc] init]; + sharedMyManager = [[self alloc] initDefault]; }); return sharedMyManager; } --(instancetype)init { - if (self = [super init]) { - self.responseData = [NSMutableData data]; +- (instancetype)initDefault +{ + self = [super init]; - OWSSingletonAssert(); + if (!self) { + return self; } + + OWSSingletonAssert(); + return self; } -+(NSString*)gistDescription{ - size_t size; - sysctlbyname("hw.machine", NULL, &size, NULL, 0); - char *machine = malloc(size); - sysctlbyname("hw.machine", machine, &size, NULL, 0); - NSString *platform = [NSString stringWithUTF8String:machine]; - free(machine); ++ (void)submitLogs +{ + [self submitLogsWithCompletion:nil]; +} - NSString *gistDesc = [NSString stringWithFormat:@"iPhone Version: %@, iOS Version: %@", platform,[UIDevice currentDevice].systemVersion]; ++ (void)submitLogsWithCompletion:(nullable SubmitDebugLogsCompletion)completionParam +{ + SubmitDebugLogsCompletion completion = ^{ + if (completionParam) { + // Wait a moment. If PasteLog opens a URL, it needs a moment to complete. + dispatch_after( + dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), completionParam); + } + }; - return gistDesc; + [self uploadLogsWithSuccess:^(NSURL *url) { + UIAlertController *alert = [UIAlertController + alertControllerWithTitle:NSLocalizedString(@"DEBUG_LOG_ALERT_TITLE", @"Title of the debug log alert.") + message:NSLocalizedString(@"DEBUG_LOG_ALERT_MESSAGE", @"Message of the debug log alert.") + preferredStyle:UIAlertControllerStyleAlert]; + [alert addAction:[UIAlertAction + actionWithTitle:NSLocalizedString(@"DEBUG_LOG_ALERT_OPTION_EMAIL", + @"Label for the 'email debug log' option of the the debug log alert.") + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *action) { + [Pastelog.sharedManager submitEmail:url]; + + completion(); + }]]; + [alert addAction:[UIAlertAction + actionWithTitle:NSLocalizedString(@"DEBUG_LOG_ALERT_OPTION_COPY_LINK", + @"Label for the 'copy link' option of the the debug log alert.") + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *action) { + UIPasteboard *pb = [UIPasteboard generalPasteboard]; + [pb setString:url.absoluteString]; + + completion(); + }]]; +#ifdef DEBUG + [alert addAction:[UIAlertAction + actionWithTitle:NSLocalizedString(@"DEBUG_LOG_ALERT_OPTION_SEND_TO_SELF", + @"Label for the 'send to self' option of the the debug log alert.") + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *action) { + [Pastelog.sharedManager sendToSelf:url]; + }]]; + [alert + addAction:[UIAlertAction + actionWithTitle:NSLocalizedString(@"DEBUG_LOG_ALERT_OPTION_SEND_TO_LAST_THREAD", + @"Label for the 'send to last thread' option of the the debug log alert.") + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *action) { + [Pastelog.sharedManager sendToMostRecentThread:url]; + }]]; +#endif + [alert + addAction:[UIAlertAction + actionWithTitle:NSLocalizedString(@"DEBUG_LOG_ALERT_OPTION_BUG_REPORT", + @"Label for the 'Open a Bug Report' option of the the debug log alert.") + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *action) { + [Pastelog.sharedManager prepareRedirection:url completion:completion]; + }]]; + [alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"DEBUG_LOG_ALERT_OPTION_SHARE", + @"Label for the 'Share' option of the the debug log alert.") + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *action) { + [AttachmentSharing showShareUIForText:url.absoluteString + completion:completion]; + }]]; + [alert addAction:[OWSAlerts cancelAction]]; + UIViewController *presentingViewController + = UIApplication.sharedApplication.frontmostViewControllerIgnoringAlerts; + [presentingViewController presentViewController:alert animated:NO completion:nil]; + }]; } -#pragma mark Network delegates ++ (void)uploadLogsWithSuccess:(nullable UploadDebugLogsSuccess)success +{ + OWSAssert(success); --(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{ - [self.responseData appendData:data]; + [[self sharedManager] uploadLogsWithSuccess:success + failure:^(NSString *localizedErrorMessage) { + [Pastelog showFailureAlertWithMessage:localizedErrorMessage]; + }]; } -- (void)connectionDidFinishLoading:(NSURLConnection *)connection { - [self.loadingAlert - dismissViewControllerAnimated:NO - completion:^{ - NSError *error; - NSDictionary *dict = - [NSJSONSerialization JSONObjectWithData:self.responseData options:0 error:&error]; - if (!error) { - self.block(nil, [dict objectForKey:@"html_url"]); - } else { - DDLogError(@"Error on debug response: %@", error); - self.block(error, nil); - } - }]; - self.loadingAlert = nil; -} +- (void)uploadLogsWithSuccess:(nullable UploadDebugLogsSuccess)successParam failure:(UploadDebugLogsFailure)failureParam +{ + OWSAssert(successParam); + OWSAssert(failureParam); + + // Ensure that we call the completions on the main thread. + UploadDebugLogsSuccess success = ^(NSURL *url) { + if (successParam) { + DispatchMainThreadSafe(^{ + successParam(url); + }); + } + }; + UploadDebugLogsFailure failure = ^(NSString *localizedErrorMessage) { + DispatchMainThreadSafe(^{ + failureParam(localizedErrorMessage); + }); + }; + + // Phase 1. Make a local copy of all of the log files. + NSDateFormatter *dateFormatter = [NSDateFormatter new]; + [dateFormatter setLocale:[NSLocale currentLocale]]; + [dateFormatter setDateFormat:@"yyyy.MM.dd hh.mm.ss"]; + NSString *dateString = [dateFormatter stringFromDate:[NSDate new]]; + NSString *logsName = [[dateString stringByAppendingString:@" "] stringByAppendingString:NSUUID.UUID.UUIDString]; + NSString *tempDirectory = NSTemporaryDirectory(); + NSString *zipFilePath = + [tempDirectory stringByAppendingPathComponent:[logsName stringByAppendingPathExtension:@"zip"]]; + NSString *zipDirPath = [tempDirectory stringByAppendingPathComponent:logsName]; + [OWSFileSystem ensureDirectoryExists:zipDirPath]; + [OWSFileSystem protectFileOrFolderAtPath:zipDirPath]; -- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { + NSArray *logFilePaths = DebugLogger.sharedLogger.allLogFilePaths; + if (logFilePaths.count < 1) { + failure(NSLocalizedString(@"DEBUG_LOG_ALERT_NO_LOGS", @"Error indicating that no debug logs could be found.")); + return; + } - NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response; + for (NSString *logFilePath in logFilePaths) { + NSString *copyFilePath = [zipDirPath stringByAppendingPathComponent:logFilePath.lastPathComponent]; + NSError *error; + [[NSFileManager defaultManager] copyItemAtPath:logFilePath toPath:copyFilePath error:&error]; + if (error) { + failure(NSLocalizedString( + @"DEBUG_LOG_ALERT_COULD_NOT_COPY_LOGS", @"Error indicating that the debug logs could not be copied.")); + return; + } + [OWSFileSystem protectFileOrFolderAtPath:copyFilePath]; + } - if ( [httpResponse statusCode] != 201) { - DDLogError(@"Failed to submit debug log: %@", httpResponse.debugDescription); - [self.loadingAlert - dismissViewControllerAnimated:NO - completion:^{ - [connection cancel]; - self.block([NSError errorWithDomain:@"PastelogKit" code:10001 userInfo:@{}], nil); - }]; - self.loadingAlert = nil; + // Phase 2. Zip up the log files. + BOOL zipSuccess = [SSZipArchive createZipFileAtPath:zipFilePath + withContentsOfDirectory:zipDirPath + keepParentDirectory:YES + compressionLevel:Z_DEFAULT_COMPRESSION + password:nil + AES:NO + progressHandler:nil]; + if (!zipSuccess) { + failure(NSLocalizedString( + @"DEBUG_LOG_ALERT_COULD_NOT_PACKAGE_LOGS", @"Error indicating that the debug logs could not be packaged.")); + return; } + + [OWSFileSystem protectFileOrFolderAtPath:zipFilePath]; + [OWSFileSystem deleteFile:zipDirPath]; + + // Phase 3. Upload the log files. + + __weak Pastelog *weakSelf = self; + self.currentUploader = [DebugLogUploader new]; + [self.currentUploader uploadFileWithURL:[NSURL fileURLWithPath:zipFilePath] + mimeType:@"application/zip" + success:^(DebugLogUploader *uploader, NSURL *url) { + if (uploader != weakSelf.currentUploader) { + // Ignore events from obsolete uploaders. + return; + } + [OWSFileSystem deleteFile:zipFilePath]; + success(url); + } + failure:^(DebugLogUploader *uploader, NSError *error) { + if (uploader != weakSelf.currentUploader) { + // Ignore events from obsolete uploaders. + return; + } + [OWSFileSystem deleteFile:zipFilePath]; + failure(NSLocalizedString( + @"DEBUG_LOG_ALERT_ERROR_UPLOADING_LOG", @"Error indicating that a debug log could not be uploaded.")); + }]; } -- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { - [self.loadingAlert dismissViewControllerAnimated:NO - completion:^{ - DDLogError(@"Uploading logs failed with error: %@", error); - self.block(error, nil); - }]; - self.loadingAlert = nil; ++ (void)showFailureAlertWithMessage:(NSString *)message +{ + UIAlertController *alert = [UIAlertController + alertControllerWithTitle:NSLocalizedString(@"DEBUG_LOG_ALERT_TITLE", + @"Title of the alert shown for failures while uploading debug logs.") + message:message + preferredStyle:UIAlertControllerStyleAlert]; + [alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"") + style:UIAlertActionStyleDefault + handler:nil]]; + UIViewController *presentingViewController = UIApplication.sharedApplication.frontmostViewControllerIgnoringAlerts; + [presentingViewController presentViewController:alert animated:NO completion:nil]; } #pragma mark Logs submission -- (void)submitEmail:(NSString*)url { +- (void)submitEmail:(NSURL *)url +{ NSString *emailAddress = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"LOGS_EMAIL"]; - NSString *urlString = [NSString stringWithString: [[NSString stringWithFormat:@"mailto:%@?subject=iOS%%20Debug%%20Log&body=", emailAddress] stringByAppendingString:[[NSString stringWithFormat:@"Log URL: %@ \n Tell us about the issue: ", url]stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]]]; + NSString *body = [NSString stringWithFormat:@"Log URL: %@ \n Tell us about the issue: ", url]; + NSString *escapedBody = + [body stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet]; + NSString *urlString = + [NSString stringWithFormat:@"mailto:%@?subject=iOS%%20Debug%%20Log&body=%@", emailAddress, escapedBody]; - [UIApplication.sharedApplication openURL: [NSURL URLWithString: urlString]]; + [UIApplication.sharedApplication openURL:[NSURL URLWithString:urlString]]; } -- (void)prepareRedirection:(NSString *)url shareCompletion:(DebugLogsSharedBlock)shareCompletion +- (void)prepareRedirection:(NSURL *)url completion:(SubmitDebugLogsCompletion)completion { - OWSAssert(shareCompletion); + OWSAssert(completion); UIPasteboard *pb = [UIPasteboard generalPasteboard]; - [pb setString:url]; + [pb setString:url.absoluteString]; UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"DEBUG_LOG_GITHUB_ISSUE_ALERT_TITLE", @@ -267,18 +492,18 @@ [alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"") style:UIAlertActionStyleDefault - handler:^(UIAlertAction *_Nonnull action) { + handler:^(UIAlertAction *action) { [UIApplication.sharedApplication openURL:[NSURL URLWithString:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"LOGS_URL"]]]; - shareCompletion(); + completion(); }]]; UIViewController *presentingViewController = UIApplication.sharedApplication.frontmostViewControllerIgnoringAlerts; [presentingViewController presentViewController:alert animated:NO completion:nil]; } -- (void)sendToSelf:(NSString *)url +- (void)sendToSelf:(NSURL *)url { if (![TSAccountManager isRegistered]) { return; @@ -288,35 +513,39 @@ DispatchMainThreadSafe(^{ __block TSThread *thread = nil; - [TSStorageManager.dbReadWriteConnection - readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { - thread = [TSContactThread getOrCreateThreadWithContactId:recipientId transaction:transaction]; - }]; - [ThreadUtil sendMessageWithText:url inThread:thread messageSender:messageSender]; + [TSStorageManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + thread = [TSContactThread getOrCreateThreadWithContactId:recipientId transaction:transaction]; + }]; + [ThreadUtil sendMessageWithText:url.absoluteString inThread:thread messageSender:messageSender]; }); // Also copy to pasteboard. - [[UIPasteboard generalPasteboard] setString:url]; + [[UIPasteboard generalPasteboard] setString:url.absoluteString]; } -- (void)sendToMostRecentThread:(NSString *)url +- (void)sendToMostRecentThread:(NSURL *)url { if (![TSAccountManager isRegistered]) { return; } - OWSMessageSender *messageSender = Environment.current.messageSender; + __block TSThread *thread = nil; + [TSStorageManager.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { + thread = [[transaction ext:TSThreadDatabaseViewExtensionName] firstObjectInGroup:TSInboxGroup]; + }]; DispatchMainThreadSafe(^{ - __block TSThread *thread = nil; - [TSStorageManager.dbReadWriteConnection - readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { - thread = [[transaction ext:TSThreadDatabaseViewExtensionName] firstObjectInGroup:[TSThread collection]]; - }]; - [ThreadUtil sendMessageWithText:url inThread:thread messageSender:messageSender]; + if (thread) { + OWSMessageSender *messageSender = Environment.current.messageSender; + [ThreadUtil sendMessageWithText:url.absoluteString inThread:thread messageSender:messageSender]; + } else { + [Pastelog showFailureAlertWithMessage:@"Could not find last thread."]; + } }); // Also copy to pasteboard. - [[UIPasteboard generalPasteboard] setString:url]; + [[UIPasteboard generalPasteboard] setString:url.absoluteString]; } @end + +NS_ASSUME_NONNULL_END diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index c68e554da..7bc110c58 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -499,12 +499,21 @@ /* The day before today. */ "DATE_YESTERDAY" = "Yesterday"; -/* Message indicating that the debug log is being uploaded. */ -"DEBUG_LOG_ACTIVITY_INDICATOR" = "Sending Debug Log..."; +/* Error indicating that the debug logs could not be copied. */ +"DEBUG_LOG_ALERT_COULD_NOT_COPY_LOGS" = "Could not copy logs."; + +/* Error indicating that the debug logs could not be packaged. */ +"DEBUG_LOG_ALERT_COULD_NOT_PACKAGE_LOGS" = "Could not package logs."; + +/* Error indicating that a debug log could not be uploaded. */ +"DEBUG_LOG_ALERT_ERROR_UPLOADING_LOG" = "Could not upload logs."; /* Message of the debug log alert. */ "DEBUG_LOG_ALERT_MESSAGE" = "What would you like to do with the link to your debug log?"; +/* Error indicating that no debug logs could be found. */ +"DEBUG_LOG_ALERT_NO_LOGS" = "Could not find any logs."; + /* Label for the 'Open a Bug Report' option of the the debug log alert. */ "DEBUG_LOG_ALERT_OPTION_BUG_REPORT" = "Open a Bug Report"; @@ -520,11 +529,12 @@ /* Label for the 'send to self' option of the the debug log alert. */ "DEBUG_LOG_ALERT_OPTION_SEND_TO_SELF" = "Send to Self"; -/* Title of the debug log alert. */ -"DEBUG_LOG_ALERT_TITLE" = "One More Step"; +/* Label for the 'Share' option of the the debug log alert. */ +"DEBUG_LOG_ALERT_OPTION_SHARE" = "Share"; -/* Title of the alert indicating the debug log upload failed. */ -"DEBUG_LOG_FAILURE_ALERT_TITLE" = "Failed to Submit Debug Log"; +/* Title of the alert shown for failures while uploading debug logs. + Title of the debug log alert. */ +"DEBUG_LOG_ALERT_TITLE" = "One More Step"; /* Message of the alert before redirecting to Github Issues. */ "DEBUG_LOG_GITHUB_ISSUE_ALERT_MESSAGE" = "The gist link was copied in your clipboard. You are about to be redirected to the GitHub issue list."; diff --git a/SignalMessaging/attachments/AttachmentSharing.h b/SignalMessaging/attachments/AttachmentSharing.h index 66bf2b833..712c77157 100644 --- a/SignalMessaging/attachments/AttachmentSharing.h +++ b/SignalMessaging/attachments/AttachmentSharing.h @@ -2,18 +2,28 @@ // Copyright (c) 2018 Open Whisper Systems. All rights reserved. // +NS_ASSUME_NONNULL_BEGIN + @class TSAttachmentStream; +typedef void (^AttachmentSharingCompletion)(void); + @interface AttachmentSharing : NSObject + (void)showShareUIForAttachment:(TSAttachmentStream *)stream; + (void)showShareUIForURL:(NSURL *)url; ++ (void)showShareUIForURL:(NSURL *)url completion:(nullable AttachmentSharingCompletion)completion; + + (void)showShareUIForText:(NSString *)text; ++ (void)showShareUIForText:(NSString *)text completion:(nullable AttachmentSharingCompletion)completion; + #ifdef DEBUG + (void)showShareUIForUIImage:(UIImage *)image; #endif @end + +NS_ASSUME_NONNULL_END diff --git a/SignalMessaging/attachments/AttachmentSharing.m b/SignalMessaging/attachments/AttachmentSharing.m index 7508a3645..c648ccd18 100644 --- a/SignalMessaging/attachments/AttachmentSharing.m +++ b/SignalMessaging/attachments/AttachmentSharing.m @@ -8,6 +8,8 @@ #import #import +NS_ASSUME_NONNULL_BEGIN + @implementation AttachmentSharing + (void)showShareUIForAttachment:(TSAttachmentStream *)stream @@ -18,21 +20,33 @@ } + (void)showShareUIForURL:(NSURL *)url +{ + [self showShareUIForURL:url completion:nil]; +} + ++ (void)showShareUIForURL:(NSURL *)url completion:(nullable AttachmentSharingCompletion)completion { OWSAssert(url); [AttachmentSharing showShareUIForActivityItems:@[ url, - ]]; + ] + completion:completion]; } + (void)showShareUIForText:(NSString *)text +{ + [self showShareUIForText:text completion:nil]; +} + ++ (void)showShareUIForText:(NSString *)text completion:(nullable AttachmentSharingCompletion)completion { OWSAssert(text); [AttachmentSharing showShareUIForActivityItems:@[ text, - ]]; + ] + completion:completion]; } #ifdef DEBUG @@ -42,11 +56,12 @@ [AttachmentSharing showShareUIForActivityItems:@[ image, - ]]; + ] + completion:nil]; } #endif -+ (void)showShareUIForActivityItems:(NSArray *)activityItems ++ (void)showShareUIForActivityItems:(NSArray *)activityItems completion:(nullable AttachmentSharingCompletion)completion { OWSAssert(activityItems); @@ -67,6 +82,10 @@ } else if (completed) { DDLogInfo(@"%@ Did share with activityType: %@", self.logTag, activityType); } + + if (completion) { + DispatchMainThreadSafe(completion); + } }]; UIViewController *fromViewController = CurrentAppContext().frontmostViewController; @@ -84,3 +103,5 @@ } @end + +NS_ASSUME_NONNULL_END diff --git a/SignalMessaging/profiles/OWSProfileManager.m b/SignalMessaging/profiles/OWSProfileManager.m index 9bcedf4da..d4476b9fc 100644 --- a/SignalMessaging/profiles/OWSProfileManager.m +++ b/SignalMessaging/profiles/OWSProfileManager.m @@ -7,7 +7,6 @@ #import "NSString+OWS.h" #import "OWSUserProfile.h" #import "UIImage+OWS.h" -#import #import #import #import diff --git a/SignalMessaging/utils/DebugLogger.h b/SignalMessaging/utils/DebugLogger.h index a3ec93bfb..a08037e98 100644 --- a/SignalMessaging/utils/DebugLogger.h +++ b/SignalMessaging/utils/DebugLogger.h @@ -1,9 +1,11 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import +NS_ASSUME_NONNULL_BEGIN + @interface DebugLogger : NSObject + (instancetype)sharedLogger; @@ -19,3 +21,5 @@ - (NSArray *)allLogFilePaths; @end + +NS_ASSUME_NONNULL_END diff --git a/SignalMessaging/utils/DebugLogger.m b/SignalMessaging/utils/DebugLogger.m index cb38f4f8f..9d859c6e5 100644 --- a/SignalMessaging/utils/DebugLogger.m +++ b/SignalMessaging/utils/DebugLogger.m @@ -11,9 +11,13 @@ #pragma mark Logging - Production logging wants us to write some logs to a file in case we need it for debugging. #import +NS_ASSUME_NONNULL_BEGIN + +const NSUInteger kMaxDebugLogFileSize = 1024 * 1024 * 3; + @interface DebugLogger () -@property (nonatomic) DDFileLogger *fileLogger; +@property (nonatomic, nullable) DDFileLogger *fileLogger; @end @@ -67,8 +71,7 @@ self.fileLogger.rollingFrequency = kDayInterval; // Keep last 3 days of logs - or last 3 logs (if logs rollover due to max file size). self.fileLogger.logFileManager.maximumNumberOfLogFiles = 3; - // Raise the max file size per log file to 3 MB. - self.fileLogger.maximumFileSize = 1024 * 1024 * 3; + self.fileLogger.maximumFileSize = kMaxDebugLogFileSize; self.fileLogger.logFormatter = [OWSScrubbingLogFormatter new]; [DDLog addLogger:self.fileLogger]; @@ -133,3 +136,5 @@ } @end + +NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Util/OWSError.h b/SignalServiceKit/src/Util/OWSError.h index 828d5401f..07a45610e 100644 --- a/SignalServiceKit/src/Util/OWSError.h +++ b/SignalServiceKit/src/Util/OWSError.h @@ -28,7 +28,8 @@ typedef NS_ENUM(NSInteger, OWSErrorCode) { OWSErrorCodeCouldNotWriteAttachmentData = 777409, OWSErrorCodeMessageDeletedBeforeSent = 777410, OWSErrorCodeDatabaseConversionFatalError = 777411, - OWSErrorCodeMoveFileToSharedDataContainerError = 777412 + OWSErrorCodeMoveFileToSharedDataContainerError = 777412, + OWSErrorCodeDebugLogUploadFailed = 777414, }; extern NSString *const OWSErrorRecipientIdentifierKey;