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