tmpdir and are serialized // php objects that can be unserialized and displayed easily // -------------------------------------------------------------- require_once("ezmlm.php"); require_once("ezmlm-parser.php"); require_once ('ezmlm-langue-fr.php'); // CLASS: ezmlm_threads will build, maintain & display thread files (even if a thread is only 1 msg) class ezmlm_threads extends ezmlm_php { // load: this is the main function that should be called. // it first checks to see if the cache files are stale, if they are it calls build // other wise it loads them and calls display function load($month) { if (!is_dir($this->tempdir . "/ezmlm-php-" . $this->listname)) { $checksum = $this->tempdir . "/ezmlm-php-" . $this->listname . "-" . $month . "-" . "checksum"; } else { $checksum = $this->tempdir . "/ezmlm-php-" . $this->listname . "/" . $month . "-" . "checksum"; } $md5 = '' ; if (!is_file($checksum)) { $this->build($month); } else { $fd = fopen($checksum,"r"); while (!preg_match('/^md5:/', $md5)) { $md5 = fgets($fd,4096); } fclose($fd); $md5 = rtrim(preg_replace('/^md5:/', '', $md5), "\n"); if ($md5 != $this->md5_of_file($this->listdir . "/archive/threads/" . $month)) { print "\n"; $this->build($month); } } $this->display($month); } // display: this loads each cache file sequentially and displays the messages in them // there is no checking of checksum's done here so load() is the preferred method to // view the threads function display($month) { $seq = 0; if (!is_dir($this->tempdir . "/ezmlm-php-" . $this->listname)) { $cache = $this->tempdir . "/ezmlm-php-" . $this->listname . "-" . $month; } else { $cache = $this->tempdir . "/ezmlm-php-" . $this->listname . "/" . $month; } // Le lien par date et par thread echo '[ '.$this->makelink('action=show_month&actionargs[]='.$month, 'par date').' ]' ; $months = array(1 => 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'); // remplacé par le tableau globals $mois dans ezmlm.php print '

'.FIL_DE_DISCUSSION.' pour '.$GLOBALS['mois'][((int)substr($month,4,2) / 1)] .', ' . substr($month,0,4) . '

'."\n"; print ''."\n"; print ''."\n"; print ''."\n"; $ctc = 0; if (is_file($cache)) { include($cache); } print ''."\n"; print '
NumDeSujetDate

'."\n"; } function thread_to_html($thread) { $html = ''; $lastdepth = -1; $ctc = 0 ; $thread_curr = $thread; $class = array ('ligne_paire', 'ligne_impaire') ; while ($thread_curr != NULL) { preg_match ('!/archive/([0-9]*)/([0-9]*)!', $thread_curr->file, $match) ; if (!isset($GLOBALS['fichiers_analyses'][$match[1]][$match[2]])) { $message = file_get_contents($this->listdir . "/archive/" . $msgdir . "/" . $msgfile) ; $mimeDecode = new Mail_mimeDecode($message) ; $mailDecode = $mimeDecode->decode() ; //$msg = new ezmlm_parser(); //$msg->parse_file($this->listdir . $thread_curr->file, TRUE); } else { $mailDecode = $GLOBALS['fichiers_analyses'][$match[1]][$match[2]] ; } $actionargs = preg_split("/\//", $thread_curr->file); $html .= ''."\n"; $html .= ''.$actionargs[2].$actionargs[3].''; $html .= $this->makelink('action=show_author_msgs&actionargs[]='. $this->makehash($this->decode_iso($mailDecode->headers['from'])),$this->decode_iso($this->protect_email($mailDecode->headers['from'],TRUE))); $html .= ''."\n"; $html .= ''; //$html .= " file) . "\">"; A quoi ça sert ? for ($i = 0; $i < $thread_curr->depth; $i++) { $html .= "  "; } if (($this->thread_subjlen > 0) and (strlen($this->decode_iso($mailDecode->headers['subject'])) > $this->thread_subjlen)) { $subject = substr($this->decode_iso($mailDecode->headers['subject']), 0, ($this->thread_subjlen - 3 - ($thread_curr->depth * 2))); $subject = $subject . "..."; } else { $subject = $this->decode_iso($mailDecode->headers['subject']); } $subject = preg_replace("/\[" . $this->listname . "\]/", "", $subject); $html .= $this->makelink("action=show_msg&actionargs[]=" . $actionargs[2] . "&actionargs[]=" . $actionargs[3], $subject); $html .= "\n"; $html .= '' .$this->date_francaise($mailDecode->headers['date']).''."\n"; $html .= "\n"; $ctc++; if ($ctc == count($this->tablecolours)) { $ctc = 0; } $lastdepth = $thread_curr->depth; $thread_curr = $thread_curr->next; } $html .= '
'."\n"; return $html; } // build: takes one argument in the format YYYYMM and builds the thread cache file // for that month if the ezmlm thread file exists. The resulting cache file is then // stored in $this->tmpdir; function build($month) { if (!is_file($this->listdir . "/archive/threads/" . $month)) { return FALSE; } if (!is_dir($this->tempdir . "/ezmlm-php-" . $this->listname)) { $fd2 = fopen($this->tempdir . "/ezmlm-php-" . $this->listname . "-" . $month,"w+"); } else { $fd2 = fopen($this->tempdir . "/ezmlm-php-" . $this->listname . "/" . $month,"w+"); } fclose($fd2); $i=0; // ouverture du fichier thread de ezmlm // Ils sont classés mois par mois $fd1 = fopen($this->listdir . "/archive/threads/" . $month, "r"); while (!feof($fd1)) { $line = fgets($fd1,4096); if (preg_match('/^[0-9]*\:[a-z]* \[.*/', $line)) { // valid ezmlm thread file entry // On place dans $subjectfile le chemin vers le fichier sujet $subjectfile = preg_replace("/^[0-9]*\:([a-z]*) \[.*/", "\\1", $line); $subjectfile = substr($subjectfile,0,2) . '/' . substr($subjectfile,2,18); $thread_head = NULL; $thread_curr = NULL; $thread_temp = NULL; $thread_depth = 1; if (!is_file($this->listdir . "/archive/subjects/" . $subjectfile)) { continue; } // on ouvre le fichier sujet // Celui-ci contient sur la première ligne le hash du sujet puis le sujet // sur les autres lignes : // num_message:annéemois:hash_auteur nom_auteur $fd2 = fopen($this->listdir . "/archive/subjects/" . $subjectfile, "r"); while (!feof($fd2)) { $line2 = fgets($fd2,4096); if (preg_match('/^[0-9]/',$line2)) { $msgnum = preg_replace('/^([0-9]*):.*/', '\\1', $line2); $msgfile = $msgnum % 100; $msgdir = (int)($msgnum / 100); if ($msgfile < 10) { $msgfile = "0" . $msgfile; } //$msg = new ezmlm_parser(); //$msg->parse_file_headers($this->listdir . "/archive/" . $msgdir . "/" . $msgfile, TRUE); $message = file_get_contents($this->listdir . "/archive/" . $msgdir . "/" . $msgfile) ; $mimeDecode = new Mail_mimeDecode($message) ; $mailDecode = $mimeDecode->decode() ; // On stocke le fichier analysée pour réutilisation ultàrieure $GLOBALS['fichiers_analyses'][$msgdir][$msgfile] = $mailDecode ; $msgid = (isset ($mailDecode->headers['message-id']) ? $mailDecode->headers['message-id'] : ''); $inreply = (isset($mailDecode->headers['in-reply-to']) ? $mailDecode->headers['in-reply-to'] : ''); $references = (isset ($mailDecode->headers['references']) ? $mailDecode->headers['references'] : '') ; $thread_depth = 1; if ($thread_head == NULL) { $thread_head = new ezmlm_thread(0,'/archive/' . $msgdir . '/' . $msgfile,$msgid); } else { $thread_curr = new ezmlm_thread($depth,'/archive/' . $msgdir . '/' . $msgfile,$msgid); if ($inreply != '') { $thread_curr->inreply = $inreply; } if ($references != '') { $thread_curr->references = $references; } $thread_head->append($thread_curr); } } } fclose($fd2); // so now after all that mess $thread_head contains a full thread tree // first build the depth of each message based on 'in-reply-to' and 'references' unset($thread_temp); $thread_temp = NULL; $thread_curr =& $thread_head->next; while (get_class($thread_curr) == 'ezmlm_thread') { unset($thread_temp); $thread_temp = NULL; if ($thread_curr->inreply != '') { $thread_temp =& $thread_head->find_msgid($thread_curr->inreply); } if ($thread_temp == NULL) { if ($thread_curr->references != '') { $refs = preg_split('/ /', $thread_curr->references); $refs = array_pop($refs); $thread_temp =& $thread_head->find_msgid($refs); } } if ($thread_temp == NULL) { // we couldn't find anything... set depth to 1, the default $thread_curr->depth = 1; } else { // we found a reference, set it to it's depth + 1 $thread_curr->depth = $thread_temp->depth + 1; } $thread_curr =& $thread_curr->next; } // now write it to a temp file named MONTH-SEQ where seq is cronologic sequence order of the thread. if (!is_dir($this->tempdir . "/ezmlm-php-" . $this->listname)) { @mkdir($this->tempdir . "/ezmlm-php-" . $this->listname, 0755); if (!is_dir($this->tempdir . "/ezmlm-php-" . $this->listname)) { $fd2 = fopen($this->tempdir . "/ezmlm-php-" . $this->listname . "-" . $month, "a"); } else { $fd2 = fopen($this->tempdir . "/ezmlm-php-" . $this->listname . "/" . $month, "a"); } } else { $fd2 = fopen($this->tempdir . "/ezmlm-php-" . $this->listname . "/" . $month, "a"); } fputs($fd2,$this->thread_to_html($thread_head)); fclose($fd2); } } // finally store our checksum if (!is_dir($this->tempdir . "/ezmlm-php-" . $this->listname)) { $fd2 = fopen($this->tempdir . "/ezmlm-php-" . $this->listname . "-" . $month . "-" . "checksum","w+"); } else { $fd2 = fopen($this->tempdir . "/ezmlm-php-" . $this->listname . "/" . $month . "-" . "checksum","w+"); } fputs($fd2,"md5:" . $this->md5_of_file($this->listdir . "/archive/threads/" . $month) . "\n"); fclose($fd2); fclose($fd1); return TRUE; } // listmessages: prints out a nice little calendar and displays the message // totals for each month. The link jumps to the thread listing. // On lit le répertoire archive/threads/ qui contient un fichier par moi avec tous les thread, par sujet // Présentés comme suit // num_thread:hash [taille_du_thread] Sujet du thread (le dernier) // les messages sont rangés par leur numéro function listmessages() { if (!is_dir($this->listdir . "/archive/threads/")) { return false ; } $threadcount = array(); $repertoire_archive = opendir($this->listdir . "/archive/"); while (false !== ($item = readdir($repertoire_archive))) { // $item contient les noms des repertoires // on ne garde que ceux qui sont des chiffres if (preg_match('/[0-9]+/', $item)) { // on ouvre le fichier d index de chaque repertoire $fichier_index = fopen($this->listdir.'/archive/'.$item.'/index', 'r'); $compteur = 0 ; while (!feof($fichier_index)) { // On ignore la premiere ligne $temp = fgets($fichier_index, 4096); // dans la seconde on recupere la date $temp = fgets($fichier_index, 4096); preg_match('/\t([0-9]+) ([a-zA-Z][a-zA-Z][a-zA-Z]) ([0-9][0-9][0-9][0-9])/', $temp, $match) ; if ($match[0] != '') { $threadmonth = date('n', strtotime($match[0])) ; $threadyear = date('Y', strtotime($match[0])) ; $threadcount[$threadyear][$threadmonth]++; } } fclose ($fichier_index); } } // La partie qui suit, simple, crée la table avec le nombre de message échangé chaque mois $res = ''."\n"; $res .= " \n"; $res .= " " ; foreach ($GLOBALS['mois'] as $valeur) $res .= '' ; $res .=" \n"; while (list($key,$val) = each($threadcount)) { $res .= " \n"; $res .= " "; for ($i = 1; $i <= 12; $i++) { if (isset($threadcount[$key][$i]) && $threadcount[$key][$i] > 0) { $res .= ""; } else { $res .= ""; } } $res .= "\n"; } $res .= "
'.$valeur.'
$keytablecolours[0] . "\" valign=\"middle\">"; $res .= $this->makelink('action=show_month&actionargs[]='.$key.($i < 10 ? '0'.$i:$i),$threadcount[$key][$i]); $res .= "tablecolours[0] . "\">
\n"; echo $res ; } } // CLASS: ezmlm-thread is a quick little class to allow us to define // a structure of the current thread in a single-linked list. // it's a little messy since php doesn't support pointers like C does // so we have to use references and a head object to append to the list. class ezmlm_thread { var $next; var $depth; var $file; var $msgid; var $inreply; var $references; function append($thread) { $thread_curr =& $this; while ($thread_curr->next != NULL) { $thread_curr =& $thread_curr->next; } $thread_curr->next = $thread; } function &find_msgid($msgid) { $thread_curr =& $this; while ($thread_curr->next != NULL) { if (trim($thread_curr->msgid) == trim($msgid)) { return $thread_curr; } $thread_curr =& $thread_curr->next; } return NULL; } function ezmlm_thread($depth,$file,$msgid) { $this->depth = $depth; $this->file = $file; $this->msgid = $msgid; $this->next = NULL; } } ?>