~ubuntu-branches/ubuntu/breezy/koffice/breezy-security

« back to all changes in this revision

Viewing changes to filters/kspread/opencalc/opencalcexport.cc

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2005-10-11 14:49:50 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051011144950-lwpngbifzp8nk0ds
Tags: 1:1.4.1-0ubuntu7
* SECURITY UPDATE: fix heap based buffer overflow in the RTF importer of KWord
* Opening specially crafted RTF files in KWord can cause
  execution of abitrary code.
* Add kubuntu_01_rtfimport_heap_overflow.diff
* References:
  CAN-2005-2971
  CESA-2005-005
  http://www.koffice.org/security/advisory-20051011-1.txt

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* This file is part of the KDE project
2
2
   Copyright (C) 2000 David Faure <faure@kde.org>
3
3
   Copyright (C) 2000 Norbert Andres <nandres@web.de>
 
4
   Copyright (C) 2005 Laurent Montel <montel@kde.org>
4
5
 
5
6
   This library is free software; you can redistribute it and/or
6
7
   modify it under the terms of the GNU Library General Public
33
34
#include <kmessagebox.h>
34
35
#include <kmdcodec.h>
35
36
#include <kgenericfactory.h>
 
37
#include <klocale.h>
 
38
 
36
39
#include <koDocumentInfo.h>
37
40
#include <koFilterChain.h>
38
41
#include <koGlobal.h>
42
45
#include <kspread_doc.h>
43
46
#include <kspread_format.h>
44
47
#include <kspread_map.h>
 
48
#include <kspread_view.h>
 
49
#include <kspread_canvas.h>
45
50
#include <kspread_sheet.h>
46
51
#include <kspread_sheetprint.h>
47
52
#include <kspread_style.h>
58
63
protected:
59
64
    virtual void setupTranslations( void )
60
65
    {
61
 
        KGlobal::locale()->insertCatalogue( "kspreadopencalcfilter" );
 
66
        KGlobal::locale()->insertCatalogue( "kofficefilters" );
62
67
    }
63
68
};
64
69
 
71
76
    return false; \
72
77
  } while(0)
73
78
 
74
 
OpenCalcExport::OpenCalcExport( KoFilter *, const char *, const QStringList & ) 
75
 
  : KoFilter() 
 
79
OpenCalcExport::OpenCalcExport( KoFilter *, const char *, const QStringList & )
 
80
  : KoFilter(), m_locale( 0 )
76
81
{
77
82
}
78
83
 
79
 
KoFilter::ConversionStatus OpenCalcExport::convert( const QCString & from, 
 
84
KoFilter::ConversionStatus OpenCalcExport::convert( const QCString & from,
80
85
                                                    const QCString & to )
81
86
{
82
87
  /* later...
83
88
     KSpreadLeader  * leader = new KSpreadLeader( m_chain );
84
89
     OpenCalcWorker * worker = new OpenCalcWorker();
85
90
     leader->setWorker( worker );
86
 
     
 
91
 
87
92
     KoFilter::ConversionStatus status = leader->convert();
88
 
     
 
93
 
89
94
     delete worker;
90
95
     delete leader;
91
 
     
 
96
 
92
97
     return status;
93
98
  */
94
99
 
99
104
 
100
105
  if ( strcmp(document->className(), "KSpreadDoc") != 0)
101
106
  {
102
 
    kdWarning(30518) << "document isn't a KSpreadDoc but a " 
 
107
    kdWarning(30518) << "document isn't a KSpreadDoc but a "
103
108
                     << document->className() << endl;
104
109
    return KoFilter::NotImplemented;
105
110
  }
110
115
    return KoFilter::NotImplemented;
111
116
  }
112
117
 
113
 
  KSpreadDoc const * const ksdoc = static_cast<const KSpreadDoc *>(document);
 
118
  const KSpreadDoc * ksdoc = static_cast<const KSpreadDoc *>(document);
114
119
 
115
120
  if ( ksdoc->mimeType() != "application/x-kspread" )
116
121
  {
118
123
    return KoFilter::NotImplemented;
119
124
  }
120
125
 
 
126
  m_locale = static_cast<KSpreadDoc*>(document)->locale();
121
127
  if ( !writeFile( ksdoc ) )
122
128
    return KoFilter::CreationError;
123
129
 
124
130
  emit sigProgress( 100 );
125
 
  
 
131
 
126
132
  return KoFilter::OK;
127
133
}
128
134
 
129
 
bool OpenCalcExport::writeFile( KSpreadDoc const * const ksdoc )
 
135
bool OpenCalcExport::writeFile( const KSpreadDoc * ksdoc )
130
136
{
131
137
  KoStore * store = KoStore::createStore( m_chain->outputFile(), KoStore::Write, "", KoStore::Zip );
132
138
 
138
144
  if ( !exportContent( store, ksdoc ) )
139
145
    STOPEXPORT;
140
146
  else
141
 
    filesWritten |= contentXML;    
 
147
    filesWritten |= contentXML;
142
148
 
143
149
  // TODO: pass sheet number and cell number
144
150
  if ( !exportDocInfo( store, ksdoc ) )
151
157
  else
152
158
    filesWritten |= stylesXML;
153
159
 
 
160
  if ( !exportSettings( store, ksdoc ) )
 
161
    STOPEXPORT;
 
162
  else
 
163
    filesWritten |= settingsXML;
 
164
 
154
165
  if ( !writeMetaFile( store, filesWritten ) )
155
166
    STOPEXPORT;
156
167
 
161
172
  return true;
162
173
}
163
174
 
164
 
bool OpenCalcExport::exportDocInfo( KoStore * store, KSpreadDoc const * const ksdoc )
 
175
bool OpenCalcExport::exportDocInfo( KoStore * store, const KSpreadDoc* ksdoc )
165
176
{
166
177
  if ( !store->open( "meta.xml" ) )
167
178
    return false;
191
202
  data = meta.createElement( "meta:initial-creator" );
192
203
  data.appendChild( meta.createTextNode( authorPage->fullName() ) );
193
204
  officeMeta.appendChild( data );
194
 
  
 
205
 
195
206
  data = meta.createElement( "meta:creator" );
196
207
  data.appendChild( meta.createTextNode( authorPage->fullName() ) );
197
208
  officeMeta.appendChild( data );
198
209
 
199
 
  data = meta.createElement( "meta:user-defined" );
200
 
  data.setAttribute( "meta:name", "Info 1" );
 
210
  data = meta.createElement( "dc:description" );
 
211
  data.appendChild( meta.createTextNode( aboutPage->abstract() ) );
 
212
  officeMeta.appendChild( data );
 
213
 
 
214
  data = meta.createElement( "meta:keywords" );
 
215
  QDomElement dataItem = meta.createElement( "meta:keyword" );
 
216
  dataItem.appendChild( meta.createTextNode( aboutPage->keywords() ) );
 
217
  data.appendChild( dataItem );
 
218
  officeMeta.appendChild( data );
 
219
 
 
220
  data = meta.createElement( "dc:title" );
201
221
  data.appendChild( meta.createTextNode( aboutPage->title() ) );
202
222
  officeMeta.appendChild( data );
203
223
 
204
 
  data = meta.createElement( "meta:user-defined" );
205
 
  data.setAttribute( "meta:name", "Info 2" );
206
 
  data.appendChild( meta.createTextNode( aboutPage->abstract() ) );
 
224
  data = meta.createElement( "dc:subject" );
 
225
  data.appendChild( meta.createTextNode( aboutPage->subject() ) );
207
226
  officeMeta.appendChild( data );
208
227
 
 
228
  const QDateTime dt ( QDateTime::currentDateTime() );
 
229
  if ( dt.isValid() )
 
230
  {
 
231
    data = meta.createElement( "dc:date" );
 
232
    data.appendChild( meta.createTextNode( dt.toString( Qt::ISODate ) ) );
 
233
    officeMeta.appendChild( data );
 
234
  }
 
235
 
209
236
  /* TODO:
210
237
    <meta:creation-date>2003-01-08T23:57:31</meta:creation-date>
211
 
    <dc:date>2003-01-08T23:58:05</dc:date>
212
238
    <dc:language>en-US</dc:language>
213
239
    <meta:editing-cycles>2</meta:editing-cycles>
214
240
    <meta:editing-duration>PT38S</meta:editing-duration>
235
261
  return true;
236
262
}
237
263
 
238
 
bool OpenCalcExport::exportContent( KoStore * store, KSpreadDoc const * const ksdoc )
 
264
bool OpenCalcExport::exportSettings( KoStore * store, const KSpreadDoc * ksdoc )
 
265
{
 
266
  if ( !store->open( "settings.xml" ) )
 
267
    return false;
 
268
 
 
269
  QDomDocument doc;
 
270
  doc.appendChild( doc.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) );
 
271
 
 
272
  QDomElement settings = doc.createElement( "office:document-settings" );
 
273
  settings.setAttribute( "xmlns:office", "http://openoffice.org/2000/office");
 
274
  settings.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" );
 
275
  settings.setAttribute( "xmlns:config", "http://openoffice.org/2001/config" );
 
276
  settings.setAttribute( "office:version", "1.0" );
 
277
 
 
278
  QDomElement begin = doc.createElement( "office:settings" );
 
279
 
 
280
  QDomElement configItem = doc.createElement("config:config-item-set" );
 
281
  configItem.setAttribute( "config:name", "view-settings" );
 
282
 
 
283
  QDomElement mapIndexed = doc.createElement( "config:config-item-map-indexed" );
 
284
  mapIndexed.setAttribute("config:name", "Views" );
 
285
  configItem.appendChild( mapIndexed );
 
286
 
 
287
  QDomElement mapItem = doc.createElement("config:config-item-map-entry" );
 
288
 
 
289
  QDomElement attribute =  doc.createElement("config:config-item" );
 
290
  attribute.setAttribute( "config:name", "ActiveTable" );
 
291
  attribute.setAttribute( "config:type", "string" );
 
292
 
 
293
  KSpreadView * view = static_cast<KSpreadView*>( ksdoc->views().getFirst());
 
294
  QString activeTable;
 
295
  if ( view ) // no view if embedded document
 
296
  {
 
297
      KSpreadCanvas * canvas = view->canvasWidget();
 
298
      activeTable = canvas->activeSheet()->sheetName();
 
299
      // save current sheet selection before to save marker, otherwise current pos is not saved
 
300
      view->saveCurrentSheetSelection();
 
301
  }
 
302
  attribute.appendChild( doc.createTextNode( activeTable ) );
 
303
  mapItem.appendChild( attribute );
 
304
 
 
305
  QDomElement configmaped = doc.createElement( "config:config-item-map-named" );
 
306
  configmaped.setAttribute( "config:name","Tables" );
 
307
 
 
308
  QPtrListIterator<KSpreadSheet> it( ksdoc->map()->sheetList() );
 
309
  for( ; it.current(); ++it )
 
310
  {
 
311
      QPoint marker;
 
312
      if ( view )
 
313
      {
 
314
          marker = view->markerFromSheet( *it );
 
315
      }
 
316
      QDomElement tmpItemMapNamed = doc.createElement( "config:config-item-map-entry" );
 
317
      tmpItemMapNamed.setAttribute( "config:name", ( *it )->tableName() );
 
318
 
 
319
      QDomElement sheetAttribute = doc.createElement( "config:config-item" );
 
320
      sheetAttribute.setAttribute( "config:name", "CursorPositionX" );
 
321
      sheetAttribute.setAttribute( "config:type", "int" );
 
322
      sheetAttribute.appendChild( doc.createTextNode( QString::number(marker.x() )  ) );
 
323
      tmpItemMapNamed.appendChild( sheetAttribute );
 
324
 
 
325
      sheetAttribute = doc.createElement( "config:config-item" );
 
326
      sheetAttribute.setAttribute( "config:name", "CursorPositionY" );
 
327
      sheetAttribute.setAttribute( "config:type", "int" );
 
328
      sheetAttribute.appendChild( doc.createTextNode( QString::number(marker.y() )  ) );
 
329
      tmpItemMapNamed.appendChild( sheetAttribute );
 
330
 
 
331
      configmaped.appendChild( tmpItemMapNamed );
 
332
  }
 
333
  mapItem.appendChild( configmaped );
 
334
 
 
335
 
 
336
 
 
337
  mapIndexed.appendChild( mapItem );
 
338
 
 
339
  begin.appendChild( configItem );
 
340
 
 
341
  settings.appendChild( begin );
 
342
 
 
343
  doc.appendChild( settings );
 
344
 
 
345
  QCString f( doc.toCString() );
 
346
  kdDebug(30518) << "Settings: " << (char const * ) f << endl;
 
347
 
 
348
  store->write( f, f.length() );
 
349
 
 
350
  if ( !store->close() )
 
351
    return false;
 
352
 
 
353
  return true;
 
354
}
 
355
 
 
356
bool OpenCalcExport::exportContent( KoStore * store, const KSpreadDoc * ksdoc )
239
357
{
240
358
  if ( !store->open( "content.xml" ) )
241
359
    return false;
282
400
  return true;
283
401
}
284
402
 
 
403
 // e.g.: Sheet4.A1:Sheet4.E28
 
404
QString convertRangeToRef( const QString & tableName, const QRect & _area )
 
405
{
 
406
    return tableName + "." + KSpreadCell::name( _area.left(), _area.top() ) + ":" + tableName + "."+ KSpreadCell::name( _area.right(), _area.bottom() );
 
407
}
 
408
 
 
409
 
285
410
QString convertRefToBase( QString const & table, QRect const & rect )
286
411
{
287
412
  QPoint bottomRight( rect.bottomRight() );
289
414
  QString s( "$" );
290
415
  s += table;
291
416
  s += ".$";
292
 
  s += util_encodeColumnLabelText( bottomRight.x() );
 
417
  s += /*util_encodeColumnLabelText*/KSpreadCell::columnName( bottomRight.x() );
293
418
  s += '$';
294
419
  s += QString::number( bottomRight.y() );
295
420
 
307
432
  QString s( "$" );
308
433
  s += table;
309
434
  s += ".$";
310
 
  s += util_encodeColumnLabelText( topLeft.x() );
 
435
  s += /*util_encodeColumnLabelText*/KSpreadCell::columnName( topLeft.x() );
311
436
  s += '$';
312
437
  s += QString::number( topLeft.y() );
313
438
  s += ":.$";
314
 
  s += util_encodeColumnLabelText( bottomRight.x() );
 
439
  s += /*util_encodeColumnLabelText*/KSpreadCell::columnName( bottomRight.x() );
315
440
  s += '$';
316
441
  s += QString::number( bottomRight.y() );
317
 
  
 
442
 
318
443
  return s;
319
444
}
320
445
 
321
 
void exportNamedExpr( QDomDocument & doc, QDomElement & parent, 
 
446
void exportNamedExpr( QDomDocument & doc, QDomElement & parent,
322
447
                      AreaList const & namedAreas )
323
448
{
324
449
  AreaList::const_iterator it  = namedAreas.begin();
331
456
    Reference ref = *it;
332
457
 
333
458
    namedRange.setAttribute( "table:name", ref.ref_name );
334
 
    namedRange.setAttribute( "table:base-cell-address", convertRefToBase( ref.table_name, ref.rect ) );
335
 
    namedRange.setAttribute( "table:cell-range-address", convertRefToRange( ref.table_name, ref.rect ) );
 
459
    namedRange.setAttribute( "table:base-cell-address", convertRefToBase( ref.sheet_name, ref.rect ) );
 
460
    namedRange.setAttribute( "table:cell-range-address", convertRefToRange( ref.sheet_name, ref.rect ) );
336
461
 
337
462
    parent.appendChild( namedRange );
338
463
 
340
465
  }
341
466
}
342
467
 
343
 
bool OpenCalcExport::exportBody( QDomDocument & doc, QDomElement & content, KSpreadDoc const * const ksdoc )
 
468
bool OpenCalcExport::exportBody( QDomDocument & doc, QDomElement & content, const KSpreadDoc * ksdoc )
344
469
{
345
470
  QDomElement fontDecls  = doc.createElement( "office:font-decls" );
346
471
  QDomElement autoStyles = doc.createElement( "office:automatic-styles" );
349
474
  if ( ksdoc->map()->isProtected() )
350
475
  {
351
476
    body.setAttribute( "table:structure-protected", "true" );
352
 
    
 
477
 
353
478
    QCString passwd;
354
479
    ksdoc->map()->password( passwd );
355
480
    if ( passwd.length() > 0 )
356
481
    {
357
482
      QCString str( KCodecs::base64Encode( passwd ) );
358
 
      body.setAttribute( "table:protection-key", QString( str.data() ) );        
 
483
      body.setAttribute( "table:protection-key", QString( str.data() ) );
359
484
    }
360
485
  }
361
486
 
362
 
  QPtrListIterator<KSpreadSheet> it( ksdoc->map()->tableList() );
 
487
 
 
488
 
 
489
  QPtrListIterator<KSpreadSheet> it( ksdoc->map()->sheetList() );
363
490
 
364
491
  for( it.toFirst(); it.current(); ++it )
365
492
  {
372
499
 
373
500
    QDomElement tabElem = doc.createElement( "table:table" );
374
501
    tabElem.setAttribute( "table:style-name", m_styles.sheetStyle( ts ) );
375
 
    
 
502
 
376
503
    if ( sheet->isProtected() )
377
504
    {
378
505
      tabElem.setAttribute( "table:protected", "true" );
382
509
      if ( passwd.length() > 0 )
383
510
      {
384
511
        QCString str( KCodecs::base64Encode( passwd ) );
385
 
        tabElem.setAttribute( "table:protection-key", QString( str.data() ) );        
 
512
        tabElem.setAttribute( "table:protection-key", QString( str.data() ) );
386
513
      }
387
514
    }
388
515
 
397
524
    }
398
525
    name = name.replace( ' ', "_" );
399
526
 
 
527
    QRect _printRange = sheet->print()->printRange();
 
528
    if ( _printRange != ( QRect( QPoint( 1, 1 ), QPoint( KS_colMax, KS_rowMax ) ) ) )
 
529
    {
 
530
        QString range= convertRangeToRef( name, _printRange );
 
531
        //kdDebug(30518)<<" range : "<<range<<endl;
 
532
        tabElem.setAttribute( "table:print-ranges", range );
 
533
    }
 
534
 
 
535
 
400
536
    tabElem.setAttribute( "table:name", name );
401
537
 
402
538
    maxRowCols( sheet, maxCols, maxRows );
403
539
 
404
540
    exportSheet( doc, tabElem, sheet, maxCols, maxRows );
405
 
    
 
541
 
406
542
    body.appendChild( tabElem );
407
543
  }
408
544
 
409
545
  KoDocument * document   = m_chain->inputDocument();
410
546
  KSpreadDoc * kspreadDoc = static_cast<KSpreadDoc *>( document );
411
 
  
 
547
 
412
548
  AreaList namedAreas = kspreadDoc->listArea();
413
549
  if ( namedAreas.count() > 0 )
414
550
  {
415
551
    QDomElement namedExpr = doc.createElement( "table:named-expressions" );
416
552
    exportNamedExpr( doc, namedExpr, namedAreas );
417
 
    
 
553
 
418
554
    body.appendChild( namedExpr );
419
555
  }
420
556
 
428
564
  return true;
429
565
}
430
566
 
431
 
void OpenCalcExport::exportSheet( QDomDocument & doc, QDomElement & tabElem, 
432
 
                                  KSpreadSheet const * const sheet, int maxCols, int maxRows )
 
567
void OpenCalcExport::exportSheet( QDomDocument & doc, QDomElement & tabElem,
 
568
                                  const KSpreadSheet * sheet, int maxCols, int maxRows )
433
569
{
434
570
  kdDebug(30518) << "exportSheet: " << sheet->tableName() << endl;
435
571
  int i = 1;
436
572
 
437
573
  while ( i <= maxCols )
438
574
  {
439
 
    ColumnFormat const * const column = sheet->columnFormat( i );
 
575
    const ColumnFormat * column = sheet->columnFormat( i );
440
576
    ColumnStyle cs;
441
577
    cs.breakB = Style::automatic;
442
578
    cs.size   = column->mmWidth() / 10;
446
582
    int repeated = 1;
447
583
    while ( j <= maxCols )
448
584
    {
449
 
      ColumnFormat const * const c = sheet->columnFormat( j );
 
585
      const ColumnFormat *c = sheet->columnFormat( j );
450
586
      ColumnStyle cs1;
451
587
      cs1.breakB = Style::automatic;
452
588
      cs1.size   = c->mmWidth() / 10;
460
596
 
461
597
    QDomElement colElem = doc.createElement( "table:table-column" );
462
598
    colElem.setAttribute( "table:style-name", m_styles.columnStyle( cs ) );
463
 
    colElem.setAttribute( "table:default-cell-style-name", "Default" );
 
599
    colElem.setAttribute( "table:default-cell-style-name", "Default" );//todo fixme create style from cell
464
600
    if ( hide )
465
601
      colElem.setAttribute( "table:visibility", "collapse" );
466
602
 
473
609
 
474
610
  for ( i = 1; i <= maxRows; ++i )
475
611
  {
476
 
    RowFormat const * const row = sheet->rowFormat( i );
 
612
    const RowFormat * row = sheet->rowFormat( i );
477
613
    RowStyle rs;
478
614
    rs.breakB = Style::automatic;
479
615
    rs.size   = row->mmHeight() / 10;
489
625
  }
490
626
}
491
627
 
492
 
void OpenCalcExport::exportCells( QDomDocument & doc, QDomElement & rowElem, 
493
 
                                  KSpreadSheet const * const sheet, int row, int maxCols )
 
628
void OpenCalcExport::exportCells( QDomDocument & doc, QDomElement & rowElem,
 
629
                                  const KSpreadSheet *sheet, int row, int maxCols )
494
630
{
495
631
  int i = 1;
496
632
  while ( i <= maxCols )
497
633
  {
498
634
    int  repeated = 1;
499
635
    bool hasComment = false;
500
 
    KSpreadCell const * const cell = sheet->cellAt( i, row );
 
636
    const KSpreadCell* cell = sheet->cellAt( i, row );
501
637
    QDomElement cellElem;
502
638
 
503
639
    if ( !cell->isObscuringForced() )
517
653
    }
518
654
 
519
655
    CellStyle c;
520
 
    CellStyle::loadData( c, cell ); // TODO: number style    
 
656
    CellStyle::loadData( c, cell ); // TODO: number style
521
657
 
522
658
    cellElem.setAttribute( "table:style-name", m_styles.cellStyle( c ) );
523
659
 
524
660
    // group empty cells with the same style
525
 
    if ( cell->isEmpty() && !hasComment && !cell->isObscuringForced() && !cell->isForceExtraCells() ) 
526
 
    {  
 
661
    if ( cell->isEmpty() && !hasComment && !cell->isObscuringForced() && !cell->isForceExtraCells() )
 
662
    {
527
663
      int j = i + 1;
528
664
      while ( j <= maxCols )
529
665
      {
530
 
        KSpreadCell const * const cell1 = sheet->cellAt( j, row );
 
666
        const KSpreadCell *cell1 = sheet->cellAt( j, row );
531
667
 
532
668
        CellStyle c1;
533
669
        CellStyle::loadData( c1, cell1 ); // TODO: number style
534
670
 
535
 
        if ( cell1->isEmpty() && !cell->hasProperty( KSpreadFormat::PComment ) 
 
671
        if ( cell1->isEmpty() && !cell->hasProperty( KSpreadFormat::PComment )
536
672
             && CellStyle::isEqual( &c, c1 ) && !cell->isObscuringForced() && !cell->isForceExtraCells() )
537
673
          ++repeated;
538
674
        else
552
688
    else if ( value.isNumber() )
553
689
    {
554
690
      kdDebug(30518) << "Type: Number" << endl;
555
 
      KSpreadFormat::FormatType type = cell->getFormatType( i, row );
 
691
      FormatType type = cell->getFormatType( i, row );
556
692
 
557
 
      if ( type == KSpreadFormat::Percentage ) 
 
693
      if ( type == Percentage_format )
558
694
        cellElem.setAttribute( "table:value-type", "percentage" );
559
695
      else
560
696
        cellElem.setAttribute( "table:value-type", "float" );
561
697
 
562
698
      cellElem.setAttribute( "table:value", QString::number( value.asFloat() ) );
563
 
    }      
 
699
    }
564
700
    else
565
701
    {
566
702
      kdDebug(30518) << "Type: " << value.type() << endl;
573
709
      QString formula( convertFormula( cell->text() ) );
574
710
      cellElem.setAttribute( "table:formula", formula );
575
711
    }
576
 
    
 
712
    else if ( !cell->link().isEmpty() )
 
713
    {
 
714
      QDomElement link = doc.createElement( "text:p" );
 
715
      QDomElement linkref = doc.createElement( "text:a" );
 
716
 
 
717
      QString tmp = cell->link();
 
718
       if ( localReferenceAnchor( tmp ) )
 
719
           linkref.setAttribute( "xlink:href", ( "#"+tmp ) );
 
720
       else
 
721
           linkref.setAttribute( "xlink:href", tmp  );
 
722
 
 
723
       linkref.appendChild( doc.createTextNode( cell->text() ) );
 
724
 
 
725
       link.appendChild( linkref );
 
726
       cellElem.appendChild( link );
 
727
    }
 
728
    else if ( !cell->isEmpty() )
 
729
    {
 
730
      QDomElement textElem = doc.createElement( "text:p" );
 
731
      textElem.appendChild( doc.createTextNode( cell->strOutText() ) );
 
732
 
 
733
      cellElem.appendChild( textElem );
 
734
      kdDebug(30518) << "Cell StrOut: " << cell->strOutText() << endl;
 
735
    }
 
736
 
577
737
    if ( cell->isForceExtraCells() )
578
738
    {
579
739
      int colSpan = cell->mergedXCells() + 1;
597
757
      cellElem.appendChild( annotation );
598
758
    }
599
759
 
600
 
    if ( !cell->isEmpty() )
601
 
    {
602
 
      QDomElement textElem = doc.createElement( "text:p" );
603
 
      textElem.appendChild( doc.createTextNode( cell->strOutText() ) );
604
 
 
605
 
      cellElem.appendChild( textElem );
606
 
      kdDebug(30518) << "Cell StrOut: " << cell->strOutText() << endl;
607
 
    }
608
 
 
609
760
    rowElem.appendChild( cellElem );
610
761
 
611
762
    i += repeated;
612
763
  }
613
764
}
614
765
 
615
 
void OpenCalcExport::maxRowCols( KSpreadSheet const * const sheet, 
 
766
void OpenCalcExport::maxRowCols( const KSpreadSheet *sheet,
616
767
                                 int & maxCols, int & maxRows )
617
768
{
618
769
  KSpreadCell const * cell = sheet->firstCell();
646
797
 
647
798
    col = col->next();
648
799
  }
649
 
  
 
800
 
650
801
}
651
802
 
652
 
bool OpenCalcExport::exportStyles( KoStore * store, KSpreadDoc const * const ksdoc )
 
803
bool OpenCalcExport::exportStyles( KoStore * store, const KSpreadDoc *ksdoc )
653
804
{
654
805
  if ( !store->open( "styles.xml" ) )
655
806
    return false;
678
829
  QDomElement officeStyles = doc.createElement( "office:styles" );
679
830
  exportDefaultCellStyle( doc, officeStyles );
680
831
 
681
 
  QDomElement fontDecls = doc.createElement( "office:font-decls" );  
 
832
  QDomElement fontDecls = doc.createElement( "office:font-decls" );
682
833
  m_styles.writeFontDecl( doc, fontDecls );
683
834
 
684
835
  // TODO: needs in new number/date/time parser...
685
836
  //  exportDefaultNumberStyles( doc, officeStyles );
686
 
  
 
837
 
687
838
  QDomElement defaultStyle = doc.createElement( "style:style" );
688
839
  defaultStyle.setAttribute( "style:name", "Default" );
689
840
  defaultStyle.setAttribute( "style:family", "table-cell" );
691
842
 
692
843
  QDomElement autoStyles = doc.createElement( "office:automatic-styles" );
693
844
  exportPageAutoStyles( doc, autoStyles, ksdoc );
694
 
  
 
845
 
695
846
  QDomElement masterStyles = doc.createElement( "office:master-styles" );
696
847
  exportMasterStyles( doc, masterStyles, ksdoc );
697
848
 
722
873
  KSpreadDoc * ksdoc    = static_cast<KSpreadDoc *>(document);
723
874
 
724
875
  KSpreadFormat * format = new KSpreadFormat( 0, ksdoc->styleManager()->defaultStyle() );
725
 
  KLocale const * const locale = ksdoc->locale();
 
876
  const KLocale *locale = ksdoc->locale();
726
877
  QString language;
727
878
  QString country;
728
879
  QString charSet;
745
896
  style.setAttribute( "style:language-complex", "none" );
746
897
  style.setAttribute( "style:country-complex", "none" );
747
898
  style.setAttribute( "style:tab-stop-distance", "1.25cm" );
748
 
                                   
 
899
 
749
900
  defStyle.appendChild( style );
750
901
  officeStyles.appendChild( defStyle );
751
902
  delete format;
757
908
}
758
909
 
759
910
void OpenCalcExport::exportPageAutoStyles( QDomDocument & doc, QDomElement & autoStyles,
760
 
                                           KSpreadDoc const * const ksdoc )
 
911
                                           const KSpreadDoc *ksdoc )
761
912
{
762
 
  QPtrListIterator<KSpreadSheet> it( ksdoc->map()->tableList() );
763
 
  KSpreadSheet const * const sheet = it.toFirst();
 
913
  QPtrListIterator<KSpreadSheet> it( ksdoc->map()->sheetList() );
 
914
  const KSpreadSheet * sheet = it.toFirst();
764
915
 
765
916
  float width  = 20.999;
766
917
  float height = 29.699;
811
962
}
812
963
 
813
964
void OpenCalcExport::exportMasterStyles( QDomDocument & doc, QDomElement & masterStyles,
814
 
                                         KSpreadDoc const * const ksdoc )
 
965
                                         const KSpreadDoc * ksdoc )
815
966
{
816
967
  QDomElement masterPage = doc.createElement( "style:master-page" );
817
968
  masterPage.setAttribute( "style:name", "Default" );
818
969
  masterPage.setAttribute( "style:page-master-name", "pm1" );
819
970
 
820
 
  QPtrListIterator<KSpreadSheet> it( ksdoc->map()->tableList() );
821
 
  KSpreadSheet const * const sheet = it.toFirst();
 
971
  QPtrListIterator<KSpreadSheet> it( ksdoc->map()->sheetList() );
 
972
  const KSpreadSheet * sheet = it.toFirst();
822
973
 
823
974
  QString headerLeft;
824
975
  QString headerCenter;
826
977
  QString footerLeft;
827
978
  QString footerCenter;
828
979
  QString footerRight;
829
 
  
 
980
 
830
981
  if ( sheet )
831
982
  {
832
983
    headerLeft   = sheet->print()->headLeft();
912
1063
    masterPage.appendChild( footer );
913
1064
  }
914
1065
 
915
 
  masterStyles.appendChild( masterPage );       
 
1066
  masterStyles.appendChild( masterPage );
916
1067
}
917
1068
 
918
 
void OpenCalcExport::addText( QString const & text, QDomDocument & doc, 
 
1069
void OpenCalcExport::addText( QString const & text, QDomDocument & doc,
919
1070
                              QDomElement & parent )
920
1071
{
921
1072
  if (text.length() > 0 )
922
1073
    parent.appendChild( doc.createTextNode( text ) );
923
1074
}
924
1075
 
925
 
void OpenCalcExport::convertPart( QString const & part, QDomDocument & doc, 
926
 
                                  QDomElement & parent, KSpreadDoc const * const ksdoc )
 
1076
void OpenCalcExport::convertPart( QString const & part, QDomDocument & doc,
 
1077
                                  QDomElement & parent, const KSpreadDoc * ksdoc )
927
1078
{
928
1079
  QString text;
929
1080
  QString var;
943
1094
        if ( var == "<page>" )
944
1095
        {
945
1096
          addText( text, doc, parent );
946
 
          
 
1097
 
947
1098
          QDomElement page = doc.createElement( "text:page-number" );
948
1099
          page.appendChild( doc.createTextNode( "1" ) );
949
1100
          parent.appendChild( page );
951
1102
        else if ( var == "<pages>" )
952
1103
        {
953
1104
          addText( text, doc, parent );
954
 
          
 
1105
 
955
1106
          QDomElement page = doc.createElement( "text:page-count" );
956
1107
          page.appendChild( doc.createTextNode( "99" ) );
957
 
          parent.appendChild( page );          
 
1108
          parent.appendChild( page );
958
1109
        }
959
1110
        else if ( var == "<date>" )
960
1111
        {
962
1113
 
963
1114
          QDomElement t = doc.createElement( "text:date" );
964
1115
          t.setAttribute( "text:date-value", "0-00-00" );
965
 
          // todo: "style:data-style-name", "N2" 
 
1116
          // todo: "style:data-style-name", "N2"
966
1117
          t.appendChild( doc.createTextNode( QDate::currentDate().toString() ) );
967
1118
          parent.appendChild( t );
968
1119
        }
1030
1181
        {
1031
1182
          // no known variable:
1032
1183
          text += var;
1033
 
          addText( text, doc, parent );          
 
1184
          addText( text, doc, parent );
1034
1185
        }
1035
1186
 
1036
1187
        text = "";
1043
1194
    }
1044
1195
    ++i;
1045
1196
  }
 
1197
  if ( !text.isEmpty() || !var.isEmpty() )
 
1198
  {
 
1199
      //we don't have var at the end =>store it
 
1200
      addText( text+var, doc, parent );
 
1201
  }
1046
1202
}
1047
1203
 
1048
1204
void insertBracket( QString & s )
1055
1211
    c = s[i];
1056
1212
    if ( c == ' ' )
1057
1213
      s[i] = '_';
1058
 
    if ( !(c.isLetterOrNumber() || c == ' ' || c == '.' 
 
1214
    if ( !(c.isLetterOrNumber() || c == ' ' || c == '.'
1059
1215
           || c == '_') )
1060
1216
    {
1061
1217
      s.insert( i + 1, '[' );
1067
1223
 
1068
1224
QString OpenCalcExport::convertFormula( QString const & formula ) const
1069
1225
{
 
1226
  QChar decimalSymbol( '.' );
 
1227
  if ( m_locale )
 
1228
  {
 
1229
    const QString decimal ( m_locale->decimalSymbol() );
 
1230
    if ( !decimal.isEmpty() )
 
1231
    {
 
1232
        decimalSymbol = decimal.at( 0 );
 
1233
    }
 
1234
  }
 
1235
 
1070
1236
  QString s;
1071
1237
  QRegExp exp("(\\$?)([a-zA-Z]+)(\\$?)([0-9]+)");
1072
1238
  int n = exp.search( formula, 0 );
1073
 
  kdDebug(30518) << "Exp: " << formula << ", n: " << n << ", Length: " << formula.length() 
 
1239
  kdDebug(30518) << "Exp: " << formula << ", n: " << n << ", Length: " << formula.length()
1074
1240
            << ", Matched length: " << exp.matchedLength() << endl;
1075
1241
 
1076
 
  bool inQuote1 = false;  
1077
 
  bool inQuote2 = false;  
 
1242
  bool inQuote1 = false;
 
1243
  bool inQuote2 = false;
1078
1244
  int i = 0;
1079
1245
  int l = (int) formula.length();
1080
1246
  if ( l <= 0 )
1089
1255
    if ( formula[i] == '"' )
1090
1256
    {
1091
1257
      inQuote1 = !inQuote1;
1092
 
      s += formula[i];      
 
1258
      s += formula[i];
1093
1259
      ++i;
1094
1260
      continue;
1095
1261
    }
1119
1285
      ++i;
1120
1286
      continue;
1121
1287
    }
 
1288
    else if ( formula[i] == decimalSymbol )
 
1289
    {
 
1290
      s += '.'; // decimal point
 
1291
      ++i;
 
1292
      continue;
 
1293
    }
1122
1294
    if ( n == i )
1123
1295
    {
1124
1296
      int ml = exp.matchedLength();
1149
1321
 
1150
1322
bool OpenCalcExport::writeMetaFile( KoStore * store, uint filesWritten )
1151
1323
{
 
1324
    store->enterDirectory( "META-INF" );
1152
1325
  if ( !store->open( "manifest.xml" ) )
1153
1326
    return false;
1154
1327
 
1157
1330
 
1158
1331
  QDomDocument meta( type );
1159
1332
  meta.appendChild( meta.createProcessingInstruction( "xml","version=\"1.0\" encoding=\"UTF-8\"" ) );
1160
 
  
 
1333
 
1161
1334
  QDomElement content = meta.createElement( "manifest:manifest" );
1162
1335
  content.setAttribute( "xmlns:manifest", "http://openoffice.org/2001/manifest" );
1163
1336
 
1167
1340
  content.appendChild( entry );
1168
1341
 
1169
1342
  entry = meta.createElement( "manifest:file-entry" );
1170
 
  entry.setAttribute( "manifest:media-type", "" );
1171
 
  entry.setAttribute( "manifest:full-path", "Pictures/" );
1172
1343
  content.appendChild( entry );
1173
1344
 
1174
1345
  if ( filesWritten & contentXML )