lopdf_bugfix_19072017/
processor.rs1use std::collections::BTreeMap;
2use super::{Document, Object, ObjectId, StringFormat};
3
4impl Document {
5 pub fn change_producer(&mut self, producer: &str) {
7 if let Some(info) = self.trailer.get_mut("Info") {
8 if let Some(dict) = match *info {
9 Object::Dictionary(ref mut dict) => Some(dict),
10 Object::Reference(ref id) => self.objects.get_mut(id).and_then(|obj|obj.as_dict_mut()),
11 _ => None,
12 } {
13 dict.set("Producer", Object::String(producer.as_bytes().to_vec(), StringFormat::Literal));
14 }
15 }
16 }
17
18 pub fn compress(&mut self) {
20 for (_, object) in self.objects.iter_mut() {
21 match *object {
22 Object::Stream(ref mut stream) => {
23 if stream.allows_compression {
24 stream.compress()
25 }
26 },
27 _ => ()
28 }
29 }
30 }
31
32 pub fn decompress(&mut self) {
34 for (_, object) in self.objects.iter_mut() {
35 match *object {
36 Object::Stream(ref mut stream) => stream.decompress(),
37 _ => ()
38 }
39 }
40 }
41
42 pub fn delete_pages(&mut self, page_numbers: &[u32]) {
44 let pages = self.get_pages();
45 for page_number in page_numbers {
46 if let Some(page) = pages.get(&page_number).and_then(|page_id|self.delete_object(page_id)) {
47 let mut page_tree_ref = page.as_dict().and_then(|dict|dict.get("Parent")).and_then(|obj|obj.as_reference());
48 while let Some(page_tree_id) = page_tree_ref {
49 if let Some(page_tree) = self.objects.get_mut(&page_tree_id).and_then(|obj|obj.as_dict_mut()) {
50 page_tree.get("Count").and_then(|obj|obj.as_i64()).map(|count|{
51 page_tree.set("Count", count - 1);
52 });
53 page_tree_ref = page_tree.get("Parent").and_then(|obj|obj.as_reference());
54 } else {
55 break;
56 }
57 }
58 }
59 }
60 }
61
62 pub fn prune_objects(&mut self) -> Vec<ObjectId> {
64 let mut ids = vec![];
65 let refs = self.traverse_objects(|_|{});
66 for id in self.objects.keys().cloned().collect::<Vec<ObjectId>>() {
67 if !refs.contains(&id) {
68 self.objects.remove(&id);
69 ids.push(id);
70 }
71 }
72 ids
73 }
74
75 pub fn delete_object(&mut self, id: &ObjectId) -> Option<Object> {
77 let action = |object: &mut Object| {
78 match *object {
79 Object::Array(ref mut array) => {
80 if let Some(index) = array.iter().position(|item: &Object| {
81 match *item {
82 Object::Reference(ref_id) => ref_id == *id,
83 _ => false
84 }
85 }) {
86 array.remove(index);
87 }
88 },
89 Object::Dictionary(ref mut dict) => {
90 let keys: Vec<String> = dict.iter().filter(|&(_, item): &(&String, &Object)| {
91 match *item {
92 Object::Reference(ref_id) => ref_id == *id,
93 _ => false
94 }
95 }).map(|(k, _)| k.clone()).collect();
96 for key in keys {
97 dict.remove(key.as_str());
98 }
99 },
100 _ => {}
101 }
102 };
103 self.traverse_objects(action);
104 self.objects.remove(id)
105 }
106
107 pub fn delete_zero_length_streams(&mut self) -> Vec<ObjectId> {
109 let mut ids = vec![];
110 for id in self.objects.keys().cloned().collect::<Vec<ObjectId>>() {
111 if self.objects.get(&id).and_then(|obj|obj.as_stream()).map(|stream|stream.content.len()==0) == Some(true) {
112 self.delete_object(&id);
113 ids.push(id);
114 }
115 }
116 ids
117 }
118
119 pub fn renumber_objects(&mut self) {
121 let mut replace = BTreeMap::new();
122 let mut new_id = 1;
123 let mut ids = self.objects.keys().cloned().collect::<Vec<ObjectId>>();
124 ids.sort();
125
126 for id in ids {
127 if id.0 != new_id {
128 replace.insert(id, (new_id, id.1));
129 }
130 new_id += 1;
131 }
132
133 for (old, new) in replace.iter() {
135 if let Some(object) = self.objects.remove(old) {
136 self.objects.insert(new.clone(), object);
137 }
138 }
139
140 let action = |object: &mut Object| {
141 match *object {
142 Object::Reference(ref mut id) => {
143 if replace.contains_key(&id) {
144 *id = replace.get(id).unwrap().clone();
145 }
146 },
147 _ => {}
148 }
149 };
150
151 self.traverse_objects(action);
152 self.max_id = new_id - 1;
153 }
154}