Commit 7a97b440 authored by Jakub Stachowski's avatar Jakub Stachowski
Browse files

Better error detection


svn path=/trunk/playground/graphics/okular/mobipocket/; revision=904178
parent ea630c83
......@@ -163,12 +163,18 @@ HuffdicDecompressor::HuffdicDecompressor(const PDB& p) : Decompressor(p)
QByteArray header=p.getRecord(0);
quint32 huff_ofs=readBELong(header,0x70);
quint32 huff_num=readBELong(header,0x74);
quint32 off1,off2;
for (unsigned int i=1;i<huff_num;i++) dicts.append(p.getRecord(huff_ofs+i));
QByteArray huff1=p.getRecord(huff_ofs);
if (huff1.isNull()) goto fail;
for (unsigned int i=1;i<huff_num;i++) {
QByteArray h=p.getRecord(huff_ofs+i);
if (h.isNull()) goto fail;
dicts.append(h);
}
quint32 off1=readBELong(huff1,16);
quint32 off2=readBELong(huff1,20);
off1=readBELong(huff1,16);
off2=readBELong(huff1,20);
if (!huff1.startsWith("HUFF")) goto fail;
if (!dicts[0].startsWith("CDIC")) goto fail;
......
......@@ -32,7 +32,7 @@ public:
memcpy(buf,b2,len);
return l;
}
void seek(int pos) { d->reset(pos); }
bool seek(int pos) { d->reset(pos); return (pos==d->position()); }
private:
InputStream *d;
};
......
......@@ -52,10 +52,10 @@ void PDBPrivate::init()
valid=true;
quint16 word;
quint32 dword;
device->seek(0x3c);
if (!device->seek(0x3c)) goto fail;
fileType=QString::fromLatin1(device->read(8));
device->seek(0x4c);
if (!device->seek(0x4c)) goto fail;
device->read((char*)&word,2);
nrecords=qFromBigEndian(word);
......@@ -64,6 +64,9 @@ void PDBPrivate::init()
recordOffsets.append(qFromBigEndian(dword));
device->read((char*)&dword,4);
}
return;
fail:
valid=false;
}
PDB::PDB(Stream* dev) : d(new PDBPrivate)
......@@ -77,7 +80,7 @@ QByteArray PDB::getRecord(int i) const
if (i>=d->nrecords) return QByteArray();
quint32 offset=d->recordOffsets[i];
bool last=(i==(d->nrecords-1));
d->device->seek(offset);
if (!d->device->seek(offset)) return QByteArray();
if (last) return d->device->readAll();
return d->device->read(d->recordOffsets[i+1]-offset);
}
......@@ -150,24 +153,28 @@ void DocumentPrivate::parseHtmlHead(const QString& data)
void DocumentPrivate::init()
{
quint32 encoding;
valid=pdb.isValid();
if (!valid) return;
QByteArray mhead=pdb.getRecord(0);
if (mhead.isNull()) goto fail;
dec = Decompressor::create(mhead[1], pdb);
if ((int)mhead[12]!=0 || (int)mhead[13]!=0) drm=true;
if (!dec) {
valid=false;
return;
}
if (!dec) goto fail;
ntextrecords=(unsigned char)mhead[8];
ntextrecords<<=8;
ntextrecords+=(unsigned char)mhead[9];
quint32 encoding=readBELong(mhead, 28);
encoding=readBELong(mhead, 28);
if (encoding==65001) isUtf=true;
if (mhead.size()>176) parseEXTH(mhead);
// try getting metadata from HTML if nothing or only title was recovered from MOBI and EXTH records
if (metadata.size()<2 && !drm) parseHtmlHead(decodeString(dec->decompress(pdb.getRecord(1))));
return;
fail:
valid=false;
}
void DocumentPrivate::findFirstImage() {
......@@ -196,8 +203,7 @@ QString DocumentPrivate::readEXTHRecord(const QByteArray& data, quint32& offset)
QImage DocumentPrivate::getImageFromRecord(int i)
{
QByteArray rec=pdb.getRecord(i);
QByteArray rec2=pdb.getRecord(i-2);
return QImage::fromData(rec);
return (rec.isNull()) ? QImage() : QImage::fromData(rec);
}
......@@ -205,8 +211,8 @@ void DocumentPrivate::parseEXTH(const QByteArray& data)
{
// try to get name
if (data.size()>=92) {
quint32 nameoffset=readBELong(data,84);
quint32 namelen=readBELong(data,88);
qint32 nameoffset=readBELong(data,84);
qint32 namelen=readBELong(data,88);
if ( (nameoffset + namelen) < data.size() ) {
metadata[Document::Title]=decodeString(data.mid(nameoffset, namelen));
}
......
......@@ -26,7 +26,7 @@ used with both QIODevice (for Okular generator) and InputStream for Strigi analy
class Stream {
public:
virtual int read(char* buf, int size)=0;
virtual void seek(int pos)=0;
virtual bool seek(int pos)=0;
QByteArray readAll();
QByteArray read(int len);
......
......@@ -23,6 +23,9 @@ extern "C"
bool MobiThumbnail::create(const QString &path, int width, int height, QImage &img)
{
Q_UNUSED(width);
Q_UNUSED(height);
Mobipocket::QFileStream f(path);
Mobipocket::Document doc(&f);
if (!doc.isValid()) return false;
......
......@@ -20,7 +20,7 @@ class QFileStream : public Stream
public:
QFileStream(const QString& name) : d(name) { d.open(QIODevice::ReadOnly); }
int read(char* buf, int size) { return d.read(buf,size); }
void seek(int pos) { d.seek(pos); }
bool seek(int pos) { return d.seek(pos); }
private:
QFile d;
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment