# This patch file was generated by NetBeans IDE
# This patch can be applied using context Tools: Apply Diff Patch action on respective folder.
# It uses platform neutral UTF-8 encoding.
# Above lines and this line are ignored by the patching process.
Index: contributions/modules/millennium/millennium.admin.inc
--- contributions/modules/millennium/millennium.admin.inc Base (1.1.2.31)
+++ contributions/modules/millennium/millennium.admin.inc Locally Modified (Based On 1.1.2.31)
@@ -9,8 +9,8 @@
  * Callback for drupal_get_form for general settings form
  */
 function millennium_admin_settings() {
-  if (variable_get('millennium_webopac_baseurl', false) === false) {
-    drupal_set_message(t('You have not yet set the Base URL.'), 'warning');
+  if (sizeof(variable_get('millennium_sources', array())) == 0) {
+    drupal_set_message(t('You have not yet set any sources.'), 'warning');
   }
 
   $node_types = node_get_types();
@@ -33,22 +33,6 @@
     '#default_value' => variable_get('millennium_marc_node_type', 'page'),
   );
 
-  $form['general']['millennium_webopac_baseurl'] = array(
-    '#type' => 'textfield',
-    '#title' => t("Base URL for WebOPAC"),
-    '#size' => 40,
-    '#default_value' => variable_get('millennium_webopac_baseurl', ''),
-    '#description' => t('For example: http://example.com/'),
-    '#prefix' => '<table id="baseurl-table"><tbody><tr><td>',
-    '#suffix' => '</td><td id="checkurl"></td></tr></tbody></table>',
-    '#ahah' => array(
-      'path' => 'millennium_checkurl_js',
-      'event' => 'change',
-      'wrapper' => 'checkurl',
-      'method' => 'replace',
-      'effect' => 'fade',
-    ),
-  );
   $form['general']['millennium_action_on_last_item_deleted'] = array(
     '#type' => 'radios',
     '#title' => t('Action when imported records are no longer found in WebOPAC'),
@@ -56,7 +40,153 @@
     '#default_value' => variable_get('millennium_action_on_last_item_deleted', 'unpublish'),
   );
   
-  $run_cron_url = l(t('run cron'), 'admin/reports/status/run-cron', array('query' => array('destination' => MILLENNIUM_SETTINGS_PATH)));
+  // Sources fieldset
+  $form['sources'] = array(
+    '#type' => 'fieldset',
+    '#collapsible' => true,
+    '#title' => t('Source OPACs'),
+    '#description' => t('You can enter OPAC sources that will be available for batch import and other operations.'),
+  );
+
+  // Show table for existing OPAC sources
+  $rows = array();
+  $headers = array(t('Action'), t('OPAC base URL'), t('OPAC name'));
+  foreach (variable_get("millennium_sources", array()) as $base_url => $source_data) {
+    // Element to remove this source
+    $remove_element = array(
+      '#name' => 'remove_source_' . $base_url,
+      '#type' => 'checkbox',
+      '#title' => t('Remove')
+    );
+    // Element to edit existing source name
+    $edit_name_element = array(
+      '#name' => 'edit_name_' . $base_url,
+      '#type' => 'textfield',
+      '#value' => $source_data["name"],
+      '#size' => 30,
+    );
+    // Add row to table
+    $rows[] = array(
+      drupal_render($remove_element),
+      l($base_url, $base_url),
+      drupal_render($edit_name_element)
+    );
+  }
+
+  // Add a final table row to allow adding new sources
+  $add_url_element = array(
+    '#name' => 'add_url',
+    '#type' => 'textfield',
+    '#size' => 30,
+  );
+  $add_name_element = array(
+    '#name' => 'add_name',
+    '#type' => 'textfield',
+    '#size' => 30,
+  );
+  $rows[] = array(t('Add new source:'), drupal_render($add_url_element), drupal_render($add_name_element));
+  // Add the themed table to the form
+  $form['sources']['table'] = array(
+    '#type' => 'markup',
+    '#value' => theme('table', $headers, $rows)
+  );
+  // Add custom validation and submission callbacks only for the table elements;
+  // the rest of the form is automatically handled by
+  // system_settings_form_submit() because of system_settings_form() call below.
+  $form['#validate'][] = 'millennium_admin_settings_form_validate';
+  $form['#submit'][] = 'millennium_admin_settings_form_submit';
+
+  // Render as a system settings form.
+  return system_settings_form($form);
+}
+
+/**
+ * Validate handler for settings form; handles special values in table
+ */
+function millennium_admin_settings_form_validate($form, &$form_state) {
+  $sources = variable_get('millennium_sources', array());
+
+  // Validate sources to remove
+  foreach ($sources as $base_url => $source_data) {
+    $base_url_as_index = str_replace(".", "_", $base_url);
+    if ($form_state['clicked_button']['#post']["remove_source_{$base_url_as_index}"]) {
+      // Check if there are existing records for this base_url
+      $count = (int)db_result(db_query("SELECT count(1) FROM {millennium_node_bib} WHERE base_url = '%s'", $base_url));
+      if ($count) {
+        form_set_error("remove_source_{$base_url_as_index}", t('The source %url cannot be removed since nodes that depend on it still exist.', array('%url' => $new_url)));
+      }
+    }
+  }
+
+  // Validate a new URL if given
+  $new_url = trim($form_state['clicked_button']['#post']['add_url']);
+  $new_name = trim($form_state['clicked_button']['#post']['add_name']);
+  if ($new_url) {
+    // Check for valid URL
+    if (strpos($new_url, 'http://') !== 0) {
+      form_set_error('add_url', t('The entered url %url is not valid.', array('%url' => $new_url)));
+      return;
+    }
+
+    // Normalize the base url
+    $new_url = check_plain(millennium_get_real_baseurl($new_url));
+
+    // Check for unique base URL
+    if (isset($sources[$new_url])) {
+      form_set_error('add_url', t('The url %url is already defined.', array('%url' => $new_url)));
+      return;
+    }
+  }
+  // All is OK, store the normalized URL for the submit function
+  $form_state['storage']['add_url'] = $new_url;
+}
+
+/**
+ * Submit handler for settings form; handles special values that are not
+ */
+function millennium_admin_settings_form_submit($form, &$form_state) {
+  #dpm($form_state);
+  $sources = variable_get('millennium_sources', array());
+
+  // Update any changes to sources
+  foreach ($sources as $base_url => $source_data) {
+    $base_url_as_index = str_replace(".", "_", $base_url);
+    #dsm("Checking $base_url");
+    #dpm($form_state['clicked_button']['#post']["remove_source_{$base_url_as_index}"]);
+    // Removal checked?
+    if ($form_state['clicked_button']['#post']["remove_source_{$base_url_as_index}"] == "1") {
+      drupal_set_message(t('Removed source %url', array('%url' => $base_url)));
+      unset($sources[$base_url]);
+      // TODO: Update taxonomy terms, etc.
+      continue;
+    }
+
+    // Name change
+    $sent_name = $form_state['clicked_button']['#post']["edit_name_{$base_url_as_index}"];
+    if ($sent_name != $source_data["name"]) {
+      $sources[$base_url]["name"] = check_plain($sent_name);
+      // TODO: Update taxonomy terms, etc.
+    }
+  }
+
+  // If sent, add the new url and name to the sources
+  $new_url = $form_state['storage']['add_url'];
+  $new_name = trim($form_state['clicked_button']['#post']['add_name']);
+  if ($new_url) {
+    $sources[$new_url] = array('name' => check_plain($new_name));
+    // TODO: Add taxonomy terms (??)
+  }
+
+  // Store the new value for sources
+  variable_set('millennium_sources', $sources);
+}
+
+/**
+ * Callback for drupal_get_form for crawl settings form.
+ */
+function millennium_admin_crawl() {
+  $form = array();
+  $run_cron_url = l(t('run cron'), 'admin/reports/status/run-cron', array('query' => array('destination' => MILLENNIUM_SETTINGS_PATH . '/crawl')));
   $form['crawl'] = array(
     '#type' => 'fieldset',
     '#collapsible' => true,
@@ -71,6 +201,13 @@
     '#description' => t('Enabling this will start (or continue) the automatic record import/update. Disabling this does not stop importing items queued manually for import.'),
     '#default_value' => variable_get('millennium_crawl_flag', 0),
   );
+  $form['crawl']['millennium_crawl_baseurl'] = array(
+    '#type' => 'select',
+    '#title' => t('Source WebOPAC'),
+    '#description' => t('Select one of the enabled sources.'),
+    '#default_value' => variable_get('millennium_crawl_baseurl', ''),
+    '#options' => drupal_map_assoc(array_keys(variable_get('millennium_sources', array()))),
+  );
   $form['crawl']['millennium_webopac_maxrecords'] = array(
     '#type' => 'select',
     '#title' => t("Items to import per cron run"),
@@ -106,7 +243,6 @@
     '#description' => t('WARNING: Set ONLY if you want to start over from that number onwards.'),
     '#default_value' => variable_get('millennium_webopac_reset', false),
   );
-
   return system_settings_form($form);
 }
 
@@ -322,15 +458,16 @@
   if ($tot_queued_items > 0) {
     $form['source']['#options']['queued'] = t('All records awaiting cron (@num items). <em>Note: this will empty the cron queue!</em>', array("@num" => $tot_queued_items));
   }
-  $form['millennium_webopac_baseurl'] = array(
+  $form['millennium_import_form_baseurl'] = array(
     '#type' => 'textfield',
     '#title' => t('Base URL for WebOPAC'),
     '#description' => t('For example: http://example.com/'),
-    '#default_value' => variable_get('millennium_import_form_baseurl', variable_get('millennium_webopac_baseurl', '')),
+    '#default_value' => variable_get('millennium_import_form_baseurl', ''),
     '#prefix' => '<table id="baseurl-table"><tbody><tr><td>',
     '#suffix' => '</td><td id="checkurl"></td></tr></tbody></table>',
+    '#autocomplete_path' => 'millennium_autocomplete_js',
     '#ahah' => array(
-      'path' => 'millennium_checkurl_js',
+      'path' => 'millennium_checkurl_js/millennium_import_form_baseurl',
       'event' => 'change',
       'wrapper' => 'checkurl',
       'method' => 'replace',
@@ -458,9 +595,9 @@
   if ($form_state["values"]["source"] == "range" ||
     $form_state["values"]["source"] == "list" ||
     $form_state["values"]["source"] == "query") {
-    $base_url = $form_state['values']['millennium_webopac_baseurl'];
+    $base_url = millennium_get_real_baseurl($form_state['values']['millennium_import_form_baseurl']);
     if (!$base_url) {
-      form_set_error('millennium_webopac_baseurl', t("Not a valid base URL."));
+      form_set_error('millennium_import_form_baseurl', t("Not a valid base URL."));
     }
   }
   if ($form_state["values"]["source"] == "range") {
@@ -537,7 +674,7 @@
 
     // Store some values for later
     variable_set('millennium_import_form_source', $form_state["values"]["source"]);
-    variable_set('millennium_import_form_baseurl', $form_state["values"]["millennium_webopac_baseurl"]);
+    variable_set('millennium_import_form_baseurl', $form_state["values"]["millennium_import_form_baseurl"]);
     variable_set('millennium_import_form_force_update', $form_state["values"]["force_update"]);
     variable_set('millennium_list_form_checkdigit', $form_state["values"]["ignore_checkdigit"]);
     variable_set('millennium_range_form_type', $form_state["values"]["type"]);
@@ -546,6 +683,8 @@
     variable_set('millennium_import_form_kw', $form_state["values"]["kw"]);
     variable_set('millennium_import_form_url', $form_state["values"]["url"]);
 
+    $base_url = millennium_get_real_baseurl($form_state['values']['millennium_import_form_baseurl']);
+
     if ($form_state["clicked_button"]["#value"] == t("Process these records during cron runs")) {
 
       // When? Cron runs
@@ -570,7 +709,7 @@
               $recnum,
               $form_state['values']['priority'],
               $form_state['values']['force_update'],
-              $form_state['values']['millennium_webopac_baseurl']);
+              $base_url);
             if ($ok)
               $queued++;
           }
@@ -587,7 +726,7 @@
             $type . $num,
             $form_state['values']['priority'],
             $form_state['values']['force_update'],
-            $form_state['values']['millennium_webopac_baseurl']);
+            $base_url);
           if ($ok) {
             $queued++;
           }
@@ -631,7 +770,7 @@
             if ($form_state["values"]["ignore_checkdigit"] == true) {
               $recnum = drupal_substr($recnum, 0, drupal_strlen($recnum)-1);
             }
-            $records_to_crawl[$form_state['values']['millennium_webopac_baseurl']][$recnum] = $recnum;
+            $records_to_crawl[$base_url][$recnum] = $recnum;
           }
         }
       }
@@ -641,7 +780,6 @@
         $type = $form_state["values"]["type"];
         $start = $form_state["values"]["start"];
         $end = $form_state["values"]["end"];
-        $base_url = millennium_get_real_baseurl($form_state['values']['millennium_webopac_baseurl']);
         for ($num = $start; $num <= $end; $num++) {
           $records_to_crawl[$base_url]["{$type}{$num}"] = "{$type}{$num}";
         }
@@ -650,7 +788,6 @@
       if ($form_state["values"]["source"] == "query") {
         require_once 'millennium.import.inc';
         variable_set('millennium_import_form_num_items', $form_state["values"]["num_items"]);
-        $base_url = $form_state['values']['millennium_webopac_baseurl'];
         $records = millennium_query_scrape(
           $form_state["values"]["kw"],
           $base_url,
Index: contributions/modules/millennium/millennium.cron.inc
--- contributions/modules/millennium/millennium.cron.inc Base (1.1.2.9)
+++ contributions/modules/millennium/millennium.cron.inc Locally Modified (Based On 1.1.2.9)
@@ -11,11 +11,11 @@
   $start_time = microtime(true);
 
   // Is URL set?
-  if (($base_url = millennium_get_real_baseurl()) === false) {
+  if (($base_url = variable_get('millennium_crawl_baseurl', false)) === false) {
     return;
   }
   if (!millennium_ping($base_url)) {
-    watchdog("Millennium", "Cron run aborted because WebOPAC at @url not responding", array("@url" => $base_url));
+    watchdog("Millennium", "Cron run aborted because WebOPAC at @url not responding", array("@url" => $base_url), WATCHDOG_ERROR);
     return;
   }
 
@@ -143,7 +143,7 @@
     // Chunk array into groups of 50 (maximum number allowed by bookcart)
     $recnums_chunks = array_chunk($recnums, 50);
     foreach ($recnums_chunks as $recnums_chunk) {
-      $fetched = millennium_fetch_records_via_bookcart($recnums_chunk);
+      $fetched = millennium_fetch_records_via_bookcart($recnums_chunk, false, $base_url);
       #dpm($fetched);
       foreach ($fetched['found'] as $data) {
         $result = millennium_process_record($data);
@@ -206,8 +206,8 @@
     $elapsed_time = microtime(true) - $start_time;
     millennium_time_history($elapsed_time, $tot_attempted, $tot_notfound, $tot_imported, $tot_fail);
 
-    watchdog("Millennium", "Cron import finished: @attempted attempted, @notfound not found on WebOpac, @imported imported ok, @failed could not import, in @time seconds (@time2 items per second)",
-      array("@attempted" => $tot_attempted, "@notfound" => $tot_notfound, "@imported" => $tot_imported, "@failed" => $tot_fail+0, "@time" => sprintf("%2.1f", $elapsed_time), "@time2" => sprintf("%2.1f", $tot_attempted / $elapsed_time))
\ No newline at end of file
+    watchdog("Millennium", "Cron import finished: @url: @attempted attempted, @notfound not found on WebOpac, @imported imported ok, @failed could not import, in @time seconds (@time2 items per second)",
+      array("@url" => $base_url, "@attempted" => $tot_attempted, "@notfound" => $tot_notfound, "@imported" => $tot_imported, "@failed" => $tot_fail+0, "@time" => sprintf("%2.1f", $elapsed_time), "@time2" => sprintf("%2.1f", $tot_attempted / $elapsed_time))
\ No newline at end of file
     );
   }
 }
Index: contributions/modules/millennium/millennium.import.inc
--- contributions/modules/millennium/millennium.import.inc Base (1.1.2.20)
+++ contributions/modules/millennium/millennium.import.inc Locally Modified (Based On 1.1.2.20)
@@ -71,12 +71,7 @@
  * @param $limit
  *   Maximum number of records to return.
  */
-function millennium_query_scrape($query, $base_url = false, $limit = 100) {
-  if ($base_url == false) {
-    $base_url = millennium_get_real_baseurl();
-  } else {
-    $base_url = millennium_get_real_baseurl($base_url);
-  }
+function millennium_query_scrape($query, $base_url, $limit = 100) {
   // Build query URL
   $url = "{$base_url}/search/X?" . drupal_urlencode($query);
   // Get records
@@ -90,7 +85,7 @@
  * @param $base_url
  *   The base url of the WebOPAC to process.
  */
-function millennium_mass_fetch($recnums, $base_url = false) {
+function millennium_mass_fetch($recnums, $base_url) {
   // This seems to be the limit for WebOPACs, do not change =)
   $max_records_for_bookcart = 40;
 
@@ -163,19 +158,13 @@
  *    'not_found' => array('i100000', 'i100005', [...])
  *  );
  */
-function millennium_fetch_records_via_bookcart($recnums, $complete_holdings = false, $base_url = false) {
+function millennium_fetch_records_via_bookcart($recnums, $complete_holdings = false, $base_url) {
   // Set the following to true for lots and lots of debugging info =)
   $debug = false;
 
   // Start timer to measure average performance
   timer_start("millennium_fetch_records_via_bookcart");
 
-  if ($base_url == false) {
-    $base_url = millennium_get_real_baseurl();
-  } else {
-    $base_url = millennium_get_real_baseurl($base_url);
-  }
-  
   $found_items = array();
   $not_found_items = array();
 
@@ -344,11 +333,11 @@
       // volume/copy" button? Do we want to check for complete holdings?
       if ($match[3] != "" && $complete_holdings == true) {
         // Yes. Issue additional request to OPAC to get holdings information for item.
-        $found_items[$current_recnum]['holdings'] = millennium_get_holdings_info($this_bib_recnum, null, $base_url);
+        $found_items[$current_recnum]['holdings'] = millennium_get_holdings_info($this_bib_recnum, $base_url);
       } else { 
         // No. Convert whatever holdings info (might be incomplete) we got along 
         // with the MARC export and add it to the item array.
-        $found_items[$current_recnum]['holdings'] = millennium_get_holdings_info($this_bib_recnum, $match[2], $base_url);
\ No newline at end of file
+        $found_items[$current_recnum]['holdings'] = millennium_get_holdings_info($this_bib_recnum, $base_url, $match[2]);
\ No newline at end of file
       }
       $found_items_index++;
     }
Index: contributions/modules/millennium/millennium.install
--- contributions/modules/millennium/millennium.install Base (1.1.2.5.2.1.2.10)
+++ contributions/modules/millennium/millennium.install Locally Modified (Based On 1.1.2.5.2.1.2.10)
@@ -23,6 +23,7 @@
   if ($phase == 'runtime') {
     $msg = array();
 
+    /* TODO: Decide if we will still check OPAC/OPACs
     $base_url = millennium_get_real_baseurl();
     if (!$base_url) {
       $msg[] = $t("You must configure a base URL; please go to the !configurationpage", array("!configurationpage" => l($t("configuration page"), MILLENNIUM_SETTINGS_PATH)));
@@ -44,6 +45,7 @@
       'description' => $description,
       'severity' => $severity,
     );
+    */
   }
   return $requirements;
 }
@@ -341,3 +343,23 @@
   );
   return $ret;
 }
+
+function millennium_update_6005() {
+  $ret = array();
+  $sources = variable_get('millennium_sources', array());
+  // Move millennium_webopac_baseurl variable into the new sources variable
+  $base_url = variable_get('millennium_webopac_baseurl', '');
+  if ($base_url && !isset($sources[$base_url])) {
+    $sources[$base_url] = array('name' => '');
+  }
+  // Add sources from all currently-imported records
+  $result = db_query("SELECT DISTINCT(base_url) FROM {millennium_node_bib}");
+  while ($data = db_fetch_object($result)) {
+    if (!isset($sources[$data->base_url])) {
+      $sources[$data->base_url] = array('name' => '');
+    }
+  }
+  // Update/create sources variable
+  variable_set('millennium_sources', $sources);
+  return $ret;
+}
\ No newline at end of file
Index: contributions/modules/millennium/millennium.module
--- contributions/modules/millennium/millennium.module Base (1.13.2.33.2.2.2.86)
+++ contributions/modules/millennium/millennium.module Locally Modified (Based On 1.13.2.33.2.2.2.86)
@@ -583,6 +583,16 @@
     'type' => MENU_DEFAULT_LOCAL_TASK,
     'weight' => -10,
   );
+  $items[MILLENNIUM_SETTINGS_PATH . '/crawl'] = array(
+    'title' => 'Automatic crawl',
+    'description' => 'Configure automatic crawl settings.',
+    'type' => MENU_LOCAL_TASK,
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('millennium_admin_crawl'),
+    'access callback' => 'user_access',
+    'access arguments' => array('administer millennium'),
+    'file' => 'millennium.admin.inc',
+  );
   $items[MILLENNIUM_SETTINGS_PATH . '/map'] = array(
     'title' => 'Taxonomy mapping',
     'description' => 'Configure MARC import mapping settings.',
@@ -623,6 +633,7 @@
     'type' => MENU_CALLBACK,
     'file' => 'millennium.pages.inc',
   );
+  /* TODO: make this work with a URL at the end
   $items['millennium/preview/%'] = array(
     'title' => 'Millennium node import preview',
     'page callback' => 'millennium_preview_import' ,
@@ -632,6 +643,7 @@
     'type' => MENU_CALLBACK,
     'file' => 'millennium.pages.inc',
   );
+   */
 
   $items['admin/reports/millennium'] = array(
     'title' => 'Millennium import statistics',
@@ -647,12 +659,19 @@
     'access arguments' => array('access content'),
     'file' => 'millennium.pages.inc',
   );
-  $items['millennium_checkurl_js'] = array(
+  $items['millennium_checkurl_js/%'] = array(
     'page callback' => 'millennium_checkurl_js',
+    'page arguments' => array(1),
     'type' => MENU_CALLBACK,
     'access arguments' => array('administer millennium'),
     'file' => 'millennium.pages.inc',
   );
+  $items['millennium_autocomplete_js'] = array(
+    'page callback' => 'millennium_autocomplete_js',
+    'type' => MENU_CALLBACK,
+    'access arguments' => array('administer millennium'),
+    'file' => 'millennium.pages.inc',
+  );
 
   $items['node/%node/millennium'] = array(
     'title' => 'Millennium Tools',
@@ -1111,7 +1130,7 @@
   if ($data['base_url']) {
     $base_url = $data['base_url'];
   } else {
-    $base_url = millennium_get_real_baseurl();
+    return array("success" => false, "error" => "No base_url in item #" . $data['item_recnum']);
   }
   
   // Had we already imported this item record?
@@ -1184,7 +1203,7 @@
 function millennium_process_item_record_new_import($data, $nid) {
   // Link item to bib, node
   $record = array('nid' => $nid, 'bib_recnum' => $data['bib_recnum'], 'item_recnum' => $data['item_recnum'],
-        'updated' => date("Y-m-d H:i:s"), 'created' => date("Y-m-d H:i:s"), 'base_url' => millennium_get_real_baseurl());
+        'updated' => date("Y-m-d H:i:s"), 'created' => date("Y-m-d H:i:s"), 'base_url' => $data['base_url']);
   $result = drupal_write_record('millennium_bib_item', $record);
   if (!$result) {
     drupal_set_message("millennium_process_item_record_new_import: drupal_write_record('millennium_bib_item') returned false");
@@ -1277,7 +1296,7 @@
   if ($data['base_url']) {
     $base_url = millennium_get_real_baseurl($data['base_url']);
   } else {
-    $base_url = millennium_get_real_baseurl();
+    return array("success" => false, "error" => "Could not get bib_recnum for bib #" . $data['bib_recnum']);
   }
 
   $bib_import_history = db_fetch_object(db_query("SELECT * FROM {millennium_node_bib} WHERE bib_recnum='%s' AND base_url = '%s'", $data['bib_recnum'], $base_url));
@@ -1313,7 +1332,7 @@
   }
 
   // Re-create a nodeobject from the MARC record
-  $new_node = millennium_record_to_nodeobject($data['bib_recnum'], $data['marc'], $base_url);
+  $new_node = millennium_record_to_nodeobject($data['bib_recnum'], $base_url, $data['marc']);
   if ($new_node->success === false) {
     #drupal_set_message("millennium_process_bib_record(): millennium_record_to_nodeobject() returned error ". $result["error"]);
     return array("success" => false, "error" => $new_node->error);
@@ -1373,7 +1392,7 @@
   if ($data['base_url']) {
     $base_url = $data['base_url'];
   } else {
-    $base_url = millennium_get_real_baseurl();
+    return;
   }
 
   // Get bibrecord number and erase any existing node-item relationships
@@ -1418,7 +1437,7 @@
   if ($data['base_url']) {
     $base_url = $data['base_url'];
   } else {
-    $base_url = millennium_get_real_baseurl();
+    return;
   }
   
   db_query("DELETE FROM {millennium_bib_item} WHERE bib_recnum='%s' AND base_url = '%s'", $data['bib_recnum'], $base_url);
@@ -1448,9 +1467,8 @@
  * @param recnum Millennium record number (b123456, i123456) to fetch
  * @param string $marc_text An optional MARC record to import from.
  */
-function millennium_record_to_nodeobject($recnum, $marc_text = null, $base_url = false) {
+function millennium_record_to_nodeobject($recnum, $base_url, $marc_text = null) {
   $result = new stdClass();
-  $base_url = millennium_get_real_baseurl($base_url);
   if ($marc_text == null) {
     $marc_text = millennium_fetch_marc($recnum, $base_url);
     if (!$marc_text) {
@@ -1540,14 +1558,11 @@
 /**
  * Returns the user-defined base URL for the Millennium server (e.g. http://example.com/)
  */
-function millennium_get_real_baseurl($base_url = false) {
-  if ($base_url === false) {
-    $base_url = variable_get('millennium_webopac_baseurl', '');
-  }
-  if ($base_url == '') {
+function millennium_get_real_baseurl($base_url) {
+  if ($base_url === false || $base_url == '') {
     return false;
   }
-  $parts = @parse_url($base_url);
+  $parts = @parse_url(trim($base_url));
   if (!$parts['host']) {
     return false;
   }
@@ -1563,7 +1578,7 @@
  * @param recnum Millennium record number (b123456, i123456) to fetch
  * @param mode String specifying type of view: plain, marc, items, xml
  */
-function millennium_fetch_recordpage($recnum, $mode = "plain", $base_url = false) {
+function millennium_fetch_recordpage($recnum, $mode = "plain", $base_url) {
   global $millennium_fetch_recordpage_cache;
   $key = $recnum . $mode . $base_url;
   #drupal_set_message("millennium_fetch_recordpage($recnum, $mode): key = $key");
@@ -1590,15 +1605,7 @@
 /**
  * Returns a URL for a certain item record view in Millennium
  */
-function millennium_permalink($recnum, $mode = 'plain', $base_url = false) {
-  if ($base_url === false) {
-    $base_url = millennium_get_real_baseurl();
-  }
-  if ($base_url == false) {
-    return false;
-  } else {
-    $base_url = millennium_get_real_baseurl($base_url);
-  }
+function millennium_permalink($recnum, $mode = 'plain', $base_url) { // TODO fix argument order
   // Determine if record is for an item or bib
   $recnum_type = substr($recnum, 0, 1);
 
@@ -1613,7 +1620,7 @@
     case "hold":
     case "items":
       if ($recnum_type == "i") {
-        $bib_recnum = db_result(db_query("SELECT bib_recnum FROM {millennium_bib_item} WHERE item_recnum='%s' AND base_url = '%s'", $recnum, millennium_get_real_baseurl()));
+        $bib_recnum = db_result(db_query("SELECT bib_recnum FROM {millennium_bib_item} WHERE item_recnum='%s' AND base_url = '%s'", $recnum, $base_url));
         $item_recnum = $recnum;
       } else {
         $bib_recnum = $recnum;
@@ -1911,7 +1918,7 @@
     return;
   }
   $locations_available = array();
-  $holdings = millennium_get_holdings_info($recnum, null, $base_url);
+  $holdings = millennium_get_holdings_info($recnum, $base_url);
   foreach ($holdings as $item) {
     if (
       !variable_get('millennium_map_available_only', FALSE)
@@ -2442,13 +2449,10 @@
  * @return array
  *   A holdings array.
  */
-function millennium_get_holdings_info($recnum, $fetched_html = null, $base_url = false) {
+function millennium_get_holdings_info($recnum, $base_url, $fetched_html = null) {
   static $cache;
   
   $items = array();
-  if ($base_url === false) {
-    $base_url = millennium_get_real_baseurl();
-  }
   
   if ($fetched_html == null) {
     // Build a cache id
Index: contributions/modules/millennium/millennium.pages.inc
--- contributions/modules/millennium/millennium.pages.inc Base (1.1.2.5)
+++ contributions/modules/millennium/millennium.pages.inc Locally Modified (Based On 1.1.2.5)
@@ -49,12 +49,13 @@
 /**
  * Callback function from hook_menu to show how an millennium record would be imported
  */
-function millennium_preview_import($recnum) {
-  $output = t("You can also !link", array('!link' => l(t("import this record now"), "millennium/import/$recnum")));
-  $output .= "<hr />";
-  $output .= _millennium_show_conversion($recnum);
-  return $output;
-}
+//DISABLED. See millennium_menu() callback to this function.
+//function millennium_preview_import($recnum) {
+//  $output = t("You can also !link", array('!link' => l(t("import this record now"), "millennium/import/$recnum")));
+//  $output .= "<hr />";
+//  $output .= _millennium_show_conversion($recnum);
+//  return $output;
+//}
 
 /**
  * Callback function from hook_menu that shows import and conversion information for node $nid
@@ -84,7 +85,7 @@
 
   $output .= "<p></p>";
   $output .= "<h2>". t('MARC record and conversion') ."</h2>";
-  $output .= _millennium_show_conversion($bib_recnum, $node->millennium_biblio_data["marc"], $data->base_url);
+  $output .= _millennium_show_conversion($bib_recnum, $data->base_url, $node->millennium_biblio_data["marc"]);
   return $output;
 }
 
@@ -139,7 +140,7 @@
   else {
     $bib_recnum = millennium_bib_recnum_from_node($nid);
     $base_url = db_result(db_query("SELECT base_url FROM {millennium_node_bib} WHERE nid=%d", $nid));
-    $holdings = millennium_get_holdings_info($bib_recnum, NULL, $base_url);
+    $holdings = millennium_get_holdings_info($bib_recnum, $base_url);
     $output = theme('millennium_holdings', $nid, $holdings, $page);
     cache_set($cid, serialize($output), 'cache', time() + 900); // 15 minutes
   }
@@ -263,7 +264,7 @@
 /**
  * Diagnostics to show conversion of MARC into fields for node object
  */
-function _millennium_show_conversion($recnum, $marc_text = false, $base_url = false) {
+function _millennium_show_conversion($recnum, $base_url, $marc_text = false) {
   $output = "";
   $base_url = millennium_get_real_baseurl($base_url);
   if ($base_url == false) {
@@ -277,7 +278,7 @@
     $marc_text_msg = t('This MARC record was just fetched from the WebOPAC.');
   }
 
-  $tmp_node = millennium_record_to_nodeobject($recnum, $marc_text, $base_url);
+  $tmp_node = millennium_record_to_nodeobject($recnum, $base_url, $marc_text);
   if (!$tmp_node || !$tmp_node->millennium_biblio_data) {
     return t("Millennium data in node has errors and can not be displayed.");
   }
@@ -313,11 +314,29 @@
 /**
  * Callback function for URL checker
  */
-function millennium_checkurl_js() {
+function millennium_checkurl_js($var_name = false) {
   $form_state = array('values' => $_POST);
-  $base_url = millennium_get_real_baseurl($form_state['values']['millennium_webopac_baseurl']);
+  $base_url = millennium_get_real_baseurl($form_state['values'][check_plain($var_name)]);
   $ok = millennium_ping($base_url);
   $output = $ok ? t("WebOPAC is responding normally.") : t("Not a valid WebOPAC.");
   $class = $ok ? "status" : "error";
   drupal_json(array('status' => TRUE, 'data' => "<div class='messages {$class}'>{$output}</div>"));
 }
+
+/**
+ * Callback function for base_url autocomplete form elements
+ */
+function millennium_autocomplete_js() {
+  $suggestions = array();
+  $search_parts = explode('/', trim($_GET['q']));
+  $search_string = implode('/', array_slice($search_parts, 1));
+  $sources = variable_get("millennium_sources", array());
+  // Look for $search_string in all sources
+  foreach ($sources as $base_url => $source_data) {
+    if (strpos($base_url, $search_string) === 0) {
+      $suggestions[$base_url] = $base_url;
+    }
+  }
+  drupal_json($suggestions);
+  exit;
+}
\ No newline at end of file
Index: contributions/modules/millennium/millennium_auth.info
--- contributions/modules/millennium/millennium_auth.info Base (1.1.2.3)
+++ contributions/modules/millennium/millennium_auth.info Locally Modified (Based On 1.1.2.3)
@@ -3,5 +3,5 @@
 description = "Allows users to log in using Millennium credentials."
 version = "$Name:  $"
 dependencies[] = millennium
-core = 6.x
+core = ponies
 package = Millennium Integration
