"Fossies" - the Fresh Open Source Software Archive

Member "openmailadmin-1.0.1/inc/lib/imap/Cyrus_IMAP.php" (26 May 2007, 7593 Bytes) of package /linux/privat/old/openmailadmin-1.0.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "Cyrus_IMAP.php" see the Fossies "Dox" file reference documentation.

    1 <?php
    2 /**
    3  * This class encapsulates the administrative backend of cyrus-imapd.
    4  * It does not rely on PHP's IMAP/POP classes and connects on demand.
    5  *
    6  * Relevant RFCs:
    7  * - mailboxes:     3501
    8  * - quota:     2047
    9  * - ACL:       2086
   10  */
   11 class Cyrus_IMAP
   12     implements IMAP_Administrator
   13 {
   14     private $sp = false;        // holds the socket ressource, if connected
   15     private $connection_data;   // everything neccessary to connect to cyrus
   16     private $version;       // version of cyrus-imapd we have connected to
   17     private $separator;     // hierarchy separator
   18     private $_logger = null;    // logging facility, as defined in PEAR::Log
   19 
   20     public  $error_msg;     // if an error occured, this variable will hold the error messages
   21 
   22     function __construct(array $connection_data, Log $logger) {
   23         $this->version      = 'unknown';
   24         $this->separator    = null;
   25         $this->connection_data  = $connection_data;
   26         $this->_logger      = $logger;
   27     }
   28 
   29     function __destruct() {
   30         $this->imap_logout();
   31     }
   32 
   33     private function imap_login() {
   34         $this->_logger->debug('I: On opening socket for IMAP connection.');
   35         $this->sp = fsockopen(  $this->connection_data['HOST'],
   36                     $this->connection_data['PORT'],
   37                     $errno, $errstr);
   38         $this->error_msg = $errstr;
   39 
   40         if(!$this->sp) {
   41             throw new ConfigurationErrorException('Socket for IMAP connection couldn\'t be opened: "'.$errstr.'"');
   42         }
   43 
   44         $txt = fgets($this->sp, 1024);
   45         $this->_logger->debug('S: '.$txt);
   46         if(preg_match('/IMAP4\sv(\d+\.\d+\.\d+)/', $txt, $arr)) {
   47             $this->version = $arr[1];
   48             $this->_logger->debug('I: Version of IMAP server is: "'.$this->version.'"');
   49         }
   50 
   51         $this->_logger->notice('C: -- on logging in with username "'.$this->connection_data['ADMIN'].'" --');
   52         if(!$this->command('. login "'.$this->connection_data['ADMIN'].'" "'.$this->connection_data['PASS'].'"')) {
   53             throw new ConfigurationErrorException('Login failed. Check your connection data.');
   54         }
   55         return true;
   56     }
   57 
   58     private function imap_logout() {
   59         if($this->sp) {
   60             $this->command('. logout');
   61             fclose($this->sp);
   62         }
   63         return true;
   64     }
   65 
   66     public function getversion() {
   67         if(!$this->sp) {
   68             $this->imap_login();
   69         }
   70         return $this->version;
   71     }
   72 
   73     private function initial_gethierarchyseparator() {
   74         $result = $this->command('. list "" ""');
   75         $tmp = strstr($result['0'], '"');
   76         $this->separator = $tmp{1};
   77         $this->_logger->debug('I: Hierarchy separator is "'.$this->separator.'".');
   78         return $this->separator;
   79     }
   80 
   81     public function gethierarchyseparator() {
   82         if(is_null($this->separator)) {
   83             $this->initial_gethierarchyseparator();
   84         }
   85         return $this->separator;
   86     }
   87 
   88     /**
   89      * @param   cmd Fully formatted command.
   90      * @return      Unless additional data is provided the return will be either true or false. On additional data an array will be returned.
   91      */
   92     private function command($cmd) {
   93         if(!$this->sp) {
   94             $this->imap_login();
   95         }
   96 
   97         $out = array();
   98 
   99         fputs($this->sp, $cmd."\n");
  100         if(!($cmd{2} == 'l' && strstr($cmd, '. login'))) {
  101             $this->_logger->debug('C: '.$cmd);
  102         }
  103         do {
  104             $row = fgets($this->sp, 1024);
  105             $this->_logger->debug('S: '.$row);
  106             $out[] = $row;
  107         } while($row{0} != '.' && !feof($this->sp));
  108 
  109         if(count($out) > 1) {
  110             return $out;
  111         } else {
  112             if($row{2} != 'O') {
  113                 $this->error_msg    = substr($row, 5);
  114             }
  115             return ($row{2} == 'O');
  116         }
  117     }
  118 
  119     public function createmb($mailboxname) {
  120         return $this->command('. create "'.$mailboxname.'"');
  121     }
  122 
  123     public function deletemb($mailboxname) {
  124         // we have to grant ourselve admin-rights on the mailbox before deleting it
  125         $this->setacl($mailboxname, $this->connection_data['ADMIN'], $this->get_acl_letters());
  126         return $this->command('. delete "'.$mailboxname.'"');
  127     }
  128 
  129     public function renamemb($oldname, $newname) {
  130         // This is for preserving already granted rights.
  131         $oldacl = $this->getacl($oldname);
  132 
  133         $this->setacl($oldname, $this->connection_data['ADMIN'], $this->get_acl_letters());
  134         $out = $this->command('. rename "'.$oldname.'" "'.$newname.'"');
  135 
  136         if(isset($oldacl[$this->connection_data['ADMIN']])) {
  137             $this->setacl($newname, $this->connection_data['ADMIN'], $oldacl[$this->connection_data['ADMIN']]);
  138         } else {
  139             $this->deleteacl($newname, $this->connection_data['ADMIN']);
  140         }
  141 
  142         return $out;
  143     }
  144 
  145     public function getmailboxes($ref = '', $pat = '*') {
  146         $result = array();
  147         foreach($this->command('. list "'.$ref.'" '.$pat) as $folder) {
  148             if(preg_match('/\*\sLIST\s\((.*)\)\s\"(.*?)\"\s\"(.*?)\"/', $folder, $arr)) {
  149                 $result[]
  150                 = array('attributes'    => $arr[1],
  151                     'delimiter' => $arr[2],
  152                     'name'      => trim($arr[3]));
  153             }
  154         }
  155         return $result;
  156     }
  157 
  158     public function getquota($mailboxname) {
  159         $out = $this->command('. getquota "'.$mailboxname.'"');
  160         if($out == false) {
  161             // quota not set, thus unlimited
  162             return new Quota();
  163         } else if(is_array($out)
  164                && preg_match('/\*\sQUOTA.*\(\w*\s(\d+)\s(\d+)\)/i', $out[0], $arr)) {
  165             return new Quota($arr[1], $arr[2]);
  166         }
  167         return new Quota();
  168     }
  169 
  170     public function get_users_quota($username) {
  171         return $this->getquota($this->format_user($username));
  172     }
  173 
  174     /**
  175      * @param   storage Partition on which quota has to be set. May be ignored.
  176      * @see     IMAP_Administrator::setquota
  177      */
  178     public function setquota($mailboxname, $quota, $storage = 'STORAGE') {
  179         if(is_numeric($quota)) {
  180             return $this->command('. setquota "'.$mailboxname.'" ('.$storage.' '.intval($quota).')');
  181         }
  182         return false;
  183     }
  184 
  185     /**
  186      * @returns     Array   with all available rights as letters.
  187      */
  188     public function get_acl_available() {
  189         $assumed = array('l', 'r', 's', 'w', 'i', 'p', 'c', 'd', 'a');
  190         if(version_compare($this->getversion(), '2.3.0', '>=')) {
  191             $assumed = array('l', 'r', 's', 'w', 'i', 'p', 'k', 'x', 't', 'e', 'c', 'd', 'a');
  192         }
  193         return $assumed;
  194     }
  195 
  196     /**
  197      * @returns     String  with all available letters which represent rights.
  198      */
  199     private function get_acl_letters() {
  200         return implode('', $this->get_acl_available());
  201     }
  202 
  203     public function getacl($mailboxname) {
  204         $reult  = array();
  205         $arr    = array();
  206         $out = $this->command('. getacl "'.$mailboxname.'"');
  207 
  208         if($out === false) {
  209             return array();
  210         }
  211 
  212         // In order to prevent confusion due to mailboxnames which may
  213         // look like ACL strings we have to eliminate the mailboxnames.
  214         $out = str_replace($mailboxname, '##', $out);
  215 
  216         if(preg_match('/\*\sACL\s[^\s]*\s(.*)/', $out[0], $arr)) {
  217             if(preg_match_all('/([^\s]*)\s(['.$this->get_acl_letters().']*)\s?/', $arr[1], $arr)) {
  218                 $result = array_combine($arr[1], $arr[2]);
  219             }
  220         }
  221 
  222         return $result;
  223     }
  224 
  225     public function setacl($mailboxname, $user, $ACL) {
  226         return $this->command('. setacl "'.$mailboxname.'" "'.$user.'" '.$ACL);
  227     }
  228 
  229     private function deleteacl($mailboxname, $user) {
  230         return $this->command('. deleteacl "'.$mailboxname.'" "'.$user.'"');
  231     }
  232 
  233     public function format_user($username, $folder = null) {
  234         $ret = '';
  235         $this->gethierarchyseparator();
  236         if(is_null($folder)) {
  237             if(isset($this->connection_data['VDOM']) && $this->connection_data['VDOM'] != '') {
  238                 $ret = $this->connection_data['VDOM'].'!user'.$this->separator.$username;
  239             } else {
  240                 $ret = 'user'.$this->separator.$username;
  241             }
  242         } else {
  243             $ret = $this->format_user($username).$this->separator.$folder;
  244         }
  245         $this->_logger->notice('I: ("'.$username.'", '.(is_null($folder) ? 'null' : '"'.$folder.'"').') has been formatted as "'.$ret.'"');
  246         return $ret;
  247     }
  248 
  249     public function is_valid_username($username) {
  250         if($this->gethierarchyseparator() == '.') {
  251             return preg_match('/^[a-z0-9]+(?:(?<![_-])[_-][a-z0-9]+)*$/i', $username);
  252         } else {
  253             return preg_match('/^[a-z0-9]+(?:(?<![_.-])[_.-][a-z0-9]+)*$/i', $username);
  254         }
  255     }
  256 
  257 }
  258 ?>