Tenta di modificare un file per un tema o un plugin.

Descrizione

Quando si modifica un file PHP, vengono effettuate richieste di loopback all'amministratore e alla homepage per verificare se è stato introdotto un errore fatale. In tal caso, la modifica PHP sarà annullata.

Parametri

$args

(stringa[])(Richiesto)Argomenti. Si noti che tutti i valori degli arg sono già privi di slave. Tuttavia, provengono direttamente da $_POST e non sono validati o sanificati in alcun modo.

  • 'file'
    (stringa) Percorso relativo al file.
  • 'plugin'
    (stringa) Percorso del file del plugin relativo alla cartella dei plugin.
  • 'tema'
    (stringa) Tema in corso di modifica.
  • 'nuovo contenuto'
    (stringa) Nuovo contenuto del file.
  • 'nonce'
    (stringa) Nonce.

Ritorno

(vero|WP_Errore) Vero in caso di successo o WP_Error in caso di fallimento.

Fonte

File: wp-admin/includes/file.php

functionwp_edit_theme_plugin_file($args){if(empty($args['file'])){returnnewWP_Error('missing_file');}$file=$args['file'];if(0!==validate_file($file)){returnnewWP_Error('bad_file');}if(!isset($args['newcontent'])){returnnewWP_Error('missing_content');}$content=$args['newcontent'];if(!isset($args['nonce'])){returnnewWP_Error('missing_nonce');}$plugin=null;$theme=null;$real_file=null;if(!empty($args['plugin'])){$plugin=$args['plugin'];if(!current_user_can('edit_plugins')){returnnewWP_Error('unauthorized',__('Sorry, you are not allowed to edit plugins for this site.'));}if(!wp_verify_nonce($args['nonce'],'edit-plugin_'.$file)){returnnewWP_Error('nonce_failure');}if(!array_key_exists($plugin,get_plugins())){returnnewWP_Error('invalid_plugin');}if(0!==validate_file($file,get_plugin_files($plugin))){returnnewWP_Error('bad_plugin_file_path',__('Sorry, that file cannot be edited.'));}$editable_extensions=wp_get_plugin_file_editable_extensions($plugin);$real_file=WP_PLUGIN_DIR.'/'.$file;$is_active=in_array($plugin,(array)get_option('active_plugins',array()),true);}elseif(!empty($args['theme'])){$stylesheet=$args['theme'];if(0!==validate_file($stylesheet)){returnnewWP_Error('bad_theme_path');}if(!current_user_can('edit_themes')){returnnewWP_Error('unauthorized',__('Sorry, you are not allowed to edit templates for this site.'));}$theme=wp_get_theme($stylesheet);if(!$theme->exists()){returnnewWP_Error('non_existent_theme',__('The requested theme does not exist.'));}if(!wp_verify_nonce($args['nonce'],'edit-theme_'.$stylesheet.'_'.$file)){returnnewWP_Error('nonce_failure');}if($theme->errors()&&'theme_no_stylesheet'===$theme->errors()->get_error_code()){returnnewWP_Error('theme_no_stylesheet',__('The requested theme does not exist.').' '.$theme->errors()->get_error_message());}$editable_extensions=wp_get_theme_file_editable_extensions($theme);$allowed_files=array();foreach($editable_extensionsas$type){switch($type){case'php':$allowed_files=array_merge($allowed_files,$theme->get_files('php',-1));break;case'css':$style_files=$theme->get_files('css',-1);$allowed_files['style.css']=$style_files['style.css'];$allowed_files=array_merge($allowed_files,$style_files);break;default:$allowed_files=array_merge($allowed_files,$theme->get_files($type,-1));break;}}// Compare based on relative paths.if(0!==validate_file($file,array_keys($allowed_files))){returnnewWP_Error('disallowed_theme_file',__('Sorry, that file cannot be edited.'));}$real_file=$theme->get_stylesheet_directory().'/'.$file;$is_active=(get_stylesheet()===$stylesheet||get_template()===$stylesheet);}else{returnnewWP_Error('missing_theme_or_plugin');}// Ensure file is real.if(!is_file($real_file)){returnnewWP_Error('file_does_not_exist',__('File does not exist! Please double check the name and try again.'));}// Ensure file extension is allowed.$extension=null;if(preg_match('/.([^.]+)$/',$real_file,$matches)){$extension=strtolower($matches[1]);if(!in_array($extension,$editable_extensions,true)){returnnewWP_Error('illegal_file_type',__('Files of this type are not editable.'));}}$previous_content=file_get_contents($real_file);if(!is_writable($real_file)){returnnewWP_Error('file_not_writable');}$f=fopen($real_file,'w+');if(false===$f){returnnewWP_Error('file_not_writable');}$written=fwrite($f,$content);fclose($f);if(false===$written){returnnewWP_Error('unable_to_write',__('Unable to write to file.'));}wp_opcache_invalidate($real_file,true);if($is_active&&'php'===$extension){$scrape_key=md5(rand());$transient='scrape_key_'.$scrape_key;$scrape_nonce=(string)rand();// It shouldn't take more than 60 seconds to make the two loopback requests.set_transient($transient,$scrape_nonce,60);$cookies=wp_unslash($_COOKIE);$scrape_params=array('wp_scrape_key'=>$scrape_key,'wp_scrape_nonce'=>$scrape_nonce,);$headers=array('Cache-Control'=>'no-cache',);/** This filter is documented in wp-includes/class-wp-http-streams.php */$sslverify=apply_filters('https_local_ssl_verify',false);// Include Basic auth in loopback requests.if(isset($_SERVER['PHP_AUTH_USER'])&&isset($_SERVER['PHP_AUTH_PW'])){$headers['Authorization']='Basic '.base64_encode(wp_unslash($_SERVER['PHP_AUTH_USER']).':'.wp_unslash($_SERVER['PHP_AUTH_PW']));}// Make sure PHP process doesn't die before loopback requests complete.set_time_limit(300);// Time to wait for loopback requests to finish.$timeout=100;$needle_start="###### wp_scraping_result_start:$scrape_key ######";$needle_end="###### wp_scraping_result_end:$scrape_key ######";// Attempt loopback request to editor to see if user just whitescreened themselves.if($plugin){$url=add_query_arg(compact('plugin','file'),admin_url('plugin-editor.php'));}elseif(isset($stylesheet)){$url=add_query_arg(array('theme'=>$stylesheet,'file'=>$file,),admin_url('theme-editor.php'));}else{$url=admin_url();}if(function_exists('session_status')&&PHP_SESSION_ACTIVE===session_status()){// Close any active session to prevent HTTP requests from timing out// when attempting to connect back to the site.session_write_close();}$url=add_query_arg($scrape_params,$url);$r=wp_remote_get($url,compact('cookies','headers','timeout','sslverify'));$body=wp_remote_retrieve_body($r);$scrape_result_position=strpos($body,$needle_start);$loopback_request_failure=array('code'=>'loopback_request_failed','message'=>__('Unable to communicate back with site to check for fatal errors, so the PHP change was reverted. You will need to upload your PHP file change by some other means, such as by using SFTP.'),);$json_parse_failure=array('code'=>'json_parse_error',);$result=null;if(false===$scrape_result_position){$result=$loopback_request_failure;}else{$error_output=substr($body,$scrape_result_position+strlen($needle_start));$error_output=substr($error_output,0,strpos($error_output,$needle_end));$result=json_decode(trim($error_output),true);if(empty($result)){$result=$json_parse_failure;}}// Try making request to homepage as well to see if visitors have been whitescreened.if(true===$result){$url=home_url('/');$url=add_query_arg($scrape_params,$url);$r=wp_remote_get($url,compact('cookies','headers','timeout','sslverify'));$body=wp_remote_retrieve_body($r);$scrape_result_position=strpos($body,$needle_start);if(false===$scrape_result_position){$result=$loopback_request_failure;}else{$error_output=substr($body,$scrape_result_position+strlen($needle_start));$error_output=substr($error_output,0,strpos($error_output,$needle_end));$result=json_decode(trim($error_output),true);if(empty($result)){$result=$json_parse_failure;}}}delete_transient($transient);if(true!==$result){// Roll-back file change.file_put_contents($real_file,$previous_content);wp_opcache_invalidate($real_file,true);if(!isset($result['message'])){$message=__('Something went wrong.');}else{$message=$result['message'];unset($result['message']);}returnnewWP_Error('php_error',$message,$result);}}if($themeinstanceofWP_Theme){$theme->cache_delete();}returntrue;}

Correlato

Utilizzi

Usi Descrizione
wp-admin/includes/file.php: wp_opcache_invalidate()

Tenta di cancellare la cache degli opcode per un singolo file PHP.

wp-admin/includes/file.php: wp_get_plugin_file_editable_extensions()

Ottiene l'elenco delle estensioni dei file modificabili nei plugin.

wp-admin/includes/file.php: wp_get_theme_file_editable_extensions()

Ottiene l'elenco delle estensioni dei file modificabili per un dato tema.

wp-admin/includes/plugin.php: get_plugins()

Controlla la cartella dei plugin e recupera tutti i file con i dati dei plugin.

wp-admin/includes/plugin.php: get_plugin_files()

Ottiene un elenco dei file di un plugin.

wp-includes/capabilities.php: current_user_can()

Restituisce se l'utente corrente ha la capacità specificata.

wp-includes/theme.php: get_template()

Recupera il nome del tema corrente.

wp-includes/theme.php: wp_get_theme()

Ottiene un oggetto WP_Theme per un tema.

wp-includes/theme.php: get_stylesheet()

Recupera il nome del foglio di stile corrente.

wp-includes/l10n.php: __()

Recupera la traduzione di $testo.

wp-includes/formatting.php: wp_unslash()

Rimuove gli slash da una stringa o rimuove ricorsivamente gli slash dalle stringhe all'interno di un array.

wp-includes/pluggable.php: wp_verify_nonce()

Verifica che sia stato usato un nonce di sicurezza corretto con limite di tempo.

wp-includes/class-wp-http-streams.php:https_local_ssl_verify

Filtra se SSL deve essere verificato per le richieste HTTP API locali.

wp-includes/functions.php: validate_file()

Convalida il nome e il percorso di un file rispetto a un insieme di regole consentite.

wp-includes/functions.php: add_query_arg()

Recupera una stringa di query URL modificata.

wp-includes/link-template.php: admin_url()

Recupera l'URL dell'area di amministrazione del sito corrente.

wp-includes/link-template.php: home_url()

Recupera l'URL del sito corrente in cui è accessibile il front-end.

wp-includes/http.php: wp_remote_get()

Esegue una richiesta HTTP con il metodo GET e restituisce la risposta.

wp-includes/http.php: wp_remote_retrieve_body()

Recupera solo il corpo dalla risposta grezza.

wp-includes/plugin.php: applica_filtri()

Richiama le funzioni di callback che sono state aggiunte a un gancio per filtri.

wp-includes/option.php: set_transient()

Imposta/aggiorna il valore di un transitorio.

wp-includes/option.php: delete_transient()

Cancella un transitorio.

wp-includes/option.php: get_option()

Recupera il valore di un'opzione in base al suo nome.

wp-includes/class-wp-error.php: WP_Error::__construct()

Inizializza l'errore.

Utilizzato da

Usato da Descrizione
wp-admin/includes/ajax-actions.php: wp_ajax_edit_theme_plugin_file()

Gestore Ajax per la modifica di un file di tema o plugin.

Changelog

Versione Descrizione
4.9.0 Introdotto.