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 '| Num | De | Sujet | Date | 
'."\n";
		print '
  | 
'."\n";
		$ctc = 0;
		if (is_file($cache)) {
			include($cache);
		}
		print ' | 
'."\n";
        print '
'."\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 .= ''.$valeur.' | ' ;
		$res .=" 
\n";
		while (list($key,$val) = each($threadcount)) {
			$res .= " \n";
			$res .= "  | $key | ";
			for ($i = 1; $i <= 12; $i++) {
				if (isset($threadcount[$key][$i]) && $threadcount[$key][$i] > 0) {
					$res .= "tablecolours[0] . "\" valign=\"middle\">";
                    $res .= $this->makelink('action=show_month&actionargs[]='.$key.($i < 10 ? '0'.$i:$i),$threadcount[$key][$i]);
					$res .= " | ";
				} else {
					$res .= "tablecolours[0] . "\"> | ";
				}
			}
			$res .= "
\n";
		}
		$res .= "
\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;
	}
}
?>