diff --git a/extensions/DigiDocQL/PreviewViewController.mm b/extensions/DigiDocQL/PreviewViewController.mm index 7f45c315f..1d6d48240 100644 --- a/extensions/DigiDocQL/PreviewViewController.mm +++ b/extensions/DigiDocQL/PreviewViewController.mm @@ -24,7 +24,7 @@ #include #import -#include +#include using namespace digidoc; @@ -37,11 +37,23 @@ std::string TSLCache() const final { NSURL *directory = [NSFileManager.defaultManager containerURLForSecurityApplicationGroupIdentifier:@"group.ee.ria.qdigidoc4.tsl"]; - return directory.path.UTF8String; + const char *path = directory.path.fileSystemRepresentation; + return path ? path : ""; } }; @implementation NSString (Digidoc) ++ (NSString*)fromUTF8:(std::string_view)value +{ + if (value.empty()) + return @""; + NSString *result = [[NSString alloc] initWithBytes:value.data() length:value.size() encoding:NSUTF8StringEncoding]; + if (result) + return result; + result = [[NSString alloc] initWithBytes:value.data() length:value.size() encoding:NSISOLatin1StringEncoding]; + return result ?: @""; +} + + (NSString*)fileSize:(unsigned long)bytes { if (const auto gb = 1UL << 3; bytes >= gb) @@ -55,30 +67,31 @@ + (NSString*)fileSize:(unsigned long)bytes + (void)parseException:(const Exception&)e result:(NSMutableArray *)result { - [result addObject:[NSString stringWithUTF8String:e.msg().c_str()]]; + [result addObject:[self htmlEntityEncode:e.msg()]]; for (const Exception &i : e.causes()) { [self parseException:i result:result]; } } -+ (NSString*)htmlEntityEncode:(std::string) s ++ (NSString*)htmlEntityEncodeString:(NSString*)value { - using pair = std::pair; - constexpr std::array replace = std::to_array({ - pair{"&", "&"}, - pair{"\"", """}, - pair{"'", "'"}, - pair{"<", "<"}, - pair{">", ">"} - }); - for(const auto &[from, to]: replace) { - size_t startPos = 0; - while ((startPos = s.find(from, startPos)) != std::string::npos) { - s.replace(startPos, from.length(), to); - startPos += to.length(); - } - }; - return [NSString stringWithUTF8String:s.c_str()]; + NSMutableString *result = [NSMutableString stringWithString:value ?: @""]; + for (NSArray *replacement in @[ + @[@"&", @"&"], + @[@"\"", @"""], + @[@"'", @"'"], + @[@"<", @"<"], + @[@">", @">"] + ]) { + [result replaceOccurrencesOfString:replacement[0] withString:replacement[1] + options:0 range:NSMakeRange(0, result.length)]; + } + return result; +} + ++ (NSString*)htmlEntityEncode:(std::string_view)value +{ + return [self htmlEntityEncodeString:[self fromUTF8:value]]; } @end @@ -104,14 +117,19 @@ - (void)providePreviewForFileRequest:(QLFilePreviewRequest *)request NSMutableString *h = [NSMutableString stringWithString:@R"( )"]; - [h appendFormat:@"

%@

", [NSString htmlEntityEncode:request.fileURL.lastPathComponent.UTF8String]]; + [h appendFormat:@"

%@

", + [NSString htmlEntityEncodeString:request.fileURL.lastPathComponent]]; try { static const bool initialized = [] { @@ -137,7 +155,7 @@ - (void)providePreviewForFileRequest:(QLFilePreviewRequest *)request for (const Signature *s : d->signatures()) { [h appendFormat:@"
Signer
%@
", [NSString htmlEntityEncode:s->signedBy()]]; - NSString *date = [NSString stringWithUTF8String:s->trustedSigningTime().c_str()]; + NSString *date = [NSString fromUTF8:s->trustedSigningTime()]; [h appendFormat:@"
Time
%@
", [dto stringFromDate:[dfrom dateFromString:date]]]; Signature::Validator v(s); @@ -183,6 +201,10 @@ - (void)providePreviewForFileRequest:(QLFilePreviewRequest *)request NSMutableArray *err = [NSMutableArray array]; [NSString parseException:e result:err]; [h appendFormat:@"Failed to load document:
%@", [err componentsJoinedByString:@"
"]]; + } catch (const std::exception &e) { + [h appendFormat:@"Failed to load document:
%@", [NSString htmlEntityEncode:e.what()]]; + } catch (...) { + [h appendString:@"Failed to load document:
Unknown error"]; } [h appendString:@""]; return [h dataUsingEncoding:NSUTF8StringEncoding];