Issues (4296)

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.

includes/admin/class-i18n-module.php (14 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
 * Class Give_i18n
5
 */
6
class Give_i18n_Banner {
7
8
	/**
9
	 * Your translation site's URL.
10
	 *
11
	 * @var string
12
	 */
13
	private $glotpress_url;
14
15
	/**
16
	 * Hook where you want to show the promo box.
17
	 *
18
	 * @var string
19
	 */
20
	private $hook;
21
22
	/**
23
	 * Will contain the site's locale.
24
	 *
25
	 * @access private
26
	 * @var string
27
	 */
28
	private $locale;
29
30
	/**
31
	 * Will contain the locale's name, obtained from your translation site.
32
	 *
33
	 * @access private
34
	 * @var string
35
	 */
36
	private $locale_name;
37
38
	/**
39
	 * Will contain the percentage translated for the plugin translation project in the locale.
40
	 *
41
	 * @access private
42
	 * @var int
43
	 */
44
	private $percent_translated;
45
46
47
	/**
48
	 * Indicates whether there's a translation available at all.
49
	 *
50
	 * @access private
51
	 * @var bool
52
	 */
53
	private $translation_exists;
54
55
	/**
56
	 * Indicates whether the translation's loaded.
57
	 *
58
	 * @access private
59
	 * @var bool
60
	 */
61
	private $translation_loaded;
62
63
	/**
64
	 * Give_i18n constructor.
65
	 *
66
	 * @param $args
67
	 */
68
	public function __construct( $args ) {
69
70
		// Only for admins.
71
		if ( ! is_admin() ) {
72
			return;
73
		}
74
75
		foreach ( $args as $key => $arg ) {
76
			$this->$key = $arg;
77
		}
78
79
		add_action( 'admin_init', array( $this, 'init' ) );
80
0 ignored issues
show
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
81
82
	}
83
84
	/**
85
	 * Initialize i18n banner.
86
	 */
87
	function init() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
88
89
		// First get user's locale (4.7+).
90
		$this->locale = function_exists( 'get_user_locale' ) ? get_user_locale() : get_locale();
91
92
		// This plugin is en_US native.
93
		if ( 'en_US' === $this->locale ) {
94
			return;
95
		}
96
97
		if (
98
			! $this->hide_promo()
99
			&& ( ! empty( $_GET['post_type'] ) && 'give_forms' === $_GET['post_type'] )
0 ignored issues
show
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
Detected usage of a non-sanitized input variable: $_GET
Loading history...
100
			&& ( ! empty( $_GET['page'] ) && 'give-settings' === $_GET['page'] )
0 ignored issues
show
Detected access of super global var $_GET, probably need manual inspection.
Loading history...
Detected usage of a non-sanitized input variable: $_GET
Loading history...
101
		) {
102
			add_action( $this->hook, array( $this, 'promo' ) );
103
		}
104
	}
105
106
107
	/**
108
	 * Check whether the promo should be hidden or not.
109
	 *
110
	 * @access private
111
	 *
112
	 * @return bool
113
	 */
114
	private function hide_promo() {
115
		$hide_promo = Give_Cache::get( 'give_i18n_give_promo_hide', true );
116
		if ( ! $hide_promo ) {
117
			if ( filter_input( INPUT_GET, 'remove_i18n_promo', FILTER_VALIDATE_INT ) === 1 ) {
0 ignored issues
show
Found "=== 1". Use Yoda Condition checks, you must
Loading history...
118
				// No expiration time, so this would normally not expire, but it wouldn't be copied to other sites etc.
119
				Give_Cache::set( 'give_i18n_give_promo_hide', true, null, true );
120
				$hide_promo = true;
121
			}
122
		}
123
124
		return $hide_promo;
125
	}
126
127
	/**
128
	 * Generates a promo message.
129
	 *
130
	 * @access private
131
	 *
132
	 * @return bool|string $message
133
	 */
134
	private function promo_message() {
135
		$message = false;
136
137
		// Using a translation less than 90% complete.
138
		if ( $this->translation_exists && $this->translation_loaded && $this->percent_translated < 90 ) {
139
			$message = __( 'As you can see, there is a translation of this plugin in %1$s. This translation is currently %3$d%% complete. We need your help to make it complete and to fix any errors. Please register at %4$s to help %5$s to %1$s!', 'give' );
140
		} elseif ( ! $this->translation_loaded && $this->translation_exists ) {
141
			$message = __( 'You\'re using WordPress in %1$s. While %2$s has been %3$d%% translated to %1$s, it has not been shipped with the plugin yet. You can help! Register at %4$s to help complete the translation to %1$s!', 'give' );
142
		} elseif ( ! $this->translation_exists ) {
143
			$message = __( 'You\'re using WordPress in a language we don\'t support yet. We\'d love for %2$s to be translated in that language too, but unfortunately, it isn\'t right now. You can change that! Register at %4$s to help translate it!', 'give' );
144
		}
145
146
		// Links.
147
		$registration_link = sprintf( '<a href="%1$s" target="_blank">%2$s</a>', 'https://wordpress.org/support/register.php', esc_html__( 'WordPress.org', 'give' ) );
148
		$translations_link = sprintf( '<a href="%1$s" target="_blank">%2$s</a>', 'https://translate.wordpress.org/projects/wp-plugins/give', esc_html__( 'complete the translation', 'give' ) );
149
150
		// Message.
151
		$message = sprintf( $message, $this->locale_name, 'Give', $this->percent_translated, $registration_link, $translations_link );
152
153
		return $message;
154
155
	}
156
157
	/**
158
	 * Outputs a promo box
159
	 */
160
	public function promo() {
161
162
		$this->translation_details();
163
		$message = $this->promo_message();
164
165
		if ( $message ) {
166
			$this->print_css();
0 ignored issues
show
The call to the method Give_i18n_Banner::print_css() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
167
168
			ob_start();
169
			?>
170
			<div id="give-i18n-notice" class="give-addon-alert updated give-notice" style="display: none">
171
172
				<a href="https://wordpress.org/support/register.php" class="alignleft give-i18n-icon" style="margin:0" target="_blank"><span class="dashicons dashicons-translation"
173
				                                                                                                                             style="font-size: 110px; text-decoration: none;"></span></a>
174
175
				<div class="give-i18n-notice-content">
176
					<a href="<?php echo esc_url( add_query_arg( array( 'remove_i18n_promo' => '1' ) ) ); ?>" class="dismiss"><span class="dashicons dashicons-dismiss"></span></a>
177
178
					<h2 style="margin: 10px 0;"><?php printf( esc_html__( 'Help Translate Give to %s', 'give' ), $this->locale_name ); ?></h2>
179
					<p><?php echo $message; ?></p>
0 ignored issues
show
Expected next thing to be a escaping function, not '$message'
Loading history...
180
					<p>
181
						<a href="https://wordpress.org/support/register.php" target="_blank"><?php _e( 'Register now &raquo;', 'give' ); ?></a>
182
					</p>
183
				</div>
184
			</div>
185
			<?php
186
187
			$notice_html = ob_get_clean();
188
189
			// Register notice.
190
			Give()->notices->register_notice( array(
191
				'id'          => 'give-i18n-notice',
192
				'type'        => 'updated',
193
				'description_html' => $notice_html,
194
				'show'        => true,
195
			) );
196
		}
197
	}
198
199
200
	/**
201
	 * Output notice css
202
	 *
203
	 * @since  1.8.16
204
	 * @access private
205
	 */
206
	private function print_css() {
207
		?>
208
		<style>
209
			/* Banner specific styles */
210
			div.give-addon-alert.updated {
211
				padding: 10px 20px;
212
				position: relative;
213
				border-color: #66BB6A;
214
				overflow: hidden;
215
			}
216
217
			div.give-addon-alert a {
218
				color: #66BB6A;
219
			}
220
221
			#give-i18n-notice > .give-i18n-icon {
222
				overflow: hidden;
223
			}
224
225
			#give-i18n-notice > .give-i18n-icon .dashicons {
226
				width: 110px;
227
				height: 110px;
228
			}
229
230
			#give-i18n-notice > .give-i18n-icon:focus {
231
				box-shadow: none;
232
			}
233
234
			.give-i18n-notice-content {
235
				margin: 0 30px 0 125px;
236
			}
237
238
			div.give-addon-alert .dismiss {
239
				position: absolute;
240
				right: 20px;
241
				height: 100%;
242
				top: 50%;
243
				margin-top: -10px;
244
				outline: none;
245
				box-shadow: none;
246
				text-decoration: none;
247
				color: #AAA;
248
			}
249
250
			div.give-addon-alert .dismiss:hover {
251
				color: #333;
252
			}
253
254
			/* RTL Styles for banner */
255
			body.rtl .give-i18n-notice-content {
256
				margin: 0 125px 0 30px;
257
			}
258
259
			body.rtl div.give-addon-alert .dismiss {
260
				left: 20px;
261
				right: auto;
262
			}
263
264
		</style>
265
		<?php
266
	}
267
268
	/**
269
	 * Try to find the transient for the translation set or retrieve them.
270
	 *
271
	 * @access private
272
	 *
273
	 * @return object|null
274
	 */
275
	private function find_or_initialize_translation_details() {
276
277
		$set = Give_Cache::get( "give_i18n_give_{$this->locale}", true );
278
279
		if ( ! $set ) {
280
			$set = $this->retrieve_translation_details();
281
			Give_Cache::set( "give_i18n_give_{$this->locale}", $set, DAY_IN_SECONDS, true );
282
		}
283
284
		return $set;
285
	}
286
287
	/**
288
	 * Try to get translation details from cache, otherwise retrieve them, then parse them.
289
	 *
290
	 * @access private
291
	 */
292
	private function translation_details() {
293
		$set = $this->find_or_initialize_translation_details();
294
295
		$this->translation_exists = ! is_null( $set );
296
		$this->translation_loaded = is_textdomain_loaded( 'give' );
297
298
		$this->parse_translation_set( $set );
0 ignored issues
show
It seems like $set defined by $this->find_or_initialize_translation_details() on line 293 can also be of type null; however, Give_i18n_Banner::parse_translation_set() does only seem to accept object, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
299
	}
300
301
	/**
302
	 * Retrieve the translation details from Give Translate.
303
	 *
304
	 * @access private
305
	 *
306
	 * @return object|null
307
	 */
308
	private function retrieve_translation_details() {
309
310
		$api_url = trailingslashit( $this->glotpress_url );
311
312
		$resp = wp_remote_get( $api_url );
0 ignored issues
show
wp_remote_get is highly discouraged, please use vip_safe_wp_remote_get() instead.
Loading history...
313
314
		if ( is_wp_error( $resp ) || wp_remote_retrieve_response_code( $resp ) === '404' ) {
0 ignored issues
show
Found "=== '". Use Yoda Condition checks, you must
Loading history...
315
			return null;
316
		}
317
318
		$body = wp_remote_retrieve_body( $resp );
319
		unset( $resp );
320
321
		if ( $body ) {
322
			$body = json_decode( $body );
323
324
			foreach ( $body->translation_sets as $set ) {
325
				if ( ! property_exists( $set, 'wp_locale' ) ) {
326
					continue;
327
				}
328
329
				if ( $this->locale == $set->wp_locale ) {
330
					return $set;
331
				}
332
			}
333
		}
334
335
		return null;
336
	}
337
338
	/**
339
	 * Set the needed private variables based on the results from Give Translate.
340
	 *
341
	 * @param object $set The translation set
342
	 *
343
	 * @access private
344
	 */
345
	private function parse_translation_set( $set ) {
346
		if ( $this->translation_exists && is_object( $set ) ) {
347
			$this->locale_name        = $set->name;
348
			$this->percent_translated = $set->percent_translated;
349
		} else {
350
			$this->locale_name        = '';
351
			$this->percent_translated = '';
0 ignored issues
show
Documentation Bug introduced by
The property $percent_translated was declared of type integer, but '' is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
352
		}
353
	}
354
}
355
356
$give_i18n = new Give_i18n_Banner( array(
357
		'hook'          => 'admin_notices',
358
		'glotpress_url' => 'https://translate.wordpress.org/api/projects/wp-plugins/give/stable/',
359
	) );
0 ignored issues
show
This line of the multi-line function call does not seem to be indented correctly. Expected 0 spaces, but found 4.
Loading history...
360