<?
set_time_limit(500000);
/*
POP3.CLASS:
Finally it's here, the shit that's been asked of me for ages, finally I got my head around
an algorithm to properly decode POP3 mailboxes without tons if type checking.
Came down to that nasty recursive code your mother told you to avoid being needed.
This is an extensible "base" API which includes:
Get Message List
Get Headers
Get Message
Split Message
Age In Days of message
*/
define("pop3NoProblem", "+OK"); // Standard OK message from a POP3 server
define("pop3FinalBoundary", "----POP3_Class_Final_Boundary_". mktime());
class pop3 {
var $pop_server = "";
var $pop_port = "";
var $pop_uid = "";
var $pop_pass = "";
var $fhandle = "";
var $LoggedOn = false;
function DateDiff($startdate, $enddate) {
// This code snippet courtessy of "stew" from PHPBuilder.COM
## difference between the two in seconds
$time_period = ( $enddate - $startdate );
$days = 0;
$hours = 0;
$minutes = 0;
$seconds = 0;
$time_increments = array('Days' => 86400, 'Hours' => 3600, 'Minutes' => 60, 'Seconds' => 1);
## will hold our values for ( day, minute, hour, seconds )
$time_span = array();
## cycle through time_increments
while (list( $key, $value ) = each( $time_increments )) {
$this_value = (int) ( $time_period / $value );
$time_period = ( $time_period % $value );
$time_span[$key] = $this_value;
}
## Also the difference in minutes between the two - JB
$time_span["min_diff"] = ($time_span["Days"] * 1440) + ($time_span["Hours"] * 60) + $time_span["Minutes"];
return $time_span;
}
function pop3($pop_server, $pop_port, $pop_uid, $pop_pass) {
$this->pop_server = $pop_server;
$this->pop_port = $pop_port;
$this->pop_uid = $pop_uid;
$this->pop_pass = $pop_pass;
// return 1 on sucessful connect.
if ($this->Connect()) { return 1; } else { return 0; }
}
function Connect() {
$this->fhandle = "";
$fp = fsockopen($this->pop_server, $this->pop_port, $errno, $errstr, 10);
if (!$fp) {
echo "Error: POP3/Connect: (Err # $errno) $errstr\n";
return 0;
} else {
$this->fhandle = $fp;
list($status, $msg) = $this->GetString();
if ($status == pop3NoProblem) {
return 1;
} else {
$this->fhandle = "";
echo "Error: POP3/Connect: Established port but did not receive standard opening response from server.\n";
echo "Status: $status, Msg: $msg\n";
return 0;
}
return 1;
}
} // END Connect()
function Disconnect() {
if ($this->fhandle) {
if ($this->LoggedOn) {
$this->Logoff();
}
fclose($this->fhandle);
}
} // END Disconnect()
function SendString($message) {
if ($this->fhandle) {
fwrite($this->fhandle, $message);
}
} // END SendString()
function GetString() {
if ($this->fhandle) {
$retval = fgets($this->fhandle, 65535);
$retArr = split("\ ", $retval, 2);
}
return $retArr;
} // END GetString()
function GetDataBlock() {
$retval = "";
if ($this->fhandle) {
$quitflag = false;
while (!$quitflag) {
$tmpstr = fgets($this->fhandle, 65535);
$tmpstr = eregi_replace("\n|\r\n", "", $tmpstr);
if ($tmpstr == ".") {
$quitflag = true;
} else {
$retval .= "$tmpstr\n";
}
}
}
return $retval;
}
function Logon() {
if ($this->fhandle) {
if ($this->LoggedOn) {
return 1; // if we're already logged on, just return
}
$this->SendString("user ". $this->pop_uid ."\r\n");
list($status, $msg) = $this->GetString();
if ($status == pop3NoProblem) {
$this->SendString("pass ". $this->pop_pass ."\r\n");
list($status, $msg) = $this->GetString();
if ($status == pop3NoProblem) {
$this->LoggedOn = true;
return 1;
} else {
echo "Error: POP3/Logon: $status, $msg\n";
return 0;
}
} else {
echo "Error: POP3/Logon: $status, $msg\n";
return 0;
}
}
} // END Logon()
function Logoff() {
if ($this->LoggedOn) {
$this->SendString("quit\r\n");
list($status, $msg) = $this->GetString();
if ($status == pop3NoProblem) {
$this->LoggedOn = false;
return 1;
} else {
echo "Error: POP3/Logoff: $status, $msg\n";
return 0;
}
}
} // END Logoff()
function GetNumberOfMessages() {
$tmpArr = Array();
if ($this->Logon()) {
$this->SendString("stat\r\n");
list($status, $msg) = $this->GetString();
if ($status == pop3NoProblem) {
$retArr = split("\ ", $msg);
$tmpArr["messages"] = $retArr[0];
$tmpArr["mailbox_size"] = $retArr[1];
return $tmpArr;
} else {
echo "Error: POP3/GetNumberOfMessages(): $status, $msg\n";
return 0;
}
} else {
return 0;
}
}
function GetHeaders($msgnum) {
$headArr = Array();
if ($this->Logon()) {
$this->SendString("list $msgnum\r\n");
$val = $this->GetString();
$sizeArr = split("\ ", $val[1]);
$headArr["size_of_message"] = trim($sizeArr[1]);
$this->SendString("top $msgnum 0\r\n");
$textblock = $this->GetDataBlock();
$lineArr = split("\n", $textblock);
for ($t=0; $t<count($lineArr); $t++) {
if (eregi("^([0-9A-Za-z_]{1,})\:", $lineArr[$t])) {
$tmpArr = split("\:", $lineArr[$t], 2);
$tmpArr[0] = strtolower(trim($tmpArr[0]));
$tmpArr[1] = trim($tmpArr[1]);
$headArr[$tmpArr[0]] = $tmpArr[1];
} elseif (eregi("^\ *([0-9A-Za-z_]{1,})", $lineArr[$t])) {
}
}
}
return $headArr;
} // END GetHeaders()
function GetMessageList() {
$tmpArr = Array();
if ($this->Logon()) {
$msgCountArr = $this->GetNumberOfMessages();
for ($t=0; $t<$msgCountArr["messages"]; $t++) {
$msgnum = $t+1;
$headArr = $this->GetHeaders($msgnum);
$tmpArr[] = $headArr;
}
}
return $tmpArr;
} // END GetMessageList()
function ReadMessage($msgnum) {
if ($this->Logon()) {
$this->SendString("retr $msgnum\r\n");
$textblock = $this->GetDataBlock();
return $textblock;
}
}
function DeleteMessage($msgnum) {
if ($this->Logon()) {
$this->SendString("dele $msgnum\r\n");
$respArr = $this->GetString();
}
}
function FindLine($start_at, $regex, $msgblock) {
$linepos = -1;
$posfound = false;
$curpos = $start_at;
while (!$posfound) {
$line = $msgblock[$curpos];
if ($regex != "") {
if (eregi($regex, $line)) {
$linepos = $curpos;
$posfound = true;
}
} else {
if ($line == "") {
$linepos = $curpos;
$posfound = true;
}
}
$curpos++;
if ($curpos >= count($msgblock)) {
$posfound = true;
}
}
return $linepos;
} // END FindLine
function GetStringBlock($start_line, $end_line, $msgArr) {
$tmpArr = Array();
for ($x=$start_line; $x<$end_line; $x++) {
$tmpArr[] = trim($msgArr[$x]);
}
return $tmpArr;
} // END GetStringBlock
function AssembleTypeArray($start_line, $end_line, $msgArr, $boundarySTR = "") {
$typeArr = Array();
$tmpArr = $this->GetStringBlock($start_line, $end_line, $msgArr);
for ($x=0; $x<count($tmpArr); $x++) {
$line = $tmpArr[$x];
$htArr = split(";", $line);
for ($jj=0; $jj<count($htArr); $jj++) {
$item = $htArr[$jj];
if (eregi("[:=](\ *)", $item)) {
$tmpArr2 = split("[:=](\ *)", $item, 2);
$typeArr[strtolower(trim($tmpArr2[0]))] = trim($tmpArr2[1]);
} elseif (eregi("=\"", $item)) {
$tmpArr2 = split("=\"", $item, 2);
$tmpArr2[1] = eregi_replace("\"$", "", $tmpArr2[1]);
$typeArr[strtolower(trim($tmpArr2[0]))] = trim($tmpArr2[1]);
}
}
}
if ($typeArr["name"]) {
$typeArr["name"] = eregi_replace("^\"|\"$", "", $typeArr["name"]);
}
if ($typeArr["filename"]) {
$typeArr["filename"] = eregi_replace("^\"|\"$", "", $typeArr["filename"]);
}
if ($typeArr["boundary"]) {
$typeArr["boundary"] = eregi_replace("\"","",$typeArr["boundary"]);
} else {
$typeArr["boundary"] = $boundarySTR;
}
if (!$typeArr["boundary"]) {
$typeArr["boundary"] = pop3FinalBoundary;
}
if (!$typeArr["content-type"]) {
$typeArr["content-type"] = "text/plain";
}
return $typeArr;
} // END AssembleTypeArray
function GetChunksFromBody($parts, $boundary, $level = 1, $headArr = "") {
$end_chunk = count($parts);
$chunkArr = Array();
// echo "GetChunksFromBody[$level]: Entering: $end_chunk segments, Boundary = $boundary\n";
for ($i=0; $i<$end_chunk; $i++) {
$parts[$i] = eregi_replace("^(\n|\r\n*)", "", $parts[$i]);
$mArr = split("\n", $parts[$i]);
if (count($mArr) > 0 & $mArr[0] != "--") {
// echo "GetChunksFromBody[$level]: First Line oF Segment $i: $mArr[0]\n";
if (eregi("content-type", $mArr[0])) {
// echo "GetChunksFromBody[$level]: Segment Found\n";
$head_end = $this->FindLine(0, "", $mArr);
$headArr = $this->AssembleTypeArray(0, $head_end, $mArr, $boundary);
$bodyArr = $this->GetStringBlock($head_end + 1, count($mArr), $mArr);
// echo "GetChunksFromBody[$level]: Content-Type: ". $headArr["content-type"] ."\n";
if ($headArr["boundary"] != $boundary) { // we've got an embedded segment to explode
// echo "GetChunksFromBody[$level]: Recursing, new boundary = ". $headArr["boundary"] . "\n";
$moreparts = explode("--". $headArr["boundary"], join("\n", $bodyArr));
$extras = $this->GetChunksFromBody($moreparts, $headArr["boundary"], $level+1);
for ($z=0; $z<count($extras); $z++) {
$chunkArr[] = $extras[$z];
}
} else {
$t["headers"] = $headArr;
$t["body"] = join("\n", $bodyArr);
$chunkArr[] = $t;
}
} else {
if (!$headArr) { $headArr = $this->AssembleTypeArray(0, 1, $mArr, $boundary); }
$bodyArr = $this->GetStringBlock(0, count($mArr), $mArr);
$t["headers"] = $headArr;
$t["body"] = join("\n", $bodyArr);
$chunkArr[] = $t;
}
} else {
// echo "GetChunksFromBody[$level]: No data in segment $i\n";
}
}
// echo "GetChunksFromBody[$level]: Leaving\n";
return $chunkArr;
}
function SplitMessage($msgblock) {
$chunks = Array();
$msgArr = split("\n", $msgblock);
$msgArr[] = "--". pop3FinalBoundary."--";
$first_head_end = $this->FindLine(1, "", $msgArr);
$hArr = $this->AssembleTypeArray(0, $first_head_end, $msgArr);
$body = join("\n", $this->GetStringBlock($first_head_end + 1, count($msgArr) -1, $msgArr));
$parts = explode("--". $hArr["boundary"], $body);
$chunks = $this->GetChunksFromBody($parts, $hArr["boundary"], 1, $hArr);
return $chunks;
}
function AgeInDays($date_received) {
$dStamp = strtotime($date_received);
$cStamp = mktime();
$diff = $this->DateDiff($dStamp, $cStamp);
return $diff["Days"];
}
function SplitSender($sender) {
$senderParts["name"] = $sender;
if (($pos = strrpos($sender, "<")) && substr($sender, -1) == ">") {
$senderParts["name"] = substr($sender, 0, $pos - 1);
$senderParts["email"] = substr($sender, $pos);
}
$senderParts["name"] = eregi_replace("\<|\>", "", $senderParts["name"]);
$firstChar = substr($senderParts["name"], 0, 1);
$lastChar = substr($senderParts["name"], -1);
if ($firstChar == "\"" || $firstChar == "'") $senderParts["name"] = substr($senderParts["name"], 1);
if ($lastChar == "\"" || $lastChar == "'") $senderParts["name"] = substr($senderParts["name"], 0, -1);
return $senderParts;
}
function HTMLFormatSender($sender) {
$sender = eregi_replace("\"", "", $sender);
$sender = eregi_replace("\<", "<", $sender);
$sender = eregi_replace("\>", ">", $sender);
return $sender;
}
} // END pop3