#!/usr/local/bin/php
<?php

include("config.php");
/* Il primo argomento _deve_ essere settato, ed e` il nome della mailing list.
 * Il secondo argomento, se settato, indica una directory che deve essere
 * percorsa ricorsivamente in cerca di mail/mbox.
 */
if(!isset($argv[1]))
	exit(1);
$ml = $argv[1];

mysql_connect($db['host'], $db['user'], $db['pass']) or die(mysql_error());
mysql_select_db($db['database']) or die(mysql_error());

function mailparse($message) {
	global $debug;
	$ret['padre'] = NULL;
	$ret['body'] = NULL;

	$message = ereg_replace("\r","",$message);
	$rows = explode("\n",$message);
	$totrows = count($rows);

	for($i=0;$i<$totrows && strlen($rows[$i])>1;$i++)
	{
		if (eregi("^Message-ID:.+",$rows[$i]))
			$ret['msgid'] = trim(substr($rows[$i],11));
		elseif (eregi("^In-Reply-To:.+",$rows[$i]))
			$ret['padre'] = trim(substr($rows[$i],strpos($rows[$i],"<"),strpos($rows[$i],">")-strpos($rows[$i],"<")+1));
		elseif (eregi("^References:.+",$buffer)) {
			if(!$ret['padre'])
				$ret['padre'] = trim(substr($rows[$i],strrpos($rows[$i],"<"),strrpos($rows[$i],">")-strrpos($rows[$i],"<")+1));
		} elseif (eregi("^From:.+",$rows[$i]))
			$ret['author'] = trim(substr($rows[$i],5));
		elseif (eregi("^Subject:.+",$rows[$i]))
			$ret['subject'] = trim(substr($rows[$i],8));
		elseif (eregi("^Date:.+",$rows[$i]))
			$ret['date'] = date("Ymdhis",strtotime(trim(substr($rows[$i],5))));
	} // for

	while ($i<$totrows)
		$ret['body'].=$rows[$i++]."\n";

  return $ret;
}

function err($q) {
	return "# Errore\n# query: $q \n# mysql_error: ". mysql_error() ."\n";
}

function mboxparse($mbox)
{
	global $debug;
	// if($debug) print_r($mbox);
	$rows = explode("\n",$mbox);
	$totrows = count($rows);
	$message = '';
	$return = array();
	for($i=0;$i<$totrows;$i++)
	{
		if(substr($rows[$i], 0, 5) === "From ")
		{
			if(strlen($message)>1) array_push($return,$message);
			$message = '';
		}
		else
		{
			$message .= $rows[$i]."\n";
		}
	}
	if(strlen($message)>1) array_push($return,$message);
	return $return;
}

function update($msgarray) {
	global $ml,$debug;

	$q = "SELECT count(*) FROM `gufi_".$ml."`
			WHERE `idthread` = ".$msgarray['idthread']."
			AND `ordinethread` = ".($msgarray['ordinethread']);
	$foores = mysql_query($q) or die (err($q));
	$foo = mysql_fetch_array($foores);
	$numupdate = $foo['count(*)'];

	if ($numupdate > 0) {
		$q = "UPDATE `gufi_".$ml."` SET `ordinethread` = `ordinethread`+1
				WHERE `idthread` = ".$msgarray['idthread']."
				AND `ordinethread` > ".($msgarray['ordinethread']-1);
		mysql_query($q) or die (err($q));
	} // numupdate

} // update

function thread($msgarray) {
	global $ml,$debug;

	if (!$msgarray['padre']) {

		// Se non ha padre e' un nuovo thread
		// Prendo l'id dell'ultimo thread
		$q   = "SELECT max(idthread) as ultimoid FROM `gufi_". $ml ."`";
		$res = mysql_query($q) or die(err($q));
		$row = mysql_fetch_array($res);

		$msgarray['idthread'] = $row['ultimoid'] + 1;
		$msgarray['livellothread'] = 0; // il primo messaggio del thread ha livello
		$msgarray['ordinethread'] = 0;  // e ordine = 0

	} else {

		// prendo l'ultima risposta a questo padre
		$q = "SELECT livellothread, ordinethread, idthread FROM gufi_".$ml."
				WHERE `padre`='".$msgarray['padre']."'
				ORDER BY `ordinethread` DESC LIMIT 1";
		$res  = mysql_query($q) or die(err($q));
		$row2 = mysql_fetch_array($res);

		if (mysql_num_rows($res) > 0) {

			// ci sono mail con questo padre, appendo e aggiorno ordinethread
			$msgarray['idthread']	  = $row2['idthread'];
			$msgarray['livellothread'] = $row2['livellothread'];
			$msgarray['ordinethread']  = $row2['ordinethread']+1;

			// Controllo per l'ordinethread. Se il padre allo stesso livello
			// ha dei figli devo appenderlo si.. ma dopo i figli!
			$q = "SELECT livellothread, ordinethread, idthread, `from` FROM gufi_".$ml."
					WHERE `idthread` = ".$msgarray['idthread']."
					AND `ordinethread` > ".$row2['ordinethread']."
					AND `livellothread` > ".$row2['livellothread']."
					ORDER BY `ordinethread` ASC";
			$rest  = mysql_query($q) or die(err($q));

			// Scorro tutti i msg con livello maggiore e ordinethread maggiore ..
			// finche' gli ordinethread restano consecutivi vuol dire che vengon
			// tutti dallo stesso padre.. appena salto uno vuol dire che ho gia'
			// oltrepassato l'ordinethread che mi interessava
			$ultimo_ordine_valido = -1;
			while ($temp = mysql_fetch_array($rest)) {
				if ($ultimo_ordine_valido == -1)
					$ultimo_ordine_valido = $temp['ordinethread'];
				else
					if ($temp['ordinethread'] == $ultimo_ordine_valido + 1)
						$ultimo_ordine_valido++;
			} // while

			// Se ho modificato l'ultimo_ordine_valido significa che aveva
			// effettivamente dei figli e devo modificare ordinethread prima
			// dell'update!
			if ($ultimo_ordine_valido != -1)
				$msgarray['ordinethread'] = $ultimo_ordine_valido+1;

			update($msgarray);

		} else {

			// nessuna mail con questo padre, prendo livello e ordine del padre
			$q = "SELECT livellothread, ordinethread, idthread FROM gufi_". $ml ."
					WHERE `msgid`='".$msgarray['padre']."'";
			$res  = mysql_query($q) or die(err($q));
			$row3 = mysql_fetch_array($res);


			if (mysql_num_rows($res) == 0) {

				// Prendo l'id dell'ultimo thread
				$q   = "SELECT max(idthread) as ultimoid FROM `gufi_". $ml ."`";
				$res = mysql_query($q) or die(err($q));
				$row = mysql_fetch_array($res);

				$msgarray['idthread'] = $row['ultimoid'] + 1;
				$msgarray['livellothread'] = 0; // il primo messaggio del thread ha livello
				$msgarray['ordinethread'] = 0;  // e ordine = 0

			} else {

				// Ho trovato il padre nel db ..
				// appendo la mail come prima risposta a questo padre
				$msgarray['idthread']	  = $row3['idthread'];
				$msgarray['livellothread'] = $row3['livellothread']+1;
				$msgarray['ordinethread']  = $row3['ordinethread']+1;

				update($msgarray);

			} // if msgarray[idthread]
		} // id row[idthread]

	} // if msgarray[padre]

	return $msgarray;

} // thread_k


function query($msgarray) {
	global $ml,$debug;


	// controllo preliminare per msgid: se c'e' gia' questo msgid da qualche
	// parte cambio il msgid ed il padre di quei record. Poi posso inserire
	// normalmente il thread
	$q = "SELECT `msgid` FROM `gufi_".$ml."` WHERE `msgid`='".mysql_escape_string($msgarray['msgid'])."'";
	$res = mysql_query($q) or die (err($q));

	if (mysql_affected_rows() > 0) {

		for ($i=0, $rand = ""; $i<rand(15, 30); $i++)
			$rand .= chr(rand(97,122));

		if($debug)
		{
			echo "## Attenzione, MSGID duplicato: \n";
			echo "## ". $msgarray['msgid'] .", ci appendo ".$rand."\n";
		}

		$q = "UPDATE `gufi_".$ml."` SET `msgid`='".mysql_escape_string($msgarray['msgid'].$rand)."'
				WHERE `msgid`='".mysql_escape_string($msgarray['msgid'])."'";
		$res = mysql_query($q) or die(err($q));

		$q = "UPDATE `gufi_".$ml."` SET `padre`='".mysql_escape_string($msgarray['msgid'].$rand)."'
				WHERE `padre`='".mysql_escape_string($msgarray['msgid'])."'";
		$res = mysql_query($q) or die(err($q));

		if($debug) echo "# Ho aggiornato msgid e padre dell'id duplicato .. \n\n";

	} // if affected_rows > 0


	$q = "INSERT INTO `gufi_".$ml."`
			(`msgid`, `padre`, `from`, `subject`, `date`, `idthread`, `body`, `livellothread`, `ordinethread`) VALUES (
			'".mysql_escape_string($msgarray['msgid'])."',
			".(!$msgarray['padre'] ? "NULL" : "'".mysql_escape_string($msgarray['padre'])."'").",
			'".mysql_escape_string($msgarray['author'])."',
			'".mysql_escape_string($msgarray['subject'])."',
			".(strlen($msgarray['date'])>1?"'".mysql_escape_string($msgarray['date'])."'":"NOW()").",
			".$msgarray['idthread'].",
			'".mysql_escape_string($msgarray['body'])."',
			".$msgarray['livellothread'].",
			".$msgarray['ordinethread']."
			)";

	// Non deve morire MAI !
	mysql_query($q); // or die (err($q));
	if (mysql_error() && $debug)
		echo "\n # ".mysql_error()."\n";

} // query()

function progress(){
	global $progcount;
	$progcount++;
	switch($progcount % 4) {
		case '0':
			print "\r-";
			break;
		case '1':
			print "\r\\";
			break;
		case '2':
			print "\r|";
			break;
		case '3':
			print "\r/";
			break;
	}
	print " ".$progcount;
}

function parsedir($path) {
	global $debug;
	if($debug) print $path."\n";

	if ($dir = opendir($path)) {
		while (false !== ($file = readdir($dir))) {
			if (is_file($path."/".$file)) {
				progress();
				if($debug) print "-".$path."/".$file."\n";
				$filename = $path."/".$file;
				//Supporto gzip
				if(eregi("\.gz$",$file))
				{
					$zd = gzopen ($path."/".$file, "r");
					while (!gzeof($file))
						$contents .= gzread($zd, 1024);
					gzclose ($zd);
					$msgs = mboxparse($contents);
					$totmsgs = count($msgs);
					for($i=0; $i<$totmsgs; $i++)
					{
						query(thread(mailparse($msgs[$i])));
					}
				}
				else
				{
					$handle = fopen ($path."/".$file, "r");
					$contents = fread ($handle, filesize ($filename));
					if($debug==2) print_r($contents);
					$msgs = mboxparse($contents);
					$totmsgs = count($msgs);
					for($i=0; $i<$totmsgs; $i++)
					{
						query(thread(mailparse($msgs[$i])));
					}
					fclose($handle);
				}

			} else if(!ereg("^\.",$file) && is_dir($path."/".$file))
				parsedir($path."/".$file);
		} // while false !==
		closedir($dir);
	} // if $dir =
}

if(isset($argv[2])) {
	print "Parsing ".$argv[2]."\n";
	parsedir($argv[2]);
	print "\nDone.\n";
} else {
	ob_start();
	$ret = readfile('php://stdin');
	$message = ob_get_contents();
	ob_end_clean();
	if(strlen($message))
		query(thread(mailparse($message)));
}

?>
