2017-02-17 13:44:25 +08:00
//
// P G P K e y A r m o r S e t t i n g T a b l e V i e w C o n t r o l l e r . s w i f t
// p a s s
//
// C r e a t e d b y M i n g s h e n S u n o n 1 7 / 2 / 2 0 1 7 .
// C o p y r i g h t © 2 0 1 7 B o b S u n . A l l r i g h t s r e s e r v e d .
//
import UIKit
import SwiftyUserDefaults
2017-05-14 20:42:59 +08:00
class PGPKeyArmorSettingTableViewController : UITableViewController , UITextViewDelegate , QRScannerControllerDelegate {
2017-02-17 13:44:25 +08:00
@IBOutlet weak var armorPublicKeyTextView : UITextView !
@IBOutlet weak var armorPrivateKeyTextView : UITextView !
2017-05-14 20:42:59 +08:00
@IBOutlet weak var scanPublicKeyCell : UITableViewCell !
@IBOutlet weak var scanPrivateKeyCell : UITableViewCell !
2017-02-17 14:58:27 +08:00
var pgpPassphrase : String ?
2017-03-16 22:39:03 -07:00
let passwordStore = PasswordStore . shared
2017-02-17 13:44:25 +08:00
2017-04-04 00:03:21 +08:00
private var recentPastedText = " "
2017-05-14 20:42:59 +08:00
class ScannedPGPKey {
static let maxNumberOfGif = 100
enum KeyType {
case publicKey , privateKey
}
var keyType = KeyType . publicKey
var numberOfSegments = 0
var previousSegment = " "
var key = " "
var message = " "
var hasStarted = false
var isDone = false
func reset ( keytype : KeyType ) {
self . keyType = keytype
numberOfSegments = 0
previousSegment = " "
key = " "
message = " Looking for the starting frame. "
hasStarted = false
isDone = false
}
func addSegment ( segment : String ) {
// s k i p d u p l i c a t e d s e g m e n t s
guard segment != previousSegment else {
return
}
previousSegment = segment
// c h e c k w h e t h e r w e h a v e f o u n d t h e f i r s t b l o c k
if hasStarted = = false {
let findPublic = segment . contains ( " -----BEGIN PGP PUBLIC KEY BLOCK----- " )
let findPrivate = segment . contains ( " -----BEGIN PGP PRIVATE KEY BLOCK----- " )
switch keyType {
case . publicKey :
if findPrivate {
message = " Please scan public key. "
}
hasStarted = findPublic
case . privateKey :
if findPublic {
message = " Please scan private key. "
}
hasStarted = findPrivate
}
}
guard hasStarted = = true else {
return
}
// c h e c k t h e n u m b e r o f s e g m e n t s
numberOfSegments = numberOfSegments + 1
guard numberOfSegments <= ScannedPGPKey . maxNumberOfGif else {
key = " Too many QR codes "
return
}
// u p d a t e f u l l t e x t a n d c h e c k w h e t h e r w e a r e d o n e
key . append ( segment )
if key . contains ( " -----END PGP PUBLIC KEY BLOCK----- " ) || key . contains ( " -----END PGP PRIVATE KEY BLOCK----- " ) {
isDone = true
}
// u p d a t e m e s s a g e
message = " \( numberOfSegments ) scanned QR codes. "
}
}
var scanned = ScannedPGPKey ( )
2017-02-17 13:44:25 +08:00
override func viewDidLoad ( ) {
super . viewDidLoad ( )
armorPublicKeyTextView . text = Defaults [ . pgpPublicKeyArmor ]
armorPrivateKeyTextView . text = Defaults [ . pgpPrivateKeyArmor ]
2017-03-16 22:39:03 -07:00
pgpPassphrase = passwordStore . pgpKeyPassphrase
2017-05-14 20:42:59 +08:00
scanPublicKeyCell ? . textLabel ? . text = " Scan Public Key QR Codes "
scanPublicKeyCell ? . textLabel ? . textColor = Globals . blue
scanPublicKeyCell ? . selectionStyle = . default
scanPublicKeyCell ? . accessoryType = . disclosureIndicator
scanPrivateKeyCell ? . textLabel ? . text = " Scan Private Key QR Codes "
scanPrivateKeyCell ? . textLabel ? . textColor = Globals . blue
scanPrivateKeyCell ? . selectionStyle = . default
scanPrivateKeyCell ? . accessoryType = . disclosureIndicator
2017-02-17 14:58:27 +08:00
}
2017-04-10 02:15:49 +08:00
override func shouldPerformSegue ( withIdentifier identifier : String , sender : Any ? ) -> Bool {
if identifier = = " savePGPKeySegue " {
if armorPublicKeyTextView . text . isEmpty {
Utils . alert ( title : " Cannot Save " , message : " Please set public key first. " , controller : self , completion : nil )
return false
}
if armorPrivateKeyTextView . text . isEmpty {
Utils . alert ( title : " Cannot Save " , message : " Please set private key first. " , controller : self , completion : nil )
return false
}
}
return true
}
2017-02-17 14:58:27 +08:00
@IBAction func save ( _ sender : Any ) {
2017-06-07 21:11:01 +08:00
let savePassphraseAlert = UIAlertController ( title : " Passphrase " , message : " Do you want to save the passphrase for later decryption? " , preferredStyle : UIAlertControllerStyle . alert )
// n o
savePassphraseAlert . addAction ( UIAlertAction ( title : " No " , style : UIAlertActionStyle . default ) { _ in
self . pgpPassphrase = nil
Defaults [ . isRememberPassphraseOn ] = false
self . performSegue ( withIdentifier : " savePGPKeySegue " , sender : self )
} )
// y e s
savePassphraseAlert . addAction ( UIAlertAction ( title : " Yes " , style : UIAlertActionStyle . destructive ) { _ in
// a s k f o r t h e p a s s p h r a s e
let alert = UIAlertController ( title : " Passphrase " , message : " Please fill in the passphrase of your PGP secret key. " , preferredStyle : UIAlertControllerStyle . alert )
alert . addAction ( UIAlertAction ( title : " OK " , style : UIAlertActionStyle . default , handler : { _ in
self . pgpPassphrase = alert . textFields ? . first ? . text
Defaults [ . isRememberPassphraseOn ] = true
self . performSegue ( withIdentifier : " savePGPKeySegue " , sender : self )
} ) )
alert . addTextField ( configurationHandler : { ( textField : UITextField ! ) in
textField . text = self . pgpPassphrase
textField . isSecureTextEntry = true
} )
self . present ( alert , animated : true , completion : nil )
2017-02-17 14:58:27 +08:00
} )
2017-06-07 21:11:01 +08:00
self . present ( savePassphraseAlert , animated : true , completion : nil )
2017-02-17 13:44:25 +08:00
}
2017-04-04 00:03:21 +08:00
func textView ( _ textView : UITextView , shouldChangeTextIn range : NSRange , replacementText text : String ) -> Bool {
if text = = UIPasteboard . general . string {
2017-04-08 23:51:43 +08:00
// u s e r p a s t e s s o m e t h i n g , g e t r e a d y t o c l e a r i n 1 0 s
2017-04-04 00:03:21 +08:00
recentPastedText = text
DispatchQueue . global ( qos : . background ) . asyncAfter ( deadline : DispatchTime . now ( ) + 10 ) { [ weak weakSelf = self ] in
if let pasteboardString = UIPasteboard . general . string ,
pasteboardString = = weakSelf ? . recentPastedText {
UIPasteboard . general . string = " "
}
}
}
return true
}
2017-05-14 20:42:59 +08:00
override func tableView ( _ tableView : UITableView , didSelectRowAt indexPath : IndexPath ) {
let selectedCell = tableView . cellForRow ( at : indexPath )
if selectedCell = = scanPublicKeyCell {
scanned . reset ( keytype : ScannedPGPKey . KeyType . publicKey )
self . performSegue ( withIdentifier : " showPGPScannerSegue " , sender : self )
} else if selectedCell = = scanPrivateKeyCell {
scanned . reset ( keytype : ScannedPGPKey . KeyType . privateKey )
self . performSegue ( withIdentifier : " showPGPScannerSegue " , sender : self )
}
tableView . deselectRow ( at : indexPath , animated : true )
}
// MARK: - Q R S c a n n e r C o n t r o l l e r D e l e g a t e M e t h o d s
func checkScannedOutput ( line : String ) -> ( accept : Bool , message : String ) {
scanned . addSegment ( segment : line )
if scanned . isDone {
return ( accept : true , message : " Done " )
} else {
return ( accept : false , message : scanned . message )
}
}
// MARK: - Q R S c a n n e r C o n t r o l l e r D e l e g a t e M e t h o d s
func handleScannedOutput ( line : String ) {
switch scanned . keyType {
case . publicKey :
armorPublicKeyTextView . text = scanned . key
case . privateKey :
armorPrivateKeyTextView . text = scanned . key
}
}
override func prepare ( for segue : UIStoryboardSegue , sender : Any ? ) {
if segue . identifier = = " showPGPScannerSegue " {
if let navController = segue . destination as ? UINavigationController {
if let viewController = navController . topViewController as ? QRScannerController {
viewController . delegate = self
}
} else if let viewController = segue . destination as ? QRScannerController {
viewController . delegate = self
}
}
}
@IBAction private func cancelPGPScanner ( segue : UIStoryboardSegue ) {
}
2017-02-17 13:44:25 +08:00
}