Skip to content

Commit e987369

Browse files
committed
Fix #912
1 parent 2059677 commit e987369

File tree

11 files changed

+97
-70
lines changed

11 files changed

+97
-70
lines changed

cmd/pdfcpu/init.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ func initFlags() {
372372
func initLogging(verbose, veryVerbose bool) {
373373
needStackTrace = verbose || veryVerbose
374374
if quiet {
375+
// TODO Need separate logger for command result output.
375376
return
376377
}
377378

cmd/pdfcpu/process.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,6 +1612,13 @@ func processRemovePropertiesCommand(conf *model.Configuration) {
16121612
}
16131613
continue
16141614
}
1615+
1616+
if !validate.DocumentProperty(arg) {
1617+
fmt.Fprintf(os.Stderr, "property name \"%s\" not allowed!\n", arg)
1618+
fmt.Fprintf(os.Stderr, "usage: %s\n\n", usagePropertiesRemove)
1619+
os.Exit(1)
1620+
}
1621+
16151622
keys = append(keys, arg)
16161623
}
16171624

pkg/api/api.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ func Write(ctx *model.Context, w io.Writer, conf *model.Configuration) error {
204204
log.Stats.Printf("XRefTable:\n%s\n", ctx)
205205
}
206206

207+
// Note side effects of validation before writing!
207208
if conf.PostProcessValidate {
208209
if err := ValidateContext(ctx); err != nil {
209210
return err

pkg/api/keyword.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func Keywords(rs io.ReadSeeker, conf *model.Configuration) ([]string, error) {
4343
return nil, err
4444
}
4545

46-
return pdfcpu.KeywordsList(ctx.XRefTable)
46+
return pdfcpu.KeywordsList(ctx)
4747
}
4848

4949
// AddKeywords adds keywords to rs's infodict and writes the result to w.
@@ -64,7 +64,7 @@ func AddKeywords(rs io.ReadSeeker, w io.Writer, files []string, conf *model.Conf
6464
return err
6565
}
6666

67-
if err = pdfcpu.KeywordsAdd(ctx.XRefTable, files); err != nil {
67+
if err = pdfcpu.KeywordsAdd(ctx, files); err != nil {
6868
return err
6969
}
7070

@@ -128,7 +128,7 @@ func RemoveKeywords(rs io.ReadSeeker, w io.Writer, keywords []string, conf *mode
128128
}
129129

130130
var ok bool
131-
if ok, err = pdfcpu.KeywordsRemove(ctx.XRefTable, keywords); err != nil {
131+
if ok, err = pdfcpu.KeywordsRemove(ctx, keywords); err != nil {
132132
return err
133133
}
134134
if !ok {

pkg/api/test/keyword_test.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,19 +70,22 @@ func TestKeywords(t *testing.T) {
7070
// # of keywords must be 0
7171
listKeywords(t, msg, fileName, nil)
7272

73-
keywords := []string{"Ö", "keyword2"}
74-
73+
keywords := []string{"Ö", "你好"}
7574
if err := api.AddKeywordsFile(fileName, "", keywords, nil); err != nil {
7675
t.Fatalf("%s add keywords: %v\n", msg, err)
7776
}
78-
7977
listKeywords(t, msg, fileName, keywords)
8078

81-
if err := api.RemoveKeywordsFile(fileName, "", []string{"keyword2"}, nil); err != nil {
82-
t.Fatalf("%s remove 1 keyword: %v\n", msg, err)
79+
keywords = []string{"world"}
80+
if err := api.AddKeywordsFile(fileName, "", keywords, nil); err != nil {
81+
t.Fatalf("%s add keywords: %v\n", msg, err)
8382
}
83+
listKeywords(t, msg, fileName, []string{"Ö", "你好", "world"})
8484

85-
listKeywords(t, msg, fileName, []string{"Ö"})
85+
if err := api.RemoveKeywordsFile(fileName, "", []string{"你好"}, nil); err != nil {
86+
t.Fatalf("%s remove 1 keyword: %v\n", msg, err)
87+
}
88+
listKeywords(t, msg, fileName, []string{"Ö", "world"})
8689

8790
if err := api.RemoveKeywordsFile(fileName, "", nil, nil); err != nil {
8891
t.Fatalf("%s remove all keywords: %v\n", msg, err)

pkg/api/test/property_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,18 +83,18 @@ func TestProperties(t *testing.T) {
8383
// # of properties must be 0
8484
listProperties(t, msg, fileName, nil)
8585

86-
properties := map[string]string{"name1": "value1", "nameÖ": "valueö"}
86+
properties := map[string]string{"name1": "value1", "nameÖ": "valueö", "cjkv": "你好"}
8787
if err := api.AddPropertiesFile(fileName, "", properties, nil); err != nil {
8888
t.Fatalf("%s add properties: %v\n", msg, err)
8989
}
9090

91-
listProperties(t, msg, fileName, []string{"name1 = value1", "nameÖ = valueö"})
91+
listProperties(t, msg, fileName, []string{"cjkv = 你好", "name1 = value1", "nameÖ = valueö"})
9292

9393
if err := api.RemovePropertiesFile(fileName, "", []string{"nameÖ"}, nil); err != nil {
9494
t.Fatalf("%s remove 1 property: %v\n", msg, err)
9595
}
9696

97-
listProperties(t, msg, fileName, []string{"name1 = value1"})
97+
listProperties(t, msg, fileName, []string{"cjkv = 你好", "name1 = value1"})
9898

9999
if err := api.RemovePropertiesFile(fileName, "", nil, nil); err != nil {
100100
t.Fatalf("%s remove all properties: %v\n", msg, err)

pkg/pdfcpu/info.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ func Info(ctx *model.Context, fileName string, selectedPages types.IntSet) (*PDF
529529

530530
info.ViewerPref = ctx.ViewerPref
531531

532-
kwl, err := KeywordsList(ctx.XRefTable)
532+
kwl, err := KeywordsList(ctx)
533533
if err != nil {
534534
return nil, err
535535
}

pkg/pdfcpu/keyword.go

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ import (
2424
)
2525

2626
// KeywordsList returns a list of keywords as recorded in the document info dict.
27-
func KeywordsList(xRefTable *model.XRefTable) ([]string, error) {
28-
ss := strings.FieldsFunc(xRefTable.Keywords, func(c rune) bool { return c == ',' || c == ';' || c == '\r' })
27+
func KeywordsList(ctx *model.Context) ([]string, error) {
28+
ss := strings.FieldsFunc(ctx.Keywords, func(c rune) bool { return c == ',' || c == ';' || c == '\r' })
2929
for i, s := range ss {
3030
ss[i] = strings.TrimSpace(s)
3131
}
@@ -34,34 +34,49 @@ func KeywordsList(xRefTable *model.XRefTable) ([]string, error) {
3434

3535
// KeywordsAdd adds keywords to the document info dict.
3636
// Returns true if at least one keyword was added.
37-
func KeywordsAdd(xRefTable *model.XRefTable, keywords []string) error {
37+
func KeywordsAdd(ctx *model.Context, keywords []string) error {
38+
if err := ensureInfoDictAndFileID(ctx); err != nil {
39+
return err
40+
}
3841

39-
list, err := KeywordsList(xRefTable)
42+
list, err := KeywordsList(ctx)
4043
if err != nil {
4144
return err
4245
}
4346

44-
for _, s := range keywords {
45-
if !types.MemberOf(s, list) {
46-
xRefTable.Keywords += ", " + types.UTF8ToCP1252(s)
47+
for _, kw := range keywords {
48+
if !types.MemberOf(kw, list) {
49+
if len(ctx.Keywords) == 0 {
50+
ctx.Keywords = kw
51+
} else {
52+
ctx.Keywords += ", " + kw
53+
}
4754
}
4855
}
4956

50-
d, err := xRefTable.DereferenceDict(*xRefTable.Info)
57+
d, err := ctx.DereferenceDict(*ctx.Info)
5158
if err != nil || d == nil {
5259
return err
5360
}
5461

55-
d["Keywords"] = types.StringLiteral(xRefTable.Keywords)
62+
s, err := types.EscapeUTF16String(ctx.Keywords)
63+
if err != nil {
64+
return err
65+
}
66+
67+
d["Keywords"] = types.StringLiteral(*s)
5668

5769
return nil
5870
}
5971

6072
// KeywordsRemove deletes keywords from the document info dict.
6173
// Returns true if at least one keyword was removed.
62-
func KeywordsRemove(xRefTable *model.XRefTable, keywords []string) (bool, error) {
63-
// TODO Handle missing info dict.
64-
d, err := xRefTable.DereferenceDict(*xRefTable.Info)
74+
func KeywordsRemove(ctx *model.Context, keywords []string) (bool, error) {
75+
if ctx.Info == nil {
76+
return false, nil
77+
}
78+
79+
d, err := ctx.DereferenceDict(*ctx.Info)
6580
if err != nil || d == nil {
6681
return false, err
6782
}
@@ -72,34 +87,36 @@ func KeywordsRemove(xRefTable *model.XRefTable, keywords []string) (bool, error)
7287
return true, nil
7388
}
7489

75-
kw := make([]string, len(keywords))
76-
for i, s := range keywords {
77-
kw[i] = types.UTF8ToCP1252(s)
78-
}
79-
80-
// Distil document keywords.
81-
ss := strings.FieldsFunc(xRefTable.Keywords, func(c rune) bool { return c == ',' || c == ';' || c == '\r' })
90+
ss := strings.FieldsFunc(ctx.Keywords, func(c rune) bool { return c == ',' || c == ';' || c == '\r' })
8291

83-
xRefTable.Keywords = ""
92+
ctx.Keywords = ""
8493
var removed bool
8594
first := true
8695

8796
for _, s := range ss {
8897
s = strings.TrimSpace(s)
89-
if types.MemberOf(s, kw) {
98+
if types.MemberOf(s, keywords) {
9099
removed = true
91100
continue
92101
}
102+
93103
if first {
94-
xRefTable.Keywords = s
104+
ctx.Keywords = s
95105
first = false
96106
continue
97107
}
98-
xRefTable.Keywords += ", " + s
108+
109+
ctx.Keywords += ", " + s
99110
}
100111

101112
if removed {
102-
d["Keywords"] = types.StringLiteral(xRefTable.Keywords)
113+
114+
s, err := types.EscapeUTF16String(ctx.Keywords)
115+
if err != nil {
116+
return false, err
117+
}
118+
119+
d["Keywords"] = types.StringLiteral(*s)
103120
}
104121

105122
return removed, nil

pkg/pdfcpu/property.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,13 @@ func PropertiesAdd(ctx *model.Context, properties map[string]string) error {
5151
d, _ := ctx.DereferenceDict(*ctx.Info)
5252

5353
for k, v := range properties {
54-
k1 := types.UTF8ToCP1252(k)
55-
d[k1] = types.StringLiteral(v)
56-
ctx.Properties[k1] = v
54+
s, err := types.Escape(v)
55+
if err != nil {
56+
return err
57+
}
58+
key := types.EncodeName(k)
59+
d[key] = types.StringLiteral(*s)
60+
ctx.Properties[key] = *s
5761
}
5862

5963
return nil
@@ -65,6 +69,7 @@ func PropertiesRemove(ctx *model.Context, properties []string) (bool, error) {
6569
if ctx.Info == nil {
6670
return false, nil
6771
}
72+
6873
d, err := ctx.DereferenceDict(*ctx.Info)
6974
if err != nil || d == nil {
7075
return false, err
@@ -73,20 +78,19 @@ func PropertiesRemove(ctx *model.Context, properties []string) (bool, error) {
7378
if len(properties) == 0 {
7479
// Remove all properties.
7580
for k := range ctx.Properties {
76-
k1 := types.UTF8ToCP1252(k)
77-
delete(d, k1)
81+
delete(d, types.EncodeName(k))
7882
}
7983
ctx.Properties = map[string]string{}
8084
return true, nil
8185
}
8286

8387
var removed bool
8488
for _, k := range properties {
85-
k1 := types.UTF8ToCP1252(k)
86-
_, ok := d[k1]
89+
key := types.EncodeName(k)
90+
_, ok := d[key]
8791
if ok && !removed {
88-
delete(d, k1)
89-
delete(ctx.Properties, k1)
92+
delete(d, key)
93+
delete(ctx.Properties, k)
9094
removed = true
9195
}
9296
}

pkg/pdfcpu/types/string.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ func Unescape(s string) ([]byte, error) {
194194
return b.Bytes(), nil
195195
}
196196

197-
// UTF8ToCP1252 converts UTF-8 to CP1252.
197+
// UTF8ToCP1252 converts UTF-8 to CP1252. Unused
198198
func UTF8ToCP1252(s string) string {
199199
bb := []byte{}
200200
for _, r := range s {
@@ -203,7 +203,7 @@ func UTF8ToCP1252(s string) string {
203203
return string(bb)
204204
}
205205

206-
// CP1252ToUTF8 converts CP1252 to UTF-8.
206+
// CP1252ToUTF8 converts CP1252 to UTF-8. Unused
207207
func CP1252ToUTF8(s string) string {
208208
utf8Buf := make([]byte, utf8.UTFMax)
209209
bb := []byte{}

0 commit comments

Comments
 (0)