This problem was presentend in the following issue: https://notabug.org/diogo/gnu-social/issues/60 AcceptHeader/util: - Perform isset before using the required array values
		
			
				
	
	
		
			123 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			123 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * Note : Code is released under the GNU LGPL
 | |
|  *
 | |
|  * Please do not change the header of this file
 | |
|  *
 | |
|  * This library is free software; you can redistribute it and/or modify it under the terms of the GNU
 | |
|  * Lesser General Public License as published by the Free Software Foundation; either version 2 of
 | |
|  * the License, or (at your option) any later version.
 | |
|  *
 | |
|  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 | |
|  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 | |
|  *
 | |
|  * See the GNU Lesser General Public License for more details.
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * The AcceptHeader page will parse and sort the different
 | |
|  * allowed types for the content negociations
 | |
|  *
 | |
|  * @author Pierrick Charron <pierrick@webstart.fr>
 | |
|  */
 | |
| class AcceptHeader extends \ArrayObject
 | |
| {
 | |
|     /**
 | |
|      * Constructor
 | |
|      *
 | |
|      * @param string $header Value of the Accept header
 | |
|      * @return void
 | |
|      */
 | |
|     public function __construct($header)
 | |
|     {
 | |
|         $acceptedTypes = $this->_parse($header);
 | |
|         usort($acceptedTypes, [$this, '_compare']);
 | |
|         parent::__construct($acceptedTypes);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Parse the accept header and return an array containing
 | |
|      * all the informations about the Accepted types
 | |
|      *
 | |
|      * @param string $data Value of the Accept header
 | |
|      * @return array
 | |
|      */
 | |
|     private function _parse($data)
 | |
|     {
 | |
|         $array = [];
 | |
|         $items = explode(',', $data);
 | |
|         foreach ($items as $item) {
 | |
|             $elems = explode(';', $item);
 | |
| 
 | |
|             $mime  = current($elems);
 | |
|             $types = explode('/', $mime);
 | |
| 
 | |
|             if (!isset($types[1])) {
 | |
|                 continue;
 | |
|             }
 | |
| 
 | |
|             $acceptElement = [
 | |
|                 'raw'     => $mime,
 | |
|                 'type'    => trim($types[0]),
 | |
|                 'subtype' => trim($types[1]),
 | |
|             ];
 | |
| 
 | |
|             $acceptElement['params'] = [];
 | |
|             while (next($elems)) {
 | |
|                 list($name, $value) = explode('=', current($elems));
 | |
|                 $acceptElement['params'][trim($name)] = trim($value);
 | |
|             }
 | |
| 
 | |
|             $array[] = $acceptElement;
 | |
|         }
 | |
|         return $array;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Compare two Accepted types with their parameters to know
 | |
|      * if one media type should be used instead of an other
 | |
|      *
 | |
|      * @param array $a The first media type and its parameters
 | |
|      * @param array $b The second media type and its parameters
 | |
|      * @return int
 | |
|      */
 | |
|     private function _compare($a, $b)
 | |
|     {
 | |
|         $a_q = isset($a['params']['q']) ? floatval($a['params']['q']) : 1.0;
 | |
|         $b_q = isset($b['params']['q']) ? floatval($b['params']['q']) : 1.0;
 | |
|         if ($a_q === $b_q) {
 | |
|             $a_count = count($a['params']);
 | |
|             $b_count = count($b['params']);
 | |
|             if ($a_count === $b_count) {
 | |
|                 if ($r = $this->_compareSubType($a['subtype'], $b['subtype'])) {
 | |
|                     return $r;
 | |
|                 } else {
 | |
|                     return $this->_compareSubType($a['type'], $b['type']);
 | |
|                 }
 | |
|             } else {
 | |
|                 return $a_count < $b_count;
 | |
|             }
 | |
|         } else {
 | |
|             return $a_q < $b_q;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Compare two subtypes
 | |
|      *
 | |
|      * @param string $a First subtype to compare
 | |
|      * @param string $b Second subtype to compare
 | |
|      * @return int
 | |
|      */
 | |
|     private function _compareSubType($a, $b)
 | |
|     {
 | |
|         if ($a === '*' && $b !== '*') {
 | |
|             return 1;
 | |
|         } elseif ($b === '*' && $a !== '*') {
 | |
|             return -1;
 | |
|         } else {
 | |
|             return 0;
 | |
|         }
 | |
|     }
 | |
| }
 |