<?
if(VALID_DOCUMENT != 1) die('what?');
//////////////////////
// Class for mailbox
//////////////////////
class MBox{
var $name;
var $name_print;
var $num_msgs;
var $recent_msgs;
var $new_msgs;
var $size;
function MBox($name,$name_print=false,$without_info=false){
$this->name = $name;
if($name_print)
$this->name_print = $name_print;
else
$this->name_print = basename($this->name);
if(!$without_info){
$this->refresh();
}
}
function getMP(){
return getIMAP();
}
function refresh(){
$mp = $this->getMP();
try{ $status = $mp->status($this->name); }
catch(Exception $e){
Notice::set($e->getMessage());
}
if($status === null){
return;
}
$this->valid = true;
$this->num_msgs = $status['messages'];
$this->recent_msgs = $status['recent'];
$this->new_msgs = $status['unseen'];
$this->size = $status['size'];
}
// Deleting all keys from mailbox
function delete($keys){
$mp =$this->getMP();
$res = $mp->delete_messages($this->name,$keys);
if(is_array($keys)){
sort($keys);
$res .= "Messages <b>".implode(", ",$keys).
"</b> deleted from <b>".$this->name."</b>\n";
}
else if(is_numeric($keys))
$res .= "Message <b>$keys</b> deleted from <b>".$this->name."</b>\n";
return $res;
}
function rename($name){
$this->name = $name;
$this->name_print = basename($name);
}
function append($msg){
$mp = $this->getMP();
$mp->append($this->name,$msg);
}
// moving all keys to another mailbox
function move($keys,$mailbox){
$mp = $this->getMP();
$mp->move_messages($this->name,$mailbox,$keys);
if(is_array($keys)){
reset($keys);
sort($keys);
$strkeys = implode(",",$keys);
}
else
$strkeys = $keys;
$res = "Messages <b>$strkeys</b> moved from <b>".$this->name."</b> to <b>".$mailbox."</b>\n";
return $res;
}
// copying all keys to another mailbox
function copy($keys,$mailbox){
$mp = $this->getMP();
$mp->copy_messages($this->name,$mailbox,$keys);
if(is_array($keys)){
reset($keys);
sort($keys);
$strkeys = implode(",",$keys);
}
else
$strkeys = $keys;
$res = "Messages <b>$strkeys</b> copied from <b>".$this->name."</b> to <b>".$mailbox."</b>\n";
return $res;
}
function setLabel($label,$keys,$set=true){
$mp = $this->getMP();
$mp->select($this->name);
if(!is_array($keys) && $keys) $keys = array($keys);
if(is_array($keys)){
foreach($keys as $k){
$mp->store_flag($this->name,$k,$label,$set);
}
reset($keys);
sort($keys);
$strkeys = implode(',',$keys);
$label_name = $label;
if(is_object($_SESSION['labels'])){
$l = $_SESSION['labels']->find($label);
$label_name = $l['name'];
}
if($set)
$res = "Messages $this->name[<b>$strkeys</b>] labeled with «<b>$label_name</b>»\n";
else
$res = "Label «<b>$label_name</b>» removed from $this->name[<b>$strkeys</b>] \n";
}
return $res;
}
function print_table_row(){
if(get_var('mailbox') == $this->name)
$class = 'checked';
print '<tr><td class="'.$class.'" style="padding-right: 8px">';
$this->print_row();
print '</td></tr>';
}
function print_row(){
print
'<a href="'.$_SERVER['PHP_SELF'].'?action=show-folder&mailbox='.$this->name.'"'.
($this->num_msgs>0?
(' title="total: '.$this->num_msgs.
($this->recent_msgs>0?' recent: '.$this->recent_msgs:'').
($this->new_msgs>0?' new: '.$this->new_msgs:'').
($this->size>0?' size: '.bytes2string($this->size,0):'').'"'):
(is_numeric($this->num_msgs)&&$this->num_msgs==0?' title="empty"':'')).
'>'.$this->name_print.'</a>'.
($this->new_msgs>0?' <span class="red">('.$this->new_msgs.')</span>':'');
}
function get_info(){
if($this->num_msgs === 0) return '0';
return
'<span class="gray">'.$this->num_msgs.'</span>'.
($this->new_msgs>0?'|<span class="red">'.$this->new_msgs.'</span>':'');
}
}
# NNTPMBox
class NNTPMBox extends MBox{
function NNTPMBox($name,$name_print=false){
parent::MBox($name,$name_print,true);
}
function getMP(){
return getNNTP();
}
}
//////////////////////////////////////
// Getting only names for mailboxes
//////////////////////////////////////
function get_mailboxes_names($except=false){
$names = array();
foreach($_SESSION['mboxes']->boxes as $box){
if(eregi("^MBox$",get_class($box)) &&
$except != $box->name)
$names[$box->name_print] = $box->name;
}
//asort($names);
return $names;
$imap = getIMAP();
$arr_boxes=array($_SESSION['procmail']->inbox_name);
$arr_boxes=array_merge($arr_boxes,$imap->listing($_SESSION['preferences']->getMailDir().'/%'));
foreach($arr_boxes as $box){
if($box){
$name = $box;
if(eregi($_SESSION['procmail']->inbox_name.'$',$name))
$names['INBOX'] = $name;
else if(eregi($_SESSION['preferences']->getFccMailbox().'$',$name))
$names['Sent Mails'] = $name;
else if(eregi($_SESSION['preferences']->getDraftMailbox().'$',$name))
$names['Postponed Mails'] = $name;
else if(eregi($_SESSION['preferences']->getRestoredMailbox().'$',$name))
$names['Restored Mails'] = $name;
else
$names[basename($name)] = $name;
}
}
asort($names);
return $names;
}
////////////////////////
// Class for mailboxes
////////////////////////
class MBoxes{
var $boxes;
var $names;
var $categories;
function MBoxes(){
$this->refresh();
}
function refresh(){
$this->boxes = array();
$this->names = array();
$this->categories = array();
$imap = getIMAP();
$exists_names = array();;
foreach($imap->listing($_SESSION['preferences']->getMailDir().'/*') as $l){
$exists_names[$l] = true;
}
// Inbox
$mailbox = new MBox($_SESSION['procmail']->inbox_name,'INBOX');
$this->boxes[$mailbox->name] = $mailbox;
$this->names[] = $mailbox->name;
$this->categories['inbox'] = $mailbox->name;
// Special
if($exists_names[$_SESSION['preferences']->getFccMailbox()]){
$mailbox = new MBox($_SESSION['preferences']->getFccMailbox(),'Sent Mails');
if($mailbox->valid){
$this->boxes[$mailbox->name] = $mailbox;
$this->names[] = $mailbox->name;
$this->categories['special'][] = $mailbox->name;
}
}
if($exists_names[$_SESSION['preferences']->getDraftMailbox()]){
$mailbox = new MBox($_SESSION['preferences']->getDraftMailbox(),'Postponed Mails');
if($mailbox->valid){
$this->boxes[$mailbox->name] = $mailbox;
$this->names[] = $mailbox->name;
$this->categories['special'][] = $mailbox->name;
}
}
if($exists_names[$_SESSION['preferences']->getRestoredMailbox()]){
$mailbox = new MBox($_SESSION['preferences']->getRestoredMailbox(),'Restored Mails');
if($mailbox->valid){
$this->boxes[$mailbox->name] = $mailbox;
$this->names[] = $mailbox->name;
$this->categories['special'][] = $mailbox->name;
}
}
// additional
$add = $_SESSION['preferences']->getMailboxesList();
if(array_not_empty($add)){
foreach($add as $name){
if($exists_names[$name]){
$mailbox = new MBox($name);
if($mailbox->valid){
$this->boxes[$mailbox->name] = $mailbox;
$this->names[] = $mailbox->name;
$this->categories['additional'][] = $mailbox->name;
}
}
}
}
// news
if(array_not_empty($_SESSION['newsrc']->get_groups())){
foreach($_SESSION['newsrc']->get_groups() as $group){
$mailbox = new NNTPMBox($group);
$this->boxes[$mailbox->name] = $mailbox;
$this->names[] = $mailbox->name;
$this->categories['news'][] = $mailbox->name;
}
}
}
// Creating MailHeaders
function createMailHeaders($mailbox='INBOX',$sort_order=SORT_BY_DATE,$start_page=1,$update=true){
$mbox = $this->find($mailbox);
if($mbox){
if($mbox->name == $_SESSION['preferences']->getFccMailbox())
return new SentMailHeaders($mbox->name,$sort_order,$start_page);
else if($mbox->name == $_SESSION['preferences']->getDraftMailbox())
return new DraftMailHeaders($mbox->name,$sort_order,$start_page);
else if(eregi('^NNTPMBox$',get_class($mbox)))
return new NNTPMailHeaders($mbox->name,$sort_order);
else
return new MailHeaders($mbox->name,$mbox->name_print,$sort_order,$start_page);
}
else
return false;
}
// Searching for mailbox
function find($name){
if(isset($this->boxes[$name]))
return $this->boxes[$name];
return null;
}
// Searching for query
function query($query,$type,$subject,$email,$body,$boxes){
$mp = getImap();
$all_headers = $mp->search($query,$type,$subject,$email,$body,$boxes);
$qheaders = array();
foreach($all_headers as $mbox=>$headers){
foreach($headers as $h){
$header = new MailHeader($mbox,$h);
$qheader = new QueryMailHeader($header);
$qheaders[] = $qheader;
}
}
return new QueryMailHeaders($query,$qheaders);
}
// Searching for labels
function getLabeled($label,$boxes){
$mp = getImap();
$all_headers = $mp->search_label($label,$boxes);
$lheaders = array();
foreach($all_headers as $mbox=>$headers){
foreach($headers as $h){
$header = new MailHeader($mbox,$h);
$lheader = new LabelMailHeader($header);
$lheaders[] = $lheader;
}
}
return new LabelMailHeaders($label,$lheaders);
}
// Deleting of mailbox
function delete($names){
if(!is_array($names))
$names = array($names);
$for_delete = array();
foreach($this->boxes as $box){
foreach($names as $name){
if($box->name == $name){
$for_delete[] = $name;
}
}
}
$deleted = array();
foreach($for_delete as $d){
$mbox = $this->find($d);
$mp = $mbox->getMP();
if($mp->delete($d)){
$res .= "Mailbox <b>$d</b> deleted.\n";
$deleted[] = $d;
}
else
$res .= "Can't delete <b>$d</b>.\n";
}
// cleanup
reset($this->boxes);
foreach($this->boxes as $key=>$box){
foreach($deleted as $d){
if($box->name == $d){
unset($this->boxes[$key]);
}
}
}
foreach($this->names as $k=>$n){
foreach($deleted as $d){
if($n == $d){
unset($this->names[$k]);
}
}
}
if($this->categories['special']){
foreach($this->categories['special'] as $k=>$n){
foreach($deleted as $d){
if($n == $d){
unset($this->categories['special'][$k]);
}
}
}
}
if($this->categories['additional']){
foreach($this->categories['additional'] as $k=>$n){
foreach($deleted as $d){
if($n == $d){
unset($this->categories['additional'][$k]);
}
}
}
}
return $res;
}
// Creating of new mailbox
function create($name){
if($this->find($name))
return false;
$mp = getIMAP();
try{ $mp->create($name);}
catch(Exception $e){ return $e->getMessage(); }
if($name == $_SESSION['preferences']->getFccMailbox()){
$mailbox = new MBox($_SESSION['preferences']->getFccMailbox(),'Sent Mails');
$this->categories['special'][] = $mailbox->name;
}
else if($name == $_SESSION['preferences']->getDraftMailbox()){
$mailbox = new MBox($_SESSION['preferences']->getDraftMailbox(),'Postponed Mails');
$this->categories['special'][] = $mailbox->name;
}
else if($name == $_SESSION['preferences']->getRestoredMailbox()){
$mailbox = new MBox($_SESSION['preferences']->getRestoredMailbox(),'Restored Mails');
$this->categories['special'][] = $mailbox->name;
}
else{
$mailbox = new MBox($name);
$this->categories['additional'][] = $mailbox->name;
}
$this->names[] = $mailbox->name;
$this->boxes[$mailbox->name] = $mailbox;
return "Mailbox $name created.";
}
// Renaming of old mailbox
function rename($name,$new_name){
$old = $this->find($name);
if(!$old)
return false;
$mp = getIMAP();
$mp->rename($name,$new_name);
unset($this->boxes[$name]);
$old->rename($new_name);
$this->boxes[$new_name] = $old;
}
function get_tree(){
$imap = getIMAP();
$list = $imap->listing($_SESSION['preferences']->getMailDir().'/*');
sort($list);
$tree = array();
foreach($list as $l){
$path = explode('/',$l);
$count = count($path);
$next = &$tree; $i=0;
foreach($path as $p){
if($i<$count-1){
if(!$next[$p])
$next[$p] = array();
$next = &$next[$p];
}
else
$next[$p] = $l;
$i++;
}
}
return $tree;
}
function get_choose_folders_presentation($tree=false,$key='',$margin=''){
$res = '';
if(!$tree){
$tree = $this->get_tree();
$first=true;
}
if(is_array($tree)){
while(count($tree) == 1){
list($cur_key,$cur) = each($tree);
if(is_array($cur)){
$tree = &$cur;
$key .= $cur_key.'/';
}
else
break;
}
$res .= '<tr><td colspan="2" width="100%">'.$margin.'<b>'.$key."</b></td></tr>\n";
if(is_array($tree)){
foreach($tree as $k=>$t){
$new_margin = str_replace('—',' ',str_replace('|',' ',$margin)).' |——';
$res .= $this->get_choose_folders_presentation($t,$k,$new_margin);
}
$res .= "\n";
}
else{
$new_margin = str_replace('—',' ',str_replace('|',' ',$margin)).' |——';
$res .= $this->get_choose_folders_presentation($tree,basename($tree),$new_margin);
}
}
else if($tree!=$_SESSION['procmail']->inbox_name){
$mbox = $this->find($tree);
$res .=
'<tr>'.
'<td width="100%" class="nowrap">'.
$margin.
(($tree!=$_SESSION['preferences']->getFccMailbox() &&
$tree!=$_SESSION['preferences']->getDraftMailbox() &&
$tree!=$_SESSION['preferences']->getRestoredMailbox())?
'<input type="checkbox" name="boxes[]" value="'.$tree.'" '.($mbox!==null?'checked="checked"':'').'/>':
' ').
' '.$key.' '.
($mbox!==null?'<sup>'.$mbox->get_info().'</sup>':'').
'</td>'.
'<td class="right nowrap">'.
($mbox!=null?
'<a href="'.$_SERVER['PHP_SELF'].'?action=folders-show-rename&mailbox='.$tree.'">rename</a>'.
' '.
'<a href="'.$_SERVER['PHP_SELF'].'?action=folders-empty&mailbox='.$tree.'">empty</a>'.
' '.
'<a href="'.$_SERVER['PHP_SELF'].'?action=folders-delete&mailbox='.$tree.'" class="confirm">delete</a>':
'').
"</td></tr>\n";
}
if($first)
return '<table width="100%" class="transparent">'.$res.'</table>';
return $res;
}
function get_simple_choose_folders_presentation($tree=false,$key='',$margin=''){
$res = '';
if(!$tree){
$tree = $this->get_tree();
}
if(is_array($tree)){
while(count($tree) == 1){
list($cur_key,$cur) = each($tree);
if(is_array($cur)){
$tree = &$cur;
$key .= $cur_key.'/';
}
else
break;
}
$res .= $margin.'<b>'.$key."</b>\n";
if(is_array($tree)){
foreach($tree as $k=>$t){
$new_margin = str_replace('—',' ',str_replace('|',' ',$margin)).' |—';
$res .= $this->get_simple_choose_folders_presentation($t,$k,$new_margin);
}
$res .= "\n";
}
else{
$new_margin = str_replace('—',' ',str_replace('|',' ',$margin)).' |—';
$res .= $this->get_simple_choose_folders_presentation($tree,basename($tree),$new_margin);
}
}
else if($tree!=$_SESSION['procmail']->inbox_name){
$res .=
$margin.
(($tree!=$_SESSION['preferences']->getFccMailbox() &&
$tree!=$_SESSION['preferences']->getDraftMailbox() &&
$tree!=$_SESSION['preferences']->getRestoredMailbox())?
'<input type="checkbox" name="boxes[]" value="'.$tree.'"'.($this->find($tree)?' checked="checked"':'').'/>':
' ').
' '.$key.
' <span style="'.SMALL_STYLE.'">'.
'<a href="'.$_SERVER['PHP_SELF'].'?action=folders-empty&mailbox='.$tree.'">empty</a>'.
'</span>'.
"<br/>\n";
}
return $res;
}
}
//////////////////////////
// Class for mail header
//////////////////////////
class MailHeader{
var $mbox_name;
var $key;
var $date;
var $id;
var $mime_type;
var $charset;
var $reference;
var $to_personals;
var $to_mail_addresses;
var $to_count;
var $cc_personals;
var $cc_mail_addresses;
var $cc_count;
var $bcc_personals;
var $bcc_mail_addresses;
var $bcc_count;
var $from_personal;
var $from_mail_address;
var $newsgroups;
var $subject;
var $is_unseen;
var $is_deleted;
var $is_answered;
var $is_urgent;
var $size;
var $labels;
var $message_id;
var $notification;
var $_header;
function MailHeader($mbox_name,&$header){
$this->_header = $header;
$this->mbox_name=$mbox_name;
$this->key=$header['key'];
$this->date = $header['date'];
$this->id = $header['message-id'];
$this->reference = $header['in-reply-to'];
$this->mime_type = $header['content-type']['mime-type'];
if(isset($header['content-type']['charset']))
$this->charset = $header['content-type']['charset'];
else if(is_object($_SESSION['preferences']))
$this->charset = $_SESSION['preferences']->getCharset();
// to
$this->to_count = 0;
if(is_array($header['to'])){
reset($header['to']);
// to addresses
foreach($header['to'] as $to){
if($to['mailbox']!='' && $to['host']!='')
$this->to_mail_addresses[] = $to['mailbox']."@".$to['host'];
else if($to['mailbox']!='')
$this->to_mail_addresses[] = $to['mailbox'];
else
$this->to_mail_addresses[] = '';
$this->to_personals[] = $to['personal-decoded'];
$this->to_count++;
}
}
// cc
$this->cc_count = 0;
if(is_array($header['cc'])){
reset($header['cc']);
// to addresses
foreach($header['cc'] as $cc){
if($cc['mailbox']!='' && $cc['host']!='')
$this->cc_mail_addresses[] = $cc['mailbox']."@".$cc['host'];
else if($cc['mailbox']!='')
$this->cc_mail_addresses[] = $cc['mailbox'];
else
$this->cc_mail_addresses[] = '';
$this->cc_personals[] = $cc['personal-decoded'];
$this->cc_count++;
}
}
// bcc
$this->bcc_count = 0;
if(is_array($header['bcc'])){
reset($header['bcc']);
// to addresses
foreach($header['bcc'] as $bcc){
if($bcc['mailbox']!='' && $bcc['host']!='')
$this->bcc_mail_addresses[] = $bcc['mailbox']."@".$bcc['host'];
else if($bcc['mailbox']!='')
$this->bcc_mail_addresses[] = $bcc['mailbox'];
else
$this->bcc_mail_addresses[] = '';
$this->bcc_personals[] = $bcc['personal-decoded'];
$this->bcc_count++;
}
}
// from address
if(isset($header['from'][0])){
$this->from_mail_address = $header['from'][0]['mailbox']."@".$header['from'][0]['host'];
if($header['from'][0]['personal'] != ''){
$this->from_personal = $header['from'][0]['personal-decoded'];
}
}
// newsgroups
if($header['newsgroups']){
$this->newsgroups = $header['newsgroups'];
}
// subject
if($header['subject-decoded'] != ''){
$this->subject = $header['subject-decoded'];
if(isset($this->charset) && $header['subject-charset'] == 'default'){
$this->subject = to_default_charset($this->subject,$this->charset);
}
if(isset($header['subject-charset']) &&
$header['subject-charset'] != 'default' &&
!isset($this->charset)){
$this->charset = $header['subject-charset'];
}
}
else
$this->subject = "none";
$this->is_unseen = ($header['unseen'] || $header['recent']);
$this->is_deleted = $header['deleted'];
$this->is_answered = $header['answered'];
$this->is_urgent = strtolower($header['priority']) == 'urgent';
$this->size = $header['size'];
if(array_not_empty($header['flags'])){
$this->labels = array();
foreach($header['flags'] as $f){
if($f){
foreach($_SESSION['labels']->get_labels() as $k=>$l){
if($f == $k){
$this->labels[] = $k;
}
}
}
}
}
if(isset($header['notification'])){
$this->notification = $header['notification'];
}
if(isset($header['message-id'])){
$this->message_id = $header['message-id'];
}
}
function has_attachment(){
return $this->mime_type === 'multipart/mixed';
}
function is_encrypted(){
return $this->mime_type === 'multipart/encrypted';
}
function is_signed(){
return $this->mime_type === 'multipart/signed';
}
function labels_print(){
$label_properties = $_SESSION['labels']->get_labels();
$lbs = array();
if($this->is_answered){
$lbs[] = '<span style="color: red" title="Answered">A</span>';
}
if($this->is_urgent){
$lbs[] = '<span style="color: red;font-weight: bold;" title="Urgent">!</span>';
}
foreach($this->labels as $l){
$lbs[] =
sprintf('<span style="color: %s" title="%s">%s</span>',
$label_properties[$l]['color'],
$label_properties[$l]['name'],
$label_properties[$l]['shortcut']);
}
return (array_not_empty($lbs)?'<span class="labels">'.implode(',',$lbs).' </span>':'');
}
function cut_string($str){
if(strlen($str) > 405){
$res = preg_split("/\n/",wordwrap($str,45));
return $res[0];
}
return $str;
}
function address_print($personal,$address,$iffull,$ifcut=false){
$personal = trim(preg_replace('/\S+@\S+/','',$personal));
if($iffull){
if($personal != '' && $address=='')
$res = $personal;
else if($personal != '')
$res = $personal." <".$address.">";
else
$res = $address;
}
else{
if($personal != '')
$res = $personal;
else
$res = preg_replace('/(@.+)$/','',$address);
}
return htmlspecialchars(($ifcut)?$this->cut_string($res):$res);
}
function to_print($index,$iffull=false,$ifcut=true){
if(is_array($this->to_personals))
reset($this->to_personals);
if(is_array($this->to_mail_addresses))
reset($this->to_mail_addresses);
return $this->address_print($this->to_personals[$index],
$this->to_mail_addresses[$index],
$iffull);
}
function cc_print($index,$iffull=false,$ifcut=true){
if(is_array($this->cc_personals))
reset($this->cc_personals);
if(is_array($this->cc_mail_addresses))
reset($this->cc_mail_addresses);
return $this->address_print($this->cc_personals[$index],
$this->cc_mail_addresses[$index],
$iffull);
}
function bcc_print($index,$iffull=false,$ifcut=true){
if(is_array($this->bcc_personals))
reset($this->bcc_personals);
if(is_array($this->bcc_mail_addresses))
reset($this->bcc_mail_addresses);
return $this->address_print($this->bcc_personals[$index],
$this->bcc_mail_addresses[$index],
$iffull);
}
function from_print($iffull=false,$ifcut=true){
return $this->address_print($this->from_personal,
$this->from_mail_address,
$iffull);
}
function get_from_address(){
if($this->from_personal)
return $this->from_personal.' <'.$this->from_mail_address.'>';
else
return $this->from_mail_address;
return '';
}
function get_tos_presentation($iffull=false){
$recipients = array();
for($i=0;$i<$this->to_count;$i++)
$recipients[] = '<nobr title="'.$this->to_print($i,true).'">'.$this->to_print($i,$iffull).'</nobr>';
return implode(', ',$recipients);
}
function get_ccs_presentation($iffull=false){
$recipients = array();
for($i=0;$i<$this->cc_count;$i++)
$recipients[] = '<nobr title="'.$this->cc_print($i,true).'">'.$this->cc_print($i,$iffull).'</nobr>';
return implode(', ',$recipients);
}
function get_bccs_presentation($iffull=false){
$recipients = array();
for($i=0;$i<$this->bcc_count;$i++)
$recipients[] = '<nobr title="'.$this->bcc_print($i,true).'">'.$this->bcc_print($i,$iffull).'</nobr>';
return implode(', ',$recipients);
}
function get_all_recepients_presentation($iffull=false){
$recipients = array();
for($i=0;$i<$this->to_count;$i++)
$recipients[] = '<nobr title="'.$this->to_print($i,true).'">'.$this->to_print($i,$iffull).'</nobr>';
for($i=0;$i<$this->cc_count;$i++)
$recipients[] = '<nobr title="'.$this->cc_print($i,true).'">'.$this->cc_print($i,$iffull).'(:cc)</nobr>';
for($i=0;$i<$this->bcc_count;$i++)
$recipients[] = '<nobr title="'.$this->bcc_print($i,true).'">'.$this->bcc_print($i,$iffull).'(:bcc)</nobr>';
if(array_not_empty($recipients))
return implode(', ',$recipients);
else return 'undisclosed recipients';
}
function subject_print(){
return $this->subject_short_print(false);
}
function subject_short_print($ifcut=true){
$subj = html_entity_decode($this->subject,ENT_NOQUOTES,$GLOBALS['DEFAULT_CHARSET']);
$strlen = strlen($subj);
$subj = ($ifcut)?$this->cut_string($subj):$subj;
$add_raquo = ($strlen!=strlen($subj));
$subj = htmlspecialchars($subj);
if($add_raquo) $subj .= " »";
return $subj;
}
function human_date_print(){
$time = time();
$diff = $time - $this->date;
if($diff < 61)
return '1 minute ago';
if($diff < 1800)
return ceil($diff/60).' minutes ago';
if($diff < 2700)
return '½ hour ago';
if($diff < 3600)
return '¾ hour ago';
if($diff < 7200)
return '1 hour ago';
if($diff < 10800)
return ceil($diff/(3600)).' hours ago';
if($diff < 86400 && date('j',$this->date) == date('j',$time))// if <24 hours and this day and
return date('H:i',$this->date);
if($diff < 15552000 && date('Y',$this->date) == date('Y',$time))// if <half year and this year
return date('M d',$this->date);
return date('M d, Y',$this->date);
}
function date_print($iffull=false){
if($iffull)
return date('r',$this->date);
else{
$time = time();
$diff = $time - $this->date;
if($diff < 86400 && date('j',$this->date) == date('j',$time))// if <24 hours and this day and
return date('H:i',$this->date);
if($diff < 15552000 && date('Y',$this->date) == date('Y',$time))// if <falf year and this year
return date('M d',$this->date);
return date('M d, Y',$this->date);
}
}
function print_table_row(){
include(TMPLPATH.'MailHeader_table_row.php');
}
function print_thread_table_row($papa=false,$sons_count=0){
include(TMPLPATH.'MailHeader_thread_table_row.php');
}
}
/////////////////////////////
// Class for mail headers
/////////////////////////////
class MailHeaders{
var $headers;
var $count;
var $name;
var $name_print;
var $sort_order;
var $mailboxes_list;
var $is_pages;
var $num_of_pages;
var $num_of_messages;
var $current_page;
var $has_next_page;
var $has_prev_page;
function MailHeaders($name,$name_print,$sort_order=false,$start_page=1){
$this->name = $name;
$this->name_print = $name_print;
$this->sort_order = $sort_order;
$this->mailboxes_list = get_mailboxes_names($name);
$mp = $this->getMP();
$status = $mp->status($this->name);
$this->num_of_messages = $status['messages'];
$this->current_page = $start_page;
if($this->num_of_messages > $_SESSION['preferences']->getMailsPerPage() && $start_page>0){
$this->is_pages = true;
$this->num_of_pages = ceil($this->num_of_messages/$_SESSION['preferences']->getMailsPerPage());
$this->current_page = min($this->num_of_pages,$start_page);
$res = $this->get_page_from_count($this->current_page);
$headers = $mp->sorted_headers($this->name,$this->sort_order,$res['from'],$res['count']);
}
else
$headers = $mp->sorted_headers($this->name,$this->sort_order);
$this->count = count($headers);
$this->headers = array();
foreach($headers as $k=>$h){
$hh = $this->createMailHeader($this->name,$headers[$k]);
$this->headers[$hh->key] = $hh;
}
}
function getMP(){
return getIMAP($GLOBALS['MAIL_USER_NAME'],$GLOBALS['MAIL_USER_PASSWORD']);
}
// factory for headers
function createMailHeader($name,&$header){
return new MailHeader($name,$header);
}
function get_header($key){
return $this->headers[$key];
}
function print_presentation(){
include(TMPLPATH.'MailHeaders_presentation.php');
}
function init_threads(){
if(isset($this->threads)) return;
$this->threads = array();
$this->threads_count = array();
$mp = $this->getMP();
Cache::initThreads($this->name);
$threads = Cache::getThreads($this->name);
// we need sort threads as headers was sorted
foreach($this->headers as $k=>$h){
foreach($threads['threads'] as $k=>$ids){
if($h->key == $ids[0]){
foreach($ids as $id){
$header = $this->get_header($id);
if(!$header){
$header = $this->createMailHeader($this->name,$mp->get_header($this->name,$id));
$this->headers[$header->key] = $header;
}
$this->threads[$k][] = $header;
}
$this->threads_count[$k] = $threads['count'][$k];
unset($threads['threads'][$k]);
}
}
}
/*
foreach($this->headers as $header){
$subject = strtolower(preg_replace(array('/re:/i','/fwd?:/i','/[\s()!,.]/'),
array('','',''),
$header->subject));
$this->threads[$subject][] = $header;
$this->threads_count[$subject]++;
}
*/
}
function get_page_from_count($page_num){
$res = array();
$res['from'] = $this->num_of_messages-($_SESSION['preferences']->getMailsPerPage()*$page_num)+1;
$res['count'] = $_SESSION['preferences']->getMailsPerPage()-1;
if($res['from'] <= 0){
$res['from'] = 1;
$res['count'] = $this->num_of_messages%$_SESSION['preferences']->getMailsPerPage()-1;
}
return $res;
}
function print_pages_row(){
if($this->is_pages){
$pages = '<u>Pages</u>: ';
for($i=1;$i<=$this->num_of_pages;$i++){
if($i == $this->current_page)
$pages .= " <b>$i</b> ";
else{
$res = $this->get_page_from_count($i);
$pages .=
' <a href="'.$_SERVER['PHP_SELF'].'?action=show-folder&mailbox='.$this->name.
($this->sort_order?'&sort_order='.$this->sort_order:'').
'&start_page='.$i.'" title="'.$res['from'].' - '.($res['from']+$res['count']).'"'.
'>'.$i.'</a>';
}
}
print '<tr><td colspan="6">'.$pages.'</td></tr>';
}
}
function print_controls_row($move=true){
include(TMPLPATH.'MailHeaders_controls_row.php');
}
}
/////////////////////////////
// Class for mail headers thread
/////////////////////////////
class MailHeadersThread{
var $mailbox_name;
var $key;
var $thread;
function MailHeadersThread($mp,$mailbox_name,$key){
$this->mp = $mp;
$this->mailbox_name = $mailbox_name;
$this->key = $key;
$threads = Cache::getThreads($this->mailbox_name);
foreach($threads['tree'] as $tree){
if(in_array_recursive($this->key,$tree)){
$this->thread = $tree;
break;
}
}
}
function has_thread(){ return isset($this->thread); }
function get_presentation($type=false,$tree=-1){
if($type == 'preview')
$action = 'preview-mail';
else
$action = 'read-mail';
if($tree == -1) $tree = $this->thread;
$was_ol=false;
$res = '';
foreach($tree as $t){
if(is_array($t)){
$res .= '<div style="margin-left:15px;">';
$res .= $this->get_presentation($type,$t);
$res .= '</div>';
}
else{
$header = $this->mp->get_header($this->mailbox_name,$t);
$h = new MailHeader($this->mailbox_name,$header);
$res .= $h->key.'. ';
if($h->key == $this->key){
$res .= '<i class="gray">'.$h->subject_print().', '.$h->from_print().', '.$h->human_date_print().'</i>';
}
else{
$res .= '<a href="index.php?action='.$action.'&mailbox='.$this->mailbox_name.'&mailkey='.$t.'">';
$res .= $h->subject_print();
$res .= '</a> ';
$res .= '<i>'.$h->from_print().', '.$h->human_date_print().'</i>';
}
if($h->has_attachment()){
$res .= ' <img src="./images/attachment.gif" alt="attachment"/>';
}
$res .= '<br/>';
}
}
$res .= '';
return $res;
}
}
/////////////////////////////
// Class for nntp mail headers
/////////////////////////////
class NNTPMailHeader extends MailHeader{
function NNTPMailHeader($name,&$header){
parent::MailHeader($name,$header);
}
function print_table_row(){
include(TMPLPATH.'NNTPMailHeader_table_row.php');
}
}
class NNTPMailHeaders extends MailHeaders{
function NNTPMailHeaders($name,$sort_order=SORT_BY_NUMBER){
parent::MailHeaders($name,$name,$sort_order,-1);
}
function getMP(){
return getNNTP();
}
// factory for headers
function createMailHeader($name,&$header){
return new NNTPMailHeader($name,$header);
}
function print_presentation(){
include(TMPLPATH.'NNTPMailHeaders_presentation.php');
}
}
///////////////////////////////////////
// Sub-classes for query mail headers
///////////////////////////////////////
class QueryMailHeader extends MailHeader{
function QueryMailHeader(&$header){
parent::MailHeader($header->mbox_name,$header->_header);
}
function print_table_row(){
include(TMPLPATH.'QueryMailHeader_table_row.php');
}
}
class QueryMailHeaders extends MailHeaders{
function QueryMailHeaders($name,&$headers){
$this->name = $name;
$this->headers = $headers;
$this->count = count($headers);
$this->mailboxes_list = get_mailboxes_names();
}
function print_presentation(){
include(TMPLPATH.'QueryMailHeaders_presentation.php');
}
function print_controls_row($move=true){
include(TMPLPATH.'QueryMailHeaders_controls_row.php');
}
}
/////////////////////////////////////
// Sub-classes for sent mail headers
/////////////////////////////////////
class SentMailHeader extends MailHeader{
var $tocc;
function SentMailHeader($mbox_name,&$header){
parent::MailHeader($mbox_name,$header);
$max_count=3;
$count = 0;
$tocc = array();
for($i=0;$i<$this->to_count;$i++){
if($count<$max_count)
$tocc[] = $this->to_print($i,false,false);
$count++;
}
for($i=0;$i<$this->cc_count;$i++){
if($count<$max_count)
$tocc[] = $this->cc_print($i,false,false);
$count++;
}
if($count>$max_count)
$tocc[] = '…';
$this->tocc = implode(', ',$tocc).(($count>$max_count)?'…':'');
}
function print_table_row(){
include(TMPLPATH.'SentMailHeader_table_row.php');
}
}
class SentMailHeaders extends MailHeaders{
function SentMailHeaders($name,$sort_order=SORT_BY_NUMBER,$start_page=1){
parent::MailHeaders($name,'Sent Mails',$sort_order,$start_page);
}
// factory for headers
function createMailHeader($name,&$header){
return new SentMailHeader($name,$header);
}
function print_presentation(){
include(TMPLPATH.'SentMailHeaders_presentation.php');
}
}
/////////////////////////////////////
// Sub-classes for draft mail headers
/////////////////////////////////////
class DraftMailHeader extends SentMailHeader{
function DraftMailHeader($mbox_name,&$header){
parent::SentMailHeader($mbox_name,$header);
}
function print_table_row(){
include(TMPLPATH.'DraftMailHeader_table_row.php');
}
}
class DraftMailHeaders extends SentMailHeaders{
function DraftMailHeaders($name,$sort_order=SORT_BY_NUMBER,$start_page){
parent::MailHeaders($name,'Draft',$sort_order,$start_page);
}
// factory for headers
function createMailHeader($name,&$header){
return new DraftMailHeader($name,$header);
}
}
///////////////////////////////////////
// Sub-classes for labeled mail headers
///////////////////////////////////////
class LabelMailHeader extends MailHeader{
function LabelMailHeader(&$header){
parent::MailHeader($header->mbox_name,$header->_header);
}
function print_table_row(){
include(TMPLPATH.'LabelMailHeader_table_row.php');
}
}
class LabelMailHeaders extends MailHeaders{
function LabelMailHeaders($label,&$headers){
$this->label = $label;
$this->name = $label;
foreach($_SESSION['labels']->get_labels() as $k=>$v){
if($k == $label){
$this->name = $v['name'];
$this->color = $v['color'];
break;
}
}
$this->headers = $headers;
$this->count = count($headers);
}
function print_presentation(){
include(TMPLPATH.'LabelMailHeaders_presentation.php');
}
}
///////////////////////////////
// Class for part of mail
///////////////////////////////
class MailPart{
var $plain_header;
var $part;
var $body;
var $size;
var $mime_type;
var $parent_mime_type;
var $filename;
var $ifattach;
var $charset;
function MailPart($key,&$part){
$this->plain_headers = $part['header']['all'];
$this->part = $key;
if($part['body']){
if(eregi('base64',$part['header']['encoding']))
$this->body = imap_base64($part['body']);
else if(eregi('quoted-printable',$part['header']['encoding']))
$this->body = imap_qprint($part['body']);
else
$this->body = $part['body'];
$this->size = strlen($this->body)*3/4;
}
else{
$this->body = $part['body'];
$this->size = 0;
}
$this->cid = $part['header']['content-id'];
$this->mime_type = $part['header']['content-type']['mime-type'];
// if we have disposition
if($part['header']['content-disposition']){
if($part['header']['content-disposition']['attachment'])
$this->ifattach = true;
if($part['header']['content-disposition']['filename']){
$arr = imap_string_decode($part['header']['content-disposition']['filename']);
$this->filename = $arr['decoded'];
if($this->filename == '')
$this->filename = $part['header']['content-disposition']['filename'];
// small hack for wrong mime types
if($this->filename != ''){
if(!preg_match('@image/@i',$this->mime_type)){
if(preg_match('/\.jpe?g/i',$this->filename)){
$this->mime_type = 'image/jpeg';
}
else if(preg_match('/\.gif/i',$this->filename)){
$this->mime_type = 'image/gif';
}
else if(preg_match('/\.png/i',$this->filename)){
$this->mime_type = 'image/png';
}
}
}
}
}
else
$this->ifattach = false;
if($part['header']['content-type']['charset'] &&
!eregi('us-ascii',$part['header']['content-type']['charset'])){
$this->charset = $part['header']['content-type']['charset'];
}
// untitled file
if($this->filename == ''){
if($part['header']['content-type']['name']){
$arr = imap_string_decode($part['header']['content-type']['name']);
$this->filename = $arr['decoded'];
if($this->filename == "")
$this->filename = $this->filename = $part['header']['content-type']['name'];
}
else if($this->if_rfc822())
$this->filename = 'RFC-822 Message';
}
// mime type hacks
if(!$this->mime_type)
$this->mime_type = 'text/plain';
else if($this->mime_type === 'application/octet-stream'){
if(preg_match('/\\.html?$/i',$this->filename) &&
preg_match('/<(html|body|table)[^>]*>/i',$this->body)){
$this->mime_type = 'text/html';
}
}
// default charset
if(!isset($this->charset)){
if(is_object($_SESSION['preferences']))
$this->charset = $_SESSION['preferences']->getCharset();
else
$this->charset = $GLOBALS['DEFAULT_CHARSET'];
}
}
function get_charset(){
return $this->charset;
}
// get body converted to default charset
function get_body(){
return to_default_charset($this->body,$this->charset);
}
// get "safe" html body
function get_safe_body(){
require_once(INCPATH.'safe_html.php');
$safehtml =& new HTML_Safe();
return $safehtml->parse($this->get_body());
}
// if we can show part
function if_printable(){
return
!$this->ifattach &&
$this->mime_type == 'text/html' ||
($this->mime_type == 'text/plain' && !$this->if_multipart()) ||
$this->mime_type == 'message/delivery-status';
}
function if_simple_printable(){
return
!$this->ifattach &&
$this->mime_type == 'text/plain' ||
($this->mime_type == 'text/html' && !$this->if_multipart()) ||
$this->mime_type == 'message/delivery-status';
}
function if_multipart(){
return $this->parent_mime_type == 'multipart/alternative';
}
function if_text_multipart(){
return $this->mime_type == 'text/plain' && $this->if_multipart();
}
function if_pgp_signature(){
return $this->mime_type == 'application/pgp-signature';
}
function if_pgp_encrypted(){
return $this->mime_type == 'application/pgp-encrypted';
}
function if_rfc822(){
return $this->mime_type == 'message/rfc822';
}
function if_attachment(){
return
!$this->if_printable() &&
strpos('multipart',$this->mime_type)===false &&
strpos('message/disposition-notification',$this->mime_type)===false &&
strpos('application/pgp-encrypted',$this->mime_type)===false &&
!$this->if_text_multipart();
}
function if_for_forward(){
// debug($this->ifattach);
return
($this->if_attachment() && !$this->if_pgp_signature()) ||
($this->if_printable() && !$this->if_multipart());
}
function nohtml($str){
return preg_replace('/&#([0-9]*);/','&#$1;',htmlspecialchars($str));
}
function nbsp($str){
return str_replace(' ',' ',$str);
}
function handle_replies($text,$wrap=false){
$lines = preg_split("/\n/",$text);
$res = '';
foreach($lines as $l){
// print htmlspecialchars($l)."<br/>";
if(eregi("^((>[ ]*)+)(.*)",$l,$m)){
$depth = strlen(str_replace(' ','',$m[1]));
if($wrap) $tmp = wordwrap($this->nohtml($l."\n"),100);
else $tmp = $this->nohtml($l."\n");
$res2 = explode("\n",$tmp);
if(count($res2)==1){
$res2 = $tmp;
}
else{
$was_empty=false;
foreach($res2 as $k=>$v) if($v==''){unset($res2[$k]);$was_empty=true;}
$res2 = implode("\n".$this->nohtml($m[1]),$res2);
if($was_empty)
$res2 .= "\n";
}
$res .= '<span class="replies'.((($depth-1)%9)+1).'">'.$this->nbsp($res2).'</span>';
}
else{
if($wrap) $res .= $this->nbsp(wordwrap($this->nohtml($l."\n"),100));
else $res .= $this->nbsp($this->nohtml($l."\n"));
}
}
return nl2br($res);
}
// find part number by content id
function find_part_by_cid($cid){
foreach($this->read_mail->parts as $p){
if($cid === $p->cid)
return $p->part;
}
return false;
}
// creating thumbnail for image
function get_thumbnail(){
if($this->thumbnail) return $this->thumbnail;
if(strpos($this->mime_type,'image/') !== 0) return null;
$tmpname = TempFileManager::getTempFile('thumb');
if(file_put_contents($tmpname,$this->body)){
$size = @getimagesize($tmpname);
$w = $size[0];
$h = $size[1];
if($w > 180 || $h > 180){
$out = execute_process("convert -size 180x180 $tmpname\[0\] -resize 180x180 +profile '*' -");
if($out['return'] != 0){
$this->thumbnail = file_get_content('./images/mime-type/image.gif');
}
else
$this->thumbnail = $out['stdout'];
}
else
$this->thumbnail = $this->body;
}
unlink($tmpname);
return $this->thumbnail;
}
// simle presentation
function get_simple_presentation($mailbox,$mailkey){
$res = '';
if($this->if_printable() || $this->if_text_multipart()){
$text = '';
if(eregi('text/html',$this->mime_type)){
$text = html2text($this->get_body(),LINE_WIDTH,true);
}
else{
$text = match_links(
htmlspecialchars(
wordwrap(
trim(preg_replace("/(\s+\n){3,}/",'',$this->get_body())),LINE_WIDTH)));
}
$res .= nl2br($text);
}
else if($this->if_attachment()){
if($this->filename)
$res .= '<b>'.h($this->filename).'</b> ';
$res .= '<i>'.$this->mime_type.'</i><br/>';
if($this->size > 0)
$res .= bytes2string($this->size).' ';
if($this->if_pgp_signature() && isset($this->signature_info)){
if(isset($this->signature_info['error']))
$res .= '<div style="'.RED_STYLE.'">'.nl2br(h($this->signature_info['error'])).'</div>';
else
$res .= '<div>'.nl2br(h($this->signature_info['info'])).'</div>';
}
if($this->need_gpg_passphrase){
$res .= '<hr/>';
$res .= '<form action="'.$_SERVER['PHP_SELF'].'" method="post">';
$res .= '<input type="hidden" name="mailbox" value="'.$mailbox.'"/>';
$res .= '<input type="hidden" name="mailkey" value="'.$mailkey.'"/>';
$res .= '<input type="hidden" name="action" value="gnupg-verify-passphrase"/>';
$res .= 'Enter private key passphrase<br/>in order to decrypt:';
$res .= '<br/>';
$res .= '<input type="password" name="password"/>';
$res .= ' ';
$res .= '<input value="ok" type="submit"/>';
$res .= '<br/>';
$res .= '</form>';
}
// we show images/html in browser
if(eregi('text/',$this->mime_type) || eregi('image/',$this->mime_type)){
$res .= ' '.
'<a href="'.$_SERVER['PHP_SELF']."?action=view-part&mailbox=$mailbox&mailkey=$mailkey".
"&part=".$this->part.'&'.sid().'">view</a>';
}
$res .= ' <a href="'.$_SERVER['PHP_SELF'].'?action=get-part&'.
"mailbox=$mailbox&mailkey=$mailkey&part=".$this->part.'&'.sid().'" '.
'title="click to save">download</a>';
}
return $res;
}
// regular presentation
function get_presentation($mailbox,$mailkey,$for_print=false){
$res = '';
if($this->if_printable()){
if(eregi('text/html',$this->mime_type)){
require_once(INCPATH.'safe_html.php');
$safehtml =& new HTML_Safe();
$res .= '<div class="message">';
$res .= $safehtml->parse($this->get_body());
// $res = preg_replace('/<([\/]?)html/i','<\\1xhtml',$this->get_body());
// $res = preg_replace('/<([\/]?)body/i','<\\1div',$res);
$res = preg_replace('/<a href="mailto:([^"?]+)"/i',
'<a href="'.$_SERVER['PHP_SELF'].'?action=compose&to=$1&'.sid().'" '.
'title="compose mail to $1"',
$res);
if(preg_match_all('/(src|background)="cid:([^"]*)"/i',$res,$match)){
foreach($match[2] as $m){
$p = $this->find_part_by_cid($m);
if($p){
$res = preg_replace('/(src|background)="cid:'.preg_quote($m).'"/i',
'$1="'.$_SERVER['PHP_SELF'].
"?action=get-part&mailbox=$mailbox&mailkey=$mailkey&part=".$p.'"',$res);
}
}
}
$res .= '</div>';
}
else if($for_print){
$res .= '<div class="message mono">'.$this->handle_replies(trim($this->get_body())).'</div>';
}
else{
$res .= '<div class="message mono">';
$res .= match_links($this->handle_replies(trim($this->get_body())));
$res .= '</div>';
}
// add 'save' link
if(!$for_print){
if($this->if_multipart()){
$res .=
'<a href="'.$_SERVER['PHP_SELF'].
"?action=view-part&mailbox=$mailbox&mailkey=$mailkey&part=".previous_part($this->part).'" title="click save as ..." class="small">'.
'view text part</a> ';
}
$res .=
'<a href="'.$_SERVER['PHP_SELF'].
"?action=view-part&mailbox=$mailbox&mailkey=$mailkey&part=".$this->part.'" title="click save as ..." class="small">'.
'save</a>';
}
}
else if($this->if_attachment()){
$res = '<table class="top center" cellpadding="2">';
//if($this->structure->description)
// $res .= 'Description :'.$this->structure->description."<br/>\n";
$res .= '<tr><th class="top center">';
if(eregi('image/',$this->mime_type)){
$tmpname = TempFileManager::getTempFile('img');
file_put_contents($tmpname,$this->body);
$size = @getimagesize($tmpname);
unlink($tmpname);
if($size[0] > MAX_IMG_WIDTH){
$w = MAX_IMG_WIDTH;
$h = intval((MAX_IMG_WIDTH*$size[1])/$size[0]);
}
else{
$w = $size[0];
$h = $size[1];
}
// Link for javascript little window
$res .=
'<a href="'.$_SERVER['PHP_SELF']."?action=view-part&mailbox=$mailbox&mailkey=$mailkey&part=".$this->part.'&'.sid().'">'.
//'<a onclick="rs('."'".$_SERVER['PHP_SELF']."?action=view-part&mailbox=$mailbox&mailkey=$mailkey".
//"&part=".$this->part.'&'.sid()."',".($w+40).','.($h+40).');">'.
'<img class="enlarge" src="'.$_SERVER['PHP_SELF']."?action=get-part&mailbox=$mailbox&mailkey=$mailkey".
"&part=".$this->part.'&thumbnail=ok&'.sid().'" '.
'title="'.strtolower($this->mime_type).'" alt="'.h($this->filename).'" name="'.$this->filename.'"/>'.
'</a>';
}
else{
$res .= '<img src="images/mime-type/'.(get_mime_icon($this->mime_type)).'" title="'.strtolower($this->mime_type).'" alt="'.strtolower($this->mime_type).'"/>';
}
$res .= '</th><td class="middle">';
// signature info
if($this->if_pgp_signature() && isset($this->signature_info)){
if(isset($this->signature_info['error']))
$res .= '<div class="small red">'.nl2br(h($this->signature_info['error'])).'</div>';
else
$res .= '<div class="small">'.nl2br(h($this->signature_info['info'])).'</div>';
}
else{
$res .= '<b>'.($this->filename?$this->filename:"Untitled part").'</b><br/>';
$res .= bytes2string($this->size).' ';
}
// we show images/html in browser
if(eregi('text/',$this->mime_type) || eregi('image/',$this->mime_type)){
$res .= ' '.
'<a href="'.$_SERVER['PHP_SELF']."?action=view-part&mailbox=$mailbox&mailkey=$mailkey".
"&part=".$this->part.'&'.sid().'" target="_blank">view</a>';
}
// can be converted to html
if($converted_to = ToHtmlConverter::is_supported($this->mime_type)){
$res .=
'<a href="'.$_SERVER['PHP_SELF'].'?action=view-part&'.
"mailbox=$mailbox&mailkey=$mailkey&part=".$this->part.'&'.sid().'" '.
'title="view as HTML">view as '.$converted_to.'</a>';
}
if($this->size > 0){
$res .= ' '.
'<a href="'.$_SERVER['PHP_SELF'].'?action=get-part&'.
"mailbox=$mailbox&mailkey=$mailkey&part=".$this->part.'&'.sid().'" '.
'title="click to save">download</a>';
$res .=
' <a onclick="rs('."'".$_SERVER['PHP_SELF']."?action=scan-virus-part&mailbox=$mailbox&mailkey=$mailkey".
"&part=".$this->part."',".'350,50);">'.
'scan for viruses'.
'</a>';
}
$res .= '</td></tr>';
$res .= '</table>';
}
// if error
if($this->error)
$res = '<div class="red small" style="float:right">'.h($this->error).'</div>'.$res;
// if decrypted
if($this->decrypted)
$res = '<img src="./images/encrypted.gif" title="decrypted" alt="decrypted" style="float:right"/>'.$res;
// gpg passphrase form
if($this->need_gpg_passphrase){
$res .= '<form action="'.$_SERVER['PHP_SELF'].'" method="post">';
$res .= '<input type="hidden" name="mailbox" value="'.$mailbox.'"/>';
$res .= '<input type="hidden" name="mailkey" value="'.$mailkey.'"/>';
$res .= '<input type="hidden" name="action" value="gnupg-verify-passphrase"/>';
$res .= '<table class="notice">';
$res .= '<tr><td class="right">';
$res .= 'Enter private key passphrase<br/>in order to decrypt:';
$res .= '</td><td class="middle">';
$res .= '<input type="password" name="password"/>';
$res .= ' ';
$res .= '<input value="ok" type="submit"/>';
$res .= '</td></tr></table>';
$res .= '</form>';
}
return $res;
}
}
// previous part
function previous_part($part){
$arr = explode('.',$part);
$arr[count($arr)-1]--;
return implode('.',$arr);
}
///////////////////////////
// Getting single part
///////////////////////////
function get_part($mailbox,$mailkey,$part){
$mp = getIMAP();
$mail = $mp->get_mail($mailbox,$mailkey);
$parts = explode(".",$part);
foreach($parts as $p){
if(!$mail)
trigger_error("$mailbox:$mailkey".'->'."$part is null.<br/>\n",
E_USER_ERROR);
if(array_not_empty($mail['parts']))
$mail = $mail['parts'][$p];
}
$mail_part = new MailPart($part,$mail);
return $mail_part;
}
function print_parts(&$mail,$key=false){
print "<b>$key</b> ".$mail['header']['content-type']['mime-type'];
if(is_array($mail['parts'])){
print '<ul>';
foreach($mail['parts'] as $k=>$p){
print '<li>';
print_parts($p,$key?"$key.$k":$k);
print '</li>';
}
print '</ul>';
}
}
// getting all parts of message (recursive helper)
function get_parts(&$mail,$key=false){
$arr = array();
if(is_array($mail['parts'])){
foreach($mail['parts'] as $k=>$p){
$ret_arr = &get_parts($p,$key?"$key.$k":$k);
foreach($ret_arr as $kk=>$pp){
if(!isset($pp->parent_mime_type) &&
(strpos("$pp->part","$key") === 0 ||
($key===false && strpos($pp->part,'.') === false))){
$ret_arr[$kk]->parent_mime_type = $mail['header']['content-type']['mime-type'];
}
}
$arr = array_merge($arr,$ret_arr);
}
}
else
$arr[] = new MailPart($key?$key:1,$mail);
return $arr;
}
/////////////////////
// Reading of mail
/////////////////////
class ReadMail{
var $_mailbox;
var $mailbox_name;
var $mailbox_name_print;
var $ifnntp;
var $header;
var $key;
var $parts_count;
var $parts;
var $iffirst;
var $iflast;
var $mailboxes_list;
var $charset;
function ReadMail(&$mailbox,$key){
if($mailbox == false)
throw new Exception('Mailbox is null');
if(eregi('^NNTPMBox$',get_class($mailbox)))
$this->ifnntp = true;
$this->_mailbox = $mailbox;
$this->mailbox_name = $mailbox->name;
$this->mailbox_name_print = $mailbox->name_print;
$this->key = $key;
$mp = $mailbox->getMP();
// get parsed mail
$mail = $mp->get_mail($this->mailbox_name,$key);
// if(is_test_user()) print_parts($mail);
$this->header = new MailHeader($this->mailbox_name,$mail['header']);
// NNTP has no threads
if(!$this->ifnntp && $_SESSION['preferences']->getDefaultView() == 'thread'){
$this->thread = new MailHeadersThread($mp,$this->mailbox_name,$this->key);
}
// get parts
$this->parts = get_parts($mail);
// GnuPG support: decrypt parts if its encrypted and verify signature
if($_SESSION['preferences']->getUseGnuPG()){
require_once('simple_gpg.php');
$gpg = new SimpleGPG();
$new_parts = array();
$was_encrypted = false;
$changed = false;
foreach($this->parts as $part_key=>$part){
if($part->if_pgp_encrypted()){
$was_encrypted = true;
}
// if was pgp-encrypted part befor or inline PGP message
else if($was_encrypted || $gpg->isInlinePGPMessage($part->body)){
$ret = $gpg->decrypt($part->body);
if($ret['returnval'] === 0){
$parser = new MailParser();
$mail = $parser->parse_mail($ret['plaintext']);
// just body
if($mail === false){
list($before,,$after) = $gpg->separatePGPMessage($part->body);
if($before != ''){
$dummy_part = new MailPart(count($new_parts)+1,$dummy_mail=array());
$dummy_part->mime_type = $part->mime_type;
$dummy_part->body = $before;
$new_parts[] = $dummy_part;
}
$part->part = count($new_parts)+1;
$part->body = $ret['plaintext'];
$part->decrypted = true;
$new_parts[] = $part;
if($after != ''){
$dummy_part = new MailPart(count($new_parts)+1,$dummy_mail=array());
$dummy_part->mime_type = $part->mime_type;
$dummy_part->body = $after;
$new_parts[] = $dummy_part;
}
}
else{
// get parts
$decrypted_parts = get_parts($mail);
foreach($decrypted_parts as $k=>$p){
$decrypted_parts[$k]->decrypted = true;
}
// add parts
$new_parts = array_merge($new_parts,$decrypted_parts);
}
// if encryption signid
if(isset($ret['GnuPGSignature']) && is_object($ret['GnuPGSignature'])){
// dummy signature part
$sig_part = new MailPart(count($new_parts)+1,$sig_mail=array());
$sig_part->ifattach = true;
$sig_part->mime_type = 'application/pgp-signature';
$sig_part->signature_info = array('info'=>$ret['signature'][0]."\n".$ret['signature'][1]);
$new_parts[] = $sig_part;
}
// trigger
$changed = true;
$was_encrypted = false;
}
else{
if(Cache::haveCachedGPGPassphrase())
$part->error = 'Can\'t decrypt, probably not your private key.';
else
$part->need_gpg_passphrase = true;
}
}
else{
// signature
if($part->if_pgp_signature() || $gpg->isInlinePGPSignature($part->body)){
// hack for inline
if(!$part->if_pgp_signature() && $gpg->isInlinePGPSignature($part->body)){
$new_parts[] = $part;
list($before,$signed,$after) = $gpg->separatePGPSignature($part->body);
$ret = $gpg->verifyInline($signed);
// part is new "dummy" signature part
$part = new MailPart(count($new_parts)+1,$sig_mail=array());
$part->ifattach = true;
$part->mime_type = 'application/pgp-signature';
}
else{
// take previous for signature part
$for_verify = $mail['parts'][$part->part-1]['source'];
$signature = $part->body;
$ret = $gpg->verify($for_verify,$signature);
}
if($ret['returnval'] === 0){
$part->signature_info = array('info'=>$ret['signature'][0]."\n".$ret['signature'][1]);
}
else{
if(is_object($ret['GnuPGSignature']))
$part->signature_info = array('error'=>$ret['signature'][0]."\n".$ret['signature'][1]);
else
$part->signature_info = array('error'=>'Signature verification error.');
}
$changed = true;
$new_parts[] = $part;
}
else
$new_parts[] = $part;
}
}
if($changed)
$this->parts = $new_parts;
}
// set $this for some of mails
foreach($this->parts as $k=>$part){
if($part->if_printable() && eregi('/html',$part->mime_type)){
$this->parts[$k]->read_mail =& $this;
}
}
if(is_object($_SESSION['preferences']))
$this->charset = $_SESSION['preferences']->getCharset();
else
$this->charset = $GLOBALS['DEFAULT_CHARSET'];
if($mail['header']['content-type']['charset'] &&
!eregi('us-ascii',$mail['header']['content-type']['charset'])){
$this->charset = $mail['header']['content-type']['charset'];
}
else{
foreach($this->parts as $p){
if($p->if_printable()){
$this->charset = $p->get_charset();
break;
}
}
}
if($mail['header']['subject-charset'] != 'default' && $this->charset !== $mail['header']['subject-charset']){
$this->charset = $mail['header']['subject-charset'];
}
$this->parts_count = count($this->parts);
reset($this->parts);
$this->iffirst = ($this->key == 1);
$status = $mp->status($this->mailbox_name);
$this->iflast = ($this->key == $status['messages']);
$this->mailboxes_list = get_mailboxes_names($this->mailbox_name);
}
function get_part($part){
foreach($this->parts as $p){
if($p->part == $part) return $p;
}
return false;
}
function get_charset(){
return $this->charset;
}
function get_full_mail_header(){
return $this->header->_header['all'];
}
function print_presentation(){
include(TMPLPATH.'ReadMail_presentation.php');
}
function print_preview_presentation(){
include(TMPLPATH.'ReadMail_preview_presentation.php');
}
function print_printable_presentation(){
include(TMPLPATH.'ReadMail_printable_presentation.php');
}
function print_controls_table(){
include(TMPLPATH.'ReadMail_controls.php');
}
}
?>