2 |
ddelon |
1 |
<?php
|
208 |
neiluj |
2 |
// $Id: ezmlm-threads.php,v 1.5 2007-04-19 15:34:35 neiluj Exp $
|
2 |
ddelon |
3 |
//
|
|
|
4 |
// ezmlm-threads.php - ezmlm-php v2.0
|
|
|
5 |
// --------------------------------------------------------------
|
|
|
6 |
// Builds, maintains & displays thread caches
|
|
|
7 |
// These cache files live in $ezmlm->tmpdir and are serialized
|
|
|
8 |
// php objects that can be unserialized and displayed easily
|
|
|
9 |
// --------------------------------------------------------------
|
|
|
10 |
|
|
|
11 |
require_once("ezmlm.php");
|
|
|
12 |
require_once("ezmlm-parser.php");
|
208 |
neiluj |
13 |
require_once ('ezmlm-langue-fr.php');
|
2 |
ddelon |
14 |
|
|
|
15 |
// CLASS: ezmlm_threads will build, maintain & display thread files (even if a thread is only 1 msg)
|
|
|
16 |
class ezmlm_threads extends ezmlm_php {
|
|
|
17 |
|
|
|
18 |
// load: this is the main function that should be called.
|
|
|
19 |
// it first checks to see if the cache files are stale, if they are it calls build
|
|
|
20 |
// other wise it loads them and calls display
|
|
|
21 |
function load($month) {
|
|
|
22 |
if (!is_dir($this->tempdir . "/ezmlm-php-" . $this->listname)) {
|
|
|
23 |
$checksum = $this->tempdir . "/ezmlm-php-" . $this->listname . "-" . $month . "-" . "checksum";
|
|
|
24 |
} else {
|
|
|
25 |
$checksum = $this->tempdir . "/ezmlm-php-" . $this->listname . "/" . $month . "-" . "checksum";
|
|
|
26 |
}
|
|
|
27 |
$md5 = '' ;
|
|
|
28 |
if (!is_file($checksum)) {
|
|
|
29 |
$this->build($month);
|
|
|
30 |
} else {
|
|
|
31 |
$fd = fopen($checksum,"r");
|
|
|
32 |
while (!preg_match('/^md5:/', $md5)) { $md5 = fgets($fd,4096); }
|
|
|
33 |
fclose($fd);
|
|
|
34 |
$md5 = rtrim(preg_replace('/^md5:/', '', $md5), "\n");
|
|
|
35 |
if ($md5 != $this->md5_of_file($this->listdir . "/archive/threads/" . $month)) {
|
|
|
36 |
print "<!-- $md5 ne " . $this->md5_of_file($this->listdir . "/archive/threads/" . $month) . " -->\n";
|
|
|
37 |
$this->build($month);
|
|
|
38 |
}
|
|
|
39 |
}
|
|
|
40 |
$this->display($month);
|
|
|
41 |
}
|
|
|
42 |
|
|
|
43 |
// display: this loads each cache file sequentially and displays the messages in them
|
|
|
44 |
// there is no checking of checksum's done here so load() is the preferred method to
|
|
|
45 |
// view the threads
|
|
|
46 |
function display($month) {
|
|
|
47 |
$seq = 0;
|
|
|
48 |
if (!is_dir($this->tempdir . "/ezmlm-php-" . $this->listname)) {
|
|
|
49 |
$cache = $this->tempdir . "/ezmlm-php-" . $this->listname . "-" . $month;
|
|
|
50 |
} else {
|
|
|
51 |
$cache = $this->tempdir . "/ezmlm-php-" . $this->listname . "/" . $month;
|
|
|
52 |
}
|
|
|
53 |
// Le lien par date et par thread
|
|
|
54 |
echo '[ '.$this->makelink('action=show_month&actionargs[]='.$month, 'par date').' ]' ;
|
|
|
55 |
$months = array(1 => 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
|
|
|
56 |
// remplacé par le tableau globals $mois dans ezmlm.php
|
208 |
neiluj |
57 |
print '<h2>'.FIL_DE_DISCUSSION.' pour '.$GLOBALS['mois'][((int)substr($month,4,2) / 1)] .', ' . substr($month,0,4) . '</h2>'."\n";
|
2 |
ddelon |
58 |
|
|
|
59 |
print '<table class="table_cadre">'."\n";
|
|
|
60 |
print '<tr><th>Num</th><th>De</th><th>Sujet</th><th>Date</th></tr>'."\n";
|
|
|
61 |
print '<tr><td colspan="3"><hr /></td></tr>'."\n";
|
|
|
62 |
$ctc = 0;
|
|
|
63 |
|
|
|
64 |
if (is_file($cache)) {
|
|
|
65 |
include($cache);
|
|
|
66 |
}
|
|
|
67 |
print '<tr><td colspan="3"></td></tr>'."\n";
|
|
|
68 |
print '</table>'."\n";
|
|
|
69 |
}
|
|
|
70 |
|
|
|
71 |
|
|
|
72 |
function thread_to_html($thread) {
|
|
|
73 |
$html = '';
|
|
|
74 |
$lastdepth = -1;
|
|
|
75 |
$ctc = 0 ;
|
|
|
76 |
$thread_curr = $thread;
|
|
|
77 |
$class = array ('ligne_paire', 'ligne_impaire') ;
|
|
|
78 |
while ($thread_curr != NULL) {
|
|
|
79 |
preg_match ('!/archive/([0-9]*)/([0-9]*)!', $thread_curr->file, $match) ;
|
|
|
80 |
if (!isset($GLOBALS['fichiers_analyses'][$match[1]][$match[2]])) {
|
|
|
81 |
$message = file_get_contents($this->listdir . "/archive/" . $msgdir . "/" . $msgfile) ;
|
|
|
82 |
$mimeDecode = new Mail_mimeDecode($message) ;
|
|
|
83 |
$mailDecode = $mimeDecode->decode() ;
|
|
|
84 |
//$msg = new ezmlm_parser();
|
|
|
85 |
//$msg->parse_file($this->listdir . $thread_curr->file, TRUE);
|
|
|
86 |
|
|
|
87 |
} else {
|
|
|
88 |
$mailDecode = $GLOBALS['fichiers_analyses'][$match[1]][$match[2]] ;
|
|
|
89 |
}
|
|
|
90 |
$actionargs = preg_split("/\//", $thread_curr->file);
|
|
|
91 |
$html .= '<tr class="'.$class[$ctc].'">'."\n";
|
|
|
92 |
$html .= '<td>'.$actionargs[2].$actionargs[3].'</td><td>';
|
|
|
93 |
$html .= $this->makelink('action=show_author_msgs&actionargs[]='.
|
|
|
94 |
$this->makehash($this->decode_iso($mailDecode->headers['from'])),$this->decode_iso($this->protect_email($mailDecode->headers['from'],TRUE)));
|
|
|
95 |
$html .= '</td>'."\n";
|
|
|
96 |
$html .= '<td><b>';
|
|
|
97 |
//$html .= " <a name=\"" . urlencode($thread_curr->file) . "\">"; A quoi ça sert ?
|
|
|
98 |
for ($i = 0; $i < $thread_curr->depth; $i++) {
|
|
|
99 |
$html .= " ";
|
|
|
100 |
}
|
|
|
101 |
if (($this->thread_subjlen > 0) and (strlen($this->decode_iso($mailDecode->headers['subject'])) > $this->thread_subjlen)) {
|
|
|
102 |
$subject = substr($this->decode_iso($mailDecode->headers['subject']), 0, ($this->thread_subjlen - 3 - ($thread_curr->depth * 2)));
|
|
|
103 |
$subject = $subject . "...";
|
|
|
104 |
} else {
|
|
|
105 |
$subject = $this->decode_iso($mailDecode->headers['subject']);
|
|
|
106 |
}
|
|
|
107 |
|
|
|
108 |
|
|
|
109 |
$subject = preg_replace("/\[" . $this->listname . "\]/", "", $subject);
|
|
|
110 |
$html .= $this->makelink("action=show_msg&actionargs[]=" . $actionargs[2] . "&actionargs[]=" . $actionargs[3], $subject);
|
|
|
111 |
$html .= "</b></td>\n";
|
|
|
112 |
$html .= '<td>' .$this->date_francaise($mailDecode->headers['date']).'</td>'."\n";
|
|
|
113 |
$html .= "</tr>\n";
|
|
|
114 |
|
|
|
115 |
$ctc++;
|
|
|
116 |
if ($ctc == count($this->tablecolours)) { $ctc = 0; }
|
|
|
117 |
|
|
|
118 |
$lastdepth = $thread_curr->depth;
|
|
|
119 |
$thread_curr = $thread_curr->next;
|
|
|
120 |
}
|
|
|
121 |
|
|
|
122 |
$html .= '<tr><td colspan="3"><hr noshade size="1" /></td></tr>'."\n";
|
|
|
123 |
return $html;
|
|
|
124 |
}
|
|
|
125 |
|
|
|
126 |
// build: takes one argument in the format YYYYMM and builds the thread cache file
|
|
|
127 |
// for that month if the ezmlm thread file exists. The resulting cache file is then
|
|
|
128 |
// stored in $this->tmpdir;
|
|
|
129 |
function build($month) {
|
|
|
130 |
if (!is_file($this->listdir . "/archive/threads/" . $month)) { return FALSE; }
|
|
|
131 |
|
|
|
132 |
if (!is_dir($this->tempdir . "/ezmlm-php-" . $this->listname)) {
|
|
|
133 |
$fd2 = fopen($this->tempdir . "/ezmlm-php-" . $this->listname . "-" . $month,"w+");
|
|
|
134 |
} else {
|
|
|
135 |
$fd2 = fopen($this->tempdir . "/ezmlm-php-" . $this->listname . "/" . $month,"w+");
|
|
|
136 |
}
|
|
|
137 |
fclose($fd2);
|
|
|
138 |
$i=0;
|
|
|
139 |
// ouverture du fichier thread de ezmlm
|
|
|
140 |
// Ils sont classés mois par mois
|
|
|
141 |
$fd1 = fopen($this->listdir . "/archive/threads/" . $month, "r");
|
|
|
142 |
while (!feof($fd1)) {
|
|
|
143 |
$line = fgets($fd1,4096);
|
|
|
144 |
if (preg_match('/^[0-9]*\:[a-z]* \[.*/', $line)) {
|
|
|
145 |
// valid ezmlm thread file entry
|
|
|
146 |
|
|
|
147 |
// On place dans $subjectfile le chemin vers le fichier sujet
|
|
|
148 |
$subjectfile = preg_replace("/^[0-9]*\:([a-z]*) \[.*/", "\\1", $line);
|
|
|
149 |
$subjectfile = substr($subjectfile,0,2) . '/' . substr($subjectfile,2,18);
|
|
|
150 |
|
|
|
151 |
$thread_head = NULL;
|
|
|
152 |
$thread_curr = NULL;
|
|
|
153 |
$thread_temp = NULL;
|
|
|
154 |
$thread_depth = 1;
|
|
|
155 |
|
|
|
156 |
if (!is_file($this->listdir . "/archive/subjects/" . $subjectfile)) { continue; }
|
|
|
157 |
// on ouvre le fichier sujet
|
|
|
158 |
// Celui-ci contient sur la première ligne le hash du sujet puis le sujet
|
|
|
159 |
// sur les autres lignes :
|
|
|
160 |
// num_message:annéemois:hash_auteur nom_auteur
|
|
|
161 |
$fd2 = fopen($this->listdir . "/archive/subjects/" . $subjectfile, "r");
|
|
|
162 |
while (!feof($fd2)) {
|
|
|
163 |
$line2 = fgets($fd2,4096);
|
|
|
164 |
if (preg_match('/^[0-9]/',$line2)) {
|
|
|
165 |
$msgnum = preg_replace('/^([0-9]*):.*/', '\\1', $line2);
|
|
|
166 |
$msgfile = $msgnum % 100;
|
|
|
167 |
$msgdir = (int)($msgnum / 100);
|
|
|
168 |
if ($msgfile < 10) { $msgfile = "0" . $msgfile; }
|
|
|
169 |
//$msg = new ezmlm_parser();
|
|
|
170 |
//$msg->parse_file_headers($this->listdir . "/archive/" . $msgdir . "/" . $msgfile, TRUE);
|
|
|
171 |
|
|
|
172 |
$message = file_get_contents($this->listdir . "/archive/" . $msgdir . "/" . $msgfile) ;
|
|
|
173 |
$mimeDecode = new Mail_mimeDecode($message) ;
|
|
|
174 |
$mailDecode = $mimeDecode->decode() ;
|
|
|
175 |
|
|
|
176 |
|
|
|
177 |
|
208 |
neiluj |
178 |
// On stocke le fichier analysée pour réutilisation ultàrieure
|
2 |
ddelon |
179 |
$GLOBALS['fichiers_analyses'][$msgdir][$msgfile] = $mailDecode ;
|
|
|
180 |
$msgid = (isset ($mailDecode->headers['message-id']) ? $mailDecode->headers['message-id'] : '');
|
|
|
181 |
$inreply = (isset($mailDecode->headers['in-reply-to']) ? $mailDecode->headers['in-reply-to'] : '');
|
|
|
182 |
$references = (isset ($mailDecode->headers['references']) ? $mailDecode->headers['references'] : '') ;
|
|
|
183 |
$thread_depth = 1;
|
|
|
184 |
|
|
|
185 |
if ($thread_head == NULL) {
|
|
|
186 |
$thread_head = new ezmlm_thread(0,'/archive/' . $msgdir . '/' . $msgfile,$msgid);
|
|
|
187 |
} else {
|
|
|
188 |
$thread_curr = new ezmlm_thread($depth,'/archive/' . $msgdir . '/' . $msgfile,$msgid);
|
|
|
189 |
if ($inreply != '') { $thread_curr->inreply = $inreply; }
|
|
|
190 |
if ($references != '') { $thread_curr->references = $references; }
|
|
|
191 |
$thread_head->append($thread_curr);
|
|
|
192 |
}
|
|
|
193 |
}
|
|
|
194 |
}
|
|
|
195 |
fclose($fd2);
|
|
|
196 |
|
|
|
197 |
// so now after all that mess $thread_head contains a full thread tree
|
|
|
198 |
// first build the depth of each message based on 'in-reply-to' and 'references'
|
|
|
199 |
unset($thread_temp);
|
|
|
200 |
$thread_temp = NULL;
|
|
|
201 |
$thread_curr =& $thread_head->next;
|
|
|
202 |
while (get_class($thread_curr) == 'ezmlm_thread') {
|
|
|
203 |
unset($thread_temp);
|
|
|
204 |
$thread_temp = NULL;
|
|
|
205 |
|
|
|
206 |
if ($thread_curr->inreply != '') { $thread_temp =& $thread_head->find_msgid($thread_curr->inreply); }
|
|
|
207 |
if ($thread_temp == NULL) {
|
|
|
208 |
if ($thread_curr->references != '') {
|
|
|
209 |
$refs = preg_split('/ /', $thread_curr->references);
|
|
|
210 |
$refs = array_pop($refs);
|
|
|
211 |
$thread_temp =& $thread_head->find_msgid($refs);
|
|
|
212 |
}
|
|
|
213 |
}
|
|
|
214 |
if ($thread_temp == NULL) {
|
|
|
215 |
// we couldn't find anything... set depth to 1, the default
|
|
|
216 |
$thread_curr->depth = 1;
|
|
|
217 |
} else {
|
|
|
218 |
// we found a reference, set it to it's depth + 1
|
|
|
219 |
$thread_curr->depth = $thread_temp->depth + 1;
|
|
|
220 |
}
|
|
|
221 |
$thread_curr =& $thread_curr->next;
|
|
|
222 |
}
|
|
|
223 |
|
|
|
224 |
// now write it to a temp file named MONTH-SEQ where seq is cronologic sequence order of the thread.
|
|
|
225 |
if (!is_dir($this->tempdir . "/ezmlm-php-" . $this->listname)) {
|
|
|
226 |
@mkdir($this->tempdir . "/ezmlm-php-" . $this->listname, 0755);
|
|
|
227 |
if (!is_dir($this->tempdir . "/ezmlm-php-" . $this->listname)) {
|
|
|
228 |
$fd2 = fopen($this->tempdir . "/ezmlm-php-" . $this->listname . "-" . $month, "a");
|
|
|
229 |
} else {
|
|
|
230 |
$fd2 = fopen($this->tempdir . "/ezmlm-php-" . $this->listname . "/" . $month, "a");
|
|
|
231 |
}
|
|
|
232 |
} else {
|
|
|
233 |
$fd2 = fopen($this->tempdir . "/ezmlm-php-" . $this->listname . "/" . $month, "a");
|
|
|
234 |
}
|
|
|
235 |
fputs($fd2,$this->thread_to_html($thread_head));
|
|
|
236 |
fclose($fd2);
|
|
|
237 |
}
|
|
|
238 |
}
|
|
|
239 |
|
|
|
240 |
// finally store our checksum
|
|
|
241 |
if (!is_dir($this->tempdir . "/ezmlm-php-" . $this->listname)) {
|
|
|
242 |
$fd2 = fopen($this->tempdir . "/ezmlm-php-" . $this->listname . "-" . $month . "-" . "checksum","w+");
|
|
|
243 |
} else {
|
|
|
244 |
$fd2 = fopen($this->tempdir . "/ezmlm-php-" . $this->listname . "/" . $month . "-" . "checksum","w+");
|
|
|
245 |
}
|
|
|
246 |
fputs($fd2,"md5:" . $this->md5_of_file($this->listdir . "/archive/threads/" . $month) . "\n");
|
|
|
247 |
fclose($fd2);
|
|
|
248 |
fclose($fd1);
|
|
|
249 |
|
|
|
250 |
return TRUE;
|
|
|
251 |
}
|
|
|
252 |
|
|
|
253 |
// listmessages: prints out a nice little calendar and displays the message
|
|
|
254 |
// totals for each month. The link jumps to the thread listing.
|
208 |
neiluj |
255 |
// On lit le répertoire archive/threads/ qui contient un fichier par moi avec tous les thread, par sujet
|
2 |
ddelon |
256 |
// Présentés comme suit
|
|
|
257 |
// num_thread:hash [taille_du_thread] Sujet du thread (le dernier)
|
|
|
258 |
// les messages sont rangés par leur numéro
|
|
|
259 |
function listmessages() {
|
|
|
260 |
if (!is_dir($this->listdir . "/archive/threads/")) {
|
|
|
261 |
return false ;
|
|
|
262 |
}
|
208 |
neiluj |
263 |
$threadcount = array();
|
|
|
264 |
|
|
|
265 |
$repertoire_archive = opendir($this->listdir . "/archive/");
|
|
|
266 |
|
|
|
267 |
while (false !== ($item = readdir($repertoire_archive))) {
|
|
|
268 |
// $item contient les noms des repertoires
|
|
|
269 |
// on ne garde que ceux qui sont des chiffres
|
|
|
270 |
|
|
|
271 |
if (preg_match('/[0-9]+/', $item)) {
|
|
|
272 |
// on ouvre le fichier d index de chaque repertoire
|
|
|
273 |
$fichier_index = fopen($this->listdir.'/archive/'.$item.'/index', 'r');
|
|
|
274 |
$compteur = 0 ;
|
|
|
275 |
|
|
|
276 |
while (!feof($fichier_index)) {
|
|
|
277 |
// On ignore la premiere ligne
|
|
|
278 |
$temp = fgets($fichier_index, 4096);
|
|
|
279 |
// dans la seconde on recupere la date
|
|
|
280 |
$temp = fgets($fichier_index, 4096);
|
|
|
281 |
preg_match('/\t([0-9]+) ([a-zA-Z][a-zA-Z][a-zA-Z]) ([0-9][0-9][0-9][0-9])/', $temp, $match) ;
|
|
|
282 |
if ($match[0] != '') {
|
|
|
283 |
$threadmonth = date('n', strtotime($match[0])) ;
|
|
|
284 |
$threadyear = date('Y', strtotime($match[0])) ;
|
|
|
285 |
$threadcount[$threadyear][$threadmonth]++;
|
|
|
286 |
}
|
2 |
ddelon |
287 |
}
|
208 |
neiluj |
288 |
fclose ($fichier_index);
|
2 |
ddelon |
289 |
}
|
|
|
290 |
}
|
208 |
neiluj |
291 |
|
2 |
ddelon |
292 |
// La partie qui suit, simple, crée la table avec le nombre de message échangé chaque mois
|
44 |
alexandre_ |
293 |
$res = '<table id="petit_calendrier">'."\n";
|
2 |
ddelon |
294 |
$res .= " <tr>\n";
|
|
|
295 |
$res .= " <td></td>" ;
|
|
|
296 |
foreach ($GLOBALS['mois'] as $valeur) $res .= '<td>'.$valeur.'</td>' ;
|
|
|
297 |
$res .=" </tr>\n";
|
|
|
298 |
|
|
|
299 |
while (list($key,$val) = each($threadcount)) {
|
|
|
300 |
$res .= " <tr>\n";
|
|
|
301 |
$res .= " <td>$key</td>";
|
|
|
302 |
for ($i = 1; $i <= 12; $i++) {
|
208 |
neiluj |
303 |
if (isset($threadcount[$key][$i]) && $threadcount[$key][$i] > 0) {
|
106 |
alexandre_ |
304 |
$res .= "<td bgcolor=\"" . $this->tablecolours[0] . "\" valign=\"middle\">";
|
208 |
neiluj |
305 |
$res .= $this->makelink('action=show_month&actionargs[]='.$key.($i < 10 ? '0'.$i:$i),$threadcount[$key][$i]);
|
2 |
ddelon |
306 |
$res .= "</td>";
|
|
|
307 |
} else {
|
|
|
308 |
$res .= "<td bgcolor=\"" . $this->tablecolours[0] . "\"></td>";
|
|
|
309 |
}
|
|
|
310 |
}
|
|
|
311 |
$res .= "</tr>\n";
|
|
|
312 |
}
|
|
|
313 |
$res .= "</table>\n";
|
|
|
314 |
echo $res ;
|
|
|
315 |
}
|
|
|
316 |
}
|
|
|
317 |
|
|
|
318 |
// CLASS: ezmlm-thread is a quick little class to allow us to define
|
|
|
319 |
// a structure of the current thread in a single-linked list.
|
|
|
320 |
// it's a little messy since php doesn't support pointers like C does
|
|
|
321 |
// so we have to use references and a head object to append to the list.
|
|
|
322 |
class ezmlm_thread {
|
|
|
323 |
var $next;
|
|
|
324 |
var $depth;
|
|
|
325 |
var $file;
|
|
|
326 |
var $msgid;
|
|
|
327 |
var $inreply;
|
|
|
328 |
var $references;
|
|
|
329 |
function append($thread) {
|
|
|
330 |
$thread_curr =& $this;
|
|
|
331 |
while ($thread_curr->next != NULL) {
|
|
|
332 |
$thread_curr =& $thread_curr->next;
|
|
|
333 |
}
|
|
|
334 |
$thread_curr->next = $thread;
|
|
|
335 |
}
|
|
|
336 |
function &find_msgid($msgid) {
|
|
|
337 |
$thread_curr =& $this;
|
|
|
338 |
while ($thread_curr->next != NULL) {
|
|
|
339 |
if (trim($thread_curr->msgid) == trim($msgid)) { return $thread_curr; }
|
|
|
340 |
$thread_curr =& $thread_curr->next;
|
|
|
341 |
}
|
|
|
342 |
return NULL;
|
|
|
343 |
}
|
|
|
344 |
function ezmlm_thread($depth,$file,$msgid) {
|
|
|
345 |
$this->depth = $depth;
|
|
|
346 |
$this->file = $file;
|
|
|
347 |
$this->msgid = $msgid;
|
|
|
348 |
$this->next = NULL;
|
|
|
349 |
}
|
|
|
350 |
}
|
|
|
351 |
?>
|