00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <olefilter.h>
00027
00028 #include <qfile.h>
00029 #include <ktempfile.h>
00030 #include <kgenericfactory.h>
00031 #include <kmimetype.h>
00032 #include <KoFilterChain.h>
00033 #include <KoDocumentInfo.h>
00034
00035
00036 #include <powerpointfilter.h>
00037
00038
00039
00040 #include <myfile.h>
00041
00042 const int OLEFilter::s_area = 30510;
00043
00044 class OLEFilterFactory : KGenericFactory<OLEFilter, KoFilter>
00045 {
00046 public:
00047 OLEFilterFactory(void) : KGenericFactory<OLEFilter, KoFilter> ("olefilter")
00048 {}
00049 protected:
00050 virtual void setupTranslations( void )
00051 {
00052 KGlobal::locale()->insertCatalogue( "kofficefilters" );
00053 }
00054 };
00055
00056 K_EXPORT_COMPONENT_FACTORY( libolefilter, OLEFilterFactory() )
00057
00058 OLEFilter::OLEFilter(KoFilter *, const char *, const QStringList&) :
00059 KoEmbeddingFilter(), numPic( 0 ),
00060 docfile( 0 ), m_embeddeeData( 0 ),
00061 m_embeddeeLength( 0 ), success( true )
00062 {
00063 olefile.data=0L;
00064 }
00065
00066 OLEFilter::~OLEFilter()
00067 {
00068 delete [] olefile.data;
00069 delete docfile;
00070 }
00071
00072 KoFilter::ConversionStatus OLEFilter::convert( const QCString& from, const QCString& to )
00073 {
00074 if(to!="application/x-kword" &&
00075 to!="application/x-kspread" &&
00076 to!="application/x-kpresenter")
00077 return KoFilter::NotImplemented;
00078 if(from!="application/vnd.ms-word" &&
00079 from!="application/vnd.ms-excel" &&
00080 from!="application/msword" &&
00081 from!="application/msexcel" &&
00082 from!="application/mspowerpoint" &&
00083 from!="application/x-hancomword")
00084 return KoFilter::NotImplemented;
00085
00086 QFile in(m_chain->inputFile());
00087 if(!in.open(IO_ReadOnly)) {
00088 kdError(s_area) << "OLEFilter::filter(): Unable to open input" << endl;
00089 in.close();
00090 return KoFilter::FileNotFound;
00091 }
00092
00093
00094
00095 olefile.length=in.size();
00096 olefile.data=new unsigned char[olefile.length];
00097 in.readBlock((char*)olefile.data, olefile.length);
00098 in.close();
00099
00100 docfile=new KLaola(olefile);
00101 if(!docfile->isOk()) {
00102 kdError(s_area) << "OLEFilter::filter(): Unable to read input file correctly!" << endl;
00103 delete [] olefile.data;
00104 olefile.data=0L;
00105 return KoFilter::StupidError;
00106 }
00107
00108
00109 convert( "" );
00110 if ( success )
00111 return KoFilter::OK;
00112 else
00113 return KoFilter::StupidError;
00114 }
00115
00116 void OLEFilter::commSlotDelayStream( const char* delay )
00117 {
00118 emit internalCommDelayStream( delay );
00119 }
00120
00121 void OLEFilter::commSlotShapeID( unsigned int& shapeID )
00122 {
00123 emit internalCommShapeID( shapeID );
00124 }
00125
00126 void OLEFilter::slotSavePart(
00127 const QString &nameIN,
00128 QString &storageId,
00129 QString &mimeType,
00130 const QString &extension,
00131 unsigned int length,
00132 const char *data)
00133 {
00134 if(nameIN.isEmpty())
00135 return;
00136
00137 int id = internalPartReference( nameIN );
00138
00139 if (id != -1)
00140 {
00141
00142
00143 storageId = QString::number( id );
00144 mimeType = internalPartMimeType( nameIN );
00145 }
00146 else
00147 {
00148
00149 m_embeddeeData = data;
00150 m_embeddeeLength = length;
00151
00152 QString srcMime( KoEmbeddingFilter::mimeTypeByExtension( extension ) );
00153 if ( srcMime == KMimeType::defaultMimeType() )
00154 kdWarning( s_area ) << "Couldn't determine the mimetype from the extension" << endl;
00155
00156 KoFilter::ConversionStatus status;
00157 QCString destMime( mimeType.latin1() );
00158 storageId = QString::number( embedPart( srcMime.latin1(), destMime, status, nameIN ) );
00159
00160
00161 mimeType = destMime;
00162
00163
00164 m_embeddeeData = 0;
00165 m_embeddeeLength = 0;
00166
00167 if ( status != KoFilter::OK )
00168 kdDebug(s_area) << "Huh??? Couldn't convert that file" << endl;
00169 }
00170 }
00171
00172 void OLEFilter::slotSaveDocumentInformation(
00173 const QString &fullName,
00174 const QString &title,
00175 const QString &company,
00176 const QString &email,
00177 const QString &telephone,
00178 const QString &fax,
00179 const QString &postalCode,
00180 const QString &country,
00181 const QString &city,
00182 const QString &street,
00183 const QString &docTitle,
00184 const QString &docAbstract)
00185 {
00186 KoDocumentInfo *info = new KoDocumentInfo();
00187 KoDocumentInfoAuthor *author = static_cast<KoDocumentInfoAuthor *>(info->page("author"));
00188 KoDocumentInfoAbout *about = static_cast<KoDocumentInfoAbout *>(info->page("about"));
00189 author->setFullName(fullName);
00190 author->setTitle(title);
00191 author->setCompany(company);
00192 author->setEmail(email);
00193 author->setTelephoneHome(telephone);
00194 author->setFax(fax);
00195 author->setCountry(postalCode);
00196 author->setPostalCode(country);
00197 author->setCity(city);
00198 author->setStreet(street);
00199 about->setTitle(docTitle);
00200 about->setTitle(docAbstract);
00201
00202 KoStoreDevice* docInfo = m_chain->storageFile( "documentinfo.xml", KoStore::Write );
00203
00204 if(!docInfo)
00205 {
00206 kdError(s_area) << "OLEFilter::slotSaveDocumentInformation(): Could not open documentinfo.xml!" << endl;
00207 return;
00208 }
00209
00210 QCString data = info->save().toCString();
00211
00212
00213 Q_LONG length = data.size()-1;
00214
00215 if(docInfo->writeBlock(data, length) != length)
00216 kdError(s_area) << "OLEFilter::slotSaveDocumentInformation(): Could not write to KoStore!" << endl;
00217 }
00218
00219 void OLEFilter::slotSavePic(
00220 const QString &nameIN,
00221 QString &storageId,
00222 const QString &extension,
00223 unsigned int length,
00224 const char *data)
00225 {
00226 if(nameIN.isEmpty())
00227 return;
00228
00229 QMap<QString, QString>::ConstIterator it = imageMap.find(nameIN);
00230
00231 if (it != imageMap.end())
00232
00233 storageId = it.data();
00234 else
00235 {
00236
00237 storageId = QString( "pictures/picture%1.%2" ).arg( numPic++ ).arg( extension );
00238 imageMap.insert(nameIN, storageId);
00239 KoStoreDevice* pic = m_chain->storageFile( storageId, KoStore::Write );
00240 if(!pic)
00241 {
00242 success = false;
00243 kdError(s_area) << "OLEFilter::slotSavePic(): Could not open KoStore!" << endl;
00244 return;
00245 }
00246
00247
00248 bool ret = pic->writeBlock(data, length) == static_cast<int>( length );
00249 if (!ret)
00250 kdError(s_area) << "OLEFilter::slotSavePic(): Could not write to KoStore!" << endl;
00251 }
00252 }
00253
00254
00255 void OLEFilter::slotPart(
00256 const QString& nameIN,
00257 QString &storageId,
00258 QString &mimeType)
00259 {
00260 if (nameIN.isEmpty())
00261 return;
00262
00263 int id = internalPartReference( nameIN );
00264
00265 if (id != -1)
00266 {
00267
00268 storageId = QString::number( id );
00269 mimeType = internalPartMimeType( nameIN );
00270 }
00271 else
00272 kdWarning( s_area ) << "slotPart() can be used for lookup operations only" << endl;
00273 }
00274
00275
00276 void OLEFilter::slotGetStream(const int &handle, myFile &stream) {
00277 stream=docfile->stream(handle);
00278 }
00279
00280
00281
00282
00283 void OLEFilter::slotGetStream(const QString &name, myFile &stream) {
00284
00285 KLaola::NodeList handle;
00286
00287 handle=docfile->find(name, true);
00288
00289 if (handle.count()==1)
00290 stream=docfile->stream(handle.at(0));
00291 else {
00292 stream.data=0L;
00293 stream.length=0;
00294 }
00295 }
00296
00297 void OLEFilter::savePartContents( QIODevice* file )
00298 {
00299 if ( m_embeddeeData != 0 && m_embeddeeLength != 0 )
00300 file->writeBlock( m_embeddeeData, m_embeddeeLength );
00301 }
00302
00303
00304 void OLEFilter::convert( const QCString& mimeTypeHint )
00305 {
00306 KLaola::NodeList list=docfile->parseCurrentDir();
00307 KLaola::OLENode *node;
00308 bool onlyDirs=true;
00309
00310
00311 for(node=list.first(); node!=0; node=list.next()) {
00312 if(node->isDirectory()) {
00313 if(docfile->enterDir(node)) {
00314
00315
00316 if (node->name() == "ObjectPool")
00317 convert( "" );
00318 else {
00319
00320
00321 QCString mimeHint( mimeTypeHelper() );
00322 if ( mimeHint.isEmpty() )
00323 mimeHint = "application/x-kword";
00324 startInternalEmbedding( node->name(), mimeHint );
00325 convert( mimeHint );
00326 endInternalEmbedding();
00327 }
00328 docfile->leaveDir();
00329 }
00330 }
00331 else
00332 onlyDirs=false;
00333 }
00334
00335 if(!onlyDirs) {
00336 QStringList nodeNames;
00337 QCString mimeType;
00338 if ( !mimeTypeHint.isEmpty() )
00339 mimeType = mimeTypeHint;
00340 else
00341 mimeType = mimeTypeHelper();
00342
00343 FilterBase *myFilter=0L;
00344
00345 #if 0
00346 if ( mimeType == "application/x-kword" ) {
00347
00348
00349 myFile main;
00350 KLaola::NodeList tmp;
00351 tmp=docfile->find("WordDocument", true);
00352
00353 if(tmp.count()==1) {
00354
00355 main=docfile->stream(tmp.at(0));
00356
00357 myFile table0, table1, data;
00358 tmp=docfile->find("0Table", true);
00359 if(tmp.count()==1)
00360 table0=docfile->stream(tmp.at(0));
00361
00362 tmp=docfile->find("1Table", true);
00363 if(tmp.count()==1)
00364 table1=docfile->stream(tmp.at(0));
00365
00366 tmp=docfile->find("Data", true);
00367 if(tmp.count()==1)
00368 data=docfile->stream(tmp.at(0));
00369
00370 myFilter=new WordFilter(main, table0, table1, data);
00371
00372
00373 connect( this, SIGNAL( internalCommShapeID( unsigned int& ) ), myFilter, SIGNAL( internalCommShapeID( unsigned int& ) ) );
00374 connect( this, SIGNAL( internalCommDelayStream( const char* ) ), myFilter, SIGNAL( internalCommDelayStream( const char* ) ) );
00375 }
00376 }
00377 else if ( mimeType == "application/x-kspread" ) {
00378
00379
00380 myFile workbook;
00381 KLaola::NodeList tmp;
00382
00383 tmp = docfile->find( "Workbook", true );
00384 if ( tmp.count() == 1 )
00385 workbook = docfile->stream( tmp.at( 0 ) );
00386 else {
00387 tmp = docfile->find( "Book", true );
00388 if ( tmp.count() == 1 )
00389 workbook = docfile->stream( tmp.at( 0 ) );
00390 }
00391 myFilter=new ExcelFilter(workbook);
00392 }
00393 else
00394 #endif
00395 if ( mimeType == "application/x-kpresenter" ) {
00396
00397
00398 myFile main, currentUser, pictures, summary, documentSummary;
00399 KLaola::NodeList tmp;
00400
00401 tmp=docfile->find("PowerPoint Document", true);
00402 if(tmp.count()==1)
00403 main=docfile->stream(tmp.at(0));
00404
00405 tmp=docfile->find("Current User", true);
00406 if(tmp.count()==1)
00407 currentUser=docfile->stream(tmp.at(0));
00408
00409 tmp=docfile->find("Pictures", true);
00410 if(tmp.count()==1)
00411 pictures=docfile->stream(tmp.at(0));
00412
00413 tmp=docfile->find("SummaryInformation", true);
00414 if(tmp.count()==1)
00415 summary=docfile->stream(tmp.at(0));
00416
00417 tmp=docfile->find("DocumentSummaryInformation", true);
00418 if(tmp.count()==1)
00419 documentSummary=docfile->stream(tmp.at(0));
00420
00421 myFilter=new PowerPointFilter(main, currentUser, pictures);
00422 }
00423 #if 0
00424 else if ( mimeType == "application/x-hancomword" ) {
00425
00426 myFile prvText;
00427 KLaola::NodeList tmp;
00428
00429 tmp = docfile->find( "PrvText", true );
00430 if( tmp.count() == 1 ) prvText = docfile->stream( tmp.at( 0 ) );
00431
00432 myFilter = new HancomWordFilter( prvText );
00433 }
00434 #endif
00435
00436 if(!myFilter) {
00437
00438 node = list.first();
00439 do {
00440 nodeNames.prepend(node->name());
00441 node = list.next();
00442 } while ( node );
00443
00444 kdWarning(s_area) << "cannot convert \"" << nodeNames.join(",") << "\"" << endl;
00445 myFilter=new FilterBase(nodeNames);
00446 }
00447
00448
00449 connectCommon(&myFilter);
00450
00451
00452 success=myFilter->filter();
00453
00454 QCString file;
00455 if(!myFilter->plainString()) {
00456 const QDomDocument * const part=myFilter->part();
00457 file=part->toCString();
00458 }
00459 else
00460 file=myFilter->CString();
00461
00462 KoStoreDevice* dev = m_chain->storageFile( "root", KoStore::Write );
00463 if(!dev) {
00464 success=false;
00465 kdError(s_area) << "OLEFilter::convert(): Could not open KoStore!" << endl;
00466 return;
00467 }
00468
00469
00470 bool ret = dev->writeBlock(file.data(), file.size()-1) == static_cast<Q_LONG>( file.size() - 1 );
00471 if (!ret)
00472 kdError(s_area) << "OLEFilter::slotSavePic(): Could not write to KoStore!" << endl;
00473 delete myFilter;
00474 }
00475 }
00476
00477 void OLEFilter::connectCommon(FilterBase **myFilter) {
00478 QObject::connect(
00479 *myFilter,
00480 SIGNAL(signalSaveDocumentInformation(const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &)),
00481 this,
00482 SLOT(slotSaveDocumentInformation(const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &)));
00483
00484 QObject::connect(
00485 *myFilter,
00486 SIGNAL(signalSavePic(const QString &, QString &, const QString &, unsigned int, const char *)),
00487 this,
00488 SLOT(slotSavePic(const QString &, QString &, const QString &, unsigned int, const char *)));
00489 QObject::connect(
00490 *myFilter,
00491 SIGNAL(signalSavePart(const QString &, QString &, QString &, const QString &, unsigned int, const char *)),
00492 this,
00493 SLOT(slotSavePart(const QString &, QString &, QString &, const QString &, unsigned int, const char *)));
00494 QObject::connect(*myFilter, SIGNAL(signalPart(const QString&, QString &, QString &)),
00495 this, SLOT(slotPart(const QString&, QString &, QString &)));
00496 QObject::connect(*myFilter, SIGNAL(signalGetStream(const int &, myFile &)), this,
00497 SLOT(slotGetStream(const int &, myFile &)));
00498 QObject::connect(*myFilter, SIGNAL(signalGetStream(const QString &, myFile &)), this,
00499 SLOT(slotGetStream(const QString &, myFile &)));
00500 QObject::connect(*myFilter, SIGNAL(sigProgress(int)), this, SIGNAL(sigProgress(int)));
00501 }
00502
00503 QCString OLEFilter::mimeTypeHelper()
00504 {
00505 KLaola::NodeList list = docfile->parseCurrentDir();
00506 KLaola::OLENode* node = list.first();
00507
00508
00509 while ( node ) {
00510 if ( node->name() == "WordDocument" )
00511 return "application/x-kword";
00512 else if ( node->name() == "Workbook" || node->name() == "Book" )
00513 return "application/x-kspread";
00514 else if ( node->name() == "PowerPoint Document" )
00515 return "application/x-kpresenter";
00516 else if ( node->name() == "PrvText" || node->name() == "BodyText" )
00517 return "application/x-hancomword";
00518 else
00519 node = list.next();
00520 }
00521 kdWarning( s_area ) << "No known mimetype detected" << endl;
00522 return "";
00523 }
00524
00525 #include <olefilter.moc>