fix for palm-download as suggested by Peter Hrastnik's patch [ 1010631 ] patch for broken pdb file-download (headers already sent)

This commit is contained in:
Ralf Becker 2004-08-18 08:30:26 +00:00
parent 05a91800b2
commit 0b6e2a605a

View File

@ -0,0 +1,284 @@
<?php
/**************************************************************************\
* eGroupWare API - Palm Database Access *
* This file written by Miles Lott <milos@groupwhere.org> *
* 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;
}
}
?>