xoreos  0.0.5
erffile.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 /* See BioWare's own specs released for Neverwinter Nights modding
26  * (<https://github.com/xoreos/xoreos-docs/tree/master/specs/bioware>)
27  */
28 
29 #include <cassert>
30 
32 #include "src/common/readfile.h"
33 #include "src/common/util.h"
34 #include "src/common/strutil.h"
35 #include "src/common/error.h"
36 #include "src/common/encoding.h"
37 #include "src/common/md5.h"
38 #include "src/common/blowfish.h"
39 #include "src/common/deflate.h"
40 
41 #include "src/aurora/erffile.h"
42 #include "src/aurora/util.h"
43 
44 static const uint32 kERFID = MKTAG('E', 'R', 'F', ' ');
45 static const uint32 kMODID = MKTAG('M', 'O', 'D', ' ');
46 static const uint32 kHAKID = MKTAG('H', 'A', 'K', ' ');
47 static const uint32 kSAVID = MKTAG('S', 'A', 'V', ' ');
48 static const uint32 kVersion10 = MKTAG('V', '1', '.', '0');
49 static const uint32 kVersion11 = MKTAG('V', '1', '.', '1');
50 static const uint32 kVersion20 = MKTAG('V', '2', '.', '0');
51 static const uint32 kVersion21 = MKTAG('V', '2', '.', '1');
52 static const uint32 kVersion22 = MKTAG('V', '2', '.', '2');
53 static const uint32 kVersion30 = MKTAG('V', '3', '.', '0');
54 
55 namespace Aurora {
56 
57 static const size_t kNWNPremiumKeyLength = 56;
58 
60  {
61  0x8A, 0x83, 0x5A, 0x2D, 0x01, 0x10, 0x5C, 0xBE, 0xCE, 0x2C, 0xD0, 0x69, 0xB8, 0x48, 0xC9, 0xBE,
62  0xAA, 0x7E, 0x57, 0xBD, 0xAB, 0x94, 0xCE, 0x0D, 0x09, 0x10, 0xBD, 0x57, 0x8D, 0x1A, 0x0D, 0x35,
63  0xC9, 0x84, 0x90, 0xFA, 0x7B, 0x65, 0x32, 0x97, 0xCF, 0x39, 0x66, 0xA7, 0x60, 0xEC, 0x99, 0xEF,
64  0x76, 0x5A, 0x3B, 0x2C, 0x2F, 0x0A, 0x24, 0xC3
65  }, {
66  0x5C, 0xA8, 0x83, 0xCE, 0x6D, 0x9C, 0x84, 0x3B, 0xDE, 0xA1, 0xD7, 0x85, 0x78, 0x87, 0xFD, 0x0D,
67  0xD7, 0x97, 0x42, 0x38, 0x93, 0x53, 0xCD, 0x3D, 0xEC, 0x03, 0xCE, 0x15, 0x09, 0x48, 0xD7, 0x9B,
68  0x86, 0x20, 0x19, 0x21, 0xC2, 0x6E, 0x42, 0xEE, 0xAF, 0xBE, 0xCA, 0x41, 0xBF, 0x0A, 0x66, 0x9A,
69  0x2A, 0x8F, 0xC2, 0x04, 0x56, 0x14, 0x77, 0x82
70  }, {
71  0x94, 0x37, 0xDD, 0x56, 0xED, 0xD9, 0xF0, 0x41, 0x91, 0x28, 0xC2, 0xD5, 0x4F, 0x97, 0xE8, 0x5D,
72  0x95, 0x42, 0x41, 0xB5, 0xA3, 0xA2, 0x03, 0xB6, 0x08, 0x8B, 0xC1, 0xC7, 0xCB, 0xEE, 0xD8, 0xD9,
73  0x83, 0x4E, 0x9F, 0xAB, 0x69, 0x41, 0x6C, 0xFC, 0x87, 0x13, 0xB5, 0xFD, 0xCA, 0x0A, 0x1D, 0x83,
74  0x89, 0x51, 0x4E, 0xF3, 0x5B, 0xED, 0x9A, 0x5C
75  }, {
76  0xEC, 0xBF, 0x9A, 0x75, 0x39, 0xE4, 0x65, 0x10, 0xCA, 0xA1, 0xB6, 0x3A, 0x76, 0xA2, 0x50, 0xDD,
77  0xE2, 0x06, 0xEA, 0x39, 0x20, 0x0F, 0xBC, 0xC7, 0x5D, 0x03, 0xD6, 0xB2, 0x75, 0x83, 0xEF, 0x08,
78  0xA7, 0xFD, 0x68, 0xDB, 0x33, 0xAA, 0x69, 0xA1, 0x39, 0x80, 0x62, 0x29, 0x8C, 0xE9, 0x2B, 0xA9,
79  0x60, 0xC6, 0x93, 0x27, 0x2C, 0x0D, 0x42, 0x26
80  }, {
81  0x72, 0xA3, 0x8B, 0x0C, 0x49, 0x63, 0x53, 0x32, 0x7D, 0x86, 0x9C, 0x3D, 0x48, 0x84, 0x77, 0xBD,
82  0xBB, 0x7C, 0x48, 0xDC, 0x33, 0x45, 0x40, 0x78, 0xAF, 0x26, 0x64, 0x96, 0x7F, 0x80, 0x44, 0x67,
83  0xF7, 0xDA, 0x08, 0x74, 0xF4, 0xD8, 0x7C, 0x2D, 0x2D, 0x1F, 0xF2, 0xD1, 0x5D, 0x18, 0xF7, 0xD2,
84  0x71, 0x28, 0xD0, 0x31, 0x5C, 0xCC, 0x6E, 0xCD
85  }, {
86  0x1D, 0xEA, 0x5E, 0x04, 0x0B, 0x43, 0xF2, 0x2F, 0x23, 0x90, 0x04, 0x38, 0x5C, 0xA1, 0x18, 0x9C,
87  0xFF, 0xB1, 0xB1, 0x86, 0xE6, 0x69, 0x67, 0x8E, 0x29, 0x08, 0x94, 0x4C, 0x08, 0x22, 0x0A, 0x8C,
88  0x9D, 0xC5, 0xFE, 0xE2, 0x27, 0x84, 0xE7, 0xD3, 0xD1, 0x6B, 0xF2, 0x38, 0xF4, 0xFF, 0xBF, 0x80,
89  0x7E, 0x1E, 0x98, 0x75, 0x32, 0xA3, 0x2C, 0xF6
90  }
91 };
92 
93 
95  clear();
96 }
97 
99 }
100 
102  resCount = 0;
103  langCount = 0;
104 
105  descriptionID = 0;
106 
107  offDescription = 0xFFFFFFFF;
108  offKeyList = 0xFFFFFFFF;
109  offResList = 0xFFFFFFFF;
110 
111  descriptionSize = 0;
112 
113  buildYear = 0;
114  buildDay = 0;
115 
116  isNWNPremium = false;
117 
118  moduleID = 0;
119 
120  encryption = kEncryptionNone;
121  compression = kCompressionNone;
122 
123  clearStringTable();
124 }
125 
127  stringTable.reset();
128 
129  stringTableSize = 0;
130 }
131 
132 bool ERFFile::ERFHeader::isSensible(size_t fileSize) {
133  if ((buildYear > 2200) || (buildYear < 2000) || (buildDay > 366))
134  return false;
135 
136  if ((resCount >= 131072) || (langCount > 32))
137  return false;
138 
139  if ((offDescription != 0xFFFFFFFF) && (offDescription > fileSize))
140  return false;
141  if ((offKeyList != 0xFFFFFFFF) && (offKeyList > fileSize))
142  return false;
143  if ((offResList != 0xFFFFFFFF) && (offResList > fileSize))
144  return false;
145 
146  return true;
147 }
148 
149 
150 ERFFile::ERFFile(Common::SeekableReadStream *erf, const std::vector<byte> &password) :
151  _erf(erf), _password(password) {
152 
153  assert(_erf);
154 
155  load();
156 }
157 
159 }
160 
161 void ERFFile::verifyVersion(uint32 id, uint32 version, bool utf16le) {
162  if ((id != kERFID) && (id != kMODID) && (id != kHAKID) && (id != kSAVID))
163  throw Common::Exception("Not an ERF file (%s)", Common::debugTag(id).c_str());
164 
165  if ((version != kVersion10) && (version != kVersion11) &&
166  (version != kVersion20) && (version != kVersion21) && (version != kVersion22) &&
167  (version != kVersion30))
168  throw Common::Exception("Unsupported ERF file version %s", Common::debugTag(version).c_str());
169 
170  if ((version != kVersion10) && (version != kVersion11) && (version != kVersion21) && !utf16le)
171  throw Common::Exception("ERF file version 2.0 or 2.2+, but not UTF-16LE");
172 }
173 
176  return;
177 
178  if (_password.empty())
179  throw Common::Exception("Encrypted; password required");
180 
182  throw Common::Exception("Unsupported XOR encryption");
183 
185  // The digest is the simple MD5 sum of the password
187  throw Common::Exception("Password digest does not match");
188 
189  // Parse the password into a number, and create an 8-byte little endian array out of it
190 
191  Common::UString passwordString(reinterpret_cast<const char *>(&_password[0]), _password.size());
192 
193  uint64 passwordNumber = 0;
194  Common::parseString(passwordString, passwordNumber);
195 
196  _password.resize(8);
197  for (size_t i = 0; i < 8; i++) {
198  _password[i] = passwordNumber & 0xFF;
199 
200  passwordNumber >>= 8;
201  }
202 
203  return;
204  }
205 
207  // The digest is the MD5 sum of an [0-255] array encrypted by the password
208  byte buffer[256];
209  for (size_t i = 0; i < sizeof(buffer); i++)
210  buffer[i] = i;
211 
212  Common::MemoryReadStream bufferStream(buffer);
214  bufferEncrypted(Common::encryptBlowfishEBC(bufferStream, _password));
215 
216  if (!Common::compareMD5Digest(*bufferEncrypted, _header.passwordDigest))
217  throw Common::Exception("Password digest does not match");
218 
219  return;
220  }
221 
222  throw Common::Exception("Invalid encryption type %u", (uint)_header.encryption);
223 }
224 
226  const std::vector<byte> &password) {
227 
229  decryptERF(decrypt(erf, erf.pos(), 152, kEncryptionBlowfishNWN, password));
230 
231  readV11Header(*decryptERF, header);
232 
233  return header.isSensible(erf.size());
234 }
235 
237  const std::vector<byte> &md5, std::vector<byte> &password) {
238 
239  assert(md5.empty() || (md5.size() == Common::kMD5Length));
240 
241  password.resize(kNWNPremiumKeyLength);
242  const size_t headerPos = erf.pos();
243 
244  for (size_t i = 0; i < ARRAYSIZE(kNWNPremiumKeys); i++) {
245  std::memcpy(&password[0], kNWNPremiumKeys[i], kNWNPremiumKeyLength);
246  if (!md5.empty())
247  std::memcpy(&password[0] + kNWNPremiumKeyLength - Common::kMD5Length, &md5[0], Common::kMD5Length);
248 
249  erf.seek(headerPos);
250  if (decryptNWNPremiumHeader(erf, header, password))
251  return true;
252  }
253 
254  return false;
255 }
256 
258  std::vector<byte> &password) {
259 
260  assert(header.encryption == kEncryptionBlowfishNWN);
261 
262  if (!password.empty() && (password.size() != Common::kMD5Length))
263  throw Common::Exception("Invalid Neverwinter Nights premium module MD5 length (%u)",
264  (uint)password.size());
265 
266  const std::vector<byte> md5 = password;
267 
268  if (!findNWNPremiumKey(erf, header, md5, password))
269  throw Common::Exception("Wrong Neverwinter Nights premium module key");
270 
271  header.isNWNPremium = true;
273 }
274 
276  readHeader(*_erf);
277 
279 
280  try {
281 
283 
285 
287 
290 
292 
294 
295  } catch (Common::Exception &e) {
296  e.add("Failed reading ERF file");
297  throw;
298  }
299 
300 }
301 
304 
305  _erf->seek(0);
306 
308 
310 }
311 
313  header.langCount = erf.readUint32LE(); // Number of languages for the description
314  header.descriptionSize = erf.readUint32LE(); // Number of bytes in the description
315  header.resCount = erf.readUint32LE(); // Number of resources in the ERF
316 
317  header.offDescription = erf.readUint32LE();
318  header.offKeyList = erf.readUint32LE();
319  header.offResList = erf.readUint32LE();
320 
321  header.buildYear = erf.readUint32LE() + 1900;
322  header.buildDay = erf.readUint32LE();
323 
324  header.descriptionID = erf.readUint32LE();
325 
326  erf.skip(116); // Reserved
327 }
328 
330  header.langCount = erf.readUint32LE(); // Number of languages for the description
331  header.descriptionSize = erf.readUint32LE(); // Number of bytes in the description
332  header.resCount = erf.readUint32LE(); // Number of resources in the ERF
333 
334  header.offDescription = erf.readUint32LE();
335  header.offKeyList = erf.readUint32LE();
336  header.offResList = erf.readUint32LE();
337 
338  header.buildYear = erf.readUint32LE() + 1900;
339  header.buildDay = erf.readUint32LE();
340 
341  header.descriptionID = erf.readUint32LE();
342 
343  erf.skip(116); // Reserved
344 
345  const uint32 keyListSize = header.offResList - header.offKeyList;
346 
347  /* Check whether the "true" V1.1 extended filenames would fit into the key
348  * list. If so, this is probably a true V1.1 ERF, as found in Neverwinter
349  * Nights 2. If not, this is a Neverwinter Nights premium module with shorter
350  * filenames. */
351  header.isNWNPremium = (header.resCount > 0) && ((keyListSize / header.resCount) < 40);
352 
353  if (!header.isSensible()) {
354  header.isNWNPremium = true;
356  }
357 }
358 
360  header.resCount = erf.readUint32LE(); // Number of resources in the ERF
361 
362  header.buildYear = erf.readUint32LE() + 1900;
363  header.buildDay = erf.readUint32LE();
364 
365  erf.skip(4); // Unknown, always 0xFFFFFFFF?
366 
367  header.offResList = 0x00000020; // Resource list always starts at 0x20 in ERF V2.0
368 }
369 
371  erf.skip(8); // Unknown, always 0x00000000 0x00000000?
372 
373  header.resCount = erf.readUint32LE(); // Number of resources in the ERF
374 
375  erf.skip(4); // Unknown, always 0x00000000?
376 
377  header.buildYear = erf.readUint16LE() + 1900;
378  header.buildDay = erf.readUint16LE();
379 
380  erf.skip(4); // Unknown, always 0xFFFF0000?
381 
382  header.offResList = 0x00000020; // Resource list always starts at 0x20 in ERF V2.1
383 
385 }
386 
388  header.resCount = erf.readUint32LE(); // Number of resources in the ERF
389 
390  header.buildYear = erf.readUint32LE() + 1900;
391  header.buildDay = erf.readUint32LE();
392 
393  erf.skip(4); // Unknown, always 0xFFFFFFFF?
394 
395  flags = erf.readUint32LE();
396 
397  header.moduleID = erf.readUint32LE();
398 
399  header.passwordDigest.resize(Common::kMD5Length);
402 
403  header.offResList = 0x00000038; // Resource list always starts at 0x38 in ERF V2.2
404 
405  header.encryption = (Encryption) ((flags >> 4) & 0x0000000F);
406  header.compression = (Compression) ((flags >> 29) & 0x00000007);
407 }
408 
410  header.stringTableSize = erf.readUint32LE(); // Number of bytes in the string table
411  header.resCount = erf.readUint32LE(); // Number of resources in the ERF
412 
413  flags = erf.readUint32LE();
414 
415  header.moduleID = erf.readUint32LE();
416 
417  header.passwordDigest.resize(Common::kMD5Length);
420 
421  header.stringTable.reset(new char[header.stringTableSize]);
422  if (erf.read(header.stringTable.get(), header.stringTableSize) != header.stringTableSize) {
423  header.clearStringTable();
424  throw Common::Exception("Failed to read ERF string table");
425  }
426 
427  // Resource list always starts after the string table in ERF V3.0
428  header.offResList = 0x00000030 + header.stringTableSize;
429 
430  header.encryption = (Encryption) ((flags >> 4) & 0x0000000F);
431  header.compression = (Compression) ((flags >> 29) & 0x00000007);
432 }
433 
435  std::vector<byte> &password) {
436 
437  header.clear();
438 
439  if (version == kVersion10) {
440 
441  /* Version 1.0:
442  * Neverwinter Nights, Knights of the Old Republic I and II,
443  * Jade Empire, The Witcher. */
444 
445  readV10Header(erf, header);
446 
447  } else if (version == kVersion11) {
448 
449  /* Version 1.1:
450  * There's two slightly different formats of the 1.1 ERF version:
451  * - The one is present in Neverwinter Nights 2. It extends the filename
452  * field in the key list to 32 characters (from 16 in V1.0)
453  * - Premium modules in Neverwinter Nights. They are identical to V1.0
454  * ERFs, except that they may be encrypted.
455  */
456 
457  const size_t headerPos = erf.pos();
458 
459  readV11Header(erf, header);
460 
461  if (header.encryption == kEncryptionBlowfishNWN) {
462  erf.seek(headerPos);
463 
464  readNWNPremiumHeader(erf, header, password);
465  }
466 
467  } else if (version == kVersion20) {
468 
469  /* Version 2.0:
470  * Unencrypted data in Dragon Age: Origins (PC). */
471 
472  readV20Header(erf, header);
473 
474  } else if (version == kVersion21) {
475 
476  /* Version 2.1:
477  * Unencrypted data in Dragon Age: Origins (Xbox). */
478 
479  readV21Header(erf, header);
480 
481  } else if (version == kVersion22) {
482 
483  /* Version 2.2:
484  * Encrypted data in Dragon Age: Origins. */
485 
486  uint32 flags = 0;
487  readV22Header(erf, header, flags);
488 
489  } else if (version == kVersion30) {
490 
491  /* Version 3.0:
492  * Dragon Age II. */
493 
494  uint32 flags = 0;
495  readV30Header(erf, header, flags);
496  }
497 }
498 
500  const ERFHeader &header) {
501 
502  description.clear();
503  if ((header.offDescription == 0) || (header.offDescription == 0xFFFFFFFF) || (header.langCount == 0))
504  return;
505 
506  if (header.encryption == kEncryptionBlowfishNWN)
507  return;
508 
509  erf.seek(header.offDescription);
510  description.readLocString(erf, header.descriptionID, header.langCount);
511 }
512 
514  _resources.resize(header.resCount);
515  _iResources.resize(header.resCount);
516 
517  if (_version == kVersion10) {
518 
519  readV10KeyList(erf, header); // Read name and type part of the resource list
520  readV10ResList(erf, header); // Read offset and size part of the resource list
521 
522  } else if (_version == kVersion11) {
523 
524  // Read name and type part of the resource list
525  if (header.isNWNPremium)
526  readV10KeyList(erf, header);
527  else
528  readV11KeyList(erf, header);
529 
530  readV10ResList (erf, header); // Read offset and size part of the resource list
531 
532  } else if (_version == kVersion20) {
533 
534  // Read the resource list
535  readV20ResList(erf, header);
536 
537  } else if (_version == kVersion21) {
538 
539  // Read the resource list
540  readV21ResList(erf, header);
541 
542  } else if (_version == kVersion22) {
543 
544  // Read the resource list
545  readV22ResList(erf, header);
546 
547  } else if (_version == kVersion30) {
548 
549  // Read the resource list
550  readV30ResList(erf, header);
551 
552  }
553 
554 }
555 
557  erf.seek(header.offKeyList);
558 
559  uint32 index = 0;
560  for (ResourceList::iterator res = _resources.begin(); res != _resources.end(); ++index, ++res) {
561  res->name = Common::readStringFixed(erf, Common::kEncodingASCII, 16);
562  erf.skip(4); // Resource ID
563  res->type = (FileType) erf.readUint16LE();
564  erf.skip(2); // Reserved
565  res->index = index;
566  }
567 }
568 
570  erf.seek(header.offKeyList);
571 
572  uint32 index = 0;
573  for (ResourceList::iterator res = _resources.begin(); res != _resources.end(); ++index, ++res) {
574  res->name = Common::readStringFixed(erf, Common::kEncodingASCII, 32);
575  erf.skip(4); // Resource ID
576  res->type = (FileType) erf.readUint16LE();
577  erf.skip(2); // Reserved
578  res->index = index;
579  }
580 }
581 
583  erf.seek(header.offResList);
584 
585  for (IResourceList::iterator res = _iResources.begin(); res != _iResources.end(); ++res) {
586  res->offset = erf.readUint32LE();
587  res->packedSize = res->unpackedSize = erf.readUint32LE();
588  }
589 }
590 
592  erf.seek(header.offResList);
593 
594  uint32 index = 0;
595  ResourceList::iterator res = _resources.begin();
596  IResourceList::iterator iRes = _iResources.begin();
597  for (; (res != _resources.end()) && (iRes != _iResources.end()); ++index, ++res, ++iRes) {
599 
600  res->name = TypeMan.setFileType(name, kFileTypeNone);
601  res->type = TypeMan.getFileType(name);
602  res->index = index;
603 
604  iRes->offset = erf.readUint32LE();
605  iRes->packedSize = iRes->unpackedSize = erf.readUint32LE();
606  }
607 
608 }
609 
611  erf.seek(header.offResList);
612 
613  uint32 index = 0;
614  ResourceList::iterator res = _resources.begin();
615  IResourceList::iterator iRes = _iResources.begin();
616  for (; (res != _resources.end()) && (iRes != _iResources.end()); ++index, ++res, ++iRes) {
618 
619  res->name = TypeMan.setFileType(name, kFileTypeNone);
620  res->type = TypeMan.getFileType(name);
621  res->index = index;
622 
623  iRes->offset = erf.readUint32LE();
624  iRes->packedSize = erf.readUint32LE();
625  iRes->unpackedSize = erf.readUint32LE();
626  }
627 
628 }
629 
631  erf.seek(header.offResList);
632 
633  uint32 index = 0;
634  ResourceList::iterator res = _resources.begin();
635  IResourceList::iterator iRes = _iResources.begin();
636  for (; (res != _resources.end()) && (iRes != _iResources.end()); ++index, ++res, ++iRes) {
638 
639  res->name = TypeMan.setFileType(name, kFileTypeNone);
640  res->type = TypeMan.getFileType(name);
641  res->index = index;
642 
643  iRes->offset = erf.readUint32LE();
644  iRes->packedSize = erf.readUint32LE();
645  iRes->unpackedSize = erf.readUint32LE();
646  }
647 
648 }
649 
651  erf.seek(header.offResList);
652 
653  uint32 index = 0;
654  ResourceList::iterator res = _resources.begin();
655  IResourceList::iterator iRes = _iResources.begin();
656  for (; (res != _resources.end()) && (iRes != _iResources.end()); ++index, ++res, ++iRes) {
657  int32 nameOffset = erf.readSint32LE();
658 
659  if (nameOffset >= 0) {
660  if ((uint32)nameOffset >= header.stringTableSize)
661  throw Common::Exception("Invalid ERF string table offset");
662 
663  Common::UString name = header.stringTable.get() + nameOffset;
664  res->name = TypeMan.setFileType(name, kFileTypeNone);
665  res->type = TypeMan.getFileType(name);
666  }
667 
668  res->index = index;
669  res->hash = erf.readUint64LE();
670 
671  uint32 typeHash = erf.readUint32LE();
672 
673  // Look up the file type by its hash
674  FileType type = TypeMan.getFileType(Common::kHashFNV32, typeHash);
675  if (type != kFileTypeNone)
676  res->type = type;
677 
678  iRes->offset = erf.readUint32LE();
679  iRes->packedSize = erf.readUint32LE();
680  iRes->unpackedSize = erf.readUint32LE();
681  }
682 
683 }
684 
686  return _header.buildYear;
687 }
688 
690  return _header.buildDay;
691 }
692 
694  return _description;
695 }
696 
698  return _resources;
699 }
700 
702  if (index >= _iResources.size())
703  throw Common::Exception("Resource index out of range (%u/%u)", index, (uint)_iResources.size());
704 
705  return _iResources[index];
706 }
707 
709  return getIResource(index).unpackedSize;
710 }
711 
713  const IResource &res = getIResource(index);
714 
716  return new Common::SeekableSubReadStream(_erf.get(), res.offset, res.offset + res.packedSize);
717 
718  _erf->seek(res.offset);
719 
720  // Read
721  Common::MemoryReadStream *stream = _erf->readStream(res.packedSize);
722 
723  // Decrypt
725  stream = decrypt(stream, _header.encryption, _password);
726 
727  // Decompress
728  return decompress(stream, res.unpackedSize);
729 }
730 
732  Encryption encryption, const std::vector<byte> &password) {
733  switch (encryption) {
737  return Common::decryptBlowfishEBC(cryptStream, password);
738 
739  default:
740  throw Common::Exception("Invalid ERF encryption %u", (uint) encryption);
741  }
742 }
743 
745  Encryption encryption, const std::vector<byte> &password) {
746 
747  assert(cryptStream);
748 
750 
751  return decrypt(*stream, encryption, password);
752 }
753 
755  Encryption encryption, const std::vector<byte> &password) {
756 
757  return decrypt(new Common::SeekableSubReadStream(&erf, pos, pos + size), encryption, password);
758 }
759 
761  Encryption encryption, const std::vector<byte> &password) {
762 
763  return decrypt(erf, erf.pos(), size, encryption, password);
764 }
765 
767  uint32 unpackedSize) const {
768 
769  Common::ScopedPtr<Common::MemoryReadStream> stream(packedStream);
770 
771  switch (_header.compression) {
772  case kCompressionNone:
773  if (stream->size() == unpackedSize)
774  return stream.release();
775 
776  return new Common::SeekableSubReadStream(stream.release(), 0, unpackedSize, true);
777 
779  return decompressBiowareZlib(stream.release(), unpackedSize);
780 
782  return decompressHeaderlessZlib(stream.release(), unpackedSize);
783 
785  return decompressStandardZlib(stream.release(), unpackedSize);
786 
787  default:
788  break;
789  }
790 
791  throw Common::Exception("Invalid ERF compression %u", (uint) _header.compression);
792 }
793 
795  uint32 unpackedSize) const {
796 
797  /* Decompress using raw inflate. An extra one byte header specifies the window size. */
798 
799  assert(packedStream);
800 
801  Common::ScopedPtr<Common::MemoryReadStream> stream(packedStream);
802 
803  const byte * const compressedData = stream->getData();
804  const uint32 packedSize = stream->size();
805 
806  return decompressZlib(compressedData + 1, packedSize - 1, unpackedSize, *compressedData >> 4);
807 }
808 
810  uint32 unpackedSize) const {
811 
812  /* Decompress using raw inflate. Use the default maximum window size (15). */
813 
814  assert(packedStream);
815 
816  Common::ScopedPtr<Common::MemoryReadStream> stream(packedStream);
817 
818  const byte * const compressedData = stream->getData();
819  const uint32 packedSize = stream->size();
820 
821  return decompressZlib(compressedData, packedSize, unpackedSize, Common::kWindowBitsMax);
822 }
823 
825  uint32 unpackedSize) const {
826 
827  /* Decompress using raw inflate. Use the default maximum window size (15), and with zlib header. */
828 
829  assert(packedStream);
830 
831  Common::ScopedPtr<Common::MemoryReadStream> stream(packedStream);
832 
833  const byte * const compressedData = stream->getData();
834  const uint32 packedSize = stream->size();
835 
836  return decompressZlib(compressedData, packedSize, unpackedSize, -Common::kWindowBitsMax);
837 }
838 
840  uint32 unpackedSize, int windowBits) const {
841 
842  // Decompress. Negative window size to signal not to look for a gzip header.
843  const byte *data = Common::decompressDeflate(compressedData, packedSize, unpackedSize, -windowBits);
844 
845  return new Common::MemoryReadStream(data, unpackedSize, true);
846 }
847 
849  // Only V3 uses hashing
851 }
852 
854  uint32 id, version;
855  bool ut16le;
856 
857  readHeader(erf, id, version, ut16le);
858  verifyVersion(id, version, ut16le);
859 
860  ERFHeader header;
861  LocString description;
862 
863  try {
864  std::vector<byte> password;
865  readERFHeader(erf, header, version, password);
866  } catch (...) {
867  return description;
868  }
869 
870  readDescription(description, erf, header);
871 
872  return description;
873 }
874 
876  Common::ReadFile erf(fileName);
877 
878  return getDescription(erf);
879 }
880 
881 } // End of namespace Aurora
Common::SeekableReadStream * decompressZlib(const byte *compressedData, uint32 packedSize, uint32 unpackedSize, int windowBits) const
Definition: erffile.cpp:839
static const uint32 kERFID
Definition: erffile.cpp:44
bool isSensible(size_t fileSize=SIZE_MAX)
Definition: erffile.cpp:132
#define MKTAG(a0, a1, a2, a3)
A wrapper macro used around four character constants, like &#39;DATA&#39;, to ensure portability.
Definition: endianness.h:140
uint16 readUint16LE()
Read an unsigned 16-bit word stored in little endian (LSB first) order from the stream and return it...
Definition: readstream.h:122
Common::SeekableReadStream * decompress(Common::MemoryReadStream *packedStream, uint32 unpackedSize) const
Definition: erffile.cpp:766
static const uint32 kVersion21
Definition: erffile.cpp:51
void add(const char *s,...) GCC_PRINTF(2
Definition: error.cpp:58
uint32 readUint32LE()
Read an unsigned 32-bit word stored in little endian (LSB first) order from the stream and return it...
Definition: readstream.h:133
#define TypeMan
Shortcut for accessing the file type manager.
Definition: util.h:85
Compression compression
The compression algorithm in use.
Definition: erffile.h:186
A class holding an UTF-8 string.
Definition: ustring.h:48
No compression as all.
Definition: erffile.h:156
uint32 stringTableSize
Size of the string table.
Definition: erffile.h:181
static const byte kNWNPremiumKeys[][kNWNPremiumKeyLength]
Definition: erffile.cpp:59
64bit Fowler-Noll-Vo hash by Glenn Fowler, Landon Curt Noll and Phong Vo.
Definition: hash.h:41
Common::SeekableReadStream * decompressStandardZlib(Common::MemoryReadStream *packedStream, uint32 unpackedSize) const
Definition: erffile.cpp:824
virtual size_t seek(ptrdiff_t offset, Origin whence=kOriginBegin)=0
Sets the stream position indicator for the stream.
A localized string.
Definition: locstring.h:43
void reset(PointerType o=0)
Resets the pointer with the new value.
Definition: scopedptr.h:87
PointerType release()
Returns the plain pointer value and releases ScopedPtr.
Definition: scopedptr.h:103
static void verifyVersion(uint32 id, uint32 version, bool utf16le)
Definition: erffile.cpp:161
void readLocString(Common::SeekableReadStream &stream, uint32 id, uint32 count)
Read a LocString out of a stream.
Definition: locstring.cpp:165
uint64_t uint64
Definition: types.h:206
Compression using DEFLATE with default parameters.
Definition: erffile.h:158
static void readV20Header(Common::SeekableReadStream &erf, ERFHeader &header)
Definition: erffile.cpp:359
void readV11KeyList(Common::SeekableReadStream &erf, const ERFHeader &header)
Definition: erffile.cpp:569
static const uint32 kSAVID
Definition: erffile.cpp:47
void readV20ResList(Common::SeekableReadStream &erf, const ERFHeader &header)
Definition: erffile.cpp:591
A simple streaming file reading class.
Definition: readfile.h:40
ResourceList _resources
External list of resource names and types.
Definition: erffile.h:217
Implementing the reading stream interfaces for plain memory blocks.
uint32 descriptionSize
Number of bytes in the description structure.
Definition: erffile.h:173
Utility functions to handle files used in BioWare&#39;s Aurora engine.
static void readV30Header(Common::SeekableReadStream &erf, ERFHeader &header, uint32 &flags)
Definition: erffile.cpp:409
UTF-16 LE (little endian).
Definition: encoding.h:44
MemoryReadStream * decryptBlowfishEBC(SeekableReadStream &input, const std::vector< byte > &key)
Decrypt the stream with the Blowfish algorithm in EBC mode.
Definition: blowfish.cpp:374
#define ARRAYSIZE(x)
Macro which determines the number of entries in a fixed size array.
Definition: util.h:131
uint32 offDescription
Offset to the description.
Definition: erffile.h:169
uint32 langCount
Number of language strings in the description.
Definition: erffile.h:166
static const uint32 kVersion10
Definition: erfwriter.cpp:31
bool _utf16le
The file&#39;s ID and version are in little-endian UTF-16.
Definition: aurorafile.h:79
static void readV22Header(Common::SeekableReadStream &erf, ERFHeader &header, uint32 &flags)
Definition: erffile.cpp:387
void verifyPasswordDigest()
Definition: erffile.cpp:174
byte * decompressDeflate(const byte *data, size_t inputSize, size_t outputSize, int windowBits)
Decompress (inflate) using zlib&#39;s DEFLATE algorithm.
Definition: deflate.cpp:63
void readV22ResList(Common::SeekableReadStream &erf, const ERFHeader &header)
Definition: erffile.cpp:630
Utility templates and functions for working with strings and streams.
The header of an ERF file.
Definition: erffile.h:163
static bool decryptNWNPremiumHeader(Common::SeekableReadStream &erf, ERFHeader &header, const std::vector< byte > &password)
Definition: erffile.cpp:225
Exception that provides a stack of explanations.
Definition: error.h:36
void readResources(Common::SeekableReadStream &erf, const ERFHeader &header)
Definition: erffile.cpp:513
FORCEINLINE int32 readSint32LE()
Read a signed 32-bit word stored in little endian (LSB first) order from the stream and return it...
Definition: readstream.h:195
const LocString & getDescription() const
Return the description.
Definition: erffile.cpp:693
static void readHeader(Common::ReadStream &stream, uint32 &id, uint32 &version, bool &utf16le)
Read the header out of a stream.
Definition: aurorafile.cpp:53
ERFFile(Common::SeekableReadStream *erf, const std::vector< byte > &password=std::vector< byte >())
Take over this stream and read an ERF file out of it.
Definition: erffile.cpp:150
Blowfish encryption as used by Dragon Age II (V3.0).
Definition: erffile.h:151
void readV10ResList(Common::SeekableReadStream &erf, const ERFHeader &header)
Definition: erffile.cpp:582
uint32 buildDay
The day of year the ERF was built.
Definition: erffile.h:176
Blowfish encryption as used by Neverwinter Nights (V1.1).
Definition: erffile.h:152
Basic exceptions to throw.
static const uint32 kVersion11
Definition: erffile.cpp:49
static void readDescription(LocString &description, Common::SeekableReadStream &erf, const ERFHeader &header)
Definition: erffile.cpp:499
Encryption / decryption using Bruce Schneier&#39;s Blowfish algorithm.
const byte * getData() const
std::vector< byte > _password
The password we were given, if any.
Definition: erffile.h:223
Compression using DEFLATE with an extra header byte.
Definition: erffile.h:157
static void readV10Header(Common::SeekableReadStream &erf, ERFHeader &header)
Definition: erffile.cpp:312
Common::SeekableReadStream * getResource(uint32 index, bool tryNoCopy=false) const
Return a stream of the resource&#39;s contents.
Definition: erffile.cpp:712
Utility templates and functions.
static const uint32 kVersion20
Definition: erffile.cpp:50
const ResourceList & getResources() const
Return the list of resources.
Definition: erffile.cpp:697
std::list< Resource > ResourceList
Definition: archive.h:57
IResourceList _iResources
Internal list of resource offsets and sizes.
Definition: erffile.h:220
void readV21ResList(Common::SeekableReadStream &erf, const ERFHeader &header)
Definition: erffile.cpp:610
bool isNWNPremium
Is this a Neverwinter Nights premium module?
Definition: erffile.h:178
virtual size_t skip(ptrdiff_t offset)
Skip the specified number of bytes, adding that offset to the current position in the stream...
Definition: readstream.h:317
Encryption encryption
The encryption algorithm in use.
Definition: erffile.h:185
std::vector< byte > passwordDigest
Digest of the encryption password, if any.
Definition: erffile.h:189
uint32 unpackedSize
The resource&#39;s unpacked size.
Definition: erffile.h:204
Handling BioWare&#39;s ERFs (encapsulated resource file).
uint32 descriptionID
ID of the description.
Definition: erffile.h:167
static void readV11Header(Common::SeekableReadStream &erf, ERFHeader &header)
Definition: erffile.cpp:329
virtual size_t read(void *dataPtr, size_t dataSize)=0
Read data from the stream.
Simple memory based &#39;stream&#39;, which implements the ReadStream interface for a plain memory block...
Definition: memreadstream.h:66
Utility functions for working with differing string encodings.
static const uint32 kHAKID
Definition: erffile.cpp:46
32bit Fowler-Noll-Vo hash by Glenn Fowler, Landon Curt Noll and Phong Vo.
Definition: hash.h:40
HashAlgo
The algorithm used for hashing.
Definition: hash.h:37
Blowfish encryption as used by Dragon Age: Origins (V2.2).
Definition: erffile.h:150
static bool findNWNPremiumKey(Common::SeekableReadStream &erf, ERFHeader &header, const std::vector< byte > &md5, std::vector< byte > &password)
Definition: erffile.cpp:236
uint32 _id
The file&#39;s ID.
Definition: aurorafile.h:77
StackException Exception
Definition: error.h:59
const Exception kReadError("Read error")
Exception when reading from a stream failed.
Definition: error.h:62
uint32 buildYear
The year the ERF was built.
Definition: erffile.h:175
uint32 _version
The file&#39;s version.
Definition: aurorafile.h:78
uint32 getBuildDay() const
Return the day of year the ERF was built.
Definition: erffile.cpp:689
uint32 moduleID
ID of the module this ERF belongs to.
Definition: erffile.h:183
virtual size_t size() const =0
Obtains the total size of the stream, measured in bytes.
ERFHeader _header
Definition: erffile.h:211
virtual size_t pos() const =0
Obtains the current value of the stream position indicator of the stream.
uint32 resCount
Number of resources in this ERF.
Definition: erffile.h:164
bool compareMD5Digest(ReadStream &stream, const std::vector< byte > &digest)
Hash the stream and compare the digests, returning true if they match.
Definition: md5.cpp:280
uint64 readUint64LE()
Read an unsigned 64-bit word stored in little endian (LSB first) order from the stream and return it...
Definition: readstream.h:144
Implementing the stream reading interfaces for files.
static Common::MemoryReadStream * decrypt(Common::SeekableReadStream &cryptStream, Encryption encryption, const std::vector< byte > &password)
Definition: erffile.cpp:731
Plain, unextended ASCII (7bit clean).
Definition: encoding.h:40
static const int kWindowBitsMax
Definition: deflate.h:41
PointerType get() const
Returns the plain pointer value.
Definition: scopedptr.h:96
Common::ScopedArray< char > stringTable
String table used for hashed ERFs.
Definition: erffile.h:180
Common::SeekableReadStream * decompressBiowareZlib(Common::MemoryReadStream *packedStream, uint32 unpackedSize) const
Definition: erffile.cpp:794
Common::ScopedPtr< Common::SeekableReadStream > _erf
Definition: erffile.h:209
XOR encryption as used by V2.2 and V3.0 (UNSUPPORTED!)
Definition: erffile.h:149
uint32 packedSize
The resource&#39;s packed size.
Definition: erffile.h:203
uint32 offset
The offset of the resource within the ERF.
Definition: erffile.h:202
void readV10KeyList(Common::SeekableReadStream &erf, const ERFHeader &header)
Definition: erffile.cpp:556
uint32 offKeyList
Offset to the key list.
Definition: erffile.h:170
No encryption at all.
Definition: erffile.h:148
uint32_t uint32
Definition: types.h:204
UString debugTag(uint32 tag, bool trim)
Create an elaborate string from an integer tag, for debugging purposes.
Definition: strutil.cpp:117
void readV30ResList(Common::SeekableReadStream &erf, const ERFHeader &header)
Definition: erffile.cpp:650
uint32 getResourceSize(uint32 index) const
Return the size of a resource.
Definition: erffile.cpp:708
Common::HashAlgo getNameHashAlgo() const
Return with which algorithm the name is hashed.
Definition: erffile.cpp:848
FileType
Various file types used by the Aurora engine and found in archives.
Definition: types.h:56
LocString _description
The ERF&#39;s description.
Definition: erffile.h:214
static const uint32 kVersion22
Definition: erffile.cpp:52
const IResource & getIResource(uint32 index) const
Definition: erffile.cpp:701
Compression using DEFLATE, standard zlib chunk.
Definition: erffile.h:159
size_t size() const
Obtains the total size of the stream, measured in bytes.
static const uint32 kMODID
Definition: erffile.cpp:45
UString readStringFixed(SeekableReadStream &stream, Encoding encoding, size_t length)
Read length bytes as a string with the given encoding out of a stream.
Definition: encoding.cpp:297
No hashing at all.
Definition: hash.h:38
SeekableSubReadStream provides access to a SeekableReadStream restricted to the range [begin...
Definition: readstream.h:359
Common::SeekableReadStream * decompressHeaderlessZlib(Common::MemoryReadStream *packedStream, uint32 unpackedSize) const
Definition: erffile.cpp:809
static void readERFHeader(Common::SeekableReadStream &erf, ERFHeader &header, uint32 version, std::vector< byte > &password)
Definition: erffile.cpp:434
Compress (deflate) and decompress (inflate) using zlib&#39;s DEFLATE algorithm.
MemoryReadStream * encryptBlowfishEBC(SeekableReadStream &input, const std::vector< byte > &key)
Encrypt the stream with the Blowfish algorithm in EBC mode.
Definition: blowfish.cpp:370
void decryptNWNPremium()
Definition: erffile.cpp:302
Internal resource information.
Definition: erffile.h:201
static const uint32 kVersion10
Definition: erffile.cpp:48
uint32 getBuildYear() const
Return the year the ERF was built.
Definition: erffile.cpp:685
Hashing/digesting using the MD5 algorithm.
uint32 offResList
Offset to the resource list.
Definition: erffile.h:171
Interface for a seekable & readable data stream.
Definition: readstream.h:265
static const size_t kMD5Length
The length of an MD5 digest in bytes.
Definition: md5.h:38
void parseString(const UString &str, T &value, bool allowEmpty)
Parse a string into any POD integer, float/double or bool type.
Definition: strutil.cpp:215
uint8 byte
Definition: types.h:209
static const uint32 kVersion30
Definition: erffile.cpp:53
static const size_t kNWNPremiumKeyLength
Definition: erffile.cpp:57
unsigned int uint
Definition: types.h:211
static void readV21Header(Common::SeekableReadStream &erf, ERFHeader &header)
Definition: erffile.cpp:370
int32_t int32
Definition: types.h:203
static void readNWNPremiumHeader(Common::SeekableReadStream &erf, ERFHeader &header, std::vector< byte > &password)
Definition: erffile.cpp:257