Skip to content

Commit 6fb37bd

Browse files
committed
Able to read stream when it's length is in object stream
1 parent 30dd8b6 commit 6fb37bd

4 files changed

Lines changed: 61 additions & 15 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "lopdf"
3-
version = "0.17.0"
3+
version = "0.18.0"
44
authors = ["Junfeng Liu <china.liujunfeng@gmail.com>"]
55
homepage = "https://github.com/J-F-Liu/lopdf"
66
documentation = "https://docs.rs/crate/lopdf/"

src/object.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ pub struct Stream {
2121
/// Can the stream be compressed by the `Document::compress()` function?
2222
/// Font streams may not be compressed, for example
2323
pub allows_compression: bool,
24+
/// Stream data's position in PDF file.
25+
pub start_position: Option<usize>,
2426
}
2527

2628
/// Basic PDF object types defined in an enum.
@@ -361,6 +363,16 @@ impl Stream {
361363
dict: dict,
362364
content: content,
363365
allows_compression: true,
366+
start_position: None,
367+
}
368+
}
369+
370+
pub fn with_position(dict: Dictionary, position: usize) -> Stream {
371+
Stream {
372+
dict: dict,
373+
content: vec![],
374+
allows_compression: true,
375+
start_position: Some(position),
364376
}
365377
}
366378

src/parser.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,16 +113,18 @@ fn dictionary() -> Parser<u8, Dictionary> {
113113
}
114114

115115
fn stream<'a>(reader: &'a Reader) -> parser::Parser<'a, u8, Stream> {
116-
dictionary() - space() - seq(b"stream") - eol() >>
117-
move |dict: Dictionary| {
118-
let length = dict.get("Length").and_then(|value| {
116+
dictionary() - space() - seq(b"stream") - eol() >> move |dict: Dictionary| {
117+
if let Some(length) = dict.get("Length").and_then(|value| {
119118
if let Some(id) = value.as_reference() {
120-
return reader.get_object(id).and_then(|value|value.as_i64());
119+
return reader.get_object(id).and_then(|value| value.as_i64());
121120
}
122121
return value.as_i64();
123-
}).expect("Stream Length should be an integer.");
124-
let stream = take(length as usize) - eol().opt() - seq(b"endstream");
125-
stream.map(move |data|Stream::new(dict.clone(), data))
122+
}) {
123+
let stream = take(length as usize) - eol().opt() - seq(b"endstream").expect("endstream");
124+
stream.map(move |data| Stream::new(dict.clone(), data))
125+
} else {
126+
take(0).pos().map(move |pos| Stream::with_position(dict.clone(), pos))
127+
}
126128
}
127129
}
128130

@@ -164,7 +166,7 @@ fn object<'a>(reader: &'a Reader) -> parser::Parser<'a, u8, Object> {
164166
}
165167

166168
pub fn indirect_object<'a>(reader: &'a Reader) -> parser::Parser<'a, u8, (ObjectId, Object)> {
167-
object_id() - seq(b"obj") - space() + object(reader) - space() - seq(b"endobj") - space()
169+
object_id() - seq(b"obj") - space() + object(reader) - space() - seq(b"endobj").opt() - space()
168170
}
169171

170172
pub fn header() -> Parser<u8, String> {

src/reader.rs

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,31 +85,63 @@ impl Reader {
8585
self.document.trailer = trailer;
8686
self.document.reference_table = xref;
8787

88-
for entry in self.document.reference_table.entries.values().filter(|entry|entry.is_normal()) {
88+
let mut zero_length_streams = vec![];
89+
for entry in self.document.reference_table.entries.values().filter(|entry| entry.is_normal()) {
8990
match *entry {
90-
XrefEntry::Normal{offset, ..} => {
91+
XrefEntry::Normal { offset, .. } => {
9192
let read_result = self.read_object(offset as usize);
9293
match read_result {
9394
Ok((object_id, mut object)) => {
9495
match object {
9596
Object::Stream(ref mut stream) => if stream.dict.type_is(b"ObjStm") {
9697
let mut obj_stream = ObjectStream::new(stream);
9798
self.document.objects.append(&mut obj_stream.objects);
99+
} else if stream.content.len() == 0 {
100+
zero_length_streams.push(object_id);
98101
},
99102
_ => {}
100103
}
101104
self.document.objects.insert(object_id, object);
102-
},
103-
Err(err) => { println!("{:?}", err); }
105+
}
106+
Err(err) => {
107+
println!("{:?}", err);
108+
}
104109
}
105-
},
106-
_ => {},
110+
}
111+
_ => {}
107112
};
108113
}
109114

115+
for object_id in zero_length_streams {
116+
if let Some(length) = self.get_stream_length(object_id) {
117+
if let Some(ref mut object) = self.document.get_object_mut(object_id) {
118+
match object {
119+
Object::Stream(ref mut stream) => if let Some(start) = stream.start_position {
120+
let end = start + length as usize;
121+
stream.set_content(self.buffer[start..end].to_vec());
122+
},
123+
_ => {}
124+
}
125+
}
126+
}
127+
}
128+
110129
Ok(())
111130
}
112131

132+
fn get_stream_length(&self, object_id: ObjectId) -> Option<i64> {
133+
let object = self.document.get_object(object_id).unwrap();
134+
match object {
135+
Object::Stream(ref stream) => stream.dict.get("Length").and_then(|value| {
136+
if let Some(id) = value.as_reference() {
137+
return self.document.get_object(id).and_then(|value| value.as_i64());
138+
}
139+
return value.as_i64();
140+
}),
141+
_ => None,
142+
}
143+
}
144+
113145
/// Get object offset by object id.
114146
fn get_offset(&self, id: ObjectId) -> Option<u32> {
115147
if let Some(entry) = self.document.reference_table.get(id.0) {

0 commit comments

Comments
 (0)