<?php


/**
 * @file
 * Install hooks for Backup and Migrate.
 */


/**
 * Implementation of hook_requirements().
 */
function backup_migrate_requirements($phase) {
  $requirements = array();

  // Ensure translations don't break during installation.
  $t = get_t();

  if ($phase == 'runtime') {
    // Get a list of all destinations, make sure none of them are publicly
    // accessible.
    // @todo Expand the API to add methods to specifically check this.
    backup_migrate_include('destinations');
    foreach (backup_migrate_get_destinations() as $dest_name => $destination) {
      if (method_exists($destination, 'get_display_location')) {
        $dest_path = $destination->get_display_location();
        if (!empty($dest_path) && file_valid_uri($dest_path)) {
          $scheme = file_uri_scheme($dest_path);
          // Support public and private storage and raw server paths.
          if ($scheme === 'private' || $scheme === 'public' || substr($dest_path, 0, 1) == '/') {
            // Check if the path exists.
            $path_exists = file_prepare_directory($dest_path, FILE_CREATE_DIRECTORY);
            if ($path_exists) {
              $real_path = drupal_realpath($dest_path);
              // See if the private path is somewhere inside the main Drupal
              // directory structure.
              if (strpos($real_path, DRUPAL_ROOT) === 0) {
                // Extract the relative path from the Drupal root path, and
                // then add the base URL, theoretically creating a fully
                // qualified URL to the storage directory.
                $url = substr($real_path, strlen(DRUPAL_ROOT) + 1);
                $url = url($url, array('absolute' => TRUE));
                $result = drupal_http_request($url);

                // If the HTTP request comes back as a status 200 that means
                // there is a directory listing of some sort; directory paths
                // should return a 503 error.
                if (!empty($result->code) && $result->code == 200) {
                  // Get the human readable information for this destination.
                  $dest_spec = $destination->get_list_row();

                  // Display a warning message.
                  $requirements['bmdest_' . $dest_name] = array(
                    'severity' => REQUIREMENT_ERROR,
                    'title' => 'Backup Migrate',
                    'value' => $t('Backup destination "%dest" is publicly accessible!', array('%dest' => $dest_spec['name'])),
                    'description' => $t('The backup destination, "%dest", stores its files in the "%path" directory. This directory is publicly available from the web server and urgently needs to be secured! Please see the Drupal manual on <a href="@manual">configuring the private directory path</a> on how to fix this problem.',
                      array(
                        '%dest' => $dest_spec['name'],
                        '%path'  => $real_path,
                        '@manual' => 'https://www.drupal.org/docs/7/core/modules/file/overview',
                      )),
                  );
                }

                // Check an individual file.
                else {
                  $files = scandir($real_path);
                  if (!empty($files)) {
                    foreach ($files as $file) {
                      // Skip the base field pointers.
                      if ($file == '.' || $file == '..') {
                        continue;
                      }

                      $result = drupal_http_request($url . '/' . $file);

                      // If the HTTP request comes back as a status 200 that
                      // means the file is accessible.
                      if (!empty($result->code) && $result->code == 200) {
                        // Get the human readable information for this
                        // destination.
                        $dest_spec = $destination->get_list_row();

                        // Display a warning message.
                        $requirements['bmdest_' . $dest_name] = array(
                          'severity' => REQUIREMENT_ERROR,
                          'title' => 'Backup Migrate',
                          'value' => $t('Files in "%dest" are publicly accessible!', array('%dest' => $dest_spec['name'])),
                          'description' => $t('The backup destination, "%dest", stores its files in the "%path" directory. These file(s) are publicly available from the web server and urgently need to be secured! Please see the Drupal manual on <a href="@manual">configuring the private directory path</a> on how to fix this problem.',
                            array(
                              '%dest' => $dest_spec['name'],
                              '%path'  => $real_path,
                              '@manual' => 'https://www.drupal.org/docs/7/core/modules/file/overview',
                            )),
                        );
                      }

                      // Only need to check one file.
                      break;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    // Leave a note if there were no problems.
    // @todo No point in displaying this until the API has been expanded.
    // if (empty($requirements)) {
    //   $requirements['bmdest_' . $dest_name] = array(
    //     'severity' => REQUIREMENT_INFO,
    //     'title' => 'Backup Migrate',
    //     'value' => $t('Backup destinations are safe'),
    //     'description' => $t('The backup destinations were all checked and none of them were exposing files to the public. This is a good thing.'),
    //   );
    // }
  }

  return $requirements;
}

/**
 * Implementation of hook_schema().
 */
function backup_migrate_schema() {
  $schema['backup_migrate_profiles'] = array(
    'export' => array(
      'key' => 'machine_name',
      'key name' => 'Profile ID',
      'admin_title' => 'name',
      'primary key' => 'profile_id',
      'identifier' => 'item', // Exports will be defined as $preset
      'default hook' => 'exportables_backup_migrate_profiles',  // Function hook name.
      'api' => array(
        'owner' => 'backup_migrate',
        'api' => 'backup_migrate_exportables',  // Base name for api include files.
        'minimum_version' => 1,
        'current_version' => 1,
      ),
    ),
    'fields' => array(
      'profile_id' => array(
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'description' => 'Primary ID field for the table. Not used for anything except internal lookups.',
        'no export' => TRUE, // Do not export database-only keys.
      ),
      'machine_name' => array(
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '0',
        'description' => 'The primary identifier for a profile.',
      ),
      'name' => array(
        'description' => 'The name of the profile.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE
      ),
      'filename' => array(
        'description' => 'The name of the profile.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE
      ),
      'append_timestamp' => array(
        'description' => 'Append a timestamp to the filename.',
        'type' => 'int',
        'size' => 'tiny',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0
      ),
      'timestamp_format' => array(
        'description' => 'The format of the timestamp.',
        'type' => 'varchar',
        'length' => 14,
        'not null' => TRUE
      ),
      'filters' => array(
        'description' => 'The filter settings for the profile.',
        'type' => 'text',
        'not null' => TRUE,
        'serialize' => TRUE,
        'serialized default' => 'a:0:{}',
      ),
    ),
    'primary key' => array('profile_id'),
  );
  $schema['backup_migrate_destinations'] = array(
    'export' => array(
      'key' => 'machine_name',
      'key name' => 'Destination ID',
      'admin_title' => 'name',
      'primary key' => 'destination_id',
      'identifier' => 'item', // Exports will be defined as $preset
      'default hook' => 'exportables_backup_migrate_destinations',  // Function hook name.
      'api' => array(
        'owner' => 'backup_migrate',
        'api' => 'backup_migrate_exportables',  // Base name for api include files.
        'minimum_version' => 1,
        'current_version' => 1,
      ),
    ),
    'fields' => array(
      'destination_id' => array(
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'description' => 'Primary ID field for the table. Not used for anything except internal lookups.',
        'no export' => TRUE, // Do not export database-only keys.
      ),
      'machine_name' => array(
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '0',
        'description' => 'The primary identifier for a destination.',
      ),
      'name' => array(
        'description' => 'The name of the destination.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE
      ),
      'subtype' => array(
        'description' => 'The type of the destination.',
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE
      ),
      'location' => array(
        'description' => 'The the location string of the destination.',
        'type' => 'text',
        'not null' => TRUE
      ),
      'settings' => array(
        'description' => 'Other settings for the destination.',
        'type' => 'text',
        'not null' => TRUE,
        'serialize' => TRUE,
        'serialized default' => 'a:0:{}',
     ),
    ),
    'primary key' => array('destination_id'),
  );
  $schema['backup_migrate_sources'] = array(
    'export' => array(
      'key' => 'machine_name',
      'key name' => 'Source ID',
      'admin_title' => 'name',
      'primary key' => 'source_id',
      'identifier' => 'item', // Exports will be defined as $preset
      'default hook' => 'exportables_backup_migrate_sources',  // Function hook name.
      'api' => array(
        'owner' => 'backup_migrate',
        'api' => 'backup_migrate_exportables',  // Base name for api include files.
        'minimum_version' => 1,
        'current_version' => 1,
      ),
    ),
    'fields' => array(
      'source_id' => array(
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'description' => 'Primary ID field for the table. Not used for anything except internal lookups.',
        'no export' => TRUE, // Do not export database-only keys.
      ),
      'machine_name' => array(
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '0',
        'description' => 'The primary identifier for a source.',
      ),
      'name' => array(
        'description' => 'The name of the source.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE
      ),
      'subtype' => array(
        'description' => 'The type of the source.',
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE
      ),
      'location' => array(
        'description' => 'The the location string of the source.',
        'type' => 'text',
        'not null' => TRUE
      ),
      'settings' => array(
        'description' => 'Other settings for the source.',
        'type' => 'text',
        'not null' => TRUE,
        'serialize' => TRUE,
        'serialized default' => 'a:0:{}',
     ),
    ),
    'primary key' => array('source_id'),
  );

  $schema['backup_migrate_schedules'] = array(
    'export' => array(
      'key' => 'machine_name',
      'key name' => 'Source ID',
      'admin_title' => 'name',
      'primary key' => 'schedule_id',
      'identifier' => 'item', // Exports will be defined as $preset
      'default hook' => 'exportables_backup_migrate_schedules',  // Function hook name.
      'api' => array(
        'owner' => 'backup_migrate',
        'api' => 'backup_migrate_exportables',  // Base name for api include files.
        'minimum_version' => 1,
        'current_version' => 1,
      ),
    ),
    'fields' => array(
      'schedule_id' => array(
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'description' => 'Primary ID field for the table. Not used for anything except internal lookups.',
        'no export' => TRUE, // Do not export database-only keys.
      ),
      'machine_name' => array(
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '0',
        'description' => 'The primary identifier for a profile.',
      ),
      'name' => array(
        'description' => 'The name of the profile.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE
      ),
      'source_id' => array(
        'description' => 'The {backup_migrate_destination}.destination_id of the source to backup from.',
        'type' => 'varchar',
        'length' => 255,
        'default' => 'db',
        'not null' => TRUE
      ),
      'destination_id' => array(
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '0',
        'description' => 'The {backup_migrate_destination}.destination_id of the destination to back up to.',
      ),
      'copy_destination_id' => array(
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE,
        'default' => '0',
        'description' => 'A second {backup_migrate_destination}.destination_id of the destination to copy the backup to.',
      ),
      'profile_id' => array(
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '0',
        'description' => 'The primary identifier for a profile.',
      ),
      'keep' => array(
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
        'description' => 'The number of backups to keep.',
      ),
      'period' => array(
        'type' => 'int',
        'not null' => TRUE,
        'default' => 0,
        'description' => 'The number of seconds between backups.',
      ),
      'enabled' => array(
        'description' => 'Whether the schedule is enabled.',
        'type' => 'int',
        'size' => 'tiny',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0
      ),
      'cron' => array(
        'description' => 'Whether the schedule should be run during cron.',
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE,
        'default' => 'builtin',
      ),
      'cron_schedule' => array(
        'description' => 'The cron schedule to run on.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
        'default' => '0 4 * * *',
      ),
    ),
    'primary key' => array('schedule_id'),
  );

  return $schema;
}

/**
 * Implementation of hook_install().
 */
function backup_migrate_install() {
}

/**
 * Remove variables on uninstall.
 */
function backup_migrate_uninstall() {
  db_query("DELETE FROM {variable} WHERE name LIKE 'backup_migrate_%'");
  db_query("DELETE FROM {variable} WHERE name LIKE 'nodesquirrel_%'");
  cache_clear_all('variables', 'cache');
}

/**
 * Update from 1.x to 2.x.
 */
function backup_migrate_update_2000() {
  _backup_migrate_setup_database_defaults();
  return array();
}

/**
 * Adding filter field for dev release of 2009-01-28
 */
function backup_migrate_update_2001() {
  $ret = array();
  $schema = drupal_get_schema_unprocessed('backup_migrate', 'backup_migrate_profiles');

  // Add the filters field to the db.
  if (!db_field_exists('backup_migrate_profiles', 'filters')) {
    db_add_field('backup_migrate_profiles', 'filters', array('description' => t('The filter settings for the profile.'),'type' => 'text', 'not null' => TRUE));
  }
  // Add the source field
  if (!db_field_exists('backup_migrate_profiles', 'source_id')) {
    db_add_field('backup_migrate_profiles', 'source_id', array('description' => t('The {backup_migrate_destination}.destination_id of the source to backup from.'), 'type' => 'varchar', 'length' => 255, 'default' => 'db', 'not null' => TRUE));
  }
  // Remove the compression field.
  if (db_field_exists('backup_migrate_profiles', 'compression')) {
    db_drop_field('backup_migrate_profiles', 'compression');
  }
  return $ret;
}

/**
 * Clearing the cache because there was a menu structure change in the dev of 2009-05-31
 */
function backup_migrate_update_2002() {
  // Cache should clear automatically. Nothing to do here.
  return array();
}

/**
 * Allowing non-int profile ids in schedules 2009-05-31
 */
function backup_migrate_update_2003() {
  $ret = array();
  $spec = array(
    'type' => 'varchar',
    'length' => 255,
    'not null' => TRUE,
    'default' => '0',
    'description' => 'The primary identifier for a profile.',
  );

  db_change_field('backup_migrate_schedules', 'profile_id', 'profile_id', $spec);
  return $ret;
}

/**
 * Allowing non-int profile ids 2009-07-01
 */
function backup_migrate_update_2004() {
  $ret = array();
  $spec = array(
    'type' => 'varchar',
    'length' => 255,
    'not null' => TRUE,
    'default' => '0',
  );

  $spec['description'] = 'The primary identifier for a destination.';
  db_change_field('backup_migrate_destinations', 'destination_id', 'destination_id', $spec);

  $spec['description'] = 'The primary identifier for a profile.';
  db_change_field('backup_migrate_profiles', 'profile_id', 'profile_id', $spec);

  $spec['description'] = 'The primary identifier for a schedule.';
  db_change_field('backup_migrate_schedules', 'schedule_id', 'schedule_id', $spec);

  // Drop the user/pass fields as they weren't being used.
  if (db_field_exists('backup_migrate_destinations', 'username')) {
    db_drop_field('backup_migrate_destinations', 'username');
  }
  if (db_field_exists('backup_migrate_destinations', 'password')) {
    db_drop_field('backup_migrate_destinations', 'password');
  }

  return $ret;
}

/**
 * Change the default database id to something friendlier 2009-08-08
 */
function backup_migrate_update_2005() {
  require_once './'. drupal_get_path('module', 'backup_migrate') .'/includes/crud.inc';
  require_once './'. drupal_get_path('module', 'backup_migrate') .'/includes/profiles.inc';

  $ret = array();
  // Change the destination ids of the defined database sources mostly to make using them with drush friendlier.

  // Change the db_url:default id to simply 'db'
  $ret[] = db_query("UPDATE {backup_migrate_profiles} SET source_id = 'db' WHERE source_id = 'db_url:default'");
  $ret[] = db_query("UPDATE {backup_migrate_schedules} SET destination_id = 'db' WHERE destination_id = 'db_url:default'");

  // Change the defined db keys from db_url:key to db:key.
  $ret[] = db_query("UPDATE {backup_migrate_profiles} SET source_id = REPLACE(source_id, 'db_url:', 'db:')");
  $ret[] = db_query("UPDATE {backup_migrate_schedules} SET destination_id = REPLACE(destination_id, 'db_url:', 'db:')");

  // Add the source field to the schedule
  if (!db_field_exists('backup_migrate_schedules', 'source_id')) {
    db_add_field('backup_migrate_schedules', 'source_id', array('description' => t('The db source to backup from.'), 'type' => 'varchar', 'length' => 255, 'default' => 'db', 'not null' => TRUE));
  }

  // Copy source data from profiles to schedules.
  $result = db_query('SELECT p.source_id, s.schedule_id FROM {backup_migrate_schedules} s LEFT JOIN {backup_migrate_profiles} p ON s.profile_id = p.profile_id', array(), array('fetch' => PDO::FETCH_ASSOC));
  foreach ($result as $schedule) {
    if (!$schedule['source_id']) {
      $schedule['source_id'] = 'db';
    }
    $ret[] = db_query("UPDATE {backup_migrate_schedules} SET source_id = '". $schedule['source_id'] ."' WHERE schedule_id = '". $schedule['profile_id'] ."'");
  }

  if (db_field_exists('backup_migrate_profiles', 'source_id')) {
    db_drop_field('backup_migrate_profiles', 'source_id');
  }

  // Copy the no-data and exclude tables settings into the 'filter' field.
  $result = db_query('SELECT * FROM {backup_migrate_profiles}', array(), array('fetch' => PDO::FETCH_ASSOC));
  foreach ($result as $item) {
    if (isset($item['nodata_tables']) && isset($item['exclude_tables'])) {
      $profile = backup_migrate_get_profile($item['profile_id']);
      $profile->filters['nodata_tables'] = unserialize($item['nodata_tables']);
      $profile->filters['exclude_tables'] = unserialize($item['exclude_tables']);
      $profile->save();
    }
  }
  if (db_field_exists('backup_migrate_profiles', 'nodata_tables')) {
    db_drop_field('backup_migrate_profiles', 'nodata_tables');
  }
  if (db_field_exists('backup_migrate_profiles', 'exclude_tables')) {
    db_drop_field('backup_migrate_profiles', 'exclude_tables');
  }

  return $ret;
}

/**
 * Move the backup and migrate directory to the private directory.
 */
function backup_migrate_update_7200() {
  $from = 'public://backup_migrate';
  $to   = 'private://backup_migrate';
  if (drupal_realpath($from) && !drupal_realpath($to)) {
    if (!rename($from, $to)) {
      drupal_set_message(t('Unable to move the backups directory to your private folder, please check file permissions and move the directory %from to %to', array('%from' => drupal_realpath($from), '%to' => drupal_realpath($to))), 'warning');
    }
  }
}


/**
 * Change the filename field to support 255 characters.
 */
function backup_migrate_update_7202() {
  $ret = array();
  db_change_field('backup_migrate_profiles', 'filename', 'filename', array('type' => 'varchar', 'length' => 255, 'not null' => TRUE));
  return $ret;
}


/**
 * Update the schedule last run times to use variables instead of saving with the schedule.
 */
function backup_migrate_update_7203() {
  $result = db_query('SELECT * FROM {backup_migrate_schedules}', array(), array('fetch' => PDO::FETCH_ASSOC));
  foreach ($result as $item) {
    if (isset($item['last_run'])) {
      variable_set('backup_migrate_schedule_last_run_' . $item['schedule_id'], $item['last_run']);
    }
  }
  if (db_field_exists('backup_migrate_schedules', 'last_run')) {
    db_drop_field('backup_migrate_schedules', 'last_run');
  }
}

/**
 * Uninstall backup migrate files if it's installed
 */
function backup_migrate_update_7300() {
  if (module_exists('backup_migrate_files')) {
    module_disable(array('backup_migrate_files'));
    $ret[] = array(
      'success' => true,
      'query' => 'Disabled the Backup and Migrate Files module',
    );
  }
  if (module_exists('nodesquirrel')) {
    module_disable(array('nodesquirrel'));
    $ret[] = array(
      'success' => true,
      'query' => 'Disabled the NodeSquirrel module',
    );
  }

  // Add sources to the schema.
  $schema['backup_migrate_sources'] = array(
    'fields' => array(
      'source_id' => array(
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE,
        'default' => '0',
        'description' => t('The primary identifier for a source.'),
      ),
      'name' => array(
        'description' => t('The name of the source.'),
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE
      ),
      'type' => array(
        'description' => t('The type of the source.'),
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE
      ),
      'location' => array(
        'description' => t('The the location string of the source.'),
        'type' => 'text',
        'not null' => TRUE
      ),
      'settings' => array(
        'description' => t('Other settings for the source.'),
        'type' => 'text',
        'not null' => TRUE,
        'serialize' => TRUE,
        'serialized default' => 'a:0:{}',
     ),
    ),
    'primary key' => array('source_id'),
  );

  if (!db_table_exists('backup_migrate_sources')) {
    db_create_table('backup_migrate_sources', $schema['backup_migrate_sources']);
  }

  // Move custom destinations to sources.
  $result = db_query("SELECT * FROM {backup_migrate_destinations} WHERE type in ('filesource', 'db')", array(), array('fetch' => PDO::FETCH_ASSOC));
  foreach ($result as $item) {
    $item['source_id'] = $item['destination_id'];
    drupal_write_record('backup_migrate_source', $item);
  }

  // Change 'destination' settings to 'source' settings
  $result = db_query('SELECT * FROM {backup_migrate_profiles}', array(), array('fetch' => PDO::FETCH_ASSOC));
  foreach ($result as $item) {
    $item['filters'] = unserialize($item['filters']);
    $item['filters']['sources'] = $item['filters']['destinations'];
    unset($item['filters']['destinations']);
    drupal_write_record('backup_migrate_profiles', $item, array('profile_id'));
  }
}

/**
 * Switch the cron switch to text.
 */
function backup_migrate_update_7301() {
  db_change_field('backup_migrate_schedules', 'cron', 'cron', array('type' => 'varchar', 'length' => 32, 'not null' => TRUE, 'default' => 'builtin'));
  db_add_field('backup_migrate_schedules', 'cron_schedule', array('description' => 'The cron schedule to run on.', 'type' => 'varchar', 'length' => 255, 'default' => '0 4 * * *', 'not null' => TRUE));
}

/**
 * Add a second destination to schedules.
 */
function backup_migrate_update_7302() {
  db_add_field('backup_migrate_schedules', 'copy_destination_id', 
    array(
        'type' => 'varchar',
        'length' => 32,
        'not null' => TRUE,
        'default' => '0',
        'description' => 'A second {backup_migrate_destination}.destination_id of the destination to copy the backup to.',
      )
  );
}

/**
 * Add a serial id field to all tables to allow them to be ctools exportable.
 */
function backup_migrate_update_7303() {
  foreach (array('backup_migrate_sources' => 'source_id', 'backup_migrate_destinations' => 'destination_id', 'backup_migrate_schedules' => 'schedule_id', 'backup_migrate_profiles' => 'profile_id') as $table => $id) {
    // Take the primary key status from the machine name so it can be renamed
    // A serial field must be defined as a key, so make a temporary index.
    // See: https://www.drupal.org/node/190027
    db_add_index($table, 'temp', array($id));
    db_drop_primary_key($table);
    // Drop our temporary index.
    db_drop_index($table, 'temp');

    // Switch the name of the id to 'machine_name' to be more ctools standard
    db_change_field($table, $id, 'machine_name', array('type' => 'varchar', 'length' => 32, 'not null' => TRUE));

    // Add a serial ID
    db_add_field($table, $id, 
      array(
          'type' => 'serial',
          'unsigned' => TRUE,
          'not null' => TRUE,
          'description' => 'Primary ID field for the table. Not used for anything except internal lookups.',
          'no export' => TRUE, // Do not export database-only keys.
        ),
        array('primary key' => array($id))
    );
  }
  foreach (array('backup_migrate_sources', 'backup_migrate_destinations') as $table) {
    db_change_field($table, 'type', 'subtype', array('type' => 'varchar', 'length' => 32, 'not null' => TRUE));
  }
}

/**
 * Update all schedules to use the built in cron if none is specified.
 */
function backup_migrate_update_7304() {
  db_query("UPDATE {backup_migrate_schedules} SET cron = 'builtin' WHERE cron = '0'");
}

/**
 * Fix schema mismatch after upgrade.
 */
function backup_migrate_update_7305() {
  foreach (array('backup_migrate_profiles', 'backup_migrate_destinations', 'backup_migrate_sources', 'backup_migrate_schedules') as $table) {
    db_change_field($table, 'machine_name', 'machine_name', array(
      'type' => 'varchar',
      'length' => 255,
      'not null' => TRUE,
      'default' => '0',
    ));
  }
  db_change_field('backup_migrate_schedules', 'cron', 'cron', array(
    'type' => 'varchar',
    'length' => 32,
    'not null' => TRUE,
    'default' => 'builtin',
  ));
}

/**
 * Leave a message to explain the mixup over the backup option.
 */
function backup_migrate_update_7306() {
  drupal_set_message(t('Please note that release 7.x-3.4 had a bug which caused all backups to be overwritten instead of having a timestamp added. Please review all backup settings to ensure they work as intended.'), 'warning');
}
