|
1 <?php |
|
2 /** |
|
3 * Zend Framework |
|
4 * |
|
5 * LICENSE |
|
6 * |
|
7 * This source file is subject to the new BSD license that is bundled |
|
8 * with this package in the file LICENSE.txt. |
|
9 * It is also available through the world-wide-web at this URL: |
|
10 * http://framework.zend.com/license/new-bsd |
|
11 * If you did not receive a copy of the license and are unable to |
|
12 * obtain it through the world-wide-web, please send an email |
|
13 * to license@zend.com so we can send you a copy immediately. |
|
14 * |
|
15 * @category Zend |
|
16 * @package Zend_Http |
|
17 * @subpackage UserAgent |
|
18 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
19 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
20 */ |
|
21 |
|
22 require_once 'Zend/Http/UserAgent/AbstractDevice.php'; |
|
23 |
|
24 /** |
|
25 * Mobile browser type matcher |
|
26 * |
|
27 * @category Zend |
|
28 * @package Zend_Http |
|
29 * @subpackage UserAgent |
|
30 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
31 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
32 */ |
|
33 class Zend_Http_UserAgent_Mobile extends Zend_Http_UserAgent_AbstractDevice |
|
34 { |
|
35 |
|
36 const DEFAULT_FEATURES_ADAPTER_CLASSNAME = 'Zend_Http_UserAgent_Features_Adapter_WurflApi'; |
|
37 |
|
38 const DEFAULT_FEATURES_ADAPTER_PATH = 'Zend/Http/UserAgent/Features/Adapter/WurflApi.php'; |
|
39 |
|
40 /** |
|
41 * User Agent Signatures |
|
42 * |
|
43 * @var array |
|
44 */ |
|
45 protected static $_uaSignatures = array( |
|
46 'iphone', |
|
47 'ipod', |
|
48 'ipad', |
|
49 'android', |
|
50 'blackberry', |
|
51 'opera mini', |
|
52 'opera mobi', |
|
53 'palm', |
|
54 'palmos', |
|
55 'elaine', |
|
56 'windows ce', |
|
57 ' ppc', |
|
58 '_mms', |
|
59 'ahong', |
|
60 'archos', |
|
61 'armv', |
|
62 'astel', |
|
63 'avantgo', |
|
64 'benq', |
|
65 'blazer', |
|
66 'brew', |
|
67 'com2', |
|
68 'compal', |
|
69 'danger', |
|
70 'pocket', |
|
71 'docomo', |
|
72 'epoc', |
|
73 'ericsson', |
|
74 'eudoraweb', |
|
75 'hiptop', |
|
76 'htc-', |
|
77 'htc_', |
|
78 'iemobile', |
|
79 'ipad', |
|
80 'iris', |
|
81 'j-phone', |
|
82 'kddi', |
|
83 'kindle', |
|
84 'lg ', |
|
85 'lg-', |
|
86 'lg/', |
|
87 'lg;lx', |
|
88 'lge vx', |
|
89 'lge', |
|
90 'lge-', |
|
91 'lge-cx', |
|
92 'lge-lx', |
|
93 'lge-mx', |
|
94 'linux armv', |
|
95 'maemo', |
|
96 'midp', |
|
97 'mini 9.5', |
|
98 'minimo', |
|
99 'mob-x', |
|
100 'mobi', |
|
101 'mobile', |
|
102 'mobilephone', |
|
103 'mot 24', |
|
104 'mot-', |
|
105 'motorola', |
|
106 'n410', |
|
107 'netfront', |
|
108 'nintendo wii', |
|
109 'nintendo', |
|
110 'nitro', |
|
111 'nokia', |
|
112 'novarra-vision', |
|
113 'nuvifone', |
|
114 'openweb', |
|
115 'opwv', |
|
116 'palmsource', |
|
117 'pdxgw', |
|
118 'phone', |
|
119 'playstation', |
|
120 'polaris', |
|
121 'portalmmm', |
|
122 'qt embedded', |
|
123 'reqwirelessweb', |
|
124 'sagem', |
|
125 'sam-r', |
|
126 'samsu', |
|
127 'samsung', |
|
128 'sec-', |
|
129 'sec-sgh', |
|
130 'semc-browser', |
|
131 'series60', |
|
132 'series70', |
|
133 'series80', |
|
134 'series90', |
|
135 'sharp', |
|
136 'sie-m', |
|
137 'sie-s', |
|
138 'smartphone', |
|
139 'sony cmd', |
|
140 'sonyericsson', |
|
141 'sprint', |
|
142 'spv', |
|
143 'symbian os', |
|
144 'symbian', |
|
145 'symbianos', |
|
146 'telco', |
|
147 'teleca', |
|
148 'treo', |
|
149 'up.browser', |
|
150 'up.link', |
|
151 'vodafone', |
|
152 'vodaphone', |
|
153 'webos', |
|
154 'webpro', |
|
155 'windows phone os 7', |
|
156 'wireless', |
|
157 'wm5 pie', |
|
158 'wms pie', |
|
159 'xiino', |
|
160 'wap', |
|
161 'up/', |
|
162 'psion', |
|
163 'j2me', |
|
164 'klondike', |
|
165 'kbrowser' |
|
166 ); |
|
167 |
|
168 /** |
|
169 * @var array |
|
170 */ |
|
171 protected static $_haTerms = array( |
|
172 'midp', |
|
173 'wml', |
|
174 'vnd.rim', |
|
175 'vnd.wap', |
|
176 ); |
|
177 |
|
178 /** |
|
179 * first 4 letters of mobile User Agent chains |
|
180 * |
|
181 * @var array |
|
182 */ |
|
183 protected static $_uaBegin = array( |
|
184 'w3c ', |
|
185 'acs-', |
|
186 'alav', |
|
187 'alca', |
|
188 'amoi', |
|
189 'audi', |
|
190 'avan', |
|
191 'benq', |
|
192 'bird', |
|
193 'blac', |
|
194 'blaz', |
|
195 'brew', |
|
196 'cell', |
|
197 'cldc', |
|
198 'cmd-', |
|
199 'dang', |
|
200 'doco', |
|
201 'eric', |
|
202 'hipt', |
|
203 'inno', |
|
204 'ipaq', |
|
205 'java', |
|
206 'jigs', |
|
207 'kddi', |
|
208 'keji', |
|
209 'leno', |
|
210 'lg-c', |
|
211 'lg-d', |
|
212 'lg-g', |
|
213 'lge-', |
|
214 'maui', |
|
215 'maxo', |
|
216 'midp', |
|
217 'mits', |
|
218 'mmef', |
|
219 'mobi', |
|
220 'mot-', |
|
221 'moto', |
|
222 'mwbp', |
|
223 'nec-', |
|
224 'newt', |
|
225 'noki', |
|
226 'oper', |
|
227 'palm', |
|
228 'pana', |
|
229 'pant', |
|
230 'phil', |
|
231 'play', |
|
232 'port', |
|
233 'prox', |
|
234 'qwap', |
|
235 'sage', |
|
236 'sams', |
|
237 'sany', |
|
238 'sch-', |
|
239 'sec-', |
|
240 'send', |
|
241 'seri', |
|
242 'sgh-', |
|
243 'shar', |
|
244 'sie-', |
|
245 'siem', |
|
246 'smal', |
|
247 'smar', |
|
248 'sony', |
|
249 'sph-', |
|
250 'symb', |
|
251 't-mo', |
|
252 'teli', |
|
253 'tim-', |
|
254 'tosh', |
|
255 'tsm-', |
|
256 'upg1', |
|
257 'upsi', |
|
258 'vk-v', |
|
259 'voda', |
|
260 'wap-', |
|
261 'wapa', |
|
262 'wapi', |
|
263 'wapp', |
|
264 'wapr', |
|
265 'webc', |
|
266 'winw', |
|
267 'winw', |
|
268 'xda', |
|
269 'xda-', |
|
270 ); |
|
271 |
|
272 /** |
|
273 * Comparison of the UserAgent chain and User Agent signatures |
|
274 * |
|
275 * @param string $userAgent User Agent chain |
|
276 * @param array $server $_SERVER like param |
|
277 * @return bool |
|
278 */ |
|
279 public static function match($userAgent, $server) |
|
280 { |
|
281 // To have a quick identification, try light-weight tests first |
|
282 if (isset($server['all_http'])) { |
|
283 if (strpos(strtolower(str_replace(' ', '', $server['all_http'])), 'operam') !== false) { |
|
284 // Opera Mini or Opera Mobi |
|
285 return true; |
|
286 } |
|
287 } |
|
288 if (isset($server['http_x_wap_profile']) || isset($server['http_profile'])) { |
|
289 return true; |
|
290 } |
|
291 |
|
292 if (self::_matchAgentAgainstSignatures($userAgent, self::$_haTerms)) { |
|
293 return true; |
|
294 } |
|
295 |
|
296 if (self::userAgentStart($userAgent)) { |
|
297 return true; |
|
298 } |
|
299 |
|
300 if (self::_matchAgentAgainstSignatures($userAgent, self::$_uaSignatures)) { |
|
301 return true; |
|
302 } |
|
303 |
|
304 return false; |
|
305 } |
|
306 |
|
307 /** |
|
308 * Retrieve beginning clause of user agent |
|
309 * |
|
310 * @param string $userAgent |
|
311 * @return string |
|
312 */ |
|
313 public static function userAgentStart($userAgent) |
|
314 { |
|
315 |
|
316 $mobile_ua = strtolower(substr($userAgent, 0, 4)); |
|
317 |
|
318 return (in_array($mobile_ua, self::$_uaBegin)); |
|
319 } |
|
320 |
|
321 /** |
|
322 * Constructor |
|
323 * |
|
324 * @return void |
|
325 */ |
|
326 public function __construct($userAgent = null, array $server = array(), array $config = array()) |
|
327 { |
|
328 // For mobile detection, an adapter must be defined |
|
329 if (empty($config['mobile']['features'])) { |
|
330 $config['mobile']['features']['path'] = self::DEFAULT_FEATURES_ADAPTER_PATH; |
|
331 $config['mobile']['features']['classname'] = self::DEFAULT_FEATURES_ADAPTER_CLASSNAME; |
|
332 } |
|
333 parent::__construct($userAgent, $server, $config); |
|
334 } |
|
335 |
|
336 /** |
|
337 * Gives the current browser type |
|
338 * |
|
339 * @return string |
|
340 */ |
|
341 public function getType() |
|
342 { |
|
343 return 'mobile'; |
|
344 } |
|
345 |
|
346 /** |
|
347 * Look for features |
|
348 * |
|
349 * @return string |
|
350 */ |
|
351 protected function _defineFeatures() |
|
352 { |
|
353 $this->setFeature('is_wireless_device', false, 'product_info'); |
|
354 |
|
355 parent::_defineFeatures(); |
|
356 |
|
357 if (isset($this->_aFeatures["mobile_browser"])) { |
|
358 $this->setFeature("browser_name", $this->_aFeatures["mobile_browser"]); |
|
359 $this->_browser = $this->_aFeatures["mobile_browser"]; |
|
360 } |
|
361 if (isset($this->_aFeatures["mobile_browser_version"])) { |
|
362 $this->setFeature("browser_version", $this->_aFeatures["mobile_browser_version"]); |
|
363 $this->_browserVersion = $this->_aFeatures["mobile_browser_version"]; |
|
364 } |
|
365 |
|
366 // markup |
|
367 if ($this->getFeature('device_os') == 'iPhone OS' |
|
368 || $this->getFeature('device_os_token') == 'iPhone OS' |
|
369 ) { |
|
370 $this->setFeature('markup', 'iphone'); |
|
371 } else { |
|
372 $this->setFeature('markup', $this->getMarkupLanguage($this->getFeature('preferred_markup'))); |
|
373 } |
|
374 |
|
375 // image format |
|
376 $this->_images = array(); |
|
377 |
|
378 if ($this->getFeature('png')) { |
|
379 $this->_images[] = 'png'; |
|
380 } |
|
381 if ($this->getFeature('jpg')) { |
|
382 $this->_images[] = 'jpg'; |
|
383 } |
|
384 if ($this->getFeature('gif')) { |
|
385 $this->_images[] = 'gif'; |
|
386 } |
|
387 if ($this->getFeature('wbmp')) { |
|
388 $this->_images[] = 'wbmp'; |
|
389 } |
|
390 |
|
391 return $this->_aFeatures; |
|
392 } |
|
393 |
|
394 /** |
|
395 * Determine markup language expected |
|
396 * |
|
397 * @access public |
|
398 * @return __TYPE__ |
|
399 */ |
|
400 public function getMarkupLanguage($preferredMarkup = null) |
|
401 { |
|
402 $return = ''; |
|
403 switch ($preferredMarkup) { |
|
404 case 'wml_1_1': |
|
405 case 'wml_1_2': |
|
406 case 'wml_1_3': |
|
407 $return = 'wml'; //text/vnd.wap.wml encoding="ISO-8859-15" |
|
408 case 'html_wi_imode_compact_generic': |
|
409 case 'html_wi_imode_html_1': |
|
410 case 'html_wi_imode_html_2': |
|
411 case 'html_wi_imode_html_3': |
|
412 case 'html_wi_imode_html_4': |
|
413 case 'html_wi_imode_html_5': |
|
414 $return = 'chtml'; //text/html |
|
415 case 'html_wi_oma_xhtmlmp_1_0': //application/vnd.wap.xhtml+xml |
|
416 case 'html_wi_w3_xhtmlbasic': //application/xhtml+xml DTD XHTML Basic 1.0 |
|
417 $return = 'xhtml'; |
|
418 case 'html_web_3_2': //text/html DTD Html 3.2 Final |
|
419 case 'html_web_4_0': //text/html DTD Html 4.01 Transitional |
|
420 $return = ''; |
|
421 } |
|
422 return $return; |
|
423 } |
|
424 |
|
425 /** |
|
426 * Determine image format support |
|
427 * |
|
428 * @return array |
|
429 */ |
|
430 public function getImageFormatSupport() |
|
431 { |
|
432 return $this->_images; |
|
433 } |
|
434 |
|
435 /** |
|
436 * Determine maximum image height supported |
|
437 * |
|
438 * @return int |
|
439 */ |
|
440 public function getMaxImageHeight() |
|
441 { |
|
442 return $this->getFeature('max_image_height'); |
|
443 } |
|
444 |
|
445 /** |
|
446 * Determine maximum image width supported |
|
447 * |
|
448 * @return int |
|
449 */ |
|
450 public function getMaxImageWidth() |
|
451 { |
|
452 return $this->getFeature('max_image_width'); |
|
453 } |
|
454 |
|
455 /** |
|
456 * Determine physical screen height |
|
457 * |
|
458 * @return int |
|
459 */ |
|
460 public function getPhysicalScreenHeight() |
|
461 { |
|
462 return $this->getFeature('physical_screen_height'); |
|
463 } |
|
464 |
|
465 /** |
|
466 * Determine physical screen width |
|
467 * |
|
468 * @return int |
|
469 */ |
|
470 public function getPhysicalScreenWidth() |
|
471 { |
|
472 return $this->getFeature('physical_screen_width'); |
|
473 } |
|
474 |
|
475 /** |
|
476 * Determine preferred markup |
|
477 * |
|
478 * @return string |
|
479 */ |
|
480 public function getPreferredMarkup() |
|
481 { |
|
482 return $this->getFeature("markup"); |
|
483 } |
|
484 |
|
485 /** |
|
486 * Determine X/HTML support level |
|
487 * |
|
488 * @return int |
|
489 */ |
|
490 public function getXhtmlSupportLevel() |
|
491 { |
|
492 return $this->getFeature('xhtml_support_level'); |
|
493 } |
|
494 |
|
495 /** |
|
496 * Does the device support Flash? |
|
497 * |
|
498 * @return bool |
|
499 */ |
|
500 public function hasFlashSupport() |
|
501 { |
|
502 return $this->getFeature('fl_browser'); |
|
503 } |
|
504 |
|
505 /** |
|
506 * Does the device support PDF? |
|
507 * |
|
508 * @return bool |
|
509 */ |
|
510 public function hasPdfSupport() |
|
511 { |
|
512 return $this->getFeature('pdf_support'); |
|
513 } |
|
514 |
|
515 /** |
|
516 * Does the device have an associated phone number? |
|
517 * |
|
518 * @return bool |
|
519 */ |
|
520 public function hasPhoneNumber() |
|
521 { |
|
522 return $this->getFeature('can_assign_phone_number'); |
|
523 } |
|
524 |
|
525 /** |
|
526 * Does the device support HTTPS? |
|
527 * |
|
528 * @return bool |
|
529 */ |
|
530 public function httpsSupport() |
|
531 { |
|
532 return ($this->getFeature('https_support') == 'supported'); |
|
533 } |
|
534 } |