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  }