/*
OrpheusMS: MapleStory Private Server based on OdinMS
Copyright (C) 2012 Aaron Weiss <aaron@deviant-core.net>
Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package provider.wz;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import provider.MapleData;
import provider.MapleDataDirectoryEntry;
import provider.MapleDataFileEntry;
import provider.MapleDataProvider;
import tools.data.input.GenericLittleEndianAccessor;
import tools.data.input.GenericSeekableLittleEndianAccessor;
import tools.data.input.InputStreamByteStream;
import tools.data.input.LittleEndianAccessor;
import tools.data.input.RandomAccessByteStream;
import tools.data.input.SeekableLittleEndianAccessor;
public class WZFile implements MapleDataProvider {
static {
ListWZFile.init();
}
private File wzfile;
private LittleEndianAccessor lea;
private SeekableLittleEndianAccessor slea;
private int headerSize;
private WZDirectoryEntry root;
private boolean provideImages;
private int cOffset;
public WZFile(File wzfile, boolean provideImages) throws IOException {
this.wzfile = wzfile;
lea = new GenericLittleEndianAccessor(new InputStreamByteStream(new BufferedInputStream(new FileInputStream(wzfile))));
RandomAccessFile raf = new RandomAccessFile(wzfile, "r");
slea = new GenericSeekableLittleEndianAccessor(new RandomAccessByteStream(raf));
root = new WZDirectoryEntry(wzfile.getName(), 0, 0, null);
this.provideImages = provideImages;
load();
}
private void load() throws IOException {
lea.readAsciiString(4);
lea.readInt();
lea.readInt();
headerSize = lea.readInt();
lea.readNullTerminatedAsciiString();
lea.readShort();
parseDirectory(root);
cOffset = (int) lea.getBytesRead();
getOffsets(root);
}
private void getOffsets(MapleDataDirectoryEntry dir) {
for (MapleDataFileEntry file : dir.getFiles()) {
file.setOffset(cOffset);
cOffset += file.getSize();
}
for (MapleDataDirectoryEntry sdir : dir.getSubdirectories()) {
getOffsets(sdir);
}
}
private void parseDirectory(WZDirectoryEntry dir) {
int entries = WZTool.readValue(lea);
for (int i = 0; i < entries; i++) {
byte marker = lea.readByte();
String name = null;
int size, checksum;
switch (marker) {
case 0x02:
name = WZTool.readDecodedStringAtOffsetAndReset(slea, lea.readInt() + this.headerSize + 1);
size = WZTool.readValue(lea);
checksum = WZTool.readValue(lea);
lea.readInt(); // dummy int
dir.addFile(new WZFileEntry(name, size, checksum, dir));
break;
case 0x03:
case 0x04:
name = WZTool.readDecodedString(lea);
size = WZTool.readValue(lea);
checksum = WZTool.readValue(lea);
lea.readInt(); // dummy int
if (marker == 3) {
dir.addDirectory(new WZDirectoryEntry(name, size, checksum, dir));
} else {
dir.addFile(new WZFileEntry(name, size, checksum, dir));
}
break;
default:
}
}
for (MapleDataDirectoryEntry idir : dir.getSubdirectories()) {
parseDirectory((WZDirectoryEntry) idir);
}
}
public WZIMGFile getImgFile(String path) throws IOException {
String segments[] = path.split("/");
WZDirectoryEntry dir = root;
for (int x = 0; x < segments.length - 1; x++) {
dir = (WZDirectoryEntry) dir.getEntry(segments[x]);
if (dir == null) {
return null;
}
}
WZFileEntry entry = (WZFileEntry) dir.getEntry(segments[segments.length - 1]);
if (entry == null) {
return null;
}
String fullPath = wzfile.getName().substring(0, wzfile.getName().length() - 3).toLowerCase() + "/" + path;
return new WZIMGFile(this.wzfile, entry, provideImages, ListWZFile.isModernImgFile(fullPath));
}
public synchronized MapleData getData(String path) {
try {
WZIMGFile imgFile = getImgFile(path);
if (imgFile == null) {
return null;
}
MapleData ret = imgFile.getRoot();
return ret;
} catch (IOException e) {
}
return null;
}
public MapleDataDirectoryEntry getRoot() {
return root;
}
}