From 55e8b2d33431d1d59c6359274f1e33417a042195 Mon Sep 17 00:00:00 2001 From: Jakub Kucharski Date: Mon, 15 Feb 2016 12:07:36 +0100 Subject: [PATCH 1/2] cpp: Added functions to save a document --- cpp/poppler-document.cpp | 31 +++++++++++++++++++++++++++++++ cpp/poppler-document.h | 4 ++++ 2 files changed, 35 insertions(+) diff --git a/cpp/poppler-document.cpp b/cpp/poppler-document.cpp index 1c24b47..830cb6d 100644 --- a/cpp/poppler-document.cpp +++ b/cpp/poppler-document.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2009-2011, Pino Toscano + * Copyright (C) 2016 Jakub Kucharski * * 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 @@ -595,6 +596,36 @@ std::vector document::embedded_files() const } /** + 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 diff --git a/cpp/poppler-document.h b/cpp/poppler-document.h index dfae398..cd0d3bd 100644 --- a/cpp/poppler-document.h +++ b/cpp/poppler-document.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2009-2010, Pino Toscano + * Copyright (C) 2016 Jakub Kucharski * * 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 @@ -81,6 +82,9 @@ public: bool has_embedded_files() const; std::vector embedded_files() const; + bool save(const std::string &filename) const; + bool save_a_copy(const std::string &filename) const; + static document* load_from_file(const std::string &file_name, const std::string &owner_password = std::string(), const std::string &user_password = std::string()); -- 2.7.1 From 342564d6b1ff992d673cf0287c2720bb1c0e96e7 Mon Sep 17 00:00:00 2001 From: Jakub Kucharski Date: Mon, 15 Feb 2016 15:45:08 +0100 Subject: [PATCH 2/2] cpp: Added document property setters & getters --- cpp/poppler-document.cpp | 448 ++++++++++++++++++++++++++++++++++++++++++++--- cpp/poppler-document.h | 26 +++ cpp/poppler-private.cpp | 27 ++- cpp/poppler-private.h | 3 + 4 files changed, 478 insertions(+), 26 deletions(-) diff --git a/cpp/poppler-document.cpp b/cpp/poppler-document.cpp index 830cb6d..0935322 100644 --- a/cpp/poppler-document.cpp +++ b/cpp/poppler-document.cpp @@ -329,7 +329,7 @@ std::vector document::info_keys() const } /** - Gets the value of the specified \p key of the document information. + Gets the value of the specified \p key of the %document information. \returns the value for the \p key, or an empty string if not available \see info_keys, info_date @@ -340,28 +340,43 @@ ustring document::info_key(const std::string &key) const return ustring(); } - Object info; - if (!d->doc->getDocInfo(&info)->isDict()) { - info.free(); + std::auto_ptr 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 = NULL; + } 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 value of the specified \p key of the %document information. - \returns the time_t value for the \p key + \returns the time_type value for the \p key \see info_keys, info_date */ time_type document::info_date(const std::string &key) const @@ -370,21 +385,404 @@ 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::auto_ptr 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 detail::convert_date(goo_date->getCString()); +} + +/** + 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; } - obj.free(); - info.free(); - return result; + + GooString *goo_date; + + if (val == time_type(-1)) { + goo_date = NULL; + } else { + goo_date = detail::date_to_GooString(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::auto_ptr 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 = NULL; + } 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::auto_ptr 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 = NULL; + } 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::auto_ptr 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 = NULL; + } 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::auto_ptr 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 = NULL; + } 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::auto_ptr 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 = NULL; + } 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::auto_ptr 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 = NULL; + } 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::auto_ptr goo_creation_date(d->doc->getDocInfoCreatDate()); + if (!goo_creation_date.get()) { + return time_type(-1); + } + + return detail::GooString_to_date(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 = NULL; + } else { + goo_creation_date = detail::date_to_GooString(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::auto_ptr goo_modification_date(d->doc->getDocInfoModDate()); + if (!goo_modification_date.get()) { + return time_type(-1); + } + + return detail::GooString_to_date(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 = NULL; + } else { + goo_mod_date = detail::date_to_GooString(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; } /** diff --git a/cpp/poppler-document.h b/cpp/poppler-document.h index cd0d3bd..147c5c5 100644 --- a/cpp/poppler-document.h +++ b/cpp/poppler-document.h @@ -23,6 +23,8 @@ #include "poppler-global.h" #include "poppler-font.h" +class GooString; + namespace poppler { @@ -62,8 +64,32 @@ public: page_layout_enum page_layout() const; void get_pdf_version(int *major, int *minor) const; std::vector info_keys() const; + ustring info_key(const std::string &key) const; + bool set_info_key(const std::string &key, const ustring &val); + time_type info_date(const std::string &key) const; + bool set_info_date(const std::string &key, time_type val); + + ustring get_title() const; + bool set_title(const ustring &title); + ustring get_author() const; + bool set_author(const ustring &author); + ustring get_subject() const; + bool set_subject(const ustring &subject); + ustring get_keywords() const; + bool set_keywords(const ustring &keywords); + ustring get_creator() const; + bool set_creator(const ustring &creator); + ustring get_producer() const; + bool set_producer(const ustring &producer); + time_type get_creation_date() const; + bool set_creation_date(time_type creation_date); + time_type get_modification_date() const; + bool set_modification_date(time_type mod_date); + + bool remove_info(); + bool is_encrypted() const; bool is_linearized() const; bool has_permission(permission_enum which) const; diff --git a/cpp/poppler-private.cpp b/cpp/poppler-private.cpp index 3c3fe95..ade9de8 100644 --- a/cpp/poppler-private.cpp +++ b/cpp/poppler-private.cpp @@ -2,6 +2,7 @@ * Copyright (C) 2009-2010, Pino Toscano * Copyright (C) 2013 Adrian Johnson * Copyright (C) 2014, Hans-Peter Deifel + * Copyright (C) 2016 Jakub Kucharski * * 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 @@ -112,7 +113,7 @@ GooString* detail::ustring_to_unicode_GooString(const ustring &str) ba[i * 2 + 2] = ((*me >> 8) & 0xff); ba[i * 2 + 3] = (*me & 0xff); } - GooString *goo = new GooString(&ba[0]); + GooString *goo = new GooString(&ba[0], 2*str.size() + 2); return goo; } @@ -138,3 +139,27 @@ time_type detail::convert_date(const char *date) time.tm_isdst = -1; return mktime(&time); } + +time_type detail::GooString_to_date(GooString *str) +{ + ustring s = unicode_GooString_to_ustring(str); + return convert_date(s.to_latin1().c_str()); +} + +GooString *detail::date_to_GooString(time_type t) +{ + time_t date = t; + + if (date == -1) { + return NULL; + } + + struct tm tm; + gmtime_r(&date, &tm); + + char str[24]; + sprintf(str, "D:%04d%02d%02d%02d%02d%02d+00'00'", tm.tm_year + 1900, + tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); + + return detail::ustring_to_unicode_GooString(ustring::from_latin1(str)); +} diff --git a/cpp/poppler-private.h b/cpp/poppler-private.h index 8d315c8..3e2391a 100644 --- a/cpp/poppler-private.h +++ b/cpp/poppler-private.h @@ -2,6 +2,7 @@ * Copyright (C) 2009, Pino Toscano * Copyright (C) 2013 Adrian Johnson * Copyright (C) 2014, Hans-Peter Deifel + * Copyright (C) 2016 Jakub Kucharski * * 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 @@ -51,6 +52,8 @@ ustring unicode_to_ustring(const Unicode *u, int length); GooString* ustring_to_unicode_GooString(const ustring &str); time_type convert_date(const char *date); +time_type GooString_to_date(GooString *str); +GooString* date_to_GooString(time_type date); } -- 2.7.1