2024-02-26 18:47:32 +00:00

295 lines
6.7 KiB
C

/*****************************************************************************
* core - A library for creating Excel XLSX core files.
*
* Used in conjunction with the libxlsxwriter library.
*
* SPDX-License-Identifier: BSD-2-Clause
* Copyright 2014-2024, John McNamara, jmcnamara@cpan.org.
*
*/
#include "xlsxwriter/xmlwriter.h"
#include "xlsxwriter/core.h"
#include "xlsxwriter/utility.h"
/*
* Forward declarations.
*/
/*****************************************************************************
*
* Private functions.
*
****************************************************************************/
/*
* Create a new core object.
*/
lxw_core *
lxw_core_new(void)
{
lxw_core *core = calloc(1, sizeof(lxw_core));
GOTO_LABEL_ON_MEM_ERROR(core, mem_error);
return core;
mem_error:
lxw_core_free(core);
return NULL;
}
/*
* Free a core object.
*/
void
lxw_core_free(lxw_core *core)
{
if (!core)
return;
free(core);
}
/*
* Convert a time_t to a ISO 8601 style "2010-01-01T00:00:00Z" date.
*/
static void
_datetime_to_iso8601_date(time_t *timer, char *str, size_t size)
{
struct tm *tmp_datetime;
time_t current_time = time(NULL);
if (*timer)
tmp_datetime = gmtime(timer);
else
tmp_datetime = gmtime(&current_time);
strftime(str, size - 1, "%Y-%m-%dT%H:%M:%SZ", tmp_datetime);
}
/*****************************************************************************
*
* XML functions.
*
****************************************************************************/
/*
* Write the XML declaration.
*/
STATIC void
_core_xml_declaration(lxw_core *self)
{
lxw_xml_declaration(self->file);
}
/*
* Write the <cp:coreProperties> element.
*/
STATIC void
_write_cp_core_properties(lxw_core *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xmlns:cp",
"http://schemas.openxmlformats.org/package/2006/metadata/core-properties");
LXW_PUSH_ATTRIBUTES_STR("xmlns:dc", "http://purl.org/dc/elements/1.1/");
LXW_PUSH_ATTRIBUTES_STR("xmlns:dcterms", "http://purl.org/dc/terms/");
LXW_PUSH_ATTRIBUTES_STR("xmlns:dcmitype", "http://purl.org/dc/dcmitype/");
LXW_PUSH_ATTRIBUTES_STR("xmlns:xsi",
"http://www.w3.org/2001/XMLSchema-instance");
lxw_xml_start_tag(self->file, "cp:coreProperties", &attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <dc:creator> element.
*/
STATIC void
_write_dc_creator(lxw_core *self)
{
if (self->properties->author) {
lxw_xml_data_element(self->file, "dc:creator",
self->properties->author, NULL);
}
else {
lxw_xml_data_element(self->file, "dc:creator", "", NULL);
}
}
/*
* Write the <cp:lastModifiedBy> element.
*/
STATIC void
_write_cp_last_modified_by(lxw_core *self)
{
if (self->properties->author) {
lxw_xml_data_element(self->file, "cp:lastModifiedBy",
self->properties->author, NULL);
}
else {
lxw_xml_data_element(self->file, "cp:lastModifiedBy", "", NULL);
}
}
/*
* Write the <dcterms:created> element.
*/
STATIC void
_write_dcterms_created(lxw_core *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char datetime[LXW_ATTR_32];
_datetime_to_iso8601_date(&self->properties->created, datetime,
LXW_ATTR_32);
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xsi:type", "dcterms:W3CDTF");
lxw_xml_data_element(self->file, "dcterms:created", datetime,
&attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <dcterms:modified> element.
*/
STATIC void
_write_dcterms_modified(lxw_core *self)
{
struct xml_attribute_list attributes;
struct xml_attribute *attribute;
char datetime[LXW_ATTR_32];
_datetime_to_iso8601_date(&self->properties->created, datetime,
LXW_ATTR_32);
LXW_INIT_ATTRIBUTES();
LXW_PUSH_ATTRIBUTES_STR("xsi:type", "dcterms:W3CDTF");
lxw_xml_data_element(self->file, "dcterms:modified", datetime,
&attributes);
LXW_FREE_ATTRIBUTES();
}
/*
* Write the <dc:title> element.
*/
STATIC void
_write_dc_title(lxw_core *self)
{
if (!self->properties->title)
return;
lxw_xml_data_element(self->file, "dc:title", self->properties->title,
NULL);
}
/*
* Write the <dc:subject> element.
*/
STATIC void
_write_dc_subject(lxw_core *self)
{
if (!self->properties->subject)
return;
lxw_xml_data_element(self->file, "dc:subject", self->properties->subject,
NULL);
}
/*
* Write the <cp:keywords> element.
*/
STATIC void
_write_cp_keywords(lxw_core *self)
{
if (!self->properties->keywords)
return;
lxw_xml_data_element(self->file, "cp:keywords",
self->properties->keywords, NULL);
}
/*
* Write the <dc:description> element.
*/
STATIC void
_write_dc_description(lxw_core *self)
{
if (!self->properties->comments)
return;
lxw_xml_data_element(self->file, "dc:description",
self->properties->comments, NULL);
}
/*
* Write the <cp:category> element.
*/
STATIC void
_write_cp_category(lxw_core *self)
{
if (!self->properties->category)
return;
lxw_xml_data_element(self->file, "cp:category",
self->properties->category, NULL);
}
/*
* Write the <cp:contentStatus> element.
*/
STATIC void
_write_cp_content_status(lxw_core *self)
{
if (!self->properties->status)
return;
lxw_xml_data_element(self->file, "cp:contentStatus",
self->properties->status, NULL);
}
/*****************************************************************************
*
* XML file assembly functions.
*
****************************************************************************/
/*
* Assemble and write the XML file.
*/
void
lxw_core_assemble_xml_file(lxw_core *self)
{
/* Write the XML declaration. */
_core_xml_declaration(self);
_write_cp_core_properties(self);
_write_dc_title(self);
_write_dc_subject(self);
_write_dc_creator(self);
_write_cp_keywords(self);
_write_dc_description(self);
_write_cp_last_modified_by(self);
_write_dcterms_created(self);
_write_dcterms_modified(self);
_write_cp_category(self);
_write_cp_content_status(self);
lxw_xml_end_tag(self->file, "cp:coreProperties");
}
/*****************************************************************************
*
* Public functions.
*
****************************************************************************/