You are here

function backup_migrate_destination_files::check_web_dir in Backup and Migrate 6.3

Same name and namespace in other branches
  1. 8.2 includes/destinations.file.inc \backup_migrate_destination_files::check_web_dir()
  2. 8.3 includes/destinations.file.inc \backup_migrate_destination_files::check_web_dir()
  3. 6.2 includes/destinations.file.inc \backup_migrate_destination_files::check_web_dir()
  4. 7.3 includes/destinations.file.inc \backup_migrate_destination_files::check_web_dir()
  5. 7.2 includes/destinations.file.inc \backup_migrate_destination_files::check_web_dir()

Check that a web accessible directory has been properly secured, othewise attempt to secure it.

1 call to backup_migrate_destination_files::check_web_dir()
backup_migrate_destination_files::check_dir in includes/destinations.file.inc
Prepare the destination directory for the backups.

File

includes/destinations.file.inc, line 233
A destination type for saving locally to the server.

Class

backup_migrate_destination_files
A destination type for saving locally to the server.

Code

function check_web_dir($directory) {

  // If the directory is specified with an absolute path, strip the site root.
  $directory = substr(realpath($directory), strlen(realpath($_SERVER['DOCUMENT_ROOT']) . base_path()));

  // Check if the file has already been tested.
  if (is_file($directory . '/tested.txt')) {
    return $directory;
  }
  else {

    // Check for a htaccess file which adequately protects the backup files.
    $htaccess_lines = "order allow,deny\ndeny from all\n";
    if (!is_file($directory . '/.htaccess') || !is_readable($directory . '/.htaccess') || strpos(file_get_contents($directory . '/.htaccess'), $htaccess_lines) === FALSE) {

      // Attempt to protect the backup files from public access using htaccess.
      if (($fp = @fopen($directory . '/.htaccess', 'w')) && @fputs($fp, $htaccess_lines)) {
        fclose($fp);
        chmod($directory . '/.htaccess', 0664);
      }
      else {
        $message = "Security warning: Couldn't modify .htaccess file. Please create a .htaccess file in your %directory directory which contains the following lines: <code>!htaccess</code> or add them to the existing .htaccess file";
        $replace = array(
          '%directory' => $directory,
          '!htaccess' => '<br />' . nl2br(check_plain($htaccess_lines)),
        );
        drupal_set_message(t($message, $replace), "error");
        watchdog('security', t($message, $replace), WATCHDOG_ERROR);
        return FALSE;
      }
    }

    // Check the user agent to make sure we're not responding to a request from drupal itself.
    // That should prevent infinite loops which could be caused by poormanscron in some circumstances.
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'Drupal') !== FALSE) {
      return FALSE;
    }

    // Check to see if the destination is publicly accessible
    $test_contents = "this file should not be publicly accessible";

    // Create the the text.txt file if it's not already there.
    if (!is_file($directory . '/test.txt') || file_get_contents($directory . '/test.txt') != $test_contents) {
      if ($fp = fopen($directory . '/test.txt', 'w')) {
        @fputs($fp, $test_contents);
        fclose($fp);
      }
      else {
        $message = t("Security notice: Backup and Migrate was unable to write a test text file to the destination directory %directory, and is therefore unable to check the security of the backup destination. Backups to the server will be disabled until the destination becomes writable and secure.", array(
          '%directory' => $directory,
        ));
        drupal_set_message($message, "error");
        return FALSE;
      }
    }

    // Attempt to read the test file via http. This may fail for other reasons,
    // so it's not a bullet-proof check.
    if ($this
      ->test_file_readable_remotely($directory . '/test.txt', $test_contents)) {
      $message = t("Security notice: Backup and Migrate will not save backup files to the server because the destination directory is publicly accessible. If you want to save files to the server, please secure the '%directory' directory", array(
        '%directory' => $directory,
      ));
      drupal_set_message($message, "error");
      return FALSE;
    }

    // Directory tested OK, so we mark it as tested.
    if ($fp = fopen($directory . '/tested.txt', 'w')) {
      $contents = t('The presence of this file indicates that this directory has been tested as safe to use as a destination for Backup and Migrate. If you change the permissions of this directory or change your web server settings, please delete this file so that the directory can be checked again.');
      @fputs($fp, $contents);
      fclose($fp);
    }
    return $directory;
  }
}