1Palm::PDB(3) User Contributed Perl Documentation Palm::PDB(3)
2
3
4
6 Palm::PDB - Parse Palm database files
7
9 This document describes version 1.400 of Palm::PDB, released March 7,
10 2015 as part of Palm-PDB version 1.400.
11
13 use Palm::PDB;
14 use SomeHelperClass;
15
16 $pdb = Palm::PDB->new;
17 $pdb->Load("myfile.pdb");
18
19 # Manipulate records in $pdb
20
21 $pdb->Write("myotherfile.pdb");
22
23 (Note: yes, you do want to use "Palm::PDB", even if you're dealing with
24 some other type of database. $pdb will be reblessed to the appropriate
25 type by "$pdb->Load".)
26
28 The Palm::PDB module provides a framework for reading and writing
29 database files for use on PalmOS devices such as the PalmPilot. It can
30 read and write both Palm Database (".pdb") and Palm Resource (".prc")
31 files.
32
33 By itself, the PDB module is not terribly useful; it is intended to be
34 used in conjunction with supplemental modules for specific types of
35 databases, such as Palm::Raw or Palm::Memo.
36
37 The Palm::PDB module encapsulates the common work of parsing the
38 structure of a Palm database. The Load() function reads the file, then
39 passes the individual chunks (header, records, etc.) to application-
40 specific functions for processing. Similarly, the Write() function
41 calls application-specific functions to get the individual chunks, then
42 writes them to a file.
43
45 new
46 $new = Palm::PDB->new;
47
48 Creates a new PDB. $new is a reference to an anonymous hash. Some of
49 its elements have special significance. See Load().
50
51 RegisterPDBHandlers
52 &Palm::PDB::RegisterPDBHandlers("classname", typespec...);
53
54 Typically:
55
56 &Palm::PDB::RegisterPDBHandlers(__PACKAGE__,
57 [ "FooB", "DATA" ],
58 );
59
60 The $pdb->Load() method acts as a virtual constructor. When it reads
61 the header of a ".pdb" file, it looks up the file's creator and type in
62 a set of tables, and reblesses $pdb into a class capable of parsing the
63 application-specific parts of the file (AppInfo block, records, etc.)
64
65 RegisterPDBHandlers() adds entries to these tables; it says that any
66 file whose creator and/or type match any of the typespecs (there may be
67 several) should be reblessed into the class classname.
68
69 Note that RegisterPDBHandlers() applies only to record databases
70 (".pdb" files). For resource databases, see RegisterPRCHandlers().
71
72 RegisterPDBHandlers() is typically called in the import() function of a
73 helper class. In this case, the class is registering itself, and it is
74 simplest just to use "__PACKAGE__" for the package name:
75
76 package PalmFoo;
77 use Palm::PDB;
78
79 sub import
80 {
81 &Palm::PDB::RegisterPDBHandlers(__PACKAGE__,
82 [ "FooZ", "DATA" ]
83 );
84 }
85
86 A typespec can be either a string, or an anonymous array with two
87 elements. If it is an anonymous array, then the first element is the
88 file's creator; the second element is its type. If a typespec is a
89 string, it is equivalent to specifying that string as the database's
90 creator, and a wildcard as its type.
91
92 The creator and type should be either four-character strings, or the
93 empty string. An empty string represents a wildcard. Thus:
94
95 &Palm::PDB::RegisterPDBHandlers("MyClass",
96 [ "fOOf", "DATA" ],
97 [ "BarB", "" ],
98 [ "", "BazQ" ],
99 "Fred"
100 );
101
102 Class MyClass will handle:
103
104 • Databases whose creator is "fOOf" and whose type is "DATA".
105
106 • Databases whose creator is "BarB", of any type.
107
108 • Databases with any creator whose type is "BazQ".
109
110 • Databases whose creator is "Fred", of any type.
111
112 RegisterPRCHandlers
113 &Palm::PDB::RegisterPRCHandlers("classname", typespec...);
114
115 Typically:
116
117 &Palm::PDB::RegisterPRCHandlers(__PACKAGE__,
118 [ "FooZ", "CODE" ],
119 );
120
121 RegisterPRCHandlers() is similar to RegisterPDBHandlers(), but
122 specifies a class to handle resource database (".prc") files.
123
124 A class for parsing applications should begin with:
125
126 package PalmApps;
127 use Palm::PDB;
128
129 sub import
130 {
131 &Palm::PDB::RegisterPRCHandlers(__PACKAGE__,
132 [ "", "appl" ]
133 );
134 }
135
136 Load
137 $pdb->Load($filename);
138
139 Reads the file $filename, parses it, reblesses $pdb to the appropriate
140 class, and invokes appropriate methods to parse the application-
141 specific parts of the database (see "HELPER CLASS METHODS").
142
143 $filename may also be an open file handle (as long as it's seekable).
144 This allows for manipulating databases in memory structures.
145
146 Load() uses the typespecs given to RegisterPDBHandlers() and
147 RegisterPRCHandlers() when deciding how to rebless $pdb. For record
148 databases, it uses the typespecs passed to RegisterPDBHandlers(), and
149 for resource databases, it uses the typespecs passed to
150 RegisterPRCHandlers().
151
152 Load() looks for matching typespecs in the following order, from most
153 to least specific:
154
155 1. A typespec that specifies both the database's creator and its type
156 exactly.
157
158 2. A typespec that specifies the database's type and has a wildcard
159 for the creator (this is rarely used).
160
161 3. A typespec that specifies the database's creator and has a wildcard
162 for the type.
163
164 4. A typespec that has wildcards for both the creator and type.
165
166 Thus, if the database has creator "FooZ" and type "DATA", Load() will
167 first look for "FooZ"/"DATA", then ""/"DATA", then "FooZ"/"", and
168 finally will fall back on ""/"" (the universal default).
169
170 After Load() returns, $pdb may contain the following fields:
171
172 $pdb->{"name"}
173 The name of the database.
174
175 $pdb->{"attributes"}{"ResDB"}
176 $pdb->{"attributes"}{"ReadOnly"}
177 $pdb->{"attributes"}{"AppInfoDirty"}
178 $pdb->{"attributes"}{"Backup"}
179 $pdb->{"attributes"}{"OKToInstallNewer"}
180 $pdb->{"attributes"}{"ResetAfterInstall"}
181 $pdb->{"attributes"}{"CopyPrevention"}
182 $pdb->{"attributes"}{"Stream"}
183 $pdb->{"attributes"}{"Hidden"}
184 $pdb->{"attributes"}{"LaunchableData"}
185 $pdb->{"attributes"}{"Recyclable"}
186 $pdb->{"attributes"}{"Bundle"}
187 $pdb->{"attributes"}{"Open"}
188 These are the attribute flags from the database header. Each is
189 true iff the corresponding flag is set.
190
191 The "LaunchableData" attribute is set on PQAs.
192
193 $pdb->{"version"}
194 The database's version number. An integer.
195
196 $pdb->{"ctime"}
197 $pdb->{"mtime"}
198 $pdb->{"baktime"}
199 The database's creation time, last modification time, and time of
200 last backup, in Unix "time_t" format (seconds since Jan. 1, 1970).
201
202 $pdb->{"modnum"}
203 The database's modification number. An integer.
204
205 $pdb->{"type"}
206 The database's type. A four-character string.
207
208 $pdb->{"creator"}
209 The database's creator. A four-character string.
210
211 $pdb->{"uniqueIDseed"}
212 The database's unique ID seed. An integer.
213
214 $pdb->{"2NULs"}
215 The two NUL bytes that appear after the record index and the
216 AppInfo block. Included here because every once in a long while,
217 they are not NULs, for some reason.
218
219 $pdb->{"appinfo"}
220 The AppInfo block, as returned by the $pdb->ParseAppInfoBlock()
221 helper method.
222
223 $pdb->{"sort"}
224 The sort block, as returned by the $pdb->ParseSortBlock() helper
225 method.
226
227 @{$pdb->{"records"}}
228 The list of records in the database, as returned by the
229 $pdb->ParseRecord() helper method. Resource databases do not have
230 this.
231
232 @{$pdb->{"resources"}}
233 The list of resources in the database, as returned by the
234 $pdb->ParseResource() helper method. Record databases do not have
235 this.
236
237 All of these fields may be set by hand, but should conform to the
238 format given above.
239
240 Write
241 $pdb->Write($filename);
242
243 Invokes methods in helper classes to get the application-specific parts
244 of the database, then writes the database to the file $filename.
245
246 $filename may also be an open file handle (as long as it's seekable).
247 This allows for manipulating databases in memory structures.
248
249 Write() uses the following helper methods:
250
251 PackAppInfoBlock()
252 PackSortBlock()
253 PackResource() or PackRecord()
254
255 See also "HELPER CLASS METHODS".
256
257 new_Record
258 $record = Palm::PDB->new_Record();
259
260 Creates a new record, with the bare minimum needed:
261
262 $record->{'category'}
263 $record->{'attributes'}{'Dirty'}
264 $record->{'id'}
265
266 The ``Dirty'' attribute is originally set, since this function will
267 usually be called to create records to be added to a database.
268
269 "new_Record" does not add the new record to a PDB. For that, you want
270 "append_Record".
271
272 is_Dirty
273 $pdb->Write( $fname ) if $pdb->is_Dirty();
274
275 Returns non-zero if any of the in-memory elements of the database have
276 been changed. This includes changes via function calls (any call that
277 changes the $pdb's "last modification" time) as well as testing the
278 "dirty" status of attributes where possible (i.e. AppInfo, records, but
279 not resource entries).
280
281 append_Record
282 $record = $pdb->append_Record;
283 $record2 = $pdb->append_Record($record1);
284
285 If called without any arguments, creates a new record with
286 new_Record(), and appends it to $pdb.
287
288 If given a reference to a record, appends that record to
289 @{$pdb->{records}}.
290
291 Returns a reference to the newly-appended record.
292
293 This method updates $pdb's "last modification" time.
294
295 new_Resource
296 $resource = Palm::PDB->new_Resource();
297
298 Creates a new resource and initializes
299
300 $resource->{type}
301 $resource->{id}
302
303 append_Resource
304 $resource = $pdb->append_Resource;
305 $resource2 = $pdb->append_Resource($resource1);
306
307 If called without any arguments, creates a new resource with
308 new_Resource(), and appends it to $pdb.
309
310 If given a reference to a resource, appends that resource to
311 @{$pdb->{resources}}.
312
313 Returns a reference to the newly-appended resource.
314
315 This method updates $pdb's "last modification" time.
316
317 findRecordByID
318 $record = $pdb->findRecordByID($id);
319
320 Looks through the list of records in $pdb, and returns a reference to
321 the record with ID $id, or the undefined value if no such record was
322 found.
323
324 delete_Record
325 $pdb->delete_Record($record, $expunge);
326
327 Marks $record for deletion, so that it will be deleted from the
328 database at the next sync.
329
330 If $expunge is false or omitted, the record will be marked for deletion
331 with archival. If $expunge is true, the record will be marked for
332 deletion without archival.
333
334 This method updates $pdb's "last modification" time.
335
336 remove_Record
337 for (@{ $pdb->{'records'} })
338 {
339 $pdb->remove_Record( $_ ) if $_->{attributes}{deleted};
340 }
341
342 Removes $record from the database. This differs from "delete_Record" in
343 that it's an actual deletion rather than just setting a flag.
344
345 This method updates $pdb's "last modification" time.
346
348 "$pdb->Load()" reblesses $pdb into a new class. This helper class is
349 expected to convert raw data from the database into parsed
350 representations of it, and vice-versa.
351
352 A helper class must have all of the methods listed below. The Palm::Raw
353 class is useful if you don't want to define all of the required
354 methods.
355
356 ParseAppInfoBlock
357 $appinfo = $pdb->ParseAppInfoBlock($buf);
358
359 $buf is a string of raw data. ParseAppInfoBlock() should parse this
360 data and return it, typically in the form of a reference to an object
361 or to an anonymous hash.
362
363 This method will not be called if the database does not have an AppInfo
364 block.
365
366 The return value from ParseAppInfoBlock() will be accessible as
367 "$pdb->{appinfo}".
368
369 PackAppInfoBlock
370 $buf = $pdb->PackAppInfoBlock();
371
372 This is the converse of ParseAppInfoBlock(). It takes $pdb's AppInfo
373 block, "$pdb->{appinfo}", and returns a string of binary data that can
374 be written to the database file.
375
376 ParseSortBlock
377 $sort = $pdb->ParseSortBlock($buf);
378
379 $buf is a string of raw data. ParseSortBlock() should parse this data
380 and return it, typically in the form of a reference to an object or to
381 an anonymous hash.
382
383 This method will not be called if the database does not have a sort
384 block.
385
386 The return value from ParseSortBlock() will be accessible as
387 "$pdb->{sort}".
388
389 PackSortBlock
390 $buf = $pdb->PackSortBlock();
391
392 This is the converse of ParseSortBlock(). It takes $pdb's sort block,
393 "$pdb->{sort}", and returns a string of raw data that can be written to
394 the database file.
395
396 ParseRecord
397 $record = $pdb->ParseRecord(
398 offset => $offset, # Record's offset in file
399 attributes => # Record attributes
400 {
401 expunged => bool, # True iff expunged
402 dirty => bool, # True iff dirty
403 deleted => bool, # True iff deleted
404 private => bool, # True iff private
405 archive => bool, # True iff to be archived
406 },
407 category => $category, # Record's category number
408 id => $id, # Record's unique ID
409 data => $buf, # Raw record data
410 );
411
412 ParseRecord() takes the arguments listed above and returns a parsed
413 representation of the record, typically as a reference to a record
414 object or anonymous hash.
415
416 The output from ParseRecord() will be appended to "@{$pdb->{records}}".
417 The records appear in this list in the same order as they appear in the
418 file.
419
420 $offset argument is not normally useful, but is included for
421 completeness.
422
423 The fields in %$attributes are boolean values. They are true iff the
424 record has the corresponding flag set.
425
426 $category is an integer in the range 0-15, which indicates which
427 category the record belongs to. This is normally an index into a table
428 given at the beginning of the AppInfo block.
429
430 A typical ParseRecord() method has this general form:
431
432 sub ParseRecord
433 {
434 my $self = shift
435 my %record = @_;
436
437 # Parse $self->{data} and put the fields into new fields in
438 # $self.
439
440 delete $record{data}; # No longer useful
441 return \%record;
442 }
443
444 PackRecord
445 $buf = $pdb->PackRecord($record);
446
447 The converse of ParseRecord(). PackRecord() takes a record as returned
448 by ParseRecord() and returns a string of raw data that can be written
449 to the database file.
450
451 PackRecord() is never called when writing a resource database.
452
453 ParseResource
454 $record = $pdb->ParseResource(
455 type => $type, # Resource type
456 id => $id, # Resource ID
457 offset => $offset, # Resource's offset in file
458 data => $buf, # Raw resource data
459 );
460
461 ParseResource() takes the arguments listed above and returns a parsed
462 representation of the resource, typically as a reference to a resource
463 object or anonymous hash.
464
465 The output from ParseResource() will be appended to
466 "@{$pdb->{resources}}". The resources appear in this list in the same
467 order as they appear in the file.
468
469 $type is a four-character string giving the resource's type.
470
471 $id is an integer that uniquely identifies the resource amongst others
472 of its type.
473
474 $offset is not normally useful, but is included for completeness.
475
476 PackResource
477 $buf = $pdb->PackResource($resource);
478
479 The converse of ParseResource(). PackResource() takes a resource as
480 returned by PackResource() and returns a string of raw data that can be
481 written to the database file.
482
483 PackResource() is never called when writing a record database.
484
486 Palm::Raw
487
488 Palm::Address
489
490 Palm::Datebook
491
492 Palm::Mail
493
494 Palm::Memo
495
496 Palm::ToDo
497
498 Palm Database Files, in the ColdSync distribution.
499
500 The Virtual Constructor (aka Factory Method) pattern is described in
501 Design Patterns, by Erich Gamma et al., Addison-Wesley.
502
504 Palm::PDB requires no configuration files or environment variables.
505
507 None reported.
508
510 These functions die too easily. They should return an error code.
511
512 Database manipulation is still an arcane art.
513
514 It may be possible to parse sort blocks further.
515
517 Andrew Arensburger "<arensb AT ooblick.com>"
518
519 Currently maintained by Christopher J. Madsen "<perl AT cjmweb.net>"
520
521 Please report any bugs or feature requests to
522 "<bug-Palm-PDB AT rt.cpan.org>" or through the web interface at
523 <http://rt.cpan.org/Public/Bug/Report.html?Queue=Palm-PDB>.
524
525 You can follow or contribute to Palm-PDB's development at
526 <https://github.com/madsen/Palm-PDB>.
527
529 This software is copyright (c) 2000 by Andrew Arensburger.
530
531 This is free software; you can redistribute it and/or modify it under
532 the same terms as the Perl 5 programming language system itself.
533
535 BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
536 FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT
537 WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER
538 PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND,
539 EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
540 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
541 ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
542 YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
543 NECESSARY SERVICING, REPAIR, OR CORRECTION.
544
545 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
546 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
547 REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE LIABLE
548 TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR
549 CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
550 SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
551 RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
552 FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
553 SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
554 DAMAGES.
555
556
557
558perl v5.36.0 2022-07-22 Palm::PDB(3)