]> git.sur5r.net Git - bacula/bacula/blob - gui/baculum/protected/Class/API.php
baculum: Prevent opening new sessions for each request
[bacula/bacula] / gui / baculum / protected / Class / API.php
1 <?php
2 /*
3  * Bacula(R) - The Network Backup Solution
4  * Baculum   - Bacula web interface
5  *
6  * Copyright (C) 2013-2015 Marcin Haba
7  *
8  * The main author of Baculum is Marcin Haba.
9  * The original author of Bacula is Kern Sibbald, with contributions
10  * from many others, a complete list can be found in the file AUTHORS.
11  *
12  * You may use this file and others of this release according to the
13  * license defined in the LICENSE file, which includes the Affero General
14  * Public License, v3.0 ("AGPLv3") and some additional permissions and
15  * terms pursuant to its AGPLv3 Section 7.
16  *
17  * This notice must be preserved when any source code is
18  * conveyed and/or propagated.
19  *
20  * Bacula(R) is a registered trademark of Kern Sibbald.
21  */
22
23 Prado::using('Application.Class.Errors');
24
25 class API extends TModule {
26
27         const API_VERSION = '0.1';
28
29         protected $appCfg;
30
31         private $allowedErrors = array(
32                 GenericError::ERROR_NO_ERRORS,
33                 BconsoleError::ERROR_INVALID_COMMAND,
34                 PoolError::ERROR_NO_VOLUMES_IN_POOL_TO_UPDATE
35         );
36
37         private function getConnection() {
38                 $ch = curl_init();
39                 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
40                 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
41                 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
42                 curl_setopt($ch, CURLOPT_COOKIE, 'PHPSESSID=' . md5(session_id()));
43                 curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
44                 curl_setopt($ch, CURLOPT_USERPWD, $this->appCfg['baculum']['login'] . ':' . $this->appCfg['baculum']['password']);
45                 return $ch;
46         }
47
48         private function getAPIHeaders() {
49                 $headers = array(
50                         'X-Baculum-API: ' . self::API_VERSION,
51                         'X-Baculum-User: ' . $this->Application->User->getName(),
52                         'X-Baculum-Pwd: ' . $this->Application->User->getPwd(),
53                         'Accept: application/json'
54                 );
55                 return $headers;
56         }
57
58         public function init($config) {
59                 $this->initSessionCache();
60                 $this->appCfg = $this->Application->getModule('configuration')->getApplicationConfig();
61         }
62
63         private function getURL() {
64                 $protocol = !empty($_SERVER['HTTPS']) ? 'https' : 'http';
65                 $host = $_SERVER['SERVER_NAME'];
66                 $port = $_SERVER['SERVER_PORT'];
67                 $urlPrefix = $this->Application->getModule('friendly-url')->getUrlPrefix();
68                 $url = sprintf('%s://%s:%d%s/', $protocol, $host, $port, $urlPrefix);
69                 return $url;
70         }
71
72         private function setParamsToUrl(&$url) {
73                 $url .= (preg_match('/\?/', $url) === 1 ? '&' : '?' ) . 'director=' . ((array_key_exists('director', $_SESSION)) ? $_SESSION['director'] : '');
74                 $this->Application->getModule('logging')->log(__FUNCTION__, PHP_EOL . PHP_EOL . 'EXECUTE URL ==> ' . $url . ' <==' . PHP_EOL . PHP_EOL, Logging::CATEGORY_APPLICATION, __FILE__, __LINE__);
75         }
76
77         /**
78          * API REQUESTS METHODS (get, set, create, delete)
79          */
80
81         public function get(array $params, $use_cache = false) {
82                 $cached = null;
83                 $ret = null;
84                 if ($use_cache === true) {
85                         $cached = $this->getSessionCache($params);
86                 }
87                 if (!is_null($cached)) {
88                         $ret = $cached;
89                 } else {
90                         $url = $this->getURL() . implode('/', $params);
91                         $this->setParamsToUrl($url);
92                         $ch = $this->getConnection();
93                         curl_setopt($ch, CURLOPT_URL, $url);
94                         curl_setopt($ch, CURLOPT_HTTPHEADER, $this->getAPIHeaders());
95                         $result = curl_exec($ch);
96                         curl_close($ch);
97                         $ret = $this->preParseOutput($result);
98                         if ($use_cache === true && $ret->error === 0) {
99                                 $this->setSessionCache($params, $ret);
100                         }
101                 }
102                 return $ret;
103         }
104
105         public function set(array $params, array $options) {
106                 $url = $this->getURL() . implode('/', $params);
107                 $this->setParamsToUrl($url);
108                 $data = http_build_query(array('update' => $options));
109                 $ch = $this->getConnection();
110                 curl_setopt($ch, CURLOPT_URL, $url);
111                 curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
112                 curl_setopt($ch, CURLOPT_HTTPHEADER, array_merge($this->getAPIHeaders(), array('X-HTTP-Method-Override: PUT', 'Content-Length: ' . strlen($data), 'Expect:')));
113                 curl_setopt($ch, CURLOPT_POST, true);
114                 curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
115                 $result = curl_exec($ch);
116                 curl_close($ch);
117                 return $this->preParseOutput($result);
118         }
119
120         public function create(array $params, array $options) {
121                 $url = $this->getURL() . implode('/', $params);
122                 $this->setParamsToUrl($url);
123                 $data = http_build_query(array('create' => $options));
124                 $ch = $this->getConnection();
125                 curl_setopt($ch, CURLOPT_URL, $url);
126                 curl_setopt($ch, CURLOPT_HTTPHEADER, array_merge($this->getAPIHeaders(), array('Expect:')));
127                 curl_setopt($ch, CURLOPT_POST, true);
128                 curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
129                 $result = curl_exec($ch);
130                 curl_close($ch);
131                 return $this->preParseOutput($result);
132         }
133
134         public function remove(array $params) {
135                 $url = $this->getURL() . implode('/', $params);
136                 $this->setParamsToUrl($url);
137                 $ch = $this->getConnection();
138                 curl_setopt($ch, CURLOPT_URL, $url);
139                 curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
140                 curl_setopt($ch, CURLOPT_HTTPHEADER, array_merge($this->getAPIHeaders(), array('X-HTTP-Method-Override: DELETE')));
141                 $result = curl_exec($ch);
142                 curl_close($ch);
143                 return $this->preParseOutput($result);
144         }
145
146         private function preParseOutput($result) {
147                 $this->Application->getModule('logging')->log(__FUNCTION__, $result, Logging::CATEGORY_APPLICATION, __FILE__, __LINE__);
148                 $resource = json_decode($result);
149                 $error = null;
150                 if(is_object($resource) && property_exists($resource, 'error')) {
151                         if(!in_array($resource->error, $this->allowedErrors)) {
152                                 $error = $resource->error;
153                         }
154                 } else {
155                         $error = AuthorizationError::ERROR_AUTHORIZATION_TO_WEBGUI_PROBLEM;
156                 }
157
158                 $this->Application->getModule('logging')->log(__FUNCTION__, $resource, Logging::CATEGORY_APPLICATION, __FILE__, __LINE__);
159                 if(!is_null($error)) {
160                         // Note! Redirection to error page takes place here.
161                         $this->Response->redirect($this->Service->constructUrl('BaculumError',array('error' => $error), false));
162                 }
163
164                 return $resource;
165         }
166
167         public function initSessionCache($force = false) {
168                 if (!isset($_SESSION) || !array_key_exists('cache', $_SESSION) || !is_array($_SESSION['cache']) || $force === true) {
169                         $_SESSION['cache'] = array();
170                 }
171         }
172
173         private function getSessionCache(array $params) {
174                 $cached = null;
175                 $key = $this->getSessionKey($params);
176                 if ($this->isSessionValue($key)) {
177                         $cached = $_SESSION['cache'][$key];
178                 }
179                 return $cached;
180         }
181
182         private function setSessionCache(array $params, $value) {
183                 $key = $this->getSessionKey($params);
184                 $_SESSION['cache'][$key] = $value;
185         }
186
187         private function getSessionKey(array $params) {
188                 $key = implode(';', $params);
189                 $key = base64_encode($key);
190                 return $key;
191         }
192
193         private function isSessionValue($key) {
194                 $is_value = array_key_exists($key, $_SESSION['cache']);
195                 return $is_value;
196         }
197 }
198 ?>