1
|
|
|
<?php |
2
|
|
|
/* |
3
|
|
|
* YOURLS |
4
|
|
|
* Compatibility functions when either missing from older PHP versions or not included by default |
5
|
|
|
*/ |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* @codeCoverageIgnore |
9
|
|
|
*/ |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* json_encode for PHP, should someone run a distro without php-json -- see http://askubuntu.com/questions/361424/ |
13
|
|
|
* |
14
|
|
|
*/ |
15
|
|
|
if( !function_exists( 'json_encode' ) ) { |
16
|
|
|
function json_encode( $array ) { |
17
|
|
|
return yourls_array_to_json( $array ); |
18
|
|
|
} |
19
|
|
|
} |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Converts an associative array of arbitrary depth and dimension into JSON representation. Used for compatibility with older PHP builds. |
23
|
|
|
* |
24
|
|
|
* @param array $array the array to convert. |
25
|
|
|
* @return mixed The resulting JSON string, or false if the argument was not an array. |
26
|
|
|
* @author Andy Rusterholz |
27
|
|
|
* @link http://php.net/json_encode (see comments) |
28
|
|
|
*/ |
29
|
|
|
function yourls_array_to_json( $array ){ |
30
|
|
|
|
31
|
|
|
if( !is_array( $array ) ){ |
32
|
|
|
return false; |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
$associative = count( array_diff( array_keys($array), array_keys( array_keys( $array )) )); |
36
|
|
|
if( $associative ){ |
37
|
|
|
|
38
|
|
|
$construct = array(); |
39
|
|
|
foreach( $array as $key => $value ){ |
40
|
|
|
|
41
|
|
|
// We first copy each key/value pair into a staging array, |
42
|
|
|
// formatting each key and value properly as we go. |
43
|
|
|
|
44
|
|
|
// Format the key: |
45
|
|
|
if( is_numeric( $key ) ){ |
46
|
|
|
$key = "key_$key"; |
47
|
|
|
} |
48
|
|
|
$key = '"'.addslashes( $key ).'"'; |
49
|
|
|
|
50
|
|
|
// Format the value: |
51
|
|
View Code Duplication |
if( is_array( $value )){ |
|
|
|
|
52
|
|
|
$value = yourls_array_to_json( $value ); |
53
|
|
|
} else if( !is_numeric( $value ) || is_string( $value ) ){ |
54
|
|
|
$value = '"'.addslashes( $value ).'"'; |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
// Add to staging array: |
58
|
|
|
$construct[] = "$key: $value"; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
// Then we collapse the staging array into the JSON form: |
62
|
|
|
$result = "{ " . implode( ", ", $construct ) . " }"; |
63
|
|
|
|
64
|
|
|
} else { // If the array is a vector (not associative): |
65
|
|
|
|
66
|
|
|
$construct = array(); |
67
|
|
|
foreach( $array as $value ){ |
68
|
|
|
|
69
|
|
|
// Format the value: |
70
|
|
View Code Duplication |
if( is_array( $value )){ |
|
|
|
|
71
|
|
|
$value = yourls_array_to_json( $value ); |
72
|
|
|
} else if( !is_numeric( $value ) || is_string( $value ) ){ |
73
|
|
|
$value = '"'.addslashes($value).'"'; |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
// Add to staging array: |
77
|
|
|
$construct[] = $value; |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
// Then we collapse the staging array into the JSON form: |
81
|
|
|
$result = "[ " . implode( ", ", $construct ) . " ]"; |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
return $result; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* BC Math functions (assuming if one doesn't exist, none does) |
90
|
|
|
* |
91
|
|
|
*/ |
92
|
|
|
if ( !function_exists( 'bcdiv' ) ) { |
93
|
|
|
function bcdiv( $dividend, $divisor ) { |
94
|
|
|
$quotient = floor( $dividend/$divisor ); |
95
|
|
|
return $quotient; |
96
|
|
|
} |
97
|
|
|
function bcmod( $dividend, $modulo ) { |
98
|
|
|
$remainder = $dividend%$modulo; |
99
|
|
|
return $remainder; |
100
|
|
|
} |
101
|
|
|
function bcmul( $left, $right ) { |
102
|
|
|
return $left * $right; |
103
|
|
|
} |
104
|
|
|
function bcadd( $left, $right ) { |
105
|
|
|
return $left + $right; |
106
|
|
|
} |
107
|
|
|
function bcpow( $base, $power ) { |
108
|
|
|
return pow( $base, $power ); |
109
|
|
|
} |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* http_build_url compatibility function |
115
|
|
|
* |
116
|
|
|
* @since 1.7.1 |
117
|
|
|
*/ |
118
|
|
|
if ( !function_exists( 'http_build_url' ) ) { |
119
|
|
|
include YOURLS_INC . '/http_build_url/http_build_url.php'; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* mb_substr compatibility function. Stolen from WP |
125
|
|
|
* |
126
|
|
|
* Only understands UTF-8 and 8bit. All other character sets will be treated as 8bit. |
127
|
|
|
* For $encoding === UTF-8, the $str input is expected to be a valid UTF-8 byte sequence. |
128
|
|
|
* The behavior of this function for invalid inputs is undefined. |
129
|
|
|
* |
130
|
|
|
* @since 1.7.1 |
131
|
|
|
*/ |
132
|
|
|
if ( ! function_exists( 'mb_substr' ) ) : |
133
|
|
|
function mb_substr( $str, $start, $length = null, $encoding = null ) { |
134
|
|
|
return yourls_mb_substr( $str, $start, $length, $encoding ); |
135
|
|
|
} |
136
|
|
|
endif; |
137
|
|
|
function yourls_mb_substr( $str, $start, $length = null, $encoding = null ) { |
138
|
|
|
if ( null === $encoding ) { |
139
|
|
|
$encoding = 'UTF-8'; |
140
|
|
|
} |
141
|
|
|
// The solution below works only for UTF-8, |
142
|
|
|
// so in case of a different charset just use built-in substr() |
143
|
|
|
if ( ! in_array( $encoding, array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ) ) { |
144
|
|
|
return is_null( $length ) ? substr( $str, $start ) : substr( $str, $start, $length ); |
145
|
|
|
} |
146
|
|
|
if ( yourls_supports_pcre_u() ) { |
147
|
|
|
// Use the regex unicode support to separate the UTF-8 characters into an array |
148
|
|
|
preg_match_all( '/./us', $str, $match ); |
149
|
|
|
$chars = is_null( $length ) ? array_slice( $match[0], $start ) : array_slice( $match[0], $start, $length ); |
150
|
|
|
return implode( '', $chars ); |
151
|
|
|
} |
152
|
|
|
$regex = '/( |
153
|
|
|
[\x00-\x7F] # single-byte sequences 0xxxxxxx |
154
|
|
|
| [\xC2-\xDF][\x80-\xBF] # double-byte sequences 110xxxxx 10xxxxxx |
155
|
|
|
| \xE0[\xA0-\xBF][\x80-\xBF] # triple-byte sequences 1110xxxx 10xxxxxx * 2 |
156
|
|
|
| [\xE1-\xEC][\x80-\xBF]{2} |
157
|
|
|
| \xED[\x80-\x9F][\x80-\xBF] |
158
|
|
|
| [\xEE-\xEF][\x80-\xBF]{2} |
159
|
|
|
| \xF0[\x90-\xBF][\x80-\xBF]{2} # four-byte sequences 11110xxx 10xxxxxx * 3 |
160
|
|
|
| [\xF1-\xF3][\x80-\xBF]{3} |
161
|
|
|
| \xF4[\x80-\x8F][\x80-\xBF]{2} |
162
|
|
|
)/x'; |
163
|
|
|
$chars = array( '' ); // Start with 1 element instead of 0 since the first thing we do is pop |
164
|
|
|
do { |
165
|
|
|
// We had some string left over from the last round, but we counted it in that last round. |
166
|
|
|
array_pop( $chars ); |
167
|
|
|
// Split by UTF-8 character, limit to 1000 characters (last array element will contain the rest of the string) |
168
|
|
|
$pieces = preg_split( $regex, $str, 1000, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY ); |
169
|
|
|
$chars = array_merge( $chars, $pieces ); |
170
|
|
|
} while ( count( $pieces ) > 1 && $str = array_pop( $pieces ) ); // If there's anything left over, repeat the loop. |
171
|
|
|
return join( '', array_slice( $chars, $start, $length ) ); |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
/** |
175
|
|
|
* mb_strlen compatibility function. Stolen from WP |
176
|
|
|
* |
177
|
|
|
* Only understands UTF-8 and 8bit. All other character sets will be treated as 8bit. |
178
|
|
|
* For $encoding === UTF-8, the $str input is expected to be a valid UTF-8 byte sequence. |
179
|
|
|
* The behavior of this function for invalid inputs is undefined. |
180
|
|
|
* |
181
|
|
|
* @since 1.7.1 |
182
|
|
|
*/ |
183
|
|
|
if ( ! function_exists( 'mb_strlen' ) ) : |
184
|
|
|
function mb_strlen( $str, $encoding = null ) { |
185
|
|
|
return yourls_mb_strlen( $str, $encoding ); |
186
|
|
|
} |
187
|
|
|
endif; |
188
|
|
|
function yourls_mb_strlen( $str, $encoding = null ) { |
189
|
|
|
if ( null === $encoding ) { |
190
|
|
|
$encoding = 'UTF-8'; |
191
|
|
|
} |
192
|
|
|
// The solution below works only for UTF-8, |
193
|
|
|
// so in case of a different charset just use built-in strlen() |
194
|
|
|
if ( ! in_array( $encoding, array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ) ) { |
195
|
|
|
return strlen( $str ); |
196
|
|
|
} |
197
|
|
|
if ( yourls_supports_pcre_u() ) { |
198
|
|
|
// Use the regex unicode support to separate the UTF-8 characters into an array |
199
|
|
|
preg_match_all( '/./us', $str, $match ); |
200
|
|
|
return count( $match[0] ); |
201
|
|
|
} |
202
|
|
|
$regex = '/(?: |
203
|
|
|
[\x00-\x7F] # single-byte sequences 0xxxxxxx |
204
|
|
|
| [\xC2-\xDF][\x80-\xBF] # double-byte sequences 110xxxxx 10xxxxxx |
205
|
|
|
| \xE0[\xA0-\xBF][\x80-\xBF] # triple-byte sequences 1110xxxx 10xxxxxx * 2 |
206
|
|
|
| [\xE1-\xEC][\x80-\xBF]{2} |
207
|
|
|
| \xED[\x80-\x9F][\x80-\xBF] |
208
|
|
|
| [\xEE-\xEF][\x80-\xBF]{2} |
209
|
|
|
| \xF0[\x90-\xBF][\x80-\xBF]{2} # four-byte sequences 11110xxx 10xxxxxx * 3 |
210
|
|
|
| [\xF1-\xF3][\x80-\xBF]{3} |
211
|
|
|
| \xF4[\x80-\x8F][\x80-\xBF]{2} |
212
|
|
|
)/x'; |
213
|
|
|
$count = 1; // Start at 1 instead of 0 since the first thing we do is decrement |
214
|
|
|
do { |
215
|
|
|
// We had some string left over from the last round, but we counted it in that last round. |
216
|
|
|
$count--; |
217
|
|
|
// Split by UTF-8 character, limit to 1000 characters (last array element will contain the rest of the string) |
218
|
|
|
$pieces = preg_split( $regex, $str, 1000 ); |
219
|
|
|
// Increment |
220
|
|
|
$count += count( $pieces ); |
221
|
|
|
} while ( $str = array_pop( $pieces ) ); // If there's anything left over, repeat the loop. |
222
|
|
|
// Fencepost: preg_split() always returns one extra item in the array |
223
|
|
|
return --$count; |
224
|
|
|
} |
225
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.