This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * Main plugin initialisation class. |
||
4 | * |
||
5 | * @package WP_To_Diaspora\Core |
||
6 | */ |
||
7 | |||
8 | // Exit if accessed directly. |
||
9 | defined( 'ABSPATH' ) || exit; |
||
10 | |||
11 | /** |
||
12 | * WP to diaspora* main plugin class. |
||
13 | */ |
||
14 | class WP2D { |
||
15 | |||
16 | /** |
||
17 | * Only instance of this class. |
||
18 | * |
||
19 | * @var WP2D |
||
20 | */ |
||
21 | private static $instance; |
||
22 | |||
23 | /** |
||
24 | * The minimum required WordPress version. |
||
25 | * |
||
26 | * @since 1.5.4 |
||
27 | * |
||
28 | * @var string |
||
29 | */ |
||
30 | private $min_wp = '4.6-src'; |
||
31 | |||
32 | /** |
||
33 | * The minimum required PHP version. |
||
34 | * |
||
35 | * @since 1.5.4 |
||
36 | * |
||
37 | * @var string |
||
38 | */ |
||
39 | private $min_php = '7.2'; |
||
40 | |||
41 | /** |
||
42 | * Instance of the API class. |
||
43 | * |
||
44 | * @var WP2D_API |
||
45 | */ |
||
46 | private $api; |
||
47 | |||
48 | /** |
||
49 | * Create / Get the instance of this class. |
||
50 | * |
||
51 | * @return WP2D Instance of this class. |
||
52 | */ |
||
53 | public static function instance() { |
||
54 | if ( null === self::$instance ) { |
||
55 | self::$instance = new self(); |
||
56 | View Code Duplication | if ( self::$instance->version_check() ) { |
|
0 ignored issues
–
show
|
|||
57 | self::$instance->constants(); |
||
58 | self::$instance->setup(); |
||
59 | } else { |
||
60 | self::$instance = null; |
||
61 | } |
||
62 | } |
||
63 | |||
64 | return self::$instance; |
||
65 | } |
||
66 | |||
67 | /** |
||
68 | * Define all the required constants. |
||
69 | * |
||
70 | * @since 1.5.0 |
||
71 | */ |
||
72 | private function constants() { |
||
73 | // Are we in debugging mode? |
||
74 | if ( isset( $_GET['debugging'] ) ) { // phpcs:ignore |
||
75 | define( 'WP2D_DEBUGGING', true ); |
||
76 | } |
||
77 | |||
78 | define( 'WP2D_DIR', dirname( __DIR__ ) ); |
||
79 | define( 'WP2D_LIB_DIR', WP2D_DIR . '/lib' ); |
||
80 | |||
81 | // Fall back to WordPress AUTH_KEY for password encryption. |
||
82 | defined( 'WP2D_ENC_KEY' ) || define( 'WP2D_ENC_KEY', AUTH_KEY ); |
||
83 | } |
||
84 | |||
85 | /** |
||
86 | * Check the minimum WordPress and PHP requirements. |
||
87 | * |
||
88 | * @since 1.5.4 |
||
89 | * |
||
90 | * @return bool If version requirements are met. |
||
91 | */ |
||
92 | private function version_check() { |
||
93 | // Check for version requirements. |
||
94 | if ( version_compare( PHP_VERSION, $this->min_php, '<' ) || version_compare( $GLOBALS['wp_version'], $this->min_wp, '<' ) ) { |
||
95 | add_action( 'admin_notices', [ $this, 'deactivate' ] ); |
||
96 | |||
97 | return false; |
||
98 | } |
||
99 | |||
100 | return true; |
||
101 | } |
||
102 | |||
103 | /** |
||
104 | * Callback to deactivate plugin and display admin notice. |
||
105 | * |
||
106 | * @since 1.5.4 |
||
107 | */ |
||
108 | public function deactivate() { |
||
109 | // First of all, deactivate the plugin. |
||
110 | deactivate_plugins( WP2D_BASENAME ); |
||
111 | |||
112 | // Get rid of the "Plugin activated" message. |
||
113 | unset( $_GET['activate'] ); // phpcs:ignore |
||
114 | |||
115 | // Then display the admin notice. |
||
116 | ?> |
||
117 | <div class="error"> |
||
118 | <p><?php echo esc_html( sprintf( 'WP to diaspora* requires at least WordPress %1$s (you have %2$s) and PHP %3$s (you have %4$s)!', $this->min_wp, $GLOBALS['wp_version'], $this->min_php, PHP_VERSION ) ); ?></p> |
||
119 | </div> |
||
120 | <?php |
||
121 | } |
||
122 | |||
123 | /** |
||
124 | * Set up the plugin. |
||
125 | */ |
||
126 | private function setup() { |
||
127 | // Add "Settings" link to plugin page. |
||
128 | add_filter( 'plugin_action_links_' . WP2D_BASENAME, [ $this, 'settings_link' ] ); |
||
129 | |||
130 | // Perform any necessary data upgrades. |
||
131 | add_action( 'admin_init', [ $this, 'upgrade' ] ); |
||
132 | |||
133 | // Admin notice when the AUTH_KEY has changed and credentials need to be re-saved. |
||
134 | add_action( 'admin_notices', [ $this, 'admin_notices' ] ); |
||
135 | |||
136 | // Enqueue CSS and JS scripts. |
||
137 | add_action( 'admin_enqueue_scripts', [ $this, 'admin_load_scripts' ] ); |
||
138 | |||
139 | // Set up the options. |
||
140 | add_action( 'init', [ 'WP2D_Options', 'instance' ] ); |
||
141 | |||
142 | // WP2D Post. |
||
143 | add_action( 'init', [ 'WP2D_Post', 'setup' ] ); |
||
144 | |||
145 | // AJAX actions for loading aspects and services. |
||
146 | add_action( 'wp_ajax_wp_to_diaspora_update_aspects_list', [ $this, 'update_aspects_list_callback' ] ); |
||
147 | add_action( 'wp_ajax_wp_to_diaspora_update_services_list', [ $this, 'update_services_list_callback' ] ); |
||
148 | |||
149 | // Check the pod connection status on the options page. |
||
150 | add_action( 'wp_ajax_wp_to_diaspora_check_pod_connection_status', [ $this, 'check_pod_connection_status_callback' ] ); |
||
151 | } |
||
152 | |||
153 | /** |
||
154 | * Load the diaspora* API for ease of use. |
||
155 | * |
||
156 | * @return WP2D_API The API object. |
||
157 | */ |
||
158 | private function load_api() { |
||
159 | if ( null === $this->api ) { |
||
160 | $this->api = WP2D_Helpers::api_quick_connect(); |
||
161 | } |
||
162 | |||
163 | return $this->api; |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * Initialise upgrade sequence. |
||
168 | */ |
||
169 | public function upgrade() { |
||
170 | // Get the current options, or assign defaults. |
||
171 | $options = WP2D_Options::instance(); |
||
172 | $version = $options->get_option( 'version' ); |
||
173 | |||
174 | // If the versions differ, this is probably an update. Need to save updated options. |
||
175 | if ( WP2D_VERSION !== $version ) { |
||
176 | |||
177 | // Password is stored encrypted since version 1.2.7. |
||
178 | // When upgrading to it, the plain text password is encrypted and saved again. |
||
179 | if ( version_compare( $version, '1.2.7', '<' ) ) { |
||
180 | $options->set_option( 'password', WP2D_Helpers::encrypt( (string) $options->get_option( 'password' ) ) ); |
||
181 | } |
||
182 | |||
183 | if ( version_compare( $version, '1.3.0', '<' ) ) { |
||
184 | // The 'user' setting is renamed to 'username'. |
||
185 | $options->set_option( 'username', $options->get_option( 'user' ) ); |
||
186 | $options->set_option( 'user', null ); |
||
187 | |||
188 | // Save tags as arrays instead of comma seperated values. |
||
189 | $global_tags = $options->get_option( 'global_tags' ); |
||
190 | $options->set_option( 'global_tags', $options->validate_tags( $global_tags ) ); |
||
191 | } |
||
192 | |||
193 | if ( version_compare( $version, '1.4.0', '<' ) ) { |
||
194 | // Turn tags_to_post string into an array. |
||
195 | $tags_to_post_old = $options->get_option( 'tags_to_post' ); |
||
196 | $tags_to_post = array_filter( [ |
||
197 | ( false !== strpos( $tags_to_post_old, 'g' ) ) ? 'global' : null, |
||
198 | ( false !== strpos( $tags_to_post_old, 'c' ) ) ? 'custom' : null, |
||
199 | ( false !== strpos( $tags_to_post_old, 'p' ) ) ? 'post' : null, |
||
200 | ] ); |
||
201 | $options->set_option( 'tags_to_post', $tags_to_post ); |
||
202 | } |
||
203 | |||
204 | // Encryption key is set in WP2D_ENC_KEY since version 2.2.0. |
||
205 | if ( version_compare( $version, '2.2.0', '<' ) ) { |
||
206 | // Remember AUTH_KEY hash to notice a change. |
||
207 | $options->set_option( 'auth_key_hash', md5( AUTH_KEY ) ); |
||
208 | |||
209 | // Upgrade encrypted password if new WP2D_ENC_KEY is used. |
||
210 | $options->attempt_password_upgrade(); |
||
211 | } |
||
212 | |||
213 | // Update version. |
||
214 | $options->set_option( 'version', WP2D_VERSION ); |
||
215 | $options->save(); |
||
216 | } |
||
217 | } |
||
218 | |||
219 | /** |
||
220 | * Load scripts and styles for Settings and Post pages of allowed post types. |
||
221 | */ |
||
222 | public function admin_load_scripts() { |
||
223 | // Get the enabled post types to load the script for. |
||
224 | $enabled_post_types = WP2D_Options::instance()->get_option( 'enabled_post_types', [] ); |
||
225 | |||
226 | // Get the screen to find out where we are. |
||
227 | $screen = get_current_screen(); |
||
228 | |||
229 | // Only load the styles and scripts on the settings page and the allowed post types. |
||
230 | if ( 'settings_page_wp_to_diaspora' === $screen->id || ( in_array( $screen->post_type, $enabled_post_types, true ) && 'post' === $screen->base ) ) { |
||
231 | wp_enqueue_style( 'tag-it', plugins_url( '/css/tag-it.min.css', WP2D_BASENAME ), [], WP2D_VERSION ); |
||
232 | wp_enqueue_style( 'chosen', plugins_url( '/css/chosen.min.css', WP2D_BASENAME ), [], WP2D_VERSION ); |
||
233 | wp_enqueue_style( 'wp-to-diaspora-admin', plugins_url( '/css/wp-to-diaspora.css', WP2D_BASENAME ), [], WP2D_VERSION ); |
||
234 | wp_enqueue_script( 'chosen', plugins_url( '/js/chosen.jquery.min.js', WP2D_BASENAME ), [ 'jquery' ], WP2D_VERSION, true ); |
||
235 | wp_enqueue_script( 'tag-it', plugins_url( '/js/tag-it.jquery.min.js', WP2D_BASENAME ), [ 'jquery', 'jquery-ui-autocomplete' ], WP2D_VERSION, true ); |
||
236 | wp_enqueue_script( 'wp-to-diaspora-admin', plugins_url( '/js/wp-to-diaspora.js', WP2D_BASENAME ), [ 'jquery' ], WP2D_VERSION, true ); |
||
237 | // Javascript-specific l10n. |
||
238 | wp_localize_script( 'wp-to-diaspora-admin', 'WP2D', [ |
||
239 | '_nonce' => wp_create_nonce( 'wp2d' ), |
||
240 | 'nonce_failure' => __( 'AJAX Nonce failure.', 'wp-to-diaspora' ), |
||
241 | 'resave_credentials' => __( 'Resave your credentials and try again.', 'wp-to-diaspora' ), |
||
242 | 'no_services_connected' => __( 'No services connected yet.', 'wp-to-diaspora' ), |
||
243 | 'sure_reset_defaults' => __( 'Are you sure you want to reset to default values?', 'wp-to-diaspora' ), |
||
244 | 'conn_testing' => __( 'Testing connection...', 'wp-to-diaspora' ), |
||
245 | 'conn_successful' => __( 'Connection successful.', 'wp-to-diaspora' ), |
||
246 | 'conn_failed' => __( 'Connection failed.', 'wp-to-diaspora' ), |
||
247 | ] ); |
||
248 | } |
||
249 | } |
||
250 | |||
251 | /** |
||
252 | * Add "AUTH_KEY" changed admin notice. |
||
253 | * |
||
254 | * @since 2.2.0 |
||
255 | */ |
||
256 | public function admin_notices() { |
||
257 | // If a custom WP2D_ENC_KEY is set, it doesn't matter if the AUTH_KEY has changed. |
||
258 | if ( AUTH_KEY !== WP2D_ENC_KEY ) { |
||
259 | return; |
||
260 | } |
||
261 | |||
262 | $options = WP2D_Options::instance(); |
||
263 | if ( md5( AUTH_KEY ) !== $options->get_option( 'auth_key_hash' ) ) { |
||
264 | printf( '<div class="error notice is-dismissible"><p>%1$s</p></div>', |
||
265 | sprintf( |
||
266 | esc_html_x( 'Looks like your WordPress secret keys have changed! Please %1$sre-save your login info%2$s.', 'placeholders are link tags to the settings page.', 'wp-to-diaspora' ), |
||
267 | '<a href="' . esc_url( admin_url( 'options-general.php?page=wp_to_diaspora' ) ) . '&tab=setup" target="_blank">', |
||
268 | '</a>' |
||
269 | ) |
||
270 | ); |
||
271 | } |
||
272 | } |
||
273 | |||
274 | /** |
||
275 | * Add the "Settings" link to the plugins page. |
||
276 | * |
||
277 | * @param array $links Links to display for plugin on plugins page. |
||
278 | * |
||
279 | * @return array Links to display for plugin on plugins page. |
||
280 | */ |
||
281 | public function settings_link( $links ) { |
||
282 | $links[] = '<a href="' . esc_url( admin_url( 'options-general.php?page=wp_to_diaspora' ) ) . '">' . __( 'Settings', 'wp-to-diaspora' ) . '</a>'; |
||
283 | |||
284 | return $links; |
||
285 | } |
||
286 | |||
287 | /** |
||
288 | * Fetch the list of aspects or services and save them to the settings. |
||
289 | * |
||
290 | * NOTE: When updating the lists, always force a fresh fetch. |
||
291 | * |
||
292 | * @param string $type Type of list to update. |
||
293 | * |
||
294 | * @return array|bool The list of aspects or services, false if an illegal parameter is passed. |
||
295 | */ |
||
296 | private function update_aspects_services_list( $type ) { |
||
297 | // Check for correct argument value. |
||
298 | if ( ! in_array( $type, [ 'aspects', 'services' ], true ) ) { |
||
299 | return false; |
||
300 | } |
||
301 | |||
302 | $options = WP2D_Options::instance(); |
||
303 | $list = $options->get_option( $type . '_list' ); |
||
304 | |||
305 | // Make sure that we have at least the 'Public' aspect. |
||
306 | if ( 'aspects' === $type && empty( $list ) ) { |
||
307 | $list = [ 'public' => __( 'Public', 'wp-to-diaspora' ) ]; |
||
308 | } |
||
309 | |||
310 | // Set up the connection to diaspora*. |
||
311 | $api = $this->load_api(); |
||
312 | |||
313 | // If there was a problem loading the API, return false. |
||
314 | if ( $api->has_last_error() ) { |
||
315 | return false; |
||
316 | } |
||
317 | |||
318 | $list_new = $list; |
||
319 | if ( 'aspects' === $type ) { |
||
320 | $list_new = $api->get_aspects( true ); |
||
321 | } elseif ( 'services' === $type ) { |
||
322 | $list_new = $api->get_services( true ); |
||
323 | } |
||
324 | |||
325 | // If the new list couldn't be fetched successfully, return false. |
||
326 | if ( $api->has_last_error() ) { |
||
327 | return false; |
||
328 | } |
||
329 | |||
330 | // We have a new list to save and return! |
||
331 | $options->set_option( $type . '_list', $list_new ); |
||
332 | $options->save(); |
||
333 | |||
334 | return $list_new; |
||
335 | } |
||
336 | |||
337 | /** |
||
338 | * Update the list of aspects and return them for use with AJAX. |
||
339 | */ |
||
340 | public function update_aspects_list_callback() { |
||
341 | check_ajax_referer( 'wp2d', 'nonce' ); |
||
342 | wp_send_json( $this->update_aspects_services_list( 'aspects' ) ); |
||
343 | } |
||
344 | |||
345 | /** |
||
346 | * Update the list of services and return them for use with AJAX. |
||
347 | */ |
||
348 | public function update_services_list_callback() { |
||
349 | check_ajax_referer( 'wp2d', 'nonce' ); |
||
350 | wp_send_json( $this->update_aspects_services_list( 'services' ) ); |
||
351 | } |
||
352 | |||
353 | /** |
||
354 | * Check the pod connection status. |
||
355 | * |
||
356 | * @return bool The status of the connection. |
||
357 | */ |
||
358 | private function check_pod_connection_status() { |
||
359 | $options = WP2D_Options::instance(); |
||
360 | |||
361 | $status = null; |
||
362 | |||
363 | if ( $options->is_pod_set_up() ) { |
||
364 | $status = ! $this->load_api()->has_last_error(); |
||
365 | } |
||
366 | |||
367 | return $status; |
||
368 | } |
||
369 | |||
370 | /** |
||
371 | * Check the connection to the pod and return the status for use with AJAX. |
||
372 | * |
||
373 | * @todo esc_html |
||
374 | */ |
||
375 | public function check_pod_connection_status_callback() { |
||
376 | if ( ! defined( 'WP2D_DEBUGGING' ) && isset( $_REQUEST['debugging'] ) ) { // phpcs:ignore |
||
377 | define( 'WP2D_DEBUGGING', true ); |
||
378 | } |
||
379 | |||
380 | View Code Duplication | if ( ! check_ajax_referer( 'wp2d', 'nonce', false ) ) { |
|
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. ![]() |
|||
381 | wp_send_json_error( [ 'message' => __( 'Invalid AJAX nonce', 'wp-to-diaspora' ) ] ); |
||
382 | } |
||
383 | |||
384 | $status = $this->check_pod_connection_status(); |
||
385 | |||
386 | $data = [ |
||
387 | 'debug' => esc_textarea( WP2D_Helpers::get_debugging() ), |
||
388 | 'message' => __( 'Connection successful.', 'wp-to-diaspora' ), |
||
389 | ]; |
||
390 | |||
391 | if ( true === $status ) { |
||
392 | wp_send_json_success( $data ); |
||
393 | } elseif ( false === $status && $this->load_api()->has_last_error() ) { |
||
394 | $data['message'] = $this->load_api()->get_last_error() . ' ' . WP2D_Contextual_Help::get_help_tab_quick_link( $this->load_api()->get_last_error_object() ); |
||
0 ignored issues
–
show
It seems like
$this->load_api()->get_last_error_object() can be null ; however, get_help_tab_quick_link() does not accept null , maybe add an additional type check?
Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code: /** @return stdClass|null */
function mayReturnNull() { }
function doesNotAcceptNull(stdClass $x) { }
// With potential error.
function withoutCheck() {
$x = mayReturnNull();
doesNotAcceptNull($x); // Potential error here.
}
// Safe - Alternative 1
function withCheck1() {
$x = mayReturnNull();
if ( ! $x instanceof stdClass) {
throw new \LogicException('$x must be defined.');
}
doesNotAcceptNull($x);
}
// Safe - Alternative 2
function withCheck2() {
$x = mayReturnNull();
if ($x instanceof stdClass) {
doesNotAcceptNull($x);
}
}
![]() |
|||
395 | wp_send_json_error( $data ); |
||
396 | } |
||
397 | // If $status === null, do nothing. |
||
398 | } |
||
399 | } |
||
400 |
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.