[poppler] 3 commits - glib/demo glib/poppler-attachment.cc glib/poppler-attachment.h glib/poppler-document.cc glib/poppler-document.h glib/poppler-private.h glib/reference

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Aug 21 10:26:07 UTC 2020


 glib/demo/annots.c                  |    2 
 glib/demo/attachments.c             |   36 ++++--
 glib/demo/info.cc                   |   12 +-
 glib/poppler-attachment.cc          |  104 +++++++++++++++++--
 glib/poppler-attachment.h           |   28 +++++
 glib/poppler-document.cc            |  197 +++++++++++++++++++++++++++++++++++-
 glib/poppler-document.h             |    8 +
 glib/poppler-private.h              |    2 
 glib/reference/poppler-sections.txt |   10 +
 9 files changed, 371 insertions(+), 28 deletions(-)

New commits:
commit 92b3edf32a9f7a3617681135290e9d2ba0205ffb
Author: Jason Crain <jason at inspiresomeone.us>
Date:   Wed Feb 12 19:16:20 2020 -0700

    glib: Add accessor functions for PopplerAttachment
    
    Issue #715

diff --git a/glib/demo/annots.c b/glib/demo/annots.c
index 96640c5c..16a0db48 100644
--- a/glib/demo/annots.c
+++ b/glib/demo/annots.c
@@ -486,7 +486,7 @@ static void pgd_annot_save_file_attachment_button_clicked(GtkButton *button, Pop
         return;
 
     file_chooser = gtk_file_chooser_dialog_new("Save attachment", GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(button))), GTK_FILE_CHOOSER_ACTION_SAVE, "_Cancel", GTK_RESPONSE_CANCEL, "_Save", GTK_RESPONSE_ACCEPT, NULL);
-    gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(file_chooser), attachment->name);
+    gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(file_chooser), poppler_attachment_get_name(attachment));
     g_signal_connect(G_OBJECT(file_chooser), "response", G_CALLBACK(pgd_annots_file_attachment_save_dialog_response), (gpointer)attachment);
     gtk_widget_show(file_chooser);
 }
diff --git a/glib/demo/attachments.c b/glib/demo/attachments.c
index 3106af19..5f834a2e 100644
--- a/glib/demo/attachments.c
+++ b/glib/demo/attachments.c
@@ -44,16 +44,20 @@ static void pgd_attachments_fill_model(GtkListStore *model, PopplerDocument *doc
         gchar *size;
         GDateTime *ctime, *mtime;
         gchar *ctime_str, *mtime_str;
+        const gchar *name;
+        const gchar *description;
 
-        size = g_strdup_printf("%" G_GSIZE_FORMAT, attachment->size);
+        name = poppler_attachment_get_name(attachment);
+        description = poppler_attachment_get_description(attachment);
+        size = g_strdup_printf("%" G_GSIZE_FORMAT, poppler_attachment_get_size(attachment));
         ctime = poppler_attachment_get_ctime(attachment);
         ctime_str = ctime ? g_date_time_format(ctime, "%c") : NULL;
         mtime = poppler_attachment_get_mtime(attachment);
         mtime_str = mtime ? g_date_time_format(mtime, "%c") : NULL;
 
         gtk_list_store_append(model, &iter);
-        gtk_list_store_set(model, &iter, ATTACHMENTS_NAME_COLUMN, attachment->name ? attachment->name : "Unknown", ATTACHMENTS_DESCRIPTION_COLUMN, attachment->description ? attachment->description : "Unknown", ATTACHMENTS_SIZE_COLUMN,
-                           size ? size : "Unknown", ATTACHMENTS_CTIME_COLUMN, ctime_str ? ctime_str : "Unknown", ATTACHMENTS_MTIME_COLUMN, mtime_str ? mtime_str : "Unknown", ATTACHMENTS_ATTACHMENT_COLUMN, attachment, -1);
+        gtk_list_store_set(model, &iter, ATTACHMENTS_NAME_COLUMN, name ? name : "Unknown", ATTACHMENTS_DESCRIPTION_COLUMN, description ? description : "Unknown", ATTACHMENTS_SIZE_COLUMN, size ? size : "Unknown", ATTACHMENTS_CTIME_COLUMN,
+                           ctime_str ? ctime_str : "Unknown", ATTACHMENTS_MTIME_COLUMN, mtime_str ? mtime_str : "Unknown", ATTACHMENTS_ATTACHMENT_COLUMN, attachment, -1);
 
         g_free(size);
         g_free(ctime_str);
@@ -127,7 +131,7 @@ static void pgd_attachments_save_button_clicked(GtkButton *button, GtkTreeView *
         return;
 
     file_chooser = gtk_file_chooser_dialog_new("Save attachment", GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(treeview))), GTK_FILE_CHOOSER_ACTION_SAVE, "_Cancel", GTK_RESPONSE_CANCEL, "_Save", GTK_RESPONSE_ACCEPT, NULL);
-    gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(file_chooser), attachment->name);
+    gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(file_chooser), poppler_attachment_get_name(attachment));
     g_signal_connect(G_OBJECT(file_chooser), "response", G_CALLBACK(pgd_attachments_save_dialog_response), (gpointer)attachment);
     gtk_widget_show(file_chooser);
 }
@@ -155,6 +159,7 @@ static void pgd_attachments_validate_button_clicked(GtkButton *button, GtkTreeVi
     GtkTreeSelection *selection;
     GtkTreeModel *model;
     GtkTreeIter iter;
+    const GString *checksum;
     GChecksum *cs;
     guint8 *digest;
     gsize digest_len;
@@ -170,7 +175,9 @@ static void pgd_attachments_validate_button_clicked(GtkButton *button, GtkTreeVi
     if (!attachment)
         return;
 
-    if (attachment->checksum->len == 0) {
+    checksum = poppler_attachment_get_checksum(attachment);
+
+    if (checksum->len == 0) {
         message_dialog_run(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(treeview))), "Impossible to validate attachment: checksum is not available");
         g_object_unref(attachment);
 
@@ -184,11 +191,11 @@ static void pgd_attachments_validate_button_clicked(GtkButton *button, GtkTreeVi
     g_checksum_get_digest(cs, digest, &digest_len);
     g_checksum_free(cs);
 
-    if (attachment->checksum->len == digest_len) {
+    if (checksum->len == digest_len) {
         gint i;
 
         for (i = 0; i < digest_len; i++) {
-            if ((guint8)attachment->checksum->str[i] != digest[i]) {
+            if ((guint8)checksum->str[i] != digest[i]) {
                 valid = FALSE;
                 break;
             }
diff --git a/glib/poppler-attachment.cc b/glib/poppler-attachment.cc
index 9aade86f..3195483b 100644
--- a/glib/poppler-attachment.cc
+++ b/glib/poppler-attachment.cc
@@ -139,6 +139,19 @@ PopplerAttachment *_poppler_attachment_new(FileSpec *emb_file)
     return attachment;
 }
 
+/**
+ * poppler_attachment_get_checksum:
+ * @attachment: a #PopplerAttachment
+ *
+ * Returns: The attachment's checksum.
+ *
+ * Since: 20.09.0
+ */
+const GString *poppler_attachment_get_checksum(PopplerAttachment *attachment)
+{
+    return attachment->checksum;
+}
+
 /**
  * poppler_attachment_get_ctime:
  * @attachment: a #PopplerAttachment
@@ -153,6 +166,19 @@ GDateTime *poppler_attachment_get_ctime(PopplerAttachment *attachment)
     return GET_PRIVATE(attachment)->ctime;
 }
 
+/**
+ * poppler_attachment_get_description:
+ * @attachment: a #PopplerAttachment
+ *
+ * Returns: The attachment's descriptive text.
+ *
+ * Since: 20.09.0
+ */
+const gchar *poppler_attachment_get_description(PopplerAttachment *attachment)
+{
+    return attachment->description;
+}
+
 /**
  * poppler_attachment_get_mtime:
  * @attachment: a #PopplerAttachment
@@ -168,6 +194,32 @@ GDateTime *poppler_attachment_get_mtime(PopplerAttachment *attachment)
     return GET_PRIVATE(attachment)->mtime;
 }
 
+/**
+ * poppler_attachment_get_name:
+ * @attachment: a #PopplerAttachment
+ *
+ * Returns: The attachment's name.
+ *
+ * Since: 20.09.0
+ */
+const gchar *poppler_attachment_get_name(PopplerAttachment *attachment)
+{
+    return attachment->name;
+}
+
+/**
+ * poppler_attachment_get_size:
+ * @attachment: a #PopplerAttachment
+ *
+ * Returns: The attachment's size.
+ *
+ * Since: 20.09.0
+ */
+gsize poppler_attachment_get_size(PopplerAttachment *attachment)
+{
+    return attachment->size;
+}
+
 static gboolean save_helper(const gchar *buf, gsize count, gpointer data, GError **error)
 {
     FILE *f = (FILE *)data;
diff --git a/glib/poppler-attachment.h b/glib/poppler-attachment.h
index 2b6019a4..3837a750 100644
--- a/glib/poppler-attachment.h
+++ b/glib/poppler-attachment.h
@@ -52,14 +52,18 @@ typedef gboolean (*PopplerAttachmentSaveFunc)(const gchar *buf, gsize count, gpo
 /* GTime is deprecated, but is part of our ABI here (see #715, #765). */
 /**
  * PopplerAttachment:
- * @name: The filename
- * @description: Descriptive text
- * @size: The size of the file
+ * @name: The filename. Deprecated in poppler 20.09.0. Use
+ *   poppler_attachment_get_name() instead.
+ * @description: Descriptive text. Deprecated in poppler 20.09.0. Use
+ *   poppler_attachment_get_description() instead.
+ * @size: The size of the file. Deprecated in poppler 20.09.0. Use
+ *   poppler_attachment_get_size() instead.
  * @mtime: The date and time when the file was last modified. Deprecated in
  *   poppler 20.09.0. Use poppler_attachment_get_mtime() instead.
  * @ctime: The date and time when the file was created. Deprecated in poppler
  *   20.09.0. Use poppler_attachment_get_ctime() instead.
- * @checksum: A 16-byte checksum of the file.
+ * @checksum: A 16-byte checksum of the file. Deprecated in poppler 20.09.0. Use
+ *   poppler_attachment_get_checksum() instead.
  */
 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
 struct _PopplerAttachment
@@ -84,10 +88,18 @@ typedef struct _PopplerAttachmentClass
 POPPLER_PUBLIC
 GType poppler_attachment_get_type(void) G_GNUC_CONST;
 POPPLER_PUBLIC
+const GString *poppler_attachment_get_checksum(PopplerAttachment *attachment);
+POPPLER_PUBLIC
 GDateTime *poppler_attachment_get_ctime(PopplerAttachment *attachment);
 POPPLER_PUBLIC
+const gchar *poppler_attachment_get_description(PopplerAttachment *attachment);
+POPPLER_PUBLIC
 GDateTime *poppler_attachment_get_mtime(PopplerAttachment *attachment);
 POPPLER_PUBLIC
+const gchar *poppler_attachment_get_name(PopplerAttachment *attachment);
+POPPLER_PUBLIC
+gsize poppler_attachment_get_size(PopplerAttachment *attachment);
+POPPLER_PUBLIC
 gboolean poppler_attachment_save(PopplerAttachment *attachment, const char *filename, GError **error);
 POPPLER_PUBLIC
 gboolean poppler_attachment_save_to_callback(PopplerAttachment *attachment, PopplerAttachmentSaveFunc save_func, gpointer user_data, GError **error);
diff --git a/glib/reference/poppler-sections.txt b/glib/reference/poppler-sections.txt
index 900b1f9f..828a8bf1 100644
--- a/glib/reference/poppler-sections.txt
+++ b/glib/reference/poppler-sections.txt
@@ -334,8 +334,12 @@ poppler_action_movie_operation_get_type
 <TITLE>PopplerAttachment</TITLE>
 PopplerAttachment
 PopplerAttachmentSaveFunc
+poppler_attachment_get_checksum
 poppler_attachment_get_ctime
+poppler_attachment_get_description
 poppler_attachment_get_mtime
+poppler_attachment_get_name
+poppler_attachment_get_size
 poppler_attachment_save
 poppler_attachment_save_to_callback
 
commit b13cd962b59e65846e3a9b18eee8a8b999b0291a
Author: Jason Crain <jason at inspiresomeone.us>
Date:   Fri Jan 3 19:05:57 2020 -0700

    glib: Deprecate PopplerDocument date properties
    
    PopplerDocument's creation-date and mod-date properties are 32-bit unix
    times, a.k.a. GTime, and will overflow in 2038. Deprecate these
    properties and replace with creation-datetime and mod-datetime, which
    are GDateTime instead, and add accessor functions.
    
    Fixes #765

diff --git a/glib/demo/info.cc b/glib/demo/info.cc
index f29bf98e..c3d0d767 100644
--- a/glib/demo/info.cc
+++ b/glib/demo/info.cc
@@ -134,7 +134,7 @@ GtkWidget *pgd_info_create_widget(PopplerDocument *document)
     gchar *perm_id;
     gchar *up_id;
     gboolean linearized;
-    GTime creation_date, mod_date;
+    GDateTime *creation_date, *mod_date;
     GEnumValue *enum_value;
     PopplerBackend backend;
     PopplerPageLayout layout;
@@ -143,8 +143,8 @@ GtkWidget *pgd_info_create_widget(PopplerDocument *document)
     PopplerViewerPreferences view_prefs;
     gint row = 0;
 
-    g_object_get(document, "title", &title, "format", &format, "author", &author, "subject", &subject, "keywords", &keywords, "creation-date", &creation_date, "mod-date", &mod_date, "creator", &creator, "producer", &producer, "linearized",
-                 &linearized, "page-mode", &mode, "page-layout", &layout, "permissions", &permissions, "viewer-preferences", &view_prefs, "metadata", &metadata, NULL);
+    g_object_get(document, "title", &title, "format", &format, "author", &author, "subject", &subject, "keywords", &keywords, "creation-datetime", &creation_date, "mod-datetime", &mod_date, "creator", &creator, "producer", &producer,
+                 "linearized", &linearized, "page-mode", &mode, "page-layout", &layout, "permissions", &permissions, "viewer-preferences", &view_prefs, "metadata", &metadata, NULL);
 
     vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 12);
 
@@ -200,12 +200,14 @@ GtkWidget *pgd_info_create_widget(PopplerDocument *document)
 
     pgd_table_add_property(GTK_GRID(table), "<b>Linearized:</b>", linearized ? "Yes" : "No", &row);
 
-    str = pgd_format_date(creation_date);
+    str = g_date_time_format(creation_date, "%c");
     pgd_table_add_property(GTK_GRID(table), "<b>Creation Date:</b>", str, &row);
+    g_clear_pointer(&creation_date, g_date_time_unref);
     g_free(str);
 
-    str = pgd_format_date(mod_date);
+    str = g_date_time_format(mod_date, "%c");
     pgd_table_add_property(GTK_GRID(table), "<b>Modification Date:</b>", str, &row);
+    g_clear_pointer(&mod_date, g_date_time_unref);
     g_free(str);
 
     enum_value = g_enum_get_value((GEnumClass *)g_type_class_peek(POPPLER_TYPE_PAGE_MODE), mode);
diff --git a/glib/poppler-document.cc b/glib/poppler-document.cc
index 85326240..e91fe342 100644
--- a/glib/poppler-document.cc
+++ b/glib/poppler-document.cc
@@ -87,7 +87,9 @@ enum
     PROP_METADATA,
     PROP_PRINT_SCALING,
     PROP_PRINT_DUPLEX,
-    PROP_PRINT_N_COPIES
+    PROP_PRINT_N_COPIES,
+    PROP_CREATION_DATETIME,
+    PROP_MOD_DATETIME
 };
 
 static void poppler_document_layers_free(PopplerDocument *document);
@@ -1429,6 +1431,50 @@ void poppler_document_set_creation_date(PopplerDocument *document, time_t creati
     document->doc->setDocInfoCreatDate(str);
 }
 
+/**
+ * poppler_document_get_creation_date_time:
+ * @document: A #PopplerDocument
+ *
+ * Returns the date the document was created as a #GDateTime
+ *
+ * Returns: (nullable): the date the document was created, or %NULL
+ *
+ * Since: 20.09.0
+ **/
+GDateTime *poppler_document_get_creation_date_time(PopplerDocument *document)
+{
+    g_return_val_if_fail(POPPLER_IS_DOCUMENT(document), nullptr);
+
+    GooString *str = document->doc->getDocInfoCreatDate();
+
+    if (!str)
+        return nullptr;
+
+    return _poppler_convert_pdf_date_to_date_time(str);
+}
+
+/**
+ * poppler_document_set_creation_date_time:
+ * @document: A #PopplerDocument
+ * @creation_datetime: (nullable): A new creation #GDateTime
+ *
+ * Sets the document's creation date. If @creation_datetime is %NULL,
+ * CreationDate entry is removed from the document's Info dictionary.
+ *
+ * Since: 20.09.0
+ **/
+void poppler_document_set_creation_date_time(PopplerDocument *document, GDateTime *creation_datetime)
+{
+    g_return_if_fail(POPPLER_IS_DOCUMENT(document));
+
+    GooString *str = nullptr;
+
+    if (creation_datetime)
+        str = _poppler_convert_date_time_to_pdf_date(creation_datetime);
+
+    document->doc->setDocInfoCreatDate(str);
+}
+
 /**
  * poppler_document_get_modification_date:
  * @document: A #PopplerDocument
@@ -1473,6 +1519,50 @@ void poppler_document_set_modification_date(PopplerDocument *document, time_t mo
     document->doc->setDocInfoModDate(str);
 }
 
+/**
+ * poppler_document_get_modification_date_time:
+ * @document: A #PopplerDocument
+ *
+ * Returns the date the document was most recently modified as a #GDateTime
+ *
+ * Returns: (nullable): the date the document was modified, or %NULL
+ *
+ * Since: 20.09.0
+ **/
+GDateTime *poppler_document_get_modification_date_time(PopplerDocument *document)
+{
+    g_return_val_if_fail(POPPLER_IS_DOCUMENT(document), nullptr);
+
+    GooString *str = document->doc->getDocInfoModDate();
+
+    if (!str)
+        return nullptr;
+
+    return _poppler_convert_pdf_date_to_date_time(str);
+}
+
+/**
+ * poppler_document_set_modification_date_time:
+ * @document: A #PopplerDocument
+ * @modification_datetime: (nullable): A new modification #GDateTime
+ *
+ * Sets the document's modification date. If @modification_datetime is %NULL,
+ * ModDate entry is removed from the document's Info dictionary.
+ *
+ * Since: 20.09.0
+ **/
+void poppler_document_set_modification_date_time(PopplerDocument *document, GDateTime *modification_datetime)
+{
+    g_return_if_fail(POPPLER_IS_DOCUMENT(document));
+
+    GooString *str = nullptr;
+
+    if (modification_datetime)
+        str = _poppler_convert_date_time_to_pdf_date(modification_datetime);
+
+    document->doc->setDocInfoModDate(str);
+}
+
 /**
  * poppler_document_is_linearized:
  * @document: A #PopplerDocument
@@ -1949,9 +2039,15 @@ static void poppler_document_get_property(GObject *object, guint prop_id, GValue
     case PROP_CREATION_DATE:
         g_value_set_int(value, poppler_document_get_creation_date(document));
         break;
+    case PROP_CREATION_DATETIME:
+        g_value_take_boxed(value, poppler_document_get_creation_date_time(document));
+        break;
     case PROP_MOD_DATE:
         g_value_set_int(value, poppler_document_get_modification_date(document));
         break;
+    case PROP_MOD_DATETIME:
+        g_value_take_boxed(value, poppler_document_get_modification_date_time(document));
+        break;
     case PROP_LINEARIZED:
         g_value_set_boolean(value, poppler_document_is_linearized(document));
         break;
@@ -2023,9 +2119,15 @@ static void poppler_document_set_property(GObject *object, guint prop_id, const
     case PROP_CREATION_DATE:
         poppler_document_set_creation_date(document, g_value_get_int(value));
         break;
+    case PROP_CREATION_DATETIME:
+        poppler_document_set_creation_date_time(document, (GDateTime *)g_value_get_boxed(value));
+        break;
     case PROP_MOD_DATE:
         poppler_document_set_modification_date(document, g_value_get_int(value));
         break;
+    case PROP_MOD_DATETIME:
+        poppler_document_set_modification_date_time(document, (GDateTime *)g_value_get_boxed(value));
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
     }
@@ -2106,15 +2208,39 @@ static void poppler_document_class_init(PopplerDocumentClass *klass)
      * PopplerDocument:creation-date:
      *
      * The date the document was created as seconds since the Epoch, or -1
+     *
+     * Deprecated: 20.09.0: This will overflow in 2038. Use creation-datetime
+     * instead.
+     */
+    g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_CREATION_DATE,
+                                    g_param_spec_int("creation-date", "Creation Date", "The date and time the document was created", -1, G_MAXINT, -1, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_DEPRECATED)));
+
+    /**
+     * PopplerDocument:creation-datetime:
+     * The #GDateTime the document was created.
+     *
+     * Since: 20.09.0
      */
-    g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_CREATION_DATE, g_param_spec_int("creation-date", "Creation Date", "The date and time the document was created", -1, G_MAXINT, -1, G_PARAM_READWRITE));
+    g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_CREATION_DATETIME, g_param_spec_boxed("creation-datetime", "Creation DateTime", "The date and time the document was created", G_TYPE_DATE_TIME, G_PARAM_READWRITE));
 
     /**
      * PopplerDocument:mod-date:
      *
      * The date the document was most recently modified as seconds since the Epoch, or -1
+     *
+     * Deprecated: 20.09.0: This will overflow in 2038. Use mod-datetime instead.
      */
-    g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_MOD_DATE, g_param_spec_int("mod-date", "Modification Date", "The date and time the document was modified", -1, G_MAXINT, -1, G_PARAM_READWRITE));
+    g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_MOD_DATE,
+                                    g_param_spec_int("mod-date", "Modification Date", "The date and time the document was modified", -1, G_MAXINT, -1, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_DEPRECATED)));
+
+    /**
+     * PopplerDocument:mod-datetime:
+     *
+     * The #GDateTime the document was most recently modified.
+     *
+     * Since: 20.09.0
+     */
+    g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_MOD_DATETIME, g_param_spec_boxed("mod-datetime", "Modification DateTime", "The date and time the document was modified", G_TYPE_DATE_TIME, G_PARAM_READWRITE));
 
     /**
      * PopplerDocument:linearized:
@@ -3345,3 +3471,32 @@ GDateTime *_poppler_convert_pdf_date_to_date_time(const GooString *date)
 
     return date_time;
 }
+
+/**
+ * _poppler_convert_date_time_to_pdf_date:
+ * @datetime: a #GDateTime
+ *
+ * Converts a #GDateTime to a PDF date.
+ *
+ * Returns: The converted date
+ **/
+GooString *_poppler_convert_date_time_to_pdf_date(GDateTime *datetime)
+{
+    int offset_min;
+    gchar *date_str;
+    GooString *out_str;
+
+    offset_min = g_date_time_get_utc_offset(datetime) / 1000000 / 60;
+    date_str = g_date_time_format(datetime, "D:%Y%m%d%H%M%S");
+
+    if (offset_min == 0) {
+        out_str = GooString::format("{0:s}Z", date_str);
+    } else {
+        char tz = offset_min > 0 ? '+' : '-';
+
+        out_str = GooString::format("{0:s}{1:c}{2:02d}'{3:02d}'", date_str, tz, offset_min / 60, offset_min % 60);
+    }
+
+    g_free(date_str);
+    return out_str;
+}
diff --git a/glib/poppler-document.h b/glib/poppler-document.h
index fd5acac9..5d19b52c 100644
--- a/glib/poppler-document.h
+++ b/glib/poppler-document.h
@@ -345,10 +345,18 @@ time_t poppler_document_get_creation_date(PopplerDocument *document);
 POPPLER_PUBLIC
 void poppler_document_set_creation_date(PopplerDocument *document, time_t creation_date);
 POPPLER_PUBLIC
+GDateTime *poppler_document_get_creation_date_time(PopplerDocument *document);
+POPPLER_PUBLIC
+void poppler_document_set_creation_date_time(PopplerDocument *document, GDateTime *creation_datetime);
+POPPLER_PUBLIC
 time_t poppler_document_get_modification_date(PopplerDocument *document);
 POPPLER_PUBLIC
 void poppler_document_set_modification_date(PopplerDocument *document, time_t modification_date);
 POPPLER_PUBLIC
+GDateTime *poppler_document_get_modification_date_time(PopplerDocument *document);
+POPPLER_PUBLIC
+void poppler_document_set_modification_date_time(PopplerDocument *document, GDateTime *modification_datetime);
+POPPLER_PUBLIC
 gboolean poppler_document_is_linearized(PopplerDocument *document);
 POPPLER_PUBLIC
 PopplerPageLayout poppler_document_get_page_layout(PopplerDocument *document);
diff --git a/glib/poppler-private.h b/glib/poppler-private.h
index 5495def6..d41b59c6 100644
--- a/glib/poppler-private.h
+++ b/glib/poppler-private.h
@@ -141,6 +141,7 @@ const PDFRectangle *_poppler_annot_get_cropbox(PopplerAnnot *poppler_annot);
 char *_poppler_goo_string_to_utf8(const GooString *s);
 gboolean _poppler_convert_pdf_date_to_gtime(const GooString *date, time_t *gdate);
 GDateTime *_poppler_convert_pdf_date_to_date_time(const GooString *date);
+GooString *_poppler_convert_date_time_to_pdf_date(GDateTime *datetime);
 
 /*
  * A convenience macro for boxed type implementations, which defines a
diff --git a/glib/reference/poppler-sections.txt b/glib/reference/poppler-sections.txt
index dc2be923..900b1f9f 100644
--- a/glib/reference/poppler-sections.txt
+++ b/glib/reference/poppler-sections.txt
@@ -160,12 +160,14 @@ poppler_document_find_dest
 poppler_document_get_attachments
 poppler_document_get_author
 poppler_document_get_creation_date
+poppler_document_get_creation_date_time
 poppler_document_get_creator
 poppler_document_get_form_field
 poppler_document_get_id
 poppler_document_get_keywords
 poppler_document_get_metadata
 poppler_document_get_modification_date
+poppler_document_get_modification_date_time
 poppler_document_get_n_attachments
 poppler_document_get_n_pages
 poppler_document_get_page
@@ -199,9 +201,11 @@ poppler_document_save
 poppler_document_save_a_copy
 poppler_document_set_author
 poppler_document_set_creation_date
+poppler_document_set_creation_date_time
 poppler_document_set_creator
 poppler_document_set_keywords
 poppler_document_set_modification_date
+poppler_document_set_modification_date_time
 poppler_document_set_producer
 poppler_document_set_subject
 poppler_document_set_title
commit c146da765689968ceb09921928152d5ecd5b0956
Author: Jason Crain <jason at inspiresomeone.us>
Date:   Fri Jan 3 18:42:21 2020 -0700

    glib: Deprecate PopplerAttachment GTime fields
    
    GTime was deprecated in glib 2.62 and will overflow in 2038.
    
    The PopplerAttachment struct publicly uses GTime for the 'mtime' and
    'ctime' fields. Deprecate these two fields and add accessor functions,
    poppler_attachment_get_ctime and poppler_attachment_get_mtime, which
    retun GDateTime* instead.
    
    Fixes #765, Related to #715

diff --git a/glib/demo/attachments.c b/glib/demo/attachments.c
index 03659f11..3106af19 100644
--- a/glib/demo/attachments.c
+++ b/glib/demo/attachments.c
@@ -42,19 +42,22 @@ static void pgd_attachments_fill_model(GtkListStore *model, PopplerDocument *doc
         PopplerAttachment *attachment = POPPLER_ATTACHMENT(l->data);
         GtkTreeIter iter;
         gchar *size;
-        gchar *ctime, *mtime;
+        GDateTime *ctime, *mtime;
+        gchar *ctime_str, *mtime_str;
 
         size = g_strdup_printf("%" G_GSIZE_FORMAT, attachment->size);
-        ctime = pgd_format_date(attachment->ctime);
-        mtime = pgd_format_date(attachment->mtime);
+        ctime = poppler_attachment_get_ctime(attachment);
+        ctime_str = ctime ? g_date_time_format(ctime, "%c") : NULL;
+        mtime = poppler_attachment_get_mtime(attachment);
+        mtime_str = mtime ? g_date_time_format(mtime, "%c") : NULL;
 
         gtk_list_store_append(model, &iter);
         gtk_list_store_set(model, &iter, ATTACHMENTS_NAME_COLUMN, attachment->name ? attachment->name : "Unknown", ATTACHMENTS_DESCRIPTION_COLUMN, attachment->description ? attachment->description : "Unknown", ATTACHMENTS_SIZE_COLUMN,
-                           size ? size : "Unknown", ATTACHMENTS_CTIME_COLUMN, ctime ? ctime : "Unknown", ATTACHMENTS_MTIME_COLUMN, mtime ? mtime : "Unknown", ATTACHMENTS_ATTACHMENT_COLUMN, attachment, -1);
+                           size ? size : "Unknown", ATTACHMENTS_CTIME_COLUMN, ctime_str ? ctime_str : "Unknown", ATTACHMENTS_MTIME_COLUMN, mtime_str ? mtime_str : "Unknown", ATTACHMENTS_ATTACHMENT_COLUMN, attachment, -1);
 
         g_free(size);
-        g_free(ctime);
-        g_free(mtime);
+        g_free(ctime_str);
+        g_free(mtime_str);
 
         g_object_unref(attachment);
     }
diff --git a/glib/poppler-attachment.cc b/glib/poppler-attachment.cc
index 3e0d69bb..9aade86f 100644
--- a/glib/poppler-attachment.cc
+++ b/glib/poppler-attachment.cc
@@ -38,6 +38,8 @@
 struct PopplerAttachmentPrivate
 {
     Object obj_stream {};
+    GDateTime *mtime;
+    GDateTime *ctime;
 };
 
 static void poppler_attachment_finalize(GObject *obj);
@@ -79,6 +81,9 @@ static void poppler_attachment_finalize(GObject *obj)
         g_string_free(attachment->checksum, TRUE);
     attachment->checksum = nullptr;
 
+    g_clear_pointer(&priv->mtime, g_date_time_unref);
+    g_clear_pointer(&priv->ctime, g_date_time_unref);
+
     priv->~PopplerAttachmentPrivate();
 
     G_OBJECT_CLASS(poppler_attachment_parent_class)->finalize(obj);
@@ -107,14 +112,20 @@ PopplerAttachment *_poppler_attachment_new(FileSpec *emb_file)
         attachment->size = embFile->size();
 
         if (embFile->createDate()) {
-            time_t aux;
-            _poppler_convert_pdf_date_to_gtime(embFile->createDate(), &aux);
-            attachment->ctime = (GTime)aux; // FIXME This will overflow on dates from after 2038
+            priv->ctime = _poppler_convert_pdf_date_to_date_time(embFile->createDate());
+            G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+            /* This will overflow on dates from after 2038. This field is
+             * deprecated, only kept for backward compatibility. */
+            attachment->ctime = (GTime)g_date_time_to_unix(priv->ctime);
+            G_GNUC_END_IGNORE_DEPRECATIONS
         }
         if (embFile->modDate()) {
-            time_t aux;
-            _poppler_convert_pdf_date_to_gtime(embFile->modDate(), &aux);
-            attachment->mtime = (GTime)aux; // FIXME This will overflow on dates from after 2038
+            priv->mtime = _poppler_convert_pdf_date_to_date_time(embFile->modDate());
+            G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+            /* This will overflow on dates from after 2038. This field is
+             * deprecated, only kept for backward compatibility. */
+            attachment->mtime = (GTime)g_date_time_to_unix(priv->mtime);
+            G_GNUC_END_IGNORE_DEPRECATIONS
         }
 
         if (embFile->checksum() && embFile->checksum()->getLength() > 0)
@@ -128,6 +139,35 @@ PopplerAttachment *_poppler_attachment_new(FileSpec *emb_file)
     return attachment;
 }
 
+/**
+ * poppler_attachment_get_ctime:
+ * @attachment: a #PopplerAttachment
+ *
+ * Returns: (transfer none) (nullable): The attachment's creation date and time
+ * as a #GDateTime, or %NULL if the creation date and time is not available.
+ *
+ * Since: 20.09.0
+ */
+GDateTime *poppler_attachment_get_ctime(PopplerAttachment *attachment)
+{
+    return GET_PRIVATE(attachment)->ctime;
+}
+
+/**
+ * poppler_attachment_get_mtime:
+ * @attachment: a #PopplerAttachment
+ *
+ * Returns: (transfer none) (nullable): The attachment's modification date and
+ * time as a #GDateTime, or %NULL if the modification date and time is not
+ * available.
+ *
+ * Since: 20.09.0
+ */
+GDateTime *poppler_attachment_get_mtime(PopplerAttachment *attachment)
+{
+    return GET_PRIVATE(attachment)->mtime;
+}
+
 static gboolean save_helper(const gchar *buf, gsize count, gpointer data, GError **error)
 {
     FILE *f = (FILE *)data;
diff --git a/glib/poppler-attachment.h b/glib/poppler-attachment.h
index c0904052..2b6019a4 100644
--- a/glib/poppler-attachment.h
+++ b/glib/poppler-attachment.h
@@ -50,11 +50,23 @@ G_BEGIN_DECLS
 typedef gboolean (*PopplerAttachmentSaveFunc)(const gchar *buf, gsize count, gpointer data, GError **error);
 
 /* GTime is deprecated, but is part of our ABI here (see #715, #765). */
+/**
+ * PopplerAttachment:
+ * @name: The filename
+ * @description: Descriptive text
+ * @size: The size of the file
+ * @mtime: The date and time when the file was last modified. Deprecated in
+ *   poppler 20.09.0. Use poppler_attachment_get_mtime() instead.
+ * @ctime: The date and time when the file was created. Deprecated in poppler
+ *   20.09.0. Use poppler_attachment_get_ctime() instead.
+ * @checksum: A 16-byte checksum of the file.
+ */
 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
 struct _PopplerAttachment
 {
     GObject parent;
 
+    /*< public >*/
     gchar *name;
     gchar *description;
     gsize size;
@@ -72,6 +84,10 @@ typedef struct _PopplerAttachmentClass
 POPPLER_PUBLIC
 GType poppler_attachment_get_type(void) G_GNUC_CONST;
 POPPLER_PUBLIC
+GDateTime *poppler_attachment_get_ctime(PopplerAttachment *attachment);
+POPPLER_PUBLIC
+GDateTime *poppler_attachment_get_mtime(PopplerAttachment *attachment);
+POPPLER_PUBLIC
 gboolean poppler_attachment_save(PopplerAttachment *attachment, const char *filename, GError **error);
 POPPLER_PUBLIC
 gboolean poppler_attachment_save_to_callback(PopplerAttachment *attachment, PopplerAttachmentSaveFunc save_func, gpointer user_data, GError **error);
diff --git a/glib/poppler-document.cc b/glib/poppler-document.cc
index 699a4c79..85326240 100644
--- a/glib/poppler-document.cc
+++ b/glib/poppler-document.cc
@@ -3309,3 +3309,39 @@ gboolean _poppler_convert_pdf_date_to_gtime(const GooString *date, time_t *gdate
 
     return retval;
 }
+
+/**
+ * _poppler_convert_pdf_date_to_date_time:
+ * @date: a PDF date
+ *
+ * Converts the PDF date in @date to a #GDateTime.
+ *
+ * Returns: The converted date, or %NULL on error.
+ **/
+GDateTime *_poppler_convert_pdf_date_to_date_time(const GooString *date)
+{
+    GDateTime *date_time = nullptr;
+    GTimeZone *time_zone = nullptr;
+    int year, mon, day, hour, min, sec, tzHours, tzMins;
+    char tz;
+
+    if (parseDateString(date->c_str(), &year, &mon, &day, &hour, &min, &sec, &tz, &tzHours, &tzMins)) {
+        if (tz == '+' || tz == '-') {
+            gchar *identifier;
+
+            identifier = g_strdup_printf("%c%02u:%02u", tz, tzHours, tzMins);
+            time_zone = g_time_zone_new(identifier);
+            g_free(identifier);
+        } else if (tz == '\0' || tz == 'Z') {
+            time_zone = g_time_zone_new_utc();
+        } else {
+            g_warning("unexpected tz val '%c'", tz);
+            time_zone = g_time_zone_new_utc();
+        }
+
+        date_time = g_date_time_new(time_zone, year, mon, day, hour, min, sec);
+        g_time_zone_unref(time_zone);
+    }
+
+    return date_time;
+}
diff --git a/glib/poppler-private.h b/glib/poppler-private.h
index 14a175bc..5495def6 100644
--- a/glib/poppler-private.h
+++ b/glib/poppler-private.h
@@ -140,6 +140,7 @@ const PDFRectangle *_poppler_annot_get_cropbox(PopplerAnnot *poppler_annot);
 
 char *_poppler_goo_string_to_utf8(const GooString *s);
 gboolean _poppler_convert_pdf_date_to_gtime(const GooString *date, time_t *gdate);
+GDateTime *_poppler_convert_pdf_date_to_date_time(const GooString *date);
 
 /*
  * A convenience macro for boxed type implementations, which defines a
diff --git a/glib/reference/poppler-sections.txt b/glib/reference/poppler-sections.txt
index 93c884e3..dc2be923 100644
--- a/glib/reference/poppler-sections.txt
+++ b/glib/reference/poppler-sections.txt
@@ -330,6 +330,8 @@ poppler_action_movie_operation_get_type
 <TITLE>PopplerAttachment</TITLE>
 PopplerAttachment
 PopplerAttachmentSaveFunc
+poppler_attachment_get_ctime
+poppler_attachment_get_mtime
 poppler_attachment_save
 poppler_attachment_save_to_callback
 


More information about the poppler mailing list