<?php
/*
sms2csv.php for Treo 650 (php version)
written by Livy - Nobody's Life
Copyright @ 2005 mylivy.net
2005 May 25
Background:
modified code from C++ version by Viacheslav Kaloshin multik@multik.org
Copyright:
You can copy, modify, and distribute the source code.
Comments:
This is not bug free.
for questions, comments, and suggestions, email me at livy@mylivy.net
function:
extract sms only, with date, name, phone number, message body.
Installation guide:
copy the source code, with no extra space infront of the beginning <?php , and save as a .php file.
upload to your server
Requirements:
PHP 4
Functions used:
dirname
move_uploaded_file
header
filesize
fopen
fread
fclose
unlink
highlight_file
substr
ord
str_pad
dechex
strtoupper
localtime
date
*/
$title="SMS2CSV - Nobody's Life";
$mode="\x0"; /* R - receive, S - sent */
$phonenumber[256]="\x0";
$name[256]="\x0";
$date[40]="\x0"; /*date field */
$textbody[4096]="\x0";
$messagetotal=0;
$outputoptions=Array( "csv" => "CSV File", "screen" => "Screen");
$timezones=Array("-12" => "GMT-12:00 (International Date Line West)",
"-11" => "GMT-11:00 (Midway Island, Samoa), ",
"-10" => "GMT-10:00 (US Hawaiian Time)",
"-9" => "GMT-9:00 (US Alaska Time)",
"-8" => "GMT-8:00 (US Pacific Time, Los Angeles)",
"-7" => "GMT-7:00 (US Mountain Time, Denver)",
"-6" => "GMT-6:00 (US Central Time, Chicago)",
"-5" => "GMT-5:00 (US Eastern Time, New York)",
"-4" => "GMT-4:00 (Atlantic Time, Quebec)",
"-3" => "GMT-3:00 (Greenland)",
"-2" => "GMT-2:00 (Mid-Atlantic)",
"-1" => "GMT-1:00 (Azores, Cape Verdi Is.)",
"0" => "GMT (London, Dublin, Edinburgh, Lisbon, Casablanca, Monrovia)",
"1" => "GMT+1:00 (Paris, Amsterdam, Berlin, Rome, Vienna, Madrid, Warsaw, Brussels)",
"2" => "GMT+2:00 (Israel, Cairo, Athens, Helsinki, Istanbul, Buchrest)",
"3" => "GMT+3:00 (Moscow, Kuwait, Baghdad, Tehran, Nairobi)",
"4" => "GMT+4:00 (Abu Dhabi, Baku)",
"5" => "GMT+5:00 (Islamabad, Ekaterinburg, Karachi, Tashkent)",
"5.5" => "GMT+5:30 (Chennai, New Delhi, Mumbai)",
"5.75" => "GMT+5:45 (Kathmandu)",
"6" => "GMT+6:00 (Almaty, Astana, Dhaka, Novosibirsk)",
"7" => "GMT+7:00 (Bankok, Jakarta, Hanoi, Krasnoyarsk)",
"8" => "GMT+8:00 (Beijing, Singapore, Taipei, Kuala Lumpur, Irkutsk, Perth)",
"9" => "GMT+9:00 (Japan, Korea, Yakutsk)",
"9.5" => "GMT+9:30 (Adelaide, Darwin)",
"10" => "GMT+10:00 (Brisbane, Sydney, Melbourne, Canberra, Guam, Hobart)",
"11" => "GMT+11:00 (Magadan, Solomon Is., New Caledonia)",
"12" => "GMT+12:00 (Auckland, Wellington, Fiji)"
);
?>
<?php
if($_POST['upload']){
$pdbDir=dirname($_SERVER["SCRIPT_FILENAME"]);
$pdbFile=$pdbDir."/".$HTTP_POST_FILES['smspdb']['name'];
$csvFile="message.csv";
$GMT=$HTTP_POST_VARS['GMT']*60*60;
$opt=$HTTP_POST_VARS['OUTPUT']; //output to screen or csv file?
if($HTTP_POST_VARS['NOGMT'])
$GMT=0;
//set cookie for GMT setting
setcookie("GMT", $HTTP_POST_VARS['GMT'], time()+2592000); //remeber GMT setting for 1 month
setcookie("NOGMT", $HTTP_POST_VARS['NOGMT'], time()+2592000);
setcookie("OUTPUT", $HTTP_POST_VARS['OUTPUT'], time()+2592000);
if (move_uploaded_file($_FILES['smspdb']['tmp_name'], $pdbFile)) {
if (file_exists($pdbFile)){
//check if Message PDB file exists
if($opt=="csv"){
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($csvFile));
}
else{
//direct print to screen
}
//read contents
$filesize=filesize($pdbFile);
$fp=fopen($pdbFile, "rb");
$buf=fread($fp, $filesize);
fclose($fp);
//delete file from server
unlink($pdbFile);
//analyse contents
analyse($buf);
}else{
print "No Message file found.";
}
} else {
echo "File was not uploaded!\n";
}
}
elseif($HTTP_GET_VARS['source']){
print "<html><head><title>$title</title></head><body>";
highlight_file(basename($_SERVER['PHP_SELF']));
print "</body></html>";
}
else{
?>
<html>
<head>
<title><?php echo $title; ?></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<p>
<b>sms2csv.php</b>: convert sms from .pdb to .csv format for Treo 650
</p>
<form enctype="multipart/form-data" method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>">
<p>Upload the <b>Messages Database.pdb</b> file from your computer. </p>
<p>
File: <input type="hidden" name="MAX_FILE_SIZE" value="3000000" />
<input name="smspdb" type="file" />
</p>
<p>
Timezone
<select name="GMT">
<?php
foreach($timezones as $t => $z){
$t==$_COOKIE["GMT"]? $select="selected" : $select="";
print "<option $select value=$t>$z</option>\n";
}
?>
</select>
<input type="checkbox" name="NOGMT" <?php echo $_COOKIE["NOGMT"]? "checked" : ""; ?>>No GMT Offset
<p>Output to
<select name="OUTPUT">
<?php
foreach($outputoptions as $o => $p){
?>
<option value=<?php echo $o; ?> <?php echo $o==$_COOKIE["OUTPUT"]? "selected": ""; ?>><?php echo $p; ?></option>
<?php
}
?>
</select>
</p>
<p>
<small><b>Disclaimer: Your uploaded .pdb file will be deleted immediately after processing. The .csv file is not saved on our server.</b></small>
<p>
<p>
<input type="submit" name="upload" value="Submit" />
</p>
</form>
<p>To download this script? Please
<a href="<?php echo $_SERVER['PHP_SELF']; ?>?source=s">View Source</a>
</p>
<p>
To fix (some known bugs, a lot more...):
<ol>
<li>sms sent not properly fetched</li>
<li>specify messag start/end date</li>
<li>MMS not extracted</li>
</ol>
</p>
<p>Post your comments <a href="http://mylivy.net/blog/?page_id=31">here</a>. </p>
<p><hr>Copyright © 2005 <a href="http://mylivy.net">mylivy.net</a>    
Last modified on <?php echo date("d.m.Y H:i:s T", filemtime(basename($_SERVER['PHP_SELF']))); ?> </p>
</body>
</html>
<?php
}
?>
<?php
function analyse($buf){
global $filesize, $messagetotal;
$messageflag=0;
$messagestart=0;
$messageend=0;
for($i=0;$i<($filesize-6);$i++){
if($buf[$i]=="\x1B" && $buf[$i+1]=="\x54" && $buf[$i+2]=="\x72" && $buf[$i+3]=="\x53" && $buf[$i+4]=="\x4D"){
$messageend=$i;
if($messagestart){ /* in additional we need to skip 'garbage' at begin of the file */
$tmpmsg=substr($buf, $messagestart, $messageend-$messagestart);
$messagetotal++;
processmessage($messagestart,$messageend);
}
$messagestart=$i;
}
}
processmessage($messageend,$filesize); /* and dont forget the last one */
}
function processmessage($begin, $end){
global $buf, $GMT, $messagetotal, $opt;
$start=$begin;
$start=$start+5; /* skip TrSM header*/
//print "process message: begin=$begin, end=$end\n";
while($start<$end){ /* message parsing */
$bufc=str_pad(dechex(ord($buf[$start])),2,'0', STR_PAD_LEFT); //convert current buffer to HEX
$bufn=str_pad(dechex(ord($buf[$start+1])),2,'0', STR_PAD_LEFT); //convert next buffer to HEX
$type=strtoupper(str_pad($bufc,4,$bufn,STR_PAD_RIGHT)); //now it is 4 bits
switch($type){
case "0001": /* unknow */
case "0002":
case "000f":
$start=$start+2+4;
break;
case "0003": /* unknow */
$start=$start+2+5;
break;
case "0004": /* unknow */
$start=$start+2+8;
break;
case "0008": /* unknow */
$start=$start+2+3;
break;
/* SMS&MMS */
case "8000": /* date/time */
case "0007":
case "0006":
$start=$start+2;
$rawtime=(ord($buf[$start])*256+ord($buf[$start+1]))*65536+ord($buf[$start+2])*256+ord($buf[$start+3]);
$diff=2082853800+5400-8*60*60; //64 years (1970-1904) +1,5 hour
$rawtime=$rawtime-$diff+$GMT;
$ti=localtime($rawtime);
$date=date("d.m.Y H:i:s", $rawtime);
$start=$start+4; /* skip date/time record */
break;
case "4009":
case "400C":
$start=$start+2+20+2; /* skip zeros */
if($type=="4009") $mode='S'; else $mode='R';
$start=getmsg($start,$phonenumber);
$start=getmsg($start+1,$name);
break;
/* SMS */
case "2002": /* SMS text filed */
$start=getmsg($start+2+2,$textbody);
$textbody=str_replace("\n", " ", $textbody); //replace new line with a space
$textbody=str_replace("\"", "\"\" ", $textbody); //replace double quote
$textbody=str_replace(",", ". ", $textbody); //replace , with . hehe... not a good idea
break;
default:
/* printf("Unknow %4X at %4X. step one byte\n",type,start);*/
$start++;
break;
}
} // end while of message parsing
if($opt=="csv")
print "$mode, $date, $phonenumber, $name, $textbody\n";
else
print "<br>$messagetotal, $mode, $date, $phonenumber, $name, $textbody";
return 0;
}
function getmsg($start, &$msgstr){
global $buf;
$b=$start;
while($buf[$b]!="\x0"){
$msgstr.=$buf[$b];
$b++;
}
return $b;
}
?>