<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet href="http://bugs.horde.org/themes/feed-rss.xsl" type="text/xsl"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
 <channel>
  <title>Postfixadmin's vacation integration</title>
  <pubDate>Fri, 08 Aug 2008 15:15:11 -0400</pubDate>
  <link>http://bugs.horde.org/ticket/1326</link>
  <atom:link rel="self" type="application/rss+xml" title="Postfixadmin's vacation integration" href="http://bugs.horde.org/ticket/1326/rss" />
  <description>Postfixadmin's vacation integration</description>

  
  
  <item>
   <title>Hi, I create a patch for vacation to use postfixadmin's vaca</title>
   <description>Hi, I create a patch for vacation to use postfixadmin's vacation module

Here's the diff :

diff -urN vacation/config/conf.xml /usr/local/www/data/files/vacation/config/conf.xml
--- vacation/config/conf.xml	Thu Nov 11 02:20:07 2004
+++ /usr/local/www/data/files/vacation/config/conf.xml	Tue Feb  8 09:01:51 2005
@@ -139,6 +139,38 @@
      &lt;/configsection&gt;
     &lt;/configsection&gt;
    &lt;/case&gt;
+   &lt;case name=&quot;postfixadmin&quot; desc=&quot;Postfix mailer based MySQL driver&quot;&gt;
+    &lt;configdescription&gt;
+     If not using realms (multiple domains or virtual hosting) then there is
+     only one possible default configuration.
+     Even if you are using realms/hosting, you have to set a default
+     configuration.  This may be overriden by realm/domain specific values by
+     defining additional arrays, one per realm/domain, with the realm/domain
+     name as the key instead of the key 'default'. This not possible with this
+     interface though.
+    &lt;/configdescription&gt;
+    &lt;configsection name=&quot;params&quot;&gt;
+     &lt;configsection name=&quot;default&quot;&gt;
+      &lt;configsql switchname=&quot;driverconfig&quot;&gt;
+       &lt;configstring name=&quot;table&quot; desc=&quot;Database table&quot;&gt;vacation&lt;/configstring&gt;
+       &lt;configstring name=&quot;user_col&quot; desc=&quot;Column which contains user names&quot;&gt;email&lt;/configstring&gt;
+       &lt;configstring name=&quot;message&quot; desc=&quot;Column with vacation message&quot;&gt;body&lt;/configstring&gt;
+       &lt;configstring name=&quot;subject&quot; desc=&quot;Column with vacation subject&quot;&gt;subject&lt;/configstring&gt;
+       &lt;configstring name=&quot;vacation&quot; desc=&quot;Vacation message yes or no&quot;&gt;active&lt;/configstring&gt;
+       &lt;configstring name=&quot;vacdom&quot; desc=&quot;Vacation domain in postfixadmin's config.inc.php&quot;&gt;autoreply.example.com&lt;/configstring&gt;
+      &lt;/configsql&gt;
+      &lt;configenum name=&quot;hordeauth&quot; desc=&quot;Should we log the user automatically
+      in with the username and password he uses to login to Horde?&quot;&gt;
+       &lt;values&gt;
+        &lt;value desc=&quot;No&quot;&gt;false&lt;/value&gt;
+        &lt;value desc=&quot;Yes, with the full username&quot;&gt;full&lt;/value&gt;
+        &lt;value desc=&quot;Yes, but with everything after the @ stripped from the
+        username&quot;&gt;true&lt;/value&gt;
+       &lt;/values&gt;
+      &lt;/configenum&gt;
+     &lt;/configsection&gt;
+    &lt;/configsection&gt;
+   &lt;/case&gt;
   &lt;/configswitch&gt;
  &lt;/configsection&gt;
 
diff -urN vacation/lib/Driver/postfixadmin.php /usr/local/www/data/files/vacation/lib/Driver/postfixadmin.php
--- vacation/lib/Driver/postfixadmin.php	Thu Jan  1 07:00:00 1970
+++ /usr/local/www/data/files/vacation/lib/Driver/postfixadmin.php	Tue Feb  8 08:57:58 2005
@@ -0,0 +1,288 @@
+&lt;?php
+/**
+ * $Horde: vacation/lib/Driver/postfixadmin.php,v 1.0 2005/01/03 14:35:41 jan Exp $
+ *
+ * Vacation_Driver_postfixadmin:: implements the Vacation_Driver API for SQL servers.
+ *
+ * @author  Riv Octovahriz &lt;riv@cbn.net.id&gt;
+ * @version $Revision: 1.0 $
+ * @since   Vacation 2.1
+ * @package Vacation
+ */
+class Vacation_Driver_postfixadmin extends Vacation_Driver {
+
+    /** SQL connection object. */
+    var $_db;
+
+    /** Boolean which contains the state of the SQL connection. */
+    var $_connected = false;
+
+    /**
+     * Check if the realm has a specific configuration. If not, try to
+     * fall back on the default configuration. If still not a valid
+     * configuration then exit with an error.
+     *
+     * @param string    $realm      The realm of the user, or &quot;default&quot; if none.
+     *                              Note: passed by reference so we can change
+     *                              its value.
+     */
+    function checkConfig(&amp;$realm)
+    {
+        // If no realm passed in, or no table config for the realm
+        // passed in, then we fall back to the default realm
+        if (empty($realm) || empty($this-&gt;params[$realm]['table'])) {
+            $realm = 'default';
+        }
+
+        // If still no table,user_col,message,subject,vacation then we have a misconfigured module.
+        if (empty($this-&gt;params[$realm]['table']) ||
+            empty($this-&gt;params[$realm]['user_col']) ||
+            empty($this-&gt;params[$realm]['message']) ||
+            empty($this-&gt;params[$realm]['subject']) ||
+            empty($this-&gt;params[$realm]['vacation']) ) {
+            $this-&gt;err_str = _(&quot;The vacation application is not properly configured.&quot;);
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Enable a vacation message for a user.
+     *
+     * @param string    $user      The username to enable vacation for.
+     * @param string    $realm     The realm of the user.
+     * @param string    $password  The password of the user.
+     * @param string    $message   The message to install.
+     * @param string    $alias     The email alias for vacation to use --
+     *                             Not yet implemented.
+     *
+     * @return boolean  Returns true on success, false on error.
+     */
+    function setVacation($user, $realm, $password, $message, $alias)
+    {
+        // Make sure the configuration file is correct
+        if (!$this-&gt;checkConfig($realm)) {
+            return false;
+        }
+
+        /* _connect() will die with Horde::fatal() upon failure. */
+        $this-&gt;_connect($realm);
+
+        /* Determine if $message contains Subject: and if it does
+         * split it. */
+        if (preg_match(&quot;/^Subject: ([^\n]+)\n(.+)$/s&quot;, $message, $m='')) {
+            $mysubject = $m[1];
+            $mymessage = $m[2];
+        } else {
+            $mysubject = '';
+            $mymessage = $message;
+        }
+
+        // Build username.
+        $myuser = $this-&gt;_buildUsername($user, $realm);
+
+        // Check if an entry already exists and create one otherwise
+        $query = 'SELECT ' . $this-&gt;params[$realm]['vacation'] . ' AS vacation';
+	$query .= ' , domain ';
+        $query .= ' FROM ' . $this-&gt;params[$realm]['table'];
+        $query .= ' WHERE ' . $this-&gt;params[$realm]['user_col'] . ' = ' . $this-&gt;_db-&gt;quote($myuser);
+        $result = $this-&gt;_db-&gt;query($query);
+        if (!is_a($result, 'PEAR_Error')) {
+	    $query = 'UPDATE alias';
+	    $query .= ' SET goto = concat(concat(goto,&quot;,&quot;),concat(goto,&quot;@' . $this-&gt;params[$realm]['vacdom'] . '&quot;))';
+	    $query .= ' , modified=NOW()';
+	    $query .= ' WHERE address = ' . $this-&gt;_db-&gt;quote($myuser);
+	    $result = $this-&gt;_db-&gt;query($query);
+        }
+
+        /* Build the SQL query. */
+	$query = 'SELECT domain FROM alias WHERE address = ' . $this-&gt;_db-&gt;quote($myuser);
+	$result = $this-&gt;_db-&gt;query($query);	
+	$query = 'INSERT INTO ' . $this-&gt;params[$realm]['table'];
+	$query .= ' ( ' . $this-&gt;params[$realm]['user_col'];
+	$query .= ' , ' . $this-&gt;params[$realm]['subject'];
+	$query .= ' , ' . $this-&gt;params[$realm]['message'];
+	$query .= ' , domain ';
+	$query .= ' , created )';
+	$query .= ' VALUES ( ' . $this-&gt;_db-&gt;quote($myuser);
+	$query .= ' , ' . $this-&gt;_db-&gt;quote($mysubject);
+	$query .= ' , ' . $this-&gt;_db-&gt;quote($mymessage);
+	$query .= ' , SUBSTRING_INDEX(' . $this-&gt;_db-&gt;quote($myuser) . ', &quot;@&quot;, -1)';
+	$query .= ' , NOW() )';
+	 
+        /* Execute the query. */
+        $result = $this-&gt;_db-&gt;query($query);
+
+        if (!is_a($result, 'PEAR_Error')) {
+            if ($result === DB_OK) {
+                $this-&gt;_disconnect();
+                return true;
+            } else {
+                $this-&gt;_disconnect();
+                return false;
+            }
+        } else {
+            $this-&gt;_disconnect();
+            return false;
+        }
+    }
+
+    /**
+     * Disable the vacation message for a user.
+     *
+     * @param string    $user      The username of the user.
+     * @param string    $realm     The realm of the user.
+     * @param string    $password  The password of the user.
+     *
+     * @return boolean  Returns true on success, false on error.
+     */
+    function unsetVacation($user, $realm, $password)
+    {
+        // Make sure the configuration file is correct
+        if (!$this-&gt;checkConfig($realm)) {
+            return false;
+        }
+
+        /* _connect() will die with Horde::fatal() upon failure. */
+        $this-&gt;_connect($realm);
+
+        // Build username.
+        $myuser = $this-&gt;_buildUsername($user, $realm);
+
+        /* Build the SQL query. */
+	$query = 'UPDATE alias';
+	$query .= ' SET goto = ' . $this-&gt;_db-&gt;quote($myuser); 
+	$query .= ' WHERE address = ' . $this-&gt;_db-&gt;quote($myuser);
+	$result = $this-&gt;_db-&gt;query($query);
+
+	$query = 'DELETE FROM ' . $this-&gt;params[$realm]['table'];
+	$query .= ' WHERE ' . $this-&gt;params[$realm]['user_col'] . ' = ' . $this-&gt;_db-&gt;quote($myuser);
+
+        /* Execute the query. */
+        $result = $this-&gt;_db-&gt;query($query);
+
+        if (!is_a($result, 'PEAR_Error')) {
+            if ($result === DB_OK) {
+                $this-&gt;_disconnect();
+                return true;
+            } else {
+                $this-&gt;_disconnect();
+                return false;
+            }
+        } else {
+            $this-&gt;_disconnect();
+            return false;
+        }
+    }
+
+    /**
+     * Retrieve the current vacation details for the user.
+     *
+     * @param   $user        The username for which to retrieve details.
+     * @param   $realm       The realm (domain) for the user.
+     * @param   $password    The password of the user.
+     *
+     * @return  mixed        Vacation details or false.
+     */
+    function _getUserDetails($user, $realm, $password)
+    {
+        // Make sure the configuration file is correct
+        if (!$this-&gt;checkConfig($realm)) {
+            return false;
+        }
+
+        /* _connect() will die with Horde::fatal() upon failure. */
+        $this-&gt;_connect($realm);
+
+        // Build username.
+        $myuser = $this-&gt;_buildUsername($user, $realm);
+
+        /* Build the SQL query. */
+        $query = 'SELECT ' . $this-&gt;params[$realm]['vacation'] . ' AS vacation';
+        $query .= ' , ' . $this-&gt;params[$realm]['message'] . ' AS message';
+        $query .= ' , ' . $this-&gt;params[$realm]['subject'] . ' AS subject';
+        $query .= ' FROM ' . $this-&gt;params[$realm]['table'];
+        $query .= ' WHERE ' . $this-&gt;params[$realm]['user_col'] . ' = ' . $this-&gt;_db-&gt;quote($myuser);
+
+        /* Execute the query. */
+        $result = $this-&gt;_db-&gt;query($query);
+
+        if (!is_a($result, 'PEAR_Error')) {
+            $row = $result-&gt;fetchRow(DB_FETCHMODE_ASSOC);
+            if (is_array($row)) {
+                $this-&gt;_disconnect();
+                $row['message'] = 'Subject: ' . $row['subject'] . &quot;\n&quot; . $row['message'];
+                return $row;
+            } else {
+                $this-&gt;_disconnect();
+                return false;
+            }
+        } else {
+            $this-&gt;_disconnect();
+            return false;
+        }
+    }
+
+    /**
+     * Do an SQL connect and login as user with privilege to change
+     * vacation.
+     *
+     * @return   boolean   True or False based on success of connect
+     */
+    function _connect($realm)
+    {
+        if (!$this-&gt;_connected) {
+            // Build the params array to pass to DB
+            $_args = array_merge($this-&gt;params, $this-&gt;params[$realm]);
+
+            Horde::assertDriverConfig($_args, 'server',
+                array('phptype', 'hostspec', 'username', 'database', 'table'),
+                'vacation authentication SQL');
+
+            /* Connect to the SQL server using the supplied parameters. */
+            require_once 'DB.php';
+            $this-&gt;_db = &amp;DB::connect($_args,
+                                      array('persistent' =&gt; !empty($_args['persistent'])));
+            if (is_a($this-&gt;_db, 'PEAR_Error')) {
+                Horde::fatal(PEAR::raiseError(_(&quot;Unable to connect to SQL server.&quot;)), __FILE__, __LINE__);
+            }
+
+            $this-&gt;_db-&gt;setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS);
+
+            $this-&gt;_connected = true;
+        }
+
+        return true;
+    }
+
+    /**
+     * Disconnect from the SQL server and clean up the connection.
+     *
+     * @return boolean true on success, false on failure.
+     */
+    function _disconnect()
+    {
+        if ($this-&gt;_connected) {
+            $this-&gt;_connected = false;
+            return $this-&gt;_db-&gt;disconnect();
+        }
+
+        return true;
+    }
+
+    /**
+     * Builds a username based on presense of realm
+     * @return string user@realm or user
+     */
+    function _buildUsername($user, $realm)
+    {
+        if ($realm === 'default' ||
+            $realm === '') {
+            return $user;
+        } else {
+            return $user . &quot;@&quot; . $realm;
+        }
+    }
+
+}
diff -urN vacation/lib/Driver.php /usr/local/www/data/files/vacation/lib/Driver.php
--- vacation/lib/Driver.php	Mon Jan  3 21:35:40 2005
+++ /usr/local/www/data/files/vacation/lib/Driver.php	Tue Feb  8 08:57:48 2005
@@ -95,10 +95,12 @@
 
         // Check vacation flag.
         if ($current_details['vacation'] === 'y' ||
-            $current_details['vacation'] === 'Y') {
+            $current_details['vacation'] === 'Y' ||
+	    $current_details['vacation'] === '1') {
             return 'Y';
         } elseif ($current_details['vacation'] === 'n' ||
-                  $current_details['vacation'] === 'N') {
+		  $current_details['vacation'] === 'N' ||
+                  $current_details['vacation'] === '0') {
             return 'N';
         } else {
             return false;
</description>
   <pubDate>Mon, 07 Feb 2005 22:27:59 -0500</pubDate>
   <link>http://bugs.horde.org/ticket/1326#t5291</link>
  </item>
  <item>
   <title>Wouldn't it make more sense to extend the Vacation_Driver_sq</title>
   <description>Wouldn't it make more sense to extend the Vacation_Driver_sql class? This looks like a lot of redundant code.

Beside that, please upload the patch as an attachment to this ticket.</description>
   <pubDate>Tue, 08 Feb 2005 03:59:59 -0500</pubDate>
   <link>http://bugs.horde.org/ticket/1326#t5311</link>
  </item>
  <item>
   <title>In my opinion, if we only extend the Vacation_Driver_sql cla</title>
   <description>In my opinion, if we only extend the Vacation_Driver_sql class, we have to do some modifications on the database itself, which i think may cause postfixadmin to break

Here's the attached patch</description>
   <pubDate>Tue, 08 Feb 2005 04:05:28 -0500</pubDate>
   <link>http://bugs.horde.org/ticket/1326#t5318</link>
  </item>
  <item>
   <title>You don't need to extend the SQL driver's DB structure, but </title>
   <description>You don't need to extend the SQL driver's DB structure, but there is a lot of duplicate code. If Vacation_Driver_sql is too inflexible at the moment to be extended by the postfixadmin driver, feel free to patch that driver too. Just make sure that you don't break it. ;-)</description>
   <pubDate>Tue, 08 Feb 2005 04:11:05 -0500</pubDate>
   <link>http://bugs.horde.org/ticket/1326#t5324</link>
  </item>
  <item>
   <title>Are you going to provide an updated patch?</title>
   <description>Are you going to provide an updated patch?</description>
   <pubDate>Sat, 22 Oct 2005 11:22:34 -0400</pubDate>
   <link>http://bugs.horde.org/ticket/1326#t12729</link>
  </item>
  <item>
   <title>No feedback.</title>
   <description>No feedback.</description>
   <pubDate>Mon, 28 Nov 2005 10:29:06 -0500</pubDate>
   <link>http://bugs.horde.org/ticket/1326#t14226</link>
  </item>
  

 </channel>
</rss>
