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

« back to all changes in this revision

Viewing changes to lib/store/koStore.cc

  • Committer: Bazaar Package Importer
  • Author(s): Ben Burton
  • Date: 2004-05-09 11:33:00 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040509113300-vfrdadqsvjfuhn3b
Tags: 1:1.3.1-1
* New upstream bugfix release.
* Built against newer imagemagick (closes: #246623).
* Made koffice-libs/kformula recommend/depend on latex-xft-fonts, which
  provides mathematical fonts that the formula editor can use.  Also
  patched the kformula part to make these fonts the default.
* Changed kword menu hint from "WordProcessors" to "Word processors"
  (closes: #246209).
* Spellchecker configuration is now fixed (closes: #221256, #227568).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// -*- c-basic-offset: 2 -*-
1
2
/* This file is part of the KDE project
2
3
   Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
 
4
   Copyright (C) 2000-2002 David Faure <david@mandrakesoft.com>, Werner Trobin <trobin@kde.org>
3
5
 
4
6
   This library is free software; you can redistribute it and/or
5
7
   modify it under the terms of the GNU Library General Public
22
24
#include <stdlib.h>
23
25
 
24
26
#include "koStore.h"
 
27
#include "koTarStore.h"
 
28
#include "koZipStore.h"
 
29
#include "koDirectoryStore.h"
25
30
 
26
 
#include <qbuffer.h>
27
31
#include <kdebug.h>
28
 
#include <ktar.h>
29
 
#include <kapp.h>
30
 
#include <config.h>
31
 
 
32
 
#define ROOTPART "root"
33
 
#define MAINNAME "maindoc.xml"
34
 
 
35
 
KoStore::KoStore( const QString & _filename, Mode _mode, const QCString & appIdentification )
36
 
{
 
32
 
 
33
#include <qfileinfo.h>
 
34
#include <qfile.h>
 
35
#include <qdir.h>
 
36
 
 
37
//#define DefaultFormat KoStore::Tar
 
38
#define DefaultFormat KoStore::Zip
 
39
 
 
40
const int KoStore::s_area = 30002;
 
41
 
 
42
KoStore::Backend KoStore::determineBackend( QIODevice* dev )
 
43
{
 
44
    unsigned char buf[5];
 
45
    if ( dev->readBlock( (char *)buf, 4 ) < 4 )
 
46
      return DefaultFormat; // will create a "bad" store (bad()==true)
 
47
    if ( buf[0] == 0037 && buf[1] == 0213 ) // gzip -> tar.gz
 
48
      return Tar;
 
49
    if ( buf[0] == 'P' && buf[1] == 'K' && buf[2] == 3 && buf[3] == 4 )
 
50
      return Zip;
 
51
    return DefaultFormat; // fallback
 
52
}
 
53
 
 
54
KoStore* KoStore::createStore( const QString& fileName, Mode mode, const QCString & appIdentification, Backend backend )
 
55
{
 
56
  if ( backend == Auto ) {
 
57
    if ( mode == KoStore::Write )
 
58
      backend = DefaultFormat;
 
59
    else
 
60
    {
 
61
      QFileInfo inf( fileName );
 
62
      if ( inf.isDir() )
 
63
        backend = Directory;
 
64
      else
 
65
      {
 
66
        QFile file( fileName );
 
67
        if ( file.open( IO_ReadOnly ) )
 
68
          backend = determineBackend( &file );
 
69
        else
 
70
          backend = DefaultFormat; // will create a "bad" store (bad()==true)
 
71
      }
 
72
    }
 
73
  }
 
74
  switch ( backend )
 
75
  {
 
76
  case Tar:
 
77
    return new KoTarStore( fileName, mode, appIdentification );
 
78
  case Zip:
 
79
    return new KoZipStore( fileName, mode, appIdentification );
 
80
  case Directory:
 
81
    return new KoDirectoryStore( fileName /* should be a dir name.... */, mode );
 
82
  default:
 
83
    kdWarning(s_area) << "Unsupported backend requested for KoStore : " << backend << endl;
 
84
    return 0L;
 
85
  }
 
86
}
 
87
 
 
88
KoStore* KoStore::createStore( QIODevice *device, Mode mode, const QCString & appIdentification, Backend backend )
 
89
{
 
90
  if ( backend == Auto )
 
91
  {
 
92
    if ( mode == KoStore::Write )
 
93
      backend = DefaultFormat;
 
94
    else {
 
95
      if ( device->open( IO_ReadOnly ) ) {
 
96
        backend = determineBackend( device );
 
97
        device->close();
 
98
      }
 
99
    }
 
100
  }
 
101
  switch ( backend )
 
102
  {
 
103
  case Tar:
 
104
    return new KoTarStore( device, mode, appIdentification );
 
105
  case Directory:
 
106
    kdError(s_area) << "Can't create a Directory store for a memory buffer!" << endl;
 
107
    // fallback
 
108
  case Zip:
 
109
    return new KoZipStore( device, mode, appIdentification );
 
110
  default:
 
111
    kdWarning(s_area) << "Unsupported backend requested for KoStore : " << backend << endl;
 
112
    return 0L;
 
113
  }
 
114
}
 
115
 
 
116
namespace {
 
117
  const char* const ROOTPART = "root";
 
118
  const char* const MAINNAME = "maindoc.xml";
 
119
}
 
120
 
 
121
bool KoStore::init( Mode _mode )
 
122
{
 
123
  d = 0;
37
124
  m_bIsOpen = false;
38
125
  m_mode = _mode;
39
 
  m_stream = 0L;
40
 
 
41
 
  kdDebug(s_area) << "KoStore Constructor filename = " << _filename
42
 
    << " mode = " << int(_mode) << endl;
43
 
 
44
 
#if KDE_VERSION >= 220 // we have the new KTar
45
 
  m_pTar = new KTarGz( _filename, "application/x-gzip" );
46
 
#else
47
 
  m_pTar = new KTarGz( _filename );
48
 
#endif
49
 
 
50
 
  m_bGood = m_pTar->open( _mode == Write ? IO_WriteOnly : IO_ReadOnly );
51
 
 
52
 
  if ( m_bGood && _mode == Read )
53
 
      m_bGood = m_pTar->directory() != 0;
54
 
 
55
 
#if KDE_VERSION >= 220 // we have the new KTar
56
 
  if ( m_bGood && _mode == Write )
57
 
      m_pTar->setOrigFileName( appIdentification );
58
 
#endif
 
126
  m_stream = 0;
59
127
 
60
128
  // Assume new style names.
61
129
  m_namingVersion = NAMING_VERSION_2_2;
 
130
  return true;
62
131
}
63
132
 
64
133
KoStore::~KoStore()
65
134
{
66
 
  m_pTar->close();
67
 
  delete m_pTar;
68
 
  if ( m_stream )
69
 
    delete m_stream;
70
 
}
71
 
 
72
 
// See the specification for details of what this function does.
73
 
QString KoStore::toExternalNaming( const QString & _internalNaming )
74
 
{
75
 
  // "root" is the main document, let's save it as "maindoc.xml"
76
 
  if (_internalNaming == ROOTPART)
77
 
    return MAINNAME;
78
 
 
79
 
  if ( _internalNaming.left(5) == "tar:/" )
80
 
  {
81
 
    QString intern( _internalNaming.mid( 5 ) ); // remove protocol
82
 
    QString result( "" );
83
 
    int pos;
84
 
    while ( ( pos = intern.find( '/' ) ) != -1 ) {
85
 
      if ( QChar(intern.at(0)).isDigit() )
86
 
        result += "part";
87
 
      result += intern.left( pos + 1 ); // copy numbers (or "pictures") + "/"
88
 
      intern = intern.mid( pos + 1 ); // remove the dir we just processed
89
 
    }
90
 
 
91
 
    // Now process the filename. If the first character is numeric, we have
92
 
    // a main document.
93
 
    if ( QChar(intern.at(0)).isDigit() )
94
 
    {
95
 
        // If this is the first part name, check if we have a store with
96
 
        // old-style names.
97
 
        if ( ( m_namingVersion == NAMING_VERSION_2_2 ) &&
98
 
             ( m_mode == Read ) &&
99
 
             ( m_pTar->directory()->entry( result + "part" + intern + ".xml" ) ) )
100
 
        {
101
 
          m_namingVersion = NAMING_VERSION_2_1;
102
 
        }
103
 
        if ( m_namingVersion == NAMING_VERSION_2_1)
104
 
        {
105
 
          result = result + "part" + intern + ".xml";
106
 
        }
107
 
        else
108
 
        {
109
 
          result = result + "part" + intern + "/" + MAINNAME;
110
 
        }
111
 
    }
112
 
    else
113
 
    {
114
 
      result += intern;
115
 
    }
116
 
 
117
 
    return result;
118
 
  }
119
 
 
120
 
  return _internalNaming;
 
135
  delete m_stream;
121
136
}
122
137
 
123
138
bool KoStore::open( const QString & _name )
124
139
{
 
140
  // This also converts from relative to absolute, i.e. merges the currentPath()
125
141
  m_sName = toExternalNaming( _name );
126
142
 
127
143
  if ( m_bIsOpen )
128
144
  {
129
145
    kdWarning(s_area) << "KoStore: File is already opened" << endl;
 
146
    //return KIO::ERR_INTERNAL;
130
147
    return false;
131
148
  }
132
149
 
133
150
  if ( m_sName.length() > 512 )
134
151
  {
135
152
      kdError(s_area) << "KoStore: Filename " << m_sName << " is too long" << endl;
136
 
    return false;
 
153
      //return KIO::ERR_MALFORMED_URL;
 
154
      return false;
137
155
  }
138
156
 
139
157
  if ( m_mode == Write )
142
160
    if ( m_strFiles.findIndex( m_sName ) != -1 ) // just check if it's there
143
161
    {
144
162
      kdWarning(s_area) << "KoStore: Duplicate filename " << m_sName << endl;
 
163
      //return KIO::ERR_FILE_ALREADY_EXIST;
145
164
      return false;
146
165
    }
147
166
 
148
167
    m_strFiles.append( m_sName );
 
168
 
149
169
    m_iSize = 0;
 
170
    if ( !openWrite( m_sName ) )
 
171
      return false;
150
172
  }
151
173
  else if ( m_mode == Read )
152
174
  {
153
175
    kdDebug(s_area) << "Opening for reading '" << m_sName << "'" << endl;
154
 
 
155
 
    const KTarEntry * entry = m_pTar->directory()->entry( m_sName );
156
 
    if ( entry == 0L )
157
 
    {
158
 
      kdWarning(s_area) << "Unknown filename " << m_sName << endl;
159
 
      return false;
160
 
    }
161
 
    if ( entry->isDirectory() )
162
 
    {
163
 
      kdWarning(s_area) << m_sName << " is a directory !" << endl;
164
 
      return false;
165
 
    }
166
 
    KTarFile * f = (KTarFile *) entry;
167
 
    m_byteArray = f->data();
168
 
    // warning, m_byteArray can be bigger than f->data().size() (if a previous file was bigger)
169
 
    // this is why we never use m_byteArray.size()
170
 
    m_iSize = f->size();
 
176
    if ( !openRead( m_sName ) )
 
177
      return false;
171
178
  }
172
179
  else
173
 
    assert( 0 );
 
180
    //return KIO::ERR_UNSUPPORTED_ACTION;
 
181
    return false;
174
182
 
175
 
  m_stream = new QBuffer( m_byteArray );
176
 
  m_stream->open( (m_mode == Write) ? IO_WriteOnly : IO_ReadOnly );
177
183
  m_bIsOpen = true;
178
 
 
179
184
  return true;
180
185
}
181
186
 
182
 
void KoStore::close()
 
187
bool KoStore::isOpen() const
 
188
{
 
189
  return m_bIsOpen;
 
190
}
 
191
 
 
192
bool KoStore::close()
183
193
{
184
194
  kdDebug(s_area) << "KoStore: Closing" << endl;
185
195
 
186
196
  if ( !m_bIsOpen )
187
197
  {
188
198
    kdWarning(s_area) << "KoStore: You must open before closing" << endl;
189
 
    return;
190
 
  }
191
 
 
192
 
  if ( m_mode == Write )
193
 
  {
194
 
    // write the whole bytearray at once into the tar file
195
 
 
196
 
    kdDebug(s_area) << "Writing file " << m_sName << " into TAR archive. size "
197
 
                   << m_iSize << endl;
198
 
    m_pTar->writeFile( m_sName , "user", "group", m_iSize, m_byteArray.data() );
199
 
  }
 
199
    //return KIO::ERR_INTERNAL;
 
200
    return false;
 
201
  }
 
202
 
 
203
  bool ret = m_mode == Write ? closeWrite() : closeRead();
200
204
 
201
205
  delete m_stream;
202
206
  m_stream = 0L;
203
207
  m_bIsOpen = false;
 
208
  return ret;
 
209
}
 
210
 
 
211
QIODevice* KoStore::device() const
 
212
{
 
213
  if ( !m_bIsOpen )
 
214
    kdWarning(s_area) << "KoStore: You must open before asking for a device" << endl;
 
215
  if ( m_mode != Read )
 
216
    kdWarning(s_area) << "KoStore: Can not get device from store that is opened for writing" << endl;
 
217
  return m_stream;
204
218
}
205
219
 
206
220
QByteArray KoStore::read( unsigned long int max )
241
255
  return data;
242
256
}
243
257
 
244
 
long KoStore::read( char *_buffer, unsigned long _len )
 
258
Q_LONG KoStore::write( const QByteArray& data )
 
259
{
 
260
  return write( data.data(), data.size() ); // see below
 
261
}
 
262
 
 
263
Q_LONG KoStore::read( char *_buffer, Q_ULONG _len )
245
264
{
246
265
  if ( !m_bIsOpen )
247
266
  {
262
281
  if ( _len == 0 )
263
282
    return 0;
264
283
 
265
 
  m_stream->readBlock( _buffer, _len );
266
 
 
267
 
  return _len;
268
 
}
269
 
 
270
 
bool KoStore::embed( const QString &dest, KoStore &store, const QString &src )
271
 
{
272
 
  if ( dest == ROOTPART )
273
 
  {
274
 
    kdError(s_area) << "KoStore: cannot embed root part" << endl;
275
 
    return false;
276
 
  }
277
 
 
278
 
  // Find the destination directory corresponding to the part to be embedded.
279
 
 
280
 
  QString destDir;
281
 
 
282
 
  destDir = toExternalNaming( dest );
283
 
  if ( destDir.mid( destDir.length() - sizeof(MAINNAME) + 1 ) == MAINNAME )
284
 
  {
285
 
    destDir = destDir.left( destDir.length() - sizeof(MAINNAME) + 1 );
286
 
  }
287
 
  else
288
 
  {
289
 
    kdError(s_area) << "KoStore: cannot embed to a part called " << destDir << endl;
290
 
    return false;
291
 
  }
292
 
 
293
 
  // Find the source directory corresponding to the part to be embedded.
294
 
 
295
 
  QString srcDir;
296
 
 
297
 
  srcDir = store.toExternalNaming( src );
298
 
  if ( srcDir.mid( srcDir.length() - sizeof(MAINNAME) + 1 ) == MAINNAME )
299
 
  {
300
 
    srcDir = srcDir.left( srcDir.length() - sizeof(MAINNAME) + 1 );
301
 
  }
302
 
  else
303
 
  {
304
 
    kdError(s_area) << "KoStore: cannot embed from a part called " << srcDir << endl;
305
 
    return false;
306
 
  }
307
 
 
308
 
  // Now recurse into the embedded part, addings its top level contents to our tar.
309
 
 
310
 
  kdDebug(s_area) << "KoStore: embedding " << srcDir << " in " << destDir << endl;
311
 
  const KTarEntry *entry;
312
 
  if ( src == ROOTPART )
313
 
  {
314
 
    entry = store.m_pTar->directory();
315
 
  }
316
 
  else
317
 
  {
318
 
    entry = store.m_pTar->directory()->entry( srcDir );
319
 
  }
320
 
  QStringList entries = dynamic_cast<const KTarDirectory *>( entry )->entries();
321
 
  unsigned i;
322
 
 
323
 
  for ( i = 0; i < entries.count(); i++ )
324
 
  {
325
 
    if ( store.m_pTar->directory()->entry( srcDir + entries[i] )->isDirectory() )
326
 
    {
327
 
      // Recurse to get the files in the next level down.
328
 
 
329
 
      if ( embed( destDir + entries[i] + "/" + MAINNAME,
330
 
                  store,
331
 
                  srcDir + entries[i] + "/" + MAINNAME ) )
332
 
      {
333
 
        kdDebug(s_area) << "KoStore: embedded " << srcDir << " in " << destDir << endl;
334
 
      }
335
 
      else
336
 
      {
337
 
        break;
338
 
      }
339
 
    }
340
 
    else
341
 
    {
342
 
kdDebug(s_area) << "KoStore: is file " << endl;
343
 
      if ( ( open( destDir + entries[i] ) && store.open( srcDir + entries[i] ) ) )
344
 
      {
345
 
        kdDebug(s_area) << "KoStore: embedding file " << entries[i] << endl;
346
 
        long length = store.size();
347
 
        write( store.read( length ));
348
 
        store.close();
349
 
        close();
350
 
      }
351
 
      else
352
 
      {
353
 
        break;
354
 
      }
355
 
    }
356
 
  }
357
 
  return i == entries.count();
358
 
}
359
 
 
360
 
long KoStore::size() const
361
 
{
362
 
  if ( !m_bIsOpen )
363
 
  {
364
 
    kdWarning(s_area) << "KoStore: You must open before asking for a size" << endl;
365
 
    return -1;
366
 
  }
367
 
  if ( m_mode != Read )
368
 
  {
369
 
    kdWarning(s_area) << "KoStore: Can not get size from store that is opened for writing" << endl;
370
 
    return -1;
371
 
  }
372
 
  return (long) m_iSize;
373
 
}
374
 
 
375
 
bool KoStore::write( const QByteArray& data )
376
 
{
377
 
  unsigned int len = data.size();
378
 
  if ( len == 0L ) return true; // nothing to do
379
 
  return write( data.data(), len ); // see below
380
 
}
381
 
 
382
 
bool KoStore::write( const char* _data, unsigned long _len )
383
 
{
384
 
  if ( _len == 0L ) return true;
 
284
  return m_stream->readBlock( _buffer, _len );
 
285
}
 
286
 
 
287
Q_LONG KoStore::write( const char* _data, Q_ULONG _len )
 
288
{
 
289
  if ( _len == 0L ) return 0;
385
290
 
386
291
  if ( !m_bIsOpen )
387
292
  {
394
299
    return 0L;
395
300
  }
396
301
 
397
 
  m_stream->writeBlock( _data, _len );
398
 
  m_iSize += _len;
399
 
 
400
 
  return true;
401
 
}
402
 
 
403
 
bool KoStore::at( int pos )
 
302
  int nwritten = m_stream->writeBlock( _data, _len );
 
303
  Q_ASSERT( nwritten == (int)_len );
 
304
  m_iSize += nwritten;
 
305
 
 
306
  return nwritten;
 
307
}
 
308
 
 
309
QIODevice::Offset KoStore::size() const
 
310
{
 
311
  if ( !m_bIsOpen )
 
312
  {
 
313
    kdWarning(s_area) << "KoStore: You must open before asking for a size" << endl;
 
314
    return static_cast<QIODevice::Offset>(-1);
 
315
  }
 
316
  if ( m_mode != Read )
 
317
  {
 
318
    kdWarning(s_area) << "KoStore: Can not get size from store that is opened for writing" << endl;
 
319
    return static_cast<QIODevice::Offset>(-1);
 
320
  }
 
321
  return m_iSize;
 
322
}
 
323
 
 
324
bool KoStore::enterDirectory( const QString& directory )
 
325
{
 
326
  //kdDebug(s_area) << "KoStore::enterDirectory " << directory << endl;
 
327
  int pos;
 
328
  bool success = true;
 
329
  QString tmp( directory );
 
330
 
 
331
  while ( ( pos = tmp.find( '/' ) ) != -1 &&
 
332
          ( success = enterDirectoryInternal( tmp.left( pos ) ) ) )
 
333
          tmp = tmp.mid( pos + 1 );
 
334
 
 
335
  if ( success && !tmp.isEmpty() )
 
336
    return enterDirectoryInternal( tmp );
 
337
  return success;
 
338
}
 
339
 
 
340
bool KoStore::leaveDirectory()
 
341
{
 
342
  if ( m_currentPath.isEmpty() )
 
343
    return false;
 
344
 
 
345
  m_currentPath.pop_back();
 
346
 
 
347
  return enterAbsoluteDirectory( expandEncodedDirectory( currentPath() ) );
 
348
}
 
349
 
 
350
QString KoStore::currentPath() const
 
351
{
 
352
  QString path;
 
353
  QStringList::ConstIterator it = m_currentPath.begin();
 
354
  QStringList::ConstIterator end = m_currentPath.end();
 
355
  for ( ; it != end; ++it ) {
 
356
    path += *it;
 
357
    path += '/';
 
358
  }
 
359
  return path;
 
360
}
 
361
 
 
362
void KoStore::pushDirectory()
 
363
{
 
364
  m_directoryStack.push( currentPath() );
 
365
}
 
366
 
 
367
void KoStore::popDirectory()
 
368
{
 
369
  m_currentPath.clear();
 
370
  enterAbsoluteDirectory( QString::null );
 
371
  enterDirectory( m_directoryStack.pop() );
 
372
}
 
373
 
 
374
bool KoStore::addLocalFile( const QString &fileName, const QString &destName )
 
375
{
 
376
  QFileInfo fi( fileName );
 
377
  uint size = fi.size();
 
378
  QFile file( fileName );
 
379
  if ( !file.open( IO_ReadOnly ))
 
380
  {
 
381
    return false;
 
382
  }
 
383
 
 
384
  if ( !open ( destName ) )
 
385
  {
 
386
    return false;
 
387
  }
 
388
 
 
389
  QByteArray data ( 8 * 1024 );
 
390
 
 
391
  uint total = 0;
 
392
  for ( int block = 0; ( block = file.readBlock ( data.data(), data.size() ) ) > 0; total += block )
 
393
  {
 
394
    data.resize(block);
 
395
    if ( write( data ) != block )
 
396
      return false;
 
397
    data.resize(8*1024);
 
398
  }
 
399
  Q_ASSERT( total == size );
 
400
 
 
401
  close();
 
402
  file.close();
 
403
 
 
404
  return true;
 
405
}
 
406
 
 
407
bool KoStore::extractFile ( const QString &srcName, const QString &fileName )
 
408
{
 
409
  if ( !open ( srcName ) )
 
410
    return false;
 
411
 
 
412
  QFile file( fileName );
 
413
 
 
414
  if( !file.open ( IO_WriteOnly ) )
 
415
  {
 
416
    close();
 
417
    return false;
 
418
  }
 
419
 
 
420
  QByteArray data ( 8 * 1024 );
 
421
  uint total = 0;
 
422
  for( int block = 0; ( block = read ( data.data(), data.size() ) ) > 0; total += block )
 
423
  {
 
424
    file.writeBlock ( data.data(), block );
 
425
  }
 
426
 
 
427
  if( size() != static_cast<QIODevice::Offset>(-1) )
 
428
        Q_ASSERT( total == size() );
 
429
 
 
430
  file.close();
 
431
  close();
 
432
 
 
433
  return true;
 
434
}
 
435
 
 
436
QStringList KoStore::addLocalDirectory( const QString &dirPath, const QString &destName )
 
437
{
 
438
  QString dot = ".";
 
439
  QString dotdot = "..";
 
440
  QStringList content;
 
441
 
 
442
  QDir dir(dirPath);
 
443
  if ( !dir.exists() )
 
444
    return 0;
 
445
 
 
446
  QStringList files = dir.entryList();
 
447
  for ( QStringList::Iterator it = files.begin(); it != files.end(); ++it )
 
448
  {
 
449
     if ( *it != dot && *it != dotdot )
 
450
     {
 
451
        QString currentFile = dirPath + "/" + *it;
 
452
        QString dest = destName.isEmpty() ? *it : (destName + "/" + *it);
 
453
 
 
454
        QFileInfo fi ( currentFile );
 
455
        if ( fi.isFile() )
 
456
        {
 
457
          addLocalFile ( currentFile, dest );
 
458
          content.append(dest);
 
459
        }
 
460
        else if ( fi.isDir() )
 
461
        {
 
462
          content += addLocalDirectory ( currentFile, dest );
 
463
        }
 
464
     }
 
465
  }
 
466
 
 
467
  return content;
 
468
}
 
469
 
 
470
 
 
471
bool KoStore::at( QIODevice::Offset pos )
404
472
{
405
473
  return m_stream->at( pos );
406
474
}
407
475
 
408
 
int KoStore::at() const
 
476
QIODevice::Offset KoStore::at() const
409
477
{
410
478
  return m_stream->at();
411
479
}
414
482
{
415
483
  return m_stream->atEnd();
416
484
}
 
485
 
 
486
// See the specification for details of what this function does.
 
487
QString KoStore::toExternalNaming( const QString & _internalNaming )
 
488
{
 
489
  if ( _internalNaming == ROOTPART )
 
490
    return expandEncodedDirectory( currentPath() ) + MAINNAME;
 
491
 
 
492
  QString intern;
 
493
  if ( _internalNaming.startsWith( "tar:/" ) ) // absolute reference
 
494
    intern = _internalNaming.mid( 5 ); // remove protocol
 
495
  else
 
496
    intern = currentPath() + _internalNaming;
 
497
 
 
498
  return expandEncodedPath( intern );
 
499
}
 
500
 
 
501
QString KoStore::expandEncodedPath( QString intern )
 
502
{
 
503
  QString result;
 
504
  int pos;
 
505
 
 
506
  if ( ( pos = intern.findRev( '/', -1 ) ) != -1 ) {
 
507
    result = expandEncodedDirectory( intern.left( pos ) ) + '/';
 
508
    intern = intern.mid( pos + 1 );
 
509
  }
 
510
 
 
511
  // Now process the filename. If the first character is numeric, we have
 
512
  // a main document.
 
513
  if ( QChar(intern.at(0)).isDigit() )
 
514
  {
 
515
    // If this is the first part name, check if we have a store with
 
516
    // old-style names.
 
517
    if ( ( m_namingVersion == NAMING_VERSION_2_2 ) &&
 
518
         ( m_mode == Read ) &&
 
519
         ( fileExists( result + "part" + intern + ".xml" ) ) )
 
520
      m_namingVersion = NAMING_VERSION_2_1;
 
521
 
 
522
    if ( m_namingVersion == NAMING_VERSION_2_1 )
 
523
      result = result + "part" + intern + ".xml";
 
524
    else
 
525
      result = result + "part" + intern + "/" + MAINNAME;
 
526
  }
 
527
  else
 
528
    result += intern;
 
529
  return result;
 
530
}
 
531
 
 
532
QString KoStore::expandEncodedDirectory( QString intern )
 
533
{
 
534
  QString result;
 
535
  int pos;
 
536
  while ( ( pos = intern.find( '/' ) ) != -1 ) {
 
537
    if ( QChar(intern.at(0)).isDigit() )
 
538
      result += "part";
 
539
    result += intern.left( pos + 1 ); // copy numbers (or "pictures") + "/"
 
540
    intern = intern.mid( pos + 1 ); // remove the dir we just processed
 
541
  }
 
542
 
 
543
  if ( QChar(intern.at(0)).isDigit() )
 
544
    result += "part";
 
545
  result += intern;
 
546
  return result;
 
547
}
 
548
 
 
549
bool KoStore::enterDirectoryInternal( const QString& directory )
 
550
{
 
551
    if ( enterRelativeDirectory( expandEncodedDirectory( directory ) ) )
 
552
    {
 
553
      m_currentPath.append( directory );
 
554
      return true;
 
555
    }
 
556
    return false;
 
557
}