Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed opening CAdES files #480

Merged
merged 4 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions MoppApp/MoppApp/ContainerActions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,8 @@ extension ContainerActions where Self: UIViewController {
let topSigningViewController = navController.viewControllers.last!

landingViewController.documentPicker.dismiss(animated: false, completion: nil)

if landingViewController.fileImportIntent == .openOrCreate && landingViewController.containerType == .asic && urls.count == 1 {
self.importDataFiles(with: urls, navController: navController, topSigningViewController: topSigningViewController, landingViewController: landingViewController, cleanup: cleanup, isEmptyFileImported: isEmptyFileImported, isSendingToSivaAgreed: true)
}

self.importDataFiles(with: urls, navController: navController, topSigningViewController: topSigningViewController, landingViewController: landingViewController, cleanup: cleanup, isEmptyFileImported: isEmptyFileImported, isSendingToSivaAgreed: true)
}

func importDataFiles(with urls: [URL], navController: UINavigationController, topSigningViewController: UIViewController, landingViewController: LandingViewController, cleanup: Bool, isEmptyFileImported: Bool, isSendingToSivaAgreed: Bool) {
Expand Down Expand Up @@ -82,16 +80,19 @@ extension ContainerActions where Self: UIViewController {
let isAsicOrPadesContainer = (ext.isAsicContainerExtension || ext == ContainerFormatPDF) &&
landingViewController.containerType == .asic
let isCdocContainer = ext.isCdocContainerExtension && landingViewController.containerType == .cdoc
if (isAsicOrPadesContainer || isCdocContainer) && urls.count == 1 {
if (urls.first?.pathExtension == "asics" || urls.first?.pathExtension == "scs") || SignatureUtil.isCades(signatures: SignatureUtil.getSignatures(filePath: urls.first!)) {
if (isAsicOrPadesContainer || isCdocContainer) && urls.count == 1 {
SiVaUtil.setIsSentToSiva(isSent: false)

if let firstUrl = urls.first, (firstUrl.pathExtension == "asics" || firstUrl.pathExtension == "scs") || MimeTypeExtractor.isCadesContainer(filePath: firstUrl) {
if self?.getTopViewController() is FileImportProgressViewController {
self?.dismiss(animated: true, completion: {
SiVaUtil.displaySendingToSiVaDialog { hasAgreed in
self?.openExistingContainer(with: urls.first!, cleanup: cleanup, isEmptyFileImported: isEmptyFileImported, isSendingToSivaAgreed: hasAgreed)
self?.openExistingContainer(with: firstUrl, cleanup: cleanup, isEmptyFileImported: isEmptyFileImported, isSendingToSivaAgreed: hasAgreed)
}
})
}
} else {
SiVaUtil.setIsSentToSiva(isSent: true)
self?.openExistingContainer(with: urls.first!, cleanup: cleanup, isEmptyFileImported: isEmptyFileImported, isSendingToSivaAgreed: isSendingToSivaAgreed)
}
} else {
Expand Down Expand Up @@ -150,8 +151,8 @@ extension ContainerActions where Self: UIViewController {
let forbiddenFileExtensions = ["ddoc", "asics", "scs"]
let fileURL = URL(fileURLWithPath: newFilePath)
let fileExtension = fileURL.pathExtension
let isSignedPDF = SiVaUtil.isDocumentSentToSiVa(fileUrl: fileURL)
if (forbiddenFileExtensions.contains(fileExtension) || isSignedPDF) {
let isSignedPDF = SiVaUtil.isSignedPDF(url: fileURL as CFURL)
if (forbiddenFileExtensions.contains(fileExtension) || isSignedPDF || MimeTypeExtractor.isCadesContainer(filePath: fileURL)) {
self.openContainer(url: url, newFilePath: newFilePath, fileName: fileName, landingViewController: landingViewController, navController: navController, isEmptyFileImported: isEmptyFileImported, isSendingToSivaAgreed: isSendingToSivaAgreed) { error in
failure(error)
}
Expand Down Expand Up @@ -189,6 +190,7 @@ extension ContainerActions where Self: UIViewController {
}

func openContainer(url: URL, newFilePath: String, fileName: String, landingViewController: LandingViewController, navController: UINavigationController?, isEmptyFileImported: Bool, isSendingToSivaAgreed: Bool, failure: @escaping ((_ error: NSError?) -> Void)) {
SiVaUtil.setIsSentToSiva(isSent: isSendingToSivaAgreed)
MoppLibContainerActions.sharedInstance().openContainer(withPath: newFilePath,
success: { (_ container: MoppLibContainer?) -> Void in
if container == nil {
Expand Down
4 changes: 3 additions & 1 deletion MoppApp/MoppApp/ContainerViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,8 @@ extension ContainerViewController : UITableViewDataSource {
if signingContainerViewDelegate.getTimestampTokensCount() >= indexPath.row {
timestampToken = signingContainerViewDelegate.getTimestampToken(index: indexPath.row) as? MoppLibSignature ?? MoppLibSignature()

if (containerViewDelegate.getDataFileCount() == 1 && isSendingToSivaAgreed && !isLoadingNestedAsicsDone) {
if (containerViewDelegate.getDataFileCount() == 1 && isSendingToSivaAgreed &&
!isLoadingNestedAsicsDone && !MimeTypeExtractor.isCadesContainer(filePath: URL(fileURLWithPath: containerViewDelegate.getContainerPath()))) {
updateState(.loading)
let dataFile = containerViewDelegate.getDataFileDisplayName(index: 0) ?? ""
let containerFilePath = containerViewDelegate.getContainerPath()
Expand Down Expand Up @@ -773,6 +774,7 @@ extension ContainerViewController : UITableViewDataSource {
if pathExtension == "asics" || pathExtension == "scs" {
SiVaUtil.displaySendingToSiVaDialog { hasAgreed in
if hasAgreed {
SiVaUtil.setIsSentToSiva(isSent: hasAgreed)
self.openNestedContainer(containerFilePath: containerFilePath, dataFile: dataFile, destinationPath: destinationPath)
return
} else {
Expand Down
74 changes: 56 additions & 18 deletions MoppApp/MoppApp/MimeTypeExtractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,32 @@ class MimeTypeExtractor {

private static let DEFAULT_MIMETYPE = "application/octet-stream"

// Check if file is zip format
private static func isZipFile(filePath: URL) -> Bool {
guard let fileHandle = FileHandle(forReadingAtPath: filePath.path) else { return false }
let fileData = fileHandle.readData(ofLength: 4)
let isZip = fileData.starts(with: [0x50, 0x4b, 0x03, 0x04])
do {
try fileHandle.close()
} catch (let zipError) {
printLog("Unable to close zip file: \(zipError.localizedDescription)")
}
return isZip
}

public static func isCadesContainer(filePath: URL) -> Bool {
if isZipFile(filePath: filePath) {
return containerHasSignatureFiles(filePath: filePath)
}

return false
}

public static func getMimeTypeFromContainer(filePath: URL) -> String {

var mimetype: String = ""

guard let fileHandle = FileHandle(forReadingAtPath: filePath.path) else { return "" }
let fileData = fileHandle.readData(ofLength: 4)
// Check if file is zip format
if fileData.starts(with: [0x50, 0x4b, 0x03, 0x04]) {
if isZipFile(filePath: filePath) {
guard let unzippedFile = unZipFile(filePath: filePath, fileName: "mimetype") else {
return mimetype
}
Expand All @@ -48,7 +66,6 @@ class MimeTypeExtractor {

removeUnzippedFolder(folderPath: unzippedFolder)
}
fileHandle.closeFile()

if isDdoc(url: filePath) {
return ContainerFormatDdocMimetype
Expand Down Expand Up @@ -110,25 +127,46 @@ class MimeTypeExtractor {
}

return fileExtension
}

private static func containerHasSignatureFiles(filePath: URL) -> Bool {
do {
let archive = try Archive(url: filePath, accessMode: .read)

for entry in archive {
let entryUrl = URL(fileURLWithPath: entry.path)
if entryUrl.lastPathComponent.contains("p7s") {
return true
}
}
} catch (let archiveError) {
printLog("Unable to open archive: \(archiveError.localizedDescription)")
return false
}

return false
}

private static func unZipFile(filePath: URL, fileName: String) -> URL? {
let outputPath = MoppFileManager.shared.tempCacheDirectoryPath().appendingPathComponent(filePath.lastPathComponent).deletingPathExtension()
guard let archive = Archive(url: filePath, accessMode: .read) else {
return nil
}
guard let fileInArchive = archive[fileName] else {
return nil
}
var destinationLocation = URL(fileURLWithPath: outputPath.path)
destinationLocation.appendPathComponent("mimetype")

do {
printLog("Extracting file: \(fileName)")
_ = try archive.extract(fileInArchive, to: destinationLocation)
return destinationLocation
} catch {
printLog("Unable to extract file \(fileInArchive). Error: \(error.localizedDescription)")
let archive = try Archive(url: filePath, accessMode: .read)
guard let fileInArchive = archive[fileName] else {
return nil
}
var destinationLocation = URL(fileURLWithPath: outputPath.path)
destinationLocation.appendPathComponent("extractedFile")
do {
printLog("Extracting file: \(fileName) to \(destinationLocation.path)")
_ = try archive.extract(fileInArchive, to: destinationLocation)
return destinationLocation
} catch {
printLog("Unable to extract file \(fileInArchive). Error: \(error.localizedDescription)")
return nil
}
} catch (let archiveError) {
printLog("Unable to open archive: \(archiveError.localizedDescription)")
return nil
}
}
Expand Down
5 changes: 5 additions & 0 deletions MoppApp/MoppApp/PreviewActions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ extension PreviewActions where Self: ContainerViewController {
let containerViewController = SigningContainerViewController.instantiate()

let destinationPathURL = URL(fileURLWithPath: destinationPath)
SiVaUtil.setIsSentToSiva(isSent: false)
if SiVaUtil.isDocumentSentToSiVa(fileUrl: destinationPathURL) {
SiVaUtil.displaySendingToSiVaDialog { hasAgreed in
if (destinationPathURL.pathExtension == "ddoc" || destinationPathURL.pathExtension == "pdf") && !hasAgreed {
Expand All @@ -59,6 +60,7 @@ extension PreviewActions where Self: ContainerViewController {
openAsicContainerPreviewDocument(containerViewController, isPDF, hasAgreed)
}
} else {
SiVaUtil.setIsSentToSiva(isSent: true)
openAsicContainerPreviewDocument(containerViewController, isPDF, true)
}
}
Expand Down Expand Up @@ -100,20 +102,23 @@ extension PreviewActions where Self: ContainerViewController {

let fileExtension = URL(fileURLWithPath: filePath).pathExtension.lowercased()

SiVaUtil.setIsSentToSiva(isSent: false)
if fileExtension != "pdf" && SiVaUtil.isDocumentSentToSiVa(fileUrl: URL(fileURLWithPath: filePath)) {
SiVaUtil.displaySendingToSiVaDialog { hasAgreed in
if hasAgreed {
openContentPreviewDocument(filePath)
}
}
} else {
SiVaUtil.setIsSentToSiva(isSent: true)
openContentPreviewDocument(filePath)
}

}

let openPDFPreview: () -> Void = { [weak self] in
self?.updateState(.loading)
SiVaUtil.setIsSentToSiva(isSent: false)
MoppLibContainerActions.sharedInstance().openContainer(
withPath: destinationPath,
success: { [weak self] (_ container: MoppLibContainer?) -> Void in
Expand Down
5 changes: 4 additions & 1 deletion MoppApp/MoppApp/RecentContainersViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -210,14 +210,17 @@ extension RecentContainersViewController : UITableViewDelegate {

if ext.isAsicContainerExtension || ext.isPdfContainerExtension {
let containerPathURL = path
SiVaUtil.setIsSentToSiva(isSent: false)
if SiVaUtil.isDocumentSentToSiVa(fileUrl: containerPathURL) || (containerPathURL.pathExtension == "asics" || containerPathURL.pathExtension == "scs") {
SiVaUtil.displaySendingToSiVaDialog { hasAgreed in
if (containerPathURL.pathExtension == "ddoc" || containerPathURL.pathExtension == "pdf") && !hasAgreed {
if (containerPathURL.pathExtension == "ddoc" || containerPathURL.pathExtension == "pdf" ||
MimeTypeExtractor.isCadesContainer(filePath: containerPathURL)) && !hasAgreed {
return
}
self.openContainer(containerPath: path.path, navController: navController, isSendingToSivaAgreed: hasAgreed)
}
} else {
SiVaUtil.setIsSentToSiva(isSent: true)
self.openContainer(containerPath: path.path, navController: navController, isSendingToSivaAgreed: true)
}
} else {
Expand Down
17 changes: 15 additions & 2 deletions MoppApp/MoppApp/SivaUtil.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,33 @@

import Foundation
import PDFKit
import MoppLib

class SiVaUtil {
static func isDocumentSentToSiVa(fileUrl: URL?) -> Bool {
guard let fileLocation = fileUrl else { return false }
let containerTypes = ["asics", "scs", "ddoc"]
let containerType = MimeTypeExtractor.determineContainer(mimetype: MimeTypeExtractor.getMimeTypeFromContainer(filePath: fileLocation), fileExtension: fileLocation.pathExtension).lowercased()

if containerType == "pdf" {
return isSignedPDF(url: fileLocation as CFURL)
let isSignedPDF = isSignedPDF(url: fileLocation as CFURL)
return isSignedPDF
}

return containerType == "ddoc" || SignatureUtil.isCades(signatures: SignatureUtil.getSignatures(filePath: fileLocation))
let isCades = MimeTypeExtractor.isCadesContainer(filePath: fileLocation)
let isSentToSiva = containerTypes.contains(containerType) || isCades

return isSentToSiva
}

static func displaySendingToSiVaDialog(completionHandler: @escaping (Bool) -> Void) {
let alert = UIAlertController(title: L(.sivaSendMessage).removeFirstLinkFromMessage(), message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: L(.actionYes).uppercased(), style: .default, handler: { (_ action: UIAlertAction) in
setIsSentToSiva(isSent: true)
completionHandler(true)
}))
alert.addAction(UIAlertAction(title: L(.actionAbort), style: .default, handler: {(_ action: UIAlertAction) -> Void in
setIsSentToSiva(isSent: false)
completionHandler(false)
}))
if let linkInUrl: String = L(.sivaSendMessage).getFirstLinkInMessage() {
Expand Down Expand Up @@ -112,4 +120,9 @@ class SiVaUtil {

return false
}

static func setIsSentToSiva(isSent: Bool) {
let validateOnlineInstance = MoppLibDigidocValidateOnline.sharedInstance()
validateOnlineInstance?.validateOnline = isSent
}
}
8 changes: 8 additions & 0 deletions MoppLib/MoppLib.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@
C5F462A8209727E8001B7D59 /* CoreBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5F462A7209727E8001B7D59 /* CoreBluetooth.framework */; };
C5F974D4217646CD00A167C7 /* TestEnvInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = C5F974D3217646CC00A167C7 /* TestEnvInfo.plist */; };
DF1503872AC5CE32007222B2 /* OCMock in Frameworks */ = {isa = PBXBuildFile; productRef = DF1503862AC5CE32007222B2 /* OCMock */; };
DF169D5A2B9000F0000DD46C /* MoppLibDigidocValidateOnline.h in Headers */ = {isa = PBXBuildFile; fileRef = DF169D592B9000F0000DD46C /* MoppLibDigidocValidateOnline.h */; settings = {ATTRIBUTES = (Public, ); }; };
DF169D5C2B90011E000DD46C /* MoppLibDigidocValidateOnline.m in Sources */ = {isa = PBXBuildFile; fileRef = DF169D5B2B90011E000DD46C /* MoppLibDigidocValidateOnline.m */; };
DF1EE2BD234DD20500E37CA8 /* MoppLibCertificateInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DF1EE2BB234DD20500E37CA8 /* MoppLibCertificateInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
DF1EE2BE234DD20500E37CA8 /* MoppLibCertificateInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = DF1EE2BC234DD20500E37CA8 /* MoppLibCertificateInfo.mm */; };
DF87E9CE292CC79500C2E3F4 /* libdigidocpp_util.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DF87E9CD292CC77C00C2E3F4 /* libdigidocpp_util.a */; };
Expand Down Expand Up @@ -178,6 +180,8 @@
C5E41C5C2180602B00D79B54 /* Idemia.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Idemia.m; sourceTree = "<group>"; };
C5F462A7209727E8001B7D59 /* CoreBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreBluetooth.framework; path = System/Library/Frameworks/CoreBluetooth.framework; sourceTree = SDKROOT; };
C5F974D3217646CC00A167C7 /* TestEnvInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = TestEnvInfo.plist; sourceTree = "<group>"; };
DF169D592B9000F0000DD46C /* MoppLibDigidocValidateOnline.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MoppLibDigidocValidateOnline.h; sourceTree = "<group>"; };
DF169D5B2B90011E000DD46C /* MoppLibDigidocValidateOnline.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MoppLibDigidocValidateOnline.m; sourceTree = "<group>"; };
DF1EE2BB234DD20500E37CA8 /* MoppLibCertificateInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MoppLibCertificateInfo.h; sourceTree = "<group>"; };
DF1EE2BC234DD20500E37CA8 /* MoppLibCertificateInfo.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MoppLibCertificateInfo.mm; sourceTree = "<group>"; };
DF87E9CD292CC77C00C2E3F4 /* libdigidocpp_util.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libdigidocpp_util.a; path = MoppLib/libdigidocpp/libdigidocpp.iphoneos/lib/libdigidocpp_util.a; sourceTree = "<group>"; };
Expand Down Expand Up @@ -440,6 +444,8 @@
E4250CFF1E096CAA00530370 /* test.bdoc */,
E4250CF21E096A0500530370 /* libdigidocpp */,
C55A20C321762448007BB191 /* mopplib.modulemap */,
DF169D592B9000F0000DD46C /* MoppLibDigidocValidateOnline.h */,
DF169D5B2B90011E000DD46C /* MoppLibDigidocValidateOnline.m */,
);
path = MoppLib;
sourceTree = "<group>";
Expand Down Expand Up @@ -507,6 +513,7 @@
545CF8411E13F30300B66EE8 /* EstEIDv3_4.h in Headers */,
C5AAAF8420CAA3D00087D6DA /* ReaderInterface.h in Headers */,
54DC0DC51E0BCC2A00C62B3D /* CardReaderWrapper.h in Headers */,
DF169D5A2B9000F0000DD46C /* MoppLibDigidocValidateOnline.h in Headers */,
C5E41C5D2180602B00D79B54 /* Idemia.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -645,6 +652,7 @@
54D1647C1E926AAB0069C725 /* MoppLibCardActions.m in Sources */,
E42B08CA1E1F11C100EA24A3 /* MoppLibSignature.m in Sources */,
54DC0DCA1E0BCCEF00C62B3D /* MoppLibConstants.m in Sources */,
DF169D5C2B90011E000DD46C /* MoppLibDigidocValidateOnline.m in Sources */,
54DC0DF51E0BEF2A00C62B3D /* NSString+Additions.m in Sources */,
540CB2211E1CDCED00FE18A3 /* MoppLibCertificate.mm in Sources */,
399C01E320BC11C20056D7AC /* MoppLibCryptoActions.m in Sources */,
Expand Down
Loading