Issues (2756)

admin/index.php (38 issues)

1
<?php
2
define( 'YOURLS_ADMIN', true );
3
require_once( dirname( __DIR__ ).'/includes/load-yourls.php' );
4
yourls_maybe_require_auth();
5
6
// Variables
7
$table_url = YOURLS_DB_TABLE_URL;
8
$search_sentence = $search_text = $url = $keyword = '';
9
/* $where will collect additional SQL arguments:
10
 * $where['sql'] will concatenate SQL clauses: $where['sql'] .= ' AND something = :value ';
11
 * $where['binds'] will hold the (name => value) placeholder pairs: $where['binds']['value'] = $value;
12
 */
13
$where = array('sql' => '', 'binds' => array());
14
$date_filter = $date_first  = $date_second = '';
15
$base_page   = yourls_admin_url( 'index.php' );
16
17
// Default SQL behavior
18
$search_in_text  = yourls__( 'URL' );
19
$search_in       = 'all';
20
$sort_by_text    = yourls__( 'Short URL' );
21
$sort_by         = 'timestamp';
22
$sort_order      = 'desc';
23
$page            = ( isset( $_GET['page'] ) ? intval($_GET['page']) : 1 );
24
$search          = yourls_get_search_text();
25
$perpage         = ( isset( $_GET['perpage'] ) && intval( $_GET['perpage'] ) ? intval($_GET['perpage']) : yourls_apply_filter( 'admin_view_per_page', 15 ) );
26
$click_limit     = ( isset( $_GET['click_limit'] ) && $_GET['click_limit'] !== '' ) ? intval( $_GET['click_limit'] ) : '' ;
27
if ( $click_limit !== '' ) {
28
	$click_filter   = ( isset( $_GET['click_filter'] ) && $_GET['click_filter'] == 'more' ? 'more' : 'less' ) ;
0 ignored issues
show
Operator == prohibited; use === instead
Loading history...
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...
Space found before semicolon; expected ");" but found ") ;"
Loading history...
29
	$click_moreless = ( $click_filter == 'more' ? '>' : '<' );
0 ignored issues
show
Operator == prohibited; use === instead
Loading history...
30
	$where['sql']   = " AND clicks $click_moreless :click_limit";
31
    $where['binds']['click_limit'] = $click_limit;
32
} else {
33
	$click_filter   = '';
34
}
35
36
// Searching
37
if( !empty( $search ) && !empty( $_GET['search_in'] ) ) {
38
	switch( $_GET['search_in'] ) {
39
		case 'all':
40
			$search_in_text = yourls__( 'All fields' );
41
			$search_in      = 'all';
42
			break;
43
		case 'keyword':
44
			$search_in_text = yourls__( 'Short URL' );
45
			$search_in      = 'keyword';
46
			break;
0 ignored issues
show
Case breaking statement indented incorrectly; expected 6 spaces, found 3
Loading history...
47
		case 'url':
48
			$search_in_text = yourls__( 'URL' );
49
			$search_in      = 'url';
50
			break;
0 ignored issues
show
Case breaking statement indented incorrectly; expected 6 spaces, found 3
Loading history...
51
		case 'title':
52
			$search_in_text = yourls__( 'Title' );
53
			$search_in      = 'title';
54
			break;
0 ignored issues
show
Case breaking statement indented incorrectly; expected 6 spaces, found 3
Loading history...
55
		case 'ip':
56
			$search_in_text = yourls__( 'IP Address' );
57
			$search_in      = 'ip';
58
			break;
0 ignored issues
show
Case breaking statement indented incorrectly; expected 6 spaces, found 3
Loading history...
59
	}
60
	$search_sentence = yourls_s( 'Searching for <strong>%1$s</strong> in <strong>%2$s</strong>.', yourls_esc_html( $search ), yourls_esc_html( $search_in_text ) );
0 ignored issues
show
This line exceeds maximum limit of 100 characters; contains 160 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...
61
	$search_text     = $search;
62
	$search          = str_replace( '*', '%', '*' . $search . '*' );
63
    if( $search_in == 'all' ) {
64
        $where['sql'] .= ' AND CONCAT_WS("",`keyword`,`url`,`title`,`ip`) LIKE (:search)';
65
        $where['binds']['search'] = $search;
66
        // Search across all fields. The resulting SQL will be something like:
67
        // SELECT * FROM `yourls_url` WHERE CONCAT_WS('',`keyword`,`url`,`title`,`ip`) LIKE ("%ozh%")
68
        // CONCAT_WS because CONCAT('foo', 'bar', NULL) = NULL. NULL wins. Not sure if values can be NULL now or in the future, so better safe.
69
        // TODO: pay attention to this bit when the DB schema changes
70
    } else {
71
        $where['sql'] .= " AND `$search_in` LIKE (:search)";
72
        $where['binds']['search'] = $search;
73
    }
74
}
75
76
// Time span
77
if( !empty( $_GET['date_filter'] ) ) {
78
	switch( $_GET['date_filter'] ) {
79
		case 'before':
80
			$date_filter = 'before';
81
			if( isset( $_GET['date_first'] ) && yourls_sanitize_date( $_GET['date_first'] ) ) {
82
				$date_first     = yourls_sanitize_date( $_GET['date_first'] );
83
				$date_first_sql = yourls_sanitize_date_for_sql( $_GET['date_first'] );
84
				$where['sql'] .= ' AND `timestamp` < :date_first_sql';
85
                $where['binds']['date_first_sql'] = $date_first_sql;
86
			}
87
			break;
0 ignored issues
show
Case breaking statement indented incorrectly; expected 6 spaces, found 3
Loading history...
88
		case 'after':
89
			$date_filter = 'after';
90
			if( isset( $_GET['date_first'] ) && yourls_sanitize_date( $_GET['date_first'] ) ) {
91
				$date_first_sql = yourls_sanitize_date_for_sql( $_GET['date_first'] );
92
				$date_first     = yourls_sanitize_date( $_GET['date_first'] );
93
				$where['sql'] .= ' AND `timestamp` > :date_first_sql';
94
                $where['binds']['date_first_sql'] = $date_first_sql;
95
			}
96
			break;
0 ignored issues
show
Case breaking statement indented incorrectly; expected 6 spaces, found 3
Loading history...
97
		case 'between':
98
			$date_filter = 'between';
99
			if( isset( $_GET['date_first'] ) && isset( $_GET['date_second'] ) && yourls_sanitize_date( $_GET['date_first'] ) && yourls_sanitize_date( $_GET['date_second'] ) ) {
0 ignored issues
show
This line exceeds maximum limit of 100 characters; contains 167 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
				$date_first_sql  = yourls_sanitize_date_for_sql( $_GET['date_first'] );
101
				$date_second_sql = yourls_sanitize_date_for_sql( $_GET['date_second'] );
102
				$date_first      = yourls_sanitize_date( $_GET['date_first'] );
103
				$date_second     = yourls_sanitize_date( $_GET['date_second'] );
104
				$where['sql'] .= ' AND `timestamp` BETWEEN :date_first_sql AND :date_second_sql';
105
                $where['binds']['date_first_sql']  = $date_first_sql;
106
                $where['binds']['date_second_sql'] = $date_second_sql;
107
			}
108
			break;
0 ignored issues
show
Case breaking statement indented incorrectly; expected 6 spaces, found 3
Loading history...
109
	}
110
}
111
112
// Sorting
113
if( !empty( $_GET['sort_by'] ) || !empty( $_GET['sort_order'] ) ) {
114
	switch( $_GET['sort_by'] ) {
115
		case 'keyword':
116
			$sort_by_text = yourls__( 'Short URL' );
117
			$sort_by      = 'keyword';
118
			break;
0 ignored issues
show
Case breaking statement indented incorrectly; expected 6 spaces, found 3
Loading history...
119
		case 'url':
120
			$sort_by_text = yourls__( 'URL' );
121
			$sort_by      = 'url';
122
			break;
0 ignored issues
show
Case breaking statement indented incorrectly; expected 6 spaces, found 3
Loading history...
123
		case 'title':
124
			$sort_by_text = yourls__( 'Title' );
125
			$sort_by      = 'title';
126
			break;
127
		case 'timestamp':
128
			$sort_by_text = yourls__( 'Date' );
129
			$sort_by      = 'timestamp';
130
			break;
0 ignored issues
show
Case breaking statement indented incorrectly; expected 6 spaces, found 3
Loading history...
131
		case 'ip':
132
			$sort_by_text = yourls__( 'IP Address' );
133
			$sort_by      = 'ip';
134
			break;
0 ignored issues
show
Case breaking statement indented incorrectly; expected 6 spaces, found 3
Loading history...
135
		case 'clicks':
136
			$sort_by_text = yourls__( 'Clicks' );
137
			$sort_by      = 'clicks';
138
			break;
0 ignored issues
show
Case breaking statement indented incorrectly; expected 6 spaces, found 3
Loading history...
139
	}
140
	switch( $_GET['sort_order'] ) {
141
		case 'asc':
142
			$sort_order      = 'asc';
143
			break;
0 ignored issues
show
Case breaking statement indented incorrectly; expected 6 spaces, found 3
Loading history...
144
		case 'desc':
145
			$sort_order      = 'desc';
146
			break;
0 ignored issues
show
Case breaking statement indented incorrectly; expected 6 spaces, found 3
Loading history...
147
	}
148
}
149
150
// Get URLs Count for current filter, total links in DB & total clicks
151
list( $total_urls, $total_clicks ) = array_values( yourls_get_db_stats() );
152
if ( !empty($where['sql']) ) {
153
	list( $total_items, $total_items_clicks ) = array_values( yourls_get_db_stats( $where ) );
154
} else {
155
	$total_items        = $total_urls;
156
	$total_items_clicks = false;
157
}
158
159
// This is a bookmarklet
160
if ( isset( $_GET['u'] ) or isset( $_GET['up'] ) ) {
161
	$is_bookmark = true;
162
	yourls_do_action( 'bookmarklet' );
163
164
	// No sanitization needed here: everything happens in yourls_add_new_link()
165
	if( isset( $_GET['u'] ) ) {
166
		// Old school bookmarklet: ?u=<url>
167
		$url = urldecode( $_GET['u'] );
168
	} else {
169
		// New style bookmarklet: ?up=<url protocol>&us=<url slashes>&ur=<url rest>
170
		$url = urldecode( $_GET['up'] . $_GET['us'] . $_GET['ur'] );
171
	}
172
	$keyword = ( isset( $_GET['k'] ) ? ( $_GET['k'] ) : '' );
173
	$title   = ( isset( $_GET['t'] ) ? ( $_GET['t'] ) : '' );
174
	$return  = yourls_add_new_link( $url, $keyword, $title );
175
176
	// If fails because keyword already exist, retry with no keyword
177
	if ( isset( $return['status'] ) && $return['status'] == 'fail' && isset( $return['code'] ) && $return['code'] == 'error:keyword' ) {
0 ignored issues
show
Operator == prohibited; use === instead
Loading history...
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...
178
		$msg = $return['message'];
179
		$return = yourls_add_new_link( $url, '' );
180
		$return['message'] .= ' ('.$msg.')';
181
	}
182
183
	// Stop here if bookmarklet with a JSON callback function
184
	if( isset( $_GET['jsonp'] ) && $_GET['jsonp'] == 'yourls' ) {
0 ignored issues
show
Operator == prohibited; use === instead
Loading history...
185
		$short   = $return['shorturl'] ? $return['shorturl'] : '';
186
		$message = $return['message'];
187
		yourls_content_type_header( 'application/javascript' );
188
		echo yourls_apply_filter( 'bookmarklet_jsonp', "yourls_callback({'short_url':'$short','message':'$message'});" );
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $short 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 $message 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...
This line exceeds maximum limit of 100 characters; contains 115 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...
189
190
		die();
191
	}
192
193
	// Now use the URL that has been sanitized and returned by yourls_add_new_link()
194
	$url = $return['url']['url'];
195
	$where['sql'] .= ' AND `url` LIKE :url ';
196
    $where['binds']['url'] = $url;
197
198
	$page   = $total_pages = $perpage = 1;
199
	$offset = 0;
200
201
	$text   = ( isset( $_GET['s'] ) ? stripslashes( $_GET['s'] ) : '' );
202
203
	// Sharing with social bookmarklets
204
	if( !empty($_GET['share']) ) {
205
		yourls_do_action( 'pre_share_redirect' );
206
		switch ( $_GET['share'] ) {
207
			case 'twitter':
208
				// share with Twitter
209
				$destination = sprintf( "https://twitter.com/intent/tweet?url=%s&text=%s", urlencode( $return['shorturl'] ), urlencode( $title ) );
210
				yourls_redirect( $destination, 303 );
211
212
				// Deal with the case when redirection failed:
213
				$return['status']    = 'error';
214
				$return['errorCode'] = 400;
215
				$return['message']   = yourls_s( 'Short URL created, but could not redirect to %s !', 'Twitter' );
216
				break;
217
218
			case 'facebook':
219
				// share with Facebook
220
				$destination = sprintf( "https://www.facebook.com/sharer/sharer.php?u=%s&t=%s", urlencode( $return['shorturl'] ), urlencode( $title ) );
221
				yourls_redirect( $destination, 303 );
222
223
				// Deal with the case when redirection failed:
224
				$return['status']    = 'error';
225
				$return['errorCode'] = 400;
226
				$return['message']   = yourls_s( 'Short URL created, but could not redirect to %s !', 'Facebook' );
227
				break;
228
229
			case 'tumblr':
230
				// share with Tumblr
231
				$destination = sprintf( "https://www.tumblr.com/share?v=3&u=%s&t=%s&s=%s", urlencode( $return['shorturl'] ), urlencode( $title ), urlencode( $text ) );
232
				yourls_redirect( $destination, 303 );
233
234
				// Deal with the case when redirection failed:
235
				$return['status']    = 'error';
236
				$return['errorCode'] = 400;
237
				$return['message']   = yourls_s( 'Short URL created, but could not redirect to %s !', 'Tumblr' );
238
				break;
239
240
			default:
241
				// Is there a custom registered social bookmark?
242
				yourls_do_action( 'share_redirect_' . $_GET['share'], $return );
243
244
				// Still here? That was an unknown 'share' method, then.
245
				$return['status']    = 'error';
246
				$return['errorCode'] = 400;
247
				$return['message']   = yourls__( 'Unknown "Share" bookmarklet' );
248
				break;
249
		}
250
	}
251
252
// This is not a bookmarklet
253
} else {
254
	$is_bookmark = false;
255
256
	// Checking $page, $offset, $perpage
0 ignored issues
show
Unused Code Comprehensibility introduced by
56% 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...
257
	if( empty($page) || $page == 0 ) {
0 ignored issues
show
Operator == prohibited; use === instead
Loading history...
258
		$page = 1;
259
	}
260
	if( empty($offset) ) {
261
		$offset = 0;
262
	}
263
	if( empty($perpage) || $perpage == 0) {
0 ignored issues
show
Operator == prohibited; use === instead
Loading history...
264
		$perpage = 50;
265
	}
266
267
	// Determine $offset
268
	$offset = ( $page-1 ) * $perpage;
269
270
	// Determine Max Number Of Items To Display On Page
271
	if( ( $offset + $perpage ) > $total_items ) {
272
		$max_on_page = $total_items;
273
	} else {
274
		$max_on_page = ( $offset + $perpage );
275
	}
276
277
	// Determine Number Of Items To Display On Page
278
	if ( ( $offset + 1 ) > $total_items ) {
279
		$display_on_page = $total_items;
280
	} else {
281
		$display_on_page = ( $offset + 1 );
282
	}
283
284
	// Determing Total Amount Of Pages
285
	$total_pages = ceil( $total_items / $perpage );
286
}
287
288
289
// Begin output of the page
290
$context = ( $is_bookmark ? 'bookmark' : 'index' );
291
yourls_html_head( $context );
292
yourls_html_logo();
293
yourls_html_menu() ;
0 ignored issues
show
Space found before semicolon; expected ");" but found ") ;"
Loading history...
294
295
yourls_do_action( 'admin_page_before_content' );
296
297
if ( !$is_bookmark ) { ?>
298
	<p><?php echo $search_sentence; ?></p>
299
	<p><?php
0 ignored issues
show
Opening PHP tag must be on a line by itself
Loading history...
300
		printf( yourls__( 'Display <strong>%1$s</strong> to <strong class="increment">%2$s</strong> of <strong class="increment">%3$s</strong> URLs' ), $display_on_page, $max_on_page, $total_items );
0 ignored issues
show
First line of embedded PHP code must be indented 1 spaces; 2 found
Loading history...
This line exceeds maximum limit of 100 characters; contains 193 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...
301
		if( $total_items_clicks !== false )
302
			echo ", " . sprintf( yourls_n( 'counting <strong>1</strong> click', 'counting <strong>%s</strong> clicks', $total_items_clicks ), yourls_number_format_i18n( $total_items_clicks ) );
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal , 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...
This line exceeds maximum limit of 100 characters; contains 184 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...
303
	?>.</p>
304
<?php } ?>
305
<p id="overall_tracking"><?php printf( yourls__( 'Overall, tracking <strong class="increment">%1$s</strong> links, <strong>%2$s</strong> clicks, and counting!' ), yourls_number_format_i18n( $total_urls ), yourls_number_format_i18n( $total_clicks ) ); ?></p>
306
<?php
307
0 ignored issues
show
Blank line found at start of embedded PHP content
Loading history...
308
yourls_do_action( 'admin_page_before_form' );
309
310
yourls_html_addnew();
311
312
// If bookmarklet, add message. Otherwise, hide hidden share box.
313
if ( !$is_bookmark ) {
314
	yourls_share_box( '', '', '', '', '', '', true );
315
} else {
316
	echo '<script type="text/javascript">$(document).ready(function(){
317
		feedback( "' . $return['message'] . '", "'. $return['status'] .'");
318
		init_clipboard();
319
	});</script>';
320
}
321
322
yourls_do_action( 'admin_page_before_table' );
323
324
yourls_table_head();
325
326
if ( !$is_bookmark ) {
327
	$params = array(
328
		'search'       => $search,
329
		'search_text'  => $search_text,
330
		'search_in'    => $search_in,
331
		'sort_by'      => $sort_by,
332
		'sort_order'   => $sort_order,
333
		'page'         => $page,
334
		'perpage'      => $perpage,
335
		'click_filter' => $click_filter,
336
		'click_limit'  => $click_limit,
337
		'total_pages'  => $total_pages,
338
		'date_filter'  => $date_filter,
339
		'date_first'   => $date_first,
340
		'date_second'  => $date_second,
341
	);
0 ignored issues
show
The closing parenthesis does not seem to be aligned correctly; expected 11 space(s), but found 1.
Loading history...
342
	yourls_html_tfooter( $params );
343
}
344
345
yourls_table_tbody_start();
346
347
// Main Query
348
$where = yourls_apply_filter( 'admin_list_where', $where );
349
$url_results = $ydb->fetchObjects( "SELECT * FROM `$table_url` WHERE 1=1 ${where['sql']} ORDER BY `$sort_by` $sort_order LIMIT $offset, $perpage;", $where['binds'] );
350
$found_rows = false;
351
if( $url_results ) {
352
	$found_rows = true;
353
	foreach( $url_results as $url_result ) {
354
		$keyword = yourls_sanitize_keyword($url_result->keyword);
355
		$timestamp = strtotime( $url_result->timestamp );
356
		$url = stripslashes( $url_result->url );
357
		$ip = $url_result->ip;
358
		$title = $url_result->title ? $url_result->title : '';
359
		$clicks = $url_result->clicks;
360
361
		echo yourls_table_add_row( $keyword, $url, $title, $ip, $clicks, $timestamp );
362
	}
363
}
364
365
$display = $found_rows ? 'display:none' : '';
366
echo '<tr id="nourl_found" style="'.$display.'"><td colspan="6">' . yourls__('No URL') . '</td></tr>';
0 ignored issues
show
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...
367
368
yourls_table_tbody_end();
369
370
yourls_table_end();
371
372
yourls_do_action( 'admin_page_after_table' );
373
374
if ( $is_bookmark )
375
	yourls_share_box( $url, $return['shorturl'], $title, $text );
376
?>
377
378
<?php yourls_html_footer( ); ?>
379