--- backup_migrate.module.orig	2009-01-20 13:31:02.000000000 +0200
+++ backup_migrate.module	2009-01-20 13:19:06.000000000 +0200
@@ -25,6 +25,8 @@ function backup_migrate_menu() {
   $items['admin/content/backup_migrate/export'] = array(
     'title' => t('Backup/Export DB'),
     'description' => t('Backup the database.'),
+    'page callback' => '_backup_migrate_export',
+    'access arguments' => array('perform backup'),
     'weight' => 0,
     'type' => MENU_DEFAULT_LOCAL_TASK,
   );
@@ -103,17 +105,18 @@ function backup_migrate_cron() {
       foreach ($databases as $db => $url) {
         _backup_migrate_dump_tables(
           $db,
-          variable_get("backup_migrate_file_name", _backup_migrate_default_file_name()),
-          variable_get("backup_migrate_exclude_tables", _backup_migrate_default_exclude_tables()),
-        variable_get("backup_migrate_nodata_tables", _backup_migrate_default_structure_only_tables()),
+          variable_get("backup_migrate_file_name_$db", _backup_migrate_default_file_name($db)),
+          variable_get("backup_migrate_exclude_tables_$db", _backup_migrate_default_exclude_tables($db)),
+        variable_get("backup_migrate_nodata_tables_$db", _backup_migrate_default_structure_only_tables($db)),
         'sql',
         "save",
-        variable_get("backup_migrate_compression", "none"),
+        variable_get("backup_migrate_compression_$db", "none"),
         "scheduled",
-        variable_get("backup_migrate_timestamp_format", 'Y-m-d\TH-i-s')
+        variable_get("backup_migrate_timestamp_format_$db", 'Y-m-d\TH-i-s')
         );
+      }
 
-      // Set the timestamp to indecate last backup time.
+      // Set the timestamp to indicate last backup time.
       variable_set("backup_migrate_schedule_last_backup", $now);
 
       // Delete older backups if needed.
@@ -208,28 +211,90 @@ function backup_migrate_schedule() {
  */
 function backup_migrate_backup() {
   $form = array();
-  $tables = _backup_migrate_get_table_names();
-  $form['backup_migrate_exclude_tables'] = array(
-    "#type" => "select",
-    "#multiple" => TRUE,
-    "#title" => t("Exclude the following tables altogether"),
-    "#options" => $tables,
-    "#default_value" => variable_get("backup_migrate_exclude_tables", _backup_migrate_default_exclude_tables()),
-    "#description" => t("The selected tables will not be added to the backup file."),
-  );
-  $form['backup_migrate_nodata_tables'] = array(
-    "#type" => "select",
-    "#multiple" => TRUE,
-    "#title" => t("Exclude the data from the following tables"),
-    "#options" => $tables,
-    "#default_value" => variable_get("backup_migrate_nodata_tables", _backup_migrate_default_structure_only_tables()),
-    "#description" => t("The selected tables will have their structure backed up but not their contents. This is useful for excluding cache data to reduce file size."),
-  );
-  $form['backup_migrate_file_name'] = array(
-    "#type" => "textfield",
-    "#title" => t("Backup file name"),
-    "#default_value" => variable_get("backup_migrate_file_name", _backup_migrate_default_file_name()),
-  );
+  $databases = db_maintenance_get_databases();
+
+  foreach ($databases as $db => $url) {
+    $dbname = ($db=='default') ? 'Drupal' : $db;
+    $tables = _db_maintenance_list_tables($db);
+
+    $form[$db] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Backup Settings for @DB', array('@DB' => $dbname, )),
+      '#collapsible' => TRUE,
+      '#collapsed' => FALSE,
+    );
+
+    $form[$db]['backup_migrate_exclude_tables_'.$db] = array(
+      "#type" => "select",
+      "#multiple" => TRUE,
+      "#title" => t("Exclude the following tables from @DB altogether", array('@DB' => $dbname, )),
+      "#options" => $tables,
+      "#default_value" => variable_get("backup_migrate_exclude_tables_$db", _backup_migrate_default_exclude_tables($db)),
+      "#description" => t("The selected tables will not be added to the backup file of the @DB database.", array('@DB' => $dbname, )),
+    );
+
+    $form[$db]['backup_migrate_nodata_tables_'.$db] = array(
+      "#type" => "select",
+      "#multiple" => TRUE,
+      "#title" => t("Exclude the data from the following tables in @DB", array('@DB' => $dbname, )),
+      "#options" => $tables,
+      "#default_value" => variable_get("backup_migrate_nodata_tables_$db", _backup_migrate_default_structure_only_tables($db)),
+      "#description" => t("The selected tables will have their structure backed up but not their contents. This is useful for excluding cache data to reduce file size."),
+    );
+    $form[$db]['backup_migrate_file_name_'.$db] = array(
+      "#type" => "textfield",
+      "#title" => t("Backup file name for the @DB database", array('@DB' => $dbname, )),
+      "#default_value" => variable_get("backup_migrate_file_name_$db", _backup_migrate_default_file_name()),
+    );
+
+    $compression_options = array("none" => "None");
+    if (@function_exists("gzencode")) {
+      $compression_options['gzip'] = "GZip";
+    }
+    if (@function_exists("bzcompress")) {
+      $compression_options['bzip'] = "BZip";
+    }
+    if (class_exists('ZipArchive')) {
+      $compression_options['zip'] = "Zip";
+    }
+
+    $form[$db]['backup_migrate_compression_'.$db] = array(
+      "#type" => "radios",
+      "#title" => t("Compression"),
+      "#description" => t("Compression of @DB backup file", array('@DB' => $dbname, )),
+      "#options" => $compression_options,
+      "#default_value" => variable_get("backup_migrate_compression_$db", "none"),
+    );
+
+    $destination_options = array(
+      "download" => t("Download"),
+    );
+    if (_backup_migrate_check_destination_dir('manual')) {
+      $destination_options['save'] = t("Save to Files Directory");
+    }
+    $form[$db]['backup_migrate_destination_'.$db] = array(
+      "#type" => "radios",
+      "#title" => t("@DB Backup Destination", array('@DB' => $dbname, )),
+      "#options" => $destination_options,
+      "#default_value" => variable_get("backup_migrate_destination_$db", "download"),
+    );
+    $form[$db]['backup_migrate_append_timestamp_'.$db] = array(
+      "#type" => "checkbox",
+      "#title" => t("Append a timestamp to @DB backup file.", array('@DB' => $dbname, )),
+      "#default_value" => variable_get("backup_migrate_append_timestamp_$db", 1),
+    );
+    $form[$db]['backup_migrate_timestamp_format_'.$db] = array(
+      "#type" => "textfield",
+      "#title" => t("@DB Timestamp format", array('@DB' => $dbname, )),
+      "#default_value" => variable_get("backup_migrate_timestamp_format_$db", 'Y-m-d\TH-i-s'),
+      "#description" => t('Should be a PHP <a href="!url">date()</a> format string.', array('!url' => 'http://www.php.net/date')),
+    );
+    $form[$db]['backup_migrate_save_settings_'.$db] = array(
+      "#type" => "checkbox",
+      "#title" => t("Save settings for @DB.", array('@DB' => $dbname, )),
+      "#default_value" => 1,
+    );
+  }
 
   if (module_exists('token')) {
     $form['token_help'] = array(
@@ -244,52 +309,6 @@ function backup_migrate_backup() {
     );
   }
 
-  $compression_options = array("none" => t("No Compression"));
-  if (@function_exists("gzencode")) {
-    $compression_options['gzip'] = t("GZip");
-  }
-  if (@function_exists("bzcompress")) {
-    $compression_options['bzip'] = t("BZip");
-  }
-  if (class_exists('ZipArchive')) {
-    $compression_options['zip'] = t("Zip");
-  }
-
-  $form['backup_migrate_compression'] = array(
-    "#type" => "radios",
-    "#title" => t("Compression"),
-    "#options" => $compression_options,
-    "#default_value" => variable_get("backup_migrate_compression", "none"),
-  );
-
-  $destination_options = array(
-    "download" => t("Download"),
-  );
-  if (_backup_migrate_check_destination_dir('manual')) {
-    $destination_options['save'] = t("Save to Files Directory");
-  }
-  $form['backup_migrate_destination'] = array(
-    "#type" => "radios",
-    "#title" => t("Destination"),
-    "#options" => $destination_options,
-    "#default_value" => variable_get("backup_migrate_destination", "download"),
-  );
-  $form['backup_migrate_append_timestamp'] = array(
-    "#type" => "checkbox",
-    "#title" => t("Append a timestamp."),
-    "#default_value" => variable_get("backup_migrate_append_timestamp", 1),
-  );
-  $form['backup_migrate_timestamp_format'] = array(
-    "#type" => "textfield",
-    "#title" => t("Timestamp format"),
-    "#default_value" => variable_get("backup_migrate_timestamp_format", 'Y-m-d\TH-i-s'),
-    "#description" => t('Should be a PHP <a href="!url">date()</a> format string.', array('!url' => 'http://www.php.net/date')),
-  );
-  $form['backup_migrate_save_settings'] = array(
-    "#type" => "checkbox",
-    "#title" => t("Save these settings."),
-    "#default_value" => 1,
-  );
   $form[] = array(
     '#type' => 'submit',
     '#value' => t('Backup Database'),
@@ -301,27 +320,44 @@ function backup_migrate_backup() {
  * Submit the form. Save the values as defaults if desired and output the backup file.
  */
 function backup_migrate_backup_submit($form, &$form_state) {
-  if ($form_state['values']['backup_migrate_save_settings']) {
-    variable_set("backup_migrate_exclude_tables", $form_state['values']['backup_migrate_exclude_tables']);
-    variable_set("backup_migrate_nodata_tables", $form_state['values']['backup_migrate_nodata_tables']);
-    variable_set("backup_migrate_file_name", $form_state['values']['backup_migrate_file_name']);
-    variable_set("backup_migrate_destination", $form_state['values']['backup_migrate_destination']);
-    variable_set("backup_migrate_compression", $form_state['values']['backup_migrate_compression']);
-    variable_set("backup_migrate_append_timestamp", $form_state['values']['backup_migrate_append_timestamp']);
-    variable_set("backup_migrate_timestamp_format", $form_state['values']['backup_migrate_timestamp_format']);
-  }
-
-  $out = _backup_migrate_dump_tables(
-    $form_state['values']['backup_migrate_file_name'],
-    $form_state['values']['backup_migrate_exclude_tables'],
-    $form_state['values']['backup_migrate_nodata_tables'],
-    'sql',
-    $form_state['values']['backup_migrate_destination'],
-    $form_state['values']['backup_migrate_compression'],
-    "manual",
-    $form_state['values']['backup_migrate_append_timestamp'] ? $form_state['values']['backup_migrate_timestamp_format'] : FALSE
-    );
+  $databases = db_maintenance_get_databases();
 
+  foreach ($databases as $db => $url) {
+    if ($form_state['values']['backup_migrate_save_settings_'.$db]) {
+      // Clean up arrays...
+      $exclude_array = array();
+      $nodata_array = array();
+      foreach ($form_state['values']["backup_migrate_exclude_tables_$db"] as $key => $value) {
+        if ($value) {
+          $exclude_array[$key] = $value;
+        }
+      }
+      foreach ($form_state['values']["backup_migrate_nodata_tables_$db"] as $key => $value) {
+        if ($value) {
+          $nodata_array[$key] = $value;
+        }
+      }
+      variable_set("backup_migrate_exclude_tables_$db", $exclude_array);
+      variable_set("backup_migrate_nodata_tables_$db", $nodata_array);
+      variable_set("backup_migrate_file_name_$db", $form_state['values']['backup_migrate_file_name_'.$db]);
+      variable_set("backup_migrate_destination_$db", $form_state['values']['backup_migrate_destination_'.$db]);
+      variable_set("backup_migrate_compression_$db", $form_state['values']['backup_migrate_compression_'.$db]);
+      variable_set("backup_migrate_append_timestamp_$db", $form_state['values']['backup_migrate_append_timestamp_'.$db]);
+      variable_set("backup_migrate_timestamp_format_$db", $form_state['values']['backup_migrate_timestamp_format_'.$db]);
+    }
+
+    $out = _backup_migrate_dump_tables(
+      $db,
+      $form_state['values']['backup_migrate_file_name_'.$db],
+      $form_state['values']['backup_migrate_exclude_tables_'.$db],
+      $form_state['values']['backup_migrate_nodata_tables_'.$db],
+      'sql',
+      $form_state['values']['backup_migrate_destination_'.$db],
+      $form_state['values']['backup_migrate_compression_'.$db],
+      "manual",
+      $form_state['values']['backup_migrate_append_timestamp_'.$db] ? $form_state['values']['backup_migrate_timestamp_format_'.$db] : FALSE
+      );
+  }
   $form_state['redirect'] = $out;
 }
 
@@ -369,9 +405,20 @@ function backup_migrate_restore() {
 
   $form[] = array(
     '#type' => 'markup',
-    '#value' => t('<p>This will delete some or all of your data and cannot be undone. If there is a sessions table in the backup file, you and all other currently logged in users will be logged out. <strong>Always test your backups on a non-production server!</strong></p>'),
+    '#value' => t('<p>This will delete some or all of your data and cannot be undone. If there is a sessions table in the backup file, you and all other currently logged in users will be logged out. <strong>Always test your backups on a non-production server!</strong><p>'),
   );
 
+  $databases = db_maintenance_get_databases();
+  if (count($databases)>1) { 
+    // there is more than one database, the user must choose which one
+    $form['database'] = array(
+      '#type' => 'select',
+      '#title' => t('Database to upload to'),
+      '#options' => _backup_migrate_db_option_list($databases),
+      '#description' => t('Select the database that this file will restore.'),
+    );
+  }
+
   $form[] = array(
     '#type' => 'submit',
     '#value' => t('Restore Database'),
@@ -391,7 +438,7 @@ function backup_migrate_restore() {
  */
 function backup_migrate_restore_submit($form, &$form_state) {
   if ($file = file_save_upload('backup_migrate_restore_upload')) {
-    _backup_migrate_restore_file($file->filepath, $file->filename, TRUE);
+    _backup_migrate_restore_file($file->filepath, $form_state['values']['database'], $file->filename, TRUE);
     watchdog('backup_migrate', 'Database restored from upload %file', array('%file' => $file->filename));
   }
 
@@ -473,9 +520,10 @@ function _backup_migrate_backup_with_def
 /**
  * Build the database dump file. Takes a list of tables to exclude and some formatting options.
  */
-function _backup_migrate_dump_tables($filename, $exclude_tables, $nodata_tables, $type = "sql", $destination = "download", $compression = "none", $mode = "manual", $append_timestamp = FALSE) {
+function _backup_migrate_dump_tables($db, $filename, $exclude_tables, $nodata_tables, $type = "sql", $destination = "download", $compression = "none", $mode = "manual", $append_timestamp = FALSE) {
   $file_mime = "text/plain";
   $success = FALSE;
+  $filename .= "_$db";
 
   if ($append_timestamp) {
     $filename .= "-". date($append_timestamp);
@@ -486,7 +534,7 @@ function _backup_migrate_dump_tables($fi
   $temp_file = _backup_migrate_temp_file();
   switch ($type) {
     case "sql":
-      $success = _backup_migrate_get_dump_sql($temp_file, $exclude_tables, $nodata_tables);
+      $success = _backup_migrate_get_dump_sql($db, $temp_file, $exclude_tables, $nodata_tables);
       $filename .= ".sql";
       $filemime = 'text/x-sql';
       break;
@@ -567,36 +615,85 @@ function _backup_migrate_send_file_to_do
   exit();
 }
 
-/**
- * Get the sql dump file. Returns a list of sql commands, one command per line.
+/** 
+ * @brief Get the sql dump file. Returns a list of sql commands, one command per line.
+ *
  *  That makes it easier to import without loading the whole file into memory.
  *  The files are a little harder to read, but human-readability is not a priority
- */
-function _backup_migrate_get_dump_sql($file, $exclude_tables, $nodata_tables) {
-  if ($dst = fopen($file, "w")) {
-    $exclude = variable_get("backup_migrate_exclude_tables", _backup_migrate_default_exclude_tables());
-    $nodata = variable_get("backup_migrate_nodata_tables", _backup_migrate_default_structure_only_tables());
-    fwrite($dst, _backup_migrate_get_sql_file_header());
-    $alltables = _backup_migrate_get_tables();
-    foreach ($alltables as $table) {
-      if ($table['Name'] && !isset($exclude[$table['Name']])) {
-        fwrite($dst, _backup_migrate_get_table_structure_sql($table));
-        if (!in_array($table['Name'], $nodata)) {
-          _backup_migrate_dump_table_data_sql_to_handle($dst, $table);
+ *  For postgres, without the 'SHOW CREATE TABLE' command, we do two dumps:
+ *  - one with structure and data, that excludes the tables in the exclude list AND
+ *    the tables in the nodata list, and
+ *  - one with the structure only, of the tables in the nodata list
+ * 
+ * @param $db The db identifier in $db_url for the db to backup
+ * @param $file The temporary file for writing the SQL to
+ * @param $exclude The array of tables that must be excluded from this db
+ * @param $nodata The array of tables that must be backed up with no data
+ * 
+ * @return TRUE on success
+ */
+function _backup_migrate_get_dump_sql($db, $file, $exclude, $nodata) {
+  $dbtype = _db_maintenance_determine_software($db);
+  if ($dbtype == 'mysql') {
+    if ($dst = fopen($file, "w")) {
+      fwrite($dst, _backup_migrate_get_sql_file_header());
+      $alltables = _backup_migrate_get_tables($db);
+      foreach ($alltables as $table) {
+        if ($table && !isset($exclude[$table])) {
+          fwrite($dst, _backup_migrate_get_table_structure_sql($table));
+          if (!in_array($table['Name'], $nodata)) {
+            _backup_migrate_dump_table_data_sql_to_handle($dst, $table);
+          }
         }
       }
+      fwrite($dst, _backup_migrate_get_sql_file_footer());
     }
-    fwrite($dst, _backup_migrate_get_sql_file_footer());
     fclose($dst);
     return TRUE;
   }
-  else {
-    return FALSE;
+  elseif ($dbtype == 'pgsql') {
+    // Dump the database into the file, excluding the nodata and exclude tables, then
+    // dump the database structure into the file for just the nodata tables
+    $exclude_array = array();
+    $nodata_array = array();
+    foreach ($exclude as $key => $value) {
+      if ($value) $exclude_array[$key] = $value;
+    }
+    foreach ($nodata as $key => $value) {
+      if ($value) $nodata_array[$key] = $value;
+    }
+    $databases = db_maintenance_get_databases();
+    $url = $databases[$db];
+    $dump_options = '--no-owner '.db_maintenance_get_pgsql_options($url);
+    $exclude_array = array_merge($exclude_array, $nodata_array);
+    $exclude_tables = ' -T '.join(' -T ', $exclude_array); 
+    $dump_exec = "PGPASSWORDFILE=../.pgpass;/usr/bin/pg_dump $exclude_tables $dump_options > $file";
+    exec($dump_exec, $output, $return);
+    if (!$return && !is_file($file)) {
+      return FALSE;
+      watchdog('backup_migrate', $output, WATCHDOG_ERROR);
+    }
+
+    $structure_tables = ' -t '.join(' -t ', $nodata_array);
+    $dump_exec = "/usr/bin/pg_dump $structure_tables --schema-only $dump_options >> $file";
+    exec($dump_exec, $output, $return);
+    if (!$return && !is_file($file)) {
+      return FALSE;
+      watchdog('backup_migrate', $output, WATCHDOG_ERROR);
+    }
+
+    return TRUE;
   }
 }
 
-/**
- * Get the sql for the structure of the given table.
+/** 
+ * @brief Get the sql for the structure of the given table.
+ * 
+ * @param $db The database name in the db_url array
+ * @param $table The table name in that db
+ * 
+ * @return The sql needed to create that table in the 
+ *         type of database that $db is (postgres or mysql)
  */
 function _backup_migrate_get_table_structure_sql($table) {
   $out = "";
@@ -666,10 +763,12 @@ function _backup_migrate_get_sql_file_fo
 /**
  * Get a list of tables in the db. Works with MySQL, Postgres not tested.
  */
-function _backup_migrate_get_tables() {
+function _backup_migrate_get_tables($db='default') {
   $out = "";
   // get auto_increment values and names of all tables
+  $olddb = db_set_active($db);
   $tables = db_query("show table status");
+  db_set_active($olddb);
   while ($table = db_fetch_array($tables)) {
     $out[$table['Name']] = $table;
   }
@@ -679,10 +778,12 @@ function _backup_migrate_get_tables() {
 /**
  * Get the list of table names.
  */
-function _backup_migrate_get_table_names() {
+function _backup_migrate_get_table_names($db='default') {
   $out = "";
   // Get auto_increment values and names of all tables.
+  $olddb = db_set_active($db);
   $tables = db_query("show table status");
+  db_set_active($olddb);
   while ($table = db_fetch_array($tables)) {
     $out[$table['Name']] = $table['Name'];
   }
@@ -692,57 +793,53 @@ function _backup_migrate_get_table_names
 /**
  * Restore from a previously backed up files. Accepts any file created by the backup function.
  */
-function _backup_migrate_restore_file($filepath, $filename = "", $delete = FALSE) {
+function _backup_migrate_restore_file($filepath, $db='', $filename = "", $delete = FALSE) {
   if (!$filename) {
     $filename = $filepath;
   }
+  $databases = db_maintenance_get_databases();
+  if (!$db) { // find the db name from the file name
+    foreach ($databases as $key => $url) {
+      if (preg_match("/_$key/", $filename)) {
+        $restoreDB = $key;
+      }
+    }
+  }
+  else {
+    $restoreDB = $db;
+  }
 
-  $file_is_temp = $delete;
+  if (!$restoreDB) {
+    if (count($databases)>1) {
+      watchdog('backup_migrate', t('Unable to work out which database to apply this restore to'), WATCHDOG_ERROR);
+      return FALSE;
+    }
+    else {
+      $restoreDB = 'default';
+    }
+  }
 
-  $open_func    = "fopen";
-  $read_func    = "fgets";
-  $close_func   = "fclose";
+  $file_is_temp = $delete;
 
-  // figure out if the file is compressed by the file extention
+  // figure out if the file is compressed by the file extension
   if (drupal_substr($filename, -4, 4) == ".sql") {
     // No compression.
   }
   if (drupal_substr($filename, -3, 3) == ".gz") {
+    // GZip compression
     if (function_exists("gzopen")) {
-      $open_func  = "gzopen";
-      $read_func  = "gzgets";
-      $close_func = "gzclose";
+      $filepath = _backup_migrate_decompress_file($filepath, 'gzip', $delete);
     }
     else {
       // GZip compression... not supported.
-      drupal_set_message(t("This version of PHP does not support gzip comressed files. Please try using an uncompressed sql backup."), 'error');
+      drupal_set_message(t("This version of PHP does not support gzip compressed files. Please try using an uncompressed sql backup."), 'error');
       drupal_goto("admin/content/backup_migrate/restore");
     }
   }
-  // BZip compression.
-  if (drupal_substr($filename, -3, 3) == ".bz") {
+  elseif (drupal_substr($filename, -3, 3) == ".bz") {
+    // BZip compression.
     if (function_exists("bzopen")) {
-      $open_func = "fopen";
-      $read_func = "fgets";
-
-      // Decompress the file to a temp file.
-      $tmp = tempnam(file_directory_temp(), 'tmp_');
-      if (($dst = fopen($tmp, "w")) && ($src = bzopen($filepath, "r"))) {
-        while ($data = bzread($src)) {
-          fwrite($dst, $data);
-        }
-        fclose($dst);
-        bzclose($src);
-        if ($delete) {
-          unlink($filepath);
-        }
-        $filepath = $tmp;
-        $delete = TRUE;
-      }
-      else {
-        drupal_set_message(t("Unable to decompress bzip file. Please try using an uncompressed backup."), 'error');
-        drupal_goto("admin/content/backup_migrate/restore");
-      }
+      $filepath = _backup_migrate_decompress_file($filepath, 'bzip', $delete);
     }
     else {
       // BZip compression... not supported.
@@ -750,33 +847,14 @@ function _backup_migrate_restore_file($f
       drupal_goto("admin/content/backup_migrate/restore");
     }
   }
-  // Zip compression.
-  if (drupal_substr($filename, -4, 4) == ".zip") {
+  elseif (drupal_substr($filename, -4, 4) == ".zip") {
+    // Zip compression.
     if (class_exists('ZipArchive')) {
       if ($filepath != $filename) {
         rename($filepath, $filepath .".zip");
         $filepath .= ".zip";
       }
-
-      $tmp = tempnam(file_directory_temp(), 'tmp_');
-      $zip = new ZipArchive;
-      if (($dst = fopen($tmp, "w")) && ($src = $zip->open($filepath))) {
-        if ($data = $zip->getFromIndex(0)) {
-          fwrite($dst, $data);
-        }
-        fclose($dst);
-        $zip->close();
-
-        if ($delete) {
-          unlink($filepath);
-        }
-        $filepath = $tmp;
-        $delete = TRUE;
-      }
-      else {
-        drupal_set_message(t("Unable to decompress zip file. Please try using an uncompressed backup."), 'error');
-        drupal_goto("admin/content/backup_migrate/restore");
-      }
+      $filepath = _backup_migrate_decompress_file($filepath, 'zip', $delete);
     }
     else {
       // Zip compression... not supported.
@@ -785,33 +863,44 @@ function _backup_migrate_restore_file($f
     }
   }
 
-  // Open the file (with fopen or gzopen depending on file format).
-  if ($handle = @$open_func($filepath, "r")) {
-    $num = 0;
-
-    // Read one line at a time and run the query.
-    while ($line = $read_func($handle)) {
-      $line = trim($line);
-      if ($line) {
-        // Use the helper instead of the api function to avoid substitution of '{' etc.
-        _db_query($line);
-        $num++;
+  if (_db_maintenance_determine_software($restoreDB) == 'mysql') {
+    if ($handle = @fopen($filepath, "r")) {
+      $num = 0;
+      $oldDB = db_set_active($restoreDB);
+      // Read one line at a time and run the query.
+      while ($line = $fread($handle)) {
+        $line = trim($line);
+        if ($line) {
+          // Use the helper instead of the api function to avoid substitution of '{' etc.
+          _db_query($line);
+          $num++;
+        }
       }
+      // Close the file with fclose/gzclose.
+      $fclose($handle);
+      db_set_active($oldDB);
+
+      // Delete the file if it is temporary.
+      if ($delete) {
+        unlink($filepath);
+      }
+      $message = t("Restore complete. %num SQL commands executed.", array("%num" => $num));
+      $message .= $file_is_temp ? "" : "(". l(t("Restore Again..."), "admin/content/backup_migrate/restorefile/". $filepath) .")";
+      drupal_set_message($message);
     }
-    // Close the file with fclose/gzclose.
-    $close_func($handle);
-
-    // Delete the file if it is temporary.
-    if ($delete) {
-      unlink($filepath);
+    else {
+      drupal_set_message(t("Unable to open file %file to restore database", array("%file" => $filepath)), 'error');
     }
-
-    $message = t("Restore complete. %num SQL commands executed.", array("%num" => $num));
-    $message .= $file_is_temp ? "" : "(". l(t("Restore Again..."), "admin/content/backup_migrate/restorefile/". $filepath) .")";
-    drupal_set_message($message);
   }
-  else {
-    drupal_set_message(t("Unable to open file %file to restore database", array("%file" => $filepath)), 'error');
+  else { // We have a postgres database, use a different mechanism:
+    $url = $databases[$restoreDB];
+    $dump_options = db_maintenance_get_pgsql_options($url);
+    $load_exec = 'DBPASSWORDFILE=../.dbpass;/usr/bin/psql '.$dump_options.' < '.$base_path.$filepath;
+    exec($load_exec, $output, $return);
+    if (!$return) {
+      return FALSE;
+      watchdog('backup_migrate', $output, WATCHDOG_ERROR);
+    }
   }
 
   // Delete any temp files we've created.
@@ -917,24 +1006,24 @@ function _backup_migrate_temp_file($exte
   if ($delete_all) {
     _backup_migrate_temp_files_delete($files);
   }
-  else {
-    $file = tempnam(file_directory_temp(), 'backup_migrate_');
-    if (!empty($extension)) {
-      unlink($file);
-      $file .= '.'. $extension;
-    }
-    $files[] = $file;
-    return $file;
+  $file = tempnam(file_directory_temp(), 'tmp_');
+  $files[] = $file; // the file is created regardless and must be cleaned up
+  if ($extension) {
+    $file .= ".$extension";
+    $files[] = $file; // the file with the extension will be used
   }
+  return $file;
 }
 
 /**
  * Delete all temporary files.
  */
-function _backup_migrate_temp_files_delete($files) {
-  foreach ($files as $file) {
+function _backup_migrate_temp_files_delete(&$files) {
+  foreach ($files as $key => $file) {
     if (file_exists($file)) {
-      @unlink($file);
+      if (unlink($file)) {
+        unset($files[$key]);
+      }
     }
   }
 }
@@ -1085,9 +1174,10 @@ function _backup_migrate_check_destinati
     }
   }
 
-  // Attempt to read the test file via http. This may fail for other reasons, so it's not a bullet-proof check.
+  // Attempt to read the test file via http. This may fail for other reasons,
+  // so it's not a bullet-proof check.
   $path = trim(substr($subdir .'/test.txt', strlen(file_directory_path())), '\\/');
-  if (_backup_migrate_test_file_readable_remotely($path, $contents)) {
+  if (_backup_migrate_test_file_readable_remotely($filename, $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;
@@ -1116,13 +1206,18 @@ function _backup_migrate_gzip_encode($so
   if (@function_exists("gzopen")) {
     if (($fp_out = gzopen($dest, 'wb'. $level)) && ($fp_in = fopen($source, 'rb'))) {
       while (!feof($fp_in)) {
-        gzwrite($fp_out, fread($fp_in, 1024 * 512));
+        set_time_limit(60);
+        gzwrite($fp_out, fread($fp_in, 1048576));
       }
       $success = TRUE;
     }
     @fclose($fp_in);
     @gzclose($fp_out);
   }
+  else {
+    watchdog('backup_migrate', 'Unable to find gzopen compression function', WATCHDOG_ERROR);
+    return $success;
+  }
   return $success;
 }
 
@@ -1134,7 +1229,8 @@ function _backup_migrate_bzip_encode($so
   if (@function_exists("bzopen")) {
     if (($fp_out = bzopen($dest, 'w')) && ($fp_in = fopen($source, 'rb'))) {
       while (!feof($fp_in)) {
-        bzwrite($fp_out, fread($fp_in, 1024 * 512));
+        set_time_limit(60);
+        bzwrite($fp_out, fread($fp_in, 1048576));
       }
       $success = TRUE;
     }
@@ -1144,6 +1240,10 @@ function _backup_migrate_bzip_encode($so
     @fclose($fp_in);
     @bzclose($fp_out);
   }
+  else {
+    watchdog('backup_migrate', 'Unable to find gzopen compression function', WATCHDOG_ERROR);
+    return $success;
+  }
   return $success;
 }
 
@@ -1199,8 +1299,10 @@ function _backup_migrate_clean_filename(
 /**
  * Tables to ingore altogether. None by default.
  */
-function _backup_migrate_default_exclude_tables() {
-  return array();
+function _backup_migrate_default_exclude_tables($db = 'default') {
+  if ($db == 'default') {
+    return array();
+  }
 }
 
 /**
@@ -1209,29 +1311,94 @@ function _backup_migrate_default_exclude
  *  but also tables which can become quite bloated but are not necessarily extremely
  *  important to back up or migrate during development (such ass access log and watchdog)
  */
-function _backup_migrate_default_structure_only_tables() {
-  $core = array(
-    'cache',
-    'cache_filter',
-    'cache_calendar_ical',
-    'cache_menu',
-    'cache_page',
-    'cache_views',
-    'sessions',
-    'search_dataset',
-    'search_index',
-    'search_keywords_log',
-    'search_total',
-    'watchdog',
-    'accesslog',
-    'devel_queries',
-    'devel_times',
-  );
-  $alltables = array_merge($core, module_invoke_all('devel_caches'));
-  global $db_prefix;
-  foreach ($alltables as $table) {
-    $prefixed_tables[] = $db_prefix . $table;
+function _backup_migrate_default_structure_only_tables($db='default') {
+  if (($db == 'default') or ($db == 'Drupal')) {
+    $core = array(
+      'cache',
+      'cache_filter',
+      'cache_calendar_ical',
+      'cache_menu',
+      'cache_page',
+      'cache_views',
+      'sessions',
+      'search_dataset',
+      'search_index',
+      'search_keywords_log',
+      'search_total',
+      'watchdog',
+      'accesslog',
+      'devel_queries',
+      'devel_times',
+    );
+    $alltables = array_merge($core, module_invoke_all('devel_caches'));
+    global $db_prefix;
+    foreach ($alltables as $table) {
+      $prefixed_tables[] = $db_prefix . $table;
+    }
+  }
+  else {
+    $prefixed_tables = array();
   }
   return $prefixed_tables;
 }
 
+function _backup_migrate_decompress_file($filename, $format, &$delete) {
+  $tmp = _backup_migrate_temp_file();
+
+  switch ($format) {
+    case 'gzip':
+      $open_func = 'gzopen';
+      $read_func = 'gzgets';
+      $close_func = 'gzclose';
+      break;
+    case 'bzip':
+      $open_func = 'bzopen';
+      $read_func = 'bzread';
+      $close_func = 'bzclose';
+      break;
+  }
+
+  if ($format == 'zip') {
+    $zip = new ZipArchive;
+    if (($destination = fopen($tmp, "w")) && ($src = $zip->open($filename))) {
+      if ($data = $zip->getFromIndex(0)) {
+        fwrite($destination, $data);
+      }
+      $zip->close();
+      fclose($destination);
+    }
+    else {
+      drupal_set_message(t("Unable to decompress @FORMAT file. Please try using an uncompressed backup.", array('@FORMAT' => $format, )), 'error');
+      drupal_goto("admin/content/backup_migrate/restore");
+    }
+  } 
+  else { // format is not zip...
+    if (($destination = fopen($tmp, "w")) && ($src = $open_func($filename, "r"))) {
+      while ($data = $read_func($src)) {
+        fwrite($destination, $data);
+      }
+      $close_func($src);
+      fclose($destination);
+    }
+    else {
+      drupal_set_message(t("Unable to decompress @FORMAT file. Please try using an uncompressed backup.", array('@FORMAT' => $format, )), 'error');
+      drupal_goto("admin/content/backup_migrate/restore");
+    }
+  }
+
+  if ($delete) {
+    unlink($filename);
+  }
+  $filename = $tmp;
+  $delete = TRUE;
+  return($filename);
+}
+ 
+function _backup_migrate_db_option_list($databases) {
+  $options = array();
+  foreach ($databases as $key => $url) {
+    $options[$key] = $key;
+  }
+  return $options;
+}
+
