From 0b6e2a605ad2fb6c3fc3fb82977e40add2480368 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Wed, 18 Aug 2004 08:30:26 +0000 Subject: [PATCH] fix for palm-download as suggested by Peter Hrastnik's patch [ 1010631 ] patch for broken pdb file-download (headers already sent) --- addressbook/inc/class.pdb.inc.php | 284 ++++++++++++++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 addressbook/inc/class.pdb.inc.php diff --git a/addressbook/inc/class.pdb.inc.php b/addressbook/inc/class.pdb.inc.php new file mode 100644 index 0000000000..9a3dc4bb0e --- /dev/null +++ b/addressbook/inc/class.pdb.inc.php @@ -0,0 +1,284 @@ + * + * 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; + } + } +?>