void FoxPro::loadHeader(SeekableReadStream &dbf, uint32 &recordSize, uint32 &recordCount, uint32 &firstRecordPos) { byte version = dbf.readByte(); if (version != 0xF5) throw Exception("Unknown database version 0x%02X", version); int lastUpdateYear = dbf.readByte() + 2000; int lastUpdateMonth = dbf.readByte(); int lastUpdateDay = dbf.readByte(); _lastUpdate = date(lastUpdateYear, lastUpdateMonth, lastUpdateDay); recordCount = dbf.readUint32LE(); firstRecordPos = dbf.readUint16LE(); recordSize = dbf.readUint16LE(); dbf.skip(16); // Reserved byte flags = dbf.readByte(); _hasIndex = flags & 0x01; _hasMemo = (flags & 0x02) != 0; if (flags & 0x04) throw Exception("DBC unsupported"); if (flags & 0xF8) throw Exception("Unknown flags 0x%02X", flags); dbf.skip(1); // Codepage marker dbf.skip(2); // Reserved }
void FoxPro::loadMemos(SeekableReadStream &fpt) { fpt.skip(4); // Next free block fpt.skip(2); // Unused _memoBlockSize = fpt.readUint16BE(); if (_memoBlockSize < 33) _memoBlockSize *= 1024; fpt.skip(504); // Unused while (!fpt.eos()) { _memos.push_back(new byte[_memoBlockSize]); byte *data = _memos.back(); fpt.read(data, _memoBlockSize); } }
void ZipFile::getFileProperties(SeekableReadStream &zip, const IFile &file, uint16 &compMethod, uint32 &compSize, uint32 &realSize) const { zip.seek(file.offset); uint32 tag = zip.readUint32LE(); if (tag != 0x04034B50) throw Exception("Unknown ZIP record %08X", tag); zip.skip(4); compMethod = zip.readUint16LE(); zip.skip(8); compSize = zip.readUint32LE(); realSize = zip.readUint32LE(); uint16 nameLength = zip.readUint16LE(); uint16 extraLength = zip.readUint16LE(); zip.skip(nameLength); zip.skip(extraLength); }
void FoxPro::loadFields(SeekableReadStream &dbf, uint32 recordSize) { // Read all field descriptions, 0x0D is the end marker uint32 fieldsLength = 0; while (!dbf.eos() && (dbf.readByte() != 0x0D)) { Field field; dbf.seek(-1, SeekableReadStream::kOriginCurrent); field.name = readStringFixed(dbf, kEncodingASCII, 11); field.type = (Type) dbf.readByte(); field.offset = dbf.readUint32LE(); field.size = dbf.readByte(); field.decimals = dbf.readByte(); field.flags = dbf.readByte(); field.autoIncNext = dbf.readUint32LE(); field.autoIncStep = dbf.readByte(); dbf.skip(8); // Reserved if (field.offset != (fieldsLength + 1)) throw Exception("Field offset makes no sense (%d != %d)", field.offset, fieldsLength + 1); if (field.type == kTypeMemo) _hasMemo = true; fieldsLength += field.size; _fields.push_back(field); } if (recordSize != (fieldsLength + 1)) throw Exception("Length of all fields does not equal the record size"); }
void ZipFile::load(SeekableReadStream &zip) { size_t endPos = findCentralDirectoryEnd(zip); if (endPos == 0) throw Exception("End of central directory record not found"); zip.seek(endPos); zip.skip(4); // Header, already checked uint16 curDisk = zip.readUint16LE(); uint16 centralDirDisk = zip.readUint16LE(); uint16 curDiskDirs = zip.readUint16LE(); uint16 totalDirs = zip.readUint16LE(); if ((curDisk != 0) || (curDisk != centralDirDisk) || (curDiskDirs != totalDirs)) throw Exception("Unsupported multi-disk ZIP file"); zip.skip(4); // Size of central directory uint32 centralDirPos = zip.readUint32LE(); zip.seek(centralDirPos); uint32 tag = zip.readUint32LE(); if (tag != 0x02014B50) throw Exception("Unknown ZIP record %08X", tag); _iFiles.reserve(totalDirs); while (tag == 0x02014B50) { File file; IFile iFile; zip.skip(20); iFile.size = zip.readUint32LE(); uint16 nameLength = zip.readUint16LE(); uint16 extraLength = zip.readUint16LE(); uint16 commentLength = zip.readUint16LE(); uint16 diskNum = zip.readUint16LE(); if (diskNum != 0) throw Exception("Unsupported multi-disk ZIP file"); zip.skip(6); // File attributes iFile.offset = zip.readUint32LE(); file.name = readStringFixed(zip, kEncodingASCII, nameLength).toLower(); zip.skip(extraLength); zip.skip(commentLength); tag = zip.readUint32LE(); if ((tag != 0x02014B50) && (tag != 0x06054B50)) throw Exception("Unknown ZIP record %08X", tag); // Ignore empty file names if (!file.name.empty()) { // HACK: Skip any filename with a trailing slash because it's // a directory. The proper solution would be to interpret the // file attributes. if (*(--file.name.end()) != '/') { file.index = _iFiles.size(); _files.push_back(file); _iFiles.push_back(iFile); } } } }