Email
|
|
|
|
<?
/*
* EZMLM class
*
* rel. 0.1
*
* Copyright (c) 2001 Sumatra Solutions srl http://www.sumatrasolutions.com
* Ludovico Magnocavallo ludo@sumatrasolutions.com
*
* License type: GNU GPL http://www.gnu.org/copyleft/gpl.html
*
* Heavily inspired by
* Perl EZMLM module (Guy Antony Halse) -- nice module available on CPAN
* KGON's KPM556 Reggae MP3 Radio =) (http://209.20.223.122:8000)
*
* Partial Mysql support, stuff still needs to be fixed
* Use at your own risk =)
*
* php (Apache) usually runs as user nobody, your best bet to make this beast work
* is to create a qmail virtual host redirected to the nobody user
* eg put into /var/qmail/control/rcpthost your virtual hostname,
* into /var/qmail/control/virtualdomains something like
* lists.mydomain.org:nobody
* then assign your nobody user a home dir (usually it has none)
* and create all your lists there
*
* $list->make(array(
* 'switches' => '0123',
* 'dir' => '/home/nobody/testa',
* 'qmail' => '/home/nobody/.qmail-testa',
* 'name' => 'testa',
* 'host' => 'lists.mydomain.org',
* 6 => 'localhost::eztest:pippo:lists:testa'
* ));
*
* $Id: Base.php,v 1.14 2001/03/05 23:25:48 ludo Exp $
*
*/
class LTP2_Ezmlm_Base {
var $EZMLM_BASE = '/usr/local/bin/ezmlm';
var $QMAIL_BASE = '/var/qmail';
var $MYSQL_BASE = '';
var $LIST_NAME = '';
var $ERROR_LEVEL = 512; // 0,256,512,1024
var $error = false;
var $list = '';
function LTP2_Ezmlm_Base($args = array()) {
while (list($key,$val) = each($args)) {
$this->$key = $val;
}
if (!empty($this->list)) {
$this->setlist($this->list);
}
}
function raise_error($method = '', $message = '', $line = 0) {
$this->error = "<u><b>ezmlm.$method ${line}:</b> <font color=red>$message</font></u>";
if ($this->ERROR_LEVEL > 0) trigger_error($this->error, $this->ERROR_LEVEL);
}
function lists($dir) {
if (empty($dir) || !file_exists($dir)) {
$this->raise_error('lists', "parameter missing or directory not found dir = $dir email = $email", __LINE__);
return(false);
}
$dh = opendir($dir);
$files = array();
while ($file = readdir($dh)) {
if (preg_match("/^./", $file) || !is_dir($dir . '/' . $file) || !file_exists($dir . '/' . $file . '/lock')) continue;
$files[] = $file;
}
return($files);
}
function files($dir) {
$textdir = $dir . '/text';
if (empty($dir) || !file_exists($dir) || !file_exists($textdir)) {
$this->raise_error('lists', "parameter missing or directory not found dir = $dir", __LINE__);
return(false);
}
$dh = opendir($textdir);
$files = array();
while ($file = readdir($dh)) {
if (preg_match("/^./", $file)) continue;
$files[$file] = $textdir . '/' . $file;
}
return($files);
}
function subscribe($list, $email, $dir = '') {
if (empty($list) || empty($email)) {
$this->raise_error('subscribe', "parameter missing list = $list email = $email", __LINE__);
return(false);
}
$list = (!empty($dir) ? $list . '/' . $dir : $list);
if (!file_exists($list)) {
$this->raise_error('subscribe', "parameter missing list = $list email = $email", __LINE__);
return(false);
}
$command = $this->EZMLM_BASE . '/ezmlm-sub ' . escapeshellcmd($list . ' ' . $email);
$ret = exec($command, $ret_array, $ret_val);
if ($ret_val != 0) {
$this->raise_error('subscribe', "command returned non-zero exit status $command $ret_val", __LINE__);
return(false);
} else {
return($ret_array);
}
}
function unsubscribe($list, $email, $dir = '') {
if (empty($list) || empty($email)) {
$this->raise_error('unsubscribe', "parameter missing list = $list email = $email", __LINE__);
return(false);
}
$list = (!empty($dir) ? $list . '/' . $dir : $list);
if (!file_exists($list)) {
$this->raise_error('unsubscribe', "parameter missing list = $list email = $email", __LINE__);
}
$command = $this->EZMLM_BASE . '/ezmlm-unsub ' . escapeshellcmd($list . ' ' . $email);
$ret = exec($command, $ret_array, $ret_val);
if ($ret_val != 0) {
$this->raise_error('unsubscribe', "command returned non-zero exit status $command $ret_val", __LINE__);
} else {
return($ret_array);
}
}
function subscribers($list, $dir = '') {
$list = (!empty($dir) ? $list . '/' . $dir : $list);
if (!file_exists($list)) {
$this->raise_error('subscribers', "parameter missing list = $list", __LINE__);
}
$command = $this->EZMLM_BASE . '/ezmlm-list ' . escapeshellcmd($list);
$ret = exec($command, $ret_array, $ret_val);
if ($ret_val != 0) {
return(array());
} else {
return($ret_array);
}
}
function issub($list,$email, $dir = '') {
if (empty($list) || empty($email)) {
$this->raise_error('issub', "parameter missing list = $list email = $email", __LINE__);
return(false);
}
$list = (!empty($dir) ? $list . '/' . $dir : $list);
if (!file_exists($list)) {
$this->raise_error('issub', "list not found $list or $dir not found inside $list", __LINE__);
return(false);
}
putenv("SENDER=" . escapeshellcmd($email));
$command = $this->EZMLM_BASE . '/ezmlm-issubn ' . escapeshellcmd($list);
$ret = exec($command, $ret_array, $ret_val); // echo("email = $email command = $command ret = $ret_val ret_array = ");
// print_r($ret_array);
if ($ret_val == 99) {
return(false);
} else if ($ret_val == 0) {
return(true);
} else {
$this->raise_error('issub', 'wrong arguments passed to ezmlm-issubn, please check ret = ' . $ret . ' command = ' . $command, __LINE__);
}
}
function _sqlConnect($host, $user, $password, $database) {
if (! $conn = @mysql_pconnect($host, $user, $password)) {
return(false);
}
if (! @mysql_select_db($database, $conn)) {
return(false);
}
return($conn);
}
function _getSqlParams($list) {
if (!file_exists("$list/sql")) return(false);
$fp = fopen("$list/sql", 'r');
$contents = fread($fp, filesize("$list/sql"));
fclose($fp);
$contents = explode(':', $contents);
return(array(
$contents[0] . (!empty($contents[1]) ? ':' . $contents[1] : ''), // host
$contents[2], // user
$contents[3], // password
$contents[4], // database
$contents[5], // prefix
));
}
function make($args) {
// let's check required arguments
if (empty($args['dir']) || empty($args['qmail']) || empty($args['name'])) {
$this->raise_error('make', 'required arguments missing (dir = ' . $args['dir'] . ', qmail = ' . $args['qmail'] . ', name = ' . $args['name'], __LINE__);
return(false);
}
// check if list exists
if (file_exists($args['dir'])) {
$this->raise_error('make', 'mailing list ' . $args['dir'] . ' already exists', __LINE__);
return(false);
}
$switches = !empty($args['switches']) ? '-' . $args['switches'] : '';
$switches = preg_replace("/^[^-aAbBcCdDeEfFgGhHjJkKlLmMnNoOpPqQrRsStTuUvVwWx]+$/",'',$switches);
$extraswitches = ''; /* if (!empty($args[0])) { // make the list a sublist of $arg = mainlist@host
if (preg_match("/^[^s|t]+@[^s|t]+.[a-zA-Z0-9]{2,3}$/", $args[0])) {
$extraswitches .= '-0 ' . $args[0] . ' ';
} else {
$this->raise_error('make', 'argument -0 not in correct format ' . $args[0], __LINE__);
return(false);
}
}
*/ if (!empty($args[3])) { // replace the From: header in list messages with From: $arg
if (preg_match("/[^s|t]+@[^s|t]+.[a-zA-Z0-9]{2,3}/", $args[3])) {
$extraswitches .= '-3 ' . $args[3] . ' ';
} else {
$this->raise_error('make', 'argument -3 not in correct format ' . $args[3], __LINE__);
return(false);
}
}
if (!empty($args[6])) { // mysql list db info for example sun::eztest:88inch:list_husky_it:list
if (substr_count($args[6], ':') == 5 && !preg_match("/[s|t]+/", $args[6])) { // number of : == 5 and no spaces or tabs
$minfo = explode(':', $args[6]);
$host = $minfo[0];
$host = !empty($minfo[1]) ? ':' . $minfo[1] : $host;
$user = $minfo[2];
$password = $minfo[3];
$database = $minfo[4];
$prefix = $minfo[5];
if (! $conn = mysql_pconnect($host, $user, $password)) {
$this->raise_error('make', "could not connect to mysql server on $host user $user password $password", __LINE__);
return(false);
} else {
if (!mysql_select_db($database, $conn)) {
mysql_create_db($database, $conn) || $this->raise_error('make', "could not create db $database on mysql server on $host user $user password $password", __LINE__);
}
$command = $this->EZMLM_BASE . "/ezmlm-mktab $prefix | mysql -f -s --host=$host --user=$user --password=$password $database";
$ret = exec($command, $ret_array, $ret_val);
if ($ret_val == 0) {
$extraswitches .= '-6 ' . $args[6];
} else {
$this->raise_error('make', "return value indicates errors, no tables created (command = <i>$command</i>, return value = <i>$ret_val</i>, error_message = <i>$ret</i>)", __LINE__);
return(false);
}
unset($ret);
unset($ret_val);
}
} else {
$this->raise_error('make', 'argument -6 not in correct format ' . $args[6], __LINE__);
return(false);
}
}
$command = $this->EZMLM_BASE . '/ezmlm-make ' . escapeshellcmd($switches . ' ' . $extraswitches . ' ' . $args['dir'] . ' ' . $args['qmail'] . ' ' . $args['name'] . ' ' . $args['host']) . ' 2>&1'; // echo("command = $command<br>");
$ret = exec($command, $ret_array, $ret_val);
if ($ret_val == 0) {
$this->setlist($args['dir']) || $this->raise_error('make', 'command processed, but no list appears to have been made, please check ' . $args['dir'] . ' manually', __LINE__);
return(false);
} else {
$this->raise_error('make', "return value indicates errors, no list created (command = <i>$command</i>, return value = <i>$ret_val</i>, error_message = <i>$ret</i>)", __LINE__);
return(false);
}
return(true);
// echo("ret = $ret ret_val = $ret_val");
}
/**
* Delete a list and its related files
*
* @access public
* @param array $args
* attenzione che name non e' il nome simbolico della lista (ad es. nobody-test),
* ma il nome reale senza il prefisso del nome utente
*/
function unmake($args) {
// let's check required arguments
if (empty($args['dir']) || empty($args['qmail'])) {
$this->raise_error('make', 'required arguments missing (dir = ' . $args['dir'] . ', qmail = ' . $args['qmail'], __LINE__);
return(0);
}
// let's check if list exists
if (!$this->setlist($args['dir'])) {
$this->raise_error('unmake', 'list not existing (dir = ' . $args['dir'] . ', qmail = ' . $args['qmail'], __LINE__);
return(0);
}
// let's see if the .qmail file exists
if (!file_exists($args['qmail'])) {
$this->raise_error('unmake', 'qmail file not existing (dir = ' . $args['dir'] . ', qmail = ' . $args['qmail'], __LINE__);
return(0);
}
// let's delete all list references
if ($args['backup']) {
// let's do a backup
preg_match('/^(.*)/(.qmail-.*)$/', $args['qmail'], $matches);
$dir = $matches[1];
$file = $matches[2];
$time = '_' . strftime("%d%b%Y_%T");
if (!file_exists("$dir/.ezmlm-backups")) {
mkdir("$dir/.ezmlm-backups", 0775) || $this->raise_error('unmake', 'cannot mkdir $dir/.ezmlm-backups', __LINE__);
}
rename("$dir/$file", "$dir/.ezmlm-backups/$file$time") || $this->raise_error('unmake', "cannot rename $dir/$file to $dir/.ezmlm-backups/$file$time", __LINE__);
rename("$dir/$file-default", "$dir/.ezmlm-backups/${file}-default$time") || $this->raise_error('unmake', "cannot rename $dir/${file}-default to $dir/.ezmlm-backups/${file}-default$time", __LINE__);
rename("$dir/$file-owner", "$dir/.ezmlm-backups/${file}-owner$time") || $this->raise_error('unmake', "cannot rename $dir/${file}-owner to $dir/.ezmlm-backups/${file}-owner$time", __LINE__);
rename("$dir/$file-return-default", "$dir/.ezmlm-backups/${file}-return-default$time") || $this->raise_error('unmake', "cannot rename $dir/${file}-return-default to $dir/.ezmlm-backups/${file}-return-default$time", __LINE__);
$dirpieces = explode('/', $args['dir']);
$dirname = $dirpieces[count($dirpieces) - 1];
unset($dirpieces[count($dirpieces) - 1]);
$dir = join('/', $dirpieces);
$command = 'mv ' . $args['dir'] . ' ' . $dir . '/.ezmlm-backups/' . $dirname . $time;
// echo("command = $command<br>");
$ret = exec($command, $ret_array, $ret_val);
if ($ret_val != 0) {
$this->raise_error('unmake', 'cannot rename ' . $args['dir'] . ' to ' . $dir . '/.ezmlm-backups/' . $dirname, __LINE__);
return(0);
}
return(true);
} else {
//let's delete the files
unlink($args['qmail']) || $this->raise_error('unmake', 'cannot unlink ' . $args['qmail'], __LINE__);
unlink($args['qmail'] . '-default') || $this->raise_error('unmake', 'cannot unlink ' . $args['qmail'] . '-default', __LINE__);
unlink($args['qmail'] . '-accept-default') || $this->raise_error('unmake', 'cannot unlink ' . $args['qmail'] . '-accept-default', __LINE__);
unlink($args['qmail'] . '-owner') || $this->raise_error('unmake', 'cannot unlink ' . $args['qmail' . '-owner'], __LINE__);
unlink($args['qmail'] . '-return-default') || $this->raise_error('unmake', 'cannot unlink ' . $args['qmail'] . '-return-default', __LINE__);
$this->rmdirminusr($args['dir']);
return(true);
}
}
function setlist($list) {
if (is_file("$list/lock")) { // $this->error = false;
return($this->LIST_NAME = $list);
} else { // $this->raise_error('setlist', "$list is not a valid list", __LINE__);
return(false);
}
}
function rmdirminusr($dir) {
$d = dir($dir);
while($entry = $d->read()) {
if ($entry != '.' && $entry != '..') {
if (is_dir($dir . '/' . $entry)) {
$this->rmdirminusr($dir . '/' . $entry);
} else {
unlink ($dir . '/' . $entry) || $this->raise_error('rmdirminusr', 'cannot unlink ' . $dir . '/' . $entry, __LINE__);
}
}
}
$d->close();
rmdir($dir) || $this->raise_error('rmdirminusr', 'cannot unlink ' . $dir, __LINE__);
}
/*
create TABLE list (
hash TINYINT UNSIGNED NOT NULL,
address VARCHAR(255) NOT NULL,
INDEX h (hash),
INDEX a (address(12)));
create TABLE list_slog (
tai TIMESTAMP,
address VARCHAR(255) NOT NULL,
fromline VARCHAR(255) NOT NULL,
edir CHAR(1) NOT NULL,
etype CHAR(1) NOT NULL,
INDEX (tai));
create TABLE list_digest (
hash TINYINT UNSIGNED NOT NULL,
address VARCHAR(255) NOT NULL,
INDEX h (hash),
INDEX a (address(12)));
create TABLE list_digest_slog (
tai TIMESTAMP,
address VARCHAR(255) NOT NULL,
fromline VARCHAR(255) NOT NULL,
edir CHAR(1) NOT NULL,
etype CHAR(1) NOT NULL,
INDEX (tai));
create TABLE list_mod (
hash TINYINT UNSIGNED NOT NULL,
address VARCHAR(255) NOT NULL,
INDEX h(hash),
INDEX a(address(12)));
create TABLE list_mod_slog (
tai TIMESTAMP,
address VARCHAR(255) NOT NULL,
fromline VARCHAR(255) NOT NULL,
edir CHAR(1) NOT NULL,
etype CHAR(1) NOT NULL,
INDEX (tai));
create TABLE list_allow (
hash TINYINT UNSIGNED NOT NULL,
address VARCHAR(255) NOT NULL,
INDEX h(hash),
INDEX a(address(12)));
create TABLE list_allow_slog (
tai TIMESTAMP,
address VARCHAR(255) NOT NULL,
fromline VARCHAR(255) NOT NULL,
edir CHAR(1) NOT NULL,
etype CHAR(1) NOT NULL,
INDEX (tai));
create TABLE list_deny (
hash TINYINT UNSIGNED NOT NULL,
address VARCHAR(255) NOT NULL,
INDEX h(hash),
INDEX a(address(12)));
create TABLE list_deny_slog (
tai TIMESTAMP,
address VARCHAR(255) NOT NULL,
fromline VARCHAR(255) NOT NULL,
edir CHAR(1) NOT NULL,
etype CHAR(1) NOT NULL,
INDEX (tai));
CREATE TABLE list_cookie (
msgnum INTEGER UNSIGNED NOT NULL,
tai TIMESTAMP NOT NULL,
cookie CHAR(20) NOT NULL,
chunk TINYINT UNSIGNED NOT NULL DEFAULT 0,
bodysize INTEGER UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (msgnum));
CREATE TABLE list_mlog (
msgnum INTEGER UNSIGNED NOT NULL,
listno INTEGER UNSIGNED NOT NULL,
tai TIMESTAMP,
subs INTEGER UNSIGNED NOT NULL DEFAULT 0,
done TINYINT NOT NULL DEFAULT 0,
PRIMARY KEY listmsg (listno,msgnum,done));
CREATE TABLE list_digest_cookie (
msgnum INTEGER UNSIGNED NOT NULL,
tai TIMESTAMP NOT NULL,
cookie CHAR(20) NOT NULL,
chunk TINYINT UNSIGNED NOT NULL DEFAULT 0,
bodysize INTEGER UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (msgnum));
CREATE TABLE list_digest_mlog (
msgnum INTEGER UNSIGNED NOT NULL,
listno INTEGER UNSIGNED NOT NULL,
tai TIMESTAMP,
subs INT UNSIGNED NOT NULL DEFAULT 0,
done TINYINT NOT NULL DEFAULT 0,
PRIMARY KEY listmsg (listno,msgnum,done));
*/
} ?>
|
|
|
Usage Example
|
$list->make(array(
'switches' => '0123',
'dir' => '/home/nobody/testa',
'qmail' => '/home/nobody/.qmail-testa',
'name' => 'testa',
'host' => 'saverio.icenet.it',
6 => 'localhost::eztest:pippo:lists:testa'
));
|
|
|
Rate This Script
|
|
|
|