<?php
/*
License
XMail Log Archiver
http://xmlogarch.sourceforge.net
Copyright (C) 2006 Bryn Mosher
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License Version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not contact , write to
hide@address.com
- or -
Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#
# This is the only thing you as a user may change in this file, but
# only if you keep getting the error:
# (4) FATAL ERROR: Could not find home.
# If you have installed XMail Log Archiver in a strange way, you'll
# need to change this. The file xmlogarch.php and the directory
# xmlogarch.d should be in this location. xmlogarch.php should be
# able to find itself when run but if you have problems you can
# change this.
$installLocation = "/var/MailRoot/bin";
# usage
# php -d -f /home/bryn/cron_scripts/xmlogarch.php
#
# before anything...
ini_set("html_errors", 0 );
ini_set( "display_errors", 1 );
error_reporting( E_ALL );
define( "_version", "0.3rc3" );
define( "_me", basename( $_SERVER['SCRIPT_FILENAME'] ) . " PID:" . getmypid() );
if ( !defined( "PHP_EOL" ) ) {
if ( preg_match( "/windows/i", $_SERVER["OS"] ) ) {
define( "PHP_EOL", "\r\n" );
} else {
define( "PHP_EOL", "\n" );
}
}
#
# some functions to use on init
function findConfig() {
$retVal = FALSE;
$confLine = implode( " ", $_SERVER['argv'] );
$paths = findPath();
$passed = FALSE;
if ( preg_match( "/((\\-\\-conf|\\-c)\\s{1}(\\S*))/i", $confLine, $newConfig ) ) {
if ( testConfig( $newConfig[3] ) ) {
$GLOBALS["configFile"] = $newConfig[3];
$GLOBALS["usedParms"][$newConfig[2]] = $newConfig[1];
$GLOBALS["configName"] = basename( $newConfig[3] );
$retVal = $newConfig[3];
return $retVal;
} else {
$passed = TRUE;
$GLOBALS["configName"] = basename( $newConfig[3] );
}
}
foreach ( $paths as $tryThis ) {
$try = $tryThis . DIRECTORY_SEPARATOR . $GLOBALS["configName"];
if ( testConfig( $try ) ) {
if ( $passed ) {
$GLOBALS["usedParms"][$newConfig[2]] = $newConfig[1];
}
$GLOBALS["configFile"] = $try;
$retVal = $try;
break;
}
}
if ( $retVal === FALSE ) {
mex( 2, "config file '" . $GLOBALS["confName"] . "' missing from " . implode( " ", $paths ) );
}
return $retVal;
}
function findFunctions () {
$retVal = FALSE;
$paths = findPath();
foreach ( $paths as $tryThis ) {
$try = $tryThis . DIRECTORY_SEPARATOR . "xmlogarch_funcs.php";
if ( testFunctions( $try ) ) {
$retVal = $try;
break;
}
}
if ( $retVal === FALSE ) {
mex( 4, "file 'xmlogarch_funcs.php' missing from " . implode( " ", $paths ) );
}
return $retVal;
}
function findHome () {
if ( file_exists ( $GLOBALS['installLocation'] . DIRECTORY_SEPARATOR . "xmlogarch.php" ) ) {
$retVal = $GLOBALS['installLocation'];
} else {
$retVal = dirname( $_SERVER['SCRIPT_FILENAME'] );
}
if ( is_dir( $retVal . DIRECTORY_SEPARATOR . "xmlogarch.d" ) ) {
return $retVal;
} else {
mex( 4, $retVal );
}
}
function findLog () {
global $logRoot;
$ourLogLoc = FAlSE;
for ( $i = 0; $i < 25; $i++ ) {
$oldLog = $logRoot . DIRECTORY_SEPARATOR . "logarch-" . date("Ymd") . str_pad( ( 24 - $i ), 2, "0", STR_PAD_LEFT ) . "00";
if ( file_exists( $oldLog ) ) {
$retVal = $ourLogLoc;
$ourLogLoc = $oldLog;
$i = 25;
}
}
if ( !$ourLogLoc ) {
$ourLogLoc = $logRoot . DIRECTORY_SEPARATOR . "logarch-" . date("YmdH") . "00";
}
$retVal = $ourLogLoc;
return $retVal;
}
function findPath () {
$retVal = array( findHome() );
$pathAdd = array( "xmlogarch.d", "xmlogarch.d" . DIRECTORY_SEPARATOR . "reports.d", "reports.d" );
$placeToBe = array( findHome(), DIRECTORY_SEPARATOR . "etc", DIRECTORY_SEPARATOR . "root", DIRECTORY_SEPARATOR . "var" );
foreach ( $pathAdd as $suff ) {
foreach( $placeToBe as $place ) {
$curr = $place . DIRECTORY_SEPARATOR . $suff;
if ( is_dir( $curr ) ) {
$retVal[] = $curr;
}
}
}
return $retVal;
}
function mex ( $status, $extraNote = NUll ) {
global $myErrorsExtended, $logIsOpen;
if ( !is_int( $status ) ) {
$noStatus = "** UNKNOWN ERROR '" . $status . "' - " . $_SERVER['SCRIPT_FILENAME'] . " TERMINATING (exit 255) ** Text: '" . var_export( $extraNote, 1 ) . "'";
if ( $logIsOpen ) {
logIt( $noStatus, $_SERVER['SCRIPT_FILENAME'] );
} else {
exec( "echo " . escapeshellcmd( $noStatus ) . " 1>&2" );
}
exit(255);
} else {
if ( $text = $myErrorsExtended[$status] ) {
$text = ( $extraNote === NULL ) ? $text : $text . " (" . $extraNote . ")";
} else {
$text = "** UNKNOWN ERROR '" . $status . "' - " . $_SERVER['SCRIPT_FILENAME'] . " TERMINATING (exit 255) ** Text: '" . var_export( $extraNote, 1 ) . "'";
}
$msg = ( $status > 0 ) ? $text : $extraNote;
if ( ( $logIsOpen ) && ( $status > 0 ) ) {
logIt( $msg, $_SERVER['SCRIPT_FILENAME'] );
} else {
if ( !$msg == "" ) {
print trim( $msg ) . PHP_EOL;
}
}
exit( $status );
}
}
function testConfig( $confFile ) {
$retVal = FALSE;
if ( file_exists( $confFile ) ) {
if ( $confConts = file_get_contents( $confFile ) ) {
if ( preg_match( "/\\<\\?php[\\S\\s]*\\?\\>/i", $confConts ) ) { # has php tags
if ( !preg_match( "/function[ \t]*\\S*\\(.*\\)[ \t]*\\{[\\S\\s]*\\}/i", $confConts ) ) { # has functions! Should not be so.
$retVal = TRUE;
}
}
}
}
return $retVal;
}
function testFunctions( $confFile ) {
$retVal = FALSE;
if ( file_exists( $confFile ) ) {
if ( $confConts = file_get_contents( $confFile ) ) {
if ( preg_match( "/\\<\\?php[\\S\\s]*\\?\\>/i", $confConts ) ) { # has php tags
if ( preg_match( "/function[ \t]*\\S*\\(.*\\)[ \t]*\\{[\\S\\s]*\\}/i", $confConts ) ) { # has functions! Should not be so.
$retVal = TRUE;
}
}
}
}
return $retVal;
}
#
# Initial stuff
# proper errors for console
$configName = "xmlogarch_conf.php";
$myErrorsExtended = array(
0 => "", # clean exit
# regular errors
1 => "(1) NOTICE: Nothing to do.",
2 => "(2) FATAL ERROR: Config file is invalid.",
3 => "(3) FATAL ERROR: Could not write to log file.",
4 => "(4) FATAL ERROR: Could not find home.",
# network errors
11 => "(11) FATAL ERROR: Could not create socket!.",
12 => "(12) FATAL ERROR: Socket recv timed out or failed.",
# zip errors
20 => "(20) FATAL ERROR: Zip command not found.",
21 => "(21) FATAL ERROR: Zip file error.",
# XMail server errors
32 => "(32) FATAL ERROR: This is not an XMail server.",
34 => "(34) FATAL ERROR: Could not log in to XMail server.",
35 => "(35) FATAL ERROR: Could not get user list from XMail server.",
36 => "(36) FATAL ERROR: Could not get alias list from XMail server.",
# PHP support errors
40 => "(40) ERROR: Your system does not support mcrypt functions. Please use a plain text password and set \$truePass to TRUE in your config file.",
);
$peakMem = 0;
$peakText = "";
$usedParms = array();
$truePass = FALSE;
# includes
# tryto check permissions and locations of these at a later date (after finished)
ini_set( "include_path", ".;" . implode( ";", findPath() ) );
include_once( findConfig() );
include_once ( findFunctions() ); #get from install path later
define( "_minute", 60 );
define( "_hour", 60 * _minute );
define( "_day", 24 * _hour );
define( "_week", 7 * _day );
define( "_dateFmt", "Y-m-d H:i:s" );
# password encryption settings
$encType = "rijndael-128";
$encMode = "ecb";
$onlyReport = FALSE;
#
# command line args
if ( !$cmdOut = cmdLine() ) {
mex( 9999, "argv error " . var_export( $_SERVER['argv'], 1 ) );
}
#
# post command line vars
if ( $testing ) {
$realMailRoot = $mailRoot;
$mailRoot = $testMailRoot;
}
$archRoot = slashDir( $mailRoot ) . slashDir( $logDir ) . $archDir;
$begun = mktime();
$domains = array();
$dots = 0;
$fqp = $xmailServer . ":" . $xmailPort;
$lastReas = FALSE;
$logIsOpen = FALSE;
$logMoveCount = 0;
$logRoot = slashDir( $mailRoot ) . $logDir;
$logTypesArr = explode( " ", $logTypes );
$ourlogData = "";
$regDate = date(_dateFmt);
if ( function_exists( "posix_getpwuid" ) ) {
$user = posix_getpwuid( posix_geteuid() );
} else {
# this must be windows
$user = array( "name" => $_ENV["USERNAME"] );
}
#
#set variable based ini settings
//error_reporting(4); # logging to findLog() forphp itself isn't working yet
ini_set( "error_log", findLog() );
ini_set( "log_errors", 1 );
ini_set( "memory_limit", $maxMem . "M" ); #sometimes logs get big or plentiful!
ini_set( "max_execution_time", "432000" ); # 120 minute runtime max!
ini_set( "sendmail_from", $user["name"] . "@" . gethostbyaddr( "127.0.0.1" ) );
logIt( "Starting " . _me . " Version: " . _version . " (" . date( _dateFmt, getlastmod() ) . ")" );
if ( $cmdOut ) {
logIt( $cmdOut[0] );
logIt( $cmdOut[1] );
}
if ( $testing ) {
#grab fresh test files
print "TEST MODE Creating working copies...";
$cmd = "rm -f " . slashDir( $mailRoot ) . slashDir( $logDir ) . slashDir( $archDir ) . implode( " " . slashDir( $mailRoot ) . slashDir( $logDir ) . slashDir( $archDir ), $logTypesArr );
exec( $cmd . " 2>&1", $execOut, $errLvl );
print " (" . $errLvl . ")";
unset( $execOut );
unset( $errLvl );
$cmd = "cp -uv --preserve=timestamps " . slashDir( $realMailRoot ) . slashDir( $logDir ) . implode( " " . slashDir( $realMailRoot ) . slashDir( $logDir ), $logTypesArr ) . " " . slashDir( $mailRoot ) . slashDir( $logDir ) . "copy";
exec( $cmd . " 2>&1", $execOut, $errLvl );
print " (" . $errLvl . ")";
unset( $execOut );
unset( $errLvl );
$cmd = "cp -f --preserve=timestamps " . slashDir( $realMailRoot ) . slashDir( $logDir ) . slashDir( $archDir ) . "xmail_log_arch.zip " . slashDir( $mailRoot ) . slashDir( $logDir ) . slashDir( $archDir ) . "xmail_log_arch.zip";
exec( $cmd . " 2>&1", $execOut, $errLvl );
print " (" . $errLvl . ")";
unset( $execOut );
unset( $errLvl );
$cmd = "cp -uv --preserve=timestamps " . slashDir( $mailRoot ) . slashDir( $logDir ) . "copy/" . implode( " " . slashDir( $mailRoot ) . slashDir( $logDir ) . "copy/", $logTypesArr ) . " " . slashDir( $mailRoot ) . $logDir;
exec( $cmd . " 2>&1", $execOut, $errLvl );
print " (" . $errLvl . ")";
unset( $execOut );
unset( $errLvl );
print " Done." . PHP_EOL;
}
#
#the real goods
logIt( "Begun: " . date( _dateFmt, $begun ) . " (" . $begun. ")" );
logIt( "Using base config '" . $configFile . "'." );
logIt( "Using log root '" . $logRoot . "'." );
logIt( "Logs are stale after " . $staleAge . " hours." );
runReports( $repModsLoc );
#
# GTFO
$ended = mktime();
logIt( "Ending clean '" . _me . "'" );
memUse( "Ending Clean", FALSE, TRUE );
$passed = getElapsed( $ended );
logIt( "Ended: " . date( _dateFmt, $ended ) . " (" . $ended . ") Elapsed: " . $passed );
mailReport();
mex( 0 );
?>