1/*
2 * Copyright (c) 2005-2007 Rob Braun
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Rob Braun nor the names of his contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29/*
30 * 04-Apr-2005
31 * DRI: Rob Braun <bbraun@synack.net>
32 */
33
34#define _FILE_OFFSET_BITS 64
35
36#include <stdlib.h>
37#include <string.h>
38#include <assert.h>
39#include <libxml/xmlwriter.h>
40#include <libxml/xmlreader.h>
41#include "xar.h"
42#include "subdoc.h"
43#include "archive.h"
44#include "filetree.h"
45
46xar_subdoc_t xar_subdoc_new(xar_t x, const char *name) {
47	xar_subdoc_t ret;
48
49	if( xar_subdoc_find(x, name) )
50		return NULL;
51
52	ret = malloc(sizeof(struct __xar_subdoc_t));
53	if( ! ret )
54		return NULL;
55
56	memset(XAR_SUBDOC(ret), 0, sizeof(struct __xar_subdoc_t));
57	XAR_SUBDOC(ret)->name = strdup(name);
58	XAR_SUBDOC(ret)->next = XAR_SUBDOC(XAR(x)->subdocs);
59	XAR(x)->subdocs = ret;
60	XAR_SUBDOC(ret)->x = x;
61
62	return ret;
63}
64
65int32_t xar_subdoc_prop_set(xar_subdoc_t s, const char *key, const char *value){
66	return xar_prop_set((xar_file_t)s, key, value);
67}
68
69int32_t xar_subdoc_prop_get(xar_subdoc_t s, const char *key, const char **value) {
70	return xar_prop_get((xar_file_t)s, key, value);
71}
72
73int32_t xar_subdoc_attr_set(xar_subdoc_t s, const char *prop, const char *key, const char *value){
74	return xar_attr_set((xar_file_t)s, prop, key, value);
75}
76
77const char *xar_subdoc_attr_get(xar_subdoc_t s, const char *prop, const char *key) {
78	return xar_attr_get((xar_file_t)s, prop, key);
79}
80
81xar_subdoc_t xar_subdoc_first(xar_t x) {
82	return XAR(x)->subdocs;
83}
84
85xar_subdoc_t xar_subdoc_next(xar_subdoc_t s) {
86	return XAR_SUBDOC(s)->next;
87}
88
89const char *xar_subdoc_name(xar_subdoc_t s) {
90	return XAR_SUBDOC(s)->name;
91}
92
93xar_subdoc_t xar_subdoc_find(xar_t x, const char *name)
94{
95	xar_subdoc_t i;
96
97	for(i = XAR(x)->subdocs; i; i = XAR_SUBDOC(i)->next) {
98		if( strcmp(name, XAR_SUBDOC(i)->name) == 0 )
99			return i;
100	}
101
102	return NULL;
103}
104
105int32_t xar_subdoc_copyout(xar_subdoc_t s, unsigned char **ret, unsigned int *size) {
106	xmlBufferPtr buf;
107	xmlTextWriterPtr writer;
108
109	buf = xmlBufferCreate();
110	if( !buf )
111		return -1;
112
113	writer = xmlNewTextWriterMemory(buf, 0);
114	if( !writer ) {
115		xmlBufferFree(buf);
116		return -1;
117	}
118
119	xmlTextWriterSetIndent(writer, 4);
120	xar_subdoc_serialize(s, writer, 0);
121
122	xmlTextWriterEndDocument(writer);
123	xmlFreeTextWriter(writer);
124
125	if( size != NULL )
126		*size = buf->use;
127	*ret = malloc(buf->size);
128	if( *ret == NULL ) {
129		xmlBufferFree(buf);
130		return -1;
131	}
132
133	assert(size != NULL);
134	memcpy(*ret, buf->content, *size);
135	xmlBufferFree(buf);
136	return 0;
137}
138
139int32_t xar_subdoc_copyin(xar_subdoc_t s, const unsigned char *buf, unsigned int len) {
140	xmlTextReaderPtr reader;
141
142	reader = xmlReaderForMemory((const char *)buf, len, NULL, NULL, 0);
143	if( !reader )
144		return -1;
145
146	xar_subdoc_unserialize(s, reader);
147	xmlFreeTextReader(reader);
148	return 0;
149}
150
151/* xar_subdoc_serialize
152 * s: a subdoc structure allocated and initialized by xar_subdoc_new()
153 * writer: and xmlTextWriterPtr that has already been opend and initialized
154 * and is pointing to the place where the subdocument will be serialized.
155 * wrap: an integer describing whether the subdocument is to be wrapped
156 * for placement in the xml header of an archive, or if we are trying to
157 * reconstruct the original document.  1 for wrapping, 0 for original.
158 */
159void xar_subdoc_serialize(xar_subdoc_t s, xmlTextWriterPtr writer, int wrap) {
160	if( !s ) return;
161	if( wrap ) {
162		xmlTextWriterStartElementNS(writer, BAD_CAST(XAR_SUBDOC(s)->prefix), BAD_CAST("subdoc"), BAD_CAST(XAR_SUBDOC(s)->ns));
163		xmlTextWriterWriteAttribute(writer, BAD_CAST("subdoc_name"), BAD_CAST(XAR_SUBDOC(s)->name));
164		if( XAR_SUBDOC(s)->value )
165			xmlTextWriterWriteString(writer, BAD_CAST(XAR_SUBDOC(s)->value));
166	}
167	xar_prop_serialize(XAR_SUBDOC(s)->props, writer);
168	xmlTextWriterEndElement(writer);
169}
170
171void xar_subdoc_remove(xar_subdoc_t s) {
172	xar_prop_t p;
173	xar_subdoc_t tmp = xar_subdoc_first(XAR_SUBDOC(s)->x);
174
175	if( tmp == s ) {
176		XAR(XAR_SUBDOC(s)->x)->subdocs = XAR_SUBDOC(s)->next;
177	} else {
178		while(XAR_SUBDOC(tmp)->next) {
179			if( XAR_SUBDOC(tmp)->next == s ) {
180				XAR_SUBDOC(tmp)->next = XAR_SUBDOC(s)->next;
181				break;
182			}
183			tmp = xar_subdoc_next(tmp);
184		}
185	}
186
187	while(XAR_SUBDOC(s)->props) {
188		p = XAR_SUBDOC(s)->props;
189		XAR_SUBDOC(s)->props = XAR_PROP(XAR_PROP(p)->next);
190		xar_prop_free(p);
191	}
192	free((char *)XAR_SUBDOC(s)->blank1);
193	free((char *)XAR_SUBDOC(s)->name);
194	free((void *)s);
195	return;
196}
197
198void xar_subdoc_unserialize(xar_subdoc_t s, xmlTextReaderPtr reader) {
199	int type;
200
201	while( xmlTextReaderRead(reader) == 1 ) {
202		type = xmlTextReaderNodeType(reader);
203		if( type == XML_READER_TYPE_ELEMENT ) {
204			xar_prop_unserialize((xar_file_t)s, NULL, reader);
205		}
206		if( type == XML_READER_TYPE_TEXT ) {
207			const char *value;
208			value = (const char *)xmlTextReaderConstValue(reader);
209			free((char*)XAR_SUBDOC(s)->value);
210			XAR_SUBDOC(s)->value = strdup(value);
211		}
212		if( type == XML_READER_TYPE_END_ELEMENT ) {
213			break;
214		}
215	}
216
217	return;
218}
219