Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • enzevalos/enzevalos_iphone
1 result
Show changes
Commits on Source (6)
Showing
with 657 additions and 270 deletions
...@@ -41,3 +41,5 @@ DerivedData ...@@ -41,3 +41,5 @@ DerivedData
DerivedData.noindex DerivedData.noindex
*.xcuserstate *.xcuserstate
*.swp *.swp
private
*.zip
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
0E1C457D24055F87006D104A /* signencinlineK9.eml in Resources */ = {isa = PBXBuildFile; fileRef = 0E1C457924055F87006D104A /* signencinlineK9.eml */; }; 0E1C457D24055F87006D104A /* signencinlineK9.eml in Resources */ = {isa = PBXBuildFile; fileRef = 0E1C457924055F87006D104A /* signencinlineK9.eml */; };
0E1C458024055FB7006D104A /* Alice.v3.pubsec.asc in Resources */ = {isa = PBXBuildFile; fileRef = 0E1C457E24055FB7006D104A /* Alice.v3.pubsec.asc */; }; 0E1C458024055FB7006D104A /* Alice.v3.pubsec.asc in Resources */ = {isa = PBXBuildFile; fileRef = 0E1C457E24055FB7006D104A /* Alice.v3.pubsec.asc */; };
0E1C458124055FB7006D104A /* Alice.v3.pub.asc in Resources */ = {isa = PBXBuildFile; fileRef = 0E1C457F24055FB7006D104A /* Alice.v3.pub.asc */; }; 0E1C458124055FB7006D104A /* Alice.v3.pub.asc in Resources */ = {isa = PBXBuildFile; fileRef = 0E1C457F24055FB7006D104A /* Alice.v3.pub.asc */; };
0E6551A72406A42300DE30FC /* SearchHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E6551A62406A42300DE30FC /* SearchHelper.swift */; };
3E6B07DE2011246500E49609 /* invitationText.html in Resources */ = {isa = PBXBuildFile; fileRef = 3E6B07DD2011246500E49609 /* invitationText.html */; }; 3E6B07DE2011246500E49609 /* invitationText.html in Resources */ = {isa = PBXBuildFile; fileRef = 3E6B07DD2011246500E49609 /* invitationText.html */; };
3EB4FA9F2012007C001D0625 /* DialogViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EB4FA9D2012007C001D0625 /* DialogViewController.swift */; }; 3EB4FA9F2012007C001D0625 /* DialogViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EB4FA9D2012007C001D0625 /* DialogViewController.swift */; };
3EB4FAA12012007C001D0625 /* Dialog.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3EB4FA9E2012007C001D0625 /* Dialog.storyboard */; }; 3EB4FAA12012007C001D0625 /* Dialog.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3EB4FA9E2012007C001D0625 /* Dialog.storyboard */; };
...@@ -270,6 +271,7 @@ ...@@ -270,6 +271,7 @@
0E1C457924055F87006D104A /* signencinlineK9.eml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = signencinlineK9.eml; sourceTree = "<group>"; }; 0E1C457924055F87006D104A /* signencinlineK9.eml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = signencinlineK9.eml; sourceTree = "<group>"; };
0E1C457E24055FB7006D104A /* Alice.v3.pubsec.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Alice.v3.pubsec.asc; sourceTree = "<group>"; }; 0E1C457E24055FB7006D104A /* Alice.v3.pubsec.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Alice.v3.pubsec.asc; sourceTree = "<group>"; };
0E1C457F24055FB7006D104A /* Alice.v3.pub.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Alice.v3.pub.asc; sourceTree = "<group>"; }; 0E1C457F24055FB7006D104A /* Alice.v3.pub.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Alice.v3.pub.asc; sourceTree = "<group>"; };
0E6551A62406A42300DE30FC /* SearchHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchHelper.swift; sourceTree = "<group>"; };
1D4A9E60565DECF52C011BC0 /* Pods-enzevalos_iphone-AdHoc.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-enzevalos_iphone-AdHoc.release.xcconfig"; path = "../enzevalos_iphone_workspace/Pods/Target Support Files/Pods-enzevalos_iphone-AdHoc/Pods-enzevalos_iphone-AdHoc.release.xcconfig"; sourceTree = "<group>"; }; 1D4A9E60565DECF52C011BC0 /* Pods-enzevalos_iphone-AdHoc.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-enzevalos_iphone-AdHoc.release.xcconfig"; path = "../enzevalos_iphone_workspace/Pods/Target Support Files/Pods-enzevalos_iphone-AdHoc/Pods-enzevalos_iphone-AdHoc.release.xcconfig"; sourceTree = "<group>"; };
3E6B07DD2011246500E49609 /* invitationText.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = invitationText.html; path = Invitation/invitationText.html; sourceTree = "<group>"; }; 3E6B07DD2011246500E49609 /* invitationText.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = invitationText.html; path = Invitation/invitationText.html; sourceTree = "<group>"; };
3E9708AD1FAC925D005825C9 /* enzevalos_iphone.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = enzevalos_iphone.entitlements; sourceTree = "<group>"; }; 3E9708AD1FAC925D005825C9 /* enzevalos_iphone.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = enzevalos_iphone.entitlements; sourceTree = "<group>"; };
...@@ -1149,6 +1151,7 @@ ...@@ -1149,6 +1151,7 @@
A1EB05971D956947008659C1 /* InboxViewController.swift */, A1EB05971D956947008659C1 /* InboxViewController.swift */,
F120607F1DA540FE00F6EF37 /* RefreshControlExtension.swift */, F120607F1DA540FE00F6EF37 /* RefreshControlExtension.swift */,
A1F9923B1DA7DD2E0073BF1B /* InboxTableViewCell.xib */, A1F9923B1DA7DD2E0073BF1B /* InboxTableViewCell.xib */,
0E6551A62406A42300DE30FC /* SearchHelper.swift */,
); );
name = inbox; name = inbox;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -1642,6 +1645,7 @@ ...@@ -1642,6 +1645,7 @@
472F39701E14F75C009260FB /* DataHandler.swift in Sources */, 472F39701E14F75C009260FB /* DataHandler.swift in Sources */,
A1C62E9A2018F716000E5273 /* OnboardingValueState.swift in Sources */, A1C62E9A2018F716000E5273 /* OnboardingValueState.swift in Sources */,
A1EB05901D956923008659C1 /* ReadViewController.swift in Sources */, A1EB05901D956923008659C1 /* ReadViewController.swift in Sources */,
0E6551A72406A42300DE30FC /* SearchHelper.swift in Sources */,
472F398E1E251B8D009260FB /* MailAddress.swift in Sources */, 472F398E1E251B8D009260FB /* MailAddress.swift in Sources */,
A198D2292056B384004CC838 /* SendViewDelegate.swift in Sources */, A198D2292056B384004CC838 /* SendViewDelegate.swift in Sources */,
479011492289975D0057AB04 /* NoSecIconStyleKit.swift in Sources */, 479011492289975D0057AB04 /* NoSecIconStyleKit.swift in Sources */,
......
...@@ -1084,6 +1084,14 @@ class DataHandler { ...@@ -1084,6 +1084,14 @@ class DataHandler {
return result return result
} }
// filter all presistent mails without public key
func getAllNoPublicKeyPersistentMail() -> [PersistentMail] {
let result = getAllPersistentMails().filter({ $0.sigState == SignatureState.NoPublicKey })
return result
}
func getAllNotSignedPersistentMail() -> [PersistentMail] { func getAllNotSignedPersistentMail() -> [PersistentMail] {
let result = getAllPersistentMails().filter({ $0.sigState == SignatureState.NoPublicKey }) let result = getAllPersistentMails().filter({ $0.sigState == SignatureState.NoPublicKey })
return result return result
......
...@@ -36,7 +36,11 @@ fileprivate func < <T : Comparable>(lhs: T?, rhs: T?) -> Bool { ...@@ -36,7 +36,11 @@ fileprivate func < <T : Comparable>(lhs: T?, rhs: T?) -> Bool {
} }
} }
/**
EnzevalosContact is used for persons and items of the address book (by apple).
One enzevalosContact maps to one person/item of the address book.
One enzevalosContact links to multiple key records since the person have multiple keys.
*/
@objc(EnzevalosContact) @objc(EnzevalosContact)
open class EnzevalosContact: NSManagedObject, Contact, Comparable { open class EnzevalosContact: NSManagedObject, Contact, Comparable {
...@@ -57,6 +61,9 @@ open class EnzevalosContact: NSManagedObject, Contact, Comparable { ...@@ -57,6 +61,9 @@ open class EnzevalosContact: NSManagedObject, Contact, Comparable {
} }
} }
/**
Just like nameOptional or a localized variant of "no name". Just in case you like to enforce a name.
*/
open var name: String { open var name: String {
if let name = nameOptional { if let name = nameOptional {
return name return name
...@@ -146,6 +153,9 @@ open class EnzevalosContact: NSManagedObject, Contact, Comparable { ...@@ -146,6 +153,9 @@ open class EnzevalosContact: NSManagedObject, Contact, Comparable {
} }
} }
/**
A set of associated public keys
*/
var publicKeys: Set<PersistentKey> { var publicKeys: Set<PersistentKey> {
get { get {
var pks = Set<PersistentKey>() var pks = Set<PersistentKey>()
...@@ -155,7 +165,9 @@ open class EnzevalosContact: NSManagedObject, Contact, Comparable { ...@@ -155,7 +165,9 @@ open class EnzevalosContact: NSManagedObject, Contact, Comparable {
return pks return pks
} }
} }
/**
A set of associated key records
*/
open var records: [KeyRecord] { open var records: [KeyRecord] {
get { get {
if let krecords = self.keyrecords as? Set<KeyRecord> { if let krecords = self.keyrecords as? Set<KeyRecord> {
...@@ -195,6 +207,9 @@ open class EnzevalosContact: NSManagedObject, Contact, Comparable { ...@@ -195,6 +207,9 @@ open class EnzevalosContact: NSManagedObject, Contact, Comparable {
return date return date
} }
/**
Related item in the address book (from apple)
*/
open var cnContact: CNContact? { open var cnContact: CNContact? {
get { get {
if let cn = cnidentifier { if let cn = cnidentifier {
...@@ -207,6 +222,9 @@ open class EnzevalosContact: NSManagedObject, Contact, Comparable { ...@@ -207,6 +222,9 @@ open class EnzevalosContact: NSManagedObject, Contact, Comparable {
} }
} }
/**
Create a new cnContact in the address book.
*/
open var newCnContact: CNContact { open var newCnContact: CNContact {
let con = CNMutableContact() let con = CNMutableContact()
let name = self.displayname let name = self.displayname
...@@ -241,13 +259,6 @@ open class EnzevalosContact: NSManagedObject, Contact, Comparable { ...@@ -241,13 +259,6 @@ open class EnzevalosContact: NSManagedObject, Contact, Comparable {
return nil return nil
} }
func getAddressByMCOAddress(_ mcoaddress: MCOAddress) -> Mail_Address? {
if (mcoaddress.mailbox) != nil {
return getAddress(mcoaddress.mailbox.lowercased())
}
return nil
}
open func getMailAddresses() -> [MailAddress] { open func getMailAddresses() -> [MailAddress] {
var adr = [MailAddress] () var adr = [MailAddress] ()
for a in addresses { for a in addresses {
...@@ -257,6 +268,9 @@ open class EnzevalosContact: NSManagedObject, Contact, Comparable { ...@@ -257,6 +268,9 @@ open class EnzevalosContact: NSManagedObject, Contact, Comparable {
return adr return adr
} }
/**
Is the address associated to the person(enzevalos contact)
*/
func isAddress(mailadr: String) -> Bool { func isAddress(mailadr: String) -> Bool {
for adr in getMailAddresses() { for adr in getMailAddresses() {
if mailadr.lowercased() == adr.mailAddress.lowercased() { if mailadr.lowercased() == adr.mailAddress.lowercased() {
......
...@@ -29,6 +29,9 @@ extension EnzevalosContact { ...@@ -29,6 +29,9 @@ extension EnzevalosContact {
} }
@NSManaged public var displayname: String? @NSManaged public var displayname: String?
/**
Identifier to look up contact in the address book
*/
@NSManaged public var cnidentifier: String? @NSManaged public var cnidentifier: String?
@NSManaged public var color: UIColor? @NSManaged public var color: UIColor?
@NSManaged public var addresses: NSSet @NSManaged public var addresses: NSSet
......
...@@ -41,6 +41,9 @@ public class Folder: NSManagedObject { ...@@ -41,6 +41,9 @@ public class Folder: NSManagedObject {
} }
} }
/**
Please read the RFC.
*/
var uids: MCOIndexSet { var uids: MCOIndexSet {
get { get {
......
...@@ -22,9 +22,15 @@ extension Folder { ...@@ -22,9 +22,15 @@ extension Folder {
@NSManaged public var keyRecords: NSSet? @NSManaged public var keyRecords: NSSet?
@NSManaged public var path: String //backendFolderPath @NSManaged public var path: String //backendFolderPath
@NSManaged public var lastUpdate: Date? @NSManaged public var lastUpdate: Date?
/**
Used for logging.
*/
@NSManaged public var pseudonym: String @NSManaged public var pseudonym: String
@NSManaged public var icon: String? @NSManaged public var icon: String?
/**
Please read the RFC!
*/
public var uidvalidity: UInt32? { public var uidvalidity: UInt32? {
set { set {
if let num = newValue { if let num = newValue {
......
...@@ -39,6 +39,11 @@ class InboxViewController: UITableViewController, InboxCellDelegator { ...@@ -39,6 +39,11 @@ class InboxViewController: UITableViewController, InboxCellDelegator {
} }
} }
} }
// how many seconds should the app wait before processing search bar input
private let searchDelay = 0.5
// holds the currently active search timer (if it exists) so it can be terminated if a new character is typed before the execution
private var searchBarTimer: Timer?
@IBOutlet weak var lastUpdateButton: UIBarButtonItem! @IBOutlet weak var lastUpdateButton: UIBarButtonItem!
var lastUpdateLabel = UILabel(frame: CGRect.zero) var lastUpdateLabel = UILabel(frame: CGRect.zero)
...@@ -248,34 +253,60 @@ class InboxViewController: UITableViewController, InboxCellDelegator { ...@@ -248,34 +253,60 @@ class InboxViewController: UITableViewController, InboxCellDelegator {
return searchController.isActive && !searchBarIsEmpty return searchController.isActive && !searchBarIsEmpty
} }
func filterContentForSearchText(_ searchText: String, scope: Int = 0) { /**
var records = [KeyRecord]() searches a given string with a delay so that the entire client doesn't lag if the inbox is very big
if scope == 0 || scope == 3 {
records += folder.records.filter({ (record: KeyRecord) -> Bool in - parameters:
return record.name.lowercased().contains(searchText.lowercased()) - searchText: srtring to look for
}) - scope: where to search (look at _filterContentForSearchText)
} */
if scope == 1 || scope == 3 { func startSearch(searchText: String, scope: Int = 0) {
records += folder.records.filter({ (record: KeyRecord) -> Bool in // check if a search has been scheduled already and stop it to prevent multiple searches
let mails = record.inboxMails if let searchBarTimer: Timer = self.searchBarTimer {
return mails.filter({ (mail: PersistentMail) -> Bool in searchBarTimer.invalidate()
mail.subject?.lowercased().contains(searchText.lowercased()) ?? false
}).count > 0
})
} }
if scope == 2 || scope == 3 {
records += folder.records.filter({ (record: KeyRecord) -> Bool in self.searchBarTimer = Timer.scheduledTimer(withTimeInterval: searchDelay, repeats: false, block: { _ in
let mails = record.inboxMails self._filterContentForSearchText(searchText, scope: scope)
return mails.filter({ (mail: PersistentMail) -> Bool in })
}
/**
Filters emails by a user input string and scope
- parameters:
- scope: 0 = contact name; 1 = subject; 2 = body; 3 = all
- searchText: the string we are looking for
*/
private func _filterContentForSearchText(_ searchText: String, scope: Int = 0) {
let records = folder.records.filter({ (record: KeyRecord) -> Bool in
if scope == 0
{
return containsSearchTerms(content: record.name, searchText: searchText)
}
let mails = record.inboxMails
return mails.filter({ (mail: PersistentMail) -> Bool in
// concatenate all strings that fall in our scope
var str = ""
if scope == 1 || scope == 3
{
str.append(contentsOf: mail.subject ?? "")
}
if scope == 2 || scope == 3
{
if let decryptedBody = mail.decryptedBody { if let decryptedBody = mail.decryptedBody {
return decryptedBody.lowercased().contains(searchText.lowercased()) str.append(decryptedBody)
} else if !mail.isEncrypted { } else if !mail.isEncrypted {
return mail.body?.lowercased().contains(searchText.lowercased()) ?? false str.append(contentsOf: mail.body ?? "")
} }
return false }
if scope == 3
{
str.append(contentsOf: record.name)
}
return containsSearchTerms(content: str, searchText: searchText)
}).count > 0 }).count > 0
}) })
}
filteredRecords = records.unique.sorted() filteredRecords = records.unique.sorted()
tableView.reloadData() tableView.reloadData()
...@@ -286,13 +317,13 @@ extension InboxViewController: UISearchResultsUpdating { ...@@ -286,13 +317,13 @@ extension InboxViewController: UISearchResultsUpdating {
// https://www.raywenderlich.com/157864/uisearchcontroller-tutorial-getting-started // https://www.raywenderlich.com/157864/uisearchcontroller-tutorial-getting-started
func updateSearchResults(for searchController: UISearchController) { func updateSearchResults(for searchController: UISearchController) {
filterContentForSearchText(searchController.searchBar.text!, scope: searchController.searchBar.selectedScopeButtonIndex) startSearch(searchText: searchController.searchBar.text!, scope: searchController.searchBar.selectedScopeButtonIndex)
} }
} }
extension InboxViewController: UISearchBarDelegate { extension InboxViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) { func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
filterContentForSearchText(searchBar.text!, scope: selectedScope) startSearch(searchText: searchBar.text!, scope: selectedScope)
} }
} }
......
...@@ -23,12 +23,17 @@ import CoreData ...@@ -23,12 +23,17 @@ import CoreData
import Contacts import Contacts
import UIKit import UIKit
/**
Key records are mostly used in the inbox and for id (views). For each key we have a single key record. There are also key records for each mail address without keys, for instance when receiving unsigned mails.
One person can have multiple key records, e.g. one with key, one without a key or multiple keys.
*/
@objc(KeyRecord) @objc(KeyRecord)
public class KeyRecord: NSManagedObject, Record { public class KeyRecord: NSManagedObject, Record {
public var isUser: Bool { public var isUser: Bool {
get{ get{
/* /**
A keyrecord matches to the user if: A keyrecord matches to the user if:
* we know the secret key, because we are the key owner * we know the secret key, because we are the key owner
* the mail addresses matches * the mail addresses matches
...@@ -45,6 +50,9 @@ public class KeyRecord: NSManagedObject, Record { ...@@ -45,6 +50,9 @@ public class KeyRecord: NSManagedObject, Record {
} }
} }
/**
Does the key record has a secret key?
*/
public var isSecretKey: Bool { public var isSecretKey: Bool {
if let id = self.keyID { if let id = self.keyID {
return DataHandler.handler.findSecretKey(keyID: id) != nil return DataHandler.handler.findSecretKey(keyID: id) != nil
...@@ -86,6 +94,11 @@ public class KeyRecord: NSManagedObject, Record { ...@@ -86,6 +94,11 @@ public class KeyRecord: NSManagedObject, Record {
return nil return nil
} }
/**
MyNick is unique where as multiple key records can have the same name.
It is used to display different key records.
*/
public var myNick: String { public var myNick: String {
if let n = self.nick { if let n = self.nick {
return n return n
...@@ -109,6 +122,10 @@ public class KeyRecord: NSManagedObject, Record { ...@@ -109,6 +122,10 @@ public class KeyRecord: NSManagedObject, Record {
return id return id
} }
/**
One person can have multiple key records, e.g. one with key, one without a key or multiple keys.
In case of multiple keys we have a primaryID. The key of this id is used for decryption etc.
*/
public var isPrimaryID: Bool { public var isPrimaryID: Bool {
if let keyID = self.keyID { if let keyID = self.keyID {
for addr in self.addresses { for addr in self.addresses {
...@@ -129,6 +146,9 @@ public class KeyRecord: NSManagedObject, Record { ...@@ -129,6 +146,9 @@ public class KeyRecord: NSManagedObject, Record {
} }
} }
/**
It is the current fingerprint of the public key.
*/
public var fingerprint: String? { public var fingerprint: String? {
get { get {
if let k = pgpKey { if let k = pgpKey {
...@@ -154,12 +174,19 @@ public class KeyRecord: NSManagedObject, Record { ...@@ -154,12 +174,19 @@ public class KeyRecord: NSManagedObject, Record {
} }
} }
/**
EnzevalosContact provides some contact information about the key record.
*/
public var ezContact: EnzevalosContact { public var ezContact: EnzevalosContact {
get { get {
return contact return contact
} }
} }
/**
Is a list of all received mails from this record.
*/
public var mails: [PersistentMail] { public var mails: [PersistentMail] {
get { get {
if let m = persistentMails as? Set<PersistentMail> { if let m = persistentMails as? Set<PersistentMail> {
...@@ -168,7 +195,10 @@ public class KeyRecord: NSManagedObject, Record { ...@@ -168,7 +195,10 @@ public class KeyRecord: NSManagedObject, Record {
return [] return []
} }
} }
/**
cnContact is the original corresponding contact in the address book.
*/
public var cnContact: CNContact? { public var cnContact: CNContact? {
get { get {
return contact.cnContact return contact.cnContact
...@@ -195,6 +225,9 @@ public class KeyRecord: NSManagedObject, Record { ...@@ -195,6 +225,9 @@ public class KeyRecord: NSManagedObject, Record {
} }
} }
/**
Corresponding mail addresses to the current key.
*/
public var addresses: [MailAddress] { public var addresses: [MailAddress] {
get { get {
if let k = activeKey { if let k = activeKey {
......
...@@ -68,6 +68,9 @@ class ListViewController: UITableViewController { ...@@ -68,6 +68,9 @@ class ListViewController: UITableViewController {
} }
} }
var loading = false var loading = false
private let searchDelay = 0.5
private var searchTimer: Timer?
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
tableView.reloadData() tableView.reloadData()
...@@ -105,63 +108,53 @@ class ListViewController: UITableViewController { ...@@ -105,63 +108,53 @@ class ListViewController: UITableViewController {
deinit { deinit {
print("===============|| ListViewController deinitialized ||===============") print("===============|| ListViewController deinitialized ||===============")
} }
func filterContentForSearchText(_ searchText: String, scope: Int = 0) { func startSearch(searchText: String, scope: Int = 0) {
// check if a search has been scheduled already and stop it to prevent multiple searches
if let searchBarTimer: Timer = self.searchTimer {
searchBarTimer.invalidate()
}
self.searchTimer = Timer.scheduledTimer(withTimeInterval: searchDelay, repeats: false, block: { _ in
self.filterContentForSearchText(searchText, scope: scope)
})
}
/**
- parameters:
- searchText: user input string to look for
- scope : 0 = subject: 1 = body: 2 = cc + to: 3 = all
*/
private func filterContentForSearchText(_ searchText: String, scope: Int = 0) {
filteredMails = contact!.mails.filter { mail in filteredMails = contact!.mails.filter { mail in
var returnValue = false // a big string that we search through, contains everything from the scopes we are searching in
switch scope { var str = ""
case 0:
if let subject = mail.subject { if scope == 0 || scope == 3 {
returnValue = subject.lowercased().contains(searchText.lowercased()) str.append(mail.subject ?? "")
} }
case 1: if scope == 1 || scope == 3 {
if !returnValue && mail.decryptedBody != nil { if let decryptedBody = mail.decryptedBody {
returnValue = mail.decryptedBody!.lowercased().contains(searchText.lowercased()) str.append(decryptedBody)
} else if !returnValue && mail.body != nil { } else if let body = mail.body {
returnValue = mail.body!.lowercased().contains(searchText.lowercased()) str.append(body)
}
case 2:
if !returnValue && mail.cc?.count > 0 {
if let result = mail.cc?.contains(where: { cc -> Bool in
if let mail = cc as? MailAddress {
return mail.mailAddress.contains(searchText.lowercased())
}
return false
}) {
returnValue = result
}
}
if !returnValue && mail.getReceivers().count > 1 {
returnValue = mail.getReceivers().contains(where: { rec -> Bool in
return rec.mailAddress.contains(searchText.lowercased())
})
}
default:
if let subject = mail.subject {
returnValue = subject.lowercased().contains(searchText.lowercased())
}
if !returnValue && mail.decryptedBody != nil {
returnValue = mail.decryptedBody!.lowercased().contains(searchText.lowercased())
} else if !returnValue && mail.body != nil && !mail.isEncrypted {
returnValue = mail.body!.lowercased().contains(searchText.lowercased())
}
if !returnValue && mail.cc?.count > 0 {
if let res = mail.cc?.contains(where: { cc -> Bool in
if let mail = cc as? MailAddress {
return mail.mailAddress.contains(searchText.lowercased())
}
return false
}) {
returnValue = res
}
}
if !returnValue && mail.getReceivers().count > 1 {
returnValue = mail.getReceivers().contains(where: { rec -> Bool in
return rec.mailAddress.contains(searchText.lowercased())
})
} }
} }
return returnValue if scope == 2 || scope == 3 {
var receivers: [MailAddress] = []
receivers.append(contentsOf: mail.getReceivers())
receivers.append(contentsOf: mail.getCCs())
// build a string of all email addresses to input in the search function
receivers.map({ addr -> String in
return addr.mailAddress
}).forEach({ addr in
str.append(addr)
})
}
return containsSearchTerms(content: str, searchText: searchText)
} }
tableView.reloadData() tableView.reloadData()
...@@ -259,13 +252,12 @@ class ListViewController: UITableViewController { ...@@ -259,13 +252,12 @@ class ListViewController: UITableViewController {
extension ListViewController: UISearchResultsUpdating { extension ListViewController: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) { func updateSearchResults(for searchController: UISearchController) {
let searchBar = searchController.searchBar let searchBar = searchController.searchBar
let _ = searchBar.scopeButtonTitles![searchBar.selectedScopeButtonIndex] startSearch(searchText: searchController.searchBar.text!, scope: searchBar.selectedScopeButtonIndex)
filterContentForSearchText(searchController.searchBar.text!, scope: searchBar.selectedScopeButtonIndex)
} }
} }
extension ListViewController: UISearchBarDelegate { extension ListViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) { func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
filterContentForSearchText(searchBar.text!, scope: selectedScope) startSearch(searchText: searchBar.text!, scope: selectedScope)
} }
} }
...@@ -25,7 +25,9 @@ import Contacts ...@@ -25,7 +25,9 @@ import Contacts
@objc(Mail_Address) @objc(Mail_Address)
open class Mail_Address: NSManagedObject, MailAddress { open class Mail_Address: NSManagedObject, MailAddress {
/**
What key should be used to send encrypted messages or to verify messages?
*/
public var primaryKey: PersistentKey? { public var primaryKey: PersistentKey? {
get { get {
if hasKey { if hasKey {
...@@ -44,6 +46,9 @@ open class Mail_Address: NSManagedObject, MailAddress { ...@@ -44,6 +46,9 @@ open class Mail_Address: NSManagedObject, MailAddress {
return address.lowercased() return address.lowercased()
} }
/**
In the address book a mail address has a label (e.g. work, private, ...).
*/
open var label: CNLabeledValue<NSString> { open var label: CNLabeledValue<NSString> {
if let cnc = self.contact?.cnContact { if let cnc = self.contact?.cnContact {
for adr in cnc.emailAddresses { for adr in cnc.emailAddresses {
...@@ -62,6 +67,9 @@ open class Mail_Address: NSManagedObject, MailAddress { ...@@ -62,6 +67,9 @@ open class Mail_Address: NSManagedObject, MailAddress {
return false return false
} }
/**
Is this a mail address of the user?
*/
public var isUser: Bool { public var isUser: Bool {
get { get {
if let userAddr = UserManager.loadUserValue(Attribute.userAddr) as? String { if let userAddr = UserManager.loadUserValue(Attribute.userAddr) as? String {
...@@ -71,6 +79,9 @@ open class Mail_Address: NSManagedObject, MailAddress { ...@@ -71,6 +79,9 @@ open class Mail_Address: NSManagedObject, MailAddress {
} }
} }
/**
Just create a MCOAddress. Mailcore (our IMAP/SMTP library) needs MCOAddresses to send mails etc.
*/
public func transform () -> MCOAddress { public func transform () -> MCOAddress {
var name = address var name = address
if let contact = contact { if let contact = contact {
......
...@@ -34,9 +34,18 @@ extension Mail_Address { ...@@ -34,9 +34,18 @@ extension Mail_Address {
@NSManaged public var cc: NSSet? @NSManaged public var cc: NSSet?
@NSManaged public var from: NSSet? @NSManaged public var from: NSSet?
@NSManaged public var to: NSSet? @NSManaged public var to: NSSet?
/**
Just for logging.
*/
@NSManaged public var pseudonym: String @NSManaged public var pseudonym: String
@NSManaged public var primaryKeyID: String? //TODO: set to private? /**
What key should be used to send encrypted messages or to verify messages?
*/
@NSManaged public var primaryKeyID: String?
@NSManaged private var keys: NSSet? @NSManaged private var keys: NSSet?
/**
Did we invited the mail address owner to use encryption?
*/
@NSManaged public var invitations: Int16 @NSManaged public var invitations: Int16
var primaryActiveKeyID: String? { var primaryActiveKeyID: String? {
......
...@@ -9,6 +9,13 @@ ...@@ -9,6 +9,13 @@
import Foundation import Foundation
import CoreData import CoreData
/**
Is a stored public key.
It stores the keydata, some additional information and relations to key records etc.
A key can be part of a key chain, such that one key introduced another key (yet not implemented)
*/
@objc(PersistentKey) @objc(PersistentKey)
public class PersistentKey: NSManagedObject { public class PersistentKey: NSManagedObject {
...@@ -44,6 +51,9 @@ public class PersistentKey: NSManagedObject { ...@@ -44,6 +51,9 @@ public class PersistentKey: NSManagedObject {
return self.verifiedDate != nil return self.verifiedDate != nil
} }
/**
Is the key expired (according to the crypto scheme)?
*/
func isExpired() -> Bool { func isExpired() -> Bool {
let pgp = SwiftPGP() let pgp = SwiftPGP()
if let key = pgp.loadKey(id: self.keyID) { if let key = pgp.loadKey(id: self.keyID) {
......
...@@ -18,22 +18,62 @@ extension PersistentKey { ...@@ -18,22 +18,62 @@ extension PersistentKey {
@NSManaged public var keyID: String @NSManaged public var keyID: String
@NSManaged public var verifiedDate: Date? @NSManaged public var verifiedDate: Date?
/**
When did we received the last signed mail?
*/
@NSManaged public var lastSeen: Date? @NSManaged public var lastSeen: Date?
/**
When did we received the last mail with autocrypt header?
*/
@NSManaged public var lastSeenAutocrypt: Date? @NSManaged public var lastSeenAutocrypt: Date?
/**
When did we imported the key?
*/
@NSManaged public var discoveryDate: Date? @NSManaged public var discoveryDate: Date?
@NSManaged private var mailaddress: NSSet? @NSManaged private var mailaddress: NSSet?
/**
What is the mail which contains this key (only the first)?
*/
@NSManaged public var firstMail: PersistentMail? @NSManaged public var firstMail: PersistentMail?
/**
A pseudonym was used for logging.
*/
@NSManaged public var pseudonym: String @NSManaged public var pseudonym: String
/**
Did we send our own public key to the owner of this public key?
This means does the owner knows our public key?
*/
@NSManaged public var sentOwnPublicKey: Bool @NSManaged public var sentOwnPublicKey: Bool
@NSManaged public var signedMails: NSSet? @NSManaged public var signedMails: NSSet?
@NSManaged private var record: KeyRecord? @NSManaged private var record: KeyRecord?
@NSManaged private var activeKey: PersistentKey? @NSManaged private var activeKey: PersistentKey?
/**
This is only for the travler scenario. You can ignore it.
*/
@NSManaged public var activeRepeal: PersistentMail? @NSManaged public var activeRepeal: PersistentMail?
/**
Currently not used.
*/
@NSManaged private var parentKey: PersistentKey? @NSManaged private var parentKey: PersistentKey?
/**
Currently not used.
*/
@NSManaged private var childKeys: NSSet? @NSManaged private var childKeys: NSSet?
/**
This is only for the travler scenario. You can ignore it.
*/
@NSManaged public var repealedByMails: NSSet? @NSManaged public var repealedByMails: NSSet?
/**
This is only for the travler scenario. You can ignore it.
*/
@NSManaged private var isRepealed: Bool @NSManaged private var isRepealed: Bool
/**
This is only for the travler scenario. You can ignore it.
*/
@NSManaged private var gotFailedCallForUse: Bool @NSManaged private var gotFailedCallForUse: Bool
/**
This is only for the travler scenario. You can ignore it.
*/
@NSManaged private var isMisstrusted: Bool @NSManaged private var isMisstrusted: Bool
var mailaddresses: NSSet? { var mailaddresses: NSSet? {
...@@ -64,6 +104,9 @@ extension PersistentKey { ...@@ -64,6 +104,9 @@ extension PersistentKey {
return parentKey != nil return parentKey != nil
} }
/**
Currently not used.
*/
var rootKey: PersistentKey { var rootKey: PersistentKey {
get { get {
var key = self var key = self
...@@ -100,7 +143,9 @@ extension PersistentKey { ...@@ -100,7 +143,9 @@ extension PersistentKey {
keys.append(rootKey) keys.append(rootKey)
return keys return keys
} }
/**
This is only for the travler scenario. You can ignore it.
*/
public var repealed: Bool { public var repealed: Bool {
get { get {
return rootKey.isRepealed return rootKey.isRepealed
...@@ -109,7 +154,9 @@ extension PersistentKey { ...@@ -109,7 +154,9 @@ extension PersistentKey {
rootKey.isRepealed = newRepealState rootKey.isRepealed = newRepealState
} }
} }
/**
This is only for the travler scenario. You can ignore it.
*/
public var failedCallForUse: Bool { public var failedCallForUse: Bool {
get { get {
return rootKey.gotFailedCallForUse return rootKey.gotFailedCallForUse
...@@ -118,7 +165,9 @@ extension PersistentKey { ...@@ -118,7 +165,9 @@ extension PersistentKey {
rootKey.gotFailedCallForUse = newState rootKey.gotFailedCallForUse = newState
} }
} }
/**
This is only for the travler scenario. You can ignore it.
*/
public var misstrust: Bool { public var misstrust: Bool {
get { get {
return rootKey.isMisstrusted return rootKey.isMisstrusted
...@@ -127,7 +176,9 @@ extension PersistentKey { ...@@ -127,7 +176,9 @@ extension PersistentKey {
rootKey.isMisstrusted = trust rootKey.isMisstrusted = trust
} }
} }
/**
This is the autocrypt prefer enc state.
*/
public var prefer_encryption: EncState{ public var prefer_encryption: EncState{
set { set {
let name = "preferEncryption" let name = "preferEncryption"
......
...@@ -21,7 +21,16 @@ ...@@ -21,7 +21,16 @@
import Foundation import Foundation
import CoreData import CoreData
/**
A PersistentMail stores all information about one mail:
- Sender, receivers
- subject, date
- body
- encryption state
- signature state
- attached files, keys
*/
@objc(PersistentMail) @objc(PersistentMail)
open class PersistentMail: NSManagedObject, Mail { open class PersistentMail: NSManagedObject, Mail {
public var predecessor: PersistentMail? = nil public var predecessor: PersistentMail? = nil
...@@ -66,6 +75,9 @@ open class PersistentMail: NSManagedObject, Mail { ...@@ -66,6 +75,9 @@ open class PersistentMail: NSManagedObject, Mail {
} }
} }
/**
This the signed first mail of the signed key?
*/
var isNewPubKey: Bool { var isNewPubKey: Bool {
guard let signedKey = self.signedKey else { guard let signedKey = self.signedKey else {
return false return false
...@@ -77,6 +89,9 @@ open class PersistentMail: NSManagedObject, Mail { ...@@ -77,6 +89,9 @@ open class PersistentMail: NSManagedObject, Mail {
return false return false
} }
/**
Just a flag if the user read this mail.
*/
var isRead: Bool { var isRead: Bool {
get { get {
let value = flag.contains(MCOMessageFlag.seen) let value = flag.contains(MCOMessageFlag.seen)
...@@ -92,6 +107,9 @@ open class PersistentMail: NSManagedObject, Mail { ...@@ -92,6 +107,9 @@ open class PersistentMail: NSManagedObject, Mail {
} }
} }
/**
Just a flag if the user answered the mail.
*/
var isAnwered: Bool { var isAnwered: Bool {
get { get {
let value = flag.contains(MCOMessageFlag.answered) let value = flag.contains(MCOMessageFlag.answered)
...@@ -132,6 +150,10 @@ open class PersistentMail: NSManagedObject, Mail { ...@@ -132,6 +150,10 @@ open class PersistentMail: NSManagedObject, Mail {
return returnString return returnString
} }
/**
Just a short part of the body. Can be used for a preview.
In case of trouble there is no preview.
*/
var shortBodyString: String? { var shortBodyString: String? {
guard !trouble else { guard !trouble else {
return nil return nil
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
import Foundation import Foundation
import CoreData import CoreData
extension PersistentMail { extension PersistentMail {
@nonobjc open override class func fetchRequest() -> NSFetchRequest<NSFetchRequestResult> { @nonobjc open override class func fetchRequest() -> NSFetchRequest<NSFetchRequestResult> {
...@@ -29,11 +28,20 @@ extension PersistentMail { ...@@ -29,11 +28,20 @@ extension PersistentMail {
} }
@NSManaged public var body: String? @NSManaged public var body: String?
/**
Deprecated
*/
@NSManaged public var visibleBody: String? @NSManaged public var visibleBody: String?
@NSManaged public var decryptedBody: String? @NSManaged public var decryptedBody: String?
@NSManaged public var encryptedBody: String? @NSManaged public var encryptedBody: String?
@NSManaged public var date: Date @NSManaged public var date: Date
@NSManaged public var secretKey: String? // secret key which is in the mail (to import) /**
secret key which is attacted to the mail (to import)
*/
@NSManaged public var secretKey: String?
/**
The corresponding key record
*/
@NSManaged public var record: KeyRecord? @NSManaged public var record: KeyRecord?
public var hasAttachment: Bool { public var hasAttachment: Bool {
...@@ -45,6 +53,9 @@ extension PersistentMail { ...@@ -45,6 +53,9 @@ extension PersistentMail {
} }
} }
/**
Some mail flags, e.g. read flag, answered flag (according to RFC)
*/
public var flag: MCOMessageFlag { public var flag: MCOMessageFlag {
set { set {
if newValue != flag { if newValue != flag {
...@@ -68,28 +79,86 @@ extension PersistentMail { ...@@ -68,28 +79,86 @@ extension PersistentMail {
} }
} }
/**
Please use encryption state
*/
@NSManaged public var isEncrypted: Bool @NSManaged public var isEncrypted: Bool
/**
This mail is signed but check isSigned, too.
We recommand to use signature state
*/
@NSManaged public var isSigned: Bool @NSManaged public var isSigned: Bool
/**
We could verify the signature (with a given public key)
*/
@NSManaged public var isCorrectlySigned: Bool @NSManaged public var isCorrectlySigned: Bool
/**
This mail is encrypted but we could not decrypt the message (e.g. the secret key is missing)
*/
@NSManaged public var unableToDecrypt: Bool @NSManaged public var unableToDecrypt: Bool
/**
Subject of a mail (according to RFC)
*/
@NSManaged public var subject: String? @NSManaged public var subject: String?
/**
Which folder is used to store the mail?
*/
@NSManaged public var folder: Folder @NSManaged public var folder: Folder
@NSManaged public var firstKey: PersistentKey? // NOT USED /**
Not used.
*/
@NSManaged public var firstKey: PersistentKey?
/**
What key is the signature key of this mail?
*/
@NSManaged public var signedKey: PersistentKey? @NSManaged public var signedKey: PersistentKey?
/**
Did we received the mail?
*/
@NSManaged public var received: Bool @NSManaged public var received: Bool
/**
Only used in traveler scenario.
*/
@NSManaged public var deleteWhileTravel: Bool @NSManaged public var deleteWhileTravel: Bool
/**
Only used in traveler scenario.
*/
@NSManaged public var storeEncrypted: Bool @NSManaged public var storeEncrypted: Bool
/**
Only used in traveler scenario.
*/
@NSManaged public var repealsKey: PersistentKey? @NSManaged public var repealsKey: PersistentKey?
/**
This can be used for threading. This is defined in a RFC.
*/
@NSManaged public var gmailMessageID: NSNumber? @NSManaged public var gmailMessageID: NSNumber?
/**
This can be used for threading. This is defined in a RFC.
*/
@NSManaged public var gmailThreadID: NSNumber? @NSManaged public var gmailThreadID: NSNumber?
/**
Please read up this mail in the RFC!
*/
@NSManaged public var messageID: String? @NSManaged public var messageID: String?
/**
Currently not used.
*/
@NSManaged public var notLoadedMessages: String? @NSManaged public var notLoadedMessages: String?
@NSManaged public var decryptedKey: PersistentKey? // Only for traveler scenario /**
Only for traveler scenario.
*/
@NSManaged public var decryptedKey: PersistentKey?
/**
Sender mail client.
*/
@NSManaged public var xMailer: String? @NSManaged public var xMailer: String?
/**
Key id of the signature key.
TODO rename to signedKeyID
*/
public var keyID: String? { public var keyID: String? {
set { set {
self.willChangeValue(forKey: "keyID") self.willChangeValue(forKey: "keyID")
...@@ -116,6 +185,9 @@ extension PersistentMail { ...@@ -116,6 +185,9 @@ extension PersistentMail {
} }
/**
Does this mail has some (crypto) errors, e.g. manipulated encryption or signature?
*/
public var trouble: Bool { public var trouble: Bool {
set { set {
self.willChangeValue(forKey: "trouble") self.willChangeValue(forKey: "trouble")
...@@ -130,6 +202,9 @@ extension PersistentMail { ...@@ -130,6 +202,9 @@ extension PersistentMail {
} }
} }
/**
Please read the RFC!
*/
public var uid: UInt64 { public var uid: UInt64 {
set { set {
self.willChangeValue(forKey: "uid") self.willChangeValue(forKey: "uid")
...@@ -146,6 +221,9 @@ extension PersistentMail { ...@@ -146,6 +221,9 @@ extension PersistentMail {
return 0 return 0
} }
} }
/**
Please read the RFC!
*/
public var uidvalidity: UInt32? { public var uidvalidity: UInt32? {
set { set {
if let num = newValue { if let num = newValue {
...@@ -215,6 +293,9 @@ extension PersistentMail { ...@@ -215,6 +293,9 @@ extension PersistentMail {
} }
/**
Enter a password and if possible import the secret keys.
*/
public func processSecretKey(pw: String?) throws -> Bool { public func processSecretKey(pw: String?) throws -> Bool {
var sk = "" var sk = ""
if let key = secretKey { if let key = secretKey {
...@@ -232,6 +313,9 @@ extension PersistentMail { ...@@ -232,6 +313,9 @@ extension PersistentMail {
@NSManaged public var cc: NSSet? @NSManaged public var cc: NSSet?
@NSManaged public var to: NSSet @NSManaged public var to: NSSet
@NSManaged public var attachments: NSSet? @NSManaged public var attachments: NSSet?
/**
Can be used for threading. Please read the RFC.
*/
@NSManaged public var referenceMails: NSSet? @NSManaged public var referenceMails: NSSet?
} }
......
//
// SearchHelper.swift
// enzevalos_iphone
//
// Created by lazarog98 on 26.02.20.
// Copyright © 2020 fu-berlin. All rights reserved.
//
import Foundation
/**
A collection of helper methods that are used for the different search bars
*/
/**
Function to be used to find mails that contain the search terms. All terms (separated by spaces) need to be contained in the search text.
- parameters:
- content: The String that will be searched
- searchText: Search terms (space-separated) that will be searched for
*/
func containsSearchTerms ( content : String?, searchText: String) -> Bool
{
guard searchText.count > 0 else {
///Case empty search
return true
}
guard let content = content else {
//Case Mail has no body/subject
return false
}
var longterms : [String] = []
var terms : [String] = []
//Break String into substrings separated by quoatation marks
longterms = searchText.components(separatedBy: "\"")
var i = 0
//even elements will be outside the quotation marks and need to be separated again
while (i < longterms.count)
{
if i % 2 == 0
{
terms.append(contentsOf: longterms[i].lowercased().components(separatedBy: " "))
}
else
{
terms.append(longterms[i].lowercased())
}
i+=1
}
var found = true
for t in terms
{
if !(t == "")
{
found = found && content.lowercased().contains(t)
}
}
return found
}
...@@ -10,19 +10,39 @@ ...@@ -10,19 +10,39 @@
import Foundation import Foundation
import CoreData import CoreData
/**
*/
extension SecretKey { extension SecretKey {
@nonobjc public class func fetchRequest() -> NSFetchRequest<SecretKey> { @nonobjc public class func fetchRequest() -> NSFetchRequest<SecretKey> {
return NSFetchRequest<SecretKey>(entityName: "SecretKey") return NSFetchRequest<SecretKey>(entityName: "SecretKey")
} }
/**
Did we exported the secretkey?
*/
@NSManaged public var exported: Bool @NSManaged public var exported: Bool
/**
When did we import the secretkey?
*/
@NSManaged public var importedDate: NSDate? @NSManaged public var importedDate: NSDate?
@NSManaged public var keyID: String @NSManaged public var keyID: String
/**
Used in the travler scenario. Just ignore it.
*/
@NSManaged public var obsolete: Bool @NSManaged public var obsolete: Bool
/**
Not used yet. Should store how we imported the key (generated on device, imported from mail via autorcrypt, via iTunes, ...)
*/
@NSManaged public var origin: Int16 @NSManaged public var origin: Int16
/**
Just added in case of multiple accounts.
*/
@NSManaged public var account: Account? @NSManaged public var account: Account?
/**
A Set of mails where as the key was used for decryption.
*/
@NSManaged public var decryptedMails: NSSet? @NSManaged public var decryptedMails: NSSet?
} }
......
...@@ -592,30 +592,34 @@ class SwiftPGP: Encryption { ...@@ -592,30 +592,34 @@ class SwiftPGP: Encryption {
return CryptoObject(chiphertext: data, plaintext: plaintext, decryptedData: plaindata, sigState: sigState, encState: encState, signKey: sigKeyID, encType: CryptoScheme.PGP, signedAdrs: signedAdr) return CryptoObject(chiphertext: data, plaintext: plaintext, decryptedData: plaindata, sigState: sigState, encState: encState, signKey: sigKeyID, encType: CryptoScheme.PGP, signedAdrs: signedAdr)
} }
// A help function for findMailForSecrectKey and findNotSignedMailForPublicKey
func keyAsKeyList(keyID: String) -> [Key] { func keyAsKeyList(keyID: String) -> [Key] {
var keyList = [Key]() var keyList = [Key]()
let key: Key = loadKey(id: keyID)! if let key: Key = loadKey(id: keyID) {
keyList.append(key) keyList.append(key)
}
return keyList return keyList
} }
func findMailForKey(keyID: String) { // Finds undecrypted mails in persistent mails and and tries to decrypt with the incoming secret key
var plaindata: Data? = nil func findMailForSecretKey(keyID: String) {
var encState = EncryptionState.UnableToDecrypt var encState = EncryptionState.UnableToDecrypt
var plaindata: Data? = nil
let key: [Key] = keyAsKeyList(keyID: keyID) let key: [Key] = keyAsKeyList(keyID: keyID)
let datahandler = DataHandler.handler let datahandler = DataHandler.handler
let mailList = datahandler.getAllNotDecryptedPersistentMail() let mailList = datahandler.getAllNotDecryptedPersistentMail()
for mail in mailList { for mail in mailList {
guard let data = mail.body?.data(using: String.Encoding.utf8, allowLossyConversion: true) // Change data
else { guard let data = mail.body?.data(using: .utf8) else {
return return
} }
// try to decrypt mail // Try to decrypt mail
(plaindata, encState) = decryptMessage(data: data, keys: key, encForCurrentSK: true) (plaindata, encState) = decryptMessage(data: data, keys: key, encForCurrentSK: true)
if let plaindata = plaindata, encState == EncryptionState.ValidedEncryptedWithCurrentKey || encState == EncryptionState.ValidEncryptedWithOldKey { if let plaindata = plaindata, encState == EncryptionState.ValidedEncryptedWithCurrentKey || encState == EncryptionState.ValidEncryptedWithOldKey {
// update database // Update database
mail.body = String.init(data: plaindata, encoding: .utf8)
mail.isEncrypted = true mail.isEncrypted = true
mail.unableToDecrypt = false
mail.body = String.init(data: plaindata, encoding: .utf8)
datahandler.save(during: "decryption of older mails") datahandler.save(during: "decryption of older mails")
} }
} }
...@@ -647,6 +651,28 @@ class SwiftPGP: Encryption { ...@@ -647,6 +651,28 @@ class SwiftPGP: Encryption {
return (nil, EncryptionState.NoEncryption) return (nil, EncryptionState.NoEncryption)
} }
// Finds unsigned mails in persistent mails and and tries to verify them with the incoming public key
func findNotSignedMailForPublicKey(keyID: String) {
var sigState = SignatureState.NoPublicKey
let key: [Key] = keyAsKeyList(keyID: keyID)
let datahandler = DataHandler.handler
let mailList = datahandler.getAllNotSignedPersistentMail()
for mail in mailList {
// Change data
guard let data = mail.body?.data(using: .utf8) else {
return
}
// Try to verify mail signature
sigState = verifySignature(data: data, attachedSignature: nil, keys: key)
if sigState == SignatureState.ValidSignature {
// Update database
mail.isSigned = true
mail.isCorrectlySigned = true
datahandler.save(during: "verifying of older mails")
}
}
}
private func verifySignature(sigString: String, attachedSignature: Data?, keys: [Key]) -> SignatureState { private func verifySignature(sigString: String, attachedSignature: Data?, keys: [Key]) -> SignatureState {
if let unarmored = try? Armor.readArmored(sigString){ if let unarmored = try? Armor.readArmored(sigString){
return verifySignature(data: unarmored, attachedSignature: attachedSignature, keys: keys) return verifySignature(data: unarmored, attachedSignature: attachedSignature, keys: keys)
......