23const int KLaola::s_area = 30510;
25KLaola::KLaola(
const myFile &file) {
32 m_nodeList.setAutoDelete(
true);
35 if( (file.length % 0x200) != 0 ) {
36 kdError(s_area) <<
"KLaola::KLaola(): Invalid file size!" << endl;
41 maxblock = file.length / 0x200 - 2;
48 readSmallBlockDepot();
53 m_currentPath.clear();
57 m_currentPath.clear();
58 if ( !m_nodeTree.isEmpty() )
59 m_currentPath.append(m_nodeTree.getFirst()->getFirst()->node);
64 delete [] bigBlockDepot;
66 delete [] smallBlockDepot;
68 delete [] smallBlockFile;
75void KLaola::createTree(
const int handle,
const short index) {
77 Node *node =
dynamic_cast<Node *
>(m_nodeList.at(handle));
80 TreeNode *tree=
new TreeNode;
90 if(node->prevHandle!=-1) {
92 createTree(node->prevHandle, index);
94 if(node->dirHandle!=-1) {
96 subtree->setAutoDelete(
true);
97 m_nodeTree.append(subtree);
98 tree->subtree=m_nodeTree.at();
100 createTree(node->dirHandle, tree->subtree);
102 subtree=m_nodeTree.at(index);
104 subtree->append(tree);
105 if(node->nextHandle!=-1) {
107 createTree(node->nextHandle, index);
111const KLaola::NodeList KLaola::currentPath()
const {
112 return m_currentPath;
115bool KLaola::enterDir(
const OLENode *dirHandle) {
121 nodes = parseCurrentDir();
122 for (node =
dynamic_cast<Node *
>(nodes.first()); node; node =
dynamic_cast<Node *
>(nodes.next()))
124 if(node->m_handle==dirHandle->handle() && node->isDirectory() && !node->deadDir) {
125 m_currentPath.append(node);
133const KLaola::NodeList KLaola::find(
const TQString &name,
bool onlyCurrentDir) {
140 if(!onlyCurrentDir) {
141 for(node=m_nodeList.first(); node; node=m_nodeList.next()) {
142 if(node->name()==name) {
149 NodeList list=parseCurrentDir();
151 for(node=list.first(); node; node=list.next()) {
152 if(node->name()==name) {
162bool KLaola::leaveDir() {
165 return m_currentPath.removeLast();
170int KLaola::nextBigBlock(
int pos)
const
174 return ( (bigBlockDepot[x+3] << 24) + (bigBlockDepot[x+2] << 16) +
175 (bigBlockDepot[x+1] << 8) + bigBlockDepot[x] );
178int KLaola::nextSmallBlock(
int pos)
const
181 if(smallBlockDepot) {
183 return ( (smallBlockDepot[x+3] << 24) + (smallBlockDepot[x+2] << 16) +
184 (smallBlockDepot[x+1] << 8) + smallBlockDepot[x] );
190bool KLaola::parseHeader() {
192 if(tqstrncmp((
const char*)m_file.data,
"\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1",8 )!=0) {
193 kdError(s_area) <<
"KLaola::parseHeader(): Invalid file format (unexpected id in header)!" << endl;
197 num_of_bbd_blocks=read32(0x2c);
198 root_startblock=read32(0x30);
199 sbd_startblock=read32(0x3c);
201 if (num_of_bbd_blocks >= 0x800000) {
202 kdError(s_area) <<
"KLaola::parseHeader(): Too many bbd blocks found in header!" << endl;
205 bbd_list=
new unsigned int[num_of_bbd_blocks];
208 for(i=0, j=0; i<num_of_bbd_blocks; ++i, j=j+4) {
209 bbd_list[i]=read32(0x4c+j);
210 if (bbd_list[i] >= (0x800000 - 1)) {
211 kdError(s_area) <<
"KLaola::parseHeader(): bbd " << i <<
" offset (" << bbd_list[i] <<
") too large" << endl;
218KLaola::NodeList KLaola::parseCurrentDir() {
228 for(i=0, subtree=m_nodeTree.first(); i<m_currentPath.count(); ++i) {
229 treeNode=subtree->first();
233 kdError(s_area) <<
"KLaola::parseCurrentDir(): path seems to be corrupted!" << endl;
236 else if(treeNode->node->handle()==m_currentPath.at(i)->handle() && treeNode->subtree!=-1) {
240 treeNode=subtree->next();
241 }
while(!found && ok);
242 subtree=m_nodeTree.at(treeNode->subtree);
246 for(treeNode=subtree->first(); treeNode!=0; treeNode=subtree->next()) {
247 node=
new Node(*treeNode->node);
248 node->deadDir = (node->dirHandle==-1 && node->isDirectory());
251 kdDebug(s_area) <<
"ignoring: " << node->describe() <<
" is empty" << endl;
253 nodeList.append(node);
259KLaola::NodeList KLaola::parseRootDir() {
261 NodeList tmpNodeList;
266 m_currentPath.clear();
267 m_currentPath.append(m_nodeTree.getFirst()->getFirst()->node);
268 tmpNodeList=parseCurrentDir();
274unsigned char KLaola::read8(
int i)
const
276 return m_file.data[i];
279unsigned short KLaola::read16(
int i)
const
281 return ( (m_file.data[i+1] << 8) + m_file.data[i] );
284unsigned int KLaola::read32(
int i)
const
286 return ( (read16(i+2) << 16) + read16(i) );
289const unsigned char *KLaola::readBBStream(
int start,
bool setmaxSblock)
297 while(tmp!=-2 && tmp>=0 && i<0x10000 && tmp<=
static_cast<int>(maxblock)) {
299 tmp=nextBigBlock(tmp);
302 p=
new unsigned char[i*0x200];
307 while(tmp!=-2 && tmp>=0 && i<0x10000 && tmp<=
static_cast<int>(maxblock)) {
308 memcpy(&p[i*0x200], &m_file.data[(tmp+1)*0x200], 0x200);
309 tmp=nextBigBlock(tmp);
316const unsigned char *KLaola::readSBStream(
int start)
const {
323 while(tmp!=-2 && tmp>=0 && i<0x10000 && tmp<=
static_cast<int>(maxSblock)) {
325 tmp=nextSmallBlock(tmp);
328 p=
new unsigned char[i*0x40];
331 while(tmp!=-2 && tmp>=0 && i<0x10000 && tmp<=
static_cast<int>(maxSblock)) {
332 memcpy(&p[i*0x40], &smallBlockFile[tmp*0x40], 0x40);
333 tmp=nextSmallBlock(tmp);
340void KLaola::readBigBlockDepot() {
341 if (num_of_bbd_blocks >= 0x800000)
344 bigBlockDepot=
new unsigned char[0x200*num_of_bbd_blocks];
345 for(
unsigned int i=0; i<num_of_bbd_blocks; ++i) {
346 unsigned int offset = (bbd_list[i]+1)*0x200;
347 if (offset > m_file.length - 0x200) {
349 memset(&bigBlockDepot[i*0x200], 0, 0x200);
352 memcpy(&bigBlockDepot[i*0x200], &m_file.data[offset], 0x200);
357void KLaola::readSmallBlockDepot() {
358 smallBlockDepot=
const_cast<unsigned char*
>(readBBStream(sbd_startblock));
361void KLaola::readSmallBlockFile() {
362 smallBlockFile=
const_cast<unsigned char*
>(readBBStream( read32( (root_startblock+1)*0x200 + 0x74),
true));
365void KLaola::readRootList() {
367 int pos=root_startblock;
370 while(pos!=-2 && pos>=0 && pos<=
static_cast<int>(maxblock)) {
371 for(
int i=0; i<4; ++i, ++handle)
372 readPPSEntry((pos+1)*0x200+0x80*i, handle);
373 pos=nextBigBlock(pos);
375 SubTree *subtree=
new SubTree;
376 subtree->setAutoDelete(
true);
377 m_nodeTree.append(subtree);
383void KLaola::readPPSEntry(
int pos,
const int handle) {
385 int nameSize = read16(pos + 0x40);
392 Node *node =
new Node(
this);
395 node->m_prefix =
static_cast<Prefix
>(read16(pos));
396 if (node->m_prefix <= RESERVED_LAST)
402 node->m_prefix = NONE;
407 for (; i < (nameSize / 2) - 1; ++i)
411 tmp = read16(pos + 2 * i);
414 node->m_handle = handle;
415 node->type =
static_cast<NodeType
>(read8(pos + 0x42));
416 node->prevHandle =
static_cast<int>(read32(pos + 0x44));
417 node->nextHandle =
static_cast<int>(read32(pos + 0x48));
418 node->dirHandle =
static_cast<int>(read32(pos + 0x4C));
419 node->ts1s =
static_cast<int>(read32(pos + 0x64));
420 node->ts1d =
static_cast<int>(read32(pos + 0x68));
421 node->ts2s =
static_cast<int>(read32(pos + 0x6C));
422 node->ts2d =
static_cast<int>(read32(pos + 0x70));
423 node->sb = read32(pos + 0x74);
424 node->size = read32(pos + 0x78);
425 node->deadDir =
false;
426 m_nodeList.append(node);
430myFile KLaola::stream(
const OLENode *node) {
432 const Node *realNode =
dynamic_cast<const Node *
>(node);
433 const unsigned char *temp;
437 if(realNode->size>=0x1000)
438 temp = readBBStream(realNode->sb);
440 temp = readSBStream(realNode->sb);
441 ret.setRawData(temp, realNode->size);
446myFile KLaola::stream(
unsigned handle) {
450 node = m_nodeList.at(handle);
454void KLaola::testIt(TQString prefix)
460 nodes = parseCurrentDir();
461 for (node = nodes.first(); node; node = nodes.next())
463 kdDebug(s_area) << prefix + node->describe() << endl;
464 if (node->isDirectory())
467 testIt(prefix +
" ");
473TQString KLaola::Node::describe()
const
475 TQString description;
479 description = TQString::number(m_handle) +
" " +
481 TQString::number(sb) +
" " +
482 TQString::number(size) +
" bytes)";
484 description +=
", directory";
488 description +=
", OLE_0";
491 description +=
", CLSID=";
492 description += readClassStream();
493 file = m_laola->stream(
this);
495 for (i = 16; i < file.length; i++)
497 description += TQString::number((file.data[i] >> 4) & 0xf, 16);
498 description += TQString::number(file.data[i] & 0xf, 16);
501 for (i = 16; i < file.length; i++)
503 TQChar tmp = file.data[i];
512 description +=
", OLE_2";
515 description +=
", parent managed";
517 case STRUCTURED_STORAGE:
518 description +=
", reserved 0x" + TQString::number(m_prefix, 16);
523 description +=
", reserved 0x" + TQString::number(m_prefix, 16);
529TQString KLaola::Node::name()
const
535TQString KLaola::Node::readClassStream()
const
539 if (m_prefix == CLSID)
546 file = m_laola->stream(
this);
547 for (i = 0; i < 4; i++)
549 clsid += TQString::number((file.data[i] >> 4) & 0xf, 16);
550 clsid += TQString::number(file.data[i] & 0xf, 16);
555 clsid += TQString::number((file.data[i] >> 4) & 0xf, 16);
556 clsid += TQString::number(file.data[i] & 0xf, 16);
561 clsid += TQString::number((file.data[i] >> 4) & 0xf, 16);
562 clsid += TQString::number(file.data[i] & 0xf, 16);
567 clsid += TQString::number((file.data[i] >> 4) & 0xf, 16);
568 clsid += TQString::number(file.data[i] & 0xf, 16);
573 clsid += TQString::number((file.data[i] >> 4) & 0xf, 16);
574 clsid += TQString::number(file.data[i] & 0xf, 16);