/src/ebook-tools-0.2.2/src/libepub/epub.c
Line | Count | Source |
1 | | #include "epub.h" |
2 | | #include "epublib.h" |
3 | | #include <stdarg.h> |
4 | | |
5 | | const char _epub_error_oom[] = "out of memory"; |
6 | | |
7 | 9.04k | struct epub *epub_open(const char *filename, int debug) { |
8 | 9.04k | char *opfName = NULL; |
9 | 9.04k | char *opfStr = NULL; |
10 | 9.04k | char *pathsep_index = NULL; |
11 | | |
12 | 9.04k | struct epub *epub = malloc(sizeof(struct epub)); |
13 | 9.04k | if (! epub) { |
14 | 0 | return NULL; |
15 | 0 | } |
16 | 9.04k | epub->ocf = NULL; |
17 | 9.04k | epub->opf = NULL; |
18 | 9.04k | _epub_err_set_str(&epub->error, "", 0); |
19 | 9.04k | epub->debug = debug; |
20 | 9.04k | _epub_print_debug(epub, DEBUG_INFO, "opening '%s'", filename); |
21 | | |
22 | 9.04k | LIBXML_TEST_VERSION; |
23 | | |
24 | 9.04k | if (! (epub->ocf = _ocf_parse(epub, filename))) { |
25 | 3.84k | epub_close(epub); |
26 | 3.84k | return NULL; |
27 | 3.84k | } |
28 | | |
29 | 5.20k | opfName = _ocf_root_fullpath_by_type(epub->ocf, |
30 | 5.20k | "application/oebps-package+xml"); |
31 | 5.20k | if (!opfName) { |
32 | 3.42k | epub_close(epub); |
33 | 3.42k | return NULL; |
34 | 3.42k | } |
35 | | |
36 | 1.78k | epub->ocf->datapath = malloc(sizeof(char) *(strlen(opfName) +1)); |
37 | 1.78k | pathsep_index = strrchr(opfName, '/'); // '/' is per OCF specs |
38 | 1.78k | if (pathsep_index) { |
39 | 1.77k | strncpy(epub->ocf->datapath, opfName, pathsep_index + 1 - opfName); |
40 | 1.77k | epub->ocf->datapath[pathsep_index - opfName + 1] = 0; |
41 | 1.77k | } |
42 | 10 | else { |
43 | 10 | epub->ocf->datapath[0] = 0; |
44 | 10 | } |
45 | | |
46 | 1.78k | _epub_print_debug(epub, DEBUG_INFO, "data path is %s", epub->ocf->datapath ); |
47 | | |
48 | 1.78k | _ocf_get_file(epub->ocf, opfName, &opfStr); |
49 | 1.78k | free(opfName); |
50 | | |
51 | | |
52 | 1.78k | if (!opfStr) { |
53 | 51 | epub_close(epub); |
54 | 51 | return NULL; |
55 | 51 | } |
56 | | |
57 | 1.73k | epub->opf = _opf_parse(epub, opfStr); |
58 | 1.73k | if (!epub->opf) { |
59 | 1.21k | free(opfStr); |
60 | 1.21k | epub_close(epub); |
61 | 1.21k | return NULL; |
62 | 1.21k | } |
63 | | |
64 | 516 | free(opfStr); |
65 | | |
66 | 516 | return epub; |
67 | 1.73k | } |
68 | | |
69 | 1.94k | xmlChar *_getXmlStr(void *str) { |
70 | 1.94k | return xmlStrdup((xmlChar *)str); |
71 | 1.94k | } |
72 | | |
73 | 0 | xmlChar *_getIdStr(void *id) { |
74 | 0 | struct id *data = (struct id *)id; |
75 | 0 | xmlChar buff[10000]; |
76 | |
|
77 | 0 | xmlStrPrintf(buff, 10000, (xmlChar *)"%s (%s:%s)", |
78 | 0 | ((data->scheme)?data->scheme:(xmlChar *)"Unspecified"), |
79 | 0 | (data->id?data->id:(xmlChar *)"Unspecified"), |
80 | 0 | data->string); |
81 | | |
82 | 0 | return xmlStrdup(buff); |
83 | 0 | } |
84 | | |
85 | 557 | xmlChar *_getDateStr(void *date) { |
86 | 557 | struct date *data = (struct date *)date; |
87 | 557 | xmlChar buff[10000]; |
88 | | |
89 | 557 | xmlStrPrintf(buff, 10000, (xmlChar *)"%s: %s", |
90 | 557 | ((data->event)?data->event:(xmlChar *)"Unspecified"), |
91 | 557 | data->date); |
92 | | |
93 | 557 | return xmlStrdup(buff); |
94 | 557 | } |
95 | | |
96 | 0 | xmlChar *_getMetaStr(void *meta) { |
97 | 0 | struct meta *data = (struct meta *)meta; |
98 | 0 | xmlChar buff[10000]; |
99 | |
|
100 | 0 | xmlStrPrintf(buff, 10000, (xmlChar *)"%s: %s", |
101 | 0 | ((data->name)?data->name:(xmlChar *)"Unspecified"), |
102 | 0 | ((data->content)?data->content:(xmlChar *)"Unspecified")); |
103 | | |
104 | 0 | return xmlStrdup(buff); |
105 | 0 | } |
106 | | |
107 | 558 | xmlChar *_getRoleStr(void *creator) { |
108 | 558 | struct creator *data = (struct creator *)creator; |
109 | 558 | xmlChar buff[10000]; |
110 | 558 | xmlStrPrintf(buff, 10000, (xmlChar *)"%s: %s(%s)", |
111 | 558 | ((data->role)?data->role:(xmlChar *)"Author"), |
112 | 558 | data->name, ((data->fileAs)?data->fileAs:data->name)); |
113 | | |
114 | 558 | return xmlStrdup(buff); |
115 | 558 | } |
116 | | |
117 | | xmlChar **epub_get_metadata(struct epub *epub, enum epub_metadata type, |
118 | 3.09k | int *size) { |
119 | 3.09k | xmlChar **data = NULL; |
120 | 3.09k | listPtr list = NULL; |
121 | 3.09k | xmlChar *(*getStr)(void *) = NULL; |
122 | 3.09k | int i; |
123 | | |
124 | 3.09k | if (!epub || !epub->opf || !epub->opf->metadata) { |
125 | 48 | _epub_print_debug(epub, DEBUG_INFO, "no metadata information available"); |
126 | 48 | return NULL; |
127 | 48 | } |
128 | | |
129 | 3.04k | switch(type) { |
130 | 0 | case EPUB_ID: |
131 | 0 | list = epub->opf->metadata->id; |
132 | 0 | getStr = _getIdStr; |
133 | 0 | break; |
134 | 508 | case EPUB_TITLE: |
135 | 508 | list = epub->opf->metadata->title; |
136 | 508 | getStr = _getXmlStr; |
137 | 508 | break; |
138 | 508 | case EPUB_SUBJECT: |
139 | 508 | list = epub->opf->metadata->subject; |
140 | 508 | getStr = _getXmlStr; |
141 | 508 | break; |
142 | 508 | case EPUB_PUBLISHER: |
143 | 508 | list = epub->opf->metadata->publisher; |
144 | 508 | getStr = _getXmlStr; |
145 | 508 | break; |
146 | 508 | case EPUB_DESCRIPTION: |
147 | 508 | list = epub->opf->metadata->description; |
148 | 508 | getStr = _getXmlStr; |
149 | 508 | break; |
150 | 508 | case EPUB_DATE: |
151 | 508 | list = epub->opf->metadata->date; |
152 | 508 | getStr = _getDateStr; |
153 | 508 | break; |
154 | 0 | case EPUB_TYPE: |
155 | 0 | list = epub->opf->metadata->type; |
156 | 0 | getStr = _getXmlStr; |
157 | 0 | break; |
158 | 0 | case EPUB_FORMAT: |
159 | 0 | list = epub->opf->metadata->format; |
160 | 0 | getStr = _getXmlStr; |
161 | 0 | break; |
162 | 0 | case EPUB_SOURCE: |
163 | 0 | list = epub->opf->metadata->source; |
164 | 0 | getStr = _getXmlStr; |
165 | 0 | break; |
166 | 0 | case EPUB_LANG: |
167 | 0 | list = epub->opf->metadata->lang; |
168 | 0 | getStr = _getXmlStr; |
169 | 0 | break; |
170 | 0 | case EPUB_RELATION: |
171 | 0 | list = epub->opf->metadata->relation; |
172 | 0 | getStr = _getXmlStr; |
173 | 0 | break; |
174 | 0 | case EPUB_COVERAGE: |
175 | 0 | list = epub->opf->metadata->coverage; |
176 | 0 | getStr = _getXmlStr; |
177 | 0 | break; |
178 | 0 | case EPUB_RIGHTS: |
179 | 0 | list = epub->opf->metadata->rights; |
180 | 0 | getStr = _getXmlStr; |
181 | 0 | break; |
182 | 508 | case EPUB_CREATOR: |
183 | 508 | list = epub->opf->metadata->creator; |
184 | 508 | getStr = _getRoleStr; |
185 | 508 | break; |
186 | 0 | case EPUB_CONTRIB: |
187 | 0 | list = epub->opf->metadata->contrib; |
188 | 0 | getStr = _getRoleStr; |
189 | 0 | break; |
190 | 0 | case EPUB_META: |
191 | 0 | list = epub->opf->metadata->meta; |
192 | 0 | getStr = _getMetaStr; |
193 | 0 | break; |
194 | 0 | default: |
195 | 0 | _epub_print_debug(epub, DEBUG_INFO, "fetching metadata: unknown type %d", type); |
196 | 0 | return NULL; |
197 | 3.04k | } |
198 | | |
199 | 3.04k | if (list->Size <= 0) |
200 | 236 | return NULL; |
201 | | |
202 | 2.81k | data = malloc(list->Size * sizeof(xmlChar *)); |
203 | 2.81k | if (! data) { |
204 | 0 | _epub_err_set_oom(&epub->error); |
205 | 0 | return NULL; |
206 | 0 | } |
207 | 2.81k | if (size) { |
208 | 2.81k | *size = list->Size; |
209 | 2.81k | } |
210 | 2.81k | list->Current = list->Head; |
211 | | |
212 | 2.81k | data[0] = getStr(GetNode(list)); |
213 | 3.05k | for (i=1;i<list->Size;i++) { |
214 | 246 | data[i] = getStr(NextNode(list)); |
215 | 246 | } |
216 | | |
217 | 2.81k | return data; |
218 | 2.81k | } |
219 | | |
220 | | // returns the next node that the iterator should return |
221 | | // if init also check if the current node is good |
222 | | // if linear is 0 return non linear else return linear |
223 | 0 | listnodePtr _get_spine_it_next(listnodePtr curr, int linear, int init) { |
224 | 0 | struct spine *node; |
225 | |
|
226 | 0 | if (! curr) |
227 | 0 | return NULL; |
228 | | |
229 | 0 | if ( ! init) { |
230 | 0 | curr = curr->Next; |
231 | 0 | } |
232 | |
|
233 | 0 | node = (struct spine *)GetNodeData(curr); |
234 | | |
235 | 0 | while(curr) { |
236 | 0 | if (! node) |
237 | 0 | return NULL; |
238 | | |
239 | 0 | node = (struct spine *)GetNodeData(curr); |
240 | | |
241 | 0 | if (node->linear == linear) |
242 | 0 | return curr; |
243 | | |
244 | 0 | curr = curr->Next; |
245 | 0 | } |
246 | | |
247 | 0 | return NULL; |
248 | 0 | } |
249 | | |
250 | 1.46k | char *_get_spine_it_url(struct eiterator *it) { |
251 | 1.46k | struct manifest *tmp; |
252 | 1.46k | void *data; |
253 | | |
254 | 1.46k | if (!it) |
255 | 0 | return NULL; |
256 | | |
257 | 1.46k | data = GetNodeData(it->curr); |
258 | 1.46k | tmp = _opf_manifest_get_by_id(it->epub->opf, |
259 | 1.46k | ((struct spine *)data)->idref); |
260 | 1.46k | if (!tmp) { |
261 | 123 | _epub_print_debug(it->epub, DEBUG_ERROR, |
262 | 123 | "spine parsing error idref %s is not in the manifest", |
263 | 123 | ((struct spine *)data)->idref); |
264 | 123 | return NULL; |
265 | 123 | } |
266 | | |
267 | 1.33k | return (char *)tmp->href; |
268 | 1.46k | } |
269 | | |
270 | | struct eiterator *epub_get_iterator(struct epub *epub, |
271 | 516 | enum eiterator_type type, int opt) { |
272 | | |
273 | 516 | struct eiterator *it = NULL; |
274 | | |
275 | 516 | if (!epub) { |
276 | 0 | return NULL; |
277 | 0 | } |
278 | | |
279 | 516 | it = malloc(sizeof(struct eiterator)); |
280 | 516 | if (!it) { |
281 | 0 | _epub_err_set_oom(&epub->error); |
282 | 0 | return NULL; |
283 | 0 | } |
284 | 516 | it->type = type; |
285 | 516 | it->epub = epub; |
286 | 516 | it->opt = opt; |
287 | 516 | it->cache = NULL; |
288 | | |
289 | 516 | switch (type) { |
290 | 516 | case EITERATOR_SPINE: |
291 | 516 | it->curr = epub->opf->spine->Head; |
292 | 516 | break; |
293 | 0 | case EITERATOR_NONLINEAR: |
294 | 0 | it->curr = _get_spine_it_next(epub->opf->spine->Head, 0, 1); |
295 | 0 | break; |
296 | 0 | case EITERATOR_LINEAR: |
297 | 0 | it->curr = _get_spine_it_next(epub->opf->spine->Head, 1, 1); |
298 | 0 | break; |
299 | 516 | } |
300 | | |
301 | | |
302 | 516 | return it; |
303 | 516 | } |
304 | | |
305 | 516 | void epub_free_iterator(struct eiterator *it) { |
306 | 516 | if (!it) { |
307 | 0 | return; |
308 | 0 | } |
309 | | |
310 | 516 | if (it->cache) |
311 | 0 | free(it->cache); |
312 | | |
313 | 516 | free(it); |
314 | 516 | } |
315 | | |
316 | | |
317 | 946 | char *epub_it_get_curr_url(struct eiterator *it) { |
318 | 946 | if (!it) { |
319 | 0 | return NULL; |
320 | 0 | } |
321 | | |
322 | 946 | switch (it->type) { |
323 | 946 | case EITERATOR_SPINE: |
324 | 946 | case EITERATOR_NONLINEAR: |
325 | 946 | case EITERATOR_LINEAR: |
326 | 946 | return _get_spine_it_url(it); |
327 | 946 | } |
328 | | |
329 | 0 | return NULL; |
330 | 946 | } |
331 | | |
332 | 946 | char *epub_it_get_curr(struct eiterator *it) { |
333 | | |
334 | 946 | if (!it || !it->curr) |
335 | 430 | return NULL; |
336 | | |
337 | 516 | if (!it->cache) { |
338 | | |
339 | 516 | switch (it->type) { |
340 | 516 | case EITERATOR_SPINE: |
341 | 516 | case EITERATOR_NONLINEAR: |
342 | 516 | case EITERATOR_LINEAR: |
343 | 516 | _ocf_get_data_file(it->epub->ocf, _get_spine_it_url(it), &(it->cache)); |
344 | 516 | break; |
345 | 516 | } |
346 | 516 | } |
347 | | |
348 | 516 | return it->cache; |
349 | 516 | } |
350 | 946 | char *epub_it_get_next(struct eiterator *it) { |
351 | 946 | if (!it) { |
352 | 0 | return NULL; |
353 | 0 | } |
354 | | |
355 | 946 | if (it->cache) { |
356 | 430 | free(it->cache); |
357 | 430 | it->cache = NULL; |
358 | 430 | } |
359 | | |
360 | 946 | if (!it->curr) |
361 | 0 | return NULL; |
362 | | |
363 | 946 | switch (it->type) { |
364 | | |
365 | 946 | case EITERATOR_SPINE: |
366 | 946 | it->curr = it->curr->Next; |
367 | 946 | break; |
368 | | |
369 | 0 | case EITERATOR_NONLINEAR: |
370 | 0 | it->curr = _get_spine_it_next(it->curr, 0, 0); |
371 | 0 | break; |
372 | | |
373 | 0 | case EITERATOR_LINEAR: |
374 | 0 | it->curr = _get_spine_it_next(it->curr, 1, 0); |
375 | 0 | break; |
376 | 946 | } |
377 | | |
378 | 946 | return epub_it_get_curr(it); |
379 | 946 | } |
380 | | |
381 | 9.04k | int epub_close(struct epub *epub) { |
382 | 9.04k | if (!epub) { |
383 | 0 | return 0; |
384 | 0 | } |
385 | | |
386 | 9.04k | if (epub->ocf) |
387 | 5.20k | _ocf_close(epub->ocf); |
388 | | |
389 | 9.04k | if (epub->opf) |
390 | 516 | _opf_close(epub->opf); |
391 | | |
392 | 9.04k | if (epub) |
393 | 9.04k | free(epub); |
394 | | |
395 | | |
396 | 9.04k | return 1; |
397 | 9.04k | } |
398 | | |
399 | 0 | void epub_set_debug(struct epub *epub, int debug) { |
400 | 0 | if (!epub) { |
401 | 0 | return; |
402 | 0 | } |
403 | | |
404 | 0 | epub->debug = debug; |
405 | 0 | } |
406 | | |
407 | 88.8k | void _epub_print_debug(struct epub *epub, int debug, const char *format, ...) { |
408 | 88.8k | va_list ap; |
409 | 88.8k | char strerr[1025]; |
410 | | |
411 | 88.8k | va_start(ap, format); |
412 | | |
413 | 88.8k | vsnprintf(strerr, 1024, format, ap); |
414 | 88.8k | strerr[1024] = 0; |
415 | | |
416 | 88.8k | if (epub && (debug == DEBUG_ERROR)) { |
417 | 6.88k | _epub_err_set_str(&epub->error, strerr, strlen(strerr)); |
418 | 6.88k | } |
419 | | |
420 | 88.8k | if (! epub || (epub->debug >= debug)) { |
421 | 6.88k | fprintf(stderr, "libepub "); |
422 | 6.88k | switch(debug) { |
423 | 6.88k | case DEBUG_ERROR: |
424 | | |
425 | 6.88k | fprintf(stderr, "(EE)"); |
426 | 6.88k | break; |
427 | 0 | case DEBUG_WARNING: |
428 | 0 | fprintf(stderr, "(WW)"); |
429 | 0 | break; |
430 | 0 | case DEBUG_INFO: |
431 | 0 | fprintf(stderr, "(II)"); |
432 | 0 | break; |
433 | 0 | case DEBUG_VERBOSE: |
434 | 0 | fprintf(stderr, "(VV)"); |
435 | 0 | break; |
436 | 6.88k | } |
437 | 6.88k | fprintf(stderr, ": \t%s\n" , strerr); |
438 | 6.88k | } |
439 | 88.8k | va_end(ap); |
440 | 88.8k | } |
441 | | |
442 | 967 | int epub_tit_next(struct titerator *tit) { |
443 | 967 | listnodePtr curr = NULL; |
444 | | |
445 | 967 | if (!tit) { |
446 | 0 | return 0; |
447 | 0 | } |
448 | | |
449 | 967 | curr = tit->next; |
450 | 967 | if (! curr) { |
451 | 503 | tit->valid = 0; |
452 | 503 | return 0; |
453 | 503 | } |
454 | | |
455 | 464 | tit->next = curr->Next; |
456 | | |
457 | 464 | switch (tit->type) { |
458 | 0 | struct guide* guide; |
459 | 0 | struct tocItem *ti; |
460 | | |
461 | 452 | case TITERATOR_GUIDE: |
462 | 452 | guide = GetNodeData(curr); |
463 | 452 | tit->cache.label = (char *)guide->title; |
464 | 452 | tit->cache.link = (char *)guide->href; |
465 | 452 | tit->cache.depth = 1; |
466 | | |
467 | 452 | break; |
468 | | |
469 | 12 | case TITERATOR_NAVMAP: |
470 | 12 | case TITERATOR_PAGES: |
471 | 12 | ti = GetNodeData(curr); |
472 | 12 | tit->cache.label = |
473 | 12 | (char *)_opf_label_get_by_doc_lang(tit->epub->opf, ti->label); |
474 | | |
475 | 12 | if (! tit->cache.label) |
476 | 0 | tit->cache.label = (char *)ti->id; |
477 | | |
478 | 12 | tit->cache.depth = ti->depth; |
479 | 12 | tit->cache.link = (char *)ti->src; |
480 | 12 | break; |
481 | | |
482 | 464 | } |
483 | | |
484 | 464 | tit->valid = 1; |
485 | 464 | return 1; |
486 | 464 | } |
487 | | |
488 | | struct titerator *epub_get_titerator(struct epub *epub, |
489 | 981 | enum titerator_type type, int opt) { |
490 | 981 | struct titerator *it = NULL; |
491 | | |
492 | 981 | if (!epub) { |
493 | 0 | return NULL; |
494 | 0 | } |
495 | | |
496 | 981 | switch (type) { |
497 | 516 | case TITERATOR_NAVMAP: |
498 | 516 | if (! epub->opf->toc || ! epub->opf->toc->navMap) |
499 | 465 | return NULL; |
500 | 51 | break; |
501 | 465 | case TITERATOR_GUIDE: |
502 | 465 | if (! epub->opf->guide) |
503 | 13 | return NULL; |
504 | 452 | break; |
505 | 452 | case TITERATOR_PAGES: |
506 | 0 | if (! epub->opf->toc || epub->opf->toc->pageList) |
507 | 0 | return NULL; |
508 | 0 | break; |
509 | 981 | } |
510 | | |
511 | 503 | it = malloc(sizeof(struct titerator)); |
512 | 503 | if (!it) { |
513 | 0 | _epub_err_set_oom(&epub->error); |
514 | 0 | return NULL; |
515 | 0 | } |
516 | 503 | it->type = type; |
517 | 503 | it->epub = epub; |
518 | 503 | it->opt = opt; |
519 | 503 | it->next = NULL; |
520 | 503 | it->valid = 0; |
521 | | |
522 | 503 | it->cache.label = NULL; |
523 | 503 | it->cache.link = NULL; |
524 | 503 | it->cache.depth = -1; |
525 | | |
526 | | |
527 | 503 | switch (type) { |
528 | 51 | case TITERATOR_NAVMAP: |
529 | 51 | it->next = epub->opf->toc->navMap->items->Head; |
530 | 51 | if (epub->opf->toc->navMap->label) { |
531 | 51 | it->cache.label = |
532 | 51 | (char *)_opf_label_get_by_doc_lang(epub->opf, |
533 | 51 | epub->opf->toc->navMap->label); |
534 | 51 | it->cache.depth = 0; |
535 | 51 | } |
536 | 51 | it->valid = 1; |
537 | 51 | break; |
538 | | |
539 | 452 | case TITERATOR_GUIDE: |
540 | 452 | it->next = epub->opf->guide->Head; |
541 | 452 | break; |
542 | | |
543 | 0 | case TITERATOR_PAGES: |
544 | 0 | it->next = epub->opf->toc->pageList->items->Head; |
545 | 0 | if (epub->opf->toc->pageList->label) { |
546 | 0 | it->cache.label = |
547 | 0 | (char *)_opf_label_get_by_doc_lang(epub->opf, |
548 | 0 | epub->opf->toc->pageList->label); |
549 | 0 | it->cache.depth = 1; |
550 | 0 | } |
551 | 0 | it->valid = 1; |
552 | 0 | break; |
553 | 503 | } |
554 | | |
555 | 503 | if ( ! it->cache.label) |
556 | 503 | epub_tit_next(it); |
557 | | |
558 | 503 | return it; |
559 | 503 | } |
560 | | |
561 | 503 | int epub_tit_curr_valid(struct titerator *tit) { |
562 | 503 | if (!tit) { |
563 | 0 | return 0; |
564 | 0 | } |
565 | | |
566 | 503 | return tit->valid; |
567 | 503 | } |
568 | | |
569 | 0 | char *epub_tit_get_curr_label(struct titerator *tit) { |
570 | 0 | if (!tit) { |
571 | 0 | return NULL; |
572 | 0 | } |
573 | | |
574 | | // FIXME how can there be unlabeled curr? |
575 | 0 | return tit->cache.label?strdup(tit->cache.label):NULL; |
576 | 0 | } |
577 | | |
578 | 0 | int epub_tit_get_curr_depth(struct titerator *tit) { |
579 | 0 | if (!tit) { |
580 | 0 | return 0; |
581 | 0 | } |
582 | | |
583 | 0 | return tit->cache.depth; |
584 | 0 | } |
585 | | |
586 | 464 | char *epub_tit_get_curr_link(struct titerator *tit) { |
587 | 464 | if (!tit) { |
588 | 0 | return NULL; |
589 | 0 | } |
590 | | |
591 | 464 | if (!tit->cache.link) { |
592 | 20 | return NULL; |
593 | 20 | } |
594 | | |
595 | 444 | return strdup(tit->cache.link); |
596 | | |
597 | 464 | } |
598 | | |
599 | 503 | void epub_free_titerator(struct titerator *tit) { |
600 | 503 | if (!tit) { |
601 | 0 | return; |
602 | 0 | } |
603 | | |
604 | 503 | free(tit); |
605 | 503 | } |
606 | | |
607 | 0 | int epub_get_ocf_file(struct epub *epub, const char *filename, char **data) { |
608 | 0 | if (!epub) { |
609 | 0 | return -1; |
610 | 0 | } |
611 | | |
612 | 0 | return _ocf_get_file(epub->ocf, filename, data); |
613 | 0 | } |
614 | | |
615 | 1.33k | int epub_get_data(struct epub *epub, const char *name, char **data) { |
616 | 1.33k | if (!epub) { |
617 | 0 | return -1; |
618 | 0 | } |
619 | | |
620 | 1.33k | return _ocf_get_data_file(epub->ocf, name, data); |
621 | 1.33k | } |
622 | | |
623 | 0 | void epub_dump(struct epub *epub) { |
624 | 0 | if (!epub) { |
625 | 0 | return; |
626 | 0 | } |
627 | | |
628 | 0 | _ocf_dump(epub->ocf); |
629 | 0 | _opf_dump(epub->opf); |
630 | 0 | } |
631 | | |
632 | 0 | void epub_cleanup() { |
633 | 0 | xmlCleanupParser(); |
634 | 0 | } |
635 | | |
636 | 0 | char *epub_last_errStr(struct epub *epub) { |
637 | 0 | char *res = NULL; |
638 | |
|
639 | 0 | if (!epub) { |
640 | 0 | return NULL; |
641 | 0 | } |
642 | | |
643 | 0 | switch (epub->error.type) { |
644 | 0 | case 0: |
645 | 0 | res = malloc(epub->error.len + 1); |
646 | 0 | if (!res) { |
647 | 0 | _epub_err_set_oom(&epub->error); |
648 | 0 | return NULL; |
649 | 0 | } |
650 | 0 | strncpy(res, epub->error.lastStr, epub->error.len); |
651 | 0 | res[epub->error.len] = 0; |
652 | 0 | break; |
653 | 0 | case 1: |
654 | 0 | res = strdup(epub->error.str); |
655 | 0 | if (!res) { |
656 | 0 | _epub_err_set_oom(&epub->error); |
657 | 0 | return NULL; |
658 | 0 | } |
659 | 0 | break; |
660 | 0 | } |
661 | | |
662 | 0 | return res; |
663 | 0 | } |
664 | | |