1: <?php
2: /**
3: * Sam storage implementation for FTP access to the users' user_prefs files.
4: *
5: * Copyright 2003-2012 Horde LLC (http://www.horde.org/)
6: *
7: * See the enclosed file COPYING for license information (GPL). If you
8: * did not receive this file, see http://www.horde.org/licenses/gpl.
9: *
10: * @author Chris Bowlby <cbowlby@tenthpowertech.com>
11: * @author Max Kalika <max@horde.org>
12: * @author Ben Chavet <ben@horde.org>
13: * @author Jan Schneider <jan@horde.org>
14: * @package Sam
15: */
16: class Sam_Driver_Spamd_Ftp extends Sam_Driver_Spamd_Base
17: {
18: /**
19: * VFS instance.
20: *
21: * @var Horde_Vfs_Base
22: */
23: protected $_vfs;
24:
25: /**
26: * Constructor.
27: *
28: * @param string $user A user name.
29: * @param array $params Class parameters:
30: * - vfs: (Horde_Vfs_Base) A VFS handle pointing to
31: * the FTP server.
32: * - user_prefs: (string) The file with the
33: * user preferences, relative to the home directory.
34: */
35: public function __construct($user, $params = array())
36: {
37: foreach (array('vfs', 'user_prefs') as $param) {
38: if (!isset($params[$param])) {
39: throw new InvalidArgumentException(
40: sprintf('"%s" parameter is missing', $param));
41: }
42: }
43:
44: $this->_vfs = $params['vfs'];
45: unset($params['vfs']);
46:
47: parent::__construct($user, $params);
48: }
49:
50: /**
51: * Retrieves user preferences from the backend.
52: *
53: * @throws Sam_Exception
54: */
55: public function retrieve()
56: {
57: /* Get preference file(s). */
58: try {
59: $content = $this->_vfs->read(
60: dirname($this->_params['system_prefs']),
61: basename($this->_params['system_prefs']));
62: $conf = $this->_parse($content);
63: $content = $this->_vfs->read(
64: dirname($this->_params['user_prefs']),
65: basename($this->_params['user_prefs']));
66: $conf = array_merge($conf, $this->_parse($content));
67: } catch (Horde_Vfs_Exception $e) {
68: throw new Sam_Exception($e);
69: }
70:
71: foreach ($conf as $option => $value) {
72: $this->_options[$this->_mapOptionToAttribute($option)] = $value;
73: }
74: }
75:
76: /**
77: * Stores user preferences in the backend.
78: *
79: * @param boolean $defaults Whether to store the global defaults instead
80: * of user options. Unused.
81: *
82: * @throws Sam_Exception
83: */
84: public function store($defaults = false)
85: {
86: /* Generate preference file. */
87: $output = '# ' . _("SpamAssassin preference file generated by Sam")
88: . ' (' . date('F j, Y, g:i a') . ")\n";
89:
90: foreach ($this->_options as $attribute => $value) {
91: if (is_array($value)) {
92: $output .= $this->_mapAttributeToOption($attribute) . ' '
93: . trim(implode(' ', $value)) . "\n";
94: } else {
95: $output .= $this->_mapAttributeToOption($attribute) . ' '
96: . trim($value) . "\n";
97: }
98: }
99:
100: /* Write preference file. */
101: try {
102: $this->_vfs->writeData(dirname($this->_params['user_prefs']),
103: basename($this->_params['user_prefs']),
104: $output,
105: true);
106: } catch (Horde_Vfs_Exception $e) {
107: throw new Sam_Exception($e);
108: }
109: }
110:
111: /**
112: * Parses the file into an option-value-hash.
113: *
114: * @param string $config The configuration file contents.
115: *
116: * @return array Hash with options and values.
117: */
118: protected function _parse($config)
119: {
120: $config = explode("\n", $config);
121: $parsed = array();
122:
123: foreach ($config as $line) {
124: // Ignore comments and whitespace.
125: $line = trim(substr($line, 0, strcspn($line, '#')));
126: if (!empty($line)) {
127: $split = preg_split('/\s+/', $line, 2);
128: if (count($split) == 2) {
129: $parsed[$split[0]] = $split[1];
130: }
131: }
132: }
133:
134: return $parsed;
135: }
136: }
137: