Rev 2 | Rev 44 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php// $Id: ezmlm-threads.php,v 1.2 2005-09-27 16:43:08 alexandre_tb Exp $//// ezmlm-threads.php - ezmlm-php v2.0// --------------------------------------------------------------// Builds, maintains & displays thread caches// These cache files live in $ezmlm->tmpdir and are serialized// php objects that can be unserialized and displayed easily// --------------------------------------------------------------require_once("ezmlm.php");require_once("ezmlm-parser.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 displayfunction 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 "<!-- $md5 ne " . $this->md5_of_file($this->listdir . "/archive/threads/" . $month) . " -->\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 threadsfunction 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 threadecho '[ '.$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.phpprint '<h2>'.PROJET_FILE_DE_DISCUSSION.' pour '.$GLOBALS['mois'][((int)substr($month,4,2) / 1)] .', ' . substr($month,0,4) . '</h2>'."\n";print '<table class="table_cadre">'."\n";print '<tr><th>Num</th><th>De</th><th>Sujet</th><th>Date</th></tr>'."\n";print '<tr><td colspan="3"><hr /></td></tr>'."\n";$ctc = 0;if (is_file($cache)) {include($cache);}print '<tr><td colspan="3"></td></tr>'."\n";print '</table>'."\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 .= '<tr class="'.$class[$ctc].'">'."\n";$html .= '<td>'.$actionargs[2].$actionargs[3].'</td><td>';$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 .= '</td>'."\n";$html .= '<td><b>';//$html .= " <a name=\"" . urlencode($thread_curr->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 .= "</b></td>\n";$html .= '<td>' .$this->date_francaise($mailDecode->headers['date']).'</td>'."\n";$html .= "</tr>\n";$ctc++;if ($ctc == count($this->tablecolours)) { $ctc = 0; }$lastdepth = $thread_curr->depth;$thread_curr = $thread_curr->next;}$html .= '<tr><td colspan="3"><hr noshade size="1" /></td></tr>'."\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 checksumif (!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épetoire 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érofunction listmessages() {if (!is_dir($this->listdir . "/archive/threads/")) {return false ;}$dir = opendir($this->listdir . "/archive/threads/");while ($item = readdir($dir)) {if (($item == ".") or ($item == "..")) { continue; }// Le nom du fichier est annéemoi ex 200501 pour janvier 2005if (preg_match("/^[0-9][0-9][0-9][0-9][0-9][0-9]/",$item)) {// on ouvre chaque fichier en lecture$fd = fopen($this->listdir . "/archive/threads/" . $item, "r");$count = 0; // on initialise un compteurwhile(!feof($fd)) {$curthread = fgets($fd,4096);$num = preg_replace("/.*\[([0-9].*)\].*/", "\\1", $curthread); // $num contient le nbre de message du thread$count = $count + $num;}$threadyear = substr($item,0,4);$threadmonth = substr($item,4,2);// on construit un tableau à 2 entrée [année][mois] = nbre_message$threadcount[$threadyear][$threadmonth] = $count;}}closedir($dir);arsort($threadcount); // modifié par alex, car remplace l'année par 0// La partie qui suit, simple, crée la table avec le nombre de message échangé chaque mois$res = '<table border="0" cellpadding="4" cellspacing="1">'."\n";$res .= " <tr>\n";$res .= " <td></td>" ;foreach ($GLOBALS['mois'] as $valeur) $res .= '<td>'.$valeur.'</td>' ;$res .=" </tr>\n";while (list($key,$val) = each($threadcount)) {$res .= " <tr>\n";$res .= " <td>$key</td>";for ($i = 1; $i <= 12; $i++) {if ($i < 10) { $key2 = "0" . $i; }else { $key2 = $i; }if (isset($threadcount[$key][$key2]) && $threadcount[$key][$key2] > 0) {$res .= "<td bgcolor=\"" . $this->tablecolours[0] . "\" align=center valign=\"middle\">";$res .= $this->makelink("action=show_month&actionargs[]=$key$key2",$threadcount[$key][$key2]);$res .= "</td>";} else {$res .= "<td bgcolor=\"" . $this->tablecolours[0] . "\"></td>";}}$res .= "</tr>\n";}$res .= "</table>\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;}}?>