diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /filters/olefilters/lib | |
download | koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip |
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'filters/olefilters/lib')
-rw-r--r-- | filters/olefilters/lib/Makefile.am | 16 | ||||
-rw-r--r-- | filters/olefilters/lib/filterbase.cc | 91 | ||||
-rw-r--r-- | filters/olefilters/lib/filterbase.h | 109 | ||||
-rw-r--r-- | filters/olefilters/lib/klaola.cc | 579 | ||||
-rw-r--r-- | filters/olefilters/lib/klaola.h | 193 | ||||
-rw-r--r-- | filters/olefilters/lib/myfile.h | 49 |
6 files changed, 1037 insertions, 0 deletions
diff --git a/filters/olefilters/lib/Makefile.am b/filters/olefilters/lib/Makefile.am new file mode 100644 index 00000000..9e902fd2 --- /dev/null +++ b/filters/olefilters/lib/Makefile.am @@ -0,0 +1,16 @@ +####### General stuff + +INCLUDES = -I$(srcdir) $(KOFFICE_INCLUDES) $(all_includes) + +####### Files + +noinst_LTLIBRARIES = libfilterbase.la libklaola.la + +libfilterbase_la_SOURCES = filterbase.cc +libfilterbase_la_METASOURCES = filterbase.moc +libfilterbase_la_LDFLAGS = $(all_libraries) + +libklaola_la_SOURCES = klaola.cc +libklaola_la_LDFLAGS = $(all_libraries) + +noinst_HEADERS = filterbase.h klaola.h diff --git a/filters/olefilters/lib/filterbase.cc b/filters/olefilters/lib/filterbase.cc new file mode 100644 index 00000000..b1ec9c32 --- /dev/null +++ b/filters/olefilters/lib/filterbase.cc @@ -0,0 +1,91 @@ +/* This file is part of the KDE project + Copyright (C) 1999 Werner Trobin <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <filterbase.h> + +FilterBase::FilterBase() : QObject() { + m_success=true; + m_ready=false; +} + +FilterBase::FilterBase(QStringList &oleStreams) : QObject() { + FilterBase(); + m_oleStreams = oleStreams; +} + +bool FilterBase::filter() { + QString newstr; + + // Page sizes, margins etc. all in points. + + const unsigned height = 841; // Height. + const unsigned width = 595; // Width. + const unsigned hMargin = 28; // Horizontal margin. + const unsigned vMargin = 42; // Vertical margin. + + newstr = QString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE DOC >\n" + "<DOC author=\"Reginald Stadlbauer and Torben Weis\" email=\"[email protected] and [email protected]\" editor=\"KWord\" mime=\"application/x-kword\">\n" + " <PAPER format=\"1\" ptWidth=\"595\" ptHeight=\"841\" mmWidth =\"210\" mmHeight=\"297\" inchWidth =\"8.26772\" inchHeight=\"11.6929\" orientation=\"0\" columns=\"1\" ptColumnspc=\"2\" mmColumnspc=\"1\" inchColumnspc=\"0.0393701\" hType=\"0\" fType=\"0\" ptHeadBody=\"9\" ptFootBody=\"9\" mmHeadBody=\"3.5\" mmFootBody=\"3.5\" inchHeadBody=\"0.137795\" inchFootBody=\"0.137795\">\n" + " <PAPERBORDERS mmLeft=\"10\" mmTop=\"15\" mmRight=\"10\" mmBottom=\"15\" ptLeft=\""); + newstr.append(QString::number(hMargin)); + newstr.append("\" ptTop=\""); + newstr.append(QString::number(vMargin)); + newstr.append("\" ptRight=\""); + newstr.append(QString::number(hMargin)); + newstr.append("\" ptBottom=\""); + newstr.append(QString::number(vMargin)); + newstr.append("\" inchLeft=\"0.393701\" inchTop=\"0.590551\" inchRight=\"0.393701\" inchBottom=\"0.590551\"/>\n" + " </PAPER>\n" + " <ATTRIBUTES processing=\"0\" standardpage=\"1\" hasHeader=\"0\" hasFooter=\"0\" unit=\"mm\"/>\n" + " <FOOTNOTEMGR>\n" + " <START value=\"1\"/>\n" + " <FORMAT superscript=\"1\" type=\"1\"/>\n" + " <FIRSTPARAG ref=\"(null)\"/>\n" + " </FOOTNOTEMGR>\n" + " <FRAMESETS>\n"); + newstr.append( + " <FRAMESET frameType=\"1\" frameInfo=\"0\" removeable=\"0\" visible=\"1\">\n" + " <FRAME left=\""); + newstr.append(QString::number(hMargin)); + newstr.append("\" top=\""); + newstr.append(QString::number(vMargin)); + newstr.append("\" right=\""); + newstr.append(QString::number(width - hMargin)); + newstr.append("\" bottom=\""); + newstr.append(QString::number(height - vMargin)); + newstr.append("\" runaround=\"1\" runaGapPT=\"2\" runaGapMM=\"1\" runaGapINCH=\"0.0393701\" lWidth=\"1\" lRed=\"255\" lGreen=\"255\" lBlue=\"255\" lStyle=\"0\" rWidth=\"1\" rRed=\"255\" rGreen=\"255\" rBlue=\"255\" rStyle=\"0\" tWidth=\"1\" tRed=\"255\" tGreen=\"255\" tBlue=\"255\" tStyle=\"0\" bWidth=\"1\" bRed=\"255\" bGreen=\"255\" bBlue=\"255\" bStyle=\"0\" bkRed=\"255\" bkGreen=\"255\" bkBlue=\"255\" bleftpt=\"0\" bleftmm=\"0\" bleftinch=\"0\" brightpt=\"0\" brightmm=\"0\" brightinch=\"0\" btoppt=\"0\" btopmm=\"0\" btopinch=\"0\" bbottompt=\"0\" bbottommm=\"0\" bbottominch=\"0"); + newstr.append("\" autoCreateNewFrame=\"1\" newFrameBehaviour=\"0\"/>\n" + " <PARAGRAPH>\n" + " <TEXT>"); + newstr.append("Cannot import OLE streams of type: "); + newstr.append(m_oleStreams.join(",")); + newstr.append("</TEXT>\n" + " </PARAGRAPH>\n" + " </FRAMESET>\n"); + newstr.append( + " </FRAMESETS>\n" + "</DOC>\n"); + m_part=QDomDocument("doc"); + m_part.setContent(newstr); + m_success=true; + m_ready=true; + return m_success; +} + +#include <filterbase.moc> diff --git a/filters/olefilters/lib/filterbase.h b/filters/olefilters/lib/filterbase.h new file mode 100644 index 00000000..942c3836 --- /dev/null +++ b/filters/olefilters/lib/filterbase.h @@ -0,0 +1,109 @@ +/* This file is part of the KDE project + Copyright (C) 1999 Werner Trobin <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +// This class is the base class for all the filters (excel97, powerpoint97, +// winword97) +// If you want to write a filter you'll have to derive your class from +// this one. + +#ifndef FILTERBASE_H +#define FILTERBASE_H + +#include <qobject.h> +#include <qdom.h> +#include <qstringlist.h> + +class myFile; +class QCString; + +// Attention: The nameOUT Strings are allocated with new[] in the +// slots. Therefore you have to delete [] them! +// If you call slotGetStream you have to delete [] the +// stream.data prt after use! +class FilterBase : public QObject { + + Q_OBJECT + +public: + + // Default constructor used by subclasses. + FilterBase(); + // This filter only ever gets used in error cases, when we could not find a + // real filter. So, pass in the names of the OLE streams making up the item + // item that could not be converted. + FilterBase(QStringList &oleStreams); + virtual ~FilterBase() {} + + // Manages the filtering process + virtual bool filter(); + + // override this to return true if you want to return a plain QCString + virtual bool plainString() const { return false; } + // okay -- let's get the QDomDocument + virtual const QDomDocument *const part() { return &m_part; } + // or get the plain QCString ;) + virtual QCString CString() const { return QCString(); } + +signals: + // See olefilter.h for information + void signalSaveDocumentInformation( + const QString &fullName, + const QString &title, + const QString &company, + const QString &email, + const QString &telephone, + const QString &fax, + const QString &postalCode, + const QString &country, + const QString &city, + const QString &street, + const QString &docTitle, + const QString &docAbstract); + void signalSavePic( + const QString &nameIN, + QString &storageId, + const QString &extension, + unsigned int length, + const char *data); + void signalSavePart( + const QString &nameIN, + QString &storageId, + QString &mimeType, + const QString &extension, + unsigned int length, + const char *data); + void signalPart(const QString& nameIN, QString &storageId, QString &mimeType); + void signalGetStream(const int &handle, myFile &stream); + // Note: might return wrong stream as names are NOT unique!!! + // (searching only in current dir) + void signalGetStream(const QString &name, myFile &stream); + void sigProgress(int value); + +protected: + bool m_success; // ok, the filtering process was successful + bool m_ready; // filtering took place, you may fetch the file now + QDomDocument m_part; // this represents the part (document) + +private: + // Don't copy or assign me... + FilterBase(const FilterBase &); + const FilterBase &operator=(const FilterBase &); + QStringList m_oleStreams; +}; +#endif // FILTERBASE_H diff --git a/filters/olefilters/lib/klaola.cc b/filters/olefilters/lib/klaola.cc new file mode 100644 index 00000000..69d5284e --- /dev/null +++ b/filters/olefilters/lib/klaola.cc @@ -0,0 +1,579 @@ +/* This file is part of the KDE project + Copyright (C) 1999 Werner Trobin <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <klaola.h> +#include <kdebug.h> + +const int KLaola::s_area = 30510; + +KLaola::KLaola(const myFile &file) { + + smallBlockDepot=0L; + bigBlockDepot=0L; + smallBlockFile=0L; + bbd_list=0L; + ok=true; + m_nodeList.setAutoDelete(true); + //m_currentPath.setAutoDelete(true); + + if( (file.length % 0x200) != 0 ) { + kdError(s_area) << "KLaola::KLaola(): Invalid file size!" << endl; + ok=false; + } + if(ok) { + m_file=file; + maxblock = file.length / 0x200 - 2; + maxSblock=0; // will be set in readSmallBlockDepot + + if(!parseHeader()) + ok=false; + if(ok) { + readBigBlockDepot(); + readSmallBlockDepot(); + readSmallBlockFile(); + readRootList(); + } + } + m_currentPath.clear(); + testIt(); + + // current path=root dirHandle + m_currentPath.clear(); + if ( !m_nodeTree.isEmpty() ) + m_currentPath.append(m_nodeTree.getFirst()->getFirst()->node); +} + +KLaola::~KLaola() { + + delete [] bigBlockDepot; + bigBlockDepot=0L; + delete [] smallBlockDepot; + smallBlockDepot=0L; + delete [] smallBlockFile; + smallBlockFile=0L; + delete [] bbd_list; + bbd_list=0L; +} + +// Comvert the given list of nodes into a tree. +void KLaola::createTree(const int handle, const short index) { + + Node *node = dynamic_cast<Node *>(m_nodeList.at(handle)); + SubTree *subtree; + + TreeNode *tree=new TreeNode; + tree->node=node; + tree->subtree=-1; + + //QString nix="### entering create tree: handle="; + //nix+=QString::number(handle); + //nix+=" index="; + //nix+=QString::number(index); + //kdDebug(s_area) << nix << endl; + + if(node->prevHandle!=-1) { + //kdDebug(s_area) << "create tree: prevHandle" << endl; + createTree(node->prevHandle, index); + } + if(node->dirHandle!=-1) { + subtree=new SubTree; + subtree->setAutoDelete(true); + m_nodeTree.append(subtree); + tree->subtree=m_nodeTree.at(); + //kdDebug(s_area) << "create tree: dirHandle" << endl; + createTree(node->dirHandle, tree->subtree); + } + subtree=m_nodeTree.at(index); + //kdDebug(s_area) << "create tree: APPEND " << handle << " tree node " << tree << endl; + subtree->append(tree); + if(node->nextHandle!=-1) { + //kdDebug(s_area) << "create tree: nextHandle" << endl; + createTree(node->nextHandle, index); + } +} + +const KLaola::NodeList KLaola::currentPath() const { + return m_currentPath; +} + +bool KLaola::enterDir(const OLENode *dirHandle) { + + NodeList nodes; + Node *node; + + if(ok) { + nodes = parseCurrentDir(); + for (node = dynamic_cast<Node *>(nodes.first()); node; node = dynamic_cast<Node *>(nodes.next())) + { + if(node->m_handle==dirHandle->handle() && node->isDirectory() && !node->deadDir) { + m_currentPath.append(node); + return true; + } + } + } + return false; +} + +const KLaola::NodeList KLaola::find(const QString &name, bool onlyCurrentDir) { + + OLENode *node; + NodeList ret; + int i=0; + + if(ok) { + if(!onlyCurrentDir) { + for(node=m_nodeList.first(); node; node=m_nodeList.next()) { + if(node->name()==name) { + ret.append(node); + ++i; + } + } + } + else { + NodeList list=parseCurrentDir(); + + for(node=list.first(); node; node=list.next()) { + if(node->name()==name) { + ret.append(node); + ++i; + } + } + } + } + return ret; +} + +bool KLaola::leaveDir() { + + if (ok) { + return m_currentPath.removeLast(); + } + return false; +} + +int KLaola::nextBigBlock(int pos) const +{ + + int x=pos*4; + return ( (bigBlockDepot[x+3] << 24) + (bigBlockDepot[x+2] << 16) + + (bigBlockDepot[x+1] << 8) + bigBlockDepot[x] ); +} + +int KLaola::nextSmallBlock(int pos) const +{ + + if(smallBlockDepot) { + int x=pos*4; + return ( (smallBlockDepot[x+3] << 24) + (smallBlockDepot[x+2] << 16) + + (smallBlockDepot[x+1] << 8) + smallBlockDepot[x] ); + } + else + return -2; // Emergency Break :) +} + +bool KLaola::parseHeader() { + + if(qstrncmp((const char*)m_file.data,"\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1",8 )!=0) { + kdError(s_area) << "KLaola::parseHeader(): Invalid file format (unexpected id in header)!" << endl; + return false; + } + + num_of_bbd_blocks=read32(0x2c); + root_startblock=read32(0x30); + sbd_startblock=read32(0x3c); + + if (num_of_bbd_blocks >= 0x800000) { + kdError(s_area) << "KLaola::parseHeader(): Too many bbd blocks found in header!" << endl; + return false; + } + bbd_list=new unsigned int[num_of_bbd_blocks]; + + unsigned int i, j; + for(i=0, j=0; i<num_of_bbd_blocks; ++i, j=j+4) { + bbd_list[i]=read32(0x4c+j); + if (bbd_list[i] >= (0x800000 - 1)) { + kdError(s_area) << "KLaola::parseHeader(): bbd " << i << " offset (" << bbd_list[i] << ") too large" << endl; + return false; + } + } + return true; +} + +KLaola::NodeList KLaola::parseCurrentDir() { + + Node *node; + SubTree *subtree; + NodeList nodeList; + TreeNode *treeNode; + unsigned int i; + bool found; + + if(ok) { + for(i=0, subtree=m_nodeTree.first(); i<m_currentPath.count(); ++i) { + treeNode=subtree->first(); + found=false; + do { + if(treeNode==0) { + kdError(s_area) << "KLaola::parseCurrentDir(): path seems to be corrupted!" << endl; + ok=false; + } + else if(treeNode->node->handle()==m_currentPath.at(i)->handle() && treeNode->subtree!=-1) { + found=true; + } + else + treeNode=subtree->next(); + } while(!found && ok); + subtree=m_nodeTree.at(treeNode->subtree); + } + } + if(ok) { + for(treeNode=subtree->first(); treeNode!=0; treeNode=subtree->next()) { + node=new Node(*treeNode->node); + node->deadDir = (node->dirHandle==-1 && node->isDirectory()); + // this is a strange situation :) + if (node->deadDir) + kdDebug(s_area) << "ignoring: " << node->describe() << " is empty" << endl; + else + nodeList.append(node); + } + } + return nodeList; +} + +KLaola::NodeList KLaola::parseRootDir() { + + NodeList tmpNodeList; + NodeList tmp; + + if(ok) { + tmp=m_currentPath; + m_currentPath.clear(); // current path=root dirHandle + m_currentPath.append(m_nodeTree.getFirst()->getFirst()->node); + tmpNodeList=parseCurrentDir(); + m_currentPath=tmp; + } + return tmpNodeList; +} + +unsigned char KLaola::read8(int i) const +{ + return m_file.data[i]; +} + +unsigned short KLaola::read16(int i) const +{ + return ( (m_file.data[i+1] << 8) + m_file.data[i] ); +} + +unsigned int KLaola::read32(int i) const +{ + return ( (read16(i+2) << 16) + read16(i) ); +} + +const unsigned char *KLaola::readBBStream(int start, bool setmaxSblock) +{ + + int i=0, tmp; + unsigned char *p=0; + + tmp=start; + /* 0x10000 chosen as arbitrary "too many blocks" limit to not loop forver */ + while(tmp!=-2 && tmp>=0 && i<0x10000 && tmp<=static_cast<int>(maxblock)) { + ++i; + tmp=nextBigBlock(tmp); + } + if(i!=0) { + p=new unsigned char[i*0x200]; + if(setmaxSblock) + maxSblock=i*8-1; + i=0; + tmp=start; + while(tmp!=-2 && tmp>=0 && i<0x10000 && tmp<=static_cast<int>(maxblock)) { + memcpy(&p[i*0x200], &m_file.data[(tmp+1)*0x200], 0x200); + tmp=nextBigBlock(tmp); + ++i; + } + } + return p; +} + +const unsigned char *KLaola::readSBStream(int start) const { + + int i=0, tmp; + unsigned char *p=0; + + tmp=start; + /* 0x10000 chosen as arbitrary "too many blocks" limit to not loop forver */ + while(tmp!=-2 && tmp>=0 && i<0x10000 && tmp<=static_cast<int>(maxSblock)) { + ++i; + tmp=nextSmallBlock(tmp); + } + if(i!=0) { + p=new unsigned char[i*0x40]; + i=0; + tmp=start; + while(tmp!=-2 && tmp>=0 && i<0x10000 && tmp<=static_cast<int>(maxSblock)) { + memcpy(&p[i*0x40], &smallBlockFile[tmp*0x40], 0x40); + tmp=nextSmallBlock(tmp); + ++i; + } + } + return p; +} + +void KLaola::readBigBlockDepot() { + if (num_of_bbd_blocks >= 0x800000) + return; + + bigBlockDepot=new unsigned char[0x200*num_of_bbd_blocks]; + for(unsigned int i=0; i<num_of_bbd_blocks; ++i) { + unsigned int offset = (bbd_list[i]+1)*0x200; + if (offset > m_file.length - 0x200) { + /* attempting to read past end of file */ + memset(&bigBlockDepot[i*0x200], 0, 0x200); + } + else { + memcpy(&bigBlockDepot[i*0x200], &m_file.data[offset], 0x200); + } + } +} + +void KLaola::readSmallBlockDepot() { + smallBlockDepot=const_cast<unsigned char*>(readBBStream(sbd_startblock)); +} + +void KLaola::readSmallBlockFile() { + smallBlockFile=const_cast<unsigned char*>(readBBStream( read32( (root_startblock+1)*0x200 + 0x74), true)); +} + +void KLaola::readRootList() { + + int pos=root_startblock; + int handle=0; + + while(pos!=-2 && pos>=0 && pos<=static_cast<int>(maxblock)) { + for(int i=0; i<4; ++i, ++handle) + readPPSEntry((pos+1)*0x200+0x80*i, handle); + pos=nextBigBlock(pos); + } + SubTree *subtree=new SubTree; + subtree->setAutoDelete(true); + m_nodeTree.append(subtree); + + createTree(0, 0); // build the tree with a recursive method :) +} + +// Add the given OLE node to the list of nodes. +void KLaola::readPPSEntry(int pos, const int handle) { + + int nameSize = read16(pos + 0x40); + + // Does the PPS Entry seem to be valid? + + if (nameSize) + { + int i; + Node *node = new Node(this); + + // The first character of the name can be a prefix. + node->m_prefix = static_cast<Prefix>(read16(pos)); + if (node->m_prefix <= RESERVED_LAST) + { + i = 1; + } + else + { + node->m_prefix = NONE; + i = 0; + } + + // Get the rest of the name. + for (; i < (nameSize / 2) - 1; ++i) + { + QChar tmp; + + tmp = read16(pos + 2 * i); + node->m_name += tmp; + } + node->m_handle = handle; + node->type = static_cast<NodeType>(read8(pos + 0x42)); + node->prevHandle = static_cast<int>(read32(pos + 0x44)); + node->nextHandle = static_cast<int>(read32(pos + 0x48)); + node->dirHandle = static_cast<int>(read32(pos + 0x4C)); + node->ts1s = static_cast<int>(read32(pos + 0x64)); + node->ts1d = static_cast<int>(read32(pos + 0x68)); + node->ts2s = static_cast<int>(read32(pos + 0x6C)); + node->ts2d = static_cast<int>(read32(pos + 0x70)); + node->sb = read32(pos + 0x74); + node->size = read32(pos + 0x78); + node->deadDir = false; + m_nodeList.append(node); + } +} + +myFile KLaola::stream(const OLENode *node) { + + const Node *realNode = dynamic_cast<const Node *>(node); + const unsigned char *temp; + myFile ret; + + if(ok) { + if(realNode->size>=0x1000) + temp = readBBStream(realNode->sb); + else + temp = readSBStream(realNode->sb); + ret.setRawData(temp, realNode->size); + } + return ret; +} + +myFile KLaola::stream(unsigned handle) { + + OLENode *node; + + node = m_nodeList.at(handle); + return stream(node); +} + +void KLaola::testIt(QString prefix) +{ + + NodeList nodes; + OLENode *node; + + nodes = parseCurrentDir(); + for (node = nodes.first(); node; node = nodes.next()) + { + kdDebug(s_area) << prefix + node->describe() << endl; + if (node->isDirectory()) + { + enterDir(node); + testIt(prefix + " "); + } + } +} + +// Return a human-readable description of a stream. +QString KLaola::Node::describe() const +{ + QString description; + myFile file; + unsigned i; + + description = QString::number(m_handle) + " " + + m_name + "(" + + QString::number(sb) + " " + + QString::number(size) + " bytes)"; + if (isDirectory()) + description += ", directory"; + switch (m_prefix) + { + case OLE_MANAGED_0: + description += ", OLE_0"; + break; + case CLSID: + description += ", CLSID="; + description += readClassStream(); + file = m_laola->stream(this); + description += ", "; + for (i = 16; i < file.length; i++) + { + description += QString::number((file.data[i] >> 4) & 0xf, 16); + description += QString::number(file.data[i] & 0xf, 16); + } + description += ", "; + for (i = 16; i < file.length; i++) + { + QChar tmp = file.data[i]; + + if (tmp.isPrint()) + description += tmp; + else + description += '.'; + } + break; + case OLE_MANAGED_2: + description += ", OLE_2"; + break; + case PARENT_MANAGED: + description += ", parent managed"; + break; + case STRUCTURED_STORAGE: + description += ", reserved 0x" + QString::number(m_prefix, 16); + break; + case NONE: + break; + default: + description += ", reserved 0x" + QString::number(m_prefix, 16); + break; + } + return description; +} + +QString KLaola::Node::name() const +{ + return m_name; +} + +// See "Associating Code with Storage" in Inside OLE. +QString KLaola::Node::readClassStream() const +{ + if (isDirectory()) + return QString::null; + if (m_prefix == CLSID) + { + myFile file; + unsigned i; + QString clsid; + + // CLSID format is: 00020900-0000-0000-C000-000000000046 + file = m_laola->stream(this); + for (i = 0; i < 4; i++) + { + clsid += QString::number((file.data[i] >> 4) & 0xf, 16); + clsid += QString::number(file.data[i] & 0xf, 16); + } + clsid += '-'; + for (; i < 6; i++) + { + clsid += QString::number((file.data[i] >> 4) & 0xf, 16); + clsid += QString::number(file.data[i] & 0xf, 16); + } + clsid += '-'; + for (; i < 8; i++) + { + clsid += QString::number((file.data[i] >> 4) & 0xf, 16); + clsid += QString::number(file.data[i] & 0xf, 16); + } + clsid += '-'; + for (; i < 10; i++) + { + clsid += QString::number((file.data[i] >> 4) & 0xf, 16); + clsid += QString::number(file.data[i] & 0xf, 16); + } + clsid += '-'; + for (; i < 16; i++) + { + clsid += QString::number((file.data[i] >> 4) & 0xf, 16); + clsid += QString::number(file.data[i] & 0xf, 16); + } + return clsid; + } + return QString::null; +} diff --git a/filters/olefilters/lib/klaola.h b/filters/olefilters/lib/klaola.h new file mode 100644 index 00000000..816a7666 --- /dev/null +++ b/filters/olefilters/lib/klaola.h @@ -0,0 +1,193 @@ +/* This file is part of the KDE project + Copyright (C) 1999 Werner Trobin <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +DESCRIPTION + + This class is used to decode OLE 2 streams. When instantiated, it + constructs an internal "filesystem" that corresponds to the OLE storage + tree. This tree can be navigated, and the individual OLE streams + returned as a linear memory buffer. +*/ + +#ifndef KLAOLA_H +#define KLAOLA_H + +#include <myfile.h> +#include <qstring.h> +#include <qptrlist.h> + +class KLaola { + +public: + KLaola(const myFile &file); // see myfile.h! + ~KLaola(); + + bool isOk() {return ok;} + + // A class representing an abstracted node in the OLE filesystem. + + class OLENode { + public: + virtual ~OLENode() {}; + virtual unsigned handle() const = 0; + virtual QString name() const = 0; + + // Does the node represent a stream datum, or a storage container + // of data? + virtual bool isDirectory() const = 0; + + // If isDirectory() is true, return the CLSID associated with + // any child CompObj node. If the Node is a CompObj, return + // its CLSID. Otherwise return QString::null. + // + // The CLSID is returned in the form: + // + // 00020900-0000-0000-C000-000000000046 + // + virtual QString readClassStream() const = 0; + + // Return a human-readable description of a stream. + virtual QString describe() const = 0; + protected: + OLENode() {} + }; + + // Wade through the "file system" + + typedef QPtrList<OLENode> NodeList; + NodeList parseRootDir(); + NodeList parseCurrentDir(); + const NodeList currentPath() const; + const NodeList find(const QString &name, bool onlyCurrentDir=false); + bool enterDir(const OLENode *node); + bool leaveDir(); + + // Return the stream for a given node. + // + // Note: data - 512 byte blocks, but length is set correctly :) + myFile stream(const OLENode *node); + myFile stream(unsigned handle); + +private: + KLaola(const KLaola &); + const KLaola &operator=(const KLaola &); + static const int s_area; + + unsigned char read8(int i) const; + unsigned short read16(int i) const; + unsigned int read32(int i) const; + + // Parsing functions. + bool parseHeader(); + void readBigBlockDepot(); + void readSmallBlockDepot(); + void readSmallBlockFile(); + void readRootList(); + void readPPSEntry(int pos, const int handle); + void createTree(const int handle, const short index); + const unsigned char *readBBStream(int start, bool setmaxSblock=false); + const unsigned char *readSBStream(int start) const; + int nextBigBlock(int pos) const; + int nextSmallBlock(int pos) const; + + // Dump the parsed structure info (similar to "lls" + // of the LAOLA-project). + void testIt(QString prefix = ""); + +public: + typedef enum + { + DIRECTORY = 1, + FILE = 2, + ROOT_ENTRY = 5 + } NodeType; + + // If the first part of an on-disk name is less than 32, it is a prefix. + typedef enum + { + OLE_MANAGED_0, + CLSID, + OLE_MANAGED_2, + PARENT_MANAGED, // Marks an element as owned by the code that + // manages the parent storage of that element. + STRUCTURED_STORAGE, // For the exclusive use of the Structured Storage + // implementation. + RESERVED_FIRST, + RESERVED_LAST = 31, + NONE = 32 + } Prefix; + + class Node: public OLENode { + public: + Node(KLaola *laola) { m_laola = laola; } + ~Node() {} + unsigned handle() const { return m_handle; } + QString name() const; + bool isDirectory() const { return (type == DIRECTORY) || (type == ROOT_ENTRY); } + QString readClassStream() const; + QString describe() const; + + KLaola *m_laola; + unsigned m_handle; // PPS entry number + Prefix m_prefix; + QString m_name; + NodeType type; + int prevHandle; // Last pps + int nextHandle; // Next pps + int dirHandle; // Dir pps + int ts1s; // Timestamp 1, seconds + int ts1d; // Timestamp 1, days + int ts2s; // Timestamp 2, seconds + int ts2d; // Timestamp 2, days + unsigned sb; // Starting block + unsigned size; // Size of property + bool deadDir; // true, if the dir is a "dead end" + }; + +private: + // Lists of nodes. + + NodeList m_nodeList; + NodeList m_currentPath; + + // The OLE storage is represented as a tree. Each node in the tree may + // refer to a subtree. Each subtree is stored as a list of nodes. + + struct TreeNode + { + Node *node; + short subtree; + }; + typedef QPtrList<TreeNode> SubTree; + QPtrList<SubTree> m_nodeTree; + + bool ok; // is the file OK? + + myFile m_file; + unsigned char *bigBlockDepot; + unsigned char *smallBlockDepot; + unsigned char *smallBlockFile; + + unsigned int maxblock; // maximum number of big-blocks + unsigned int maxSblock; // small-blocks + unsigned int num_of_bbd_blocks; // number of big block depot blocks + unsigned int root_startblock; // Root chain's first big block + unsigned int sbd_startblock; // small block depot's first big block + unsigned int *bbd_list; //array of num_of_bbd_blocks big block numbers +}; +#endif // KLAOLA_H diff --git a/filters/olefilters/lib/myfile.h b/filters/olefilters/lib/myfile.h new file mode 100644 index 00000000..7be578b3 --- /dev/null +++ b/filters/olefilters/lib/myfile.h @@ -0,0 +1,49 @@ +/* This file is part of the KDE project + Copyright (C) 1999 Werner Trobin <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +DESCRIPTION + + A data-structure to hold the file data for an OLE stream. Shared storage is + used to implement reference counting and storage reclamation. +*/ + +#ifndef MYFILE_H +#define MYFILE_H + +#include <qcstring.h> + +class myFile: public QByteArray +{ +public: + myFile() { data = 0L; length = 0; } + + // NOTE: this implementation may look completely ugly, but its features are + // mostly for backwards compatibility. If you feel like cleaning up, be my + // guest! + + const unsigned char *data; + unsigned int length; + + void setRawData(const unsigned char *data, unsigned length) + { + this->data = data; + this->length = length; + QByteArray::setRawData((const char *)data, length); + } +}; +#endif // MYFILE_H |