summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher James Halse Rogers <raof@ubuntu.com>2017-12-15 17:21:27 +1100
committerRichard Hughes <richard@hughsie.com>2017-12-28 20:23:56 +0000
commitf0623d1cdbfdb30ed44c94d6bceb46874e3fac46 (patch)
treed92d358c6a30b9c79420e8a581148ec1a671d544
parent0f729460aada6343dd3aca9c6c192208f018959e (diff)
downloadcolord-f0623d1cdbfdb30ed44c94d6bceb46874e3fac46.tar.gz
libcolord: Add cd_icc_set_created
This allows clients to override the creation time of an ICC profile, particularly useful for code that tries to build deterministically.
-rw-r--r--lib/colord/cd-icc.c62
-rw-r--r--lib/colord/cd-icc.h2
2 files changed, 64 insertions, 0 deletions
diff --git a/lib/colord/cd-icc.c b/lib/colord/cd-icc.c
index 5e9441a..e5f436a 100644
--- a/lib/colord/cd-icc.c
+++ b/lib/colord/cd-icc.c
@@ -29,9 +29,11 @@
#include <glib.h>
#include <glib/gstdio.h>
#include <lcms2.h>
+#include <lcms2_plugin.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <errno.h>
#include <math.h>
#include "cd-context-lcms.h"
@@ -70,6 +72,7 @@ typedef struct
gdouble version;
GHashTable *mluc_data[CD_MLUC_LAST]; /* key is 'en_GB' or '' for default */
GHashTable *metadata;
+ gint64 creation_time;
guint32 size;
GPtrArray *named_colors;
guint temperature;
@@ -1673,6 +1676,43 @@ cd_icc_save_data (CdIcc *icc,
goto out;
}
+ /* finally, optionally override the created date */
+ if (priv->creation_time != -1) {
+ /*
+ * LCMS2 maintainer rejects adding API to do this,
+ * instead suggesting you munge the header directly:
+ * https://github.com/mm2/Little-CMS/issues/71
+ */
+ struct tm creation_time;
+ cmsICCHeader *header;
+ g_autoptr(GByteArray) mutable_data = NULL;
+
+ data = cd_icc_serialize_profile (icc, error);
+ if (data == NULL)
+ goto out;
+
+ mutable_data = g_bytes_unref_to_array (data);
+ data = NULL;
+
+ if (!gmtime_r (&priv->creation_time, &creation_time)) {
+ g_set_error (error,
+ CD_ICC_ERROR,
+ CD_ICC_ERROR_FAILED_TO_SAVE,
+ "failed to translate creation time: %s (%i)",
+ g_strerror (errno),
+ errno);
+ goto out;
+ }
+ header = (cmsICCHeader*)mutable_data->data;
+ _cmsEncodeDateTimeNumber (&header->date, &creation_time);
+
+ /* we've changed the creation date, recalculate MD5 */
+ cmsCloseProfile (priv->lcms_profile);
+ priv->lcms_profile = cmsOpenProfileFromMemTHR (priv->context_lcms,
+ mutable_data->data,
+ mutable_data->len);
+ }
+
/* write profile id */
ret = cmsMD5computeID (priv->lcms_profile);
if (!ret) {
@@ -2398,6 +2438,10 @@ cd_icc_get_created (CdIcc *icc)
g_return_val_if_fail (CD_IS_ICC (icc), NULL);
+ /* If the creation time has been overridden, return that */
+ if (priv->creation_time != (gint64)-1)
+ return g_date_time_new_from_unix_local (priv->creation_time);
+
/* get the profile creation time and date */
if (!cmsGetHeaderCreationDateTime (priv->lcms_profile, &created_tm))
return NULL;
@@ -2414,6 +2458,23 @@ cd_icc_get_created (CdIcc *icc)
}
/**
+ * cd_icc_set_created
+ * @icc: A valid #CdIcc
+ *
+ * Sets the ICC creation date and time.
+ *
+ * Since: 1.4.2
+ **/
+void
+cd_icc_set_created (CdIcc *icc, GDateTime* creation_time)
+{
+ CdIccPrivate *priv = GET_PRIVATE (icc);
+
+ g_return_if_fail (CD_IS_ICC (icc));
+ priv->creation_time = g_date_time_to_unix (creation_time);
+}
+
+/**
* cd_icc_get_checksum:
* @icc: A valid #CdIcc
*
@@ -3945,6 +4006,7 @@ cd_icc_init (CdIcc *icc)
g_str_equal,
g_free,
g_free);
+ priv->creation_time = -1;
for (i = 0; i < CD_MLUC_LAST; i++) {
priv->mluc_data[i] = g_hash_table_new_full (g_str_hash,
g_str_equal,
diff --git a/lib/colord/cd-icc.h b/lib/colord/cd-icc.h
index 35c605b..31699eb 100644
--- a/lib/colord/cd-icc.h
+++ b/lib/colord/cd-icc.h
@@ -195,6 +195,8 @@ void cd_icc_remove_metadata (CdIcc *icc,
GPtrArray *cd_icc_get_named_colors (CdIcc *icc);
gboolean cd_icc_get_can_delete (CdIcc *icc);
GDateTime *cd_icc_get_created (CdIcc *icc);
+void cd_icc_set_created (CdIcc *icc,
+ GDateTime *creation_time);
const gchar *cd_icc_get_checksum (CdIcc *icc);
const gchar *cd_icc_get_description (CdIcc *icc,
const gchar *locale,