Issues (141)

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/boilerplate/SRF_Boilerplate.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
/**
4
 * Boilerplate query printer
5
 *
6
 * Add your description here ...
7
 *
8
 * @see http://www.semantic-mediawiki.org/wiki/Writing_result_printers
9
 *
10
 * @since 1.8
11
 *
12
 * @licence GNU GPL v2 or later
13
 * @author mwjames
14
 */
15
16
/**
17
 * Description ... this part is used for the doxygen processor
18
 *
19
 * @ingroup SemanticResultFormats
20
 */
21
class SRFBoilerplate extends SMWResultPrinter {
22
23
	/**
24
	 * @see SMWResultPrinter::getName
25
	 * @return string
26
	 */
27
	public function getName() {
28
		// Add your result printer name here
29
		return wfMessage( 'srf-printername-boilerplate' )->text();
30
	}
31
32
	/**
33
	 * @see SMWResultPrinter::getResultText
34
	 *
35
	 * @param SMWQueryResult $result
36
	 * @param $outputMode
37
	 *
38
	 * @return string
39
	 */
40
	protected function getResultText( SMWQueryResult $result, $outputMode ) {
41
42
		// Data processing
43
		// It is advisable to separate data processing from output logic
44
		$data = $this->getResultData( $result, $outputMode );
45
46
		// Check if the data processing returned any results otherwise just bailout
47
		if ( $data === [] ) {
48
			// Add an error message to return method
49
			return $result->addErrors( [ wfMessage( 'srf-no-results' )->inContentLanguage()->text() ] );
50
		} else {
51
			// Add options if needed to format the output
52
53
			// $outputMode can be specified as
54
			// SMW_OUTPUT_HTML
55
			// SMW_OUTPUT_FILE
56
			// SMW_OUTPUT_WIKI
57
58
			// For implementing template support this options has to be set but if you
59
			// manipulate data via jQuery/JavaScript it is less likely that you need
60
			// this option since templates will influence how wiki text is parsed
61
			// but will have no influence in how a HTML representation is altered
62
			// $this->hasTemplates = true;
63
64
			$options = [
65
				'mode' => $outputMode
66
			];
67
68
			// Return formatted results
69
			return $this->getFormatOutput( $data, $options );
70
		}
71
	}
72
73
	/**
74
	 * Returns an array with data
75
	 *
76
	 * @since 1.8
77
	 *
78
	 * @param SMWQueryResult $result
79
	 * @param $outputMode
80
	 *
81
	 * @return array
82
	 */
83
	protected function getResultData( SMWQueryResult $result, $outputMode ) {
84
85
		$data = [];
86
87
		// This is an example implementation on how to select available data from
88
		// a result set. Please make appropriate adoptions necessary for your
89
		// application.
90
91
		// Some methods are declared as private to show case which objects are
92
		// directly accessible within SMWQueryResult
93
94
		// Get all SMWDIWikiPage objects that make up the results
95
		// $subjects = $this->getSubjects( $result->getResults() );
96
97
		// Get all print requests property labels
98
		// $labels = $this->getLabels( $result->getPrintRequests() );
99
100
		/**
101
		 * Get all values for all rows that belong to the result set
102
		 *
103
		 * @var SMWResultArray $rows
104
		 */
105
		while ( $rows = $result->getNext() ) {
106
107
			/**
108
			 * @var SMWResultArray $field
109
			 * @var SMWDataValue $dataValue
110
			 */
111
			foreach ( $rows as $field ) {
112
113
				// Initialize the array each time it passes a new row to avoid data from
114
				// a previous row is remaining
115
				$rowData = [];
116
117
				// Get the label for the current property
118
				$propertyLabel = $field->getPrintRequest()->getLabel();
119
120
				// Get the label for the current subject
121
				// getTitle()->getText() will return only the main text without the
122
				// fragment(#) which can be arbitrary in case subobjects are involved
123
124
				// getTitle()->getFullText() will return the text with the fragment(#)
125
				// which is important when using subobjects
126
				$subjectLabel = $field->getResultSubject()->getTitle()->getFullText();
127
128
				while ( ( $dataValue = $field->getNextDataValue() ) !== false ) {
129
130
					// Get the data value item
131
					$rowData[] = $this->getDataValueItem( $dataValue->getDataItem()->getDIType(), $dataValue );
132
				}
133
134
				// Example how to build a hierarchical array by collecting all values
135
				// belonging to one subject/row using labels as array key representation
136
				$data[$subjectLabel][$propertyLabel][] = $rowData;
137
			}
138
		}
139
140
		// Return the data
141
		// return array( 'labels' => $labels, 'subjects' => $subjects, 'data' => $data );
142
		return $data;
143
	}
144
145
	/**
146
	 * A quick getway method to find all SMWDIWikiPage objects that make up the results
147
	 *
148
	 * @since 1.8
149
	 *
150
	 * @param SMWQueryResult $result
151
	 *
152
	 * @return array
153
	 */
154
	private function getSubjects( $result ) {
0 ignored issues
show
This method is not used, and could be removed.
Loading history...
155
		$subjects = [];
156
157
		foreach ( $result as $wikiDIPage ) {
158
			$subjects[] = $wikiDIPage->getTitle()->getText();
159
		}
160
		return $subjects;
161
	}
162
163
	/**
164
	 * Get all print requests property labels
165
	 *
166
	 * @since 1.8
167
	 *
168
	 * @param SMWQueryResult $result
169
	 *
170
	 * @return array
171
	 */
172
	private function getLabels( $result ) {
0 ignored issues
show
This method is not used, and could be removed.
Loading history...
173
		$printRequestsLabels = [];
174
175
		foreach ( $result as $printRequests ) {
176
			$printRequestsLabels[] = $printRequests->getLabel();
177
		}
178
		return $printRequestsLabels;
179
	}
180
181
	/**
182
	 * Get a single data value item
183
	 *
184
	 * @since 1.8
185
	 *
186
	 * @param integer $type
187
	 * @param SMWDataValue $dataValue
188
	 *
189
	 * @return mixed
190
	 */
191
	private function getDataValueItem( $type, SMWDataValue $dataValue ) {
192
193
		if ( $type == SMWDataItem::TYPE_NUMBER ) {
194
195
			// Set unit if available
196
			$dataValue->setOutputFormat( $this->params['unit'] );
197
198
			// Check if unit is available and return the converted value otherwise
199
			// just return a plain number
200
			return $dataValue->getUnit() !== '' ? $dataValue->getShortWikiText() : $dataValue->getNumber();
0 ignored issues
show
It seems like you code against a specific sub-type and not the parent class SMWDataValue as the method getUnit() does only exist in the following sub-classes of SMWDataValue: SMWNumberValue, SMWQuantityValue, SMW\DataValues\TemperatureValue. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
It seems like you code against a specific sub-type and not the parent class SMWDataValue as the method getNumber() does only exist in the following sub-classes of SMWDataValue: SMWNumberValue, SMWQuantityValue, SMW\DataValues\TemperatureValue. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
201
		} else {
202
203
			// For all other data types return the wikivalue
204
			return $dataValue->getWikiValue();
205
		}
206
	}
207
208
	/**
209
	 * Prepare data for the output
210
	 *
211
	 * @since 1.8
212
	 *
213
	 * @param array $data
214
	 * @param array $options
215
	 *
216
	 * @return string
217
	 */
218
	protected function getFormatOutput( $data, $options ) {
219
220
		// The generated ID is to distinguish similar instances of the same
221
		// printer that can appear within the same page
222
		static $statNr = 0;
223
		$ID = 'srf-boilerplate-' . ++$statNr;
224
225
		// or use the PHP uniqid() to generate an unambiguous ID
226
		// $ID = uniqid();
227
228
		// Used to set that the output and being treated as HTML (opposed to plain wiki text)
229
		$this->isHTML = true;
230
231
		// Correct escaping is vital to minimize possibilites of malicious code snippets
232
		// and also a coherent string evalution therefore it is recommended
233
		// that data transferred to the JS plugin is JSON encoded
234
235
		// Assign the ID to make a data instance readly available and distinguishable
236
		// from other content within the same page
237
		$requireHeadItem = [ $ID => FormatJson::encode( $data ) ];
238
		SMWOutputs::requireHeadItem( $ID, Skin::makeVariablesScript( $requireHeadItem ) );
239
240
		// Add resource definitions that has been registered with SRF_Resource.php
241
		// Resource definitions contain scripts, styles, messages etc.
242
		// SMWOutputs::requireResource( 'ext.srf.boilerplate.namespace' );
243
		SMWOutputs::requireResource( 'ext.srf.boilerplate.simple' );
244
245
		// Prepares an HTML element showing a rotating spinner indicating that something
246
		// will appear at this placeholder. The element will be visible as for as
247
		// long as jquery is not loaded and the JS plugin did not hide/removed the element.
248
		$processing = SRFUtils::htmlProcessingElement();
249
250
		// Add two elements a outer wrapper that is assigned a class which the JS plugin
251
		// can select and will fetch all instances of the same result printer and an innner
252
		// container which is set invisible (display=none) for as long as the JS plugin
253
		// holds the content hidden. It is normally the place where the "hard work"
254
		// is done hidden from the user until it is ready.
255
		// The JS plugin can prepare the output within this container without presenting
256
		// unfinished visual content, to avoid screen clutter and improve user experience.
257
		return Html::rawElement(
258
			'div',
259
			[
260
				'class' => 'srf-boilerplate'
261
			],
262
			$processing . Html::element(
263
				'div',
264
				[
265
					'id' => $ID,
266
					'class' => 'container',
267
					'style' => 'display:none;'
268
				],
269
				null
270
			)
271
		);
272
	}
273
274
	/**
275
	 * @see SMWResultPrinter::getParamDefinitions
276
	 *
277
	 * @since 1.8
278
	 *
279
	 * @param $definitions array of IParamDefinition
280
	 *
281
	 * @return array of IParamDefinition|array
282
	 */
283
	public function getParamDefinitions( array $definitions ) {
284
		$params = parent::getParamDefinitions( $definitions );
285
286
		// Add your parameters here
287
288
		// Example of a unit paramter
289
		$params['unit'] = [
290
			'message' => 'srf-paramdesc-unit',
291
			'default' => '',
292
		];
293
294
		return $params;
295
	}
296
}