[dev] [patch] new sam driver

Ben Chavet ben at chavet.net
Fri Apr 9 08:52:38 PDT 2004


> > As far as what it is called, that really doesn't matter to me so much.  I
> > used gollem, ingo, & vacation as my inspiration & reference to write this.
> > Ingo and gollem called their drivers vfs, so that's what I went with.
> 
> Okay - with those, though, you really can use any VFS backend, because it
> doesn't matter where the data is as long as the app can get to it. With 
> SAM, we
> already have a SQL driver (and SQL VFS won't work for it), and the FTP driver
> is the only one that seems to make sense (again, to *me* - if I'm missing
> something, please let me know).

Fair enough.  Here is a new patch for an ftp driver.

Modified Files:
  sam/lib/Driver.php  <-- Let me know if this breaks anything.
  sam/config/backends.php.dist

New Files:
  sam/lib/Driver/ftp.php

--Ben
-------------- next part --------------
<?php

/**
 * $Horde$
 *
 * Copyright 2003-2004 Chris Bowlby <excalibur at hub.org>
 * Copyright 2003-2004 Max Kalika <max at horde.org>
 * Copyright 2004 Ben Chavet <ben at horde.org>
 *
 * See the enclosed file COPYING for license information (GPL). If you
 * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
 *
 * @author  Chris Bowlby <excalibur at hub.org>
 * @author  Max Kalika <max at horde.org>
 * @author  Ben Chavet <ben at horde.org>
 * @version $Revision$
 * @since   SAM 0.0.1
 * @package sam
 */

class SAM_Driver_ftp extends SAM_Driver {

    /**
     * List of the capabilities supported by this driver.
     *
     * @var array $_capabilities
     */
    var $_capabilities = array('tag_level',
                               'hit_level',
                               'kill_level',
                               'subject_tag',
                               'rewrite_sub',
                               'spam_quarantine',
                               'level_stars',
                               'report_header',
                               'terse_report',
                               'defang_mime',
                               'skip_rbl',
                               'skip_virus',
                               'skip_spam',
                               'skip_banned',
                               'skip_header',
                               'allow_virus',
                               'allow_spam',
                               'allow_banned',
                               'allow_header',);

    /**
     * Constructs a new FTP storage object.
     *
     * @access public
     *
     * @param string $user               The user who owns these SPAM options.
     * @param optional array $params     A hash containing connection
     *                                   parameters.
     */
    function SAM_Driver_ftp($user, $params = array())
    {
        $default_params = array(
            'hostspec'   => 'localhost',
            'port'       => 21,
            'user_prefs' => '.spamassassin/user_prefs',
            'vfstype'    => 'ftp'
        );
        $this->_user = $user;
        $this->_params = array_merge($default_params, $params);
    }

    /**
     * Converts a SAM attribute to an option that SpamAssassin will use.
     *
     * @access private
     *
     * @param string $attribute          The SAM attribute to convert.
     *
     * @return string   The converted SpamAssassin option or the original
     *                  attribute if no match is found.
     */
    function _mapAttributeToOption($attribute)
    {
        return isset($this->_params['option_map'][$attribute]) 
            ? $this->_params['option_map'][$attribute] : $attribute;
           
    }

    /**
     * Converts a SpamAssassin option to a SAM attribute.
     *
     * @access private
     *
     * @param string $option             The SpamAssassin option to convert.
     *
     * @return string   The converted SAM attribute or the original option if
     *                  no match is found.
     */
    function _mapOptionToAttribute($option)
    {
        $attribute_map = array();
        if (isset($this->_params['option_map'])) {
            $attribute_map = array_flip($this->_params['option_map']);
        }

        return isset($attribute_map[$option])
               ? $attribute_map[$option] : $option;
    }

    /**
     * Retreives the user options and stores them in the member array.
     *
     * @access public
     *
     * @return mixed    True on success or a PEAR_Error object on failure.
     */
    function retrieve()
    { 
        $options = $this->_retrieve();
        if (!is_a($options, 'PEAR_Error')) {
            $this->_options = $options;
        } else {
            return $options;
        }

        return true;
    }

    /**
     * Stores the user options from the member array.
     *
     * @access public
     *
     * @return mixed    True on success or a PEAR_Error object on failure.
     */
    function store()
    {
        return $this->_store();
    }

    /**
     * Retrieve an option set from the storage backend.
     *
     * @access private
     *
     * @return mixed    Array of field-value pairs or a PEAR_Error object
     *                  on failure.
     */
    function _retrieve()
    {
        $this->_params['username'] = $this->_user;
        $this->_params['password'] = Auth::getCredential('password');

        // get config file(s)
        require_once 'VFS.php';
        $vfs = &VFS::singleton('ftp', $this->_params);
        $system_config = $vfs->read('', $this->_params['system_prefs']);
        $user_config = $vfs->read('', $this->_params['user_prefs']);
        $vfs->_disconnect();

        if (!is_a($system_config, 'PEAR_Error') && !is_a($user_config, 'PEAR_Error')) {
            $conf = array_merge($this->_parse($system_config), $this->_parse($user_config));
        } else if (!is_a($system_config, 'PEAR_Error')) {
            $conf = $this->_parse($system_config);
        } else if (!is_a($user_config, 'PEAR_Error')) {
            $conf = $this->_parse($user_config);
        } else {
            $conf = array();
        }

        $return = array();
        foreach($conf as $line) {
            if (isset($line[1])) {
                $return[$this->_mapOptionToAttribute($line[0])] = $line[1];
            }
        }
        return $return;
    }

    function _parse($config) 
    {
        // Ignore comments and whitespace
        $conf = explode("\n", $config);
        foreach ($conf as $index => $line) {
            $comment = strpos($line, '#');
            if ($comment === 0 || trim($line) == '') {
                unset($conf[$index]);
            } else if ($comment) {
                $conf[$index] = substr($line, 0, $comment);
            }
        }

        foreach ($conf as $index => $line) {
            $conf[$index] = preg_split("/\s+/", trim($line));
        }

        return $conf;
    }

    /**
     * Store an option set from the member array to the storage backend.
     *
     * @access private
     *
     * @return mixed    True on success or a PEAR_Error object on failure.
     */
    function _store()
    {
       $this->_params['username'] = $this->_user;
       $this->_params['password'] = Auth::getCredential('password');
        
        // generate config file
        $output = _("# SpamAssassin config file generated by SAM") . ' (' . date('F j, Y, g:i a') . ")\n";
        $store = $this->_options;
        foreach ($store as $attribute => $value) {
            $output .= $this->_mapAttributeToOption($attribute) . "  $value\n";
        }

        // write config file
        require_once 'VFS.php';
        $vfs = &VFS::singleton('ftp', $this->_params);
        $res = $vfs->writeData('', $this->_params['user_prefs'], $output);
        $vfs->_disconnect();
        if (is_a($res, 'PEAR_Error')) {
            return $res;
        }
        return true;
     }
 
}
-------------- next part --------------
Index: Driver.php
===================================================================
RCS file: /repository/sam/lib/Driver.php,v
retrieving revision 1.18
diff -u -r1.18 Driver.php
--- Driver.php	30 Oct 2003 23:38:07 -0000	1.18
+++ Driver.php	9 Apr 2004 15:41:20 -0000
@@ -146,7 +146,7 @@
      */
     function optionToBoolean($option)
     {
-        return $option === $this->booleanToOption(true);
+        return $option == $this->booleanToOption(true);
     }
 
     /**
-------------- next part --------------
Index: backends.php.dist
===================================================================
RCS file: /repository/sam/config/backends.php.dist,v
retrieving revision 1.7
diff -u -r1.7 backends.php.dist
--- backends.php.dist	5 Apr 2004 23:28:29 -0000	1.7
+++ backends.php.dist	9 Apr 2004 15:47:26 -0000
@@ -169,3 +169,24 @@
         ),
     ),
 );
+
+$backends['ftp'] = array(
+    'preferred' => '',
+    'hordeauth' => true,
+    'driver' => 'ftp',
+    'params' => array(
+        'hostspec' => 'localhost',
+        // Location of system-wide config file. Used for
+        // any undefined user prefs.
+        'system_prefs' => '/etc/mail/spamassassin/local.cf',
+        // Location of per-user config file.
+        'user_prefs' => '.spamassassin/user_prefs',
+        'port' => 21,
+        'option_map' => array(
+            'hit_level' => 'required_hits',
+            'subject_tag' => 'subject_tag',
+            'rewrite_sub' => 'rewrite_subject',
+            'level_stars' => 'spam_level_stars',
+        )
+    )
+);


More information about the dev mailing list