Subversion Repositories eFlore/Applications.cel

Rev

Rev 1920 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1920 Rev 2463
1
<?php
1
<?php
2
// In : utf8 url_encoded (get et post)
2
// declare(encoding='UTF-8');
3
// Out : utf8
3
/**
-
 
4
 * Classe principale de gestion des web-services.
4
 
5
 *
-
 
6
 * @internal   Mininum PHP version : 5.2
-
 
7
 * @category   CEL
-
 
8
 * @package    Services
-
 
9
 * @subpackage Index
-
 
10
 * @version    0.1
-
 
11
 * @author     Mathias CHOUET <mathias@tela-botanica.org>
-
 
12
 * @author     Jean-Pascal MILCENT <jpm@tela-botanica.org>
-
 
13
 * @author     Aurelien PERONNET <aurelien@tela-botanica.org>
-
 
14
 * @license    GPL v3 <http://www.gnu.org/licenses/gpl.txt>
-
 
15
 * @license    CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
5
// TODO : gerer les retours : dans ce controleur : code retour et envoi ...
16
 * @copyright  1999-2014 Tela Botanica <accueil@tela-botanica.org>
-
 
17
 */
6
class JRest {
18
class JRest {
7
 
19
 
8
 	/** Parsed configuration file */
20
 	/** Parsed configuration file */
9
    private $config;
21
    private $config;
10
 
22
 
11
	/** The HTTP request method used. */
23
	/** The HTTP request method used. */
12
	private $method = 'GET';
24
	private $method = 'GET';
13
 
25
 
14
	/** The HTTP request data sent (if any). */
26
	/** The HTTP request data sent (if any). */
15
	private $requestData = NULL;
27
	private $requestData = NULL;
16
 
28
 
17
	/** Array of strings to convert into the HTTP response. */
29
	/** Array of strings to convert into the HTTP response. */
18
	private $output = array();
30
	private $output = array();
19
 
31
 
20
	/** Nom resource. */
32
	/** Nom resource. */
21
	private $resource = NULL;
33
	private $resource = NULL;
22
 
34
 
23
	/** Identifiant unique resource. */
35
	/** Identifiant unique resource. */
24
	private $uid = NULL;
36
	private $uid = NULL;
25
 
37
 
26
	/**
38
	/**
27
	 * Constructor. Parses the configuration file "JRest.ini", grabs any request data sent, records the HTTP
39
	 * Constructor. Parses the configuration file "JRest.ini", grabs any request data sent, records the HTTP
28
	 * request method used and parses the request URL to find out the requested resource
40
	 * request method used and parses the request URL to find out the requested resource
29
	 * @param str iniFile Configuration file to use
41
	 * @param str iniFile Configuration file to use
30
	 */
42
	 */
31
	public function JRest($iniFile = 'jrest.ini.php') {
43
	public function JRest($iniFile = 'jrest.ini.php') {
32
		$this->config = parse_ini_file($iniFile, TRUE);
44
		$this->config = parse_ini_file($iniFile, TRUE);
33
		if (isset($_SERVER['REQUEST_URI']) && isset($_SERVER['REQUEST_METHOD']) && isset($_SERVER['QUERY_STRING'])) {
45
		if (isset($_SERVER['REQUEST_URI']) && isset($_SERVER['REQUEST_METHOD']) && isset($_SERVER['QUERY_STRING'])) {
34
			if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] > 0) {
46
			if (isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] > 0) {
35
				$this->requestData = '';
47
				$this->requestData = '';
36
				$httpContent = fopen('php://input', 'r');
48
				$httpContent = fopen('php://input', 'r');
37
				while ($data = fread($httpContent, 1024)) {
49
				while ($data = fread($httpContent, 1024)) {
38
					$this->requestData .= $data;
50
					$this->requestData .= $data;
39
				}
51
				}
40
				fclose($httpContent);
52
				fclose($httpContent);
41
			}
53
			}
42
			if (strlen($_SERVER['QUERY_STRING']) == 0) {
54
			if (strlen($_SERVER['QUERY_STRING']) == 0) {
43
				$len = strlen($_SERVER['REQUEST_URI']);
55
				$len = strlen($_SERVER['REQUEST_URI']);
44
			} else {
56
			} else {
45
				$len = -(strlen($_SERVER['QUERY_STRING']) + 1);
57
				$len = -(strlen($_SERVER['QUERY_STRING']) + 1);
46
			}
58
			}
47
			
59
 
48
			$urlString = '';
60
			$urlString = '';
49
			if  (substr_count($_SERVER['REQUEST_URI'], $this->config['settings']['baseURL']) > 0) {
61
			if  (substr_count($_SERVER['REQUEST_URI'], $this->config['settings']['baseURL']) > 0) {
50
				$urlString = substr($_SERVER['REQUEST_URI'], strlen($this->config['settings']['baseURL']), $len);
62
				$urlString = substr($_SERVER['REQUEST_URI'], strlen($this->config['settings']['baseURL']), $len);
51
			} else if (substr_count($_SERVER['REQUEST_URI'], $this->config['settings']['baseAlternativeURL']) > 0) {
63
			} else if (substr_count($_SERVER['REQUEST_URI'], $this->config['settings']['baseAlternativeURL']) > 0) {
52
				$urlString = substr($_SERVER['REQUEST_URI'], strlen($this->config['settings']['baseAlternativeURL']), $len);
64
				$urlString = substr($_SERVER['REQUEST_URI'], strlen($this->config['settings']['baseAlternativeURL']), $len);
53
			}
65
			}
54
 
66
 
55
			$urlParts = explode('/', $urlString);
67
			$urlParts = explode('/', $urlString);
56
 
68
 
57
			if (isset($urlParts[0])) $this->resource = $urlParts[0];
69
			if (isset($urlParts[0])) $this->resource = $urlParts[0];
58
			if (count($urlParts) > 1 && $urlParts[1] != '') {
70
			if (count($urlParts) > 1 && $urlParts[1] != '') {
59
				array_shift($urlParts);
71
				array_shift($urlParts);
60
				foreach ($urlParts as $uid) {
72
				foreach ($urlParts as $uid) {
61
					if ($uid != '') {
73
					if ($uid != '') {
62
						$this->uid[] = urldecode($uid);
74
						$this->uid[] = urldecode($uid);
63
					}
75
					}
64
				}
76
				}
65
			}
77
			}
66
 
78
 
67
			$this->method = $_SERVER['REQUEST_METHOD'];
79
			$this->method = $_SERVER['REQUEST_METHOD'];
68
		} else {
80
		} else {
69
			trigger_error('I require the server variables REQUEST_URI, REQUEST_METHOD and QUERY_STRING to work.', E_USER_ERROR);
81
			trigger_error('I require the server variables REQUEST_URI, REQUEST_METHOD and QUERY_STRING to work.', E_USER_ERROR);
70
		}
82
		}
71
	}
83
	}
72
 
84
 
73
	/**
85
	/**
74
	 * Execute the request.
86
	 * Execute the request.
75
	 */
87
	 */
76
	function exec() {
88
	function exec() {
77
		switch ($this->method) {
89
		switch ($this->method) {
78
			case 'GET':
90
			case 'GET':
79
				$this->get();
91
				$this->get();
80
				break;
92
				break;
81
			case 'POST':
93
			case 'POST':
82
				$this->post();
94
				$this->post();
83
				break;
95
				break;
84
			case 'DELETE':
96
			case 'DELETE':
85
				$this->delete();
97
				$this->delete();
86
				break;
98
				break;
87
			case 'PUT':
99
			case 'PUT':
88
				$this->add();
100
				$this->add();
89
				break;
101
				break;
90
		}
102
		}
91
	}
103
	}
92
 
104
 
93
	/**
105
	/**
94
	 * Execute a GET request. A GET request fetches a list of resource when no resource name is given, a list of element
106
	 * Execute a GET request. A GET request fetches a list of resource when no resource name is given, a list of element
95
	 * when a resource name is given, or a resource element when a resource and resource unique identifier are given. It does not change the
107
	 * when a resource name is given, or a resource element when a resource and resource unique identifier are given. It does not change the
96
	 * database contents.
108
	 * database contents.
97
	 */
109
	 */
98
	private function get() {
110
	private function get() {
99
		if ($this->resource) {
111
		if ($this->resource) {
100
			$resource_file = 'services/'.ucfirst($this->resource).'.php';
112
			$resource_file = 'services/'.ucfirst($this->resource).'.php';
101
			$resource_class = ucfirst($this->resource);
113
			$resource_class = ucfirst($this->resource);
102
			if (file_exists($resource_file))  {
114
			if (file_exists($resource_file))  {
103
				include_once $resource_file;
115
				include_once $resource_file;
104
				if (class_exists($resource_class)) {
116
				if (class_exists($resource_class)) {
105
					$service = new $resource_class($this->config);
117
					$service = new $resource_class($this->config);
106
					if ($this->uid) { // get a resource element
118
					if ($this->uid) { // get a resource element
107
						if (method_exists($service, 'getElement')) {
119
						if (method_exists($service, 'getElement')) {
108
							$service->getElement($this->uid);
120
							$service->getElement($this->uid);
109
						}
121
						}
110
					} elseif (method_exists($service, 'getRessource')) { // get all elements of a ressource
122
					} elseif (method_exists($service, 'getRessource')) { // get all elements of a ressource
111
						$service->getRessource();
123
						$service->getRessource();
112
					}
124
					}
113
				}
125
				}
114
			}
126
			}
115
		} else { // get resources
127
		} else { // get resources
116
			// include set.jrest.php, instanticiation et appel
128
			// include set.jrest.php, instanticiation et appel
117
		}
129
		}
118
	}
130
	}
119
 
131
 
120
	private function post() {
132
	private function post() {
121
	   	$pairs = array();
133
	   	$pairs = array();
122
		// Récupération des paramètres passés dans le contenu de la requête HTTP (= POST)
134
		// Récupération des paramètres passés dans le contenu de la requête HTTP (= POST)
123
	   	if ($this->requestData) {
135
	   	if ($this->requestData) {
124
			$pairs = $this->parseRequestData();
136
			$pairs = $this->parseRequestData();
125
		}
137
		}
126
 
138
 
127
		// Ajout des informations concernant l'upload de fichier passées dans la variable $_FILE
139
		// Ajout des informations concernant l'upload de fichier passées dans la variable $_FILE
128
		if(isset($_FILES)) {
140
		if(isset($_FILES)) {
129
			foreach ($_FILES as $v) {
141
			foreach ($_FILES as $v) {
130
				$pairs[$v['name']] = $v;
142
				$pairs[$v['name']] = $v;
131
			}
143
			}
132
 
144
 
133
			// Ne pas effacer cette ligne ! Elle est indispensable pour les services du Carnet en ligne
145
			// Ne pas effacer cette ligne ! Elle est indispensable pour les services du Carnet en ligne
134
			// qui n'utilisent que le tableau pairs dans les posts
146
			// qui n'utilisent que le tableau pairs dans les posts
135
			$pairs = array_merge($_POST, $pairs);
147
			$pairs = array_merge($_POST, $pairs);
136
		}
148
		}
137
 
149
 
138
		// gestion du contenu du post
150
		// gestion du contenu du post
139
		if(isset($_POST))
151
		if(isset($_POST))
140
		{
152
		{
141
			// Safari ne sait pas envoyer des DELETE avec gwt...
153
			// Safari ne sait pas envoyer des DELETE avec gwt...
142
			// Nous utilisons le parametre "action" passé dans le POST qui doit contenir DELETE pour lancer la supression
154
			// Nous utilisons le parametre "action" passé dans le POST qui doit contenir DELETE pour lancer la supression
143
			if (isset($pairs['action']) && $pairs['action'] == 'DELETE') {
155
			if (isset($pairs['action']) && $pairs['action'] == 'DELETE') {
144
				$this->delete();
156
				$this->delete();
145
				return;
157
				return;
146
			}
158
			}
147
 
159
 
148
			if (count($pairs) != 0) {
160
			if (count($pairs) != 0) {
149
				if ($this->uid) { // get a resource element
161
				if ($this->uid) { // get a resource element
150
					$resource_file = 'services/'.ucfirst($this->resource).'.php';
162
					$resource_file = 'services/'.ucfirst($this->resource).'.php';
151
					$resource_class = ucfirst($this->resource);
163
					$resource_class = ucfirst($this->resource);
152
					if (file_exists($resource_file)) {
164
					if (file_exists($resource_file)) {
153
						include_once $resource_file;
165
						include_once $resource_file;
154
						if (class_exists($resource_class)) {
166
						if (class_exists($resource_class)) {
155
							$service = new $resource_class($this->config);
167
							$service = new $resource_class($this->config);
156
							if (method_exists($service,'updateElement')) { // Update element
168
							if (method_exists($service,'updateElement')) { // Update element
157
								$ret_value = false;
169
								$ret_value = false;
158
								try {
170
								try {
159
									// TODO : a voir le retour ...
171
									// TODO : a voir le retour ...
160
									$ret_value = $service->updateElement($this->uid, $pairs);
172
									$ret_value = $service->updateElement($this->uid, $pairs);
161
									if($ret_value) $this->created();
173
									if($ret_value) $this->created();
162
									else $this->badRequest();
174
									else $this->badRequest();
163
								} catch (Exception $e) {
175
								} catch (Exception $e) {
164
									$this->badRequest($e);
176
									$this->badRequest($e);
165
								}
177
								}
166
							}
178
							}
167
						}
179
						}
168
					}
180
					}
169
				} else { // get all elements of a ressource
181
				} else { // get all elements of a ressource
170
					$this->add($pairs);
182
					$this->add($pairs);
171
				}
183
				}
172
			} else {
184
			} else {
173
				$this->lengthRequired();
185
				$this->lengthRequired();
174
			}
186
			}
175
		}
187
		}
176
	}
188
	}
177
 
189
 
178
	private function delete() {
190
	private function delete() {
179
		$resource_file = 'services/'.ucfirst($this->resource).'.php';
191
		$resource_file = 'services/'.ucfirst($this->resource).'.php';
180
		$resource_class = ucfirst($this->resource);
192
		$resource_class = ucfirst($this->resource);
181
		if (file_exists($resource_file)) {
193
		if (file_exists($resource_file)) {
182
			include_once $resource_file;
194
			include_once $resource_file;
183
			if (class_exists($resource_class)) {
195
			if (class_exists($resource_class)) {
184
				$service = new $resource_class($this->config);
196
				$service = new $resource_class($this->config);
185
				if ($this->uid) { // get a resource element
197
				if ($this->uid) { // get a resource element
186
		 			if (method_exists($service, 'deleteElement')) { // Delete element
198
		 			if (method_exists($service, 'deleteElement')) { // Delete element
187
						if ($service->deleteElement($this->uid)) {
199
						if ($service->deleteElement($this->uid)) {
188
							$this->noContent();
200
							$this->noContent();
189
						}
201
						}
190
	 				}
202
	 				}
191
				}
203
				}
192
			}
204
			}
193
		}
205
		}
194
	}
206
	}
195
 
207
 
196
	private function add($pairs = null) {
208
	private function add($pairs = null) {
197
		if (is_null($pairs)) {
209
		if (is_null($pairs)) {
198
			$pairs = array();
210
			$pairs = array();
199
			// Récupération des paramètres passés dans le contenu de la requête HTTP (= POST)
211
			// Récupération des paramètres passés dans le contenu de la requête HTTP (= POST)
200
			// FIXME : vérifier que l'on récupère bien les données passées par PUT
212
			// FIXME : vérifier que l'on récupère bien les données passées par PUT
201
		   	if ($this->requestData) {
213
		   	if ($this->requestData) {
202
				$pairs = $this->parseRequestData();
214
				$pairs = $this->parseRequestData();
203
			}
215
			}
204
		}
216
		}
205
 
217
 
206
		if (count($pairs) != 0) {
218
		if (count($pairs) != 0) {
207
			$resource_file = 'services/'.ucfirst($this->resource).'.php';
219
			$resource_file = 'services/'.ucfirst($this->resource).'.php';
208
			$resource_class = ucfirst($this->resource);
220
			$resource_class = ucfirst($this->resource);
209
			if (file_exists($resource_file)) {
221
			if (file_exists($resource_file)) {
210
				include_once $resource_file;
222
				include_once $resource_file;
211
				if (class_exists($resource_class)) {
223
				if (class_exists($resource_class)) {
212
					$service = new $resource_class($this->config);
224
					$service = new $resource_class($this->config);
213
					if (method_exists($service,'createElement')) { // Create a new element
225
					if (method_exists($service,'createElement')) { // Create a new element
214
						$ret_value = false;
226
						$ret_value = false;
215
						try {
227
						try {
216
							$ret_value = $service->createElement($pairs);
228
							$ret_value = $service->createElement($pairs);
217
							if($ret_value) $this->created();
229
							if($ret_value) $this->created();
218
							else $this->badRequest();
230
							else $this->badRequest();
219
						} catch (Exception $e) {
231
						} catch (Exception $e) {
220
							$this->badRequest($e);
232
							$this->badRequest($e);
221
						}
233
						}
222
					}
234
					}
223
				}
235
				}
224
			}
236
			}
225
		} else {
237
		} else {
226
			$this->lengthRequired();
238
			$this->lengthRequired();
227
		}
239
		}
228
	}
240
	}
229
 
241
 
230
	/**
242
	/**
231
	 * Parse the HTTP request data.
243
	 * Parse the HTTP request data.
232
	 * @return str[] Array of name value pairs
244
	 * @return str[] Array of name value pairs
233
	 */
245
	 */
234
	private function parseRequestData() {
246
	private function parseRequestData() {
235
		$values = array();
247
		$values = array();
236
		$pairs = explode('&', $this->requestData);
248
		$pairs = explode('&', $this->requestData);
237
		foreach ($pairs as $pair) {
249
		foreach ($pairs as $pair) {
238
			$parts = explode('=', $pair);
250
			$parts = explode('=', $pair);
239
			if (isset($parts[0]) && isset($parts[1])) {
251
			if (isset($parts[0]) && isset($parts[1])) {
240
				$parts[1] = rtrim(urldecode($parts[1]));
252
				$parts[1] = rtrim(urldecode($parts[1]));
241
				$values[$parts[0]] = $parts[1];
253
				$values[$parts[0]] = $parts[1];
242
			}
254
			}
243
		}
255
		}
244
		return $values;
256
		return $values;
245
	}
257
	}
246
 
258
 
247
	/**
259
	/**
248
	 * Send a HTTP 201 response header.
260
	 * Send a HTTP 201 response header.
249
	 */
261
	 */
250
	private function created($url = FALSE) {
262
	private function created($url = FALSE) {
251
		header('HTTP/1.0 201 Created');
263
		header('HTTP/1.0 201 Created');
252
		if ($url) {
264
		if ($url) {
253
			header('Location: '.$url);
265
			header('Location: '.$url);
254
		}
266
		}
255
	}
267
	}
256
 
268
 
257
	/**
269
	/**
258
	 * Send a HTTP 204 response header.
270
	 * Send a HTTP 204 response header.
259
	 */
271
	 */
260
	private function noContent() {
272
	private function noContent() {
261
		header('HTTP/1.0 204 No Content');
273
		header('HTTP/1.0 204 No Content');
262
	}
274
	}
263
 
275
 
264
	/**
276
	/**
265
	 * Send a HTTP 400 response header.
277
	 * Send a HTTP 400 response header.
266
	 */
278
	 */
267
	private function badRequest(Exception $e = NULL) {
279
	private function badRequest(Exception $e = NULL) {
268
		header('HTTP/1.0 400 Bad Request');
280
		header('HTTP/1.0 400 Bad Request');
269
		if($e) echo $e->getMessage();
281
		if($e) echo $e->getMessage();
270
	}
282
	}
271
 
283
 
272
	/**
284
	/**
273
	 * Send a HTTP 401 response header.
285
	 * Send a HTTP 401 response header.
274
	 */
286
	 */
275
	private function unauthorized($realm = 'JRest') {
287
	private function unauthorized($realm = 'JRest') {
276
		if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])) {
288
		if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])) {
277
			header('WWW-Authenticate: Basic realm="'.$realm.'"');
289
			header('WWW-Authenticate: Basic realm="'.$realm.'"');
278
		}
290
		}
279
		header('HTTP/1.0 401 Unauthorized');
291
		header('HTTP/1.0 401 Unauthorized');
280
	}
292
	}
281
 
293
 
282
	/**
294
	/**
283
	 * Send a HTTP 404 response header.
295
	 * Send a HTTP 404 response header.
284
	 */
296
	 */
285
	private function notFound() {
297
	private function notFound() {
286
		header('HTTP/1.0 404 Not Found');
298
		header('HTTP/1.0 404 Not Found');
287
	}
299
	}
288
 
300
 
289
	/**
301
	/**
290
	 * Send a HTTP 405 response header.
302
	 * Send a HTTP 405 response header.
291
	 */
303
	 */
292
	private function methodNotAllowed($allowed = 'GET, HEAD') {
304
	private function methodNotAllowed($allowed = 'GET, HEAD') {
293
		header('HTTP/1.0 405 Method Not Allowed');
305
		header('HTTP/1.0 405 Method Not Allowed');
294
		header('Allow: '.$allowed);
306
		header('Allow: '.$allowed);
295
	}
307
	}
296
 
308
 
297
	/**
309
	/**
298
	 * Send a HTTP 406 response header.
310
	 * Send a HTTP 406 response header.
299
	 */
311
	 */
300
	private function notAcceptable() {
312
	private function notAcceptable() {
301
		header('HTTP/1.0 406 Not Acceptable');
313
		header('HTTP/1.0 406 Not Acceptable');
302
		echo join(', ', array_keys($this->config['renderers']));
314
		echo join(', ', array_keys($this->config['renderers']));
303
	}
315
	}
304
 
316
 
305
	/**
317
	/**
306
	 * Send a HTTP 411 response header.
318
	 * Send a HTTP 411 response header.
307
	 */
319
	 */
308
	private function lengthRequired() {
320
	private function lengthRequired() {
309
		header('HTTP/1.0 411 Length Required');
321
		header('HTTP/1.0 411 Length Required');
310
	}
322
	}
311
 
323
 
312
	/**
324
	/**
313
	 * Send a HTTP 500 response header.
325
	 * Send a HTTP 500 response header.
314
	 */
326
	 */
315
	private function internalServerError() {
327
	private function internalServerError() {
316
		header('HTTP/1.0 500 Internal Server Error');
328
		header('HTTP/1.0 500 Internal Server Error');
317
	}
329
	}
318
}
330
}
319
?>
331
?>