Completed
Push — master ( 64c2b9...b347c3 )
by ྅༻ Ǭɀħ
02:41
created

yourls_no_cache_headers()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 0
dl 0
loc 6
ccs 0
cts 5
cp 0
crap 6
rs 10
c 0
b 0
f 0
1
<?php
2
/*
0 ignored issues
show
Coding Style introduced by
Empty line required before block comment
Loading history...
3
 * YOURLS general functions
4
 *
5
 */
6
7
/**
8
 * Make an optimized regexp pattern from a string of characters
9
 * @param $string
10
 * @return string
11
 */
12
function yourls_make_regexp_pattern( $string ) {
13
    // Simple benchmarks show that regexp with smarter sequences (0-9, a-z, A-Z...) are not faster or slower than 0123456789 etc...
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 131 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
14
    // add @ as an escaped character because @ is used as the regexp delimiter in yourls-loader.php
15 7
    return preg_quote( $string, '@' );
16
}
17
18
/**
19
 * Function: Get client IP Address. Returns a DB safe string.
20
 * @return string
21
 */
22
function yourls_get_IP() {
23 3
	$ip = '';
24
25
	// Precedence: if set, X-Forwarded-For > HTTP_X_FORWARDED_FOR > HTTP_CLIENT_IP > HTTP_VIA > REMOTE_ADDR
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 104 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
26 3
	$headers = [ 'X-Forwarded-For', 'HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'HTTP_VIA', 'REMOTE_ADDR' ];
0 ignored issues
show
Coding Style introduced by
Arrays with multiple values should not be declared on a single line.
Loading history...
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 103 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
27 3
	foreach( $headers as $header ) {
28 3
		if ( !empty( $_SERVER[ $header ] ) ) {
29 3
			$ip = $_SERVER[ $header ];
30 3
			break;
31
		}
32
	}
33
34
	// headers can contain multiple IPs (X-Forwarded-For = client, proxy1, proxy2). Take first one.
35 3
	if ( strpos( $ip, ',' ) !== false )
36
		$ip = substr( $ip, 0, strpos( $ip, ',' ) );
37
38 3
	return (string)yourls_apply_filter( 'get_IP', yourls_sanitize_ip( $ip ) );
39
}
40
41
/**
42
 * Get next id a new link will have if no custom keyword provided
43
 *
44
 * @since 1.0
45
 * @return int            id of next link
46
 */
47
function yourls_get_next_decimal() {
48 3
	return (int)yourls_apply_filter( 'get_next_decimal', (int)yourls_get_option( 'next_id' ) );
49
}
50
51
/**
52
 * Update id for next link with no custom keyword
53
 *
54
 * Note: this function relies upon yourls_update_option(), which will return either true or false
55
 * depending if there has been an actual MySQL query updating the DB.
56
 * In other words, this function may return false yet this would not mean it has functionnaly failed
57
 * In other words I'm not sure we really need this function to return something :face_with_eyes_looking_up:
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 107 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
58
 * See issue 2621 for more on this.
59
 *
60
 * @since 1.0
61
 * @param integer $int     id for next link
62
 * @return bool            true or false depending on if there has been an actual MySQL query. See note above.
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 110 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
63
 */
64
function yourls_update_next_decimal( $int = '' ) {
65 2
	$int = ( $int == '' ) ? yourls_get_next_decimal() + 1 : (int)$int ;
0 ignored issues
show
Coding Style introduced by
Operator == prohibited; use === instead
Loading history...
Coding Style introduced by
Space found before semicolon; expected "$int;" but found "$int ;"
Loading history...
66 2
	$update = yourls_update_option( 'next_id', $int );
67 2
	yourls_do_action( 'update_next_decimal', $int, $update );
68 2
	return $update;
69
}
70
71
/**
72
 * Return XML output.
73
 * @param array $array
74
 * @return string
75
 */
76
function yourls_xml_encode( $array ) {
77 1
    require_once( YOURLS_INC.'/functions-xml.php' );
78 1
    return ( new yourls_array2xml() )->array2xml( $array );
79
}
80
81
/**
82
 * Update click count on a short URL. Return 0/1 for error/success.
83
 * @param string $keyword
84
 * @param bool   $clicks
85
 * @return mixed|string
86
 */
87
function yourls_update_clicks( $keyword, $clicks = false ) {
88
	// Allow plugins to short-circuit the whole function
89 2
	$pre = yourls_apply_filter( 'shunt_update_clicks', false, $keyword, $clicks );
90 2
	if ( false !== $pre )
91
		return $pre;
92
93 2
	global $ydb;
94 2
	$keyword = yourls_sanitize_keyword( $keyword );
95 2
	$table = YOURLS_DB_TABLE_URL;
96 2
	if ( $clicks !== false && is_int( $clicks ) && $clicks >= 0 )
0 ignored issues
show
introduced by
The condition is_int($clicks) is always false.
Loading history...
97
		$update = $ydb->fetchAffected( "UPDATE `$table` SET `clicks` = :clicks WHERE `keyword` = :keyword", [ 'clicks' => $clicks, 'keyword' => $keyword ] );
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $table instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 151 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
98
	else
99 2
		$update = $ydb->fetchAffected( "UPDATE `$table` SET `clicks` = clicks + 1 WHERE `keyword` = :keyword", [ 'keyword' => $keyword ] );
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $table instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 133 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
100
101 2
	yourls_do_action( 'update_clicks', $keyword, $update, $clicks );
102 2
	return $update;
103
}
104
105
/**
106
 * Return array of stats. (string)$filter is 'bottom', 'last', 'rand' or 'top'. (int)$limit is the number of links to return
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 124 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
107
 *
108
 */
109
function yourls_get_stats( $filter = 'top', $limit = 10, $start = 0 ) {
110 1
	global $ydb;
111
112 1
	switch( $filter ) {
113 1
		case 'bottom':
114
			$sort_by    = '`clicks`';
115
			$sort_order = 'asc';
116
			break;
0 ignored issues
show
Coding Style introduced by
Case breaking statement indented incorrectly; expected 6 spaces, found 3
Loading history...
117 1
		case 'last':
118
			$sort_by    = '`timestamp`';
119
			$sort_order = 'desc';
120
			break;
0 ignored issues
show
Coding Style introduced by
Case breaking statement indented incorrectly; expected 6 spaces, found 3
Loading history...
121 1
		case 'rand':
122 1
		case 'random':
123
			$sort_by    = 'RAND()';
124
			$sort_order = '';
125
			break;
0 ignored issues
show
Coding Style introduced by
Case breaking statement indented incorrectly; expected 6 spaces, found 3
Loading history...
126 1
		case 'top':
127
		default:
128 1
			$sort_by    = '`clicks`';
129 1
			$sort_order = 'desc';
130 1
			break;
0 ignored issues
show
Coding Style introduced by
Case breaking statement indented incorrectly; expected 6 spaces, found 3
Loading history...
131
	}
132
133
	// Fetch links
134 1
	$limit = intval( $limit );
135 1
	$start = intval( $start );
136 1
	if ( $limit > 0 ) {
137
138
		$table_url = YOURLS_DB_TABLE_URL;
139
		$results = $ydb->fetchObjects( "SELECT * FROM `$table_url` WHERE 1=1 ORDER BY $sort_by $sort_order LIMIT $start, $limit;" );
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $table_url instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $sort_by instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $sort_order instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $start instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $limit instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 126 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
140
141
		$return = [];
142
		$i = 1;
143
144
		foreach ( (array)$results as $res ) {
145
			$return['links']['link_'.$i++] = [
0 ignored issues
show
Coding Style introduced by
Increment and decrement operators must be bracketed when used in string concatenation
Loading history...
146
				'shorturl' => yourls_link($res->keyword),
0 ignored issues
show
Coding Style introduced by
Array double arrow not aligned correctly; expected 2 space(s) but found 1
Loading history...
147
				'url'      => $res->url,
0 ignored issues
show
Coding Style introduced by
Array double arrow not aligned correctly; expected 7 space(s) but found 6
Loading history...
148
				'title'    => $res->title,
0 ignored issues
show
Coding Style introduced by
Array double arrow not aligned correctly; expected 5 space(s) but found 4
Loading history...
149
				'timestamp'=> $res->timestamp,
0 ignored issues
show
Coding Style introduced by
Array double arrow not aligned correctly; expected 1 space(s) but found 0
Loading history...
150
				'ip'       => $res->ip,
0 ignored issues
show
Coding Style introduced by
Array double arrow not aligned correctly; expected 8 space(s) but found 7
Loading history...
151
				'clicks'   => $res->clicks,
0 ignored issues
show
Coding Style introduced by
Array double arrow not aligned correctly; expected 4 space(s) but found 3
Loading history...
152
            ];
0 ignored issues
show
Coding Style introduced by
The closing parenthesis does not seem to be aligned correctly; expected 36 space(s), but found 12.
Loading history...
153
		}
154
	}
155
156 1
	$return['stats'] = yourls_get_db_stats();
157
158 1
	$return['statusCode'] = 200;
159
160 1
	return yourls_apply_filter( 'get_stats', $return, $filter, $limit, $start );
161
}
162
163
/**
164
 * Get total number of URLs and sum of clicks. Input: optional "AND WHERE" clause. Returns array
165
 *
166
 * The $where parameter will contain additional SQL arguments:
167
 *   $where['sql'] will concatenate SQL clauses: $where['sql'] = ' AND something = :value AND otherthing < :othervalue';
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 120 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
168
 *   $where['binds'] will hold the (name => value) placeholder pairs: $where['binds'] = array('value' => $value, 'othervalue' => $value2)
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 137 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
169
 *
170
 * @param  $where array  See comment above
171
 * @return array
172
 */
173
function yourls_get_db_stats( $where = [ 'sql' => '', 'binds' => [] ] ) {
174 2
	global $ydb;
175 2
	$table_url = YOURLS_DB_TABLE_URL;
176
177 2
	$totals = $ydb->fetchObject( "SELECT COUNT(keyword) as count, SUM(clicks) as sum FROM `$table_url` WHERE 1=1 " . $where['sql'] , $where['binds'] );
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $table_url instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 148 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
178 2
	$return = [ 'total_links' => $totals->count, 'total_clicks' => $totals->sum ];
0 ignored issues
show
Coding Style introduced by
Arrays with multiple values should not be declared on a single line.
Loading history...
179
180 2
	return yourls_apply_filter( 'get_db_stats', $return, $where );
181
}
182
183
/**
184
 * Get number of SQL queries performed
185
 *
186
 */
187
function yourls_get_num_queries() {
188 2
	global $ydb;
189
190 2
	return yourls_apply_filter( 'get_num_queries', $ydb->get_num_queries() );
191
}
192
193
/**
194
 * Returns a sanitized a user agent string. Given what I found on http://www.user-agents.org/ it should be OK.
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 110 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
195
 *
196
 */
197
function yourls_get_user_agent() {
198 2
    $ua = '-';
199
200 2
    if ( isset( $_SERVER['HTTP_USER_AGENT'] ) ) {
201 2
        $ua = strip_tags( html_entity_decode( $_SERVER['HTTP_USER_AGENT'] ));
202 2
        $ua = preg_replace('![^0-9a-zA-Z\':., /{}\(\)\[\]\+@&\!\?;_\-=~\*\#]!', '', $ua );
203
    }
204
205 2
    return yourls_apply_filter( 'get_user_agent', substr( $ua, 0, 255 ) );
206
}
207
208
/**
209
 * Returns the sanitized referrer submitted by the browser.
210
 *
211
 * @return string               HTTP Referrer or 'direct' if no referrer was provided
212
 */
213
function yourls_get_referrer() {
214
    $referrer = isset( $_SERVER['HTTP_REFERER'] ) ? yourls_sanitize_url_safe( $_SERVER['HTTP_REFERER'] ) : 'direct';
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 116 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
215
216
    return yourls_apply_filter( 'get_referrer', substr( $referrer, 0, 200 ) );
217
}
218
219
/**
220
 * Redirect to another page
221
 *
222
 * YOURLS redirection, either to internal or external URLs. If headers have not been sent, redirection
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 102 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
223
 * is achieved with PHP's header(). If headers have been sent already and we're not in a command line
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 101 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
224
 * client, redirection occurs with Javascript.
225
 *
226
 * @since 1.4
227
 * @param string $location      URL to redirect to
228
 * @param int    $code          HTTP status code to send
229
 * @return int                  1 for header redirection, 2 for js redirection, 3 otherwise
230
 */
231
function yourls_redirect( $location, $code = 301 ) {
232
	yourls_do_action( 'pre_redirect', $location, $code );
233
	$location = yourls_apply_filter( 'redirect_location', $location, $code );
234
	$code     = yourls_apply_filter( 'redirect_code', $code, $location );
235
	// Redirect, either properly if possible, or via Javascript otherwise
236
	if( !headers_sent() ) {
237
		yourls_status_header( $code );
238
		header( "Location: $location" );
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $location instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
239
        return 1;
240
	}
241
242
	if( php_sapi_name() !== 'cli') {
243
        yourls_redirect_javascript( $location );
244
        return 2;
245
	}
246
247
	return 3;
248
}
249
250
/**
251
 * Redirect to an existing short URL
252
 *
253
 * Redirect client to an existing short URL (no check performed) and execute misc tasks: update
254
 * clicks for short URL, update logs, and send a nocache header to prevent bots indexing short
255
 * URLS (see #2202)
256
 *
257
 * @since  1.7.3
258
 * @param  string $url
259
 * @param  string $keyword
260
 */
261
function yourls_redirect_shorturl($url, $keyword) {
262
    yourls_do_action( 'redirect_shorturl', $url, $keyword );
263
264
    // Update click count in main table
265
    yourls_update_clicks( $keyword );
266
267
    // Update detailed log for stats
268
    yourls_log_redirect( $keyword );
269
270
    // Tell (Google)bots not to index this short URL, see #2202
271
    if ( !headers_sent() ) {
272
        header( "X-Robots-Tag: noindex", true );
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal X-Robots-Tag: noindex does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
273
    }
274
275
    yourls_redirect( $url, 301 );
276
}
277
278
/**
279
 * Send headers to explicitely tell browser not to cache content or redirection
280
 *
281
 * @since 1.7.10
282
 * @return void
283
 */
284
function yourls_no_cache_headers() {
285
    if( !headers_sent() ) {
286
        header( 'Expires: Thu, 23 Mar 1972 07:00:00 GMT' );
287
        header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
288
        header( 'Cache-Control: no-cache, must-revalidate, max-age=0' );
289
        header( 'Pragma: no-cache' );
290
    }
291
}
292
293
/**
294
 * Send a filerable content type header
295
 *
296
 * @since 1.7
297
 * @param string $type content type ('text/html', 'application/json', ...)
298
 * @return bool whether header was sent
299
 */
300
function yourls_content_type_header( $type ) {
301 8
    yourls_do_action( 'content_type_header', $type );
302 8
	if( !headers_sent() ) {
303
		$charset = yourls_apply_filter( 'content_type_header_charset', 'utf-8' );
304
		header( "Content-Type: $type; charset=$charset" );
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $type instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $charset instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
305
		return true;
306
	}
307 8
	return false;
308
}
309
310
/**
311
 * Set HTTP status header
312
 *
313
 * @since 1.4
314
 * @param int $code  status header code
315
 * @return bool      whether header was sent
316
 */
317
function yourls_status_header( $code = 200 ) {
318 8
	yourls_do_action( 'status_header', $code );
319
320 8
	if( headers_sent() )
321 8
		return false;
322
323
	$protocol = $_SERVER['SERVER_PROTOCOL'];
324
	if ( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol )
0 ignored issues
show
Coding Style introduced by
Operator != prohibited; use !== instead
Loading history...
325
		$protocol = 'HTTP/1.0';
326
327
	$code = intval( $code );
328
	$desc = yourls_get_HTTP_status( $code );
329
330
	@header ("$protocol $code $desc"); // This causes problems on IIS and some FastCGI setups
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for header(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

330
	/** @scrutinizer ignore-unhandled */ @header ("$protocol $code $desc"); // This causes problems on IIS and some FastCGI setups

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
Bug introduced by
Are you sure the usage of header($protocol.' '.$code.' '.$desc) is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $protocol instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $code instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $desc instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
331
332
    return true;
333
}
334
335
/**
336
 * Redirect to another page using Javascript.
337
 * Set optional (bool)$dontwait to false to force manual redirection (make sure a message has been read by user)
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 112 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
338
 *
339
 * @param string $location
340
 * @param bool   $dontwait
341
 */
342
function yourls_redirect_javascript( $location, $dontwait = true ) {
343 1
    yourls_do_action( 'pre_redirect_javascript', $location, $dontwait );
344 1
    $location = yourls_apply_filter( 'redirect_javascript', $location, $dontwait );
345 1
    if ( $dontwait ) {
346 1
        $message = yourls_s( 'if you are not redirected after 10 seconds, please <a href="%s">click here</a>', $location );
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 123 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
347
        echo <<<REDIR
348 1
		<script type="text/javascript">
349 1
		window.location="$location";
350
		</script>
351 1
		<small>($message)</small>
352
REDIR;
353
    }
354
    else {
355
        echo '<p>'.yourls_s( 'Please <a href="%s">click here</a>', $location ).'</p>';
356
    }
357 1
    yourls_do_action( 'post_redirect_javascript', $location );
358 1
}
359
360
/**
361
 * Return an HTTP status code
362
 * @param int $code
363
 * @return string
364
 */
365
function yourls_get_HTTP_status( $code ) {
366 52
	$code = intval( $code );
367
	$headers_desc = [
368 52
		100 => 'Continue',
369
		101 => 'Switching Protocols',
370
		102 => 'Processing',
371
372
		200 => 'OK',
373
		201 => 'Created',
374
		202 => 'Accepted',
375
		203 => 'Non-Authoritative Information',
376
		204 => 'No Content',
377
		205 => 'Reset Content',
378
		206 => 'Partial Content',
379
		207 => 'Multi-Status',
380
		226 => 'IM Used',
381
382
		300 => 'Multiple Choices',
383
		301 => 'Moved Permanently',
384
		302 => 'Found',
385
		303 => 'See Other',
386
		304 => 'Not Modified',
387
		305 => 'Use Proxy',
388
		306 => 'Reserved',
389
		307 => 'Temporary Redirect',
390
391
		400 => 'Bad Request',
392
		401 => 'Unauthorized',
393
		402 => 'Payment Required',
394
		403 => 'Forbidden',
395
		404 => 'Not Found',
396
		405 => 'Method Not Allowed',
397
		406 => 'Not Acceptable',
398
		407 => 'Proxy Authentication Required',
399
		408 => 'Request Timeout',
400
		409 => 'Conflict',
401
		410 => 'Gone',
402
		411 => 'Length Required',
403
		412 => 'Precondition Failed',
404
		413 => 'Request Entity Too Large',
405
		414 => 'Request-URI Too Long',
406
		415 => 'Unsupported Media Type',
407
		416 => 'Requested Range Not Satisfiable',
408
		417 => 'Expectation Failed',
409
		422 => 'Unprocessable Entity',
410
		423 => 'Locked',
411
		424 => 'Failed Dependency',
412
		426 => 'Upgrade Required',
413
414
		500 => 'Internal Server Error',
415
		501 => 'Not Implemented',
416
		502 => 'Bad Gateway',
417
		503 => 'Service Unavailable',
418
		504 => 'Gateway Timeout',
419
		505 => 'HTTP Version Not Supported',
420
		506 => 'Variant Also Negotiates',
421
		507 => 'Insufficient Storage',
422
		510 => 'Not Extended'
0 ignored issues
show
Coding Style introduced by
Each line in an array declaration must end in a comma
Loading history...
423
    ];
0 ignored issues
show
Coding Style introduced by
The closing parenthesis does not seem to be aligned correctly; expected 17 space(s), but found 4.
Loading history...
424
425 52
    return isset( $headers_desc[ $code ] ) ? $headers_desc[ $code ] : '';
426
}
427
428
/**
429
 * Log a redirect (for stats)
430
 *
431
 * This function does not check for the existence of a valid keyword, in order to save a query. Make sure the keyword
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 117 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
432
 * exists before calling it.
433
 *
434
 * @since 1.4
435
 * @param string $keyword short URL keyword
436
 * @return mixed Result of the INSERT query (1 on success)
437
 */
438
function yourls_log_redirect( $keyword ) {
439
	// Allow plugins to short-circuit the whole function
440
	$pre = yourls_apply_filter( 'shunt_log_redirect', false, $keyword );
441
	if ( false !== $pre )
442
		return $pre;
443
444
	if ( !yourls_do_log_redirect() )
445
		return true;
446
447
	$table = YOURLS_DB_TABLE_LOG;
448
    $ip = yourls_get_IP();
449
    $binds = [
450
        'now' => date( 'Y-m-d H:i:s' ),
0 ignored issues
show
Coding Style introduced by
Array double arrow not aligned correctly; expected 6 space(s) but found 1
Loading history...
451
        'keyword'  => yourls_sanitize_keyword($keyword),
452
        'referrer' => substr( yourls_get_referrer(), 0, 200 ),
453
        'ua'       => substr(yourls_get_user_agent(), 0, 255),
454
        'ip'       => $ip,
455
        'location' => yourls_geo_ip_to_countrycode($ip),
456
    ];
0 ignored issues
show
Coding Style introduced by
The closing parenthesis does not seem to be aligned correctly; expected 13 space(s), but found 4.
Loading history...
457
458
    return yourls_get_db()->fetchAffected("INSERT INTO `$table` (click_time, shorturl, referrer, user_agent, ip_address, country_code) VALUES (:now, :keyword, :referrer, :ua, :ip, :location)", $binds );
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $table instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 202 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
459
}
460
461
/**
462
 * Check if we want to not log redirects (for stats)
463
 *
464
 */
465
function yourls_do_log_redirect() {
466 1
	return ( !defined( 'YOURLS_NOSTATS' ) || YOURLS_NOSTATS != true );
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison !== instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
467
}
468
469
/**
470
 * Check if an upgrade is needed
471
 * @return bool
472
 */
473
function yourls_upgrade_is_needed() {
474
    // check YOURLS_DB_VERSION exist && match values stored in YOURLS_DB_TABLE_OPTIONS
475
    list( $currentver, $currentsql ) = yourls_get_current_version_from_sql();
476
    if ( $currentsql < YOURLS_DB_VERSION ) {
477
        return true;
478
    }
479
480
    // Check if YOURLS_VERSION exist && match value stored in YOURLS_DB_TABLE_OPTIONS, update DB if required
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 108 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
481
    if ( $currentver < YOURLS_VERSION ) {
482
        yourls_update_option( 'version', YOURLS_VERSION );
483
    }
484
485
    return false;
486
}
487
488
/**
489
 * Get current version & db version as stored in the options DB. Prior to 1.4 there's no option table.
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 102 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
490
 * @return array
491
 */
492
function yourls_get_current_version_from_sql() {
493
    $currentver = yourls_get_option( 'version' );
494
    $currentsql = yourls_get_option( 'db_version' );
495
496
    // Values if version is 1.3
497
    if ( !$currentver ) {
498
        $currentver = '1.3';
499
    }
500
    if ( !$currentsql ) {
501
        $currentsql = '100';
502
    }
503
504
    return [ $currentver, $currentsql ];
0 ignored issues
show
Coding Style introduced by
Arrays with multiple values should not be declared on a single line.
Loading history...
505
}
506
507
/**
508
 * Determine if the current page is private
509
 *
510
 */
511
function yourls_is_private() {
512 1
    $private = false;
513
514 1
    if ( defined( 'YOURLS_PRIVATE' ) && YOURLS_PRIVATE ) {
515
516 1
        $private = true;
517
518
        // Allow overruling for particular pages:
519
520
        // API
521 1
        if ( yourls_is_API() ) {
522
            if ( !defined( 'YOURLS_PRIVATE_API' ) || YOURLS_PRIVATE_API ) {
0 ignored issues
show
Bug introduced by
The constant YOURLS_PRIVATE_API was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
523
                $private = true;
524
            }
525
        }
526 1
        elseif ( yourls_is_infos() ) {
527
            if ( !defined( 'YOURLS_PRIVATE_INFOS' ) || YOURLS_PRIVATE_INFOS ) {
0 ignored issues
show
Bug introduced by
The constant YOURLS_PRIVATE_INFOS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
528
                $private = true;
529
            }
530
            // Others
531
        }
532
    }
533
534 1
    return yourls_apply_filter( 'is_private', $private );
535
}
536
537
/**
538
 * Allow several short URLs for the same long URL ?
539
 * @return bool
540
 */
541
function yourls_allow_duplicate_longurls() {
542
    // special treatment if API to check for WordPress plugin requests
543 4
    if ( yourls_is_API() && isset( $_REQUEST[ 'source' ] ) && $_REQUEST[ 'source' ] == 'plugin' ) {
0 ignored issues
show
Coding Style introduced by
Operator == prohibited; use === instead
Loading history...
544
            return false;
545
    }
546 4
    return defined( 'YOURLS_UNIQUE_URLS' ) && !YOURLS_UNIQUE_URLS;
547
}
548
549
/**
550
 * Check if an IP shortens URL too fast to prevent DB flood. Return true, or die.
551
 * @param string $ip
552
 * @return bool|mixed|string
553
 */
554
function yourls_check_IP_flood( $ip = '' ) {
555
556
	// Allow plugins to short-circuit the whole function
557 3
	$pre = yourls_apply_filter( 'shunt_check_IP_flood', false, $ip );
558 3
	if ( false !== $pre )
559
		return $pre;
560
561 3
	yourls_do_action( 'pre_check_ip_flood', $ip ); // at this point $ip can be '', check it if your plugin hooks in here
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 117 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
562
563
	// Raise white flag if installing or if no flood delay defined
564
	if(
565 3
		( defined('YOURLS_FLOOD_DELAY_SECONDS') && YOURLS_FLOOD_DELAY_SECONDS === 0 ) ||
0 ignored issues
show
introduced by
The condition YOURLS_FLOOD_DELAY_SECONDS === 0 is always false.
Loading history...
566
		!defined('YOURLS_FLOOD_DELAY_SECONDS') ||
567
		yourls_is_installing()
568
	)
569 3
		return true;
570
571
	// Don't throttle logged in users
572
	if( yourls_is_private() ) {
573
		 if( yourls_is_valid_user() === true )
574
			return true;
575
	}
576
577
	// Don't throttle whitelist IPs
578
	if( defined( 'YOURLS_FLOOD_IP_WHITELIST' ) && YOURLS_FLOOD_IP_WHITELIST ) {
579
		$whitelist_ips = explode( ',', YOURLS_FLOOD_IP_WHITELIST );
580
		foreach( (array)$whitelist_ips as $whitelist_ip ) {
581
			$whitelist_ip = trim( $whitelist_ip );
582
			if ( $whitelist_ip == $ip )
0 ignored issues
show
Coding Style introduced by
Operator == prohibited; use === instead
Loading history...
583
				return true;
584
		}
585
	}
586
587
	$ip = ( $ip ? yourls_sanitize_ip( $ip ) : yourls_get_IP() );
588
589
	yourls_do_action( 'check_ip_flood', $ip );
590
591
	$table = YOURLS_DB_TABLE_URL;
592
	$lasttime = yourls_get_db()->fetchValue( "SELECT `timestamp` FROM $table WHERE `ip` = :ip ORDER BY `timestamp` DESC LIMIT 1", [ 'ip' => $ip ] );
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $table instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 145 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
593
	if( $lasttime ) {
594
		$now = date( 'U' );
595
		$then = date( 'U', strtotime( $lasttime ) );
596
		if( ( $now - $then ) <= YOURLS_FLOOD_DELAY_SECONDS ) {
597
			// Flood!
598
			yourls_do_action( 'ip_flood', $ip, $now - $then );
599
			yourls_die( yourls__( 'Too many URLs added too fast. Slow down please.' ), yourls__( 'Too Many Requests' ), 429 );
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 117 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
600
		}
601
	}
602
603
	return true;
604
}
605
606
/**
607
 * Check if YOURLS is installing
608
 *
609
 * @since 1.6
610
 * @return bool
611
 */
612
function yourls_is_installing() {
613 1
	return (bool)yourls_apply_filter( 'is_installing', defined( 'YOURLS_INSTALLING' ) && YOURLS_INSTALLING );
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 106 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
614
}
615
616
/**
617
 * Check if YOURLS is upgrading
618
 *
619
 * @since 1.6
620
 * @return bool
621
 */
622
function yourls_is_upgrading() {
623 1
    return (bool)yourls_apply_filter( 'is_upgrading', defined( 'YOURLS_UPGRADING' ) && YOURLS_UPGRADING );
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 106 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
624
}
625
626
/**
627
 * Check if YOURLS is installed
628
 *
629
 * Checks property $ydb->installed that is created by yourls_get_all_options()
630
 *
631
 * See inline comment for updating from 1.3 or prior.
632
 *
633
 * @return bool
634
 */
635
function yourls_is_installed() {
636 2
	return (bool)yourls_apply_filter( 'is_installed', yourls_get_db()->is_installed() );
637
}
638
639
/**
640
 * Set installed state
641
 *
642
 * @since  1.7.3
643
 * @param bool $bool whether YOURLS is installed or not
644
 * @return void
645
 */
646
function yourls_set_installed( $bool ) {
647
    yourls_get_db()->set_installed( $bool );
648
}
649
650
/**
651
 * Generate random string of (int)$length length and type $type (see function for details)
652
 *
653
 * @param int    $length
654
 * @param int    $type
655
 * @param string $charlist
656
 * @return mixed|string
657
 */
658
function yourls_rnd_string ( $length = 5, $type = 0, $charlist = '' ) {
659 1
    $length = intval( $length );
660
661
    // define possible characters
662
    switch ( $type ) {
663
664
        // no vowels to make no offending word, no 0/1/o/l to avoid confusion between letters & digits. Perfect for passwords.
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 126 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
665 1
        case '1':
666
            $possible = "23456789bcdfghjkmnpqrstvwxyz";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal 23456789bcdfghjkmnpqrstvwxyz does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
667
            break;
668
669
        // Same, with lower + upper
670 1
        case '2':
671
            $possible = "23456789bcdfghjkmnpqrstvwxyzBCDFGHJKMNPQRSTVWXYZ";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal 23456789bcdfghjkmnpqrstvwxyzBCDFGHJKMNPQRSTVWXYZ does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
672
            break;
673
674
        // all letters, lowercase
675 1
        case '3':
676
            $possible = "abcdefghijklmnopqrstuvwxyz";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal abcdefghijklmnopqrstuvwxyz does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
677
            break;
678
679
        // all letters, lowercase + uppercase
680 1
        case '4':
681
            $possible = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal abcdefghijklmnopqrstuvwx...DEFGHIJKLMNOPQRSTUVWXYZ does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
682
            break;
683
684
        // all digits & letters lowercase
685 1
        case '5':
686
            $possible = "0123456789abcdefghijklmnopqrstuvwxyz";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal 0123456789abcdefghijklmnopqrstuvwxyz does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
687
            break;
688
689
        // all digits & letters lowercase + uppercase
690 1
        case '6':
691 1
            $possible = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal 0123456789abcdefghijklmn...DEFGHIJKLMNOPQRSTUVWXYZ does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
692 1
            break;
693
694
        // custom char list, or comply to charset as defined in config
695
        default:
696
        case '0':
697
            $possible = $charlist ? $charlist : yourls_get_shorturl_charset();
698
            break;
699
    }
700
701 1
    $str = substr( str_shuffle( $possible ), 0, $length );
702 1
    return yourls_apply_filter( 'rnd_string', $str, $length, $type, $charlist );
703
}
704
705
/**
706
 * Check if we're in API mode.
707
 * @return bool
708
 */
709
function yourls_is_API() {
710 24
    return (bool)yourls_apply_filter( 'is_API', defined( 'YOURLS_API' ) && YOURLS_API );
711
}
712
713
/**
714
 * Check if we're in Ajax mode.
715
 * @return bool
716
 */
717
function yourls_is_Ajax() {
718
    return (bool)yourls_apply_filter( 'is_Ajax', defined( 'YOURLS_AJAX' ) && YOURLS_AJAX );
719
}
720
721
/**
722
 * Check if we're in GO mode (yourls-go.php).
723
 * @return bool
724
 */
725
function yourls_is_GO() {
726
    return (bool)yourls_apply_filter( 'is_GO', defined( 'YOURLS_GO' ) && YOURLS_GO );
727
}
728
729
/**
730
 * Check if we're displaying stats infos (yourls-infos.php). Returns bool
731
 *
732
 */
733
function yourls_is_infos() {
734 1
    return (bool)yourls_apply_filter( 'is_infos', defined( 'YOURLS_INFOS' ) && YOURLS_INFOS );
735
}
736
737
/**
738
 * Check if we're in the admin area. Returns bool
739
 *
740
 */
741
function yourls_is_admin() {
742 11
    return (bool)yourls_apply_filter( 'is_admin', defined( 'YOURLS_ADMIN' ) && YOURLS_ADMIN );
743
}
744
745
/**
746
 * Check if the server seems to be running on Windows. Not exactly sure how reliable this is.
747
 *
748
 */
749
function yourls_is_windows() {
750
	return defined( 'DIRECTORY_SEPARATOR' ) && DIRECTORY_SEPARATOR == '\\';
751
}
752
753
/**
754
 * Check if SSL is required.
755
 * @return bool
756
 */
757
function yourls_needs_ssl() {
758 5
    return (bool)yourls_apply_filter( 'needs_ssl', defined( 'YOURLS_ADMIN_SSL' ) && YOURLS_ADMIN_SSL );
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 103 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
759
}
760
761
/**
762
 * Check if SSL is used. Stolen from WP.
763
 * @return bool
764
 */
765
function yourls_is_ssl() {
766 38
    $is_ssl = false;
767 38
    if ( isset( $_SERVER[ 'HTTPS' ] ) ) {
768
        if ( 'on' == strtolower( $_SERVER[ 'HTTPS' ] ) ) {
0 ignored issues
show
Coding Style introduced by
Operator == prohibited; use === instead
Loading history...
769
            $is_ssl = true;
770
        }
771
        if ( '1' == $_SERVER[ 'HTTPS' ] ) {
0 ignored issues
show
Coding Style introduced by
Operator == prohibited; use === instead
Loading history...
772
            $is_ssl = true;
773
        }
774
    }
775 38
    elseif ( isset( $_SERVER[ 'SERVER_PORT' ] ) && ( '443' == $_SERVER[ 'SERVER_PORT' ] ) ) {
0 ignored issues
show
Coding Style introduced by
Operator == prohibited; use === instead
Loading history...
776
        $is_ssl = true;
777
    }
778 38
    return (bool)yourls_apply_filter( 'is_ssl', $is_ssl );
779
}
780
781
/**
782
 * Get a remote page title
783
 *
784
 * This function returns a string: either the page title as defined in HTML, or the URL if not found
785
 * The function tries to convert funky characters found in titles to UTF8, from the detected charset.
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 101 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
786
 * Charset in use is guessed from HTML meta tag, or if not found, from server's 'content-type' response.
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 104 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
787
 *
788
 * @param string $url URL
789
 * @return string Title (sanitized) or the URL if no title found
790
 */
791
function yourls_get_remote_title( $url ) {
792
    // Allow plugins to short-circuit the whole function
793
    $pre = yourls_apply_filter( 'shunt_get_remote_title', false, $url );
794
    if ( false !== $pre ) {
795
        return $pre;
796
    }
797
798
    $url = yourls_sanitize_url( $url );
799
800
    // Only deal with http(s)://
801
    if ( !in_array( yourls_get_protocol( $url ), [ 'http://', 'https://' ] ) ) {
802
        return $url;
803
    }
804
805
    $title = $charset = false;
806
807
    $max_bytes = yourls_apply_filter( 'get_remote_title_max_byte', 32768 ); // limit data fetching to 32K in order to find a <title> tag
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 136 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
808
809
    $response = yourls_http_get( $url, [], [], [ 'max_bytes' => $max_bytes ] ); // can be a Request object or an error string
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 125 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
810
    if ( is_string( $response ) ) {
0 ignored issues
show
introduced by
The condition is_string($response) is always false.
Loading history...
811
        return $url;
812
    }
813
814
    // Page content. No content? Return the URL
815
    $content = $response->body;
816
    if ( !$content ) {
817
        return $url;
818
    }
819
820
    // look for <title>. No title found? Return the URL
821
    if ( preg_match( '/<title>(.*?)<\/title>/is', $content, $found ) ) {
822
        $title = $found[ 1 ];
823
        unset( $found );
824
    }
825
    if ( !$title ) {
826
        return $url;
827
    }
828
829
    // Now we have a title. We'll try to get proper utf8 from it.
830
831
    // Get charset as (and if) defined by the HTML meta tag. We should match
832
    // <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
833
    // or <meta charset='utf-8'> and all possible variations: see https://gist.github.com/ozh/7951236
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 101 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
834
    if ( preg_match( '/<meta[^>]*charset\s*=["\' ]*([a-zA-Z0-9\-_]+)/is', $content, $found ) ) {
835
        $charset = $found[ 1 ];
836
        unset( $found );
837
    }
838
    else {
839
        // No charset found in HTML. Get charset as (and if) defined by the server response
840
        $_charset = current( $response->headers->getValues( 'content-type' ) );
841
        if ( preg_match( '/charset=(\S+)/', $_charset, $found ) ) {
842
            $charset = trim( $found[ 1 ], ';' );
843
            unset( $found );
844
        }
845
    }
846
847
    // Conversion to utf-8 if what we have is not utf8 already
848
    if ( strtolower( $charset ) != 'utf-8' && function_exists( 'mb_convert_encoding' ) ) {
0 ignored issues
show
Coding Style introduced by
Operator != prohibited; use !== instead
Loading history...
849
        // We use @ to remove warnings because mb_ functions are easily bitching about illegal chars
850
        if ( $charset ) {
851
            $title = @mb_convert_encoding( $title, 'UTF-8', $charset );
852
        }
853
        else {
854
            $title = @mb_convert_encoding( $title, 'UTF-8' );
855
        }
856
    }
857
858
    // Remove HTML entities
859
    $title = html_entity_decode( $title, ENT_QUOTES, 'UTF-8' );
860
861
    // Strip out evil things
862
    $title = yourls_sanitize_title( $title, $url );
863
864
    return (string)yourls_apply_filter( 'get_remote_title', $title, $url );
865
}
866
867
/**
868
 * Quick UA check for mobile devices.
869
 * @return bool
870
 */
871
function yourls_is_mobile_device() {
872
	// Strings searched
873
	$mobiles = [
874 1
		'android', 'blackberry', 'blazer',
0 ignored issues
show
Coding Style introduced by
This array value does not seem to be aligned correcty; expected 13 spaces, but found 2.
Loading history...
Coding Style introduced by
Each value in a multi-line array must be on a new line
Loading history...
875
		'compal', 'elaine', 'fennec', 'hiptop',
0 ignored issues
show
Coding Style introduced by
This array value does not seem to be aligned correcty; expected 13 spaces, but found 2.
Loading history...
Coding Style introduced by
Each value in a multi-line array must be on a new line
Loading history...
876
		'iemobile', 'iphone', 'ipod', 'ipad',
0 ignored issues
show
Coding Style introduced by
This array value does not seem to be aligned correcty; expected 13 spaces, but found 2.
Loading history...
Coding Style introduced by
Each value in a multi-line array must be on a new line
Loading history...
877
		'iris', 'kindle', 'opera mobi', 'opera mini',
0 ignored issues
show
Coding Style introduced by
This array value does not seem to be aligned correcty; expected 13 spaces, but found 2.
Loading history...
Coding Style introduced by
Each value in a multi-line array must be on a new line
Loading history...
878
		'palm', 'phone', 'pocket', 'psp', 'symbian',
0 ignored issues
show
Coding Style introduced by
This array value does not seem to be aligned correcty; expected 13 spaces, but found 2.
Loading history...
Coding Style introduced by
Each value in a multi-line array must be on a new line
Loading history...
879
		'treo', 'wap', 'windows ce', 'windows phone'
0 ignored issues
show
Coding Style introduced by
This array value does not seem to be aligned correcty; expected 13 spaces, but found 2.
Loading history...
Coding Style introduced by
Each value in a multi-line array must be on a new line
Loading history...
Coding Style introduced by
There should be a trailing comma after the last value of an array declaration.
Loading history...
880
    ];
0 ignored issues
show
Coding Style introduced by
The closing parenthesis does not seem to be aligned correctly; expected 12 space(s), but found 4.
Loading history...
881
882
	// Current user-agent
883 1
	$current = strtolower( $_SERVER['HTTP_USER_AGENT'] );
884
885
	// Check and return
0 ignored issues
show
Unused Code Comprehensibility introduced by
40% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
886 1
	$is_mobile = ( str_replace( $mobiles, '', $current ) != $current );
887 1
	return (bool)yourls_apply_filter( 'is_mobile_device', $is_mobile );
888
}
889
890
/**
891
 * Get request in YOURLS base (eg in 'http://sho.rt/yourls/abcd' get 'abdc')
892
 *
893
 * With no parameter passed, this function will guess current page and consider
894
 * it is the requested page.
895
 * For testing purposes, parameters can be passed.
896
 *
897
 * @since 1.5
898
 * @param string $yourls_site   Optional, YOURLS installation URL (default to constant YOURLS_SITE)
899
 * @param string $uri           Optional, page requested (default to $_SERVER['REQUEST_URI'] eg '/yourls/abcd' )
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 112 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
900
 * @return string               request relative to YOURLS base (eg 'abdc')
901
 */
902
function yourls_get_request($yourls_site = false, $uri = false) {
903
    // Allow plugins to short-circuit the whole function
904 47
    $pre = yourls_apply_filter( 'shunt_get_request', false );
905 47
    if ( false !== $pre ) {
906
        return $pre;
907
    }
908
909 47
    yourls_do_action( 'pre_get_request', $yourls_site, $uri );
910
911
    // Default values
912 47
    if ( false === $yourls_site ) {
913
        $yourls_site = yourls_get_yourls_site();
914
    }
915 47
    if ( false === $uri ) {
916
        $uri = $_SERVER[ 'REQUEST_URI' ];
917
    }
918
919
    // Even though the config sample states YOURLS_SITE should be set without trailing slash...
920 47
    $yourls_site = rtrim( $yourls_site, '/' );
921
922
    // Now strip the YOURLS_SITE path part out of the requested URI, and get the request relative to YOURLS base
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 112 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
923
    // +---------------------------+-------------------------+---------------------+--------------+
924
    // |       if we request       | and YOURLS is hosted on | YOURLS path part is | "request" is |
925
    // +---------------------------+-------------------------+---------------------+--------------+
926
    // | http://sho.rt/abc         | http://sho.rt           | /                   | abc          |
927
    // | https://SHO.rt/subdir/abc | https://shor.rt/subdir/ | /subdir/            | abc          |
928
    // +---------------------------+-------------------------+---------------------+--------------+
929
    // and so on. You can find various test cases in /tests/tests/utilities/get_request.php
930
931
    // Take only the URL_PATH part of YOURLS_SITE (ie "https://sho.rt:1337/path/to/yourls" -> "/path/to/yourls")
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 112 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
932 47
    $yourls_site = parse_url( $yourls_site, PHP_URL_PATH ).'/';
933
934
    // Strip path part from request if exists
935 47
    $request = $uri;
936 47
    if ( substr( $uri, 0, strlen( $yourls_site ) ) == $yourls_site ) {
0 ignored issues
show
Coding Style introduced by
Operator == prohibited; use === instead
Loading history...
937 46
        $request = ltrim( substr( $uri, strlen( $yourls_site ) ), '/' );
938
    }
939
940
    // Unless request looks like a full URL (ie request is a simple keyword) strip query string
941 47
    if ( !preg_match( "@^[a-zA-Z]+://.+@", $request ) ) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal @^[a-zA-Z]+://.+@ does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
942 42
        $request = current( explode( '?', $request ) );
943
    }
944
945 47
    $request = yourls_sanitize_url( $request );
946
947 47
    return (string)yourls_apply_filter( 'get_request', $request );
948
}
949
950
/**
951
 * Fix $_SERVER['REQUEST_URI'] variable for various setups. Stolen from WP.
952
 *
953
 */
954
function yourls_fix_request_uri() {
955
956
    $default_server_values = [
957
        'SERVER_SOFTWARE' => '',
958
        'REQUEST_URI'     => '',
959
    ];
0 ignored issues
show
Coding Style introduced by
The closing parenthesis does not seem to be aligned correctly; expected 29 space(s), but found 4.
Loading history...
960
    $_SERVER = array_merge( $default_server_values, $_SERVER );
961
962
    // Fix for IIS when running with PHP ISAPI
963
    if ( empty( $_SERVER[ 'REQUEST_URI' ] ) || ( php_sapi_name() != 'cgi-fcgi' && preg_match( '/^Microsoft-IIS\//', $_SERVER[ 'SERVER_SOFTWARE' ] ) ) ) {
0 ignored issues
show
Coding Style introduced by
Operator != prohibited; use !== instead
Loading history...
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 153 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
964
965
        // IIS Mod-Rewrite
966
        if ( isset( $_SERVER[ 'HTTP_X_ORIGINAL_URL' ] ) ) {
967
            $_SERVER[ 'REQUEST_URI' ] = $_SERVER[ 'HTTP_X_ORIGINAL_URL' ];
968
        }
969
        // IIS Isapi_Rewrite
970
        elseif ( isset( $_SERVER[ 'HTTP_X_REWRITE_URL' ] ) ) {
971
            $_SERVER[ 'REQUEST_URI' ] = $_SERVER[ 'HTTP_X_REWRITE_URL' ];
972
        }
973
        else {
974
            // Use ORIG_PATH_INFO if there is no PATH_INFO
975
            if ( !isset( $_SERVER[ 'PATH_INFO' ] ) && isset( $_SERVER[ 'ORIG_PATH_INFO' ] ) ) {
976
                $_SERVER[ 'PATH_INFO' ] = $_SERVER[ 'ORIG_PATH_INFO' ];
977
            }
978
979
            // Some IIS + PHP configurations puts the script-name in the path-info (No need to append it twice)
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 111 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
980
            if ( isset( $_SERVER[ 'PATH_INFO' ] ) ) {
981
                if ( $_SERVER[ 'PATH_INFO' ] == $_SERVER[ 'SCRIPT_NAME' ] ) {
0 ignored issues
show
Coding Style introduced by
Operator == prohibited; use === instead
Loading history...
982
                    $_SERVER[ 'REQUEST_URI' ] = $_SERVER[ 'PATH_INFO' ];
983
                }
984
                else {
985
                    $_SERVER[ 'REQUEST_URI' ] = $_SERVER[ 'SCRIPT_NAME' ].$_SERVER[ 'PATH_INFO' ];
986
                }
987
            }
988
989
            // Append the query string if it exists and isn't null
990
            if ( !empty( $_SERVER[ 'QUERY_STRING' ] ) ) {
991
                $_SERVER[ 'REQUEST_URI' ] .= '?'.$_SERVER[ 'QUERY_STRING' ];
992
            }
993
        }
994
    }
995
}
996
997
/**
998
 * Check for maintenance mode. If yes, die. See yourls_maintenance_mode(). Stolen from WP.
999
 *
1000
 */
1001
function yourls_check_maintenance_mode() {
1002
1003
	$file = YOURLS_ABSPATH . '/.maintenance' ;
0 ignored issues
show
Coding Style introduced by
Space found before semicolon; expected "'/.maintenance';" but found "'/.maintenance' ;"
Loading history...
1004
	if ( !file_exists( $file ) || yourls_is_upgrading() || yourls_is_installing() )
1005
		return;
1006
1007
	global $maintenance_start;
1008
1009
	include_once( $file );
1010
	// If the $maintenance_start timestamp is older than 10 minutes, don't die.
1011
	if ( ( time() - $maintenance_start ) >= 600 )
1012
		return;
1013
1014
	// Use any /user/maintenance.php file
1015
	if( file_exists( YOURLS_USERDIR.'/maintenance.php' ) ) {
1016
		include_once( YOURLS_USERDIR.'/maintenance.php' );
1017
		die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
1018
	}
1019
1020
	// https://www.youtube.com/watch?v=Xw-m4jEY-Ns
1021
	$title   = yourls__( 'Service temporarily unavailable' );
1022
	$message = yourls__( 'Our service is currently undergoing scheduled maintenance.' ) . "</p>\n<p>" .
1023
	yourls__( 'Things should not last very long, thank you for your patience and please excuse the inconvenience' );
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 113 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1024
	yourls_die( $message, $title , 503 );
1025
1026
}
0 ignored issues
show
Coding Style introduced by
Function closing brace must go on the next line following the body; found 1 blank lines before brace
Loading history...
1027
1028
/**
1029
 * Return current admin page, or null if not an admin page
1030
 *
1031
 * @return mixed string if admin page, null if not an admin page
1032
 * @since 1.6
1033
 */
1034
function yourls_current_admin_page() {
1035
	if( yourls_is_admin() ) {
1036
		$current = substr( yourls_get_request(), 6 );
1037
		if( $current === false )
1038
			$current = 'index.php'; // if current page is http://sho.rt/admin/ instead of http://sho.rt/admin/index.php
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 110 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1039
1040
		return $current;
1041
	}
1042
	return null;
1043
}
1044
1045
/**
1046
 * Check if a URL protocol is allowed
1047
 *
1048
 * Checks a URL against a list of whitelisted protocols. Protocols must be defined with
1049
 * their complete scheme name, ie 'stuff:' or 'stuff://' (for instance, 'mailto:' is a valid
1050
 * protocol, 'mailto://' isn't, and 'http:' with no double slashed isn't either
1051
 *
1052
 * @since 1.6
1053
 * @see yourls_get_protocol()
1054
 *
1055
 * @param string $url URL to be check
1056
 * @param array $protocols Optional. Array of protocols, defaults to global $yourls_allowedprotocols
1057
 * @return bool true if protocol allowed, false otherwise
1058
 */
1059
function yourls_is_allowed_protocol( $url, $protocols = [] ) {
1060 90
    if ( empty( $protocols ) ) {
1061
        global $yourls_allowedprotocols;
1062
        $protocols = $yourls_allowedprotocols;
1063
    }
1064
1065 90
    return yourls_apply_filter( 'is_allowed_protocol', in_array( yourls_get_protocol( $url ), $protocols ), $url, $protocols );
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 127 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1066
}
1067
1068
/**
1069
 * Get protocol from a URL (eg mailto:, http:// ...)
1070
 *
1071
 * What we liberally call a "protocol" in YOURLS is the scheme name + colon + double slashes if present of a URI. Examples:
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 123 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1072
 * "something://blah" -> "something://"
1073
 * "something:blah"   -> "something:"
1074
 * "something:/blah"  -> "something:"
1075
 *
1076
 * Unit Tests for this function are located in tests/format/urls.php
1077
 *
1078
 * @since 1.6
1079
 *
1080
 * @param string $url URL to be check
1081
 * @return string Protocol, with slash slash if applicable. Empty string if no protocol
1082
 */
1083
function yourls_get_protocol( $url ) {
1084
	/*
1085
	http://en.wikipedia.org/wiki/URI_scheme#Generic_syntax
0 ignored issues
show
Coding Style introduced by
First line of comment not aligned correctly; expected 5 spaces but found 1
Loading history...
Coding Style introduced by
Block comments must start with a capital letter
Loading history...
1086
	The scheme name consists of a sequence of characters beginning with a letter and followed by any
0 ignored issues
show
Coding Style introduced by
Comment line indented incorrectly; expected at least 5 spaces but found 1
Loading history...
1087
	combination of letters, digits, plus ("+"), period ("."), or hyphen ("-"). Although schemes are
0 ignored issues
show
Coding Style introduced by
Comment line indented incorrectly; expected at least 5 spaces but found 1
Loading history...
1088
	case-insensitive, the canonical form is lowercase and documents that specify schemes must do so
0 ignored issues
show
Coding Style introduced by
Comment line indented incorrectly; expected at least 5 spaces but found 1
Loading history...
1089
	with lowercase letters. It is followed by a colon (":").
0 ignored issues
show
Coding Style introduced by
Comment line indented incorrectly; expected at least 5 spaces but found 1
Loading history...
1090
	*/
0 ignored issues
show
Coding Style introduced by
Empty line required after block comment
Loading history...
1091 182
    preg_match( '!^[a-zA-Z][a-zA-Z0-9+.-]+:(//)?!', $url, $matches );
1092 182
	return (string)yourls_apply_filter( 'get_protocol', isset( $matches[0] ) ? $matches[0] : '', $url );
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 101 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1093
}
1094
1095
/**
1096
 * Get relative URL (eg 'abc' from 'http://sho.rt/abc')
1097
 *
1098
 * Treat indifferently http & https. If a URL isn't relative to the YOURLS install, return it as is
1099
 * or return empty string if $strict is true
1100
 *
1101
 * @since 1.6
1102
 * @param string $url URL to relativize
1103
 * @param bool $strict if true and if URL isn't relative to YOURLS install, return empty string
1104
 * @return string URL
1105
 */
1106
function yourls_get_relative_url( $url, $strict = true ) {
1107 5
    $url = yourls_sanitize_url( $url );
1108
1109
    // Remove protocols to make it easier
1110 5
    $noproto_url = str_replace( 'https:', 'http:', $url );
1111 5
    $noproto_site = str_replace( 'https:', 'http:', yourls_get_yourls_site() );
1112
1113
    // Trim URL from YOURLS root URL : if no modification made, URL wasn't relative
1114 5
    $_url = str_replace( $noproto_site.'/', '', $noproto_url );
1115 5
    if ( $_url == $noproto_url ) {
0 ignored issues
show
Coding Style introduced by
Operator == prohibited; use === instead
Loading history...
1116 4
        $_url = ( $strict ? '' : $url );
1117
    }
1118 5
    return yourls_apply_filter( 'get_relative_url', $_url, $url );
1119
}
1120
1121
/**
1122
 * Marks a function as deprecated and informs when it has been used. Stolen from WP.
1123
 *
1124
 * There is a hook deprecated_function that will be called that can be used
1125
 * to get the backtrace up to what file and function called the deprecated
1126
 * function.
1127
 *
1128
 * The current behavior is to trigger a user error if YOURLS_DEBUG is true.
1129
 *
1130
 * This function is to be used in every function that is deprecated.
1131
 *
1132
 * @since 1.6
1133
 * @uses yourls_do_action() Calls 'deprecated_function' and passes the function name, what to use instead,
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 106 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1134
 *   and the version the function was deprecated in.
1135
 * @uses yourls_apply_filter() Calls 'deprecated_function_trigger_error' and expects boolean value of true to do
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 112 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1136
 *   trigger or false to not trigger error.
1137
 *
1138
 * @param string $function The function that was called
1139
 * @param string $version The version of WordPress that deprecated the function
1140
 * @param string $replacement Optional. The function that should have been called
1141
 */
1142
function yourls_deprecated_function( $function, $version, $replacement = null ) {
1143
1144
	yourls_do_action( 'deprecated_function', $function, $replacement, $version );
1145
1146
	// Allow plugin to filter the output error trigger
1147
	if ( yourls_get_debug_mode() && yourls_apply_filter( 'deprecated_function_trigger_error', true ) ) {
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 101 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1148
		if ( ! is_null( $replacement ) )
1149
			trigger_error( sprintf( yourls__('%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.'), $function, $version, $replacement ) );
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 152 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1150
		else
1151
			trigger_error( sprintf( yourls__('%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.'), $function, $version ) );
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 150 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1152
	}
1153
}
1154
1155
/**
1156
 * Return the value if not an empty string
1157
 *
1158
 * Used with array_filter(), to remove empty keys but not keys with value 0 or false
1159
 *
1160
 * @since 1.6
1161
 * @param mixed $val Value to test against ''
1162
 * @return bool True if not an empty string
1163
 */
1164
function yourls_return_if_not_empty_string( $val ) {
1165
    return ( $val !== '' );
1166
}
1167
1168
/**
1169
 * Explode a URL in an array of ( 'protocol' , 'slashes if any', 'rest of the URL' )
1170
 *
1171
 * Some hosts trip up when a query string contains 'http://' - see http://git.io/j1FlJg
1172
 * The idea is that instead of passing the whole URL to a bookmarklet, eg index.php?u=http://blah.com,
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 102 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1173
 * we pass it by pieces to fool the server, eg index.php?proto=http:&slashes=//&rest=blah.com
1174
 *
1175
 * Known limitation: this won't work if the rest of the URL itself contains 'http://', for example
1176
 * if rest = blah.com/file.php?url=http://foo.com
1177
 *
1178
 * Sample returns:
1179
 *
1180
 *   with 'mailto:[email protected]?subject=hey' :
1181
 *   array( 'protocol' => 'mailto:', 'slashes' => '', 'rest' => '[email protected]?subject=hey' )
1182
 *
1183
 *   with 'http://example.com/blah.html' :
1184
 *   array( 'protocol' => 'http:', 'slashes' => '//', 'rest' => 'example.com/blah.html' )
1185
 *
1186
 * @since 1.7
1187
 * @param string $url URL to be parsed
1188
 * @param array $array Optional, array of key names to be used in returned array
1189
 * @return array|false false if no protocol found, array of ('protocol' , 'slashes', 'rest') otherwise
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 102 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1190
 */
1191
function yourls_get_protocol_slashes_and_rest( $url, $array = [ 'protocol', 'slashes', 'rest' ] ) {
1192
    $proto = yourls_get_protocol( $url );
1193
1194
    if ( !$proto or count( $array ) != 3 ) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
Coding Style introduced by
Operator != prohibited; use !== instead
Loading history...
1195
        return false;
1196
    }
1197
1198
    list( $null, $rest ) = explode( $proto, $url, 2 );
1199
1200
    list( $proto, $slashes ) = explode( ':', $proto );
1201
1202
    return [
1203
        $array[ 0 ] => $proto.':',
1204
        $array[ 1 ] => $slashes,
1205
        $array[ 2 ] => $rest
0 ignored issues
show
Coding Style introduced by
Each line in an array declaration must end in a comma
Loading history...
1206
    ];
0 ignored issues
show
Coding Style introduced by
The closing parenthesis does not seem to be aligned correctly; expected 11 space(s), but found 4.
Loading history...
1207
}
1208
1209
/**
1210
 * Set URL scheme (to HTTP or HTTPS)
1211
 *
1212
 * @since 1.7.1
1213
 * @param string $url    URL
1214
 * @param string $scheme scheme, either 'http' or 'https'
1215
 * @return string URL with chosen scheme
1216
 */
1217
function yourls_set_url_scheme( $url, $scheme = false ) {
1218 10
    if ( in_array( $scheme, [ 'http', 'https' ] ) ) {
1219 10
        $url = preg_replace( '!^[a-zA-Z0-9+.-]+://!', $scheme.'://', $url );
0 ignored issues
show
Bug introduced by
Are you sure $scheme of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1219
        $url = preg_replace( '!^[a-zA-Z0-9+.-]+://!', /** @scrutinizer ignore-type */ $scheme.'://', $url );
Loading history...
1220
    }
1221 10
    return $url;
1222
}
1223
1224
/**
1225
 * Tell if there is a new YOURLS version
1226
 *
1227
 * This function checks, if needed, if there's a new version of YOURLS and, if applicable, display
1228
 * an update notice.
1229
 *
1230
 * @since 1.7.3
1231
 */
1232
function yourls_tell_if_new_version() {
1233
    yourls_debug_log( 'Check for new version: '.( yourls_maybe_check_core_version() ? 'yes' : 'no' ) );
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 100 characters; contains 103 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
1234
    yourls_new_core_version_notice();
1235
}
1236