forked from extern/egroupware
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:
parent
05a91800b2
commit
0b6e2a605a
284
addressbook/inc/class.pdb.inc.php
Normal file
284
addressbook/inc/class.pdb.inc.php
Normal 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;
|
||||
}
|
||||
}
|
||||
?>
|
Loading…
Reference in New Issue
Block a user