2010-09-27 01:14:42 +02:00
< ? php
2011-10-16 21:33:31 +02:00
# $Id$
2010-09-27 01:14:42 +02:00
2011-10-16 21:33:31 +02:00
/**
2010-09-27 01:14:42 +02:00
* Handlers User level alias actions - e . g . add alias , get aliases , update etc .
*/
2011-03-02 23:37:22 +01:00
class DomainHandler extends PFAHandler {
2010-09-27 01:14:42 +02:00
2011-03-02 23:37:22 +01:00
protected $username = null ; # actually it's the domain - variable name kept for consistence with the other classes
2011-10-16 20:50:33 +02:00
protected $db_table = null ;
2011-03-02 23:37:22 +01:00
protected $id_field = null ;
protected $struct = array ();
protected $new = 0 ; # 1 on create, otherwise 0
2011-10-17 01:37:11 +02:00
protected $values = array ();
protected $values_valid = false ;
2010-09-27 01:14:42 +02:00
public $errormsg = array ();
2011-10-16 23:41:27 +02:00
2011-10-19 19:52:26 +02:00
# messages used in various functions
# (stored separately to make the functions reuseable)
protected $msg = array ();
2011-10-16 23:41:27 +02:00
2010-09-27 01:14:42 +02:00
/**
2011-10-19 00:11:22 +02:00
* Constructor : fill $struct etc .
* @ param string $new
2010-09-27 01:14:42 +02:00
*/
2011-10-19 00:11:22 +02:00
public function __construct ( $new = 0 ) {
2011-03-02 23:37:22 +01:00
if ( $new ) $this -> new = 1 ;
$this -> initStruct ();
2011-10-19 19:52:26 +02:00
$this -> initMsg ();
2011-10-19 00:11:22 +02:00
}
/**
* initialize with $username and check if it is valid
* @ param string $username
*/
public function init ( $username ) {
$this -> username = strtolower ( $username );
2011-10-16 23:41:27 +02:00
$exists = $this -> view ( false );
2011-10-19 00:11:22 +02:00
if ( $this -> new ) {
2011-10-16 23:41:27 +02:00
if ( $exists ) {
2011-10-19 19:52:26 +02:00
$this -> errormsg [] = Lang :: read ( $this -> msg [ 'error_already_exists' ]);
2011-10-19 00:11:22 +02:00
return false ;
2011-10-16 23:41:27 +02:00
} elseif ( ! $this -> validate_id () ) {
# errormsg filled by validate_id()
2011-10-19 00:11:22 +02:00
return false ;
2011-10-16 23:41:27 +02:00
} else {
2011-10-19 00:11:22 +02:00
return true ;
2011-10-16 23:41:27 +02:00
}
} else { # edit mode
if ( ! $exists ) {
2011-10-19 19:52:26 +02:00
$this -> errormsg [] = Lang :: read ( $this -> msg [ 'error_does_not_exist' ]);
2011-10-19 00:11:22 +02:00
return false ;
2011-10-16 23:41:27 +02:00
} else {
2011-10-19 00:11:22 +02:00
return true ;
2011-10-16 23:41:27 +02:00
}
}
2011-03-02 23:37:22 +01:00
}
2011-10-16 23:41:27 +02:00
protected function validate_id () {
$valid = check_domain ( $this -> username );
if ( $valid ) {
return true ;
} else {
2011-10-18 01:44:40 +02:00
$this -> errormsg [] = Lang :: read ( 'pAdminCreate_domain_domain_text_error2' ); # TODO: half of the errormsg is currently delivered via flash_error() in check_domain
2011-10-16 23:41:27 +02:00
return false ;
}
}
2011-10-19 19:52:26 +02:00
# init $this->struct, $this->db_table and $this->id_field
2011-10-16 23:41:27 +02:00
protected function initStruct () {
2011-10-16 20:50:33 +02:00
$this -> db_table = 'domain' ;
2011-03-02 23:37:22 +01:00
$this -> id_field = 'domain' ;
2011-07-30 00:06:52 +02:00
# TODO: shorter PALANG labels ;-)
# TODO: hardcode 'default' to Config::read in pacol()?
$transp = boolconf ( 'transport' ) ? 1 : 0 ; # TOOD: use a function or write a Config::intbool function
2011-10-16 20:50:33 +02:00
$quota = boolconf ( 'quota' ) ? 1 : 0 ; # TOOD: use a function or write a Config::intbool function
2011-07-30 00:06:52 +02:00
$dom_q = boolconf ( 'domain_quota' ) ? 1 : 0 ; # TOOD: use a function or write a Config::intbool function
2011-03-02 23:37:22 +01:00
2011-04-20 00:08:20 +02:00
$this -> struct = array (
2011-07-30 00:06:52 +02:00
# field name allow display in... type $PALANG label $PALANG description default / options / not in database
2011-03-02 23:37:22 +01:00
# editing? form list
2011-10-16 21:33:31 +02:00
'domain' => pacol ( $this -> new , 1 , 1 , 'text' , 'pAdminEdit_domain_domain' , '' ),
'description' => pacol ( 1 , 1 , 1 , 'text' , 'pAdminEdit_domain_description' , '' ),
'aliases' => pacol ( 1 , 1 , 1 , 'num' , 'pAdminEdit_domain_aliases' , 'pAdminEdit_domain_aliases_text' , Config :: read ( 'aliases' ) ),
'mailboxes' => pacol ( 1 , 1 , 1 , 'num' , 'pAdminEdit_domain_mailboxes' , 'pAdminEdit_domain_mailboxes_text' , Config :: read ( 'mailboxes' ) ),
'maxquota' => pacol ( $quota , $quota , $quota , 'num' , 'pAdminEdit_domain_maxquota' , 'pAdminEdit_domain_maxquota_text' , Config :: read ( 'maxquota' ) ),
'quota' => pacol ( $dom_q , $dom_q , $dom_q , 'num' , 'pAdminEdit_domain_quota' , 'pAdminEdit_domain_maxquota_text' , Config :: read ( 'domain_quota_default' ) ),
'transport' => pacol ( $transp , $transp , $transp , 'enum' , 'pAdminEdit_domain_transport' , 'pAdminEdit_domain_transport_text' , Config :: read ( 'transport_default' ) ,
2011-07-30 00:06:52 +02:00
/*options*/ $this -> getTransports () ),
2011-10-16 21:33:31 +02:00
'backupmx' => pacol ( 1 , 1 , 1 , 'bool' , 'pAdminEdit_domain_backupmx' , '' ),
2011-10-19 00:56:33 +02:00
'active' => pacol ( 1 , 1 , 1 , 'bool' , 'pAdminEdit_domain_active' , '' , 1 ),
'default_aliases' => pacol ( $this -> new , 1 , 0 , 'bool' , 'pAdminCreate_domain_defaultaliases ' , '' , 1 , '' , /*not in db*/ 1 ),
2011-10-17 00:32:22 +02:00
'created' => pacol ( 0 , 0 , 1 , 'ts' , '' /* TODO: "created" label */ , '' ),
2011-10-16 21:33:31 +02:00
'modified' => pacol ( 0 , 0 , 1 , 'ts' , 'pAdminList_domain_modified' , '' ),
2011-03-02 23:37:22 +01:00
);
2010-09-27 01:14:42 +02:00
}
2011-10-19 19:52:26 +02:00
# messages used in various functions.
# always list the key to hand over to Lang::read
# the only exception is 'logname' which uses the key for db_log
protected function initMsg () {
$this -> msg [ 'error_already_exists' ] = 'pAdminCreate_domain_domain_text_error' ;
$this -> msg [ 'error_does_not_exist' ] = 'domain_does_not_exist' ;
if ( $this -> new ) {
$this -> msg [ 'logname' ] = 'create_domain' ;
$this -> msg [ 'store_error' ] = 'pAdminCreate_domain_result_error' ;
} else {
$this -> msg [ 'logname' ] = 'edit_domain' ;
$this -> msg [ 'store_error' ] = 'pAdminEdit_domain_result_error' ;
}
}
2011-10-18 01:44:40 +02:00
public function getStruct () {
return $this -> struct ;
}
2011-10-19 22:21:43 +02:00
public function getId_field () {
return $this -> id_field ;
}
2010-09-27 01:14:42 +02:00
public function getTransports () {
2011-02-14 00:01:44 +01:00
return Config :: read ( 'transport_options' );
2010-09-27 01:14:42 +02:00
}
2011-03-02 23:37:22 +01:00
# TODO: specific for CLI? If yes, move to CLI code
2010-09-27 01:14:42 +02:00
public function getTransport ( $id ) {
2011-02-14 00:01:44 +01:00
$transports = Config :: read ( 'transport_options' );
return $transports [ $id - 1 ];
2010-09-27 01:14:42 +02:00
}
2011-10-16 21:33:31 +02:00
2011-10-17 01:37:11 +02:00
public function set ( $values ) {
2011-03-02 23:37:22 +01:00
# TODO: make this a generic function for add and edit
2011-10-16 20:50:33 +02:00
if ( $this -> new == 1 ) {
$values [ $this -> id_field ] = $this -> username ;
}
2011-03-02 23:37:22 +01:00
# base validation
2011-10-17 01:37:11 +02:00
$this -> values = array ();
$this -> values_valid = false ;
2011-03-02 23:37:22 +01:00
foreach ( $this -> struct as $key => $row ) {
2011-10-16 21:33:31 +02:00
if ( $row [ 'editable' ] == 0 ) { # not editable
2011-10-16 20:50:33 +02:00
if ( $this -> new == 1 ) {
2011-10-17 01:37:11 +02:00
$this -> values [ $key ] = $row [ 'default' ];
2011-10-16 20:50:33 +02:00
}
2011-10-16 21:33:31 +02:00
} else {
2011-10-19 19:52:26 +02:00
if ( isset ( $values [ $key ])) {
if ( $row [ 'type' ] != " password " || strlen ( $values [ $key ]) > 0 || $this -> new == 1 ) { # skip on empty (aka unchanged) password on edit
$valid = true ; # trust input unless validator objects
$func = " _inp_ " . $row [ 'type' ];
if ( method_exists ( $this , $func ) ) {
if ( ! $this -> { $func }( $key , $values [ $key ])) $valid = false ;
} else {
# TODO: warning if no validation function exists?
}
# TODO: more validation (_field_$fieldname() ?)
if ( $valid ) {
2011-10-17 01:37:11 +02:00
$this -> values [ $key ] = $values [ $key ];
}
2011-03-02 23:37:22 +01:00
}
2011-10-19 19:52:26 +02:00
} elseif ( $this -> new ) { # new, field not set in input data
$this -> errormsg [] = " field $key is missing " ;
# echo "MISSING / not set: $key\n";
} else { # edit, field unchanged
# echo "skipped / not set: $key\n";
2011-03-02 23:37:22 +01:00
}
}
}
2011-10-17 01:37:11 +02:00
if ( count ( $this -> errormsg ) == 0 ) {
$this -> values_valid = true ;
}
return $this -> values_valid ;
}
2011-10-18 01:44:40 +02:00
public function store () {
2011-10-17 01:37:11 +02:00
if ( $this -> values_valid == false ) {
$this -> errormsg [] = " one or more values are invalid! " ;
return false ;
}
2011-10-16 20:50:33 +02:00
2011-10-17 01:37:11 +02:00
$db_values = $this -> values ;
2011-10-16 20:50:33 +02:00
2011-10-19 19:52:26 +02:00
foreach ( array_keys ( $db_values ) as $key ) {
switch ( $this -> struct [ $key ][ 'type' ]) { # modify field content for some types
case 'bool' :
$db_values [ $key ] = db_get_boolean ( $db_values [ $key ]);
break ;
# TODO: passwords -> pacrypt()
}
if ( $this -> struct [ $key ][ 'not_in_db' ] == 1 ) unset ( $db_values [ $key ]); # remove 'not in db' columns
}
if ( $this -> new ) {
$result = db_insert ( $this -> db_table , $db_values );
} else {
$result = db_update ( $this -> db_table , $this -> id_field , $this -> username , $db_values );
}
2011-02-14 00:01:44 +01:00
if ( $result != 1 ) {
2011-10-19 19:52:26 +02:00
$this -> errormsg [] = Lang :: read ( $this -> msg [ 'store_error' ]) . " \n ( " . $this -> username . " ) \n " ; # TODO: change message + use sprintf
2011-02-14 00:15:40 +01:00
return false ;
2011-02-14 00:01:44 +01:00
} else {
2011-10-19 19:52:26 +02:00
# TODO: drop the "else {" - if $result != 1, the "return false" will already exit the function
# TODO: everything after this comment (= specific to domains) should be a separate function,
# TODO: because everything above is generic "write values to DB" code
2011-10-17 01:37:11 +02:00
if ( $this -> new && $this -> values [ 'default_aliases' ]) {
2011-02-14 00:01:44 +01:00
foreach ( Config :: read ( 'default_aliases' ) as $address => $goto ) {
2011-04-20 00:08:20 +02:00
$address = $address . " @ " . $this -> username ;
2011-02-14 00:01:44 +01:00
# TODO: use AliasHandler->add instead of writing directly to the alias table
2010-09-27 01:14:42 +02:00
$arr = array (
'address' => $address ,
'goto' => $goto ,
2011-04-20 00:08:20 +02:00
'domain' => $this -> username ,
2011-02-14 00:01:44 +01:00
);
$result = db_insert ( 'alias' , $arr );
2011-07-30 00:06:52 +02:00
# TODO: error checking
2010-09-27 01:14:42 +02:00
}
}
2011-10-19 19:52:26 +02:00
if ( $this -> new ) {
$tMessage = Lang :: read ( 'pAdminCreate_domain_result_success' ) . " ( " . $this -> username . " ) " ; # TODO: tMessage is not used/returned anywhere
} else {
# TODO: success message for edit
}
2010-09-27 01:14:42 +02:00
}
2011-10-19 19:52:26 +02:00
if ( $this -> new ) {
if ( ! domain_postcreation ( $this -> username )) {
$this -> errormsg [] = Lang :: read ( 'pAdminCreate_domain_error' );
}
} else {
# we don't have domain_postedit()
2010-09-27 01:14:42 +02:00
}
2011-10-19 19:52:26 +02:00
db_log ( $this -> username , $this -> msg [ 'logname' ], " " );
2011-02-14 00:15:40 +01:00
return true ;
2010-09-27 01:14:42 +02:00
}
2011-10-16 21:33:31 +02:00
2011-10-16 23:41:27 +02:00
public function view ( $errors = true ) {
2011-10-17 00:32:22 +02:00
$select_cols = array ();
$bool_fields = array ();
2011-10-16 21:33:31 +02:00
2011-10-22 13:12:03 +02:00
$colformat = array (
# TODO: replace hardcoded %Y-%m-%d with a country-specific date format via *.lang?
'ts' => " DATE_FORMAT(###KEY###, '%Y-%m-%d') AS ###KEY###, ###KEY### AS _###KEY### " ,
);
2011-10-17 00:32:22 +02:00
# get list of fields to display
foreach ( $this -> struct as $key => $row ) {
if ( $row [ 'display_in_list' ] != 0 && $row [ 'not_in_db' ] == 0 ) {
2011-10-22 13:12:03 +02:00
if ( isset ( $colformat [ $row [ 'type' ]])) {
$select_cols [] = str_replace ( '###KEY###' , $key , $colformat [ $row [ 'type' ]] );
2011-10-17 00:32:22 +02:00
} else {
$select_cols [] = $key ;
}
2011-10-22 13:12:03 +02:00
if ( $row [ 'type' ] == 'bool' ) {
$bool_fields [] = $key ; # remember boolean fields (will be converted to integer 0/1 later) - TODO: do this in the sql query/$colformat with CASE?
}
2011-10-17 00:32:22 +02:00
}
}
$cols = join ( ',' , $select_cols );
$table = table_by_key ( $this -> db_table );
2011-10-22 13:12:03 +02:00
$where = db_where_clause ( array ( $this -> id_field => $this -> username ), $this -> struct );
$result = db_query ( " SELECT $cols FROM $table $where " );
2010-09-27 01:14:42 +02:00
if ( $result [ 'rows' ] != 0 ) {
2011-02-14 00:01:44 +01:00
$this -> return = db_array ( $result [ 'result' ]);
2011-10-17 00:32:22 +02:00
foreach ( $bool_fields as $field ) {
$this -> return [ $field ] = db_boolean_to_int ( $this -> return [ $field ]); # convert bool to integer (0/1)
}
2011-02-14 00:15:40 +01:00
return true ;
2010-09-27 01:14:42 +02:00
}
2011-10-19 19:52:26 +02:00
if ( $errors ) $this -> errormsg [] = Lang :: read ( $this -> msg [ 'error_does_not_exist' ]);
2011-03-02 23:37:22 +01:00
# $this->errormsg[] = $result['error'];
2011-02-14 00:15:40 +01:00
return false ;
2010-09-27 01:14:42 +02:00
}
2011-02-14 00:35:49 +01:00
/**
* @ return true on success false on failure
*/
2011-10-16 21:33:31 +02:00
public function delete () {
if ( ! $this -> view () ) {
2011-02-14 00:35:49 +01:00
$this -> errormsg [] = 'A domain with that name does not exist.' ; # TODO: make translatable
return false ;
}
$this -> errormsg [] = '*** Domain deletion not implemented yet ***' ;
return false ; # XXX function aborts here until TODO below is implemented! XXX
# TODO: recursively delete mailboxes, aliases, alias_domains, fetchmail entries etc. before deleting the domain
# TODO: move the needed code from delete.php here
2011-10-16 20:50:33 +02:00
$result = db_delete ( $this -> db_table , $this -> id_field , $this -> username );
2011-10-16 21:33:31 +02:00
if ( $result == 1 ) {
2011-02-14 00:35:49 +01:00
list ( /*NULL*/ , $domain ) = explode ( '@' , $this -> username );
2011-02-15 23:20:27 +01:00
db_log ( $domain , 'delete_domain' , $this -> username ); # TODO delete_domain is not a valid db_log keyword yet because we don't yet log add/delete domain
2011-02-14 00:35:49 +01:00
return true ;
}
}
2010-09-27 01:14:42 +02:00
}
/* vim: set expandtab softtabstop=4 tabstop=4 shiftwidth=4: */