| verzia 1.20, 2002/12/23 02:40:05 |
verzia 1.21, 2003/02/11 20:10:30 |
|
|
| #include <sys/types.h> |
#include <sys/types.h> |
| #include <unistd.h> |
#include <unistd.h> |
| #include <assert.h> |
#include <assert.h> |
| |
#include <ctype.h> |
| |
|
| #include "cpdf.h" |
#include "cpdf.h" |
| #include "parse.h" |
#include "parse.h" |
| Riadok 93 char **array(char *buffer) |
|
| Riadok 94 char **array(char *buffer) |
|
| int index = 0, len, end = 0; |
int index = 0, len, end = 0; |
| last = buffer + 1; |
last = buffer + 1; |
| do { |
do { |
| ret = |
ret = (char **) realloc(ret, (index + 1) << 2); |
| (char **) realloc(ret, (index + 1) * sizeof(char **)); |
|
| if (*buffer == '[' || *buffer == ']') { |
if (*buffer == '[' || *buffer == ']') { |
| if (*buffer == '[') { |
if (*buffer == '[') { |
| ret[index] = &delim[0]; |
ret[index] = &delim[0]; |
| Riadok 135 char *read_obj(long offset) |
|
| Riadok 135 char *read_obj(long offset) |
|
| char entry[BUFLEN], *obj = NULL; |
char entry[BUFLEN], *obj = NULL; |
| int size = 0; |
int size = 0; |
| fseek(fp, offset, SEEK_SET); |
fseek(fp, offset, SEEK_SET); |
| memset(entry, '\0', BUFLEN); |
|
| fget(entry, BUFLEN, fp); |
fget(entry, BUFLEN, fp); |
| do { |
do { |
| fget(entry, BUFLEN, fp); |
fget(entry, BUFLEN, fp); |
| /* stream need special care in reading */ |
|
| if (strstr(entry, "stream")) { |
|
| char *p; |
|
| int len; |
|
| long off; |
|
| obj = resize(obj, size + strlen(entry)); |
|
| strncpy(obj + size, entry, strlen(entry) + 1); |
|
| size += strlen(entry); |
|
| p = strstr(obj, "Length"); |
|
| sscanf(p, "Length %d", &len); |
|
| for (p += 6; *p != '/'; p++) |
|
| if (!strncmp(p, "0 R", 3)) { |
|
| off = ftell(fp); |
|
| p = (char *) get_object(len, NULL); |
|
| sscanf(p, "%d\nendobj", &len); |
|
| fseek(fp, off, SEEK_SET); |
|
| break; |
|
| } |
|
| len += sizeof("endstream"); |
|
| size += len; |
|
| obj = resize(obj, size); |
|
| fread(obj + strlen(obj), sizeof(char), len, fp); |
|
| continue; |
|
| } |
|
| if (strstr(entry, "endobj")) |
if (strstr(entry, "endobj")) |
| break; |
break; |
| obj = resize(obj, size + strlen(entry)); |
obj = resize(obj, size + strlen(entry)); |
| strncpy(obj + size, entry, strlen(entry)); |
strncpy(obj + size, entry, strlen(entry)); |
| size += strlen(entry); |
size += strlen(entry); |
| |
/* stream need special care in reading */ |
| |
if (strstr(entry, "stream")) { |
| |
while (1) { |
| |
size++; |
| |
obj = resize(obj, size); |
| |
if ((obj[size - 1] = fgetc(fp)) == 'e') { |
| |
size += 8; |
| |
obj = resize(obj, size); |
| |
fread(obj + size - 8, 8, |
| |
sizeof(char), fp); |
| |
if (!strncmp |
| |
(obj + size - 8, "ndstream", |
| |
8)) |
| |
break; |
| |
} |
| |
} |
| |
} |
| } while (1); |
} while (1); |
| return obj; |
return obj; |
| } |
} |
| Riadok 197 void *get_object(int num, int *type) |
|
| Riadok 189 void *get_object(int num, int *type) |
|
| { |
{ |
| void *ret = NULL; |
void *ret = NULL; |
| char *dict; |
char *dict; |
| struct object *obj = (struct object *) *(objects + num - 1); |
struct object *obj; |
| |
if(!num || num > obj_count) |
| |
abort(); |
| |
obj = (struct object *) *(objects + num - 1); |
| if (obj->parsed) { |
if (obj->parsed) { |
| if (type) |
if (type) |
| *type = obj->type; |
*type = obj->type; |
| Riadok 207 void *get_object(int num, int *type) |
|
| Riadok 202 void *get_object(int num, int *type) |
|
| obj->type = get_typenum(dict); |
obj->type = get_typenum(dict); |
| if (type) |
if (type) |
| *type = obj->type; |
*type = obj->type; |
| |
/* maybe goto's are ugly but here are usefull :) */ |
| if (obj->type == CATALOG) { |
if (obj->type == CATALOG) { |
| ret = fill_catalog(dict); |
ret = fill_catalog(dict); |
| goto out; |
goto out; |
| Riadok 251 void add_obj(char *s, int num) |
|
| Riadok 247 void add_obj(char *s, int num) |
|
| /* get filter number */ |
/* get filter number */ |
| char get_filternum(char *filter) |
char get_filternum(char *filter) |
| { |
{ |
| if (!strncmp(filter, "Fl", 2)) |
if (*filter == 'F' && *(filter + 1) == 'l') |
| return FLATEDECODE; |
return FLATEDECODE; |
| if (!strncmp(filter, "DCTDecode", 9)) |
if (!strncmp(filter, "DCTDecode", 9)) |
| return DCTDECODE; |
return DCTDECODE; |
| Riadok 262 char get_filternum(char *filter) |
|
| Riadok 258 char get_filternum(char *filter) |
|
| long get_startxref(void) |
long get_startxref(void) |
| { |
{ |
| char startxref[XREFLINE]; |
char startxref[XREFLINE]; |
| int i = XREFLINE - 2; |
int i; |
| long offset; |
|
| startxref[XREFLINE - 1] = '\0'; |
|
| fstat(fp->_fileno, &fpstat); |
fstat(fp->_fileno, &fpstat); |
| offset = fpstat.st_size - EOFSIZE; |
fseek(fp, fpstat.st_size - XREFLINE, SEEK_SET); |
| fseek(fp, offset, SEEK_SET); |
fread(&startxref[0],XREFLINE,sizeof(char),fp); |
| while (1) { |
for(i = 0;!isdigit(startxref[i]);i++); |
| startxref[i] = fgetc(fp); |
return strtoul(&startxref[i], NULL, 10); |
| if (startxref[i] == '\r' || startxref[i] == '\n') |
|
| break; |
|
| i--; |
|
| offset--; |
|
| fseek(fp, offset, SEEK_SET); |
|
| } |
|
| return strtoul(&startxref[i + 1], NULL, 10); |
|
| } |
} |
| |
|
| void probe_ptree(int num) |
void probe_ptree(int num) |
| { |
{ |
| |
void *ptr; |
| struct pages *pages; |
struct pages *pages; |
| int type, a; |
int type; |
| pages = (struct pages *) get_object(num, NULL); |
pages = (struct pages *) get_object(num, &type); |
| |
page_tree = (int *) xcalloc(pages->count + 1, sizeof(int)); |
| |
current_page = 0; |
| pages->kids++; |
pages->kids++; |
| a = atoi(*pages->kids); |
while (current_page != pages->count) { |
| pages = (struct pages *) get_object(a, &type); |
|
| while (type != PAGE) { |
|
| a = atoi(pages->kids[1]); |
|
| pages = (struct pages *) get_object(a, &type); |
|
| } |
|
| page_tree[current_page] = a; |
|
| return; |
|
| /* while(1) { |
|
| if(**pages->kids == ']' && !pages->parent) |
|
| break; |
|
| if(**pages->kids == ']') { |
|
| free(pages->old_kids); |
|
| pages = (struct pages *) get_object(pages->parent,NULL); |
|
| } |
|
| num = atoi(*pages->kids); |
num = atoi(*pages->kids); |
| p = (struct pages *) get_object(num,&type); |
if (num) { |
| if(type == PAGE) { |
ptr = get_object(num, &type); |
| page_tree[current_page] = num; |
if (type == PAGES) { |
| current_page++; |
pages = ptr; |
| pages->kids += 3; |
pages->kids++; |
| continue; |
continue; |
| |
} else { |
| |
for(num = pages->count;num;num--) { |
| |
page_tree[current_page] = atoi(*pages->kids); |
| |
current_page++; |
| |
free(pages->kids[0]); |
| |
free(pages->kids[1]); |
| |
free(pages->kids[2]); |
| |
pages->kids += 3; |
| |
} |
| |
free(pages->old_kids); |
| |
if (!pages->parent) |
| |
break; |
| |
pages = |
| |
(struct pages *) get_object(pages-> |
| |
parent, |
| |
NULL); |
| |
} |
| } |
} |
| |
free(pages->kids[0]); |
| |
free(pages->kids[1]); |
| |
free(pages->kids[2]); |
| pages->kids += 3; |
pages->kids += 3; |
| pages = p; |
|
| } |
} |
| return;*/ |
free(pages->old_kids); |
| |
return; |
| } |
} |
| |
|
| /* find objects and add it to object structure */ |
/* find objects and add it to object structure */ |
| void parse_xref(void) |
void parse_xref(void) |
| { |
{ |
| char xref[XREFLINE], *p; |
char xref[XREFLINE]; |
| int entry[2]; |
char *xreftable, *p; |
| fseek(fp, get_startxref(), SEEK_SET); |
int entry[2], xtblsize; |
| fget(xref, XREFLINE, fp); |
trailer.prev = get_startxref(); |
| if (!strstr(xref, "xref")) { |
|
| fprintf(stderr, "PDF document si corrupted!\n"); |
|
| /* reconstruction ? */ |
|
| return; |
|
| } |
|
| objects = NULL; |
objects = NULL; |
| obj_count = 0; |
obj_count = 0; |
| do { |
while (trailer.prev) { |
| |
fseek(fp, trailer.prev, SEEK_SET); |
| |
fget(xref, XREFLINE, fp); |
| |
if (strncmp(xref, "xref", 4)) { |
| |
fprintf(stderr, "PDF document is corrupted!\n"); |
| |
/* reconstruction ? */ |
| |
return; |
| |
} |
| fget(xref, XREFLINE, fp); |
fget(xref, XREFLINE, fp); |
| sscanf(xref, "%d %d", &entry[0], &entry[1]); |
sscanf(xref, "%d %d", &entry[0], &entry[1]); |
| entry[1] += entry[0]; |
xtblsize = entry[1] * XREFLINE + 1; |
| if (entry[0] == 0) |
p = xreftable = (char *) xmalloc(xtblsize); |
| |
fread(xreftable, xtblsize - 1, sizeof(char), fp); |
| |
if (!entry[0]) |
| entry[0]++; |
entry[0]++; |
| |
else |
| |
entry[1] += entry[0]; |
| if (entry[1] > obj_count) { |
if (entry[1] > obj_count) { |
| objects = (struct object **) realloc(objects, |
objects = (struct object **) |
| entry[1] * |
realloc(objects, entry[1] << 2); |
| sizeof(char |
|
| *)); |
|
| obj_count = entry[1]; |
obj_count = entry[1]; |
| } |
} |
| do { |
for (p[xtblsize] = '\0'; *p != '\0'; p += XREFLINE) { |
| fget(xref, XREFLINE, fp); |
if (p[XREFLINE - 3] == 'f') |
| if (!strncmp(xref, "trailer", 7)) |
|
| break; |
|
| if (xref[XREFLINE - 3] == 'f') |
|
| continue; |
continue; |
| add_obj(xref, entry[0]); |
p[XREFLINE - 1] = '\0'; |
| |
add_obj(p, entry[0]); |
| entry[0]++; |
entry[0]++; |
| } while (1); |
} |
| |
free(xreftable); |
| { |
{ |
| char *tline = (char *) xmalloc(3 * XREFLINE); |
char tline[3 * XREFLINE]; |
| fget(tline, 3 * XREFLINE, fp); |
fget(tline, 3 * XREFLINE, fp); |
| trailer.prev = 0; |
trailer.prev = 0; |
| while (tline[0] != '>' && tline[1] != '>') { |
while (tline[0] != '>' && tline[1] != '>') { |
| Riadok 370 void parse_xref(void) |
|
| Riadok 369 void parse_xref(void) |
|
| &trailer.encrypt); |
&trailer.encrypt); |
| fget(tline, 3 * XREFLINE, fp); |
fget(tline, 3 * XREFLINE, fp); |
| } |
} |
| free(tline); |
|
| } |
} |
| if (!trailer.prev) |
} |
| break; |
|
| fseek(fp, trailer.prev, SEEK_SET); |
|
| fget(xref, XREFLINE, fp); |
|
| } while (1); |
|
| return; |
return; |
| } |
} |
| |
|
| Riadok 385 int parse_catalog(void) |
|
| Riadok 379 int parse_catalog(void) |
|
| struct catalog *c = NULL; |
struct catalog *c = NULL; |
| c = (struct catalog *) get_object(trailer.root, NULL); |
c = (struct catalog *) get_object(trailer.root, NULL); |
| if (!c) { |
if (!c) { |
| /* error */ |
fprintf(stderr, "Can't find catalog!\n"); |
| |
exit(-1); |
| } |
} |
| return c->pages; |
return c->pages; |
| } |
} |
| Riadok 393 int parse_catalog(void) |
|
| Riadok 388 int parse_catalog(void) |
|
| void parse_pdf(void) |
void parse_pdf(void) |
| { |
{ |
| int ret; |
int ret; |
| struct pages *pages; |
|
| parse_xref(); |
parse_xref(); |
| ret = parse_catalog(); |
ret = parse_catalog(); |
| pages = (struct pages *) get_object(ret, NULL); |
|
| page_tree = (int *) xcalloc(pages->count, 1); |
|
| current_page = 0; |
|
| ret = parse_catalog(); |
|
| probe_ptree(ret); |
probe_ptree(ret); |
| current_page = 0; |
|
| loop(); |
|
| return; |
return; |
| } |
} |
| |
|
| Riadok 513 struct contents *fill_contents(char *dic |
|
| Riadok 501 struct contents *fill_contents(char *dic |
|
| |
|
| sscanf(p, "Length %d", &content->length); |
sscanf(p, "Length %d", &content->length); |
| for (p += 6; *p != '/'; p++) |
for (p += 6; *p != '/'; p++) |
| if (!strncmp(p, "0 R", 3)) { |
if (*p == '0' && *(p + 1) == ' ' && *(p + 2) == 'R') { |
| p = (char *) get_object(content->length, NULL); |
p = (char *) get_object(content->length, NULL); |
| sscanf(p, "%d\nendobj", &content->length); |
sscanf(p, "%d\nendobj", &content->length); |
| break; |
break; |
| } |
} |
| p = strstr(dictionary, "Filter"); |
p = strstr(dictionary, "Filter"); |
| if (!p) { |
if (p) |
| /* error */ |
content->filter = get_filternum(&p[8]); |
| free(content); |
else |
| return NULL; |
content->filter = -1; |
| } |
|
| content->filter = get_filternum(&p[8]); |
|
| p = strstr(dictionary, "stream") + sizeof("stream"); |
p = strstr(dictionary, "stream") + sizeof("stream"); |
| if (!p) { |
if (!p) { |
| /* error */ |
/* error */ |