diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 52a8cb6a45b8d8c0067448d57295a6d48fd7c0ef..a7002355768279bb2bca7a4064c2a18544d0fe98 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -240,6 +240,8 @@
  */
 const DRUPAL_PHP_FUNCTION_PATTERN = '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*';
 
+require_once DRUPAL_ROOT . '/core/includes/config.inc';
+
 /**
  * Provides a caching wrapper to be used in place of large array structures.
  *
@@ -767,7 +769,7 @@ function drupal_settings_initialize() {
   global $base_url, $base_path, $base_root;
 
   // Export the following settings.php variables to the global namespace
-  global $databases, $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url, $db_prefix, $drupal_hash_salt, $is_https, $base_secure_url, $base_insecure_url;
+  global $databases, $cookie_domain, $conf, $installed_profile, $update_free_access, $db_url, $db_prefix, $drupal_hash_salt, $is_https, $base_secure_url, $base_insecure_url, $config_directory_name, $config_signature_key;
   $conf = array();
 
   if (file_exists(DRUPAL_ROOT . '/' . conf_path() . '/settings.php')) {
@@ -1343,8 +1345,10 @@ function drupal_page_header() {
  * response is sent.
  */
 function drupal_serve_page_from_cache(stdClass $cache) {
+  $config = config('system.performance');
+
   // Negotiate whether to use compression.
-  $page_compression = variable_get('page_compression', TRUE) && extension_loaded('zlib');
+  $page_compression = $config->get('page_compression') && extension_loaded('zlib');
   $return_compressed = $page_compression && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE;
 
   // Get headers set in hook_boot(). Keys are lower-case.
@@ -1370,7 +1374,7 @@ function drupal_serve_page_from_cache(stdClass $cache) {
   // max-age > 0, allowing the page to be cached by external proxies, when a
   // session cookie is present unless the Vary header has been replaced or
   // unset in hook_boot().
-  $max_age = !isset($_COOKIE[session_name()]) || isset($hook_boot_headers['vary']) ? variable_get('page_cache_maximum_age', 0) : 0;
+  $max_age = !isset($_COOKIE[session_name()]) || isset($hook_boot_headers['vary']) ? $config->get('page_cache_maximum_age') : 0;
   $default_headers['Cache-Control'] = 'public, max-age=' . $max_age;
 
   // Entity tag should change if the output changes.
@@ -2336,7 +2340,8 @@ function _drupal_bootstrap_page_cache() {
   }
   else {
     drupal_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES, FALSE);
-    $cache_enabled = variable_get('cache');
+    $config = config('system.performance');
+    $cache_enabled = $config->get('cache');
   }
   drupal_block_denied(ip_address());
   // If there is no session cookie and cache is enabled (or forced), try
diff --git a/core/includes/common.inc b/core/includes/common.inc
index 9f50506e945bb98fe688fc9a5806913c25ca958e..46caf3e34e7b41b34ee8a0ff9940e32dd00284f3 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -2599,7 +2599,8 @@ function drupal_page_footer() {
   // Commit the user session, if needed.
   drupal_session_commit();
 
-  if (variable_get('cache', 0) && ($cache = drupal_page_set_cache())) {
+  $config = config('system.performance');
+  if ($config->get('cache') && ($cache = drupal_page_set_cache())) {
     drupal_serve_page_from_cache($cache);
   }
   else {
@@ -3177,7 +3178,14 @@ function drupal_group_css($css) {
  * @see system_element_info()
  */
 function drupal_aggregate_css(&$css_groups) {
-  $preprocess_css = (variable_get('preprocess_css', FALSE) && (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update'));
+  // Only aggregate during normal site operation.
+  if (defined('MAINTENANCE_MODE')) {
+    $preprocess_css = FALSE;
+  }
+  else {
+    $config = config('system.performance');
+    $preprocess_css = $config->get('preprocess_css');
+  }
 
   // For each group that needs aggregation, aggregate its items.
   foreach ($css_groups as $key => $group) {
@@ -4410,9 +4418,16 @@ function drupal_group_js($javascript) {
  * @see drupal_pre_render_scripts()
  */
 function drupal_aggregate_js(&$js_groups) {
-  // Only aggregate when the site is configured to do so, and not during an
-  // update.
-  if (variable_get('preprocess_js', FALSE) && (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update')) {
+  // Only aggregate during normal site operation.
+  if (defined('MAINTENANCE_MODE')) {
+    $preprocess_js = FALSE;
+  }
+  else {
+    $config = config('system.performance');
+    $preprocess_js = $config->get('preprocess_js');
+  }
+
+  if ($preprocess_js) {
     foreach ($js_groups as $key => $group) {
       if ($group['type'] == 'file' && $group['preprocess']) {
         $js_groups[$key]['data'] = drupal_build_js_cache($group['items']);
@@ -5187,7 +5202,7 @@ function drupal_page_set_cache() {
     }
 
     if ($cache->data['body']) {
-      if (variable_get('page_compression', TRUE) && extension_loaded('zlib')) {
+      if (config('system.performance')->get('page_compression') && extension_loaded('zlib')) {
         $cache->data['body'] = gzencode($cache->data['body'], 9, FORCE_GZIP);
       }
       cache('page')->set($cache->cid, $cache->data, $cache->expire);
diff --git a/core/includes/config.inc b/core/includes/config.inc
new file mode 100644
index 0000000000000000000000000000000000000000..8c2772b2f7d372d0ada5c139875aaf3d23ca1575
--- /dev/null
+++ b/core/includes/config.inc
@@ -0,0 +1,242 @@
+<?php
+
+use Drupal\Core\Config\DrupalVerifiedStorageSQL;
+
+/**
+ * @file
+ * This is the API for configuration storage.
+ */
+
+/**
+ * Gets the randomly generated config directory name.
+ *
+ * @return
+ *   The directory name.
+ */
+function config_get_config_directory() {
+  global $config_directory_name;
+
+  if ($test_prefix = drupal_valid_test_ua()) {
+    $path = conf_path() . '/files/simpletest/config_' . $test_prefix;
+  }
+  else {
+    $path = conf_path() . '/files/' . $config_directory_name;
+  }
+  return $path;
+}
+
+/**
+ * Moves the default config supplied by a module to the live config directory.
+ *
+ * @param
+ *   The name of the module we are installing.
+ *
+ * @todo Make this acknowledge other storage engines rather than having
+ *   SQL be hardcoded.
+ */
+function config_install_default_config($module) {
+  $module_config_dir = drupal_get_path('module', $module) . '/config';
+  $drupal_config_dir = config_get_config_directory();
+  if (is_dir(drupal_get_path('module', $module) . '/config')) {
+    $files = glob($module_config_dir . '/' . '*.xml');
+    foreach ($files as $key => $file) {
+      // Load config data into the active store and write it out to the
+      // file system in the drupal config directory. Note the config name
+      // needs to be the same as the file name WITHOUT the extension.
+      $parts = explode('/', $file);
+      $file = array_pop($parts);
+      $config_name = str_replace('.xml', '', $file);
+
+      $verified_storage = new DrupalVerifiedStorageSQL($config_name);
+      $verified_storage->write(file_get_contents($module_config_dir . '/' . $file));
+    }
+  }
+}
+
+/**
+ * Retrieves an iterable array which lists the children under a config 'branch'.
+ *
+ * Given the following configuration files:
+ * - core.entity.node_type.article.xml
+ * - core.entity.node_type.page.xml
+ *
+ * You can pass a prefix 'core.entity.node_type' and get back an array of the
+ * filenames that match. This allows you to iterate through all files in a
+ * branch.
+ *
+ * @param $prefix
+ *   The prefix of the files we are searching for.
+ *
+ * @return
+ *   An array of file names under a branch.
+ */
+function config_get_signed_file_storage_names_with_prefix($prefix = '') {
+  $files = glob(config_get_config_directory() . '/' . $prefix . '*.xml');
+  $clean_name = function ($value) {
+    return basename($value, '.xml');
+  };
+  return array_map($clean_name, $files);
+}
+
+/**
+ * Generates a hash of a config file's contents using our encryption key.
+ *
+ * @param $data
+ *   The contents of a configuration file.
+ *
+ * @return
+ *   A hash of the data.
+ */
+function config_sign_data($data) {
+  // The configuration key is loaded from settings.php and imported into the global namespace
+  global $config_signature_key;
+
+  // SHA-512 is both secure and very fast on 64 bit CPUs.
+  return hash_hmac('sha512', $data, $config_signature_key);
+}
+
+/**
+ * @todo
+ *
+ * @param $prefix
+ *   @todo
+ *
+ * @return
+ *   @todo
+ */
+function config_get_verified_storage_names_with_prefix($prefix = '') {
+  return DrupalVerifiedStorageSQL::getNamesWithPrefix($prefix);
+}
+
+/**
+ * Retrieves a configuration object.
+ *
+ * This is the main entry point to the configuration API. Calling
+ * @code config(book.admin) @endcode will return a configuration object in which
+ * the book module can store its administrative settings.
+ *
+ * @param $name
+ *   The name of the configuration object to retrieve. The name corresponds to
+ *   an XML configuration file. For @code config(book.admin) @endcode, the
+ *   config object returned will contain the contents of book.admin.xml.
+ * @param $class
+ *   The class name of the config object to be returned. Defaults to
+ *   DrupalConfig.
+ *
+ * @return
+ *   An instance of the class specified in the $class parameter.
+ *
+ * @todo Replace this with an appropriate factory / ability to inject in
+ *   alternate storage engines..
+ */
+function config($name, $class = 'Drupal\Core\Config\DrupalConfig') {
+  return new $class(new DrupalVerifiedStorageSQL($name));
+}
+
+/**
+ * Decodes configuration data from its native format to an associative array.
+ *
+ * @param $data
+ *   Configuration data.
+ *
+ * @return
+ *   An associative array representation of the data.
+ */
+function config_decode($data) {
+  if (empty($data)) {
+    return array();
+  }
+
+  // This is the fastest and easiest way to get from a string of XML to a PHP
+  // array since SimpleXML and json_decode()/encode() are native to PHP. Our
+  // only other choice would be a custom userspace implementation which would
+  // be a lot less performant and more complex.
+  $xml = new SimpleXMLElement($data);
+  $json = json_encode($xml);
+  return json_decode($json, TRUE);
+}
+
+/**
+ * Standardizes SimpleXML object output into simple arrays for easier use.
+ *
+ * @param $xmlObject
+ *   A valid XML string.
+ *
+ * @return
+ *   An array representation of A SimpleXML object.
+ */
+function config_xml_to_array($data) {
+  $out = array();
+  $xmlObject = simplexml_load_string($data);
+
+  if (is_object($xmlObject)) {
+    $attributes = (array) $xmlObject->attributes();
+    if (isset($attributes['@attributes'])) {
+      $out['#attributes'] = $attributes['@attributes'];
+    }
+  }
+  if (trim((string) $xmlObject)) {
+    return trim((string) $xmlObject);
+  }
+  foreach ($xmlObject as $index => $content) {
+    if (is_object($content)) {
+      $out[$index] = config_xml_to_array($content);
+    }
+  }
+
+  return $out;
+}
+
+/**
+ * Encodes an array into the native configuration format.
+ *
+ * @param $data
+ *   An associative array or an object
+ *
+ * @return
+ *   A representation of this array or object in the native configuration
+ *   format.
+ *
+ * @todo The loaded XML can be invalid; throwing plenty of PHP warnings but no
+ *   catchable error.
+ */
+function config_encode($data) {
+  // Convert the supplied array into a SimpleXMLElement.
+  $xml_object = new SimpleXMLElement("<?xml version=\"1.0\"?><config></config>");
+  config_array_to_xml($data, $xml_object);
+
+  // Pretty print the result.
+  $dom = new DOMDocument('1.0');
+  $dom->preserveWhiteSpace = false;
+  $dom->formatOutput = true;
+  $dom->loadXML($xml_object->asXML());
+
+  return $dom->saveXML();
+}
+
+/**
+ * Encodes an array into XML
+ *
+ * @param $data
+ *   An associative array or an object
+ *
+ * @return
+ *   A representation of this array or object in the native configuration
+ *   format.
+ */
+function config_array_to_xml($array, &$xml_object) {
+  foreach ($array as $key => $value) {
+    if (is_array($value)) {
+      if (!is_numeric($key)){
+        $subnode = $xml_object->addChild("$key");
+        config_array_to_xml($value, $subnode);
+      }
+      else {
+        config_array_to_xml($value, $xml_object);
+      }
+    }
+    else {
+      $xml_object->addChild($key, $value);
+    }
+  }
+}
diff --git a/core/includes/file.inc b/core/includes/file.inc
index 0e69bfe69baf53534398ca3a94eb513119e722d6..6ac7b922269156420c13f86589a7565265188aa3 100644
--- a/core/includes/file.inc
+++ b/core/includes/file.inc
@@ -464,6 +464,7 @@ function file_ensure_htaccess() {
     file_save_htaccess('private://', TRUE);
   }
   file_save_htaccess('temporary://', TRUE);
+  file_save_htaccess(config_get_config_directory(), TRUE);
 }
 
 /**
diff --git a/core/includes/form.inc b/core/includes/form.inc
index 9051eef2a3a99f0871cb74f23049aeeae557373d..0124abce7eb3a7b1907f5c32855433d4de2b7e0a 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -865,7 +865,8 @@ function drupal_process_form($form_id, &$form, &$form_state) {
       // 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', 0) && !empty($form_state['values']['form_build_id'])) {
+      $config = config('system.performance');
+      if (!$config->get('cache') && !empty($form_state['values']['form_build_id'])) {
         cache('form')->delete('form_' . $form_state['values']['form_build_id']);
         cache('form')->delete('form_state_' . $form_state['values']['form_build_id']);
       }
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 49147a807826338251dd94f59c65e65446a67f83..6645edf045938e868c4aa6f162b9375da35debe7 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -1010,7 +1010,36 @@ function install_settings_form_submit($form, &$form_state) {
     'value'    => drupal_hash_base64(drupal_random_bytes(55)),
     'required' => TRUE,
   );
+
+  $settings['config_signature_key'] = array(
+    'value'    => drupal_hash_base64(drupal_random_bytes(55)),
+    'required' => TRUE,
+  );
+
+  // This duplicates drupal_get_token() because that function can't work yet.
+  // Wondering if it makes sense to move this later in the process, but its
+  // nice having all the settings stuff here.
+  //
+  // @todo This is actually causing a bug right now, because you can install
+  // without hitting install_settings_form_submit() if your settings.php
+  // already has the db stuff in it, and right now in that case your
+  // config directory never gets created. So this needs to be moved elsewhere.
+  $settings['config_directory_name'] = array(
+    'value'     => 'config_' . drupal_hmac_base64('', session_id() . $settings['config_signature_key']['value'] . $settings['drupal_hash_salt']['value']),
+    'required'  => TRUE,
+  );
+
   drupal_rewrite_settings($settings);
+  // Actually create the config directory named above.
+  $config_path = conf_path() . '/files/' . $settings['config_directory_name']['value'];
+  if (!file_prepare_directory($config_path, FILE_CREATE_DIRECTORY)) {
+    // How best to handle errors here?
+  };
+
+  // Write out a .htaccess file that will protect the config directory from
+  // prying eyes.
+  file_save_htaccess($config_path, TRUE);
+
   // Indicate that the settings file has been verified, and check the database
   // for the last completed task, now that we have a valid connection. This
   // last step is important since we want to trigger an error if the new
diff --git a/core/includes/install.inc b/core/includes/install.inc
index 8a25693a1c2a0dce3c827f9d17827912b19d5967..fb10d7b098871a465d92b09b0a04af515d0b71fb 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -434,6 +434,7 @@ function drupal_install_system() {
       ))
     ->execute();
   system_rebuild_module_data();
+  config_install_default_config('system');
 }
 
 /**
diff --git a/core/includes/language.inc b/core/includes/language.inc
index f12f34afa6d2813cb0cc345b0820c9ff454d8df9..f9b5c3b59bbcc62a1b77139622b899577302acc2 100644
--- a/core/includes/language.inc
+++ b/core/includes/language.inc
@@ -375,7 +375,8 @@ function language_provider_invoke($provider_id, $provider = NULL) {
 
     // If the language provider has no cache preference or this is satisfied
     // we can execute the callback.
-    $cache = !isset($provider['cache']) || $user->uid || $provider['cache'] == variable_get('cache', 0);
+    $config = config('system.performance');
+    $cache = !isset($provider['cache']) || $user->uid || $provider['cache'] == $config->get('cache');
     $callback = isset($provider['callbacks']['language']) ? $provider['callbacks']['language'] : FALSE;
     $langcode = $cache && function_exists($callback) ? $callback($languages) : FALSE;
     $results[$provider_id] = isset($languages[$langcode]) ? $languages[$langcode] : FALSE;
diff --git a/core/includes/module.inc b/core/includes/module.inc
index d61aba9a7e59d5e55be5b9feae8d52e254032112..aa9eaf5f684969a13f74bbae9cb97e371156c241 100644
--- a/core/includes/module.inc
+++ b/core/includes/module.inc
@@ -461,6 +461,9 @@ function module_enable($module_list, $enable_dependencies = TRUE) {
         $versions = drupal_get_schema_versions($module);
         $version = $versions ? max($versions) : SCHEMA_INSTALLED;
 
+        // Copy any default configuration data to the system config directory/
+        config_install_default_config($module);
+
         // If the module has no current updates, but has some that were
         // previously removed, set the version to the value of
         // hook_update_last_removed().
diff --git a/core/lib/Drupal/Core/Cache/DatabaseBackend.php b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
index 37af13c8438b27c6efd8c795ca4322e833198d3e..7afd6983a84b2def878e6702bcb5aa5a56e4672c 100644
--- a/core/lib/Drupal/Core/Cache/DatabaseBackend.php
+++ b/core/lib/Drupal/Core/Cache/DatabaseBackend.php
@@ -101,7 +101,8 @@ protected function prepareItem($cache) {
     // timer. The cache variable is loaded into the $user object by
     // _drupal_session_read() in session.inc. 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) && $user->cache > $cache->created) {
+    $config = config('system.performance');
+    if ($cache->expire != CACHE_PERMANENT && $config->get('cache_lifetime') && $user->cache > $cache->created) {
       // This cache data is too old and thus not valid for us, ignore it.
       return FALSE;
     }
diff --git a/core/lib/Drupal/Core/Config/ConfigException.php b/core/lib/Drupal/Core/Config/ConfigException.php
new file mode 100644
index 0000000000000000000000000000000000000000..c60a449822f8ce3793b59277bd042b2cce890563
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/ConfigException.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace Drupal\Core\Config;
+
+/**
+ * @todo
+ */
+class ConfigException extends \Exception {}
diff --git a/core/lib/Drupal/Core/Config/ConfigFileStorageException.php b/core/lib/Drupal/Core/Config/ConfigFileStorageException.php
new file mode 100644
index 0000000000000000000000000000000000000000..ce7fb305834eb06b87d613bd93b4e854f247921e
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/ConfigFileStorageException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Drupal\Core\Config;
+
+use Drupal\Core\Config\ConfigException;
+
+/**
+ * @todo
+ */
+class ConfigFileStorageException extends ConfigException {}
diff --git a/core/lib/Drupal/Core/Config/ConfigFileStorageReadException.php b/core/lib/Drupal/Core/Config/ConfigFileStorageReadException.php
new file mode 100644
index 0000000000000000000000000000000000000000..a3ac95c87c0a4780160ad1bb57d01565d4b7a968
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/ConfigFileStorageReadException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Drupal\Core\Config;
+
+use Drupal\Core\Config\ConfigFileStorageException;
+
+/**
+ * @todo
+ */
+class ConfigFileStorageReadException extends ConfigFileStorageException {}
diff --git a/core/lib/Drupal/Core/Config/ConfigFileStorageSignatureException.php b/core/lib/Drupal/Core/Config/ConfigFileStorageSignatureException.php
new file mode 100644
index 0000000000000000000000000000000000000000..65c5c59028e53bbfd52c61a2095375ecf40bbf80
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/ConfigFileStorageSignatureException.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace Drupal\Core\Config;
+
+use Drupal\Core\Config\ConfigFileStorageException;
+
+/**
+ * @todo
+ */
+class ConfigFileStorageSignatureException extends ConfigFileStorageException {}
diff --git a/core/lib/Drupal/Core/Config/DrupalConfig.php b/core/lib/Drupal/Core/Config/DrupalConfig.php
new file mode 100644
index 0000000000000000000000000000000000000000..54397e7a03f1aceee96c01917f72c947bc031b72
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/DrupalConfig.php
@@ -0,0 +1,198 @@
+<?php
+
+namespace Drupal\Core\Config;
+
+use Drupal\Core\Config\DrupalConfigVerifiedStorageInterface;
+use Drupal\Core\Config\ConfigException;
+
+/**
+ * Represents the default configuration storage object.
+ */
+class DrupalConfig {
+
+  /**
+   * The storage engine to save this config object to.
+   *
+   * @var DrupalConfigVerifiedStorageInterface
+   */
+  protected $_verifiedStorage;
+
+  protected $data = array();
+
+  /**
+   * Constructs a DrupalConfig object.
+   *
+   * @param DrupalConfigVerifiedStorageInterface $verified_storage
+   *   The storage engine where this config object should be saved.
+   *
+   * @todo $this should really know about $name and make it publicly accessible.
+   */
+  public function __construct(DrupalConfigVerifiedStorageInterface $verified_storage) {
+    $this->_verifiedStorage = $verified_storage;
+    $this->read();
+  }
+
+  /**
+   * Reads config data from the active store into our object.
+   */
+  public function read() {
+    $active = (array) config_decode($this->_verifiedStorage->read());
+    foreach ($active as $key => $value) {
+      $this->set($key, $value);
+    }
+  }
+
+  /**
+   * Checks whether a particular value is overridden.
+   *
+   * @param $key
+   *   @todo
+   *
+   * @return
+   *   @todo
+   */
+  public function isOverridden($key) {
+    return isset($this->_overrides[$key]);
+  }
+
+  /**
+   * Gets data from this config object.
+   *
+   * @param $key
+   *   A string that maps to a key within the configuration data.
+   *   For instance in the following XML:
+   *   @code
+   *   <foo>
+   *     <bar>baz</bar>
+   *   </foo>
+   *   @endcode
+   *   A key of 'foo.bar' would return the string 'baz'. However, a key of 'foo'
+   *   would return array('bar' => 'baz').
+   *   If no key is specified, then the entire data array is returned.
+   *
+   * The configuration system does not retain data types. Every saved value is
+   * casted to a string. In most cases this is not an issue; however, it can
+   * cause issues with Booleans, which are casted to "1" (TRUE) or "0" (FALSE).
+   * In particular, code relying on === or !== will no longer function properly.
+   *
+   * @see http://php.net/manual/en/language.operators.comparison.php.
+   *
+   * @return
+   *   The data that was requested.
+   */
+  public function get($key = '') {
+    if (empty($key)) {
+      return $this->data;
+    }
+    else {
+      $parts = explode('.', $key);
+      if (count($parts) == 1) {
+        return isset($this->data[$key]) ? $this->data[$key] : NULL;
+      }
+      else {
+        $key_exists = NULL;
+        $value = drupal_array_get_nested_value($this->data, $parts, $key_exists);
+        return $key_exists ? $value : NULL;
+      }
+    }
+  }
+
+  /**
+   * Sets value in this config object.
+   *
+   * @param $key
+   *   @todo
+   * @param $value
+   *   @todo
+   */
+  public function set($key, $value) {
+    // Remove all non-alphanumeric characters from the key.
+    // @todo Reverse this and throw an exception when encountering a key with
+    //   invalid name. The identical validation also needs to happen in get().
+    //   Furthermore, the dot/period is a reserved character; it may appear
+    //   between keys, but not within keys.
+    $key = preg_replace('@[^a-zA-Z0-9_.-]@', '', $key);
+
+    // Type-cast value into a string.
+    $value = $this->castValue($value);
+
+    $parts = explode('.', $key);
+    if (count($parts) == 1) {
+      $this->data[$key] = $value;
+    }
+    else {
+      drupal_array_set_nested_value($this->data, $parts, $value);
+    }
+    return $this;
+  }
+
+  /**
+   * Casts a saved value to a string.
+   *
+   * The configuration system only saves strings or arrays. Any scalar
+   * non-string value is cast to a string. The one exception is boolean FALSE
+   * which would normally become '' when cast to a string, but is manually
+   * cast to '0' here for convenience and consistency.
+   *
+   * Any non-scalar value that is not an array (aka objects) gets cast
+   * to an array.
+   *
+   * @param $value
+   *   A value being saved into the configuration system.
+   * @param $value
+   *   The value cast to a string or array.
+   */
+  public function castValue($value) {
+    if (is_scalar($value)) {
+      // Handle special case of FALSE, which should be '0' instead of ''.
+      if ($value === FALSE) {
+        $value = '0';
+      }
+      else {
+        $value = (string) $value;
+      }
+    }
+    else {
+      // Any non-scalar value must be an array.
+      if (!is_array($value)) {
+        $value = (array) $value;
+      }
+      // Recurse into any nested keys.
+      foreach ($value as $key => $nested_value) {
+        $value[$key] = $this->castValue($nested_value);
+      }
+    }
+    return $value;
+  }
+
+  /**
+   * Unsets value in this config object.
+   *
+   * @param $key
+   *   Name of the key whose value should be unset.
+   */
+  public function clear($key) {
+    $parts = explode('.', $key);
+    if (count($parts) == 1) {
+      unset($this->data[$key]);
+    }
+    else {
+      drupal_array_unset_nested_value($this->data, $parts);
+    }
+  }
+
+  /**
+   * Saves the configuration object to disk as XML.
+   */
+  public function save() {
+    $this->_verifiedStorage->write(config_encode($this->data));
+  }
+
+  /**
+   * Deletes the configuration object on disk.
+   */
+  public function delete() {
+    $this->data = array();
+    $this->_verifiedStorage->delete();
+  }
+}
diff --git a/core/lib/Drupal/Core/Config/DrupalConfigVerifiedStorage.php b/core/lib/Drupal/Core/Config/DrupalConfigVerifiedStorage.php
new file mode 100644
index 0000000000000000000000000000000000000000..ca37cdd659254370ca62781094ffabc1ca0f6262
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/DrupalConfigVerifiedStorage.php
@@ -0,0 +1,102 @@
+<?php
+
+namespace Drupal\Core\Config;
+
+use Drupal\Core\Config\DrupalConfigVerifiedStorageInterface;
+use Drupal\Core\Config\SignedFileStorage;
+
+/**
+ * @todo
+ */
+abstract class DrupalConfigVerifiedStorage implements DrupalConfigVerifiedStorageInterface {
+
+  protected $name;
+
+  /**
+   * The local signed file object to read from and write to.
+   *
+   * @var SignedFileStorage
+   */
+  protected $signedFile;
+
+  /**
+   * Implements DrupalConfigVerifiedStorageInterface::__construct().
+   */
+  function __construct($name) {
+    $this->name = $name;
+  }
+
+  /**
+   * Instantiates a new signed file object or returns the existing one.
+   *
+   * @return SignedFileStorage
+   *   The signed file object for this configuration object.
+   */
+  protected function signedFileStorage() {
+    if (!isset($this->signedFile)) {
+      $this->signedFile = new SignedFileStorage($this->name);
+    }
+    return $this->signedFile;
+  }
+
+  /**
+   * Implements DrupalConfigVerifiedStorageInterface::copyToFile().
+   */
+  public function copyToFile() {
+    return $this->writeToFile($this->read());
+  }
+
+  /**
+   * Implements DrupalConfigVerifiedStorageInterface::deleteFile().
+   */
+  public function deleteFile() {
+    return $this->signedFileStorage()->delete();
+  }
+
+  /**
+   * Implements DrupalConfigVerifiedStorageInterface::copyFromFile().
+   */
+  public function copyFromFile() {
+    return $this->writeToActive($this->readFromFile());
+  }
+
+  /**
+   * @todo
+   *
+   * @return
+   *   @todo
+   */
+  public function readFromFile() {
+    return $this->signedFileStorage()->read($this->name);
+  }
+
+  /**
+   * Implements DrupalConfigVerifiedStorageInterface::isOutOfSync().
+   */
+  public function isOutOfSync() {
+    return $this->read() !== $this->readFromFile();
+  }
+
+  /**
+   * Implements DrupalConfigVerifiedStorageInterface::write().
+   */
+  public function write($data) {
+    $this->writeToActive($data);
+    $this->writeToFile($data);
+  }
+
+  /**
+   * Implements DrupalConfigVerifiedStorageInterface::writeToFile().
+   */
+  public function writeToFile($data) {
+    return $this->signedFileStorage()->write($data);
+  }
+
+  /**
+   * Implements DrupalConfigVerifiedStorageInterface::delete().
+   */
+  public function delete() {
+    $this->deleteFromActive();
+    $this->deleteFile();
+  }
+}
diff --git a/core/lib/Drupal/Core/Config/DrupalConfigVerifiedStorageInterface.php b/core/lib/Drupal/Core/Config/DrupalConfigVerifiedStorageInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..2fdce769057332905ea7bc2862e1e1ec0bb2ccc3
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/DrupalConfigVerifiedStorageInterface.php
@@ -0,0 +1,84 @@
+<?php
+
+namespace Drupal\Core\Config;
+
+/**
+ * Defines an interface for verified storage manipulation.
+ *
+ * This class allows reading and writing configuration data from/to the
+ * verified storage and copying to/from the signed file storing the same data.
+ */
+interface DrupalConfigVerifiedStorageInterface {
+
+  /**
+   * Constructs a verified storage manipulation class.
+   *
+   * @param $name
+   *   Lowercase string, the name for the configuration data.
+   */
+  function __construct($name);
+
+  /**
+   * Reads the configuration data from the verified storage.
+   */
+  function read();
+
+  /**
+   * Copies the configuration data from the verified storage into a file.
+   */
+  function copyToFile();
+
+  /**
+   * Copies the configuration data from the file into the verified storage.
+   */
+  function copyFromFile();
+
+  /**
+   * Deletes the configuration data file.
+   */
+  function deleteFile();
+
+  /**
+   * Checks whether the file and the verified storage is in sync.
+   *
+   * @return
+   *   TRUE if the file and the verified storage contains the same data, FALSE
+   *   if not.
+   */
+  function isOutOfSync();
+
+  /**
+   * Writes the configuration data into the active storage and the file.
+   *
+   * @param $data
+   *   The configuration data to write.
+   */
+  function write($data);
+
+  /**
+   * Writes the configuration data into the active storage but not the file.
+   *
+   * Use this function if you need to make temporary changes to your
+   * configuration.
+   *
+   * @param $data
+   *   The configuration data to write into active storage.
+   */
+  function writeToActive($data);
+
+  /**
+   * Writes the configuration data into the file.
+   *
+   * @param $data
+   *   The configuration data to write into the file.
+   */
+  function writeToFile($data);
+
+  /**
+   * Gets names starting with this prefix.
+   *
+   * @param $prefix
+   *   @todo
+   */
+  static function getNamesWithPrefix($prefix);
+}
diff --git a/core/lib/Drupal/Core/Config/DrupalVerifiedStorageSQL.php b/core/lib/Drupal/Core/Config/DrupalVerifiedStorageSQL.php
new file mode 100644
index 0000000000000000000000000000000000000000..97d499a555f8a481be113b36593a243f96f83703
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/DrupalVerifiedStorageSQL.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace Drupal\Core\Config;
+
+use Drupal\Core\Config\DrupalConfigVerifiedStorage;
+use Exception;
+
+/**
+ * Represents an SQL-based configuration storage object.
+ */
+class DrupalVerifiedStorageSQL extends DrupalConfigVerifiedStorage {
+
+  /**
+   * Overrides DrupalConfigVerifiedStorage::read().
+   */
+  public function read() {
+    // There are situations, like in the installer, where we may attempt a
+    // read without actually having the database available. In this case,
+    // catch the exception and just return an empty array so the caller can
+    // handle it if need be.
+    try {
+      return db_query('SELECT data FROM {config} WHERE name = :name', array(':name' => $this->name))->fetchField();
+    } catch (Exception $e) {
+      return array();
+    }
+  }
+
+  /**
+   * Implements DrupalConfigVerifiedStorageInterface::writeToActive().
+   */
+  public function writeToActive($data) {
+    return db_merge('config')
+      ->key(array('name' => $this->name))
+      ->fields(array('data' => $data))
+      ->execute();
+  }
+
+  /**
+   * @todo
+   */
+  public function deleteFromActive() {
+    db_delete('config')
+      ->condition('name', $this->name)
+      ->execute();
+  }
+
+  /**
+   * Implements DrupalConfigVerifiedStorageInterface::getNamesWithPrefix().
+   */
+  static public function getNamesWithPrefix($prefix = '') {
+    return db_query('SELECT name FROM {config} WHERE name LIKE :name', array(':name' => db_like($prefix) . '%'))->fetchCol();
+  }
+}
diff --git a/core/lib/Drupal/Core/Config/SignedFileStorage.php b/core/lib/Drupal/Core/Config/SignedFileStorage.php
new file mode 100644
index 0000000000000000000000000000000000000000..c66902963d6d550342e36194a0312ca5e54e4f02
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/SignedFileStorage.php
@@ -0,0 +1,143 @@
+<?php
+
+namespace Drupal\Core\Config;
+
+/**
+ * Represents the signed file storage interface.
+ *
+ * Classes implementing this interface allow reading and writing configuration
+ * data to and from disk, while automatically managing and verifying
+ * cryptographic signatures.
+ */
+class SignedFileStorage {
+
+  /**
+   * Constructs a SignedFileStorage object.
+   *
+   * @param string $name
+   *   The name for the configuration data. Should be lowercase.
+   */
+  public function __construct($name) {
+    $this->name = $name;
+  }
+
+  /**
+   * Reads and returns a signed file and its signature.
+   *
+   * @return
+   *   An array with "signature" and "data" keys.
+   *
+   * @throws
+   *   Exception
+   */
+  protected function readWithSignature() {
+    $content = file_get_contents($this->getFilePath());
+    if ($content === FALSE) {
+      throw new \Exception('Read file is invalid.');
+    }
+    $signature = file_get_contents($this->getFilePath() . '.sig');
+    if ($signature === FALSE) {
+      throw new \Exception('Signature file is invalid.');
+    }
+    return array('data' => $content, 'signature' => $signature);
+  }
+
+  /**
+   * Checks whether the XML configuration file already exists on disk.
+   *
+   * @return
+   *   @todo
+   */
+  protected function exists() {
+    return file_exists($this->getFilePath());
+  }
+
+  /**
+   * Returns the path to the XML configuration file.
+   *
+   * @return
+   *   @todo
+   */
+  public function getFilePath() {
+    return config_get_config_directory() . '/' . $this->name  . '.xml';
+  }
+
+  /**
+   * Recreates the signature for the file.
+   */
+  public function resign() {
+    if ($this->exists()) {
+      $parts = $this->readWithSignature();
+      $this->write($parts['data']);
+    }
+  }
+
+  /**
+   * Cryptographically verifies the integrity of the configuration file.
+   *
+   * @param $contentOnSuccess
+   *   Whether or not to return the contents of the verified configuration file.
+   *
+   * @return mixed
+   *   If $contentOnSuccess was TRUE, returns the contents of the verified
+   *   configuration file; otherwise returns TRUE on success. Always returns
+   *   FALSE if the configuration file was not successfully verified.
+   */
+  public function verify($contentOnSuccess = FALSE) {
+    if ($this->exists()) {
+      $split = $this->readWithSignature();
+      $expected_signature = config_sign_data($split['data']);
+      if ($expected_signature === $split['signature']) {
+        if ($contentOnSuccess) {
+          return $split['data'];
+        }
+        return TRUE;
+      }
+    }
+    return FALSE;
+  }
+
+  /**
+   * Writes the contents of the configuration file to disk.
+   *
+   * @param $data
+   *   The data to be written to the file.
+   *
+   * @throws
+   *   Exception
+   */
+  public function write($data) {
+    $signature = config_sign_data($data);
+    if (!file_put_contents($this->getFilePath(), $data)) {
+      throw new \Exception('Failed to write configuration file: ' . $this->getFilePath());
+    }
+    if (!file_put_contents($this->getFilePath() . '.sig', $signature)) {
+      throw new \Exception('Failed to write signature file: ' . $this->getFilePath());
+    }
+  }
+
+  /**
+   * Returns the contents of the configuration file.
+   *
+   * @return
+   *   @todo
+   */
+  public function read() {
+    if ($this->exists()) {
+      $verification = $this->verify(TRUE);
+      if ($verification === FALSE) {
+        throw new \Exception('Invalid signature in file header.');
+      }
+      return $verification;
+    }
+  }
+
+  /**
+   * Deletes a configuration file.
+   */
+  public function delete() {
+    // Needs error handling and etc.
+    @drupal_unlink($this->getFilePath());
+    @drupal_unlink($this->getFilePath() . '.sig');
+  }
+}
diff --git a/core/modules/block/config/block.performance.xml b/core/modules/block/config/block.performance.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ff3f7e1c7c3a83815ed44b2970414701efcc7b7c
--- /dev/null
+++ b/core/modules/block/config/block.performance.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<config>
+  <block_cache>0</block_cache>
+</config>
diff --git a/core/modules/color/color.test b/core/modules/color/color.test
index 06e4cb94d4212e4fce7c657a973e188d6e506cc5..616d19a76d506a104d2f9e2266d3a26acef4827f 100644
--- a/core/modules/color/color.test
+++ b/core/modules/color/color.test
@@ -92,7 +92,9 @@ class ColorTestCase extends DrupalWebTestCase {
     $this->assertTrue(strpos($stylesheet_content, 'color: ' . $test_values['scheme_color']) !== FALSE, 'Make sure the color we changed is in the color stylesheet. (' . $theme . ')');
 
     // Test with aggregated CSS turned on.
-    variable_set('preprocess_css', 1);
+    $config = config('system.performance');
+    $config->set('preprocess_css', 1);
+    $config->save();
     $this->drupalGet('<front>');
     $stylesheets = variable_get('drupal_css_cache_files', array());
     $stylesheet_content = '';
@@ -100,7 +102,8 @@ class ColorTestCase extends DrupalWebTestCase {
       $stylesheet_content .= join("\n", file(drupal_realpath($uri)));
     }
     $this->assertTrue(strpos($stylesheet_content, 'public://') === FALSE, 'Make sure the color paths have been translated to local paths. (' . $theme . ')');
-    variable_set('preprocess_css', 0);
+    $config->set('preprocess_css', 0);
+    $config->save();
   }
 
   /**
diff --git a/core/modules/config/config.info b/core/modules/config/config.info
new file mode 100644
index 0000000000000000000000000000000000000000..643a3fc689dc01c0d849f42a87629eb049798f70
--- /dev/null
+++ b/core/modules/config/config.info
@@ -0,0 +1,5 @@
+name = Configuration manager
+package = Core
+version = VERSION
+core = 8.x
+files[] = config.test
diff --git a/core/modules/config/config.module b/core/modules/config/config.module
new file mode 100644
index 0000000000000000000000000000000000000000..b3d9bbc7f3711e882119cd6b3af051245d859d04
--- /dev/null
+++ b/core/modules/config/config.module
@@ -0,0 +1 @@
+<?php
diff --git a/core/modules/config/config.test b/core/modules/config/config.test
new file mode 100644
index 0000000000000000000000000000000000000000..395a3a99c34bbb8da3560581c70310b9ba044993
--- /dev/null
+++ b/core/modules/config/config.test
@@ -0,0 +1,270 @@
+<?php
+
+/**
+ * @file
+ * Tests for the Configuration module.
+ */
+
+use Drupal\Core\Config\SignedFileStorage;
+
+/**
+ * Tests the secure file writer.
+ */
+class ConfigFileSecurityTestCase extends DrupalWebTestCase {
+  protected $profile = 'testing';
+
+  protected $filename = 'foo.bar';
+
+  protected $testContent = 'Good morning, Denver!';
+
+  public static function getInfo() {
+    return array(
+      'name' => 'File security',
+      'description' => 'Tests security of saved configuration files.',
+      'group' => 'Configuration',
+    );
+  }
+
+  /**
+   * Tests that a file written by this system has a valid signature.
+   */
+  function testFileVerify() {
+    $file = new SignedFileStorage($this->filename);
+    $file->write($this->testContent);
+
+    $this->assertTrue($file->verify(), 'A file verifies after being written.');
+
+    unset($file);
+
+    // Load the file again, so that there is no stale data from the old object.
+    $file = new SignedFileStorage($this->filename);
+    $this->assertTrue($file->verify(), 'A file verifies after being written and reloaded.');
+  }
+
+  /**
+   * Tests that a file written by this system can be successfully read back.
+   */
+  function testFilePersist() {
+    $file = new SignedFileStorage($this->filename);
+    $file->write($this->testContent);
+
+    unset($file);
+
+    // Reading should throw an exception in case of bad validation.
+    // Note that if any other exception is thrown, we let the test system
+    // handle catching and reporting it.
+    try {
+      $file = new SignedFileStorage($this->filename);
+      $saved_content = $file->read();
+
+      $this->assertEqual($saved_content, $this->testContent, 'A file can be read back successfully.');
+    }
+    catch (Exception $e) {
+      $this->fail('File failed verification when being read.');
+    }
+  }
+
+  /**
+   * Tests that a file fails validation if it's been monkeyed with.
+   */
+  function testFileNotVerify() {
+    $file = new SignedFileStorage($this->filename);
+    $file->write($this->testContent);
+
+    // Manually overwrite the body of the secure file. Note that we skip the
+    // first line, which is reserved for the signature and such, to overwrite
+    // just the payload.
+    $raw_file = new SplFileObject($file->getFilePath(), 'a+');
+    $raw_file->fwrite('Good morning, Detroit!');
+    $raw_file->fflush();
+    unset($raw_file);
+
+    unset($file);
+
+    $file = new SignedFileStorage($this->filename);
+    $this->assertFalse($file->verify(), 'Corrupted file does not verify.');
+  }
+}
+
+/**
+ * Tests reading and writing file contents.
+ */
+class ConfigFileContentTestCase extends DrupalWebTestCase {
+  protected $profile = 'testing';
+
+  protected $fileExtension = 'xml';
+
+  public static function getInfo() {
+    return array(
+      'name' => 'File content',
+      'description' => 'Tests reading and writing of configuration files.',
+      'group' => 'Configuration',
+    );
+  }
+
+  /**
+   * Tests setting, writing, and reading of a configuration setting.
+   */
+  function testReadWriteConfig() {
+    $config_dir = config_get_config_directory();
+    $name = 'foo.bar';
+    $key = 'foo';
+    $value = 'bar';
+    $nested_key = 'biff.bang';
+    $nested_value = 'pow';
+    $array_key = 'array';
+    $array_value = array(
+      'foo' => 'bar',
+      'biff' => array(
+        'bang' => 'pow',
+      )
+    );
+    $casting_array_key = 'casting_array';
+    $casting_array_false_value_key = 'casting_array.cast.false';
+    $casting_array_value = array(
+      'cast' => array(
+        'false' => FALSE,
+      )
+    );
+    $nested_array_key = 'nested.array';
+    $true_key = 'true';
+    $false_key = 'false';
+
+    // Attempt to read non-existing configuration.
+    $config = config($name);
+
+    // Verify an configuration object is returned.
+//    $this->assertEqual($config->name, $name);
+    $this->assertTrue($config, t('Config object created.'));
+
+    // Verify the configuration object is empty.
+    $this->assertEqual($config->get(), array(), t('New config object is empty.'));
+
+    // Verify nothing was saved.
+    $db_config = db_query('SELECT * FROM {config} WHERE name = :name', array(':name' => $name))->fetch();
+    $this->assertIdentical($db_config, FALSE, t('Active store does not have a record for %name', array('%name' => $name)));
+    $this->assertFalse(file_exists($config_dir . '/' . $name . '.' . $this->fileExtension), 'Configuration file does not exist.');
+
+    // Add a top level value
+    $config = config($name);
+    $config->set($key, $value);
+
+    // Add a nested value
+    $config->set($nested_key, $nested_value);
+
+    // Add an array
+    $config->set($array_key, $array_value);
+
+    // Add a nested array
+    $config->set($nested_array_key, $array_value);
+
+    // Add a boolean false value. Should get cast to 0
+    $config->set($false_key, FALSE);
+
+    // Add a boolean true value. Should get cast to 1
+    $config->set($true_key, TRUE);
+
+    // Add an array with a nested boolean false that should get cast to 0.
+    $config->set($casting_array_key, $casting_array_value);
+    $config->save();
+
+    // Verify the database entry exists.
+    $db_config = db_query('SELECT * FROM {config} WHERE name = :name', array(':name' => $name))->fetch();
+    $this->assertEqual($db_config->name, $name, t('After saving configuration, active store has a record for %name', array('%name' => $name)));
+
+    // Verify the file exists.
+    $this->assertTrue(file_exists($config_dir . '/' . $name . '.' . $this->fileExtension), t('After saving configuration, config file exists.'));
+
+    // Read top level value
+    $config = config($name);
+//    $this->assertEqual($config->name, $name);
+    $this->assertTrue($config, 'Config object created.');
+    $this->assertEqual($config->get($key), 'bar', t('Top level configuration value found.'));
+
+    // Read nested value
+    $this->assertEqual($config->get($nested_key), $nested_value, t('Nested configuration value found.'));
+
+    // Read array
+    $this->assertEqual($config->get($array_key), $array_value, t('Top level array configuration value found.'));
+
+    // Read nested array
+    $this->assertEqual($config->get($nested_array_key), $array_value, t('Nested array configuration value found.'));
+
+    // Read a top level value that doesn't exist
+    $this->assertNull($config->get('i_dont_exist'), t('Non-existent top level value returned NULL.'));
+
+    // Read a nested value that doesn't exist
+    $this->assertNull($config->get('i.dont.exist'), t('Non-existent nested value returned NULL.'));
+
+    // Read false value
+    $this->assertEqual($config->get($false_key), '0', t('Boolean FALSE value returned the string \'0\'.'));
+
+    // Read true value
+    $this->assertEqual($config->get($true_key), '1', t('Boolean TRUE value returned the string \'1\'.'));
+
+    // Read false that had been nested in an array value
+    $this->assertEqual($config->get($casting_array_false_value_key), '0', t('Nested boolean FALSE value returned the string \'0\'.'));
+
+    // Unset a top level value
+    $config->clear($key);
+
+    // Unset a nested value
+    $config->clear($nested_key);
+    $config->save();
+    $config = config($name);
+
+    // Read unset top level value
+    $this->assertNull($config->get($key), t('Top level value unset.'));
+
+    // Read unset nested value
+    $this->assertNull($config->get($nested_key), t('Nested value unset.'));
+
+    // Create two new configuration files to test listing
+    $config = config('foo.baz');
+    $config->set($key, $value);
+    $config->save();
+
+    // Test chained set()->save()
+    $chained_name = 'biff.bang';
+    $config = config($chained_name);
+    $config->set($key, $value)->save();
+
+    // Verify the database entry exists from a chained save.
+    $db_config = db_query('SELECT * FROM {config} WHERE name = :name', array(':name' => $chained_name))->fetch();
+    $this->assertEqual($db_config->name, $chained_name, t('After saving configuration by chaining through set(), active store has a record for %name', array('%name' => $chained_name)));
+
+    // Verify the file exists from a chained save.
+    $this->assertTrue(file_exists($config_dir . '/' . $chained_name . '.' . $this->fileExtension), t('After saving configuration by chaining through set(), config file exists.'));
+
+    // Get file listing for all files starting with 'foo'. Should return
+    // two elements.
+    $files = config_get_signed_file_storage_names_with_prefix('foo');
+    $this->assertEqual(count($files), 2, 'Two files listed with the prefix \'foo\'.');
+
+    // Get file listing for all files starting with 'biff'. Should return
+    // one element.
+    $files = config_get_signed_file_storage_names_with_prefix('biff');
+    $this->assertEqual(count($files), 1, 'One file listed with the prefix \'biff\'.');
+
+    // Get file listing for all files starting with 'foo.bar'. Should return
+    // one element.
+    $files = config_get_signed_file_storage_names_with_prefix('foo.bar');
+    $this->assertEqual(count($files), 1, 'One file listed with the prefix \'foo.bar\'.');
+
+    // Get file listing for all files starting with 'bar'. Should return
+    // an empty array.
+    $files = config_get_signed_file_storage_names_with_prefix('bar');
+    $this->assertEqual($files, array(), 'No files listed with the prefix \'bar\'.');
+
+    // Delete the configuration.
+    $config = config($name);
+    $config->delete();
+
+    // Verify the database entry no longer exists.
+    $db_config = db_query('SELECT * FROM {config} WHERE name = :name', array(':name' => $name))->fetch();
+    $this->assertIdentical($db_config, FALSE);
+    $this->assertFalse(file_exists($config_dir . '/' . $name . '.' . $this->fileExtension));
+
+    // Attempt to delete non-existing configuration.
+  }
+}
diff --git a/core/modules/image/config/image.styles.large.xml b/core/modules/image/config/image.styles.large.xml
new file mode 100644
index 0000000000000000000000000000000000000000..62448c18212ba96c3a64a66c6785d1354153cde0
--- /dev/null
+++ b/core/modules/image/config/image.styles.large.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<config>
+  <name>large</name>
+  <effects>
+    <image_scale_480_480_1>
+      <name>image_scale</name>
+      <ieid>image_scale_480_480_1</ieid>
+      <data>
+        <width>480</width>
+        <height>480</height>
+        <upscale>1</upscale>
+      </data>
+      <weight>0</weight>
+    </image_scale_480_480_1>
+  </effects>
+</config>
diff --git a/core/modules/image/config/image.styles.medium.xml b/core/modules/image/config/image.styles.medium.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d30187766ebef2af567249bc1186ecaf49296698
--- /dev/null
+++ b/core/modules/image/config/image.styles.medium.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<config>
+  <name>medium</name>
+  <effects>
+    <image_scale_220_220_1>
+      <name>image_scale</name>
+      <ieid>image_scale_220_220_1</ieid>
+      <data>
+        <width>220</width>
+        <height>220</height>
+        <upscale>1</upscale>
+      </data>
+      <weight>0</weight>
+    </image_scale_220_220_1>
+  </effects>
+</config>
diff --git a/core/modules/image/config/image.styles.thumbnail.xml b/core/modules/image/config/image.styles.thumbnail.xml
new file mode 100644
index 0000000000000000000000000000000000000000..385abe614859117f10c99dac902adfb152dc7132
--- /dev/null
+++ b/core/modules/image/config/image.styles.thumbnail.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<config>
+  <name>thumbnail</name>
+  <effects>
+    <image_scale_100_100_1>
+      <name>image_scale</name>
+      <ieid>image_scale_100_100_1</ieid>
+      <data>
+        <width>100</width>
+        <height>100</height>
+        <upscale>1</upscale>
+      </data>
+      <weight>0</weight>
+    </image_scale_100_100_1>
+  </effects>
+</config>
diff --git a/core/modules/image/image.admin.inc b/core/modules/image/image.admin.inc
index 9643841019177f1f8891f10ae4d1f3b80018b8c8..539e7560f1697663849db0dc7945ea7ba8272bfd 100644
--- a/core/modules/image/image.admin.inc
+++ b/core/modules/image/image.admin.inc
@@ -38,13 +38,6 @@ function image_style_form($form, &$form_state, $style) {
   $title = t('Edit %name style', array('%name' => $style['name']));
   drupal_set_title($title, PASS_THROUGH);
 
-  // Adjust this form for styles that must be overridden to edit.
-  $editable = (bool) ($style['storage'] & IMAGE_STORAGE_EDITABLE);
-
-  if (!$editable && empty($form_state['input'])) {
-    drupal_set_message(t('This image style is currently being provided by a module. Click the "Override defaults" button to change its settings.'), 'warning');
-  }
-
   $form_state['image_style'] = $style;
   $form['#tree'] = TRUE;
   $form['#attached']['css'][drupal_get_path('module', 'image') . '/image.admin.css'] = array();
@@ -56,27 +49,15 @@ function image_style_form($form, &$form_state, $style) {
     '#markup' => theme('image_style_preview', array('style' => $style)),
   );
 
-  // Allow the name of the style to be changed, unless this style is
-  // provided by a module's hook_default_image_styles().
-  if ($style['storage'] & IMAGE_STORAGE_MODULE) {
-    $form['name'] = array(
-      '#type' => 'item',
-      '#title' => t('Image style name'),
-      '#markup' => $style['name'],
-      '#description' => t('This image style is being provided by %module module and may not be renamed.', array('%module' => $style['module'])),
-    );
-  }
-  else {
-    $form['name'] = array(
-      '#type' => 'textfield',
-      '#size' => '64',
-      '#title' => t('Image style name'),
-      '#default_value' => $style['name'],
-      '#description' => t('The name is used in URLs for generated images. Use only lowercase alphanumeric characters, underscores (_), and hyphens (-).'),
-      '#element_validate' => array('image_style_name_validate'),
-      '#required' => TRUE,
-    );
-  }
+  $form['name'] = array(
+    '#type' => 'textfield',
+    '#size' => '64',
+    '#title' => t('Image style name'),
+    '#default_value' => $style['name'],
+    '#description' => t('The name is used in URLs for generated images. Use only lowercase alphanumeric characters, underscores (_), and hyphens (-).'),
+    '#element_validate' => array('image_style_name_validate'),
+    '#required' => TRUE,
+  );
 
   // Build the list of existing image effects for this image style.
   $form['effects'] = array(
@@ -95,25 +76,19 @@ function image_style_form($form, &$form_state, $style) {
       '#title' => t('Weight for @title', array('@title' => $effect['label'])),
       '#title_display' => 'invisible',
       '#default_value' => $effect['weight'],
-      '#access' => $editable,
     );
 
-    // Only attempt to display these fields for editable styles as the 'ieid'
-    // key is not set for styles defined in code.
-    if ($editable) {
-      $form['effects'][$key]['configure'] = array(
-        '#type' => 'link',
-        '#title' => t('edit'),
-        '#href' => 'admin/config/media/image-styles/edit/' . $style['name'] . '/effects/' . $effect['ieid'],
-        '#access' => $editable && isset($effect['form callback']),
-      );
-      $form['effects'][$key]['remove'] = array(
-        '#type' => 'link',
-        '#title' => t('delete'),
-        '#href' => 'admin/config/media/image-styles/edit/' . $style['name'] . '/effects/' . $effect['ieid'] . '/delete',
-        '#access' => $editable,
-      );
-    }
+    $form['effects'][$key]['configure'] = array(
+      '#type' => 'link',
+      '#title' => t('edit'),
+      '#href' => 'admin/config/media/image-styles/edit/' . $style['name'] . '/effects/' . $key,
+      '#access' => isset($effect['form callback']),
+    );
+    $form['effects'][$key]['remove'] = array(
+      '#type' => 'link',
+      '#title' => t('delete'),
+      '#href' => 'admin/config/media/image-styles/edit/' . $style['name'] . '/effects/' . $key . '/delete',
+    );
   }
 
   // Build the new image effect addition form and add it to the effect list.
@@ -124,7 +99,6 @@ function image_style_form($form, &$form_state, $style) {
   $form['effects']['new'] = array(
     '#tree' => FALSE,
     '#weight' => isset($form_state['input']['weight']) ? $form_state['input']['weight'] : NULL,
-    '#access' => $editable,
   );
   $form['effects']['new']['new'] = array(
     '#type' => 'select',
@@ -148,17 +122,9 @@ function image_style_form($form, &$form_state, $style) {
 
   // Show the Override or Submit button for this style.
   $form['actions'] = array('#type' => 'actions');
-  $form['actions']['override'] = array(
-    '#type' => 'submit',
-    '#value' => t('Override defaults'),
-    '#validate' => array(),
-    '#submit' => array('image_style_form_override_submit'),
-    '#access' => !$editable,
-  );
   $form['actions']['submit'] = array(
     '#type' => 'submit',
     '#value' => t('Update style'),
-    '#access' => $editable,
   );
 
   return $form;
@@ -188,43 +154,54 @@ function image_style_form_add_submit($form, &$form_state) {
   }
   // If there's no form, immediately add the image effect.
   else {
-    $effect['isid'] = $style['isid'];
-    $effect['weight'] = $form_state['values']['weight'];
-    image_effect_save($effect);
+    $effect = array(
+      'name' => $effect['name'],
+      'data' => array(),
+      'weight' => $form_state['values']['weight'],
+    );
+    image_effect_save($style['name'], $effect);
     drupal_set_message(t('The image effect was successfully applied.'));
   }
 }
 
-/**
- * Submit handler for overriding a module-defined style.
- */
-function image_style_form_override_submit($form, &$form_state) {
-  drupal_set_message(t('The %style style has been overridden, allowing you to change its settings.', array('%style' => $form_state['image_style']['name'])));
-  image_default_style_save($form_state['image_style']);
-}
-
 /**
  * Submit handler for saving an image style.
  */
 function image_style_form_submit($form, &$form_state) {
-  // Update the image style name if it has changed.
   $style = $form_state['image_style'];
-  if (isset($form_state['values']['name']) && $style['name'] != $form_state['values']['name']) {
-    $style['name'] = $form_state['values']['name'];
-  }
 
   // Update image effect weights.
   if (!empty($form_state['values']['effects'])) {
     foreach ($form_state['values']['effects'] as $ieid => $effect_data) {
       if (isset($style['effects'][$ieid])) {
-        $effect = $style['effects'][$ieid];
-        $effect['weight'] = $effect_data['weight'];
-        image_effect_save($effect);
+        $effect = array(
+          'name' => $style['effects'][$ieid]['name'],
+          'data' => $style['effects'][$ieid]['data'],
+          'weight' => $effect_data['weight'],
+          'ieid' => $ieid,
+        );
+        $style['effects'][$ieid] = $effect;
       }
     }
   }
 
+  // Update the image style name if it has changed. We also need to delete the
+  // old style, because there is no concept of rename at the moment, just
+  // create and delete.
+  // @todo The config API does not yet support the concept of a rename, but
+  //   hooks need to be able to change old style name references to the new
+  //   name, so first save the new style, then delete the old, so that the
+  //   delete function can receive the name of a fully saved style to update
+  //   references to.
+  if (isset($form_state['values']['name']) && $style['name'] != $form_state['values']['name']) {
+    $old_style = $style;
+    $style['name'] = $form_state['values']['name'];
+  }
   image_style_save($style);
+  if (isset($old_style)) {
+    image_style_delete($old_style, $style['name']);
+  }
+
   if ($form_state['values']['op'] == t('Update style')) {
     drupal_set_message(t('Changes to the style have been saved.'));
   }
@@ -273,7 +250,7 @@ function image_style_add_form_submit($form, &$form_state) {
 function image_style_name_validate($element, $form_state) {
   // Check for duplicates.
   $styles = image_styles();
-  if (isset($styles[$element['#value']]) && (!isset($form_state['image_style']['isid']) || $styles[$element['#value']]['isid'] != $form_state['image_style']['isid'])) {
+  if (isset($styles[$element['#value']]) && (!isset($form_state['image_style']['name']) || $styles[$element['#value']]['name'] != $form_state['image_style']['name'])) {
     form_set_error($element['#name'], t('The image style name %name is already in use.', array('%name' => $element['#value'])));
   }
 
@@ -323,30 +300,6 @@ function image_style_delete_form_submit($form, &$form_state) {
   $form_state['redirect'] = 'admin/config/media/image-styles';
 }
 
-/**
- * Confirmation form to revert a database style to its default.
- */
-function image_style_revert_form($form, $form_state, $style) {
-  $form_state['image_style'] = $style;
-
-  return confirm_form(
-    $form,
-    t('Revert the %style style?', array('%style' => $style['name'])),
-    'admin/config/media/image-styles',
-    t('Reverting this style will delete the customized settings and restore the defaults provided by the @module module.', array('@module' => $style['module'])),
-    t('Revert'),  t('Cancel')
-  );
-}
-
-/**
- * Submit handler to convert an overridden style to its default.
- */
-function image_style_revert_form_submit($form, &$form_state) {
-  drupal_set_message(t('The %style style has been reverted to its defaults.', array('%style' => $form_state['image_style']['name'])));
-  image_default_style_revert($form_state['image_style']);
-  $form_state['redirect'] = 'admin/config/media/image-styles';
-}
-
 /**
  * Form builder; Form for adding and editing image effects.
  *
@@ -416,12 +369,14 @@ function image_effect_form($form, &$form_state, $style, $effect) {
  * Submit handler for updating an image effect.
  */
 function image_effect_form_submit($form, &$form_state) {
-  $style = $form_state['image_style'];
-  $effect = array_merge($form_state['image_effect'], $form_state['values']);
-  $effect['isid'] = $style['isid'];
-  image_effect_save($effect);
+  $effect = array(
+    'name' => $form_state['image_effect']['name'],
+    'data' => $form_state['values']['data'],
+    'weight' => $form_state['values']['weight'],
+  );
+  image_effect_save($form_state['image_style']['name'], $effect);
   drupal_set_message(t('The image effect was successfully applied.'));
-  $form_state['redirect'] = 'admin/config/media/image-styles/edit/' . $style['name'];
+  $form_state['redirect'] = 'admin/config/media/image-styles/edit/' . $form_state['image_style']['name'];
 }
 
 /**
@@ -449,7 +404,7 @@ function image_effect_delete_form_submit($form, &$form_state) {
   $style = $form_state['image_style'];
   $effect = $form_state['image_effect'];
 
-  image_effect_delete($effect);
+  image_effect_delete($style['name'], $effect);
   drupal_set_message(t('The image effect %name has been deleted.', array('%name' => $effect['label'])));
   $form_state['redirect'] = 'admin/config/media/image-styles/edit/' . $style['name'];
 }
@@ -645,31 +600,19 @@ function image_rotate_form($data) {
 function theme_image_style_list($variables) {
   $styles = $variables['styles'];
 
-  $header = array(t('Style name'), t('Settings'), array('data' => t('Operations'), 'colspan' => 3));
+  $header = array(t('Style name'), array('data' => t('Operations'), 'colspan' => 3));
   $rows = array();
+  $link_attributes = array(
+    'attributes' => array(
+      'class' => array('image-style-link'),
+    ),
+  );
+
   foreach ($styles as $style) {
     $row = array();
     $row[] = l($style['name'], 'admin/config/media/image-styles/edit/' . $style['name']);
-    $link_attributes = array(
-      'attributes' => array(
-        'class' => array('image-style-link'),
-      ),
-    );
-    if ($style['storage'] == IMAGE_STORAGE_NORMAL) {
-      $row[] = t('Custom');
-      $row[] = l(t('edit'), 'admin/config/media/image-styles/edit/' . $style['name'], $link_attributes);
-      $row[] = l(t('delete'), 'admin/config/media/image-styles/delete/' . $style['name'], $link_attributes);
-    }
-    elseif ($style['storage'] == IMAGE_STORAGE_OVERRIDE) {
-      $row[] = t('Overridden');
-      $row[] = l(t('edit'), 'admin/config/media/image-styles/edit/' . $style['name'], $link_attributes);
-      $row[] = l(t('revert'), 'admin/config/media/image-styles/revert/' . $style['name'], $link_attributes);
-    }
-    else {
-      $row[] = t('Default');
-      $row[] = l(t('edit'), 'admin/config/media/image-styles/edit/' . $style['name'], $link_attributes);
-      $row[] = '';
-    }
+    $row[] = l(t('edit'), 'admin/config/media/image-styles/edit/' . $style['name'], $link_attributes);
+    $row[] = l(t('delete'), 'admin/config/media/image-styles/delete/' . $style['name'], $link_attributes);
     $rows[] = $row;
   }
 
@@ -694,13 +637,12 @@ function theme_image_style_list($variables) {
  */
 function theme_image_style_effects($variables) {
   $form = $variables['form'];
-
   $rows = array();
 
   foreach (element_children($form) as $key) {
     $row = array();
     $form[$key]['weight']['#attributes']['class'] = array('image-effect-order-weight');
-    if (is_numeric($key)) {
+    if ($key != 'new') {
       $summary = drupal_render($form[$key]['summary']);
       $row[] = drupal_render($form[$key]['label']) . (empty($summary) ? '' : ' ' . $summary);
       $row[] = drupal_render($form[$key]['weight']);
@@ -728,7 +670,7 @@ function theme_image_style_effects($variables) {
     array('data' => t('Operations'), 'colspan' => 2),
   );
 
-  if (count($rows) == 1 && $form['new']['#access']) {
+  if (count($rows) == 1 && (!isset($form['new']['#access']) || $form['new']['#access'])) {
     array_unshift($rows, array(array(
       'data' => t('There are currently no effects in this style. Add one by selecting an option below.'),
       'colspan' => 4,
diff --git a/core/modules/image/image.install b/core/modules/image/image.install
index 02be57ca4c5f810c6eb901d25f028839e12d068d..91349a92a29213f2636d45e1b693e2da1a6eea9c 100644
--- a/core/modules/image/image.install
+++ b/core/modules/image/image.install
@@ -22,87 +22,6 @@ function image_uninstall() {
   file_unmanaged_delete_recursive(file_default_scheme() . '://styles');
 }
 
-/**
- * Implements hook_schema().
- */
-function image_schema() {
-  $schema = array();
-
-  $schema['image_styles'] = array(
-    'description' => 'Stores configuration options for image styles.',
-    'fields' => array(
-      'isid' => array(
-        'description' => 'The primary identifier for an image style.',
-        'type' => 'serial',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-      ),
-      'name' => array(
-        'description' => 'The style name.',
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-      ),
-    ),
-    'primary key' => array('isid'),
-    'unique keys' => array(
-      'name' => array('name'),
-    ),
-  );
-
-  $schema['image_effects'] = array(
-    'description' => 'Stores configuration options for image effects.',
-    'fields' => array(
-      'ieid' => array(
-        'description' => 'The primary identifier for an image effect.',
-        'type' => 'serial',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-      ),
-      'isid' => array(
-        'description' => 'The {image_styles}.isid for an image style.',
-        'type' => 'int',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'weight' => array(
-        'description' => 'The weight of the effect in the style.',
-        'type' => 'int',
-        'unsigned' => FALSE,
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'name' => array(
-        'description' => 'The unique name of the effect to be executed.',
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-      ),
-      'data' => array(
-        'description' => 'The configuration data for the effect.',
-        'type' => 'blob',
-        'not null' => TRUE,
-        'size' => 'big',
-        'serialize' => TRUE,
-      ),
-    ),
-    'primary key' => array('ieid'),
-    'indexes' => array(
-      'isid' => array('isid'),
-      'weight' => array('weight'),
-    ),
-    'foreign keys' => array(
-      'image_style' => array(
-        'table' => 'image_styles',
-        'columns' => array('isid' => 'isid'),
-      ),
-    ),
-  );
-
-  return $schema;
-}
-
 /**
  * Implements hook_field_schema().
  */
diff --git a/core/modules/image/image.module b/core/modules/image/image.module
index 0e48d155247eb21cc10ba5b928c00f7e7dea13e9..e6a9bc89063a1d4946aa1995184a1365cd1f882f 100644
--- a/core/modules/image/image.module
+++ b/core/modules/image/image.module
@@ -135,15 +135,6 @@ function image_menu() {
     'access arguments' => array('administer image styles'),
     'file' => 'image.admin.inc',
   );
-  $items['admin/config/media/image-styles/revert/%image_style'] = array(
-    'title' => 'Revert style',
-    'description' => 'Revert an image style.',
-    'load arguments' => array(NULL, (string) IMAGE_STORAGE_OVERRIDE),
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('image_style_revert_form', 5),
-    'access arguments' => array('administer image styles'),
-    'file' => 'image.admin.inc',
-  );
   $items['admin/config/media/image-styles/edit/%image_style/effects/%image_effect'] = array(
     'title' => 'Edit image effect',
     'description' => 'Edit an existing effect within a style.',
@@ -330,45 +321,6 @@ function image_file_predelete($file) {
   image_path_flush($file->uri);
 }
 
-/**
- * Implements hook_image_default_styles().
- */
-function image_image_default_styles() {
-  $styles = array();
-
-  $styles['thumbnail'] = array(
-    'effects' => array(
-      array(
-        'name' => 'image_scale',
-        'data' => array('width' => 100, 'height' => 100, 'upscale' => 1),
-        'weight' => 0,
-      ),
-    )
-  );
-
-  $styles['medium'] = array(
-    'effects' => array(
-      array(
-        'name' => 'image_scale',
-        'data' => array('width' => 220, 'height' => 220, 'upscale' => 1),
-        'weight' => 0,
-      ),
-    )
-  );
-
-  $styles['large'] = array(
-    'effects' => array(
-      array(
-        'name' => 'image_scale',
-        'data' => array('width' => 480, 'height' => 480, 'upscale' => 0),
-        'weight' => 0,
-      ),
-    )
-  );
-
-  return $styles;
-}
-
 /**
  * Implements hook_image_style_save().
  */
@@ -483,55 +435,30 @@ function image_path_flush($path) {
  * @see image_style_load()
  */
 function image_styles() {
-  $styles = &drupal_static(__FUNCTION__);
-
-  // Grab from cache or build the array.
-  if (!isset($styles)) {
-    if ($cache = cache()->get('image_styles')) {
-      $styles = $cache->data;
-    }
-    else {
+  // @todo Configuration must not be statically cached nor cache-system cached.
+  //   However, there's a drupal_alter() involved here.
+
+//  $styles = &drupal_static(__FUNCTION__);
+//
+//  // Grab from cache or build the array.
+//  if (!isset($styles)) {
+//    if ($cache = cache()->get('image_styles')) {
+//      $styles = $cache->data;
+//    }
+//    else {
       $styles = array();
 
-      // Select the module-defined styles.
-      foreach (module_implements('image_default_styles') as $module) {
-        $module_styles = module_invoke($module, 'image_default_styles');
-        foreach ($module_styles as $style_name => $style) {
-          $style['name'] = $style_name;
-          $style['module'] = $module;
-          $style['storage'] = IMAGE_STORAGE_DEFAULT;
-          foreach ($style['effects'] as $key => $effect) {
-            $definition = image_effect_definition_load($effect['name']);
-            $effect = array_merge($definition, $effect);
-            $style['effects'][$key] = $effect;
-          }
-          $styles[$style_name] = $style;
-        }
-      }
-
-      // Select all the user-defined styles.
-      $user_styles = db_select('image_styles', NULL, array('fetch' => PDO::FETCH_ASSOC))
-        ->fields('image_styles')
-        ->orderBy('name')
-        ->execute()
-        ->fetchAllAssoc('name', PDO::FETCH_ASSOC);
-
-      // Allow the user styles to override the module styles.
-      foreach ($user_styles as $style_name => $style) {
-        $style['module'] = NULL;
-        $style['storage'] = IMAGE_STORAGE_NORMAL;
-        $style['effects'] = image_style_effects($style);
-        if (isset($styles[$style_name]['module'])) {
-          $style['module'] = $styles[$style_name]['module'];
-          $style['storage'] = IMAGE_STORAGE_OVERRIDE;
-        }
-        $styles[$style_name] = $style;
+      // Select the styles we have configured.
+      $configured_styles = config_get_verified_storage_names_with_prefix('image.styles');
+      foreach ($configured_styles as $config_name) {
+        // @todo Allow to retrieve the name without prefix only.
+        $style = image_style_load(str_replace('image.styles.', '', $config_name));
+        $styles[$style['name']] = $style;
       }
-
       drupal_alter('image_styles', $styles);
-      cache()->set('image_styles', $styles);
-    }
-  }
+//      cache()->set('image_styles', $styles);
+//    }
+//  }
 
   return $styles;
 }
@@ -541,45 +468,31 @@ function image_styles() {
  *
  * @param $name
  *   The name of the style.
- * @param $isid
- *   Optional. The numeric id of a style if the name is not known.
- * @param $include
- *   If set, this loader will restrict to a specific type of image style, may be
- *   one of the defined Image style storage constants.
  * @return
  *   An image style array containing the following keys:
- *   - "isid": The unique image style ID.
  *   - "name": The unique image style name.
  *   - "effects": An array of image effects within this image style.
- *   If the image style name or ID is not valid, an empty array is returned.
+ *   If the image style name is not valid, an empty array is returned.
  * @see image_effect_load()
  */
-function image_style_load($name = NULL, $isid = NULL, $include = NULL) {
-  $styles = image_styles();
-
-  // If retrieving by name.
-  if (isset($name) && isset($styles[$name])) {
-    $style = $styles[$name];
-  }
+function image_style_load($name) {
+  $style = config('image.styles.' . $name)->get();
 
-  // If retrieving by image style id.
-  if (!isset($name) && isset($isid)) {
-    foreach ($styles as $name => $database_style) {
-      if (isset($database_style['isid']) && $database_style['isid'] == $isid) {
-        $style = $database_style;
-        break;
-      }
-    }
+  // @todo Requires a more reliable + generic method to check for whether the
+  //   configuration object exists.
+  if (!isset($style['name'])) {
+    return FALSE;
   }
 
-  // Restrict to the specific type of flag. This bitwise operation basically
-  // states "if the storage is X, then allow".
-  if (isset($style) && (!isset($include) || ($style['storage'] & (int) $include))) {
-    return $style;
+  foreach ($style['effects'] as $ieid => $effect) {
+    $definition = image_effect_definition_load($effect['name']);
+    $effect = array_merge($definition, $effect);
+    $style['effects'][$ieid] = $effect;
   }
+  // Sort effects by weight.
+  uasort($style['effects'], 'drupal_sort_weight');
 
-  // Otherwise the style was not found.
-  return FALSE;
+  return $style;
 }
 
 /**
@@ -588,22 +501,21 @@ function image_style_load($name = NULL, $isid = NULL, $include = NULL) {
  * @param style
  *   An image style array.
  * @return
- *   An image style array. In the case of a new style, 'isid' will be populated.
+ *   An image style array.
  */
 function image_style_save($style) {
-  if (isset($style['isid']) && is_numeric($style['isid'])) {
-    // Load the existing style to make sure we account for renamed styles.
-    $old_style = image_style_load(NULL, $style['isid']);
-    image_style_flush($old_style);
-    drupal_write_record('image_styles', $style, 'isid');
-    if ($old_style['name'] != $style['name']) {
-      $style['old_name'] = $old_style['name'];
-    }
+  $config = config('image.styles.' . $style['name']);
+  $config->set('name', $style['name']);
+  if (isset($style['effects'])) {
+    $config->set('effects', $style['effects']);
   }
   else {
-    drupal_write_record('image_styles', $style);
-    $style['is_new'] = TRUE;
+    $config->set('effects', array());
   }
+  $config->save();
+  // @todo is_new must only be set when the configuration object did not exist
+  //   yet.
+  $style['is_new'] = TRUE;
 
   // Let other modules update as necessary on save.
   module_invoke_all('image_style_save', $style);
@@ -628,8 +540,8 @@ function image_style_save($style) {
 function image_style_delete($style, $replacement_style_name = '') {
   image_style_flush($style);
 
-  db_delete('image_effects')->condition('isid', $style['isid'])->execute();
-  db_delete('image_styles')->condition('isid', $style['isid'])->execute();
+  $config = config('image.styles.' . $style['name']);
+  $config->delete();
 
   // Let other modules update as necessary on save.
   $style['old_name'] = $style['name'];
@@ -648,17 +560,11 @@ function image_style_delete($style, $replacement_style_name = '') {
  *   An array of image effects associated with specified image style in the
  *   format array('isid' => array()), or an empty array if the specified style
  *   has no effects.
+ *
+ * @todo Remove this function; it's entirely obsolete.
  */
 function image_style_effects($style) {
-  $effects = image_effects();
-  $style_effects = array();
-  foreach ($effects as $effect) {
-    if ($style['isid'] == $effect['isid']) {
-      $style_effects[$effect['ieid']] = $effect;
-    }
-  }
-
-  return $style_effects;
+  return $style['effects'];
 }
 
 /**
@@ -854,11 +760,11 @@ function image_style_flush($style) {
   // Let other modules update as necessary on flush.
   module_invoke_all('image_style_flush', $style);
 
-  // Clear image style and effect caches.
-  cache()->delete('image_styles');
-  cache()->deletePrefix('image_effects:');
-  drupal_static_reset('image_styles');
-  drupal_static_reset('image_effects');
+//  // Clear image style and effect caches.
+//  cache()->delete('image_styles');
+//  cache()->deletePrefix('image_effects:');
+//  drupal_static_reset('image_styles');
+//  drupal_static_reset('image_effects');
 
   // Clear field caches so that formatters may be added for this style.
   field_info_cache_clear();
@@ -876,15 +782,15 @@ function image_style_flush($style) {
  *
  * @param $style_name
  *   The name of the style to be used with this image.
- * @param $uri
+ * @param $path
  *   The path to the image.
  * @return
  *   The absolute URL where a style image can be downloaded, suitable for use
  *   in an <img> tag. Requesting the URL will cause the image to be created.
  * @see image_style_deliver()
  */
-function image_style_url($style_name, $uri) {
-  $uri = image_style_path($style_name, $uri);
+function image_style_url($style_name, $path) {
+  $uri = image_style_path($style_name, $path);
 
   // If not using clean URLs, the image derivative callback is only available
   // with the query string. If the file does not exist, use url() to ensure
@@ -924,44 +830,6 @@ function image_style_path($style_name, $uri) {
   return $scheme . '://styles/' . $style_name . '/' . $scheme . '/' . $path;
 }
 
-/**
- * Save a default image style to the database.
- *
- * @param style
- *   An image style array provided by a module.
- * @return
- *   An image style array. The returned style array will include the new 'isid'
- *   assigned to the style.
- */
-function image_default_style_save($style) {
-  $style = image_style_save($style);
-  $effects = array();
-  foreach ($style['effects'] as $effect) {
-    $effect['isid'] = $style['isid'];
-    $effect = image_effect_save($effect);
-    $effects[$effect['ieid']] = $effect;
-  }
-  $style['effects'] = $effects;
-  return $style;
-}
-
-/**
- * Revert the changes made by users to a default image style.
- *
- * @param style
- *   An image style array.
- * @return
- *   Boolean TRUE if the operation succeeded.
- */
-function image_default_style_revert($style) {
-  image_style_flush($style);
-
-  db_delete('image_effects')->condition('isid', $style['isid'])->execute();
-  db_delete('image_styles')->condition('isid', $style['isid'])->execute();
-
-  return TRUE;
-}
-
 /**
  * Pull in image effects exposed by modules implementing hook_image_effect_info().
  *
@@ -1015,8 +883,6 @@ function image_effect_definitions() {
  *
  * @param $effect
  *   The name of the effect definition to load.
- * @param $style
- *   An image style array to which this effect will be added.
  * @return
  *   An array containing the image effect definition with the following keys:
  *   - "effect": The unique name for the effect being performed. Usually prefixed
@@ -1028,18 +894,8 @@ function image_effect_definitions() {
  *   - "summary": (optional) The name of a theme function that will display a
  *     one-line summary of the effect. Does not include the "theme_" prefix.
  */
-function image_effect_definition_load($effect, $style_name = NULL) {
+function image_effect_definition_load($effect) {
   $definitions = image_effect_definitions();
-
-  // If a style is specified, do not allow loading of default style
-  // effects.
-  if (isset($style_name)) {
-    $style = image_style_load($style_name, NULL);
-    if ($style['storage'] == IMAGE_STORAGE_DEFAULT) {
-      return FALSE;
-    }
-  }
-
   return isset($definitions[$effect]) ? $definitions[$effect] : FALSE;
 }
 
@@ -1049,6 +905,8 @@ function image_effect_definition_load($effect, $style_name = NULL) {
  * @return
  *   An array of all image effects.
  * @see image_effect_load()
+ *
+ * @todo Remove after moving/resolving the todo.
  */
 function image_effects() {
   $effects = &drupal_static(__FUNCTION__);
@@ -1057,6 +915,9 @@ function image_effects() {
     $effects = array();
 
     // Add database image effects.
+    // @todo Strictly speaking, this is obsolete. However, it demonstrates a
+    //   use-case for retrieving/listing configuration objects using a wildcard
+    //   within the name (instead of only the suffix).
     $result = db_select('image_effects', NULL, array('fetch' => PDO::FETCH_ASSOC))
       ->fields('image_effects')
       ->orderBy('image_effects.weight', 'ASC')
@@ -1082,13 +943,10 @@ function image_effects() {
  *   The image effect ID.
  * @param $style_name
  *   The image style name.
- * @param $include
- *   If set, this loader will restrict to a specific type of image style, may be
- *   one of the defined Image style storage constants.
+ *
  * @return
  *   An image effect array, consisting of the following keys:
  *   - "ieid": The unique image effect ID.
- *   - "isid": The unique image style ID that contains this image effect.
  *   - "weight": The weight of this image effect within the image style.
  *   - "name": The name of the effect definition that powers this image effect.
  *   - "data": An array of configuration options for this image effect.
@@ -1098,9 +956,20 @@ function image_effects() {
  * @see image_style_load()
  * @see image_effect_definition_load()
  */
-function image_effect_load($ieid, $style_name, $include = NULL) {
-  if (($style = image_style_load($style_name, NULL, $include)) && isset($style['effects'][$ieid])) {
-    return $style['effects'][$ieid];
+function image_effect_load($ieid, $style_name) {
+  if (($style = image_style_load($style_name)) && isset($style['effects'][$ieid])) {
+    $effect = $style['effects'][$ieid];
+    $definition = image_effect_definition_load($effect['name']);
+    $effect = array_merge($definition, $effect);
+    // @todo The effect's key name within the style is unknown. It *should* be
+    //   identical to the ieid, but that is in no way guaranteed. And of course,
+    //   the ieid key *within* the effect is senseless duplication in the first
+    //   place. This problem can be eliminated in many places, but especially
+    //   for loaded menu arguments like %image_effect, the actual router
+    //   callbacks don't have access to 'ieid' anymore (unless resorting to
+    //   dirty %index and %map tricks).
+    $effect['ieid'] = $ieid;
+    return $effect;
   }
   return FALSE;
 }
@@ -1108,19 +977,32 @@ function image_effect_load($ieid, $style_name, $include = NULL) {
 /**
  * Save an image effect.
  *
+ * @param $style_name
+ *   The image style this effect belongs to.
  * @param $effect
  *   An image effect array.
  * @return
  *   An image effect array. In the case of a new effect, 'ieid' will be set.
  */
-function image_effect_save($effect) {
-  if (!empty($effect['ieid'])) {
-    drupal_write_record('image_effects', $effect, 'ieid');
-  }
-  else {
-    drupal_write_record('image_effects', $effect);
+function image_effect_save($style_name, $effect) {
+  $config = config('image.styles.' . $style_name);
+
+  if (!isset($effect['ieid']) || empty($effect['ieid'])) {
+    // We need to generate the ieid and save the new effect.
+    // The machine name is all the elements of the data array concatenated
+    // together, delimited by underscores.
+    $effect['ieid'] = $effect['name'];
+    foreach ($effect['data'] as $key => $value) {
+      $effect['ieid'] .= '_' . $value;
+    }
+    // @todo The machine name must not use any special non-alphanumeric
+    //   characters, and may also not contain dots/periods, as that is the
+    //   config system's nested key syntax.
+    $effect['ieid'] = preg_replace('@[^a-zA-Z0-9_-]@', '', $effect['ieid']);
   }
-  $style = image_style_load(NULL, $effect['isid']);
+  $config->set('effects.' . $effect['ieid'], $effect);
+  $config->save();
+  $style = image_style_load($style_name);
   image_style_flush($style);
   return $effect;
 }
@@ -1128,12 +1010,16 @@ function image_effect_save($effect) {
 /**
  * Delete an image effect.
  *
+ * @param $style_name
+ *   The image style this effect belongs to.
  * @param $effect
  *   An image effect array.
  */
-function image_effect_delete($effect) {
-  db_delete('image_effects')->condition('ieid', $effect['ieid'])->execute();
-  $style = image_style_load(NULL, $effect['isid']);
+function image_effect_delete($style_name, $effect) {
+  $config = config('image.styles.' . $style_name);
+  $config->clear('effects.' . $effect['ieid']);
+  $config->save();
+  $style = image_style_load($style_name);
   image_style_flush($style);
 }
 
diff --git a/core/modules/image/image.test b/core/modules/image/image.test
index 4d4532cfa8ba9a9202d4e72cd1746e0e3cc02c96..7a4683b6456bbb335e91ce25ab32e2d5af86eea7 100644
--- a/core/modules/image/image.test
+++ b/core/modules/image/image.test
@@ -468,7 +468,7 @@ class ImageAdminStylesUnitTest extends ImageFieldTestCase {
 
     // Load the style by the new name with the new weights.
     drupal_static_reset('image_styles');
-    $style = image_style_load($style_name, NULL);
+    $style = image_style_load($style_name);
 
     // Confirm the new style order was saved.
     $effect_edits_order = array_reverse($effect_edits_order);
@@ -506,76 +506,6 @@ class ImageAdminStylesUnitTest extends ImageFieldTestCase {
 
   }
 
-  /**
-   * Test to override, edit, then revert a style.
-   */
-  function testDefaultStyle() {
-    // Setup a style to be created and effects to add to it.
-    $style_name = 'thumbnail';
-    $edit_path = 'admin/config/media/image-styles/edit/' . $style_name;
-    $delete_path = 'admin/config/media/image-styles/delete/' . $style_name;
-    $revert_path = 'admin/config/media/image-styles/revert/' . $style_name;
-
-    // Ensure deleting a default is not possible.
-    $this->drupalGet($delete_path);
-    $this->assertText(t('Page not found'), t('Default styles may not be deleted.'));
-
-    // Ensure that editing a default is not possible (without overriding).
-    $this->drupalGet($edit_path);
-    $this->assertNoField('edit-name', t('Default styles may not be renamed.'));
-    $this->assertNoField('edit-submit', t('Default styles may not be edited.'));
-    $this->assertNoField('edit-add', t('Default styles may not have new effects added.'));
-
-    // Create an image to make sure the default works before overriding.
-    drupal_static_reset('image_styles');
-    $style = image_style_load($style_name);
-    $image_path = $this->createSampleImage($style);
-    $this->assertEqual($this->getImageCount($style), 1, t('Image style %style image %file successfully generated.', array('%style' => $style['name'], '%file' => $image_path)));
-
-    // Verify that effects attached to a default style do not have an ieid key.
-    foreach ($style['effects'] as $effect) {
-      $this->assertFalse(isset($effect['ieid']), t('The %effect effect does not have an ieid.', array('%effect' => $effect['name'])));
-    }
-
-    // Override the default.
-    $this->drupalPost($edit_path, array(), t('Override defaults'));
-    $this->assertRaw(t('The %style style has been overridden, allowing you to change its settings.', array('%style' => $style_name)), t('Default image style may be overridden.'));
-
-    // Add sample effect to the overridden style.
-    $this->drupalPost($edit_path, array('new' => 'image_desaturate'), t('Add'));
-    drupal_static_reset('image_styles');
-    $style = image_style_load($style_name);
-
-    // Verify that effects attached to the style have an ieid now.
-    foreach ($style['effects'] as $effect) {
-      $this->assertTrue(isset($effect['ieid']), t('The %effect effect has an ieid.', array('%effect' => $effect['name'])));
-    }
-
-    // The style should now have 2 effect, the original scale provided by core
-    // and the desaturate effect we added in the override.
-    $effects = array_values($style['effects']);
-    $this->assertEqual($effects[0]['name'], 'image_scale', t('The default effect still exists in the overridden style.'));
-    $this->assertEqual($effects[1]['name'], 'image_desaturate', t('The added effect exists in the overridden style.'));
-
-    // Check that we are unable to rename an overridden style.
-    $this->drupalGet($edit_path);
-    $this->assertNoField('edit-name', t('Overridden styles may not be renamed.'));
-
-    // Create an image to ensure the override works properly.
-    $image_path = $this->createSampleImage($style);
-    $this->assertEqual($this->getImageCount($style), 1, t('Image style %style image %file successfully generated.', array('%style' => $style['name'], '%file' => $image_path)));
-
-    // Revert the image style.
-    $this->drupalPost($revert_path, array(), t('Revert'));
-    drupal_static_reset('image_styles');
-    $style = image_style_load($style_name);
-
-    // The style should now have the single effect for scale.
-    $effects = array_values($style['effects']);
-    $this->assertEqual($effects[0]['name'], 'image_scale', t('The default effect still exists in the reverted style.'));
-    $this->assertFalse(array_key_exists(1, $effects), t('The added effect has been removed in the reverted style.'));
-  }
-
   /**
    * Test deleting a style and choosing a replacement style.
    */
@@ -935,6 +865,7 @@ class ImageFieldValidateTestCase extends ImageFieldTestCase {
  * Tests that images have correct dimensions when styled.
  */
 class ImageDimensionsUnitTest extends DrupalWebTestCase {
+  protected $profile = 'testing';
 
   public static function getInfo() {
     return array(
@@ -945,7 +876,7 @@ class ImageDimensionsUnitTest extends DrupalWebTestCase {
   }
 
   function setUp() {
-    parent::setUp('image_module_test');
+    parent::setUp('rdf', 'image', 'image_module_test');
   }
 
   /**
@@ -968,6 +899,10 @@ class ImageDimensionsUnitTest extends DrupalWebTestCase {
       'width' => 40,
       'height' => 20,
     );
+    // Verify that the original image matches the hard-coded values.
+    $image_info = image_get_info($original_uri);
+    $this->assertEqual($image_info['width'], $variables['width']);
+    $this->assertEqual($image_info['height'], $variables['height']);
 
     // Scale an image that is wider than it is high.
     $effect = array(
@@ -977,19 +912,19 @@ class ImageDimensionsUnitTest extends DrupalWebTestCase {
         'height' => 90,
         'upscale' => TRUE,
       ),
-      'isid' => $style['isid'],
+      'weight' => 0,
     );
 
-    image_effect_save($effect);
+    image_effect_save('test', $effect);
     $img_tag = theme_image_style($variables);
-    $this->assertEqual($img_tag, '<img typeof="foaf:Image" src="' . $url . '" width="120" height="60" alt="" />', t('Expected img tag was found.'));
+    $this->assertEqual($img_tag, '<img typeof="foaf:Image" src="' . $url . '" width="120" height="60" alt="" />');
     $this->assertFalse(file_exists($generated_uri), t('Generated file does not exist.'));
     $this->drupalGet($url);
     $this->assertResponse(200, t('Image was generated at the URL.'));
     $this->assertTrue(file_exists($generated_uri), t('Generated file does exist after we accessed it.'));
     $image_info = image_get_info($generated_uri);
-    $this->assertEqual($image_info['width'], 120, t('Expected width was found.'));
-    $this->assertEqual($image_info['height'], 60, t('Expected height was found.'));
+    $this->assertEqual($image_info['width'], 120);
+    $this->assertEqual($image_info['height'], 60);
 
     // Rotate 90 degrees anticlockwise.
     $effect = array(
@@ -998,19 +933,19 @@ class ImageDimensionsUnitTest extends DrupalWebTestCase {
         'degrees' => -90,
         'random' => FALSE,
       ),
-      'isid' => $style['isid'],
+      'weight' => 1,
     );
 
-    image_effect_save($effect);
+    image_effect_save('test', $effect);
     $img_tag = theme_image_style($variables);
-    $this->assertEqual($img_tag, '<img typeof="foaf:Image" src="' . $url . '" width="60" height="120" alt="" />', t('Expected img tag was found.'));
+    $this->assertEqual($img_tag, '<img typeof="foaf:Image" src="' . $url . '" width="60" height="120" alt="" />');
     $this->assertFalse(file_exists($generated_uri), t('Generated file does not exist.'));
     $this->drupalGet($url);
     $this->assertResponse(200, t('Image was generated at the URL.'));
     $this->assertTrue(file_exists($generated_uri), t('Generated file does exist after we accessed it.'));
     $image_info = image_get_info($generated_uri);
-    $this->assertEqual($image_info['width'], 60, t('Expected width was found.'));
-    $this->assertEqual($image_info['height'], 120, t('Expected height was found.'));
+    $this->assertEqual($image_info['width'], 60);
+    $this->assertEqual($image_info['height'], 120);
 
     // Scale an image that is higher than it is wide (rotated by previous effect).
     $effect = array(
@@ -1020,19 +955,19 @@ class ImageDimensionsUnitTest extends DrupalWebTestCase {
         'height' => 90,
         'upscale' => TRUE,
       ),
-      'isid' => $style['isid'],
+      'weight' => 2,
     );
 
-    image_effect_save($effect);
+    image_effect_save('test', $effect);
     $img_tag = theme_image_style($variables);
-    $this->assertEqual($img_tag, '<img typeof="foaf:Image" src="' . $url . '" width="45" height="90" alt="" />', t('Expected img tag was found.'));
+    $this->assertEqual($img_tag, '<img typeof="foaf:Image" src="' . $url . '" width="45" height="90" alt="" />');
     $this->assertFalse(file_exists($generated_uri), t('Generated file does not exist.'));
     $this->drupalGet($url);
     $this->assertResponse(200, t('Image was generated at the URL.'));
     $this->assertTrue(file_exists($generated_uri), t('Generated file does exist after we accessed it.'));
     $image_info = image_get_info($generated_uri);
-    $this->assertEqual($image_info['width'], 45, t('Expected width was found.'));
-    $this->assertEqual($image_info['height'], 90, t('Expected height was found.'));
+    $this->assertEqual($image_info['width'], 45);
+    $this->assertEqual($image_info['height'], 90);
 
     // Test upscale disabled.
     $effect = array(
@@ -1042,37 +977,37 @@ class ImageDimensionsUnitTest extends DrupalWebTestCase {
         'height' => 200,
         'upscale' => FALSE,
       ),
-      'isid' => $style['isid'],
+      'weight' => 3,
     );
 
-    image_effect_save($effect);
+    image_effect_save('test', $effect);
     $img_tag = theme_image_style($variables);
-    $this->assertEqual($img_tag, '<img typeof="foaf:Image" src="' . $url . '" width="45" height="90" alt="" />', t('Expected img tag was found.'));
+    $this->assertEqual($img_tag, '<img typeof="foaf:Image" src="' . $url . '" width="45" height="90" alt="" />');
     $this->assertFalse(file_exists($generated_uri), t('Generated file does not exist.'));
     $this->drupalGet($url);
     $this->assertResponse(200, t('Image was generated at the URL.'));
     $this->assertTrue(file_exists($generated_uri), t('Generated file does exist after we accessed it.'));
     $image_info = image_get_info($generated_uri);
-    $this->assertEqual($image_info['width'], 45, t('Expected width was found.'));
-    $this->assertEqual($image_info['height'], 90, t('Expected height was found.'));
+    $this->assertEqual($image_info['width'], 45);
+    $this->assertEqual($image_info['height'], 90);
 
     // Add a desaturate effect.
     $effect = array(
       'name' => 'image_desaturate',
       'data' => array(),
-      'isid' => $style['isid'],
+      'weight' => 4,
     );
 
-    image_effect_save($effect);
+    image_effect_save('test', $effect);
     $img_tag = theme_image_style($variables);
-    $this->assertEqual($img_tag, '<img typeof="foaf:Image" src="' . $url . '" width="45" height="90" alt="" />', t('Expected img tag was found.'));
+    $this->assertEqual($img_tag, '<img typeof="foaf:Image" src="' . $url . '" width="45" height="90" alt="" />');
     $this->assertFalse(file_exists($generated_uri), t('Generated file does not exist.'));
     $this->drupalGet($url);
     $this->assertResponse(200, t('Image was generated at the URL.'));
     $this->assertTrue(file_exists($generated_uri), t('Generated file does exist after we accessed it.'));
     $image_info = image_get_info($generated_uri);
-    $this->assertEqual($image_info['width'], 45, t('Expected width was found.'));
-    $this->assertEqual($image_info['height'], 90, t('Expected height was found.'));
+    $this->assertEqual($image_info['width'], 45);
+    $this->assertEqual($image_info['height'], 90);
 
     // Add a random rotate effect.
     $effect = array(
@@ -1081,12 +1016,12 @@ class ImageDimensionsUnitTest extends DrupalWebTestCase {
         'degrees' => 180,
         'random' => TRUE,
       ),
-      'isid' => $style['isid'],
+      'weight' => 5,
     );
 
-    image_effect_save($effect);
+    image_effect_save('test', $effect);
     $img_tag = theme_image_style($variables);
-    $this->assertEqual($img_tag, '<img typeof="foaf:Image" src="' . $url . '" alt="" />', t('Expected img tag was found.'));
+    $this->assertEqual($img_tag, '<img typeof="foaf:Image" src="' . $url . '" alt="" />');
     $this->assertFalse(file_exists($generated_uri), t('Generated file does not exist.'));
     $this->drupalGet($url);
     $this->assertResponse(200, t('Image was generated at the URL.'));
@@ -1101,19 +1036,19 @@ class ImageDimensionsUnitTest extends DrupalWebTestCase {
         'height' => 30,
         'anchor' => 'center-center',
       ),
-      'isid' => $style['isid'],
+      'weight' => 6,
     );
 
-    image_effect_save($effect);
+    image_effect_save('test', $effect);
     $img_tag = theme_image_style($variables);
-    $this->assertEqual($img_tag, '<img typeof="foaf:Image" src="' . $url . '" width="30" height="30" alt="" />', t('Expected img tag was found.'));
+    $this->assertEqual($img_tag, '<img typeof="foaf:Image" src="' . $url . '" width="30" height="30" alt="" />');
     $this->assertFalse(file_exists($generated_uri), t('Generated file does not exist.'));
     $this->drupalGet($url);
     $this->assertResponse(200, t('Image was generated at the URL.'));
     $this->assertTrue(file_exists($generated_uri), t('Generated file does exist after we accessed it.'));
     $image_info = image_get_info($generated_uri);
-    $this->assertEqual($image_info['width'], 30, t('Expected width was found.'));
-    $this->assertEqual($image_info['height'], 30, t('Expected height was found.'));
+    $this->assertEqual($image_info['width'], 30);
+    $this->assertEqual($image_info['height'], 30);
 
     // Rotate to a non-multiple of 90 degrees.
     $effect = array(
@@ -1122,30 +1057,30 @@ class ImageDimensionsUnitTest extends DrupalWebTestCase {
         'degrees' => 57,
         'random' => FALSE,
       ),
-      'isid' => $style['isid'],
+      'weight' => 7,
     );
 
-    $effect = image_effect_save($effect);
+    $effect = image_effect_save('test', $effect);
     $img_tag = theme_image_style($variables);
-    $this->assertEqual($img_tag, '<img typeof="foaf:Image" src="' . $url . '" alt="" />', t('Expected img tag was found.'));
+    $this->assertEqual($img_tag, '<img typeof="foaf:Image" src="' . $url . '" alt="" />');
     $this->assertFalse(file_exists($generated_uri), t('Generated file does not exist.'));
     $this->drupalGet($url);
     $this->assertResponse(200, t('Image was generated at the URL.'));
     $this->assertTrue(file_exists($generated_uri), t('Generated file does exist after we accessed it.'));
 
-    image_effect_delete($effect);
+    image_effect_delete('test', $effect);
 
     // Ensure that an effect with no dimensions callback unsets the dimensions.
     // This ensures compatibility with 7.0 contrib modules.
     $effect = array(
       'name' => 'image_module_test_null',
       'data' => array(),
-      'isid' => $style['isid'],
+      'weight' => 8,
     );
 
-    image_effect_save($effect);
+    image_effect_save('test', $effect);
     $img_tag = theme_image_style($variables);
-    $this->assertEqual($img_tag, '<img typeof="foaf:Image" src="' . $url . '" alt="" />', t('Expected img tag was found.'));
+    $this->assertEqual($img_tag, '<img typeof="foaf:Image" src="' . $url . '" alt="" />');
   }
 }
 
diff --git a/core/modules/poll/poll.test b/core/modules/poll/poll.test
index ad63d0fee4f2db440c4e38065d021b1664723dce..9275af84b7c7dc88c08ba3a402c20a1611c5f2ad 100644
--- a/core/modules/poll/poll.test
+++ b/core/modules/poll/poll.test
@@ -496,7 +496,9 @@ class PollVoteCheckHostname extends PollTestCase {
 
     // Enable page cache to verify that the result page is not saved in the
     // cache when anonymous voting is allowed.
-    variable_set('cache', 1);
+    $config = config('system.performance');
+    $config->set('cache', 1);
+    $config->save();
 
     // Create poll.
     $title = $this->randomName();
diff --git a/core/modules/simpletest/drupal_web_test_case.php b/core/modules/simpletest/drupal_web_test_case.php
index 940915fde215af011f4e66dd21281fd6b64201ad..e8cbaadcbc3bb320c59d47e6662fa88cf186891e 100644
--- a/core/modules/simpletest/drupal_web_test_case.php
+++ b/core/modules/simpletest/drupal_web_test_case.php
@@ -1313,6 +1313,8 @@ protected function setUp() {
     // Store necessary current values before switching to prefixed database.
     $this->originalLanguage = $language_interface;
     $this->originalLanguageDefault = variable_get('language_default');
+    $this->originalConfigDirectory = $GLOBALS['config_directory_name'];
+    $this->originalConfigSignatureKey = $GLOBALS['config_signature_key'];
     $this->originalFileDirectory = variable_get('file_public_path', conf_path() . '/files');
     $this->originalProfile = drupal_get_profile();
     $clean_url_original = variable_get('clean_url', 0);
@@ -1349,6 +1351,14 @@ protected function setUp() {
     file_prepare_directory($temp_files_directory, FILE_CREATE_DIRECTORY);
     $this->generatedTestFiles = FALSE;
 
+    // Create and set a new configuration directory and signature key.
+    // The child site automatically adjusts the global $config_directory_name to
+    // a test-prefix-specific directory within the public files directory.
+    $GLOBALS['config_directory_name'] = 'simpletest/config_' . $this->databasePrefix;
+    $this->configFileDirectory = $this->originalFileDirectory . '/' . $GLOBALS['config_directory_name'];
+    file_prepare_directory($this->configFileDirectory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
+    $GLOBALS['config_signature_key'] = drupal_hash_base64(drupal_random_bytes(55));
+
     // Log fatal errors.
     ini_set('log_errors', 1);
     ini_set('error_log', $public_files_directory . '/error.log');
@@ -1571,6 +1581,10 @@ protected function tearDown() {
     // Rebuild caches.
     $this->refreshVariables();
 
+    // Reset configuration globals.
+    $GLOBALS['config_directory_name'] = $this->originalConfigDirectory;
+    $GLOBALS['config_signature_key'] = $this->originalConfigSignatureKey;
+
     // Reset language.
     $language_interface = $this->originalLanguage;
     if ($this->originalLanguageDefault) {
diff --git a/core/modules/simpletest/tests/bootstrap.test b/core/modules/simpletest/tests/bootstrap.test
index 13fdf07d800b42010c55645e7c3ef6ca09fb399a..fee8fcc0dd1299d1b1f23a1324035befcd3b6707 100644
--- a/core/modules/simpletest/tests/bootstrap.test
+++ b/core/modules/simpletest/tests/bootstrap.test
@@ -116,7 +116,9 @@ class BootstrapPageCacheTestCase extends DrupalWebTestCase {
    * Test support for requests containing If-Modified-Since and If-None-Match headers.
    */
   function testConditionalRequests() {
-    variable_set('cache', 1);
+    $config = config('system.performance');
+    $config->set('cache', 1);
+    $config->save();
 
     // Fill the cache.
     $this->drupalGet('');
@@ -154,7 +156,9 @@ class BootstrapPageCacheTestCase extends DrupalWebTestCase {
    * Test cache headers.
    */
   function testPageCache() {
-    variable_set('cache', 1);
+    $config = config('system.performance');
+    $config->set('cache', 1);
+    $config->save();
 
     // Fill the cache.
     $this->drupalGet('system-test/set-header', array('query' => array('name' => 'Foo', 'value' => 'bar')));
@@ -198,7 +202,9 @@ class BootstrapPageCacheTestCase extends DrupalWebTestCase {
    * mod_deflate Apache module.
    */
   function testPageCompression() {
-    variable_set('cache', 1);
+    $config = config('system.performance');
+    $config->set('cache', 1);
+    $config->save();
 
     // Fill the cache and verify that output is compressed.
     $this->drupalGet('', array(), array('Accept-Encoding: gzip,deflate'));
@@ -291,14 +297,18 @@ class HookBootExitTestCase extends DrupalWebTestCase {
    */
   function testHookBootExit() {
     // Test with cache disabled. Boot and exit should always fire.
-    variable_set('cache', 0);
+    $config = config('system.performance');
+    $config->set('cache', 0);
+    $config->save();
+
     $this->drupalGet('');
     $calls = 1;
     $this->assertEqual(db_query('SELECT COUNT(*) FROM {watchdog} WHERE type = :type AND message = :message', array(':type' => 'system_test', ':message' => 'hook_boot'))->fetchField(), $calls, t('hook_boot called with disabled cache.'));
     $this->assertEqual(db_query('SELECT COUNT(*) FROM {watchdog} WHERE type = :type AND message = :message', array(':type' => 'system_test', ':message' => 'hook_exit'))->fetchField(), $calls, t('hook_exit called with disabled cache.'));
 
     // Test with normal cache. Boot and exit should be called.
-    variable_set('cache', 1);
+    $config->set('cache', 1);
+    $config->save();
     $this->drupalGet('');
     $calls++;
     $this->assertEqual(db_query('SELECT COUNT(*) FROM {watchdog} WHERE type = :type AND message = :message', array(':type' => 'system_test', ':message' => 'hook_boot'))->fetchField(), $calls, t('hook_boot called with normal cache.'));
diff --git a/core/modules/simpletest/tests/cache.test b/core/modules/simpletest/tests/cache.test
index bca4e250b3790e79ae8937d32c15423ea97bcc69..81f237725631d3776ae11cde5ede5a6b8db8b906 100644
--- a/core/modules/simpletest/tests/cache.test
+++ b/core/modules/simpletest/tests/cache.test
@@ -95,7 +95,9 @@ class CacheTestCase extends DrupalWebTestCase {
    *   The time in seconds the cache should minimal live.
    */
   protected function setupLifetime($time) {
-    variable_set('cache_lifetime', $time);
+    $config = config('system.performance');
+    $config->set('cache_lifetime', $time);
+    $config->save();
     variable_set('cache_flush', 0);
   }
 }
diff --git a/core/modules/simpletest/tests/common.test b/core/modules/simpletest/tests/common.test
index 30449b652982a2320be97ee7648a1edfef36e790..eeb5e497f6d2305756f35a89f0b33ac68b4ef44d 100644
--- a/core/modules/simpletest/tests/common.test
+++ b/core/modules/simpletest/tests/common.test
@@ -1191,8 +1191,10 @@ class CommonJavaScriptTestCase extends DrupalWebTestCase {
     parent::setUp('locale', 'simpletest', 'common_test');
 
     // Disable preprocessing
-    $this->preprocess_js = variable_get('preprocess_js', 0);
-    variable_set('preprocess_js', 0);
+    $config = config('system.performance');
+    $this->preprocess_js = $config->get('preprocess_js');
+    $config->set('preprocess_js', 0);
+    $config->save();
 
     // Reset drupal_add_js() and drupal_add_library() statics before each test.
     drupal_static_reset('drupal_add_js');
@@ -1201,7 +1203,9 @@ class CommonJavaScriptTestCase extends DrupalWebTestCase {
 
   function tearDown() {
     // Restore configured value for JavaScript preprocessing.
-    variable_set('preprocess_js', $this->preprocess_js);
+    $config = config('system.performance');
+    $config->set('preprocess_js', $this->preprocess_js);
+    $config->save();
     parent::tearDown();
   }
 
@@ -1399,7 +1403,9 @@ class CommonJavaScriptTestCase extends DrupalWebTestCase {
     // Now ensure that with aggregation on, one file is made for the
     // 'every_page' files, and one file is made for the others.
     drupal_static_reset('drupal_add_js');
-    variable_set('preprocess_js', 1);
+    $config = config('system.performance');
+    $config->set('preprocess_js', 1);
+    $config->save();
     drupal_add_js('core/misc/ajax.js');
     drupal_add_js('core/misc/authorize.js', array('every_page' => TRUE));
     drupal_add_js('core/misc/autocomplete.js');
diff --git a/core/modules/simpletest/tests/session.test b/core/modules/simpletest/tests/session.test
index 746f632ca28db2faa5f0134418667c6d7c4bf8ce..6303ca5b21b92ad21c1677279daeb8893353b8a5 100644
--- a/core/modules/simpletest/tests/session.test
+++ b/core/modules/simpletest/tests/session.test
@@ -139,7 +139,9 @@ class SessionTestCase extends DrupalWebTestCase {
     $this->assertSessionEmpty(TRUE);
 
     // The same behavior is expected when caching is enabled.
-    variable_set('cache', 1);
+    $config = config('system.performance');
+    $config->set('cache', 1);
+    $config->save();
     $this->drupalGet('');
     $this->assertSessionCookie(FALSE);
     $this->assertSessionEmpty(TRUE);
diff --git a/core/modules/simpletest/tests/theme.test b/core/modules/simpletest/tests/theme.test
index a3b5c3d84d7cccdb9f84446cc22f1f8820d86b88..a795054c5d6b05edafc253c3cbfc061a63033cbb 100644
--- a/core/modules/simpletest/tests/theme.test
+++ b/core/modules/simpletest/tests/theme.test
@@ -100,7 +100,9 @@ class ThemeUnitTest extends DrupalWebTestCase {
     // what is output to the HTML HEAD based on what is in a theme's .info file,
     // so it doesn't matter what page we get, as long as it is themed with the
     // test theme. First we test with CSS aggregation disabled.
-    variable_set('preprocess_css', 0);
+    $config = config('system.performance');
+    $config->set('preprocess_css', 0);
+    $config->save();
     $this->drupalGet('theme-test/suggestion');
     $this->assertNoText('system.base.css', t('The theme\'s .info file is able to override a module CSS file from being added to the page.'));
 
@@ -108,9 +110,11 @@ class ThemeUnitTest extends DrupalWebTestCase {
     // triggered during drupal_build_css_cache() when a source file doesn't
     // exist. Then allow remaining tests to continue with aggregation disabled
     // by default.
-    variable_set('preprocess_css', 1);
+    $config->set('preprocess_css', 1);
+    $config->save();
     $this->drupalGet('theme-test/suggestion');
-    variable_set('preprocess_css', 0);
+    $config->set('preprocess_css', 0);
+    $config->save();
   }
 
   /**
diff --git a/core/modules/statistics/statistics.test b/core/modules/statistics/statistics.test
index e3ae35c1ecbf49041c2aee0876edeb9ba23790ce..bf3aeac4cb202ecb55dbbe879cfb69adf8dec6bf 100644
--- a/core/modules/statistics/statistics.test
+++ b/core/modules/statistics/statistics.test
@@ -69,7 +69,9 @@ class StatisticsLoggingTestCase extends DrupalWebTestCase {
     $this->node = $this->drupalCreateNode(array('title' => $this->randomName(255), 'uid' => $this->auth_user->uid));
 
     // Enable page caching.
-    variable_set('cache', TRUE);
+    $config = config('system.performance');
+    $config->set('cache', 1);
+    $config->save();
 
     // Enable access logging.
     variable_set('statistics_enable_access_log', 1);
diff --git a/core/modules/system/config/system.performance.xml b/core/modules/system/config/system.performance.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8edf1eb5b5bbecefffa24eebbec5c067c426bd37
--- /dev/null
+++ b/core/modules/system/config/system.performance.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<config>
+  <cache>0</cache>
+  <cache_lifetime>0</cache_lifetime>
+  <page_cache_maximum_age>0</page_cache_maximum_age>
+  <page_compression>0</page_compression>
+  <preprocess_css>0</preprocess_css>
+  <preprocess_js>0</preprocess_js>
+</config>
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index 1c865a6356f25deee43107fcc37eb92385dcbf0e..a45a0e3e0bf0c045b7299c0deb2d2752adb49377 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -1637,10 +1637,11 @@ function system_logging_settings() {
  * Form builder; Configure site performance settings.
  *
  * @ingroup forms
- * @see system_settings_form()
+ * @see system_performance_settings_submit().
  */
-function system_performance_settings() {
+function system_performance_settings($form, &$form_state) {
   drupal_add_js(drupal_get_path('module', 'system') . '/system.js');
+  $config = config('system.performance');
 
   $form['clear_cache'] = array(
     '#type' => 'fieldset',
@@ -1658,11 +1659,10 @@ function system_performance_settings() {
     '#title' => t('Caching'),
   );
 
-  $cache = variable_get('cache', 0);
   $form['caching']['cache'] = array(
     '#type' => 'checkbox',
     '#title' => t('Cache pages for anonymous users'),
-    '#default_value' => $cache,
+    '#default_value' => $config->get('cache'),
     '#weight' => -2,
   );
   $period = drupal_map_assoc(array(0, 60, 180, 300, 600, 900, 1800, 2700, 3600, 10800, 21600, 32400, 43200, 86400), 'format_interval');
@@ -1670,16 +1670,16 @@ function system_performance_settings() {
   $form['caching']['cache_lifetime'] = array(
     '#type' => 'select',
     '#title' => t('Minimum cache lifetime'),
-    '#default_value' => variable_get('cache_lifetime', 0),
+    '#default_value' => $config->get('cache_lifetime'),
     '#options' => $period,
-    '#description' => t('Cached pages will not be re-created until at least this much time has elapsed.')
+    '#description' => t('Cached pages will not be re-created until at least this much time has elapsed.'),
   );
   $form['caching']['page_cache_maximum_age'] = array(
     '#type' => 'select',
     '#title' => t('Expiration of cached pages'),
-    '#default_value' => variable_get('page_cache_maximum_age', 0),
+    '#default_value' => $config->get('page_cache_maximum_age'),
     '#options' => $period,
-    '#description' => t('The maximum time an external cache can use an old version of a page.')
+    '#description' => t('The maximum time an external cache can use an old version of a page.'),
   );
 
   $directory = 'public://';
@@ -1696,34 +1696,57 @@ function system_performance_settings() {
     '#description' => t('External resources can be optimized automatically, which can reduce both the size and number of requests made to your website.') . $disabled_message,
   );
 
-  $js_hide = $cache ? '' : ' class="js-hide"';
+  $js_hide = $config->get('cache') ? '' : ' class="js-hide"';
   $form['bandwidth_optimization']['page_compression'] = array(
     '#type' => 'checkbox',
     '#title' => t('Compress cached pages.'),
-    '#default_value' => variable_get('page_compression', TRUE),
+    '#default_value' => $config->get('page_compression'),
     '#prefix' => '<div id="page-compression-wrapper"' . $js_hide . '>',
     '#suffix' => '</div>',
   );
   $form['bandwidth_optimization']['preprocess_css'] = array(
     '#type' => 'checkbox',
     '#title' => t('Aggregate and compress CSS files.'),
-    '#default_value' => intval(variable_get('preprocess_css', 0) && $is_writable),
+    '#default_value' => $config->get('preprocess_css'),
     '#disabled' => $disabled,
   );
   $form['bandwidth_optimization']['preprocess_js'] = array(
     '#type' => 'checkbox',
     '#title' => t('Aggregate JavaScript files.'),
-    '#default_value' => intval(variable_get('preprocess_js', 0) && $is_writable),
+    '#default_value' => $config->get('preprocess_js'),
     '#disabled' => $disabled,
   );
 
+  $form['actions'] = array('#type' => 'actions');
+  $form['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save configuration'),
+  );
+
   $form['#submit'][] = 'drupal_clear_css_cache';
   $form['#submit'][] = 'drupal_clear_js_cache';
   // This form allows page compression settings to be changed, which can
   // invalidate the page cache, so it needs to be cleared on form submit.
   $form['#submit'][] = 'system_clear_page_cache_submit';
+  $form['#submit'][] = 'system_performance_settings_submit';
 
-  return system_settings_form($form);
+  return $form;
+}
+
+/**
+ * Form submission handler for system_performance_settings().
+ *
+ * @ingroup forms
+ */
+function system_performance_settings_submit($form, &$form_state) {
+  $config = config('system.performance');
+  $config->set('cache', $form_state['values']['cache']);
+  $config->set('cache_lifetime', $form_state['values']['cache_lifetime']);
+  $config->set('page_cache_maximum_age', $form_state['values']['page_cache_maximum_age']);
+  $config->set('page_compression', $form_state['values']['page_compression']);
+  $config->set('preprocess_css', $form_state['values']['preprocess_css']);
+  $config->set('preprocess_js', $form_state['values']['preprocess_js']);
+  $config->save();
 }
 
 /**
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index d562bf68e286e94b7f1c9ab4d179af8684649fde..03116583761edc6ef55674c6b36da1e591fe3a8d 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -697,6 +697,28 @@ function system_schema() {
   $schema['cache_path'] = $schema['cache'];
   $schema['cache_path']['description'] = 'Cache table for path alias lookup.';
 
+  $schema['config'] = array(
+    'description' => 'Default active store for the configuration system.',
+    'fields' => array(
+      'name' => array(
+        'description' => 'The identifier for the configuration entry, such as module.example (the name of the file, minus the file extension).',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'data' => array(
+        'description' => 'The raw data for this configuration entry.',
+        'type' => 'blob',
+        'not null' => TRUE,
+        'size' => 'big',
+        'translatable' => TRUE,
+      ),
+    ),
+    'primary key' => array('name'),
+  );
+
+
   $schema['date_format_type'] = array(
     'description' => 'Stores configured date format types.',
     'fields' => array(
@@ -1667,6 +1689,36 @@ function system_update_8002() {
   }
 }
 
+/**
+ * Adds {config} table for new Configuration system.
+ */
+function system_update_8003() {
+  // @todo Temporary.
+  if (db_table_exists('config')) {
+    db_drop_table('config');
+  }
+  db_create_table('config', array(
+    'description' => 'Default active store for the configuration system.',
+    'fields' => array(
+      'name' => array(
+        'description' => 'The identifier for the configuration entry, such as module.example (the name of the file, minus the file extension).',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'data' => array(
+        'description' => 'The raw data for this configuration entry.',
+        'type' => 'blob',
+        'not null' => TRUE,
+        'size' => 'big',
+        'translatable' => TRUE,
+      ),
+    ),
+    'primary key' => array('name'),
+  ));
+}
+
 /**
  * @} End of "defgroup updates-7.x-to-8.x"
  * The next series of updates should start at 9000.
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 1c0543d158c9df0c577cbb29ad8b95728cf79261..86a5f7b6730be544cd8d177a74b2232a0dc690d3 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -2772,12 +2772,27 @@ function system_settings_form_submit($form, &$form_state) {
   // Exclude unnecessary elements.
   form_state_values_clean($form_state);
 
+  $config_objects = array();
   foreach ($form_state['values'] as $key => $value) {
+    if (isset($form_state['config'][$key])) {
+      $config_name = $form_state['config'][$key]['name'];
+      $config_key = $form_state['config'][$key]['path'];
+      if (empty($config_objects[$config_name])) {
+        $config_objects[$config_name] = config($config_name);
+      }
+      if (!empty($config_objects[$config_name])) {
+        $config_objects[$config_name]->set($config_key, $value);
+        continue;
+      }
+    }
     if (is_array($value) && isset($form_state['values']['array_filter'])) {
       $value = array_keys(array_filter($value));
     }
     variable_set($key, $value);
   }
+  foreach ($config_objects as $config) {
+    $config->save();
+  }
 
   drupal_set_message(t('The configuration options have been saved.'));
 }
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
index f434ac5d90730a63e4016c6486e8d5fa00dbb49c..230a7659c9dbb3a66825159da4a09b4ae03a43f8 100755
--- a/sites/default/default.settings.php
+++ b/sites/default/default.settings.php
@@ -236,6 +236,28 @@
  */
 $drupal_hash_salt = '';
 
+/**
+ * Location of the site configuration files.
+ *
+ * By default, Drupal configuration files are stored in a randomly named
+ * directory under the default public files path. On install the
+ * named directory is created in the default files directory. For enhanced
+ * security, you may set this variable to a location outside your docroot.
+ *
+ * @todo Flesh this out, provide more details, etc.
+ *
+ * Example:
+ *   $config_directory_name = '/some/directory/outside/webroot';
+ */
+$config_directory_name = '';
+
+/**
+ * Configuration signature key.
+ *
+ * Drupal configuration files are signed using this key.
+ */
+$config_signature_key = '';
+
 /**
  * Base URL (optional).
  *