* * Access to palm OS database structures (?) * * ------------------------------------------------------------------------ * * Portions of code from ToPTIP * * Copyright (C) 2000-2001 Pierre Dittgen * * This file is a translation of the txt2pdbdoc tool * * written in C Paul J. Lucas (plj@best.com) * * ------------------------------------------------------------------------ * * This library may be part of the eGroupWare API * * ------------------------------------------------------------------------ * * This library is free software; you can redistribute it and/or modify it * * under the terms of the GNU Lesser General Public License as published by * * the Free Software Foundation; either version 2.1 of the License, * * or any later version. * * This library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * * along with this library; if not, write to the Free Software Foundation, * * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * \**************************************************************************/ /* $Id$ */ // ONLY THE FETCH FUNCTION SHOULD BE CALLED AT THIS TIME: // $pdb = CreateObject('addressbook.pdb'); // $pdb->fetch($content, $title, $document); // // This will force a download of the pdb file. // // READ DOES NOT WORK // FORMAT OF FILE IS A DOC, NOT A TRUE PALM ADDRESS BOOK class pdb { var $record_size = 4096; // Size of text record var $pdb_header_size = 78; // Size of the file header (don't touch!) var $pdb_record_header_size = 8; // Size of a text record header (don't touch either!) /** * Convert a integer value to a two bytes value string */ function int2($value) { return sprintf("%c%c", $value / 256, $value % 256); } /** * Convert a integer value to a four bytes value string */ function int4($value) { for($i=0; $i<4; $i++) { $b[$i] = $value % 256; $value = (int)(($value - $b[$i]) / 256); } return sprintf("%c%c%c%c", $b[3], $b[2], $b[1], $b[0]); } /** * Writes the header of the pdb file containing the title of the document * and different parameters including its size */ function write_header($fd, $title, $content_length) { // ============ File header ========================================= // Title of the document, it's limited to 31 characters if(strlen($title) > 31) { $title = substr($title, 0, 31); } fwrite($fd, $title); // Completion with null '\0' characters for($i=0; $i<32-strlen($title); $i++) { fwrite($fd, sprintf("%c", 0), 1); } // attributes & version fields fwrite($fd, $this->int2(0)); fwrite($fd, $this->int2(0)); // create & modify time fwrite($fd, sprintf("%c%c%c%c", 6, 209, 68, 174), 4); fwrite($fd, sprintf("%c%c%c%c", 6, 209, 68, 174), 4); // backup time, modification number, app Info Id, sort info Id fwrite($fd, $this->int4(0)); fwrite($fd, $this->int4(0)); fwrite($fd, $this->int4(0)); fwrite($fd, $this->int4(0)); // Type & creator fwrite($fd, 'TEXt', 4); fwrite($fd, 'REAd', 4); // Id seed & next record list fwrite($fd, $this->int4(0)); fwrite($fd, $this->int4(0)); // Number of text records $full_tr = (int)($content_length / $this->record_size); $notfull_tr = $content_length % $this->record_size; $num_records = $full_tr; if($notfull_tr != 0) { $num_records++; } // + 1 cause of record 0 fwrite($fd, $this->int2($num_records + 1)); // From here... $num_offsets = $num_records + 1; $offset = $this->pdb_header_size + $this->pdb_record_header_size * $num_offsets; $index = 0x40 << 24 | 0x6F8000; // Why not! fwrite($fd, $this->int4($offset)); fwrite($fd, $this->int4($index++)); $val = 110 + ($num_offsets - 2) * 8; while(--$num_offsets != 0) { fwrite($fd, $this->int4($val)); $val += 4096; fwrite($fd, $this->int4($index++)); } // To here // Don't ask me how it works ;-) // ====== Write record 0 ============ fwrite($fd, $this->int2(1)); // Version fwrite($fd, $this->int2(0)); // Reserved1 fwrite($fd, $this->int4($content_length)); // doc size fwrite($fd, $this->int2($num_records)); // num records fwrite($fd, $this->int2($this->record_size)); // record size fwrite($fd, $this->int4(0)); // Reserved2 } /** * Writes the given text, title on the given file descriptor * Note: It's saved as uncompressed doc * Note2: File descriptor is not closed at the end of the function */ function write($fd, $content, $title) { // Write header $this->write_header($fd, $title, strlen($content)); // Write content fwrite($fd, $content); // And flushes all fflush($fd); } /** * Reads the header of the pdb file * and different parameters including its size */ function read_header($fd) { // ============ File header ========================================= // Title of the document, it's limited to 31 characters $title = fread(31,$fd); // Completion with null '\0' characters for($i=0; $i<32-strlen($title); $i++) { fwrite($fd, sprintf("%c", 0), 1); } // attributes & version fields fwrite($fd, $this->int2(0)); fwrite($fd, $this->int2(0)); // create & modify time fwrite($fd, sprintf("%c%c%c%c", 6, 209, 68, 174), 4); fwrite($fd, sprintf("%c%c%c%c", 6, 209, 68, 174), 4); // backup time, modification number, app Info Id, sort info Id fwrite($fd, $this->int4(0)); fwrite($fd, $this->int4(0)); fwrite($fd, $this->int4(0)); fwrite($fd, $this->int4(0)); // Type & creator fwrite($fd, 'TEXt', 4); fwrite($fd, 'REAd', 4); // Id seed & next record list fwrite($fd, $this->int4(0)); fwrite($fd, $this->int4(0)); // Number of text records $full_tr = (int)($content_length / $this->record_size); $notfull_tr = $content_length % $this->record_size; $num_records = $full_tr; if($notfull_tr != 0) { $num_records++; } // + 1 cause of record 0 fwrite($fd, $this->int2($num_records + 1)); // From here... $num_offsets = $num_records + 1; $offset = $this->pdb_header_size + $this->pdb_record_header_size * $num_offsets; $index = 0x40 << 24 | 0x6F8000; // Why not! fwrite($fd, $this->int4($offset)); fwrite($fd, $this->int4($index++)); $val = 110 + ($num_offsets - 2) * 8; while(--$num_offsets != 0) { fwrite($fd, $this->int4($val)); $val += 4096; fwrite($fd, $this->int4($index++)); } // To here // Don't ask me how it works ;-) // ====== Write record 0 ============ fwrite($fd, $this->int2(1)); // Version fwrite($fd, $this->int2(0)); // Reserved1 fwrite($fd, $this->int4($content_length)); // doc size fwrite($fd, $this->int2($num_records)); // num records fwrite($fd, $this->int2($this->record_size)); // record size fwrite($fd, $this->int4(0)); // Reserved2 } /** * Reads a pdb from the given file descriptor * Note2: File descriptor is not closed at the end of the function */ function read($fd) { // Read header $header = $this->read_header($fd); // Read content $content = fread($fd); // And flushes all flush($fd); } /** * Creates a palmdoc and force the user to download it */ function fetch($content, $title, $document) { // Creates a temp file to put the current doc $tempfile = tempnam(".", "palm"); // Creates the doc from the content $fd = fopen($tempfile, 'w'); $this->write($fd, $content, $title); fclose($fd); // Forces the download header("Content-Type: application/force-download"); header("Content-Disposition: attachment; filename=\"$document\""); // And writes the file content on stdout $fd = fopen("$tempfile", 'r'); $content = fread($fd, filesize($tempfile)); fclose($fd); print($content); // Cleaning unlink($tempfile); exit; } } ?>