Commit a8c93bd324d0362a26c1e6591eead5c52f865c0d

Authored by Jay Berkenbilt
1 parent 8288a4eb

Push QPDF member variables into a nested class

Pushing member variables into a nested class enables addition of new
member variables without breaking binary compatibility.
include/qpdf/QPDF.hh
... ... @@ -635,11 +635,11 @@ class QPDF
635 635 qpdf(qpdf),
636 636 og(og)
637 637 {
638   - qpdf->resolving.insert(og);
  638 + qpdf->m->resolving.insert(og);
639 639 }
640 640 virtual ~ResolveRecorder()
641 641 {
642   - this->qpdf->resolving.erase(og);
  642 + this->qpdf->m->resolving.erase(og);
643 643 }
644 644 private:
645 645 QPDF* qpdf;
... ... @@ -1113,79 +1113,95 @@ class QPDF
1113 1113 std::set<QPDFObjGen>& visited, bool top);
1114 1114 void filterCompressedObjects(std::map<int, int> const& object_stream_data);
1115 1115  
  1116 + class Members
  1117 + {
  1118 + friend class QPDF;
  1119 +
  1120 + public:
  1121 + ~Members();
  1122 +
  1123 + private:
  1124 + Members();
  1125 + Members(Members const&);
  1126 +
  1127 + QPDFTokenizer tokenizer;
  1128 + PointerHolder<InputSource> file;
  1129 + std::string last_object_description;
  1130 + bool encrypted;
  1131 + bool encryption_initialized;
  1132 + bool ignore_xref_streams;
  1133 + bool suppress_warnings;
  1134 + std::ostream* out_stream;
  1135 + std::ostream* err_stream;
  1136 + bool attempt_recovery;
  1137 + int encryption_V;
  1138 + int encryption_R;
  1139 + bool encrypt_metadata;
  1140 + std::map<std::string, encryption_method_e> crypt_filters;
  1141 + encryption_method_e cf_stream;
  1142 + encryption_method_e cf_string;
  1143 + encryption_method_e cf_file;
  1144 + std::string provided_password;
  1145 + std::string user_password;
  1146 + std::string encryption_key;
  1147 + std::string cached_object_encryption_key;
  1148 + int cached_key_objid;
  1149 + int cached_key_generation;
  1150 + std::string pdf_version;
  1151 + std::map<QPDFObjGen, QPDFXRefEntry> xref_table;
  1152 + std::set<int> deleted_objects;
  1153 + std::map<QPDFObjGen, ObjCache> obj_cache;
  1154 + std::set<QPDFObjGen> resolving;
  1155 + QPDFObjectHandle trailer;
  1156 + std::vector<QPDFObjectHandle> all_pages;
  1157 + std::map<QPDFObjGen, int> pageobj_to_pages_pos;
  1158 + bool pushed_inherited_attributes_to_pages;
  1159 + std::vector<QPDFExc> warnings;
  1160 + std::map<QPDF*, ObjCopier> object_copiers;
  1161 + PointerHolder<QPDFObjectHandle::StreamDataProvider> copied_streams;
  1162 + // copied_stream_data_provider is owned by copied_streams
  1163 + CopiedStreamDataProvider* copied_stream_data_provider;
  1164 + std::set<QPDFObjGen> attachment_streams;
  1165 + bool reconstructed_xref;
  1166 +
  1167 + // Linearization data
  1168 + qpdf_offset_t first_xref_item_offset; // actual value from file
  1169 + bool uncompressed_after_compressed;
  1170 +
  1171 + // Linearization parameter dictionary and hint table data: may be
  1172 + // read from file or computed prior to writing a linearized file
  1173 + QPDFObjectHandle lindict;
  1174 + LinParameters linp;
  1175 + HPageOffset page_offset_hints;
  1176 + HSharedObject shared_object_hints;
  1177 + HGeneric outline_hints;
  1178 +
  1179 + // Computed linearization data: used to populate above tables
  1180 + // during writing and to compare with them during validation.
  1181 + // c_ means computed.
  1182 + LinParameters c_linp;
  1183 + CHPageOffset c_page_offset_data;
  1184 + CHSharedObject c_shared_object_data;
  1185 + HGeneric c_outline_data;
  1186 +
  1187 + // Object ordering data for linearized files: initialized by
  1188 + // calculateLinearizationData(). Part numbers refer to the PDF
  1189 + // 1.4 specification.
  1190 + std::vector<QPDFObjectHandle> part4;
  1191 + std::vector<QPDFObjectHandle> part6;
  1192 + std::vector<QPDFObjectHandle> part7;
  1193 + std::vector<QPDFObjectHandle> part8;
  1194 + std::vector<QPDFObjectHandle> part9;
  1195 +
  1196 + // Optimization data
  1197 + std::map<ObjUser, std::set<QPDFObjGen> > obj_user_to_objects;
  1198 + std::map<QPDFObjGen, std::set<ObjUser> > object_to_obj_users;
  1199 + };
1116 1200  
1117   - QPDFTokenizer tokenizer;
1118   - PointerHolder<InputSource> file;
1119   - std::string last_object_description;
1120   - bool encrypted;
1121   - bool encryption_initialized;
1122   - bool ignore_xref_streams;
1123   - bool suppress_warnings;
1124   - std::ostream* out_stream;
1125   - std::ostream* err_stream;
1126   - bool attempt_recovery;
1127   - int encryption_V;
1128   - int encryption_R;
1129   - bool encrypt_metadata;
1130   - std::map<std::string, encryption_method_e> crypt_filters;
1131   - encryption_method_e cf_stream;
1132   - encryption_method_e cf_string;
1133   - encryption_method_e cf_file;
1134   - std::string provided_password;
1135   - std::string user_password;
1136   - std::string encryption_key;
1137   - std::string cached_object_encryption_key;
1138   - int cached_key_objid;
1139   - int cached_key_generation;
1140   - std::string pdf_version;
1141   - std::map<QPDFObjGen, QPDFXRefEntry> xref_table;
1142   - std::set<int> deleted_objects;
1143   - std::map<QPDFObjGen, ObjCache> obj_cache;
1144   - std::set<QPDFObjGen> resolving;
1145   - QPDFObjectHandle trailer;
1146   - std::vector<QPDFObjectHandle> all_pages;
1147   - std::map<QPDFObjGen, int> pageobj_to_pages_pos;
1148   - bool pushed_inherited_attributes_to_pages;
1149   - std::vector<QPDFExc> warnings;
1150   - std::map<QPDF*, ObjCopier> object_copiers;
1151   - PointerHolder<QPDFObjectHandle::StreamDataProvider> copied_streams;
1152   - // copied_stream_data_provider is owned by copied_streams
1153   - CopiedStreamDataProvider* copied_stream_data_provider;
1154   - std::set<QPDFObjGen> attachment_streams;
1155   - bool reconstructed_xref;
1156   -
1157   - // Linearization data
1158   - qpdf_offset_t first_xref_item_offset; // actual value from file
1159   - bool uncompressed_after_compressed;
1160   -
1161   - // Linearization parameter dictionary and hint table data: may be
1162   - // read from file or computed prior to writing a linearized file
1163   - QPDFObjectHandle lindict;
1164   - LinParameters linp;
1165   - HPageOffset page_offset_hints;
1166   - HSharedObject shared_object_hints;
1167   - HGeneric outline_hints;
1168   -
1169   - // Computed linearization data: used to populate above tables
1170   - // during writing and to compare with them during validation. c_
1171   - // means computed.
1172   - LinParameters c_linp;
1173   - CHPageOffset c_page_offset_data;
1174   - CHSharedObject c_shared_object_data;
1175   - HGeneric c_outline_data;
1176   -
1177   - // Object ordering data for linearized files: initialized by
1178   - // calculateLinearizationData(). Part numbers refer to the PDF
1179   - // 1.4 specification.
1180   - std::vector<QPDFObjectHandle> part4;
1181   - std::vector<QPDFObjectHandle> part6;
1182   - std::vector<QPDFObjectHandle> part7;
1183   - std::vector<QPDFObjectHandle> part8;
1184   - std::vector<QPDFObjectHandle> part9;
1185   -
1186   - // Optimization data
1187   - std::map<ObjUser, std::set<QPDFObjGen> > obj_user_to_objects;
1188   - std::map<QPDFObjGen, std::set<ObjUser> > object_to_obj_users;
  1201 + // Keep all member variables inside the Members object, which we
  1202 + // dynamically allocate. This makes it possible to add new private
  1203 + // members without breaking binary compatibility.
  1204 + PointerHolder<Members> m;
1189 1205 };
1190 1206  
1191 1207 #endif // __QPDF_HH__
... ...
libqpdf/QPDF.cc
... ... @@ -74,7 +74,7 @@ QPDF::QPDFVersion()
74 74 return QPDF::qpdf_version;
75 75 }
76 76  
77   -QPDF::QPDF() :
  77 +QPDF::Members::Members() :
78 78 encrypted(false),
79 79 encryption_initialized(false),
80 80 ignore_xref_streams(false),
... ... @@ -98,6 +98,15 @@ QPDF::QPDF() :
98 98 {
99 99 }
100 100  
  101 +QPDF::Members::~Members()
  102 +{
  103 +}
  104 +
  105 +QPDF::QPDF() :
  106 + m(new Members())
  107 +{
  108 +}
  109 +
101 110 QPDF::~QPDF()
102 111 {
103 112 // If two objects are mutually referential (through each object
... ... @@ -114,10 +123,10 @@ QPDF::~QPDF()
114 123 // reference will reread the object from the file, which would
115 124 // have the effect of undoing any modifications that may have been
116 125 // made to any of the objects.
117   - this->xref_table.clear();
  126 + this->m->xref_table.clear();
118 127 for (std::map<QPDFObjGen, ObjCache>::iterator iter =
119   - this->obj_cache.begin();
120   - iter != obj_cache.end(); ++iter)
  128 + this->m->obj_cache.begin();
  129 + iter != this->m->obj_cache.end(); ++iter)
121 130 {
122 131 QPDFObject::ObjAccessor::releaseResolved(
123 132 (*iter).second.object.getPointer());
... ... @@ -158,7 +167,7 @@ void
158 167 QPDF::processInputSource(PointerHolder<InputSource> source,
159 168 char const* password)
160 169 {
161   - this->file = source;
  170 + this->m->file = source;
162 171 parse(password);
163 172 }
164 173  
... ... @@ -171,41 +180,41 @@ QPDF::emptyPDF()
171 180 void
172 181 QPDF::setIgnoreXRefStreams(bool val)
173 182 {
174   - this->ignore_xref_streams = val;
  183 + this->m->ignore_xref_streams = val;
175 184 }
176 185  
177 186 void
178 187 QPDF::setOutputStreams(std::ostream* out, std::ostream* err)
179 188 {
180   - this->out_stream = out ? out : &std::cout;
181   - this->err_stream = err ? err : &std::cerr;
  189 + this->m->out_stream = out ? out : &std::cout;
  190 + this->m->err_stream = err ? err : &std::cerr;
182 191 }
183 192  
184 193 void
185 194 QPDF::setSuppressWarnings(bool val)
186 195 {
187   - this->suppress_warnings = val;
  196 + this->m->suppress_warnings = val;
188 197 }
189 198  
190 199 void
191 200 QPDF::setAttemptRecovery(bool val)
192 201 {
193   - this->attempt_recovery = val;
  202 + this->m->attempt_recovery = val;
194 203 }
195 204  
196 205 std::vector<QPDFExc>
197 206 QPDF::getWarnings()
198 207 {
199   - std::vector<QPDFExc> result = this->warnings;
200   - this->warnings.clear();
  208 + std::vector<QPDFExc> result = this->m->warnings;
  209 + this->m->warnings.clear();
201 210 return result;
202 211 }
203 212  
204 213 bool
205 214 QPDF::findHeader()
206 215 {
207   - qpdf_offset_t global_offset = this->file->tell();
208   - std::string line = this->file->readLine(1024);
  216 + qpdf_offset_t global_offset = this->m->file->tell();
  217 + std::string line = this->m->file->readLine(1024);
209 218 char const* p = line.c_str();
210 219 if (strncmp(p, "%PDF-", 5) != 0)
211 220 {
... ... @@ -239,7 +248,7 @@ QPDF::findHeader()
239 248 }
240 249 if (valid)
241 250 {
242   - this->pdf_version = version;
  251 + this->m->pdf_version = version;
243 252 if (global_offset != 0)
244 253 {
245 254 // Empirical evidence strongly suggests that when there is
... ... @@ -247,7 +256,7 @@ QPDF::findHeader()
247 256 // offsets in the file are such that 0 points to the
248 257 // beginning of the header.
249 258 QTC::TC("qpdf", "QPDF global offset");
250   - this->file = new OffsetInputSource(this->file, global_offset);
  259 + this->m->file = new OffsetInputSource(this->m->file, global_offset);
251 260 }
252 261 }
253 262 return valid;
... ... @@ -256,14 +265,14 @@ QPDF::findHeader()
256 265 bool
257 266 QPDF::findStartxref()
258 267 {
259   - QPDFTokenizer::Token t = readToken(this->file, true);
  268 + QPDFTokenizer::Token t = readToken(this->m->file, true);
260 269 if (t == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "startxref"))
261 270 {
262   - t = readToken(this->file, true);
  271 + t = readToken(this->m->file, true);
263 272 if (t.getType() == QPDFTokenizer::tt_integer)
264 273 {
265 274 // Position in front of offset token
266   - this->file->seek(this->file->getLastOffset(), SEEK_SET);
  275 + this->m->file->seek(this->m->file->getLastOffset(), SEEK_SET);
267 276 return true;
268 277 }
269 278 }
... ... @@ -275,37 +284,37 @@ QPDF::parse(char const* password)
275 284 {
276 285 if (password)
277 286 {
278   - this->provided_password = password;
  287 + this->m->provided_password = password;
279 288 }
280 289  
281 290 // Find the header anywhere in the first 1024 bytes of the file.
282 291 PatternFinder hf(*this, &QPDF::findHeader);
283   - if (! this->file->findFirst("%PDF-", 0, 1024, hf))
  292 + if (! this->m->file->findFirst("%PDF-", 0, 1024, hf))
284 293 {
285 294 QTC::TC("qpdf", "QPDF not a pdf file");
286   - warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  295 + warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
287 296 "", 0, "can't find PDF header"));
288 297 // QPDFWriter writes files that usually require at least
289 298 // version 1.2 for /FlateDecode
290   - this->pdf_version = "1.2";
  299 + this->m->pdf_version = "1.2";
291 300 }
292   - if (atof(this->pdf_version.c_str()) < 1.2)
  301 + if (atof(this->m->pdf_version.c_str()) < 1.2)
293 302 {
294   - this->tokenizer.allowPoundAnywhereInName();
  303 + this->m->tokenizer.allowPoundAnywhereInName();
295 304 }
296 305  
297 306 // PDF spec says %%EOF must be found within the last 1024 bytes of
298 307 // the file. We add an extra 30 characters to leave room for the
299 308 // startxref stuff.
300   - this->file->seek(0, SEEK_END);
301   - qpdf_offset_t end_offset = this->file->tell();
  309 + this->m->file->seek(0, SEEK_END);
  310 + qpdf_offset_t end_offset = this->m->file->tell();
302 311 qpdf_offset_t start_offset = (end_offset > 1054 ? end_offset - 1054 : 0);
303 312 PatternFinder sf(*this, &QPDF::findStartxref);
304 313 qpdf_offset_t xref_offset = 0;
305   - if (this->file->findLast("startxref", start_offset, 0, sf))
  314 + if (this->m->file->findLast("startxref", start_offset, 0, sf))
306 315 {
307 316 xref_offset = QUtil::string_to_ll(
308   - readToken(this->file).getValue().c_str());
  317 + readToken(this->m->file).getValue().c_str());
309 318 }
310 319  
311 320 try
... ... @@ -313,14 +322,14 @@ QPDF::parse(char const* password)
313 322 if (xref_offset == 0)
314 323 {
315 324 QTC::TC("qpdf", "QPDF can't find startxref");
316   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), "", 0,
  325 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), "", 0,
317 326 "can't find startxref");
318 327 }
319 328 read_xref(xref_offset);
320 329 }
321 330 catch (QPDFExc& e)
322 331 {
323   - if (this->attempt_recovery)
  332 + if (this->m->attempt_recovery)
324 333 {
325 334 reconstruct_xref(e);
326 335 QTC::TC("qpdf", "QPDF reconstructed xref table");
... ... @@ -338,28 +347,29 @@ QPDF::parse(char const* password)
338 347 void
339 348 QPDF::warn(QPDFExc const& e)
340 349 {
341   - this->warnings.push_back(e);
342   - if (! this->suppress_warnings)
  350 + this->m->warnings.push_back(e);
  351 + if (! this->m->suppress_warnings)
343 352 {
344   - *err_stream << "WARNING: "
345   - << this->warnings.back().what() << std::endl;
  353 + *this->m->err_stream
  354 + << "WARNING: "
  355 + << this->m->warnings.back().what() << std::endl;
346 356 }
347 357 }
348 358  
349 359 void
350 360 QPDF::setTrailer(QPDFObjectHandle obj)
351 361 {
352   - if (this->trailer.isInitialized())
  362 + if (this->m->trailer.isInitialized())
353 363 {
354 364 return;
355 365 }
356   - this->trailer = obj;
  366 + this->m->trailer = obj;
357 367 }
358 368  
359 369 void
360 370 QPDF::reconstruct_xref(QPDFExc& e)
361 371 {
362   - if (this->reconstructed_xref)
  372 + if (this->m->reconstructed_xref)
363 373 {
364 374 // Avoid xref reconstruction infinite loops. This is getting
365 375 // very hard to reproduce because qpdf is throwing many fewer
... ... @@ -367,19 +377,19 @@ QPDF::reconstruct_xref(QPDFExc&amp; e)
367 377 throw e;
368 378 }
369 379  
370   - this->reconstructed_xref = true;
  380 + this->m->reconstructed_xref = true;
371 381  
372   - warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), "", 0,
  382 + warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), "", 0,
373 383 "file is damaged"));
374 384 warn(e);
375   - warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), "", 0,
  385 + warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), "", 0,
376 386 "Attempting to reconstruct cross-reference table"));
377 387  
378 388 // Delete all references to type 1 (uncompressed) objects
379 389 std::set<QPDFObjGen> to_delete;
380 390 for (std::map<QPDFObjGen, QPDFXRefEntry>::iterator iter =
381   - this->xref_table.begin();
382   - iter != this->xref_table.end(); ++iter)
  391 + this->m->xref_table.begin();
  392 + iter != this->m->xref_table.end(); ++iter)
383 393 {
384 394 if (((*iter).second).getType() == 1)
385 395 {
... ... @@ -389,21 +399,22 @@ QPDF::reconstruct_xref(QPDFExc&amp; e)
389 399 for (std::set<QPDFObjGen>::iterator iter = to_delete.begin();
390 400 iter != to_delete.end(); ++iter)
391 401 {
392   - this->xref_table.erase(*iter);
  402 + this->m->xref_table.erase(*iter);
393 403 }
394 404  
395   - this->file->seek(0, SEEK_END);
396   - qpdf_offset_t eof = this->file->tell();
397   - this->file->seek(0, SEEK_SET);
  405 + this->m->file->seek(0, SEEK_END);
  406 + qpdf_offset_t eof = this->m->file->tell();
  407 + this->m->file->seek(0, SEEK_SET);
398 408 bool in_obj = false;
399 409 qpdf_offset_t line_start = 0;
400   - while (this->file->tell() < eof)
401   - {
402   - this->file->findAndSkipNextEOL();
403   - qpdf_offset_t next_line_start = this->file->tell();
404   - this->file->seek(line_start, SEEK_SET);
405   - QPDFTokenizer::Token t1 = readToken(this->file, true);
406   - qpdf_offset_t token_start = this->file->tell() - t1.getValue().length();
  410 + while (this->m->file->tell() < eof)
  411 + {
  412 + this->m->file->findAndSkipNextEOL();
  413 + qpdf_offset_t next_line_start = this->m->file->tell();
  414 + this->m->file->seek(line_start, SEEK_SET);
  415 + QPDFTokenizer::Token t1 = readToken(this->m->file, true);
  416 + qpdf_offset_t token_start =
  417 + this->m->file->tell() - t1.getValue().length();
407 418 if (token_start >= next_line_start)
408 419 {
409 420 // don't process yet
... ... @@ -419,8 +430,8 @@ QPDF::reconstruct_xref(QPDFExc&amp; e)
419 430 {
420 431 if (t1.getType() == QPDFTokenizer::tt_integer)
421 432 {
422   - QPDFTokenizer::Token t2 = readToken(this->file, true);
423   - QPDFTokenizer::Token t3 = readToken(this->file, true);
  433 + QPDFTokenizer::Token t2 = readToken(this->m->file, true);
  434 + QPDFTokenizer::Token t3 = readToken(this->m->file, true);
424 435 if ((t2.getType() == QPDFTokenizer::tt_integer) &&
425 436 (t3 == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "obj")))
426 437 {
... ... @@ -430,11 +441,12 @@ QPDF::reconstruct_xref(QPDFExc&amp; e)
430 441 insertXrefEntry(obj, 1, token_start, gen, true);
431 442 }
432 443 }
433   - else if ((! this->trailer.isInitialized()) &&
434   - (t1 == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "trailer")))
  444 + else if ((! this->m->trailer.isInitialized()) &&
  445 + (t1 == QPDFTokenizer::Token(
  446 + QPDFTokenizer::tt_word, "trailer")))
435 447 {
436 448 QPDFObjectHandle t =
437   - readObject(this->file, "trailer", 0, 0, false);
  449 + readObject(this->m->file, "trailer", 0, 0, false);
438 450 if (! t.isDictionary())
439 451 {
440 452 // Oh well. It was worth a try.
... ... @@ -445,11 +457,11 @@ QPDF::reconstruct_xref(QPDFExc&amp; e)
445 457 }
446 458 }
447 459 }
448   - this->file->seek(next_line_start, SEEK_SET);
  460 + this->m->file->seek(next_line_start, SEEK_SET);
449 461 line_start = next_line_start;
450 462 }
451 463  
452   - if (! this->trailer.isInitialized())
  464 + if (! this->m->trailer.isInitialized())
453 465 {
454 466 // We could check the last encountered object to see if it was
455 467 // an xref stream. If so, we could try to get the trailer
... ... @@ -457,7 +469,7 @@ QPDF::reconstruct_xref(QPDFExc&amp; e)
457 469 // with bad startxref pointers even when they have object
458 470 // streams.
459 471  
460   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), "", 0,
  472 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), "", 0,
461 473 "unable to find trailer "
462 474 "dictionary while recovering damaged file");
463 475 }
... ... @@ -479,8 +491,8 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
479 491 {
480 492 char buf[7];
481 493 memset(buf, 0, sizeof(buf));
482   - this->file->seek(xref_offset, SEEK_SET);
483   - this->file->read(buf, sizeof(buf) - 1);
  494 + this->m->file->seek(xref_offset, SEEK_SET);
  495 + this->m->file->read(buf, sizeof(buf) - 1);
484 496 // The PDF spec says xref must be followed by a line
485 497 // terminator, but files exist in the wild where it is
486 498 // terminated by arbitrary whitespace.
... ... @@ -506,25 +518,25 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
506 518 }
507 519 }
508 520  
509   - if (! this->trailer.isInitialized())
  521 + if (! this->m->trailer.isInitialized())
510 522 {
511   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), "", 0,
  523 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), "", 0,
512 524 "unable to find trailer while reading xref");
513 525 }
514   - int size = this->trailer.getKey("/Size").getIntValue();
  526 + int size = this->m->trailer.getKey("/Size").getIntValue();
515 527 int max_obj = 0;
516   - if (! xref_table.empty())
  528 + if (! this->m->xref_table.empty())
517 529 {
518   - max_obj = (*(xref_table.rbegin())).first.getObj();
  530 + max_obj = (*(this->m->xref_table.rbegin())).first.getObj();
519 531 }
520   - if (! this->deleted_objects.empty())
  532 + if (! this->m->deleted_objects.empty())
521 533 {
522   - max_obj = std::max(max_obj, *(this->deleted_objects.rbegin()));
  534 + max_obj = std::max(max_obj, *(this->m->deleted_objects.rbegin()));
523 535 }
524 536 if (size != max_obj + 1)
525 537 {
526 538 QTC::TC("qpdf", "QPDF xref size mismatch");
527   - warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), "", 0,
  539 + warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), "", 0,
528 540 std::string("reported number of objects (") +
529 541 QUtil::int_to_string(size) +
530 542 ") inconsistent with actual number of objects (" +
... ... @@ -533,7 +545,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
533 545  
534 546 // We no longer need the deleted_objects table, so go ahead and
535 547 // clear it out to make sure we never depend on its being set.
536   - this->deleted_objects.clear();
  548 + this->m->deleted_objects.clear();
537 549 }
538 550  
539 551 bool
... ... @@ -677,9 +689,9 @@ QPDF::parse_xrefEntry(std::string const&amp; line,
677 689  
678 690 if (invalid)
679 691 {
680   - warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  692 + warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
681 693 "xref table",
682   - this->file->getLastOffset(),
  694 + this->m->file->getLastOffset(),
683 695 "accepting invalid xref table entry"));
684 696 }
685 697  
... ... @@ -694,13 +706,13 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
694 706 {
695 707 std::vector<QPDFObjGen> deleted_items;
696 708  
697   - this->file->seek(xref_offset, SEEK_SET);
  709 + this->m->file->seek(xref_offset, SEEK_SET);
698 710 bool done = false;
699 711 while (! done)
700 712 {
701 713 char linebuf[51];
702 714 memset(linebuf, 0, sizeof(linebuf));
703   - this->file->read(linebuf, sizeof(linebuf) - 1);
  715 + this->m->file->read(linebuf, sizeof(linebuf) - 1);
704 716 std::string line = linebuf;
705 717 int obj = 0;
706 718 int num = 0;
... ... @@ -708,19 +720,19 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
708 720 if (! parse_xrefFirst(line, obj, num, bytes))
709 721 {
710 722 QTC::TC("qpdf", "QPDF invalid xref");
711   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
712   - "xref table", this->file->getLastOffset(),
  723 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  724 + "xref table", this->m->file->getLastOffset(),
713 725 "xref syntax invalid");
714 726 }
715   - this->file->seek(this->file->getLastOffset() + bytes, SEEK_SET);
  727 + this->m->file->seek(this->m->file->getLastOffset() + bytes, SEEK_SET);
716 728 for (int i = obj; i < obj + num; ++i)
717 729 {
718 730 if (i == 0)
719 731 {
720 732 // This is needed by checkLinearization()
721   - this->first_xref_item_offset = this->file->tell();
  733 + this->m->first_xref_item_offset = this->m->file->tell();
722 734 }
723   - std::string xref_entry = this->file->readLine(30);
  735 + std::string xref_entry = this->m->file->readLine(30);
724 736 // For xref_table, these will always be small enough to be ints
725 737 qpdf_offset_t f1 = 0;
726 738 int f2 = 0;
... ... @@ -729,8 +741,8 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
729 741 {
730 742 QTC::TC("qpdf", "QPDF invalid xref entry");
731 743 throw QPDFExc(
732   - qpdf_e_damaged_pdf, this->file->getName(),
733   - "xref table", this->file->getLastOffset(),
  744 + qpdf_e_damaged_pdf, this->m->file->getName(),
  745 + "xref table", this->m->file->getLastOffset(),
734 746 "invalid xref entry (obj=" +
735 747 QUtil::int_to_string(i) + ")");
736 748 }
... ... @@ -745,45 +757,45 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
745 757 insertXrefEntry(i, 1, f1, f2);
746 758 }
747 759 }
748   - qpdf_offset_t pos = this->file->tell();
749   - QPDFTokenizer::Token t = readToken(this->file);
  760 + qpdf_offset_t pos = this->m->file->tell();
  761 + QPDFTokenizer::Token t = readToken(this->m->file);
750 762 if (t == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "trailer"))
751 763 {
752 764 done = true;
753 765 }
754 766 else
755 767 {
756   - this->file->seek(pos, SEEK_SET);
  768 + this->m->file->seek(pos, SEEK_SET);
757 769 }
758 770 }
759 771  
760 772 // Set offset to previous xref table if any
761 773 QPDFObjectHandle cur_trailer =
762   - readObject(this->file, "trailer", 0, 0, false);
  774 + readObject(this->m->file, "trailer", 0, 0, false);
763 775 if (! cur_trailer.isDictionary())
764 776 {
765 777 QTC::TC("qpdf", "QPDF missing trailer");
766   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
767   - "", this->file->getLastOffset(),
  778 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  779 + "", this->m->file->getLastOffset(),
768 780 "expected trailer dictionary");
769 781 }
770 782  
771   - if (! this->trailer.isInitialized())
  783 + if (! this->m->trailer.isInitialized())
772 784 {
773 785 setTrailer(cur_trailer);
774 786  
775   - if (! this->trailer.hasKey("/Size"))
  787 + if (! this->m->trailer.hasKey("/Size"))
776 788 {
777 789 QTC::TC("qpdf", "QPDF trailer lacks size");
778   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
779   - "trailer", this->file->getLastOffset(),
  790 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  791 + "trailer", this->m->file->getLastOffset(),
780 792 "trailer dictionary lacks /Size key");
781 793 }
782   - if (! this->trailer.getKey("/Size").isInteger())
  794 + if (! this->m->trailer.getKey("/Size").isInteger())
783 795 {
784 796 QTC::TC("qpdf", "QPDF trailer size not integer");
785   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
786   - "trailer", this->file->getLastOffset(),
  797 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  798 + "trailer", this->m->file->getLastOffset(),
787 799 "/Size key in trailer dictionary is not "
788 800 "an integer");
789 801 }
... ... @@ -791,7 +803,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
791 803  
792 804 if (cur_trailer.hasKey("/XRefStm"))
793 805 {
794   - if (this->ignore_xref_streams)
  806 + if (this->m->ignore_xref_streams)
795 807 {
796 808 QTC::TC("qpdf", "QPDF ignoring XRefStm in trailer");
797 809 }
... ... @@ -807,7 +819,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
807 819 }
808 820 else
809 821 {
810   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  822 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
811 823 "xref stream", xref_offset,
812 824 "invalid /XRefStm");
813 825 }
... ... @@ -827,8 +839,8 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
827 839 if (! cur_trailer.getKey("/Prev").isInteger())
828 840 {
829 841 QTC::TC("qpdf", "QPDF trailer prev not integer");
830   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
831   - "trailer", this->file->getLastOffset(),
  842 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  843 + "trailer", this->m->file->getLastOffset(),
832 844 "/Prev key in trailer dictionary is not "
833 845 "an integer");
834 846 }
... ... @@ -847,7 +859,7 @@ qpdf_offset_t
847 859 QPDF::read_xrefStream(qpdf_offset_t xref_offset)
848 860 {
849 861 bool found = false;
850   - if (! this->ignore_xref_streams)
  862 + if (! this->m->ignore_xref_streams)
851 863 {
852 864 int xobj;
853 865 int xgen;
... ... @@ -875,7 +887,7 @@ QPDF::read_xrefStream(qpdf_offset_t xref_offset)
875 887 if (! found)
876 888 {
877 889 QTC::TC("qpdf", "QPDF can't find xref");
878   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  890 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
879 891 "", xref_offset, "xref not found");
880 892 }
881 893  
... ... @@ -896,7 +908,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj)
896 908 dict.getKey("/Size").isInteger() &&
897 909 (Index_obj.isArray() || Index_obj.isNull())))
898 910 {
899   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  911 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
900 912 "xref stream", xref_offset,
901 913 "Cross-reference stream does not have"
902 914 " proper /W and /Index keys");
... ... @@ -910,7 +922,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj)
910 922 W[i] = W_obj.getArrayItem(i).getIntValue();
911 923 if (W[i] > max_bytes)
912 924 {
913   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  925 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
914 926 "xref stream", xref_offset,
915 927 "Cross-reference stream's /W contains"
916 928 " impossibly large values");
... ... @@ -919,7 +931,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj)
919 931 }
920 932 if (entry_size == 0)
921 933 {
922   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  934 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
923 935 "xref stream", xref_offset,
924 936 "Cross-reference stream's /W indicates"
925 937 " entry size of 0");
... ... @@ -933,7 +945,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj)
933 945 int n_index = Index_obj.getArrayNItems();
934 946 if ((n_index % 2) || (n_index < 2))
935 947 {
936   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  948 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
937 949 "xref stream", xref_offset,
938 950 "Cross-reference stream's /Index has an"
939 951 " invalid number of values");
... ... @@ -946,7 +958,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj)
946 958 }
947 959 else
948 960 {
949   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  961 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
950 962 "xref stream", xref_offset,
951 963 "Cross-reference stream's /Index's item " +
952 964 QUtil::int_to_string(i) +
... ... @@ -969,7 +981,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj)
969 981 {
970 982 if (indx.at(i) > max_num_entries - num_entries)
971 983 {
972   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  984 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
973 985 "xref stream", xref_offset,
974 986 "Cross-reference stream claims to contain"
975 987 " too many entries: " +
... ... @@ -989,7 +1001,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj)
989 1001  
990 1002 if (expected_size != actual_size)
991 1003 {
992   - QPDFExc x(qpdf_e_damaged_pdf, this->file->getName(),
  1004 + QPDFExc x(qpdf_e_damaged_pdf, this->m->file->getName(),
993 1005 "xref stream", xref_offset,
994 1006 "Cross-reference stream data has the wrong size;"
995 1007 " expected = " + QUtil::int_to_string(expected_size) +
... ... @@ -1050,7 +1062,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj)
1050 1062 {
1051 1063 if (fields[0] != 2)
1052 1064 {
1053   - this->uncompressed_after_compressed = true;
  1065 + this->m->uncompressed_after_compressed = true;
1054 1066 }
1055 1067 }
1056 1068 else if (fields[0] == 2)
... ... @@ -1060,13 +1072,13 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj)
1060 1072 if (obj == 0)
1061 1073 {
1062 1074 // This is needed by checkLinearization()
1063   - this->first_xref_item_offset = xref_offset;
  1075 + this->m->first_xref_item_offset = xref_offset;
1064 1076 }
1065 1077 insertXrefEntry(obj, static_cast<int>(fields[0]),
1066 1078 fields[1], static_cast<int>(fields[2]));
1067 1079 }
1068 1080  
1069   - if (! this->trailer.isInitialized())
  1081 + if (! this->m->trailer.isInitialized())
1070 1082 {
1071 1083 setTrailer(dict);
1072 1084 }
... ... @@ -1075,8 +1087,8 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj)
1075 1087 {
1076 1088 if (! dict.getKey("/Prev").isInteger())
1077 1089 {
1078   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1079   - "xref stream", this->file->getLastOffset(),
  1090 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  1091 + "xref stream", this->m->file->getLastOffset(),
1080 1092 "/Prev key in xref stream dictionary is not "
1081 1093 "an integer");
1082 1094 }
... ... @@ -1108,12 +1120,12 @@ QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite)
1108 1120 { // private scope
1109 1121 int gen = (f0 == 2 ? 0 : f2);
1110 1122 QPDFObjGen og(obj, gen);
1111   - if (this->xref_table.count(og))
  1123 + if (this->m->xref_table.count(og))
1112 1124 {
1113 1125 if (overwrite)
1114 1126 {
1115 1127 QTC::TC("qpdf", "QPDF xref overwrite object");
1116   - this->xref_table.erase(og);
  1128 + this->m->xref_table.erase(og);
1117 1129 }
1118 1130 else
1119 1131 {
... ... @@ -1121,7 +1133,7 @@ QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite)
1121 1133 return;
1122 1134 }
1123 1135 }
1124   - if (this->deleted_objects.count(obj))
  1136 + if (this->m->deleted_objects.count(obj))
1125 1137 {
1126 1138 QTC::TC("qpdf", "QPDF xref deleted object");
1127 1139 return;
... ... @@ -1131,22 +1143,22 @@ QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite)
1131 1143 switch (f0)
1132 1144 {
1133 1145 case 0:
1134   - this->deleted_objects.insert(obj);
  1146 + this->m->deleted_objects.insert(obj);
1135 1147 break;
1136 1148  
1137 1149 case 1:
1138 1150 // f2 is generation
1139 1151 QTC::TC("qpdf", "QPDF xref gen > 0", ((f2 > 0) ? 1 : 0));
1140   - this->xref_table[QPDFObjGen(obj, f2)] = QPDFXRefEntry(f0, f1, f2);
  1152 + this->m->xref_table[QPDFObjGen(obj, f2)] = QPDFXRefEntry(f0, f1, f2);
1141 1153 break;
1142 1154  
1143 1155 case 2:
1144   - this->xref_table[QPDFObjGen(obj, 0)] = QPDFXRefEntry(f0, f1, f2);
  1156 + this->m->xref_table[QPDFObjGen(obj, 0)] = QPDFXRefEntry(f0, f1, f2);
1145 1157 break;
1146 1158  
1147 1159 default:
1148   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1149   - "xref stream", this->file->getLastOffset(),
  1160 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  1161 + "xref stream", this->m->file->getLastOffset(),
1150 1162 "unknown xref stream entry type " +
1151 1163 QUtil::int_to_string(f0));
1152 1164 break;
... ... @@ -1157,21 +1169,24 @@ void
1157 1169 QPDF::showXRefTable()
1158 1170 {
1159 1171 for (std::map<QPDFObjGen, QPDFXRefEntry>::iterator iter =
1160   - this->xref_table.begin();
1161   - iter != this->xref_table.end(); ++iter)
  1172 + this->m->xref_table.begin();
  1173 + iter != this->m->xref_table.end(); ++iter)
1162 1174 {
1163 1175 QPDFObjGen const& og = (*iter).first;
1164 1176 QPDFXRefEntry const& entry = (*iter).second;
1165   - *out_stream << og.getObj() << "/" << og.getGen() << ": ";
  1177 + *this->m->out_stream << og.getObj() << "/" << og.getGen() << ": ";
1166 1178 switch (entry.getType())
1167 1179 {
1168 1180 case 1:
1169   - *out_stream << "uncompressed; offset = " << entry.getOffset();
  1181 + *this->m->out_stream
  1182 + << "uncompressed; offset = " << entry.getOffset();
1170 1183 break;
1171 1184  
1172 1185 case 2:
1173   - *out_stream << "compressed; stream = " << entry.getObjStreamNumber()
1174   - << ", index = " << entry.getObjStreamIndex();
  1186 + *this->m->out_stream
  1187 + << "compressed; stream = "
  1188 + << entry.getObjStreamNumber()
  1189 + << ", index = " << entry.getObjStreamIndex();
1175 1190 break;
1176 1191  
1177 1192 default:
... ... @@ -1179,7 +1194,7 @@ QPDF::showXRefTable()
1179 1194 " showing xref_table");
1180 1195 break;
1181 1196 }
1182   - *out_stream << std::endl;
  1197 + *this->m->out_stream << std::endl;
1183 1198 }
1184 1199 }
1185 1200  
... ... @@ -1188,8 +1203,8 @@ QPDF::getAllObjects()
1188 1203 {
1189 1204 std::vector<QPDFObjectHandle> result;
1190 1205 for (std::map<QPDFObjGen, QPDFXRefEntry>::iterator iter =
1191   - this->xref_table.begin();
1192   - iter != this->xref_table.end(); ++iter)
  1206 + this->m->xref_table.begin();
  1207 + iter != this->m->xref_table.end(); ++iter)
1193 1208 {
1194 1209  
1195 1210 QPDFObjGen const& og = (*iter).first;
... ... @@ -1203,18 +1218,18 @@ void
1203 1218 QPDF::setLastObjectDescription(std::string const& description,
1204 1219 int objid, int generation)
1205 1220 {
1206   - this->last_object_description.clear();
  1221 + this->m->last_object_description.clear();
1207 1222 if (! description.empty())
1208 1223 {
1209   - this->last_object_description += description;
  1224 + this->m->last_object_description += description;
1210 1225 if (objid > 0)
1211 1226 {
1212   - this->last_object_description += ": ";
  1227 + this->m->last_object_description += ": ";
1213 1228 }
1214 1229 }
1215 1230 if (objid > 0)
1216 1231 {
1217   - this->last_object_description += "object " +
  1232 + this->m->last_object_description += "object " +
1218 1233 QUtil::int_to_string(objid) + " " +
1219 1234 QUtil::int_to_string(generation);
1220 1235 }
... ... @@ -1231,20 +1246,20 @@ QPDF::readObject(PointerHolder&lt;InputSource&gt; input,
1231 1246 bool empty = false;
1232 1247 PointerHolder<StringDecrypter> decrypter_ph;
1233 1248 StringDecrypter* decrypter = 0;
1234   - if (this->encrypted && (! in_object_stream))
  1249 + if (this->m->encrypted && (! in_object_stream))
1235 1250 {
1236 1251 decrypter_ph = new StringDecrypter(this, objid, generation);
1237 1252 decrypter = decrypter_ph.getPointer();
1238 1253 }
1239 1254 QPDFObjectHandle object = QPDFObjectHandle::parse(
1240   - input, description, this->tokenizer, empty, decrypter, this);
  1255 + input, description, this->m->tokenizer, empty, decrypter, this);
1241 1256 if (empty)
1242 1257 {
1243 1258 // Nothing in the PDF spec appears to allow empty objects, but
1244 1259 // they have been encountered in actual PDF files and Adobe
1245 1260 // Reader appears to ignore them.
1246 1261 warn(QPDFExc(qpdf_e_damaged_pdf, input->getName(),
1247   - this->last_object_description,
  1262 + this->m->last_object_description,
1248 1263 input->getLastOffset(),
1249 1264 "empty object treated as null"));
1250 1265 }
... ... @@ -1299,7 +1314,7 @@ QPDF::readObject(PointerHolder&lt;InputSource&gt; input,
1299 1314 warn(QPDFExc(
1300 1315 qpdf_e_damaged_pdf,
1301 1316 input->getName(),
1302   - this->last_object_description,
  1317 + this->m->last_object_description,
1303 1318 input->tell(),
1304 1319 "stream keyword followed"
1305 1320 " by carriage return only"));
... ... @@ -1315,7 +1330,7 @@ QPDF::readObject(PointerHolder&lt;InputSource&gt; input,
1315 1330 input->unreadCh(ch);
1316 1331 }
1317 1332 warn(QPDFExc(qpdf_e_damaged_pdf, input->getName(),
1318   - this->last_object_description,
  1333 + this->m->last_object_description,
1319 1334 input->tell(),
1320 1335 "stream keyword not followed"
1321 1336 " by proper line terminator"));
... ... @@ -1337,7 +1352,7 @@ QPDF::readObject(PointerHolder&lt;InputSource&gt; input,
1337 1352 {
1338 1353 QTC::TC("qpdf", "QPDF stream without length");
1339 1354 throw QPDFExc(qpdf_e_damaged_pdf, input->getName(),
1340   - this->last_object_description, offset,
  1355 + this->m->last_object_description, offset,
1341 1356 "stream dictionary lacks /Length key");
1342 1357 }
1343 1358  
... ... @@ -1346,7 +1361,7 @@ QPDF::readObject(PointerHolder&lt;InputSource&gt; input,
1346 1361 {
1347 1362 QTC::TC("qpdf", "QPDF stream length not integer");
1348 1363 throw QPDFExc(qpdf_e_damaged_pdf, input->getName(),
1349   - this->last_object_description, offset,
  1364 + this->m->last_object_description, offset,
1350 1365 "/Length key in stream dictionary is not "
1351 1366 "an integer");
1352 1367 }
... ... @@ -1359,14 +1374,14 @@ QPDF::readObject(PointerHolder&lt;InputSource&gt; input,
1359 1374 {
1360 1375 QTC::TC("qpdf", "QPDF missing endstream");
1361 1376 throw QPDFExc(qpdf_e_damaged_pdf, input->getName(),
1362   - this->last_object_description,
  1377 + this->m->last_object_description,
1363 1378 input->getLastOffset(),
1364 1379 "expected endstream");
1365 1380 }
1366 1381 }
1367 1382 catch (QPDFExc& e)
1368 1383 {
1369   - if (this->attempt_recovery)
  1384 + if (this->m->attempt_recovery)
1370 1385 {
1371 1386 warn(e);
1372 1387 length = recoverStreamLength(
... ... @@ -1396,12 +1411,12 @@ bool
1396 1411 QPDF::findEndstream()
1397 1412 {
1398 1413 // Find endstream or endobj. Position the input at that token.
1399   - QPDFTokenizer::Token t = readToken(this->file, true);
  1414 + QPDFTokenizer::Token t = readToken(this->m->file, true);
1400 1415 if ((t.getType() == QPDFTokenizer::tt_word) &&
1401 1416 ((t.getValue() == "endobj") ||
1402 1417 (t.getValue() == "endstream")));
1403 1418 {
1404   - this->file->seek(this->file->getLastOffset(), SEEK_SET);
  1419 + this->m->file->seek(this->m->file->getLastOffset(), SEEK_SET);
1405 1420 return true;
1406 1421 }
1407 1422 return false;
... ... @@ -1415,19 +1430,19 @@ QPDF::recoverStreamLength(PointerHolder&lt;InputSource&gt; input,
1415 1430 // Try to reconstruct stream length by looking for
1416 1431 // endstream or endobj
1417 1432 warn(QPDFExc(qpdf_e_damaged_pdf, input->getName(),
1418   - this->last_object_description, stream_offset,
  1433 + this->m->last_object_description, stream_offset,
1419 1434 "attempting to recover stream length"));
1420 1435  
1421 1436 PatternFinder ef(*this, &QPDF::findEndstream);
1422 1437 size_t length = 0;
1423   - if (this->file->findFirst("end", stream_offset, 0, ef))
  1438 + if (this->m->file->findFirst("end", stream_offset, 0, ef))
1424 1439 {
1425   - length = this->file->tell() - stream_offset;
  1440 + length = this->m->file->tell() - stream_offset;
1426 1441 // Reread endstream but, if it was endobj, don't skip that.
1427   - QPDFTokenizer::Token t = readToken(this->file);
  1442 + QPDFTokenizer::Token t = readToken(this->m->file);
1428 1443 if (t.getValue() == "endobj")
1429 1444 {
1430   - this->file->seek(this->file->getLastOffset(), SEEK_SET);
  1445 + this->m->file->seek(this->m->file->getLastOffset(), SEEK_SET);
1431 1446 }
1432 1447 }
1433 1448  
... ... @@ -1438,8 +1453,8 @@ QPDF::recoverStreamLength(PointerHolder&lt;InputSource&gt; input,
1438 1453  
1439 1454 // Make sure this is inside this object
1440 1455 for (std::map<QPDFObjGen, QPDFXRefEntry>::iterator iter =
1441   - this->xref_table.begin();
1442   - iter != this->xref_table.end(); ++iter)
  1456 + this->m->xref_table.begin();
  1457 + iter != this->m->xref_table.end(); ++iter)
1443 1458 {
1444 1459 QPDFObjGen const& og = (*iter).first;
1445 1460 QPDFXRefEntry const& entry = (*iter).second;
... ... @@ -1472,13 +1487,14 @@ QPDF::recoverStreamLength(PointerHolder&lt;InputSource&gt; input,
1472 1487 if (length == 0)
1473 1488 {
1474 1489 warn(QPDFExc(qpdf_e_damaged_pdf, input->getName(),
1475   - this->last_object_description, stream_offset,
1476   - "unable to recover stream data; treating stream as empty"));
  1490 + this->m->last_object_description, stream_offset,
  1491 + "unable to recover stream data;"
  1492 + " treating stream as empty"));
1477 1493 }
1478 1494 else
1479 1495 {
1480 1496 warn(QPDFExc(qpdf_e_damaged_pdf, input->getName(),
1481   - this->last_object_description, stream_offset,
  1497 + this->m->last_object_description, stream_offset,
1482 1498 "recovered stream length: " +
1483 1499 QUtil::int_to_string(length)));
1484 1500 }
... ... @@ -1490,8 +1506,8 @@ QPDF::recoverStreamLength(PointerHolder&lt;InputSource&gt; input,
1490 1506 QPDFTokenizer::Token
1491 1507 QPDF::readToken(PointerHolder<InputSource> input, bool allow_bad)
1492 1508 {
1493   - return this->tokenizer.readToken(
1494   - input, this->last_object_description, allow_bad);
  1509 + return this->m->tokenizer.readToken(
  1510 + input, this->m->last_object_description, allow_bad);
1495 1511 }
1496 1512  
1497 1513 QPDFObjectHandle
... ... @@ -1500,7 +1516,7 @@ QPDF::readObjectAtOffset(bool try_recovery,
1500 1516 int exp_objid, int exp_generation,
1501 1517 int& objid, int& generation)
1502 1518 {
1503   - if (! this->attempt_recovery)
  1519 + if (! this->m->attempt_recovery)
1504 1520 {
1505 1521 try_recovery = false;
1506 1522 }
... ... @@ -1514,17 +1530,17 @@ QPDF::readObjectAtOffset(bool try_recovery,
1514 1530 if (offset == 0)
1515 1531 {
1516 1532 QTC::TC("qpdf", "QPDF bogus 0 offset", 0);
1517   - warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1518   - this->last_object_description, 0,
  1533 + warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  1534 + this->m->last_object_description, 0,
1519 1535 "object has offset 0"));
1520 1536 return QPDFObjectHandle::newNull();
1521 1537 }
1522 1538  
1523   - this->file->seek(offset, SEEK_SET);
  1539 + this->m->file->seek(offset, SEEK_SET);
1524 1540  
1525   - QPDFTokenizer::Token tobjid = readToken(this->file);
1526   - QPDFTokenizer::Token tgen = readToken(this->file);
1527   - QPDFTokenizer::Token tobj = readToken(this->file);
  1541 + QPDFTokenizer::Token tobjid = readToken(this->m->file);
  1542 + QPDFTokenizer::Token tgen = readToken(this->m->file);
  1543 + QPDFTokenizer::Token tobj = readToken(this->m->file);
1528 1544  
1529 1545 bool objidok = (tobjid.getType() == QPDFTokenizer::tt_integer);
1530 1546 int genok = (tgen.getType() == QPDFTokenizer::tt_integer);
... ... @@ -1539,8 +1555,8 @@ QPDF::readObjectAtOffset(bool try_recovery,
1539 1555 if (! (objidok && genok && objok))
1540 1556 {
1541 1557 QTC::TC("qpdf", "QPDF expected n n obj");
1542   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1543   - this->last_object_description, offset,
  1558 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  1559 + this->m->last_object_description, offset,
1544 1560 "expected n n obj");
1545 1561 }
1546 1562 objid = atoi(tobjid.getValue().c_str());
... ... @@ -1549,8 +1565,8 @@ QPDF::readObjectAtOffset(bool try_recovery,
1549 1565 if (objid == 0)
1550 1566 {
1551 1567 QTC::TC("qpdf", "QPDF object id 0");
1552   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1553   - this->last_object_description, offset,
  1568 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  1569 + this->m->last_object_description, offset,
1554 1570 "object with ID 0");
1555 1571 }
1556 1572  
... ... @@ -1558,8 +1574,8 @@ QPDF::readObjectAtOffset(bool try_recovery,
1558 1574 (! ((objid == exp_objid) && (generation == exp_generation))))
1559 1575 {
1560 1576 QTC::TC("qpdf", "QPDF err wrong objid/generation");
1561   - QPDFExc e(qpdf_e_damaged_pdf, this->file->getName(),
1562   - this->last_object_description, offset,
  1577 + QPDFExc e(qpdf_e_damaged_pdf, this->m->file->getName(),
  1578 + this->m->last_object_description, offset,
1563 1579 std::string("expected ") +
1564 1580 QUtil::int_to_string(exp_objid) + " " +
1565 1581 QUtil::int_to_string(exp_generation) + " obj");
... ... @@ -1583,10 +1599,10 @@ QPDF::readObjectAtOffset(bool try_recovery,
1583 1599 // Try again after reconstructing xref table
1584 1600 reconstruct_xref(e);
1585 1601 QPDFObjGen og(exp_objid, exp_generation);
1586   - if (this->xref_table.count(og) &&
1587   - (this->xref_table[og].getType() == 1))
  1602 + if (this->m->xref_table.count(og) &&
  1603 + (this->m->xref_table[og].getType() == 1))
1588 1604 {
1589   - qpdf_offset_t new_offset = this->xref_table[og].getOffset();
  1605 + qpdf_offset_t new_offset = this->m->xref_table[og].getOffset();
1590 1606 QPDFObjectHandle result = readObjectAtOffset(
1591 1607 false, new_offset, description,
1592 1608 exp_objid, exp_generation, objid, generation);
... ... @@ -1597,7 +1613,7 @@ QPDF::readObjectAtOffset(bool try_recovery,
1597 1613 {
1598 1614 QTC::TC("qpdf", "QPDF object gone after xref reconstruction");
1599 1615 warn(QPDFExc(
1600   - qpdf_e_damaged_pdf, this->file->getName(),
  1616 + qpdf_e_damaged_pdf, this->m->file->getName(),
1601 1617 "", 0,
1602 1618 std::string(
1603 1619 "object " +
... ... @@ -1616,19 +1632,20 @@ QPDF::readObjectAtOffset(bool try_recovery,
1616 1632 }
1617 1633  
1618 1634 QPDFObjectHandle oh = readObject(
1619   - this->file, description, objid, generation, false);
  1635 + this->m->file, description, objid, generation, false);
1620 1636  
1621   - if (! (readToken(this->file) ==
  1637 + if (! (readToken(this->m->file) ==
1622 1638 QPDFTokenizer::Token(QPDFTokenizer::tt_word, "endobj")))
1623 1639 {
1624 1640 QTC::TC("qpdf", "QPDF err expected endobj");
1625   - warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1626   - this->last_object_description, this->file->getLastOffset(),
  1641 + warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  1642 + this->m->last_object_description,
  1643 + this->m->file->getLastOffset(),
1627 1644 "expected endobj"));
1628 1645 }
1629 1646  
1630 1647 QPDFObjGen og(objid, generation);
1631   - if (! this->obj_cache.count(og))
  1648 + if (! this->m->obj_cache.count(og))
1632 1649 {
1633 1650 // Store the object in the cache here so it gets cached
1634 1651 // whether we first know the offset or whether we first know
... ... @@ -1640,30 +1657,30 @@ QPDF::readObjectAtOffset(bool try_recovery,
1640 1657 // linearization hint tables. Offsets and lengths of objects
1641 1658 // may imply the end of an object to be anywhere between these
1642 1659 // values.
1643   - qpdf_offset_t end_before_space = this->file->tell();
  1660 + qpdf_offset_t end_before_space = this->m->file->tell();
1644 1661  
1645 1662 // skip over spaces
1646 1663 while (true)
1647 1664 {
1648 1665 char ch;
1649   - if (this->file->read(&ch, 1))
  1666 + if (this->m->file->read(&ch, 1))
1650 1667 {
1651 1668 if (! isspace(static_cast<unsigned char>(ch)))
1652 1669 {
1653   - this->file->seek(-1, SEEK_CUR);
  1670 + this->m->file->seek(-1, SEEK_CUR);
1654 1671 break;
1655 1672 }
1656 1673 }
1657 1674 else
1658 1675 {
1659   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1660   - this->last_object_description, offset,
  1676 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  1677 + this->m->last_object_description, offset,
1661 1678 "EOF after endobj");
1662 1679 }
1663 1680 }
1664   - qpdf_offset_t end_after_space = this->file->tell();
  1681 + qpdf_offset_t end_after_space = this->m->file->tell();
1665 1682  
1666   - this->obj_cache[og] =
  1683 + this->m->obj_cache[og] =
1667 1684 ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh),
1668 1685 end_before_space, end_after_space);
1669 1686 }
... ... @@ -1678,14 +1695,14 @@ QPDF::resolve(int objid, int generation)
1678 1695 // to insert things into the object cache that don't actually
1679 1696 // exist in the file.
1680 1697 QPDFObjGen og(objid, generation);
1681   - if (this->resolving.count(og))
  1698 + if (this->m->resolving.count(og))
1682 1699 {
1683 1700 // This can happen if an object references itself directly or
1684 1701 // indirectly in some key that has to be resolved during
1685 1702 // object parsing, such as stream length.
1686 1703 QTC::TC("qpdf", "QPDF recursion loop in resolve");
1687   - warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1688   - "", this->file->getLastOffset(),
  1704 + warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  1705 + "", this->m->file->getLastOffset(),
1689 1706 "loop detected resolving object " +
1690 1707 QUtil::int_to_string(objid) + " " +
1691 1708 QUtil::int_to_string(generation)));
... ... @@ -1693,15 +1710,15 @@ QPDF::resolve(int objid, int generation)
1693 1710 }
1694 1711 ResolveRecorder rr(this, og);
1695 1712  
1696   - if (! this->obj_cache.count(og))
  1713 + if (! this->m->obj_cache.count(og))
1697 1714 {
1698   - if (! this->xref_table.count(og))
  1715 + if (! this->m->xref_table.count(og))
1699 1716 {
1700 1717 // PDF spec says unknown objects resolve to the null object.
1701 1718 return new QPDF_Null;
1702 1719 }
1703 1720  
1704   - QPDFXRefEntry const& entry = this->xref_table[og];
  1721 + QPDFXRefEntry const& entry = this->m->xref_table[og];
1705 1722 bool success = false;
1706 1723 try
1707 1724 {
... ... @@ -1724,7 +1741,8 @@ QPDF::resolve(int objid, int generation)
1724 1741 break;
1725 1742  
1726 1743 default:
1727   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), "", 0,
  1744 + throw QPDFExc(qpdf_e_damaged_pdf,
  1745 + this->m->file->getName(), "", 0,
1728 1746 "object " +
1729 1747 QUtil::int_to_string(objid) + "/" +
1730 1748 QUtil::int_to_string(generation) +
... ... @@ -1738,7 +1756,7 @@ QPDF::resolve(int objid, int generation)
1738 1756 }
1739 1757 catch (std::exception& e)
1740 1758 {
1741   - warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), "", 0,
  1759 + warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), "", 0,
1742 1760 "object " +
1743 1761 QUtil::int_to_string(objid) + "/" +
1744 1762 QUtil::int_to_string(generation) +
... ... @@ -1748,12 +1766,12 @@ QPDF::resolve(int objid, int generation)
1748 1766 {
1749 1767 QTC::TC("qpdf", "QPDF resolve failure to null");
1750 1768 QPDFObjectHandle oh = QPDFObjectHandle::newNull();
1751   - this->obj_cache[og] =
  1769 + this->m->obj_cache[og] =
1752 1770 ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1);
1753 1771 }
1754 1772 }
1755 1773  
1756   - return this->obj_cache[og].object;
  1774 + return this->m->obj_cache[og].object;
1757 1775 }
1758 1776  
1759 1777 void
... ... @@ -1763,9 +1781,9 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1763 1781 QPDFObjectHandle obj_stream = getObjectByID(obj_stream_number, 0);
1764 1782 if (! obj_stream.isStream())
1765 1783 {
1766   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1767   - this->last_object_description,
1768   - this->file->getLastOffset(),
  1784 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  1785 + this->m->last_object_description,
  1786 + this->m->file->getLastOffset(),
1769 1787 "supposed object stream " +
1770 1788 QUtil::int_to_string(obj_stream_number) +
1771 1789 " is not a stream");
... ... @@ -1775,18 +1793,18 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1775 1793 // object stream for the objects in the stream.
1776 1794 QPDFObjGen stream_og(obj_stream_number, 0);
1777 1795 qpdf_offset_t end_before_space =
1778   - this->obj_cache[stream_og].end_before_space;
  1796 + this->m->obj_cache[stream_og].end_before_space;
1779 1797 qpdf_offset_t end_after_space =
1780   - this->obj_cache[stream_og].end_after_space;
  1798 + this->m->obj_cache[stream_og].end_after_space;
1781 1799  
1782 1800 QPDFObjectHandle dict = obj_stream.getDict();
1783 1801 if (! (dict.getKey("/Type").isName() &&
1784 1802 dict.getKey("/Type").getName() == "/ObjStm"))
1785 1803 {
1786 1804 QTC::TC("qpdf", "QPDF ERR object stream with wrong type");
1787   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1788   - this->last_object_description,
1789   - this->file->getLastOffset(),
  1805 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  1806 + this->m->last_object_description,
  1807 + this->m->file->getLastOffset(),
1790 1808 "supposed object stream " +
1791 1809 QUtil::int_to_string(obj_stream_number) +
1792 1810 " has wrong type");
... ... @@ -1795,9 +1813,9 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1795 1813 if (! (dict.getKey("/N").isInteger() &&
1796 1814 dict.getKey("/First").isInteger()))
1797 1815 {
1798   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1799   - this->last_object_description,
1800   - this->file->getLastOffset(),
  1816 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  1817 + this->m->last_object_description,
  1818 + this->m->file->getLastOffset(),
1801 1819 "object stream " +
1802 1820 QUtil::int_to_string(obj_stream_number) +
1803 1821 " has incorrect keys");
... ... @@ -1821,7 +1839,8 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1821 1839 (toffset.getType() == QPDFTokenizer::tt_integer)))
1822 1840 {
1823 1841 throw QPDFExc(qpdf_e_damaged_pdf, input->getName(),
1824   - this->last_object_description, input->getLastOffset(),
  1842 + this->m->last_object_description,
  1843 + input->getLastOffset(),
1825 1844 "expected integer in object stream header");
1826 1845 }
1827 1846  
... ... @@ -1840,14 +1859,14 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
1840 1859 {
1841 1860 int obj = (*iter).first;
1842 1861 QPDFObjGen og(obj, 0);
1843   - QPDFXRefEntry const& entry = this->xref_table[og];
  1862 + QPDFXRefEntry const& entry = this->m->xref_table[og];
1844 1863 if ((entry.getType() == 2) &&
1845 1864 (entry.getObjStreamNumber() == obj_stream_number))
1846 1865 {
1847 1866 int offset = (*iter).second;
1848 1867 input->seek(offset, SEEK_SET);
1849 1868 QPDFObjectHandle oh = readObject(input, "", obj, 0, true);
1850   - this->obj_cache[og] =
  1869 + this->m->obj_cache[og] =
1851 1870 ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh),
1852 1871 end_before_space, end_after_space);
1853 1872 }
... ... @@ -1862,16 +1881,16 @@ QPDFObjectHandle
1862 1881 QPDF::makeIndirectObject(QPDFObjectHandle oh)
1863 1882 {
1864 1883 QPDFObjGen o1(0, 0);
1865   - if (! this->obj_cache.empty())
  1884 + if (! this->m->obj_cache.empty())
1866 1885 {
1867   - o1 = (*(this->obj_cache.rbegin())).first;
  1886 + o1 = (*(this->m->obj_cache.rbegin())).first;
1868 1887 }
1869   - QPDFObjGen o2 = (*(this->xref_table.rbegin())).first;
  1888 + QPDFObjGen o2 = (*(this->m->xref_table.rbegin())).first;
1870 1889 QTC::TC("qpdf", "QPDF indirect last obj from xref",
1871 1890 (o2.getObj() > o1.getObj()) ? 1 : 0);
1872 1891 int max_objid = std::max(o1.getObj(), o2.getObj());
1873 1892 QPDFObjGen next(max_objid + 1, 0);
1874   - this->obj_cache[next] =
  1893 + this->m->obj_cache[next] =
1875 1894 ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1);
1876 1895 return QPDFObjectHandle::Factory::newIndirect(
1877 1896 this, next.getObj(), next.getGen());
... ... @@ -1910,7 +1929,7 @@ QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh)
1910 1929  
1911 1930 // Replace the object in the object cache
1912 1931 QPDFObjGen og(objid, generation);
1913   - this->obj_cache[og] =
  1932 + this->m->obj_cache[og] =
1914 1933 ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1);
1915 1934 }
1916 1935  
... ... @@ -1946,7 +1965,7 @@ QPDF::copyForeignObject(QPDFObjectHandle foreign, bool allow_page)
1946 1965 "QPDF::copyForeign called with object from this QPDF");
1947 1966 }
1948 1967  
1949   - ObjCopier& obj_copier = this->object_copiers[other];
  1968 + ObjCopier& obj_copier = this->m->object_copiers[other];
1950 1969 if (! obj_copier.visiting.empty())
1951 1970 {
1952 1971 throw std::logic_error("obj_copier.visiting is not empty"
... ... @@ -2016,7 +2035,8 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier&amp; obj_copier,
2016 2035 QTC::TC("qpdf", "QPDF loop reserving objects");
2017 2036 return;
2018 2037 }
2019   - if (obj_copier.object_map.find(foreign_og) != obj_copier.object_map.end())
  2038 + if (obj_copier.object_map.find(foreign_og) !=
  2039 + obj_copier.object_map.end())
2020 2040 {
2021 2041 QTC::TC("qpdf", "QPDF already reserved object");
2022 2042 return;
... ... @@ -2139,15 +2159,16 @@ QPDF::replaceForeignIndirectObjects(
2139 2159 replaceForeignIndirectObjects(
2140 2160 old_dict.getKey(*iter), obj_copier, false));
2141 2161 }
2142   - if (this->copied_stream_data_provider == 0)
  2162 + if (this->m->copied_stream_data_provider == 0)
2143 2163 {
2144   - this->copied_stream_data_provider = new CopiedStreamDataProvider();
2145   - this->copied_streams = this->copied_stream_data_provider;
  2164 + this->m->copied_stream_data_provider =
  2165 + new CopiedStreamDataProvider();
  2166 + this->m->copied_streams = this->m->copied_stream_data_provider;
2146 2167 }
2147 2168 QPDFObjGen local_og(result.getObjGen());
2148   - this->copied_stream_data_provider->registerForeignStream(
  2169 + this->m->copied_stream_data_provider->registerForeignStream(
2149 2170 local_og, foreign);
2150   - result.replaceStreamData(this->copied_streams,
  2171 + result.replaceStreamData(this->m->copied_streams,
2151 2172 dict.getKey("/Filter"),
2152 2173 dict.getKey("/DecodeParms"));
2153 2174 }
... ... @@ -2181,21 +2202,21 @@ QPDF::swapObjects(int objid1, int generation1, int objid2, int generation2)
2181 2202 resolve(objid2, generation2);
2182 2203 QPDFObjGen og1(objid1, generation1);
2183 2204 QPDFObjGen og2(objid2, generation2);
2184   - ObjCache t = this->obj_cache[og1];
2185   - this->obj_cache[og1] = this->obj_cache[og2];
2186   - this->obj_cache[og2] = t;
  2205 + ObjCache t = this->m->obj_cache[og1];
  2206 + this->m->obj_cache[og1] = this->m->obj_cache[og2];
  2207 + this->m->obj_cache[og2] = t;
2187 2208 }
2188 2209  
2189 2210 std::string
2190 2211 QPDF::getFilename() const
2191 2212 {
2192   - return this->file->getName();
  2213 + return this->m->file->getName();
2193 2214 }
2194 2215  
2195 2216 std::string
2196 2217 QPDF::getPDFVersion() const
2197 2218 {
2198   - return this->pdf_version;
  2219 + return this->m->pdf_version;
2199 2220 }
2200 2221  
2201 2222 int
... ... @@ -2225,17 +2246,17 @@ QPDF::getExtensionLevel()
2225 2246 QPDFObjectHandle
2226 2247 QPDF::getTrailer()
2227 2248 {
2228   - return this->trailer;
  2249 + return this->m->trailer;
2229 2250 }
2230 2251  
2231 2252 QPDFObjectHandle
2232 2253 QPDF::getRoot()
2233 2254 {
2234   - QPDFObjectHandle root = this->trailer.getKey("/Root");
  2255 + QPDFObjectHandle root = this->m->trailer.getKey("/Root");
2235 2256 if (! root.isDictionary())
2236 2257 {
2237   - throw QPDFExc(qpdf_e_damaged_pdf, file->getName(),
2238   - "", file->getLastOffset(),
  2258 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  2259 + "", this->m->file->getLastOffset(),
2239 2260 "unable to find /Root dictionary");
2240 2261 }
2241 2262 return root;
... ... @@ -2245,8 +2266,8 @@ void
2245 2266 QPDF::getObjectStreamData(std::map<int, int>& omap)
2246 2267 {
2247 2268 for (std::map<QPDFObjGen, QPDFXRefEntry>::iterator iter =
2248   - this->xref_table.begin();
2249   - iter != this->xref_table.end(); ++iter)
  2269 + this->m->xref_table.begin();
  2270 + iter != this->m->xref_table.end(); ++iter)
2250 2271 {
2251 2272 QPDFObjGen const& og = (*iter).first;
2252 2273 QPDFXRefEntry const& entry = (*iter).second;
... ... @@ -2270,12 +2291,13 @@ QPDF::getCompressibleObjGens()
2270 2291 // orphaned items.
2271 2292  
2272 2293 // Exclude encryption dictionary, if any
2273   - QPDFObjectHandle encryption_dict = trailer.getKey("/Encrypt");
  2294 + QPDFObjectHandle encryption_dict =
  2295 + this->m->trailer.getKey("/Encrypt");
2274 2296 QPDFObjGen encryption_dict_og = encryption_dict.getObjGen();
2275 2297  
2276 2298 std::set<QPDFObjGen> visited;
2277 2299 std::list<QPDFObjectHandle> queue;
2278   - queue.push_front(this->trailer);
  2300 + queue.push_front(this->m->trailer);
2279 2301 std::vector<QPDFObjGen> result;
2280 2302 while (! queue.empty())
2281 2303 {
... ... @@ -2353,25 +2375,25 @@ QPDF::pipeStreamData(int objid, int generation,
2353 2375 {
2354 2376 bool success = false;
2355 2377 std::vector<PointerHolder<Pipeline> > to_delete;
2356   - if (this->encrypted)
  2378 + if (this->m->encrypted)
2357 2379 {
2358 2380 decryptStream(pipeline, objid, generation, stream_dict, to_delete);
2359 2381 }
2360 2382  
2361 2383 try
2362 2384 {
2363   - this->file->seek(offset, SEEK_SET);
  2385 + this->m->file->seek(offset, SEEK_SET);
2364 2386 char buf[10240];
2365 2387 while (length > 0)
2366 2388 {
2367 2389 size_t to_read = (sizeof(buf) < length ? sizeof(buf) : length);
2368   - size_t len = this->file->read(buf, to_read);
  2390 + size_t len = this->m->file->read(buf, to_read);
2369 2391 if (len == 0)
2370 2392 {
2371 2393 throw QPDFExc(qpdf_e_damaged_pdf,
2372   - this->file->getName(),
2373   - this->last_object_description,
2374   - this->file->getLastOffset(),
  2394 + this->m->file->getName(),
  2395 + this->m->last_object_description,
  2396 + this->m->file->getLastOffset(),
2375 2397 "unexpected EOF reading stream data");
2376 2398 }
2377 2399 length -= len;
... ... @@ -2392,8 +2414,8 @@ QPDF::pipeStreamData(int objid, int generation,
2392 2414 if (! suppress_warnings)
2393 2415 {
2394 2416 QTC::TC("qpdf", "QPDF decoding error warning");
2395   - warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
2396   - "", this->file->getLastOffset(),
  2417 + warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  2418 + "", this->m->file->getLastOffset(),
2397 2419 "error decoding stream data for object " +
2398 2420 QUtil::int_to_string(objid) + " " +
2399 2421 QUtil::int_to_string(generation) + ": " + e.what()));
... ... @@ -2442,7 +2464,7 @@ QPDF::findAttachmentStreams()
2442 2464 item.getKey("/EF").getKey("/F").isStream())
2443 2465 {
2444 2466 QPDFObjectHandle stream = item.getKey("/EF").getKey("/F");
2445   - this->attachment_streams.insert(stream.getObjGen());
  2467 + this->m->attachment_streams.insert(stream.getObjGen());
2446 2468 }
2447 2469 }
2448 2470 }
... ...
libqpdf/QPDF_encryption.cc
... ... @@ -760,9 +760,9 @@ QPDF::interpretCF(QPDFObjectHandle cf)
760 760 if (cf.isName())
761 761 {
762 762 std::string filter = cf.getName();
763   - if (this->crypt_filters.count(filter) != 0)
  763 + if (this->m->crypt_filters.count(filter) != 0)
764 764 {
765   - return this->crypt_filters[filter];
  765 + return this->m->crypt_filters[filter];
766 766 }
767 767 else if (filter == "/Identity")
768 768 {
... ... @@ -783,29 +783,29 @@ QPDF::interpretCF(QPDFObjectHandle cf)
783 783 void
784 784 QPDF::initializeEncryption()
785 785 {
786   - if (this->encryption_initialized)
  786 + if (this->m->encryption_initialized)
787 787 {
788 788 return;
789 789 }
790   - this->encryption_initialized = true;
  790 + this->m->encryption_initialized = true;
791 791  
792 792 // After we initialize encryption parameters, we must used stored
793 793 // key information and never look at /Encrypt again. Otherwise,
794 794 // things could go wrong if someone mutates the encryption
795 795 // dictionary.
796 796  
797   - if (! this->trailer.hasKey("/Encrypt"))
  797 + if (! this->m->trailer.hasKey("/Encrypt"))
798 798 {
799 799 return;
800 800 }
801 801  
802   - // Go ahead and set this->encryption here. That way, isEncrypted
  802 + // Go ahead and set this->m->encrypted here. That way, isEncrypted
803 803 // will return true even if there were errors reading the
804 804 // encryption dictionary.
805   - this->encrypted = true;
  805 + this->m->encrypted = true;
806 806  
807 807 std::string id1;
808   - QPDFObjectHandle id_obj = this->trailer.getKey("/ID");
  808 + QPDFObjectHandle id_obj = this->m->trailer.getKey("/ID");
809 809 if ((id_obj.isArray() &&
810 810 (id_obj.getArrayNItems() == 2) &&
811 811 id_obj.getArrayItem(0).isString()))
... ... @@ -817,31 +817,31 @@ QPDF::initializeEncryption()
817 817 // Treating a missing ID as the empty string enables qpdf to
818 818 // decrypt some invalid encrypted files with no /ID that
819 819 // poppler can read but Adobe Reader can't.
820   - warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
821   - "trailer", this->file->getLastOffset(),
  820 + warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  821 + "trailer", this->m->file->getLastOffset(),
822 822 "invalid /ID in trailer dictionary"));
823 823 }
824 824  
825   - QPDFObjectHandle encryption_dict = this->trailer.getKey("/Encrypt");
  825 + QPDFObjectHandle encryption_dict = this->m->trailer.getKey("/Encrypt");
826 826 if (! encryption_dict.isDictionary())
827 827 {
828   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
829   - this->last_object_description,
830   - this->file->getLastOffset(),
  828 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  829 + this->m->last_object_description,
  830 + this->m->file->getLastOffset(),
831 831 "/Encrypt in trailer dictionary is not a dictionary");
832 832 }
833 833  
834 834 if (! (encryption_dict.getKey("/Filter").isName() &&
835 835 (encryption_dict.getKey("/Filter").getName() == "/Standard")))
836 836 {
837   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
838   - "encryption dictionary", this->file->getLastOffset(),
  837 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  838 + "encryption dictionary", this->m->file->getLastOffset(),
839 839 "unsupported encryption filter");
840 840 }
841 841 if (! encryption_dict.getKey("/SubFilter").isNull())
842 842 {
843   - warn(QPDFExc(qpdf_e_unsupported, this->file->getName(),
844   - "encryption dictionary", this->file->getLastOffset(),
  843 + warn(QPDFExc(qpdf_e_unsupported, this->m->file->getName(),
  844 + "encryption dictionary", this->m->file->getLastOffset(),
845 845 "file uses encryption SubFilters,"
846 846 " which qpdf does not support"));
847 847 }
... ... @@ -852,8 +852,8 @@ QPDF::initializeEncryption()
852 852 encryption_dict.getKey("/U").isString() &&
853 853 encryption_dict.getKey("/P").isInteger()))
854 854 {
855   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
856   - "encryption dictionary", this->file->getLastOffset(),
  855 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  856 + "encryption dictionary", this->m->file->getLastOffset(),
857 857 "some encryption dictionary parameters are missing "
858 858 "or the wrong type");
859 859 }
... ... @@ -869,15 +869,15 @@ QPDF::initializeEncryption()
869 869 if (! (((R >= 2) && (R <= 6)) &&
870 870 ((V == 1) || (V == 2) || (V == 4) || (V == 5))))
871 871 {
872   - throw QPDFExc(qpdf_e_unsupported, this->file->getName(),
873   - "encryption dictionary", this->file->getLastOffset(),
  872 + throw QPDFExc(qpdf_e_unsupported, this->m->file->getName(),
  873 + "encryption dictionary", this->m->file->getLastOffset(),
874 874 "Unsupported /R or /V in encryption dictionary; R = " +
875 875 QUtil::int_to_string(R) + " (max 6), V = " +
876 876 QUtil::int_to_string(V) + " (max 5)");
877 877 }
878 878  
879   - this->encryption_V = V;
880   - this->encryption_R = R;
  879 + this->m->encryption_V = V;
  880 + this->m->encryption_R = R;
881 881  
882 882 // OE, UE, and Perms are only present if V >= 5.
883 883 std::string OE;
... ... @@ -890,8 +890,9 @@ QPDF::initializeEncryption()
890 890 pad_short_parameter(U, key_bytes);
891 891 if (! ((O.length() == key_bytes) && (U.length() == key_bytes)))
892 892 {
893   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
894   - "encryption dictionary", this->file->getLastOffset(),
  893 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  894 + "encryption dictionary",
  895 + this->m->file->getLastOffset(),
895 896 "incorrect length for /O and/or /U in "
896 897 "encryption dictionary");
897 898 }
... ... @@ -902,8 +903,9 @@ QPDF::initializeEncryption()
902 903 encryption_dict.getKey("/UE").isString() &&
903 904 encryption_dict.getKey("/Perms").isString()))
904 905 {
905   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
906   - "encryption dictionary", this->file->getLastOffset(),
  906 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  907 + "encryption dictionary",
  908 + this->m->file->getLastOffset(),
907 909 "some V=5 encryption dictionary parameters are "
908 910 "missing or the wrong type");
909 911 }
... ... @@ -922,8 +924,9 @@ QPDF::initializeEncryption()
922 924 (UE.length() < OUE_key_bytes_V5) ||
923 925 (Perms.length() < Perms_key_bytes_V5))
924 926 {
925   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
926   - "encryption dictionary", this->file->getLastOffset(),
  927 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  928 + "encryption dictionary",
  929 + this->m->file->getLastOffset(),
927 930 "incorrect length for some of"
928 931 " /O, /U, /OE, /UE, or /Perms in"
929 932 " encryption dictionary");
... ... @@ -936,16 +939,17 @@ QPDF::initializeEncryption()
936 939 Length = encryption_dict.getKey("/Length").getIntValue();
937 940 if ((Length % 8) || (Length < 40) || (Length > 256))
938 941 {
939   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
940   - "encryption dictionary", this->file->getLastOffset(),
  942 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  943 + "encryption dictionary",
  944 + this->m->file->getLastOffset(),
941 945 "invalid /Length value in encryption dictionary");
942 946 }
943 947 }
944 948  
945   - this->encrypt_metadata = true;
  949 + this->m->encrypt_metadata = true;
946 950 if ((V >= 4) && (encryption_dict.getKey("/EncryptMetadata").isBool()))
947 951 {
948   - this->encrypt_metadata =
  952 + this->m->encrypt_metadata =
949 953 encryption_dict.getKey("/EncryptMetadata").getBoolValue();
950 954 }
951 955  
... ... @@ -986,40 +990,40 @@ QPDF::initializeEncryption()
986 990 method = e_unknown;
987 991 }
988 992 }
989   - this->crypt_filters[filter] = method;
  993 + this->m->crypt_filters[filter] = method;
990 994 }
991 995 }
992 996  
993 997 QPDFObjectHandle StmF = encryption_dict.getKey("/StmF");
994 998 QPDFObjectHandle StrF = encryption_dict.getKey("/StrF");
995 999 QPDFObjectHandle EFF = encryption_dict.getKey("/EFF");
996   - this->cf_stream = interpretCF(StmF);
997   - this->cf_string = interpretCF(StrF);
  1000 + this->m->cf_stream = interpretCF(StmF);
  1001 + this->m->cf_string = interpretCF(StrF);
998 1002 if (EFF.isName())
999 1003 {
1000   - this->cf_file = interpretCF(EFF);
  1004 + this->m->cf_file = interpretCF(EFF);
1001 1005 }
1002 1006 else
1003 1007 {
1004   - this->cf_file = this->cf_stream;
  1008 + this->m->cf_file = this->m->cf_stream;
1005 1009 }
1006 1010 }
1007 1011  
1008 1012 EncryptionData data(V, R, Length / 8, P, O, U, OE, UE, Perms,
1009   - id1, this->encrypt_metadata);
  1013 + id1, this->m->encrypt_metadata);
1010 1014 if (check_owner_password(
1011   - this->user_password, this->provided_password, data))
  1015 + this->m->user_password, this->m->provided_password, data))
1012 1016 {
1013 1017 // password supplied was owner password; user_password has
1014 1018 // been initialized for V < 5
1015 1019 }
1016   - else if (check_user_password(this->provided_password, data))
  1020 + else if (check_user_password(this->m->provided_password, data))
1017 1021 {
1018   - this->user_password = this->provided_password;
  1022 + this->m->user_password = this->m->provided_password;
1019 1023 }
1020 1024 else
1021 1025 {
1022   - throw QPDFExc(qpdf_e_password, this->file->getName(),
  1026 + throw QPDFExc(qpdf_e_password, this->m->file->getName(),
1023 1027 "", 0, "invalid password");
1024 1028 }
1025 1029  
... ... @@ -1028,8 +1032,8 @@ QPDF::initializeEncryption()
1028 1032 // For V < 5, the user password is encrypted with the owner
1029 1033 // password, and the user password is always used for
1030 1034 // computing the encryption key.
1031   - this->encryption_key = compute_encryption_key(
1032   - this->user_password, data);
  1035 + this->m->encryption_key = compute_encryption_key(
  1036 + this->m->user_password, data);
1033 1037 }
1034 1038 else
1035 1039 {
... ... @@ -1037,12 +1041,13 @@ QPDF::initializeEncryption()
1037 1041 // compute the encryption key, and neither password can be
1038 1042 // used to recover the other.
1039 1043 bool perms_valid;
1040   - this->encryption_key = recover_encryption_key_with_password(
1041   - this->provided_password, data, perms_valid);
  1044 + this->m->encryption_key = recover_encryption_key_with_password(
  1045 + this->m->provided_password, data, perms_valid);
1042 1046 if (! perms_valid)
1043 1047 {
1044   - warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1045   - "encryption dictionary", this->file->getLastOffset(),
  1048 + warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  1049 + "encryption dictionary",
  1050 + this->m->file->getLastOffset(),
1046 1051 "/Perms field in encryption dictionary"
1047 1052 " doesn't match expected value"));
1048 1053 }
... ... @@ -1052,23 +1057,24 @@ QPDF::initializeEncryption()
1052 1057 std::string
1053 1058 QPDF::getKeyForObject(int objid, int generation, bool use_aes)
1054 1059 {
1055   - if (! this->encrypted)
  1060 + if (! this->m->encrypted)
1056 1061 {
1057 1062 throw std::logic_error(
1058 1063 "request for encryption key in non-encrypted PDF");
1059 1064 }
1060 1065  
1061   - if (! ((objid == this->cached_key_objid) &&
1062   - (generation == this->cached_key_generation)))
  1066 + if (! ((objid == this->m->cached_key_objid) &&
  1067 + (generation == this->m->cached_key_generation)))
1063 1068 {
1064   - this->cached_object_encryption_key =
1065   - compute_data_key(this->encryption_key, objid, generation,
1066   - use_aes, this->encryption_V, this->encryption_R);
1067   - this->cached_key_objid = objid;
1068   - this->cached_key_generation = generation;
  1069 + this->m->cached_object_encryption_key =
  1070 + compute_data_key(this->m->encryption_key, objid, generation,
  1071 + use_aes, this->m->encryption_V,
  1072 + this->m->encryption_R);
  1073 + this->m->cached_key_objid = objid;
  1074 + this->m->cached_key_generation = generation;
1069 1075 }
1070 1076  
1071   - return this->cached_object_encryption_key;
  1077 + return this->m->cached_object_encryption_key;
1072 1078 }
1073 1079  
1074 1080 void
... ... @@ -1079,9 +1085,9 @@ QPDF::decryptString(std::string&amp; str, int objid, int generation)
1079 1085 return;
1080 1086 }
1081 1087 bool use_aes = false;
1082   - if (this->encryption_V >= 4)
  1088 + if (this->m->encryption_V >= 4)
1083 1089 {
1084   - switch (this->cf_string)
  1090 + switch (this->m->cf_string)
1085 1091 {
1086 1092 case e_none:
1087 1093 return;
... ... @@ -1098,15 +1104,15 @@ QPDF::decryptString(std::string&amp; str, int objid, int generation)
1098 1104 break;
1099 1105  
1100 1106 default:
1101   - warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1102   - this->last_object_description,
1103   - this->file->getLastOffset(),
  1107 + warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  1108 + this->m->last_object_description,
  1109 + this->m->file->getLastOffset(),
1104 1110 "unknown encryption filter for strings"
1105 1111 " (check /StrF in /Encrypt dictionary);"
1106 1112 " strings may be decrypted improperly"));
1107 1113 // To avoid repeated warnings, reset cf_string. Assume
1108 1114 // we'd want to use AES if V == 4.
1109   - this->cf_string = e_aes;
  1115 + this->m->cf_string = e_aes;
1110 1116 break;
1111 1117 }
1112 1118 }
... ... @@ -1145,9 +1151,9 @@ QPDF::decryptString(std::string&amp; str, int objid, int generation)
1145 1151 }
1146 1152 catch (std::runtime_error& e)
1147 1153 {
1148   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1149   - this->last_object_description,
1150   - this->file->getLastOffset(),
  1154 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  1155 + this->m->last_object_description,
  1156 + this->m->file->getLastOffset(),
1151 1157 "error decrypting string for object " +
1152 1158 QUtil::int_to_string(objid) + " " +
1153 1159 QUtil::int_to_string(generation) + ": " + e.what());
... ... @@ -1170,7 +1176,7 @@ QPDF::decryptStream(Pipeline*&amp; pipeline, int objid, int generation,
1170 1176 return;
1171 1177 }
1172 1178 bool use_aes = false;
1173   - if (this->encryption_V >= 4)
  1179 + if (this->m->encryption_V >= 4)
1174 1180 {
1175 1181 encryption_method_e method = e_unknown;
1176 1182 std::string method_source = "/StmF from /Encrypt dictionary";
... ... @@ -1221,21 +1227,21 @@ QPDF::decryptStream(Pipeline*&amp; pipeline, int objid, int generation,
1221 1227  
1222 1228 if (method == e_unknown)
1223 1229 {
1224   - if ((! this->encrypt_metadata) && (type == "/Metadata"))
  1230 + if ((! this->m->encrypt_metadata) && (type == "/Metadata"))
1225 1231 {
1226 1232 QTC::TC("qpdf", "QPDF_encryption cleartext metadata");
1227 1233 method = e_none;
1228 1234 }
1229 1235 else
1230 1236 {
1231   - if (this->attachment_streams.count(
  1237 + if (this->m->attachment_streams.count(
1232 1238 QPDFObjGen(objid, generation)) > 0)
1233 1239 {
1234   - method = this->cf_file;
  1240 + method = this->m->cf_file;
1235 1241 }
1236 1242 else
1237 1243 {
1238   - method = this->cf_stream;
  1244 + method = this->m->cf_stream;
1239 1245 }
1240 1246 }
1241 1247 }
... ... @@ -1259,15 +1265,15 @@ QPDF::decryptStream(Pipeline*&amp; pipeline, int objid, int generation,
1259 1265  
1260 1266 default:
1261 1267 // filter local to this stream.
1262   - warn(QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
1263   - this->last_object_description,
1264   - this->file->getLastOffset(),
  1268 + warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  1269 + this->m->last_object_description,
  1270 + this->m->file->getLastOffset(),
1265 1271 "unknown encryption filter for streams"
1266 1272 " (check " + method_source + ");"
1267 1273 " streams may be decrypted improperly"));
1268 1274 // To avoid repeated warnings, reset cf_stream. Assume
1269 1275 // we'd want to use AES if V == 4.
1270   - this->cf_stream = e_aes;
  1276 + this->m->cf_stream = e_aes;
1271 1277 break;
1272 1278 }
1273 1279 }
... ... @@ -1331,13 +1337,13 @@ QPDF::compute_encryption_parameters_V5(
1331 1337 std::string const&
1332 1338 QPDF::getPaddedUserPassword() const
1333 1339 {
1334   - return this->user_password;
  1340 + return this->m->user_password;
1335 1341 }
1336 1342  
1337 1343 std::string
1338 1344 QPDF::getTrimmedUserPassword() const
1339 1345 {
1340   - std::string result = this->user_password;
  1346 + std::string result = this->m->user_password;
1341 1347 trim_user_password(result);
1342 1348 return result;
1343 1349 }
... ... @@ -1345,13 +1351,13 @@ QPDF::getTrimmedUserPassword() const
1345 1351 std::string
1346 1352 QPDF::getEncryptionKey() const
1347 1353 {
1348   - return this->encryption_key;
  1354 + return this->m->encryption_key;
1349 1355 }
1350 1356  
1351 1357 bool
1352 1358 QPDF::isEncrypted() const
1353 1359 {
1354   - return this->encrypted;
  1360 + return this->m->encrypted;
1355 1361 }
1356 1362  
1357 1363 bool
... ... @@ -1368,7 +1374,7 @@ QPDF::isEncrypted(int&amp; R, int&amp; P, int&amp; V,
1368 1374 encryption_method_e& string_method,
1369 1375 encryption_method_e& file_method)
1370 1376 {
1371   - if (this->encrypted)
  1377 + if (this->m->encrypted)
1372 1378 {
1373 1379 QPDFObjectHandle trailer = getTrailer();
1374 1380 QPDFObjectHandle encrypt = trailer.getKey("/Encrypt");
... ... @@ -1378,9 +1384,9 @@ QPDF::isEncrypted(int&amp; R, int&amp; P, int&amp; V,
1378 1384 P = Pkey.getIntValue();
1379 1385 R = Rkey.getIntValue();
1380 1386 V = Vkey.getIntValue();
1381   - stream_method = this->cf_stream;
1382   - string_method = this->cf_stream;
1383   - file_method = this->cf_file;
  1387 + stream_method = this->m->cf_stream;
  1388 + string_method = this->m->cf_stream;
  1389 + file_method = this->m->cf_file;
1384 1390 return true;
1385 1391 }
1386 1392 else
... ...
libqpdf/QPDF_linearization.cc
... ... @@ -72,7 +72,7 @@ QPDF::checkLinearization()
72 72 }
73 73 catch (QPDFExc& e)
74 74 {
75   - *out_stream << e.what() << std::endl;
  75 + *this->m->out_stream << e.what() << std::endl;
76 76 }
77 77 return result;
78 78 }
... ... @@ -82,7 +82,7 @@ QPDF::isLinearized()
82 82 {
83 83 // If the first object in the file is a dictionary with a suitable
84 84 // /Linearized key and has an /L key that accurately indicates the
85   - // file size, initialize this->lindict and return true.
  85 + // file size, initialize this->m->lindict and return true.
86 86  
87 87 // A linearized PDF spec's first object will be contained within
88 88 // the first 1024 bytes of the file and will be a dictionary with
... ... @@ -95,10 +95,10 @@ QPDF::isLinearized()
95 95 static int const tbuf_size = 1025;
96 96  
97 97 char* buf = new char[tbuf_size];
98   - this->file->seek(0, SEEK_SET);
  98 + this->m->file->seek(0, SEEK_SET);
99 99 PointerHolder<char> b(true, buf);
100 100 memset(buf, '\0', tbuf_size);
101   - this->file->read(buf, tbuf_size - 1);
  101 + this->m->file->read(buf, tbuf_size - 1);
102 102  
103 103 int lindict_obj = -1;
104 104 char* p = buf;
... ... @@ -115,16 +115,16 @@ QPDF::isLinearized()
115 115 }
116 116 // Seek to the digit. Then skip over digits for a potential
117 117 // next iteration.
118   - this->file->seek(p - buf, SEEK_SET);
  118 + this->m->file->seek(p - buf, SEEK_SET);
119 119 while (((p - buf) < tbuf_size) && QUtil::is_digit(*p))
120 120 {
121 121 ++p;
122 122 }
123 123  
124   - QPDFTokenizer::Token t1 = readToken(this->file, true);
125   - QPDFTokenizer::Token t2 = readToken(this->file, true);
126   - QPDFTokenizer::Token t3 = readToken(this->file, true);
127   - QPDFTokenizer::Token t4 = readToken(this->file, true);
  124 + QPDFTokenizer::Token t1 = readToken(this->m->file, true);
  125 + QPDFTokenizer::Token t2 = readToken(this->m->file, true);
  126 + QPDFTokenizer::Token t3 = readToken(this->m->file, true);
  127 + QPDFTokenizer::Token t4 = readToken(this->m->file, true);
128 128 if ((t1.getType() == QPDFTokenizer::tt_integer) &&
129 129 (t2.getType() == QPDFTokenizer::tt_integer) &&
130 130 (t3 == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "obj")) &&
... ... @@ -158,19 +158,19 @@ QPDF::isLinearized()
158 158 if (L.isInteger())
159 159 {
160 160 qpdf_offset_t Li = L.getIntValue();
161   - this->file->seek(0, SEEK_END);
162   - if (Li != this->file->tell())
  161 + this->m->file->seek(0, SEEK_END);
  162 + if (Li != this->m->file->tell())
163 163 {
164 164 QTC::TC("qpdf", "QPDF /L mismatch");
165 165 return false;
166 166 }
167 167 else
168 168 {
169   - this->linp.file_size = Li;
  169 + this->m->linp.file_size = Li;
170 170 }
171 171 }
172 172  
173   - this->lindict = candidate;
  173 + this->m->lindict = candidate;
174 174  
175 175 return true;
176 176 }
... ... @@ -191,12 +191,12 @@ QPDF::readLinearizationData()
191 191 }
192 192  
193 193 // /L is read and stored in linp by isLinearized()
194   - QPDFObjectHandle H = lindict.getKey("/H");
195   - QPDFObjectHandle O = lindict.getKey("/O");
196   - QPDFObjectHandle E = lindict.getKey("/E");
197   - QPDFObjectHandle N = lindict.getKey("/N");
198   - QPDFObjectHandle T = lindict.getKey("/T");
199   - QPDFObjectHandle P = lindict.getKey("/P");
  194 + QPDFObjectHandle H = this->m->lindict.getKey("/H");
  195 + QPDFObjectHandle O = this->m->lindict.getKey("/O");
  196 + QPDFObjectHandle E = this->m->lindict.getKey("/E");
  197 + QPDFObjectHandle N = this->m->lindict.getKey("/N");
  198 + QPDFObjectHandle T = this->m->lindict.getKey("/T");
  199 + QPDFObjectHandle P = this->m->lindict.getKey("/P");
200 200  
201 201 if (! (H.isArray() &&
202 202 O.isInteger() &&
... ... @@ -205,9 +205,9 @@ QPDF::readLinearizationData()
205 205 T.isInteger() &&
206 206 (P.isInteger() || P.isNull())))
207 207 {
208   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  208 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
209 209 "linearization dictionary",
210   - this->file->getLastOffset(),
  210 + this->m->file->getLastOffset(),
211 211 "some keys in linearization dictionary are of "
212 212 "the wrong type");
213 213 }
... ... @@ -216,9 +216,9 @@ QPDF::readLinearizationData()
216 216 unsigned int n_H_items = H.getArrayNItems();
217 217 if (! ((n_H_items == 2) || (n_H_items == 4)))
218 218 {
219   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  219 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
220 220 "linearization dictionary",
221   - this->file->getLastOffset(),
  221 + this->m->file->getLastOffset(),
222 222 "H has the wrong number of items");
223 223 }
224 224  
... ... @@ -232,9 +232,9 @@ QPDF::readLinearizationData()
232 232 }
233 233 else
234 234 {
235   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  235 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
236 236 "linearization dictionary",
237   - this->file->getLastOffset(),
  237 + this->m->file->getLastOffset(),
238 238 "some H items are of the wrong type");
239 239 }
240 240 }
... ... @@ -272,20 +272,20 @@ QPDF::readLinearizationData()
272 272 // accurate and bail right now if it's not.
273 273 if (N.getIntValue() != static_cast<long long>(getAllPages().size()))
274 274 {
275   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  275 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
276 276 "linearization hint table",
277   - this->file->getLastOffset(),
  277 + this->m->file->getLastOffset(),
278 278 "/N does not match number of pages");
279 279 }
280 280  
281 281 // file_size initialized by isLinearized()
282   - this->linp.first_page_object = O.getIntValue();
283   - this->linp.first_page_end = E.getIntValue();
284   - this->linp.npages = N.getIntValue();
285   - this->linp.xref_zero_offset = T.getIntValue();
286   - this->linp.first_page = first_page;
287   - this->linp.H_offset = H0_offset;
288   - this->linp.H_length = H0_length;
  282 + this->m->linp.first_page_object = O.getIntValue();
  283 + this->m->linp.first_page_end = E.getIntValue();
  284 + this->m->linp.npages = N.getIntValue();
  285 + this->m->linp.xref_zero_offset = T.getIntValue();
  286 + this->m->linp.first_page = first_page;
  287 + this->m->linp.H_offset = H0_offset;
  288 + this->m->linp.H_length = H0_length;
289 289  
290 290 // Read hint streams
291 291  
... ... @@ -320,9 +320,9 @@ QPDF::readLinearizationData()
320 320 int HSi = HS.getIntValue();
321 321 if ((HSi < 0) || (HSi >= h_size))
322 322 {
323   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  323 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
324 324 "linearization hint table",
325   - this->file->getLastOffset(),
  325 + this->m->file->getLastOffset(),
326 326 "/S (shared object) offset is out of bounds");
327 327 }
328 328 readHSharedObject(BitStream(h_buf + HSi, h_size - HSi));
... ... @@ -332,13 +332,13 @@ QPDF::readLinearizationData()
332 332 int HOi = HO.getIntValue();
333 333 if ((HOi < 0) || (HOi >= h_size))
334 334 {
335   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  335 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
336 336 "linearization hint table",
337   - this->file->getLastOffset(),
  337 + this->m->file->getLastOffset(),
338 338 "/O (outline) offset is out of bounds");
339 339 }
340 340 readHGeneric(BitStream(h_buf + HOi, h_size - HOi),
341   - this->outline_hints);
  341 + this->m->outline_hints);
342 342 }
343 343 }
344 344  
... ... @@ -349,14 +349,14 @@ QPDF::readHintStream(Pipeline&amp; pl, qpdf_offset_t offset, size_t length)
349 349 int gen;
350 350 QPDFObjectHandle H = readObjectAtOffset(
351 351 false, offset, "linearization hint stream", -1, 0, obj, gen);
352   - ObjCache& oc = this->obj_cache[QPDFObjGen(obj, gen)];
  352 + ObjCache& oc = this->m->obj_cache[QPDFObjGen(obj, gen)];
353 353 qpdf_offset_t min_end_offset = oc.end_before_space;
354 354 qpdf_offset_t max_end_offset = oc.end_after_space;
355 355 if (! H.isStream())
356 356 {
357   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  357 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
358 358 "linearization dictionary",
359   - this->file->getLastOffset(),
  359 + this->m->file->getLastOffset(),
360 360 "hint table is not a stream");
361 361 }
362 362  
... ... @@ -373,7 +373,7 @@ QPDF::readHintStream(Pipeline&amp; pl, qpdf_offset_t offset, size_t length)
373 373 QTC::TC("qpdf", "QPDF hint table length indirect");
374 374 // Force resolution
375 375 (void) length_obj.getIntValue();
376   - ObjCache& oc = this->obj_cache[length_obj.getObjGen()];
  376 + ObjCache& oc = this->m->obj_cache[length_obj.getObjGen()];
377 377 min_end_offset = oc.end_before_space;
378 378 max_end_offset = oc.end_after_space;
379 379 }
... ... @@ -385,12 +385,12 @@ QPDF::readHintStream(Pipeline&amp; pl, qpdf_offset_t offset, size_t length)
385 385 if ((computed_end < min_end_offset) ||
386 386 (computed_end > max_end_offset))
387 387 {
388   - *out_stream << "expected = " << computed_end
389   - << "; actual = " << min_end_offset << ".."
390   - << max_end_offset << std::endl;
391   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  388 + *this->m->out_stream << "expected = " << computed_end
  389 + << "; actual = " << min_end_offset << ".."
  390 + << max_end_offset << std::endl;
  391 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
392 392 "linearization dictionary",
393   - this->file->getLastOffset(),
  393 + this->m->file->getLastOffset(),
394 394 "hint table length mismatch");
395 395 }
396 396 H.pipeStreamData(&pl, 0, qpdf_dl_specialized);
... ... @@ -403,7 +403,7 @@ QPDF::readHPageOffset(BitStream h)
403 403 // All comments referring to the PDF spec refer to the spec for
404 404 // version 1.4.
405 405  
406   - HPageOffset& t = this->page_offset_hints;
  406 + HPageOffset& t = this->m->page_offset_hints;
407 407  
408 408 t.min_nobjects = h.getBits(32); // 1
409 409 t.first_page_offset = h.getBits(32); // 2
... ... @@ -421,7 +421,7 @@ QPDF::readHPageOffset(BitStream h)
421 421  
422 422 std::vector<HPageOffsetEntry>& entries = t.entries;
423 423 entries.clear();
424   - unsigned int nitems = this->linp.npages;
  424 + unsigned int nitems = this->m->linp.npages;
425 425 load_vector_int(h, nitems, entries,
426 426 t.nbits_delta_nobjects,
427 427 &HPageOffsetEntry::delta_nobjects);
... ... @@ -450,7 +450,7 @@ QPDF::readHPageOffset(BitStream h)
450 450 void
451 451 QPDF::readHSharedObject(BitStream h)
452 452 {
453   - HSharedObject& t = this->shared_object_hints;
  453 + HSharedObject& t = this->m->shared_object_hints;
454 454  
455 455 t.first_shared_obj = h.getBits(32); // 1
456 456 t.first_shared_offset = h.getBits(32); // 2
... ... @@ -509,7 +509,7 @@ QPDF::checkLinearizationInternal()
509 509  
510 510 // Check all values in linearization parameter dictionary
511 511  
512   - LinParameters& p = this->linp;
  512 + LinParameters& p = this->m->linp;
513 513  
514 514 // L: file size in bytes -- checked by isLinearized
515 515  
... ... @@ -533,7 +533,7 @@ QPDF::checkLinearizationInternal()
533 533 {
534 534 QPDFObjectHandle const& page = pages.at(i);
535 535 QPDFObjGen og(page.getObjGen());
536   - if (this->xref_table[og].getType() == 2)
  536 + if (this->m->xref_table[og].getType() == 2)
537 537 {
538 538 errors.push_back("page dictionary for page " +
539 539 QUtil::int_to_string(i) + " is compressed");
... ... @@ -541,25 +541,25 @@ QPDF::checkLinearizationInternal()
541 541 }
542 542  
543 543 // T: offset of whitespace character preceding xref entry for object 0
544   - this->file->seek(p.xref_zero_offset, SEEK_SET);
  544 + this->m->file->seek(p.xref_zero_offset, SEEK_SET);
545 545 while (1)
546 546 {
547 547 char ch;
548   - this->file->read(&ch, 1);
  548 + this->m->file->read(&ch, 1);
549 549 if (! ((ch == ' ') || (ch == '\r') || (ch == '\n')))
550 550 {
551   - this->file->seek(-1, SEEK_CUR);
  551 + this->m->file->seek(-1, SEEK_CUR);
552 552 break;
553 553 }
554 554 }
555   - if (this->file->tell() != this->first_xref_item_offset)
  555 + if (this->m->file->tell() != this->m->first_xref_item_offset)
556 556 {
557 557 QTC::TC("qpdf", "QPDF err /T mismatch");
558 558 errors.push_back("space before first xref item (/T) mismatch "
559 559 "(computed = " +
560   - QUtil::int_to_string(this->first_xref_item_offset) +
  560 + QUtil::int_to_string(this->m->first_xref_item_offset) +
561 561 "; file = " +
562   - QUtil::int_to_string(this->file->tell()));
  562 + QUtil::int_to_string(this->m->file->tell()));
563 563 }
564 564  
565 565 // P: first page number -- Implementation note 124 says Acrobat
... ... @@ -570,7 +570,7 @@ QPDF::checkLinearizationInternal()
570 570 // at the end of the containing xref section if any object streams
571 571 // are in use.
572 572  
573   - if (this->uncompressed_after_compressed)
  573 + if (this->m->uncompressed_after_compressed)
574 574 {
575 575 errors.push_back("linearized file contains an uncompressed object"
576 576 " after a compressed one in a cross-reference stream");
... ... @@ -584,8 +584,8 @@ QPDF::checkLinearizationInternal()
584 584 { // local scope
585 585 std::map<int, int> object_stream_data;
586 586 for (std::map<QPDFObjGen, QPDFXRefEntry>::const_iterator iter =
587   - this->xref_table.begin();
588   - iter != this->xref_table.end(); ++iter)
  587 + this->m->xref_table.begin();
  588 + iter != this->m->xref_table.end(); ++iter)
589 589 {
590 590 QPDFObjGen const& og = (*iter).first;
591 591 QPDFXRefEntry const& entry = (*iter).second;
... ... @@ -609,22 +609,22 @@ QPDF::checkLinearizationInternal()
609 609 // agree with pdlin. As of this writing, the test suite doesn't
610 610 // contain any files with threads.
611 611  
612   - if (this->part6.empty())
  612 + if (this->m->part6.empty())
613 613 {
614 614 throw std::logic_error("linearization part 6 unexpectedly empty");
615 615 }
616 616 qpdf_offset_t min_E = -1;
617 617 qpdf_offset_t max_E = -1;
618   - for (std::vector<QPDFObjectHandle>::iterator iter = this->part6.begin();
619   - iter != this->part6.end(); ++iter)
  618 + for (std::vector<QPDFObjectHandle>::iterator iter = this->m->part6.begin();
  619 + iter != this->m->part6.end(); ++iter)
620 620 {
621 621 QPDFObjGen og((*iter).getObjGen());
622   - if (this->obj_cache.count(og) == 0)
  622 + if (this->m->obj_cache.count(og) == 0)
623 623 {
624 624 // All objects have to have been dereferenced to be classified.
625 625 throw std::logic_error("linearization part6 object not in cache");
626 626 }
627   - ObjCache const& oc = this->obj_cache[og];
  627 + ObjCache const& oc = this->m->obj_cache[og];
628 628 min_E = std::max(min_E, oc.end_before_space);
629 629 max_E = std::max(max_E, oc.end_after_space);
630 630 }
... ... @@ -655,7 +655,7 @@ QPDF::checkLinearizationInternal()
655 655 for (std::list<std::string>::iterator iter = errors.begin();
656 656 iter != errors.end(); ++iter)
657 657 {
658   - *out_stream << "ERROR: " << (*iter) << std::endl;
  658 + *this->m->out_stream << "ERROR: " << (*iter) << std::endl;
659 659 }
660 660 }
661 661  
... ... @@ -665,7 +665,7 @@ QPDF::checkLinearizationInternal()
665 665 for (std::list<std::string>::iterator iter = warnings.begin();
666 666 iter != warnings.end(); ++iter)
667 667 {
668   - *out_stream << "WARNING: " << (*iter) << std::endl;
  668 + *this->m->out_stream << "WARNING: " << (*iter) << std::endl;
669 669 }
670 670 }
671 671  
... ... @@ -675,15 +675,15 @@ QPDF::checkLinearizationInternal()
675 675 qpdf_offset_t
676 676 QPDF::maxEnd(ObjUser const& ou)
677 677 {
678   - assert(this->obj_user_to_objects.count(ou) > 0);
679   - std::set<QPDFObjGen> const& ogs = this->obj_user_to_objects[ou];
  678 + assert(this->m->obj_user_to_objects.count(ou) > 0);
  679 + std::set<QPDFObjGen> const& ogs = this->m->obj_user_to_objects[ou];
680 680 qpdf_offset_t end = 0;
681 681 for (std::set<QPDFObjGen>::const_iterator iter = ogs.begin();
682 682 iter != ogs.end(); ++iter)
683 683 {
684 684 QPDFObjGen const& og = *iter;
685   - assert(this->obj_cache.count(og) > 0);
686   - end = std::max(end, this->obj_cache[og].end_after_space);
  685 + assert(this->m->obj_cache.count(og) > 0);
  686 + end = std::max(end, this->m->obj_cache[og].end_after_space);
687 687 }
688 688 return end;
689 689 }
... ... @@ -691,7 +691,7 @@ QPDF::maxEnd(ObjUser const&amp; ou)
691 691 qpdf_offset_t
692 692 QPDF::getLinearizationOffset(QPDFObjGen const& og)
693 693 {
694   - QPDFXRefEntry entry = this->xref_table[og];
  694 + QPDFXRefEntry entry = this->m->xref_table[og];
695 695 qpdf_offset_t result = 0;
696 696 switch (entry.getType())
697 697 {
... ... @@ -737,7 +737,7 @@ QPDF::lengthNextN(int first_object, int n,
737 737 for (int i = 0; i < n; ++i)
738 738 {
739 739 QPDFObjGen og(first_object + i, 0);
740   - if (this->xref_table.count(og) == 0)
  740 + if (this->m->xref_table.count(og) == 0)
741 741 {
742 742 errors.push_back(
743 743 "no xref table entry for " +
... ... @@ -745,8 +745,8 @@ QPDF::lengthNextN(int first_object, int n,
745 745 }
746 746 else
747 747 {
748   - assert(this->obj_cache.count(og) > 0);
749   - length += this->obj_cache[og].end_after_space -
  748 + assert(this->m->obj_cache.count(og) > 0);
  749 + length += this->m->obj_cache[og].end_after_space -
750 750 getLinearizationOffset(og);
751 751 }
752 752 }
... ... @@ -778,9 +778,9 @@ QPDF::checkHPageOffset(std::list&lt;std::string&gt;&amp; errors,
778 778  
779 779 unsigned int npages = pages.size();
780 780 int table_offset = adjusted_offset(
781   - this->page_offset_hints.first_page_offset);
  781 + this->m->page_offset_hints.first_page_offset);
782 782 QPDFObjGen first_page_og(pages.at(0).getObjGen());
783   - assert(this->xref_table.count(first_page_og) > 0);
  783 + assert(this->m->xref_table.count(first_page_og) > 0);
784 784 int offset = getLinearizationOffset(first_page_og);
785 785 if (table_offset != offset)
786 786 {
... ... @@ -791,13 +791,13 @@ QPDF::checkHPageOffset(std::list&lt;std::string&gt;&amp; errors,
791 791 {
792 792 QPDFObjGen page_og(pages.at(pageno).getObjGen());
793 793 int first_object = page_og.getObj();
794   - assert(this->xref_table.count(page_og) > 0);
  794 + assert(this->m->xref_table.count(page_og) > 0);
795 795 offset = getLinearizationOffset(page_og);
796 796  
797   - HPageOffsetEntry& he = this->page_offset_hints.entries.at(pageno);
798   - CHPageOffsetEntry& ce = this->c_page_offset_data.entries.at(pageno);
  797 + HPageOffsetEntry& he = this->m->page_offset_hints.entries.at(pageno);
  798 + CHPageOffsetEntry& ce = this->m->c_page_offset_data.entries.at(pageno);
799 799 int h_nobjects = he.delta_nobjects +
800   - this->page_offset_hints.min_nobjects;
  800 + this->m->page_offset_hints.min_nobjects;
801 801 if (h_nobjects != ce.nobjects)
802 802 {
803 803 // This happens with pdlin when there are thumbnails.
... ... @@ -812,7 +812,7 @@ QPDF::checkHPageOffset(std::list&lt;std::string&gt;&amp; errors,
812 812 // computed value if there is a discrepancy.
813 813 int length = lengthNextN(first_object, h_nobjects, errors);
814 814 int h_length = he.delta_page_length +
815   - this->page_offset_hints.min_page_length;
  815 + this->m->page_offset_hints.min_page_length;
816 816 if (length != h_length)
817 817 {
818 818 // This condition almost certainly indicates a bad hint
... ... @@ -853,12 +853,12 @@ QPDF::checkHPageOffset(std::list&lt;std::string&gt;&amp; errors,
853 853 for (int i = 0; i < ce.nshared_objects; ++i)
854 854 {
855 855 int idx = ce.shared_identifiers.at(i);
856   - if (idx >= this->c_shared_object_data.nshared_total)
  856 + if (idx >= this->m->c_shared_object_data.nshared_total)
857 857 {
858 858 throw std::logic_error(
859 859 "index out of bounds for shared object hint table");
860 860 }
861   - int obj = this->c_shared_object_data.entries.at(idx).object;
  861 + int obj = this->m->c_shared_object_data.entries.at(idx).object;
862 862 computed_shared.insert(obj);
863 863 }
864 864  
... ... @@ -916,7 +916,7 @@ QPDF::checkHSharedObject(std::list&lt;std::string&gt;&amp; errors,
916 916 // these whenever there are no shared objects not referenced by
917 917 // the first page (i.e., nshared_total == nshared_first_page).
918 918  
919   - HSharedObject& so = this->shared_object_hints;
  919 + HSharedObject& so = this->m->shared_object_hints;
920 920 if (so.nshared_total < so.nshared_first_page)
921 921 {
922 922 errors.push_back("shared object hint table: ntotal < nfirst_page");
... ... @@ -932,7 +932,7 @@ QPDF::checkHSharedObject(std::list&lt;std::string&gt;&amp; errors,
932 932 if (i == so.nshared_first_page)
933 933 {
934 934 QTC::TC("qpdf", "QPDF lin check shared past first page");
935   - if (this->part8.empty())
  935 + if (this->m->part8.empty())
936 936 {
937 937 errors.push_back(
938 938 "part 8 is empty but nshared_total > "
... ... @@ -940,7 +940,7 @@ QPDF::checkHSharedObject(std::list&lt;std::string&gt;&amp; errors,
940 940 }
941 941 else
942 942 {
943   - int obj = this->part8.at(0).getObjectID();
  943 + int obj = this->m->part8.at(0).getObjectID();
944 944 if (obj != so.first_shared_obj)
945 945 {
946 946 errors.push_back(
... ... @@ -955,7 +955,7 @@ QPDF::checkHSharedObject(std::list&lt;std::string&gt;&amp; errors,
955 955 cur_object = so.first_shared_obj;
956 956  
957 957 QPDFObjGen og(cur_object, 0);
958   - assert(this->xref_table.count(og) > 0);
  958 + assert(this->m->xref_table.count(og) > 0);
959 959 int offset = getLinearizationOffset(og);
960 960 int h_offset = adjusted_offset(so.first_shared_offset);
961 961 if (offset != h_offset)
... ... @@ -996,15 +996,15 @@ QPDF::checkHOutlines(std::list&lt;std::string&gt;&amp; warnings)
996 996 // wrong starting place). pdlin appears to generate correct
997 997 // values in those cases.
998 998  
999   - if (this->c_outline_data.nobjects == this->outline_hints.nobjects)
  999 + if (this->m->c_outline_data.nobjects == this->m->outline_hints.nobjects)
1000 1000 {
1001   - if (this->c_outline_data.nobjects == 0)
  1001 + if (this->m->c_outline_data.nobjects == 0)
1002 1002 {
1003 1003 return;
1004 1004 }
1005 1005  
1006   - if (this->c_outline_data.first_object ==
1007   - this->outline_hints.first_object)
  1006 + if (this->m->c_outline_data.first_object ==
  1007 + this->m->outline_hints.first_object)
1008 1008 {
1009 1009 // Check length and offset. Acrobat gets these wrong.
1010 1010 QPDFObjectHandle outlines = getRoot().getKey("/Outlines");
... ... @@ -1018,12 +1018,12 @@ QPDF::checkHOutlines(std::list&lt;std::string&gt;&amp; warnings)
1018 1018 return;
1019 1019 }
1020 1020 QPDFObjGen og(outlines.getObjGen());
1021   - assert(this->xref_table.count(og) > 0);
  1021 + assert(this->m->xref_table.count(og) > 0);
1022 1022 int offset = getLinearizationOffset(og);
1023 1023 ObjUser ou(ObjUser::ou_root_key, "/Outlines");
1024 1024 int length = maxEnd(ou) - offset;
1025 1025 int table_offset =
1026   - adjusted_offset(this->outline_hints.first_object_offset);
  1026 + adjusted_offset(this->m->outline_hints.first_object_offset);
1027 1027 if (offset != table_offset)
1028 1028 {
1029 1029 warnings.push_back(
... ... @@ -1031,7 +1031,7 @@ QPDF::checkHOutlines(std::list&lt;std::string&gt;&amp; warnings)
1031 1031 QUtil::int_to_string(table_offset) +
1032 1032 "; computed = " + QUtil::int_to_string(offset));
1033 1033 }
1034   - int table_length = this->outline_hints.group_length;
  1034 + int table_length = this->m->outline_hints.group_length;
1035 1035 if (length != table_length)
1036 1036 {
1037 1037 warnings.push_back(
... ... @@ -1063,41 +1063,42 @@ QPDF::showLinearizationData()
1063 1063 }
1064 1064 catch (QPDFExc& e)
1065 1065 {
1066   - *out_stream << e.what() << std::endl;
  1066 + *this->m->out_stream << e.what() << std::endl;
1067 1067 }
1068 1068 }
1069 1069  
1070 1070 void
1071 1071 QPDF::dumpLinearizationDataInternal()
1072 1072 {
1073   - *out_stream << this->file->getName() << ": linearization data:" << std::endl
1074   - << std::endl;
1075   -
1076   - *out_stream
1077   - << "file_size: " << this->linp.file_size << std::endl
1078   - << "first_page_object: " << this->linp.first_page_object << std::endl
1079   - << "first_page_end: " << this->linp.first_page_end << std::endl
1080   - << "npages: " << this->linp.npages << std::endl
1081   - << "xref_zero_offset: " << this->linp.xref_zero_offset << std::endl
1082   - << "first_page: " << this->linp.first_page << std::endl
1083   - << "H_offset: " << this->linp.H_offset << std::endl
1084   - << "H_length: " << this->linp.H_length << std::endl
  1073 + *this->m->out_stream
  1074 + << this->m->file->getName() << ": linearization data:" << std::endl
  1075 + << std::endl;
  1076 +
  1077 + *this->m->out_stream
  1078 + << "file_size: " << this->m->linp.file_size << std::endl
  1079 + << "first_page_object: " << this->m->linp.first_page_object << std::endl
  1080 + << "first_page_end: " << this->m->linp.first_page_end << std::endl
  1081 + << "npages: " << this->m->linp.npages << std::endl
  1082 + << "xref_zero_offset: " << this->m->linp.xref_zero_offset << std::endl
  1083 + << "first_page: " << this->m->linp.first_page << std::endl
  1084 + << "H_offset: " << this->m->linp.H_offset << std::endl
  1085 + << "H_length: " << this->m->linp.H_length << std::endl
1085 1086 << std::endl;
1086 1087  
1087   - *out_stream << "Page Offsets Hint Table" << std::endl
1088   - << std::endl;
  1088 + *this->m->out_stream << "Page Offsets Hint Table" << std::endl
  1089 + << std::endl;
1089 1090 dumpHPageOffset();
1090   - *out_stream << std::endl
1091   - << "Shared Objects Hint Table" << std::endl
1092   - << std::endl;
  1091 + *this->m->out_stream << std::endl
  1092 + << "Shared Objects Hint Table" << std::endl
  1093 + << std::endl;
1093 1094 dumpHSharedObject();
1094 1095  
1095   - if (this->outline_hints.nobjects > 0)
  1096 + if (this->m->outline_hints.nobjects > 0)
1096 1097 {
1097   - *out_stream << std::endl
1098   - << "Outlines Hint Table" << std::endl
1099   - << std::endl;
1100   - dumpHGeneric(this->outline_hints);
  1098 + *this->m->out_stream << std::endl
  1099 + << "Outlines Hint Table" << std::endl
  1100 + << std::endl;
  1101 + dumpHGeneric(this->m->outline_hints);
1101 1102 }
1102 1103 }
1103 1104  
... ... @@ -1107,9 +1108,9 @@ QPDF::adjusted_offset(int offset)
1107 1108 // All offsets >= H_offset have to be increased by H_length
1108 1109 // since all hint table location values disregard the hint table
1109 1110 // itself.
1110   - if (offset >= this->linp.H_offset)
  1111 + if (offset >= this->m->linp.H_offset)
1111 1112 {
1112   - return offset + this->linp.H_length;
  1113 + return offset + this->m->linp.H_length;
1113 1114 }
1114 1115 return offset;
1115 1116 }
... ... @@ -1118,8 +1119,8 @@ QPDF::adjusted_offset(int offset)
1118 1119 void
1119 1120 QPDF::dumpHPageOffset()
1120 1121 {
1121   - HPageOffset& t = this->page_offset_hints;
1122   - *out_stream
  1122 + HPageOffset& t = this->m->page_offset_hints;
  1123 + *this->m->out_stream
1123 1124 << "min_nobjects: " << t.min_nobjects
1124 1125 << std::endl
1125 1126 << "first_page_offset: " << adjusted_offset(t.first_page_offset)
... ... @@ -1147,10 +1148,10 @@ QPDF::dumpHPageOffset()
1147 1148 << "shared_denominator: " << t.shared_denominator
1148 1149 << std::endl;
1149 1150  
1150   - for (int i1 = 0; i1 < this->linp.npages; ++i1)
  1151 + for (int i1 = 0; i1 < this->m->linp.npages; ++i1)
1151 1152 {
1152 1153 HPageOffsetEntry& pe = t.entries.at(i1);
1153   - *out_stream
  1154 + *this->m->out_stream
1154 1155 << "Page " << i1 << ":" << std::endl
1155 1156 << " nobjects: " << pe.delta_nobjects + t.min_nobjects
1156 1157 << std::endl
... ... @@ -1164,10 +1165,10 @@ QPDF::dumpHPageOffset()
1164 1165 << " nshared_objects: " << pe.nshared_objects << std::endl;
1165 1166 for (int i2 = 0; i2 < pe.nshared_objects; ++i2)
1166 1167 {
1167   - *out_stream << " identifier " << i2 << ": "
1168   - << pe.shared_identifiers.at(i2) << std::endl;
1169   - *out_stream << " numerator " << i2 << ": "
1170   - << pe.shared_numerators.at(i2) << std::endl;
  1168 + *this->m->out_stream << " identifier " << i2 << ": "
  1169 + << pe.shared_identifiers.at(i2) << std::endl;
  1170 + *this->m->out_stream << " numerator " << i2 << ": "
  1171 + << pe.shared_numerators.at(i2) << std::endl;
1171 1172 }
1172 1173 }
1173 1174 }
... ... @@ -1175,8 +1176,8 @@ QPDF::dumpHPageOffset()
1175 1176 void
1176 1177 QPDF::dumpHSharedObject()
1177 1178 {
1178   - HSharedObject& t = this->shared_object_hints;
1179   - *out_stream
  1179 + HSharedObject& t = this->m->shared_object_hints;
  1180 + *this->m->out_stream
1180 1181 << "first_shared_obj: " << t.first_shared_obj
1181 1182 << std::endl
1182 1183 << "first_shared_offset: " << adjusted_offset(t.first_shared_offset)
... ... @@ -1195,19 +1196,20 @@ QPDF::dumpHSharedObject()
1195 1196 for (int i = 0; i < t.nshared_total; ++i)
1196 1197 {
1197 1198 HSharedObjectEntry& se = t.entries.at(i);
1198   - *out_stream << "Shared Object " << i << ":" << std::endl;
1199   - *out_stream << " group length: "
1200   - << se.delta_group_length + t.min_group_length << std::endl;
  1199 + *this->m->out_stream
  1200 + << "Shared Object " << i << ":" << std::endl
  1201 + << " group length: "
  1202 + << se.delta_group_length + t.min_group_length << std::endl;
1201 1203 // PDF spec says signature present nobjects_minus_one are
1202 1204 // always 0, so print them only if they have a non-zero value.
1203 1205 if (se.signature_present)
1204 1206 {
1205   - *out_stream << " signature present" << std::endl;
  1207 + *this->m->out_stream << " signature present" << std::endl;
1206 1208 }
1207 1209 if (se.nobjects_minus_one != 0)
1208 1210 {
1209   - *out_stream << " nobjects: "
1210   - << se.nobjects_minus_one + 1 << std::endl;
  1211 + *this->m->out_stream << " nobjects: "
  1212 + << se.nobjects_minus_one + 1 << std::endl;
1211 1213 }
1212 1214 }
1213 1215 }
... ... @@ -1215,7 +1217,7 @@ QPDF::dumpHSharedObject()
1215 1217 void
1216 1218 QPDF::dumpHGeneric(HGeneric& t)
1217 1219 {
1218   - *out_stream
  1220 + *this->m->out_stream
1219 1221 << "first_object: " << t.first_object
1220 1222 << std::endl
1221 1223 << "first_object_offset: " << adjusted_offset(t.first_object_offset)
... ... @@ -1242,7 +1244,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1242 1244 // this function. Note that actual offsets and lengths are not
1243 1245 // computed here, but anything related to object ordering is.
1244 1246  
1245   - if (this->object_to_obj_users.empty())
  1247 + if (this->m->object_to_obj_users.empty())
1246 1248 {
1247 1249 // Note that we can't call optimize here because we don't know
1248 1250 // whether it should be called with or without allow changes.
... ... @@ -1298,15 +1300,15 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1298 1300  
1299 1301 // * outlines: part 6 or 9
1300 1302  
1301   - this->part4.clear();
1302   - this->part6.clear();
1303   - this->part7.clear();
1304   - this->part8.clear();
1305   - this->part9.clear();
1306   - this->c_linp = LinParameters();
1307   - this->c_page_offset_data = CHPageOffset();
1308   - this->c_shared_object_data = CHSharedObject();
1309   - this->c_outline_data = HGeneric();
  1303 + this->m->part4.clear();
  1304 + this->m->part6.clear();
  1305 + this->m->part7.clear();
  1306 + this->m->part8.clear();
  1307 + this->m->part9.clear();
  1308 + this->m->c_linp = LinParameters();
  1309 + this->m->c_page_offset_data = CHPageOffset();
  1310 + this->m->c_shared_object_data = CHSharedObject();
  1311 + this->m->c_outline_data = HGeneric();
1310 1312  
1311 1313 QPDFObjectHandle root = getRoot();
1312 1314 bool outlines_in_first_page = false;
... ... @@ -1349,8 +1351,8 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1349 1351 std::set<QPDFObjGen> lc_root;
1350 1352  
1351 1353 for (std::map<QPDFObjGen, std::set<ObjUser> >::iterator oiter =
1352   - this->object_to_obj_users.begin();
1353   - oiter != this->object_to_obj_users.end(); ++oiter)
  1354 + this->m->object_to_obj_users.begin();
  1355 + oiter != this->m->object_to_obj_users.end(); ++oiter)
1354 1356 {
1355 1357 QPDFObjGen const& og = (*oiter).first;
1356 1358  
... ... @@ -1505,17 +1507,18 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1505 1507 // npages is the size of the existing pages vector, which has been
1506 1508 // created by traversing the pages tree, and as such is a
1507 1509 // reasonable size.
1508   - this->c_linp.npages = npages;
1509   - this->c_page_offset_data.entries = std::vector<CHPageOffsetEntry>(npages);
  1510 + this->m->c_linp.npages = npages;
  1511 + this->m->c_page_offset_data.entries =
  1512 + std::vector<CHPageOffsetEntry>(npages);
1510 1513  
1511 1514 // Part 4: open document objects. We don't care about the order.
1512 1515  
1513 1516 assert(lc_root.size() == 1);
1514   - this->part4.push_back(objGenToIndirect(*(lc_root.begin())));
  1517 + this->m->part4.push_back(objGenToIndirect(*(lc_root.begin())));
1515 1518 for (std::set<QPDFObjGen>::iterator iter = lc_open_document.begin();
1516 1519 iter != lc_open_document.end(); ++iter)
1517 1520 {
1518   - this->part4.push_back(objGenToIndirect(*iter));
  1521 + this->m->part4.push_back(objGenToIndirect(*iter));
1519 1522 }
1520 1523  
1521 1524 // Part 6: first page objects. Note: implementation note 124
... ... @@ -1533,8 +1536,8 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1533 1536 "object not in lc_first_page_private");
1534 1537 }
1535 1538 lc_first_page_private.erase(first_page_og);
1536   - this->c_linp.first_page_object = pages.at(0).getObjectID();
1537   - this->part6.push_back(pages.at(0));
  1539 + this->m->c_linp.first_page_object = pages.at(0).getObjectID();
  1540 + this->m->part6.push_back(pages.at(0));
1538 1541  
1539 1542 // The PDF spec "recommends" an order for the rest of the objects,
1540 1543 // but we are going to disregard it except to the extent that it
... ... @@ -1544,19 +1547,19 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1544 1547 for (std::set<QPDFObjGen>::iterator iter = lc_first_page_private.begin();
1545 1548 iter != lc_first_page_private.end(); ++iter)
1546 1549 {
1547   - this->part6.push_back(objGenToIndirect(*iter));
  1550 + this->m->part6.push_back(objGenToIndirect(*iter));
1548 1551 }
1549 1552  
1550 1553 for (std::set<QPDFObjGen>::iterator iter = lc_first_page_shared.begin();
1551 1554 iter != lc_first_page_shared.end(); ++iter)
1552 1555 {
1553   - this->part6.push_back(objGenToIndirect(*iter));
  1556 + this->m->part6.push_back(objGenToIndirect(*iter));
1554 1557 }
1555 1558  
1556 1559 // Place the outline dictionary if it goes in the first page section.
1557 1560 if (outlines_in_first_page)
1558 1561 {
1559   - pushOutlinesToPart(this->part6, lc_outlines, object_stream_data);
  1562 + pushOutlinesToPart(this->m->part6, lc_outlines, object_stream_data);
1560 1563 }
1561 1564  
1562 1565 // Fill in page offset hint table information for the first page.
... ... @@ -1565,7 +1568,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1565 1568 // in garbage values for all the shared object identifiers on the
1566 1569 // first page.
1567 1570  
1568   - this->c_page_offset_data.entries.at(0).nobjects = this->part6.size();
  1571 + this->m->c_page_offset_data.entries.at(0).nobjects = this->m->part6.size();
1569 1572  
1570 1573 // Part 7: other pages' private objects
1571 1574  
... ... @@ -1583,16 +1586,16 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1583 1586 QUtil::int_to_string(i) + " not in lc_other_page_private");
1584 1587 }
1585 1588 lc_other_page_private.erase(page_og);
1586   - this->part7.push_back(pages.at(i));
  1589 + this->m->part7.push_back(pages.at(i));
1587 1590  
1588 1591 // Place all non-shared objects referenced by this page,
1589 1592 // updating the page object count for the hint table.
1590 1593  
1591   - this->c_page_offset_data.entries.at(i).nobjects = 1;
  1594 + this->m->c_page_offset_data.entries.at(i).nobjects = 1;
1592 1595  
1593 1596 ObjUser ou(ObjUser::ou_page, i);
1594   - assert(this->obj_user_to_objects.count(ou) > 0);
1595   - std::set<QPDFObjGen> ogs = this->obj_user_to_objects[ou];
  1597 + assert(this->m->obj_user_to_objects.count(ou) > 0);
  1598 + std::set<QPDFObjGen> ogs = this->m->obj_user_to_objects[ou];
1596 1599 for (std::set<QPDFObjGen>::iterator iter = ogs.begin();
1597 1600 iter != ogs.end(); ++iter)
1598 1601 {
... ... @@ -1600,8 +1603,8 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1600 1603 if (lc_other_page_private.count(og))
1601 1604 {
1602 1605 lc_other_page_private.erase(og);
1603   - this->part7.push_back(objGenToIndirect(og));
1604   - ++this->c_page_offset_data.entries.at(i).nobjects;
  1606 + this->m->part7.push_back(objGenToIndirect(og));
  1607 + ++this->m->c_page_offset_data.entries.at(i).nobjects;
1605 1608 }
1606 1609 }
1607 1610 }
... ... @@ -1620,7 +1623,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1620 1623 for (std::set<QPDFObjGen>::iterator iter = lc_other_page_shared.begin();
1621 1624 iter != lc_other_page_shared.end(); ++iter)
1622 1625 {
1623   - this->part8.push_back(objGenToIndirect(*iter));
  1626 + this->m->part8.push_back(objGenToIndirect(*iter));
1624 1627 }
1625 1628  
1626 1629 // Part 9: other objects
... ... @@ -1634,7 +1637,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1634 1637  
1635 1638 // Place the pages tree.
1636 1639 std::set<QPDFObjGen> pages_ogs =
1637   - this->obj_user_to_objects[ObjUser(ObjUser::ou_root_key, "/Pages")];
  1640 + this->m->obj_user_to_objects[ObjUser(ObjUser::ou_root_key, "/Pages")];
1638 1641 assert(! pages_ogs.empty());
1639 1642 for (std::set<QPDFObjGen>::iterator iter = pages_ogs.begin();
1640 1643 iter != pages_ogs.end(); ++iter)
... ... @@ -1643,7 +1646,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1643 1646 if (lc_other.count(og))
1644 1647 {
1645 1648 lc_other.erase(og);
1646   - this->part9.push_back(objGenToIndirect(og));
  1649 + this->m->part9.push_back(objGenToIndirect(og));
1647 1650 }
1648 1651 }
1649 1652  
... ... @@ -1661,7 +1664,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1661 1664 if (lc_thumbnail_private.count(thumb_og))
1662 1665 {
1663 1666 lc_thumbnail_private.erase(thumb_og);
1664   - this->part9.push_back(thumb);
  1667 + this->m->part9.push_back(thumb);
1665 1668 }
1666 1669 else
1667 1670 {
... ... @@ -1673,7 +1676,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1673 1676 // lc_thumbnail_private.
1674 1677 }
1675 1678 std::set<QPDFObjGen>& ogs =
1676   - this->obj_user_to_objects[ObjUser(ObjUser::ou_thumb, i)];
  1679 + this->m->obj_user_to_objects[ObjUser(ObjUser::ou_thumb, i)];
1677 1680 for (std::set<QPDFObjGen>::iterator iter = ogs.begin();
1678 1681 iter != ogs.end(); ++iter)
1679 1682 {
... ... @@ -1681,7 +1684,7 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1681 1684 if (lc_thumbnail_private.count(og))
1682 1685 {
1683 1686 lc_thumbnail_private.erase(og);
1684   - this->part9.push_back(objGenToIndirect(og));
  1687 + this->m->part9.push_back(objGenToIndirect(og));
1685 1688 }
1686 1689 }
1687 1690 }
... ... @@ -1698,28 +1701,28 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1698 1701 for (std::set<QPDFObjGen>::iterator iter = lc_thumbnail_shared.begin();
1699 1702 iter != lc_thumbnail_shared.end(); ++iter)
1700 1703 {
1701   - this->part9.push_back(objGenToIndirect(*iter));
  1704 + this->m->part9.push_back(objGenToIndirect(*iter));
1702 1705 }
1703 1706  
1704 1707 // Place outlines unless in first page
1705 1708 if (! outlines_in_first_page)
1706 1709 {
1707   - pushOutlinesToPart(this->part9, lc_outlines, object_stream_data);
  1710 + pushOutlinesToPart(this->m->part9, lc_outlines, object_stream_data);
1708 1711 }
1709 1712  
1710 1713 // Place all remaining objects
1711 1714 for (std::set<QPDFObjGen>::iterator iter = lc_other.begin();
1712 1715 iter != lc_other.end(); ++iter)
1713 1716 {
1714   - this->part9.push_back(objGenToIndirect(*iter));
  1717 + this->m->part9.push_back(objGenToIndirect(*iter));
1715 1718 }
1716 1719  
1717 1720 // Make sure we got everything exactly once.
1718 1721  
1719 1722 unsigned int num_placed =
1720   - this->part4.size() + this->part6.size() + this->part7.size() +
1721   - this->part8.size() + this->part9.size();
1722   - unsigned int num_wanted = this->object_to_obj_users.size();
  1723 + this->m->part4.size() + this->m->part6.size() + this->m->part7.size() +
  1724 + this->m->part8.size() + this->m->part9.size();
  1725 + unsigned int num_wanted = this->m->object_to_obj_users.size();
1723 1726 if (num_placed != num_wanted)
1724 1727 {
1725 1728 throw std::logic_error(
... ... @@ -1743,28 +1746,29 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1743 1746 // can map from object number only without regards to generation.
1744 1747 std::map<int, int> obj_to_index;
1745 1748  
1746   - this->c_shared_object_data.nshared_first_page = this->part6.size();
1747   - this->c_shared_object_data.nshared_total =
1748   - this->c_shared_object_data.nshared_first_page + this->part8.size();
  1749 + this->m->c_shared_object_data.nshared_first_page = this->m->part6.size();
  1750 + this->m->c_shared_object_data.nshared_total =
  1751 + this->m->c_shared_object_data.nshared_first_page +
  1752 + this->m->part8.size();
1749 1753  
1750 1754 std::vector<CHSharedObjectEntry>& shared =
1751   - this->c_shared_object_data.entries;
1752   - for (std::vector<QPDFObjectHandle>::iterator iter = this->part6.begin();
1753   - iter != this->part6.end(); ++iter)
  1755 + this->m->c_shared_object_data.entries;
  1756 + for (std::vector<QPDFObjectHandle>::iterator iter = this->m->part6.begin();
  1757 + iter != this->m->part6.end(); ++iter)
1754 1758 {
1755 1759 QPDFObjectHandle& oh = *iter;
1756 1760 int obj = oh.getObjectID();
1757 1761 obj_to_index[obj] = shared.size();
1758 1762 shared.push_back(CHSharedObjectEntry(obj));
1759 1763 }
1760   - QTC::TC("qpdf", "QPDF lin part 8 empty", this->part8.empty() ? 1 : 0);
1761   - if (! this->part8.empty())
  1764 + QTC::TC("qpdf", "QPDF lin part 8 empty", this->m->part8.empty() ? 1 : 0);
  1765 + if (! this->m->part8.empty())
1762 1766 {
1763   - this->c_shared_object_data.first_shared_obj =
1764   - this->part8.at(0).getObjectID();
  1767 + this->m->c_shared_object_data.first_shared_obj =
  1768 + this->m->part8.at(0).getObjectID();
1765 1769 for (std::vector<QPDFObjectHandle>::iterator iter =
1766   - this->part8.begin();
1767   - iter != this->part8.end(); ++iter)
  1770 + this->m->part8.begin();
  1771 + iter != this->m->part8.end(); ++iter)
1768 1772 {
1769 1773 QPDFObjectHandle& oh = *iter;
1770 1774 int obj = oh.getObjectID();
... ... @@ -1772,8 +1776,8 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1772 1776 shared.push_back(CHSharedObjectEntry(obj));
1773 1777 }
1774 1778 }
1775   - if (static_cast<size_t>(this->c_shared_object_data.nshared_total) !=
1776   - this->c_shared_object_data.entries.size())
  1779 + if (static_cast<size_t>(this->m->c_shared_object_data.nshared_total) !=
  1780 + this->m->c_shared_object_data.entries.size())
1777 1781 {
1778 1782 throw std::logic_error(
1779 1783 "shared object hint table has wrong number of entries");
... ... @@ -1784,15 +1788,15 @@ QPDF::calculateLinearizationData(std::map&lt;int, int&gt; const&amp; object_stream_data)
1784 1788  
1785 1789 for (unsigned int i = 1; i < npages; ++i)
1786 1790 {
1787   - CHPageOffsetEntry& pe = this->c_page_offset_data.entries.at(i);
  1791 + CHPageOffsetEntry& pe = this->m->c_page_offset_data.entries.at(i);
1788 1792 ObjUser ou(ObjUser::ou_page, i);
1789   - assert(this->obj_user_to_objects.count(ou) > 0);
1790   - std::set<QPDFObjGen> const& ogs = this->obj_user_to_objects[ou];
  1793 + assert(this->m->obj_user_to_objects.count(ou) > 0);
  1794 + std::set<QPDFObjGen> const& ogs = this->m->obj_user_to_objects[ou];
1791 1795 for (std::set<QPDFObjGen>::const_iterator iter = ogs.begin();
1792 1796 iter != ogs.end(); ++iter)
1793 1797 {
1794 1798 QPDFObjGen const& og = *iter;
1795   - if ((this->object_to_obj_users[og].size() > 1) &&
  1799 + if ((this->m->object_to_obj_users[og].size() > 1) &&
1796 1800 (obj_to_index.count(og.getObj()) > 0))
1797 1801 {
1798 1802 int idx = obj_to_index[og.getObj()];
... ... @@ -1818,18 +1822,18 @@ QPDF::pushOutlinesToPart(
1818 1822 outlines = getUncompressedObject(outlines, object_stream_data);
1819 1823 QPDFObjGen outlines_og(outlines.getObjGen());
1820 1824 QTC::TC("qpdf", "QPDF lin outlines in part",
1821   - ((&part == (&this->part6)) ? 0
1822   - : (&part == (&this->part9)) ? 1
  1825 + ((&part == (&this->m->part6)) ? 0
  1826 + : (&part == (&this->m->part9)) ? 1
1823 1827 : 9999)); // can't happen
1824   - this->c_outline_data.first_object = outlines_og.getObj();
1825   - this->c_outline_data.nobjects = 1;
  1828 + this->m->c_outline_data.first_object = outlines_og.getObj();
  1829 + this->m->c_outline_data.nobjects = 1;
1826 1830 lc_outlines.erase(outlines_og);
1827 1831 part.push_back(outlines);
1828 1832 for (std::set<QPDFObjGen>::iterator iter = lc_outlines.begin();
1829 1833 iter != lc_outlines.end(); ++iter)
1830 1834 {
1831 1835 part.push_back(objGenToIndirect(*iter));
1832   - ++this->c_outline_data.nobjects;
  1836 + ++this->m->c_outline_data.nobjects;
1833 1837 }
1834 1838 }
1835 1839  
... ... @@ -1843,11 +1847,11 @@ QPDF::getLinearizedParts(
1843 1847 std::vector<QPDFObjectHandle>& part9)
1844 1848 {
1845 1849 calculateLinearizationData(object_stream_data);
1846   - part4 = this->part4;
1847   - part6 = this->part6;
1848   - part7 = this->part7;
1849   - part8 = this->part8;
1850   - part9 = this->part9;
  1850 + part4 = this->m->part4;
  1851 + part6 = this->m->part6;
  1852 + part7 = this->m->part7;
  1853 + part8 = this->m->part8;
  1854 + part9 = this->m->part9;
1851 1855 }
1852 1856  
1853 1857 static inline int nbits(int val)
... ... @@ -1889,7 +1893,7 @@ QPDF::calculateHPageOffset(
1889 1893  
1890 1894 std::vector<QPDFObjectHandle> const& pages = getAllPages();
1891 1895 unsigned int npages = pages.size();
1892   - CHPageOffset& cph = this->c_page_offset_data;
  1896 + CHPageOffset& cph = this->m->c_page_offset_data;
1893 1897 std::vector<CHPageOffsetEntry>& cphe = cph.entries;
1894 1898  
1895 1899 // Calculate minimum and maximum values for number of objects per
... ... @@ -1902,7 +1906,7 @@ QPDF::calculateHPageOffset(
1902 1906 int max_length = min_length;
1903 1907 int max_shared = cphe.at(0).nshared_objects;
1904 1908  
1905   - HPageOffset& ph = this->page_offset_hints;
  1909 + HPageOffset& ph = this->m->page_offset_hints;
1906 1910 std::vector<HPageOffsetEntry>& phe = ph.entries;
1907 1911 // npages is the size of the existing pages array.
1908 1912 phe = std::vector<HPageOffsetEntry>(npages);
... ... @@ -1940,7 +1944,7 @@ QPDF::calculateHPageOffset(
1940 1944 ph.nbits_delta_page_length = nbits(max_length - min_length);
1941 1945 ph.nbits_nshared_objects = nbits(max_shared);
1942 1946 ph.nbits_shared_identifier =
1943   - nbits(this->c_shared_object_data.nshared_total);
  1947 + nbits(this->m->c_shared_object_data.nshared_total);
1944 1948 ph.shared_denominator = 4; // doesn't matter
1945 1949  
1946 1950 // It isn't clear how to compute content offset and content
... ... @@ -1975,9 +1979,9 @@ QPDF::calculateHSharedObject(
1975 1979 std::map<int, qpdf_offset_t> const& lengths,
1976 1980 std::map<int, int> const& obj_renumber)
1977 1981 {
1978   - CHSharedObject& cso = this->c_shared_object_data;
  1982 + CHSharedObject& cso = this->m->c_shared_object_data;
1979 1983 std::vector<CHSharedObjectEntry>& csoe = cso.entries;
1980   - HSharedObject& so = this->shared_object_hints;
  1984 + HSharedObject& so = this->m->shared_object_hints;
1981 1985 std::vector<HSharedObjectEntry>& soe = so.entries;
1982 1986 soe.clear();
1983 1987  
... ... @@ -2026,14 +2030,14 @@ QPDF::calculateHOutline(
2026 2030 std::map<int, qpdf_offset_t> const& lengths,
2027 2031 std::map<int, int> const& obj_renumber)
2028 2032 {
2029   - HGeneric& cho = this->c_outline_data;
  2033 + HGeneric& cho = this->m->c_outline_data;
2030 2034  
2031 2035 if (cho.nobjects == 0)
2032 2036 {
2033 2037 return;
2034 2038 }
2035 2039  
2036   - HGeneric& ho = this->outline_hints;
  2040 + HGeneric& ho = this->m->outline_hints;
2037 2041  
2038 2042 ho.first_object =
2039 2043 (*(obj_renumber.find(cho.first_object))).second;
... ... @@ -2083,7 +2087,7 @@ write_vector_vector(BitWriter&amp; w,
2083 2087 void
2084 2088 QPDF::writeHPageOffset(BitWriter& w)
2085 2089 {
2086   - HPageOffset& t = this->page_offset_hints;
  2090 + HPageOffset& t = this->m->page_offset_hints;
2087 2091  
2088 2092 w.writeBits(t.min_nobjects, 32); // 1
2089 2093 w.writeBits(t.first_page_offset, 32); // 2
... ... @@ -2130,7 +2134,7 @@ QPDF::writeHPageOffset(BitWriter&amp; w)
2130 2134 void
2131 2135 QPDF::writeHSharedObject(BitWriter& w)
2132 2136 {
2133   - HSharedObject& t = this->shared_object_hints;
  2137 + HSharedObject& t = this->m->shared_object_hints;
2134 2138  
2135 2139 w.writeBits(t.first_shared_obj, 32); // 1
2136 2140 w.writeBits(t.first_shared_offset, 32); // 2
... ... @@ -2193,10 +2197,10 @@ QPDF::generateHintStream(std::map&lt;int, QPDFXRefEntry&gt; const&amp; xref,
2193 2197 S = c.getCount();
2194 2198 writeHSharedObject(w);
2195 2199 O = 0;
2196   - if (this->outline_hints.nobjects > 0)
  2200 + if (this->m->outline_hints.nobjects > 0)
2197 2201 {
2198 2202 O = c.getCount();
2199   - writeHGeneric(w, this->outline_hints);
  2203 + writeHGeneric(w, this->m->outline_hints);
2200 2204 }
2201 2205 c.finish();
2202 2206  
... ...
libqpdf/QPDF_optimization.cc
... ... @@ -62,7 +62,7 @@ void
62 62 QPDF::optimize(std::map<int, int> const& object_stream_data,
63 63 bool allow_changes)
64 64 {
65   - if (! this->obj_user_to_objects.empty())
  65 + if (! this->m->obj_user_to_objects.empty())
66 66 {
67 67 // already optimized
68 68 return;
... ... @@ -83,19 +83,19 @@ QPDF::optimize(std::map&lt;int, int&gt; const&amp; object_stream_data,
83 83 }
84 84  
85 85 // Traverse pages tree pushing all inherited resources down to the
86   - // page level. This also initializes this->all_pages.
  86 + // page level. This also initializes this->m->all_pages.
87 87 pushInheritedAttributesToPage(allow_changes, false);
88 88  
89 89 // Traverse pages
90   - int n = this->all_pages.size();
  90 + int n = this->m->all_pages.size();
91 91 for (int pageno = 0; pageno < n; ++pageno)
92 92 {
93 93 updateObjectMaps(ObjUser(ObjUser::ou_page, pageno),
94   - this->all_pages.at(pageno));
  94 + this->m->all_pages.at(pageno));
95 95 }
96 96  
97 97 // Traverse document-level items
98   - std::set<std::string> keys = this->trailer.getKeys();
  98 + std::set<std::string> keys = this->m->trailer.getKeys();
99 99 for (std::set<std::string>::iterator iter = keys.begin();
100 100 iter != keys.end(); ++iter)
101 101 {
... ... @@ -107,7 +107,7 @@ QPDF::optimize(std::map&lt;int, int&gt; const&amp; object_stream_data,
107 107 else
108 108 {
109 109 updateObjectMaps(ObjUser(ObjUser::ou_trailer_key, key),
110   - this->trailer.getKey(key));
  110 + this->m->trailer.getKey(key));
111 111 }
112 112 }
113 113  
... ... @@ -129,8 +129,8 @@ QPDF::optimize(std::map&lt;int, int&gt; const&amp; object_stream_data,
129 129  
130 130 ObjUser root_ou = ObjUser(ObjUser::ou_root);
131 131 QPDFObjGen root_og = QPDFObjGen(root.getObjGen());
132   - obj_user_to_objects[root_ou].insert(root_og);
133   - object_to_obj_users[root_og].insert(root_ou);
  132 + this->m->obj_user_to_objects[root_ou].insert(root_og);
  133 + this->m->object_to_obj_users[root_og].insert(root_ou);
134 134  
135 135 filterCompressedObjects(object_stream_data);
136 136 }
... ... @@ -151,7 +151,7 @@ QPDF::pushInheritedAttributesToPage(bool allow_changes, bool warn_skipped_keys)
151 151 // The record of whether we've done this is cleared by
152 152 // updateAllPagesCache(). If we're warning for skipped keys,
153 153 // re-traverse unconditionally.
154   - if (this->pushed_inherited_attributes_to_pages && (! warn_skipped_keys))
  154 + if (this->m->pushed_inherited_attributes_to_pages && (! warn_skipped_keys))
155 155 {
156 156 return;
157 157 }
... ... @@ -159,12 +159,12 @@ QPDF::pushInheritedAttributesToPage(bool allow_changes, bool warn_skipped_keys)
159 159 // key_ancestors is a mapping of page attribute keys to a stack of
160 160 // Pages nodes that contain values for them.
161 161 std::map<std::string, std::vector<QPDFObjectHandle> > key_ancestors;
162   - this->all_pages.clear();
  162 + this->m->all_pages.clear();
163 163 pushInheritedAttributesToPageInternal(
164   - this->trailer.getKey("/Root").getKey("/Pages"),
165   - key_ancestors, this->all_pages, allow_changes, warn_skipped_keys);
  164 + this->m->trailer.getKey("/Root").getKey("/Pages"),
  165 + key_ancestors, this->m->all_pages, allow_changes, warn_skipped_keys);
166 166 assert(key_ancestors.empty());
167   - this->pushed_inherited_attributes_to_pages = true;
  167 + this->m->pushed_inherited_attributes_to_pages = true;
168 168 }
169 169  
170 170 void
... ... @@ -192,8 +192,8 @@ QPDF::pushInheritedAttributesToPageInternal2(
192 192 if (visited.count(this_og) > 0)
193 193 {
194 194 throw QPDFExc(
195   - qpdf_e_pages, this->file->getName(),
196   - this->last_object_description, 0,
  195 + qpdf_e_pages, this->m->file->getName(),
  196 + this->m->last_object_description, 0,
197 197 "Loop detected in /Pages structure (inherited attributes)");
198 198 }
199 199 visited.insert(this_og);
... ... @@ -219,9 +219,9 @@ QPDF::pushInheritedAttributesToPageInternal2(
219 219 {
220 220 if (! allow_changes)
221 221 {
222   - throw QPDFExc(qpdf_e_internal, this->file->getName(),
223   - this->last_object_description,
224   - this->file->getLastOffset(),
  222 + throw QPDFExc(qpdf_e_internal, this->m->file->getName(),
  223 + this->m->last_object_description,
  224 + this->m->file->getLastOffset(),
225 225 "optimize detected an "
226 226 "inheritable attribute when called "
227 227 "in no-change mode");
... ... @@ -269,8 +269,8 @@ QPDF::pushInheritedAttributesToPageInternal2(
269 269 setLastObjectDescription("Pages object",
270 270 cur_pages.getObjectID(),
271 271 cur_pages.getGeneration());
272   - warn(QPDFExc(qpdf_e_pages, this->file->getName(),
273   - this->last_object_description, 0,
  272 + warn(QPDFExc(qpdf_e_pages, this->m->file->getName(),
  273 + this->m->last_object_description, 0,
274 274 "Unknown key " + key + " in /Pages object"
275 275 " is being discarded as a result of"
276 276 " flattening the /Pages tree"));
... ... @@ -337,9 +337,9 @@ QPDF::pushInheritedAttributesToPageInternal2(
337 337 }
338 338 else
339 339 {
340   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
341   - this->last_object_description,
342   - this->file->getLastOffset(),
  340 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  341 + this->m->last_object_description,
  342 + this->m->file->getLastOffset(),
343 343 "invalid Type " + type + " in page tree");
344 344 }
345 345 visited.erase(this_og);
... ... @@ -382,8 +382,8 @@ QPDF::updateObjectMapsInternal(ObjUser const&amp; ou, QPDFObjectHandle oh,
382 382 QTC::TC("qpdf", "QPDF opt loop detected");
383 383 return;
384 384 }
385   - this->obj_user_to_objects[ou].insert(og);
386   - this->object_to_obj_users[og].insert(ou);
  385 + this->m->obj_user_to_objects[ou].insert(og);
  386 + this->m->object_to_obj_users[og].insert(ou);
387 387 visited.insert(og);
388 388 }
389 389  
... ... @@ -445,8 +445,8 @@ QPDF::filterCompressedObjects(std::map&lt;int, int&gt; const&amp; object_stream_data)
445 445 std::map<QPDFObjGen, std::set<ObjUser> > t_object_to_obj_users;
446 446  
447 447 for (std::map<ObjUser, std::set<QPDFObjGen> >::iterator i1 =
448   - this->obj_user_to_objects.begin();
449   - i1 != this->obj_user_to_objects.end(); ++i1)
  448 + this->m->obj_user_to_objects.begin();
  449 + i1 != this->m->obj_user_to_objects.end(); ++i1)
450 450 {
451 451 ObjUser const& ou = (*i1).first;
452 452 std::set<QPDFObjGen> const& objects = (*i1).second;
... ... @@ -468,8 +468,8 @@ QPDF::filterCompressedObjects(std::map&lt;int, int&gt; const&amp; object_stream_data)
468 468 }
469 469  
470 470 for (std::map<QPDFObjGen, std::set<ObjUser> >::iterator i1 =
471   - this->object_to_obj_users.begin();
472   - i1 != this->object_to_obj_users.end(); ++i1)
  471 + this->m->object_to_obj_users.begin();
  472 + i1 != this->m->object_to_obj_users.end(); ++i1)
473 473 {
474 474 QPDFObjGen const& og = (*i1).first;
475 475 std::set<ObjUser> const& objusers = (*i1).second;
... ... @@ -490,6 +490,6 @@ QPDF::filterCompressedObjects(std::map&lt;int, int&gt; const&amp; object_stream_data)
490 490 }
491 491 }
492 492  
493   - this->obj_user_to_objects = t_obj_user_to_objects;
494   - this->object_to_obj_users = t_object_to_obj_users;
  493 + this->m->obj_user_to_objects = t_obj_user_to_objects;
  494 + this->m->object_to_obj_users = t_object_to_obj_users;
495 495 }
... ...
libqpdf/QPDF_pages.cc
... ... @@ -44,12 +44,12 @@ std::vector&lt;QPDFObjectHandle&gt; const&amp;
44 44 QPDF::getAllPages()
45 45 {
46 46 // Note that pushInheritedAttributesToPage may also be used to
47   - // initialize this->all_pages.
48   - if (this->all_pages.empty())
  47 + // initialize this->m->all_pages.
  48 + if (this->m->all_pages.empty())
49 49 {
50   - getAllPagesInternal(getRoot().getKey("/Pages"), this->all_pages);
  50 + getAllPagesInternal(getRoot().getKey("/Pages"), this->m->all_pages);
51 51 }
52   - return this->all_pages;
  52 + return this->m->all_pages;
53 53 }
54 54  
55 55 void
... ... @@ -69,8 +69,8 @@ QPDF::getAllPagesInternal2(QPDFObjectHandle cur_pages,
69 69 if (visited.count(this_og) > 0)
70 70 {
71 71 throw QPDFExc(
72   - qpdf_e_pages, this->file->getName(),
73   - this->last_object_description, 0,
  72 + qpdf_e_pages, this->m->file->getName(),
  73 + this->m->last_object_description, 0,
74 74 "Loop detected in /Pages structure (getAllPages)");
75 75 }
76 76 visited.insert(this_og);
... ... @@ -103,9 +103,9 @@ QPDF::getAllPagesInternal2(QPDFObjectHandle cur_pages,
103 103 }
104 104 else
105 105 {
106   - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
107   - this->last_object_description,
108   - this->file->getLastOffset(),
  106 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
  107 + this->m->last_object_description,
  108 + this->m->file->getLastOffset(),
109 109 "invalid Type " + type + " in page tree");
110 110 }
111 111 visited.erase(this_og);
... ... @@ -119,9 +119,9 @@ QPDF::updateAllPagesCache()
119 119 // it that they got from calls to getAllPages(). We can defer
120 120 // recalculation of pageobj_to_pages_pos until needed.
121 121 QTC::TC("qpdf", "QPDF updateAllPagesCache");
122   - this->all_pages.clear();
123   - this->pageobj_to_pages_pos.clear();
124   - this->pushed_inherited_attributes_to_pages = false;
  122 + this->m->all_pages.clear();
  123 + this->m->pageobj_to_pages_pos.clear();
  124 + this->m->pushed_inherited_attributes_to_pages = false;
125 125 getAllPages();
126 126 }
127 127  
... ... @@ -131,26 +131,26 @@ QPDF::flattenPagesTree()
131 131 // If not already done, flatten the /Pages structure and
132 132 // initialize pageobj_to_pages_pos.
133 133  
134   - if (! this->pageobj_to_pages_pos.empty())
  134 + if (! this->m->pageobj_to_pages_pos.empty())
135 135 {
136 136 return;
137 137 }
138 138  
139 139 // Push inherited objects down to the /Page level. As a side
140   - // effect this->all_pages will also be generated.
  140 + // effect this->m->all_pages will also be generated.
141 141 pushInheritedAttributesToPage(true, true);
142 142  
143 143 QPDFObjectHandle pages = getRoot().getKey("/Pages");
144 144  
145   - int const len = this->all_pages.size();
  145 + int const len = this->m->all_pages.size();
146 146 for (int pos = 0; pos < len; ++pos)
147 147 {
148 148 // populate pageobj_to_pages_pos and fix parent pointer
149   - insertPageobjToPage(this->all_pages.at(pos), pos, true);
150   - this->all_pages.at(pos).replaceKey("/Parent", pages);
  149 + insertPageobjToPage(this->m->all_pages.at(pos), pos, true);
  150 + this->m->all_pages.at(pos).replaceKey("/Parent", pages);
151 151 }
152 152  
153   - pages.replaceKey("/Kids", QPDFObjectHandle::newArray(this->all_pages));
  153 + pages.replaceKey("/Kids", QPDFObjectHandle::newArray(this->m->all_pages));
154 154 // /Count has not changed
155 155 if (pages.getKey("/Count").getIntValue() != len)
156 156 {
... ... @@ -165,21 +165,22 @@ QPDF::insertPageobjToPage(QPDFObjectHandle const&amp; obj, int pos,
165 165 QPDFObjGen og(obj.getObjGen());
166 166 if (check_duplicate)
167 167 {
168   - if (! this->pageobj_to_pages_pos.insert(std::make_pair(og, pos)).second)
  168 + if (! this->m->pageobj_to_pages_pos.insert(
  169 + std::make_pair(og, pos)).second)
169 170 {
170 171 QTC::TC("qpdf", "QPDF duplicate page reference");
171 172 setLastObjectDescription("page " + QUtil::int_to_string(pos) +
172 173 " (numbered from zero)",
173 174 og.getObj(), og.getGen());
174   - throw QPDFExc(qpdf_e_pages, this->file->getName(),
175   - this->last_object_description, 0,
  175 + throw QPDFExc(qpdf_e_pages, this->m->file->getName(),
  176 + this->m->last_object_description, 0,
176 177 "duplicate page reference found;"
177 178 " this would cause loss of data");
178 179 }
179 180 }
180 181 else
181 182 {
182   - this->pageobj_to_pages_pos[og] = pos;
  183 + this->m->pageobj_to_pages_pos[og] = pos;
183 184 }
184 185 }
185 186  
... ... @@ -195,13 +196,13 @@ QPDF::insertPage(QPDFObjectHandle newpage, int pos)
195 196 if (! newpage.isIndirect())
196 197 {
197 198 QTC::TC("qpdf", "QPDF insert non-indirect page");
198   - newpage = this->makeIndirectObject(newpage);
  199 + newpage = makeIndirectObject(newpage);
199 200 }
200 201 else if (newpage.getOwningQPDF() != this)
201 202 {
202 203 QTC::TC("qpdf", "QPDF insert foreign page");
203 204 newpage.getOwningQPDF()->pushInheritedAttributesToPage();
204   - newpage = this->copyForeignObject(newpage, true);
  205 + newpage = copyForeignObject(newpage, true);
205 206 }
206 207 else
207 208 {
... ... @@ -210,26 +211,26 @@ QPDF::insertPage(QPDFObjectHandle newpage, int pos)
210 211  
211 212 QTC::TC("qpdf", "QPDF insert page",
212 213 (pos == 0) ? 0 : // insert at beginning
213   - (pos == static_cast<int>(this->all_pages.size())) ? 1 : // at end
  214 + (pos == static_cast<int>(this->m->all_pages.size())) ? 1 : // at end
214 215 2); // insert in middle
215 216  
216 217 QPDFObjectHandle pages = getRoot().getKey("/Pages");
217 218 QPDFObjectHandle kids = pages.getKey("/Kids");
218 219 assert ((pos >= 0) &&
219   - (static_cast<size_t>(pos) <= this->all_pages.size()));
  220 + (static_cast<size_t>(pos) <= this->m->all_pages.size()));
220 221  
221 222 newpage.replaceKey("/Parent", pages);
222 223 kids.insertItem(pos, newpage);
223 224 int npages = kids.getArrayNItems();
224 225 pages.replaceKey("/Count", QPDFObjectHandle::newInteger(npages));
225   - this->all_pages.insert(this->all_pages.begin() + pos, newpage);
226   - assert(this->all_pages.size() == static_cast<size_t>(npages));
  226 + this->m->all_pages.insert(this->m->all_pages.begin() + pos, newpage);
  227 + assert(this->m->all_pages.size() == static_cast<size_t>(npages));
227 228 for (int i = pos + 1; i < npages; ++i)
228 229 {
229   - insertPageobjToPage(this->all_pages.at(i), i, false);
  230 + insertPageobjToPage(this->m->all_pages.at(i), i, false);
230 231 }
231 232 insertPageobjToPage(newpage, pos, true);
232   - assert(this->pageobj_to_pages_pos.size() == static_cast<size_t>(npages));
  233 + assert(this->m->pageobj_to_pages_pos.size() == static_cast<size_t>(npages));
233 234 }
234 235  
235 236 void
... ... @@ -238,7 +239,8 @@ QPDF::removePage(QPDFObjectHandle page)
238 239 int pos = findPage(page); // also ensures flat /Pages
239 240 QTC::TC("qpdf", "QPDF remove page",
240 241 (pos == 0) ? 0 : // remove at beginning
241   - (pos == static_cast<int>(this->all_pages.size() - 1)) ? 1 : // end
  242 + (pos == static_cast<int>(
  243 + this->m->all_pages.size() - 1)) ? 1 : // end
242 244 2); // remove in middle
243 245  
244 246 QPDFObjectHandle pages = getRoot().getKey("/Pages");
... ... @@ -247,13 +249,13 @@ QPDF::removePage(QPDFObjectHandle page)
247 249 kids.eraseItem(pos);
248 250 int npages = kids.getArrayNItems();
249 251 pages.replaceKey("/Count", QPDFObjectHandle::newInteger(npages));
250   - this->all_pages.erase(this->all_pages.begin() + pos);
251   - assert(this->all_pages.size() == static_cast<size_t>(npages));
252   - this->pageobj_to_pages_pos.erase(page.getObjGen());
253   - assert(this->pageobj_to_pages_pos.size() == static_cast<size_t>(npages));
  252 + this->m->all_pages.erase(this->m->all_pages.begin() + pos);
  253 + assert(this->m->all_pages.size() == static_cast<size_t>(npages));
  254 + this->m->pageobj_to_pages_pos.erase(page.getObjGen());
  255 + assert(this->m->pageobj_to_pages_pos.size() == static_cast<size_t>(npages));
254 256 for (int i = pos; i < npages; ++i)
255 257 {
256   - insertPageobjToPage(this->all_pages.at(i), i, false);
  258 + insertPageobjToPage(this->m->all_pages.at(i), i, false);
257 259 }
258 260 }
259 261  
... ... @@ -295,12 +297,12 @@ QPDF::findPage(QPDFObjGen const&amp; og)
295 297 {
296 298 flattenPagesTree();
297 299 std::map<QPDFObjGen, int>::iterator it =
298   - this->pageobj_to_pages_pos.find(og);
299   - if (it == this->pageobj_to_pages_pos.end())
  300 + this->m->pageobj_to_pages_pos.find(og);
  301 + if (it == this->m->pageobj_to_pages_pos.end())
300 302 {
301 303 setLastObjectDescription("page object", og.getObj(), og.getGen());
302   - throw QPDFExc(qpdf_e_pages, this->file->getName(),
303   - this->last_object_description, 0,
  304 + throw QPDFExc(qpdf_e_pages, this->m->file->getName(),
  305 + this->m->last_object_description, 0,
304 306 "page object not referenced in /Pages tree");
305 307 }
306 308 return (*it).second;
... ...