Subversion Repositories Applications.annuaire

Rev

Rev 412 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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