Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,11 @@
#import "digidocpp/Exception.h"
#import "DigiDocConfWrapper.h"
#import "../Model/DigiDocConfig.h"
#import "../Container/DigiDocContainerWrapper.h"
#import "Exception/Util/ExceptionUtil.h"

static constexpr int kTSLTimeOutSeconds = 5;

static dispatch_queue_t libdigidocppQueue(void) {
static dispatch_queue_t queue;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
queue = dispatch_queue_create("ee.ria.digidoc.libdigidocpp", DISPATCH_QUEUE_SERIAL);
});
return queue;
}

struct DigiDocConfCurrent final : public digidoc::ConfCurrent {
private:
DigiDocConfig *currentConf;
Expand Down Expand Up @@ -215,23 +207,27 @@ int logLevel() const final {
private:
template<typename Func>
static void withCurrentConf(Func&& fn) {
digidoc::Conf *conf = DigiDocConfCurrent::instance();
if (!conf) return;
DigiDocConfCurrent *currentConf = dynamic_cast<DigiDocConfCurrent*>(conf);
if (currentConf) {
fn(currentConf);
@synchronized ([DigiDocContainerWrapper class]) {
digidoc::Conf *conf = DigiDocConfCurrent::instance();
if (!conf) return;
DigiDocConfCurrent *currentConf = dynamic_cast<DigiDocConfCurrent*>(conf);
if (currentConf) {
fn(currentConf);
}
}
}

public:
static void initConf(DigiDocConfig *conf, NSString *userAgent, void (^completion)(NSError * _Nullable error)) {
dispatch_async(libdigidocppQueue(), ^{
dispatch_async([DigiDocContainerWrapper libraryQueue], ^{
NSError *error = nil;
try {
std::string userAgentInfo = userAgent.UTF8String;
DigiDocConfCurrent *currentConf = new DigiDocConfCurrent(conf);
digidoc::Conf::init(currentConf);
digidoc::initialize(userAgentInfo, userAgentInfo);
@synchronized ([DigiDocContainerWrapper class]) {
DigiDocConfCurrent *currentConf = new DigiDocConfCurrent(conf);
digidoc::Conf::init(currentConf);
digidoc::initialize(userAgentInfo, userAgentInfo);
}
} catch (const digidoc::Exception &e) {
std::vector<digidoc::Exception> causes = e.causes();
NSDictionary *userInfo = @{
Expand All @@ -249,9 +245,11 @@ static void initConf(DigiDocConfig *conf, NSString *userAgent, void (^completion
}

void updateConfiguration(DigiDocConfig *conf) {
dispatch_async(dispatch_get_main_queue(), ^{
DigiDocConfCurrent *newCurrentConf = new DigiDocConfCurrent(conf);
digidoc::Conf::init(newCurrentConf);
dispatch_async([DigiDocContainerWrapper libraryQueue], ^{
@synchronized ([DigiDocContainerWrapper class]) {
DigiDocConfCurrent *newCurrentConf = new DigiDocConfCurrent(conf);
digidoc::Conf::init(newCurrentConf);
}
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@ NS_ASSUME_NONNULL_BEGIN

@interface DigiDocContainerWrapper : NSObject

+ (dispatch_queue_t)libraryQueue;

+ (void)create:(NSString *)containerPath withDataFilePaths:(NSArray<NSString *> *)dataFilePaths completion:(void (^)(NSError * _Nullable error))completion;

+ (nullable DigiDocContainer *)open:(NSString *)containerPath validateOnline:(BOOL)validateOnline error:(NSError **)error;

+ (void)open:(NSString *)containerPath
validateOnline:(BOOL)validateOnline
completion:(void (^)(DigiDocContainer * _Nullable container, NSError * _Nullable error))completion;

+ (void)addDataFilesToContainerWithPath:(NSString *)containerPath withDataFilePaths:(NSArray<NSString*> *)dataFilePaths completion:(void (^)(NSError * _Nullable error))completion;

+ (void)container:(NSString *)containerPath saveDataFile:(NSString *)fileName to:(NSString *)path completion:(void (^)(NSError * _Nullable error))completion;
Expand All @@ -34,4 +40,28 @@ NS_ASSUME_NONNULL_BEGIN

@end

NS_SWIFT_SENDABLE
@interface DigiDocValidationSession : NSObject

@property (nonatomic, readonly) NSUInteger signatureCount;

+ (void)open:(NSString *)containerPath
validateOnline:(BOOL)validateOnline
completion:(void (^NS_SWIFT_SENDABLE)(DigiDocValidationSession * _Nullable session,
DigiDocContainer * _Nullable container,
NSError * _Nullable error))completion
NS_SWIFT_NAME(open(_:validateOnline:completion:));

- (void)validateSignatureAtIndex:(NSUInteger)index
completion:(void (^NS_SWIFT_SENDABLE)(DigiDocSignature * _Nullable signature,
NSError * _Nullable error))completion
NS_SWIFT_NAME(validateSignature(at:completion:));

- (void)closeWithCompletion:(void (^NS_SWIFT_SENDABLE)(void))completion
NS_SWIFT_NAME(close(completion:));

- (instancetype)init NS_UNAVAILABLE;

@end

NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
@interface DigiDocContainerWrapper ()
+ (DigiDocSignatureStatus)determineSignatureStatus:(int)status;
+ (DigiDocSignatureWarning)determineSignatureWarning:(digidoc::Exception::ExceptionCode)code;
+ (NSError *)errorFromException:(const digidoc::Exception &)e;
+ (DigiDocSignature *)getSignatureMetadata:(digidoc::Signature *)signature pos:(int)pos;
+ (DigiDocSignature *)getSignature:(digidoc::Signature *)signature pos:(int)pos;
@end

struct DigiDocContainerOpenCB: public digidoc::ContainerOpenCB {
Expand Down Expand Up @@ -80,12 +83,23 @@ static bool canExtend(const std::vector<digidoc::Signature *> &signatures, const

@implementation DigiDocContainerWrapper {}

+ (dispatch_queue_t)libraryQueue {
static dispatch_queue_t queue;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
queue = dispatch_queue_create("ee.ria.digidoc.libdigidocpp", DISPATCH_QUEUE_SERIAL);
});
return queue;
}

+ (void)dispatch:(void (^)(void))command completion:(void (^)(NSError *error))completion {
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_async([self libraryQueue], ^{
NSError *error = nil;

try {
command();
@synchronized ([DigiDocContainerWrapper class]) {
command();
}
} catch (const digidoc::Exception &e) {
std::vector<digidoc::Exception> causes = e.causes();
NSDictionary *userInfo = @{
Expand Down Expand Up @@ -152,7 +166,7 @@ + (DigiDocSignatureWarning)determineSignatureWarning:(digidoc::Exception::Except
}
}

+ (DigiDocSignature *)getSignature:(digidoc::Signature *)signature pos:(int)pos mediaType:(const std::string&)mediaType dataFileCount:(NSInteger)dataFileCount {
+ (DigiDocSignature *)getSignatureMetadata:(digidoc::Signature *)signature pos:(int)pos {

digidoc::X509Cert signingCert = signature->signingCertificate();
digidoc::X509Cert ocspCert = signature->OCSPCertificate();
Expand Down Expand Up @@ -184,7 +198,8 @@ + (DigiDocSignature *)getSignature:(digidoc::Signature *)signature pos:(int)pos
digiDocSignature.timeStampTime = [NSString stringWithUTF8String:signature->TimeStampTime().c_str()];
digiDocSignature.signedBy = [NSString stringWithUTF8String:name.c_str()];
digiDocSignature.format = [NSString stringWithUTF8String:signature->profile().c_str()];
digiDocSignature.messageImprint = [NSData dataWithBytes:signature->messageImprint().data() length:signature->messageImprint().size()];
auto messageImprint = signature->messageImprint();
digiDocSignature.messageImprint = [NSData dataWithBytes:messageImprint.data() length:messageImprint.size()];
digiDocSignature.trustedSigningTime = [NSString stringWithUTF8String:signature->trustedSigningTime().c_str()];

auto archiveTimestamps = signature->ArchiveTimeStamps();
Expand All @@ -209,10 +224,19 @@ + (DigiDocSignature *)getSignature:(digidoc::Signature *)signature pos:(int)pos
digiDocSignature.country = [NSString stringWithUTF8String:signature->countryName().c_str()];
digiDocSignature.zipCode = [NSString stringWithUTF8String:signature->postalCode().c_str()];

digiDocSignature.status = UnknownStatus;
digiDocSignature.diagnosticsInfo = @"";
digiDocSignature.warnings = @[];

return digiDocSignature;
}

+ (DigiDocSignature *)getSignature:(digidoc::Signature *)signature pos:(int)pos {
DigiDocSignature *digiDocSignature = [DigiDocContainerWrapper getSignatureMetadata:signature pos:pos];

digidoc::Signature::Validator validator(signature);
digidoc::Signature::Validator::Status status = validator.status();
digiDocSignature.diagnosticsInfo = [NSString stringWithUTF8String:validator.diagnostics().c_str()];
digiDocSignature.status = [DigiDocContainerWrapper determineSignatureStatus:status];
digiDocSignature.status = [DigiDocContainerWrapper determineSignatureStatus:validator.status()];

std::vector<digidoc::Exception::ExceptionCode> validatorWarnings = validator.warnings();
NSMutableArray<NSNumber *> *warnings = [NSMutableArray arrayWithCapacity:validatorWarnings.size()];
Expand All @@ -222,7 +246,6 @@ + (DigiDocSignature *)getSignature:(digidoc::Signature *)signature pos:(int)pos
digiDocSignature.warnings = warnings;

return digiDocSignature;

}

+ (void)create:(NSString *)containerPath withDataFilePaths:(NSArray<NSString *> *)dataFilePaths completion:(void (^)(NSError * _Nullable error))completion {
Expand Down Expand Up @@ -291,7 +314,7 @@ + (nullable DigiDocContainer *)open:(NSString *)containerPath validateOnline:(BO
NSMutableArray *signatures = [NSMutableArray array];
int pos = 0;
for (digidoc::Signature *signature: container->signatures()) {
[signatures addObject:[DigiDocContainerWrapper getSignature:signature pos:pos++ mediaType:container->mediaType() dataFileCount:container->dataFiles().size()]];
[signatures addObject:[DigiDocContainerWrapper getSignature:signature pos:pos++]];
}

NSString *mediatype = [NSString stringWithUTF8String:container->mediaType().c_str()];
Expand All @@ -316,6 +339,28 @@ + (nullable DigiDocContainer *)open:(NSString *)containerPath validateOnline:(BO
}
}

+ (void)open:(NSString *)containerPath
validateOnline:(BOOL)validateOnline
completion:(void (^)(DigiDocContainer * _Nullable container, NSError * _Nullable error))completion {
dispatch_async([self libraryQueue], ^{
NSError *error = nil;
DigiDocContainer *container = [self open:containerPath validateOnline:validateOnline error:&error];

dispatch_async(dispatch_get_main_queue(), ^{
completion(container, error);
});
});
}

+ (NSError *)errorFromException:(const digidoc::Exception &)e {
std::vector<digidoc::Exception> causes = e.causes();
NSDictionary *userInfo = @{
NSLocalizedDescriptionKey: [NSString stringWithUTF8String:e.msg().c_str()],
@"causes": [ExceptionUtil exceptionCauses:static_cast<void *>(&causes)]
};
return [NSError errorWithDomain:@"LibdigidocLib" code:e.code() userInfo:userInfo];
}

+ (NSString *)libdigidocppVersion {
return [NSString stringWithUTF8String:digidoc::version().c_str()];
}
Expand Down Expand Up @@ -477,4 +522,135 @@ + (void)extendContainerToLTA:(NSString *)containerPath
}


@end

@interface DigiDocValidationSession ()
- (instancetype)initWithContainer:(std::unique_ptr<digidoc::Container> &&)container;
@end

@implementation DigiDocValidationSession {
std::unique_ptr<digidoc::Container> _container;
std::vector<digidoc::Signature *> _signatures;
}

- (instancetype)initWithContainer:(std::unique_ptr<digidoc::Container> &&)container {
self = [super init];
if (self) {
_container = std::move(container);
_signatures = _container->signatures();
_signatureCount = _signatures.size();
}
return self;
}

+ (void)open:(NSString *)containerPath
validateOnline:(BOOL)validateOnline
completion:(void (^NS_SWIFT_SENDABLE)(DigiDocValidationSession * _Nullable session,
DigiDocContainer * _Nullable container,
NSError * _Nullable error))completion {
dispatch_async([DigiDocContainerWrapper libraryQueue], ^{
NSError *error = nil;
DigiDocValidationSession *session = nil;
DigiDocContainer *parsed = nil;

@synchronized ([DigiDocContainerWrapper class]) {
try {
DigiDocContainerOpenCB cb(validateOnline);
std::unique_ptr<digidoc::Container> container =
digidoc::Container::openPtr(containerPath.UTF8String, &cb);

if (!container) {
error = [NSError errorWithDomain:@"LibdigidocLib" code:3 userInfo:@{
NSLocalizedDescriptionKey: @"Unable to open container"
}];
} else {
NSMutableArray *datafiles = [NSMutableArray array];
for (const digidoc::DataFile *dataFile : container->dataFiles()) {
DigiDocDataFile *digiDocDataFile = [DigiDocDataFile new];
digiDocDataFile.fileId = [NSString stringWithUTF8String:dataFile->id().c_str()];
digiDocDataFile.fileName = [NSString stringWithUTF8String:dataFile->fileName().c_str()];
digiDocDataFile.fileSize = dataFile->fileSize();
digiDocDataFile.mediaType = [NSString stringWithUTF8String:dataFile->mediaType().c_str()];
[datafiles addObject:digiDocDataFile];
}

NSMutableArray *signatures = [NSMutableArray array];
int pos = 0;
for (digidoc::Signature *signature: container->signatures()) {
[signatures addObject:[DigiDocContainerWrapper getSignatureMetadata:signature pos:pos++]];
}

parsed = [[DigiDocContainer alloc]
initWithFileName:containerPath.lastPathComponent
filePath:containerPath
dataFiles:datafiles
signatures:signatures
mediatype:[NSString stringWithUTF8String:container->mediaType().c_str()]];

session = [[DigiDocValidationSession alloc] initWithContainer:std::move(container)];
}
} catch(const digidoc::Exception &e) {
error = [DigiDocContainerWrapper errorFromException:e];
}
}

dispatch_async(dispatch_get_main_queue(), ^{
completion(session, parsed, error);
});
});
}

- (void)validateSignatureAtIndex:(NSUInteger)index
completion:(void (^NS_SWIFT_SENDABLE)(DigiDocSignature * _Nullable signature,
NSError * _Nullable error))completion {
dispatch_async([DigiDocContainerWrapper libraryQueue], ^{
DigiDocSignature *signature = nil;
NSError *error = nil;

@synchronized ([DigiDocContainerWrapper class]) {
if (!self->_container || index >= self->_signatures.size()) {
error = [NSError errorWithDomain:@"LibdigidocLib" code:4 userInfo:@{
NSLocalizedDescriptionKey: @"Validation session is closed or the index is out of range"
}];
} else {
try {
signature = [DigiDocContainerWrapper getSignature:self->_signatures[index] pos:(int)index];
} catch(const digidoc::Exception &e) {
error = [DigiDocContainerWrapper errorFromException:e];
}
}
}

dispatch_async(dispatch_get_main_queue(), ^{
completion(signature, error);
});
});
}

- (void)closeWithCompletion:(void (^NS_SWIFT_SENDABLE)(void))completion {
dispatch_async([DigiDocContainerWrapper libraryQueue], ^{
@synchronized ([DigiDocContainerWrapper class]) {
self->_signatures.clear();
self->_container.reset();
}

dispatch_async(dispatch_get_main_queue(), ^{
completion();
});
});
}

- (void)dealloc {
digidoc::Container *container = _container.release();
if (!container) {
return;
}

dispatch_async([DigiDocContainerWrapper libraryQueue], ^{
@synchronized ([DigiDocContainerWrapper class]) {
delete container;
}
});
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ NS_ASSUME_NONNULL_BEGIN

@interface DigiDocSigningWrapper : NSObject

- (void)prepareSignature:(NSData *)cert containerPath:(NSString *)containerPath roleData:(DigiDocRoleData *)roleData userAgent:(NSString *)userAgent completion:(void (^)(NSData * _Nullable dataToSign, NSError * _Nullable error))completion;
- (void)addSignature:(NSData *)data completion:(void (^)(BOOL valid, NSError * _Nullable error))completion;
- (void)prepareSignature:(NSData *)cert containerPath:(NSString *)containerPath roleData:(DigiDocRoleData *)roleData userAgent:(NSString *)userAgent completion:(void (^NS_SWIFT_SENDABLE)(NSData * _Nullable dataToSign, NSError * _Nullable error))completion;
- (void)addSignature:(NSData *)data completion:(void (^NS_SWIFT_SENDABLE)(BOOL valid, NSError * _Nullable error))completion;

@end

Expand Down
Loading
Loading