1 /* GXPSCoreProperties
2 *
3 * Copyright (C) 2013 Carlos Garcia Campos <carlosgc@gnome.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include <config.h>
21
22 #include "gxps-core-properties.h"
23 #include "gxps-private.h"
24 #include "gxps-error.h"
25 #include <string.h>
26 #include <errno.h>
27
28 /**
29 * SECTION:gxps-core-properties
30 * @Short_description: XPS Core Properties
31 * @Title: GXPSCoreProperties
32 * @See_also: #GXPSFile
33 *
34 * #GXPSCoreProperties represents the metadata of a #GXPSFile.
35 * #GXPSCoreProperties objects can not be created directly, they
36 * are retrieved from a #GXPSFile with gxps_file_get_core_properties().
37 *
38 * Since: 0.2.3
39 */
40
41 enum {
42 PROP_0,
43 PROP_ARCHIVE,
44 PROP_SOURCE
45 };
46
47 struct _GXPSCorePropertiesPrivate {
48 GXPSArchive *zip;
49 gchar *source;
50
51 gboolean initialized;
52 GError *init_error;
53
54 gchar *category;
55 gchar *content_status;
56 gchar *content_type;
57 time_t created;
58 gchar *creator;
59 gchar *description;
60 gchar *identifier;
61 gchar *keywords;
62 gchar *language;
63 gchar *last_modified_by;
64 time_t last_printed;
65 time_t modified;
66 gchar *revision;
67 gchar *subject;
68 gchar *title;
69 gchar *version;
70 };
71
72 static void initable_iface_init (GInitableIface *initable_iface);
73
74 G_DEFINE_TYPE_WITH_CODE (GXPSCoreProperties, gxps_core_properties, G_TYPE_OBJECT,
75 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init))
76
77 /* CoreProperties parser */
78 typedef enum {
79 CP_UNKNOWN,
80 CP_CATEGORY,
81 CP_CONTENT_STATUS,
82 CP_CONTENT_TYPE,
83 CP_CREATED,
84 CP_CREATOR,
85 CP_DESCRIPTION,
86 CP_IDENTIFIER,
87 CP_KEYWORDS,
88 CP_LANGUAGE,
89 CP_LAST_MODIFIED_BY,
90 CP_LAST_PRINTED,
91 CP_MODIFIED,
92 CP_REVISION,
93 CP_SUBJECT,
94 CP_TITLE,
95 CP_VERSION
96 } CoreProperty;
97
98 typedef struct _CorePropsParserData {
99 GXPSCoreProperties *core_props;
100 CoreProperty property;
101 GString *buffer;
102 } CorePropsParserData;
103
104 static gchar *
parse_int(const gchar * value,gint * int_value)105 parse_int (const gchar *value,
106 gint *int_value)
107 {
108 gint64 result;
109 gchar *endptr = NULL;
110
111 *int_value = -1;
112
113 if (!value)
114 return NULL;
115
116 errno = 0;
117 result = g_ascii_strtoll (value, &endptr, 10);
118 if (errno || endptr == value || result > G_MAXINT || result < G_MININT)
119 return NULL;
120
121 *int_value = result;
122
123 return endptr;
124 }
125
126 static gboolean
parse_date(const gchar * date,gint * year,gint * mon,gint * day,gint * hour,gint * min,gint * sec,gint * tz)127 parse_date (const gchar *date,
128 gint *year,
129 gint *mon,
130 gint *day,
131 gint *hour,
132 gint *min,
133 gint *sec,
134 gint *tz)
135 {
136 gint value;
137 const gchar *str = date;
138
139 /* Year:
140 * YYYY (eg 1997)
141 * Year and month:
142 * YYYY-MM (eg 1997-07)
143 * Complete date:
144 * YYYY-MM-DD (eg 1997-07-16)
145 * Complete date plus hours and minutes:
146 * YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00)
147 * Complete date plus hours, minutes and seconds:
148 * YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00)
149 * Complete date plus hours, minutes, seconds and a decimal fraction of a second
150 * YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00)
151 * where:
152 *
153 * YYYY = four-digit year
154 * MM = two-digit month (01=January, etc.)
155 * DD = two-digit day of month (01 through 31)
156 * hh = two digits of hour (00 through 23) (am/pm NOT allowed)
157 * mm = two digits of minute (00 through 59)
158 * ss = two digits of second (00 through 59)
159 * s = one or more digits representing a decimal fraction of a second
160 * TZD = time zone designator (Z or +hh:mm or -hh:mm)
161 */
162
163 /* Year */
164 str = parse_int (str, &value);
165 *year = value;
166 if (!str)
167 return value != -1;
168
169 if (*str != '-')
170 return FALSE;
171 str++;
172
173 /* Month */
174 str = parse_int (str, &value);
175 *mon = value;
176 if (!str)
177 return value != -1;
178
179 if (*str != '-')
180 return FALSE;
181 str++;
182
183 /* Day */
184 str = parse_int (str, &value);
185 *day = value;
186 if (!str)
187 return value != -1;
188
189 if (*str != 'T')
190 return FALSE;
191 str++;
192
193 /* Hour */
194 str = parse_int (str, &value);
195 *hour = value;
196 if (!str)
197 return value != -1;
198
199 if (*str != ':')
200 return FALSE;
201 str++;
202
203 /* Minute */
204 str = parse_int (str, &value);
205 *min = value;
206 if (!str)
207 return value != -1;
208
209 if (*str != ':')
210 return FALSE;
211 str++;
212
213 /* Second */
214 str = parse_int (str, &value);
215 *sec = value;
216 if (!str)
217 return value != -1;
218
219 /* Fraction of a second */
220 if (*str == '.') {
221 str = parse_int (++str, &value);
222 if (!str)
223 return TRUE;
224 }
225
226 /* Time Zone */
227 if (*str == '+' || *str == '-') {
228 gint tz_hour = -1, tz_min = -1;
229 gint sign = *str == '+' ? 1 : -1;
230
231 str++;
232
233 str = parse_int (str, &value);
234 if (!str)
235 return value != -1;
236 tz_hour = value;
237
238 if (*str != ':')
239 return FALSE;
240 str++;
241
242 str = parse_int (str, &value);
243 if (!str)
244 return value != -1;
245 tz_min = value;
246
247 *tz = (tz_hour * 3600 + tz_min * 60) * sign;
248 } else if (*str == 'Z') {
249 *tz = 0;
250 }
251
252 return TRUE;
253 }
254
255 static time_t
w3cdtf_to_time_t(const gchar * date)256 w3cdtf_to_time_t (const gchar *date)
257 {
258 struct tm stm;
259 gint year = -1, mon = -1, day = -1;
260 gint hour = -1, min = -1, sec = -1;
261 gint tz = 0;
262 time_t retval;
263
264 if (!parse_date (date, &year, &mon, &day, &hour, &min, &sec, &tz))
265 return (time_t)-1;
266
267 stm.tm_year = year - 1900;
268 stm.tm_mon = mon - 1;
269 stm.tm_mday = day;
270 stm.tm_hour = hour;
271 stm.tm_min = min;
272 stm.tm_sec = sec;
273 stm.tm_isdst = -1;
274
275 retval = mktime (&stm);
276 if (retval == (time_t)-1)
277 return retval;
278
279 return retval + tz;
280 }
281
282 static void
core_props_start_element(GMarkupParseContext * context,const gchar * element_name,const gchar ** names,const gchar ** values,gpointer user_data,GError ** error)283 core_props_start_element (GMarkupParseContext *context,
284 const gchar *element_name,
285 const gchar **names,
286 const gchar **values,
287 gpointer user_data,
288 GError **error)
289 {
290 CorePropsParserData *data = (CorePropsParserData *)user_data;
291
292 data->buffer = g_string_new (NULL);
293
294 if (strcmp (element_name, "category") == 0)
295 data->property = CP_CATEGORY;
296 else if (strcmp (element_name, "contentStatus") == 0)
297 data->property = CP_CONTENT_STATUS;
298 else if (strcmp (element_name, "contentType") == 0)
299 data->property = CP_CONTENT_TYPE;
300 else if (strcmp (element_name, "dcterms:created") == 0)
301 data->property = CP_CREATED;
302 else if (strcmp (element_name, "dc:creator") == 0)
303 data->property = CP_CREATOR;
304 else if (strcmp (element_name, "dc:description") == 0)
305 data->property = CP_DESCRIPTION;
306 else if (strcmp (element_name, "dc:identifier") == 0)
307 data->property = CP_IDENTIFIER;
308 else if (strcmp (element_name, "keywords") == 0)
309 data->property = CP_KEYWORDS;
310 else if (strcmp (element_name, "dc:language") == 0)
311 data->property = CP_LANGUAGE;
312 else if (strcmp (element_name, "lastModifiedBy") == 0)
313 data->property = CP_LAST_MODIFIED_BY;
314 else if (strcmp (element_name, "lastPrinted") == 0)
315 data->property = CP_LAST_PRINTED;
316 else if (strcmp (element_name, "dcterms:modified") == 0)
317 data->property = CP_MODIFIED;
318 else if (strcmp (element_name, "revision") == 0)
319 data->property = CP_REVISION;
320 else if (strcmp (element_name, "dc:subject") == 0)
321 data->property = CP_SUBJECT;
322 else if (strcmp (element_name, "dc:title") == 0)
323 data->property = CP_TITLE;
324 else if (strcmp (element_name, "version") == 0)
325 data->property = CP_VERSION;
326 else if ((strcmp (element_name, "coreProperties") == 0) ||
327 (strcmp (element_name, "cp:coreProperties") == 0)) {
328 /* Do nothing */
329 } else {
330 gxps_parse_error (context,
331 data->core_props->priv->source,
332 G_MARKUP_ERROR_UNKNOWN_ELEMENT,
333 element_name, NULL, NULL, error);
334 }
335 }
336
337 static void
core_props_end_element(GMarkupParseContext * context,const gchar * element_name,gpointer user_data,GError ** error)338 core_props_end_element (GMarkupParseContext *context,
339 const gchar *element_name,
340 gpointer user_data,
341 GError **error)
342 {
343 CorePropsParserData *data = (CorePropsParserData *)user_data;
344 GXPSCorePropertiesPrivate *priv = data->core_props->priv;
345 gchar *text;
346 gsize text_len;
347
348 if (!data->buffer)
349 return;
350
351 text_len = data->buffer->len;
352 text = g_string_free (data->buffer, FALSE);
353 data->buffer = NULL;
354
355 switch (data->property) {
356 case CP_CATEGORY:
357 priv->category = g_strndup (text, text_len);
358 break;
359 case CP_CONTENT_STATUS:
360 priv->content_status = g_strndup (text, text_len);
361 break;
362 case CP_CONTENT_TYPE:
363 priv->content_type = g_strndup (text, text_len);
364 break;
365 case CP_CREATED:
366 priv->created = w3cdtf_to_time_t (text);
367 break;
368 case CP_CREATOR:
369 priv->creator = g_strndup (text, text_len);
370 break;
371 case CP_DESCRIPTION:
372 priv->description = g_strndup (text, text_len);
373 break;
374 case CP_IDENTIFIER:
375 priv->identifier = g_strndup (text, text_len);
376 break;
377 case CP_KEYWORDS:
378 priv->keywords = g_strndup (text, text_len);
379 break;
380 case CP_LANGUAGE:
381 priv->language = g_strndup (text, text_len);
382 break;
383 case CP_LAST_MODIFIED_BY:
384 priv->last_modified_by = g_strndup (text, text_len);
385 break;
386 case CP_LAST_PRINTED:
387 priv->last_printed = w3cdtf_to_time_t (text);
388 break;
389 case CP_MODIFIED:
390 priv->modified = w3cdtf_to_time_t (text);
391 break;
392 case CP_REVISION:
393 priv->revision = g_strndup (text, text_len);
394 break;
395 case CP_SUBJECT:
396 priv->subject = g_strndup (text, text_len);
397 break;
398 case CP_TITLE:
399 priv->title = g_strndup (text, text_len);
400 break;
401 case CP_VERSION:
402 priv->version = g_strndup (text, text_len);
403 break;
404 case CP_UNKNOWN:
405 break;
406 }
407
408 data->property = CP_UNKNOWN;
409 g_free (text);
410 }
411
412 static void
core_props_text(GMarkupParseContext * context,const gchar * text,gsize text_len,gpointer user_data,GError ** error)413 core_props_text (GMarkupParseContext *context,
414 const gchar *text,
415 gsize text_len,
416 gpointer user_data,
417 GError **error)
418 {
419 CorePropsParserData *data = (CorePropsParserData *)user_data;
420
421 if (!data->buffer)
422 return;
423
424 g_string_append_len (data->buffer, text, text_len);
425 }
426
427 static const GMarkupParser core_props_parser = {
428 core_props_start_element,
429 core_props_end_element,
430 core_props_text,
431 NULL,
432 NULL
433 };
434
435 static gboolean
gxps_core_properties_parse(GXPSCoreProperties * core_props,GError ** error)436 gxps_core_properties_parse (GXPSCoreProperties *core_props,
437 GError **error)
438 {
439 GInputStream *stream;
440 GMarkupParseContext *ctx;
441 CorePropsParserData parser_data;
442
443 stream = gxps_archive_open (core_props->priv->zip,
444 core_props->priv->source);
445 if (!stream) {
446 g_set_error (error,
447 GXPS_ERROR,
448 GXPS_ERROR_SOURCE_NOT_FOUND,
449 "CoreProperties source %s not found in archive",
450 core_props->priv->source);
451 return FALSE;
452 }
453
454 parser_data.core_props = core_props;
455 parser_data.property = 0;
456 parser_data.buffer = NULL;
457
458 ctx = g_markup_parse_context_new (&core_props_parser, 0, &parser_data, NULL);
459 gxps_parse_stream (ctx, stream, error);
460 g_object_unref (stream);
461
462 g_markup_parse_context_free (ctx);
463
464 return (*error != NULL) ? FALSE : TRUE;
465 }
466
467 static void
gxps_core_properties_finalize(GObject * object)468 gxps_core_properties_finalize (GObject *object)
469 {
470 GXPSCoreProperties *core_props = GXPS_CORE_PROPERTIES (object);
471
472 g_clear_object (&core_props->priv->zip);
473 g_clear_pointer (&core_props->priv->source, g_free);
474 g_clear_error (&core_props->priv->init_error);
475
476 G_OBJECT_CLASS (gxps_core_properties_parent_class)->finalize (object);
477 }
478
479 static void
gxps_core_properties_init(GXPSCoreProperties * core_props)480 gxps_core_properties_init (GXPSCoreProperties *core_props)
481 {
482 core_props->priv = G_TYPE_INSTANCE_GET_PRIVATE (core_props,
483 GXPS_TYPE_CORE_PROPERTIES,
484 GXPSCorePropertiesPrivate);
485 }
486
487 static void
gxps_core_properties_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)488 gxps_core_properties_set_property (GObject *object,
489 guint prop_id,
490 const GValue *value,
491 GParamSpec *pspec)
492 {
493 GXPSCoreProperties *core_props = GXPS_CORE_PROPERTIES (object);
494
495 switch (prop_id) {
496 case PROP_ARCHIVE:
497 core_props->priv->zip = g_value_dup_object (value);
498 break;
499 case PROP_SOURCE:
500 core_props->priv->source = g_value_dup_string (value);
501 break;
502 default:
503 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
504 break;
505 }
506 }
507
508 static void
gxps_core_properties_class_init(GXPSCorePropertiesClass * klass)509 gxps_core_properties_class_init (GXPSCorePropertiesClass *klass)
510 {
511 GObjectClass *object_class = G_OBJECT_CLASS (klass);
512
513 object_class->set_property = gxps_core_properties_set_property;
514 object_class->finalize = gxps_core_properties_finalize;
515
516 g_object_class_install_property (object_class,
517 PROP_ARCHIVE,
518 g_param_spec_object ("archive",
519 "Archive",
520 "The archive",
521 GXPS_TYPE_ARCHIVE,
522 G_PARAM_WRITABLE |
523 G_PARAM_CONSTRUCT_ONLY));
524 g_object_class_install_property (object_class,
525 PROP_SOURCE,
526 g_param_spec_string ("source",
527 "Source",
528 "The Core Properties Source File",
529 NULL,
530 G_PARAM_WRITABLE |
531 G_PARAM_CONSTRUCT_ONLY));
532
533 g_type_class_add_private (klass, sizeof (GXPSCorePropertiesPrivate));
534 }
535
536 static gboolean
gxps_core_properties_initable_init(GInitable * initable,GCancellable * cancellable,GError ** error)537 gxps_core_properties_initable_init (GInitable *initable,
538 GCancellable *cancellable,
539 GError **error)
540 {
541 GXPSCoreProperties *core_props = GXPS_CORE_PROPERTIES (initable);
542
543 if (core_props->priv->initialized) {
544 if (core_props->priv->init_error) {
545 g_propagate_error (error, g_error_copy (core_props->priv->init_error));
546
547 return FALSE;
548 }
549
550 return TRUE;
551 }
552
553 core_props->priv->initialized = TRUE;
554
555 if (!gxps_core_properties_parse (core_props, &core_props->priv->init_error)) {
556 g_propagate_error (error, g_error_copy (core_props->priv->init_error));
557 return FALSE;
558 }
559
560 return TRUE;
561 }
562
563 static void
initable_iface_init(GInitableIface * initable_iface)564 initable_iface_init (GInitableIface *initable_iface)
565 {
566 initable_iface->init = gxps_core_properties_initable_init;
567 }
568
569 GXPSCoreProperties *
_gxps_core_properties_new(GXPSArchive * zip,const gchar * source,GError ** error)570 _gxps_core_properties_new (GXPSArchive *zip,
571 const gchar *source,
572 GError **error)
573 {
574 return g_initable_new (GXPS_TYPE_CORE_PROPERTIES,
575 NULL, error,
576 "archive", zip,
577 "source", source,
578 NULL);
579 }
580
581 /**
582 * gxps_core_properties_get_title:
583 * @core_props: a #GXPSCoreProperties
584 *
585 * Get the title.
586 *
587 * Returns: a string containing the title or %NULL
588 *
589 * Since: 0.2.3
590 */
591 const gchar *
gxps_core_properties_get_title(GXPSCoreProperties * core_props)592 gxps_core_properties_get_title (GXPSCoreProperties *core_props)
593 {
594 g_return_val_if_fail (GXPS_IS_CORE_PROPERTIES (core_props), NULL);
595
596 return core_props->priv->title;
597 }
598
599 /**
600 * gxps_core_properties_get_creator:
601 * @core_props: a #GXPSCoreProperties
602 *
603 * Get the creator.
604 *
605 * Returns: a string containing the creator or %NULL
606 *
607 * Since: 0.2.3
608 */
609 const gchar *
gxps_core_properties_get_creator(GXPSCoreProperties * core_props)610 gxps_core_properties_get_creator (GXPSCoreProperties *core_props)
611 {
612 g_return_val_if_fail (GXPS_IS_CORE_PROPERTIES (core_props), NULL);
613
614 return core_props->priv->creator;
615 }
616
617 /**
618 * gxps_core_properties_get_description:
619 * @core_props: a #GXPSCoreProperties
620 *
621 * Get the description.
622 *
623 * Returns: a string containing the description or %NULL
624 *
625 * Since: 0.2.3
626 */
627 const gchar *
gxps_core_properties_get_description(GXPSCoreProperties * core_props)628 gxps_core_properties_get_description (GXPSCoreProperties *core_props)
629 {
630 g_return_val_if_fail (GXPS_IS_CORE_PROPERTIES (core_props), NULL);
631
632 return core_props->priv->description;
633 }
634
635 /**
636 * gxps_core_properties_get_subject:
637 * @core_props: a #GXPSCoreProperties
638 *
639 * Get the subject.
640 *
641 * Returns: a string containing the subject or %NULL
642 *
643 * Since: 0.2.3
644 */
645 const gchar *
gxps_core_properties_get_subject(GXPSCoreProperties * core_props)646 gxps_core_properties_get_subject (GXPSCoreProperties *core_props)
647 {
648 g_return_val_if_fail (GXPS_IS_CORE_PROPERTIES (core_props), NULL);
649
650 return core_props->priv->subject;
651 }
652
653 /**
654 * gxps_core_properties_get_keywords:
655 * @core_props: a #GXPSCoreProperties
656 *
657 * Get the keywords.
658 *
659 * Returns: a string containing the keywords or %NULL
660 *
661 * Since: 0.2.3
662 */
663 const gchar *
gxps_core_properties_get_keywords(GXPSCoreProperties * core_props)664 gxps_core_properties_get_keywords (GXPSCoreProperties *core_props)
665 {
666 g_return_val_if_fail (GXPS_IS_CORE_PROPERTIES (core_props), NULL);
667
668 return core_props->priv->keywords;
669 }
670
671 /**
672 * gxps_core_properties_get_version:
673 * @core_props: a #GXPSCoreProperties
674 *
675 * Get the version number.
676 *
677 * Returns: a string containing the version number or %NULL
678 *
679 * Since: 0.2.3
680 */
681 const gchar *
gxps_core_properties_get_version(GXPSCoreProperties * core_props)682 gxps_core_properties_get_version (GXPSCoreProperties *core_props)
683 {
684 g_return_val_if_fail (GXPS_IS_CORE_PROPERTIES (core_props), NULL);
685
686 return core_props->priv->version;
687 }
688
689 /**
690 * gxps_core_properties_get_revision:
691 * @core_props: a #GXPSCoreProperties
692 *
693 * Get the revision number.
694 *
695 * Returns: a string containing the revision number or %NULL
696 *
697 * Since: 0.2.3
698 */
699 const gchar *
gxps_core_properties_get_revision(GXPSCoreProperties * core_props)700 gxps_core_properties_get_revision (GXPSCoreProperties *core_props)
701 {
702 g_return_val_if_fail (GXPS_IS_CORE_PROPERTIES (core_props), NULL);
703
704 return core_props->priv->revision;
705 }
706
707 /**
708 * gxps_core_properties_get_identifier:
709 * @core_props: a #GXPSCoreProperties
710 *
711 * Get the unique identifier.
712 *
713 * Returns: a string containing the identifier or %NULL
714 *
715 * Since: 0.2.3
716 */
717 const gchar *
gxps_core_properties_get_identifier(GXPSCoreProperties * core_props)718 gxps_core_properties_get_identifier (GXPSCoreProperties *core_props)
719 {
720 g_return_val_if_fail (GXPS_IS_CORE_PROPERTIES (core_props), NULL);
721
722 return core_props->priv->identifier;
723 }
724
725 /**
726 * gxps_core_properties_get_language:
727 * @core_props: a #GXPSCoreProperties
728 *
729 * Get the language.
730 *
731 * Returns: a string containing the language or %NULL
732 *
733 * Since: 0.2.3
734 */
735 const gchar *
gxps_core_properties_get_language(GXPSCoreProperties * core_props)736 gxps_core_properties_get_language (GXPSCoreProperties *core_props)
737 {
738 g_return_val_if_fail (GXPS_IS_CORE_PROPERTIES (core_props), NULL);
739
740 return core_props->priv->language;
741 }
742
743 /**
744 * gxps_core_properties_get_category:
745 * @core_props: a #GXPSCoreProperties
746 *
747 * Get the category.
748 *
749 * Returns: a string containing the category or %NULL
750 *
751 * Since: 0.2.3
752 */
753 const gchar *
gxps_core_properties_get_category(GXPSCoreProperties * core_props)754 gxps_core_properties_get_category (GXPSCoreProperties *core_props)
755 {
756 g_return_val_if_fail (GXPS_IS_CORE_PROPERTIES (core_props), NULL);
757
758 return core_props->priv->category;
759 }
760
761 /**
762 * gxps_core_properties_get_content_status:
763 * @core_props: a #GXPSCoreProperties
764 *
765 * Get the status of the content (e.g. Draft, Reviewed, Final)
766 *
767 * Returns: a string containing the status of the content or %NULL
768 *
769 * Since: 0.2.3
770 */
771 const gchar *
gxps_core_properties_get_content_status(GXPSCoreProperties * core_props)772 gxps_core_properties_get_content_status (GXPSCoreProperties *core_props)
773 {
774 g_return_val_if_fail (GXPS_IS_CORE_PROPERTIES (core_props), NULL);
775
776 return core_props->priv->content_status;
777 }
778
779 /**
780 * gxps_core_properties_get_content_type:
781 * @core_props: a #GXPSCoreProperties
782 *
783 * Get the type of content represented, generally defined by a
784 * specific use and intended audience. This is not the MIME-Type.
785 *
786 * Returns: a string containing the type of content or %NULL
787 *
788 * Since: 0.2.3
789 */
790 const gchar *
gxps_core_properties_get_content_type(GXPSCoreProperties * core_props)791 gxps_core_properties_get_content_type (GXPSCoreProperties *core_props)
792 {
793 g_return_val_if_fail (GXPS_IS_CORE_PROPERTIES (core_props), NULL);
794
795 return core_props->priv->content_type;
796 }
797
798 /**
799 * gxps_core_properties_get_created:
800 * @core_props: a #GXPSCoreProperties
801 *
802 * Get the creating date.
803 *
804 * Returns: the creating date as a <type>time_t</type> or -1.
805 *
806 * Since: 0.2.3
807 */
808 time_t
gxps_core_properties_get_created(GXPSCoreProperties * core_props)809 gxps_core_properties_get_created (GXPSCoreProperties *core_props)
810 {
811 g_return_val_if_fail (GXPS_IS_CORE_PROPERTIES (core_props), -1);
812
813 return core_props->priv->created;
814 }
815
816 /**
817 * gxps_core_properties_get_last_modified_by:
818 * @core_props: a #GXPSCoreProperties
819 *
820 * Get the user who performed the last modification.
821 *
822 * Returns: a string containing the user who performed the
823 * last modification or %NULL
824 *
825 * Since: 0.2.3
826 */
827 const gchar *
gxps_core_properties_get_last_modified_by(GXPSCoreProperties * core_props)828 gxps_core_properties_get_last_modified_by (GXPSCoreProperties *core_props)
829 {
830 g_return_val_if_fail (GXPS_IS_CORE_PROPERTIES (core_props), NULL);
831
832 return core_props->priv->last_modified_by;
833 }
834
835 /**
836 * gxps_core_properties_get_modified:
837 * @core_props: a #GXPSCoreProperties
838 *
839 * Get the last modification date.
840 *
841 * Returns: the modification date as a <type>time_t</type> or -1.
842 *
843 * Since: 0.2.3
844 */
845 time_t
gxps_core_properties_get_modified(GXPSCoreProperties * core_props)846 gxps_core_properties_get_modified (GXPSCoreProperties *core_props)
847 {
848 g_return_val_if_fail (GXPS_IS_CORE_PROPERTIES (core_props), -1);
849
850 return core_props->priv->modified;
851 }
852
853 /**
854 * gxps_core_properties_get_last_printed:
855 * @core_props: a #GXPSCoreProperties
856 *
857 * Get the date of the last printing.
858 *
859 * Returns: the date of the last printing as a <type>time_t</type> or -1.
860 *
861 * Since: 0.2.3
862 */
863 time_t
gxps_core_properties_get_last_printed(GXPSCoreProperties * core_props)864 gxps_core_properties_get_last_printed (GXPSCoreProperties *core_props)
865 {
866 g_return_val_if_fail (GXPS_IS_CORE_PROPERTIES (core_props), -1);
867
868 return core_props->priv->last_printed;
869 }
870