1: <?php
2: /**
3: * Defines the AJAX interface for an application.
4: *
5: * Copyright 2010-2012 Horde LLC (http://www.horde.org/)
6: *
7: * See the enclosed file COPYING for license information (LGPL). If you
8: * did not receive this file, see http://www.horde.org/licenses/lgpl21.
9: *
10: * @author Michael Slusarz <slusarz@horde.org>
11: * @category Horde
12: * @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
13: * @package Core
14: */
15: abstract class Horde_Core_Ajax_Application
16: {
17: /**
18: * Determines if notification information is sent in response.
19: *
20: * @var boolean
21: */
22: public $notify = false;
23:
24: /**
25: * The action to perform.
26: *
27: * @var string
28: */
29: protected $_action;
30:
31: /**
32: * The Horde application.
33: *
34: * @var string
35: */
36: protected $_app;
37:
38: /**
39: * Default domain.
40: *
41: * @see parseEmailAddress()
42: * @var string
43: */
44: protected $_defaultDomain;
45:
46: /**
47: * The list of actions that require readonly access to the session.
48: *
49: * @var array
50: */
51: protected $_readOnly = array();
52:
53: /**
54: * The request variables.
55: *
56: * @var Horde_Variables
57: */
58: protected $_vars;
59:
60: /**
61: * Constructor.
62: *
63: * @param string $app The application name.
64: * @param Horde_Variables $vars Form/request data.
65: * @param string $action The AJAX action to perform.
66: */
67: public function __construct($app, Horde_Variables $vars, $action = null)
68: {
69: $this->_app = $app;
70: $this->_vars = $vars;
71:
72: if (!is_null($action)) {
73: /* Close session if action is labeled as read-only. */
74: if (in_array($action, $this->_readOnly)) {
75: $GLOBALS['session']->close();
76: }
77:
78: $this->_action = $action;
79: }
80: }
81:
82: /**
83: * Performs the AJAX action.
84: *
85: * @return mixed The result of the action call.
86: * @throws Horde_Exception
87: */
88: public function doAction()
89: {
90: if (!$this->_action) {
91: return false;
92: }
93:
94: if (method_exists($this, $this->_action)) {
95: return call_user_func(array($this, $this->_action));
96: }
97:
98: /* Look for hook in application. */
99: try {
100: return Horde::callHook('ajaxaction', array($this->_action, $this->_vars), $this->_app);
101: } catch (Horde_Exception_HookNotSet $e) {
102: } catch (Horde_Exception $e) {
103: }
104:
105: throw new Horde_Exception('Handler for action "' . $this->_action . '" does not exist.');
106: }
107:
108: /**
109: * Determines the HTTP response output type.
110: *
111: * @see Horde::sendHTTPResponse().
112: *
113: * @return string The output type.
114: */
115: public function responseType()
116: {
117: return 'json';
118: }
119:
120: /**
121: * Logs the user off the Horde session.
122: *
123: * This needs to be done here (server), rather than on the browser,
124: * because the logout tokens might otherwise expire.
125: */
126: public function logOut()
127: {
128: Horde::getServiceLink('logout', $this->_app)->setRaw(true)->redirect();
129: }
130:
131: /**
132: * AJAX actions performed through the endpoint are normally not a good
133: * URL to return to. Thus, by default after a session timeout, return
134: * to the base of the application instead.
135: *
136: * @return Horde_Url The logout Horde_Url object.
137: */
138: public function getSessionLogoutUrl()
139: {
140: return $GLOBALS['registry']->getLogoutUrl(array(
141: 'reason' => Horde_Auth::REASON_SESSION
142: ))->add('url', Horde::url('', false, array(
143: 'app' => $this->_app,
144: 'append_session' => -1
145: )));
146: }
147:
148: /**
149: * Returns a hash of group IDs and group names that the user has access
150: * to.
151: *
152: * @return object Object with the following properties:
153: * - groups: (array) Groups hash.
154: */
155: public function listGroups()
156: {
157: $result = new stdClass;
158: try {
159: $groups = $GLOBALS['injector']
160: ->getInstance('Horde_Group')
161: ->listAll(empty($GLOBALS['conf']['share']['any_group'])
162: ? $GLOBALS['registry']->getAuth()
163: : null);
164: if ($groups) {
165: asort($groups);
166: $result->groups = $groups;
167: }
168: } catch (Horde_Group_Exception $e) {
169: Horde::logMessage($e);
170: }
171:
172: return $result;
173: }
174:
175: /**
176: * Parses a valid email address out of a complete address string.
177: *
178: * Variables used:
179: * - mbox: (string) The name of the new mailbox.
180: * - parent: (string) The parent mailbox.
181: *
182: * @return object Object with the following properties:
183: * - email: (string) The parsed email address.
184: *
185: * @throws Horde_Exception
186: * @throws Horde_Mail_Exception
187: */
188: public function parseEmailAddress()
189: {
190: $rfc822 = new Horde_Mail_Rfc822();
191: $params = array();
192: if ($this->_defaultDomain) {
193: $params['default_domain'] = $this->_defaultDomain;
194: }
195: $res = $rfc822->parseAddressList(Horde_Mime::encodeAddress($this->_vars->email, 'UTF-8', $this->_defaultDomain), $params);
196: if (!count($res)) {
197: throw new Horde_Exception(Horde_Core_Translation::t("No valid email address found"));
198: }
199:
200: return (object)array(
201: 'email' => Horde_Mime_Address::writeAddress($res[0]->mailbox, $res[0]->host)
202: );
203: }
204:
205: /**
206: * Loads a chunk of PHP code (usually an HTML template) from the
207: * application's templates directory.
208: *
209: * @return object Object with the following properties:
210: * - chunk: (string) A chunk of PHP output.
211: */
212: public function chunkContent()
213: {
214: $chunk = basename(Horde_Util::getPost('chunk'));
215: $result = new stdClass;
216: if (!empty($chunk)) {
217: Horde::startBuffer();
218: include $GLOBALS['registry']->get('templates', $this->_app) . '/chunks/' . $chunk . '.php';
219: $result->chunk = Horde::endBuffer();
220: }
221:
222: return $result;
223: }
224:
225: /**
226: * Sets a preference value.
227: *
228: * Variables used:
229: * - pref: (string) The preference name.
230: * - value: (mixed) The preference value.
231: *
232: * @return boolean True on success.
233: */
234: public function setPrefValue()
235: {
236: return $GLOBALS['prefs']->setValue($this->_vars->pref, $this->_vars->value);
237: }
238:
239: }
240: