github.com/pdfcpu/pdfcpu@v0.11.1/pkg/api/validate.go (about) 1 /* 2 Copyright 2020 The pdfcpu Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package api 18 19 import ( 20 "fmt" 21 "io" 22 "os" 23 "time" 24 25 "github.com/pdfcpu/pdfcpu/pkg/log" 26 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu" 27 "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/model" 28 "github.com/pkg/errors" 29 ) 30 31 // Validate validates a PDF stream read from rs. 32 func Validate(rs io.ReadSeeker, conf *model.Configuration) error { 33 if rs == nil { 34 return errors.New("pdfcpu: Validate: missing rs") 35 } 36 37 if conf == nil { 38 conf = model.NewDefaultConfiguration() 39 } 40 conf.Cmd = model.VALIDATE 41 42 from1 := time.Now() 43 44 ctx, err := ReadContext(rs, conf) 45 if err != nil { 46 return err 47 } 48 49 dur1 := time.Since(from1).Seconds() 50 from2 := time.Now() 51 52 if err = ValidateContext(ctx); err != nil { 53 s := "" 54 if conf.ValidationMode == model.ValidationStrict { 55 s = " (try -mode=relaxed)" 56 } 57 err = errors.Wrap(err, fmt.Sprintf("validation error (obj#:%d)%s", ctx.CurObj, s)) 58 } 59 60 if err == nil { 61 if conf.Optimize { 62 if log.CLIEnabled() { 63 log.CLI.Println("optimizing...") 64 } 65 err = pdfcpu.OptimizeXRefTable(ctx) 66 } 67 } 68 69 dur2 := time.Since(from2).Seconds() 70 dur := time.Since(from1).Seconds() 71 72 if log.StatsEnabled() { 73 log.Stats.Printf("XRefTable:\n%s\n", ctx) 74 } 75 76 model.ValidationTimingStats(dur1, dur2, dur) 77 78 // at this stage: no binary breakup available! 79 if ctx.Read.FileSize > 0 { 80 ctx.Read.LogStats(ctx.Optimized) 81 } 82 83 return err 84 } 85 86 // ValidateFile validates inFile. 87 func ValidateFile(inFile string, conf *model.Configuration) error { 88 if conf == nil { 89 conf = model.NewDefaultConfiguration() 90 } 91 92 log.CLI.Printf("validating(mode=%s) %s ...\n", conf.ValidationModeString(), inFile) 93 94 f, err := os.Open(inFile) 95 if err != nil { 96 return err 97 } 98 99 defer f.Close() 100 101 if err = Validate(f, conf); err != nil { 102 return err 103 } 104 105 log.CLI.Println("validation ok") 106 107 return nil 108 } 109 110 // ValidateFiles validates inFiles. 111 func ValidateFiles(inFiles []string, conf *model.Configuration) error { 112 if conf == nil { 113 conf = model.NewDefaultConfiguration() 114 } 115 116 for i, fn := range inFiles { 117 if i > 0 { 118 log.CLI.Println() 119 } 120 if err := ValidateFile(fn, conf); err != nil { 121 if len(inFiles) == 1 { 122 return err 123 } 124 fmt.Fprintf(os.Stderr, "%s: %v\n", fn, err) 125 } 126 } 127 128 return nil 129 } 130 131 // DumpObject writes an object from rs to stdout. 132 func DumpObject(rs io.ReadSeeker, mode, objNr int, conf *model.Configuration) error { 133 if rs == nil { 134 return errors.New("pdfcpu: DumpObject: missing rs") 135 } 136 137 if conf == nil { 138 conf = model.NewDefaultConfiguration() 139 } 140 conf.Cmd = model.DUMP 141 142 ctx, err := ReadContext(rs, conf) 143 if err != nil { 144 return err 145 } 146 147 if err = ValidateContext(ctx); err != nil { 148 s := "" 149 if conf.ValidationMode == model.ValidationStrict { 150 s = " (try -mode=relaxed)" 151 } 152 return errors.Wrap(err, fmt.Sprintf("validation error (obj#:%d)%s", ctx.CurObj, s)) 153 } 154 155 ctx.DumpObject(objNr, mode) 156 157 return err 158 } 159 160 // DumpObjectFile writes an object from rs to stdout. 161 func DumpObjectFile(inFile string, mode, objNr int, conf *model.Configuration) error { 162 if conf == nil { 163 conf = model.NewDefaultConfiguration() 164 } 165 166 f, err := os.Open(inFile) 167 if err != nil { 168 return err 169 } 170 171 defer f.Close() 172 173 return DumpObject(f, mode, objNr, conf) 174 }