...
 
Commits (66)
This diff is collapsed.
......@@ -48,7 +48,7 @@
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A13526961D955BE000D3BFE1"
BlueprintIdentifier = "476EEF9522A872BF00BB4EF7"
BuildableName = "enzevalos_iphoneUITests.xctest"
BlueprintName = "enzevalos_iphoneUITests"
ReferencedContainer = "container:enzevalos_iphone.xcodeproj">
......@@ -65,11 +65,6 @@
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
<AdditionalOption
key = "NSZombieEnabled"
value = "YES"
isEnabled = "YES">
</AdditionalOption>
</AdditionalOptions>
</TestAction>
<LaunchAction
......
......@@ -53,7 +53,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// Register defaults for signature handling
UserDefaults.standard.register(defaults: ["Signature.Switch": false])
UserDefaults.standard.register(defaults: ["Signature.Text": "Verfasst mit Letterbox. Mehr Informationen: http://letterbox.imp.fu-berlin.de?invitation=0"])
UserDefaults.standard.register(defaults: ["Signature.Text": "Verfasst mit Letterbox. Mehr Informationen: http://letterbox-app.org"])
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = Onboarding.onboarding()
......@@ -144,27 +144,27 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
})
let handler = DataHandler.init()
let keyId = handler.createNewSecretKey(adr: UserManager.loadUserValue(Attribute.userAddr) as! String)
_ = handler.getContact(name: UserManager.loadUserValue(Attribute.accountname) as! String, address: UserManager.loadUserValue(Attribute.userAddr) as! String, key: keyId.keyID!, prefer_enc: true)
_ = handler.getContact(name: UserManager.loadUserValue(Attribute.accountname) as! String, address: UserManager.loadUserValue(Attribute.userAddr) as! String, key: keyId.keyID, prefer_enc: true)
handler.save(during: "setup user")
StudySettings.setupStudyKeys()
Mailbot.firstMail()
DataHandler.handler.callForFolders(done: { err in
for f in DataHandler.handler.allFolders {
if f.flags.contains(MCOIMAPFolderFlag.drafts) {
UserManager.storeUserValue(f.path as AnyObject?, attribute: Attribute.draftFolderPath)
}
if f.flags.contains(MCOIMAPFolderFlag.sentMail) {
UserManager.storeUserValue(f.path as AnyObject?, attribute: Attribute.sentFolderPath)
}
if f.flags.contains(MCOIMAPFolderFlag.trash) {
UserManager.storeUserValue(f.path as AnyObject?, attribute: Attribute.trashFolderPath)
}
if f.flags.contains(MCOIMAPFolderFlag.archive) {
UserManager.storeUserValue(f.path as AnyObject?, attribute: Attribute.archiveFolderPath)
}
if f.flags.contains(MCOIMAPFolderFlag.inbox) {
UserManager.storeUserValue(f.path as AnyObject?, attribute: Attribute.inboxFolderPath)
}
if f.flags.contains(MCOIMAPFolderFlag.drafts) {
UserManager.storeUserValue(f.path as AnyObject?, attribute: Attribute.draftFolderPath)
}
if f.flags.contains(MCOIMAPFolderFlag.sentMail) {
UserManager.storeUserValue(f.path as AnyObject?, attribute: Attribute.sentFolderPath)
}
if f.flags.contains(MCOIMAPFolderFlag.trash) {
UserManager.storeUserValue(f.path as AnyObject?, attribute: Attribute.trashFolderPath)
}
if f.flags.contains(MCOIMAPFolderFlag.archive) {
UserManager.storeUserValue(f.path as AnyObject?, attribute: Attribute.archiveFolderPath)
}
if f.flags.contains(MCOIMAPFolderFlag.inbox) {
UserManager.storeUserValue(f.path as AnyObject?, attribute: Attribute.inboxFolderPath)
}
}
DispatchQueue.main.async(execute: {
self.onboardingDone()
......
......@@ -114,14 +114,13 @@ class Autocrypt {
let encPref = EncState.MUTUAL
let pgp = SwiftPGP()
if let id = skID {
if let key = pgp.exportKey(id: id, isSecretkey: false, autocrypt: true) {
var string = "\(ADDR)=" + adr
string = string + "; \(ENCRYPTION)=\(encPref.name)"
string = string + "; \(KEY)=" + key
builder.header.setExtraHeaderValue(string, forName: AUTOCRYPTHEADER)
}
if let key = pgp.exportKey(id: skID, isSecretkey: false, autocrypt: true) {
var string = "\(ADDR)=" + adr
string = string + "; \(ENCRYPTION)=\(encPref.name)"
string = string + "; \(KEY)=" + key
builder.header.setExtraHeaderValue(string, forName: AUTOCRYPTHEADER)
}
}
static func recommandateEncryption (receiver: MailAddress) -> (hasAutocrypt: Bool, recommandEnc: Bool){
......@@ -142,7 +141,7 @@ class Autocrypt {
static func createAutocryptKeyExport(builder: MCOMessageBuilder, keyID: String, key: String) {
builder.header.setExtraHeaderValue("v1", forName: SETUPMESSAGE)
builder.addAttachment(MCOAttachment.init(text: "This message contains a secret for reading secure mails on other devices. \n 1) Input the passcode from your smartphone to unlock the message on your other device. \n 2) Import the secret key into your pgp program on the device. \n\n For more information visit: https://userpage.fu-berlin.de/letterbox/faq.html#otherDevices \n\n"))
builder.addAttachment(MCOAttachment.init(text: "This message contains a secret for reading secure mails on other devices. \n 1) Input the passcode from your smartphone to unlock the message on your other device. \n 2) Import the secret key into your pgp program on the device. \n\n For more information visit: https://https://autocrypt.org/ \n\n"))
if let keyAttachment = MCOAttachment.init(text: key){
builder.addAttachment(keyAttachment)
......
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13527"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -12,6 +12,24 @@ class ButtonCell: UITableViewCell {
@IBOutlet weak var button: UIButton!
var listener: ButtonCellHandler?
var id = 0
static func createButtonCell(tableView: UITableView, normalTitle: String, id: Int, listener: ButtonCellHandler) -> ButtonCell {
var cell: ButtonCell
if let tmpCell = tableView.dequeueReusableCell(withIdentifier: "ButtonCell") as? ButtonCell{
cell = tmpCell
} else {
tableView.register(UINib.init(nibName: "ButtonCell", bundle: nil), forCellReuseIdentifier: "ButtonCell")
cell = tableView.dequeueReusableCell(withIdentifier: "ButtonCell") as! ButtonCell
}
cell.button.setTitle(normalTitle, for: .normal)
cell.id = id
cell.listener = listener
cell.button.adjustsImageWhenHighlighted = true
cell.button.showsTouchWhenHighlighted = true
return cell
}
var isEnabled: Bool {
set {
button.isEnabled = newValue
......@@ -30,6 +48,10 @@ class ButtonCell: UITableViewCell {
}
}
func isEmpty() -> Bool {
return button == nil
}
}
......
//
// CryptoManagementViewController.swift
// enzevalos_iphone
//
// Created by Oliver Wiese on 02.10.19.
// Copyright © 2019 fu-berlin. All rights reserved.
//
import UIKit
class CryptoManagementViewController: UITableViewController {
enum Cells {
case Info, YourID, OtherID
var name: String {
get {
switch self {
case .Info:
return "InfoField"
case .YourID:
return "YourID"
case .OtherID:
return "OtherID"
}
}
}
var text: String {
get {
switch self {
case .Info:
return NSLocalizedString("Management.Crypto.Name.Info", comment: "Here you can organize and manage your and others cryptographic idenities.")
case .YourID:
return NSLocalizedString("Management.Crypto.Name.You", comment: "Your ID")
case .OtherID:
return NSLocalizedString("Management.Name.Crypto.Other", comment: "Other ID")
}
}
}
}
enum SectionType {
case Info, KeyLists
var numberOfRows: Int {
switch self {
case .Info:
return 1
case .KeyLists:
return 2
}
}
static func findSectionType(numberOfSection: Int) -> SectionType {
if numberOfSection == 0 {
return .Info
}
else {
return .KeyLists
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.title = NSLocalizedString("Management.Crypto.Title", comment: "")
//let infoButton = UIButton(type: .infoLight)
//let barButton = UIBarButtonItem(customView: infoButton)
//self.navigationItem.rightBarButtonItem = barButton
let feedbackButton = UIBarButtonItem(title: FeedbackButtonHelper.Name, style: .plain, target: self, action:#selector(feedback))
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
self.toolbarItems = [space, feedbackButton]
}
@objc func feedback() {
FeedbackButtonHelper.composeFeedback(view: .Management, navigationController: self.navigationController)
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return SectionType.findSectionType(numberOfSection: section).numberOfRows
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let sectionType = SectionType.findSectionType(numberOfSection: indexPath.section)
if sectionType == .Info {
return infoCell(cellForRowAt: indexPath)
}
else{
// key lists
if indexPath.row == 0 {
return yourIDCell(cellForRowAt: indexPath)
}
else {
return otherIDCell(cellForRowAt: indexPath)
}
}
}
private func infoCell(cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = simpleCell(type: .Info, cellForRowAt: indexPath)
cell.textLabel?.numberOfLines = 0
return cell
}
private func yourIDCell(cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return simpleCell(type: .YourID, cellForRowAt: indexPath)
}
private func otherIDCell(cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = simpleCell(type: Cells.OtherID, cellForRowAt: indexPath)
return cell
}
private func simpleCell(type: Cells, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: type.name, for: indexPath)
cell.textLabel?.text = type.text
return cell
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
if segue.identifier == "showOtherID2" || segue.identifier == "showOtherID" {
let destinationViewController = segue.destination as! KeyTableViewController
destinationViewController.type = .PublicKey
} else {
let destinationViewController = segue.destination as! KeyTableViewController
destinationViewController.type = .SecretKey
}
if let cell = sender as? UITableViewCell {
cell.selectionStyle = .none
}
}
}
......@@ -304,13 +304,13 @@ class DataHandler {
sk = NSEntityDescription.insertNewObject(forEntityName: "SecretKey", into: managedObjectContext) as! SecretKey
sk.keyID = keyID
sk.obsolete = false
sk.importedDate = Date()
sk.importedDate = Date() as NSDate
UserManager.storeUserValue(keyID as AnyObject, attribute: Attribute.prefSecretKeyID)
let adr = UserManager.loadUserValue(Attribute.userAddr) as! String
let name = adr // TODO Change here displayname
_ = getContact(name: name, address: adr, key: keyID, prefer_enc: true)
if addPk {
_ = newPublicKey(keyID: keyID, cryptoType: CryptoScheme.PGP, adr: adr, autocrypt: false)
_ = newPublicKey(keyID: keyID, cryptoType: CryptoScheme.PGP, adr: adr, autocrypt: false, transferType: nil)
}
}
if saveKey {
......@@ -335,12 +335,12 @@ class DataHandler {
let pgp = SwiftPGP()
let key = pgp.generateKey(adr: adr)
let sk = DataHandler.handler.newSecretKey(keyID: key, addPk: false)
let pk = DataHandler.handler.newPublicKey(keyID: key, cryptoType: CryptoScheme.PGP, adr: adr, autocrypt: false, newGenerated: true)
let pk = DataHandler.handler.newPublicKey(keyID: key, cryptoType: CryptoScheme.PGP, adr: adr, autocrypt: false, newGenerated: true, transferType: nil)
pk.sentOwnPublicKey = true
return sk
}
func newPublicKey(keyID: String, cryptoType: CryptoScheme, adr: String, autocrypt: Bool, firstMail: PersistentMail? = nil, newGenerated: Bool = false, saveKey: Bool = true) -> PersistentKey {
func newPublicKey(keyID: String, cryptoType: CryptoScheme, adr: String, autocrypt: Bool, firstMail: PersistentMail? = nil, newGenerated: Bool = false, saveKey: Bool = true, transferType: LogData.TransferType?) -> PersistentKey {
var date = Date.init()
if let mail = firstMail {
if date.compare(mail.date).rawValue > 0 {
......@@ -380,10 +380,12 @@ class DataHandler {
var importChannel = LogData.TransferType.autocrypt
if newGenerated {
importChannel = LogData.TransferType.generated
} else if let transferType = transferType {
importChannel = transferType
} else if !autocrypt {
importChannel = .mail
}
Logger.log(discover: pk.keyID, mailAddress: adr, importChannel: importChannel, knownPrivateKey: DataHandler.handler.findSecretKeys().map { ($0.keyID ?? "") == keyID }.reduce(false, { $0 || $1 }), knownBefore: true)
Logger.log(discover: pk.keyID, mailAddress: adr, importChannel: importChannel, knownPrivateKey: DataHandler.handler.findSecretKeys().map { ($0.keyID) == keyID }.reduce(false, { $0 || $1 }), knownBefore: true)
}
} else {
pk = NSEntityDescription.insertNewObject(forEntityName: "PersistentKey", into: managedObjectContext) as! PersistentKey
......@@ -416,7 +418,7 @@ class DataHandler {
} else if !autocrypt {
importChannel = .mail
}
Logger.log(discover: pk.keyID, mailAddress: adr, importChannel: importChannel, knownPrivateKey: DataHandler.handler.findSecretKeys().map { ($0.keyID ?? "") == keyID }.reduce(false, { $0 || $1 }), knownBefore: false)
Logger.log(discover: pk.keyID, mailAddress: adr, importChannel: importChannel, knownPrivateKey: DataHandler.handler.findSecretKeys().map { ($0.keyID) == keyID }.reduce(false, { $0 || $1 }), knownBefore: false)
}
}
let travelHandler = TravelHandler.instance()
......@@ -960,7 +962,7 @@ class DataHandler {
}
}
else {
mail.signedKey = newPublicKey(keyID: decData.signKey!, cryptoType: decData.encType, adr: decData.signedAdrs.first!, autocrypt: false, firstMail: mail, newGenerated: false, saveKey: false)
mail.signedKey = newPublicKey(keyID: decData.signKey!, cryptoType: decData.encType, adr: decData.signedAdrs.first!, autocrypt: false, firstMail: mail, newGenerated: false, saveKey: false, transferType: nil)
}
}
......@@ -1052,6 +1054,24 @@ class DataHandler {
return result
}
func findRecordsInbox() -> [KeyRecord] {
let fReq: NSFetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "KeyRecord")
fReq.predicate = NSPredicate(format: "persistentMails.@count > 0")
let sortDescriptor = NSSortDescriptor(key: "newestDate", ascending: false)
fReq.sortDescriptors = [sortDescriptor]
do {
let result = try self.managedObjectContext.fetch(fReq)
if let res = result as? [KeyRecord] {
return res
}
} catch _ as NSError {
print("error")
}
return [KeyRecord]()
}
func getAllPersistentMails() -> [PersistentMail] {
if let mails = findAll("PersistentMail") as? [PersistentMail] {
return mails
......
//
// DateExtension.swift
// enzevalos_iphone
//
// Created by Oliver Wiese on 26.09.19.
// Copyright © 2019 fu-berlin. All rights reserved.
//
import Foundation
extension Date{
func timeAgo() -> DateComponents {
let calender = Calendar.current
let start = calender.startOfDay(for: self)
let current = calender.startOfDay(for: Date())
return calender.dateComponents([.day, .month, .year], from: start, to: current)
}
func isToday() -> Bool {
let dateComponents = self.timeAgo()
if let day = dateComponents.day, let month = dateComponents.month, let year = dateComponents.year, day == 0 && month == 0, year == 0 {
return true
}
return false
}
func timeAgoText() -> String {
let components = self.timeAgo()
if let years = components.year, years > 0 {
if years == 1 {
return NSLocalizedString("Time.Year.One", comment: "one year")
}
else {
return String(format: NSLocalizedString("Time.Year.Multiple", comment: "multiple years"), years)
}
}
else if let months = components.month, months > 0 {
if months == 1 {
return NSLocalizedString("Time.Month.One", comment: "one month")
}
else {
let s = NSLocalizedString("Time.Month.Multiple", comment: "multiple month")
return String(format: s, months)
}
}
else if let days = components.day {
if days == 0 {
return NSLocalizedString("Time.Day.Today", comment: "today")
}
else if days == 1 {
return NSLocalizedString("Time.Day.One", comment: "one day")
}
else {
let s = NSLocalizedString("Time.Day.Multiple", comment: "multiple days")
return String(format: s, days)
}
}
return self.description(with: .autoupdatingCurrent)
}
}
......@@ -71,7 +71,7 @@ private func importPublicKey(file: String, type: String, adr: String) {
do {
let ids = try pgp.importKeysFromFile(file: path, pw: nil)
for id in ids {
_ = datahandler.newPublicKey(keyID: id, cryptoType: CryptoScheme.PGP, adr: adr, autocrypt: false)
_ = datahandler.newPublicKey(keyID: id, cryptoType: CryptoScheme.PGP, adr: adr, autocrypt: false, transferType: nil)
}
} catch _ {
......
......@@ -21,7 +21,7 @@
import UIKit
class ExportInfoViewController: UITableViewController {
let url = "userpage.fu-berlin.de/letterbox/faq.html#otherDevices"
let url = "letterbox-app.org/otherDevices"
var calledFromTravel = false
@IBAction func websiteButtonTouch(_ sender: Any) {
......@@ -51,6 +51,20 @@ class ExportInfoViewController: UITableViewController {
tableView.estimatedRowHeight = 140
navigationItem.setRightBarButton(navigationItem.rightBarButtonItem, animated: false)
navigationItem.rightBarButtonItem?.title = NSLocalizedString("Next", comment: "next step")
let feedbackButton = UIBarButtonItem(title: FeedbackButtonHelper.Name, style: .plain, target: self, action:#selector(feedback))
let space = FeedbackButtonHelper.SpaceButton
if var items = self.toolbarItems {
items.append(space)
items.append(feedbackButton)
} else {
self.toolbarItems = [space, feedbackButton]
}
navigationController?.toolbar.isHidden = false
}
@objc func feedback() {
FeedbackButtonHelper.composeFeedback(view: .Export1, navigationController: self.navigationController)
}
override func viewWillAppear(_ animated: Bool) {
......@@ -69,7 +83,7 @@ class ExportInfoViewController: UITableViewController {
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ExportInfoCell") as! ExportInfoCell
cell.infoTextLabel.text = NSLocalizedString("ExportInfoViewText", comment: "")
cell.infoTextLabel.text = NSLocalizedString("Export.InfoView.Text", comment: "")
let qrCodeImage = QRCode.generate(input: "https://" + url)
let scaleX = cell.qrCode.frame.size.width / qrCodeImage.extent.size.width
......
......@@ -54,7 +54,8 @@ class ExportViewController: UITableViewController {
let handler = DataHandler.handler
let sk = handler.prefSecretKey() //handler.findSecretKeys()
let pgp = SwiftPGP()
if let sk = sk, let keyId = sk.keyID {
if let sk = sk {
let keyId = sk.keyID
if alreadySent {
if let message = pgp.exportKey(id: keyId, isSecretkey: true, autocrypt: true, newPasscode: true) {
passcode = pgp.loadExportPasscode(id: keyId)!
......@@ -148,18 +149,31 @@ class ExportViewController: UITableViewController {
if ids.count > 0 {
let id = ids[0]
let pgp = SwiftPGP()
if let keyId = id.keyID {
passcode = pgp.loadExportPasscode(id: keyId) ?? ""
alreadySent = passcode != ""
}
let keyId = id.keyID
passcode = pgp.loadExportPasscode(id: keyId) ?? ""
alreadySent = passcode != ""
}
// Logger.queue.async(flags: .barrier) {
Logger.log(exportKeyViewOpen: 2)
// }
let feedbackButton = UIBarButtonItem(title: FeedbackButtonHelper.Name, style: .plain, target: self, action:#selector(feedback))
let space = FeedbackButtonHelper.SpaceButton
if var items = self.toolbarItems {
items.append(space)
items.append(feedbackButton)
} else {
self.toolbarItems = [space, feedbackButton]
}
navigationController?.toolbar.isHidden = false
}
@objc func feedback() {
FeedbackButtonHelper.composeFeedback(view: .Export2, navigationController: self.navigationController)
}
func mailSend(_ error: Error?) {
if (error != nil) {
NSLog("Error sending email: \(String(describing: error))")
......
//
// FeedbackButtonHelper.swift
// enzevalos_iphone
//
// Created by Oliver Wiese on 18.10.19.
// Copyright © 2019 fu-berlin. All rights reserved.
//
import Foundation
enum ViewName: String {
case Inbox, Read, Compose, Key, Contact, Folder, Management, Information, SecretKeyTable, Paste, KeyTable, Import, Export1, Export2
}
class FeedbackButtonHelper {
static let Name = NSLocalizedString("Feedback.Name", comment: "Feedback")
static var SpaceButton: UIBarButtonItem {
get {
return UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
}
}
static func composeFeedback(view: ViewName, navigationController: UINavigationController?) {
let receiver = SUPPORT_MAIL_ADR
let subject = String(format: NSLocalizedString("Feedback.Mail.Subject", comment: "Feedback"), view.rawValue)
let body = String(format: NSLocalizedString("Feedback.Mail.Body", comment: ""), view.rawValue)
let mail = EphemeralMail(to: NSSet(object: receiver), subject: subject, body: String(format: body, StudySettings.studyID))
if let navi = navigationController, let sendController = FeedbackButtonHelper.createSendViewController(navigationController: navi) {
sendController.prefilledMail = mail
sendController.isFeedback = true
}
}
private static func createSendViewController(navigationController: UINavigationController) -> SendViewController? {
let mainStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
if let viewController = mainStoryboard.instantiateViewController(withIdentifier: "SendViewController") as? SendViewController {
navigationController.pushViewController(viewController, animated: true)
return viewController
}
return nil
}
}
......@@ -57,6 +57,9 @@ public class Folder: NSManagedObject {
guard keyRecords != nil && keyRecords?.count ?? 0 > 0 else {
return []
}
if UserManager.backendInboxFolderPath == self.path {
return DataHandler.handler.findRecordsInbox()
}
let rs = DataHandler.handler.getAllKeyRecords()
return rs
}
......
......@@ -24,7 +24,8 @@ class FolderViewController: UITableViewController {
var mailHandler = AppDelegate.getAppDelegate().mailHandler
var folders: [Folder] = []
@IBOutlet weak var manageButton: UIBarButtonItem!
var isFirstFolderViewController = true
var presentedFolder: Folder? = nil
......@@ -44,6 +45,7 @@ class FolderViewController: UITableViewController {
self.refreshControl?.addTarget(self, action: #selector(FolderViewController.refresh), for: UIControl.Event.valueChanged)
self.refreshControl?.attributedTitle = NSAttributedString(string: NSLocalizedString("PullToRefresh", comment: "Pull to refresh"))
lastUpdateText = NSLocalizedString("Updating", comment: "Getting new data")
manageButton.title = NSLocalizedString("Management.Button", comment: "Manage")
if isFirstFolderViewController {
folders = DataHandler.handler.allRootFolders.sorted().filter { $0.path != UserManager.backendInboxFolderPath }
......@@ -73,6 +75,13 @@ class FolderViewController: UITableViewController {
lastUpdateLabel.font = UIFont.systemFont(ofSize: 13)
lastUpdateLabel.textColor = UIColor.black
lastUpdateButton.customView = lastUpdateLabel
let feedbackButton = UIBarButtonItem(title: FeedbackButtonHelper.Name, style: .plain, target: self, action:#selector(feedback))
self.toolbarItems?.append(feedbackButton)
}
@objc func feedback() {
FeedbackButtonHelper.composeFeedback(view: .Folder, navigationController: self.navigationController)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
......
//
// ImportKeyOverviewController.swift
// enzevalos_iphone
//
// Created by Oliver Wiese on 04.10.19.
// Copyright © 2019 fu-berlin. All rights reserved.
//
import UIKit
class ImportKeyOverviewController: UITableViewController, ButtonCellHandler {
enum KeyActions {
case iTunes, Paste
}
enum KeyState {
case Public, Secret
}
var currentState: KeyState = .Secret
override func viewDidLoad() {
super.viewDidLoad()
self.title = NSLocalizedString("Import.Overview.Title", comment: "Add a key")
let feedbackButton = UIBarButtonItem(title: FeedbackButtonHelper.Name, style: .plain, target: self, action:#selector(feedback))
let space = FeedbackButtonHelper.SpaceButton
if var items = self.toolbarItems {
items.append(space)
items.append(feedbackButton)
} else {
self.toolbarItems = [space, feedbackButton]
}
navigationController?.toolbar.isHidden = false
}
@objc func feedback() {
FeedbackButtonHelper.composeFeedback(view: .Import, navigationController: self.navigationController)
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var identifier = "InfoTextCell"
if indexPath.section == 0 {
// Info field
identifier = "InfoTextCell"
let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath)
var text = NSLocalizedString("Import.Overview.Info.Public", comment: "Copy and paste a key etc.")
if self.currentState == .Secret {
text = NSLocalizedString("Import.Overview.Info.Secret", comment: "Secret key info")
}
cell.textLabel?.text = text
return cell
} else if indexPath.section == 1 {
return ButtonCell.createButtonCell(tableView: tableView, normalTitle: NSLocalizedString("Import.Button.Itunes", comment: "import from iTunes"), id: KeyActions.iTunes.hashValue, listener: self)
} else {
// paste import
return ButtonCell.createButtonCell(tableView: tableView, normalTitle: NSLocalizedString("Import.Button.Paste", comment: "paste key"), id: KeyActions.Paste.hashValue, listener: self)
}
}
func touchDown(id: Int) {
if id == KeyActions.iTunes.hashValue {
// Call iTunes field
var type = KeyTableViewController.KeyType.ImportPublicKeyItunes
if currentState == .Secret {
type = .ImportSecretKeyItunes
}
_ = KeyTableViewController.pushKeyTableView(navigationController: self.navigationController, type: type)
} else if id == KeyActions.Paste.hashValue {
// open Textfield to paste key
_ = PasteKeyViewController.pushPasteKeyView(navigationController: self.navigationController)
}
}
}
......@@ -92,6 +92,12 @@ class InboxViewController: UITableViewController, InboxCellDelegator {
[weak self] _ in
self?.tableView.reloadData()
})
let feedbackButton = UIBarButtonItem(title: FeedbackButtonHelper.Name, style: .plain, target: self, action:#selector(feedback))
self.toolbarItems?.append(feedbackButton)
}
@objc func feedback() {
FeedbackButtonHelper.composeFeedback(view: .Inbox, navigationController: self.navigationController)
}
@objc func refresh(_ refreshControl: UIRefreshControl?) {
......@@ -112,7 +118,6 @@ class InboxViewController: UITableViewController, InboxCellDelegator {
} else {
lastUpdateText = NSLocalizedString("NeverUpdated", comment: "Error while loading mailscomment")
if AppDelegate.getAppDelegate().currentReachabilityStatus != .notReachable && counterRefreshs < 100{
print("REFRESH AGAIN!")
counterRefreshs += 1
refresh(nil)
}
......
......@@ -55,6 +55,7 @@ extension IntroInfoButton where Self: UIViewController {
if let url = url {
alert.addAction(UIAlertAction(title: NSLocalizedString("MoreInformation", comment: "More Information label"), style: .default, handler: { (action: UIAlertAction!) -> Void in
UIApplication.shared.openURL(URL(string: url)!)
//MoreInformationViewController.pushInfoView(navigationController: self.navigationController, state: .Secure)
}))
}
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: { (action: UIAlertAction!) -> Void in
......
......@@ -32,14 +32,24 @@ class ItunesKeyHandling {
}
static let iTunesKeyHandler = ItunesKeyHandling()
var newSecretKeys: [TempKey] {
get {
func extractSecretKeys(withKnownKeys: Bool) -> [TempKey] {
var newSecretKeys = storedKeys.filter{$0.isSecret}
if !withKnownKeys {
var knownIDs = DataHandler.handler.findSecretKeys().map{$0.keyID}
knownIDs = knownIDs.filter{return !($0 == "" || $0 == nil)}
var newSecretKeys = storedKeys.filter{$0.isSecret}
knownIDs = knownIDs.filter{return !($0 == "")}
newSecretKeys = newSecretKeys.filter{!knownIDs.contains($0.keyID)}
return newSecretKeys
}
return newSecretKeys
}
func extractPublicKeys(withKnownKeys: Bool) -> [TempKey] {
var newPublicKeys = storedKeys.filter{!$0.isSecret}
if !withKnownKeys {
var knownIDs = DataHandler.handler.findPublicKeys().map{$0.keyID}
knownIDs = knownIDs.filter{return !($0 == "")}
newPublicKeys = newPublicKeys.filter{!knownIDs.contains($0.keyID)}
}
return newPublicKeys
}
var hasStoredKeys: Bool {
......@@ -86,7 +96,7 @@ class ItunesKeyHandling {
func importPublicKeys() -> [String]{
var publicKeys = storedKeys.filter{!$0.isSecret}
publicKeys = publicKeys.filter{DataHandler.handler.findKey(keyID: $0.keyID!) == nil}
publicKeys = publicKeys.filter{DataHandler.handler.findKey(keyID: $0.keyID) == nil}
let keyIds = pgp.store(tempKeys: publicKeys)
//TODO: Store in Datahandler -> in tempKey?
return keyIds
......@@ -104,9 +114,7 @@ class MinimalImportUI {
var secretKeyPasswordField: UITextField? = nil
func importSecretKeyDialog(first: Bool) {
guard let keyID = secretKey.keyID else {
return
}
let keyID = secretKey.keyID
let format = NSLocalizedString("Read.Import.Secret.Body.Plain", comment: "NewSecretKeyMessage")
var message = String.localizedStringWithFormat(format, keyID)
if secretKey.hasPassword {
......
......@@ -10,14 +10,73 @@ import Foundation
class KeyCell: UITableViewCell {
@IBOutlet weak var idLabel: UILabel!
@IBOutlet weak var originLabel: UILabel!
@IBOutlet weak var dateLabel: UILabel!
@IBOutlet weak var prefIcon: UIImageView!
@IBOutlet weak var orignName: UILabel!
@IBOutlet weak var dateName: UILabel!
@IBOutlet weak var mailAddress: UILabel!
func setLabels(key: PersistentKey) {
var mailAddrString: String?
var id = key.keyID
let date = key.discoveryDate
let pref = false
if let record = key.keyRecord {
mailAddrString = record.addressNames.first
id = record.myNick
} else {
if let addresses = key.mailaddresses {
for addr in addresses {
if let mail = addr as? MailAddress {
mailAddrString = mail.mailAddress
break
}
}
}
}
setLabels(id: id, addr: mailAddrString, date: date, origin: nil, pref: pref)
}
func setLabels(key: SecretKey) {
var id = key.keyID
var mail: String? = nil
let date = key.importDate
let pref = DataHandler.handler.prefSecretKey()?.keyID == key.keyID
if let addr = UserManager.loadUserValue(.userAddr) as? String {
mail = addr
let record = DataHandler.handler.getKeyRecord(addr: addr, keyID: id)
id = record.myNick
}
setLabels(id: id, addr: mail, date: date, origin: nil, pref: pref)
}
func setLabels(key: DisplayKey) {
setLabels(id: key.keyID, addr: nil, date: key.importDate, origin: nil, pref: false)
}
private func setLabels(id: String, addr: String?, date: Date?, origin: String?, pref: Bool) {
idLabel.text = id
if let addr = addr {
mailAddress.text = addr
mailAddress.isHidden = false
} else {
mailAddress.isHidden = true
}
if let date = date {
dateLabel.text = date.timeAgoText()
dateName.text = NSLocalizedString("SecretKeyCell.date", comment: "known since")
} else {
dateLabel.isHidden = true
dateName.isHidden = true
}
if pref {
prefIcon.image = NoSecIconStyleKit.imageOfFavorite
prefIcon.isHidden = false
} else {
prefIcon.isHidden = true
}
}
}
This diff is collapsed.
......@@ -85,7 +85,41 @@ public class KeyRecord: NSManagedObject, Record {
}
return nil
}
public var myNick: String {
if let n = self.nick {
return n
} else {
return defaultNick()
}
}
private func defaultNick() -> String {
let records = ezContact.records
var i = 1
for r in records.sorted() {
if r.fingerprint == self.fingerprint {
break
}
i = i+1
}
let id = "\(i)) \(name)"
self.nick = id
DataHandler.handler.save(during: "change id")
return id
}
public var isPrimaryID: Bool {
if let keyID = self.keyID {
for addr in self.addresses {
if keyID == addr.primaryKey?.keyID {
return true
}
}
}
return false
}
public var cryptoscheme: CryptoScheme {
get {
if let k = activeKey {
......@@ -143,7 +177,14 @@ public class KeyRecord: NSManagedObject, Record {
public var color: UIColor {
get {
return contact.getColor()
// Overflow?!
let prim = 653
var text = self.ezContact.name
if let fingerprint = self.activeKey?.fingerprint {
text = fingerprint
}
let hash = (abs(text.hash)) % prim
return UIColor(hue: CGFloat(hash) / CGFloat(prim), saturation: 1, brightness: 0.75, alpha: 1)
}
}
......@@ -230,8 +271,6 @@ public class KeyRecord: NSManagedObject, Record {
}
return nil
}
}
......
......@@ -33,6 +33,8 @@ extension KeyRecord {
@NSManaged public var key: PersistentKey?
@NSManaged public var persistentMails: NSSet?
@NSManaged public var newestDate: Date?
@NSManaged public var nick: String?
var activeKey: PersistentKey? {
get {
......
This diff is collapsed.
......@@ -23,7 +23,9 @@ import UIKit
class KeyViewController: UIViewController {
@IBOutlet var tableView: UITableView!
static let HiddeMailAddresses = true
var openDate: Date = Date() //used for logging issues [see Logger.log(keyViewClose keyID:String, timevisited: Date)]
var record: KeyRecord?
......@@ -35,14 +37,27 @@ class KeyViewController: UIViewController {
if let record = self.record, let keyID = record.keyID {
Logger.log(keyViewOpen: keyID)
}
self.title = NSLocalizedString("KeyDetails", comment: "Details of the key")
let feedbackButton = UIBarButtonItem(title: FeedbackButtonHelper.Name, style: .plain, target: self, action:#selector(feedback))
self.navigationItem.rightBarButtonItem = feedbackButton
}
@objc func feedback() {
FeedbackButtonHelper.composeFeedback(view: .Key, navigationController: self.navigationController)
}
override func viewDidDisappear(_ animated: Bool) {
// Logger.queue.async(flags: .barrier) {
if let record = self.record, let keyID = record.keyID {
Logger.log(keyViewClose: keyID, secondsOpened: Int(Date().timeIntervalSince(self.openDate)))
let duration = Date().timeIntervalSince(self.openDate)
Logger.log(keyViewClose: keyID, secondsOpened: Int(duration))
}
// }
if let row = tableView.indexPathForSelectedRow {
tableView.deselectRow(at: row, animated: false)
}
super.viewDidDisappear(animated)
}
}
......@@ -75,30 +90,22 @@ extension KeyViewController: UITableViewDataSource {
if toRowType(indexPath) == .keyID {
let cell = tableView.dequeueReusableCell(withIdentifier: "KeyIDCell")!
cell.textLabel?.text = NSLocalizedString("KeyID", comment: "Identifier of the key")
cell.detailTextLabel?.text = record?.keyID
cell.detailTextLabel?.text = record?.keyID?.makeBlocks()
return cell
}
else if toRowType(indexPath) == .fingerprint {
let cell = tableView.dequeueReusableCell(withIdentifier: "FingerprintCell")!
cell.detailTextLabel?.numberOfLines = 0
var result: String = ""
let characters = Array((record?.fingerprint ?? ""))
var i = 0
stride(from: 0, to: characters.count, by: 4).forEach {
result += String(characters[$0..<min($0 + 4, characters.count)])
if $0 + 4 < characters.count {
i = (i + 1) % 3
if i == 0 {
result += "\n"
}
else {
result += " "
}
}
if let fingerprint = record?.fingerprint {
cell.detailTextLabel?.text = fingerprint.makeBlocks()
cell.detailTextLabel?.numberOfLines = 2
cell.textLabel?.text = NSLocalizedString("Fingerprint", comment: "Fingerprint of key")
cell.textLabel?.numberOfLines = 1
cell.isHidden = false
}
else {
cell.isHidden = true
}
cell.detailTextLabel?.text = result
cell.textLabel?.text = NSLocalizedString("Fingerprint", comment: "Fingerprint of key")
cell.isHidden = true
return cell
}
else if toRowType(indexPath) == .encryptionType {
......@@ -123,7 +130,17 @@ extension KeyViewController: UITableViewDataSource {
}
else if toRowType(indexPath) == .discoveryMail {
let cell = tableView.dequeueReusableCell(withIdentifier: "DiscoveryMailCell")!
cell.textLabel?.text = "Mail"
cell.textLabel?.text = NSLocalizedString("Key.DiscoveryChannel", comment: "Discovered by ")
if let label = cell.detailTextLabel {
if record?.key?.firstMail != nil {
label.text = NSLocalizedString("Key.DiscoveryChannel.Mail", comment: "mail")
}
else {
cell.accessoryType = .none
label.text = NSLocalizedString("Key.DiscoveryChannel.Unknown", comment: "unknown")
}
}
return cell
}
else if toRowType(indexPath) == .verified {
......@@ -175,6 +192,7 @@ extension KeyViewController: UITableViewDataSource {
if DataHandler.handler.findSecretKeys().count < 2 && !ItunesKeyHandling.iTunesKeyHandler.hasStoredKeys {
cell.isHidden = true
}
cell.isHidden = true
}
return cell
}
......@@ -185,7 +203,7 @@ extension KeyViewController: UITableViewDataSource {
}
func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
if section == 1 {
if section == 1 && !KeyViewController.HiddeMailAddresses {
return NSLocalizedString("Checkmarks", comment: "Checkmarks")
}
return nil
......@@ -204,9 +222,9 @@ extension KeyViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if toSectionType(section) == .keyDetails {
return NSLocalizedString("KeyDetails", comment: "Details of the key")
return nil
}
if toSectionType(section) == .addresses {
if toSectionType(section) == .addresses && !KeyViewController.HiddeMailAddresses {
return NSLocalizedString("KeyAddresses", comment: "Mailaddresses Connected to the key")
}
return nil
......@@ -263,7 +281,8 @@ extension KeyViewController: UITableViewDataSource {
row -= 1
}
//DiscoveryMail
if row != 0 && key.firstMail != nil {
// && key.firstMail != nil
if row != 0 {
returnValue = KeyViewRowType(rawValue: returnValue.rawValue + 1)!
row -= 1
}
......@@ -284,6 +303,25 @@ extension KeyViewController: UITableViewDataSource {
}
return returnValue
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let mail = record?.key?.firstMail {
// Segue to the second view controller
self.performSegue(withIdentifier: "firstMail", sender: mail)
}
}
// This function is called before the segue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "firstMail" {
if let mail = record?.key?.firstMail {
let DestinationViewController: ReadViewController = segue.destination as! ReadViewController
DestinationViewController.mail = mail
}
}
}
}
extension KeyViewController: ButtonCellHandler {
......@@ -309,6 +347,10 @@ extension KeyViewController: ButtonCellHandler {
self.navigationController?.pushViewController(secretKeyCon, animated: true)
}
}
else if id == KeyActions.SeeFirstMail.hashValue {
}
}
......@@ -318,9 +360,9 @@ enum KeyViewSectionType: Int {
}
enum KeyViewRowType: Int {
case noKey = 0, keyID, fingerprint, encryptionType, discoveryTime, discoveryMail, verified, revoked
case noKey = 0, keyID, fingerprint, encryptionType, discoveryTime, discoveryMail, readdFirstMail, verified, revoked
}
enum KeyActions {
case Copy, Change
case Copy, Change, SeeFirstMail
}
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
......
......@@ -8,10 +8,10 @@
import Foundation
class Logger{
class Logger {
static var logging = StudySettings.studyMode
static let loggingInterval = 21600 //60*60*6 seconds = 6 hours
static let loggingInterval = 86400 // 21600 = 60*60*6 seconds = 6 hours
static let resendInterval = 5 * 60
static let logReceiver = LOGGING_MAIL_ADR
......@@ -19,13 +19,15 @@ class Logger{
static fileprivate func sendCheck() {
if nextDeadline <= Date() && AppDelegate.getAppDelegate().currentReachabilityStatus != .notReachable && UserManager.loadUserValue(Attribute.accountname) != nil && UserDefaults.standard.bool(forKey: "launchedBefore"){
let deadlineIsNow = nextDeadline <= Date()
if deadlineIsNow && AppDelegate.getAppDelegate().currentReachabilityStatus != .notReachable && UserManager.loadUserValue(Attribute.accountname) != nil && UserDefaults.standard.bool(forKey: "launchedBefore"){
//Do not send duplicate mails
let tmpNextDeadline = Date(timeIntervalSinceNow: TimeInterval(resendInterval))
let tmpNextDeadline = Date(timeIntervalSinceNow: TimeInterval(loggingInterval))
nextDeadline = tmpNextDeadline
UserManager.storeUserValue(nextDeadline as AnyObject?, attribute: Attribute.nextDeadline)
sendLog()
}
}
static func log(setupStudy studypara: [StudyParameterProtocol.Type], alreadyRegistered: Bool) {
......@@ -39,7 +41,6 @@ class Logger{
if !logging {
return
}
LogData.newSimpleEvent(event: .newSession)
sendCheck()
}
......@@ -151,11 +152,39 @@ class Logger{
if !logging {
return
}
LogData.importKey(keyType: .secretKey, transferType: .mail, known: false)
LogData.importKey(keyType: .secretKey, transferType: .mail, known: false, successful: success)
sendCheck()
}
static func log(importPrivateKey type<