Issues (166)

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.

formats/jqplot/SRF_jqPlotSeries.php (1 issue)

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
/**
4
 * A query printer for charts series using the jqPlot JavaScript library.
5
 *
6
 * @since 1.8
7
 * @licence GNU GPL v2 or later
8
 *
9
 * @author mwjames
10
 */
11
class SRFjqPlotSeries extends SMWResultPrinter {
12
13
	/**
14
	 * @see SMWResultPrinter::getName
15
	 */
16
	public function getName() {
17
		return wfMessage( 'srf-printername-jqplotseries' )->text();
18
	}
19
20
	/**
21
	 * Returns an array with the numerical data in the query result.
22
	 *
23
	 *
24
	 * @param SMWQueryResult $result
25
	 * @param $outputMode
26
	 *
27
	 * @return string
28
	 */
29
	protected function getResultText( SMWQueryResult $result, $outputMode ) {
30
31
		// Get data set
32
		$data = $this->getResultData( $result, $outputMode );
33
34
		// Check data availability
35
		if ( $data['series'] === [] ) {
36
			return $result->addErrors(
37
				[
38
					wfMessage( 'srf-warn-empy-chart' )
39
						->inContentLanguage()->text() ]
40
			);
41
		} else {
42
			$options['sask'] = SRFUtils::htmlQueryResultLink( $this->getLink( $result, SMW_OUTPUT_HTML ) );
43
			return $this->getFormatOutput( $this->getFormatSettings( $this->getNumbersTicks( $data ), $options ) );
44
		}
45
	}
46
47
	/**
48
	 * Returns an array with the numerical data
49
	 *
50
	 * @since 1.8
51
	 *
52
	 * @param SMWQueryResult $result
53
	 * @param $outputMode
54
	 *
55
	 * @return array
56
	 */
57
	protected function getResultData( SMWQueryResult $res, $outputMode ) {
58
		$data = [];
59
		$data['series'] = [];
60
61
		while ( $row = $res->getNext() ) {
62
			// Loop over their fields (properties)
63
			$label = '';
64
			$i = 0;
65
66
			foreach ( $row as /* SMWResultArray */
67
					  $field ) {
68
				$i++;
69
				$rowNumbers = [];
70
71
				// Grouping by subject (page object) or property
72
				if ( $this->params['group'] === 'subject' ) {
73
					$groupedBy = $field->getResultSubject()->getTitle()->getText();
74
				} else {
75
					$groupedBy = $field->getPrintRequest()->getLabel();
76
				}
77
78
				// Property label
79
				$property = $field->getPrintRequest()->getLabel();
80
81
				// First column property typeid
82
				$i == 1 ? $data['fcolumntypeid'] = $field->getPrintRequest()->getTypeID() : '';
83
84
				// Loop over all values for the property.
85
				while ( ( /* SMWDataValue */
86
					$object = $field->getNextDataValue() ) !== false ) {
87
88
					if ( $object->getDataItem()->getDIType() == SMWDataItem::TYPE_NUMBER ) {
89
						$number = $object->getNumber();
90
91
						// Checking against the row and in case the first column is a numeric
92
						// value it is handled as label with the remaining steps continue to work
93
						// as it were a text label
94
						// The first column container will not be part of the series container
95
						if ( $i == 1 ) {
96
							$label = $number;
97
							continue;
98
						}
99
100
						if ( $label !== '' && $number >= $this->params['min'] ) {
101
102
							// Reference array summarize all items per row
103
							$rowNumbers += [ 'subject' => $label, 'value' => $number, 'property' => $property ];
104
105
							// Store plain numbers for simpler handling
106
							$data['series'][$groupedBy][] = $number;
107
						}
108
					} elseif ( $object->getDataItem()->getDIType() == SMWDataItem::TYPE_TIME ) {
109
						$label = $object->getShortWikiText();
110
					} else {
111
						$label = $object->getWikiValue();
112
					}
113
				}
114
				// Only for array's with numbers
115
				if ( count( $rowNumbers ) > 0 ) {
116
117
					// For cases where mainlabel=- we assume that the subject should not be
118
					// used as identifier and therefore we try to match the groupby
119
					// with the first available text label
120
					if ( $this->params['mainlabel'] == '-' && $this->params['group'] === 'subject' ) {
121
						$data[$this->params['group']][$label][] = $rowNumbers;
122
					} else {
123
						$data[$this->params['group']][$groupedBy][] = $rowNumbers;
124
					}
125
				}
126
			}
127
		}
128
		return $data;
129
	}
130
131
	/**
132
	 * Data set sorting
133
	 *
134
	 * @since 1.8
135
	 *
136
	 * @param array $data label => value
137
	 *
138
	 * @return array
139
	 */
140
	private function getFormatSettings( $data, $options ) {
141
142
		// Init
143
		$dataSet = [];
144
		$options['mode'] = 'series';
145
		$options['autoscale'] = false;
146
147
		// Available markers
148
		$marker = [ 'circle', 'diamond', 'square', 'filledCircle', 'filledDiamond', 'filledSquare' ];
149
150
		// Series colour(has to be null otherwise jqplot runs with a type error)
151
		$seriescolors = $this->params['chartcolor'] !== '' ? array_filter(
152
			explode( ",", $this->params['chartcolor'] )
153
		) : null;
154
155
		// Re-grouping
156
		foreach ( $data[$this->params['group']] as $rowKey => $row ) {
157
			$values = [];
158
159
			foreach ( $row as $key => $value ) {
160
				// Switch labels according to the group parameter
161
				$label = $this->params['grouplabel'] === 'property' ? $value['property'] : $value['subject'];
162
				$values[] = [ $label, $value['value'] ];
163
			}
164
			$dataSet[] = $values;
165
		}
166
167
		// Series plotting parameters
168
		foreach ( $data[$this->params['group']] as $key => $row ) {
169
			$series[] = [
170
				'label' => $key,
171
				'xaxis' => 'xaxis', // xaxis could also be xaxis2 or ...
172
				'yaxis' => 'yaxis',
173
				'fill' => $this->params['stackseries'],
174
				'showLine' => $this->params['charttype'] !== 'scatter',
175
				'showMarker' => true,
176
				'trendline' => [
177
					'show' => in_array( $this->params['trendline'], [ 'exp', 'linear' ] ),
178
					'shadow' => $this->params['theme'] !== 'simple',
179
					'type' => $this->params['trendline'],
180
				],
181
				'markerOptions' => [
182
					'style' => $marker[array_rand( $marker )],
183
					'shadow' => $this->params['theme'] !== 'simple'
184
				],
185
				'rendererOptions' => [ 'barDirection' => $this->params['direction'] ]
186
			];
187
		};
188
189
		// Basic parameters
190
		$parameters = [
191
			'numbersaxislabel' => $this->params['numbersaxislabel'],
192
			'labelaxislabel' => $this->params['labelaxislabel'],
193
			'charttitle' => $this->params['charttitle'],
194
			'charttext' => $this->params['charttext'],
195
			'infotext' => $this->params['infotext'],
196
			'theme' => $this->params['theme'] ? $this->params['theme'] : null,
197
			'valueformat' => $this->params['datalabels'] === 'label' ? '' : $this->params['valueformat'],
198
			'ticklabels' => $this->params['ticklabels'],
199
			'highlighter' => $this->params['highlighter'],
200
			'autoscale' => $options['autoscale'],
201
			'gridview' => $this->params['gridview'],
202
			'direction' => $this->params['direction'],
203
			'smoothlines' => $this->params['smoothlines'],
204
			'cursor' => $this->params['cursor'],
205
			'chartlegend' => $this->params['chartlegend'] !== '' ? $this->params['chartlegend'] : 'none',
206
			'colorscheme' => $this->params['colorscheme'] !== '' ? $this->params['colorscheme'] : null,
207
			'pointlabels' => $this->params['datalabels'] === 'none' ? false : $this->params['datalabels'],
208
			'datalabels' => $this->params['datalabels'],
209
			'stackseries' => $this->params['stackseries'],
210
			'grid' => $this->params['theme'] === 'vector' ? [ 'borderColor' => '#a7d7f9' ] : ( $this->params['theme'] === 'simple' ? [ 'borderColor' => '#ddd' ] : null ),
211
			'seriescolors' => $seriescolors,
212
			'hideZeroes' => $this->params['hidezeroes']
213
		];
214
215
		return [
216
			'data' => $dataSet,
217
			//'rawdata'      => $data , // control array
218
			'series' => $series,
0 ignored issues
show
The variable $series does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
219
			'ticks' => $data['numbersticks'],
220
			'total' => $data['total'],
221
			'fcolumntypeid' => $data['fcolumntypeid'],
222
			'sask' => $options['sask'],
223
			'mode' => $options['mode'],
224
			'renderer' => $this->params['charttype'],
225
			'parameters' => $parameters
226
		];
227
	}
228
229
	/**
230
	 * Fetch numbers ticks
231
	 *
232
	 * @since 1.8
233
	 *
234
	 * @param array $data
235
	 */
236
	protected function getNumbersTicks( array $data ) {
237
238
		// Only look for numeric values that have been stored
239
		$numerics = array_values( $data['series'] );
240
241
		// Find min and max values to determine the graphs axis parameter
242
		$maxValue = count( $numerics ) == 0 ? 0 : max( array_map( "max", $numerics ) );
243
244
		if ( $this->params['min'] === false ) {
245
			$minValue = count( $numerics ) == 0 ? 0 : min( array_map( "min", $numerics ) );
246
		} else {
247
			$minValue = $this->params['min'];
248
		}
249
250
		// Get ticks info
251
		$data['numbersticks'] = SRFjqPlot::getNumbersTicks( $minValue, $maxValue );
252
		$data['total'] = array_sum( array_map( "array_sum", $numerics ) );
253
254
		return $data;
255
	}
256
257
	/**
258
	 * Add resource definitions
259
	 *
260
	 * @since 1.8
261
	 *
262
	 * @param array $data
263
	 *
264
	 * @return string
265
	 */
266
	protected function addResources() {
267
		// RL module
268
		switch ( $this->params['charttype'] ) {
269
			case 'bubble':
270
				SMWOutputs::requireResource( 'ext.srf.jqplot.bubble' );
271
				break;
272
			case 'donut':
273
				SMWOutputs::requireResource( 'ext.srf.jqplot.donut' );
274
				break;
275
			case 'scatter':
276
			case 'line':
277
			case 'bar':
278
				SMWOutputs::requireResource( 'ext.srf.jqplot.bar' );
279
				break;
280
		}
281
282
		// Trendline plugin
283
		if ( in_array( $this->params['trendline'], [ 'exp', 'linear' ] ) ) {
284
			SMWOutputs::requireResource( 'ext.srf.jqplot.trendline' );
285
		}
286
287
		// Cursor plugin
288
		if ( in_array( $this->params['cursor'], [ 'zoom', 'tooltip' ] ) ) {
289
			SMWOutputs::requireResource( 'ext.srf.jqplot.cursor' );
290
		}
291
292
		// Highlighter plugin
293
		if ( $this->params['highlighter'] ) {
294
			SMWOutputs::requireResource( 'ext.srf.jqplot.highlighter' );
295
		}
296
297
		// Enhancedlegend plugin
298
		if ( $this->params['chartlegend'] ) {
299
			SMWOutputs::requireResource( 'ext.srf.jqplot.enhancedlegend' );
300
		}
301
302
		// gridview plugin
303
		if ( in_array( $this->params['gridview'], [ 'tabs' ] ) ) {
304
			SMWOutputs::requireResource( 'ext.srf.util.grid' );
305
		}
306
307
		// Pointlabels plugin
308
		if ( in_array( $this->params['datalabels'], [ 'value', 'label', 'percent' ] ) ) {
309
			SMWOutputs::requireResource( 'ext.srf.jqplot.pointlabels' );
310
		}
311
	}
312
313
	/**
314
	 * Prepare data for the output
315
	 *
316
	 * @since 1.8
317
	 *
318
	 * @param array $data
319
	 *
320
	 * @return string
321
	 */
322
	protected function getFormatOutput( array $data ) {
323
324
		$this->isHTML = true;
325
326
		static $statNr = 0;
327
		$chartID = 'jqplot-series-' . ++$statNr;
328
329
		// Encoding
330
		$requireHeadItem = [ $chartID => FormatJson::encode( $data ) ];
331
		SMWOutputs::requireHeadItem( $chartID, SRFUtils::makeVariablesScript( $requireHeadItem ) );
332
333
		// Add RL resources
334
		$this->addResources();
335
336
		// Processing placeholder
337
		$processing = SRFUtils::htmlProcessingElement( $this->isHTML );
338
339
		// Conversion due to a string as value that can contain %
340
		$width = strstr( $this->params['width'], "%" ) ? $this->params['width'] : $this->params['width'] . 'px';
341
342
		// Chart/graph placeholder
343
		$chart = Html::rawElement(
344
			'div',
345
			[
346
				'id' => $chartID,
347
				'class' => 'container',
348
				'style' => "display:none; width: {$width}; height: {$this->params['height']}px;"
349
			],
350
			null
351
		);
352
353
		// Beautify class selector
354
		$class = $this->params['charttype'] ? '-' . $this->params['charttype'] : '';
355
		$class = $this->params['class'] ? $class . ' ' . $this->params['class'] : $class . ' jqplot-common';
356
357
		// Chart/graph wrappper
358
		return Html::rawElement(
359
			'div',
360
			[
361
				'class' => 'srf-jqplot' . $class,
362
			],
363
			$processing . $chart
364
		);
365
	}
366
367
	/**
368
	 * @see SMWResultPrinter::getParamDefinitions
369
	 *
370
	 * @since 1.8
371
	 *
372
	 * @param $definitions array of IParamDefinition
373
	 *
374
	 * @return array of IParamDefinition|array
375
	 */
376
	public function getParamDefinitions( array $definitions ) {
377
		$params = array_merge( parent::getParamDefinitions( $definitions ), SRFjqPlot::getCommonParams() );
378
379
		$params['infotext'] = [
380
			'message' => 'srf-paramdesc-infotext',
381
			'default' => '',
382
		];
383
384
		$params['stackseries'] = [
385
			'type' => 'boolean',
386
			'message' => 'srf-paramdesc-stackseries',
387
			'default' => false,
388
		];
389
390
		$params['group'] = [
391
			'message' => 'srf-paramdesc-group',
392
			'default' => 'subject',
393
			'values' => [ 'property', 'subject' ],
394
		];
395
396
		$params['grouplabel'] = [
397
			'message' => 'srf-paramdesc-grouplabel',
398
			'default' => 'subject',
399
			'values' => [ 'property', 'subject' ],
400
		];
401
402
		$params['charttype'] = [
403
			'message' => 'srf-paramdesc-charttype',
404
			'default' => 'bar',
405
			'values' => [ 'bar', 'line', 'donut', 'bubble', 'scatter' ],
406
		];
407
408
		$params['trendline'] = [
409
			'message' => 'srf-paramdesc-trendline',
410
			'default' => 'none',
411
			'values' => [ 'none', 'exp', 'linear' ],
412
		];
413
414
		$params['cursor'] = [
415
			'message' => 'srf-paramdesc-chartcursor',
416
			'default' => 'none',
417
			'values' => [ 'none', 'zoom', 'tooltip' ],
418
		];
419
420
		$params['gridview'] = [
421
			'message' => 'srf-paramdesc-gridview',
422
			'default' => 'none',
423
			'values' => [ 'none', 'tabs' ],
424
		];
425
426
		$params['hidezeroes'] = [
427
			'type' => 'boolean',
428
			'message' => 'srf-paramdesc-hidezeroes',
429
			'default' => false,
430
		];
431
432
		return $params;
433
	}
434
}
435