Install WordPress plugins without WP-admin access

Install WordPress plugins without admin access, and automate your WordPress customization and plugin installation. WordPress has a little drop-in plugin option available in the form of /wp-content/install.php. This install.php file is not present at default, but when created it can be used to install plugins without wp-admin access. This might come in handy for unattended WordPress installations, customization, and so on.

If you have access to the FTP environment of a WordPress website you can use this to force the installation of plugins for example. Suppose you are a webhoster and you want your customers to install a captcha- or cache-plugin, this is what you can use. Of course this is very intrusive.

The install.php file requires the wp-admin/includes/plugin.php file, and then uses an array of plugin names to install. Files are downloaded automatically through WordPress’s API, are unpacked and activated.

All you need to do is populate the array with plugin names you want to install.

WordPress install.php example code

Here you have a PHP example that’ll install a captcha- and db-cache plugin:

<?php
/**
 * Install WordPress plugins without WP-Admin access
 * Jan Reilink, Twitter: HertogJanR
 * Author URI: https://www.saotn.org
 */

require( "../wp-admin/includes/plugin.php" );
$wpkgr_selected_plugins = array ( 
  0 => 'captcha',
  1 => 'db-cache-reloaded-fix', 
);

if( $wpkgr_selected_plugins !== NULL ) {

  foreach ( $wpkgr_selected_plugins as $plugin ) {
    $request = new StdClass();
    $request->slug = stripslashes( $plugin );
    $post_data = array( 
      'action' => 'plugin_information', 
      'request' => serialize( $request )
    );
    $options = array( 
      CURLOPT_URL => 'http://api.wordpress.org/plugins/info/1.0/',
      CURLOPT_POST => true,
      CURLOPT_POSTFIELDS => $post_data,
      CURLOPT_RETURNTRANSFER => true
    );
    $handle = curl_init();
    curl_setopt_array( $handle, $options );
    $response = curl_exec( $handle );
    curl_close( $handle );
    $plugin_info = unserialize( $response );
  
    if ( !file_exists( WP_CONTENT_DIR . '/plugins/' . $plugin_info->slug ) ) {
      echo "Downloading and Extracting $plugin_info->name";
      $file = WP_CONTENT_DIR . '/plugins/' . basename( $plugin_info->download_link );
      $fp = fopen( $file, 'w' );

      /**
       * Don't turn off CURLOPT_SSL_VERIFYPEER, but fix your PHP configuration - find out how:
       * https://www.saotn.org/dont-turn-off-curlopt_ssl_verifypeer-fix-php-configuration/
       */
      $ch = curl_init();
      curl_setopt( $ch, CURLOPT_USERAGENT, 'WPKGR' );
      curl_setopt( $ch, CURLOPT_URL, $plugin_info->download_link );
      curl_setopt( $ch, CURLOPT_FAILONERROR, TRUE );
      curl_setopt( $ch, CURLOPT_HEADER, 0 );
      @curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, TRUE );
      curl_setopt( $ch, CURLOPT_AUTOREFERER, TRUE );
      curl_setopt( $ch, CURLOPT_BINARYTRANSFER, TRUE );
      curl_setopt( $ch, CURLOPT_TIMEOUT, 120 );
      curl_setopt( $ch, CURLOPT_FILE, $fp );
      $b = curl_exec( $ch );

      if ( !$b ) {
        $message = 'Download error: '. curl_error( $ch ) .', please try again';
        curl_close( $ch );
        throw new Exception( $message );
      }

      fclose($fp);

      if ( !file_exists( $file ) ) throw new Exception( 'Zip file not downloaded' );

      if ( class_exists( 'ZipArchive' ) ) {
        $zip = new ZipArchive;
        if( $zip->open( $file ) !== TRUE ) throw new Exception( 'Unable to open Zip file' );
        $zip->extractTo( ABSPATH . 'wp-content/plugins/' );
        $zip->close();
      }
      else {
        die( "no zip possible" );
      }
      unlink( $file );
      echo "<strong>Done!</strong><br />";
    } //end if file exists

  } //end foreach
  
} //if plugins

echo "Configuring WordPress";

  function run_activate_plugin( $plugin ) {
    $current = get_option( 'active_plugins' );
    $plugin = plugin_basename( trim( $plugin ) );
    $current[] = $plugin;
    sort( $current );
    do_action( 'activate_plugin', trim( $plugin ) );
    update_option( 'active_plugins', $current );
    do_action( 'activate_' . trim( $plugin ) );
    do_action( 'activated_plugin', trim( $plugin) );
  }

if( $wpkgr_selected_plugins !== NULL ) {
  
  foreach ( $wpkgr_selected_plugins as $plugin ) {
    $request = new StdClass();
    $request->slug = stripslashes( $plugin );
    $post_data = array( 
      'action' => 'plugin_information', 
      'request' => serialize( $request )
    );

    $options = array( 
      CURLOPT_URL => 'http://api.wordpress.org/plugins/info/1.0/',
      CURLOPT_POST => true,
      CURLOPT_POSTFIELDS => $post_data,
      CURLOPT_RETURNTRANSFER => true
    );

    $handle = curl_init();
    curl_setopt_array( $handle, $options );
    $response = curl_exec( $handle );
    curl_close( $handle );
    $plugin_info = unserialize( $response );
    $daplugins = get_plugins( '/' . $plugin_info->slug );
    $paths = array_keys( $daplugins );
    $plugin_file = $plugin_info->slug . '/' . $paths[0];
    run_activate_plugin( $plugin_file );
  } //end foreach
} //if plugins

echo "<strong>Done!</strong>";

// Let's delete install.php
unlink( ABSPATH . 'wp-content/install.php' );
?>Code language: PHP (php)

The install.php will be automatically removed when it’s finished.

More on WordPress’ install.php plugin drop-in and customizing WordPress installation

You can find more information in the following posts:

Jan Reilink

Hi, my name is Jan. I am not a hacker, coder, developer or guru. I am merely an application manager / systems administrator, doing my daily thing at Embrace - The Human Cloud. In the past I worked for clidn and Vevida. With over 20 years of experience, my specialties include Windows Server, IIS, Linux (CentOS, Debian), security, PHP, websites & optimization. I blog at https://www.saotn.org.

1 Comment
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
T
28/03/2020 20:27

hi dear friend, thanks for this
i have a question
which parts of the file should be edited for another plugin?
i cant open that link you pointed!