diff options
Diffstat (limited to 'cpp/poppler-document.cpp')
-rw-r--r-- | cpp/poppler-document.cpp | 842 |
1 files changed, 704 insertions, 138 deletions
diff --git a/cpp/poppler-document.cpp b/cpp/poppler-document.cpp index 1c24b476..70cae1b6 100644 --- a/cpp/poppler-document.cpp +++ b/cpp/poppler-document.cpp @@ -1,5 +1,10 @@ /* * Copyright (C) 2009-2011, Pino Toscano <pino@kde.org> + * Copyright (C) 2016 Jakub Alba <jakubalba@gmail.com> + * Copyright (C) 2017, 2022, Albert Astals Cid <aacid@kde.org> + * Copyright (C) 2018, 2020, Adam Reichold <adam.reichold@t-online.de> + * Copyright (C) 2019, Masamichi Hosoda <trueroad@trueroad.jp> + * Copyright (C) 2019, 2020, Oliver Sander <oliver.sander@tu-dresden.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,19 +21,27 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ +/** + \file poppler-document.h + */ +#include "poppler-destination.h" #include "poppler-document.h" #include "poppler-embedded-file.h" #include "poppler-page.h" #include "poppler-toc.h" +#include "poppler-destination-private.h" #include "poppler-document-private.h" #include "poppler-embedded-file-private.h" +#include "poppler-page-private.h" #include "poppler-private.h" #include "poppler-toc-private.h" #include "Catalog.h" +#include "DateInfo.h" #include "ErrorCodes.h" #include "GlobalParams.h" +#include "Link.h" #include "Outline.h" #include <algorithm> @@ -37,77 +50,28 @@ using namespace poppler; -unsigned int poppler::initer::count = 0U; - -initer::initer() -{ - if (!count) { - globalParams = new GlobalParams(); - setErrorCallback(detail::error_function, NULL); - } - count++; -} - -initer::~initer() -{ - if (count > 0) { - --count; - if (!count) { - delete globalParams; - globalParams = 0; - } - } -} - - -document_private::document_private(GooString *file_path, const std::string &owner_password, - const std::string &user_password) - : initer() - , doc(0) - , raw_doc_data(0) - , raw_doc_data_length(0) - , is_locked(false) +document_private::document_private(std::unique_ptr<GooString> &&file_path, const std::string &owner_password, const std::string &user_password) : document_private() { - GooString goo_owner_password(owner_password.c_str()); - GooString goo_user_password(user_password.c_str()); - doc = new PDFDoc(file_path, &goo_owner_password, &goo_user_password); + doc = new PDFDoc(std::move(file_path), GooString(owner_password.c_str()), GooString(user_password.c_str())); } -document_private::document_private(byte_array *file_data, - const std::string &owner_password, - const std::string &user_password) - : initer() - , doc(0) - , raw_doc_data(0) - , raw_doc_data_length(0) - , is_locked(false) +document_private::document_private(byte_array *file_data, const std::string &owner_password, const std::string &user_password) : document_private() { - Object obj; - obj.initNull(); file_data->swap(doc_data); - MemStream *memstr = new MemStream(&doc_data[0], 0, doc_data.size(), &obj); - GooString goo_owner_password(owner_password.c_str()); - GooString goo_user_password(user_password.c_str()); - doc = new PDFDoc(memstr, &goo_owner_password, &goo_user_password); + MemStream *memstr = new MemStream(&doc_data[0], 0, doc_data.size(), Object(objNull)); + doc = new PDFDoc(memstr, GooString(owner_password.c_str()), GooString(user_password.c_str())); } -document_private::document_private(const char *file_data, int file_data_length, - const std::string &owner_password, - const std::string &user_password) - : initer() - , doc(0) - , raw_doc_data(file_data) - , raw_doc_data_length(file_data_length) - , is_locked(false) +document_private::document_private(const char *file_data, int file_data_length, const std::string &owner_password, const std::string &user_password) : document_private() { - Object obj; - obj.initNull(); - MemStream *memstr = new MemStream(const_cast<char *>(raw_doc_data), 0, raw_doc_data_length, &obj); - GooString goo_owner_password(owner_password.c_str()); - GooString goo_user_password(user_password.c_str()); - doc = new PDFDoc(memstr, &goo_owner_password, &goo_user_password); + raw_doc_data = file_data; + raw_doc_data_length = file_data_length; + MemStream *memstr = new MemStream(raw_doc_data, 0, raw_doc_data_length, Object(objNull)); + doc = new PDFDoc(memstr, GooString(owner_password.c_str()), GooString(user_password.c_str())); } +document_private::document_private() : GlobalParamsIniter(detail::error_function), doc(nullptr), raw_doc_data(nullptr), raw_doc_data_length(0), is_locked(false) { } + document_private::~document_private() { delete_all(embedded_files); @@ -115,7 +79,7 @@ document_private::~document_private() delete doc; } -document* document_private::check_document(document_private *doc, byte_array *file_data) +document *document_private::check_document(document_private *doc, byte_array *file_data) { if (doc->doc->isOk() || doc->doc->getErrorCode() == errEncrypted) { if (doc->doc->getErrorCode() == errEncrypted) { @@ -129,7 +93,7 @@ document* document_private::check_document(document_private *doc, byte_array *fi } delete doc; } - return 0; + return nullptr; } /** @@ -177,11 +141,7 @@ document* document_private::check_document(document_private *doc, byte_array *fi attachments. */ - -document::document(document_private &dd) - : d(&dd) -{ -} +document::document(document_private &dd) : d(&dd) { } document::~document() { @@ -197,23 +157,20 @@ bool document::is_locked() const } /** - Unlocks the current doocument, if locked. + Unlocks the current document, if locked. \returns the new locking status of the document */ bool document::unlock(const std::string &owner_password, const std::string &user_password) { if (d->is_locked) { - document_private *newdoc = 0; + document_private *newdoc = nullptr; if (d->doc_data.size() > 0) { - newdoc = new document_private(&d->doc_data, - owner_password, user_password); + newdoc = new document_private(&d->doc_data, owner_password, user_password); } else if (d->raw_doc_data) { - newdoc = new document_private(d->raw_doc_data, d->raw_doc_data_length, - owner_password, user_password); + newdoc = new document_private(d->raw_doc_data, d->raw_doc_data_length, owner_password, user_password); } else { - newdoc = new document_private(new GooString(d->doc->getFileName()), - owner_password, user_password); + newdoc = new document_private(std::make_unique<GooString>(d->doc->getFileName()), owner_password, user_password); } if (!newdoc->doc->isOk()) { d->doc_data.swap(newdoc->doc_data); @@ -311,9 +268,8 @@ std::vector<std::string> document::info_keys() const return std::vector<std::string>(); } - Object info; - if (!d->doc->getDocInfo(&info)->isDict()) { - info.free(); + Object info = d->doc->getDocInfo(); + if (!info.isDict()) { return std::vector<std::string>(); } @@ -323,7 +279,6 @@ std::vector<std::string> document::info_keys() const keys[i] = std::string(info_dict->getKey(i)); } - info.free(); return keys; } @@ -339,25 +294,40 @@ ustring document::info_key(const std::string &key) const return ustring(); } - Object info; - if (!d->doc->getDocInfo(&info)->isDict()) { - info.free(); + std::unique_ptr<GooString> goo_value(d->doc->getDocInfoStringEntry(key.c_str())); + if (!goo_value.get()) { return ustring(); } - Dict *info_dict = info.getDict(); - Object obj; - ustring result; - if (info_dict->lookup(PSTR(key.c_str()), &obj)->isString()) { - result = detail::unicode_GooString_to_ustring(obj.getString()); + return detail::unicode_GooString_to_ustring(goo_value.get()); +} + +/** + Sets the value of the specified \p key of the %document information to \p val. + If \p val is empty, the entry specified by \p key is removed. + + \returns true on success, false on failure + */ +bool document::set_info_key(const std::string &key, const ustring &val) +{ + if (d->is_locked) { + return false; } - obj.free(); - info.free(); - return result; + + GooString *goo_val; + + if (val.empty()) { + goo_val = nullptr; + } else { + goo_val = detail::ustring_to_unicode_GooString(val); + } + + d->doc->setDocInfoStringEntry(key.c_str(), goo_val); + return true; } /** - Gets the time_t value value of the specified \p key of the document + Gets the time_type value of the specified \p key of the document information. \returns the time_t value for the \p key @@ -369,21 +339,541 @@ time_type document::info_date(const std::string &key) const return time_type(-1); } - Object info; - if (!d->doc->getDocInfo(&info)->isDict()) { - info.free(); + std::unique_ptr<GooString> goo_date(d->doc->getDocInfoStringEntry(key.c_str())); + if (!goo_date.get()) { return time_type(-1); } - Dict *info_dict = info.getDict(); - Object obj; - time_type result = time_type(-1); - if (info_dict->lookup(PSTR(key.c_str()), &obj)->isString()) { - result = detail::convert_date(obj.getString()->getCString()); + return static_cast<time_type>(dateStringToTime(goo_date.get())); +} + +/** + Gets the time_t value of the specified \p key of the document + information. + + \returns the time_t value for the \p key + \see info_keys, info_date + */ +time_t document::info_date_t(const std::string &key) const +{ + if (d->is_locked) { + return time_t(-1); } - obj.free(); - info.free(); - return result; + + std::unique_ptr<GooString> goo_date(d->doc->getDocInfoStringEntry(key.c_str())); + if (!goo_date.get()) { + return time_t(-1); + } + + return dateStringToTime(goo_date.get()); +} + +/** + Sets the time_type value of the specified \p key of the %document information + to \p val. + If \p val == time_type(-1), the entry specified by \p key is removed. + + \returns true on success, false on failure + */ +bool document::set_info_date(const std::string &key, time_type val) +{ + if (d->is_locked) { + return false; + } + + GooString *goo_date; + + if (val == time_type(-1)) { + goo_date = nullptr; + } else { + time_t t = static_cast<time_t>(val); + goo_date = timeToDateString(&t); + } + + d->doc->setDocInfoStringEntry(key.c_str(), goo_date); + return true; +} + +/** + Sets the time_t value of the specified \p key of the %document information + to \p val. + If \p val == time_t(-1), the entry specified by \p key is removed. + + \returns true on success, false on failure + */ +bool document::set_info_date_t(const std::string &key, time_t val) +{ + if (d->is_locked) { + return false; + } + + GooString *goo_date; + + if (val == time_t(-1)) { + goo_date = nullptr; + } else { + goo_date = timeToDateString(&val); + } + + d->doc->setDocInfoStringEntry(key.c_str(), goo_date); + return true; +} + +/** + Gets the %document's title. + + \returns the document's title, or an empty string if not available + \see set_title, info_key + */ +ustring document::get_title() const +{ + if (d->is_locked) { + return ustring(); + } + + std::unique_ptr<GooString> goo_title(d->doc->getDocInfoTitle()); + if (!goo_title.get()) { + return ustring(); + } + + return detail::unicode_GooString_to_ustring(goo_title.get()); +} + +/** + Sets the %document's title to \p title. + If \p title is empty, the %document's title is removed. + + \returns true on success, false on failure + */ +bool document::set_title(const ustring &title) +{ + if (d->is_locked) { + return false; + } + + GooString *goo_title; + + if (title.empty()) { + goo_title = nullptr; + } else { + goo_title = detail::ustring_to_unicode_GooString(title); + } + + d->doc->setDocInfoTitle(goo_title); + return true; +} + +/** + Gets the document's author. + + \returns the document's author, or an empty string if not available + \see set_author, info_key + */ +ustring document::get_author() const +{ + if (d->is_locked) { + return ustring(); + } + + std::unique_ptr<GooString> goo_author(d->doc->getDocInfoAuthor()); + if (!goo_author.get()) { + return ustring(); + } + + return detail::unicode_GooString_to_ustring(goo_author.get()); +} + +/** + Sets the %document's author to \p author. + If \p author is empty, the %document's author is removed. + + \returns true on success, false on failure + */ +bool document::set_author(const ustring &author) +{ + if (d->is_locked) { + return false; + } + + GooString *goo_author; + + if (author.empty()) { + goo_author = nullptr; + } else { + goo_author = detail::ustring_to_unicode_GooString(author); + } + + d->doc->setDocInfoAuthor(goo_author); + return true; +} + +/** + Gets the document's subject. + + \returns the document's subject, or an empty string if not available + \see set_subject, info_key + */ +ustring document::get_subject() const +{ + if (d->is_locked) { + return ustring(); + } + + std::unique_ptr<GooString> goo_subject(d->doc->getDocInfoSubject()); + if (!goo_subject.get()) { + return ustring(); + } + + return detail::unicode_GooString_to_ustring(goo_subject.get()); +} + +/** + Sets the %document's subject to \p subject. + If \p subject is empty, the %document's subject is removed. + + \returns true on success, false on failure + */ +bool document::set_subject(const ustring &subject) +{ + if (d->is_locked) { + return false; + } + + GooString *goo_subject; + + if (subject.empty()) { + goo_subject = nullptr; + } else { + goo_subject = detail::ustring_to_unicode_GooString(subject); + } + + d->doc->setDocInfoSubject(goo_subject); + return true; +} + +/** + Gets the document's keywords. + + \returns the document's keywords, or an empty string if not available + \see set_keywords, info_key + */ +ustring document::get_keywords() const +{ + if (d->is_locked) { + return ustring(); + } + + std::unique_ptr<GooString> goo_keywords(d->doc->getDocInfoKeywords()); + if (!goo_keywords.get()) { + return ustring(); + } + + return detail::unicode_GooString_to_ustring(goo_keywords.get()); +} + +/** + Sets the %document's keywords to \p keywords. + If \p keywords is empty, the %document's keywords are removed. + + \returns true on success, false on failure + */ +bool document::set_keywords(const ustring &keywords) +{ + if (d->is_locked) { + return false; + } + + GooString *goo_keywords; + + if (keywords.empty()) { + goo_keywords = nullptr; + } else { + goo_keywords = detail::ustring_to_unicode_GooString(keywords); + } + + d->doc->setDocInfoKeywords(goo_keywords); + return true; +} + +/** + Gets the document's creator. + + \returns the document's creator, or an empty string if not available + \see set_creator, info_key + */ +ustring document::get_creator() const +{ + if (d->is_locked) { + return ustring(); + } + + std::unique_ptr<GooString> goo_creator(d->doc->getDocInfoCreator()); + if (!goo_creator.get()) { + return ustring(); + } + + return detail::unicode_GooString_to_ustring(goo_creator.get()); +} + +/** + Sets the %document's creator to \p creator. + If \p creator is empty, the %document's creator is removed. + + \returns true on success, false on failure + */ +bool document::set_creator(const ustring &creator) +{ + if (d->is_locked) { + return false; + } + + GooString *goo_creator; + + if (creator.empty()) { + goo_creator = nullptr; + } else { + goo_creator = detail::ustring_to_unicode_GooString(creator); + } + + d->doc->setDocInfoCreator(goo_creator); + return true; +} + +/** + Gets the document's producer. + + \returns the document's producer, or an empty string if not available + \see set_producer, info_key + */ +ustring document::get_producer() const +{ + if (d->is_locked) { + return ustring(); + } + + std::unique_ptr<GooString> goo_producer(d->doc->getDocInfoProducer()); + if (!goo_producer.get()) { + return ustring(); + } + + return detail::unicode_GooString_to_ustring(goo_producer.get()); +} + +/** + Sets the %document's producer to \p producer. + If \p producer is empty, the %document's producer is removed. + + \returns true on success, false on failure + */ +bool document::set_producer(const ustring &producer) +{ + if (d->is_locked) { + return false; + } + + GooString *goo_producer; + + if (producer.empty()) { + goo_producer = nullptr; + } else { + goo_producer = detail::ustring_to_unicode_GooString(producer); + } + + d->doc->setDocInfoProducer(goo_producer); + return true; +} + +/** + Gets the document's creation date as a time_type value. + + \returns the document's creation date as a time_type value + \see set_creation_date, info_date + */ +time_type document::get_creation_date() const +{ + if (d->is_locked) { + return time_type(-1); + } + + std::unique_ptr<GooString> goo_creation_date(d->doc->getDocInfoCreatDate()); + if (!goo_creation_date.get()) { + return time_type(-1); + } + + return static_cast<time_type>(dateStringToTime(goo_creation_date.get())); +} + +/** + Gets the document's creation date as a time_t value. + + \returns the document's creation date as a time_t value + \see set_creation_date, info_date + */ +time_t document::get_creation_date_t() const +{ + if (d->is_locked) { + return time_t(-1); + } + + std::unique_ptr<GooString> goo_creation_date(d->doc->getDocInfoCreatDate()); + if (!goo_creation_date.get()) { + return time_t(-1); + } + + return dateStringToTime(goo_creation_date.get()); +} + +/** + Sets the %document's creation date to \p creation_date. + If \p creation_date == time_type(-1), the %document's creation date is removed. + + \returns true on success, false on failure + */ +bool document::set_creation_date(time_type creation_date) +{ + if (d->is_locked) { + return false; + } + + GooString *goo_creation_date; + + if (creation_date == time_type(-1)) { + goo_creation_date = nullptr; + } else { + time_t t = static_cast<time_t>(creation_date); + goo_creation_date = timeToDateString(&t); + } + + d->doc->setDocInfoCreatDate(goo_creation_date); + return true; +} + +/** + Sets the %document's creation date to \p creation_date. + If \p creation_date == time_t(-1), the %document's creation date is removed. + + \returns true on success, false on failure + */ +bool document::set_creation_date_t(time_t creation_date) +{ + if (d->is_locked) { + return false; + } + + GooString *goo_creation_date; + + if (creation_date == time_t(-1)) { + goo_creation_date = nullptr; + } else { + goo_creation_date = timeToDateString(&creation_date); + } + + d->doc->setDocInfoCreatDate(goo_creation_date); + return true; +} + +/** + Gets the document's modification date as a time_type value. + + \returns the document's modification date as a time_type value + \see set_modification_date, info_date + */ +time_type document::get_modification_date() const +{ + if (d->is_locked) { + return time_type(-1); + } + + std::unique_ptr<GooString> goo_modification_date(d->doc->getDocInfoModDate()); + if (!goo_modification_date.get()) { + return time_type(-1); + } + + return static_cast<time_type>(dateStringToTime(goo_modification_date.get())); +} + +/** + Gets the document's modification date as a time_t value. + + \returns the document's modification date as a time_t value + \see set_modification_date, info_date + */ +time_t document::get_modification_date_t() const +{ + if (d->is_locked) { + return time_t(-1); + } + + std::unique_ptr<GooString> goo_modification_date(d->doc->getDocInfoModDate()); + if (!goo_modification_date.get()) { + return time_t(-1); + } + + return dateStringToTime(goo_modification_date.get()); +} + +/** + Sets the %document's modification date to \p mod_date. + If \p mod_date == time_type(-1), the %document's modification date is removed. + + \returns true on success, false on failure + */ +bool document::set_modification_date(time_type mod_date) +{ + if (d->is_locked) { + return false; + } + + GooString *goo_mod_date; + + if (mod_date == time_type(-1)) { + goo_mod_date = nullptr; + } else { + time_t t = static_cast<time_t>(mod_date); + goo_mod_date = timeToDateString(&t); + } + + d->doc->setDocInfoModDate(goo_mod_date); + return true; +} + +/** + Sets the %document's modification date to \p mod_date. + If \p mod_date == time_t(-1), the %document's modification date is removed. + + \returns true on success, false on failure + */ +bool document::set_modification_date_t(time_t mod_date) +{ + if (d->is_locked) { + return false; + } + + GooString *goo_mod_date; + + if (mod_date == time_t(-1)) { + goo_mod_date = nullptr; + } else { + goo_mod_date = timeToDateString(&mod_date); + } + + d->doc->setDocInfoModDate(goo_mod_date); + return true; +} + +/** + Removes the %document's Info dictionary. + + \returns true on success, false on failure + */ +bool document::remove_info() +{ + if (d->is_locked) { + return false; + } + + d->doc->removeDocInfo(); + return true; } /** @@ -437,7 +927,7 @@ bool document::has_permission(permission_enum which) const */ ustring document::metadata() const { - std::auto_ptr<GooString> md(d->doc->getCatalog()->readMetadata()); + std::unique_ptr<GooString> md(d->doc->getCatalog()->readMetadata()); if (md.get()) { return detail::unicode_GooString_to_ustring(md.get()); } @@ -459,15 +949,15 @@ bool document::get_pdf_id(std::string *permanent_id, std::string *update_id) con GooString goo_permanent_id; GooString goo_update_id; - if (!d->doc->getID(permanent_id ? &goo_permanent_id : 0, update_id ? &goo_update_id : 0)) { + if (!d->doc->getID(permanent_id ? &goo_permanent_id : nullptr, update_id ? &goo_update_id : nullptr)) { return false; } if (permanent_id) { - *permanent_id = goo_permanent_id.getCString(); + *permanent_id = goo_permanent_id.c_str(); } if (update_id) { - *update_id = goo_update_id.getCString(); + *update_id = goo_update_id.c_str(); } return true; @@ -491,13 +981,13 @@ int document::pages() const \returns a new page object or NULL */ -page* document::create_page(const ustring &label) const +page *document::create_page(const ustring &label) const { - std::auto_ptr<GooString> goolabel(detail::ustring_to_unicode_GooString(label)); + std::unique_ptr<GooString> goolabel(detail::ustring_to_unicode_GooString(label)); int index = 0; if (!d->doc->getCatalog()->labelToIndex(goolabel.get(), &index)) { - return 0; + return nullptr; } return create_page(index); } @@ -510,9 +1000,19 @@ page* document::create_page(const ustring &label) const \returns a new page object or NULL */ -page* document::create_page(int index) const +page *document::create_page(int index) const { - return index >= 0 && index < d->doc->getNumPages() ? new page(d, index) : 0; + if (index >= 0 && index < d->doc->getNumPages()) { + page *p = new page(d, index); + if (p->d->page) { + return p; + } else { + delete p; + return nullptr; + } + } else { + return nullptr; + } } /** @@ -542,7 +1042,7 @@ std::vector<font_info> document::fonts() const \returns a new font iterator */ -font_iterator* document::create_font_iterator(int start_page) const +font_iterator *document::create_font_iterator(int start_page) const { return new font_iterator(start_page, d); } @@ -552,7 +1052,7 @@ font_iterator* document::create_font_iterator(int start_page) const \returns a new toc object if a TOC is available, NULL otherwise */ -toc* document::create_toc() const +toc *document::create_toc() const { return toc_private::load_from_outline(d->doc->getOutline()); } @@ -587,28 +1087,102 @@ std::vector<embedded_file *> document::embedded_files() const const int num = d->doc->getCatalog()->numEmbeddedFiles(); d->embedded_files.resize(num); for (int i = 0; i < num; ++i) { - FileSpec *fs = d->doc->getCatalog()->embeddedFile(i); - d->embedded_files[i] = embedded_file_private::create(fs); + std::unique_ptr<FileSpec> fs = d->doc->getCatalog()->embeddedFile(i); + d->embedded_files[i] = embedded_file_private::create(std::move(fs)); } } return d->embedded_files; } /** + Creates a map of all the named destinations in the %document. + + \note The destination names may contain \\0 and other binary values + so they are not printable and cannot convert to null-terminated C strings. + + \returns the map of the each name and destination + + \since 0.74 + */ +std::map<std::string, destination> document::create_destination_map() const +{ + std::map<std::string, destination> m; + + Catalog *catalog = d->doc->getCatalog(); + if (!catalog) { + return m; + } + + // Iterate from name-dict + const int nDests = catalog->numDests(); + for (int i = 0; i < nDests; ++i) { + std::string key(catalog->getDestsName(i)); + std::unique_ptr<LinkDest> link_dest = catalog->getDestsDest(i); + + if (link_dest) { + destination dest(new destination_private(link_dest.get(), d->doc)); + + m.emplace(std::move(key), std::move(dest)); + } + } + + // Iterate from name-tree + const int nDestsNameTree = catalog->numDestNameTree(); + for (int i = 0; i < nDestsNameTree; ++i) { + std::string key(catalog->getDestNameTreeName(i)->c_str(), catalog->getDestNameTreeName(i)->getLength()); + std::unique_ptr<LinkDest> link_dest = catalog->getDestNameTreeDest(i); + + if (link_dest) { + destination dest(new destination_private(link_dest.get(), d->doc)); + + m.emplace(std::move(key), std::move(dest)); + } + } + + return m; +} + +/** + Saves the %document to file \p file_name. + + \returns true on success, false on failure + */ +bool document::save(const std::string &file_name) const +{ + if (d->is_locked) { + return false; + } + + GooString fname(file_name.c_str()); + return d->doc->saveAs(fname) == errNone; +} + +/** + Saves the original version of the %document to file \p file_name. + + \returns true on success, false on failure + */ +bool document::save_a_copy(const std::string &file_name) const +{ + if (d->is_locked) { + return false; + } + + GooString fname(file_name.c_str()); + return d->doc->saveWithoutChangesAs(fname) == errNone; +} + +/** Tries to load a PDF %document from the specified file. \param file_name the file to open \returns a new document if the load succeeded (even if the document is locked), NULL otherwise */ -document* document::load_from_file(const std::string &file_name, - const std::string &owner_password, - const std::string &user_password) +document *document::load_from_file(const std::string &file_name, const std::string &owner_password, const std::string &user_password) { - document_private *doc = new document_private( - new GooString(file_name.c_str()), - owner_password, user_password); - return document_private::check_document(doc, 0); + document_private *doc = new document_private(std::make_unique<GooString>(file_name.c_str()), owner_password, user_password); + return document_private::check_document(doc, nullptr); } /** @@ -621,16 +1195,13 @@ document* document::load_from_file(const std::string &file_name, \returns a new document if the load succeeded (even if the document is locked), NULL otherwise */ -document* document::load_from_data(byte_array *file_data, - const std::string &owner_password, - const std::string &user_password) +document *document::load_from_data(byte_array *file_data, const std::string &owner_password, const std::string &user_password) { if (!file_data || file_data->size() < 10) { - return 0; + return nullptr; } - document_private *doc = new document_private( - file_data, owner_password, user_password); + document_private *doc = new document_private(file_data, owner_password, user_password); return document_private::check_document(doc, file_data); } @@ -648,17 +1219,12 @@ document* document::load_from_data(byte_array *file_data, \since 0.16 */ -document* document::load_from_raw_data(const char *file_data, - int file_data_length, - const std::string &owner_password, - const std::string &user_password) +document *document::load_from_raw_data(const char *file_data, int file_data_length, const std::string &owner_password, const std::string &user_password) { if (!file_data || file_data_length < 10) { - return 0; + return nullptr; } - document_private *doc = new document_private( - file_data, file_data_length, - owner_password, user_password); - return document_private::check_document(doc, 0); + document_private *doc = new document_private(file_data, file_data_length, owner_password, user_password); + return document_private::check_document(doc, nullptr); } |