Skip to content

Commit

Permalink
Provide a pdf.Write(io.Writer) method
Browse files Browse the repository at this point in the history
More bytes.Buffer removal
  • Loading branch information
CaptainCodeman committed Sep 25, 2017
1 parent b52036a commit 29752b7
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 52 deletions.
1 change: 0 additions & 1 deletion content_obj.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ func (c *ContentObj) write(w io.Writer, objID int) error {
}

streamlen := buff.Len()
println(streamlen)

io.WriteString(w, "<<\n")
if isFlate {
Expand Down
93 changes: 56 additions & 37 deletions gopdf.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,9 +375,13 @@ func (gp *GoPdf) WritePdf(pdfPath string) {
ioutil.WriteFile(pdfPath, gp.GetBytesPdf(), 0644)
}

func (gp *GoPdf) Write(w io.Writer) error {
return gp.compilePdf(w)
}

func (gp *GoPdf) Read(p []byte) (int, error) {
if gp.buf.Len() == 0 && gp.buf.Cap() == 0 {
if err := gp.compilePdf(); err != nil {
if err := gp.compilePdf(&gp.buf); err != nil {
return 0, err
}
}
Expand All @@ -389,36 +393,54 @@ func (gp *GoPdf) Close() error {
return nil
}

func (gp *GoPdf) compilePdf() error {
func (gp *GoPdf) compilePdf(w io.Writer) error {
gp.prepare()
err := gp.Close()
if err != nil {
return err
}
max := len(gp.pdfObjs)
gp.buf.WriteString("%PDF-1.7\n\n")
io.WriteString(w, "%PDF-1.7\n\n")
linelens := make([]int, max)
i := 0
writer := newCountingWriter(w)
for i < max {
objID := i + 1
linelens[i] = gp.buf.Len()
linelens[i] = writer.offset
pdfObj := gp.pdfObjs[i]
gp.buf.WriteString(strconv.Itoa(objID) + " 0 obj\n")
pdfObj.write(&gp.buf, objID)
gp.buf.WriteString("endobj\n\n")
fmt.Fprintf(writer, "%d 0 obj\n", objID)
pdfObj.write(writer, objID)
io.WriteString(writer, "endobj\n\n")
i++
}
gp.xref(linelens, &gp.buf, &i)
gp.xref(writer, writer.offset, linelens, i)
return nil
}

type (
countingWriter struct {
offset int
writer io.Writer
}
)

func newCountingWriter(w io.Writer) *countingWriter {
return &countingWriter{writer: w}
}

func (cw *countingWriter) Write(b []byte) (int, error) {
n, err := cw.writer.Write(b)
cw.offset += n
return n, err
}

//GetBytesPdfReturnErr : get bytes of pdf file
func (gp *GoPdf) GetBytesPdfReturnErr() ([]byte, error) {
err := gp.Close()
if err != nil {
return nil, err
}
err = gp.compilePdf()
err = gp.compilePdf(&gp.buf)
return gp.buf.Bytes(), err
}

Expand Down Expand Up @@ -745,69 +767,66 @@ func (gp *GoPdf) prepare() {
}
}

func (gp *GoPdf) xref(linelens []int, buff *bytes.Buffer, i *int) error {
func (gp *GoPdf) xref(w io.Writer, xrefbyteoffset int, linelens []int, i int) error {

xrefbyteoffset := buff.Len()
buff.WriteString("xref\n")
buff.WriteString("0 " + strconv.Itoa((*i)+1) + "\n")
buff.WriteString("0000000000 65535 f \n")
io.WriteString(w, "xref\n")
fmt.Fprintf(w, "0 %d\n", i+1)
io.WriteString(w, "0000000000 65535 f \n")
j := 0
max := len(linelens)
for j < max {
linelen := linelens[j]
buff.WriteString(gp.formatXrefline(linelen) + " 00000 n \n")
fmt.Fprintf(w, "%s 00000 n \n", gp.formatXrefline(linelen))
j++
}
buff.WriteString("trailer\n")
buff.WriteString("<<\n")
buff.WriteString("/Size " + strconv.Itoa(max+1) + "\n")
buff.WriteString("/Root 1 0 R\n")
io.WriteString(w, "trailer\n")
io.WriteString(w, "<<\n")
fmt.Fprintf(w, "/Size %d\n", max+1)
io.WriteString(w, "/Root 1 0 R\n")
if gp.isUseProtection() {
buff.WriteString(fmt.Sprintf("/Encrypt %d 0 R\n", gp.encryptionObjID))
buff.WriteString("/ID [()()]\n")
fmt.Fprintf(w, "/Encrypt %d 0 R\n", gp.encryptionObjID)
io.WriteString(w, "/ID [()()]\n")
}
if gp.isUseInfo {
gp.bindInfo(buff)
gp.writeInfo(w)
}
buff.WriteString(">>\n")
buff.WriteString("startxref\n")
buff.WriteString(strconv.Itoa(xrefbyteoffset))
buff.WriteString("\n%%EOF\n")

(*i)++
io.WriteString(w, ">>\n")
io.WriteString(w, "startxref\n")
fmt.Fprintf(w, "%d", xrefbyteoffset)
io.WriteString(w, "\n%%EOF\n")

return nil
}

func (gp *GoPdf) bindInfo(buff *bytes.Buffer) {
func (gp *GoPdf) writeInfo(w io.Writer) {
var zerotime time.Time
buff.WriteString("/Info <<\n")
io.WriteString(w, "/Info <<\n")

if gp.info.Author != "" {
buff.WriteString(fmt.Sprintf("/Author <FEFF%s>\n", encodeUtf8(gp.info.Author)))
fmt.Fprintf(w, "/Author <FEFF%s>\n", encodeUtf8(gp.info.Author))
}

if gp.info.Title != "" {
buff.WriteString(fmt.Sprintf("/Title <FEFF%s>\n", encodeUtf8(gp.info.Title)))
fmt.Fprintf(w, "/Title <FEFF%s>\n", encodeUtf8(gp.info.Title))
}

if gp.info.Subject != "" {
buff.WriteString(fmt.Sprintf("/Subject <FEFF%s>\n", encodeUtf8(gp.info.Subject)))
fmt.Fprintf(w, "/Subject <FEFF%s>\n", encodeUtf8(gp.info.Subject))
}

if gp.info.Creator != "" {
buff.WriteString(fmt.Sprintf("/Creator <FEFF%s>\n", encodeUtf8(gp.info.Creator)))
fmt.Fprintf(w, "/Creator <FEFF%s>\n", encodeUtf8(gp.info.Creator))
}

if gp.info.Producer != "" {
buff.WriteString(fmt.Sprintf("/Producer <FEFF%s>\n", encodeUtf8(gp.info.Producer)))
fmt.Fprintf(w, "/Producer <FEFF%s>\n", encodeUtf8(gp.info.Producer))
}

if !zerotime.Equal(gp.info.CreationDate) {
buff.WriteString(fmt.Sprintf("/CreationDate(D:%s)>>\n", infodate(gp.info.CreationDate)))
fmt.Fprintf(w, "/CreationDate(D:%s)>>\n", infodate(gp.info.CreationDate))
}

buff.WriteString(" >>\n")
io.WriteString(w, " >>\n")
}

//ปรับ xref ให้เป็น 10 หลัก
Expand Down
6 changes: 2 additions & 4 deletions image_obj_parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,13 @@ func writeImgProp(w io.Writer, imginfo imgInfo) error {
if imginfo.trns != nil && len(imginfo.trns) > 0 {
j := 0
max := len(imginfo.trns)
var trns bytes.Buffer
io.WriteString(w, "/Mask [")
for j < max {
//trn := int(imginfo.trns[j])
//trns.WriteByte(imginfo.trns[j])
fmt.Fprintf(w, "%d ", imginfo.trns[j])
fmt.Fprintf(w, "%d ", imginfo.trns[j])
j++
}
fmt.Fprintf(w, "/Mask [%s]\n", trns.String())
io.WriteString(w, "]\n")
}

if haveSMask(imginfo) {
Expand Down
15 changes: 5 additions & 10 deletions pdf_protection.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package gopdf

import (
"bytes"
"crypto/md5"
"crypto/rc4"
"encoding/binary"
Expand Down Expand Up @@ -98,16 +97,12 @@ func (p *PDFProtection) createOValue(userPassWithPadding []byte, ownerPassWithPa
}

func (p *PDFProtection) createUValue(userPassWithPadding []byte, oValue []byte, protection int) ([]byte, error) {
m := md5.New()
m.Write(userPassWithPadding)
m.Write(oValue)
m.Write([]byte{byte(protection), byte(0xff), byte(0xff), byte(0xff)})

var tmp bytes.Buffer
tmp.Write(userPassWithPadding)
tmp.Write(oValue)
tmp.WriteByte(byte(protection))
tmp.WriteByte(byte(0xff))
tmp.WriteByte(byte(0xff))
tmp.WriteByte(byte(0xff))

tmp2 := md5.Sum(tmp.Bytes())
tmp2 := m.Sum(nil)
p.encryptionKey = tmp2[0:5]
cip, err := rc4.NewCipher(p.encryptionKey)
if err != nil {
Expand Down

0 comments on commit 29752b7

Please sign in to comment.