~ubuntu-branches/ubuntu/precise/koffice/precise

« back to all changes in this revision

Viewing changes to filters/kword/palmdoc/palmdb.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2010-09-21 15:36:35 UTC
  • mfrom: (1.4.1 upstream) (60.2.11 maverick)
  • Revision ID: james.westby@ubuntu.com-20100921153635-6tejqkiro2u21ydi
Tags: 1:2.2.2-0ubuntu3
Add kubuntu_03_fix-crash-on-closing-sqlite-connection-2.2.2.diff and
kubuntu_04_support-large-memo-values-for-msaccess-2.2.2.diff as
recommended by upstream http://kexi-
project.org/wiki/wikiview/index.php@Kexi2.2_Patches.html#sqlite_stab
ility

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
*/
19
19
 
20
20
/*
21
 
   The database layout for PalmDB files is described in 
 
21
   The database layout for PalmDB files is described in
22
22
   http://www.palmos.com/dev/support/docs/protein_books/FileFormats/Intro.html
23
23
*/
24
24
 
34
34
 
35
35
PalmDB::PalmDB()
36
36
{
37
 
  // some default values
38
 
  setName( "Unnamed" );
39
 
  setAttributes( 0 );
40
 
  setVersion( 0 );
41
 
  setCreationDate( QDateTime::currentDateTime() );
42
 
  setModificationDate( QDateTime::currentDateTime() );
43
 
  setLastBackupDate( QDateTime::currentDateTime() );
44
 
  setType( QString() );
45
 
  setCreator( QString() );
 
37
    // some default values
 
38
    setName("Unnamed");
 
39
    setAttributes(0);
 
40
    setVersion(0);
 
41
    setCreationDate(QDateTime::currentDateTime());
 
42
    setModificationDate(QDateTime::currentDateTime());
 
43
    setLastBackupDate(QDateTime::currentDateTime());
 
44
    setType(QString());
 
45
    setCreator(QString());
46
46
 
47
47
}
48
48
 
49
49
PalmDB::~PalmDB()
50
50
{
51
 
    while(!records.isEmpty()) delete records.takeFirst();
52
 
  records.clear();
 
51
    while (!records.isEmpty()) delete records.takeFirst();
 
52
    records.clear();
53
53
}
54
54
 
55
 
bool PalmDB::load( const char* filename )
 
55
bool PalmDB::load(const char* filename)
56
56
{
57
 
  // open input file
58
 
  QFile in (filename);
59
 
  if (!in.open (QIODevice::ReadOnly))
60
 
    return false;
61
 
 
62
 
  QDataStream stream;
63
 
  stream.setDevice (&in);
64
 
 
65
 
  unsigned filesize = stream.device()->size();
66
 
  if( filesize < 72 ) return false;
67
 
 
68
 
  // always big-endian
69
 
  stream.setByteOrder (QDataStream::BigEndian);
70
 
 
71
 
  // now start to read PDB header (72 bytes)
72
 
 
73
 
  // read and encode database name
74
 
  // The name field is 32 bytes long, and is NUL terminated.
75
 
  // Use the length parameter of fromLatin1() anyway.
76
 
  quint8 name[32];
77
 
  for(int k = 0; k < 32; k++)
78
 
    stream >> name[k];
79
 
  m_name = QString::fromLatin1( (char*) name, 31 );
80
 
 
81
 
  // read database attribute
82
 
  quint16 attr;
83
 
  stream >> attr;
84
 
  m_attributes = attr;
85
 
 
86
 
  // read database version (app-specific)
87
 
  quint16 ver;
88
 
  stream >> ver;
89
 
  m_version = ver;
90
 
 
91
 
  // NOTE: PDB specifies date as number of seconds since 1 Jan 1904
92
 
  // QDateTime::setTime_t expects number of seconds since 1 Jan 1970
93
 
  // so, we make adjustment with a constant offset of 2082844800
94
 
  const int adjust = 2082844800;
95
 
 
96
 
  // read creation date
97
 
  quint32 creation;
98
 
  stream >> creation;
99
 
  m_creationDate.setTime_t( creation - adjust );
100
 
 
101
 
  // read modification date
102
 
  quint32 modification;
103
 
  stream >> modification;
104
 
  m_modificationDate.setTime_t( modification - adjust );
105
 
 
106
 
  // read last backup date
107
 
  quint32 lastbackup;
108
 
  stream >> lastbackup;
109
 
  m_lastBackupDate.setTime_t( lastbackup - adjust );
110
 
 
111
 
  // read modification number
112
 
  quint32 modnum;
113
 
  stream >> modnum;
114
 
 
115
 
  // read app info id and sort info id
116
 
  quint32 appid, sortid;
117
 
  stream >> appid;
118
 
  stream >> sortid;
119
 
 
120
 
  // read and encode database type
121
 
  quint8 dbt[4];
122
 
  stream >> dbt[0] >> dbt[1] >> dbt[2] >> dbt[3];
123
 
  m_type = QString::fromLatin1( (char*) dbt, 4 );
124
 
 
125
 
  // read and encode database creator
126
 
  quint8 dbc[4];
127
 
  stream >> dbc[0] >> dbc[1] >> dbc[2] >> dbc[3];
128
 
  m_creator = QString::fromLatin1( (char*) dbc, 4 );
129
 
 
130
 
  // read unique id seed
131
 
  quint32 idseed;
132
 
  stream >> idseed;
133
 
  m_uniqueIDSeed = idseed;
134
 
 
135
 
  // now start to read PDB record list (variable-length)
136
 
 
137
 
  // next record list
138
 
  // FIXME what to do with this ?
139
 
  quint32 nextlist;
140
 
  stream >> nextlist;
141
 
 
142
 
  // number of records
143
 
  quint16 numrec;
144
 
  stream >> numrec;
145
 
 
146
 
  // read entries in record list
147
 
  // find out location and size of each record
148
 
  QVector<unsigned> recpos( numrec );
149
 
  QVector<int> recsize( numrec );
150
 
 
151
 
  // FIXME any other better way to find record size ?
152
 
  for( int r = 0; r < numrec; r++ )
153
 
  {
154
 
    quint32 pos;
155
 
    quint8 flag, dummy;
156
 
    stream >> pos >> flag >> dummy >> dummy >> dummy;
157
 
    recpos[r] = pos; recsize[r] = filesize - pos;
158
 
    if( r> 0 ) recsize[r-1] = pos - recpos[r-1]; // fixup
159
 
  }
160
 
 
161
 
  // debugging
 
57
    // open input file
 
58
    QFile in(filename);
 
59
    if (!in.open(QIODevice::ReadOnly))
 
60
        return false;
 
61
 
 
62
    QDataStream stream;
 
63
    stream.setDevice(&in);
 
64
 
 
65
    unsigned filesize = stream.device()->size();
 
66
    if (filesize < 72) return false;
 
67
 
 
68
    // always big-endian
 
69
    stream.setByteOrder(QDataStream::BigEndian);
 
70
 
 
71
    // now start to read PDB header (72 bytes)
 
72
 
 
73
    // read and encode database name
 
74
    // The name field is 32 bytes long, and is NUL terminated.
 
75
    // Use the length parameter of fromLatin1() anyway.
 
76
    quint8 name[32];
 
77
    for (int k = 0; k < 32; k++)
 
78
        stream >> name[k];
 
79
    m_name = QString::fromLatin1((char*) name, 31);
 
80
 
 
81
    // read database attribute
 
82
    quint16 attr;
 
83
    stream >> attr;
 
84
    m_attributes = attr;
 
85
 
 
86
    // read database version (app-specific)
 
87
    quint16 ver;
 
88
    stream >> ver;
 
89
    m_version = ver;
 
90
 
 
91
    // NOTE: PDB specifies date as number of seconds since 1 Jan 1904
 
92
    // QDateTime::setTime_t expects number of seconds since 1 Jan 1970
 
93
    // so, we make adjustment with a constant offset of 2082844800
 
94
    const int adjust = 2082844800;
 
95
 
 
96
    // read creation date
 
97
    quint32 creation;
 
98
    stream >> creation;
 
99
    m_creationDate.setTime_t(creation - adjust);
 
100
 
 
101
    // read modification date
 
102
    quint32 modification;
 
103
    stream >> modification;
 
104
    m_modificationDate.setTime_t(modification - adjust);
 
105
 
 
106
    // read last backup date
 
107
    quint32 lastbackup;
 
108
    stream >> lastbackup;
 
109
    m_lastBackupDate.setTime_t(lastbackup - adjust);
 
110
 
 
111
    // read modification number
 
112
    quint32 modnum;
 
113
    stream >> modnum;
 
114
 
 
115
    // read app info id and sort info id
 
116
    quint32 appid, sortid;
 
117
    stream >> appid;
 
118
    stream >> sortid;
 
119
 
 
120
    // read and encode database type
 
121
    quint8 dbt[4];
 
122
    stream >> dbt[0] >> dbt[1] >> dbt[2] >> dbt[3];
 
123
    m_type = QString::fromLatin1((char*) dbt, 4);
 
124
 
 
125
    // read and encode database creator
 
126
    quint8 dbc[4];
 
127
    stream >> dbc[0] >> dbc[1] >> dbc[2] >> dbc[3];
 
128
    m_creator = QString::fromLatin1((char*) dbc, 4);
 
129
 
 
130
    // read unique id seed
 
131
    quint32 idseed;
 
132
    stream >> idseed;
 
133
    m_uniqueIDSeed = idseed;
 
134
 
 
135
    // now start to read PDB record list (variable-length)
 
136
 
 
137
    // next record list
 
138
    // FIXME what to do with this ?
 
139
    quint32 nextlist;
 
140
    stream >> nextlist;
 
141
 
 
142
    // number of records
 
143
    quint16 numrec;
 
144
    stream >> numrec;
 
145
 
 
146
    // read entries in record list
 
147
    // find out location and size of each record
 
148
    QVector<unsigned> recpos(numrec);
 
149
    QVector<int> recsize(numrec);
 
150
 
 
151
    // FIXME any other better way to find record size ?
 
152
    for (int r = 0; r < numrec; r++) {
 
153
        quint32 pos;
 
154
        quint8 flag, dummy;
 
155
        stream >> pos >> flag >> dummy >> dummy >> dummy;
 
156
        recpos[r] = pos; recsize[r] = filesize - pos;
 
157
        if (r > 0) recsize[r-1] = pos - recpos[r-1]; // fixup
 
158
    }
 
159
 
 
160
    // debugging
162
161
#ifdef PDB_DEBUG
163
 
  qDebug( "name: \"%s\"", m_name.latin1() );
164
 
  qDebug( "type: \"%s\"", m_type.latin1() );
165
 
  qDebug( "creator: \"%s\"", m_creator.latin1() );
166
 
  qDebug( "attributes: 0x%04X", m_attributes );
167
 
  qDebug( "version: 0x%04X", m_version );
168
 
  qDebug( "creation date: %s", m_creationDate.toString().latin1() );
169
 
  qDebug( "modification date: %s", m_modificationDate.toString().latin1() );
170
 
  qDebug( "last backup date: %s", m_lastBackupDate.toString().latin1() );
171
 
  qDebug( "number of records: %d", numrec );
172
 
  for( int r = 0; r < numrec; r++ )
173
 
    qDebug( "  rec %d at 0x%X size %d", r, recpos[r], recsize[r] );
 
162
    qDebug("name: \"%s\"", qPrintable(m_name));
 
163
    qDebug("type: \"%s\"", qPrintable(m_type));
 
164
    qDebug("creator: \"%s\"", qPrintable(m_creator));
 
165
    qDebug("attributes: 0x%04X", m_attributes);
 
166
    qDebug("version: 0x%04X", m_version);
 
167
    qDebug("creation date: %s", qPrintable(m_creationDate.toString()));
 
168
    qDebug("modification date: %s", qPrintable(m_modificationDate.toString()));
 
169
    qDebug("last backup date: %s", qPrintable(m_lastBackupDate.toString()));
 
170
    qDebug("number of records: %d", numrec);
 
171
    for (int r = 0; r < numrec; r++)
 
172
        qDebug("  rec %d at 0x%X size %d", r, recpos[r], recsize[r]);
174
173
#endif
175
174
 
176
 
  // load all records
177
 
  records.clear();
178
 
  for( int r = 0; r < numrec; r++ )
179
 
  {
180
 
    QByteArray* data = new QByteArray;
 
175
    // load all records
 
176
    records.clear();
 
177
    for (int r = 0; r < numrec; r++) {
 
178
        QByteArray* data = new QByteArray;
181
179
 
182
 
    if( recpos[r] < filesize )
183
 
      if( recsize[r] >= 0 )
184
 
        {
185
 
          data->resize( recsize[r] );
186
 
          stream.device()->at( recpos[r] );
 
180
        if (recpos[r] < filesize)
 
181
            if (recsize[r] >= 0) {
 
182
                data->resize(recsize[r]);
 
183
                stream.device()->at(recpos[r]);
187
184
#ifdef __GNUC__
188
185
# warning "kde4 port it"
189
186
#endif
190
 
          //for( int q = 0; q < recsize[r]; q++ )
191
 
            //{ quint8 c; stream >> c; data->at(q) = c; }
 
187
                //for( int q = 0; q < recsize[r]; q++ )
 
188
                //{ quint8 c; stream >> c; data->at(q) = c; }
 
189
            }
 
190
        records.append(data);
 
191
    }
 
192
 
 
193
    // close input file
 
194
    in.close();
 
195
 
 
196
    return true;
 
197
}
 
198
 
 
199
bool PalmDB::save(const char* filename)
 
200
{
 
201
    // open output file
 
202
    QFile out(filename);
 
203
    if (!out.open(QIODevice::WriteOnly))
 
204
        return false;
 
205
 
 
206
    QDataStream stream;
 
207
    stream.setDevice(&out);
 
208
 
 
209
    // always big-endian
 
210
    stream.setByteOrder(QDataStream::BigEndian);
 
211
 
 
212
    // now write PDB header (72 bytes)
 
213
 
 
214
    // write database name
 
215
    setName(name());
 
216
    const char *dbname = m_name.toLatin1();
 
217
    for (unsigned k = 0; k < 31; k++) {
 
218
        quint8 c = (k < m_name.length()) ? dbname[k] : 0;
 
219
        stream << c;
 
220
    }
 
221
    {
 
222
        // NUL-terminate the database name
 
223
        quint8 c = 0;
 
224
        stream << c;
 
225
    }
 
226
 
 
227
 
 
228
 
 
229
    // write database attribute
 
230
    quint16 attr = m_attributes;
 
231
    stream << attr;
 
232
 
 
233
    // write database version (app-specific)
 
234
    quint16 ver = m_version;
 
235
    stream << ver;
 
236
 
 
237
    // reference date is 1 Jan 1904
 
238
    // see also note in function load() above
 
239
    QDateTime ref = QDateTime(QDate(1904, 1, 1));
 
240
 
 
241
    // write creation date
 
242
    quint32 creation = -m_creationDate.secsTo(ref);
 
243
    stream << creation;
 
244
 
 
245
    // write modification date
 
246
    quint32 modification = -m_modificationDate.secsTo(ref);
 
247
    stream << modification;
 
248
 
 
249
    // write last backup date
 
250
    quint32 lastbackup = -m_lastBackupDate.secsTo(ref);
 
251
    stream << lastbackup;
 
252
 
 
253
    // write modification number
 
254
    quint32 modnum = 0;
 
255
    stream << modnum;
 
256
 
 
257
    // write app info id and sort info id
 
258
    quint32 appid = 0, sortid = 0;
 
259
    stream << appid;
 
260
    stream << sortid;
 
261
 
 
262
    // write and encode database type
 
263
    quint8 dbt[4];
 
264
    const char *dbtype = m_type.toLatin1();
 
265
    for (int p = 0; p < 4; p++) dbt[p] = dbtype[p];
 
266
    stream << dbt[0] << dbt[1] << dbt[2] << dbt[3];
 
267
 
 
268
    // write and encode database creator
 
269
    quint8 dbc[4];
 
270
    const char *dbcreator = m_creator.toLatin1();
 
271
    for (int p = 0; p < 4; p++) dbc[p] = dbcreator[p];
 
272
    stream << dbc[0] << dbc[1] << dbc[2] << dbc[3];
 
273
 
 
274
    // write unique id seed
 
275
    quint32 idseed = 0;
 
276
    stream << idseed;
 
277
 
 
278
    // now start to read PDB record list (variable-length)
 
279
 
 
280
    // next record list
 
281
    quint32 nextlist = 0;
 
282
    stream << nextlist;
 
283
 
 
284
    // number of records
 
285
    quint16 numrec = records.count();
 
286
    stream << numrec;
 
287
 
 
288
    // where is the first record ?
 
289
    // 78 is size of PDB header, 2 is filler before data
 
290
    quint32 pos = 78 + 2;
 
291
    pos += records.count() * 8;
 
292
 
 
293
    // write record list
 
294
    for (unsigned r = 0; r < records.count(); r++) {
 
295
        quint8 flag = 0, dummy = 0;
 
296
        stream << pos;
 
297
        stream << flag;
 
298
        stream  << dummy << dummy << dummy;
 
299
        pos += records.at(r)->count();
 
300
    }
 
301
 
 
302
    // write 2-byte dummy
 
303
    quint16 filler = 0;
 
304
    stream << filler;
 
305
 
 
306
    // write all records
 
307
    for (unsigned r = 0; r < records.count(); r++) {
 
308
        QByteArray *data = records.at(r);
 
309
        if (!data) continue;
 
310
        for (unsigned j = 0; j < data->count(); j++) {
 
311
            quint8 c = data->at(j);
 
312
            stream << c;
192
313
        }
193
 
    records.append( data );
194
 
  }
195
 
 
196
 
  // close input file
197
 
  in.close();
198
 
 
199
 
  return true;
200
 
}
201
 
 
202
 
bool PalmDB::save( const char* filename )
203
 
{
204
 
  // open output file
205
 
  QFile out( filename );
206
 
  if( !out.open( QIODevice::WriteOnly ) )
207
 
    return false;
208
 
 
209
 
  QDataStream stream;
210
 
  stream.setDevice( &out );
211
 
 
212
 
  // always big-endian
213
 
  stream.setByteOrder (QDataStream::BigEndian);
214
 
 
215
 
  // now write PDB header (72 bytes)
216
 
 
217
 
  // write database name
218
 
  setName( name() );
219
 
  const char *dbname = m_name.latin1();
220
 
  for( unsigned k=0; k<31; k++ )
221
 
  {
222
 
    quint8 c = (k<m_name.length()) ? dbname[k] : 0;
223
 
    stream << c;
224
 
  }
225
 
  {
226
 
    // NUL-terminate the database name
227
 
    quint8 c = 0;
228
 
    stream << c;
229
 
  }
230
 
 
231
 
 
232
 
 
233
 
  // write database attribute
234
 
  quint16 attr = m_attributes;
235
 
  stream << attr;
236
 
 
237
 
  // write database version (app-specific)
238
 
  quint16 ver = m_version;
239
 
  stream << ver;
240
 
 
241
 
  // reference date is 1 Jan 1904
242
 
  // see also note in function load() above
243
 
  QDateTime ref = QDateTime(QDate( 1904, 1, 1) );
244
 
 
245
 
  // write creation date
246
 
  quint32 creation = -m_creationDate.secsTo( ref );
247
 
  stream << creation;
248
 
 
249
 
  // write modification date
250
 
  quint32 modification = -m_modificationDate.secsTo( ref );
251
 
  stream << modification;
252
 
 
253
 
  // write last backup date
254
 
  quint32 lastbackup = -m_lastBackupDate.secsTo( ref );
255
 
  stream << lastbackup;
256
 
 
257
 
  // write modification number
258
 
  quint32 modnum = 0;
259
 
  stream << modnum;
260
 
 
261
 
  // write app info id and sort info id
262
 
  quint32 appid = 0, sortid = 0;
263
 
  stream << appid;
264
 
  stream << sortid;
265
 
 
266
 
  // write and encode database type
267
 
  quint8 dbt[4];
268
 
  const char *dbtype = m_type.latin1();
269
 
  for( int p=0; p<4; p++ ) dbt[p]=dbtype[p];
270
 
  stream << dbt[0] << dbt[1] << dbt[2] << dbt[3];
271
 
 
272
 
  // write and encode database creator
273
 
  quint8 dbc[4];
274
 
  const char *dbcreator = m_creator.latin1();
275
 
  for( int p=0; p<4; p++ ) dbc[p]=dbcreator[p];
276
 
  stream << dbc[0] << dbc[1] << dbc[2] << dbc[3];
277
 
 
278
 
  // write unique id seed
279
 
  quint32 idseed = 0;
280
 
  stream << idseed;
281
 
 
282
 
  // now start to read PDB record list (variable-length)
283
 
 
284
 
  // next record list
285
 
  quint32 nextlist = 0;
286
 
  stream << nextlist;
287
 
 
288
 
  // number of records
289
 
  quint16 numrec = records.count();
290
 
  stream << numrec;
291
 
 
292
 
  // where is the first record ?
293
 
  // 78 is size of PDB header, 2 is filler before data
294
 
  quint32 pos = 78 + 2;
295
 
  pos += records.count()*8;
296
 
 
297
 
  // write record list
298
 
  for( unsigned r = 0; r < records.count(); r++ )
299
 
  {
300
 
    quint8 flag = 0, dummy = 0;
301
 
    stream << pos;
302
 
    stream << flag;
303
 
    stream  << dummy << dummy << dummy;
304
 
    pos += records.at(r)->count();
305
 
  }
306
 
 
307
 
  // write 2-byte dummy
308
 
  quint16 filler = 0;
309
 
  stream << filler;
310
 
 
311
 
  // write all records
312
 
  for( unsigned r = 0; r < records.count(); r++ )
313
 
  {
314
 
    QByteArray *data = records.at( r );
315
 
    if( !data ) continue;
316
 
    for( unsigned j=0; j<data->count(); j++ )
317
 
      {
318
 
        quint8 c = data->at( j ); 
319
 
        stream << c;  
320
 
      }
321
 
  }
322
 
 
323
 
  // close output file
324
 
  out.close();
325
 
 
326
 
  return true;
327
 
}
328
 
 
329
 
void PalmDB::setType( const QString& t )
330
 
{
331
 
  m_type = t;
332
 
  if( m_type.length() > 4 )
333
 
    m_type = m_type.left( 4 );
334
 
  while( m_type.length() < 4 )
335
 
    m_type.append( 32 );
336
 
}
337
 
 
338
 
 
339
 
void PalmDB::setCreator( const QString& c )
340
 
{
341
 
  m_creator = c;
342
 
  if( m_creator.length() > 4 )
343
 
    m_type = m_creator.left( 4 );
344
 
  while( m_creator.length() < 4 )
345
 
    m_creator.append( 32 );
 
314
    }
 
315
 
 
316
    // close output file
 
317
    out.close();
 
318
 
 
319
    return true;
 
320
}
 
321
 
 
322
void PalmDB::setType(const QString& t)
 
323
{
 
324
    m_type = t;
 
325
    if (m_type.length() > 4)
 
326
        m_type = m_type.left(4);
 
327
    while (m_type.length() < 4)
 
328
        m_type.append(32);
 
329
}
 
330
 
 
331
 
 
332
void PalmDB::setCreator(const QString& c)
 
333
{
 
334
    m_creator = c;
 
335
    if (m_creator.length() > 4)
 
336
        m_type = m_creator.left(4);
 
337
    while (m_creator.length() < 4)
 
338
        m_creator.append(32);
346
339
}