The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Palm::SMS - parse SMS database files

SYNOPSIS

    use Palm::PDB;
    use Palm::SMS;

    my $pdb = new Palm::PDB;
    $pdb->Load("sms.pdb");

    my $record = $pdb->{records}[0];
    print "$record->{text}\n";

DESCRIPTION

The SMS PDB handler is a helper class for the Palm::PDB module. It is intended for reading, manipulating, and writing the .pdb files used by Handspring SMS application on PalmOS devices such as Handspring Treo 270.

Palm::SMS module is the result of a reverse engineering attempt of trasforming a Handspring Treo 270 SMS PDB file into a plain text file. The PDB test file was produced by Handspring's application SMS v. 3.5H.

Due to lack of knowledge about how PDB files work and what format SMS database files conform to, at present this module is not suitable for from-scratch SMS generation. Conversely, you may find it extremely useful if you intend to extract SMS messages from merged PDB files and convert them to a human readable form.

Fields

    $record = $pdb->{records}[N];

    $record->{name}
    $record->{firstName}
    $record->{phone}
    $record->{folder}
    $record->{timestamp}
    $record->{text}

    $record->{smsh}
    $record->{unknown1}
    $record->{unknown2}
    $record->{unknown3}

The fields provided for each record are the following:

name

A string containing the name of the person who wrote the message.

firstname

A string containing the first name of the person who wrote the message.

phone

A string containing the phone number.

timestamp

An integer which represents the number of seconds elapsed from Unix epoch to message creation time.

It is worth noticing that there is no way of retrieving neither the TZ nor the DST out of data stored in the PDB file. This timestamp always expresses the time of your handheld's clock at message creation time. Hence, I suggest passing the value GMT as third argument to Date::Format's time2str() to get the right timestamp rappresentation:

  use Date::Format;
  ...
  $timestamp = time2str("%T %%Z",   $record->{timestamp}, "GMT");
  $timestamp = time2str($timestamp, $record->{timestamp}       );
folder

An integer which represents in which folder the message was stored. English folder names (such as Inbox or Sent) are available as

  $Palm::SMS::folders[$record->{folder}];
text

A string containing the message body.

The module provides additional fields which will probably be less commonly used.

smsh

This string of four bytes ("SMSh") is present at the start of each record.

unknown1
unknown2
unknown3

These fields contain a chunk of bytes whose function is not yet known. Please, refer to the ParseRecord() method.

Fields for the Treo 680

The Treo 680 uses different software, and Palm have not documented its message format. Consequently only some information is available, and some records that are extracted are extracted incorrectly. The following fields are available, and have been reverse-engineered from a single sample database. Consequently, you should treat their values with suspicion.

Treo 680 databases are read-only.

If the Palm::Treo680MessagesDB module is available, then that will be used instead. Over time, that module is intended to do a better job, as and when I figure out new bits of the puzzle.

device

This will always be "Treo 680"

direction

The direction of the SMS relative to your phone. This will be either 'inbound' or 'outbound'

number

The other party's phone number (same as for any other device)

name

The other party's name (same as for any other device)

text

The text of the message (same as for any other device)

type

A number representing the type of message. If this is 'unknown' then none of the above fields will be populated.

rawdata

The raw binary data of the record

METHODS

new

  $pdb = new Palm::SMS;

Creates a new PDB, initialized with the various Palm::SMS fields and an empty record list.

Use this method if you're creating a SMS PDB from scratch.

new_Record

  $record = $pdb->new_Record;

  $record->{phone}  = "1234567890";
  $record->{folder} = 1;
  ...

  $phone  = $record->{phone};
  $folder = $Palm::SMS::folders[$record->{folder}];
  ...

Creates a new SMS record, with blank values for all of the fields.

new_Record does not add the new record to $pdb. For that, you want $pdb->append_Record.

Default field values are:

  name     : undef
  firstName: undef
  phone    : undef
  timestamp: localtime()
  folder   : 1
  text     : undef

  smsh     : "SMSh"
  unknown1 : undef
  unknown2 : undef
  unknown3 : undef

ParseRecord

ParseRecord() returns a parsed representation of the record, typically as a reference to a record object or anonymous hash. It is automatically called from within Palm::PDB and, as such, is not intented to be used directly from applications.

The record structure which an SMS posses is:

    smsh     :  4-byte ASCII string
    unknown1 :  2-byte data whose function is unknown
    timestamp:  32-bit, big-endian, unsigned integer rappresenting
                the number of seconds since 1904
    unknown2 :  26-byte data whose function is unknown
    phone    :  Null terminated string
    name     :  Null terminated string
    firstname:  Null terminated string
    unknown3 :  16-byte data whose function is unknown
    text     :  Null terminated (sent messages only) string

folder field value is copied from category field which is computed by Palm::PDB and then delted since there is no application info block (see Palm::StdAppInfo) in the PDB file.

unknown3 is empty for messages belonging to category 1 (folder Sent).

It is worth noticing that length, offset, and even availability of unknown data are not preserved between module version when their meaning becomes clear.

PackRecord

This is the converse of ParseRecord(). PackRecord() takes a record as returned by ParseRecord() and returns a string of raw data that can be written to the database file. As ParseRecord(), this function is not intended to be used directly from applications.

Because there are chunk of record data whose function is unknown (see ParseRecord()), this method may produce an invalid result, expecially when passed record was created from scratch via new_Record().

This method is granted to work if the record being packed has been unpacked from an existing PDB and no information has been added.

BUGS

Not all data chunks have a known function. Hence, the module is suitable only for data extraction and simple database manipulations.

I heard rumors that SMS format changes with GSM network providers. Please, contact me if this module cannot correctly handle your messages, hopefully attaching a patch which corrects the shortcoming.

SEE ALSO

Palm::PDB by Andrew Arensburger <arensb@ooblick.com>

Palm::Treo680MessagesDB

smssync v 1.0 by Janne Mäntyharju <janne.mantyharju@iki.fi>

AUTHOR and MAINTAINER

Lorenzo Cappelletti <lorenzo.cappelletti@email.it> with some contributions from David Cantrell <david@cantrell.org.uk>.

David Cantrell is now the primary maintainer.

COPYRIGHT AND DISCLAIMER

This program is Copyright 2005-2009 by Lorenzo Cappelletti and David Cantrell. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 556:

Non-ASCII character seen before =encoding in 'Mäntyharju'. Assuming CP1252