Code

fixes: #1175
[gosa.git] / gosa-plugins / mail / personal / mail / sieve / class_sieve.inc
index 60a146550460425eae9a7fef0bb7374e9f57bd05..91c826f402b0c97d611ae825fa45ba11650e8177 100644 (file)
@@ -103,13 +103,13 @@ class sieve
     unset($this->error_raw);
 
     $this->line=fgets($this->fp,1024);
-    $this->token = split(" ", $this->line, 2);
+    $this->token = explode(" ", $this->line, 2);
 
     if($this->token[0] == "NO"){
       /* we need to try and extract the error code from here.  There are two possibilites: one, that it will take the form of:
          NO ("yyyyy") "zzzzzzz" or, two, NO {yyyyy} "zzzzzzzzzzz" */
       $this->x = 0;
-      list($this->ltoken, $this->mtoken, $this->rtoken) = split(" ", $this->line." ", 3);
+      list($this->ltoken, $this->mtoken, $this->rtoken) = explode(" ", $this->line." ", 3);
       if($this->mtoken[0] == "{"){
         while($this->mtoken[$this->x] != "}" or $this->err_len < 1){
           $this->err_len = substr($this->mtoken, 1, $this->x);
@@ -222,6 +222,9 @@ class sieve
     $this->error= "";
     $this->error_raw="";
     $this->options = $options;
+
+    @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, $this->error_raw,
+        "<b>SIEVE: Host: $host:$port. Options: $options - Auth Types: $auth_types </b>");
   }
 
   function parse_for_quotes($string)
@@ -284,6 +287,10 @@ class sieve
 
     $this->fp=@fsockopen($this->host,$this->port,$err_id,$err_str);
     if($this->fp == false){
+
+      @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,$this->error_raw,
+          "<b>SIEVE: Socket connection failed. (".$this->host.":".$this->port.")</b>");
+
       $this->error_raw = $err_str;
       return false;
     }
@@ -294,7 +301,7 @@ class sieve
     //response.  They repsond as follows: "Cyrus timsieved v1.0.0" "SASL={PLAIN,........}"
     //So, if we see IMLEMENTATION in the first line, then we are done.
 
-    if(ereg("IMPLEMENTATION",$this->line))
+    if(strstr($this->line, "IMPLEMENTATION"))
     {
       //we're on the Cyrus V2 sieve server
       while(sieve::status($this->line) == F_DATA){
@@ -308,13 +315,11 @@ class sieve
 
           if(strcmp($this->item[0], "SIEVE") == 0){
             $this->cap_type="modules";
-            $this->modules = split(" ", $this->item[1]);
           }else{
             $this->cap_type="auth";
-            $this->modules = $this->item;
           }
 
-          $this->modules = split(" ", $this->item[1]);
+          $this->modules = explode(" ", $this->item[1]);
           if(is_array($this->modules)){
             foreach($this->modules as $this->module)
               $this->capabilities[$this->cap_type][$this->module]=true;
@@ -344,7 +349,7 @@ class sieve
       $this->modules = substr($this->item[1], strpos($this->item[1], "{"),strlen($this->item[1])-1);
 
       //then split again at the ", " stuff.
-      $this->modules = split($this->modules, ", ");
+      $this->modules = explode(", ", $this->modules);
 
       //fill up our $this->modules property
       if(is_array($this->modules)){
@@ -360,14 +365,18 @@ class sieve
 
     if(sieve::status($this->line) == F_NO){            //here we should do some returning of error codes?
       $this->error=EC_UNKNOWN;
+
+      @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,$this->error_raw,
+          "<b>SIEVE: Unknown sieve response, giving up.</b>");
+
       $this->error_raw = "Server not allowing connections.";
       return false;
     }
 
     /* Loop through each allowed authentication type and see if the server allows the type */
-    foreach(split(" ",$this->auth_types) as $auth_type)
+    foreach(explode(" ",$this->auth_types) as $auth_type)
     {
-      if ($this->capabilities["auth"][$auth_type])
+      if (isset($this->capabilities["auth"][$auth_type]))
       {
         /* We found an auth type that is allowed. */
         $this->auth_in_use = $auth_type;
@@ -375,13 +384,30 @@ class sieve
       }
     }
 
+    /* Sometimes we do not get any authentification methods, assume PLAIN here.
+     * #TODO Maybe there is a better solution for this?
+     */
+    if($this->auth_in_use == ""){
+      @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,$this->error_raw,
+          "<b>SIEVE: No authentification mechanisms received, try using PLAIN!.</b>");
+        $this->auth_in_use  = "PLAIN";
+    }
+
     /* Fill error message if no auth types are present */
-    if (!isset($this->capabilities["auth"])){
+    if (($this->options != "tls") && (!isset($this->capabilities["auth"]))){
       $this->error=EC_UNKNOWN;
       $this->error_raw = "No authentication methods found - please check your sieve setup for missing sasl modules";
       return false;
     }
 
+    /* DEBUG */    
+    $imp = "";
+    if(isset($this->capabilities['implementation'])){
+      $imp = $this->capabilities['implementation'];
+    }
+    @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,$imp,
+        "<b>SIEVE: Socket connection established. </b>");
+
     /* call our authentication program */  
     return sieve::authenticate();
 
@@ -394,6 +420,10 @@ class sieve
 
     fputs($this->fp,"LOGOUT\r\n");
     fclose($this->fp);
+
+    @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"",
+        "<b>SIEVE: Logout!</b>");
+
     $this->loggedin=false;
     return true;
   }
@@ -407,8 +437,15 @@ class sieve
     fputs($this->fp, "PUTSCRIPT \"$scriptname\" {".$len."+}\r\n");
     fputs($this->fp, "$this->script\r\n");
 
-    return sieve::get_response();
-
+    if(sieve::get_response()){
+      @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"",
+          "<b>SIEVE: Script '".$scriptname."' successfully send!</b>");
+      return(TRUE);
+    }else{
+      @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,trim($this->error_raw),
+          "<b>SIEVE: Script couldn't be send!</b>");
+      return(FALSE);
+    }
   }  
 
   //it appears the timsieved does not honor the NUMBER type.  see lex.c in timsieved src.
@@ -427,9 +464,17 @@ class sieve
     if($this->loggedin==false)
       return false;
 
-    fputs($this->fp, "SETACTIVE \"$scriptname\"\r\n");   
-    return sieve::get_response();
+    fputs($this->fp, "SETACTIVE \"$scriptname\"\r\n");  
 
+    if(sieve::get_response()){
+      @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"",
+          "<b>SIEVE: Set active script '".$scriptname."' was successful!</b>");
+      return(TRUE);
+    }else{
+      @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,trim($this->error_raw),
+          "<b>SIEVE: Set active script '".$scriptname."' failed!</b>");
+      return(FALSE);
+    }
   }
 
   function sieve_getscript($scriptname)
@@ -439,8 +484,16 @@ class sieve
       return false;
 
     fputs($this->fp, "GETSCRIPT \"$scriptname\"\r\n");
-    return sieve::get_response();
 
+    if(sieve::get_response()){
+      @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"",
+          "<b>SIEVE: Get script '".$scriptname."' was successful!</b>");
+      return(TRUE);
+    }else{
+      @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,trim($this->error_raw),
+          "<b>SIEVE: Get script '".$scriptname."' failed!</b>");
+      return(FALSE);
+    }
   }
 
 
@@ -451,7 +504,15 @@ class sieve
 
     fputs($this->fp, "DELETESCRIPT \"$scriptname\"\r\n");    
 
-    return sieve::get_response();
+    if(sieve::get_response()){
+      @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"",
+          "<b>SIEVE: Delete script '".$scriptname."' was successful!</b>");
+      return(TRUE);
+    }else{
+      @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,trim($this->error_raw),
+          "<b>SIEVE: Delete  script '".$scriptname."' failed!</b>");
+      return(FALSE);
+    }
   }
 
 
@@ -459,11 +520,15 @@ class sieve
   { 
     fputs($this->fp, "LISTSCRIPTS\r\n"); 
     sieve::get_response();             //should always return true, even if there are no scripts...
-    if(isset($this->found_script) and $this->found_script)
+    if(isset($this->found_script) and $this->found_script){
+      @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, implode($this->response,", "),
+          "<b>SIEVE: List scripts was successful!</b>");
       return true;
-    else{
+    }else{
       $this->error=EC_NOSCRIPTS;       //sieve::getresponse has no way of telling wether a script was found...
       $this->error_raw="No scripts found for this account.";
+      @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__, $this->error_raw,
+          "<b>SIEVE: List scripts returned no scripts</b>");
       return false;
     }
   }
@@ -493,43 +558,75 @@ class sieve
       /* Check if PHP supports TLS encryption for sockets 
        */
       if(function_exists("stream_socket_enable_crypto")){
+
+        /* Initiate TLS and get response 
+         */
         if (@ fputs ($this->fp, "STARTTLS\r\n") === false) {
+          @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"couldn't send data to socket.",
+              "<b>SIEVE: TLS couldn't be initiated. </b>");
           $this->error_raw = "fputs() returned 'false'"; return (false);
-        } @ $linha = fgets ($this->fp, 1024); if ($linha === false) {
-          $this->error_raw = "fgets() returned 'false'"; return (false);
-        } if (! preg_match ("/\\s*OK\\s/i", $linha)) {
-          $this->error_raw = "expected an 'OK', but server replied: '" . trim ($linha) . "'"; return (false);
-        } if (! @ stream_socket_enable_crypto ($this->fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
-          $this->error_raw = "stream_socket_enable_crypto() returned 'false'"; return (false);
+        } 
+        @ $linha = fgets ($this->fp, 1024); 
+        if ($linha === false) {
+          $this->error_raw = "fgets() returned 'false'"; 
+          @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"couldn't read data from socket.",
+              "<b>SIEVE: TLS couldn't be initiated. </b>");
+          return (false);
+        }
+        if (! preg_match ("/\\s*OK\\s/i", $linha)) {
+          @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"server returned '".trim ($linha)."' instead of 'OK'",
+              "<b>SIEVE: TLS couldn't be initiated. </b>");
+          $this->error_raw = "expected an 'OK', but server replied: '" . trim ($linha) . "'"; 
+          return (false);
+        } 
+        if (! @ stream_socket_enable_crypto ($this->fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
+          @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,
+              "The socket doesn't seem to support STREAM_CRYPTO_METHOD_TLS_CLIENT",
+              "<b>SIEVE: TLS couldn't be initiated. </b>");
+          $this->error_raw = "stream_socket_enable_crypto() returned 'false'"; 
+          return (false);
         }
+        @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"",
+            "<b>SIEVE: TLS successfully initiated. </b>");
       }
     }
 
     switch ($this->auth_in_use) {
 
       case "PLAIN":
+      {
         $auth=base64_encode("$this->user\0$this->auth\0$this->pass");
 
-      $this->len=strlen($auth);                        
-      fputs($this->fp, "AUTHENTICATE \"PLAIN\" {".$this->len."+}\r\n");
-      fputs($this->fp, "$auth\r\n");
+        $this->len=strlen($auth);                      
+        fputs($this->fp, "AUTHENTICATE \"PLAIN\" {".$this->len."+}\r\n");
+        fputs($this->fp, "$auth\r\n");
 
-      $this->line=fgets($this->fp,1024);               
-      while(sieve::status($this->line) == F_DATA)
-        $this->line=fgets($this->fp,1024);
+        $this->line=fgets($this->fp,1024);             
+        while(sieve::status($this->line) == F_DATA)
+          $this->line=fgets($this->fp,1024);
 
-      if(sieve::status($this->line) == F_NO){
-        $this->error_raw = $this->line;
-        return false;
-      }
-      $this->loggedin=true;
-      return true;    
-      break;
+        if(sieve::status($this->line) == F_NO){
+          $this->error_raw = $this->line;
+          @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,trim($this->error_raw),
+              "<b>SIEVE: Authentication for '".$this->user."-".$this->auth_in_use."' failed.</b>");
+
+          return false;
+        }
+
+        @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"",
+            "<b>SIEVE: Authentication for '".$this->user."-".$this->auth_in_use."' was successful.</b>");
+        $this->loggedin=true;
+        return true;    
+      }break;
 
       default:
-      $this->error_raw = "Unsupported authentication method '".$this->auth_in_use."'!";
-      return false;
-      break;
+      {
+        @DEBUG (DEBUG_MAIL, __LINE__, __FUNCTION__, __FILE__,"Unsupported authentication method '".$this->auth_in_use."'!",
+            "<b>SIEVE: Authentication for '".$this->user."' with type '".$this->auth_in_use."' failed.</b>");
+
+        $this->error_raw = "Unsupported authentication method '".$this->auth_in_use."'!";
+        return false;
+      }   break;
 
     }//end switch