Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 70
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
Util
0.00% covered (danger)
0.00%
0 / 70
0.00% covered (danger)
0.00%
0 / 7
930
0.00% covered (danger)
0.00%
0 / 1
 urlencode
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 urldecode
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 splitHeader
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
42
 getHeaders
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
56
 parseParameters
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
56
 buildHttpQuery
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
30
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2declare( strict_types = 1 );
3
4/**
5 * @section LICENSE
6 * Copyright (c) 2007 Andy Smith
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining
9 * a copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including without
11 * limitation the rights to use, copy, modify, merge, publish, distribute,
12 * sublicense, and/or sell copies of the Software, and to permit persons to
13 * whom the Software is furnished to do so, subject to the following
14 * conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *
27 * @file
28 */
29
30namespace MediaWiki\OAuthClient;
31
32class Util {
33
34    /**
35     * @param string|string[] $input
36     * @return string|string[]
37     */
38    public static function urlencode( $input ) {
39        if ( is_array( $input ) ) {
40            return array_map( __METHOD__, $input );
41
42        } elseif ( is_scalar( $input ) ) {
43            return rawurlencode( $input );
44
45        } else {
46            return '';
47        }
48    }
49
50    /**
51     * @param string $string
52     * @return string
53     */
54    public static function urldecode( $string ) {
55        return urldecode( $string );
56    }
57
58    /**
59     * Utility function for turning the Authorization: header into parameters,
60     * has to do some unescaping Can filter out any non-oauth parameters if
61     * needed (default behaviour)
62     *
63     * @param string $header
64     * @param bool $oauthOnly
65     * @return array
66     */
67    public static function splitHeader( $header, $oauthOnly = true ) {
68        $re = '/(' . ( $oauthOnly ? 'oauth_' : '' ) .
69            '[a-z_-]*)=(:?"([^"]*)"|([^,]*))/';
70        $params = [];
71        if ( preg_match_all( $re, $header, $m ) ) {
72            foreach ( $m[1] as $i => $h ) {
73                $params[$h] = static::urldecode(
74                    empty( $m[3][$i] ) ? $m[4][$i] : $m[3][$i]
75                );
76            }
77            if ( isset( $params['realm'] ) ) {
78                unset( $params['realm'] );
79            }
80        }
81        return $params;
82    }
83
84    /**
85     * @return array
86     */
87    public static function getHeaders() {
88        if ( function_exists( 'apache_request_headers' ) ) {
89            // we need this to get the actual Authorization: header
90            // because apache tends to tell us it doesn't exist
91            $headers = apache_request_headers();
92
93            // sanitize the output of apache_request_headers because
94            // we always want the keys to be Cased-Like-This and arh()
95            // returns the headers in the same case as they are in the
96            // request
97            $out = [];
98            foreach ( $headers as $key => $value ) {
99                $key = str_replace(
100                    ' ', '-',
101                    ucwords( strtolower( str_replace( '-', ' ', $key ) ) )
102                );
103                $out[$key] = $value;
104            }
105        } else {
106            // otherwise we don't have apache and are just going to have to
107            // hope that $_SERVER actually contains what we need
108            $out = [];
109            if ( isset( $_SERVER['CONTENT_TYPE'] ) ) {
110                $out['Content-Type'] = $_SERVER['CONTENT_TYPE'];
111            }
112            if ( isset( $_ENV['CONTENT_TYPE'] ) ) {
113                $out['Content-Type'] = $_ENV['CONTENT_TYPE'];
114            }
115
116            foreach ( $_SERVER as $key => $value ) {
117                if ( substr( $key, 0, 5 ) == 'HTTP_' ) {
118                    // this is chaos, basically it is just there to capitalize
119                    // the first letter of every word that is not an initial
120                    // HTTP and strip HTTP_ prefix
121                    // Code from przemek
122                    $key = str_replace(
123                        ' ', '-',
124                        ucwords( strtolower(
125                            str_replace( '_', ' ', substr( $key, 5 ) )
126                        ) )
127                    );
128                    $out[$key] = $value;
129                }
130            }
131        }
132        return $out;
133    }
134
135    /**
136     * This function takes a input like a=b&a=c&d=e and returns the parsed
137     * parameters like this array('a' => array('b','c'), 'd' => 'e')
138     *
139     * @param string $input
140     * @return array
141     */
142    public static function parseParameters( $input ) {
143        if ( !isset( $input ) || !$input ) {
144            return [];
145        }
146
147        $pairs = explode( '&', $input );
148
149        $parsed = [];
150        foreach ( $pairs as $pair ) {
151            $split = explode( '=', $pair, 2 );
152            $parameter = static::urldecode( $split[0] );
153            $value = isset( $split[1] ) ? static::urldecode( $split[1] ) : '';
154
155            if ( isset( $parsed[$parameter] ) ) {
156                // We have already recieved parameter(s) with this name, so
157                // add to the list of parameters with this name
158
159                if ( is_scalar( $parsed[$parameter] ) ) {
160                    // This is the first duplicate, so transform scalar
161                    // (string) into an array so we can add the duplicates
162                    $parsed[$parameter] = [ $parsed[$parameter] ];
163                }
164
165                $parsed[$parameter][] = $value;
166            } else {
167                $parsed[$parameter] = $value;
168            }
169        }
170        return $parsed;
171    }
172
173    /**
174     * @param array $params
175     * @return string
176     */
177    public static function buildHttpQuery( array $params ) {
178        if ( !$params ) {
179            return '';
180        }
181
182        // Urlencode both keys and values
183        $keys = static::urlencode( array_keys( $params ) );
184        $values = static::urlencode( array_values( $params ) );
185        $params = array_combine( $keys, $values );
186
187        // Parameters are sorted by name, using lexicographical byte value
188        // ordering. Ref: Spec: 9.1.1 (1)
189        uksort( $params, 'strcmp' );
190
191        $pairs = [];
192        foreach ( $params as $parameter => $value ) {
193            if ( is_array( $value ) ) {
194                // If two or more parameters share the same name, they are
195                // sorted by their value
196                // Ref: Spec: 9.1.1 (1)
197                sort( $value, SORT_STRING );
198                foreach ( $value as $duplicate_value ) {
199                    $pairs[] = "{$parameter}={$duplicate_value}";
200                }
201            } else {
202                $pairs[] = "{$parameter}={$value}";
203            }
204        }
205        // For each parameter, the name is separated from the corresponding
206        // value by an '=' character (ASCII code 61)
207        // Each name-value pair is separated by an '&' character (ASCII code 38)
208        return implode( '&', $pairs );
209    }
210
211    /**
212     * Disallow construction of utility class.
213     */
214    private function __construct() {
215        // no-op
216    }
217}