Issues (83)

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/MslsMetaBox.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
 * MslsMetaBox
4
 * @author Dennis Ploetner <[email protected]>
5
 * @since 0.9.8
6
 */
7
8
namespace lloc\Msls;
9
10
use lloc\Msls\ContentImport\MetaBox as ContentImportMetaBox;
11
12
/**
13
 * Meta box for the edit mode of the (custom) post types
14
 * @package Msls
15
 */
16
class MslsMetaBox extends MslsMain {
17
18
	/**
19
	 * Suggest
20
	 *
21
	 * Echo a JSON-ified array of posts of the given post-type and
22
	 * the requested search-term and then die silently
23
	 */
24
	public static function suggest() {
25
		$json = new MslsJson;
26
27
		if ( filter_has_var( INPUT_POST, 'blog_id' ) ) {
28
			switch_to_blog(
29
				filter_input( INPUT_POST, 'blog_id', FILTER_SANITIZE_NUMBER_INT )
30
			);
31
32
			$args = [
33
				'post_status'    => get_post_stati( [ 'internal' => '' ] ),
34
				'posts_per_page' => 10,
35
			];
36
37
			if ( filter_has_var( INPUT_POST, 'post_type' ) ) {
38
				$args['post_type'] = sanitize_text_field(
39
					filter_input( INPUT_POST, 'post_type' )
40
				);
41
			}
42
43
			if ( filter_has_var( INPUT_POST, 's' ) ) {
44
				$args['s'] = sanitize_text_field(
45
					filter_input( INPUT_POST, 's' )
46
				);
47
			}
48
49
			$json = self::get_suggested_fields( $json, $args );
50
		}
51
52
		wp_die( $json->encode() );
53
	}
54
55
	/**
56
	 * @param MslsJson $json
57
	 * @param array $args
58
	 *
59
	 * @return mixed
60
	 */
61
	public static function get_suggested_fields( $json, $args ) {
62
		/**
63
		 * Overrides the query-args for the suggest fields in the MetaBox
64
		 *
65
		 * @param array $args
66
		 *
67
		 * @since 0.9.9
68
		 *
69
		 */
70
		$args = (array) apply_filters( 'msls_meta_box_suggest_args', $args );
71
72
		$my_query = new \WP_Query( $args );
73
		while ( $my_query->have_posts() ) {
74
			$my_query->the_post();
75
76
			/**
77
			 * Manipulates the WP_Post object before using it
78
			 *
79
			 * @param \WP_Post $post
80
			 *
81
			 * @since 0.9.9
82
			 *
83
			 */
84
			$my_query->post = apply_filters( 'msls_meta_box_suggest_post', $my_query->post );
85
86
			if ( is_object( $my_query->post ) ) {
87
				$json->add( get_the_ID(), get_the_title() );
88
			}
89
		}
90
91
		wp_reset_postdata();
92
		restore_current_blog();
93
94
		return $json;
95
	}
96
97
	/**
98
	 * Init
99
	 *
100
	 * @codeCoverageIgnore
101
	 *
102
	 * @return MslsMetaBox
103
	 */
104
	public static function init() {
105
		$options    = MslsOptions::instance();
106
		$collection = MslsBlogCollection::instance();
107
		$obj        = new static( $options, $collection );
108
109
		if ( ! $options->is_excluded() ) {
110
			add_action( 'add_meta_boxes', [ $obj, 'add' ] );
111
			add_action( 'save_post', [ $obj, 'set' ] );
112
			add_action( 'trashed_post', [ $obj, 'delete' ] );
113
		}
114
115
		return $obj;
116
	}
117
118
	/**
119
	 * Add
120
	 */
121
	public function add() {
122
		foreach ( MslsPostType::instance()->get() as $post_type ) {
123
			add_meta_box(
124
				'msls',
125
				apply_filters(
126
					'msls_metabox_post_select_title',
127
					__( 'Multisite Language Switcher', 'multisite-language-switcher' )
128
				),
129
				[
130
					$this,
131
					(
132
					MslsOptions::instance()->activate_autocomplete ?
133
						'render_input' :
134
						'render_select'
135
					),
136
				],
137
				$post_type,
138
				'side',
139
				'high'
140
			);
141
142
			if ( MslsOptions::instance()->activate_content_import ) {
143
				add_meta_box(
144
					'msls-content-import',
145
					apply_filters(
146
						'msls_metabox_post_import_title',					
147
						__( 'Multisite Language Switcher - Import content', 'multisite-language-switcher' )
148
					),
149
					[
150
						ContentImportMetaBox::instance(),
151
						'render',
152
					],
153
					$post_type,
154
					'side',
155
					'high' );
156
				add_action( 'admin_footer', [ ContentImportMetaBox::instance(), 'print_modal_html' ] );
157
			}
158
		}
159
	}
160
161
	/**
162
	 * Render the classic select-box
163
	 * @uses selected
164
	 */
165
	public function render_select() {
166
		$blogs = $this->collection->get();
167
		if ( $blogs ) {
168
			global $post;
169
170
			$type   = get_post_type( $post->ID );
171
			$mydata = new MslsOptionsPost( $post->ID );
172
173
			$this->maybe_set_linked_post( $mydata );
174
175
			$temp = $post;
176
177
			wp_nonce_field( MslsPlugin::path(), 'msls_noncename' );
178
179
			$lis = '';
180
181
			foreach ( $blogs as $blog ) {
182
				switch_to_blog( $blog->userblog_id );
183
184
				$language = $blog->get_language();
185
				$icon     = MslsAdminIcon::create()
186
				                         ->set_language( $language )
187
				                         ->set_icon_type( 'flag' );
188
189
				if ( $mydata->has_value( $language ) ) {
190
					$icon->set_href( $mydata->$language );
191
				}
192
193
				$selects  = '';
194
				$p_object = get_post_type_object( $type );
195
196
				if ( $p_object->hierarchical ) {
197
					$args = [
198
						'post_type'         => $type,
199
						'selected'          => $mydata->$language,
200
						'name'              => 'msls_input_' . $language,
201
						'show_option_none'  => ' ',
202
						'option_none_value' => 0,
203
						'sort_column'       => 'menu_order, post_title',
204
						'echo'              => 0,
205
					];
206
					/**
207
					 * Overrides the args for wp_dropdown_pages when using the HTML select in the MetaBox
208
					 *
209
					 * @param array $args
210
					 *
211
					 * @since 1.0.5
212
					 *
213
					 */
214
					$args = (array) apply_filters( 'msls_meta_box_render_select_hierarchical', $args );
215
216
					$selects .= wp_dropdown_pages( $args );
217
				} else {
218
					$selects .= sprintf(
219
						'<select name="msls_input_%s"><option value="0"></option>%s</select>',
220
						$language,
221
						$this->render_options( $type, $mydata->$language )
222
					);
223
				}
224
225
				$lis .= sprintf(
226
					'<li><label for="msls_input_%s">%s</label>%s</li>',
227
					$language,
228
					$icon,
229
					$selects
230
				);
231
232
				restore_current_blog();
233
			}
234
235
			printf(
236
				'<ul>%s</ul><input type="submit" class="button-secondary" value="%s"/>',
237
				$lis,
238
				__( 'Update', 'multisite-language-switcher' )
239
			);
240
241
			$post = $temp;
242
		} else {
243
			printf(
244
				'<p>%s</p>',
245
				__( 'You should define at least another blog in a different language in order to have some benefit from this plugin!', 'multisite-language-switcher' )
246
			);
247
		}
248
	}
249
250
	/**
251
	 * @param string $type
252
	 * @param string $msls_id
253
	 *
254
	 * @return string
255
	 */
256
	public function render_options( $type, $msls_id ) {
257
		$options = [];
258
259
		$my_query = new \WP_Query( [
260
			'post_type'      => $type,
261
			'post_status'    => get_post_stati( [ 'internal' => '' ] ),
262
			'orderby'        => 'title',
263
			'order'          => 'ASC',
264
			'posts_per_page' => - 1,
265
			'fields'         => 'ids',
266
		] );
267
268
		if ( $my_query->have_posts() ) {
269
			foreach ( $my_query->posts as $post_id ) {
270
				$options[] = $this->render_option( $post_id, $msls_id );
271
			}
272
		}
273
274
		return implode( PHP_EOL, $options );
275
	}
276
277
	/**
278
	 * @param string $post_id
279
	 * @param string $msls_id
280
	 *
281
	 * @return string
282
	 */
283
	public function render_option( $post_id, $msls_id ) {
284
		return sprintf( '<option value="%s" %s>%s</option>', $post_id, selected( $post_id, $msls_id, false ), get_the_title( $post_id ) );
285
	}
286
287
	/**
288
	 * Render the suggest input-field
289
	 *
290
	 * @param bool $echo Whether the metabox markup should be echoed to the page or not.
291
	 */
292
	public function render_input( $echo = true ) {
0 ignored issues
show
The parameter $echo is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
293
		$blogs = $this->collection->get();
294
295
		if ( $blogs ) {
296
			global $post;
297
298
			$post_type = get_post_type( $post->ID );
299
			$my_data   = new MslsOptionsPost( $post->ID );
300
301
			$this->maybe_set_linked_post( $my_data );
302
303
			$temp  = $post;
304
			$items = '';
305
306
			wp_nonce_field( MslsPlugin::path(), 'msls_noncename' );
307
308
			foreach ( $blogs as $blog ) {
309
				switch_to_blog( $blog->userblog_id );
310
311
				$language = $blog->get_language();
312
				$icon     = MslsAdminIcon::create()
313
					->set_language( $language )
314
					->set_icon_type( 'flag' );
315
316
				$value = $title = '';
317
318
				if ( $my_data->has_value( $language ) ) {
319
					$icon->set_href( $my_data->$language );
320
					$value = $my_data->$language;
321
					$title = get_the_title( $value );
322
				}
323
324
				$items .= sprintf(
325
					'<li>
326
					<label for="msls_title_%1$s">%2$s</label>
327
					<input type="hidden" id="msls_id_%1$s" name="msls_input_%3$s" value="%4$s"/>
328
					<input class="msls_title" id="msls_title_%1$s" name="msls_title_%1$s" type="text" value="%5$s"/>
329
					</li>',
330
					$blog->userblog_id,
331
					$icon,
332
					$language,
333
					$value,
334
					$title
335
				);
336
337
				restore_current_blog();
338
			}
339
340
			$input_button = sprintf(
341
				'<input type="submit" class="button-secondary clear" value="%s"/>',
342
				__( 'Update', 'multisite-language-switcher' )
343
			);
344
345
			/**
346
			 * Returns the input button, return an empty string if you'ld like to hide the button
347
			 *
348
			 * @param string $input_button
349
			 *
350
			 * @since 1.0.2
351
			 *
352
			 */
353
			$input_button = ( string ) apply_filters( 'msls_meta_box_render_input_button', $input_button );
354
355
			printf(
356
				'<ul>%s</ul>
357
				<input type="hidden" name="msls_post_type" id="msls_post_type" value="%s"/>
358
				<input type="hidden" name="msls_action" id="msls_action" value="suggest_posts"/>
359
				%s',
360
				$items,
361
				$post_type,
362
				$input_button
363
			);
364
365
			$post = $temp;
366
		} else {
367
			printf(
368
				'<p>%s</p>',
369
				__( 'You should define at least another blog in a different language in order to have some benefit from this plugin!', 'multisite-language-switcher' )
370
			);
371
		}
372
	}
373
374
	/**
375
	 * Set
376
	 *
377
	 * @param int $post_id
378
	 */
379
	public function set( $post_id ) {
380
		if ( $this->is_autosave( $post_id ) || ! $this->verify_nonce() ) {
381
			return;
382
		}
383
384
		$capability = (
385
		'page' == filter_input( INPUT_POST, 'post_type', FILTER_SANITIZE_STRING ) ?
386
			'edit_page' :
387
			'edit_post'
388
		);
389
390
		if ( ! current_user_can( $capability, $post_id ) ) {
391
			return;
392
		}
393
394
		$this->save( $post_id, MslsOptionsPost::class );
395
	}
396
397
	/**
398
	 * Sets the selected element in the data from the `$_GET` superglobal, if any.
399
	 *
400
	 * @param MslsOptionsPost $mydata
401
	 *
402
	 * @return MslsOptionsPost
403
	 */
404
	public function maybe_set_linked_post( MslsOptionsPost $mydata ) {
405
		if ( ! isset( $_GET['msls_id'], $_GET['msls_lang'] ) ) {
406
			return $mydata;
407
		}
408
409
		$origin_lang = trim( $_GET['msls_lang'] );
410
411
		if ( isset( $mydata->{$origin_lang} ) ) {
412
			return $mydata;
413
		}
414
415
		$origin_post_id = (int) $_GET['msls_id'];
416
417
		$origin_blog_id = $this->collection->get_blog_id( $origin_lang );
418
419
		if ( null === $origin_blog_id ) {
420
			return $mydata;
421
		}
422
423
		switch_to_blog( $origin_blog_id );
424
		$origin_post = get_post( $origin_post_id );
425
		restore_current_blog();
426
427
		if ( ! $origin_post instanceof \WP_Post ) {
428
			return $mydata;
429
		}
430
431
		$mydata->{$origin_lang} = $origin_post_id;
432
433
		return $mydata;
434
	}
435
}
436