Beispiel #1
0
// pd.Stream() returns contents of a stream.
func (pd *PdfReaderT) Stream(reference []byte) (DictionaryT, []byte) {
	q, d := pd.Resolve(reference)
	dic := pd.Dic(d)
	l := pd.Num(dic["/Length"])
	pd.rdr.Seek(int64(q), 0)
	t, _ := ps.Token(pd.rdr)
	if string(t) != "stream" {
		util.Log("Stream", string(reference), "not a stream", string(t))
		return nil, []byte{}
	}
	ps.SkipLE(pd.rdr)
	return dic, pd.rdr.Slice(l)
}
Beispiel #2
0
// xrefReadTable() reads the xref table(s) of a PDF file. This is not recursive
// in favour of not to have to keep track of already used starting points
// for xrefs.
func xrefReadTable(f fancy.Reader, p int) (map[int]int, DictionaryT) {
	var trailer DictionaryT
	var back [MAX_PDF_UPDATES]int
	b := 0
	s := _Bytes
	for ok := true; ok; {
		back[b] = p
		b++
		p = xrefSkip(f, p)
		f.Seek(int64(p), 0)
		s, _ = ps.Token(f)
		if string(s) != "trailer" {
			util.Log("no trailer / xref table")
			return nil, nil
		}
		s, _ = ps.Token(f)
		if trailer == nil {
			trailer = Dictionary(s)
		}
		s, ok = Dictionary(s)["/Prev"]
		p = num(s)
	}
	r := make(map[int]int)
	for b != 0 {
		b--
		f.Seek(int64(back[b]), 0)
		ps.Token(f) // skip "xref"
		for {
			m := tuple(f, 2)
			if string(m[0]) == "trailer" {
				break
			}
			ps.SkipLE(f)
			o := num(m[0])
			dat := f.Slice(num(m[1]) * 20)
			for i := 0; i < len(dat); i += 20 {
				if dat[i+17] != 'n' {
					delete(r, o)
				} else {
					r[o] = num(dat[i : i+10])
				}
				o++
			}
		}
	}
	return r, trailer
}
Beispiel #3
0
func Read(rdr fancy.Reader) (r *CharMapperT) {
	r = New()
	if rdr == nil { // make identity setup
		r.Uni.AddRange(0, 256, 0)
		r.Ranges.AddDef(0, 256, 1)
		return
	}
	cm := NewInterpreter(r)
	for {
		t, _ := ps.Token(rdr)
		if len(t) == 0 {
			break
		}
		if f, ok := Ops[string(t)]; ok {
			util.Log(string(t), cm)
			f(cm)
		} else {
			cm.St.Push(t)
		}
	}
	return
}
Beispiel #4
0
// Load() loads a PDF file of a given name.
func Load(fn string) *PdfReaderT {
	var rr [][2]int // list of entries to resolve

	r := new(PdfReaderT)
	r.File = fn
	r.rdr = fancy.FileReader(fn)
	if r.rdr == nil {
		util.Log(fn, "FileReader error")
		return nil
	}

	v := make([]byte, 16)
	r.rdr.ReadAt(v, 0)

	if v[0] != '%' || v[1] != 'P' || v[2] != 'D' || v[3] != 'F' {
		util.Log(string(v), "not a PDF")
		r.rdr.Close()
		return nil
	}

	x := bytes.IndexByte(v, '\r')
	if x > 0 {
		v = v[:x]
	}
	r.Version = string(v)

	if r.Startxref = xrefStart(r.rdr); r.Startxref == -1 {
		util.Log(fn, "xrefStart error")
		r.rdr.Close()
		return nil
	}

	if r.Xref, r.Trailer = xrefReadTable(r.rdr, r.Startxref); r.Xref == nil {
		r.Xref, rr, r.Trailer = xrefReadStream(r.rdr, r.Startxref)
	}

	if r.Xref == nil {
		util.Log(fn, "xrefRead error")
		r.rdr.Close()
		return nil
	}

	if r.Trailer == nil {
		r.rdr.Seek(int64(xrefSkip(r.rdr, r.Startxref)), 0)

		s, _ := ps.Token(r.rdr)
		if string(s) != "trailer" {
			util.Log(fn, "no trailer")
			r.rdr.Close()
			return nil
		}
		s, _ = ps.Token(r.rdr)
		if r.Trailer = Dictionary(s); r.Trailer == nil {
			util.Log(fn, "no trailer dictionary")
			r.rdr.Close()
			return nil
		}
	}

	r.rcache = make(map[string][]byte)
	r.rncache = make(map[string]int)
	r.dicache = make(map[string]DictionaryT)

	if rr != nil {
		curr := -1

		var dic DictionaryT
		var s []byte

		for _, v := range rr {
			o, i := v[0], v[1]

			if o != curr {
				curr = o

				dic, s = r.DecodedStream(util.MakeRef(curr))

				first := num(dic["/First"])
				n := num(dic["/N"])

				rdr := fancy.SliceReader(s)

				p := tuple(rdr, n*2)

				util.Log("Object-Stream", curr)
				for i := 0; i < len(p); i += 2 {
					oo := num(p[i+0])
					offs := num(p[i+1])

					util.Log(oo, first+offs)

					rdr.Seek(int64(first+offs), 0)
					s, _ := ps.Token(rdr)
					util.Log(string(s))

					ref := string(util.MakeRef(oo))
					r.rcache[ref] = s
					r.rncache[ref] = -1
				}

			}

			util.Log(o, i)
		}
	}

	r.PageMode = string(r.Dic(r.Trailer["/Root"])["/PageMode"])

	return r
}
Beispiel #5
0
func decodeStream(dic DictionaryT, data []byte) []byte {
	if f, ok := dic["/Filter"]; ok {
		filter := ForcedArray(f)
		var decos [][]byte
		if d, ok := dic["/DecodeParms"]; ok {
			decos = ForcedArray(d)
		} else {
			decos = make([][]byte, len(filter))
		}

		for ff := range filter {
			// XXX: if there are multiple filters but only one DecodeParams,
			//      it should be used for all filters

			deco := Dictionary(decos[ff])
			switch string(filter[ff]) {
			case "/FlateDecode":
				data = fancy.ReadAndClose(zlib.NewReader(fancy.SliceReader(data)))
			case "/LZWDecode":
				early := true
				if deco != nil {
					if s, ok := deco["/EarlyChange"]; ok {
						early = num(s) == 1
					}
				}
				data = lzw.Decode(data, early)
			case "/ASCII85Decode":
				ds := data
				for len(ds) > 1 && ds[len(ds)-1] < 33 {
					ds = ds[0 : len(ds)-1]
				}
				if len(ds) >= 2 && ds[len(ds)-1] == '>' && ds[len(ds)-2] == '~' {
					ds = ds[0 : len(ds)-2]
				}
				data = fancy.ReadAll(ascii85.NewDecoder(fancy.SliceReader(ds)))
			case "/ASCIIHexDecode":
				data, _ = hex.DecodeString(string(data))
			default:
				util.Log("Unsupported filter", string(filter[ff]))
				data = []byte{}
			}

			if s, ok := deco["/Predictor"]; ok {
				pred := num(s)

				switch {
				case pred == 1:
					// no predictor

				case pred > 10:
					colors := numdef(deco["/Colors"], 1)
					columns := numdef(deco["/Columns"], 1)
					bitspercomponent := numdef(deco["/BitsPerComponent"], 8)

					util.Log("applying predictor", pred, colors, columns, bitspercomponent)
					data = util.ApplyPNGPredictor(pred, colors, columns, bitspercomponent, data)

				default:
					util.Log("Unsupported predictor", pred)
					return nil
				}
			}
		}
	}
	return data
}
Beispiel #6
0
// xrefReadStream() reads the xref stream(s) of a PDF file. This is not recursive
// in favour of not to have to keep track of already used starting points
// for xrefs.
func xrefReadStream(f fancy.Reader, p int) (xr map[int]int, r [][2]int, trailer DictionaryT) {
	s := _Bytes

	xr = map[int]int{}
	r = [][2]int{}

	for ok := true; ok; {
		f.Seek(int64(p), 0)
		ps.Token(f) // skip "xref"

		//for {
		m := tuple(f, 2)
		if string(m[1]) != "obj" {
			util.Logf("unexpected %q\n", m)
			return nil, nil, nil
		}

		s, _ = ps.Token(f)
		dic := Dictionary(s)

		if trailer == nil {
			trailer = dic
		}

		s, ok = dic["/Prev"]
		p = num(s)

		s, _ = ps.Token(f)
		if string(s) != "stream" {
			util.Log("not a stream", s)
			return nil, nil, nil
		}
		ps.SkipLE(f)

		for k, v := range dic {
			util.Logf("%s %s", k, v)
		}

		size := num(dic["/Size"])
		index := []int{0, size}

		if _, ok := dic["/Index"]; ok {
			a := Array(dic["/Index"])
			index[0] = num(a[0])
			index[1] = num(a[1])

			// can len(index) be != 2 ?
		}

		l := num(dic["/Length"])
		xref := f.Slice(l)

		w := Array(dic["/W"])
		if len(w) != 3 {
			util.Log("unexpected /W", w)
		}

		fl1 := num(w[0])
		fl2 := num(w[1])
		fl3 := num(w[2])

		width := fl1 + fl2 + fl3

		xref = decodeStream(dic, xref)

		s, _ = ps.Token(f) // endstream
		s, _ = ps.Token(f) // endobj

		pos := index[0]

		for i := 0; i < len(xref); i += width {
			ent := xref[i : i+width]
			f1 := bnum(ent[0:fl1])
			f2 := bnum(ent[fl1 : fl1+fl2])
			f3 := bnum(ent[fl1+fl2:])

			switch f1 {
			case 0:
				// free object
				util.Log("free", f2, f3)
				// delete(r, f2)

			case 1:
				// regular object
				util.Log("ref", pos, f3, f2)
				xr[pos] = f2

			case 2:
				// compressed object
				util.Log("cref", pos, f2, f3)
				r = append(r, [2]int{f2, f3})
			}

			pos += 1
		}
		//}
	}

	return xr, r, trailer
}
Beispiel #7
0
func (t *TiffBuilder) WriteIFD(data []byte, next bool) {
	util.Logf("offset: %08x\n", t.offset)

	n := len(t.ifd)
	t.offset += 6 + (12 * uint32(n))

	t.Write(uint16(n))

	padding := false

	for _, e := range t.ifd {
		if e.Tag == TAG_STRIP_OFFSETS || e.Type == IFD_RATIONAL {
			e.ValueOffset = t.offset

			if e.Tag == TAG_STRIP_OFFSETS {
				util.Log("offset:", t.offset)

				t.offset += uint32(len(data)) + 4
				padding = (t.offset & 1) == 1
				if padding {
					t.offset += 1
				}
			} else {
				util.Log("offset:", t.offset)
				t.offset += 8 // 4 + 4
			}
		}

		util.Logf("tag:%v type:%v count:%v value:%v\n", e.Tag, e.Type, e.Count, e.ValueOffset)

		t.Write(e.Tag)
		t.Write(e.Type)
		t.Write(e.Count)

		if e.Count != 1 {
			t.Write(e.ValueOffset)
		} else if e.Type == IFD_LONG {
			t.Write(e.ValueOffset)
		} else if e.Type == IFD_RATIONAL {
			t.Write(e.ValueOffset)
		} else if e.Type == IFD_SHORT {
			t.Write(uint16(e.ValueOffset))
			t.Write(uint16(0))
		} else {
			log.Fatal("unsupported type")
		}
	}

	if next {
		util.Log("next:", t.offset)
		t.Write(uint32(t.offset))
	} else {
		util.Log("next:0")
		t.Write(uint32(0))
	}

	util.Log("datalen:", len(data))
	t.WriteBytes(data)

	if padding {
		t.WriteBytes([]byte{0})
		util.Log("padding:", t.offset)
	}

	for _, e := range t.ifd {
		if e.Type != IFD_RATIONAL {
			continue
		}

		t.Write(e.Num)
		t.Write(e.Den)
	}

	t.ifd = []IFDEntry{}
}