Commit d66fead4 authored by Martin's avatar Martin
Browse files

Merge branch 'master' into IOS-1120

parents 2851843d 47d0e16f
......@@ -4,16 +4,16 @@ OpenSSL-for-iPhone: 32c016ad67e4e929b5fa20613a027a6e1f416248
Pantomime: e235e6ed900af2e1f1ae4f648f610b2c4a99c64d
SwipeCellKit: 9cdeb3fea34352d7a69ed318e12759f9c6bdc189
changesets_script: 039c5be097e669e035bcf90f75c8428081de27d6
common-dependency-build-helpers-4-apple-hardware: 3e5a81e9fabd5adb0aea37ca96b7f68b1e055622
common-dependency-build-helpers-4-apple-hardware: 7f6820bbd40e1ebd1b66ba233f77d90b2ad028d5
ldns: 42b9bc034e66236599aa9fc7c1d8786ef33cf372
libAccountSettings: 7e8a7dd83610e3f867c8ff33a301f78ec51c9eb1
libetpan: 6423db53608e58774755767450757be00f1bf77e
libetpan: 482130edfac3aa058e38da398ae247852211149c
pEp-Translate: ffdbdef89d1aa13d0dd834e00121b0a783bf277a
pEpEngine: dc4dc6a838e5242764a5c52ef4b95a40946c2b5f tags/Release_2.1.49
pEpObjCAdapter: d10bfa0ac2cb4ff24e802ded6bb98f0847938396
pEpObjCAdapter: 898ea171c7d4a3dcd6570860a287a15b7bf27385
pep-toolbox: 09c7b58a841a9b6fda9dbfae33bfe6d831686b1f
pep4ios: e8049c91027a2465d3ce42479aaba2fce4233c90 tags/v1.1.264
pep4ios: 851b6e1e6b666b4202bda2ff6418cc6f8766b8bc
pep_for_ios_intern: 5bb17eb1255e341f22a0c36dd110a659e7e94309
sqlite: ad9c42f7cc31015d5702043eb02f127f183a660c
libiconv: 01b38e6c9fc240ca17afb32f31804785bc910b73
sequoia: f44d645fe665b031a1286e70075b69f92e5bb919 tags/openpgp/v1.3.0
sequoia: 269093abfc2cd3239169854bdd9045735fb54cf0 tags/Release_1.3.1_equals_1.3.0_plus_patches
......@@ -49,10 +49,6 @@ sudo port install pkgconfig
rustup update
rustup target add aarch64-apple-ios x86_64-apple-ios
sudo port pkgconfig
rustup update nightly
rustup default nightly
rustup component add rust-src
rustup default stable
```
### Set up Xcode
......
......@@ -42,6 +42,8 @@ public class VerifiableAccount: VerifiableAccountProtocol {
/// Someone who tells us whether or not to create a pEp folder for storing sync messages for
/// synced accounts.
private let usePEPFolderProvider: UsePEPFolderProviderProtocol?
public var originalImapPassword: String?
public var originalSmtpPassword: String?
// MARK: - VerifiableAccountProtocol (delegate)
......@@ -53,7 +55,8 @@ public class VerifiableAccount: VerifiableAccountProtocol {
public var address: String?
public var userName: String?
public var authMethod: AuthMethod?
public var password: String?
public var imapPassword: String?
public var smtpPassword: String?
public var keySyncEnable: Bool
public var accessToken: OAuth2AccessTokenProtocol?
public var clientCertificate: ClientCertificate?
......@@ -75,7 +78,8 @@ public class VerifiableAccount: VerifiableAccountProtocol {
address: String? = nil,
userName: String? = nil,
authMethod: AuthMethod? = nil,
password: String? = nil,
imapPassword: String? = nil,
smtpPassword: String? = nil,
accessToken: OAuth2AccessTokenProtocol? = nil,
loginNameIMAP: String? = nil,
serverIMAP: String? = nil,
......@@ -89,12 +93,15 @@ public class VerifiableAccount: VerifiableAccountProtocol {
manuallyTrustedImapServer: Bool = false,
keySyncEnable: Bool = true,
containsCompleteServerInfo: Bool = false,
usePEPFolderProvider: UsePEPFolderProviderProtocol? = nil) {
usePEPFolderProvider: UsePEPFolderProviderProtocol? = nil,
originalImapPassword: String? = nil,
originalSmtpPassword: String? = nil) {
self.verifiableAccountDelegate = verifiableAccountDelegate
self.address = address
self.userName = userName
self.authMethod = authMethod
self.password = password
self.imapPassword = imapPassword
self.smtpPassword = smtpPassword
self.accessToken = accessToken
self.loginNameIMAP = loginNameIMAP
self.serverIMAP = serverIMAP
......@@ -109,6 +116,8 @@ public class VerifiableAccount: VerifiableAccountProtocol {
self.keySyncEnable = keySyncEnable
self.containsCompleteServerInfo = containsCompleteServerInfo
self.usePEPFolderProvider = usePEPFolderProvider
self.originalImapPassword = originalImapPassword
self.originalSmtpPassword = originalSmtpPassword
}
// MARK: - VerifiableAccountProtocol (behaviour)
......@@ -198,13 +207,33 @@ extension VerifiableAccount {
switch theImapResult {
case .failure(let error):
resetPasswordsInKeychain()
verifiableAccountDelegate?.didEndVerification(result: .failure(error))
case .success(()):
switch theSmtpResult {
case .failure(let error):
resetPasswordsInKeychain()
verifiableAccountDelegate?.didEndVerification(result: .failure(error))
case .success(()):
self.verifiableAccountDelegate?.didEndVerification(result: .success(()))
verifiableAccountDelegate?.didEndVerification(result: .success(()))
}
}
}
// Set the original passwords again to save it in Key Chain.
// This prevents to have a failing password stored because of the account verification.
private func resetPasswordsInKeychain() {
let context = Stack.shared.newPrivateConcurrentContext
context.performAndWait {
if let address = address,
let cdAccount = CdAccount.by(address: address, context: context) {
let account = cdAccount.account()
if let originalPassword = originalImapPassword {
account.imapServer?.credentials.password = originalPassword
}
if let originalPassword = originalSmtpPassword {
account.smtpServer?.credentials.password = originalPassword
}
}
}
}
......@@ -214,8 +243,8 @@ extension VerifiableAccount {
extension VerifiableAccount {
private var isValidPassword: Bool {
if let pass = password {
return pass.count > 0
if let imapPass = imapPassword, let smtpPass = smtpPassword {
return imapPass.count > 0 && smtpPass.count > 0
}
return false
}
......@@ -226,8 +255,8 @@ extension VerifiableAccount {
(authMethod == .saslXoauth2 || (loginNameIMAP?.count ?? 0) >= 1) &&
(authMethod == .saslXoauth2 || (loginNameSMTP?.count ?? 0) >= 1) &&
(address?.count ?? 0) > 0 &&
((authMethod == .saslXoauth2 && accessToken != nil && password == nil) ||
(accessToken == nil && password != nil)) &&
((authMethod == .saslXoauth2 && accessToken != nil && imapPassword == nil && smtpPassword == nil) ||
(accessToken == nil && imapPassword != nil && smtpPassword != nil)) &&
portIMAP > 0 &&
portSMTP > 0 &&
(serverIMAP?.count ?? 0) > 0 &&
......@@ -364,7 +393,7 @@ extension VerifiableAccount {
credentials: theImapServer.credentials ?? CdServerCredentials(context: moc),
loginName: me.loginNameIMAP,
address: me.address,
password: me.password,
password: me.imapPassword,
clientCertificate: cdClientCertificate,
accessToken: me.accessToken)
credentialsImap.servers = NSSet(array: [theImapServer])
......@@ -374,7 +403,7 @@ extension VerifiableAccount {
credentials: theSmtpServer.credentials ?? CdServerCredentials(context: moc),
loginName: me.loginNameSMTP,
address: me.address,
password: me.password,
password: me.smtpPassword,
clientCertificate: cdClientCertificate,
accessToken: me.accessToken)
credentialsSmtp.servers = NSSet(array: [theSmtpServer])
......@@ -461,7 +490,6 @@ extension VerifiableAccount {
extension VerifiableAccount: VerifiableAccountIMAPDelegate {
func verified(verifier: VerifiableAccountIMAP,
result: Result<Void, Error>) {
verifier.delegate = nil
syncQueue.async { [weak self] in
self?.imapResult = result
self?.checkSuccess()
......@@ -474,7 +502,6 @@ extension VerifiableAccount: VerifiableAccountIMAPDelegate {
extension VerifiableAccount: VerifiableAccountSMTPDelegate {
func verified(verifier: VerifiableAccountSMTP,
result: Result<Void, Error>) {
verifier.delegate = nil
syncQueue.async { [weak self] in
self?.smtpResult = result
self?.checkSuccess()
......@@ -491,12 +518,15 @@ extension VerifiableAccount {
/// to find out if server data is still missing or not.
/// - Parameter type: The account type
public static func verifiableAccount(for type: AccountType,
usePEPFolderProvider: UsePEPFolderProviderProtocol? = nil) -> VerifiableAccountProtocol {
usePEPFolderProvider: UsePEPFolderProviderProtocol? = nil,
originalImapPassword: String? = nil,
originalSmtpPassword: String? = nil) -> VerifiableAccountProtocol {
var account = VerifiableAccount(verifiableAccountDelegate: nil,
address: nil,
userName: nil,
authMethod: .cramMD5,
password: nil,
imapPassword: nil,
smtpPassword: nil,
accessToken: nil,
loginNameIMAP: nil,
serverIMAP: nil,
......@@ -510,14 +540,18 @@ extension VerifiableAccount {
manuallyTrustedImapServer: false,
keySyncEnable: true,
containsCompleteServerInfo: false,
usePEPFolderProvider: usePEPFolderProvider)
usePEPFolderProvider: usePEPFolderProvider,
originalImapPassword: originalImapPassword,
originalSmtpPassword: originalSmtpPassword)
switch type {
case .gmail:
account = VerifiableAccount(verifiableAccountDelegate: nil,
address: nil,
userName: nil,
authMethod: .saslXoauth2,
password: nil,
imapPassword: nil,
smtpPassword: nil,
accessToken: nil,
loginNameIMAP: nil,
serverIMAP: "imap.gmail.com",
......@@ -537,7 +571,8 @@ extension VerifiableAccount {
address: nil,
userName: nil,
authMethod: .cramMD5,
password: nil,
imapPassword: nil,
smtpPassword: nil,
accessToken: nil,
loginNameIMAP: nil,
serverIMAP: "outlook.office365.com",
......@@ -557,7 +592,8 @@ extension VerifiableAccount {
address: nil,
userName: nil,
authMethod: .cramMD5,
password: nil,
imapPassword: nil,
smtpPassword: nil,
accessToken: nil,
loginNameIMAP: nil,
serverIMAP: "imap.mail.me.com",
......@@ -577,7 +613,8 @@ extension VerifiableAccount {
address: nil,
userName: nil,
authMethod: .cramMD5,
password: nil,
imapPassword: nil,
smtpPassword: nil,
accessToken: nil,
loginNameIMAP: nil,
serverIMAP: "outlook.office365.com",
......
......@@ -31,7 +31,7 @@ extension VerifiableAccountValidationError: LocalizedError {
}
/// The delegate used for the `VerifiableAccountProtocol`.
public protocol VerifiableAccountDelegate: class {
public protocol VerifiableAccountDelegate: AnyObject {
/// Gets called once the verification has finished, successfully or not.
/// The given `result` indicates success or failure.
func didEndVerification(result: Result<Void, Error>)
......@@ -74,8 +74,12 @@ public protocol VerifiableAccountProtocol {
var authMethod: AuthMethod? { get set }
/// The password, if needed, to log in.
/// Valid for both IMAP and SMTP servers.
var password: String? { get set }
/// Valid for IMAP servers.
var imapPassword: String? { get set }
/// The password, if needed, to log in.
/// Valid for SMTP servers.
var smtpPassword: String? { get set }
/// Enable/disale keySync to this account only. By default its true.
/// Only works if keySync is globally enable. Else will be ignored.
......
......@@ -14,7 +14,7 @@ import pEpIOSToolboxForExtensions
import pEpIOSToolbox
#endif
protocol SmtpConnectionDelegate: class {
protocol SmtpConnectionDelegate: AnyObject {
func messageSent(_ smtpConnection: SmtpConnectionProtocol, theNotification: Notification?)
func messageNotSent(_ smtpConnection: SmtpConnectionProtocol, theNotification: Notification?)
func transactionInitiationCompleted(_ smtpConnection: SmtpConnectionProtocol, theNotification: Notification?)
......
......@@ -16,7 +16,7 @@ import pEpIOSToolboxForExtensions
import pEpIOSToolbox
#endif
protocol VerifiableAccountIMAPDelegate: class {
protocol VerifiableAccountIMAPDelegate: AnyObject {
func verified(verifier: VerifiableAccountIMAP,
result: Result<Void, Error>)
}
......
......@@ -16,7 +16,7 @@ import pEpIOSToolboxForExtensions
import pEpIOSToolbox
#endif
protocol VerifiableAccountSMTPDelegate: class {
protocol VerifiableAccountSMTPDelegate: AnyObject {
func verified(verifier: VerifiableAccountSMTP,
result: Result<Void, Error>)
}
......@@ -80,6 +80,7 @@ extension VerifiableAccountSMTP: SmtpConnectionDelegate {
}
func authenticationCompleted(_ smtpConnection: SmtpConnectionProtocol, theNotification: Notification?) {
delegate?.verified(verifier: self, result: .success(()))
}
func authenticationFailed(_ smtpConnection: SmtpConnectionProtocol, theNotification: Notification?) {
......@@ -118,9 +119,7 @@ extension VerifiableAccountSMTP: SmtpConnectionDelegate {
notifyUnexpectedCallback(name: #function)
}
func serviceInitialized(_ smtpConnection: SmtpConnectionProtocol, theNotification: Notification?) {
delegate?.verified(verifier: self, result: .success(()))
}
func serviceInitialized(_ smtpConnection: SmtpConnectionProtocol, theNotification: Notification?) { }
func serviceReconnected(_ smtpConnection: SmtpConnectionProtocol, theNotification: Notification?) {
notifyUnexpectedCallback(name: #function)
......
......@@ -57,7 +57,8 @@ class VerifiableAccountTest: PersistentStoreDrivenTestBase {
let result = checkBasicVerification() { v in
var verifiable = v
verifiable.password = "xxxxxxxxxx"
verifiable.imapPassword = "xxxxxxxxxx"
verifiable.smtpPassword = "xxxxxxxxxx"
return verifiable
}
......@@ -169,7 +170,8 @@ extension VerifiableAccountTest {
// Note: auth method is never taken from LAS. We either have OAuth2,
// as determined previously, or we will defer to pantomime to find out the best method.
verifiableAccount.authMethod = nil
verifiableAccount.password = acc.imapServer?.credentials.password
verifiableAccount.imapPassword = acc.imapServer?.credentials.password
verifiableAccount.smtpPassword = acc.smtpServer?.credentials.password
verifiableAccount.accessToken = nil
verifiableAccount.serverIMAP = acc.imapServer?.address
verifiableAccount.portIMAP = (acc.imapServer?.port)!
......
......@@ -36,7 +36,8 @@ class TestDataBase {
var imapServerType: Server.ServerType = .imap
var imapServerTransport: Server.Transport = .startTls
var imapServerPort: UInt16 = 993
var password: String?
var imapPassword: String?
var smtpPassword: String?
init(accountName: String,
idAddress: String,
......@@ -51,7 +52,8 @@ class TestDataBase {
smtpServerType: Server.ServerType,
smtpServerTransport: Server.Transport,
smtpServerPort: UInt16,
password: String) {
imapPassword: String,
smtpPassword: String) {
self.accountName = accountName
self.idAddress = idAddress
self.idUserName = idUserName
......@@ -65,7 +67,8 @@ class TestDataBase {
self.imapServerType = imapServerType
self.imapServerTransport = imapServerTransport
self.imapServerPort = imapServerPort
self.password = password
self.imapPassword = imapPassword
self.smtpPassword = smtpPassword
}
func cdAccount(context: NSManagedObjectContext = Stack.shared.mainContext) -> CdAccount {
......@@ -86,7 +89,7 @@ class TestDataBase {
smtp.transport = smtpServerTransport
let keySmtp = UUID().uuidString
CdServerCredentials.add(password: password, forKey: keySmtp)
CdServerCredentials.add(password: smtpPassword, forKey: keySmtp)
let credSmtp = CdServerCredentials(context: context)
credSmtp.loginName = smtpLoginName ?? id.address
credSmtp.key = keySmtp
......@@ -99,7 +102,7 @@ class TestDataBase {
imap.transport = imapServerTransport
let keyImap = UUID().uuidString
CdServerCredentials.add(password: password, forKey: keyImap)
CdServerCredentials.add(password: imapPassword, forKey: keyImap)
let credImap = CdServerCredentials(context: context)
credImap.loginName = imapLoginName ?? id.address
credImap.key = keyImap
......@@ -146,7 +149,8 @@ class TestDataBase {
verifiableAccount.loginNameIMAP = imapLoginName ?? idAddress
verifiableAccount.loginNameSMTP = smtpLoginName ?? idAddress
verifiableAccount.accessToken = nil
verifiableAccount.password = password
verifiableAccount.imapPassword = "xxxxxxxxxx"
verifiableAccount.smtpPassword = "xxxxxxxxxx"
verifiableAccount.serverIMAP = imapServerAddress
verifiableAccount.portIMAP = imapServerPort
......@@ -208,7 +212,8 @@ class TestDataBase {
smtpServerTransport: Server.Transport.tls,
smtpServerPort: 465,
password: "whatever_you_want"))
imapPassword: "whatever_you_want",
smtpPassword: "whatever_you_want"))
fatalError("Abstract method. Must be overridden")
}
......@@ -232,7 +237,8 @@ class TestDataBase {
smtpServerTransport: Server.Transport.plain,
smtpServerPort: 3025,
password: "pwd"))
imapPassword: "pwd",
smtpPassword: "pwd"))
}
/**
......
......@@ -26,18 +26,18 @@
<dict>
<key>NSExtensionActivationRule</key>
<dict>
<key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
<integer>1</integer>
<key>NSExtensionActivationSupportsText</key>
<true/>
<key>NSExtensionActivationSupportsMovieWithMaxCount</key>
<integer>1</integer>
<key>NSExtensionActivationSupportsImageWithMaxCount</key>
<key>NSExtensionActivationSupportsAttachmentsWithMaxCount</key>
<integer>3</integer>
<key>NSExtensionActivationSupportsFileWithMaxCount</key>
<integer>3</integer>
<key>NSExtensionActivationSupportsAttachmentsWithMaxCount</key>
<key>NSExtensionActivationSupportsImageWithMaxCount</key>
<integer>3</integer>
<key>NSExtensionActivationSupportsMovieWithMaxCount</key>
<integer>1</integer>
<key>NSExtensionActivationSupportsText</key>
<true/>
<key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
<integer>1</integer>
</dict>
</dict>
<key>NSExtensionMainStoryboard</key>
......
......@@ -337,6 +337,16 @@ extension ShareViewModel {
img,
imgData,
mimeType))
} else if let img = item as? UIImage,
let data = img.jpeg(.high) {
let defaultImageName = "image"
let mimeType = itemProvider.supportedMimeTypeForInlineAttachment() ?? MimeTypeUtils.mimeType(fromFileExtension: "jpg")
sharedData.add(itemProvider: itemProvider,
dataWithType: .image(attributedTitle,
defaultImageName,
img,
data,
mimeType))
} else {
me.shareViewModelDelegate?.attachmentCouldNotBeLoaded(error: error)
}
......
......@@ -4042,7 +4042,7 @@
INFOPLIST_FILE = "pEp-share/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MARKETING_VERSION = 1.1.265;
MARKETING_VERSION = 1.1.266;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "security.pEp.pEp-share";
......@@ -4076,7 +4076,7 @@
INFOPLIST_FILE = "pEp-share/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MARKETING_VERSION = 1.1.265;
MARKETING_VERSION = 1.1.266;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "security.pEp.pEp-share";
PRODUCT_NAME = "$(TARGET_NAME)";
......@@ -4254,7 +4254,7 @@
INFOPLIST_FILE = pEpForiOS/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = "${inherited}";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.1.265;
MARKETING_VERSION = 1.1.266;
ONLY_ACTIVE_ARCH = "$(inherited)";
OTHER_SWIFT_FLAGS = "-DDEBUG_LOGGING -D DEBUG $(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = security.pEp;
......@@ -4293,7 +4293,7 @@
INFOPLIST_FILE = pEpForiOS/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = "${inherited}";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.1.265;
MARKETING_VERSION = 1.1.266;
ONLY_ACTIVE_ARCH = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = security.pEp;
PRODUCT_MODULE_NAME = pEpForiOS;
......
......@@ -8,6 +8,7 @@
import UIKit
import Photos
import PhotosUI
import ContactsUI
import SwipeCellKit
......@@ -479,19 +480,19 @@ extension ComposeViewController {
extension ComposeViewController {
private func presentMediaAttachmentPickerProvider() {
let media = Capability.media
media.requestAndInformUserInErrorCase(viewController: self) {
[weak self] (permissionsGranted: Bool, error: Capability.AccessError?) in
guard permissionsGranted else {
return
mediaAttachmentPickerProvider?.getPicker(from: self, { [weak self] picker in
guard let me = self else {
Log.shared.errorAndCrash("Lost myself")
return nil
}
guard let me = self,
let picker = me.mediaAttachmentPickerProvider?.imagePicker else {
// Valid case. We might have been dismissed already.
return
guard let picker = picker else {
// Valid case: lack of permissions for example.
// Nothing to do.
return nil
}
me.present(picker, animated: true)
}
return nil
})
}
}
......
......@@ -7,6 +7,13 @@
//
import UIKit
import UniformTypeIdentifiers
import PhotosUI
#if EXT_SHARE
import pEpIOSToolboxForExtensions
#else
import pEpIOSToolbox
#endif
class MediaAttachmentPickerProvider: NSObject {
public private(set) var imagePicker = UIImagePickerController()
......@@ -21,10 +28,33 @@ class MediaAttachmentPickerProvider: NSObject {
setup()
}
private func setup() {
imagePicker.delegate = self
if let mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary) {
imagePicker.mediaTypes = mediaTypes
/// Retrieve the picker if possible, otherwise nil.
/// It could be nil due lack of permissions.
/// - Parameters:
/// - requesterViewController: The VC that request the picker will be used to show alert to inform the user in case no permission is granted for iOS versions less than 14.
/// - callback: The callback with the picker.
public func getPicker(from requesterViewController: UIViewController, _ callback: @escaping (UIViewController?) -> ()?) {
if #available(iOS 14.0, *) {
var configuration = PHPickerConfiguration()
configuration.filter = .any(of: [.livePhotos, .images, .videos])
configuration.preferredAssetRepresentationMode = .current
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
callback(picker)
} else {
let media = Capability.media
media.requestAndInformUserInErrorCase(viewController: requesterViewController)