/
reference.go
125 lines (106 loc) · 2.71 KB
/
reference.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package reptilian
import (
"errors"
)
func (d *Doc) getObj(ref *IndObjT) (*ObjT, error) {
var i int
i = int(*ref) - 1
if len(d.Buf.Obj) < i {
return nil, errors.New("Invalid object reference")
}
return d.Buf.Obj[i], nil
}
func getType(o *ObjT) (string, error) {
Goose.Logf(1, "Dic: %s", o.Header)
ident := o.Header.Dic["Type"]
switch ident.(type) {
case *NameT:
return string(*ident.(*NameT)), nil
default:
return "", errors.New("Unknown type")
}
}
func (d *Doc) getCheckingType(ref *IndObjT, t string) (*ObjT, error) {
var i int
var o *ObjT
var s string
var err error
i = int(*ref)
if len(d.Buf.Obj) < i {
return nil, errors.New("Invalid '" + t + "' reference")
}
o, err = d.getObj(ref)
if err != nil {
return nil, err
}
s, err = getType(o)
if err != nil {
return nil, err
}
if s == t {
return o, nil
}
return nil, errors.New("Corrupted '" + t + "'")
}
func (d *Doc) Catalog() (*DicT, error) {
var o *ObjT
var err error
Goose.Logf(1, "trailer: %s", d.Buf.Trailer)
if d.Buf.Trailer == nil {
return nil, errors.New("Catalog not found")
}
info := d.Buf.Trailer.Dic["Info"]
Goose.Logf(1, "info: %s", info)
switch info.(type) {
case *IndObjT:
o, err = d.getCheckingType(info.(*IndObjT), "Catalog")
if err != nil {
return nil, err
}
return &o.Header, nil
default:
return nil, errors.New("Catalog not found")
}
}
func (d *Doc) Pages() (*ObjT, error) {
root := d.Buf.Trailer.Dic["Root"]
switch root.(type) {
case *IndObjT:
return d.getCheckingType(root.(*IndObjT), "Pages")
default:
// Corrupted PDF: Root not found!
// Let's try the catalog...
info, err := d.Catalog()
if err != nil {
return nil, err
}
pages, ok := info.Dic["Pages"]
if !ok {
return nil, errors.New("Pages not found")
}
switch pages.(type) {
case *IndObjT:
return d.getCheckingType(pages.(*IndObjT), "Page")
default:
return nil, errors.New("Pages not found")
}
}
}
func (d *Doc) Content(n int) (string, error) {
var i int
switch d.Index["Pages"][n].Header.Dic["Contents"].(type) {
case *IndObjT:
i = int(*(d.Index["Pages"][n].Header.Dic["Contents"].(*IndObjT)))
if i > len(d.Buf.Obj) {
return "", errors.New("Invalid page content reference")
}
switch d.Buf.Obj[i].Stream[0].(type) {
case *StringT:
return string(*(d.Buf.Obj[i].Stream[0].(*StringT))), nil
default:
return "", errors.New("Page content not found")
}
default:
return "", errors.New("Corrupted page content")
}
}