Subversion-Projekte lars-tiefland.cakephp

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/* SVN FILE: $Id: request_handler.php 7961 2008-12-25 23:21:36Z gwoo $ */
3
/**
4
 * Request object for handling alternative HTTP requests
5
 *
6
 * Alternative HTTP requests can come from wireless units like mobile phones, palmtop computers,
7
 * and the like.  These units have no use for Ajax requests, and this Component can tell how Cake
8
 * should respond to the different needs of a handheld computer and a desktop machine.
9
 *
10
 * CakePHP(tm) :  Rapid Development Framework (http://www.cakephp.org)
11
 * Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
12
 *
13
 * Licensed under The MIT License
14
 * Redistributions of files must retain the above copyright notice.
15
 *
16
 * @filesource
17
 * @copyright     Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
18
 * @link          http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
19
 * @package       cake
20
 * @subpackage    cake.cake.libs.controller.components
21
 * @since         CakePHP(tm) v 0.10.4.1076
22
 * @version       $Revision: 7961 $
23
 * @modifiedby    $LastChangedBy: gwoo $
24
 * @lastmodified  $Date: 2008-12-25 15:21:36 -0800 (Thu, 25 Dec 2008) $
25
 * @license       http://www.opensource.org/licenses/mit-license.php The MIT License
26
 */
27
 
28
if (!defined('REQUEST_MOBILE_UA')) {
29
	define('REQUEST_MOBILE_UA', '(iPhone|MIDP|AvantGo|BlackBerry|J2ME|Opera Mini|DoCoMo|NetFront|Nokia|PalmOS|PalmSource|portalmmm|Plucker|ReqwirelessWeb|SonyEricsson|Symbian|UP\.Browser|Windows CE|Xiino)');
30
}
31
 
32
/**
33
 * Request object for handling HTTP requests
34
 *
35
 * @package       cake
36
 * @subpackage    cake.cake.libs.controller.components
37
 *
38
 */
39
class RequestHandlerComponent extends Object {
40
/**
41
 * The layout that will be switched to for Ajax requests
42
 *
43
 * @var string
44
 * @access public
45
 * @see RequestHandler::setAjax()
46
 */
47
	var $ajaxLayout = 'ajax';
48
/**
49
 * Determines whether or not callbacks will be fired on this component
50
 *
51
 * @var boolean
52
 * @access public
53
 */
54
	var $enabled = true;
55
/**
56
 * Holds the content-type of the response that is set when using
57
 * RequestHandler::respondAs()
58
 *
59
 * @var string
60
 * @access private
61
 */
62
	var $__responseTypeSet = null;
63
/**
64
 * Holds the copy of Controller::$params
65
 *
66
 * @var array
67
 * @access public
68
 */
69
	var $params = array();
70
/**
71
 * Friendly content-type mappings used to set response types and determine
72
 * request types.  Can be modified with RequestHandler::setContent()
73
 *
74
 * @var array
75
 * @access private
76
 * @see RequestHandlerComponent::setContent
77
 */
78
	var $__requestContent = array(
79
		'javascript'	=> 'text/javascript',
80
		'js'			=> 'text/javascript',
81
		'json'			=> 'application/json',
82
		'css'			=> 'text/css',
83
		'html'			=> array('text/html', '*/*'),
84
		'text'			=> 'text/plain',
85
		'txt'			=> 'text/plain',
86
		'csv'			=> array('application/vnd.ms-excel', 'text/plain'),
87
		'form'			=> 'application/x-www-form-urlencoded',
88
		'file'			=> 'multipart/form-data',
89
		'xhtml'			=> array('application/xhtml+xml', 'application/xhtml', 'text/xhtml'),
90
		'xhtml-mobile'	=> 'application/vnd.wap.xhtml+xml',
91
		'xml'			=> array('application/xml', 'text/xml'),
92
		'rss'			=> 'application/rss+xml',
93
		'atom'			=> 'application/atom+xml',
94
		'amf'			=> 'application/x-amf',
95
		'wap'			=> array(
96
			'text/vnd.wap.wml',
97
			'text/vnd.wap.wmlscript',
98
			'image/vnd.wap.wbmp'
99
		),
100
		'wml'			=> 'text/vnd.wap.wml',
101
		'wmlscript'		=> 'text/vnd.wap.wmlscript',
102
		'wbmp'			=> 'image/vnd.wap.wbmp',
103
		'pdf'			=> 'application/pdf',
104
		'zip'			=> 'application/x-zip',
105
		'tar'			=> 'application/x-tar'
106
	);
107
/**
108
 * Content-types accepted by the client.  If extension parsing is enabled in the
109
 * Router, and an extension is detected, the corresponding content-type will be
110
 * used as the overriding primary content-type accepted.
111
 *
112
 * @var array
113
 * @access private
114
 * @see Router::parseExtensions()
115
 */
116
	var $__acceptTypes = array();
117
/**
118
 * The template to use when rendering the given content type.
119
 *
120
 * @var string
121
 * @access private
122
 */
123
	var $__renderType = null;
124
/**
125
 * Contains the file extension parsed out by the Router
126
 *
127
 * @var string
128
 * @access public
129
 * @see Router::parseExtensions()
130
 */
131
	var $ext = null;
132
/**
133
 * Flag set when MIME types have been initialized
134
 *
135
 * @var boolean
136
 * @access private
137
 * @see RequestHandler::__initializeTypes()
138
 */
139
	var $__typesInitialized = false;
140
/**
141
 * Constructor. Parses the accepted content types accepted by the client using HTTP_ACCEPT
142
 *
143
 */
144
	function __construct() {
145
		$this->__acceptTypes = explode(',', env('HTTP_ACCEPT'));
146
 
147
		foreach ($this->__acceptTypes as $i => $type) {
148
			if (strpos($type, ';')) {
149
				$type = explode(';', $type);
150
				$this->__acceptTypes[$i] = $type[0];
151
			}
152
		}
153
		parent::__construct();
154
	}
155
/**
156
 * Initializes the component, gets a reference to Controller::$parameters, and
157
 * checks to see if a file extension has been parsed by the Router.  If yes, the
158
 * corresponding content-type is pushed onto the list of accepted content-types
159
 * as the first item.
160
 *
161
 * @param object $controller A reference to the controller
162
 * @return void
163
 * @see Router::parseExtensions()
164
 * @access public
165
 */
166
	function initialize(&$controller) {
167
		if (isset($controller->params['url']['ext'])) {
168
			$this->ext = $controller->params['url']['ext'];
169
		}
170
	}
171
/**
172
 * The startup method of the RequestHandler enables several automatic behaviors
173
 * related to the detection of certain properties of the HTTP request, including:
174
 *
175
 * - Disabling layout rendering for Ajax requests (based on the HTTP_X_REQUESTED_WITH header)
176
 * - If Router::parseExtensions() is enabled, the layout and template type are
177
 *   switched based on the parsed extension.  For example, if controller/action.xml
178
 *   is requested, the view path becomes <i>app/views/controller/xml/action.ctp</i>.
179
 * - If a helper with the same name as the extension exists, it is added to the controller.
180
 * - If the extension is of a type that RequestHandler understands, it will set that
181
 *   Content-type in the response header.
182
 * - If the XML data is POSTed, the data is parsed into an XML object, which is assigned
183
 *   to the $data property of the controller, which can then be saved to a model object.
184
 *
185
 * @param object $controller A reference to the controller
186
 * @return void
187
 * @access public
188
 */
189
	function startup(&$controller) {
190
		if (!$this->enabled) {
191
			return;
192
		}
193
 
194
		$this->__initializeTypes();
195
		$controller->params['isAjax'] = $this->isAjax();
196
		$isRecognized = (
197
			!in_array($this->ext, array('html', 'htm')) &&
198
			in_array($this->ext, array_keys($this->__requestContent))
199
		);
200
 
201
		if (!empty($this->ext) && $isRecognized) {
202
			$this->renderAs($controller, $this->ext);
203
		} elseif ($this->isAjax()) {
204
			$this->renderAs($controller, 'ajax');
205
		}
206
 
207
		if ($this->requestedWith('xml')) {
208
			if (!class_exists('XmlNode')) {
209
				App::import('Core', 'Xml');
210
			}
211
			$xml = new Xml(trim(file_get_contents('php://input')));
212
 
213
			if (is_object($xml->child('data')) && count($xml->children) == 1) {
214
				$controller->data = $xml->child('data');
215
			} else {
216
				$controller->data = $xml;
217
			}
218
		}
219
	}
220
/**
221
 * Handles (fakes) redirects for Ajax requests using requestAction()
222
 *
223
 * @param object $controller A reference to the controller
224
 * @param mixed $url A string or array containing the redirect location
225
 * @access public
226
 */
227
	function beforeRedirect(&$controller, $url) {
228
		if (!$this->isAjax()) {
229
			return;
230
		}
231
		foreach ($_POST as $key => $val) {
232
			unset($_POST[$key]);
233
		}
234
		echo $this->requestAction($url, array('return'));
235
		$this->_stop();
236
	}
237
/**
238
 * Returns true if the current HTTP request is Ajax, false otherwise
239
 *
240
 * @return boolean True if call is Ajax
241
 * @access public
242
 */
243
	function isAjax() {
244
		return env('HTTP_X_REQUESTED_WITH') === "XMLHttpRequest";
245
	}
246
/**
247
 * Returns true if the current HTTP request is coming from a Flash-based client
248
 *
249
 * @return boolean True if call is from Flash
250
 * @access public
251
 */
252
	function isFlash() {
253
		return (preg_match('/^(Shockwave|Adobe) Flash/', env('HTTP_USER_AGENT')) == 1);
254
	}
255
/**
256
 * Returns true if the current request is over HTTPS, false otherwise.
257
 *
258
 * @return bool True if call is over HTTPS
259
 * @access public
260
 */
261
	function isSSL() {
262
		return env('HTTPS');
263
	}
264
/**
265
 * Returns true if the current call accepts an XML response, false otherwise
266
 *
267
 * @return boolean True if client accepts an XML response
268
 * @access public
269
 */
270
	function isXml() {
271
		return $this->prefers('xml');
272
	}
273
/**
274
 * Returns true if the current call accepts an RSS response, false otherwise
275
 *
276
 * @return boolean True if client accepts an RSS response
277
 * @access public
278
 */
279
	function isRss() {
280
		return $this->prefers('rss');
281
	}
282
/**
283
 * Returns true if the current call accepts an Atom response, false otherwise
284
 *
285
 * @return boolean True if client accepts an RSS response
286
 * @access public
287
 */
288
	function isAtom() {
289
		return $this->prefers('atom');
290
	}
291
/**
292
 * Returns true if user agent string matches a mobile web browser, or if the
293
 * client accepts WAP content.
294
 *
295
 * @return boolean True if user agent is a mobile web browser
296
 * @access public
297
 */
298
	function isMobile() {
299
		preg_match('/' . REQUEST_MOBILE_UA . '/i', env('HTTP_USER_AGENT'), $match);
300
		if (!empty($match) || $this->accepts('wap')) {
301
			return true;
302
		}
303
		return false;
304
	}
305
/**
306
 * Returns true if the client accepts WAP content
307
 *
308
 * @return bool
309
 * @access public
310
 */
311
	function isWap() {
312
		return $this->prefers('wap');
313
	}
314
/**
315
 * Returns true if the current call a POST request
316
 *
317
 * @return boolean True if call is a POST
318
 * @access public
319
 */
320
	function isPost() {
321
		return (strtolower(env('REQUEST_METHOD')) == 'post');
322
	}
323
/**
324
 * Returns true if the current call a PUT request
325
 *
326
 * @return boolean True if call is a PUT
327
 * @access public
328
 */
329
	function isPut() {
330
		return (strtolower(env('REQUEST_METHOD')) == 'put');
331
	}
332
/**
333
 * Returns true if the current call a GET request
334
 *
335
 * @return boolean True if call is a GET
336
 * @access public
337
 */
338
	function isGet() {
339
		return (strtolower(env('REQUEST_METHOD')) == 'get');
340
	}
341
/**
342
 * Returns true if the current call a DELETE request
343
 *
344
 * @return boolean True if call is a DELETE
345
 * @access public
346
 */
347
	function isDelete() {
348
		return (strtolower(env('REQUEST_METHOD')) == 'delete');
349
	}
350
/**
351
 * Gets Prototype version if call is Ajax, otherwise empty string.
352
 * The Prototype library sets a special "Prototype version" HTTP header.
353
 *
354
 * @return string Prototype version of component making Ajax call
355
 * @access public
356
 */
357
	function getAjaxVersion() {
358
		if (env('HTTP_X_PROTOTYPE_VERSION') != null) {
359
			return env('HTTP_X_PROTOTYPE_VERSION');
360
		}
361
		return false;
362
	}
363
/**
364
 * Adds/sets the Content-type(s) for the given name.  This method allows
365
 * content-types to be mapped to friendly aliases (or extensions), which allows
366
 * RequestHandler to automatically respond to requests of that type in the
367
 * startup method.
368
 *
369
 * @param string $name The name of the Content-type, i.e. "html", "xml", "css"
370
 * @param mixed $type The Content-type or array of Content-types assigned to the name,
371
 *                    i.e. "text/html", or "application/xml"
372
 * @return void
373
 * @access public
374
 */
375
	function setContent($name, $type = null) {
376
		if (is_array($name)) {
377
			$this->__requestContent = array_merge($this->__requestContent, $name);
378
			return;
379
		}
380
		$this->__requestContent[$name] = $type;
381
	}
382
/**
383
 * Gets the server name from which this request was referred
384
 *
385
 * @return string Server address
386
 * @access public
387
 */
388
	function getReferrer() {
389
		if (env('HTTP_HOST') != null) {
390
			$sessHost = env('HTTP_HOST');
391
		}
392
 
393
		if (env('HTTP_X_FORWARDED_HOST') != null) {
394
			$sessHost = env('HTTP_X_FORWARDED_HOST');
395
		}
396
		return trim(preg_replace('/(?:\:.*)/', '', $sessHost));
397
	}
398
/**
399
 * Gets remote client IP
400
 *
401
 * @return string Client IP address
402
 * @access public
403
 */
404
	function getClientIP($safe = true) {
405
		if (!$safe && env('HTTP_X_FORWARDED_FOR') != null) {
406
			$ipaddr = preg_replace('/(?:,.*)/', '', env('HTTP_X_FORWARDED_FOR'));
407
		} else {
408
			if (env('HTTP_CLIENT_IP') != null) {
409
				$ipaddr = env('HTTP_CLIENT_IP');
410
			} else {
411
				$ipaddr = env('REMOTE_ADDR');
412
			}
413
		}
414
 
415
		if (env('HTTP_CLIENTADDRESS') != null) {
416
			$tmpipaddr = env('HTTP_CLIENTADDRESS');
417
 
418
			if (!empty($tmpipaddr)) {
419
				$ipaddr = preg_replace('/(?:,.*)/', '', $tmpipaddr);
420
			}
421
		}
422
		return trim($ipaddr);
423
	}
424
/**
425
 * Determines which content types the client accepts.  Acceptance is based on
426
 * the file extension parsed by the Router (if present), and by the HTTP_ACCEPT
427
 * header.
428
 *
429
 * @param mixed $type Can be null (or no parameter), a string type name, or an
430
 *					array of types
431
 * @return mixed If null or no parameter is passed, returns an array of content
432
 *				types the client accepts.  If a string is passed, returns true
433
 *				if the client accepts it.  If an array is passed, returns true
434
 *				if the client accepts one or more elements in the array.
435
 * @access public
436
 * @see RequestHandlerComponent::setContent()
437
 */
438
	function accepts($type = null) {
439
		$this->__initializeTypes();
440
 
441
		if ($type == null) {
442
			return $this->mapType($this->__acceptTypes);
443
 
444
		} elseif (is_array($type)) {
445
			foreach ($type as $t) {
446
				if ($this->accepts($t) == true) {
447
					return true;
448
				}
449
			}
450
			return false;
451
		} elseif (is_string($type)) {
452
 
453
			if (!isset($this->__requestContent[$type])) {
454
				return false;
455
			}
456
 
457
			$content = $this->__requestContent[$type];
458
 
459
			if (is_array($content)) {
460
				foreach ($content as $c) {
461
					if (in_array($c, $this->__acceptTypes)) {
462
						return true;
463
					}
464
				}
465
			} else {
466
				if (in_array($content, $this->__acceptTypes)) {
467
					return true;
468
				}
469
			}
470
		}
471
	}
472
/**
473
 * Determines the content type of the data the client has sent (i.e. in a POST request)
474
 *
475
 * @param mixed $type Can be null (or no parameter), a string type name, or an array of types
476
 * @return mixed
477
 * @access public
478
 */
479
	function requestedWith($type = null) {
480
		if (!$this->isPost() && !$this->isPut()) {
481
			return null;
482
		}
483
 
484
		list($contentType) = explode(';', env('CONTENT_TYPE'));
485
		if ($type == null) {
486
			return $this->mapType($contentType);
487
		} elseif (is_array($type)) {
488
			foreach ($type as $t) {
489
				if ($this->requestedWith($t)) {
490
					return $this->mapType($t);
491
				}
492
			}
493
			return false;
494
		} elseif (is_string($type)) {
495
			return ($type == $this->mapType($contentType));
496
		}
497
	}
498
/**
499
 * Determines which content-types the client prefers.  If no parameters are given,
500
 * the content-type that the client most likely prefers is returned.  If $type is
501
 * an array, the first item in the array that the client accepts is returned.
502
 * Preference is determined primarily by the file extension parsed by the Router
503
 * if provided, and secondarily by the list of content-types provided in
504
 * HTTP_ACCEPT.
505
 *
506
 * @param mixed $type An optional array of 'friendly' content-type names, i.e.
507
 *                     'html', 'xml', 'js', etc.
508
 * @return mixed If $type is null or not provided, the first content-type in the
509
 *                list, based on preference, is returned.
510
 * @access public
511
 * @see RequestHandlerComponent::setContent()
512
 */
513
	function prefers($type = null) {
514
		$this->__initializeTypes();
515
		$accept = $this->accepts();
516
 
517
		if ($type == null) {
518
			if (empty($this->ext)) {
519
				if (is_array($accept)) {
520
					return $accept[0];
521
				}
522
				return $accept;
523
			}
524
			return $this->ext;
525
		}
526
 
527
		if (is_string($type)) {
528
			$types = array($type);
529
		}
530
 
531
		if (count($types) === 1) {
532
			if (!empty($this->ext)) {
533
				return ($types[0] == $this->ext);
534
			}
535
			return ($types[0] == $accept[0]);
536
		}
537
		$accepts = array();
538
 
539
		foreach ($types as $type) {
540
			if (in_array($type, $accept)) {
541
				$accepts[] = $type;
542
			}
543
		}
544
 
545
		if (count($accepts) === 0) {
546
			return false;
547
		} elseif (count($types) === 1) {
548
			return ($types[0] === $accepts[0]);
549
		} elseif (count($accepts) === 1) {
550
            return $accepts[0];
551
		}
552
 
553
		$accepts = array_intersect($this->__acceptTypes, $accepts);
554
		return $accepts[0];
555
	}
556
/**
557
 * Sets the layout and template paths for the content type defined by $type.
558
 *
559
 * @param object $controller A reference to a controller object
560
 * @param string $type Type of response to send (e.g: 'ajax')
561
 * @return void
562
 * @access public
563
 * @see RequestHandlerComponent::setContent()
564
 * @see RequestHandlerComponent::respondAs()
565
 */
566
	function renderAs(&$controller, $type) {
567
		$this->__initializeTypes();
568
		$options = array('charset' => 'UTF-8');
569
 
570
		if (Configure::read('App.encoding') !== null) {
571
			$options = array('charset' => Configure::read('App.encoding'));
572
		}
573
 
574
		if ($type == 'ajax') {
575
			$controller->layout = $this->ajaxLayout;
576
			return $this->respondAs('html', $options);
577
		}
578
		$controller->ext = '.ctp';
579
 
580
		if (empty($this->__renderType)) {
581
			$controller->viewPath .= '/' . $type;
582
		} else {
583
			$remove = preg_replace("/(?:\/{$type})$/", '/' . $type, $controller->viewPath);
584
			$controller->viewPath = $remove;
585
		}
586
		$this->__renderType = $type;
587
		$controller->layoutPath = $type;
588
 
589
		if (isset($this->__requestContent[$type])) {
590
			$this->respondAs($type, $options);
591
		}
592
 
593
		$helper = ucfirst($type);
594
		$isAdded = (
595
			in_array($helper, $controller->helpers) ||
596
			array_key_exists($helper, $controller->helpers)
597
		);
598
 
599
		if (!$isAdded) {
600
			if (App::import('Helper', $helper)) {
601
				$controller->helpers[] = $helper;
602
			}
603
		}
604
	}
605
/**
606
 * Sets the response header based on type map index name.  If DEBUG is greater than 2, the header
607
 * is not set.
608
 *
609
 * @param mixed $type Friendly type name, i.e. 'html' or 'xml', or a full content-type,
610
 * 					  like 'application/x-shockwave'.
611
 * @param array $options If $type is a friendly type name that is associated with
612
 *                     more than one type of content, $index is used to select
613
 *                     which content-type to use.
614
 * @return boolean Returns false if the friendly type name given in $type does
615
 *                 not exist in the type map, or if the Content-type header has
616
 *                 already been set by this method.
617
 * @access public
618
 * @see RequestHandlerComponent::setContent()
619
 */
620
	function respondAs($type, $options = array()) {
621
		$this->__initializeTypes();
622
		if ($this->__responseTypeSet != null) {
623
			return false;
624
		}
625
		if (!array_key_exists($type, $this->__requestContent) && strpos($type, '/') === false) {
626
			return false;
627
		}
628
		$defaults = array('index' => 0, 'charset' => null, 'attachment' => false);
629
		$options = array_merge($defaults, $options);
630
 
631
		if (strpos($type, '/') === false && isset($this->__requestContent[$type])) {
632
			$cType = null;
633
			if (is_array($this->__requestContent[$type]) && isset($this->__requestContent[$type][$options['index']])) {
634
				$cType = $this->__requestContent[$type][$options['index']];
635
			} elseif (is_array($this->__requestContent[$type]) && isset($this->__requestContent[$type][0])) {
636
				$cType = $this->__requestContent[$type][0];
637
			} elseif (isset($this->__requestContent[$type])) {
638
				$cType = $this->__requestContent[$type];
639
			} else {
640
				return false;
641
			}
642
 
643
			if (is_array($cType)) {
644
				if ($this->prefers($cType)) {
645
					$cType = $this->prefers($cType);
646
				} else {
647
					$cType = $cType[0];
648
				}
649
			}
650
		} else {
651
			$cType = $type;
652
		}
653
 
654
		if ($cType != null) {
655
			$header = 'Content-type: ' . $cType;
656
 
657
			if (!empty($options['charset'])) {
658
				$header .= '; charset=' . $options['charset'];
659
			}
660
			if (!empty($options['attachment'])) {
661
				header("Content-Disposition: attachment; filename=\"{$options['attachment']}\"");
662
			}
663
			if (Configure::read() < 2 && !defined('CAKEPHP_SHELL')) {
664
				@header($header);
665
			}
666
			$this->__responseTypeSet = $cType;
667
			return true;
668
		}
669
		return false;
670
	}
671
/**
672
 * Returns the current response type (Content-type header), or null if none has been set
673
 *
674
 * @return mixed A string content type alias, or raw content type if no alias map exists,
675
 *               otherwise null
676
 * @access public
677
 */
678
	function responseType() {
679
		if ($this->__responseTypeSet == null) {
680
			return null;
681
		}
682
		return $this->mapType($this->__responseTypeSet);
683
	}
684
/**
685
 * Maps a content-type back to an alias
686
 *
687
 * @param mixed $type Content type
688
 * @return mixed Alias
689
 * @access public
690
 */
691
	function mapType($ctype) {
692
		if (is_array($ctype)) {
693
			$out = array();
694
			foreach ($ctype as $t) {
695
				$out[] = $this->mapType($t);
696
			}
697
			return $out;
698
		} else {
699
			$keys = array_keys($this->__requestContent);
700
			$count = count($keys);
701
 
702
			for ($i = 0; $i < $count; $i++) {
703
				$name = $keys[$i];
704
				$type = $this->__requestContent[$name];
705
 
706
				if (is_array($type) && in_array($ctype, $type)) {
707
					return $name;
708
				} elseif (!is_array($type) && $type == $ctype) {
709
					return $name;
710
				}
711
			}
712
			return $ctype;
713
		}
714
	}
715
/**
716
 * Initializes MIME types
717
 *
718
 * @return void
719
 * @access private
720
 */
721
	function __initializeTypes() {
722
		if ($this->__typesInitialized) {
723
			return;
724
		}
725
		if (isset($this->__requestContent[$this->ext])) {
726
			$content = $this->__requestContent[$this->ext];
727
			if (is_array($content)) {
728
				$content = $content[0];
729
			}
730
			array_unshift($this->__acceptTypes, $content);
731
		}
732
		$this->__typesInitialized = true;
733
	}
734
}
735
 
736
?>