Issues (85)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Pagination.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * @package    Fuel\Common
4
 * @version    2.0
5
 * @author     Fuel Development Team
6
 * @license    MIT License
7
 * @copyright  2010 - 2015 Fuel Development Team
8
 * @link       http://fuelphp.com
9
 */
10
11
namespace Fuel\Common;
12
13
/**
14
 * @since 1.0
15
 */
16
class Pagination
17
{
18
	/**
19
	 * @var  Fuel\Foundation\Input  current input instance
20
	 */
21
	protected $input;
22
23
	/**
24
	 * @var  Fuel\Display\View  pagination view
25
	 */
26
	protected $view;
27
28
	/**
29
	 * @var  array  configuration values
30
	 */
31
	protected $config = array(
32
		'current'        => 0,
33
		'offset'         => 0,
34
		'limit'          => 0,
35
		'totalPages'     => 0,
36
		'totalItems'     => 0,
37
		'numberOfLinks'  => 3,
38
		'uriSegment'     => 3,
39
		'getVariable'    => '',
40
		'showFirst'      => false,
41
		'showLast'       => false,
42
		'linkOffset'     => 0.5,
43
		'align'          => 'center',
44
	);
45
46
	/**
47
	 * @var  string  the pagination Url template. Use {page} for the location of the page number
48
	 */
49
	protected $paginationUrl = null;
50
51
	/**
52
	 * Construct a pagination object
53
	 *
54
	 * @param  Fuel\Display\Manager  The current applications ViewManager object
55
	 * @param  Fuel\Foundation\Input  The current requests Input container
56
	 * @param  string  View to be used to generate the pagination HTML
57
	 *
58
	 */
59
	public function __construct($viewmanager, $input, $view)
60
	{
61
		// store the input instance passed
62
		$this->input = $input;
63
64
		// construct the pagination view
65
		$this->view = $viewmanager->forge($view);
66
	}
67
68
	/**
69
	 * Render the pagination view when the object is cast to string or echo'd
70
	 */
71
	public function __toString()
72
	{
73
		return (string) $this->render();
74
	}
75
76
	/**
77
	 * Getter for configuration items
78
	 */
79
	public function __get($key)
80
	{
81
		return $this->get($key);
82
	}
83
84
	/**
85
	 * Getter for configuration items
86
	 */
87
	public function get($key)
88
	{
89
		if (isset($this->config[$key]))
90
		{
91
			return $this->config[$key];
92
		}
93
	}
94
95
	/**
96
	 * Setter for configuration items
97
	 */
98
	public function __set($key, $value)
99
	{
100
		$this->set($key, $value);
101
	}
102
103
	/**
104
	 * Setter for configuration items
105
	 */
106
	public function set($var, $value = null)
107
	{
108
		if ( ! is_array($var))
109
		{
110
			$var = array ($var => $value);
111
		}
112
113
		foreach ($var as $key => $value)
114
		{
115
			$value = $this->validateConfig($key, $value);
116
117
			if (isset($this->config[$key]))
118
			{
119
				// preserve the type
120
				if (is_bool($this->config[$key]))
121
				{
122
					$this->config[$key] = (bool) $value;
123
				}
124
				elseif (is_string($this->config[$key]))
125
				{
126
					$this->config[$key] = (string) $value;
127
				}
128
				else
129
				{
130
					$this->config[$key] = (int) $value;
131
				}
132
			}
133
		}
134
	}
135
136
	/**
137
	 * Setter for the pagination url. It must contain a {page} placeholder for the page number
138
	 *
139
	 * @param  string  $url  The pagination Url template to be used to generate link urls
140
	 */
141
	public function setUrl($url)
142
	{
143
		$this->paginationUrl = $url;
144
	}
145
146
	/**
147
	 * Render the pagination view, and return the view
148
	 *
149
	 * @return  View  the configured view object
150
	 */
151
	public function render()
152
	{
153
		// make sure we have a correct url
154
		$this->paginationUrl();
155
156
		// and a current page number
157
		$this->calculateNumbers();
158
159
		$urls = array();
160
161
		// generate the URL's for the pagination block
162
		if ($this->config['totalPages'] > 1)
163
		{
164
			// calculate start- and end page numbers
165
			$start = $this->config['current'] - floor($this->config['numberOfLinks'] * $this->config['linkOffset']);
166
			$end = $this->config['current'] + floor($this->config['numberOfLinks'] * ( 1 - $this->config['linkOffset']));
167
168
			// adjust for the first few pages
169
			if ($start < 1)
170
			{
171
				$end -= $start - 1;
172
				$start = 1;
173
			}
174
175
			// make sure we don't overshoot the current page due to rounding issues
176
			if ($end < $this->config['current'])
177
			{
178
				$start++;
179
				$end++;
180
			}
181
182
			// make sure we don't overshoot the total
183
			if ($end > $this->config['totalPages'])
184
			{
185
				$start = max(1, $start - $end + $this->config['totalPages']);
186
				$end = $this->config['totalPages'];
187
			}
188
189
			// now generate the URL's for the pagination block
190
			for($i = $start; $i <= $end; $i++)
191
			{
192
				$urls[$i] = $this->generateUrl($i);
193
			}
194
		}
195
196
		// send the generated url's to the view
197
		$this->view->set('urls', $urls);
198
199
		// store the current and total pages
200
		$this->view->set('active', $this->config['current']);
201
		$this->view->set('total', $this->config['totalPages']);
202
203
		// do we need to add a first link?
204
		if ($this->config['showFirst'])
205
		{
206
			$this->view->set('first', $this->generateUrl(1));
207
		}
208
209
		if (isset($start) and $start > 1)
210
		{
211
			$this->view->set('previous', $this->generateUrl($start-1));
212
		}
213
214
		if (isset($end) and $end !== $this->config['totalPages'])
215
		{
216
			$this->view->set('next', $this->generateUrl($end+1));
217
		}
218
219
		// do we need to add a last link?
220
		if ($this->config['showLast'])
221
		{
222
			$this->view->set('last', $this->generateUrl($this->config['totalPages']));
223
		}
224
225
		$this->view->set('align', $this->config['align']);
226
227
		// return the view
228
		return $this->view;
229
	}
230
231
	/**
232
	 * Generate the link to a particular page
233
	 *
234
	 * @param  int  $link  page number
235
	 *
236
	 * @return  string  generated link to a page
237
	 */
238
	protected function generateUrl($link)
239
	{
240
		return str_replace('{page}', $link, $this->paginationUrl);
241
	}
242
243
	/**
244
	 * Construct the pagination Url from the current Url and the configuration set
245
	 */
246
	protected function paginationUrl()
247
	{
248
		// if we have one, don't bother
249
		if ( ! empty($this->paginationUrl))
250
		{
251
			return;
252
		}
253
254
		// do we have any GET variables?
255
		$get = $this->input->getQuery();
256
257
		// do we need to set one
258
		if ( ! empty($this->config['getVariable']))
259
		{
260
			// don't use curly braces here, http_build_query will encode them
261
			$get[$this->config['getVariable']] = '___PAGE___';
262
		}
263
264
		// do we need to create a segment?
265
		if ( ! empty($this->config['uriSegment']))
266
		{
267
			$segments = explode('/', trim($this->input->getPathInfo(),'/'));
268
			$segments[$this->config['uriSegment']] = '{page}';
269
270
			// construct the Uri
271
			$this->paginationUrl = '/'.implode('/', $segments);
272
		}
273
		else
274
		{
275
			// start with the current Uri
276
			$this->paginationUrl = $this->input->getPathInfo();
277
		}
278
279
		// attach the extension if needed
280
		$this->paginationUrl .= $this->input->getExtension();
281
282
		// any get variables?
283
		if ( ! empty($get))
284
		{
285
			$this->paginationUrl .= '?'.str_replace('___PAGE___', '{page}', http_build_query($get->getContents()));
286
		}
287
	}
288
289
	/**
290
	 * If no current page number is given, calculate it
291
	 */
292
	protected function calculateNumbers()
293
	{
294
		// do we need to fetch or calculate the current page number?
295
		if (empty($this->config['current']))
296
		{
297
			// do we have a segment number?
298
			if ( ! empty($this->config['uriSegment']))
299
			{
300
				$segments = explode('/', trim($this->input->getPathInfo(),'/'));
301 View Code Duplication
				if (isset($segments[$this->config['uriSegment']]) and is_numeric($segments[$this->config['uriSegment']]))
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
302
				{
303
					$this->config['current'] = $segments[$this->config['uriSegment']];
304
				}
305
			}
306
307
			// do we have a getVariable set?
308
			if ( ! empty($this->config['getVariable']) and $get = $this->input->getQuery())
309
			{
310 View Code Duplication
				if (isset($get[$this->config['getVariable']]) and is_numeric($get[$this->config['getVariable']]))
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
311
				{
312
					$this->config['current'] = $get[$this->config['uriSegment']];
313
				}
314
			}
315
316
			// if none could be determine, try to calculate it
317 View Code Duplication
			if (empty($this->config['current']) and $this->config['offset'] and $this->config['limit'])
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
318
			{
319
				$this->config['current'] = (int) ($this->config['offset'] / $this->config['limit']) + 1;
320
			}
321
322
			// if all else fails, default to one
323
			if (empty($this->config['current']))
324
			{
325
				$this->config['current'] = 1;
326
			}
327
		}
328
329
		// do we need to calculate the total number of pages
330 View Code Duplication
		if (empty($this->config['totalPages']) and ! empty($this->config['totalItems']) and ! empty($this->config['limit']))
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
331
		{
332
			$this->config['totalPages'] = (int) ($this->config['totalItems'] / $this->config['limit']) + 1;
333
		}
334
	}
335
336
	/**
337
	 * Generate a pagination link
338
	 */
339
	protected function validateConfig($name, $value)
340
	{
341
		switch ($name)
342
		{
343
			case 'offset':
344
			case 'totalItems':
345
				// make sure it's an integer
346
				if ($value != intval($value))
347
				{
348
					$value = 0;
349
				}
350
				// and that it's within bounds
351
				$value = max(0, $value);
352
			break;
353
354
			// validate integer values
355
			case 'current':
356
			case 'limit':
357
			case 'totalPages':
358
			case 'numberOfLinks':
359
			case 'uriSegment':
360
				// make sure it's an integer
361
				if ($value != intval($value))
362
				{
363
					$value = 1;
364
				}
365
				// and that it's within bounds
366
				$value = max(1, $value);
367
			break;
368
369
			// validate booleans
370
			case 'showFirst':
371
			case 'showLast':
372
				if ( ! is_bool($value))
373
				{
374
					$value = (bool) $value;
375
				}
376
			break;
377
378
			// possible alignment values
379
			case 'align':
380
				if ( ! in_array($value = strtolower($value), array('left', 'center', 'right')))
381
				{
382
					$value = 'center';
383
				}
384
			break;
385
386
			// validate the link offset, and adjust if needed
387
			case 'linkOffset':
388
				// make sure we have a fraction between 0 and 1
389
				if ($value > 1)
390
				{
391
					$value = $value / 100;
392
				}
393
394
				// and that it's within bounds
395
				$value = max(0.01, min($value, 0.99));
396
			break;
397
		}
398
399
		return $value;
400
	}
401
}
402