1/*
2 * << Haru Free PDF Library >> -- hpdf_namedict.c
3 *
4 * URL: http://libharu.org
5 *
6 * Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
7 * Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
8 *
9 * Permission to use, copy, modify, distribute and sell this software
10 * and its documentation for any purpose is hereby granted without fee,
11 * provided that the above copyright notice appear in all copies and
12 * that both that copyright notice and this permission notice appear
13 * in supporting documentation.
14 * It is provided "as is" without express or implied warranty.
15 *
16 */
17
18#include "hpdf_conf.h"
19#include "hpdf_utils.h"
20#include "hpdf_consts.h"
21#include "hpdf_namedict.h"
22
23#ifndef HPDF_UNUSED
24#define HPDF_UNUSED(a) ((void)(a))
25#endif
26
27static const char * const HPDF_NAMEDICT_KEYS[] = {
28 "EmbeddedFiles"
29 };
30
31HPDF_NameDict
32HPDF_NameDict_New (HPDF_MMgr mmgr,
33 HPDF_Xref xref)
34{
35 HPDF_NameDict ndict;
36
37 HPDF_PTRACE((" HPDF_NameDict_New\n"));
38
39 ndict = HPDF_Dict_New (mmgr);
40 if (!ndict)
41 return NULL;
42
43 if (HPDF_Xref_Add (xref, ndict) != HPDF_OK)
44 return NULL;
45
46 ndict->header.obj_class |= HPDF_OSUBCLASS_NAMEDICT;
47
48 return ndict;
49}
50
51HPDF_NameTree
52HPDF_NameDict_GetNameTree (HPDF_NameDict namedict,
53 HPDF_NameDictKey key)
54{
55 if (!namedict)
56 return NULL;
57 return HPDF_Dict_GetItem (namedict, HPDF_NAMEDICT_KEYS[key], HPDF_OCLASS_DICT);
58}
59
60HPDF_STATUS
61HPDF_NameDict_SetNameTree (HPDF_NameDict namedict,
62 HPDF_NameDictKey key,
63 HPDF_NameTree ntree)
64{
65 return HPDF_Dict_Add (namedict, HPDF_NAMEDICT_KEYS[key], ntree);
66}
67
68HPDF_BOOL
69HPDF_NameDict_Validate (HPDF_NameDict namedict)
70{
71 if (!namedict)
72 return HPDF_FALSE;
73
74 if (namedict->header.obj_class != (HPDF_OSUBCLASS_NAMEDICT |
75 HPDF_OCLASS_DICT)) {
76 HPDF_SetError (namedict->error, HPDF_INVALID_OBJECT, 0);
77 return HPDF_FALSE;
78 }
79
80 return HPDF_TRUE;
81}
82
83
84/*------- NameTree -------*/
85
86HPDF_NameTree
87HPDF_NameTree_New (HPDF_MMgr mmgr,
88 HPDF_Xref xref)
89{
90 HPDF_STATUS ret = HPDF_OK;
91 HPDF_NameTree ntree;
92 HPDF_Array items;
93
94 HPDF_PTRACE((" HPDF_NameTree_New\n"));
95
96 ntree = HPDF_Dict_New (mmgr);
97 if (!ntree)
98 return NULL;
99
100 if (HPDF_Xref_Add (xref, ntree) != HPDF_OK)
101 return NULL;
102
103 ntree->header.obj_class |= HPDF_OSUBCLASS_NAMETREE;
104
105 items = HPDF_Array_New (mmgr);
106 if (!ntree)
107 return NULL;
108
109 ret += HPDF_Dict_Add (ntree, "Names", items);
110 if (ret != HPDF_OK)
111 return NULL;
112
113 return ntree;
114}
115
116HPDF_STATUS
117HPDF_NameTree_Add (HPDF_NameTree tree,
118 HPDF_String name,
119 void *obj)
120{
121 HPDF_Array items;
122 HPDF_INT32 i, icount;
123
124 if (!tree || !name)
125 return HPDF_INVALID_PARAMETER;
126
127 items = HPDF_Dict_GetItem (tree, "Names", HPDF_OCLASS_ARRAY);
128 if (!items)
129 return HPDF_INVALID_OBJECT;
130
131 /* "The keys shall be sorted in lexical order" -- 7.9.6, Name Trees.
132 * Since we store keys sorted, it's best to do a linear insertion sort
133 * Find the first element larger than 'key', and insert 'key' and then
134 * 'obj' into the items. */
135
136 icount = HPDF_Array_Items(items);
137
138 /* If we're larger than the last element, append */
139 if (icount) {
140 HPDF_String last = HPDF_Array_GetItem(items, icount - 2, HPDF_OCLASS_STRING);
141
142 if (HPDF_String_Cmp(name, last) > 0) {
143 HPDF_Array_Add(items, name);
144 HPDF_Array_Add(items, obj);
145 return HPDF_OK;
146 }
147 }
148
149 /* Walk backwards through the list until we're smaller than an element=
150 * That's the element to insert in front of. */
151 for (i = icount - 4; i >= 0; i -= 2) {
152 HPDF_String elem = HPDF_Array_GetItem(items, i, HPDF_OCLASS_STRING);
153
154 if (i == 0 || HPDF_String_Cmp(name, elem) < 0) {
155 HPDF_Array_Insert(items, elem, name);
156 HPDF_Array_Insert(items, elem, obj);
157 return HPDF_OK;
158 }
159 }
160
161 /* Items list is empty */
162 HPDF_Array_Add(items, name);
163 HPDF_Array_Add(items, obj);
164 return HPDF_OK;
165}
166
167HPDF_BOOL
168HPDF_NameTree_Validate (HPDF_NameTree nametree)
169{
170 if (!nametree)
171 return HPDF_FALSE;
172
173 if (nametree->header.obj_class != (HPDF_OSUBCLASS_NAMETREE |
174 HPDF_OCLASS_DICT)) {
175 HPDF_SetError (nametree->error, HPDF_INVALID_OBJECT, 0);
176 return HPDF_FALSE;
177 }
178
179 return HPDF_TRUE;
180}
181
182
183/*------- EmbeddedFile -------*/
184
185HPDF_EmbeddedFile
186HPDF_EmbeddedFile_New (HPDF_MMgr mmgr,
187 HPDF_Xref xref,
188 const char *file)
189{
190 HPDF_STATUS ret = HPDF_OK;
191 HPDF_Dict ef; /* the dictionary for the embedded file: /Type /EF */
192 HPDF_String name; /* the name of the file: /F (name) */
193 HPDF_Dict eff; /* ef has an /EF <<blah>> key - this is it */
194 HPDF_Dict filestream; /* the stream that /EF <</F _ _ R>> refers to */
195 HPDF_Stream stream;
196
197 ef = HPDF_Dict_New (mmgr);
198 if (!ef)
199 return NULL;
200 if (HPDF_Xref_Add (xref, ef) != HPDF_OK)
201 return NULL;
202
203 filestream = HPDF_DictStream_New (mmgr, xref);
204 if (!filestream)
205 return NULL;
206 stream = HPDF_FileReader_New (mmgr, file);
207 if (!stream)
208 return NULL;
209 HPDF_Stream_Free(filestream->stream);
210 filestream->stream = stream;
211 filestream->filter = HPDF_STREAM_FILTER_FLATE_DECODE;
212
213 eff = HPDF_Dict_New (mmgr);
214 if (!eff)
215 return NULL;
216
217 name = HPDF_String_New (mmgr, file, NULL);
218 if (!name)
219 return NULL;
220
221 ret += HPDF_Dict_AddName (ef, "Type", "F");
222 ret += HPDF_Dict_Add (ef, "F", name);
223 ret += HPDF_Dict_Add (ef, "EF", eff);
224 ret += HPDF_Dict_Add (eff, "F", filestream);
225
226 if (ret != HPDF_OK)
227 return NULL;
228
229 return ef;
230}
231
232HPDF_BOOL
233HPDF_EmbeddedFile_Validate (HPDF_EmbeddedFile emfile)
234{
235 HPDF_UNUSED (emfile);
236 return HPDF_TRUE;
237}
238