Index: modules/block/block.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/block/block.module,v
retrieving revision 1.262
diff -u -r1.262 block.module
--- modules/block/block.module	28 May 2007 06:08:39 -0000	1.262
+++ modules/block/block.module	31 May 2007 23:25:40 -0000
@@ -97,7 +97,7 @@
     'page arguments' => array('block_add_block_form'),
     'type' => MENU_LOCAL_TASK,
   );
-  $default = variable_get('theme_default', 'garland');
+  $default = variable_get('theme_default');
   foreach (list_themes() as $key => $theme) {
     $items['admin/build/block/list/'. $key] = array(
       'title' => '!key settings',
@@ -228,7 +228,7 @@
     $custom_theme = $theme;
   }
   else {
-    $custom_theme = variable_get('theme_default', 'garland');
+    $custom_theme = variable_get('theme_default');
   }
   init_theme();
 
@@ -706,7 +706,7 @@
       if ($block->pages) {
         if ($block->visibility < 2) {
           $path = drupal_get_path_alias($_GET['q']);
-          $regexp = '/^('. preg_replace(array('/(\r\n?|\n)/', '/\\\\\*/', '/(^|\|)\\\\<front\\\\>($|\|)/'), array('|', '.*', '\1'. preg_quote(variable_get('site_frontpage', 'node'), '/') .'\2'), preg_quote($block->pages, '/')) .')$/';
+          $regexp = '/^('. preg_replace(array('/(\r\n?|\n)/', '/\\\\\*/', '/(^|\|)\\\\<front\\\\>($|\|)/'), array('|', '.*', '\1'. preg_quote(variable_get('site_frontpage'), '/') .'\2'), preg_quote($block->pages, '/')) .')$/';
           // Compare with the internal and path alias (if any).
           $page_match = preg_match($regexp, $path);
           if ($path != $_GET['q']) {
Index: includes/locale.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/locale.inc,v
retrieving revision 1.132
diff -u -r1.132 locale.inc
--- includes/locale.inc	30 May 2007 08:08:57 -0000	1.132
+++ includes/locale.inc	31 May 2007 23:25:35 -0000
@@ -424,7 +424,7 @@
       LANGUAGE_NEGOTIATION_PATH_DEFAULT => t('Path prefix only. If a suitable path prefix is not identified, the default language is used.'),
       LANGUAGE_NEGOTIATION_PATH => t('Path prefix with language fallback. If a suitable  path prefix is not identified, language is based on user preferences and browser language settings.'),
       LANGUAGE_NEGOTIATION_DOMAIN => t('Domain name only. If a suitable domain name is not identified, the default language is used.')),
-    '#default_value' => variable_get('language_negotiation', LANGUAGE_NEGOTIATION_NONE),
+    '#default_value' => variable_get('language_negotiation'),
     '#description' => t('The used language detection mode. Changing this also changes how paths are constructed, so setting a different value breaks all incoming links. Do not change on a live site without thinking twice!')
   );
   $form['submit'] = array(
@@ -879,7 +879,7 @@
   }
 
   // Increment count of enabled languages.
-  variable_set('language_count', variable_get('language_count', 1) + 1);
+  variable_set('language_count', variable_get('language_count') + 1);
 
   watchdog('locale', 'The %language language (%code) has been created.', array('%language' => $name, '%code' => $langcode));
 }
@@ -1595,7 +1595,7 @@
   // Generating Portable Object file for a language
   if (isset($language)) {
     $filename = $language .'.po';
-    $header = "# $meta->name translation of ". variable_get('site_name', 'Drupal') ."\n";
+    $header = "# $meta->name translation of ". variable_get('site_name') ."\n";
     $header .= '# Copyright (c) '. date('Y') .' '. $user->name .' <'. $user->mail .">\n";
     $header .= "#\n";
     $header .= "msgid \"\"\n";
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.647
diff -u -r1.647 common.inc
--- includes/common.inc	29 May 2007 14:37:49 -0000	1.647
+++ includes/common.inc	31 May 2007 23:25:27 -0000
@@ -323,8 +323,7 @@
   drupal_maintenance_theme();
   drupal_set_header('HTTP/1.1 503 Service unavailable');
   drupal_set_title(t('Site off-line'));
-  print theme('maintenance_page', filter_xss_admin(variable_get('site_offline_message',
-    t('@site is currently under maintenance. We should be back shortly. Thank you for your patience.', array('@site' => variable_get('site_name', 'Drupal'))))));
+  print theme('maintenance_page', filter_xss_admin(variable_get('site_offline_message')));
 }
 
 /**
@@ -340,7 +339,7 @@
     $_REQUEST['destination'] = $_GET['q'];
   }
 
-  $path = drupal_get_normal_path(variable_get('site_404', ''));
+  $path = drupal_get_normal_path(variable_get('site_404'));
   if ($path && $path != $_GET['q']) {
     $return = menu_execute_active_handler($path);
   }
@@ -365,7 +364,7 @@
     $_REQUEST['destination'] = $_GET['q'];
   }
 
-  $path = drupal_get_normal_path(variable_get('site_403', ''));
+  $path = drupal_get_normal_path(variable_get('site_403'));
   if ($path && $path != $_GET['q']) {
     $return = menu_execute_active_handler($path);
   }
@@ -543,7 +542,7 @@
     $entry = $types[$errno] .': '. $message .' in '. $filename .' on line '. $line .'.';
 
     // Force display of error messages in update.php
-    if (variable_get('error_level', 1) == 1 || strstr($_SERVER['PHP_SELF'], 'update.php')) {
+    if (variable_get('error_level') == 1 || strstr($_SERVER['PHP_SELF'], 'update.php')) {
       drupal_set_message($entry, 'error');
     }
 
@@ -703,7 +702,7 @@
   // handful of string replacements. See settings.php for examples.
   // Cache the $custom_strings variable to improve performance.
   if (!isset($custom_strings[$langcode])) {
-    $custom_strings[$langcode] = variable_get('locale_custom_strings_'. $langcode, array());
+    $custom_strings[$langcode] = variable_get_default('locale_custom_strings_'. $langcode, array());
   }
   // Custom strings work for English too, even if locale module is disabled.
   if (isset($custom_strings[$langcode][$string])) {
@@ -1085,11 +1084,11 @@
 function format_date($timestamp, $type = 'medium', $format = '', $timezone = NULL, $langcode = NULL) {
   if (!isset($timezone)) {
     global $user;
-    if (variable_get('configurable_timezones', 1) && $user->uid && strlen($user->timezone)) {
+    if (variable_get('configurable_timezones') && $user->uid && strlen($user->timezone)) {
       $timezone = $user->timezone;
     }
     else {
-      $timezone = variable_get('date_default_timezone', 0);
+      $timezone = variable_get('date_default_timezone');
     }
   }
 
@@ -1097,17 +1096,17 @@
 
   switch ($type) {
     case 'small':
-      $format = variable_get('date_format_short', 'm/d/Y - H:i');
+      $format = variable_get_default('date_format_short', 'm/d/Y - H:i');
       break;
     case 'large':
-      $format = variable_get('date_format_long', 'l, F j, Y - H:i');
+      $format = variable_get_default('date_format_long', 'l, F j, Y - H:i');
       break;
     case 'custom':
       // No change to format
       break;
     case 'medium':
     default:
-      $format = variable_get('date_format_medium', 'D, m/d/Y - H:i');
+      $format = variable_get_default('date_format_medium', 'D, m/d/Y - H:i');
   }
 
   $max = strlen($format);
@@ -1222,7 +1221,7 @@
 
   // Cache the clean_url variable to improve performance.
   if (!isset($clean_url)) {
-    $clean_url = (bool)variable_get('clean_url', '0');
+    $clean_url = (bool)variable_get('clean_url');
   }
 
   $base = $options['absolute'] ? $base_url .'/' : base_path();
@@ -1345,7 +1344,7 @@
  * react to the closing of the page by calling hook_exit().
  */
 function drupal_page_footer() {
-  if (variable_get('cache', 0)) {
+  if (variable_get('cache')) {
     page_set_cache();
   }
 
@@ -1535,9 +1534,9 @@
   $no_module_preprocess = '';
   $no_theme_preprocess = '';
 
-  $preprocess_css = variable_get('preprocess_css', FALSE);
+  $preprocess_css = variable_get('preprocess_css');
   $directory = file_directory_path();
-  $is_writable = is_dir($directory) && is_writable($directory) && (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC);
+  $is_writable = is_dir($directory) && is_writable($directory) && (variable_get('file_downloads') == FILE_DOWNLOADS_PUBLIC);
 
   foreach ($css as $media => $types) {
     // If CSS preprocessing is off, we still need to output the styles.
@@ -1825,7 +1824,7 @@
  *   String to encode
  */
 function drupal_urlencode($text) {
-  if (variable_get('clean_url', '0')) {
+  if (variable_get_default('clean_url', 0)) {
     return str_replace(array('%2F', '%26', '%23'),
                        array('/', '%2526', '%2523'),
                        urlencode($text));
@@ -1842,7 +1841,7 @@
  *   The private key
  */
 function drupal_get_private_key() {
-  if (!($key = variable_get('drupal_private_key', 0))) {
+  if (!($key = variable_get('drupal_private_key'))) {
     $key = md5(uniqid(mt_rand(), true)) . md5(uniqid(mt_rand(), true));
     variable_set('drupal_private_key', $key);
   }
@@ -1874,7 +1873,7 @@
  */
 function drupal_valid_token($token, $value = '', $skip_anonymous = FALSE) {
   global $user;
-  return (($skip_anonymous && $user->uid == 0) || ($token == md5(session_id() . $value . variable_get('drupal_private_key', ''))));
+  return (($skip_anonymous && $user->uid == 0) || ($token == md5(session_id() . $value . variable_get('drupal_private_key'))));
 }
 
 /**
@@ -1930,6 +1929,8 @@
   fix_gpc_magic();
   // Load all enabled modules
   module_load_all();
+  // Get all variable metadata
+  variable_load_metadata();
   // Let all modules take action before menu system handles the reqest
   module_invoke_all('init');
 
@@ -2012,7 +2013,7 @@
   // To prevent e-mail from looking like spam, the addresses in the Sender and
   // Return-Path headers should have a domain authorized to use the originating
   // SMTP server.  Errors-To is redundant, but shouldn't hurt.
-  $default_from = variable_get('site_mail', ini_get('sendmail_from'));
+  $default_from = variable_get('site_mail');
   if ($default_from) {
     $defaults['From'] = $defaults['Reply-To'] = $defaults['Sender'] = $defaults['Return-Path'] = $defaults['Errors-To'] = $default_from;
   }
@@ -2032,8 +2033,8 @@
   $headers = $message['#headers'];
 
   // Allow for custom mail backend
-  if (variable_get('smtp_library', '') && file_exists(variable_get('smtp_library', ''))) {
-    include_once './' . variable_get('smtp_library', '');
+  if (variable_get('smtp_library') && file_exists(variable_get('smtp_library'))) {
+    include_once './' . variable_get('smtp_library');
     return drupal_mail_wrapper($mailkey, $to, $subject, $body, $from, $headers);
   }
   else {
@@ -2082,7 +2083,7 @@
   }
 
   // Fetch the cron semaphore
-  $semaphore = variable_get('cron_semaphore', FALSE);
+  $semaphore = variable_get_default('cron_semaphore', FALSE);
 
   if ($semaphore) {
     if (time() - $semaphore > 3600) {
@@ -2091,7 +2092,7 @@
       watchdog('cron', 'Cron has been running for more than an hour and is most likely stuck.', array(), WATCHDOG_ERROR);
 
       // Release cron semaphore
-      variable_del('cron_semaphore');
+      variable_del_default('cron_semaphore', FALSE);
     }
     else {
       // Cron is still running normally.
@@ -2125,7 +2126,7 @@
  */
 function drupal_cron_cleanup() {
   // See if the semaphore is still locked.
-  if (variable_get('cron_semaphore', FALSE)) {
+  if (variable_get_default('cron_semaphore', FALSE)) {
     watchdog('cron', 'Cron run exceeded the time limit and was aborted.', array(), WATCHDOG_WARNING);
 
     // Release cron semaphore
@@ -2168,7 +2169,7 @@
   // table contains the name of the current profile, and we can call variable_get()
   // to determine what one is active.
   if (!isset($profile)) {
-    $profile = variable_get('install_profile', 'default');
+    $profile = variable_get('install_profile');
   }
   $searchdir = array($directory);
   $files = array();
Index: includes/file.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/file.inc,v
retrieving revision 1.99
diff -u -r1.99 file.inc
--- includes/file.inc	30 May 2007 08:08:57 -0000	1.99
+++ includes/file.inc	31 May 2007 23:25:30 -0000
@@ -43,7 +43,7 @@
   if (strpos($path, file_directory_path() .'/') === 0) {
     $path = trim(substr($path, strlen(file_directory_path())), '\\/');
   }
-  switch (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC)) {
+  switch (variable_get_default('file_downloads', FILE_DOWNLOADS_PUBLIC)) {
     case FILE_DOWNLOADS_PUBLIC:
       return $GLOBALS['base_url'] .'/'. file_directory_path() .'/'. str_replace('\\', '/', $path);
     case FILE_DOWNLOADS_PRIVATE:
@@ -356,7 +356,7 @@
   $original = $filename;
 
   // Allow potentially insecure uploads for very savvy users and admin
-  if (!variable_get('allow_insecure_uploads', 0)) {
+  if (!variable_get_default('allow_insecure_uploads', 0)) {
     $whitelist = array_unique(explode(' ', trim($extensions)));
 
     // Split the filename up by periods. The first part becomes the basename
@@ -519,8 +519,7 @@
     // @todo: this should not be here. we need to figure out the right place.
     $extensions = '';
     foreach ($user->roles as $rid => $name) {
-      $extensions .= ' '. variable_get("upload_extensions_$rid",
-      variable_get('upload_extensions_default', 'jpg jpeg gif png txt html doc xls pdf ppt pps odt ods odp'));
+      $extensions .= ' '. variable_get_element('upload_extensions', $rid);
     }
 
     // Begin building file object.
@@ -911,7 +910,7 @@
  * @return A string containing a temp directory.
  */
 function file_directory_temp() {
-  $temporary_directory = variable_get('file_directory_temp', NULL);
+  $temporary_directory = variable_get_default('file_directory_temp', NULL);
 
   if (is_null($temporary_directory)) {
     $directories = array();
@@ -952,7 +951,7 @@
  * @return A string containing the path to Drupal's 'files' directory.
  */
 function file_directory_path() {
-  return variable_get('file_directory_path', 'files');
+  return variable_get('file_directory_path');
 }
 
 /**
Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.200
diff -u -r1.200 form.inc
--- includes/form.inc	28 May 2007 18:53:29 -0000	1.200
+++ includes/form.inc	31 May 2007 23:25:32 -0000
@@ -281,7 +281,7 @@
       // We'll clear out the cached copies of the form and its stored data
       // here, as we've finished with them. The in-memory copies are still
       // here, though.
-      if (variable_get('cache', CACHE_DISABLED) == CACHE_DISABLED) {
+      if (variable_get('cache') == CACHE_DISABLED) {
         cache_clear_all('form_'. $form_state['values']['form_build_id'], 'cache_form');
         cache_clear_all('storage_'. $form_state['values']['form_build_id'], 'cache_form');
       }
@@ -393,6 +393,17 @@
 
   drupal_alter('form_'. $form_id, $form, $form_state);
   drupal_alter('form', $form, $form_state, $form_id);
+  
+  // Now if we have a form with persistent variables, do the variable rewriting
+  // This will set all default values and disable variables in settings file
+  // This step needs to be done after form_alter because other modules may have
+  // been adding variables to the form. To skip this, set $form['#variable'] = FALSE
+  if (isset($form['#variable']) && $form['#variable']) {
+    global $conf;
+    $form['#variable_list'] = form_list_variables($form, TRUE, TRUE, $conf);
+    // We add the variables validation
+    $form['#validate'][] = 'form_validate_variables';
+  }
 }
 
 
@@ -1268,7 +1279,7 @@
   $element['#tree'] = TRUE;
 
   // Determine the order of day, month, year in the site's chosen date format.
-  $format = variable_get('date_format_short', 'm/d/Y - H:i');
+  $format = variable_get('date_format_short');
   $sort = array();
   $sort['day'] = max(strpos($format, 'd'), strpos($format, 'j'));
   $sort['month'] = max(strpos($format, 'm'), strpos($format, 'M'));
@@ -1956,3 +1967,132 @@
 /**
  * @} End of "defgroup batch".
  */
+
+/**
+ * Returns list of form elements that are persistent variables.
+ * 
+ * Optionally also sets default values for variables
+ * and admits a list of variables to be disabled in the form.
+ * Typically these are the $conf variables in settings file
+ * 
+ * Form elements that are persistent variables are marked with
+ * a #variable property.
+ * 
+ * Variable elements are special variables marked with a #variable_element 
+ * property, and the variable name can be set in the element or the fieldset
+ * with the '#variable_name' property
+ * 
+ * @param $form
+ *   Form array
+ * @param $rebuild
+ *   Wether to rebuild the list of variables or just return it if stored in the form
+ * @param $setdefaults
+ *   Set variable defaults if not set.
+ * @param $disable
+ *   List of variable names to disably. Tipically they'll be the ones in $conf array
+ * @param $variable_name
+ *   Internal use only
+ * @param $variable_element
+ *   Internal use only
+ * 
+ * @return
+ *   Variable list of the form $index => array($name, $element)
+ *   $index is the form element name. For simple variables $element is NULL
+ *   I.e. 'site_name' => array('site_name', NULL)
+ */
+function form_list_variables(&$form, $rebuild = FALSE, $setdefaults = FALSE, $disable = array(), $variable_name = NULL, $variable_element = NULL) {
+  if (!$rebuild && isset($form['#variable_list'])) {
+    return $form['#variable_list'];
+  }
+  $list = array();
+  
+  // The variable name/element can be set in the form or it may be the array index
+  // Also, when going up the tree, it can be defined by a fieldset
+  $variable_element = isset($form['#variable_element']) ? $form['#variable_element'] : $variable_element;
+  $variable_name = isset($form['#variable_name']) ? $form['#variable_name'] : $variable_name;
+  
+  foreach (element_children($form) as $index) {
+    // We process this element if it's marked as variable in the form
+    if (isset($form[$index]['#variable'])) {
+      // The variable name can be set in the parent element, can be the form index,
+      // or a different variable name can be set in the form
+      $name = $variable_name ? $variable_name : $index;
+      $name =  isset($form[$index]['#variable_name']) ? $form[$index]['#variable_name'] : $name;
+      // Check wether this is a full variable or a variable element
+      if (isset($form[$index]['#variable_element'])) {
+        // This item is marked as a variable element
+        $element = $form[$index]['#variable_element'];
+      } elseif (!is_null($variable_element) && ($type = variable_get_metadata($name, 'type')) && ($type & VARIABLE_GROUP)) {
+        // This is a group variable and we have a the variable element defined
+        $element = $variable_element;
+      } else {
+        // This is a full variable
+        $element = NULL;
+      }
+      // Set default value if there's one for this variable /element
+      // We always use the default language to get these default values
+      $default_value = $element ? variable_get_element($name, $element, language_default('language')) : variable_get($name, language_default('language'));
+      if ($setdefaults && !is_null($default_value) && !isset($form[$index]['#default_value'])) {
+        $form[$index]['#default_value'] = $default_value;
+      }
+      // Disable if variable is in $disable list
+      if ($disable && isset($disable[$name]) && !isset($form[$index]['#disabled'])) {
+        $form[$index]['#disabled'] = TRUE;
+      }        
+      // Store the variable name and the element name
+      $list[$index] = array($name, $element);
+    }
+    elseif (isset($form[$index]['#type']) && $form[$index]['#type'] == 'fieldset' && (empty($form[$index]['#tree']) || !$form[$index]['#tree'])) {
+      // We go up the tree, passing along $variable_name and $variable_element in case there are nested fieldsets
+      $list += form_list_variables($form[$index], TRUE, $setdefaults, $disable, $variable_name, $variable_element);
+    }         
+  }
+  return $list;
+}
+
+/**
+ * Perform additional validations on  print "form_list_variables: default: $default_value";variable values based on predefined variable data
+ */
+function form_validate_variables($form, &$form_state, $form_values) {
+  foreach (form_list_variables($form) as $index => $variable) {
+    list($name, $element) = $variable;
+    $type = variable_get_metadata($name, 'type');
+    if (isset($form_values[$index]) && ($value = $form_values[$index])) {
+      switch ($type & VARIABLE_TYPE) {
+        case VARIABLE_MAIL:
+          if (!valid_email_address($value)) {
+            form_set_error($index, t('You must enter a valid email address'));
+          }
+          break;
+        case VARIABLE_NUMBER:
+          if (!is_numeric($value)) {
+            form_set_error($index, t('You must enter a numeric value'));
+          }
+          break;
+      }
+    }
+  }
+}
+
+/**
+ * Execute the settings form saving or resetting variables.
+ *
+ * If you want node type configure style handling of your checkboxes,
+ * add an array_filter value to your form.
+ *
+ */
+function form_submit_variables($form, &$form_state, $form_values, $reset = FALSE) {
+  foreach (form_list_variables($form) as $index => $variable) {
+    list($name, $element) = $variable;
+    if ($reset && isset($form_values[$index])) {
+      $element ? variable_del_element($name, $element) : variable_del($name);
+    }
+    elseif (isset($form_values[$index])) {
+      $value = $form_values[$index];
+      if (is_array($value) && isset($form_values['array_filter'])) {
+        $value = array_keys(array_filter($value));
+      }
+      $element ? variable_set_element($name, $element, $value) : variable_set($name, $value);
+    }
+  }
+}
\ No newline at end of file
Index: includes/path.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/path.inc,v
retrieving revision 1.15
diff -u -r1.15 path.inc
--- includes/path.inc	26 Mar 2007 01:32:22 -0000	1.15
+++ includes/path.inc	31 May 2007 23:25:38 -0000
@@ -18,7 +18,7 @@
     $_GET['q'] = drupal_get_normal_path(trim($_GET['q'], '/'));
   }
   else {
-    $_GET['q'] = drupal_get_normal_path(variable_get('site_frontpage', 'node'));
+    $_GET['q'] = drupal_get_normal_path(variable_get('site_frontpage'));
   }
 }
 
@@ -220,5 +220,5 @@
 function drupal_is_front_page() {
   // As drupal_init_path updates $_GET['q'] with the 'site_frontpage' path,
   // we can check it against the 'site_frontpage' variable.
-  return $_GET['q'] == drupal_get_normal_path(variable_get('site_frontpage', 'node'));
+  return $_GET['q'] == drupal_get_normal_path(variable_get('site_frontpage'));
 }
Index: includes/bootstrap.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.169
diff -u -r1.169 bootstrap.inc
--- includes/bootstrap.inc	30 May 2007 08:08:57 -0000	1.169
+++ includes/bootstrap.inc	31 May 2007 23:25:24 -0000
@@ -132,6 +132,76 @@
 define('LANGUAGE_NEGOTIATION_DOMAIN', 3);
 
 /**
+ * Variable base types. These are basic data types that may be combined with modifiers
+ */
+define('VARIABLE_STRING', 0x0001); // String value. May be plain text or markup
+define('VARIABLE_PATH', 0x0002); // String containing a path
+define('VARIABLE_NUMBER', 0x0004); // Numeric value
+define('VARIABLE_MAIL', 0x0010); // Valid e-mail address
+define('VARIABLE_BOOL', 0X0040); // Boolean TRUE or FALSE value
+define('VARIABLE_VALUE', 0x0020); // Value from a predefined range
+define('VARIABLE_DATA', 0x0008); // Other types of data
+
+/**
+ * Variable type modifiers. May be used to add some information into variable type
+ */
+define('VARIABLE_GROUP', 0x0100); // Defines a group of variables
+define('VARIABLE_LOCALIZE', 0x1000); // The default of this variable must be localized
+define('VARIABLE_FALLBACK', 0x2000); // This variable will use another one as a fallback for defaults
+
+/**
+ * Variable derived types. They consist of a base type and a modifier.
+ */
+define('VARIABLE_TEXT', VARIABLE_STRING | VARIABLE_LOCALIZE); // Localizable string, plain text
+define('VARIABLE_HTML', VARIABLE_STRING | VARIABLE_LOCALIZE); // Localizable string, markup
+
+/**
+ * Variable type mask to extract the basic data type with a logical AND.
+ */
+define('VARIABLE_TYPE', 0x00FF);
+
+/**
+ * Define default variables, the very minimum to start up.
+ * These variables can ve overridden in the settings file
+ */
+function _variable_defaults() {
+  return array(
+    'session_inc' => './includes/session.inc',
+    'cache_inc' => './includes/cache.inc',
+    'page_cache_fastpath' => 0,
+    'cache' => CACHE_DISABLED,
+    'language_count' => 1,
+    'language_default' => (object) array('language' => 'en', 'name' => 'English', 'native' => 'English', 'direction' => 0, 'enabled' => 1, 'plurals' => 0, 'formula' => '', 'domain' => '', 'prefix' => '', 'weight' => 0),
+    'language_negotiation' => LANGUAGE_NEGOTIATION_NONE,
+    'reverse_proxy' => FALSE,
+    // Install system: install.php
+    'site_name' => 'Drupal',
+    'site_mail' => ini_get('sendmail_from'),
+    'date_default_timezone' => 0,
+    'clean_url' => 0,
+    'preprocess_css' => 0,
+    'file_directory_path' => 'files',
+    // Common variables used without modules: common.inc and included files
+    'smtp_library' => '',
+    'install_profile' => 'default',
+    'error_level' => 1,
+    // This is a special variable used in file.inc and for other variables's default
+    'upload_extensions_default' => 'jpg jpeg gif png txt html doc xls pdf ppt pps odt ods odp',
+    // Path system: path.inc
+    'site_frontpage' => 'node',
+    // All variables needed for the maintenance theme
+    'theme_default' => 'garland',
+    'site_mission' => '',
+    'site_footer' => '',
+    'site_slogan' => '',
+    // Filter system: filter.module
+    'filter_allowed_protocols' => array('http', 'https', 'ftp', 'news', 'nntp', 'telnet', 'mailto', 'irc', 'ssh', 'sftp', 'webcal'),
+    'filter_default_format' => 1,
+    'drupal_private_key' => 0,
+  );
+}
+
+/**
  * Start the timer with the specified name. If you start and stop
  * the same timer multiple times, the measured intervals will be
  * accumulated.
@@ -260,8 +330,11 @@
  * session name correctly.
  */
 function conf_init() {
-  global $base_url, $base_path, $base_root;
-
+  global $base_url, $base_path, $base_root, $variables;
+  
+  // Initialize global variables array
+  $variables = array();
+  
   // Export the following settings.php variables to the global namespace
   global $db_url, $db_prefix, $cookie_domain, $conf, $installed_profile;
   $conf = array();
@@ -396,7 +469,7 @@
  * with variable_set() as well as those explicitly specified in the configuration
  * file.
  */
-function variable_init($conf = array()) {
+function variable_init() {
   // NOTE: caching the variables improves performance by 20% when serving cached pages.
   if ($cached = cache_get('variables', 'cache')) {
     $variables = $cached->data;
@@ -404,15 +477,15 @@
   else {
     $result = db_query('SELECT * FROM {variable}');
     while ($variable = db_fetch_object($result)) {
-      $variables[$variable->name] = unserialize($variable->value);
+      if ($variable->element) {
+        $variables[$variable->name][$variable->element] = unserialize($variable->value);
+      } else {
+        $variables[$variable->name] = unserialize($variable->value);
+      }
     }
     cache_set('variables', $variables);
   }
 
-  foreach ($conf as $name => $value) {
-    $variables[$name] = $value;
-  }
-
   return $variables;
 }
 
@@ -421,15 +494,164 @@
  *
  * @param $name
  *   The name of the variable to return.
+ * @param $langcode
+ *   Language code, as some default values need localization
+ * @return
+ *   The value of the variable. NULL if no value found.
+ */
+function variable_get($name, $langcode = NULL) {
+  global $variables;
+  
+  // Special DEBUG, to catch left variable_gets with default
+  if ($langcode && $langcode != 'en') {
+    drupal_set_message("DEBUG: variable_get: $name, $langcode"); //break_it_to_see_backtrace();
+  }
+  
+  $value = isset($variables[$name]) ? $variables[$name] : variable_get_metadata($name, 'default', $langcode);
+
+  return $value;
+}
+
+/**
+ * Return an element of a persistent group variable if exists
+ * 
+ * A group variable is a special variable type that is stored as an array
+ * with different properties or elements. With these special variable functions
+ * we can get and set individual properties of the array.
+ * 
+ * Example:
+ * @code
+ *  $format = 1; // This is a filter format id
+ *  // To get the allowed HTML for this filter format
+ *  variable_get_element('filter_allowed_html', $format);
+ *  // To set a value for this variable element
+ *  variable_set_element('filter_allowed_html', $format, $value);
+ * @endcode
+ * 
+ * @param $name
+ *   The name of the variable.
+ * @param $element
+ *   Name of the element to return
+ * @param $langcode
+ *   Language code, as some default values need localization
+ * @return
+ *   The value of the variable. NULL if no value found.
+ */
+function variable_get_element($name, $element, $langcode = NULL) {
+  global $variables;
+  
+  return isset($variables[$name][$element]) ? $variables[$name][$element] : variable_get_metadata($name, 'default', $langcode, $element);
+}
+
+/**
+ * Return a persistent variable if exists, or the default otherwise
+ * 
+ * Use this function only in the cases when:
+ * - You need to check whether a variable is actually set, so you don't want to
+ *   get default values from the variable system. 
+ * - There's no system default for a variable and you need to have a not null one
+ *   This can happen on bootstrap functions or when you use a variable from a module
+ *   that may not be enabled/loaded.
+ * - Super fast variable retrieving, for performance critical variables like 'dev_query'
+ * 
+ * @param $name
+ *   The name of the variable to return.
  * @param $default
- *   The default value to use if this variable has never been set.
+ *   The default value to use if this variable is not set.
+ * 
  * @return
  *   The value of the variable.
  */
-function variable_get($name, $default) {
-  global $conf;
+function variable_get_default($name, $default) {
+  global $variables;  
+  return isset($variables[$name]) ? $variables[$name] : $default;
+}
+
+/**
+ * Get metadata about a variable
+ * 
+ * @param $name
+ *   Variable name. 
+ * @param $type
+ *   Optional data to retrieve
+ *   - 'default' to get the default value for a variable
+ *   - 'type' to get a variable type
+ *   - None to get all the metadata for the variable
+ * @param $langcode
+ *   Optional language code to localize the variable default.
+ * @param $element
+ *   Optional element for variable elements. 
+ * 
+ * @return
+ *   Requested metadata or NULL if not available
+ */
+function variable_get_metadata($name, $type = NULL, $langcode = NULL, $element = NULL) {
+  global $variables;
+  // drupal_set_message("variable_get_metadata: $name, $type, $element");
+  // Get the data to be used for the rest of this function
+  $data = isset($variables['#metadata'][$name]) ? $variables['#metadata'][$name] : array();
+  // So we do have metadata for this variable, return the value asked
+  switch ($type) {
+    case 'type':
+      return isset($data['type']) ? $data['type'] : NULL;
+    case 'default':
+      // If this is a group variable and we have no element, the default will be an array
+      if (!$element && isset($data['type']) && ($data['type'] & VARIABLE_GROUP)) {
+        return isset($variables['#defaults'][$name]) ? $variables['#defaults'][$name] : array();
+      }
+      if (isset($data['default'])) {
+        if ($data['type'] & VARIABLE_FALLBACK) {
+          // The default for this variable is another variable. Fall back system.
+          return variable_get($data['default'], $langcode);
+        } elseif ($data['type'] & VARIABLE_LOCALIZE) {
+          // For some variables we need to localize the default
+          return t($data['default'], (isset($data['default_args']) ? $data['default_args'] : array()), $langcode); 
+        } else {
+          return $data['default'];
+        }          
+      } elseif ($element) {
+        // There may be a variable with a special name, appending _default
+        return variable_get($name.'_default', $langcode);
+      } else {
+        // Last try, return system default if exists or NULL
+        return (isset($variables['#defaults'][$name])) ? $variables['#defaults'][$name] : NULL;
+      }
+    default:
+      return $data;     
+  }
+}
 
-  return isset($conf[$name]) ? $conf[$name] : $default;
+/**
+ * Manages metadata about variables.
+ * 
+ * The metadata is collected from modules hook_variable() so it won't be available 
+ * before module loading.
+ *  
+ * To load all the metadata at once, call this function once with no parameters. For 
+ * incremental loading, like the one that happens from bootstrap for cached
+ * pages, call it after each module loading.
+ * 
+ * @param $type
+ *   Operation to perform
+ *   - 'refresh' to reload all variable metadata from modules
+ *   - 'module' to load metadata incrementally for a module
+ * @param $param
+ *   Optional module name for incremental loading.
+ */
+function variable_load_metadata($op = 'refresh', $param = NULL) {
+  global $variables;
+  if (!isset($variables['#metadata'])) {
+    $variables['#metadata'] = array();
+  }
+  switch ($op) {
+    case 'refresh':
+      $variables['#metadata'] = module_invoke_all('variable');
+      break;
+    case 'module':
+      if ($metadata = module_invoke($param, 'variable')) {
+        $variables['#metadata'] = array_merge($variables['#metadata'], $metadata);
+      }
+  }
 }
 
 /**
@@ -440,19 +662,75 @@
  * @param $value
  *   The value to set. This can be any PHP data type; these functions take care
  *   of serialization as necessary.
+ * @param $element
+ *   Internal use only. See variable_group_set().
  */
 function variable_set($name, $value) {
-  global $conf;
+  global $variables;
+  
+  if (isset($variables[$name]) && $variables[$name] == $value) {
+    // Variable not changed, do nothing
+    return;
+  } 
+
+  // Check the value against the default value for this variable
+  if (!is_null($default = variable_get_metadata($name, 'default', language_default('language'))) && $value == $default) {
+    // This means the value we want to set is the default value of the variable
+    // so we just delete the variable from the database if it is there
+    variable_del($name);
+    return;
+  }
 
+  // If we get to this point, we actually need to set the value in the database
   $serialized_value = serialize($value);
   db_query("UPDATE {variable} SET value = '%s' WHERE name = '%s'", $serialized_value, $name);
   if (!db_affected_rows()) {
     @db_query("INSERT INTO {variable} (name, value) VALUES ('%s', '%s')", $name, $serialized_value);
   }
-
+  
   cache_clear_all('variables', 'cache');
+  
+  $variables[$name] = $value;
+}
 
-  $conf[$name] = $value;
+/**
+ * Set a persistent group variable.
+ *
+ * This is actually a wrapper for variable_set which provides a more logical parameter ordering
+ * and serves to have marked all group variables in the code.
+ * 
+ * @param $name
+ *   The name of the variable.
+ * @param $element
+ *   The name of the element to set
+ * @param $value
+ *   The value to set. This can be any PHP data type; these functions take care
+ *   of serialization as necessary.
+ */
+function variable_set_element($name, $element, $value) {
+  global $variables;
+  
+  if (isset($variables[$name][$element]) && $variables[$name][$element] == $value) {
+    // Variable element not changed, do nothing
+    return;
+  } 
+  // Check the value against the default value for this variable element
+  if (!is_null($default = variable_get_metadata($name, 'default', language_default('language'), $element)) && $value == $default) {
+    // This means the value we want to set is the default value of the variable element
+    // so we just delete the variable element
+    variable_del_element($name, $element);
+    return;
+  } 
+  // If we get to this point, we actually need to set the value element
+  $serialized_value = serialize($value);
+  db_query("UPDATE {variable} SET value = '%s' WHERE name = '%s' AND element = '%s'", $serialized_value, $name, $element);
+  if (!db_affected_rows()) {
+    @db_query("INSERT INTO {variable} (name, element, value) VALUES ('%s', '%s', '%s')", $name, $element, $serialized_value);
+  }
+  
+  cache_clear_all('variables', 'cache');
+  
+  $variables[$name] = $value;
 }
 
 /**
@@ -462,14 +740,35 @@
  *   The name of the variable to undefine.
  */
 function variable_del($name) {
-  global $conf;
-
-  db_query("DELETE FROM {variable} WHERE name = '%s'", $name);
-  cache_clear_all('variables', 'cache');
+  global $variables;
+  
+  // If it isn't in $variables it means that it isn't in the database either
+  if (isset($variables[$name])) {
+    db_query("DELETE FROM {variable} WHERE name = '%s'", $name);
+    cache_clear_all('variables', 'cache');
 
-  unset($conf[$name]);
+    unset($variables[$name]);
+  }
 }
 
+/**
+ * Unset a persistent variable element.
+ *
+ * @param $name
+ *   Name of the variable to undefine.
+ * @param $element
+ *   Variable group to undefine
+ */
+function variable_del_element($name, $element) {
+  global $variables;
+  
+  if (isset($variables[$name][$element])) {
+    db_query("DELETE FROM {variable} WHERE name = '%s' AND element = '%s'", $name, $element);
+    cache_clear_all('variables', 'cache');
+    
+    unset($variables[$name][$element]);
+  }
+}
 
 /**
  * Retrieve the current page from the cache.
@@ -502,6 +801,7 @@
 function bootstrap_invoke_all($hook) {
   foreach (module_list(TRUE, TRUE) as $module) {
     drupal_load('module', $module);
+    variable_load_metadata('module', $module);
     module_invoke($module, $hook);
  }
 }
@@ -530,7 +830,6 @@
   if ($filename) {
     include_once "./$filename";
     $files[$type][$name] = TRUE;
-
     return TRUE;
   }
 
@@ -860,7 +1159,7 @@
 }
 
 function _drupal_bootstrap($phase) {
-  global $conf;
+  global $conf, $variables;
 
   switch ($phase) {
 
@@ -868,6 +1167,10 @@
       drupal_unset_globals();
       // Initialize the configuration
       conf_init();
+      // Initialize the minimum set of variables for bootstrap
+      // that may be overridden by the the settings file, in $conf array
+      $variables = isset($conf) ? $conf : array();
+      $variables['#defaults'] = _variable_defaults();
       break;
 
     case DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE:
@@ -890,14 +1193,17 @@
       break;
 
     case DRUPAL_BOOTSTRAP_SESSION:
-      require_once variable_get('session_inc', './includes/session.inc');
+      require_once variable_get('session_inc');
       session_set_save_handler('sess_open', 'sess_close', 'sess_read', 'sess_write', 'sess_destroy_sid', 'sess_gc');
       session_start();
       break;
 
     case DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE:
-      // Initialize configuration variables, using values from settings.php if available.
-      $conf = variable_init(isset($conf) ? $conf : array());
+      // Initialize configuration variables, using this order of preference:
+      // 1. Values from settings.php if available, they're in $conf
+      // 2. Values loaded from the database
+      // 3. Default startup variables
+      $variables += variable_init();
 
       _drupal_cache_init($phase);
 
@@ -929,20 +1235,20 @@
  * Drupal's bootstrap process.
  */
 function _drupal_cache_init($phase) {
-  require_once variable_get('cache_inc', './includes/cache.inc');
+  require_once variable_get('cache_inc');
 
-  if ($phase == DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE && variable_get('page_cache_fastpath', 0)) {
+  if ($phase == DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE && variable_get('page_cache_fastpath')) {
     if (page_cache_fastpath()) {
       exit();
     }
   }
   elseif ($phase == DRUPAL_BOOTSTRAP_LATE_PAGE_CACHE) {
     if ($cache = page_get_cache()) {
-      if (variable_get('cache', CACHE_DISABLED) == CACHE_AGGRESSIVE) {
+      if (variable_get('cache') == CACHE_AGGRESSIVE) {
         drupal_page_cache_header($cache);
         exit();
       }
-      elseif (variable_get('cache', CACHE_DISABLED) == CACHE_NORMAL) {
+      elseif (variable_get('cache') == CACHE_NORMAL) {
         require_once './includes/module.inc';
         bootstrap_invoke_all('boot');
         drupal_page_cache_header($cache);
@@ -1004,7 +1310,7 @@
 
   // Ensure the language is correctly returned, even without multilanguage support.
   // Useful for eg. XML/HTML 'lang' attributes.
-  if (variable_get('language_count', 1) == 1) {
+  if (variable_get('language_count') == 1) {
     $language = language_default();
   }
   else {
@@ -1058,7 +1364,8 @@
  *   Optional property of the language object to return
  */
 function language_default($property = NULL) {
-  $language = variable_get('language_default', (object) array('language' => 'en', 'name' => 'English', 'native' => 'English', 'direction' => 0, 'enabled' => 1, 'plurals' => 0, 'formula' => '', 'domain' => '', 'prefix' => '', 'weight' => 0));
+  // Special case, this function defines the default language
+  $language = variable_get('language_default');
   return $property ? $language->$property : $language;
 }
 
@@ -1080,7 +1387,7 @@
   }
   else {
     $remote_ip = $_SERVER['REMOTE_ADDR'];
-    if (variable_get('reverse_proxy', FALSE) && array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) {
+    if (variable_get('reverse_proxy') && array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) {
       $ip_array = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
       // If there are several arguments, the leftmost one is the farthest client
       $remote_ip = $ip_array[0];
Index: includes/cache.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/cache.inc,v
retrieving revision 1.12
diff -u -r1.12 cache.inc
--- includes/cache.inc	25 May 2007 21:01:30 -0000	1.12
+++ includes/cache.inc	31 May 2007 23:25:24 -0000
@@ -15,8 +15,8 @@
   global $user;
 
   // Garbage collection necessary when enforcing a minimum cache lifetime
-  $cache_flush = variable_get('cache_flush', 0);
-  if ($cache_flush && ($cache_flush + variable_get('cache_lifetime', 0) <= time())) {
+  $cache_flush = variable_get_default('cache_flush', 0);
+  if ($cache_flush && ($cache_flush + variable_get('cache_lifetime') <= time())) {
     // Time to flush old cache data
     db_query("DELETE FROM {". $table ."} WHERE expire != %d AND expire <= %d", CACHE_PERMANENT, $cache_flush);
     variable_set('cache_flush', 0);
@@ -26,7 +26,7 @@
   if (isset($cache->data)) {
     // If the data is permanent or we're not enforcing a minimum cache lifetime
     // always return the cached data.
-    if ($cache->expire == CACHE_PERMANENT || !variable_get('cache_lifetime', 0)) {
+    if ($cache->expire == CACHE_PERMANENT || !variable_get('cache_lifetime')) {
       $cache->data = db_decode_blob($cache->data);
       if ($cache->serialized) {
         $cache->data = unserialize($cache->data);
@@ -138,19 +138,19 @@
   }
 
   if (empty($cid)) {
-    if (variable_get('cache_lifetime', 0)) {
+    if (variable_get('cache_lifetime')) {
       // We store the time in the current user's $user->cache variable which
       // will be saved into the sessions table by sess_write(). We then
       // simulate that the cache was flushed for this user by not returning
       // cached data that was cached before the timestamp.
       $user->cache = time();
 
-      $cache_flush = variable_get('cache_flush', 0);
+      $cache_flush = variable_get_default('cache_flush', 0);
       if ($cache_flush == 0) {
         // This is the first request to clear the cache, start a timer.
         variable_set('cache_flush', time());
       }
-      else if (time() > ($cache_flush + variable_get('cache_lifetime', 0))) {
+      else if (time() > ($cache_flush + variable_get('cache_lifetime'))) {
         // Clear the cache for everyone, cache_flush_delay seconds have
         // passed since the first request to clear the cache.
         db_query("DELETE FROM {". $table ."} WHERE expire != %d AND expire < %d", CACHE_PERMANENT, time());
Index: includes/language.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/language.inc,v
retrieving revision 1.4
diff -u -r1.4 language.inc
--- includes/language.inc	18 Apr 2007 21:56:18 -0000	1.4
+++ includes/language.inc	31 May 2007 23:25:33 -0000
@@ -12,7 +12,7 @@
 function language_initialize() {
   global $user;
 
-  $mode = variable_get('language_negotiation', LANGUAGE_NEGOTIATION_NONE);
+  $mode = variable_get('language_negotiation');
   switch ($mode) {
     case LANGUAGE_NEGOTIATION_NONE:
       return language_default();
@@ -101,7 +101,7 @@
 
     // Language can be passed as an option, or we go for current language.
     $path_language = isset($options['language']) ? $options['language'] : $language;
-    switch (variable_get('language_negotiation', LANGUAGE_NEGOTIATION_NONE)) {
+    switch (variable_get_default('language_negotiation', LANGUAGE_NEGOTIATION_NONE)) {
 
       case LANGUAGE_NEGOTIATION_NONE:
         break;
Index: includes/database.pgsql.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database.pgsql.inc,v
retrieving revision 1.48
diff -u -r1.48 database.pgsql.inc
--- includes/database.pgsql.inc	30 May 2007 09:11:21 -0000	1.48
+++ includes/database.pgsql.inc	31 May 2007 23:25:28 -0000
@@ -153,14 +153,14 @@
 function _db_query($query, $debug = 0) {
   global $active_db, $last_result, $queries;
 
-  if (variable_get('dev_query', 0)) {
+  if (variable_get_default('dev_query', 0)) {
     list($usec, $sec) = explode(' ', microtime());
     $timer = (float)$usec + (float)$sec;
   }
 
   $last_result = pg_query($active_db, $query);
 
-  if (variable_get('dev_query', 0)) {
+  if (variable_get_default('dev_query', 0)) {
     $bt = debug_backtrace();
     $query = $bt[2]['function'] ."\n". $query;
     list($usec, $sec) = explode(' ', microtime());
Index: includes/theme.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.inc,v
retrieving revision 1.356
diff -u -r1.356 theme.inc
--- includes/theme.inc	22 May 2007 19:56:00 -0000	1.356
+++ includes/theme.inc	31 May 2007 23:25:39 -0000
@@ -41,7 +41,7 @@
 
   // Only select the user selected theme if it is available in the
   // list of enabled themes.
-  $theme = !empty($user->theme) && $themes[$user->theme]->status ? $user->theme : variable_get('theme_default', 'garland');
+  $theme = !empty($user->theme) && $themes[$user->theme]->status ? $user->theme : variable_get('theme_default');
 
   // Allow modules to override the present theme... only select custom theme
   // if it is available in the list of installed themes.
@@ -616,10 +616,10 @@
       $defaults['toggle_node_info_'. $type] = 1;
     }
   }
-  $settings = array_merge($defaults, variable_get('theme_settings', array()));
+  $settings = array_merge($defaults, variable_get_default('theme_settings', array()));
 
   if ($key) {
-    $settings = array_merge($settings, variable_get(str_replace('/', '_', 'theme_'. $key .'_settings'), array()));
+    $settings = array_merge($settings, variable_get_default(str_replace('/', '_', 'theme_'. $key .'_settings'), array()));
   }
 
   // Only offer search box if search.module is enabled.
@@ -657,7 +657,7 @@
     $theme_object = $themes[$theme_key];
 
     if ($settings['mission'] == '') {
-      $settings['mission'] = variable_get('site_mission', '');
+      $settings['mission'] = variable_get('site_mission');
     }
 
     if (!$settings['toggle_mission']) {
@@ -1387,7 +1387,7 @@
     $output .= ' ('. t('not verified') .')';
   }
   else {
-    $output = variable_get('anonymous', t('Anonymous'));
+    $output = ($value = variable_get('anonymous')) ? $value : t('Anonymous');
   }
 
   return $output;
@@ -1488,12 +1488,12 @@
 
   // Construct page title
   if (drupal_get_title()) {
-    $head_title = array(strip_tags(drupal_get_title()), variable_get('site_name', 'Drupal'));
+    $head_title = array(strip_tags(drupal_get_title()), variable_get('site_name'));
   }
   else {
-    $head_title = array(variable_get('site_name', 'Drupal'));
-    if (variable_get('site_slogan', '')) {
-      $head_title[] = variable_get('site_slogan', '');
+    $head_title = array(variable_get('site_name'));
+    if (variable_get('site_slogan')) {
+      $head_title[] = variable_get('site_slogan');
     }
   }
   $variables['head_title']        = implode(' | ', $head_title);
@@ -1501,7 +1501,7 @@
   $variables['breadcrumb']        = theme('breadcrumb', drupal_get_breadcrumb());
   $variables['closure']           = theme('closure');
   $variables['feed_icons']        = drupal_get_feeds();
-  $variables['footer_message']    = filter_xss_admin(variable_get('site_footer', FALSE)) . "\n" . theme('blocks', 'footer');
+  $variables['footer_message']    = filter_xss_admin(variable_get('site_footer')) . "\n" . theme('blocks', 'footer');
   $variables['head']              = drupal_get_html_head();
   $variables['help']              = theme('help');
   $variables['language']          = $GLOBALS['language'];
@@ -1511,8 +1511,8 @@
   $variables['primary_links']     = menu_primary_links();
   $variables['search_box']        = (theme_get_setting('toggle_search') ? drupal_get_form('search_theme_form') : '');
   $variables['secondary_links']   = menu_secondary_links();
-  $variables['site_name']         = (theme_get_setting('toggle_name') ? variable_get('site_name', 'Drupal') : '');
-  $variables['site_slogan']       = (theme_get_setting('toggle_slogan') ? variable_get('site_slogan', '') : '');
+  $variables['site_name']         = (theme_get_setting('toggle_name') ? variable_get('site_name') : '');
+  $variables['site_slogan']       = (theme_get_setting('toggle_slogan') ? variable_get('site_slogan') : '');
   $variables['css']               = drupal_add_css();
   $variables['styles']            = drupal_get_css();
   $variables['scripts']           = drupal_get_js();
Index: includes/install.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/install.inc,v
retrieving revision 1.40
diff -u -r1.40 install.inc
--- includes/install.inc	21 May 2007 10:56:05 -0000	1.40
+++ includes/install.inc	31 May 2007 23:25:33 -0000
@@ -354,6 +354,13 @@
 function drupal_uninstall_module($module) {
   module_load_install($module);
   module_invoke($module, 'uninstall');
+  // Delete module variables. We do this after hook_uninstall to give
+  // the module a chance to use stored variables for uninstall.
+  if ($variables = module_invoke($module, 'variable')) {
+    foreach (array_keys($variables) as $name) {
+      variable_del($name);
+    }
+  }
   drupal_set_installed_schema_version($module, SCHEMA_UNINSTALLED);
 }
 
Index: includes/database.mysql.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database.mysql.inc,v
retrieving revision 1.73
diff -u -r1.73 database.mysql.inc
--- includes/database.mysql.inc	25 May 2007 21:01:30 -0000	1.73
+++ includes/database.mysql.inc	31 May 2007 23:25:27 -0000
@@ -136,14 +136,14 @@
 function _db_query($query, $debug = 0) {
   global $active_db, $queries;
 
-  if (variable_get('dev_query', 0)) {
+  if (variable_get_default('dev_query', 0)) {
     list($usec, $sec) = explode(' ', microtime());
     $timer = (float)$usec + (float)$sec;
   }
 
   $result = mysql_query($query, $active_db);
 
-  if (variable_get('dev_query', 0)) {
+  if (variable_get_default('dev_query', 0)) {
     $bt = debug_backtrace();
     $query = $bt[2]['function'] ."\n". $query;
     list($usec, $sec) = explode(' ', microtime());
Index: includes/module.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/module.inc,v
retrieving revision 1.102
diff -u -r1.102 module.inc
--- includes/module.inc	25 May 2007 12:46:43 -0000	1.102
+++ includes/module.inc	31 May 2007 23:25:37 -0000
@@ -68,7 +68,7 @@
           // Determine the current throttle status and see if the module should be
           // loaded based on server load. We have to directly access the throttle
           // variables, since throttle.module may not be loaded yet.
-          $throttle = ($module->throttle && variable_get('throttle_level', 0) > 0);
+          $throttle = ($module->throttle && variable_get_default('throttle_level', 0) > 0);
           if (!$throttle) {
             drupal_get_filename('module', $module->name, $module->filename);
             $list[$module->name] = $module->name;
Index: includes/database.mysqli.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database.mysqli.inc,v
retrieving revision 1.37
diff -u -r1.37 database.mysqli.inc
--- includes/database.mysqli.inc	25 May 2007 21:01:30 -0000	1.37
+++ includes/database.mysqli.inc	31 May 2007 23:25:28 -0000
@@ -127,14 +127,14 @@
 function _db_query($query, $debug = 0) {
   global $active_db, $queries;
 
-  if (variable_get('dev_query', 0)) {
+  if (variable_get_default('dev_query', 0)) {
     list($usec, $sec) = explode(' ', microtime());
     $timer = (float)$usec + (float)$sec;
   }
 
   $result = mysqli_query($active_db, $query);
 
-  if (variable_get('dev_query', 0)) {
+  if (variable_get_default('dev_query', 0)) {
     $bt = debug_backtrace();
     $query = $bt[2]['function'] ."\n". $query;
     list($usec, $sec) = explode(' ', microtime());
Index: includes/menu.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/menu.inc,v
retrieving revision 1.172
diff -u -r1.172 menu.inc
--- includes/menu.inc	30 May 2007 15:26:33 -0000	1.172
+++ includes/menu.inc	31 May 2007 23:25:37 -0000
@@ -687,7 +687,7 @@
 
           $args = $parents = array_unique($parents);
           $placeholders = implode(', ', array_fill(0, count($args), '%d'));
-          $expanded = variable_get('menu_expanded', array());
+          $expanded = variable_get_default('menu_expanded', array());
           if (in_array($menu_name, $expanded)) {
             do {
               $result = db_query("SELECT mlid FROM {menu_links} WHERE expanded != 0 AND has_children != 0 AND menu_name = '%s' AND plid IN (". $placeholders .') AND mlid NOT IN ('. $placeholders .')', array_merge(array($menu_name), $args, $args));
@@ -1706,7 +1706,7 @@
  */
 function _menu_site_is_offline() {
   // Check if site is set to off-line mode
-  if (variable_get('site_offline', 0)) {
+  if (variable_get_default('site_offline', 0)) {
     // Check if the user has administration privileges
     if (!user_access('administer site configuration')) {
       // Check if this is an attempt to login
Index: includes/image.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/image.inc,v
retrieving revision 1.21
diff -u -r1.21 image.inc
--- includes/image.inc	12 May 2007 05:51:20 -0000	1.21
+++ includes/image.inc	31 May 2007 23:25:32 -0000
@@ -30,7 +30,7 @@
 function image_get_toolkit() {
   static $toolkit;
   if (!$toolkit) {
-    $toolkit = variable_get('image_toolkit', 'gd');
+    $toolkit = variable_get('image_toolkit');
     $toolkit_file = './includes/image.'. $toolkit .'.inc';
     if ($toolkit != 'gd' && file_exists($toolkit_file)) {
       include_once $toolkit_file;
@@ -220,7 +220,7 @@
       '#description' => t('Define the image quality for JPEG manipulations. Ranges from 0 to 100. Higher values mean better image quality but bigger files.'),
       '#size' => 10,
       '#maxlength' => 3,
-      '#default_value' => variable_get('image_jpeg_quality', 75),
+      '#default_value' => variable_get_default('image_jpeg_quality', 75),
       '#field_suffix' => t('%'),
     );
 
@@ -348,7 +348,7 @@
     return FALSE;
   }
   if ($extension == 'jpeg') {
-    return $close_func($res, $destination, variable_get('image_jpeg_quality', 75));
+    return $close_func($res, $destination, variable_get_default('image_jpeg_quality', 75));
   }
   else {
     return $close_func($res, $destination);
Index: modules/user/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.module,v
retrieving revision 1.788
diff -u -r1.788 user.module
--- modules/user/user.module	30 May 2007 08:08:59 -0000	1.788
+++ modules/user/user.module	31 May 2007 23:26:02 -0000
@@ -322,20 +322,20 @@
   // If required, validate the uploaded picture.
   $validators = array(
     'file_validate_is_image' => array(),
-    'file_validate_image_resolution' => array(variable_get('user_picture_dimensions', '85x85')),
-    'file_validate_size' => array(variable_get('user_picture_file_size', '30') * 1024),
+    'file_validate_image_resolution' => array(variable_get('user_picture_dimensions')),
+    'file_validate_size' => array(variable_get('user_picture_file_size') * 1024),
   );
   if ($file = file_save_upload('picture_upload', $validators)) {
     // The image was saved using file_save_upload() and was added to the
     // files table as a temorary file. We'll make a copy and let the garbage
     // collector delete the original upload.
     $info = image_get_info($file->filepath);
-    $destination = variable_get('user_picture_path', 'pictures') .'/picture-'. $form['#uid'] .'.'. $info['extension'];
+    $destination = variable_get('user_picture_path') .'/picture-'. $form['#uid'] .'.'. $info['extension'];
     if (file_copy($file, $destination, FILE_EXISTS_REPLACE)) {
       $form_values['picture'] = $file->filepath;
     }
     else {
-      form_set_error('picture_upload', t("Failed to upload the picture image; the %directory directory doesn't exist or is not writable.", array('%directory' => variable_get('user_picture_path', 'pictures'))));
+      form_set_error('picture_upload', t("Failed to upload the picture image; the %directory directory doesn't exist or is not writable.", array('%directory' => variable_get('user_picture_path'))));
     }
   }
 }
@@ -454,7 +454,7 @@
  * Ensure that user pictures (avatars) are always downloadable.
  */
 function user_file_download($file) {
-  if (strpos($file, variable_get('user_picture_path', 'pictures') .'/picture-') === 0) {
+  if (strpos($file, variable_get('user_picture_path') .'/picture-') === 0) {
     $info = image_get_info(file_create_path($file));
     return array('Content-type: '. $info['mime_type']);
   }
@@ -535,7 +535,7 @@
     '#value' => t('Log in'),
   );
   $items = array();
-  if (variable_get('user_register', 1)) {
+  if (variable_get('user_register')) {
     $items[] = l(t('Create new account'), 'user/register', array('title' => t('Create a new user account.')));
   }
   $items[] = l(t('Request new password'), 'user/password', array('title' => t('Request new password via e-mail.')));
@@ -561,15 +561,15 @@
     $form['user_block_whois_new_count'] = array(
       '#type' => 'select',
       '#title' => t('Number of users to display'),
-      '#default_value' => variable_get('user_block_whois_new_count', 5),
+      '#default_value' => variable_get('user_block_whois_new_count'),
       '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)),
     );
     return $form;
   }
   else if ($op == 'configure' && $delta == 3) {
     $period = drupal_map_assoc(array(30, 60, 120, 180, 300, 600, 900, 1800, 2700, 3600, 5400, 7200, 10800, 21600, 43200, 86400), 'format_interval');
-    $form['user_block_seconds_online'] = array('#type' => 'select', '#title' => t('User activity'), '#default_value' => variable_get('user_block_seconds_online', 900), '#options' => $period, '#description' => t('A user is considered online for this long after they have last viewed a page.'));
-    $form['user_block_max_list_count'] = array('#type' => 'select', '#title' => t('User list length'), '#default_value' => variable_get('user_block_max_list_count', 10), '#options' => drupal_map_assoc(array(0, 5, 10, 15, 20, 25, 30, 40, 50, 75, 100)), '#description' => t('Maximum number of currently online users to display.'));
+    $form['user_block_seconds_online'] = array('#type' => 'select', '#title' => t('User activity'), '#default_value' => variable_get('user_block_seconds_online'), '#options' => $period, '#description' => t('A user is considered online for this long after they have last viewed a page.'));
+    $form['user_block_max_list_count'] = array('#type' => 'select', '#title' => t('User list length'), '#default_value' => variable_get('user_block_max_list_count'), '#options' => drupal_map_assoc(array(0, 5, 10, 15, 20, 25, 30, 40, 50, 75, 100)), '#description' => t('Maximum number of currently online users to display.'));
 
     return $form;
   }
@@ -603,7 +603,7 @@
       case 2:
         if (user_access('access content')) {
           // Retrieve a list of new users who have subsequently accessed the site successfully.
-          $result = db_query_range('SELECT uid, name FROM {users} WHERE status != 0 AND access != 0 ORDER BY created DESC', 0, variable_get('user_block_whois_new_count', 5));
+          $result = db_query_range('SELECT uid, name FROM {users} WHERE status != 0 AND access != 0 ORDER BY created DESC', 0, variable_get('user_block_whois_new_count'));
           while ($account = db_fetch_object($result)) {
             $items[] = $account;
           }
@@ -617,7 +617,7 @@
       case 3:
         if (user_access('access content')) {
           // Count users with activity in the past defined period.
-          $interval = time() - variable_get('user_block_seconds_online', 900);
+          $interval = time() - variable_get('user_block_seconds_online');
 
           // Perform database queries to gather online user lists.  We use s.timestamp
           // rather than u.access because it is much faster is much faster..
@@ -634,7 +634,7 @@
           }
 
           // Display a list of currently online users.
-          $max_users = variable_get('user_block_max_list_count', 10);
+          $max_users = variable_get('user_block_max_list_count');
           if ($authenticated_count && $max_users) {
             $items = array();
 
@@ -658,12 +658,12 @@
     if (!empty($account->picture) && file_exists($account->picture)) {
       $picture = file_create_url($account->picture);
     }
-    else if (variable_get('user_picture_default', '')) {
-      $picture = variable_get('user_picture_default', '');
+    else if (variable_get('user_picture_default')) {
+      $picture = variable_get('user_picture_default');
     }
 
     if (isset($picture)) {
-      $alt = t("@user's picture", array('@user' => $account->name ? $account->name : variable_get('anonymous', t('Anonymous'))));
+      $alt = t("@user's picture", array('@user' => $account->name ? $account->name : variable_get('anonymous')));
       $picture = theme('image', $picture, $alt, $alt, '', FALSE);
       if (!empty($account->uid) && user_access('access user profiles')) {
         $picture = l($picture, "user/$account->uid", array('attributes' => array('title' => t('View user profile.')), 'html' => TRUE));
@@ -730,7 +730,7 @@
 }
 
 function user_register_access() {
-  return !$GLOBALS['user']->uid && variable_get('user_register', 1);
+  return !$GLOBALS['user']->uid && variable_get('user_register');
 }
 
 function user_view_access($account) {
@@ -1040,10 +1040,10 @@
     '#attributes' => array('tabindex' => '1'),
   );
   if (variable_get('drupal_authentication_service', FALSE) && count(user_auth_help_links()) > 0) {
-    $form['name']['#description'] = t('Enter your @s username, or an ID from one of our affiliates: !a.', array('@s' => variable_get('site_name', 'Drupal'), '!a' => implode(', ', user_auth_help_links())));
+    $form['name']['#description'] = t('Enter your @s username, or an ID from one of our affiliates: !a.', array('@s' => variable_get('site_name'), '!a' => implode(', ', user_auth_help_links())));
   }
   else {
-    $form['name']['#description'] = t('Enter your @s username.', array('@s' => variable_get('site_name', 'Drupal')));
+    $form['name']['#description'] = t('Enter your @s username.', array('@s' => variable_get('site_name')));
   }
   $form['pass'] = array('#type' => 'password',
     '#title' => t('Password'),
@@ -1285,7 +1285,7 @@
 
   // Display the registration form.
   if (!$admin) {
-    $form['user_registration_help'] = array('#value' => filter_xss_admin(variable_get('user_registration_help', '')));
+    $form['user_registration_help'] = array('#value' => filter_xss_admin(variable_get('user_registration_help')));
   }
   $affiliates = user_auth_help_links();
   if (!$admin && count($affiliates) > 0) {
@@ -1335,14 +1335,14 @@
 
   $mail = $form_values['mail'];
   $name = $form_values['name'];
-  if (!variable_get('user_email_verification', TRUE) || $admin) {
+  if (!variable_get('user_email_verification') || $admin) {
     $pass = $form_values['pass'];
   }
   else {
     $pass = user_password();
   };
   $notify = isset($form_values['notify']) ? $form_values['notify'] : NULL;
-  $from = variable_get('site_mail', ini_get('sendmail_from'));
+  $from = variable_get('site_mail');
   if (isset($form_values['roles'])) {
     $roles = array_filter($form_values['roles']);     // Remove unset roles
   }
@@ -1361,7 +1361,7 @@
   $merge_data = array('pass' => $pass, 'init' => $mail, 'roles' => $roles);
   if (!$admin) {
     // Set the user's status because it was not displayed in the form.
-    $merge_data['status'] = variable_get('user_register', 1) == 1;
+    $merge_data['status'] = variable_get('user_register') == 1;
   }
   $account = user_save('', array_merge($form_values, $merge_data));
   $form_state['user'] = $account;
@@ -1371,7 +1371,7 @@
   // The first user may login immediately, and receives a customized welcome e-mail.
   if ($account->uid == 1) {
     drupal_set_message(t('<p>Welcome to Drupal. You are now logged in as user #1, which gives you full control over your website.</p>'));
-    if (variable_get('user_email_verification', TRUE)) {
+    if (variable_get('user_email_verification')) {
       drupal_set_message(t('</p><p> Your password is <strong>%pass</strong>. You may change your password below.</p>', array('%pass' => $pass)));
     }
 
@@ -1384,7 +1384,7 @@
     if ($admin && !$notify) {
       drupal_set_message(t('Created a new user account. No e-mail has been sent.'));
     }
-    else if (!variable_get('user_email_verification', TRUE) && $account->status && !$admin) {
+    else if (!variable_get('user_email_verification') && $account->status && !$admin) {
       // No e-mail verification is required, create new user account, and login user immediately.
       _user_mail_notify('register_no_approval_required', $account, $pass);
       user_authenticate($account->name, trim($pass));
@@ -1442,7 +1442,7 @@
       '#size' => 25,
     );
   }
-  elseif (!variable_get('user_email_verification', TRUE) || $admin) {
+  elseif (!variable_get('user_email_verification') || $admin) {
     $form['account']['pass'] = array(
       '#type' => 'password_confirm',
       '#description' => t('Provide a password for the new account in both fields.'),
@@ -1463,7 +1463,7 @@
   }
 
   // Signature:
-  if (variable_get('user_signatures', 0) && module_exists('comment') && !$register) {
+  if (variable_get('user_signatures') && module_exists('comment') && !$register) {
     $form['signature_settings'] = array(
       '#type' => 'fieldset',
       '#title' => t('Signature settings'),
@@ -1478,7 +1478,7 @@
   }
 
   // Picture/avatar:
-  if (variable_get('user_pictures', 0) && !$register) {
+  if (variable_get('user_pictures') && !$register) {
     $form['picture'] = array('#type' => 'fieldset', '#title' => t('Picture'), '#weight' => 1);
     $picture = theme('user_picture', (object)$edit);
     if ($picture) {
@@ -1488,7 +1488,7 @@
     else {
       $form['picture']['picture_delete'] = array('#type' => 'hidden');
     }
-    $form['picture']['picture_upload'] = array('#type' => 'file', '#title' => t('Upload picture'), '#size' => 48, '#description' => t('Your virtual face or picture. Maximum dimensions are %dimensions and the maximum size is %size kB.', array('%dimensions' => variable_get('user_picture_dimensions', '85x85'), '%size' => variable_get('user_picture_file_size', '30'))) .' '. variable_get('user_picture_guidelines', ''));
+    $form['picture']['picture_upload'] = array('#type' => 'file', '#title' => t('Upload picture'), '#size' => 48, '#description' => t('Your virtual face or picture. Maximum dimensions are %dimensions and the maximum size is %size kB.', array('%dimensions' => variable_get('user_picture_dimensions'), '%size' => variable_get('user_picture_file_size'))) .' '. variable_get('user_picture_guidelines'));
     $form['#validate'][] = 'user_validate_picture';
   }
   $form['#uid'] = $uid;
@@ -1661,41 +1661,14 @@
 function _user_mail_text($messageid, $variables = array()) {
 
   // Check if an admin setting overrides the default string.
-  if ($admin_setting = variable_get('user_mail_'. $messageid, FALSE)) {
+  if ($admin_setting = variable_get('user_mail_'. $messageid)) {
     return strtr($admin_setting, $variables);
   }
   // No override, return with default strings.
+  // Replicate previous behaviour
   else {
-    switch ($messageid) {
-      case 'register_no_approval_required_subject':
-        return t('Account details for !username at !site', $variables);
-      case 'register_no_approval_required_body':
-        return t("!username,\n\nThank you for registering at !site. You may now log in to !login_uri using the following username and password:\n\nusername: !username\npassword: !password\n\nYou may also log in by clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.\n\n\n--  !site team", $variables);
-      case 'register_admin_created_subject':
-        return t('An administrator created an account for you at !site', $variables);
-      case 'register_admin_created_body':
-        return t("!username,\n\nA site administrator at !site has created an account for you. You may now log in to !login_uri using the following username and password:\n\nusername: !username\npassword: !password\n\nYou may also log in by clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.\n\n\n--  !site team", $variables);
-      case 'register_pending_approval_subject':
-        return t('Account details for !username at !site (pending admin approval)', $variables);
-      case 'register_pending_approval_body':
-        return t("!username,\n\nThank you for registering at !site. Your application for an account is currently pending approval. Once it has been approved, you will receive another e-mail containing information about how to log in, set your password, and other details.\n\n\n--  !site team", $variables);
-      case 'password_reset_subject':
-        return t('Replacement login information for !username at !site', $variables);
-      case 'password_reset_body':
-        return t("!username,\n\nA request to reset the password for your account has been made at !site.\n\nYou may now log in to !uri_brief clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once. It expires after one day and nothing will happen if it's not used.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.", $variables);
-      case 'status_activated_subject':
-        return t('Account details for !username at !site (approved)', $variables);
-      case 'status_activated_body':
-        return "!username,\n\nYour account at !site has been activated.\n\nYou may now log in by clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.\n\nOnce you have set your own password, you will be able to log in to !login_uri in the future using the following username:\n\nusername: !username\n";
-      case 'status_blocked_subject':
-        return t('Account details for !username at !site (blocked)', $variables);
-      case 'status_blocked_body':
-        return "!username,\n\nYour account on !site has been blocked.";
-      case 'status_deleted_subject':
-        return t('Account details for !username at !site (deleted)', $variables);
-      case 'status_deleted_body':
-        return "!username,\n\nYour account on !site has been deleted.";
-    }
+    $data = variable_get_metadata('user_mail_'. $messageid);
+    return t($data['default'], $variables);
   }
 }
 
@@ -2438,9 +2411,9 @@
 function user_admin_settings() {
   // User registration settings.
   $form['registration'] = array('#type' => 'fieldset', '#title' => t('User registration settings'));
-  $form['registration']['user_register'] = array('#type' => 'radios', '#title' => t('Public registrations'), '#default_value' => variable_get('user_register', 1), '#options' => array(t('Only site administrators can create new user accounts.'), t('Visitors can create accounts and no administrator approval is required.'), t('Visitors can create accounts but administrator approval is required.')));
-  $form['registration']['user_email_verification'] = array('#type' => 'checkbox', '#title' => t('Require e-mail verification when a visitor creates an account'), '#default_value' => variable_get('user_email_verification', TRUE), '#description' => t('If this box is checked, new users will be required to validate their e-mail address prior to logging into to the site, and will be assigned a system-generated password. With it unchecked, users will be logged in immediately upon registering, and may select their own passwords during registration.'));
-  $form['registration']['user_registration_help'] = array('#type' => 'textarea', '#title' => t('User registration guidelines'), '#default_value' => variable_get('user_registration_help', ''), '#description' => t("This text is displayed at the top of the user registration form. It's useful for helping or instructing your users."));
+  $form['registration']['user_register'] = array('#variable' => TRUE, '#type' => 'radios', '#title' => t('Public registrations'), '#options' => array(t('Only site administrators can create new user accounts.'), t('Visitors can create accounts and no administrator approval is required.'), t('Visitors can create accounts but administrator approval is required.')));
+  $form['registration']['user_email_verification'] = array('#variable' => TRUE, '#type' => 'checkbox', '#title' => t('Require e-mail verification when a visitor creates an account'), '#description' => t('If this box is checked, new users will be required to validate their e-mail address prior to logging into to the site, and will be assigned a system-generated password. With it unchecked, users will be logged in immediately upon registering, and may select their own passwords during registration.'));
+  $form['registration']['user_registration_help'] = array('#variable' => TRUE, '#type' => 'textarea', '#title' => t('User registration guidelines'), '#description' => t("This text is displayed at the top of the user registration form. It's useful for helping or instructing your users."));
 
   // User e-mail settings.
   $form['email'] = array(
@@ -2456,19 +2429,19 @@
     '#type' => 'fieldset',
     '#title' => t('Welcome, new user created by administrator'),
     '#collapsible' => TRUE,
-    '#collapsed' => (variable_get('user_register', 1) != 0),
+    '#collapsed' => (variable_get('user_register') != 0),
     '#description' => t('Customize the welcome e-mail message that is sent to new member accounts created by an administrator.') .' '. $email_token_help,
   );
   $form['email']['admin_created']['user_mail_register_admin_created_subject'] = array(
+    '#variable' => TRUE, 
     '#type' => 'textfield',
     '#title' => t('Subject'),
-    '#default_value' => _user_mail_text('register_admin_created_subject'),
     '#maxlength' => 180,
   );
   $form['email']['admin_created']['user_mail_register_admin_created_body'] = array(
+    '#variable' => TRUE,
     '#type' => 'textarea',
     '#title' => t('Body'),
-    '#default_value' => _user_mail_text('register_admin_created_body'),
     '#rows' => 15,
   );
 
@@ -2476,19 +2449,19 @@
     '#type' => 'fieldset',
     '#title' => t('Welcome, no approval required'),
     '#collapsible' => TRUE,
-    '#collapsed' => (variable_get('user_register', 1) != 1),
+    '#collapsed' => (variable_get('user_register') != 1),
     '#description' => t('Customize the welcome e-mail message that is sent to new members upon registering when no administrator approval is required.') .' '. $email_token_help
   );
   $form['email']['no_approval_required']['user_mail_register_no_approval_required_subject'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Subject'),
-    '#default_value' => _user_mail_text('register_no_approval_required_subject'),
     '#maxlength' => 180,
   );
   $form['email']['no_approval_required']['user_mail_register_no_approval_required_body'] = array(
+    '#variable' => TRUE,
     '#type' => 'textarea',
     '#title' => t('Body'),
-    '#default_value' => _user_mail_text('register_no_approval_required_body'),
     '#rows' => 15,
   );
 
@@ -2500,15 +2473,15 @@
     '#description' => t('Customize the welcome message which is sent to new members that are awaiting approval.') .' '. $email_token_help,
   );
   $form['email']['pending_approval']['user_mail_register_pending_approval_subject'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Subject'),
-    '#default_value' => _user_mail_text('register_pending_approval_subject'),
     '#maxlength' => 180,
   );
   $form['email']['pending_approval']['user_mail_register_pending_approval_body'] = array(
+    '#variable' => TRUE,
     '#type' => 'textarea',
     '#title' => t('Body'),
-    '#default_value' => _user_mail_text('register_pending_approval_body'),
     '#rows' => 8,
   );
 
@@ -2520,15 +2493,15 @@
     '#description' => t('Customize the e-mail message sent to users that request a new password.') .' '. $email_token_help,
   );
   $form['email']['password_reset']['user_mail_password_reset_subject'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Subject'),
-    '#default_value' => _user_mail_text('password_reset_subject'),
     '#maxlength' => 180,
   );
   $form['email']['password_reset']['user_mail_password_reset_body'] = array(
+    '#variable' => TRUE,
     '#type' => 'textarea',
     '#title' => t('Body'),
-    '#default_value' => _user_mail_text('password_reset_body'),
     '#rows' => 12,
   );
 
@@ -2540,20 +2513,20 @@
     '#description' => t('Configure if an e-mail message should be sent to users when their accounts are activated, and if so, what the subject and body should be. This is particularly useful if your site requires administrator approval for new account requests.') .' '. $email_token_help,
   );
   $form['email']['activated']['user_mail_status_activated_notify'] = array(
+    '#variable' => TRUE,
     '#type' => 'checkbox',
     '#title' => t('Notify user when account is activated.'),
-    '#default_value' => variable_get('user_mail_status_activated_notify', TRUE),
   );
   $form['email']['activated']['user_mail_status_activated_subject'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Subject'),
-    '#default_value' => _user_mail_text('status_activated_subject'),
     '#maxlength' => 180,
   );
   $form['email']['activated']['user_mail_status_activated_body'] = array(
+    '#variable' => TRUE,
     '#type' => 'textarea',
     '#title' => t('Body'),
-    '#default_value' => _user_mail_text('status_activated_body'),
     '#rows' => 15,
   );
 
@@ -2565,20 +2538,20 @@
     '#description' => t('Configure if an e-mail message should be sent to users when their accounts are blocked, and if so, what the subject and body should be.') .' '. $email_token_help,
   );
   $form['email']['blocked']['user_mail_status_blocked_notify'] = array(
+    '#variable' => TRUE,
     '#type' => 'checkbox',
     '#title' => t('Notify user when account is blocked.'),
-    '#default_value' => variable_get('user_mail_status_blocked_notify', FALSE),
   );
   $form['email']['blocked']['user_mail_status_blocked_subject'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Subject'),
-    '#default_value' => _user_mail_text('status_blocked_subject'),
     '#maxlength' => 180,
   );
   $form['email']['blocked']['user_mail_status_blocked_body'] = array(
+    '#variable' => TRUE,
     '#type' => 'textarea',
     '#title' => t('Body'),
-    '#default_value' => _user_mail_text('status_blocked_body'),
     '#rows' => 3,
   );
 
@@ -2590,20 +2563,20 @@
     '#description' => t('Configure if an e-mail message should be sent to users when their accounts are deleted, and if so, what the subject and body should be.') .' '. $email_token_help,
   );
   $form['email']['deleted']['user_mail_status_deleted_notify'] = array(
+    '#variable' => TRUE,
     '#type' => 'checkbox',
     '#title' => t('Notify user when account is deleted.'),
-    '#default_value' => variable_get('user_mail_status_deleted_notify', FALSE),
   );
   $form['email']['deleted']['user_mail_status_deleted_subject'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Subject'),
-    '#default_value' => _user_mail_text('status_deleted_subject'),
     '#maxlength' => 180,
   );
   $form['email']['deleted']['user_mail_status_deleted_body'] = array(
+    '#variable' => TRUE,
     '#type' => 'textarea',
     '#title' => t('Body'),
-    '#default_value' => _user_mail_text('status_deleted_body'),
     '#rows' => 3,
   );
 
@@ -2613,15 +2586,16 @@
     '#title' => t('Signatures'),
   );
   $form['signatures']['user_signatures'] = array(
+    '#variable' => TRUE,
     '#type' => 'radios',
     '#title' => t('Signature support'),
-    '#default_value' => variable_get('user_signatures', 0),
+    '#default_value' => variable_get('user_signatures'),
     '#options' => array(t('Disabled'), t('Enabled')),
   );
 
   // If picture support is enabled, check whether the picture directory exists:
   if (variable_get('user_pictures', 0)) {
-    $picture_path = file_create_path(variable_get('user_picture_path', 'pictures'));
+    $picture_path = file_create_path(variable_get('user_picture_path'));
     file_check_directory($picture_path, 1, 'user_picture_path');
   }
 
@@ -2629,11 +2603,11 @@
     '#type' => 'fieldset',
     '#title' => t('Pictures'),
   );
-  $picture_support = variable_get('user_pictures', 0);
+  $picture_support = variable_get('user_pictures');
   $form['pictures']['user_pictures'] = array(
+    '#variable' => TRUE,
     '#type' => 'radios',
     '#title' => t('Picture support'),
-    '#default_value' => $picture_support,
     '#options' => array(t('Disabled'), t('Enabled')),
     '#prefix' => '<div class="user-admin-picture-radios">',
     '#suffix' => '</div>',
@@ -2651,41 +2625,41 @@
     '#suffix' => '</div>',
   );
   $form['pictures']['settings']['user_picture_path'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Picture image path'),
-    '#default_value' => variable_get('user_picture_path', 'pictures'),
     '#size' => 30,
     '#maxlength' => 255,
     '#description' => t('Subdirectory in the directory %dir where pictures will be stored.', array('%dir' => file_directory_path() .'/')),
   );
   $form['pictures']['settings']['user_picture_default'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Default picture'),
-    '#default_value' => variable_get('user_picture_default', ''),
     '#size' => 30,
     '#maxlength' => 255,
     '#description' => t('URL of picture to display for users with no custom picture selected. Leave blank for none.'),
   );
   $form['pictures']['settings']['user_picture_dimensions'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Picture maximum dimensions'),
-    '#default_value' => variable_get('user_picture_dimensions', '85x85'),
     '#size' => 15,
     '#maxlength' => 10,
     '#description' => t('Maximum dimensions for pictures, in pixels.'),
   );
   $form['pictures']['settings']['user_picture_file_size'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Picture maximum file size'),
-    '#default_value' => variable_get('user_picture_file_size', '30'),
     '#size' => 15,
     '#maxlength' => 10,
     '#description' => t('Maximum file size for pictures, in kB.'),
   );
   $form['pictures']['settings']['user_picture_guidelines'] = array(
+    '#variable' => TRUE,
     '#type' => 'textarea',
     '#title' => t('Picture guidelines'),
-    '#default_value' => variable_get('user_picture_guidelines', ''),
     '#description' => t("This text is displayed at the picture upload form in addition to the default guidelines. It's useful for helping or instructing your users."),
   );
 
@@ -2747,7 +2721,7 @@
     case 'admin/user/search':
       return '<p>'. t('Enter a simple pattern ("*" may be used as a wildcard match) to search for a username. For example, one may search for "br" and Drupal might return "brian", "brad", and "brenda".') .'</p>';
     case 'user/help#user':
-      $site = variable_get('site_name', 'Drupal');
+      $site = variable_get('site_name');
 
       $affiliates = user_auth_help_links();
       if (count($affiliates)) {
@@ -3044,7 +3018,7 @@
 function user_comment($comment, $op) {
   // Validate signature.
   if ($op == 'view') {
-    if (variable_get('user_signatures', 0) && !empty($comment->signature)) {
+    if (variable_get('user_signatures') && !empty($comment->signature)) {
       $comment->signature = check_markup($comment->signature, $comment->format);
     }
     else {
@@ -3085,7 +3059,7 @@
   global $base_url;
   $tokens = array(
     '!username' => $account->name,
-    '!site' => variable_get('site_name', 'Drupal'),
+    '!site' => variable_get('site_name'),
     '!login_url' => user_pass_reset_url($account),
     '!uri' => $base_url,
     '!uri_brief' => substr($base_url, strlen('http://')),
@@ -3136,10 +3110,10 @@
   }
   // By default, we always notify except for deleted and blocked.
   $default_notify = ($op != 'status_deleted' && $op != 'status_blocked');
-  $notify = variable_get('user_mail_'. $op .'_notify', $default_notify);
+  $notify = variable_get_default('user_mail_'. $op .'_notify', $default_notify);
   $result = NULL;
   if ($notify) {
-    $from = variable_get('site_mail', ini_get('sendmail_from'));
+    $from = variable_get('site_mail');
     $variables = user_mail_tokens($account, $password);
     $subject = _user_mail_text($op .'_subject', $variables);
     $body = _user_mail_text($op .'_body', $variables);
@@ -3151,3 +3125,62 @@
   }
   return $result;
 }
+
+/**
+ * Implementation of hook_variable()
+ */
+function user_variable() {
+  return array(
+    // User registration settings
+    'user_register' => array('type' => VARIABLE_DATA, 'default' => 1),
+    'user_email_verification' => array('type' => VARIABLE_DATA, 'default' => TRUE),
+    'user_registration_help' => array('type' => VARIABLE_STRING, 'default' => ''),
+    // User pictures
+    'user_pictures' => array('type' => VARIABLE_DATA, 'default' => 0),
+    'user_picture_default' => array('type' => VARIABLE_STRING, 'default' => ''),
+    'user_picture_dimensions' => array('type' => VARIABLE_STRING, 'default' => '85x85'), 
+    'user_picture_file_size' => array('type' => VARIABLE_NUMBER, 'default' => 30),
+    'user_picture_path' => array('type' => VARIABLE_PATH, 'default' => 'pictures'),
+    'user_picture_guidelines' => array('type' => VARIABLE_STRING, 'default' => ''),
+    // User block
+    'user_block_whois_new_count' => array('type' => VARIABLE_NUMBER, 'default' => 5),
+    'user_block_seconds_online' => array('type' => VARIABLE_NUMBER, 'default' => 900),
+    'user_block_max_list_count' => array('type' => VARIABLE_NUMBER, 'default' => 10),
+    
+    // User mail settings
+    'user_mail_status_activated_notify' => array('type' => VARIABLE_DATA, 'default' => TRUE),
+    'user_mail_status_blocked_notify' => array('type' => VARIABLE_DATA, 'default' => FALSE),
+    'user_mail_status_deleted_notify' => array('type' => VARIABLE_DATA, 'default' => FALSE),
+    
+    // User mail text
+    'user_mail_register_no_approval_required_subject' => array('type' => VARIABLE_TEXT,
+      'default' => 'Account details for !username at !site'),
+    'user_mail_register_no_approval_required_body' => array('type' => VARIABLE_TEXT,
+      'default' => "!username,\n\nThank you for registering at !site. You may now log in to !login_uri using the following username and password:\n\nusername: !username\npassword: !password\n\nYou may also log in by clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.\n\n\n--  !site team"),
+    'user_mail_register_admin_created_subject' => array('type' => VARIABLE_TEXT,
+      'default' => 'An administrator created an account for you at !site'),
+    'user_mail_register_admin_created_body' => array('type' => VARIABLE_TEXT,
+      'default' => "!username,\n\nA site administrator at !site has created an account for you. You may now log in to !login_uri using the following username and password:\n\nusername: !username\npassword: !password\n\nYou may also log in by clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.\n\n\n--  !site team"),
+    'user_mail_register_pending_approval_subject' => array('type' => VARIABLE_TEXT,
+      'default' => 'Account details for !username at !site (pending admin approval)'),
+    'user_mail_register_pending_approval_body' => array('type' => VARIABLE_TEXT,
+      'default' => "!username,\n\nThank you for registering at !site. Your application for an account is currently pending approval. Once it has been approved, you will receive another e-mail containing information about how to log in, set your password, and other details.\n\n\n--  !site team"),
+    'user_mail_password_reset_subject' => array('type' => VARIABLE_TEXT,
+      'default' => 'Replacement login information for !username at !site'),
+    'user_mail_password_reset_body' => array('type' => VARIABLE_TEXT,
+      'default' => "!username,\n\nA request to reset the password for your account has been made at !site.\n\nYou may now log in to !uri_brief clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once. It expires after one day and nothing will happen if it's not used.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password."),
+    'user_mail_status_activated_subject' => array('type' => VARIABLE_TEXT,
+      'default' => 'Account details for !username at !site (approved)'),
+    'user_mail_status_activated_body' => array('type' => VARIABLE_TEXT, 
+      'default' => "!username,\n\nYour account at !site has been activated.\n\nYou may now log in by clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.\n\nOnce you have set your own password, you will be able to log in to !login_uri in the future using the following username:\n\nusername: !username\n"),
+    'user_mail_status_blocked_subject' => array('type' => VARIABLE_TEXT,
+      'default' => 'Account details for !username at !site (blocked)'),
+    'user_mail_status_blocked_body' => array('type' => VARIABLE_TEXT,
+        'default' => "!username,\n\nYour account on !site has been blocked."),
+    'user_mail_status_deleted_subject' => array('type' => VARIABLE_TEXT,
+        'default' => 'Account details for !username at !site (deleted)'),
+    'user_mail_status_deleted_body' => array('type' => VARIABLE_TEXT,
+        'default' => "!username,\n\nYour account on !site has been deleted."),
+
+  );  
+}
\ No newline at end of file
Index: modules/taxonomy/taxonomy.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v
retrieving revision 1.356
diff -u -r1.356 taxonomy.module
--- modules/taxonomy/taxonomy.module	28 May 2007 06:08:46 -0000	1.356
+++ modules/taxonomy/taxonomy.module	31 May 2007 23:25:57 -0000
@@ -1268,10 +1268,10 @@
     $sql = db_rewrite_sql($sql);
     $sql_count = db_rewrite_sql($sql_count);
     if ($pager) {
-      $result = pager_query($sql, variable_get('default_nodes_main', 10), 0, $sql_count);
+      $result = pager_query($sql, variable_get('default_nodes_main'), 0, $sql_count);
     }
     else {
-      $result = db_query_range($sql, 0, variable_get('feed_default_items', 10));
+      $result = db_query_range($sql, 0, variable_get('feed_default_items'));
     }
   }
 
@@ -1288,7 +1288,7 @@
     while ($node = db_fetch_object($result)) {
       $output .= node_view(node_load($node->nid), 1);
     }
-    $output .= theme('pager', NULL, variable_get('default_nodes_main', 10), 0);
+    $output .= theme('pager', NULL, variable_get('default_nodes_main'), 0);
   }
   else {
     $output .= '<p>'. t('There are currently no posts in this category.') .'</p>';
@@ -1418,7 +1418,7 @@
         case 'feed':
           $term = taxonomy_get_term($tids[0]);
           $channel['link'] = url('taxonomy/term/'. $str_tids .'/'. $depth, array('absolute' => TRUE));
-          $channel['title'] = variable_get('site_name', 'Drupal') .' - '. $title;
+          $channel['title'] = variable_get('site_name') .' - '. $title;
           $channel['description'] = $term->description;
 
           $result = taxonomy_select_nodes($tids, $terms['operator'], $depth, FALSE);
Index: modules/comment/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v
retrieving revision 1.547
diff -u -r1.547 comment.module
--- modules/comment/comment.module	29 May 2007 06:27:37 -0000	1.547
+++ modules/comment/comment.module	31 May 2007 23:25:43 -0000
@@ -396,7 +396,7 @@
 
       if ($node->comment == COMMENT_NODE_READ_WRITE) {
         if (user_access('post comments')) {
-          if (variable_get('comment_form_location', COMMENT_FORM_SEPARATE_PAGE) == COMMENT_FORM_SEPARATE_PAGE) {
+          if (variable_get('comment_form_location') == COMMENT_FORM_SEPARATE_PAGE) {
             $links['comment_add'] = array(
               'title' => t('Add new comment'),
               'href' => "comment/reply/$node->nid",
@@ -424,10 +424,10 @@
 
 function comment_form_alter(&$form, $form_state, $form_id) {
   if ($form_id == 'node_type_form' && isset($form['identity']['type'])) {
-    $form['workflow']['comment'] = array(
+    $form['workflow']['comment_node'] = array(
+      '#variable' => TRUE,
       '#type' => 'radios',
       '#title' => t('Default comment setting'),
-      '#default_value' => variable_get('comment_'. $form['#node_type']->type, COMMENT_NODE_READ_WRITE),
       '#options' => array(t('Disabled'), t('Read only'), t('Read/Write')),
       '#description' => t('Users with the <em>administer comments</em> permission will be able to override this setting.'),
     );
@@ -465,7 +465,7 @@
 
     case 'prepare':
       if (!isset($node->comment)) {
-        $node->comment = variable_get("comment_$node->type", COMMENT_NODE_READ_WRITE);
+        $node->comment = variable_get_element('node_comment', $node->type);
       }
       break;
 
@@ -521,33 +521,33 @@
   );
 
   $form['viewing_options']['comment_default_mode'] = array(
+    '#variable' => TRUE,
     '#type' => 'radios',
     '#title' => t('Default display mode'),
-    '#default_value' => variable_get('comment_default_mode', COMMENT_MODE_THREADED_EXPANDED),
     '#options' => _comment_get_modes(),
     '#description' => t('The default view for comments. Expanded views display the body of the comment. Threaded views keep replies together.'),
   );
 
   $form['viewing_options']['comment_default_order'] = array(
+    '#variable' => TRUE,
     '#type' => 'radios',
     '#title' => t('Default display order'),
-    '#default_value' => variable_get('comment_default_order', COMMENT_ORDER_NEWEST_FIRST),
     '#options' => _comment_get_orders(),
     '#description' => t('The default sorting for new users and anonymous users while viewing comments. These users may change their view using the comment control panel. For registered users, this change is remembered as a persistent user preference.'),
   );
 
   $form['viewing_options']['comment_default_per_page'] = array(
+    '#variable' => TRUE,
     '#type' => 'select',
     '#title' => t('Default comments per page'),
-    '#default_value' => variable_get('comment_default_per_page', 50),
     '#options' => _comment_per_page(),
     '#description' => t('Default number of comments for each page: more comments are distributed in several pages.'),
   );
 
   $form['viewing_options']['comment_controls'] = array(
+    '#variable' => TRUE,
     '#type' => 'radios',
     '#title' => t('Comment controls'),
-    '#default_value' => variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN),
     '#options' => array(
       t('Display above the comments'),
       t('Display below the comments'),
@@ -563,9 +563,9 @@
   );
 
   $form['posting_settings']['comment_anonymous'] = array(
+    '#variable' => TRUE,
     '#type' => 'radios',
     '#title' => t('Anonymous commenting'),
-    '#default_value' => variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT),
     '#options' => array(
       COMMENT_ANONYMOUS_MAYNOT_CONTACT => t('Anonymous posters may not enter their contact information'),
       COMMENT_ANONYMOUS_MAY_CONTACT => t('Anonymous posters may leave their contact information'),
@@ -577,24 +577,24 @@
   }
 
   $form['posting_settings']['comment_subject_field'] = array(
+    '#variable' => TRUE,
     '#type' => 'radios',
     '#title' => t('Comment subject field'),
-    '#default_value' => variable_get('comment_subject_field', 1),
     '#options' => array(t('Disabled'), t('Enabled')),
     '#description' => t('Can users provide a unique subject for their comments?'),
   );
 
   $form['posting_settings']['comment_preview'] = array(
+    '#variable' => TRUE,
     '#type' => 'radios',
     '#title' => t('Preview comment'),
-    '#default_value' => variable_get('comment_preview', COMMENT_PREVIEW_REQUIRED),
     '#options' => array(t('Optional'), t('Required')),
   );
 
   $form['posting_settings']['comment_form_location'] = array(
+    '#variable' => TRUE,
     '#type' => 'radios',
     '#title' => t('Location of comment submission form'),
-    '#default_value' => variable_get('comment_form_location', COMMENT_FORM_SEPARATE_PAGE),
     '#options' => array(t('Display on separate page'), t('Display below post or comments')),
   );
 
@@ -759,7 +759,7 @@
 
         // Add the comment to database.
         $status = user_access('post comments without approval') ? COMMENT_PUBLISHED : COMMENT_NOT_PUBLISHED;
-        $roles = variable_get('comment_roles', array());
+        $roles = variable_get('comment_roles');
         $score = 0;
 
         foreach (array_intersect(array_keys($roles), array_keys($user->roles)) as $rid) {
@@ -1036,7 +1036,7 @@
 
       // Start a form, for use with comment control.
       $result = pager_query($query, $comments_per_page, 0, $query_count, $query_args);
-      if (db_num_rows($result) && (variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_ABOVE || variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_ABOVE_BELOW)) {
+      if (db_num_rows($result) && (variable_get('comment_controls') == COMMENT_CONTROLS_ABOVE || variable_get('comment_controls') == COMMENT_CONTROLS_ABOVE_BELOW)) {
         $output .= drupal_get_form('comment_controls', $mode, $order, $comments_per_page);
       }
 
@@ -1081,13 +1081,13 @@
       }
       $output .= theme('pager', NULL, $comments_per_page, 0);
 
-      if (db_num_rows($result) && (variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_BELOW || variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_ABOVE_BELOW)) {
+      if (db_num_rows($result) && (variable_get('comment_controls') == COMMENT_CONTROLS_BELOW || variable_get('comment_controls') == COMMENT_CONTROLS_ABOVE_BELOW)) {
         $output .= drupal_get_form('comment_controls', $mode, $order, $comments_per_page);
       }
     }
 
     // If enabled, show new comment form.
-    if (user_access('post comments') && node_comment_mode($nid) == COMMENT_NODE_READ_WRITE && (variable_get('comment_form_location', COMMENT_FORM_SEPARATE_PAGE) == COMMENT_FORM_BELOW)) {
+    if (user_access('post comments') && node_comment_mode($nid) == COMMENT_NODE_READ_WRITE && (variable_get('comment_form_location') == COMMENT_FORM_BELOW)) {
       $output .= comment_form_box(array('nid' => $nid), t('Post new comment'));
     }
 
@@ -1416,7 +1416,7 @@
 
   // Check validity of name, mail and homepage (if given)
   if (!$user->uid || isset($edit['is_anonymous'])) {
-    if (variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT) > COMMENT_ANONYMOUS_MAYNOT_CONTACT) {
+    if (variable_get('comment_anonymous') > COMMENT_ANONYMOUS_MAYNOT_CONTACT) {
       if ($edit['name']) {
         $taken = db_result(db_query("SELECT COUNT(uid) FROM {users} WHERE LOWER(name) = '%s'", $edit['name']), 0);
 
@@ -1425,7 +1425,7 @@
         }
 
       }
-      else if (variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT) == COMMENT_ANONYMOUS_MUST_CONTACT) {
+      else if (variable_get('comment_anonymous') == COMMENT_ANONYMOUS_MUST_CONTACT) {
         form_set_error('name', t('You have to leave your name.'));
       }
 
@@ -1434,7 +1434,7 @@
           form_set_error('mail', t('The e-mail address you specified is not valid.'));
         }
       }
-      else if (variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT) == COMMENT_ANONYMOUS_MUST_CONTACT) {
+      else if (variable_get('comment_anonymous') == COMMENT_ANONYMOUS_MUST_CONTACT) {
         form_set_error('mail', t('You have to leave an e-mail address.'));
       }
 
@@ -1458,7 +1458,7 @@
 
   $op = isset($_POST['op']) ? $_POST['op'] : '';
 
-  if (!$user->uid && variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT) != COMMENT_ANONYMOUS_MAYNOT_CONTACT) {
+  if (!$user->uid && variable_get('comment_anonymous') != COMMENT_ANONYMOUS_MAYNOT_CONTACT) {
     drupal_add_js(drupal_get_path('module', 'comment') . '/comment.js');
   }
 
@@ -1551,8 +1551,8 @@
       $form['author'] = array('#type' => 'value', '#value' => $user->name);
     }
   }
-  else if (variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT) == COMMENT_ANONYMOUS_MAY_CONTACT) {
-    $form['name'] = array('#type' => 'textfield', '#title' => t('Your name'), '#maxlength' => 60, '#size' => 30, '#default_value' => $edit['name'] ? $edit['name'] : variable_get('anonymous', t('Anonymous'))
+  else if (variable_get('comment_anonymous') == COMMENT_ANONYMOUS_MAY_CONTACT) {
+    $form['name'] = array('#type' => 'textfield', '#title' => t('Your name'), '#maxlength' => 60, '#size' => 30, '#default_value' => $edit['name'] ? $edit['name'] : variable_get('anonymous')
     );
 
     $form['mail'] = array('#type' => 'textfield', '#title' => t('E-mail'), '#maxlength' => 64, '#size' => 30, '#default_value' => $edit['mail'], '#description' => t('The content of this field is kept private and will not be shown publicly.')
@@ -1560,15 +1560,15 @@
 
     $form['homepage'] = array('#type' => 'textfield', '#title' => t('Homepage'), '#maxlength' => 255, '#size' => 30, '#default_value' => $edit['homepage']);
   }
-  else if (variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT) == COMMENT_ANONYMOUS_MUST_CONTACT) {
-    $form['name'] = array('#type' => 'textfield', '#title' => t('Your name'), '#maxlength' => 60, '#size' => 30, '#default_value' => $edit['name'] ? $edit['name'] : variable_get('anonymous', t('Anonymous')), '#required' => TRUE);
+  else if (variable_get('comment_anonymous') == COMMENT_ANONYMOUS_MUST_CONTACT) {
+    $form['name'] = array('#type' => 'textfield', '#title' => t('Your name'), '#maxlength' => 60, '#size' => 30, '#default_value' => $edit['name'] ? $edit['name'] : variable_get('anonymous'), '#required' => TRUE);
 
     $form['mail'] = array('#type' => 'textfield', '#title' => t('E-mail'), '#maxlength' => 64, '#size' => 30, '#default_value' => $edit['mail'], '#description' => t('The content of this field is kept private and will not be shown publicly.'), '#required' => TRUE);
 
     $form['homepage'] = array('#type' => 'textfield', '#title' => t('Homepage'), '#maxlength' => 255, '#size' => 30, '#default_value' => $edit['homepage']);
   }
 
-  if (variable_get('comment_subject_field', 1) == 1) {
+  if (variable_get('comment_subject_field') == 1) {
     $form['subject'] = array('#type' => 'textfield', '#title' => t('Subject'), '#maxlength' => 64, '#default_value' => !empty($edit['subject']) ? $edit['subject'] : '');
   }
 
@@ -1602,7 +1602,7 @@
   // Only show post button if preview is optional or if we are in preview mode.
   // We show the post button in preview mode even if there are form errors so that
   // optional form elements (e.g., captcha) can be updated in preview mode.
-  if (!form_get_errors() && ((variable_get('comment_preview', COMMENT_PREVIEW_REQUIRED) == COMMENT_PREVIEW_OPTIONAL) || ($op == t('Preview comment')) || ($op == t('Post comment')))) {
+  if (!form_get_errors() && ((variable_get('comment_preview') == COMMENT_PREVIEW_OPTIONAL) || ($op == t('Preview comment')) || ($op == t('Post comment')))) {
     $form['submit'] = array('#type' => 'submit', '#value' => t('Post comment'), '#weight' => 20);
   }
 
@@ -1654,7 +1654,7 @@
       $comment->name = check_plain($account->name);
     }
     else {
-      $comment->name = variable_get('anonymous', t('Anonymous'));
+      $comment->name = variable_get('anonymous');
     }
     $comment->timestamp = !empty($edit['timestamp']) ? $edit['timestamp'] : time();
     $output .= theme('comment_view', $comment);
@@ -1879,14 +1879,14 @@
   }
   else {
     // we cannot use drupal_get_destination() because these links sometimes appear on /node and taxo listing pages
-    if (variable_get('comment_form_location', COMMENT_FORM_SEPARATE_PAGE) == COMMENT_FORM_SEPARATE_PAGE) {
+    if (variable_get('comment_form_location') == COMMENT_FORM_SEPARATE_PAGE) {
       $destination = "destination=". drupal_urlencode("comment/reply/$nid#comment-form");
     }
     else {
       $destination = "destination=". drupal_urlencode("node/$nid#comment-form");
     }
 
-    if (variable_get('user_register', 1)) {
+    if (variable_get('user_register')) {
       return t('<a href="@login">Login</a> or <a href="@register">register</a> to post comments', array('@login' => url('user/login', array('query' => $destination)), '@register' => url('user/register', array('query' => $destination))));
     }
     else {
@@ -1973,15 +1973,15 @@
     // get the setting's site default
     switch ($setting) {
       case 'mode':
-        $default = variable_get('comment_default_mode', COMMENT_MODE_THREADED_EXPANDED);
+        $default = variable_get('comment_default_mode');
         break;
       case 'sort':
-        $default = variable_get('comment_default_order', COMMENT_ORDER_NEWEST_FIRST);
+        $default = variable_get('comment_default_order');
         break;
       case 'comments_per_page':
-        $default = variable_get('comment_default_per_page', '50');
+        $default = variable_get('comment_default_per_page');
     }
-    if (variable_get('comment_controls', COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_HIDDEN) {
+    if (variable_get('comment_controls') == COMMENT_CONTROLS_HIDDEN) {
       // if comment controls are disabled use site default
       $value = $default;
     }
@@ -2078,3 +2078,27 @@
 function vancode2int($c = '00') {
   return base_convert(substr($c, 1), 36, 10);
 }
+
+/**
+ * Implementation of hook_variable().
+ */
+function comment_variable() {
+  return array(
+    // Coment settings
+    'comment_default_mode' => array('type' => VARIABLE_VALUE, 'default' => COMMENT_MODE_THREADED_EXPANDED),
+    'comment_default_mode' => array('type' => VARIABLE_VALUE, 'default' => COMMENT_MODE_THREADED_EXPANDED),
+    'comment_default_order' => array('type' => VARIABLE_VALUE, 'default' => COMMENT_ORDER_NEWEST_FIRST),
+    'comment_default_per_page' => array('type' => VARIABLE_NUMBER, 'default' => 50),
+    'comment_controls' => array('type' => VARIABLE_VALUE, 'default' => COMMENT_CONTROLS_HIDDEN),
+    'comment_anonymous' => array('type' => VARIABLE_VALUE, 'default' => COMMENT_ANONYMOUS_MAYNOT_CONTACT),
+    'comment_subject_field' => array('type' => VARIABLE_BOOL, 'default' => 1),
+    'comment_preview' => array('type' => VARIABLE_VALUE, 'default' => COMMENT_PREVIEW_REQUIRED),
+    'comment_form_location' => array('type' => VARIABLE_VALUE, 'default' => COMMENT_FORM_SEPARATE_PAGE),    
+    'comment_roles' => array('type' => VARIABLE_DATA, 'default' => array()),
+    
+    // Group variables, per node type
+    // Default comment setting
+    'comment_node' => array('type' => VARIABLE_GROUP | VARIABLE_VALUE, 'default' => COMMENT_NODE_READ_WRITE),
+    
+  );
+}
\ No newline at end of file
Index: modules/node/content_types.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/content_types.inc,v
retrieving revision 1.33
diff -u -r1.33 content_types.inc
--- modules/node/content_types.inc	28 May 2007 06:08:43 -0000	1.33
+++ modules/node/content_types.inc	31 May 2007 23:25:45 -0000
@@ -146,13 +146,16 @@
     '#description' => t('This text will be displayed at the top of the submission form for this content type. It is useful for helping or instructing your users.')
   );
   $form['workflow'] = array(
+    '#variable_element' => $type->type,
     '#type' => 'fieldset',
     '#title' => t('Workflow'),
     '#collapsible' => TRUE,
   );
+  // We use the variables system for handling this element
+  $form['#variable'] = TRUE;
   $form['workflow']['node_options'] = array('#type' => 'checkboxes',
+    '#variable' => TRUE,
     '#title' => t('Default options'),
-    '#default_value' => variable_get('node_options_'. $type->type, array('status', 'promote')),
     '#options' => array(
       'status' => t('Published'),
       'promote' => t('Promoted to front page'),
@@ -288,37 +291,24 @@
 
   $status = node_type_save($type);
 
-  $variables = $form_values;
-
-  // Remove everything that's been saved already - whatever's left is assumed
-  // to be a persistent variable.
-  foreach ($variables as $key => $value) {
-    if (isset($type->$key)) {
-      unset($variables[$key]);
-    }
-  }
-
-  unset($variables['form_token'], $variables['op'], $variables['submit'], $variables['delete'], $variables['reset'], $variables['form_id']);
-
-  // Save or reset persistent variable values.
-  foreach ($variables as $key => $value) {
-    $key .= '_'. $type->type;
-    if ($op == t('Reset to defaults')) {
-      variable_del($key);
-    }
-    else {
-      if (is_array($value)) {
-        $value = array_keys(array_filter($value));
-      }
-      variable_set($key, $value);
-
-      if ($type->old_type != $type->type) {
-        $key = str_replace($type->type, $type->old_type, $key);
-        variable_del($key);
+  // Save or reset persistent variable values ussing form variables API.
+  if ($op == t('Reset to defaults')) {
+    form_submit_variables($form, $form_state, $form_values, TRUE);
+  } else {
+    // If the content type has changed, first we should unset old variables
+    // and replace the element name with new content type.
+    if ($type->old_type != $type->type) {
+      // First we unset old variables
+      form_submit_variables($form, $form_state, $form_values, TRUE);
+      // Now we replace the element name with the new content type
+      foreach (form_list_variables($form) as $index => $variable) {
+        list($name, $element) = $variable;
+        $form_values[$index] = ($element && $element == $type->old_type) ? array($name, $type->type) : array($name, $element);
       }
     }
+    form_submit_variables($form, $form_state, $form_values);
   }
-
+  
   node_types_rebuild();
   cache_clear_all();
   menu_rebuild();
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.821
diff -u -r1.821 node.module
--- modules/node/node.module	30 May 2007 06:24:06 -0000	1.821
+++ modules/node/node.module	31 May 2007 23:25:49 -0000
@@ -197,7 +197,7 @@
  */
 function node_teaser($body, $format = NULL) {
 
-  $size = variable_get('teaser_length', 600);
+  $size = variable_get('teaser_length');
 
   // Find where the delimiter is in the body
   $delimiter = strpos($body, '<!--break-->');
@@ -376,7 +376,8 @@
  */
 function node_type_delete($type) {
   db_query("DELETE FROM {node_type} WHERE type = '%s'", $type);
-
+  // Unset variables
+  variable_del_element('node_options', $type);
   $info = node_get_types('type', $type);
   module_invoke_all('node_type', 'delete', $info);
 }
@@ -868,8 +869,8 @@
       return;
 
     case 'status':
-      $last = variable_get('node_cron_last', 0);
-      $last_nid = variable_get('node_cron_last_nid', 0);
+      $last = variable_get_default('node_cron_last', 0);
+      $last_nid = variable_get_default('node_cron_last_nid', 0);
       $total = db_result(db_query('SELECT COUNT(*) FROM {node} WHERE status = 1'));
       $remaining = db_result(db_query('SELECT COUNT(*) FROM {node} n LEFT JOIN {node_comment_statistics} c ON n.nid = c.nid WHERE n.status = 1 AND ((GREATEST(n.created, n.changed, c.last_comment_timestamp) = %d AND n.nid > %d ) OR (n.created > %d OR n.changed > %d OR c.last_comment_timestamp > %d))', $last, $last_nid, $last, $last, $last));
       return array('remaining' => $remaining, 'total' => $total);
@@ -886,14 +887,14 @@
       if (module_exists('comment')) {
         $ranking['node_rank_comments'] = t('Number of comments');
       }
-      if (module_exists('statistics') && variable_get('statistics_count_content_views', 0)) {
+      if (module_exists('statistics') && variable_get_default('statistics_count_content_views', 0)) {
         $ranking['node_rank_views'] = t('Number of views');
       }
 
       // Note: reversed to reflect that higher number = higher ranking.
       $options = drupal_map_assoc(range(0, 10));
       foreach ($ranking as $var => $title) {
-        $form['content_ranking']['factors'][$var] = array('#title' => $title, '#type' => 'select', '#options' => $options, '#default_value' => variable_get($var, 5));
+        $form['content_ranking']['factors'][$var] = array('#title' => $title, '#type' => 'select', '#options' => $options, '#default_value' => variable_get_default($var, 5));
       }
       return $form;
 
@@ -932,24 +933,24 @@
       // Used to avoid joining on node_comment_statistics twice
       $stats_join = FALSE;
       $total = 0;
-      if ($weight = (int)variable_get('node_rank_relevance', 5)) {
+      if ($weight = (int)variable_get('node_rank_relevance')) {
         // Average relevance values hover around 0.15
         $ranking[] = '%d * i.relevance';
         $arguments2[] = $weight;
         $total += $weight;
       }
-      if ($weight = (int)variable_get('node_rank_recent', 5)) {
+      if ($weight = (int)variable_get('node_rank_recent')) {
         // Exponential decay with half-life of 6 months, starting at last indexed node
         $ranking[] = '%d * POW(2, (GREATEST(n.created, n.changed, c.last_comment_timestamp) - %d) * 6.43e-8)';
         $arguments2[] = $weight;
-        $arguments2[] = (int)variable_get('node_cron_last', 0);
+        $arguments2[] = (int)variable_get_default('node_cron_last', 0);
         $join2 .= ' INNER JOIN {node} n ON n.nid = i.sid LEFT JOIN {node_comment_statistics} c ON c.nid = i.sid';
         $stats_join = TRUE;
         $total += $weight;
       }
-      if (module_exists('comment') && $weight = (int)variable_get('node_rank_comments', 5)) {
+      if (module_exists('comment') && $weight = (int)variable_get('node_rank_comments')) {
         // Inverse law that maps the highest reply count on the site to 1 and 0 to 0.
-        $scale = variable_get('node_cron_comments_scale', 0.0);
+        $scale = variable_get_default('node_cron_comments_scale', 0.0);
         $ranking[] = '%d * (2.0 - 2.0 / (1.0 + c.comment_count * %f))';
         $arguments2[] = $weight;
         $arguments2[] = $scale;
@@ -958,10 +959,10 @@
         }
         $total += $weight;
       }
-      if (module_exists('statistics') && variable_get('statistics_count_content_views', 0) &&
-          $weight = (int)variable_get('node_rank_views', 5)) {
+      if (module_exists('statistics') && variable_get_default('statistics_count_content_views', 0) &&
+          $weight = (int)variable_get('node_rank_views')) {
         // Inverse law that maps the highest view count on the site to 1 and 0 to 0.
-        $scale = variable_get('node_cron_views_scale', 0.0);
+        $scale = variable_get_default('node_cron_views_scale', 0.0);
         $ranking[] = '%d * (2.0 - 2.0 / (1.0 + nc.totalcount * %f))';
         $arguments2[] = $weight;
         $arguments2[] = $scale;
@@ -1043,12 +1044,12 @@
   }
 
   $form['default_nodes_main'] = array(
-    '#type' => 'select', '#title' => t('Number of posts on main page'), '#default_value' => variable_get('default_nodes_main', 10),
+    '#variable' => TRUE, '#type' => 'select', '#title' => t('Number of posts on main page'),
     '#options' =>  drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30)),
     '#description' => t('The default maximum number of posts to display per page on overview pages such as the main page.')
   );
   $form['teaser_length'] = array(
-    '#type' => 'select', '#title' => t('Length of trimmed posts'), '#default_value' => variable_get('teaser_length', 600),
+    '#variable' => TRUE, '#type' => 'select', '#title' => t('Length of trimmed posts'),
     '#options' => array(0 => t('Unlimited'), 200 => t('200 characters'), 400 => t('400 characters'), 600 => t('600 characters'),
       800 => t('800 characters'), 1000 => t('1000 characters'), 1200 => t('1200 characters'), 1400 => t('1400 characters'),
       1600 => t('1600 characters'), 1800 => t('1800 characters'), 2000 => t('2000 characters')),
@@ -1056,7 +1057,7 @@
   );
 
   $form['node_preview'] = array(
-    '#type' => 'radios', '#title' => t('Preview post'), '#default_value' => variable_get('node_preview', 0),
+    '#variable' => TRUE, '#type' => 'radios', '#title' => t('Preview post'),
     '#options' => array(t('Optional'), t('Required')), '#description' => t('Must users preview posts before submitting?')
   );
 
@@ -1855,10 +1856,10 @@
   global $base_url, $language;
 
   if (!$nodes) {
-    $nodes = db_query_range(db_rewrite_sql('SELECT n.nid, n.created FROM {node} n WHERE n.promote = 1 AND n.status = 1 ORDER BY n.created DESC'), 0, variable_get('feed_default_items', 10));
+    $nodes = db_query_range(db_rewrite_sql('SELECT n.nid, n.created FROM {node} n WHERE n.promote = 1 AND n.status = 1 ORDER BY n.created DESC'), 0, variable_get('feed_default_items'));
   }
 
-  $item_length = variable_get('feed_item_length', 'teaser');
+  $item_length = variable_get('feed_item_length');
   $namespaces = array('xmlns:dc="http://purl.org/dc/elements/1.1/"');
 
   $items = '';
@@ -1912,9 +1913,9 @@
 
   $channel_defaults = array(
     'version'     => '2.0',
-    'title'       => variable_get('site_name', 'Drupal') .' - '. variable_get('site_slogan', ''),
+    'title'       => variable_get('site_name') .' - '. variable_get('site_slogan'),
     'link'        => $base_url,
-    'description' => variable_get('site_mission', ''),
+    'description' => variable_get('site_mission'),
     'language'    => $language->language
   );
   $channel = array_merge($channel_defaults, $channel);
@@ -2067,7 +2068,7 @@
     $form['title']['#weight'] = -5;
   }
 
-  $node_options = variable_get('node_options_'. $node->type, array('status', 'promote'));
+  $node_options = variable_get_default('node_options_'. $node->type, array('status', 'promote'));
   // If this is a new node, fill in the default values.
   if (!isset($node->nid)) {
     foreach (array('status', 'promote', 'sticky') as $key) {
@@ -2102,7 +2103,7 @@
     '#collapsed' => TRUE,
     '#weight' => 20,
   );
-  $form['author']['name'] = array('#type' => 'textfield', '#title' => t('Authored by'), '#maxlength' => 60, '#autocomplete_path' => 'user/autocomplete', '#default_value' => $node->name ? $node->name : '', '#weight' => -1, '#description' => t('Leave blank for %anonymous.', array('%anonymous' => variable_get('anonymous', t('Anonymous')))));
+  $form['author']['name'] = array('#type' => 'textfield', '#title' => t('Authored by'), '#maxlength' => 60, '#autocomplete_path' => 'user/autocomplete', '#default_value' => $node->name ? $node->name : '', '#weight' => -1, '#description' => t('Leave blank for %anonymous.', array('%anonymous' => variable_get('anonymous'))));
   $form['author']['date'] = array('#type' => 'textfield', '#title' => t('Authored on'), '#maxlength' => 25, '#description' => t('Format: %time. Leave blank to use the time of form submission.', array('%time' => $node->date)));
 
   if (isset($node->nid)) {
@@ -2446,17 +2447,17 @@
  * Menu callback; Generate a listing of promoted nodes.
  */
 function node_page_default() {
-  $result = pager_query(db_rewrite_sql('SELECT n.nid, n.sticky, n.created FROM {node} n WHERE n.promote = 1 AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC'), variable_get('default_nodes_main', 10));
+  $result = pager_query(db_rewrite_sql('SELECT n.nid, n.sticky, n.created FROM {node} n WHERE n.promote = 1 AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC'), variable_get('default_nodes_main'));
 
   if (db_num_rows($result)) {
     $feed_url = url('rss.xml', array('absolute' => TRUE));
-    drupal_add_feed($feed_url, variable_get('site_name', 'Drupal') .' '. t('RSS'));
+    drupal_add_feed($feed_url, variable_get('site_name') .' '. t('RSS'));
 
     $output = '';
     while ($node = db_fetch_object($result)) {
       $output .= node_view(node_load($node->nid), 1);
     }
-    $output .= theme('pager', NULL, variable_get('default_nodes_main', 10));
+    $output .= theme('pager', NULL, variable_get('default_nodes_main'));
   }
   else {
     // Check for existence of admin account.
@@ -2525,9 +2526,9 @@
 
   register_shutdown_function('node_update_shutdown');
 
-  $last = variable_get('node_cron_last', 0);
-  $last_nid = variable_get('node_cron_last_nid', 0);
-  $limit = (int)variable_get('search_cron_limit', 100);
+  $last = variable_get_default('node_cron_last', 0);
+  $last_nid = variable_get_default('node_cron_last_nid', 0);
+  $limit = (int)variable_get_default('search_cron_limit', 100);
 
   // Store the maximum possible comments per thread (used for ranking by reply count)
   variable_set('node_cron_comments_scale', 1.0 / max(1, db_result(db_query('SELECT MAX(comment_count) FROM {node_comment_statistics}'))));
@@ -3094,3 +3095,23 @@
   }
   return $forms;
 }
+
+/**
+ * Implementation of hook_variable().
+ */
+function node_variable() {
+  return array(
+    // Content settings
+    'teaser_length' => array('type' => VARIABLE_NUMBER, 'default' => 600),
+    'default_nodes_main' => array('type' => VARIABLE_NUMBER, 'default' => 10),
+    'node_preview' => array('type' => VARIABLE_DATA, 'default' => 0),   
+    // Search
+    'node_rank_relevance' => array('type' => VARIABLE_NUMBER, 'default' => 5),
+    'node_rank_recent' => array('type' => VARIABLE_NUMBER, 'default' => 5),
+    'node_rank_comments' => array('type' => VARIABLE_NUMBER, 'default' => 5),
+    'node_rank_views' => array('type' => VARIABLE_NUMBER, 'default' => 5),
+    // Group variables, per content type
+    // Node publishing options
+    'node_options' => array('type' => VARIABLE_GROUP | VARIABLE_DATA, 'default' => array('status', 'promote')),
+  );
+}
\ No newline at end of file
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.485
diff -u -r1.485 system.module
--- modules/system/system.module	30 May 2007 08:08:58 -0000	1.485
+++ modules/system/system.module	31 May 2007 23:25:55 -0000
@@ -352,7 +352,7 @@
   // Use the administrative theme if the user is looking at a page in the admin/* path.
   if (arg(0) == 'admin') {
     global $custom_theme;
-    $custom_theme = variable_get('admin_theme', '0');
+    $custom_theme = variable_get('admin_theme');
     drupal_add_css(drupal_get_path('module', 'system') .'/admin.css', 'module');
   }
 
@@ -370,7 +370,7 @@
   if ($type == 'form' && $category == 'account') {
     $form['theme_select'] = system_theme_select_form(t('Selecting a different theme will change the look and feel of the site.'), isset($edit['theme']) ? $edit['theme'] : NULL, 2);
 
-    if (variable_get('configurable_timezones', 1)) {
+    if (variable_get('configurable_timezones')) {
       $zones = _system_zonelist();
       $form['timezone'] = array(
         '#type' => 'fieldset',
@@ -381,7 +381,7 @@
       $form['timezone']['timezone'] = array(
         '#type' => 'select',
         '#title' => t('Time zone'),
-        '#default_value' => strlen($edit['timezone']) ? $edit['timezone'] : variable_get('date_default_timezone', 0),
+        '#default_value' => strlen($edit['timezone']) ? $edit['timezone'] : variable_get('date_default_timezone'),
         '#options' => $zones,
         '#description' => t('Select your current local time. Dates and times throughout this site will be displayed using this time zone.'),
       );
@@ -433,11 +433,11 @@
   }
 
   $form['admin_theme'] = array(
+    '#variable' => 'true',
     '#type' => 'select',
     '#options' => $options,
     '#title' => t('Administration theme'),
     '#description' => t('Choose which theme the administration pages should display in. If you choose "System default" the administration pages will use the same theme as the rest of the site.'),
-    '#default_value' => variable_get('admin_theme', '0'),
   );
 
   $form['#submit'][] = 'system_admin_theme_submit';
@@ -447,7 +447,7 @@
 
 function system_admin_theme_submit($form, &$form_state, $form_values) {
   // If we're changing themes, make sure the theme has its blocks initialized.
-  if ($form_values['admin_theme'] != variable_get('admin_theme', '0')) {
+  if ($form_values['admin_theme'] != variable_get('admin_theme')) {
     $result = db_query("SELECT status FROM {blocks} WHERE theme = '%s'", $form_values['admin_theme']);
     if (!db_num_rows($result)) {
       system_initialize_theme_blocks($form_values['admin_theme']);
@@ -491,7 +491,7 @@
 
       foreach ($enabled as $info) {
         // For the default theme, revert to an empty string so the user's theme updates when the site theme is changed.
-        $info->key = $info->name == variable_get('theme_default', 'garland') ? '' : $info->name;
+        $info->key = $info->name == variable_get('theme_default') ? '' : $info->name;
 
         $screenshot = NULL;
         $theme_key = $info->name;
@@ -506,7 +506,7 @@
         $screenshot = $screenshot ? theme('image', $screenshot, t('Screenshot for %theme theme', array('%theme' => $info->name)), '', array('class' => 'screenshot'), FALSE) : t('no screenshot');
 
         $form['themes'][$info->key]['screenshot'] = array('#value' => $screenshot);
-        $form['themes'][$info->key]['description'] = array('#type' => 'item', '#title' => $info->name,  '#value' => dirname($info->filename) . ($info->name == variable_get('theme_default', 'garland') ? '<br /> <em>'. t('(site default theme)') .'</em>' : ''));
+        $form['themes'][$info->key]['description'] = array('#type' => 'item', '#title' => $info->name,  '#value' => dirname($info->filename) . ($info->name == variable_get('theme_default') ? '<br /> <em>'. t('(site default theme)') .'</em>' : ''));
         $options[$info->key] = '';
       }
 
@@ -539,58 +539,57 @@
   $zones = array();
   foreach ($zonelist as $offset) {
     $zone = $offset * 3600;
-    $zones[$zone] = format_date($timestamp, 'custom', variable_get('date_format_long', 'l, F j, Y - H:i') .' O', $zone);
+    $zones[$zone] = format_date($timestamp, 'custom', variable_get('date_format_long') .' O', $zone);
   }
   return $zones;
 }
 
 function system_site_information_settings() {
   $form['site_name'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Name'),
-    '#default_value' => variable_get('site_name', 'Drupal'),
     '#description' => t('The name of this website.'),
     '#required' => TRUE
   );
   $form['site_mail'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('E-mail address'),
-    '#default_value' => variable_get('site_mail', ini_get('sendmail_from')),
     '#description' => t('A valid e-mail address to be used as the "From" address by the auto-mailer during registration, new password requests, notifications, etc.  To lessen the likelihood of e-mail being marked as spam, this e-mail address should use the same domain as the website.'),
     '#required' => TRUE,
   );
   $form['site_slogan'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Slogan'),
-    '#default_value' => variable_get('site_slogan', ''),
     '#description' => t('The slogan of this website. Some themes display a slogan when available.')
   );
-
   $form['site_mission'] = array(
+    '#variable' => TRUE,
     '#type' => 'textarea',
     '#title' => t('Mission'),
-    '#default_value' => variable_get('site_mission', ''),
     '#description' => t('Your site\'s mission statement or focus.')
   );
   $form['site_footer'] = array(
+    '#variable' => TRUE,
     '#type' => 'textarea',
     '#title' => t('Footer message'),
-    '#default_value' => variable_get('site_footer', ''),
     '#description' => t('This text will be displayed at the bottom of each page. Useful for adding a copyright notice to your pages.')
   );
   $form['anonymous'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Anonymous user'),
-    '#default_value' => variable_get('anonymous', t('Anonymous')),
     '#description' => t('The name used to indicate anonymous users.')
   );
   $form['site_frontpage'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Default front page'),
-    '#default_value' => variable_get('site_frontpage', 'node'),
     '#size' => 40,
     '#description' => t('The home page displays content from this relative URL. If unsure, specify "node".'),
-    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
+    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url') ? '' : '?q=')
   );
 
   return system_settings_form($form);
@@ -598,14 +597,14 @@
 
 function system_clean_url_settings() {
   $form['clean_url'] = array(
+    '#variable' => TRUE,
     '#type' => 'radios',
     '#title' => t('Clean URLs'),
-    '#default_value' => variable_get('clean_url', 0),
     '#options' => array(t('Disabled'), t('Enabled')),
     '#description' => t('This option makes Drupal emit "clean" URLs (i.e. without <code>?q=</code> in the URL).'),
   );
 
-  if (!variable_get('clean_url', 0)) {
+  if (!variable_get('clean_url')) {
     if (strpos(request_uri(), '?q=') !== FALSE) {
       drupal_add_js(array('cleanURL' => array('success' => t('Your server has been successfully tested to support this feature.'), 'failure' => t('Your system configuration does not currently support this feature. The <a href="http://drupal.org/node/15365">handbook page on Clean URLs</a> has additional troubleshooting information.'), 'testing' => t('Testing clean URLs...'))), 'setting');
       drupal_add_js(drupal_get_path('module', 'system') .'/system.js', 'module');
@@ -634,25 +633,26 @@
 function system_error_reporting_settings() {
 
   $form['site_403'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Default 403 (access denied) page'),
-    '#default_value' => variable_get('site_403', ''),
     '#size' => 40,
     '#description' => t('This page is displayed when the requested document is denied to the current user. If unsure, specify nothing.'),
-    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
+    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url') ? '' : '?q=')
   );
 
   $form['site_404'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Default 404 (not found) page'),
-    '#default_value' =>  variable_get('site_404', ''),
     '#size' => 40,
     '#description' => t('This page is displayed when no other content matches the requested document. If unsure, specify nothing.'),
-    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url', 0) ? '' : '?q=')
+    '#field_prefix' => url(NULL, array('absolute' => TRUE)) . (variable_get('clean_url') ? '' : '?q=')
   );
 
   $form['error_level'] = array(
-    '#type' => 'select', '#title' => t('Error reporting'), '#default_value' => variable_get('error_level', 1),
+    '#variable' => TRUE,
+    '#type' => 'select', '#title' => t('Error reporting'),
     '#options' => array(t('Write errors to the log'), t('Write errors to the log and to the screen')),
     '#description' =>  t('Where Drupal, PHP and SQL errors are logged. On a production server it is recommended that errors are only written to the error log. On a test server it can be helpful to write logs to the screen.')
   );
@@ -680,9 +680,9 @@
   );
 
   $form['page_cache']['cache'] = array(
+    '#variable' => TRUE,
     '#type' => 'radios',
     '#title' => t('Caching mode'),
-    '#default_value' => variable_get('cache', CACHE_DISABLED),
     '#options' => array(CACHE_DISABLED => t('Disabled'), CACHE_NORMAL => t('Normal (recommended, no side effects)'), CACHE_AGGRESSIVE => t('Aggressive (experts only, possible side effects)')),
     '#description' => $description
   );
@@ -690,9 +690,9 @@
   $period = drupal_map_assoc(array(0, 60, 180, 300, 600, 900, 1800, 2700, 3600, 10800, 21600, 32400, 43200, 86400), 'format_interval');
   $period[0] = t('none');
   $form['page_cache']['cache_lifetime'] = array(
+    '#variable' => TRUE,
     '#type' => 'select',
     '#title' => t('Minimum cache lifetime'),
-    '#default_value' => variable_get('cache_lifetime', 0),
     '#options' => $period,
     '#description' => t('On high-traffic sites it can become necessary to enforce a minimum cache lifetime. The minimum cache lifetime is the minimum amount of time that will go by before the cache is emptied and recreated. A larger minimum cache lifetime offers better performance, but users will not see new content for a longer period of time.')
   );
@@ -704,11 +704,12 @@
   );
 
   $directory = file_directory_path();
-  $is_writable = is_dir($directory) && is_writable($directory) && (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC);
+  $is_writable = is_dir($directory) && is_writable($directory) && (variable_get('file_downloads') == FILE_DOWNLOADS_PUBLIC);
   $form['bandwidth_optimizations']['preprocess_css'] = array(
+    '#variable' => TRUE,  
     '#type' => 'radios',
     '#title' => t('Aggregate and compress CSS files'),
-    '#default_value' => variable_get('preprocess_css', FALSE) && $is_writable,
+    '#default_value' => variable_get('preprocess_css') && $is_writable,
     '#disabled' => !$is_writable,
     '#options' => array(t('Disabled'), t('Enabled')),
     '#description' => t("Some Drupal modules include their own CSS files. When these modules are enabled, each module's CSS file adds an additional HTTP request to the page, which can increase the load time of each page. These HTTP requests can also slightly increase server load. It is recommended to only turn this option on when your site is in production, as it can interfere with theme development. This option is disabled if you have not set up your files directory, or if your download method is set to private."),
@@ -721,9 +722,9 @@
   );
 
   $form['reverse_proxy']['reverse_proxy'] = array(
+    '#variable' => TRUE,
     '#type' => 'radios',
     '#title' => t('Reverse proxy'),
-    '#default_value' => variable_get('reverse_proxy', FALSE),
     '#options' => array(t('Disabled'), t('Enabled')),
     '#description' => t('Enable this setting to determine the correct IP address of the remote client by examining information stored in the X-Forwarded-For headers. X-Forwarded-For headers are a standard mechanism for identifying client systems connecting through a reverse proxy server, such as Squid or Pound. Reverse proxy servers are often used to enhance the performance of heavily visited sites and may also provide other site caching, security or encryption benefits. If this Drupal installation operates behind a reverse proxy, this setting should be enabled so that correct IP address information is captured in Drupal\'s session management, logging, statistics and access management systems; if you are unsure about this setting, do not have a reverse proxy, or Drupal operates in a shared hosting environment, this setting should be set to disabled.'),
   );
@@ -736,6 +737,7 @@
 function system_file_system_settings() {
 
   $form['file_directory_path'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('File system path'),
     '#default_value' => file_directory_path(),
@@ -745,6 +747,7 @@
   );
 
   $form['file_directory_temp'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Temporary directory'),
     '#default_value' => file_directory_temp(),
@@ -754,9 +757,9 @@
   );
 
   $form['file_downloads'] = array(
+    '#variable' => TRUE,
     '#type' => 'radios',
     '#title' => t('Download method'),
-    '#default_value' => variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC),
     '#options' => array(FILE_DOWNLOADS_PUBLIC => t('Public - files are available using HTTP directly.'), FILE_DOWNLOADS_PRIVATE => t('Private - files are transferred by Drupal.')),
     '#description' => t('If you want any sort of access control on the downloading of files, this needs to be set to <em>private</em>. You can change this at any time, however all download URLs will change and there may be unexpected problems so it is not recommended.')
   );
@@ -768,9 +771,10 @@
   $toolkits_available = image_get_available_toolkits();
   if (count($toolkits_available) > 1) {
     $form['image_toolkit'] = array(
+      '#variable' => TRUE,
       '#type' => 'radios',
       '#title' => t('Select an image processing toolkit'),
-      '#default_value' => variable_get('image_toolkit', image_get_toolkit()),
+      '#default_value' => variable_get_default('image_toolkit', image_get_toolkit()),
       '#options' => $toolkits_available
     );
   }
@@ -784,16 +788,16 @@
 function system_rss_feeds_settings() {
 
   $form['feed_default_items'] = array(
+    '#variable' => TRUE,
     '#type' => 'select',
     '#title' => t('Number of items per feed'),
-    '#default_value' => variable_get('feed_default_items', 10),
     '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30)),
     '#description' => t('The default number of items to include in a feed.')
   );
   $form['feed_item_length'] = array(
+    '#variable' => TRUE,
     '#type' => 'select',
     '#title' => t('Display of XML feed items'),
-    '#default_value' => variable_get('feed_item_length', 'teaser'),
     '#options' => array('title' => t('Titles only'), 'teaser' => t('Titles plus teaser'), 'fulltext' => t('Full text')),
     '#description' => t('Global setting for the length of XML feed items that are output by default.')
   );
@@ -843,25 +847,25 @@
   );
 
   $form['locale']['date_default_timezone'] = array(
+    '#variable' => TRUE,
     '#type' => 'select',
     '#title' => t('Default time zone'),
-    '#default_value' => variable_get('date_default_timezone', 0),
     '#options' => $zones,
     '#description' => t('Select the default site time zone.')
   );
 
   $form['locale']['configurable_timezones'] = array(
+    '#variable' => TRUE,
     '#type' => 'radios',
     '#title' => t('User-configurable time zones'),
-    '#default_value' => variable_get('configurable_timezones', 1),
     '#options' => array(t('Disabled'), t('Enabled')),
     '#description' => t('When enabled, users can set their own time zone and dates will be displayed accordingly.')
   );
 
   $form['locale']['date_first_day'] = array(
+    '#variable' => TRUE,
     '#type' => 'select',
     '#title' => t('First day of week'),
-    '#default_value' => variable_get('date_first_day', 0),
     '#options' => array(0 => t('Sunday'), 1 => t('Monday'), 2 => t('Tuesday'), 3 => t('Wednesday'), 4 => t('Thursday'), 5 => t('Friday'), 6 => t('Saturday')),
     '#description' => t('The first day of the week for calendar views.')
   );
@@ -871,8 +875,9 @@
     '#title' => t('Formatting'),
   );
 
-  $date_format_short = variable_get('date_format_short', $date_short[1]);
+  $date_format_short = variable_get_default('date_format_short', $date_short[1]);
   $form['date_formats']['date_format_short'] = array(
+    '#variable' => TRUE,
     '#prefix' => '<div class="date-container"><div>',
     '#suffix' => '</div>',
     '#type' => 'select',
@@ -883,8 +888,9 @@
     '#description' => t('The short format of date display.'),
   );
 
-  $default_short_custom = variable_get('date_format_short_custom', (isset($date_short_choices[$date_format_short]) ? $date_format_short : ''));
+  $default_short_custom = variable_get_default('date_format_short_custom', (isset($date_short_choices[$date_format_short]) ? $date_format_short : ''));
   $form['date_formats']['date_format_short_custom'] = array(
+    '#variable' => TRUE,
     '#prefix' => '<div class="custom-container">',
     '#suffix' => '</div></div>',
     '#type' => 'textfield',
@@ -894,8 +900,9 @@
     '#description' => t('A user-defined short date format. See the <a href="@url">PHP manual</a> for available options. This format is currently set to display as <span>%date</span>.', array('@url' => 'http://php.net/manual/function.date.php', '%date' => format_date(time(), 'custom', $default_short_custom))),
   );
 
-  $date_format_medium = variable_get('date_format_medium', $date_medium[1]);
+  $date_format_medium = variable_get_default('date_format_medium', $date_medium[1]);
   $form['date_formats']['date_format_medium'] = array(
+    '#variable' => TRUE,
     '#prefix' => '<div class="date-container"><div>',
     '#suffix' => '</div>',
     '#type' => 'select',
@@ -906,8 +913,9 @@
     '#description' => t('The medium sized date display.'),
   );
 
-  $default_medium_custom = variable_get('date_format_medium_custom', (isset($date_medium_choices[$date_format_medium]) ? $date_format_medium : ''));
+  $default_medium_custom = variable_get_default('date_format_medium_custom', (isset($date_medium_choices[$date_format_medium]) ? $date_format_medium : ''));
   $form['date_formats']['date_format_medium_custom'] = array(
+    '#variable' => TRUE,
     '#prefix' => '<div class="custom-container">',
     '#suffix' => '</div></div>',
     '#type' => 'textfield',
@@ -917,7 +925,7 @@
     '#description' => t('A user-defined medium date format. See the <a href="@url">PHP manual</a> for available options. This format is currently set to display as <span>%date</span>.', array('@url' => 'http://php.net/manual/function.date.php', '%date' => format_date(time(), 'custom', $default_medium_custom))),
   );
 
-  $date_format_long = variable_get('date_format_long', $date_long[0]);
+  $date_format_long = variable_get_default('date_format_long', $date_long[0]);
   $form['date_formats']['date_format_long'] = array(
     '#prefix' => '<div class="date-container"><div>',
     '#suffix' => '</div>',
@@ -929,8 +937,9 @@
     '#description' => t('Longer date format used for detailed display.')
   );
 
-  $default_long_custom = variable_get('date_format_long_custom', (isset($date_long_choices[$date_format_long]) ? $date_format_long : ''));
+  $default_long_custom = variable_get_default('date_format_long_custom', (isset($date_long_choices[$date_format_long]) ? $date_format_long : ''));
   $form['date_formats']['date_format_long_custom'] = array(
+    '#variable' => TRUE,
     '#prefix' => '<div class="custom-container">',
     '#suffix' => '</div></div>',
     '#type' => 'textfield',
@@ -971,17 +980,17 @@
 function system_site_maintenance_settings() {
 
   $form['site_offline'] = array(
+    '#variable' => 'site_offline',
     '#type' => 'radios',
     '#title' => t('Site status'),
-    '#default_value' => variable_get('site_offline', 0),
     '#options' => array(t('Online'), t('Off-line')),
     '#description' => t('When set to "Online", all visitors will be able to browse your site normally. When set to "Off-line", only users with the "administer site configuration" permission will be able to access your site to perform maintenance; all other visitors will see the site off-line message configured below. Authorized users can log in during "Off-line" mode directly via the <a href="@user-login">user login</a> page.', array('@user-login' => url('user'))),
   );
-
+  // This variable has a default value that must be compiled
   $form['site_offline_message'] = array(
+    '#variable' => 'site_offline_message',
     '#type' => 'textarea',
     '#title' => t('Site off-line message'),
-    '#default_value' => variable_get('site_offline_message', t('@site is currently under maintenance. We should be back shortly. Thank you for your patience.', array('@site' => variable_get('site_name', 'Drupal')))),
     '#description' => t('Message to show visitors when the site is in off-line mode.')
   );
 
@@ -1211,7 +1220,7 @@
 function system_initialize_theme_blocks($theme) {
   // Initialize theme's blocks if none already registered.
   if (!(db_num_rows(db_query("SELECT module FROM {blocks} WHERE theme = '%s'", $theme)))) {
-    $default_theme = variable_get('theme_default', 'garland');
+    $default_theme = variable_get('theme_default');
     $regions = system_region_list($theme);
     $result = db_query("SELECT * FROM {blocks} WHERE theme = '%s'", $default_theme);
     while ($block = db_fetch_array($result)) {
@@ -1229,12 +1238,18 @@
  * Add default buttons to a form and set its prefix
  */
 function system_settings_form($form) {
+  global $conf;
+  
   $form['buttons']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration') );
   $form['buttons']['reset'] = array('#type' => 'submit', '#value' => t('Reset to defaults') );
-
+  
+  // We mark the form as a variables form so it will be rewritten by form variables API
+  $form['#variable'] = TRUE;
+  
   if (!empty($_POST) && form_get_errors()) {
     drupal_set_message(t('The settings have not been saved because of the errors.'), 'error');
   }
+  
   $form['#submit'][] = 'system_settings_form_submit';
   $form['#validate'][] = 'system_settings_form_validate';
   $form['#theme'] = 'system_settings_form';
@@ -1270,20 +1285,9 @@
 function system_settings_form_submit($form, &$form_state, $form_values) {
   $op = isset($form_values['op']) ? $form_values['op'] : '';
 
-  // Exclude unnecessary elements.
-  unset($form_values['submit'], $form_values['reset'], $form_values['form_id'], $form_values['op'], $form_values['form_token']);
-
-  foreach ($form_values as $key => $value) {
-    if ($op == t('Reset to defaults')) {
-      variable_del($key);
-    }
-    else {
-      if (is_array($value) && isset($form_values['array_filter'])) {
-        $value = array_keys(array_filter($value));
-      }
-      variable_set($key, $value);
-    }
-  }
+  // Save or reset variables
+  form_submit_variables($form, $form_state, $form_values, $op == t('Reset to defaults'));
+    
   if ($op == t('Reset to defaults')) {
     drupal_set_message(t('The configuration options have been reset to their default values.'));
   }
@@ -1332,7 +1336,7 @@
   }
 
   $form['status'] = array('#type' => 'checkboxes', '#options' => $options, '#default_value' => $status);
-  $form['theme_default'] = array('#type' => 'radios', '#options' => $options, '#default_value' => variable_get('theme_default', 'garland'));
+  $form['theme_default'] = array('#type' => 'radios', '#options' => $options, '#default_value' => variable_get('theme_default'));
   $form['buttons']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration') );
   $form['buttons']['reset'] = array('#type' => 'submit', '#value' => t('Reset to defaults') );
 
@@ -1394,7 +1398,7 @@
         }
       }
     }
-    if (($admin_theme = variable_get('admin_theme', '0')) != '0' && $admin_theme != $form_values['theme_default']) {
+    if (($admin_theme = variable_get_default('admin_theme', '0')) != '0' && $admin_theme != $form_values['theme_default']) {
       drupal_set_message(t('Please note that the <a href="!admin_theme_page">administration theme</a> is still set to the %admin_theme theme; consequently, the theme on this page remains unchanged. All non-administrative sections of the site, however, will show the selected %selected_theme theme by default.', array(
         '!admin_theme_page' => url('admin/settings/admin'),
         '%admin_theme' => $admin_theme,
@@ -2217,7 +2221,7 @@
 
   // Some features are not always available
   $disabled = array();
-  if (!variable_get('user_pictures', 0)) {
+  if (!variable_get('user_pictures')) {
     $disabled['toggle_node_user_picture'] = TRUE;
     $disabled['toggle_comment_user_picture'] = TRUE;
   }
@@ -2353,7 +2357,7 @@
     $old = 'toggle_node_info_'. $info->old_type;
     $new = 'toggle_node_info_'. $info->type;
 
-    $theme_settings = variable_get('theme_settings', array());
+    $theme_settings = variable_get_default('theme_settings', array());
     if (isset($theme_settings[$old])) {
       $theme_settings[$new] = $theme_settings[$old];
       unset($theme_settings[$old]);
@@ -2426,7 +2430,7 @@
  */
 function system_admin_compact_mode() {
   global $user;
-  return (isset($user->admin_compact_mode)) ? $user->admin_compact_mode : variable_get('admin_compact_mode', FALSE);
+  return (isset($user->admin_compact_mode)) ? $user->admin_compact_mode : variable_get_default('admin_compact_mode', FALSE);
 }
 
 /**
@@ -2678,3 +2682,56 @@
     print theme('page', $output, FALSE, FALSE);
   }
 }
+
+/**
+ * Implementation of hook_variable()
+ *
+ * Some of these defaults are set in bootstrap.inc. 
+ * We list them here for informative purposes though.
+ */
+function system_variable() {
+  return array(
+    // Site information
+    'site_name' => array('type' => VARIABLE_TEXT, 'default' => 'Drupal'),
+    'site_mail' => array('type' => VARIABLE_MAIL, 'default' => ini_get('sendmail_from')),
+    'site_slogan' => array('type' => VARIABLE_TEXT, 'default' => ''),
+    'site_mission' => array('type' => VARIABLE_HTML, 'default' => ''),
+    'site_footer' => array('type' => VARIABLE_HTML, 'default' => ''),
+    'anonymous' => array('type' => VARIABLE_TEXT, 'default' => 'Anonymous'),
+    'site_frontpage' => array('type' => VARIABLE_PATH, 'default' => 'node'),
+    // Site maintenance
+    'site_offline' => array('type' => VARIABLE_NUMBER, 'default' => 0),
+    'site_offline_message' => array('type' => VARIABLE_HTML, 
+      'default' => '@site is currently under maintenance. We should be back shortly. Thank you for your patience.',
+      'default_args' => array('@site' => variable_get('site_name'))
+    ),
+    // Custom error pages
+    'site_403' => array('type' => VARIABLE_PATH, 'default' => ''),
+    'site_404' => array('type' => VARIABLE_PATH, 'default' => ''),
+    // Administration theme
+    'admin_theme' => array('type' => VARIABLE_DATA, 'default' => 0),
+    // Performance settings.
+    'cache' => array('type' => VARIABLE_DATA, 'default' => FALSE),
+    'cache_lifetime' => array('type' => VARIABLE_DATA, 'default' => 0),
+    'preprocess_css' => array('type' => VARIABLE_DATA, 'default' => FALSE),
+    // Image toolkit
+    'image_toolkit' => array('type' => VARIABLE_STRING, 'default' => 'gd'),
+    // Date and time settings
+    'date_default_timezone' => array('type' => VARIABLE_NUMBER, 'default' => 0),
+    'configurable_timezones' => array('type' => VARIABLE_NUMBER, 'default' => 1),
+    'date_first_day' => array('type' => VARIABLE_NUMBER, 'default' => 0),
+    'date_format_short' => array('type' => VARIABLE_STRING, 'default' => 'm/d/Y - H:i'),
+    //'date_format_short_custom' => array('type' => VARIABLE_STRING, 'default' => 'gd'),
+    'date_format_medium' => array('type' => VARIABLE_STRING, 'default' =>  'D, m/d/Y - H:i'),
+    //'date_format_medium_custom' => array('type' => VARIABLE_STRING, 'default' => 'gd'),
+    'date_format_long' => array('type' => VARIABLE_STRING, 'default' => 'l, F j, Y - H:i'),
+    //'date_format_long_custom' => array('type' => VARIABLE_STRING, 'default' => 'gd'),
+    // Files
+    'file_downloads'  => array('type' => VARIABLE_DATA, 'default' => FILE_DOWNLOADS_PUBLIC),
+    'file_directory_path' => array('type' => VARIABLE_PATH, 'default' => 'files'),
+    'file_directory_temp' => array('type' => VARIABLE_PATH, 'default' => NULL),
+    // RSS Feeds settings
+    'feed_default_items' => array('type' => VARIABLE_NUMBER, 'default' => 10),
+    'feed_item_length' => array('type' => VARIABLE_DATA, 'default' => 'teaser'),
+  );
+}
Index: modules/system/system.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.install,v
retrieving revision 1.119
diff -u -r1.119 system.install
--- modules/system/system.install	30 May 2007 08:08:58 -0000	1.119
+++ modules/system/system.install	31 May 2007 23:25:52 -0000
@@ -3339,6 +3339,17 @@
 
   return $ret;
 }
+
+/**
+ * Add element field to variable table
+ */
+function system_update_6023() {
+  $ret = array();
+  db_add_field($ret, 'variable', 'element', array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => ''));
+  db_drop_primary_key($ret, 'variable');
+  db_add_primary_key($ret, 'variable', array('name', 'element'));
+  return $ret;
+}
 /**
  * @} End of "defgroup updates-5.x-to-6.x"
  * The next series of updates should start at 7000.
Index: modules/system/system.schema
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.schema,v
retrieving revision 1.4
diff -u -r1.4 system.schema
--- modules/system/system.schema	30 May 2007 08:08:59 -0000	1.4
+++ modules/system/system.schema	31 May 2007 23:25:56 -0000
@@ -186,9 +186,10 @@
   $schema['variable'] = array(
     'fields' => array(
       'name'     => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => ''),
+      'element'     => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, 'default' => ''),
       'value'    => array('type' => 'text', 'not null' => TRUE, 'size' => 'big'),
     ),
-    'primary key' => array('name'),
+    'primary key' => array('name', 'element'),
   );
 
   return $schema;
Index: update.php
===================================================================
RCS file: /cvs/drupal/drupal/update.php,v
retrieving revision 1.223
diff -u -r1.223 update.php
--- update.php	25 May 2007 12:46:43 -0000	1.223
+++ update.php	31 May 2007 23:25:23 -0000
@@ -131,7 +131,7 @@
  * update in the 4.6 to 4.7 migration.
  */
 function update_fix_schema_version() {
-  if ($update_start = variable_get('update_start', FALSE)) {
+  if ($update_start = variable_get_default('update_start', FALSE)) {
     // Some updates were made to the 4.6 branch and 4.7 branch. This sets
     // temporary variables to prevent the updates from being executed twice and
     // throwing errors.
@@ -210,7 +210,7 @@
 function update_fix_sessions() {
   $ret = array();
 
-  if (drupal_get_installed_schema_version('system') < 130 && !variable_get('update_sessions_fixed', FALSE)) {
+  if (drupal_get_installed_schema_version('system') < 130 && !variable_get_default('update_sessions_fixed', FALSE)) {
     if ($GLOBALS['db_type'] == 'mysql') {
       db_query("ALTER TABLE {sessions} ADD cache int(11) NOT NULL default '0' AFTER timestamp");
     }
@@ -230,7 +230,7 @@
  * when update 115 is removed. It is part of the Drupal 4.5 to 4.7 migration.
  */
 function update_fix_watchdog_115() {
-  if (drupal_get_installed_schema_version('system') < 115 && !variable_get('update_watchdog_115_fixed', FALSE)) {
+  if (drupal_get_installed_schema_version('system') < 115 && !variable_get_default('update_watchdog_115_fixed', FALSE)) {
     if ($GLOBALS['db_type'] == 'mysql') {
       $ret[] = update_sql("ALTER TABLE {watchdog} ADD severity tinyint(3) unsigned NOT NULL default '0'");
     }
@@ -253,7 +253,7 @@
  * when update 142 is removed. It is part of the Drupal 4.6 to 4.7 migration.
  */
 function update_fix_watchdog() {
-  if (drupal_get_installed_schema_version('system') < 142 && !variable_get('update_watchdog_fixed', FALSE)) {
+  if (drupal_get_installed_schema_version('system') < 142 && !variable_get_default('update_watchdog_fixed', FALSE)) {
     switch ($GLOBALS['db_type']) {
       case 'pgsql':
         $ret = array();
@@ -510,7 +510,7 @@
 
 // This code may be removed later. It is part of the Drupal 4.6 to 4.7 migration.
 function update_fix_access_table() {
-  if (variable_get('update_access_fixed', FALSE)) {
+  if (variable_get_default('update_access_fixed', FALSE)) {
     return;
   }
 
Index: install.php
===================================================================
RCS file: /cvs/drupal/drupal/install.php,v
retrieving revision 1.55
diff -u -r1.55 install.php
--- install.php	28 May 2007 18:50:49 -0000	1.55
+++ install.php	31 May 2007 23:25:22 -0000
@@ -15,7 +15,7 @@
  *   The installation phase we should proceed to.
  */
 function install_main() {
-  global $profile, $install_locale, $conf;
+  global $profile, $install_locale, $variables;
   require_once './includes/cache-install.inc';
   require_once './includes/bootstrap.inc';
   drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
@@ -25,7 +25,7 @@
   // process, we temporarily replace the normal cache system with
   // a stubbed-out version that short-circuits the actual caching
   // process and avoids any errors.
-  $conf['cache_inc'] = './includes/cache-install.inc';
+  $variables['cache_inc'] = './includes/cache-install.inc';
   require_once './modules/system/system.install';
   require_once './includes/file.inc';
 
@@ -830,14 +830,14 @@
   $form['site_information']['site_name'] = array(
     '#type' => 'textfield',
     '#title' => st('Site name'),
-    '#default_value' => variable_get('site_name', 'Drupal'),
+    '#default_value' => variable_get('site_name'),
     '#required' => TRUE,
     '#weight' => -20,
   );
   $form['site_information']['site_mail'] = array(
     '#type' => 'textfield',
     '#title' => st('Site e-mail address'),
-    '#default_value' => variable_get('site_mail', ini_get('sendmail_from')),
+    '#default_value' => variable_get('site_mail'),
     '#description' => st('A valid e-mail address to be used as the "From" address by the auto-mailer during registration, new password requests, notifications, etc.  To lessen the likelihood of e-mail being marked as spam, this e-mail address should use the same domain as the website.'),
     '#required' => TRUE,
     '#weight' => -15,
@@ -885,7 +885,7 @@
   $form['server_settings']['date_default_timezone'] = array(
     '#type' => 'select',
     '#title' => st('Default time zone'),
-    '#default_value' => variable_get('date_default_timezone', 0),
+    '#default_value' => variable_get('date_default_timezone'),
     '#options' => $zones,
     '#description' => st('By default, dates in this site will be displayed in the chosen time zone.'),
     '#weight' => 5,
@@ -905,7 +905,7 @@
   $form['server_settings']['clean_url'] = array(
     '#type' => 'radios',
     '#title' => st('Clean URLs'),
-    '#default_value' => variable_get('clean_url', 0),
+    '#default_value' => variable_get('clean_url'),
     '#options' => array(st('Disabled'), st('Enabled')),
     '#description' => st('This option makes Drupal emit "clean" URLs (i.e. without <code>?q=</code> in the URL).'),
     '#disabled' => TRUE,
Index: modules/dblog/dblog.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/dblog/dblog.module,v
retrieving revision 1.8
diff -u -r1.8 dblog.module
--- modules/dblog/dblog.module	30 May 2007 08:34:12 -0000	1.8
+++ modules/dblog/dblog.module	31 May 2007 23:25:43 -0000
@@ -85,9 +85,9 @@
 
 function dblog_admin_settings() {
   $form['dblog_row_limit'] = array(
+    '#variable' => TRUE,
     '#type' => 'select',
     '#title' => t('Discard log entries above the following row limit'),
-    '#default_value' => variable_get('dblog_row_limit', 1000),
     '#options' => drupal_map_assoc(array(100, 1000, 10000, 100000, 1000000)),
     '#description' => t('The maximum number of rows to keep in the database log. Older entries will be automatically discarded. Requires crontab.')
   );
@@ -106,7 +106,7 @@
   if ($min) {
     $max = db_result(db_query('SELECT MAX(wid) FROM {watchdog}'));
     if ($max) {
-      if (($max - $min) > variable_get('dblog_row_limit', 1000)) {
+      if (($max - $min) > variable_get('dblog_row_limit')) {
         db_query('DELETE FROM {watchdog} WHERE wid < %d', $max - $min);
       }
     }
@@ -452,3 +452,12 @@
     'args' => $args,
   );
 }
+
+/**
+ * Implementation of hook_variable().
+ */
+function dblog_variable() {
+  return array(
+    'dblog_row_limit' => array('type' => VARIABLE_NUMBER, 'default' => 1000),
+  );
+}
\ No newline at end of file
Index: profiles/default/default.profile
===================================================================
RCS file: /cvs/drupal/drupal/profiles/default/default.profile,v
retrieving revision 1.12
diff -u -r1.12 default.profile
--- profiles/default/default.profile	16 May 2007 13:45:17 -0000	1.12
+++ profiles/default/default.profile	31 May 2007 23:26:02 -0000
@@ -110,7 +110,7 @@
   variable_set('comment_page', COMMENT_NODE_DISABLED);
 
   // Don't display date and author information for page nodes by default.
-  $theme_settings = variable_get('theme_settings', array());
+  $theme_settings = variable_get_default('theme_settings', array());
   $theme_settings['toggle_node_info_page'] = FALSE;
   variable_set('theme_settings', $theme_settings);
 
Index: modules/filter/filter.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.module,v
retrieving revision 1.175
diff -u -r1.175 filter.module
--- modules/filter/filter.module	28 May 2007 06:08:42 -0000	1.175
+++ modules/filter/filter.module	31 May 2007 23:25:45 -0000
@@ -155,14 +155,14 @@
   global $base_url;
   switch ($delta) {
     case 0:
-      if (variable_get("filter_html_$format", FILTER_HTML_STRIP) ==  FILTER_HTML_STRIP) {
-        if ($allowed_html = variable_get("allowed_html_$format", '<a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>')) {
+      if (variable_get_element('filter_hmtl', $format) ==  FILTER_HTML_STRIP) {
+        if ($allowed_html = variable_get_element('filter_allowed_html', $format)) {
           switch ($long) {
             case 0:
               return t('Allowed HTML tags') .': '. check_plain($allowed_html);
             case 1:
               $output = '<p>'. t('Allowed HTML tags') .': '. check_plain($allowed_html) .'</p>';
-              if (!variable_get("filter_html_help_$format", 1)) {
+              if (!variable_get_element('filter_html_help', $format)) {
                 return $output;
               }
 
@@ -170,7 +170,7 @@
 <p>This site allows HTML content. While learning all of HTML may feel intimidating, learning how to use a very small number of the most basic HTML "tags" is very easy. This table provides examples for each tag that is enabled on this site.</p>
 <p>For more information see W3C\'s <a href="http://www.w3.org/TR/html/">HTML Specifications</a> or use your favorite search engine to find other sites that explain HTML.</p>');
               $tips = array(
-                'a' => array( t('Anchors are used to make links to other pages.'), '<a href="'. $base_url .'">'. variable_get('site_name', 'Drupal') .'</a>'),
+                'a' => array( t('Anchors are used to make links to other pages.'), '<a href="'. $base_url .'">'. variable_get('site_name') .'</a>'),
                 'br' => array( t('By default line break tags are automatically added, so use this tag to add additional ones. Use of this tag is different because it is not used with an open/close pair like all the others. Use the extra " /" inside the tag to maintain XHTML 1.0 compatibility'), t('Text with <br />line break')),
                 'p' => array( t('By default paragraph tags are automatically added, so use this tag to add additional ones.'), '<p>'. t('Paragraph one.') .'</p> <p>'. t('Paragraph two.') .'</p>'),
                 'strong' => array( t('Strong'), '<strong>'. t('Strong') .'</strong>'),
@@ -284,14 +284,14 @@
         $roles[] = $name;
       }
     }
-    $default = ($id == variable_get('filter_default_format', 1));
+    $default = ($id == variable_get('filter_default_format'));
     $options[$id] = '';
     $form[$format->name]['id'] = array('#value' => $id);
     $form[$format->name]['roles'] = array('#value' => $default ? t('All roles may use default format') : ($roles ? implode(', ', $roles) : t('No roles may use this format')));
     $form[$format->name]['configure'] = array('#value' => l(t('configure'), 'admin/settings/filters/'. $id));
     $form[$format->name]['delete'] = array('#value' => $default ? '' : l(t('delete'), 'admin/settings/filters/delete/'. $id));
   }
-  $form['default'] = array('#type' => 'radios', '#options' => $options, '#default_value' => variable_get('filter_default_format', 1));
+  $form['default'] = array('#type' => 'radios', '#options' => $options, '#default_value' => variable_get('filter_default_format'));
   $form['submit'] = array('#type' => 'submit', '#value' => t('Set default format'));
   return $form;
 }
@@ -333,7 +333,7 @@
   $format = db_fetch_object(db_query('SELECT * FROM {filter_formats} WHERE format = %d', $format));
 
   if ($format) {
-    if ($format->format != variable_get('filter_default_format', 1)) {
+    if ($format->format != variable_get('filter_default_format')) {
       $form['format'] = array('#type' => 'hidden', '#value' => $format->format);
       $form['name'] = array('#type' => 'hidden', '#value' => $format->name);
 
@@ -373,7 +373,7 @@
  * Generate a filter format form.
  */
 function filter_admin_format_form($format = NULL) {
-  $default = ($format->format == variable_get('filter_default_format', 1));
+  $default = ($format->format == variable_get('filter_default_format'));
   if ($default) {
     $help = t('All roles for the default format must be enabled and cannot be changed.');
     $form['default_format'] = array('#type' => 'hidden', '#value' => 1);
@@ -608,7 +608,7 @@
         $args[] = $rid;
       }
       $query .= ' WHERE '. implode(' OR ', $where) .' OR format = %d';
-      $args[] = variable_get('filter_default_format', 1);
+      $args[] = variable_get('filter_default_format');
     }
 
     $result = db_query($query, $args);
@@ -653,7 +653,7 @@
  * Resolve a format id, including the default format.
  */
 function filter_resolve_format($format) {
-  return $format == FILTER_FORMAT_DEFAULT ? variable_get('filter_default_format', 1) : $format;
+  return $format == FILTER_FORMAT_DEFAULT ? variable_get('filter_default_format') : $format;
 }
 /**
  * Check if text in a certain input format is allowed to be cached.
@@ -804,7 +804,7 @@
     // Only one format available: use a hidden form item and only show tips.
     $format = array_shift($formats);
     $form[$format->format] = array('#type' => 'value', '#value' => $format->format, '#parents' => $parents);
-    $tips = _filter_tips(variable_get('filter_default_format', 1), FALSE);
+    $tips = _filter_tips(variable_get('filter_default_format'), FALSE);
     $form['format']['guidelines'] = array(
       '#title' => t('Formatting guidelines'),
       '#value' => theme('filter_tips', $tips, FALSE, $extra),
@@ -829,7 +829,7 @@
  */
 function filter_access($format) {
   $format = filter_resolve_format($format);
-  if (user_access('administer filters') || ($format == variable_get('filter_default_format', 1))) {
+  if (user_access('administer filters') || ($format == variable_get('filter_default_format'))) {
     return TRUE;
   }
   else {
@@ -1005,35 +1005,37 @@
  */
 function _filter_html_settings($format) {
   $form['filter_html'] = array(
+    // This sets the element name for all the fieldset
+    '#variable_element' => $format,
     '#type' => 'fieldset',
     '#title' => t('HTML filter'),
     '#collapsible' => TRUE,
   );
-  $form['filter_html']["filter_html_$format"] = array(
+  $form['filter_html']['filter_html'] = array(
+    '#variable' => TRUE,
     '#type' => 'radios',
     '#title' => t('Filter HTML tags'),
-    '#default_value' => variable_get("filter_html_$format", FILTER_HTML_STRIP),
     '#options' => array(FILTER_HTML_STRIP => t('Strip disallowed tags'), FILTER_HTML_ESCAPE => t('Escape all tags')),
     '#description' => t('How to deal with HTML tags in user-contributed content. If set to "Strip disallowed tags", dangerous tags are removed (see below). If set to "Escape tags", all HTML is escaped and presented as it was typed.'),
   );
-  $form['filter_html']["allowed_html_$format"] = array(
+  $form['filter_html']['filter_allowed_html'] = array(
+    '#variable_element' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Allowed HTML tags'),
-    '#default_value' => variable_get("allowed_html_$format", '<a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>'),
     '#size' => 64,
     '#maxlength' => 255,
     '#description' => t('If "Strip disallowed tags" is selected, optionally specify tags which should not be stripped. JavaScript event attributes are always stripped.'),
   );
-  $form['filter_html']["filter_html_help_$format"] = array(
+  $form['filter_html']['filter_html_help'] = array(
+    '#variable_element' => TRUE,
     '#type' => 'checkbox',
     '#title' => t('Display HTML help'),
-    '#default_value' => variable_get("filter_html_help_$format", 1),
     '#description' => t('If enabled, Drupal will display some basic HTML help in the long filter tips.'),
   );
-  $form['filter_html']["filter_html_nofollow_$format"] = array(
+  $form['filter_html']['filter_html_nofollow'] = array(
+    '#variable_element' => TRUE,
     '#type' => 'checkbox',
     '#title' => t('Spam link deterrent'),
-    '#default_value' => variable_get("filter_html_nofollow_$format", FALSE),
     '#description' => t('If enabled, Drupal will add rel="nofollow" to all links, as a measure to reduce the effectiveness of spam links. Note: this will also prevent valid links from being followed by search engines, therefore it is likely most effective when enabled for anonymous users.'),
   );
   return $form;
@@ -1043,17 +1045,17 @@
  * HTML filter. Provides filtering of input into accepted HTML.
  */
 function _filter_html($text, $format) {
-  if (variable_get("filter_html_$format", FILTER_HTML_STRIP) == FILTER_HTML_STRIP) {
-    $allowed_tags = preg_split('/\s+|<|>/', variable_get("allowed_html_$format", '<a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>'), -1, PREG_SPLIT_NO_EMPTY);
+  if (variable_get_element('filter_html', $format) == FILTER_HTML_STRIP) {
+    $allowed_tags = preg_split('/\s+|<|>/', variable_get_element('filter_allowed_html', $format), -1, PREG_SPLIT_NO_EMPTY);
     $text = filter_xss($text, $allowed_tags);
   }
 
-  if (variable_get("filter_html_$format", FILTER_HTML_STRIP) == FILTER_HTML_ESCAPE) {
+  if (variable_get_element('filter_html', $format) == FILTER_HTML_ESCAPE) {
     // Escape HTML
     $text = check_plain($text);
   }
 
-  if (variable_get("filter_html_nofollow_$format", FALSE)) {
+  if (variable_get_element('filter_html_nofollow', $format)) {
     $text = preg_replace('/<a([^>]+)>/i', '<a\\1 rel="nofollow">', $text);
   }
 
@@ -1069,10 +1071,11 @@
     '#title' => t('URL filter'),
     '#collapsible' => TRUE,
   );
-  $form['filter_urlfilter']['filter_url_length_'. $format] = array(
+  $form['filter_urlfilter']['filter_url_length'] = array(
+    '#variable' => TRUE,
+    '#variable_element' => $format,
     '#type' => 'textfield',
     '#title' => t('Maximum link text length'),
-    '#default_value' => variable_get('filter_url_length_'. $format, 72),
     '#maxlength' => 4,
     '#description' => t('URLs longer than this number of characters will be truncated to prevent long strings that break formatting. The link itself will be retained; just the text portion of the link will be truncated.'),
   );
@@ -1085,7 +1088,7 @@
  */
 function _filter_url($text, $format) {
   // Pass length to regexp callback
-  _filter_url_trim(NULL, variable_get('filter_url_length_'. $format, 72));
+  _filter_url_trim(NULL, variable_get_element('filter_url_length', $format));
 
   $text   = ' '. $text .' ';
 
@@ -1518,7 +1521,7 @@
 function filter_xss_bad_protocol($string, $decode = TRUE) {
   static $allowed_protocols;
   if (!isset($allowed_protocols)) {
-    $allowed_protocols = array_flip(variable_get('filter_allowed_protocols', array('http', 'https', 'ftp', 'news', 'nntp', 'telnet', 'mailto', 'irc', 'ssh', 'sftp', 'webcal')));
+    $allowed_protocols = array_flip(variable_get('filter_allowed_protocols'));
   }
 
   // Get the plain text representation of the attribute value (i.e. its meaning).
@@ -1554,3 +1557,17 @@
  * @} End of "Standard filters".
  */
 
+/**
+ * Implementation of hook_variable().
+ */
+function filter_variable() {
+  return array(
+    'filter_default_format' => array('type' => VARIABLE_VALUE, 'default' => 1),
+    // These are variable groups, for different formats
+    'filter_html' => array('type' => VARIABLE_GROUP | VARIABLE_VALUE, 'default' => FILTER_HTML_STRIP),
+    'filter_allowed_html' => array('type' => VARIABLE_GROUP | VARIABLE_STRING, 'default' =>  '<a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>'),
+    'filter_html_help' => array('type' => VARIABLE_GROUP | VARIABLE_BOOL, 'default' => 1),
+    'filter_html_nofollow' => array('type' => VARIABLE_GROUP | VARIABLE_BOOL, 'default' => FALSE),
+    'filter_url_length'  => array('type' => VARIABLE_GROUP | VARIABLE_NUMBER, 'default' => 72)
+  );
+}
Index: modules/upload/upload.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/upload/upload.module,v
retrieving revision 1.163
diff -u -r1.163 upload.module
--- modules/upload/upload.module	30 May 2007 08:08:59 -0000	1.163
+++ modules/upload/upload.module	31 May 2007 23:25:58 -0000
@@ -151,9 +151,6 @@
  * Menu callback for the upload settings form.
  */
 function upload_admin_settings() {
-  $upload_extensions_default = variable_get('upload_extensions_default', 'jpg jpeg gif png txt html doc xls pdf ppt pps odt ods odp');
-  $upload_uploadsize_default = variable_get('upload_uploadsize_default', 1);
-  $upload_usersize_default = variable_get('upload_usersize_default', 1);
 
   $form['settings_general'] = array(
     '#type' => 'fieldset',
@@ -161,42 +158,42 @@
     '#collapsible' => TRUE,
   );
   $form['settings_general']['upload_max_resolution'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Maximum resolution for uploaded images'),
-    '#default_value' => variable_get('upload_max_resolution', 0),
     '#size' => 15,
     '#maxlength' => 10,
     '#description' => t('The maximum allowed image size (e.g. 640x480). Set to 0 for no restriction. If an <a href="!image-toolkit-link">image toolkit</a> is installed, files exceeding this value will be scalled down to fit.', array('!image-toolkit-link' => url('admin/settings/image-toolkit'))),
     '#field_suffix' => '<kbd>'. t('WIDTHxHEIGHT') .'</kbd>'
   );
   $form['settings_general']['upload_list_default'] = array(
+    '#variable' => TRUE,
     '#type' => 'select',
     '#title' => t('List files by default'),
-    '#default_value' => variable_get('upload_list_default', 1),
     '#options' => array(0 => t('No'), 1 => t('Yes')),
     '#description' => t('Set whether files attached to nodes are listed or not in the node view by default.'),
   );
 
   $form['settings_general']['upload_extensions_default'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Default permitted file extensions'),
-    '#default_value' => $upload_extensions_default,
     '#maxlength' => 255,
     '#description' => t('Default extensions that users can upload. Separate extensions with a space and do not include the leading dot.'),
   );
   $form['settings_general']['upload_uploadsize_default'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Default maximum file size per upload'),
-    '#default_value' => $upload_uploadsize_default,
     '#size' => 5,
     '#maxlength' => 5,
     '#description' => t('The default maximum file size a user can upload. If an image is uploaded and a maximum resolution is set, the size will be checked after the file has been resized.'),
     '#field_suffix' => t('MB'),
   );
   $form['settings_general']['upload_usersize_default'] = array(
+    '#variable' => TRUE,
     '#type' => 'textfield',
     '#title' => t('Default total file size per user'),
-    '#default_value' => $upload_usersize_default,
     '#size' => 5,
     '#maxlength' => 5,
     '#description' => t('The default maximum size of all files a user can have on the site.'),
@@ -210,31 +207,32 @@
 
   foreach ($roles as $rid => $role) {
     $form['settings_role_'. $rid] = array(
+      '#variable_element' => $rid,
       '#type' => 'fieldset',
       '#title' => t('Settings for @role', array('@role' => $role)),
       '#collapsible' => TRUE,
       '#collapsed' => TRUE,
     );
     $form['settings_role_'. $rid]['upload_extensions_'. $rid] = array(
+      '#variable' => TRUE, '#variable_name' => 'upload_extensions',
       '#type' => 'textfield',
       '#title' => t('Permitted file extensions'),
-      '#default_value' => variable_get('upload_extensions_'. $rid, $upload_extensions_default),
       '#maxlength' => 255,
       '#description' => t('Extensions that users in this role can upload. Separate extensions with a space and do not include the leading dot.'),
     );
     $form['settings_role_'. $rid]['upload_uploadsize_'. $rid] = array(
+      '#variable' => TRUE, '#variable_name' => 'upload_uploadsize',
       '#type' => 'textfield',
       '#title' => t('Maximum file size per upload'),
-      '#default_value' => variable_get('upload_uploadsize_'. $rid, $upload_uploadsize_default),
       '#size' => 5,
       '#maxlength' => 5,
       '#description' => t('The maximum size of a file a user can upload. If an image is uploaded and a maximum resolution is set, the size will be checked after the file has been resized.'),
       '#field_suffix' => t('MB'),
     );
     $form['settings_role_'. $rid]['upload_usersize_'. $rid] = array(
+      '#variable' => TRUE, '#variable_name' => 'upload_usersize',
       '#type' => 'textfield',
       '#title' => t('Total file size per user'),
-      '#default_value' => variable_get('upload_usersize_'. $rid, $upload_usersize_default),
       '#size' => 5,
       '#maxlength' => 5,
       '#description' => t('The maximum size of all files a user can have on the site.'),
@@ -265,18 +263,18 @@
  *       A string specifying the maximum resolution of images.
  */
 function _upload_file_limits($user) {
-  $file_limit = variable_get('upload_uploadsize_default', 1);
-  $user_limit = variable_get('upload_usersize_default', 1);
-  $all_extensions = explode(' ', variable_get('upload_extensions_default', 'jpg jpeg gif png txt html doc xls pdf ppt pps odt ods odp'));
+  $file_limit = variable_get('upload_uploadsize_default');
+  $user_limit = variable_get('upload_usersize_default');
+  $all_extensions = explode(' ', variable_get('upload_extensions_default'));
   foreach ($user->roles as $rid => $name) {
-    $extensions = variable_get("upload_extensions_$rid", variable_get('upload_extensions_default', 'jpg jpeg gif png txt html doc xls pdf ppt pps odt ods odp'));
+    $extensions = variable_get_element('upload_extensions', $rid);
     $all_extensions = array_merge($all_extensions, explode(' ', $extensions));
 
     // A zero value indicates no limit, take the least restrictive limit.
-    $file_size = variable_get("upload_uploadsize_$rid", variable_get('upload_uploadsize_default', 1)) * 1024 * 1024;
+    $file_size = variable_get_element('upload_uploadsize', $rid) * 1024 * 1024;
     $file_limit = ($file_limit && $file_size) ? max($file_limit, $file_size) : 0;
 
-    $user_size = variable_get("upload_usersize_$rid", variable_get('upload_usersize_default', 1)) * 1024 * 1024;
+    $user_size = variable_get_element('upload_usersize', $rid) * 1024 * 1024;
     $user_limit = ($user_limit && $user_size) ? max($user_limit, $user_size) : 0;
   }
   $all_extensions = implode(' ', array_unique($all_extensions));
@@ -284,7 +282,7 @@
     'extensions' => $all_extensions,
     'file_size' => $file_limit,
     'user_size' => $user_limit,
-    'resolution' => variable_get('upload_max_resolution', 0),
+    'resolution' => variable_get('upload_max_resolution'),
   );
 }
 
@@ -339,7 +337,7 @@
 
   // Save new file uploads.
   if (($user->uid != 1 || user_access('upload files')) && ($file = file_save_upload('upload', $validators))) {
-    $file->list = variable_get('upload_list_default',1);
+    $file->list = variable_get('upload_list_default');
     $file->description = $file->filename;
     $_SESSION['upload_current_file'] = $file->fid;
     $_SESSION['upload_files'][$file->fid] = $file;
@@ -355,10 +353,10 @@
 
 function upload_form_alter(&$form, $form_state, $form_id) {
   if ($form_id == 'node_type_form' && isset($form['identity']['type'])) {
-    $form['workflow']['upload'] = array(
+    $form['workflow']['upload_node'] = array(
+      '#variable' => TRUE, 
       '#type' => 'radios',
       '#title' => t('Attachments'),
-      '#default_value' => variable_get('upload_'. $form['#node_type']->type, 1),
       '#options' => array(t('Disabled'), t('Enabled')),
     );
   }
@@ -418,7 +416,7 @@
 
     case 'load':
       $output = '';
-      if (variable_get("upload_$node->type", 1) == 1) {
+      if (variable_get_element('upload_node', $node->type) == 1) {
         $output['files'] = upload_load($node);
         return $output;
       }
@@ -623,7 +621,7 @@
       // problem formapi has recognizing new checkboxes. see comments in
       // _upload_prepare.
       if (isset($_SESSION['upload_current_file']) && $_SESSION['upload_current_file'] == $file->fid) {
-        $form['files'][$key]['list']['#value'] = variable_get('upload_list_default', 1);
+        $form['files'][$key]['list']['#value'] = variable_get('upload_list_default');
       }
       $form['files'][$key]['filename'] = array('#type' => 'value',  '#value' => $file->filename);
       $form['files'][$key]['filepath'] = array('#type' => 'value',  '#value' => $file->filepath);
@@ -734,3 +732,38 @@
   print drupal_to_js(array('status' => TRUE, 'data' => $output));
   exit;
 }
+
+/**
+ * Implementation of hook_variables().
+ */
+function upload_variable() {
+  return array(
+    // List files by default for node attachments.
+    'upload_list_default' => array('type' => VARIABLE_BOOL, 'default' => 1),
+    
+    // Special default variables
+    // Default maximum file size per upload
+    'upload_uploadsize_default' => array('type' => VARIABLE_NUMBER, 'default' => 1),
+    // Default total file size per user
+    'upload_usersize_default' => array('type' => VARIABLE_NUMBER, 'default' => 1),
+     // Maximum resolution for uploaded images
+    'upload_max_resolution_default' => array('type' => VARIABLE_STRING, 'default' => 0),
+
+    // Group variables, per role. All they use another variable as fallback
+
+    // Permitted file extensions.
+    'upload_extensions' => array('type' => VARIABLE_GROUP | VARIABLE_STRING | VARIABLE_FALLBACK, 
+      'default' => 'upload_extensions_default'),
+    'upload_uploadsize' => array('type' => VARIABLE_GROUP | VARIABLE_NUMBER | VARIABLE_FALLBACK,
+      'default' => 'upload_uploadsize_default'),
+    // Default total file size per user
+    'upload_usersize' => array('type' => VARIABLE_GROUP | VARIABLE_NUMBER | VARIABLE_FALLBACK,
+      'default' => 'upload_usersize_default'),
+    // Maximum resolution for uploaded images
+    'upload_max_resolution' => array('type' => VARIABLE_GROUP | VARIABLE_STRING | VARIABLE_FALLBACK,
+       'default' => 'upload_max_resolution_default'), 
+    
+    // Group variables, per node type
+    'upload_node' => array('type' => VARIABLE_GROUP | VARIABLE_BOOL, 'default' => 1),   
+  );
+}
Index: modules/color/color.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/color/color.module,v
retrieving revision 1.21
diff -u -r1.21 color.module
--- modules/color/color.module	28 May 2007 06:08:41 -0000	1.21
+++ modules/color/color.module	31 May 2007 23:25:41 -0000
@@ -17,7 +17,7 @@
 function color_form_alter(&$form, $form_state, $form_id) {
   // Insert the color changer into the theme settings page.
   // TODO: Last condition in the following if disables color changer when private files are used this should be solved in a different way. See issue #92059.
-  if ($form_id == 'system_theme_settings' && color_get_info(arg(4)) && function_exists('gd_info') && variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC) {
+  if ($form_id == 'system_theme_settings' && color_get_info(arg(4)) && function_exists('gd_info') && variable_get('file_downloads') == FILE_DOWNLOADS_PUBLIC) {
     $form['color'] = array(
       '#type' => 'fieldset',
       '#title' => t('Color scheme'),
@@ -33,7 +33,7 @@
   if ($form_id == 'system_theme_select_form' || $form_id == 'system_themes') {
     $themes = list_themes();
     foreach (element_children($form) as $theme) {
-      if ($screenshot = variable_get('color_'. $theme .'_screenshot', NULL)) {
+      if ($screenshot = variable_get_default('color_'. $theme .'_screenshot', NULL)) {
         if (isset($form[$theme]['screenshot'])) {
           $form[$theme]['screenshot']['#value'] = theme('image', $screenshot, '', '', array('class' => 'screenshot'), FALSE);
         }
@@ -49,14 +49,14 @@
   global $theme_key;
 
   // Override stylesheet
-  $path = variable_get('color_'. $theme_key .'_stylesheet', NULL);
+  $path = variable_get_default('color_'. $theme_key .'_stylesheet', NULL);
   if ($path) {
     $vars['css']['all']['theme'][$path] = TRUE;
     $vars['styles'] = drupal_get_css($vars['css']);
   }
 
   // Override logo
-  $logo = variable_get('color_'. $theme_key .'_logo', NULL);
+  $logo = variable_get_default('color_'. $theme_key .'_logo', NULL);
   if ($logo && $vars['logo'] && preg_match('!'. $theme_key .'/logo.png$!', $vars['logo'])) {
     $vars['logo'] = base_path() . $logo;
   }
@@ -87,7 +87,7 @@
   }
 
   // Load variable
-  return $default ? $palette : variable_get('color_'. $theme .'_palette', $palette);
+  return $default ? $palette : variable_get_default('color_'. $theme .'_palette', $palette);
 }
 
 /**
@@ -109,7 +109,7 @@
   )), 'setting');
 
   // See if we're using a predefined scheme
-  $current = implode(',', variable_get('color_'. $theme .'_palette', array()));
+  $current = implode(',', variable_get_default('color_'. $theme .'_palette', array()));
   // Note: we use the original theme when the default scheme is chosen.
   $current = isset($info['schemes'][$current]) ? $current : ($current == '' ? reset($info['schemes']) : '');
 
@@ -218,7 +218,7 @@
   }
 
   // Delete old files
-  foreach (variable_get('color_'. $theme .'_files', array()) as $file) {
+  foreach (variable_get_default('color_'. $theme .'_files', array()) as $file) {
     @unlink($file);
   }
   if ($file = dirname($file)) {
@@ -238,7 +238,7 @@
 
   // Prepare target locations for generated files
   $id = $theme .'-'. substr(md5(serialize($palette) . microtime()), 0, 8);
-  $paths['color'] = variable_get('file_directory_path', 'files') .'/color';
+  $paths['color'] = variable_get('file_directory_path') .'/color';
   $paths['target'] = $paths['color'] .'/'. $id;
   foreach ($paths as $path) {
     if (!is_dir($path)) {
