123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453 |
- //
- // KMPDFDigitalSignViewController.swift
- // PDF Reader Pro Edition
- //
- // Created by Niehaoyu on 2023/10/19.
- //
- import Cocoa
- class KMPDFDigitalSignViewController: NSViewController, CPDFViewDelegate {
- @IBOutlet weak var contendView: NSView!
- @IBOutlet weak var headerView: NSView!
- @IBOutlet weak var tipLabel: NSTextField!
- @IBOutlet weak var exitBox: NSBox!
- @IBOutlet weak var exitButton: KMCustomButton!
- @IBOutlet weak var saveBox: NSBox!
- @IBOutlet weak var saveButton: KMCustomButton!
-
- @IBOutlet weak var stateBGView: NSView!
- @IBOutlet weak var stateLbl: NSTextField!
- @IBOutlet weak var stateButton: NSButton!
-
- @IBOutlet weak var pdfContendView: NSView!
- @IBOutlet weak var contentTopConst: NSLayoutConstraint!
-
-
- var editWidgeAnnotation: CPDFSignatureWidgetAnnotation!
- var stateVC: CDSignatureCertificateStateViewController!
-
- @objc var scaleFactor: CGFloat = 0
- @objc var url: URL!
- @objc var password = String()
- @objc var currentPageIndex: Int = 0
-
- var signatures = NSArray()
- var type:CPromptSignaturesState = .failure
-
- @objc var titleChangeBlock: ((_ title: String, _ pageIndex: NSInteger)->Void)?
- @objc var buttonActionBlock: ((_ actionType: DSignatureActionType, _ isChanged: Bool)->Void)?
-
- var pdfView: CPDFDigtalView!
-
- override func viewDidAppear() {
- super.viewDidAppear()
-
- let contextString = NSLocalizedString("Please box an area for the signature to be added, then you can add a new digital signature.", comment: "")
- _ = CustomAlertView.alertView(message: contextString, fromView: self.view, withStyle: .black)
- }
-
- override func viewDidLoad() {
- super.viewDidLoad()
- // Do view setup here.
-
- self.contendView.wantsLayer = true
- self.contendView.layer?.backgroundColor = KMAppearance.Layout.bgColor().cgColor
-
- self.headerView.wantsLayer = true
- self.headerView.layer?.backgroundColor = KMAppearance.Interactive.a0Color().cgColor
-
- self.tipLabel.stringValue = NSLocalizedString("You are Under Digital Sign Mode", comment: "")
-
- self.exitBox.borderColor = KMAppearance.Layout.w70Color()
- self.exitBox.borderWidth = 1.0
- self.exitButton.title = NSLocalizedString("Exit", comment: "")
-
- self.saveBox.fillColor = NSColor.white
- self.saveButton.title = NSLocalizedString("Exit", comment: "")
- self.saveButton.setTitleColor(KMAppearance.Interactive.a0Color())
-
- self.exitBox.isHidden = true
-
- self.pdfView = CPDFDigtalView.init(frame: self.pdfContendView.bounds)
- self.pdfView.autoresizingMask = [.width, .height]
-
- let document = CPDFDocument.init(url: self.url)
- if self.password.count > 0 {
- document?.unlock(withPassword: self.password)
- }
- self.pdfView.delegate = self
- self.pdfView.document = document
- self.pdfView.autoScales = true
- self.pdfView.pdfListViewDelegate = self
- self.pdfContendView.addSubview(self.pdfView)
-
- self.stateBGView.wantsLayer = true
- self.stateBGView.layer?.backgroundColor = KMAppearance.Else.textHighlightColor().cgColor
- self.stateLbl.textColor = NSColor.labelColor
-
- self.reloadState()
-
- NotificationCenter.default.addObserver(self, selector: #selector(signatureStateChangeNoti), name: NSNotification.Name(rawValue: "CSignatureTrustCerDidChangeNotification"), object: nil)
- }
-
- //MARK: Public Method
-
- func reloadState() {
- if self.pdfView.signatures.count > 0 {
- self.stateBGView.isHidden = false
- self.contentTopConst.constant = 44
- } else {
- self.stateBGView.isHidden = true
- self.contentTopConst.constant = 0
- }
-
- self.signatures = self.pdfView.signatures! as NSArray
-
- var isSignVerified = false
- var isCertTrusted = false
-
- for item in self.signatures {
- let signature: CPDFSignature = item as! CPDFSignature
- if signature.signers != nil {
- let signer = signature.signers.first
- if signer?.isCertTrusted == false {
- isCertTrusted = false
- break
- } else {
- isCertTrusted = true
- }
- }
- }
-
- for item in self.signatures {
- let signature: CPDFSignature = item as! CPDFSignature
- if signature.signers != nil {
- let signer = signature.signers.first
- if signer?.isSignVerified == false {
- isSignVerified = false
- break
- } else {
- isSignVerified = true
- }
- }
- }
-
- self.stateBGView.isHidden = false
-
- if (isSignVerified && isCertTrusted) {
- self.type = .Success;
- } else if(isSignVerified && !isCertTrusted) {
- self.type = .Unknown;
- } else {
- self.type = .failure;
- }
-
- if (.Success == self.type) {
- self.stateButton.image = NSImage(named: "ImageNameSigntureVerifySuccess")
- self.stateLbl.stringValue = NSLocalizedString("Signature is valid.", comment: "")
- } else if(.Unknown == self.type) {
- self.stateButton.image = NSImage(named: "ImageNameSigntureTrustedFailure")
- if(self.signatures.count > 1) {
- self.stateLbl.stringValue = NSLocalizedString("At least one signature is invalid.", comment: "")
- } else {
- self.stateLbl.stringValue = NSLocalizedString("Signature is invalid", comment: "")
- }
- } else {
- self.stateButton.image = NSImage(named: "ImageNameSigntureVerifyFailure")
- if(self.signatures.count > 1) {
- self.stateLbl.stringValue = NSLocalizedString("At least one signature is invalid.", comment: "")
- } else {
- self.stateLbl.stringValue = NSLocalizedString("Signature is invalid", comment: "")
- }
- }
- }
-
- func writeSignatureToWidget(_ widget: CPDFSignatureWidgetAnnotation, _ path: String, _ password: String, _ config: CPDFSignatureConfig, _ isLock: Bool) ->() {
-
- let fileName = self.pdfView.document.documentURL?.lastPathComponent
- let fileNameWithoutExtension = URL(fileURLWithPath: fileName!).deletingPathExtension().lastPathComponent
- let outputSavePanel = NSSavePanel()
- outputSavePanel.directoryURL = self.pdfView.document.documentURL.deletingLastPathComponent()
- outputSavePanel.title = NSLocalizedString("", comment: "Save as PDF")
- outputSavePanel.allowedFileTypes = ["pdf"]
- outputSavePanel.nameFieldStringValue = fileNameWithoutExtension + "_" + NSLocalizedString("Signed", comment: "")
- let result = outputSavePanel.runModal()
- if result == .OK {
- let contentArr = NSMutableArray()
- var locationStr = ""
- var reasonStr = NSLocalizedString("none", comment: "")
- for item in config.contents {
- if item.key == NSLocalizedString("Reason", comment: "") {
- if item.value == NSLocalizedString("<your signing reason here>", comment: "") {
- item.value = " " + NSLocalizedString("none", comment: "")
- }
- reasonStr = item.value
- } else if item.key == NSLocalizedString("Location", comment: "") {
- if item.value == NSLocalizedString("<your signing location here>", comment: "") {
- item.value = " "
- }
- locationStr = item.value
- }
- contentArr.add(item)
- }
- config.contents = contentArr as? [CPDFSignatureConfigItem]
- widget.signAppearanceConfig(config)
-
- let success = self.pdfView.document.writeSignature(to: outputSavePanel.url, withWidget: widget, pkcs12Cert: path, password: password, location: locationStr, reason: reasonStr, permissions: .forbidChange)
- widget.removeSignature()
- if success {
- DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) {
- NSDocumentController.shared.openDocument(withContentsOf: outputSavePanel.url!, display: true) { document, documentWasAlreadyOpen, error in
- if error != nil {
- NSApp.presentError(error!)
- return
- }
- }
- }
- } else {
- let alert = NSAlert.init()
- alert.messageText = NSLocalizedString("Save failed!", comment: "")
- alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
- alert.runModal()
- }
- widget.page.removeAnnotation(widget)
- self.pdfView.setNeedsDisplayAnnotationViewFor(widget.page)
- } else {
- widget.page.removeAnnotation(widget)
- self.pdfView.setNeedsDisplayAnnotationViewFor(widget.page)
- }
- }
-
- //MARK: Setter
-
-
-
- //MARK: IBAction
- @IBAction func exitButtonAction(_ sender: NSButton) {
-
- }
-
- @IBAction func saveButtonAction(_ sender: NSButton) {
-
- // var documentArray = NSDocumentController.shared.documents
- var didFileEdit = false
- // for i in 0...documentArray.count-1 {
- // let document = documentArray[i]
- // if document.fileURL!.path == self.pdfView.document.documentURL.path {
- // didFileEdit = document.isDocumentEdited
- //
- // break
- // }
- // }
- guard let callBack = self.buttonActionBlock else {
- return
- }
- callBack(.cancel, didFileEdit)
-
- }
-
-
- //MARK: CPDFViewDelegate
- func pdfViewDocumentDidLoaded(_ pdfView: CPDFView!) {
- self.pdfView.go(toPageIndex: self.currentPageIndex, animated: true)
- }
-
- func pdfViewCurrentPageDidChanged(_ pdfView: CPDFView!) {
- let fileName = pdfView.document.documentURL.deletingPathExtension().lastPathComponent
- let title = String(format: "%@ (page %ld / %ld)", fileName, pdfView.currentPageIndex+1, pdfView.document.pageCount)
-
- self.currentPageIndex = pdfView.currentPageIndex
- guard let callBack = self.titleChangeBlock else {
- return
- }
- callBack(title, self.currentPageIndex)
- }
- func popUpSignatureWidgetState(_ signature: CPDFSignature, _ pdfListView: CPDFDigtalView) ->(){
- if self.stateVC == nil {
- self.stateVC = CDSignatureCertificateStateViewController.init()
- }
- self.stateVC.signature = signature
- self.stateVC.pdfListView = pdfListView
- self.stateVC.actionBlock = { [weak self, weak stateVC] stateVCSelf, actionType in
- guard let self = self, let stateVC = stateVC else { return }
- if actionType == .cancel {
- stateVC.dismiss(stateVCSelf)
- } else if actionType == .confirm {
- if let signer = signature.signers.first, let data = signer.certificates {
- let signatureDetail = DSignatureDetailsViewController.init()
- signatureDetail.certificates = data
- signatureDetail.signature = signature
- signatureDetail.pdfListView = pdfListView
- stateVCSelf.presentAsSheet(signatureDetail)
- } else {
- NSSound.beep()
- }
- }
- }
- if let stateVC = self.stateVC {
- self.presentAsSheet(stateVC)
- stateVC.reloadData()
- }
- }
-
- func signElectronicSignature(_ signatureWidgetAnnotation: CPDFSignatureWidgetAnnotation) -> () {
-
- // PDFCustomSignatureWindowController *signatureWindowController = [[PDFCustomSignatureWindowController alloc] init];
- // __block typeof(self) blockSelf = self;
- // [signatureWindowController beginSheetModalForWindow:[NSApp mainWindow] completionHandler:^(PDFSignature *signature){
- // if (signature) {
- // [signatureWidgetAnnotation signWithImage:signature.pathsImage];
- // [blockSelf.PDFListView setNeedsDisplayAnnotationViewForPage:signatureWidgetAnnotation.page];
- // }
- // }];
- // [signatureWindowController release];
- }
-
- //MARK: Notification
- @objc fileprivate func signatureStateChangeNoti() {
-
- let signatures = self.pdfView.document.signatures()!
-
- let tempArr = NSMutableArray()
- for signature in signatures {
- if signature.signers != nil {
- if signature.signers.count > 0 {
- signature.verifySignature(with: self.pdfView.document)
- tempArr.add(signature)
- }
- }
- }
- self.pdfView.signatures = tempArr as? [Any]
-
- self.reloadState()
-
- if self.stateVC != nil {
- let signatureWidget = self.editWidgeAnnotation!
- var signature = signatureWidget.signature()
- if signature == nil {
- return
- }
- self.stateVC.signature = signature
- self.stateVC.reloadData()
- }
- }
- }
- extension KMPDFDigitalSignViewController: CPDFDigtalViewDelegate {
- func pdfListViewAddAnnotation(_ pdfListView: CPDFDigtalView!, forAdd annotation: CPDFAnnotation!, in pdfPage: CPDFPage!) {
-
- let widget = CPDFSignatureWidgetAnnotation.init(PDFListViewNoteWith: self.pdfView.document)
- widget.bounds = CGRectMake(-1000, -1000, 545, 178);
- annotation.page.addAnnotation(widget)
-
- let configWindowVC = DSignatureConfigWindowController.init(windowNibName: "DSignatureConfigWindowController")
- configWindowVC.viewType = .fileList;
- configWindowVC.appearanceWidget = widget;
- configWindowVC.isCreatDS = false
- configWindowVC.complentionHandle = {[unowned self] isSign, dic, config, isLock in
- widget.page.removeAnnotation(widget)
- if isSign {
- if (dic.object(forKey: SAVEFILEPATH_KEY) != nil) {
- let p12Path = dic.object(forKey: SAVEFILEPATH_KEY) as! String
- let password = dic.object(forKey: PASSWORD_KEY)
- if p12Path.count > 0 {
- self.writeSignatureToWidget(annotation as! CPDFSignatureWidgetAnnotation, p12Path, password as! String, config, isLock)
- }
- }
- }
- }
- configWindowVC.actionBlock = { controller, type in
- if (type == .cancel) {
- NSApplication.shared.stopModal()
- controller.window?.orderOut(nil)
- controller.window?.close()
-
- annotation.page.removeAnnotation(annotation)
- widget.page.removeAnnotation(widget)
- self.pdfView.setNeedsDisplayAnnotationViewFor(annotation.page)
-
- } else if (type == .confirm) {
- NSApplication.shared.stopModal()
- controller.window?.orderOut(nil)
- controller.window?.close()
- }
- }
- configWindowVC.window?.center()
- NSApplication.shared.runModal(for: configWindowVC.window!)
- }
-
- func pdfListViewEditAnnotation(_ pdfListView: CPDFDigtalView!, for anotation: CPDFAnnotation!) {
- if anotation.className == CPDFSignatureWidgetAnnotation.className() {
- let signatureWidget = anotation as! CPDFSignatureWidgetAnnotation
- var signature = signatureWidget.signature()
- if signature == nil {
- return
- }
- if signature?.signers != nil {
- self.editWidgeAnnotation = signatureWidget
- self.popUpSignatureWidgetState(signature!, self.pdfView)
- } else if signatureWidget.isSigned() {
- // self.signElectronicSignature(signatureWidget)
- } else {
-
- }
-
- //// __block WindowController *weakself = self;
- // CPDFSignatureWidgetAnnotation *signatureWidget = (CPDFSignatureWidgetAnnotation *)annotation;
- // CPDFSignature *signature = [signatureWidget signature];
- // if (signature.signers.count > 0) {
- // [self popUpSignatureWidgetState:signature];
- // } else if (signatureWidget.isSigned) {
- // [self signElectronicSignature:signatureWidget];
- // } else {
- // CDSignatureSignTypeWindowController *signType = [[CDSignatureSignTypeWindowController alloc] init];
- // signType.callback = ^(CDSignType type) {
- // dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- // if(type == CDSignType_ElectronicSignature) {
- // [weakself signElectronicSignature:signatureWidget];
- // } else {
- // [weakself signDigitalSignature:signatureWidget];
- // }
- // });
- // };
- // [signType startModal:nil];
- // [signType release];
- // }
- }
- }
-
- func pdfListViewDeleteAnnotation(_ pdfListView: CPDFDigtalView!, for anotation: CPDFAnnotation!) {
- let fileName = self.pdfView.document.documentURL?.lastPathComponent
- let fileNameWithoutExtension = URL(fileURLWithPath: fileName!).deletingPathExtension().lastPathComponent
-
- let outputSavePanel = NSSavePanel()
- outputSavePanel.directoryURL = self.pdfView.document.documentURL.deletingLastPathComponent()
- outputSavePanel.title = NSLocalizedString("", comment: "Save as PDF")
- outputSavePanel.allowedFileTypes = ["pdf"]
- outputSavePanel.nameFieldStringValue = fileNameWithoutExtension + "_" + NSLocalizedString("Signed", comment: "")
- let result = outputSavePanel.runModal()
- if result == .OK {
- let success = self.pdfView.document.write(to: outputSavePanel.url)
- if success {
- DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) {
- NSDocumentController.shared.openDocument(withContentsOf: outputSavePanel.url!, display: true) { document, documentWasAlreadyOpen, error in
- if error != nil {
- NSApp.presentError(error!)
- return
- }
- }
- }
- } else {
- let alert = NSAlert.init()
- alert.messageText = NSLocalizedString("Save failed!", comment: "")
- alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
- alert.runModal()
- }
- }
- }
- }
|