mirror of
				https://github.com/JakubMelka/PDF4QT.git
				synced 2025-06-05 21:59:17 +02:00 
			
		
		
		
	Adjusting password
This commit is contained in:
		| @@ -34,7 +34,7 @@ namespace pdf | |||||||
| { | { | ||||||
|  |  | ||||||
| PDFDocumentReader::PDFDocumentReader(const std::function<QString(bool*)>& getPasswordCallback) : | PDFDocumentReader::PDFDocumentReader(const std::function<QString(bool*)>& getPasswordCallback) : | ||||||
|     m_successfull(true), |     m_result(Result::OK), | ||||||
|     m_getPasswordCallback(getPasswordCallback) |     m_getPasswordCallback(getPasswordCallback) | ||||||
| { | { | ||||||
|  |  | ||||||
| @@ -56,13 +56,13 @@ PDFDocument PDFDocumentReader::readFromFile(const QString& fileName) | |||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             m_successfull = false; |             m_result = Result::Failed; | ||||||
|             m_errorMessage = tr("File '%1' cannot be opened for reading. %1").arg(file.errorString()); |             m_errorMessage = tr("File '%1' cannot be opened for reading. %1").arg(file.errorString()); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
|         m_successfull = false; |         m_result = Result::Failed; | ||||||
|         m_errorMessage = tr("File '%1' doesn't exist.").arg(fileName); |         m_errorMessage = tr("File '%1' doesn't exist.").arg(fileName); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -82,7 +82,7 @@ PDFDocument PDFDocumentReader::readFromDevice(QIODevice* device) | |||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             m_successfull = false; |             m_result = Result::Failed; | ||||||
|             m_errorMessage = tr("Device is not opened for reading."); |             m_errorMessage = tr("Device is not opened for reading."); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -94,7 +94,7 @@ PDFDocument PDFDocumentReader::readFromDevice(QIODevice* device) | |||||||
|     } |     } | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
|         m_successfull = false; |         m_result = Result::Failed; | ||||||
|         m_errorMessage = tr("Can't open device for reading."); |         m_errorMessage = tr("Can't open device for reading."); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -246,7 +246,7 @@ PDFDocument PDFDocumentReader::readFromBuffer(const QByteArray& buffer) | |||||||
|         { |         { | ||||||
|             Q_ASSERT(entry.type == PDFXRefTable::EntryType::Occupied); |             Q_ASSERT(entry.type == PDFXRefTable::EntryType::Occupied); | ||||||
|  |  | ||||||
|             if (m_successfull) |             if (m_result == Result::OK) | ||||||
|             { |             { | ||||||
|                 try |                 try | ||||||
|                 { |                 { | ||||||
| @@ -259,7 +259,7 @@ PDFDocument PDFDocumentReader::readFromBuffer(const QByteArray& buffer) | |||||||
|                 catch (PDFParserException exception) |                 catch (PDFParserException exception) | ||||||
|                 { |                 { | ||||||
|                     QMutexLocker lock(&m_mutex); |                     QMutexLocker lock(&m_mutex); | ||||||
|                     m_successfull = false; |                     m_result = Result::Failed; | ||||||
|                     m_errorMessage = exception.getMessage(); |                     m_errorMessage = exception.getMessage(); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @@ -318,10 +318,15 @@ PDFDocument PDFDocumentReader::readFromBuffer(const QByteArray& buffer) | |||||||
|         PDFSecurityHandlerPointer securityHandler = PDFSecurityHandler::createSecurityHandler(encryptObject, id); |         PDFSecurityHandlerPointer securityHandler = PDFSecurityHandler::createSecurityHandler(encryptObject, id); | ||||||
|         PDFSecurityHandler::AuthorizationResult authorizationResult = securityHandler->authenticate(m_getPasswordCallback); |         PDFSecurityHandler::AuthorizationResult authorizationResult = securityHandler->authenticate(m_getPasswordCallback); | ||||||
|  |  | ||||||
|         if (authorizationResult == PDFSecurityHandler::AuthorizationResult::Failed || |         if (authorizationResult == PDFSecurityHandler::AuthorizationResult::Cancelled) | ||||||
|             authorizationResult == PDFSecurityHandler::AuthorizationResult::Cancelled) |         { | ||||||
|  |             // User cancelled the document reading | ||||||
|  |             m_result = Result::Cancelled; | ||||||
|  |             return PDFDocument(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (authorizationResult == PDFSecurityHandler::AuthorizationResult::Failed) | ||||||
|         { |         { | ||||||
|             // TODO: If user cancels it, do not display error message. |  | ||||||
|             throw PDFParserException(PDFTranslationContext::tr("Authorization failed. Bad password provided.")); |             throw PDFParserException(PDFTranslationContext::tr("Authorization failed. Bad password provided.")); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -340,7 +345,7 @@ PDFDocument PDFDocumentReader::readFromBuffer(const QByteArray& buffer) | |||||||
|  |  | ||||||
|         auto processObjectStream = [this, &getObject, &objectFetcher, &objects, &objectStreamEntries] (const PDFObjectReference& objectStreamReference) |         auto processObjectStream = [this, &getObject, &objectFetcher, &objects, &objectStreamEntries] (const PDFObjectReference& objectStreamReference) | ||||||
|         { |         { | ||||||
|             if (!m_successfull) |             if (m_result != Result::OK) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| @@ -423,7 +428,7 @@ PDFDocument PDFDocumentReader::readFromBuffer(const QByteArray& buffer) | |||||||
|             catch (PDFParserException exception) |             catch (PDFParserException exception) | ||||||
|             { |             { | ||||||
|                 QMutexLocker lock(&m_mutex); |                 QMutexLocker lock(&m_mutex); | ||||||
|                 m_successfull = false; |                 m_result = Result::Failed; | ||||||
|                 m_errorMessage = exception.getMessage(); |                 m_errorMessage = exception.getMessage(); | ||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
| @@ -436,7 +441,7 @@ PDFDocument PDFDocumentReader::readFromBuffer(const QByteArray& buffer) | |||||||
|     } |     } | ||||||
|     catch (PDFParserException parserException) |     catch (PDFParserException parserException) | ||||||
|     { |     { | ||||||
|         m_successfull = false; |         m_result = Result::Failed; | ||||||
|         m_errorMessage = parserException.getMessage(); |         m_errorMessage = parserException.getMessage(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -445,7 +450,7 @@ PDFDocument PDFDocumentReader::readFromBuffer(const QByteArray& buffer) | |||||||
|  |  | ||||||
| void PDFDocumentReader::reset() | void PDFDocumentReader::reset() | ||||||
| { | { | ||||||
|     m_successfull = true; |     m_result = Result::OK; | ||||||
|     m_errorMessage = QString(); |     m_errorMessage = QString(); | ||||||
|     m_version = PDFVersion(); |     m_version = PDFVersion(); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -43,6 +43,13 @@ public: | |||||||
|     constexpr inline PDFDocumentReader& operator=(const PDFDocumentReader&) = delete; |     constexpr inline PDFDocumentReader& operator=(const PDFDocumentReader&) = delete; | ||||||
|     constexpr inline PDFDocumentReader& operator=(PDFDocumentReader&&) = delete; |     constexpr inline PDFDocumentReader& operator=(PDFDocumentReader&&) = delete; | ||||||
|  |  | ||||||
|  |     enum class Result | ||||||
|  |     { | ||||||
|  |         OK,         ///< Document was successfully loaded | ||||||
|  |         Failed,     ///< Error occured during document reading | ||||||
|  |         Cancelled   ///< User cancelled document reading | ||||||
|  |     }; | ||||||
|  |  | ||||||
|     /// Reads a PDF document from the specified file. If file doesn't exist, |     /// Reads a PDF document from the specified file. If file doesn't exist, | ||||||
|     /// cannot be opened or contain invalid pdf, empty PDF file is returned. |     /// cannot be opened or contain invalid pdf, empty PDF file is returned. | ||||||
|     /// No exception is thrown. |     /// No exception is thrown. | ||||||
| @@ -58,8 +65,8 @@ public: | |||||||
|     /// PDF is read, then empty PDF document is returned. No exception is thrown. |     /// PDF is read, then empty PDF document is returned. No exception is thrown. | ||||||
|     PDFDocument readFromBuffer(const QByteArray& buffer); |     PDFDocument readFromBuffer(const QByteArray& buffer); | ||||||
|  |  | ||||||
|     /// Returns true, if document was successfully read from device |     /// Returns result code for reading document from the device | ||||||
|     bool isSuccessfull() const { return m_successfull; } |     Result getReadingResult() const { return m_result; } | ||||||
|  |  | ||||||
|     /// Returns error message, if document reading was unsuccessfull |     /// Returns error message, if document reading was unsuccessfull | ||||||
|     const QString& getErrorMessage() const { return m_errorMessage; } |     const QString& getErrorMessage() const { return m_errorMessage; } | ||||||
| @@ -83,8 +90,8 @@ private: | |||||||
|     /// (providing thread safety) |     /// (providing thread safety) | ||||||
|     QMutex m_mutex; |     QMutex m_mutex; | ||||||
|  |  | ||||||
|     /// This bool flag is set, if pdf document was successfully read from the device |     /// Result of document reading from the device | ||||||
|     std::atomic<bool> m_successfull; |     std::atomic<Result> m_result; | ||||||
|  |  | ||||||
|     /// In case if error occurs, it is stored here |     /// In case if error occurs, it is stored here | ||||||
|     QString m_errorMessage; |     QString m_errorMessage; | ||||||
|   | |||||||
| @@ -1871,6 +1871,33 @@ QString PDFEncoding::convert(const QByteArray& stream, PDFEncoding::Encoding enc | |||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | QByteArray PDFEncoding::convertToEncoding(const QString& string, PDFEncoding::Encoding encoding) | ||||||
|  | { | ||||||
|  |     QByteArray result; | ||||||
|  |  | ||||||
|  |     const encoding::EncodingTable* table = getTableForEncoding(encoding); | ||||||
|  |     Q_ASSERT(table); | ||||||
|  |  | ||||||
|  |     result.reserve(string.size()); | ||||||
|  |     for (QChar character : string) | ||||||
|  |     { | ||||||
|  |         ushort unicode = character.unicode(); | ||||||
|  |         unsigned char converted = 0; | ||||||
|  |  | ||||||
|  |         for (int i = 0; i < table->size(); ++i) | ||||||
|  |         { | ||||||
|  |             if (unicode == (*table)[static_cast<unsigned char>(i)]) | ||||||
|  |             { | ||||||
|  |                 converted = i; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         result.push_back(converted); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  |  | ||||||
| QString PDFEncoding::convertTextString(const QByteArray& stream) | QString PDFEncoding::convertTextString(const QByteArray& stream) | ||||||
| { | { | ||||||
|     if (hasUnicodeLeadMarkings(stream)) |     if (hasUnicodeLeadMarkings(stream)) | ||||||
|   | |||||||
| @@ -59,6 +59,14 @@ public: | |||||||
|     /// \returns Converted unicode string |     /// \returns Converted unicode string | ||||||
|     static QString convert(const QByteArray& stream, Encoding encoding); |     static QString convert(const QByteArray& stream, Encoding encoding); | ||||||
|  |  | ||||||
|  |     /// Converts unicode string to the byte array using the specified encoding. | ||||||
|  |     /// It performs reverse functionality than function \p convert. If the character | ||||||
|  |     /// in the encoding is not found, then it is converted to character code 0. | ||||||
|  |     /// \param string String to be converted | ||||||
|  |     /// \param encoding Encoding used in the conversion | ||||||
|  |     /// \sa convert | ||||||
|  |     static QByteArray convertToEncoding(const QString& string, Encoding encoding); | ||||||
|  |  | ||||||
|     /// Convert text string to the unicode string, using either PDFDocEncoding, |     /// Convert text string to the unicode string, using either PDFDocEncoding, | ||||||
|     /// or UTF-16BE encoding. Please see PDF Reference 1.7, Chapter 3.8.1. If |     /// or UTF-16BE encoding. Please see PDF Reference 1.7, Chapter 3.8.1. If | ||||||
|     /// UTF-16BE encoding is used, then leading bytes should be 0xFE and 0xFF |     /// UTF-16BE encoding is used, then leading bytes should be 0xFE and 0xFF | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ | |||||||
|  |  | ||||||
| #include "pdfsecurityhandler.h" | #include "pdfsecurityhandler.h" | ||||||
| #include "pdfexception.h" | #include "pdfexception.h" | ||||||
|  | #include "pdfencoding.h" | ||||||
|  |  | ||||||
| #include <openssl/rc4.h> | #include <openssl/rc4.h> | ||||||
| #include <openssl/md5.h> | #include <openssl/md5.h> | ||||||
| @@ -369,8 +370,8 @@ PDFSecurityHandler::AuthorizationResult PDFStandardSecurityHandler::authenticate | |||||||
|                         AES_KEY key = { }; |                         AES_KEY key = { }; | ||||||
|                         AES_set_decrypt_key(reinterpret_cast<const unsigned char*>(fileEncryptionDecryptionKey.data()), fileEncryptionDecryptionKey.size() * 8, &key); |                         AES_set_decrypt_key(reinterpret_cast<const unsigned char*>(fileEncryptionDecryptionKey.data()), fileEncryptionDecryptionKey.size() * 8, &key); | ||||||
|                         unsigned char aesInitializationVector[AES_BLOCK_SIZE] = { }; |                         unsigned char aesInitializationVector[AES_BLOCK_SIZE] = { }; | ||||||
|                         m_authorizationData.fileEncryptionKey.resize(m_OE.size()); |                         m_authorizationData.fileEncryptionKey.resize(m_UE.size()); | ||||||
|                         AES_cbc_encrypt(reinterpret_cast<const unsigned char*>(m_OE.data()), reinterpret_cast<unsigned char*>(m_authorizationData.fileEncryptionKey.data()), m_OE.size(), &key, aesInitializationVector, AES_DECRYPT); |                         AES_cbc_encrypt(reinterpret_cast<const unsigned char*>(m_UE.data()), reinterpret_cast<unsigned char*>(m_authorizationData.fileEncryptionKey.data()), m_UE.size(), &key, aesInitializationVector, AES_DECRYPT); | ||||||
|  |  | ||||||
|                         // We have authorized owner access |                         // We have authorized owner access | ||||||
|                         m_authorizationData.authorizationResult =  AuthorizationResult::UserAuthorized; |                         m_authorizationData.authorizationResult =  AuthorizationResult::UserAuthorized; | ||||||
| @@ -380,6 +381,36 @@ PDFSecurityHandler::AuthorizationResult PDFStandardSecurityHandler::authenticate | |||||||
|                 // Stop, if we authorized the document usage |                 // Stop, if we authorized the document usage | ||||||
|                 if (m_authorizationData.isAuthorized()) |                 if (m_authorizationData.isAuthorized()) | ||||||
|                 { |                 { | ||||||
|  |                     // According the PDF specification, we must also check, if flags are not manipulated. | ||||||
|  |                     Q_ASSERT(m_Perms.size() == AES_BLOCK_SIZE); | ||||||
|  |                     AES_KEY key = { }; | ||||||
|  |                     AES_set_decrypt_key(reinterpret_cast<const unsigned char*>(m_authorizationData.fileEncryptionKey.data()), m_authorizationData.fileEncryptionKey.size() * 8, &key); | ||||||
|  |                     QByteArray decodedPerms(m_Perms.size(), char(0)); | ||||||
|  |                     AES_ecb_encrypt(reinterpret_cast<const unsigned char*>(m_Perms.data()), reinterpret_cast<unsigned char*>(decodedPerms.data()), &key, AES_DECRYPT); | ||||||
|  |  | ||||||
|  |                     // 1) Checks, if bytes 9, 10, 11 are 'a', 'd', 'b' | ||||||
|  |                     if (decodedPerms[9] != 'a' || decodedPerms[10] != 'd' || decodedPerms[11] != 'b') | ||||||
|  |                     { | ||||||
|  |                         throw PDFParserException(PDFTranslationContext::tr("Permissions entry in the Encryption dictionary is invalid.")); | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     // 2) Verify, that bytes 0-3 are valid permissions entry | ||||||
|  |                     const uint32_t permissions = qFromLittleEndian(*reinterpret_cast<const uint32_t*>(decodedPerms.data())); | ||||||
|  |                     if (permissions != m_permissions) | ||||||
|  |                     { | ||||||
|  |                         throw PDFParserException(PDFTranslationContext::tr("Security permissions are manipulated. Can't open the document.")); | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     // 3) Verify, that byte 8 is 'T' or 'F' and is equal to EncryptMetadata entry | ||||||
|  |                     if (decodedPerms[8] != 'T' && decodedPerms[8] != 'F') | ||||||
|  |                     { | ||||||
|  |                         throw PDFParserException(PDFTranslationContext::tr("Security permissions are manipulated. Can't open the document.")); | ||||||
|  |                     } | ||||||
|  |                     if ((decodedPerms[8] == 'T') != m_encryptMetadata) | ||||||
|  |                     { | ||||||
|  |                         throw PDFParserException(PDFTranslationContext::tr("Security permissions are manipulated. Can't open the document.")); | ||||||
|  |                     } | ||||||
|  |  | ||||||
|                     return m_authorizationData.authorizationResult; |                     return m_authorizationData.authorizationResult; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
| @@ -390,8 +421,7 @@ PDFSecurityHandler::AuthorizationResult PDFStandardSecurityHandler::authenticate | |||||||
|                 return AuthorizationResult::Failed; |                 return AuthorizationResult::Failed; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // TODO: Handle passwords better - in some revisions, must be in PDFDocEncoding! |         password = adjustPassword(getPasswordCallback(&passwordObtained)); | ||||||
|         password = getPasswordCallback(&passwordObtained).toUtf8(); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return AuthorizationResult::Cancelled; |     return AuthorizationResult::Cancelled; | ||||||
| @@ -767,4 +797,114 @@ PDFStandardSecurityHandler::UserOwnerData_r6 PDFStandardSecurityHandler::parsePa | |||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | QByteArray PDFStandardSecurityHandler::adjustPassword(const QString& password) | ||||||
|  | { | ||||||
|  |     QByteArray result; | ||||||
|  |  | ||||||
|  |     switch (m_R) | ||||||
|  |     { | ||||||
|  |         case 2: | ||||||
|  |         case 3: | ||||||
|  |         case 4: | ||||||
|  |         { | ||||||
|  |             // According to the PDF specification, convert string to PDFDocEncoding encoding | ||||||
|  |             result = PDFEncoding::convertToEncoding(password, PDFEncoding::Encoding::PDFDoc); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         case 6: | ||||||
|  |         { | ||||||
|  |             // According to the PDF specification, use SASLprep profile for stringprep RFC 4013, please see these websites: | ||||||
|  |             //      - RFC 4013: https://tools.ietf.org/html/rfc4013 (SASLprep profile for stringprep algorithm) | ||||||
|  |             //      - RFC 3454: https://tools.ietf.org/html/rfc3454 (stringprep algorithm - preparation of internationalized strings) | ||||||
|  |             // | ||||||
|  |             // Note: we don't do checks according the RFC 4013, just use the mapping and normalize string in KC | ||||||
|  |  | ||||||
|  |             QString preparedPassword; | ||||||
|  |             preparedPassword.reserve(password.size()); | ||||||
|  |  | ||||||
|  |             // RFC 4013 Section 2.1, use mapping | ||||||
|  |  | ||||||
|  |             for (const QChar character : password) | ||||||
|  |             { | ||||||
|  |                 if (isUnicodeMappedToNothing(character.unicode())) | ||||||
|  |                 { | ||||||
|  |                     // Mapped to nothing | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if (isUnicodeNonAsciiSpaceCharacter(character.unicode())) | ||||||
|  |                 { | ||||||
|  |                     // Map to space character | ||||||
|  |                     preparedPassword += QChar(QChar::Space); | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     preparedPassword += character; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // RFC 4013, Section 2.2, normalization to KC | ||||||
|  |             preparedPassword = preparedPassword.normalized(QString::NormalizationForm_KC); | ||||||
|  |  | ||||||
|  |             // We don't do other checks. We will transform password to the UTF-8 encoding | ||||||
|  |             // and according the PDF specification, we take only first 127 characters. | ||||||
|  |             result = preparedPassword.toUtf8().left(127); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         default: | ||||||
|  |             break; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool PDFStandardSecurityHandler::isUnicodeNonAsciiSpaceCharacter(ushort unicode) | ||||||
|  | { | ||||||
|  |     switch (unicode) | ||||||
|  |     { | ||||||
|  |         case 0x00A0: | ||||||
|  |         case 0x1680: | ||||||
|  |         case 0x2000: | ||||||
|  |         case 0x2001: | ||||||
|  |         case 0x2002: | ||||||
|  |         case 0x2003: | ||||||
|  |         case 0x2004: | ||||||
|  |         case 0x2005: | ||||||
|  |         case 0x2006: | ||||||
|  |         case 0x2007: | ||||||
|  |         case 0x2008: | ||||||
|  |         case 0x2009: | ||||||
|  |         case 0x200A: | ||||||
|  |         case 0x200B: | ||||||
|  |         case 0x202F: | ||||||
|  |         case 0x205F: | ||||||
|  |         case 0x3000: | ||||||
|  |             return true; | ||||||
|  |  | ||||||
|  |         default: | ||||||
|  |             return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool PDFStandardSecurityHandler::isUnicodeMappedToNothing(ushort unicode) | ||||||
|  | { | ||||||
|  |     switch (unicode) | ||||||
|  |     { | ||||||
|  |         case 0x00AD: | ||||||
|  |         case 0x034F: | ||||||
|  |         case 0x1806: | ||||||
|  |         case 0x180B: | ||||||
|  |         case 0x180C: | ||||||
|  |         case 0x180D: | ||||||
|  |         case 0x200B: | ||||||
|  |         case 0x200C: | ||||||
|  |         case 0x200D: | ||||||
|  |             return true; | ||||||
|  |  | ||||||
|  |         default: | ||||||
|  |             return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| }   // namespace pdf | }   // namespace pdf | ||||||
|   | |||||||
| @@ -176,6 +176,19 @@ private: | |||||||
|     /// Parses parts of the user/owner data (U/O values of the encryption dictionary) |     /// Parses parts of the user/owner data (U/O values of the encryption dictionary) | ||||||
|     UserOwnerData_r6 parseParts(const QByteArray& data) const; |     UserOwnerData_r6 parseParts(const QByteArray& data) const; | ||||||
|  |  | ||||||
|  |     /// Adjusts the password according to the PDF specification | ||||||
|  |     QByteArray adjustPassword(const QString& password); | ||||||
|  |  | ||||||
|  |     /// Returns true, if character with unicode code is non-ascii space character | ||||||
|  |     /// according the RFC 3454, section C.1.2 | ||||||
|  |     /// \param unicode Unicode code to be tested | ||||||
|  |     static bool isUnicodeNonAsciiSpaceCharacter(ushort unicode); | ||||||
|  |  | ||||||
|  |     /// Returns true, if character with unicode code is mapped to nothing, | ||||||
|  |     /// according the RFC 3454, section B.1 | ||||||
|  |     /// \param unicode Unicode code to be tested | ||||||
|  |     static bool isUnicodeMappedToNothing(ushort unicode); | ||||||
|  |  | ||||||
|     /// Revision number of standard security number |     /// Revision number of standard security number | ||||||
|     int m_R = 0; |     int m_R = 0; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -281,7 +281,9 @@ void PDFViewerMainWindow::openDocument(const QString& fileName) | |||||||
|     pdf::PDFDocument document = reader.readFromFile(fileName); |     pdf::PDFDocument document = reader.readFromFile(fileName); | ||||||
|     QApplication::restoreOverrideCursor(); |     QApplication::restoreOverrideCursor(); | ||||||
|  |  | ||||||
|     if (reader.isSuccessfull()) |     switch (reader.getReadingResult()) | ||||||
|  |     { | ||||||
|  |         case pdf::PDFDocumentReader::Result::OK: | ||||||
|         { |         { | ||||||
|             // Mark current directory as this |             // Mark current directory as this | ||||||
|             QFileInfo fileInfo(fileName); |             QFileInfo fileInfo(fileName); | ||||||
| @@ -292,10 +294,17 @@ void PDFViewerMainWindow::openDocument(const QString& fileName) | |||||||
|             setDocument(m_pdfDocument.data()); |             setDocument(m_pdfDocument.data()); | ||||||
|  |  | ||||||
|             statusBar()->showMessage(tr("Document '%1' was successfully loaded!").arg(fileName), 4000); |             statusBar()->showMessage(tr("Document '%1' was successfully loaded!").arg(fileName), 4000); | ||||||
|  |             break; | ||||||
|         } |         } | ||||||
|     else |  | ||||||
|  |         case pdf::PDFDocumentReader::Result::Failed: | ||||||
|         { |         { | ||||||
|             QMessageBox::critical(this, tr("PDF Viewer"), tr("Document read error: %1").arg(reader.getErrorMessage())); |             QMessageBox::critical(this, tr("PDF Viewer"), tr("Document read error: %1").arg(reader.getErrorMessage())); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         case pdf::PDFDocumentReader::Result::Cancelled: | ||||||
|  |             break; // Do nothing, user cancelled the document reading | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user