diff --git a/cdn.admin.inc b/cdn.admin.inc
index 34d925a..5531898 100644
--- a/cdn.admin.inc
+++ b/cdn.admin.inc
@@ -16,51 +16,60 @@ function cdn_admin_general_settings_form($form, &$form_state) {
   $form = array();
   _cdn_settings_form_prepare($form, $form_state);
 
-  $perm_url = url('admin/people/permissions',
-                  array('fragment' => 'module-cdn'));
-
-  $form[CDN_STATUS_VARIABLE] = array(
-    '#type' => 'radios',
-    '#title' => t('Status'),
-    '#description' => t(
-      "If you don't want to use the CDN to serve files to your visitors yet,
-      but you do want to see if it's working well for your site, then enable
-      testing mode.<br />Users will only get the files from the CDN if they
-      have the <a href=\"!perm-url\">%cdn-testing-mode-permission
-      permission</a>.",
-      array(
-        '!perm-url' => $perm_url,
-        '%cdn-testing-mode-permission' => 'access files on CDN when in testing mode',
-      )
-    ),
-    '#required' => TRUE,
-    '#options' => array(
-      CDN_DISABLED => t('Disabled'),
-      CDN_TESTING  => t('Testing mode'),
-      CDN_ENABLED  => t('Enabled'),
-    ),
-    '#default_value' => variable_get(CDN_STATUS_VARIABLE, CDN_DISABLED),
-  );
+  $perm_url = \Drupal\Core\Url::fromRoute('user.admin_permissions');
+
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $form[CDN_STATUS_VARIABLE] = array(
+//     '#type' => 'radios',
+//     '#title' => t('Status'),
+//     '#description' => t(
+//       "If you don't want to use the CDN to serve files to your visitors yet,
+//       but you do want to see if it's working well for your site, then enable
+//       testing mode.<br />Users will only get the files from the CDN if they
+//       have the <a href=\"!perm-url\">%cdn-testing-mode-permission
+//       permission</a>.",
+//       array(
+//         '!perm-url' => $perm_url,
+//         '%cdn-testing-mode-permission' => 'access files on CDN when in testing mode',
+//       )
+//     ),
+//     '#required' => TRUE,
+//     '#options' => array(
+//       CDN_DISABLED => t('Disabled'),
+//       CDN_TESTING  => t('Testing mode'),
+//       CDN_ENABLED  => t('Enabled'),
+//     ),
+//     '#default_value' => variable_get(CDN_STATUS_VARIABLE, CDN_DISABLED),
+//   );
+
+
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $form[CDN_STATS_VARIABLE] = array(
+//     '#type' => 'checkbox',
+//     '#title' => t('Display statistics'),
+//     '#description' => t(
+//       'Shows the CDN integration statistics of the current page, to users with
+//         the <a href="!perm-url">%access-per-page-statistics permission</a>.',
+//         array(
+//           '!perm-url' => $perm_url,
+//           '%access-per-page-statistics' => 'access per-page statistics',
+//         )
+//     ),
+//     '#return_value'  => CDN_ENABLED,
+//     '#default_value' => variable_get(CDN_STATS_VARIABLE, CDN_DISABLED),
+//     '#states' => array(
+//       'invisible' => array(
+//         ':input[name="' . CDN_STATUS_VARIABLE . '"]' => array('value' => '' . CDN_DISABLED),
+//       ),
+//     ),
+//   );
 
-  $form[CDN_STATS_VARIABLE] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Display statistics'),
-    '#description' => t(
-      'Shows the CDN integration statistics of the current page, to users with
-        the <a href="!perm-url">%access-per-page-statistics permission</a>.',
-        array(
-          '!perm-url' => $perm_url,
-          '%access-per-page-statistics' => 'access per-page statistics',
-        )
-    ),
-    '#return_value'  => CDN_ENABLED,
-    '#default_value' => variable_get(CDN_STATS_VARIABLE, CDN_DISABLED),
-    '#states' => array(
-      'invisible' => array(
-        ':input[name="' . CDN_STATUS_VARIABLE . '"]' => array('value' => '' . CDN_DISABLED),
-      ),
-    ),
-  );
 
   return system_settings_form($form);
 }
@@ -72,17 +81,22 @@ function cdn_admin_details_form($form, &$form_state) {
   $form = array();
   _cdn_settings_form_prepare($form, $form_state);
 
-  $form[CDN_MODE_VARIABLE] = array(
-    '#type' => 'radios',
-    '#title' => t('Mode'),
-    '#description' => _cdn_help('admin-details-mode') . t('Choose a CDN integration mode.'),
-    '#required' => TRUE,
-    '#options'  => array(
-      CDN_MODE_BASIC    => t('Origin Pull'),
-      CDN_MODE_ADVANCED => t('File Conveyor'),
-    ),
-    '#default_value' => variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC),
-  );
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $form[CDN_MODE_VARIABLE] = array(
+//     '#type' => 'radios',
+//     '#title' => t('Mode'),
+//     '#description' => _cdn_help('admin-details-mode') . t('Choose a CDN integration mode.'),
+//     '#required' => TRUE,
+//     '#options'  => array(
+//       CDN_MODE_BASIC    => t('Origin Pull'),
+//       CDN_MODE_ADVANCED => t('File Conveyor'),
+//     ),
+//     '#default_value' => variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC),
+//   );
+
 
   $form['settings'] = array(
     '#type' => 'fieldset',
@@ -93,42 +107,48 @@ function cdn_admin_details_form($form, &$form_state) {
   // Origin Pull mode settings.
   //
 
-  $form['settings'][CDN_BASIC_MAPPING_VARIABLE] = array(
-    '#type'          => 'textarea',
-    '#title'         => t('CDN mapping'),
-    '#description'   => _cdn_help('admin-details-mode-pull-cdn-mapping') . t("Define which files are mapped to which CDN."),
-    '#size'          => 35,
-    '#default_value' => variable_get(CDN_BASIC_MAPPING_VARIABLE, ''),
-    '#states' => array(
-      'visible' => array(
-        ':input[name="' . CDN_MODE_VARIABLE . '"]' => array('value' => CDN_MODE_BASIC),
-      )
-    ),
-  );
-  $form['settings'][CDN_BASIC_FARFUTURE_VARIABLE] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Far Future expiration'),
-    '#description' => _cdn_help('admin-details-mode-pull-far-future') .
-      t('Mark all files served from the CDN to expire in the far future —
-      improves client-side cacheability.<br /><strong>Note:</strong> this
-      requires the !preprocess-css-link performance setting to be enabled (or
-      your site will break).<br><strong>Note:</strong> only use Far Future
-      expiration when using a CDN or a reverse proxy.',
-      array(
-        '!preprocess-css-link' => l(
-          '"Aggregate and compress CSS files"',
-          'admin/config/development/performance',
-          array('fragment' => 'edit-bandwidth-optimization')
-        ),
-      )
-    ),
-    '#default_value' => variable_get(CDN_BASIC_FARFUTURE_VARIABLE, CDN_BASIC_FARFUTURE_DEFAULT),
-    '#states' => array(
-      'visible' => array(
-        ':input[name="' . CDN_MODE_VARIABLE . '"]' => array('value' => CDN_MODE_BASIC),
-      )
-    ),
-  );
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $form['settings'][CDN_BASIC_MAPPING_VARIABLE] = array(
+//     '#type'          => 'textarea',
+//     '#title'         => t('CDN mapping'),
+//     '#description'   => _cdn_help('admin-details-mode-pull-cdn-mapping') . t("Define which files are mapped to which CDN."),
+//     '#size'          => 35,
+//     '#default_value' => variable_get(CDN_BASIC_MAPPING_VARIABLE, ''),
+//     '#states' => array(
+//       'visible' => array(
+//         ':input[name="' . CDN_MODE_VARIABLE . '"]' => array('value' => CDN_MODE_BASIC),
+//       )
+//     ),
+//   );
+
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $form['settings'][CDN_BASIC_FARFUTURE_VARIABLE] = array(
+//     '#type' => 'checkbox',
+//     '#title' => t('Far Future expiration'),
+//     '#description' => _cdn_help('admin-details-mode-pull-far-future') .
+//       t('Mark all files served from the CDN to expire in the far future —
+//       improves client-side cacheability.<br /><strong>Note:</strong> this
+//       requires the !preprocess-css-link performance setting to be enabled (or
+//       your site will break).<br><strong>Note:</strong> only use Far Future
+//       expiration when using a CDN or a reverse proxy.',
+//       array(
+//         '!preprocess-css-link' => \Drupal::l('"Aggregate and compress CSS files"', \Drupal\Core\Url::fromRoute('system.performance_settings')),
+//       )
+//     ),
+//     '#default_value' => variable_get(CDN_BASIC_FARFUTURE_VARIABLE, CDN_BASIC_FARFUTURE_DEFAULT),
+//     '#states' => array(
+//       'visible' => array(
+//         ':input[name="' . CDN_MODE_VARIABLE . '"]' => array('value' => CDN_MODE_BASIC),
+//       )
+//     ),
+//   );
+
 
   $format_variables = array(
     '@format-directory'                => '<' . t('directory') . '>',
@@ -137,27 +157,32 @@ function cdn_admin_details_form($form, &$form_state) {
   );
 
   $methods = array();
-  $ufi_info = module_invoke_all('cdn_unique_file_identifier_info');
+  $ufi_info = \Drupal::moduleHandler()->invokeAll('cdn_unique_file_identifier_info');
   foreach ($ufi_info as $ufi_method => $ufi) {
     $methods[] = $ufi['label']
                  . ' (<code>' . $ufi_method . '</code>): '
                  . $ufi['description'];
   }
-  $format_variables['!ufi-methods'] = theme('item_list', array('items' => $methods));
-
-  $form['settings'][CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_VARIABLE] = array(
-    '#type'          => 'textarea',
-    '#title'         => t('Unique file identifier generation'),
-    '#description'   => _cdn_help('admin-details-mode-pull-ufi') . t('Define how unique file identifiers (UFIs) are generated.'),
-    '#size'          => 35,
-    '#default_value' => variable_get(CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_VARIABLE, CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_DEFAULT),
-    '#states' => array(
-      'visible' => array(
-        ':input[name="' . CDN_MODE_VARIABLE . '"]' => array('value' => CDN_MODE_BASIC),
-        ':input[name="' . CDN_BASIC_FARFUTURE_VARIABLE . '"]' => array('checked' => TRUE),
-      )
-    ),
-  );
+  $format_variables['!ufi-methods'] = _theme('item_list', array('items' => $methods));
+
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $form['settings'][CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_VARIABLE] = array(
+//     '#type'          => 'textarea',
+//     '#title'         => t('Unique file identifier generation'),
+//     '#description'   => _cdn_help('admin-details-mode-pull-ufi') . t('Define how unique file identifiers (UFIs) are generated.'),
+//     '#size'          => 35,
+//     '#default_value' => variable_get(CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_VARIABLE, CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_DEFAULT),
+//     '#states' => array(
+//       'visible' => array(
+//         ':input[name="' . CDN_MODE_VARIABLE . '"]' => array('value' => CDN_MODE_BASIC),
+//         ':input[name="' . CDN_BASIC_FARFUTURE_VARIABLE . '"]' => array('checked' => TRUE),
+//       )
+//     ),
+//   );
+
 
   $form['settings']['ufis'] = array(
     '#type'        => 'fieldset',
@@ -189,30 +214,40 @@ function cdn_admin_details_form($form, &$form_state) {
   // File Conveyor mode settings.
   //
 
-  $form['settings'][CDN_ADVANCED_PID_FILE_VARIABLE] = array(
-    '#type'          => 'textfield',
-    '#title'         => t('PID file'),
-    '#description'   => _cdn_help('admin-details-mode-fc-pid') . t('Full path to File Conveyor\'s PID file.'),
-    '#size'          => 60,
-    '#default_value' => variable_get(CDN_ADVANCED_PID_FILE_VARIABLE, ''),
-    '#states' => array(
-      'visible' => array(
-        ':input[name="' . CDN_MODE_VARIABLE . '"]' => array('value' => CDN_MODE_ADVANCED),
-      ),
-    ),
-  );
-  $form['settings'][CDN_ADVANCED_SYNCED_FILES_DB_VARIABLE] = array(
-    '#type'          => 'textfield',
-    '#title'         => t('Synced files database'),
-    '#description'   => _cdn_help('admin-details-mode-fc-db') . t('Full path to File Conveyor\'s synced files database file.'),
-    '#size'          => 60,
-    '#default_value' => variable_get(CDN_ADVANCED_SYNCED_FILES_DB_VARIABLE, ''),
-    '#states' => array(
-      'visible' => array(
-        ':input[name="' . CDN_MODE_VARIABLE . '"]' => array('value' => CDN_MODE_ADVANCED),
-      ),
-    ),
-  );
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $form['settings'][CDN_ADVANCED_PID_FILE_VARIABLE] = array(
+//     '#type'          => 'textfield',
+//     '#title'         => t('PID file'),
+//     '#description'   => _cdn_help('admin-details-mode-fc-pid') . t('Full path to File Conveyor\'s PID file.'),
+//     '#size'          => 60,
+//     '#default_value' => variable_get(CDN_ADVANCED_PID_FILE_VARIABLE, ''),
+//     '#states' => array(
+//       'visible' => array(
+//         ':input[name="' . CDN_MODE_VARIABLE . '"]' => array('value' => CDN_MODE_ADVANCED),
+//       ),
+//     ),
+//   );
+
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $form['settings'][CDN_ADVANCED_SYNCED_FILES_DB_VARIABLE] = array(
+//     '#type'          => 'textfield',
+//     '#title'         => t('Synced files database'),
+//     '#description'   => _cdn_help('admin-details-mode-fc-db') . t('Full path to File Conveyor\'s synced files database file.'),
+//     '#size'          => 60,
+//     '#default_value' => variable_get(CDN_ADVANCED_SYNCED_FILES_DB_VARIABLE, ''),
+//     '#states' => array(
+//       'visible' => array(
+//         ':input[name="' . CDN_MODE_VARIABLE . '"]' => array('value' => CDN_MODE_ADVANCED),
+//       ),
+//     ),
+//   );
+
 
   return system_settings_form($form);
 }
@@ -224,51 +259,66 @@ function cdn_admin_other_settings_form($form, &$form_state) {
   $form = array();
   _cdn_settings_form_prepare($form, $form_state);
 
-  if (variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC) == CDN_MODE_ADVANCED) {
-    $form[CDN_DRUPAL_ROOT_VARIABLE] = array(
-      '#type' => 'textfield',
-      '#title' => t('Drupal root directory'),
-      '#description' => t(
-        'In 99% of the cases the default value is sufficient and correct. In
-        some advanced setups that make use of symbolic links however, it is
-        possible that the Drupal root directory is incorrectly detected. In
-        those cases, you should enter it here.<br />
-        <strong>This setting only affects the status report, it does not affect
-        the CDN integration itself in any way.</strong>'
-      ),
-      '#required'      => TRUE,
-      '#default_value' => variable_get(CDN_DRUPAL_ROOT_VARIABLE, realpath('.')),
-    );
-  }
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// if (variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC) == CDN_MODE_ADVANCED) {
+//     $form[CDN_\Drupal::root()_VARIABLE] = array(
+//       '#type' => 'textfield',
+//       '#title' => t('Drupal root directory'),
+//       '#description' => t(
+//         'In 99% of the cases the default value is sufficient and correct. In
+//         some advanced setups that make use of symbolic links however, it is
+//         possible that the Drupal root directory is incorrectly detected. In
+//         those cases, you should enter it here.<br />
+//         <strong>This setting only affects the status report, it does not affect
+//         the CDN integration itself in any way.</strong>'
+//       ),
+//       '#required'      => TRUE,
+//       '#default_value' => variable_get(CDN_\Drupal::root()_VARIABLE, realpath('.')),
+//     );
+//   }
+
 
   $form['https'] = array(
     '#type' => 'fieldset',
     '#title' => t('HTTPS'),
   );
-  $form['https'][CDN_HTTPS_SUPPORT_VARIABLE] = array(
-    '#type'          => 'checkbox',
-    '#title'         => t('CDN supports HTTPS'),
-    '#default_value' => variable_get(CDN_HTTPS_SUPPORT_VARIABLE, FALSE),
-    '#description' => _cdn_help('admin-other-https') . t('Enable if you use HTTPS and your CDN supports it too.'),
-  );
-  if (variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC) == CDN_MODE_BASIC) {
-    $form['https'][CDN_BASIC_MAPPING_HTTPS_VARIABLE] = array(
-      '#type'          => 'textarea',
-      '#title'         => t('CDN mapping for HTTPS'),
-      '#description'   => t('If your CDN supports HTTPS, but requires you to
-                            use different URLs, then you can define an
-                            alternative CDN mapping here. This overrides the
-                            "regular" CDN mapping completely, when using
-                            HTTPS.'),
-      '#size'          => 35,
-      '#default_value' => variable_get(CDN_BASIC_MAPPING_HTTPS_VARIABLE, ''),
-      '#states' => array(
-        'visible' => array(
-          ':input[name="' . CDN_HTTPS_SUPPORT_VARIABLE . '"]' => array('checked' => TRUE),
-        )
-      ),
-    );
-  }
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $form['https'][CDN_HTTPS_SUPPORT_VARIABLE] = array(
+//     '#type'          => 'checkbox',
+//     '#title'         => t('CDN supports HTTPS'),
+//     '#default_value' => variable_get(CDN_HTTPS_SUPPORT_VARIABLE, FALSE),
+//     '#description' => _cdn_help('admin-other-https') . t('Enable if you use HTTPS and your CDN supports it too.'),
+//   );
+
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// if (variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC) == CDN_MODE_BASIC) {
+//     $form['https'][CDN_BASIC_MAPPING_HTTPS_VARIABLE] = array(
+//       '#type'          => 'textarea',
+//       '#title'         => t('CDN mapping for HTTPS'),
+//       '#description'   => t('If your CDN supports HTTPS, but requires you to
+//                             use different URLs, then you can define an
+//                             alternative CDN mapping here. This overrides the
+//                             "regular" CDN mapping completely, when using
+//                             HTTPS.'),
+//       '#size'          => 35,
+//       '#default_value' => variable_get(CDN_BASIC_MAPPING_HTTPS_VARIABLE, ''),
+//       '#states' => array(
+//         'visible' => array(
+//           ':input[name="' . CDN_HTTPS_SUPPORT_VARIABLE . '"]' => array('checked' => TRUE),
+//         )
+//       ),
+//     );
+//   }
+
 
   $path_explanation = t(
     "Enter one file pattern per line. The '*' character is a wildcard.<br />
@@ -297,14 +347,19 @@ function cdn_admin_other_settings_form($form, &$form_state) {
     '#collapsible' => TRUE,
     '#collapsed' => TRUE
   );
-  $form['exceptions']['file_path'][CDN_EXCEPTION_FILE_PATH_BLACKLIST_VARIABLE] = array(
-    '#type' => 'textarea',
-    '#title' => t('Blacklist'),
-    '#default_value' => variable_get(CDN_EXCEPTION_FILE_PATH_BLACKLIST_VARIABLE, CDN_EXCEPTION_FILE_PATH_BLACKLIST_DEFAULT),
-    '#description' => $path_explanation,
-  );
-  $blacklist_modules = module_implements('cdn_blacklist');
-  $blacklist_modules = array_unique(array_merge($blacklist_modules, module_implements('cdn_blacklist_alter')));
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $form['exceptions']['file_path'][CDN_EXCEPTION_FILE_PATH_BLACKLIST_VARIABLE] = array(
+//     '#type' => 'textarea',
+//     '#title' => t('Blacklist'),
+//     '#default_value' => variable_get(CDN_EXCEPTION_FILE_PATH_BLACKLIST_VARIABLE, CDN_EXCEPTION_FILE_PATH_BLACKLIST_DEFAULT),
+//     '#description' => $path_explanation,
+//   );
+
+  $blacklist_modules = \Drupal::moduleHandler()->getImplementations('cdn_blacklist');
+  $blacklist_modules = array_unique(array_merge($blacklist_modules, \Drupal::moduleHandler()->getImplementations('cdn_blacklist_alter')));
   $blacklist_modules_string = '';
   for ($i = 0; $i < count($blacklist_modules); $i++) {
     $blacklist_modules_string .= '<code>' . $blacklist_modules[$i] . '</code>';
@@ -323,12 +378,17 @@ function cdn_admin_other_settings_form($form, &$form_state) {
                         array('!module-list' => $blacklist_modules_string)),
     '#disabled' => TRUE,
   );
-  $form['exceptions']['file_path'][CDN_EXCEPTION_FILE_PATH_WHITELIST_VARIABLE] = array(
-    '#type' => 'textarea',
-    '#title' => t('Whitelist'),
-    '#default_value' => variable_get(CDN_EXCEPTION_FILE_PATH_WHITELIST_VARIABLE, CDN_EXCEPTION_FILE_PATH_WHITELIST_DEFAULT),
-    '#description' => $path_explanation,
-  );
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $form['exceptions']['file_path'][CDN_EXCEPTION_FILE_PATH_WHITELIST_VARIABLE] = array(
+//     '#type' => 'textarea',
+//     '#title' => t('Whitelist'),
+//     '#default_value' => variable_get(CDN_EXCEPTION_FILE_PATH_WHITELIST_VARIABLE, CDN_EXCEPTION_FILE_PATH_WHITELIST_DEFAULT),
+//     '#description' => $path_explanation,
+//   );
+
 
   $form['exceptions']['drupal_path'] = array(
     '#type' => 'fieldset',
@@ -339,21 +399,26 @@ function cdn_admin_other_settings_form($form, &$form_state) {
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
   );
-  $form['exceptions']['drupal_path'][CDN_EXCEPTION_DRUPAL_PATH_BLACKLIST_VARIABLE] = array(
-    '#type' => 'textarea',
-    '#title' => t('Blacklist'),
-    '#default_value' => variable_get(CDN_EXCEPTION_DRUPAL_PATH_BLACKLIST_VARIABLE, CDN_EXCEPTION_DRUPAL_PATH_BLACKLIST_DEFAULT),
-    '#description' => t(
-      "Enter one page per line as Drupal paths. The '*' character is a
-      wildcard. Example paths are %blog for the blog page and %blog-wildcard
-      for every personal blog. %front is the front page.",
-      array(
-       '%blog'          => 'blog',
-       '%blog-wildcard' => 'blog/*',
-       '%front'         => '<front>',
-      )
-    ),
-  );
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $form['exceptions']['drupal_path'][CDN_EXCEPTION_DRUPAL_PATH_BLACKLIST_VARIABLE] = array(
+//     '#type' => 'textarea',
+//     '#title' => t('Blacklist'),
+//     '#default_value' => variable_get(CDN_EXCEPTION_DRUPAL_PATH_BLACKLIST_VARIABLE, CDN_EXCEPTION_DRUPAL_PATH_BLACKLIST_DEFAULT),
+//     '#description' => t(
+//       "Enter one page per line as Drupal paths. The '*' character is a
+//       wildcard. Example paths are %blog for the blog page and %blog-wildcard
+//       for every personal blog. %front is the front page.",
+//       array(
+//        '%blog'          => 'blog',
+//        '%blog-wildcard' => 'blog/*',
+//        '%front'         => '<front>',
+//       )
+//     ),
+//   );
+
 
   $form['exceptions']['auth_users'] = array(
     '#type' => 'fieldset',
@@ -364,12 +429,17 @@ function cdn_admin_other_settings_form($form, &$form_state) {
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
   );
-  $form['exceptions']['auth_users'][CDN_EXCEPTION_AUTH_USERS_BLACKLIST_VARIABLE] = array(
-    '#type'          => 'textarea',
-    '#title'         => t('Blacklist'),
-    '#default_value' => variable_get(CDN_EXCEPTION_AUTH_USERS_BLACKLIST_VARIABLE, CDN_EXCEPTION_AUTH_USERS_BLACKLIST_DEFAULT),
-    '#description'   => $path_explanation,
-  );
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $form['exceptions']['auth_users'][CDN_EXCEPTION_AUTH_USERS_BLACKLIST_VARIABLE] = array(
+//     '#type'          => 'textarea',
+//     '#title'         => t('Blacklist'),
+//     '#default_value' => variable_get(CDN_EXCEPTION_AUTH_USERS_BLACKLIST_VARIABLE, CDN_EXCEPTION_AUTH_USERS_BLACKLIST_DEFAULT),
+//     '#description'   => $path_explanation,
+//   );
+
 
 
   $form['cdn_pick_server'] = array(
@@ -392,7 +462,12 @@ function cdn_admin_other_settings_form($form, &$form_state) {
     );
   }
   else {
-    $php_code = variable_get(CDN_PICK_SERVER_PHP_CODE_VARIABLE, '');
+    // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $php_code = variable_get(CDN_PICK_SERVER_PHP_CODE_VARIABLE, '');
+
     $form['cdn_pick_server'][CDN_PICK_SERVER_PHP_CODE_VARIABLE] = array(
       '#type' => 'textarea',
       '#title' => t('PHP code for cdn_pick_server()'),
@@ -427,13 +502,29 @@ function cdn_admin_details_form_validate($form, &$form_state) {
   if ($form_state['values'][CDN_MODE_VARIABLE] == CDN_MODE_BASIC) {
     $domains = cdn_get_domains();
     $token = md5(rand());
-    variable_set('cdn_reverse_proxy_test', $token);
+    \Drupal::configFactory()->getEditable('cdn.settings')->set('cdn_reverse_proxy_test', $token)->save();
     $yays = array();
     $nays = array();
     foreach ($domains as $domain) {
       $url = 'http://' . $domain . base_path() . 'cdn/farfuture/reverse-proxy-test/' . $token;
-      $r1 = drupal_http_request($url);
-      $r2 = drupal_http_request($url);
+      // @FIXME
+// drupal_http_request() has been replaced by the Guzzle HTTP client, which is bundled
+// with Drupal core.
+// 
+// 
+// @see https://www.drupal.org/node/1862446
+// @see http://docs.guzzlephp.org/en/latest
+// $r1 = drupal_http_request($url);
+
+      // @FIXME
+// drupal_http_request() has been replaced by the Guzzle HTTP client, which is bundled
+// with Drupal core.
+// 
+// 
+// @see https://www.drupal.org/node/1862446
+// @see http://docs.guzzlephp.org/en/latest
+// $r2 = drupal_http_request($url);
+
       unset($r1->headers);
       unset($r2->headers);
       $args = array('%domain' => $domain);
@@ -449,18 +540,18 @@ function cdn_admin_details_form_validate($form, &$form_state) {
         }
       }
     }
-    variable_set('cdn_reverse_proxy_test', FALSE);
+    \Drupal::configFactory()->getEditable('cdn.settings')->set('cdn_reverse_proxy_test', FALSE)->save();
     if (!empty($yays)) {
       drupal_set_message(t('Perfect domains: !yay-list',
         array(
-          '!yay-list' => theme('item_list', array('items' => $yays)),
+          '!yay-list' => _theme('item_list', array('items' => $yays)),
         )
       ));
     }
     if (!empty($nays)) {
       drupal_set_message(t('Potentially problematic domains: !nay-list',
         array(
-          '!nay-list' => theme('item_list', array('items' => $nays)),
+          '!nay-list' => _theme('item_list', array('items' => $nays)),
         )
       ), 'warning');
     }
@@ -501,7 +592,7 @@ function cdn_admin_settings_submit_show_cache_warning($form, &$form_state) {
                         be done in the <a href="!link">"Clear cache"
                         field set</a> on the "Performance" settings form.',
                         array(
-                          '!link' => url('admin/config/development/performance')
+                          '!link' => \Drupal\Core\Url::fromRoute('system.performance_settings')
                         )
                       ),
                       'info'
@@ -574,8 +665,8 @@ function _cdn_admin_check_requirements() {
           !error-list
           You can also see them on the !status-report.',
           array(
-            '!status-report' => l(t('status report'), 'admin/reports/status'),
-            '!error-list' => theme('item_list', array('items' => $errors)),
+            '!status-report' => \Drupal::l(t('status report'), \Drupal\Core\Url::fromRoute('system.status')),
+            '!error-list' => _theme('item_list', array('items' => $errors)),
           )
       ),
       'error'
@@ -601,7 +692,7 @@ function _cdn_settings_form_prepare(&$form, $form_state) {
 }
 
 function _cdn_check_advanced_help() {
-  if (!module_exists('advanced_help')) {
+  if (!\Drupal::moduleHandler()->moduleExists('advanced_help')) {
     $sql = "SELECT filename
             FROM {system}
             WHERE type = 'module'
@@ -611,25 +702,25 @@ function _cdn_check_advanced_help() {
       drupal_set_message(t(
         'If you enable the <a href="@modules-url">Advanced Help</a> module,
         the CDN module will provide more and better help.',
-        array('@modules-url' => url('admin/modules'))
+        array('@modules-url' => \Drupal\Core\Url::fromRoute('system.modules_list'))
       ));
     }
     else {
       drupal_set_message(t(
         'If you install the <a href="@adv-help-url">Advanced Help</a> module,
         the CDN module will provide more and better help.',
-        array('@adv-help-url' => url('http://drupal.org/project/advanced_help'))
+        array('@adv-help-url' => \Drupal\Core\Url::fromUri('http://drupal.org/project/advanced_help'))
       ));
     }
   }
 }
 
 function _cdn_help($topic) {
-  if (!module_exists('advanced_help')) {
+  if (!\Drupal::moduleHandler()->moduleExists('advanced_help')) {
     return '';
   }
   else {
-    return theme(
+    return _theme(
       'advanced_help_topic',
       array('module' => 'cdn', 'topic' => $topic)
     );
diff --git a/cdn.advanced.inc b/cdn.advanced.inc
index 1cc06d4..af86218 100644
--- a/cdn.advanced.inc
+++ b/cdn.advanced.inc
@@ -62,16 +62,26 @@ function cdn_advanced_get_servers($path) {
 function _cdn_advanced_get_db_connection() {
   static $db;
 
-  $synced_files_db = variable_get(CDN_ADVANCED_SYNCED_FILES_DB_VARIABLE, FALSE);
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $synced_files_db = variable_get(CDN_ADVANCED_SYNCED_FILES_DB_VARIABLE, FALSE);
+
 
   if ($synced_files_db === FALSE || !file_exists($synced_files_db) || filesize($synced_files_db) == 0) {
     $db = FALSE;
   }
   elseif (!isset($db)) {
     try {
-      $db = new PDO('sqlite:' . variable_get(CDN_ADVANCED_SYNCED_FILES_DB_VARIABLE, ''));
+      // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $db = new PDO('sqlite:' . variable_get(CDN_ADVANCED_SYNCED_FILES_DB_VARIABLE, ''));
+
     } catch (PDOException $e) {
-      watchdog('cdn', "Could not open synced files DB: %error.", array('%error' => $e));
+      \Drupal::logger('cdn')->notice("Could not open synced files DB: %error.", array('%error' => $e));
       $db = FALSE;
     }
   }
diff --git a/cdn.basic.css.inc b/cdn.basic.css.inc
index be7175d..1ee08f6 100644
--- a/cdn.basic.css.inc
+++ b/cdn.basic.css.inc
@@ -20,7 +20,12 @@ function _cdn_aggregate_css(&$css_groups) {
     return;
   }
 
-  $preprocess_css = (variable_get('preprocess_css', FALSE) && (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update'));
+  // @FIXME
+// // @FIXME
+// // This looks like another module's variable. You'll need to rewrite this call
+// // to ensure that it uses the correct configuration object.
+// $preprocess_css = (variable_get('preprocess_css', FALSE) && (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update'));
+
 
   // For each group that needs aggregation, aggregate its items.
   foreach ($css_groups as $key => $group) {
@@ -61,14 +66,24 @@ function _cdn_aggregate_css(&$css_groups) {
  */
 function _cdn_build_css_cache($css, $suffix = '') {
   // Create different CSS aggregation maps for HTTP and HTTPS.
-  $https_mapping = variable_get(CDN_BASIC_MAPPING_HTTPS_VARIABLE, '');
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $https_mapping = variable_get(CDN_BASIC_MAPPING_HTTPS_VARIABLE, '');
+
   $css_cache_var = (!empty($https_mapping) && cdn_serve_from_https())
     ? 'cdn_css_cache_files_https'
     : 'cdn_css_cache_files_http';
 
   $data = '';
   $uri = '';
-  $map = variable_get($css_cache_var, array());
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $map = variable_get($css_cache_var, array());
+
   // Create a new array so that only the file names are used to create the hash.
   // This prevents new aggregates from being created unnecessarily.
   $css_data = array();
@@ -88,7 +103,7 @@ function _cdn_build_css_cache($css, $suffix = '') {
         $contents = drupal_load_stylesheet($stylesheet['data'], TRUE);
 
         // Get the parent directory of this file, relative to the Drupal root.
-        $css_base_url = drupal_substr($stylesheet['data'], 0, strrpos($stylesheet['data'], '/'));
+        $css_base_url = \Drupal\Component\Utility\Unicode::substr($stylesheet['data'], 0, strrpos($stylesheet['data'], '/'));
         _cdn_build_css_path(NULL, $css_base_url . '/');
 
         // Anchor all paths in the CSS with its base URL, ignoring external and absolute paths.
@@ -105,7 +120,7 @@ function _cdn_build_css_cache($css, $suffix = '') {
 
     // Prefix filename to prevent blocking by firewalls which reject files
     // starting with "ad*".
-    $filename = 'css_' . drupal_hash_base64($data) . $suffix . '.css';
+    $filename = 'css_' . \Drupal\Component\Utility\Crypt::hashBase64($data) . $suffix . '.css';
     // Create the css/ within the files folder.
     $csspath = ($css_cache_var == 'cdn_css_cache_files_https')
       ? 'public://cdn/css/https'
@@ -120,14 +135,24 @@ function _cdn_build_css_cache($css, $suffix = '') {
     // that rewrite rules are working) and the zlib extension is available then
     // create a gzipped version of this file. This file is served conditionally
     // to browsers that accept gzip using .htaccess rules.
-    if (variable_get('css_gzip_compression', TRUE) && variable_get('clean_url', 0) && extension_loaded('zlib')) {
-      if (!file_exists($uri . '.gz') && !file_unmanaged_save_data(gzencode($data, 9, FORCE_GZIP), $uri . '.gz', FILE_EXISTS_REPLACE)) {
-        return FALSE;
-      }
-    }
+    // @FIXME
+// // @FIXME
+// // This looks like another module's variable. You'll need to rewrite this call
+// // to ensure that it uses the correct configuration object.
+// if (variable_get('css_gzip_compression', TRUE) && variable_get('clean_url', 0) && extension_loaded('zlib')) {
+//       if (!file_exists($uri . '.gz') && !file_unmanaged_save_data(gzencode($data, 9, FORCE_GZIP), $uri . '.gz', FILE_EXISTS_REPLACE)) {
+//         return FALSE;
+//       }
+//     }
+
     // Save the updated map.
     $map[$key] = $uri;
-    variable_set($css_cache_var, $map);
+    // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// variable_set($css_cache_var, $map);
+
   }
   return $uri;
 }
diff --git a/cdn.basic.farfuture.inc b/cdn.basic.farfuture.inc
index 5a7f6b5..c0f3404 100644
--- a/cdn.basic.farfuture.inc
+++ b/cdn.basic.farfuture.inc
@@ -12,7 +12,7 @@
 function cdn_basic_farfuture_download($token, $ufi, $path) {
   // Validate the token to make sure this request originated from CDN.
   $path_info = pathinfo($path);
-  $sec_token = drupal_hmac_base64($ufi . $path_info['filename'], drupal_get_private_key() . drupal_get_hash_salt());
+  $sec_token = \Drupal\Component\Utility\Crypt::hmacBase64($ufi . $path_info['filename'], drupal_get_private_key() . drupal_get_hash_salt());
   if ($token != $sec_token) {
     header('HTTP/1.1 403 Forbidden');
     exit();
@@ -26,12 +26,7 @@ function cdn_basic_farfuture_download($token, $ufi, $path) {
   }
 
   if (!file_exists($path)) {
-    watchdog(
-      'cdn',
-      'CDN Far Future 404: %file.',
-      array('%file' => $path),
-      WATCHDOG_ALERT
-    );
+    \Drupal::logger('cdn')->alert('CDN Far Future 404: %file.', array('%file' => $path));
     header('HTTP/1.1 404 Not Found');
     exit();
   }
@@ -92,8 +87,13 @@ function cdn_basic_farfuture_download($token, $ufi, $path) {
   // If the extension of the file that's being served is one of the far future
   // extensions (by default: images, fonts and flash content), then cache it
   // in the far future.
-  $farfuture_extensions  = variable_get(CDN_BASIC_FARFUTURE_EXTENSIONS_VARIABLE, CDN_BASIC_FARFUTURE_EXTENSIONS_DEFAULT);
-  $extension = drupal_strtolower(pathinfo($path, PATHINFO_EXTENSION));
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $farfuture_extensions  = variable_get(CDN_BASIC_FARFUTURE_EXTENSIONS_VARIABLE, CDN_BASIC_FARFUTURE_EXTENSIONS_DEFAULT);
+
+  $extension = \Drupal\Component\Utility\Unicode::strtolower(pathinfo($path, PATHINFO_EXTENSION));
   if (in_array($extension, explode("\n", $farfuture_extensions))) {
     // Remove all previously set Cache-Control headers, because we're going to
     // override it. Since multiple Cache-Control headers might have been set,
@@ -129,7 +129,7 @@ function cdn_basic_farfuture_download($token, $ufi, $path) {
     if (in_array($extension, explode("\n", CDN_BASIC_FARFUTURE_GZIP_EXTENSIONS))) {
       // Ensure a gzipped version of the file is stored on disk, instead of
       // gzipping the file on every request.
-      $gzip_path = drupal_realpath('public://') . '/' . CDN_BASIC_FARFUTURE_GZIP_DIRECTORY . "/$path.$ufi.gz";
+      $gzip_path = \Drupal::service("file_system")->realpath('public://') . '/' . CDN_BASIC_FARFUTURE_GZIP_DIRECTORY . "/$path.$ufi.gz";
       if (!file_exists($gzip_path)) {
         _cdn_basic_farfuture_create_directory_structure(dirname($gzip_path));
         file_put_contents($gzip_path, gzencode(file_get_contents($path), 9));
@@ -158,7 +158,11 @@ function cdn_basic_farfuture_download($token, $ufi, $path) {
 }
 
 function cdn_basic_farfuture_reverseproxy_test($token) {
-  $reference_token = variable_get('cdn_reverse_proxy_test');
+  // @FIXME
+// Could not extract the default value because it is either indeterminate, or
+// not scalar. You'll need to provide a default value in
+// config/install/cdn.settings.yml and config/schema/cdn.schema.yml.
+$reference_token = \Drupal::config('cdn.settings')->get('cdn_reverse_proxy_test');
   if ($reference_token === FALSE || $token != $reference_token) {
     header('HTTP/1.1 403 Forbidden');
     exit();
@@ -191,7 +195,7 @@ function cdn_basic_farfuture_get_ufi_method($path, $mapping) {
   foreach (array_keys($mapping) as $directory) {
     if (drupal_match_path($path, $directory)) {
       // Parse the file extension from the given path; convert it to lower case.
-      $file_extension = drupal_strtolower(pathinfo($path, PATHINFO_EXTENSION));
+      $file_extension = \Drupal\Component\Utility\Unicode::strtolower(pathinfo($path, PATHINFO_EXTENSION));
 
       // Based on the file extension, determine which key should be used to find
       // the CDN URLs in the mapping lookup table, if any.
@@ -235,12 +239,17 @@ function cdn_basic_farfuture_get_identifier($path) {
 
   // Gather all unique file identifier info.
   if (!isset($ufi_info)) {
-    $ufi_info = module_invoke_all('cdn_unique_file_identifier_info');
+    $ufi_info = \Drupal::moduleHandler()->invokeAll('cdn_unique_file_identifier_info');
   }
 
   // We only need to parse the textual CDN mapping once into a lookup table.
   if (!isset($mapping)) {
-    $mapping = _cdn_basic_farfuture_parse_raw_mapping(variable_get(CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_VARIABLE, CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_DEFAULT));
+    // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $mapping = _cdn_basic_farfuture_parse_raw_mapping(variable_get(CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_VARIABLE, CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_DEFAULT));
+
   }
 
   $ufi_method = cdn_basic_farfuture_get_ufi_method($path, $mapping);
@@ -288,12 +297,12 @@ function _cdn_basic_farfuture_parse_raw_mapping($mapping_raw) {
       // - part 3: unique file identifier method
       if (count($parts) == 2) {
         $extensions = array('*'); // Use the asterisk as a wildcard.
-        $ufi_method = drupal_strtolower(trim($parts[1]));
+        $ufi_method = \Drupal\Component\Utility\Unicode::strtolower(trim($parts[1]));
       }
       elseif (count($parts) == 3) {
         // Convert to lower case, remove periods, whitespace and split on ' '.
-        $extensions = explode(' ', trim(str_replace('.', '', drupal_strtolower($parts[1]))));
-        $ufi_method = drupal_strtolower(trim($parts[2]));
+        $extensions = explode(' ', trim(str_replace('.', '', \Drupal\Component\Utility\Unicode::strtolower($parts[1]))));
+        $ufi_method = \Drupal\Component\Utility\Unicode::strtolower(trim($parts[2]));
       }
 
       // Create the mapping lookup table.
@@ -406,7 +415,7 @@ function _cdn_basic_farfuture_get_mimetype($path) {
   if (!isset($mapping)) {
     // The default file map, defined in file.mimetypes.inc is quite big.
     // We only load it when necessary.
-    include_once DRUPAL_ROOT . '/includes/file.mimetypes.inc';
+    include_once \Drupal::root() . '/includes/file.mimetypes.inc';
     $mapping = file_mimetype_mapping();
   }
 
@@ -422,7 +431,7 @@ function _cdn_basic_farfuture_get_mimetype($path) {
   //   - image.jpeg, and
   //   - awesome.image.jpeg
   while ($additional_part = array_pop($file_parts)) {
-    $extension = drupal_strtolower($additional_part . ($extension ? '.' . $extension : ''));
+    $extension = \Drupal\Component\Utility\Unicode::strtolower($additional_part . ($extension ? '.' . $extension : ''));
     if (isset($mapping['extensions'][$extension])) {
       return $mapping['mimetypes'][$mapping['extensions'][$extension]];
     }
@@ -442,9 +451,16 @@ function _cdn_basic_farfuture_get_mimetype($path) {
  */
 function _cdn_basic_farfuture_generate_file($path) {
   // Check if there's a file to generate in the first place!
-  if (!menu_get_item($path)) {
-    return FALSE;
-  }
+  // @FIXME
+// menu_get_item() has been removed. To retrieve route information, use the
+// RouteMatch object, which you can retrieve by calling \Drupal::routeMatch().
+// 
+// 
+// @see https://www.drupal.org/node/2203305
+// if (!menu_get_item($path)) {
+//     return FALSE;
+//   }
+
 
   // While it should already be impossible to enter recursion because of the
   // above menu system check, we still want to detect this just to be safe.
@@ -454,12 +470,12 @@ function _cdn_basic_farfuture_generate_file($path) {
   // 404, etc.
   // @see http://drupal.org/node/1417616#comment-5694960
   if (request_uri() == base_path() . $path) {
-    watchdog('cdn', 'Recursion detected for %file!', array('%file' => $path), WATCHDOG_ALERT);
+    \Drupal::logger('cdn')->alert('Recursion detected for %file!', array('%file' => $path));
     header('HTTP/1.1 404 Not Found');
     exit();
   }
 
-  $url = $GLOBALS['base_url'] . '/' . drupal_encode_path($path);
+  $url = $GLOBALS['base_url'] . '/' . \Drupal\Component\Utility\UrlHelper::encodePath($path);
 
   $headers = array(
     // Make sure we hit the server and do not end up with a stale
@@ -467,20 +483,23 @@ function _cdn_basic_farfuture_generate_file($path) {
     'Cache-Control' => 'no-cache',
     'Pragma'        => 'no-cache',
   );
-  drupal_http_request($url, array('headers' => $headers));
+  // @FIXME
+// drupal_http_request() has been replaced by the Guzzle HTTP client, which is bundled
+// with Drupal core.
+// 
+// 
+// @see https://www.drupal.org/node/1862446
+// @see http://docs.guzzlephp.org/en/latest
+// drupal_http_request($url, array('headers' => $headers));
+
 
   $exists = file_exists($path);
-  watchdog(
-    'cdn',
-    'Nested HTTP request to generate %file: %result (URL: %url, time: !time).',
-    array(
+  \Drupal::logger('cdn')-> watchdog_notice : watchdog_critical('Nested HTTP request to generate %file: %result (URL: %url, time: !time).', array(
       '!time'   => (int) $_SERVER['REQUEST_TIME'],
       '%file'   => $path,
       '%url'    => $url,
       '%result' => $exists ? 'success' : 'failure',
-    ),
-    $exists ? WATCHDOG_NOTICE : WATCHDOG_CRITICAL
-  );
+    ));
   return $exists;
 }
 
diff --git a/cdn.basic.inc b/cdn.basic.inc
index fae07c2..4a38a0f 100644
--- a/cdn.basic.inc
+++ b/cdn.basic.inc
@@ -25,7 +25,7 @@ function cdn_basic_get_servers($path) {
   }
 
   // Parse the file extension from the given path; convert it to lower case.
-  $file_extension = drupal_strtolower(pathinfo($path, PATHINFO_EXTENSION));
+  $file_extension = \Drupal\Component\Utility\Unicode::strtolower(pathinfo($path, PATHINFO_EXTENSION));
 
   // Based on the file extension, determine which key should be used to find
   // the CDN URLs in the mapping lookup table, if any.
@@ -60,14 +60,24 @@ function cdn_basic_get_servers($path) {
  * @return array
  */
 function cdn_basic_get_mapping() {
-  $https_mapping = variable_get(CDN_BASIC_MAPPING_HTTPS_VARIABLE, '');
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $https_mapping = variable_get(CDN_BASIC_MAPPING_HTTPS_VARIABLE, '');
+
   if (!empty($https_mapping) && cdn_serve_from_https()) {
     // if we have https mapping enabled and we are on a HTTPS page
     $mapping = $https_mapping;
   }
   else {
     // otherwise use the non-https mapping
-    $mapping = variable_get(CDN_BASIC_MAPPING_VARIABLE, '');
+    // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $mapping = variable_get(CDN_BASIC_MAPPING_VARIABLE, '');
+
   }
 
   return $mapping;
@@ -103,7 +113,7 @@ function _cdn_basic_parse_raw_mapping($mapping_raw) {
       if (strpos($line, '|') !== FALSE) {
         $parts = explode('|', $line);
         $cdn_urls = explode(' ', trim($parts[0]));
-        $extensions = explode(' ', trim(str_replace('.', '', drupal_strtolower($parts[1])))); // Convert to lower case, remove periods, whitespace and split on ' '.
+        $extensions = explode(' ', trim(str_replace('.', '', \Drupal\Component\Utility\Unicode::strtolower($parts[1])))); // Convert to lower case, remove periods, whitespace and split on ' '.
       }
       else {
         $cdn_urls   = explode(' ', trim($line));
diff --git a/cdn.constants.inc b/cdn.constants.inc
index 2f393e0..d465697 100644
--- a/cdn.constants.inc
+++ b/cdn.constants.inc
@@ -22,7 +22,7 @@ define('CDN_MODE_BASIC', 'basic');
 define('CDN_MODE_ADVANCED', 'advanced');
 define('CDN_STATUS_VARIABLE', 'cdn_status');
 define('CDN_STATS_VARIABLE', 'cdn_stats');
-define('CDN_DRUPAL_ROOT_VARIABLE', 'cdn_drupal_root');
+define('CDN_\Drupal::root()_VARIABLE', 'cdn_drupal_root');
 define('CDN_HTTPS_SUPPORT_VARIABLE', 'cdn_https_support');
 define('CDN_PICK_SERVER_PHP_CODE_VARIABLE', 'CDN_PICK_SERVER_PHP_CODE_VARIABLE');
 
diff --git a/cdn.fallback.inc b/cdn.fallback.inc
index e682b55..0206a0e 100644
--- a/cdn.fallback.inc
+++ b/cdn.fallback.inc
@@ -124,8 +124,8 @@ function _cdn_html_alter_file_url(&$html, $pattern, $search_index, $path_index,
     // changed and is not already root-relative or protocol-relative, then
     // generate a file URL as Drupal core would: prepend the base path.
     $old_path = $path;
-    drupal_alter('file_url', $path);
-    if ($path == $old_path && drupal_substr($path, 0, 1) != '/' && drupal_substr($path, 0, 2) != '//') {
+    \Drupal::moduleHandler()->alter('file_url', $path);
+    if ($path == $old_path && \Drupal\Component\Utility\Unicode::substr($path, 0, 1) != '/' && \Drupal\Component\Utility\Unicode::substr($path, 0, 2) != '//') {
       $path = base_path() . $path;
     }
 
diff --git a/cdn.info.yml b/cdn.info.yml
new file mode 100644
index 0000000..66a41dd
--- /dev/null
+++ b/cdn.info.yml
@@ -0,0 +1,5 @@
+name: CDN
+description: 'Integrates your site with a CDN, through altering file URLs.'
+core: 8.x
+package: 'Performance and scalability'
+type: module
diff --git a/cdn.install b/cdn.install
index 9c4ec43..3744135 100644
--- a/cdn.install
+++ b/cdn.install
@@ -20,14 +20,24 @@ function cdn_requirements($phase) {
   module_load_include('module', 'cdn');
 
   $requirements = array();
-  $t = get_t();
+  $t = 't';
 
   switch ($phase) {
     case 'install' :
     case 'runtime' :
       // CDN  status.
-      $status = variable_get(CDN_STATUS_VARIABLE, CDN_DISABLED);
-      $mode   = variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC);
+      // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $status = variable_get(CDN_STATUS_VARIABLE, CDN_DISABLED);
+
+      // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $mode   = variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC);
+
 
       $requirements['cdn']['title'] = $t('CDN');
 
@@ -62,16 +72,22 @@ function cdn_requirements($phase) {
       if ($status != CDN_DISABLED) {
         if ($mode == CDN_MODE_BASIC) {
           $requirements['cdn']['value'] .= ' – ' . t('Origin Pull mode');
-          $farfuture = variable_get(CDN_BASIC_FARFUTURE_VARIABLE, CDN_BASIC_FARFUTURE_DEFAULT);
-          $preprocess_css = variable_get('preprocess_css');
+          // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $farfuture = variable_get(CDN_BASIC_FARFUTURE_VARIABLE, CDN_BASIC_FARFUTURE_DEFAULT);
+
+          // @FIXME
+// // @FIXME
+// // This looks like another module's variable. You'll need to rewrite this call
+// // to ensure that it uses the correct configuration object.
+// $preprocess_css = variable_get('preprocess_css');
+
 
           if (!$preprocess_css) {
             $args = array(
-              '!preprocess-css-link' => l(
-                '"Aggregate and compress CSS files"',
-                'admin/config/development/performance',
-                array('fragment' => 'edit-bandwidth-optimization')
-              ),
+              '!preprocess-css-link' => \Drupal::l('"Aggregate and compress CSS files"', \Drupal\Core\Url::fromRoute('system.performance_settings')),
             );
             if ($farfuture) {
               $requirements['cdn']['description'] = t(
@@ -107,12 +123,27 @@ function cdn_requirements($phase) {
 
           $items = array();
 
-          $daemon_pid_file = variable_get(CDN_ADVANCED_PID_FILE_VARIABLE, FALSE);
-          $synced_files_db = variable_get(CDN_ADVANCED_SYNCED_FILES_DB_VARIABLE, FALSE);
+          // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $daemon_pid_file = variable_get(CDN_ADVANCED_PID_FILE_VARIABLE, FALSE);
+
+          // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $synced_files_db = variable_get(CDN_ADVANCED_SYNCED_FILES_DB_VARIABLE, FALSE);
+
 
           if ($synced_files_db !== FALSE) {
             $persistent_data_db = str_replace(CDN_DAEMON_SYNCED_FILES_DB, CDN_DAEMON_PERSISTENT_DATA_DB, $synced_files_db);
-            $drupal_root_path = variable_get(CDN_DRUPAL_ROOT_VARIABLE, realpath('.'));
+            // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $drupal_root_path = variable_get(CDN_\Drupal::root()_VARIABLE, realpath('.'));
+
 
             $synced_files_db_exists      = file_exists($synced_files_db);
             $synced_files_db_readable    = @fopen($synced_files_db, 'r');
@@ -185,7 +216,7 @@ function cdn_requirements($phase) {
             $requirements['cdn']['severity'] = REQUIREMENT_ERROR;
           }
 
-          $requirements['cdn']['description'] .= '<br />' . theme('item_list', array('items' => $items));
+          $requirements['cdn']['description'] .= '<br />' . _theme('item_list', array('items' => $items));
         }
       }
   }
@@ -202,17 +233,17 @@ function cdn_requirements($phase) {
  * than in version 1: there now is the ability to have multiple CDN URLs.
  */
 function cdn_update_6200() {
-  $url  = variable_get('cdn_basic_url', '');
-  $exts = variable_get('cdn_basic_extensions', '');
+  $url  = \Drupal::config('cdn.settings')->get('cdn_basic_url');
+  $exts = \Drupal::config('cdn.settings')->get('cdn_basic_extensions');
 
   // Store URL variable in new format, then delete old variables.
   $cdn_basic_mapping = $url;
   if (!empty($exts)) {
     $cdn_basic_mapping .= '|' . $exts;
   }
-  variable_set('cdn_basic_mapping', $url . '|' . $exts);
-  variable_del('cdn_basic_url');
-  variable_del('cdn_basic_extensions');
+  \Drupal::configFactory()->getEditable('cdn.settings')->set('cdn_basic_mapping', $url . '|' . $exts)->save();
+  \Drupal::config('cdn.settings')->clear('cdn_basic_url')->save();
+  \Drupal::config('cdn.settings')->clear('cdn_basic_extensions')->save();
 
   return t('Updated variables to allow for multiple Origin Pull CDN URLs instead of just one.');
 }
@@ -221,16 +252,24 @@ function cdn_update_6200() {
  * More consistent variable names: upgrade path.
  */
 function cdn_update_6201() {
-  $cdn_exception_path_blacklist = variable_get('cdn_exclusion');
-  variable_del('cdn_exclusion');
+  // @FIXME
+// Could not extract the default value because it is either indeterminate, or
+// not scalar. You'll need to provide a default value in
+// config/install/cdn.settings.yml and config/schema/cdn.schema.yml.
+$cdn_exception_path_blacklist = \Drupal::config('cdn.settings')->get('cdn_exclusion');
+  \Drupal::config('cdn.settings')->clear('cdn_exclusion')->save();
   if (isset($cdn_exception_path_blacklist)) {
-    variable_set('cdn_exception_path_blacklist', $cdn_exception_path_blacklist);
+    \Drupal::configFactory()->getEditable('cdn.settings')->set('cdn_exception_path_blacklist', $cdn_exception_path_blacklist)->save();
   }
 
-  $cdn_exception_auth_users_blacklist = variable_get('cdn_exclusion_logged_in');
-  variable_del('cdn_exclusion_logged_in');
+  // @FIXME
+// Could not extract the default value because it is either indeterminate, or
+// not scalar. You'll need to provide a default value in
+// config/install/cdn.settings.yml and config/schema/cdn.schema.yml.
+$cdn_exception_auth_users_blacklist = \Drupal::config('cdn.settings')->get('cdn_exclusion_logged_in');
+  \Drupal::config('cdn.settings')->clear('cdn_exclusion_logged_in')->save();
   if (isset($cdn_exception_auth_users_blacklist)) {
-    variable_set('cdn_exception_auth_users_blacklist', $cdn_exception_auth_users_blacklist);
+    \Drupal::configFactory()->getEditable('cdn.settings')->set('cdn_exception_auth_users_blacklist', $cdn_exception_auth_users_blacklist)->save();
   }
 
   return t('Updated variables (internal name changes only, for improved consistency).');
@@ -270,13 +309,13 @@ function cdn_update_7200() {
 function cdn_update_7210() {
   $ret = array();
 
-  if (variable_get('cdn_mode', FALSE) == 'advanced') {
+  if (\Drupal::config('cdn.settings')->get('cdn_mode') == 'advanced') {
     // Only do this if cdn_update_6210() for the Drupal 6 version of this
     // module hasn't run.
-    if (variable_get('cdn_advanced_pid_file', FALSE) != FALSE) {
-      $synced_files_db = variable_get('cdn_advanced_synced_files_db', FALSE);
+    if (\Drupal::config('cdn.settings')->get('cdn_advanced_pid_file') != FALSE) {
+      $synced_files_db = \Drupal::config('cdn.settings')->get('cdn_advanced_synced_files_db');
       $daemon_pid_file = str_replace('synced_files.db', 'daemon.pid', $synced_files_db);
-      variable_set('cdn_advanced_pid_file', $daemon_pid_file);
+      \Drupal::configFactory()->getEditable('cdn.settings')->set('cdn_advanced_pid_file', $daemon_pid_file)->save();
 
       $ret[] = array('success' => TRUE, 'query' => 'Created File Conveyor PID file variable.');
     }
diff --git a/cdn.module b/cdn.module
index a2ccc88..24cfe28 100644
--- a/cdn.module
+++ b/cdn.module
@@ -16,11 +16,36 @@ require_once('cdn.constants.inc');
  * Implements hook_file_url_alter().
  */
 function cdn_file_url_alter(&$original_uri) {
-  $mode                  = variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC);
-  $farfuture             = variable_get(CDN_BASIC_FARFUTURE_VARIABLE, CDN_BASIC_FARFUTURE_DEFAULT);
-  $stats                 = variable_get(CDN_STATS_VARIABLE, FALSE) && user_access(CDN_PERM_ACCESS_STATS);
-  $https_support         = variable_get(CDN_HTTPS_SUPPORT_VARIABLE, FALSE);
-  $maintenance_mode      = variable_get('maintenance_mode', FALSE);
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $mode                  = variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC);
+
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $farfuture             = variable_get(CDN_BASIC_FARFUTURE_VARIABLE, CDN_BASIC_FARFUTURE_DEFAULT);
+
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $stats                 = variable_get(CDN_STATS_VARIABLE, FALSE) && \Drupal::currentUser()->hasPermission(CDN_PERM_ACCESS_STATS);
+
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $https_support         = variable_get(CDN_HTTPS_SUPPORT_VARIABLE, FALSE);
+
+  // @FIXME
+// // @FIXME
+// // This looks like another module's variable. You'll need to rewrite this call
+// // to ensure that it uses the correct configuration object.
+// $maintenance_mode      = variable_get('maintenance_mode', FALSE);
+
   $is_https_page         = cdn_request_is_https();
 
   // Don't alter file URLs when running update.php.
@@ -29,12 +54,12 @@ function cdn_file_url_alter(&$original_uri) {
   }
 
   if (cdn_status_is_enabled()) {
-    $scheme = file_uri_scheme($original_uri);
+    $scheme = \Drupal::service("file_system")->uriScheme($original_uri);
 
     // If the current URI is an absolute or protocol-relative URI, return
     // immediately.
     if (($scheme && ($scheme == 'http' || $scheme == 'https'))
-        || drupal_substr($original_uri, 0, 2) == '//'
+        || \Drupal\Component\Utility\Unicode::substr($original_uri, 0, 2) == '//'
        )
     {
       return;
@@ -42,13 +67,13 @@ function cdn_file_url_alter(&$original_uri) {
     elseif ($scheme) {
       // Only alter URLs for local stream wrappers. If a file is served
       // remotely, it doesn't make sense to serve it from a CDN.
-      $local_schemes = array_keys(file_get_stream_wrappers(STREAM_WRAPPERS_LOCAL));
+      $local_schemes = array_keys(\Drupal::service("stream_wrapper_manager")->getWrappers(STREAM_WRAPPERS_LOCAL));
       if (!in_array($scheme, $local_schemes)) {
         return;
       }
 
       // Attempt to get an external URL using the appropriate wrapper.
-      if ($wrapper = file_stream_wrapper_get_instance_by_uri($original_uri)) {
+      if ($wrapper = \Drupal::service("stream_wrapper_manager")->getViaUri($original_uri)) {
         $uri = str_replace($GLOBALS['base_url'] . '/', '', $wrapper->getExternalUrl());
       }
       else {
@@ -62,7 +87,7 @@ function cdn_file_url_alter(&$original_uri) {
     if (!cdn_check_protocol()) {
       return;
     }
-    if (!cdn_check_drupal_path(current_path())) {
+    if (!cdn_check_drupal_path(\Drupal\Core\Url::fromRoute("<current>")->toString())) {
       return;
     }
     if (!cdn_check_file($uri)) {
@@ -85,13 +110,13 @@ function cdn_file_url_alter(&$original_uri) {
       // generate the derivative file.) When that fails, don't serve it from
       // the CDN.
       if (!file_exists($uri) && !_cdn_basic_farfuture_generate_file($uri)) {
-        $path = drupal_encode_path($uri);
+        $path = \Drupal\Component\Utility\UrlHelper::encodePath($uri);
         return;
       }
       // Generate a unique file identifier (UFI).
       $ufi = cdn_basic_farfuture_get_identifier($uri);
       // Now that file operations have been performed, re-encode the URI.
-      $uri = drupal_encode_path($uri);
+      $uri = \Drupal\Component\Utility\UrlHelper::encodePath($uri);
       // Generate the new path.
       $uri_before_farfuture = $uri;
 
@@ -99,7 +124,7 @@ function cdn_file_url_alter(&$original_uri) {
       // CDN. We cannot use drupal_get_token() since it depends on the user
       // session.
       $path_info = pathinfo(urldecode($uri));
-      $token = drupal_hmac_base64($ufi . $path_info['filename'], drupal_get_private_key() . drupal_get_hash_salt());
+      $token = \Drupal\Component\Utility\Crypt::hmacBase64($ufi . $path_info['filename'], drupal_get_private_key() . drupal_get_hash_salt());
       $uri = "cdn/farfuture/$token/$ufi/$uri";
     }
 
@@ -112,42 +137,47 @@ function cdn_file_url_alter(&$original_uri) {
     $servers = ($mode == CDN_MODE_BASIC) ? cdn_basic_get_servers($uri) : cdn_advanced_get_servers($uri);
 
     // The file is not available on any server.
-    if (count($servers) == 0) {
-      $cdn_url    = FALSE;
-      $server = FALSE;
-    }
-    // If the file is available from multiple servers, then allow a special
-    // function to pick the desired server. The decision can be made on any
-    // desired criteria: user's location, user's role, current date …
-    elseif (count($servers) > 1 && function_exists('cdn_pick_server')) {
-      $picked_server = cdn_pick_server($servers);
-      $cdn_url = $picked_server['url'];
-      $server  = $picked_server['server'];
-    }
-    // Allow this special function to be defined as a Drupal variable; this
-    // Drupal variable then contains the body of this function. This is handy
-    // for experimentation and novice Drupal users.
-    elseif (count($servers) > 1 && variable_get(CDN_PICK_SERVER_PHP_CODE_VARIABLE, '') !== '') {
-      $php_code = variable_get(CDN_PICK_SERVER_PHP_CODE_VARIABLE, '');
-      $picked_server = _cdn_eval_pick_server($php_code, $servers);
-      $cdn_url = $picked_server['url'];
-      $server  = $picked_server['server'];
-    }
-    // The file is available from multiple servers; pick a server randomly
-    // (yet consistently: this uses consistent hashing!), so that each server
-    // will serve approximately the same number of files.
-    elseif (count($servers > 1)) {
-      $filename = basename($servers[0]['url']);
-      $unique_file_id = hexdec(substr(md5($filename), 0, 5));
-      $choice = $unique_file_id % count($servers);
-      $cdn_url = $servers[$choice]['url'];
-      $server  = $servers[$choice]['server'];
-    }
-    // The file is only avaible from one server.
-    else {
-      $cdn_url = $servers[0]['url'];
-      $server  = $servers[0]['server'];
-    }
+    // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// if (count($servers) == 0) {
+//       $cdn_url    = FALSE;
+//       $server = FALSE;
+//     }
+//     // If the file is available from multiple servers, then allow a special
+//     // function to pick the desired server. The decision can be made on any
+//     // desired criteria: user's location, user's role, current date …
+//     elseif (count($servers) > 1 && function_exists('cdn_pick_server')) {
+//       $picked_server = cdn_pick_server($servers);
+//       $cdn_url = $picked_server['url'];
+//       $server  = $picked_server['server'];
+//     }
+//     // Allow this special function to be defined as a Drupal variable; this
+//     // Drupal variable then contains the body of this function. This is handy
+//     // for experimentation and novice Drupal users.
+//     elseif (count($servers) > 1 && variable_get(CDN_PICK_SERVER_PHP_CODE_VARIABLE, '') !== '') {
+//       $php_code = variable_get(CDN_PICK_SERVER_PHP_CODE_VARIABLE, '');
+//       $picked_server = _cdn_eval_pick_server($php_code, $servers);
+//       $cdn_url = $picked_server['url'];
+//       $server  = $picked_server['server'];
+//     }
+//     // The file is available from multiple servers; pick a server randomly
+//     // (yet consistently: this uses consistent hashing!), so that each server
+//     // will serve approximately the same number of files.
+//     elseif (count($servers > 1)) {
+//       $filename = basename($servers[0]['url']);
+//       $unique_file_id = hexdec(substr(md5($filename), 0, 5));
+//       $choice = $unique_file_id % count($servers);
+//       $cdn_url = $servers[$choice]['url'];
+//       $server  = $servers[$choice]['server'];
+//     }
+//     // The file is only avaible from one server.
+//     else {
+//       $cdn_url = $servers[0]['url'];
+//       $server  = $servers[0]['server'];
+//     }
+
 
     // If the current page is being served via HTTPS, and the CDN supports
     // HTTPS, then use the HTTPS file URL.
@@ -175,64 +205,69 @@ function cdn_file_url_alter(&$original_uri) {
  */
 function cdn_cdn_unique_file_identifier_info() {
   // Keys are machine names.
-  return array(
-    'md5_hash' => array(
-      'label'        => t('MD5 hash'),
-      'prefix'       => 'md5',
-      'description'  => t('MD5 hash of the file.'),
-      'filesystem'   => TRUE,
-      'callback'     => 'md5_file',
-    ),
-    'mtime' => array(
-      'label'        => t('Last modification time'),
-      'prefix'       => 'mtime',
-      'description'  => t('Last modification time of the file.'),
-      'filesystem'   => TRUE,
-      'callback'     => 'filemtime',
-    ),
-    'perpetual' => array(
-      'label'        => t('Perpetual'),
-      'prefix'       => 'perpetual',
-      'description'  => t('Perpetual files never change (or are never cached
-                          by the browser, e.g. video files).'),
-      'filesystem'   => FALSE,
-      'value'        => 'forever',
-    ),
-    'drupal_version' => array(
-      'label'        => t('Drupal version'),
-      'prefix'       => 'drupal',
-      'description'  => t('Drupal core version — this should only be applied
-                          to files that ship with Drupal core.'),
-      'filesystem'   => FALSE,
-      'value'        => VERSION,
-    ),
-    'drupal_cache' => array(
-      'label'        => t('Drupal cache'),
-      'prefix'       => 'drupal-cache',
-      'description'  => t('Uses the current Drupal cache ID
-                          (<code>css_js_query_string</code>). This ID is
-                          updated automatically whenever the Drupal cache is
-                          flushed (e.g. when you submit the modules form). Be
-                          aware that this can change relatively often, forcing
-                          redownloads by your visitors.'),
-      'filesystem'   => FALSE,
-      'value'        => variable_get('css_js_query_string', 0),
-    ),
-    'deployment_id' => array(
-      'label'        => t('Deployment ID'),
-      'prefix'       => 'deployment',
-      'description'  => t('A developer-defined deployment ID. Can be an
-                          arbitrary string or number, as long as it uniquely
-                          identifies deployments and therefore the affected
-                          files.<br />
-                          Define this deployment ID in any enabled module or
-                          in <code>settings.php</code> as the
-                          <code>CDN_DEPLOYMENT_ID</code>
-                          constant, and it will be picked up instantaneously.'),
-      'filesystem'   => FALSE,
-      'callback'     => '_cdn_ufi_deployment_id',
-    ),
-  );
+  // @FIXME
+// // @FIXME
+// // This looks like another module's variable. You'll need to rewrite this call
+// // to ensure that it uses the correct configuration object.
+// return array(
+//     'md5_hash' => array(
+//       'label'        => t('MD5 hash'),
+//       'prefix'       => 'md5',
+//       'description'  => t('MD5 hash of the file.'),
+//       'filesystem'   => TRUE,
+//       'callback'     => 'md5_file',
+//     ),
+//     'mtime' => array(
+//       'label'        => t('Last modification time'),
+//       'prefix'       => 'mtime',
+//       'description'  => t('Last modification time of the file.'),
+//       'filesystem'   => TRUE,
+//       'callback'     => 'filemtime',
+//     ),
+//     'perpetual' => array(
+//       'label'        => t('Perpetual'),
+//       'prefix'       => 'perpetual',
+//       'description'  => t('Perpetual files never change (or are never cached
+//                           by the browser, e.g. video files).'),
+//       'filesystem'   => FALSE,
+//       'value'        => 'forever',
+//     ),
+//     'drupal_version' => array(
+//       'label'        => t('Drupal version'),
+//       'prefix'       => 'drupal',
+//       'description'  => t('Drupal core version — this should only be applied
+//                           to files that ship with Drupal core.'),
+//       'filesystem'   => FALSE,
+//       'value'        => VERSION,
+//     ),
+//     'drupal_cache' => array(
+//       'label'        => t('Drupal cache'),
+//       'prefix'       => 'drupal-cache',
+//       'description'  => t('Uses the current Drupal cache ID
+//                           (<code>css_js_query_string</code>). This ID is
+//                           updated automatically whenever the Drupal cache is
+//                           flushed (e.g. when you submit the modules form). Be
+//                           aware that this can change relatively often, forcing
+//                           redownloads by your visitors.'),
+//       'filesystem'   => FALSE,
+//       'value'        => variable_get('css_js_query_string', 0),
+//     ),
+//     'deployment_id' => array(
+//       'label'        => t('Deployment ID'),
+//       'prefix'       => 'deployment',
+//       'description'  => t('A developer-defined deployment ID. Can be an
+//                           arbitrary string or number, as long as it uniquely
+//                           identifies deployments and therefore the affected
+//                           files.<br />
+//                           Define this deployment ID in any enabled module or
+//                           in <code>settings.php</code> as the
+//                           <code>CDN_DEPLOYMENT_ID</code>
+//                           constant, and it will be picked up instantaneously.'),
+//       'filesystem'   => FALSE,
+//       'callback'     => '_cdn_ufi_deployment_id',
+//     ),
+//   );
+
 }
 
 /**
@@ -243,7 +278,12 @@ function cdn_element_info_alter(&$type) {
     return;
   }
 
-  $mode = variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC);
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $mode = variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC);
+
   if ($mode == CDN_MODE_BASIC) {
     // Override Drupal's CSS aggregation system.
     cdn_load_include('basic.css');
@@ -427,11 +467,24 @@ function cdn_init() {
 
   // When per-page statistics are enabled, add the CSS that will be used to
   // make these statistics more usable.
-  if (variable_get(CDN_STATS_VARIABLE, FALSE)
-      && user_access(CDN_PERM_ACCESS_STATS)
-  ) {
-    drupal_add_css(drupal_get_path('module', 'cdn') . '/cdn.css', array('every_page' => TRUE));
-  }
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// if (variable_get(CDN_STATS_VARIABLE, FALSE)
+//       && \Drupal::currentUser()->hasPermission(CDN_PERM_ACCESS_STATS)
+//   ) {
+//     // @FIXME
+// // The Assets API has totally changed. CSS, JavaScript, and libraries are now
+// // attached directly to render arrays using the #attached property.
+// //
+// //
+// // @see https://www.drupal.org/node/2169605
+// // @see https://www.drupal.org/node/2408597
+// // drupal_add_css(drupal_get_path('module', 'cdn') . '/cdn.css', array('every_page' => TRUE));
+// 
+//   }
+
 }
 
 /**
@@ -451,28 +504,33 @@ function cdn_exit($destination = NULL) {
     return;
   }
 
-  if (!$destination
-      && variable_get(CDN_STATUS_VARIABLE, CDN_DISABLED) != CDN_DISABLED
-      && variable_get(CDN_STATS_VARIABLE, FALSE)
-      && user_access(CDN_PERM_ACCESS_STATS)
-  ) {
-    list(
-      $file_count,
-      $cdn_file_count,
-      $synced_files_per_server_count,
-      $total_time,
-      $synced_files,
-      $unsynced_files,
-    ) = _cdn_devel_page_stats();
-    print theme('cdn_page_stats', array(
-      'file_count'                    => $file_count,
-      'cdn_file_count'                => $cdn_file_count,
-      'synced_files_per_server_count' => $synced_files_per_server_count,
-      'total_time'                    => $total_time,
-      'synced_files'                  => $synced_files,
-      'unsynced_files'                => $unsynced_files
-    ));
-  }
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// if (!$destination
+//       && variable_get(CDN_STATUS_VARIABLE, CDN_DISABLED) != CDN_DISABLED
+//       && variable_get(CDN_STATS_VARIABLE, FALSE)
+//       && \Drupal::currentUser()->hasPermission(CDN_PERM_ACCESS_STATS)
+//   ) {
+//     list(
+//       $file_count,
+//       $cdn_file_count,
+//       $synced_files_per_server_count,
+//       $total_time,
+//       $synced_files,
+//       $unsynced_files,
+//     ) = _cdn_devel_page_stats();
+//     print theme('cdn_page_stats', array(
+//       'file_count'                    => $file_count,
+//       'cdn_file_count'                => $cdn_file_count,
+//       'synced_files_per_server_count' => $synced_files_per_server_count,
+//       'total_time'                    => $total_time,
+//       'synced_files'                  => $synced_files,
+//       'unsynced_files'                => $unsynced_files
+//     ));
+//   }
+
 }
 
 /**
@@ -483,11 +541,11 @@ function cdn_flush_caches() {
   cdn_get_blacklist(TRUE);
 
   // Clear aggregated CSS files for pages served via HTTP.
-  variable_del('cdn_css_cache_files_http');
+  \Drupal::config('cdn.settings')->clear('cdn_css_cache_files_http')->save();
   file_scan_directory('public://cdn/css/http', '/.*/', array('callback' => 'drupal_delete_file_if_stale'));
 
   // Clear aggregated CSS files for pages served via HTTPS.
-  variable_del('cdn_css_cache_files_https');
+  \Drupal::config('cdn.settings')->clear('cdn_css_cache_files_https')->save();
   file_scan_directory('public://cdn/css/https', '/.*/', array('callback' => 'drupal_delete_file_if_stale'));
 }
 
@@ -498,7 +556,7 @@ function cdn_cdn_blacklist() {
   $blacklist = array();
 
   // Blacklist wysiwyg library files.
-  if (module_exists('wysiwyg')) {
+  if (\Drupal::moduleHandler()->moduleExists('wysiwyg')) {
     foreach (wysiwyg_get_all_editors() as $editor) {
       if (!$editor['installed']) {
         continue;
@@ -526,7 +584,12 @@ function cdn_cdn_blacklist() {
 function cdn_cacheaudit() {
   $results = array(array('Settings', 'Value'));
 
-  $status = variable_get(CDN_STATUS_VARIABLE, CDN_DISABLED);
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $status = variable_get(CDN_STATUS_VARIABLE, CDN_DISABLED);
+
   if ($status == CDN_ENABLED) {
     $status_value = 'enabled';
   }
@@ -538,13 +601,23 @@ function cdn_cacheaudit() {
   }
   $results[] = array('Status', $status_value);
 
-  $mode = variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC);
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $mode = variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC);
+
   $results[] = array('Mode', $mode ? 'Origin Pull' : 'File Conveyor');
 
   if ($mode == CDN_MODE_BASIC) {
     cdn_load_include('basic');
     $results[] = array('    mappings', count(_cdn_basic_parse_raw_mapping(cdn_basic_get_mapping())));
-    $results[] = array('    Far Future expiration', variable_get(CDN_BASIC_FARFUTURE_VARIABLE, CDN_BASIC_FARFUTURE_DEFAULT));
+    // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $results[] = array('    Far Future expiration', variable_get(CDN_BASIC_FARFUTURE_VARIABLE, CDN_BASIC_FARFUTURE_DEFAULT));
+
   }
 
   $results[] = array('Domains', count(cdn_get_domains()));
@@ -567,56 +640,61 @@ function cdn_get_domains() {
   $domains = array();
 
   // Origin Pull mode domains.
-  if (variable_get(CDN_MODE_VARIABLE, FALSE) == CDN_MODE_BASIC) {
-    cdn_load_include('basic');
-    $mapping = cdn_basic_get_mapping();
-    $lines = preg_split("/[\n\r]+/", $mapping, -1, PREG_SPLIT_NO_EMPTY);
-    foreach ($lines as $line) {
-      // Ignore empty lines.
-      $line = trim($line);
-      if (empty($line)) {
-        continue;
-      }
-
-      // Parse this line. It may or may not limit the CDN URL to a list of
-      // file extensions.
-      $parts = explode('|', $line);
-      // It may also list more than one domain.
-      foreach (explode(' ', $parts[0]) as $part) {
-        // Remove white space.
-        $part = trim($part);
-        // Allow for protocol-relative domains. We prepend "http:", otherwise
-        // parse_url() won't return anything.
-        if (strpos($part, '//') === 0) {
-          $part = 'http:' . $part;
-        }
-        $domains[] = parse_url($part, PHP_URL_HOST);
-      }
-    }
-  }
-  // File Conveyor mode domains.
-  elseif (variable_get(CDN_MODE_VARIABLE, FALSE) == CDN_MODE_ADVANCED) {
-    cdn_load_include('advanced');
-    $db = _cdn_advanced_get_db_connection();
-
-    // In case no connection to the database could be made, pretend no
-    // domains are being used.
-    if (!$db) {
-      return array();
-    }
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// if (variable_get(CDN_MODE_VARIABLE, FALSE) == CDN_MODE_BASIC) {
+//     cdn_load_include('basic');
+//     $mapping = cdn_basic_get_mapping();
+//     $lines = preg_split("/[\n\r]+/", $mapping, -1, PREG_SPLIT_NO_EMPTY);
+//     foreach ($lines as $line) {
+//       // Ignore empty lines.
+//       $line = trim($line);
+//       if (empty($line)) {
+//         continue;
+//       }
+// 
+//       // Parse this line. It may or may not limit the CDN URL to a list of
+//       // file extensions.
+//       $parts = explode('|', $line);
+//       // It may also list more than one domain.
+//       foreach (explode(' ', $parts[0]) as $part) {
+//         // Remove white space.
+//         $part = trim($part);
+//         // Allow for protocol-relative domains. We prepend "http:", otherwise
+//         // parse_url() won't return anything.
+//         if (strpos($part, '//') === 0) {
+//           $part = 'http:' . $part;
+//         }
+//         $domains[] = parse_url($part, PHP_URL_HOST);
+//       }
+//     }
+//   }
+//   // File Conveyor mode domains.
+//   elseif (variable_get(CDN_MODE_VARIABLE, FALSE) == CDN_MODE_ADVANCED) {
+//     cdn_load_include('advanced');
+//     $db = _cdn_advanced_get_db_connection();
+// 
+//     // In case no connection to the database could be made, pretend no
+//     // domains are being used.
+//     if (!$db) {
+//       return array();
+//     }
+// 
+//     // Retrieve all unique domains (by retrieving one URL per server) and then
+//     // parsing the domain names in those URLs.
+//     $sql = "SELECT url
+//             FROM synced_files
+//             GROUP BY server";
+//     $stmt = $db->prepare($sql);
+//     $stmt->execute();
+//     $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+//     foreach ($rows as $row) {
+//       $domains[] = parse_url($row['url'], PHP_URL_HOST);
+//     }
+//   }
 
-    // Retrieve all unique domains (by retrieving one URL per server) and then
-    // parsing the domain names in those URLs.
-    $sql = "SELECT url
-            FROM synced_files
-            GROUP BY server";
-    $stmt = $db->prepare($sql);
-    $stmt->execute();
-    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
-    foreach ($rows as $row) {
-      $domains[] = parse_url($row['url'], PHP_URL_HOST);
-    }
-  }
 
   return array_unique($domains);
 }
@@ -639,13 +717,13 @@ function cdn_get_blacklist($reset = FALSE) {
   static $blacklist = NULL;
 
   if (is_null($blacklist) || $reset) {
-    $cache = cache_get('cdn_blacklist');
+    $cache = \Drupal::cache()->get('cdn_blacklist');
     if (!isset($cache->data) || $reset) {
       // Query modules for a list of files to be included into the blacklist.
-      $blacklist = module_invoke_all('cdn_blacklist');
+      $blacklist = \Drupal::moduleHandler()->invokeAll('cdn_blacklist');
 
       // Invoke hook_cdn_blacklist_alter.
-      drupal_alter('cdn_blacklist', $blacklist);
+      \Drupal::moduleHandler()->alter('cdn_blacklist', $blacklist);
 
       // Remove duplicates.
       $blacklist = array_unique($blacklist);
@@ -654,7 +732,7 @@ function cdn_get_blacklist($reset = FALSE) {
       $blacklist = implode("\n", $blacklist);
 
       // Save to the cache.
-      cache_set('cdn_blacklist', $blacklist, 'cache', CACHE_TEMPORARY);
+      \Drupal::cache('cache')->set('cdn_blacklist', $blacklist, CACHE_TEMPORARY);
     }
     else {
       $blacklist = $cache->data;
@@ -668,8 +746,13 @@ function cdn_get_blacklist($reset = FALSE) {
  * Check if CDN module should serve files from a HTTPS location.
  */
 function cdn_serve_from_https() {
-  return variable_get(CDN_HTTPS_SUPPORT_VARIABLE, FALSE)
-         && cdn_request_is_https();
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// return variable_get(CDN_HTTPS_SUPPORT_VARIABLE, FALSE)
+//          && cdn_request_is_https();
+
 }
 
 /**
@@ -695,10 +778,15 @@ function cdn_request_is_https() {
  * Check if the CDN module is enabled.
  */
 function cdn_status_is_enabled() {
-  $status = variable_get(CDN_STATUS_VARIABLE, CDN_DISABLED);
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $status = variable_get(CDN_STATUS_VARIABLE, CDN_DISABLED);
+
   return $status == CDN_ENABLED
          ||
-         ($status == CDN_TESTING && user_access(CDN_PERM_ACCESS_TESTING));
+         ($status == CDN_TESTING && \Drupal::currentUser()->hasPermission(CDN_PERM_ACCESS_TESTING));
 }
 
 /**
@@ -707,7 +795,12 @@ function cdn_status_is_enabled() {
  * Note: currently only checks HTTPS, in the future possibly also SPDY.
  */
 function cdn_check_protocol() {
-  $https_support = variable_get(CDN_HTTPS_SUPPORT_VARIABLE, FALSE);
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $https_support = variable_get(CDN_HTTPS_SUPPORT_VARIABLE, FALSE);
+
 
   // If the current page is being served via HTTPS, and the CDN does not
   // support HTTPS, then don't rewrite the file URL, because it would make the
@@ -727,9 +820,19 @@ function cdn_check_protocol() {
  *   A Drupal path.
  */
 function cdn_check_drupal_path($path) {
-  global $user;
-  $blacklist       = variable_get(CDN_EXCEPTION_DRUPAL_PATH_BLACKLIST_VARIABLE, CDN_EXCEPTION_DRUPAL_PATH_BLACKLIST_DEFAULT);
-  $auth_blacklist  = variable_get(CDN_EXCEPTION_AUTH_USERS_BLACKLIST_VARIABLE, CDN_EXCEPTION_AUTH_USERS_BLACKLIST_DEFAULT);
+  $user = \Drupal::currentUser();
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $blacklist       = variable_get(CDN_EXCEPTION_DRUPAL_PATH_BLACKLIST_VARIABLE, CDN_EXCEPTION_DRUPAL_PATH_BLACKLIST_DEFAULT);
+
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $auth_blacklist  = variable_get(CDN_EXCEPTION_AUTH_USERS_BLACKLIST_VARIABLE, CDN_EXCEPTION_AUTH_USERS_BLACKLIST_DEFAULT);
+
 
   // Check if the Drupal path matches one of the blacklisted Drupal paths.
   if (drupal_match_path($path, $blacklist)) {
@@ -751,8 +854,18 @@ function cdn_check_drupal_path($path) {
  *   A file URI.
  */
 function cdn_check_file($uri) {
-  $file_path_blacklist = variable_get(CDN_EXCEPTION_FILE_PATH_BLACKLIST_VARIABLE, CDN_EXCEPTION_FILE_PATH_BLACKLIST_DEFAULT);
-  $file_path_whitelist = variable_get(CDN_EXCEPTION_FILE_PATH_WHITELIST_VARIABLE, CDN_EXCEPTION_FILE_PATH_WHITELIST_DEFAULT);
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $file_path_blacklist = variable_get(CDN_EXCEPTION_FILE_PATH_BLACKLIST_VARIABLE, CDN_EXCEPTION_FILE_PATH_BLACKLIST_DEFAULT);
+
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $file_path_whitelist = variable_get(CDN_EXCEPTION_FILE_PATH_WHITELIST_VARIABLE, CDN_EXCEPTION_FILE_PATH_WHITELIST_DEFAULT);
+
   $module_blacklist    = cdn_get_blacklist();
 
   // A file should not be served from a CDN when it matches one of the
diff --git a/cdn.permissions.yml b/cdn.permissions.yml
new file mode 100644
index 0000000..69f2f30
--- /dev/null
+++ b/cdn.permissions.yml
@@ -0,0 +1,11 @@
+'administer CDN configuration':
+  title: 'Administer CDN configuration settings'
+  'restrict access': true
+'access per-page statistics':
+  title: 'Access per-page statistics'
+'access files on CDN when in testing mode':
+  title: 'Access files on the CDN when in testing mode'
+  description: "Users with this permission will get files from the\n                          CDN when testing mode is enabled."
+'touch files':
+  title: 'Touch files'
+  description: "'Touch' files through the links provided by the\n                          per-page statistics. This will change the last\n                          modification time of the file, and depending on your\n                          set-up, may cause a resync of the file."
diff --git a/cdn.services.yml b/cdn.services.yml
new file mode 100644
index 0000000..c0f87d3
--- /dev/null
+++ b/cdn.services.yml
@@ -0,0 +1,11 @@
+services:
+  exit_subscriber:
+    class: Drupal\cdn\EventSubscriber\ExitSubscriber
+    tags:
+      -
+        name: event_subscriber
+  init_subscriber:
+    class: Drupal\cdn\EventSubscriber\InitSubscriber
+    tags:
+      -
+        name: event_subscriber
diff --git a/cdn.stats.inc b/cdn.stats.inc
index 3ed0e41..7fa1a13 100644
--- a/cdn.stats.inc
+++ b/cdn.stats.inc
@@ -148,8 +148,8 @@ function _cdn_get_absolute_path($uri) {
   }
 
   $absolute_path = '';
-  if (file_uri_scheme($uri)) {
-    if ($wrapper = file_stream_wrapper_get_instance_by_uri($uri)) {
+  if (\Drupal::service("file_system")->uriScheme($uri)) {
+    if ($wrapper = \Drupal::service("stream_wrapper_manager")->getViaUri($uri)) {
       $absolute_path = $wrapper->realpath();
     }
   }
diff --git a/cdn.test b/cdn.test
index c1b49a2..ea349c9 100644
--- a/cdn.test
+++ b/cdn.test
@@ -48,7 +48,7 @@ class CDNTestCase extends DrupalUnitTestCase {
   }
 
   function loadFile($file) {
-    $cdn_path = DRUPAL_ROOT . '/' . drupal_get_path('module', 'cdn');
+    $cdn_path = \Drupal::root() . '/' . drupal_get_path('module', 'cdn');
     require_once "$cdn_path/$file";
   }
 
@@ -117,7 +117,7 @@ class CDNTestCase extends DrupalUnitTestCase {
    *  A Drupal root-relative path.
    */
   function getExpandedFilePath($uri) {
-    $wrapper = file_stream_wrapper_get_instance_by_uri($uri);
+    $wrapper = \Drupal::service("stream_wrapper_manager")->getViaUri($uri);
     return str_replace($GLOBALS['base_url'] . '/', '', $wrapper->getExternalUrl());
   }
 
@@ -302,7 +302,12 @@ class CDNOriginPullTestCase extends CDNTestCase {
     $this->touchFile($uri);
 
     cdn_file_url_alter($uri);
-    $expected = 'http://cdn-a.com' . base_path() . variable_get('file_public_path', conf_path() . '/files') . '/' . drupal_encode_path($filename);
+    // @FIXME
+// // @FIXME
+// // This looks like another module's variable. You'll need to rewrite this call
+// // to ensure that it uses the correct configuration object.
+// $expected = 'http://cdn-a.com' . base_path() . variable_get('file_public_path', conf_path() . '/files') . '/' . drupal_encode_path($filename);
+
     $this->assertIdentical($uri, $expected, 'cdn_file_url_alter() works correctly.');
   }
 }
@@ -341,7 +346,12 @@ class CDNOriginPullFarFutureTestCase extends CDNTestCase {
     if ($mapping !== FALSE) {
       $this->variableSet(CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_VARIABLE, $mapping);
     }
-    $parsed = _cdn_basic_farfuture_parse_raw_mapping(variable_get(CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_VARIABLE, CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_DEFAULT));
+    // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $parsed = _cdn_basic_farfuture_parse_raw_mapping(variable_get(CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_VARIABLE, CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_DEFAULT));
+
     $this->assertEqual($parsed_reference, $parsed, $message);
   }
 
@@ -355,7 +365,12 @@ class CDNOriginPullFarFutureTestCase extends CDNTestCase {
    *   The reference the resulting UFI method will be compared to.
    */
   function assertUFIMethod($path, $ufi_method_reference) {
-    $ufi_mapping = _cdn_basic_farfuture_parse_raw_mapping(variable_get(CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_VARIABLE, CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_DEFAULT));
+    // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $ufi_mapping = _cdn_basic_farfuture_parse_raw_mapping(variable_get(CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_VARIABLE, CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_DEFAULT));
+
     $this->assertEqual(
       $ufi_method_reference,
       cdn_basic_farfuture_get_ufi_method($path, $ufi_mapping),
@@ -457,13 +472,18 @@ class CDNOriginPullFarFutureTestCase extends CDNTestCase {
     cdn_file_url_alter($uri);
 
     $path_info = pathinfo($filename);
-    $expected = implode('/', array(
-      'http://cdn-a.com' . base_path() . 'cdn/farfuture',
-      drupal_hmac_base64('perpetual:forever' . $path_info['filename'], drupal_get_private_key() . drupal_get_hash_salt()),
-      'perpetual:forever',
-      variable_get('file_public_path', conf_path() . '/files'),
-      drupal_encode_path($filename)
-    ));
+    // @FIXME
+// // @FIXME
+// // This looks like another module's variable. You'll need to rewrite this call
+// // to ensure that it uses the correct configuration object.
+// $expected = implode('/', array(
+//       'http://cdn-a.com' . base_path() . 'cdn/farfuture',
+//       drupal_hmac_base64('perpetual:forever' . $path_info['filename'], drupal_get_private_key() . drupal_get_hash_salt()),
+//       'perpetual:forever',
+//       variable_get('file_public_path', conf_path() . '/files'),
+//       drupal_encode_path($filename)
+//     ));
+
     $this->assertIdentical($uri, $expected, 'cdn_file_url_alter() works correctly.');
   }
 }
diff --git a/config/install/cdn.settings.yml b/config/install/cdn.settings.yml
new file mode 100644
index 0000000..52aa922
--- /dev/null
+++ b/config/install/cdn.settings.yml
@@ -0,0 +1,5 @@
+cdn_basic_url: ''
+cdn_basic_extensions: ''
+cdn_mode: false
+cdn_advanced_pid_file: false
+cdn_advanced_synced_files_db: false
diff --git a/config/schema/cdn.schema.yml b/config/schema/cdn.schema.yml
new file mode 100644
index 0000000..2540835
--- /dev/null
+++ b/config/schema/cdn.schema.yml
@@ -0,0 +1,14 @@
+cdn.settings:
+  type: mapping
+  label: Settings
+  mapping:
+    cdn_basic_url:
+      type: string
+    cdn_basic_extensions:
+      type: string
+    cdn_mode:
+      type: boolean
+    cdn_advanced_pid_file:
+      type: boolean
+    cdn_advanced_synced_files_db:
+      type: boolean
diff --git a/src/EventSubscriber/ExitSubscriber.php b/src/EventSubscriber/ExitSubscriber.php
new file mode 100644
index 0000000..5165236
--- /dev/null
+++ b/src/EventSubscriber/ExitSubscriber.php
@@ -0,0 +1,63 @@
+<?php /**
+ * @file
+ * Contains \Drupal\cdn\EventSubscriber\ExitSubscriber.
+ */
+
+namespace Drupal\cdn\EventSubscriber;
+
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+class ExitSubscriber implements EventSubscriberInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getSubscribedEvents() {
+    return [KernelEvents::TERMINATE => ['onEvent', 0]];
+  }
+
+  public function onEvent($destination = NULL) {
+    // When the _cdn_devel_page_stats() function does not exist, there are no
+  // stats to show, hence we can return immediately.
+  // This can happen when the stats are disabled (for the current user or
+  // entirely), or when a cached page is being served.
+    if (!function_exists('_cdn_devel_page_stats')) {
+      return;
+    }
+
+    // Try not to break non-HTML pages.
+    if (function_exists('drupal_get_http_header') && !strstr(drupal_get_http_header('Content-Type'), 'html')) {
+      return;
+    }
+
+    // @FIXME
+    // // @FIXME
+    // // The correct configuration object could not be determined. You'll need to
+    // // rewrite this call manually.
+    // if (!$destination
+    //       && variable_get(CDN_STATUS_VARIABLE, CDN_DISABLED) != CDN_DISABLED
+    //       && variable_get(CDN_STATS_VARIABLE, FALSE)
+    //       && \Drupal::currentUser()->hasPermission(CDN_PERM_ACCESS_STATS)
+    //   ) {
+    //     list(
+    //       $file_count,
+    //       $cdn_file_count,
+    //       $synced_files_per_server_count,
+    //       $total_time,
+    //       $synced_files,
+    //       $unsynced_files,
+    //     ) = _cdn_devel_page_stats();
+    //     print theme('cdn_page_stats', array(
+    //       'file_count'                    => $file_count,
+    //       'cdn_file_count'                => $cdn_file_count,
+    //       'synced_files_per_server_count' => $synced_files_per_server_count,
+    //       'total_time'                    => $total_time,
+    //       'synced_files'                  => $synced_files,
+    //       'unsynced_files'                => $unsynced_files
+    //     ));
+    //   }
+
+  }
+
+}
diff --git a/src/EventSubscriber/InitSubscriber.php b/src/EventSubscriber/InitSubscriber.php
new file mode 100644
index 0000000..451d752
--- /dev/null
+++ b/src/EventSubscriber/InitSubscriber.php
@@ -0,0 +1,49 @@
+<?php /**
+ * @file
+ * Contains \Drupal\cdn\EventSubscriber\InitSubscriber.
+ */
+
+namespace Drupal\cdn\EventSubscriber;
+
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+class InitSubscriber implements EventSubscriberInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getSubscribedEvents() {
+    return [KernelEvents::REQUEST => ['onEvent', 0]];
+  }
+
+  public function onEvent() {
+    if (!cdn_status_is_enabled()) {
+      return;
+    }
+
+    _cdn_prefetch_dns();
+
+    // When per-page statistics are enabled, add the CSS that will be used to
+    // make these statistics more usable.
+    // @FIXME
+    // // @FIXME
+    // // The correct configuration object could not be determined. You'll need to
+    // // rewrite this call manually.
+    // if (variable_get(CDN_STATS_VARIABLE, FALSE)
+    //       && \Drupal::currentUser()->hasPermission(CDN_PERM_ACCESS_STATS)
+    //   ) {
+    //     // @FIXME
+    // // The Assets API has totally changed. CSS, JavaScript, and libraries are now
+    // // attached directly to render arrays using the #attached property.
+    // //
+    // //
+    // // @see https://www.drupal.org/node/2169605
+    // // @see https://www.drupal.org/node/2408597
+    // // drupal_add_css(drupal_get_path('module', 'cdn') . '/cdn.css', array('every_page' => TRUE));
+    // 
+    //   }
+
+  }
+
+}
diff --git a/src/Form/CdnAdminDetailsForm.php b/src/Form/CdnAdminDetailsForm.php
new file mode 100644
index 0000000..d951cc7
--- /dev/null
+++ b/src/Form/CdnAdminDetailsForm.php
@@ -0,0 +1,309 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\cdn\Form\CdnAdminDetailsForm.
+ */
+
+namespace Drupal\cdn\Form;
+
+use Drupal\Core\Form\ConfigFormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\Element;
+
+class CdnAdminDetailsForm extends ConfigFormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'cdn_admin_details_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    $config = $this->config('cdn.settings');
+
+    foreach (Element::children($form) as $variable) {
+      $config->set($variable, $form_state->getValue($form[$variable]['#parents']));
+    }
+    $config->save();
+
+    if (method_exists($this, '_submitForm')) {
+      $this->_submitForm($form, $form_state);
+    }
+
+    parent::submitForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getEditableConfigNames() {
+    return ['cdn.settings'];
+  }
+
+  public function buildForm(array $form, \Drupal\Core\Form\FormStateInterface &$form_state) {
+    $form = [];
+    _cdn_settings_form_prepare($form, $form_state);
+
+    // @FIXME
+    // // @FIXME
+    // // The correct configuration object could not be determined. You'll need to
+    // // rewrite this call manually.
+    // $form[CDN_MODE_VARIABLE] = array(
+    //     '#type' => 'radios',
+    //     '#title' => t('Mode'),
+    //     '#description' => _cdn_help('admin-details-mode') . t('Choose a CDN integration mode.'),
+    //     '#required' => TRUE,
+    //     '#options'  => array(
+    //       CDN_MODE_BASIC    => t('Origin Pull'),
+    //       CDN_MODE_ADVANCED => t('File Conveyor'),
+    //     ),
+    //     '#default_value' => variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC),
+    //   );
+
+
+    $form['settings'] = [
+      '#type' => 'fieldset',
+      '#title' => t('Mode-specific settings'),
+    ];
+
+    //
+    // Origin Pull mode settings.
+    //
+
+    // @FIXME
+    // // @FIXME
+    // // The correct configuration object could not be determined. You'll need to
+    // // rewrite this call manually.
+    // $form['settings'][CDN_BASIC_MAPPING_VARIABLE] = array(
+    //     '#type'          => 'textarea',
+    //     '#title'         => t('CDN mapping'),
+    //     '#description'   => _cdn_help('admin-details-mode-pull-cdn-mapping') . t("Define which files are mapped to which CDN."),
+    //     '#size'          => 35,
+    //     '#default_value' => variable_get(CDN_BASIC_MAPPING_VARIABLE, ''),
+    //     '#states' => array(
+    //       'visible' => array(
+    //         ':input[name="' . CDN_MODE_VARIABLE . '"]' => array('value' => CDN_MODE_BASIC),
+    //       )
+    //     ),
+    //   );
+
+    // @FIXME
+    // // @FIXME
+    // // The correct configuration object could not be determined. You'll need to
+    // // rewrite this call manually.
+    // $form['settings'][CDN_BASIC_FARFUTURE_VARIABLE] = array(
+    //     '#type' => 'checkbox',
+    //     '#title' => t('Far Future expiration'),
+    //     '#description' => _cdn_help('admin-details-mode-pull-far-future') .
+    //       t('Mark all files served from the CDN to expire in the far future —
+    //       improves client-side cacheability.<br /><strong>Note:</strong> this
+    //       requires the !preprocess-css-link performance setting to be enabled (or
+    //       your site will break).<br><strong>Note:</strong> only use Far Future
+    //       expiration when using a CDN or a reverse proxy.',
+    //       array(
+    //         '!preprocess-css-link' => \Drupal::l('"Aggregate and compress CSS files"', \Drupal\Core\Url::fromRoute('system.performance_settings')),
+    //       )
+    //     ),
+    //     '#default_value' => variable_get(CDN_BASIC_FARFUTURE_VARIABLE, CDN_BASIC_FARFUTURE_DEFAULT),
+    //     '#states' => array(
+    //       'visible' => array(
+    //         ':input[name="' . CDN_MODE_VARIABLE . '"]' => array('value' => CDN_MODE_BASIC),
+    //       )
+    //     ),
+    //   );
+
+
+    $format_variables = [
+      '@format-directory' => '<' . t('directory') . '>',
+      '@format-extensions' => '<' . t('extensions') . '>',
+      '@format-unique-identifier-method' => '<' . t('unique identifier method') . '>',
+    ];
+
+    $methods = [];
+    $ufi_info = \Drupal::moduleHandler()->invokeAll('cdn_unique_file_identifier_info');
+    foreach ($ufi_info as $ufi_method => $ufi) {
+      $methods[] = $ufi['label'] . ' (<code>' . $ufi_method . '</code>): ' . $ufi['description'];
+    }
+    $format_variables['!ufi-methods'] = _theme('item_list', [
+      'items' => $methods
+      ]);
+
+    // @FIXME
+    // // @FIXME
+    // // The correct configuration object could not be determined. You'll need to
+    // // rewrite this call manually.
+    // $form['settings'][CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_VARIABLE] = array(
+    //     '#type'          => 'textarea',
+    //     '#title'         => t('Unique file identifier generation'),
+    //     '#description'   => _cdn_help('admin-details-mode-pull-ufi') . t('Define how unique file identifiers (UFIs) are generated.'),
+    //     '#size'          => 35,
+    //     '#default_value' => variable_get(CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_VARIABLE, CDN_BASIC_FARFUTURE_UNIQUE_IDENTIFIER_MAPPING_DEFAULT),
+    //     '#states' => array(
+    //       'visible' => array(
+    //         ':input[name="' . CDN_MODE_VARIABLE . '"]' => array('value' => CDN_MODE_BASIC),
+    //         ':input[name="' . CDN_BASIC_FARFUTURE_VARIABLE . '"]' => array('checked' => TRUE),
+    //       )
+    //     ),
+    //   );
+
+
+    $form['settings']['ufis'] = [
+      '#type' => 'fieldset',
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+      '#title' => t('Available UFI methods'),
+      '#input' => TRUE,
+      '#id' => 'ufi-fs-id',
+      '#prefix' => '<div id="ufi-fs-id-wrapper">',
+      '#suffix' => '</div>',
+      '#states' => [
+        'visible' => [
+          ':input[name="' . CDN_MODE_VARIABLE . '"]' => [
+            'value' => CDN_MODE_BASIC
+            ],
+          ':input[name="' . CDN_BASIC_FARFUTURE_VARIABLE . '"]' => [
+            'checked' => TRUE
+            ],
+        ]
+        ],
+    ];
+
+    $form['settings']['ufis']['content'] = [
+      '#markup' => t('Available UFI methods: !ufi-methods', $format_variables) . '<p>' . t('Note that if no UFI method is specified for a file
+                          (because no rule matches), the CDN module will fall
+                          back to the mtime method.') . '</p>',
+      '#prefix' => '<div>',
+      '#suffix' => '</div>',
+    ];
+
+    //
+    // File Conveyor mode settings.
+    //
+
+    // @FIXME
+    // // @FIXME
+    // // The correct configuration object could not be determined. You'll need to
+    // // rewrite this call manually.
+    // $form['settings'][CDN_ADVANCED_PID_FILE_VARIABLE] = array(
+    //     '#type'          => 'textfield',
+    //     '#title'         => t('PID file'),
+    //     '#description'   => _cdn_help('admin-details-mode-fc-pid') . t('Full path to File Conveyor\'s PID file.'),
+    //     '#size'          => 60,
+    //     '#default_value' => variable_get(CDN_ADVANCED_PID_FILE_VARIABLE, ''),
+    //     '#states' => array(
+    //       'visible' => array(
+    //         ':input[name="' . CDN_MODE_VARIABLE . '"]' => array('value' => CDN_MODE_ADVANCED),
+    //       ),
+    //     ),
+    //   );
+
+    // @FIXME
+    // // @FIXME
+    // // The correct configuration object could not be determined. You'll need to
+    // // rewrite this call manually.
+    // $form['settings'][CDN_ADVANCED_SYNCED_FILES_DB_VARIABLE] = array(
+    //     '#type'          => 'textfield',
+    //     '#title'         => t('Synced files database'),
+    //     '#description'   => _cdn_help('admin-details-mode-fc-db') . t('Full path to File Conveyor\'s synced files database file.'),
+    //     '#size'          => 60,
+    //     '#default_value' => variable_get(CDN_ADVANCED_SYNCED_FILES_DB_VARIABLE, ''),
+    //     '#states' => array(
+    //       'visible' => array(
+    //         ':input[name="' . CDN_MODE_VARIABLE . '"]' => array('value' => CDN_MODE_ADVANCED),
+    //       ),
+    //     ),
+    //   );
+
+
+    return parent::buildForm($form, $form_state);
+  }
+
+  public function validateForm(array &$form, \Drupal\Core\Form\FormStateInterface &$form_state) {
+    // If ctools_dependent supported required dependent form items, this ugly
+  // piece of code would not be necessary.
+    if ($form_state->getValue([CDN_MODE_VARIABLE]) == CDN_MODE_BASIC) {
+      if (empty($form_state->getValue([CDN_BASIC_MAPPING_VARIABLE]))) {
+        $form_state->setError($form['settings'][CDN_BASIC_MAPPING_VARIABLE], t('!name field is required.', [
+          '!name' => $form['settings'][CDN_BASIC_MAPPING_VARIABLE]['#title']
+          ]));
+      }
+    }
+    else {
+      if (empty($form_state->getValue([CDN_ADVANCED_SYNCED_FILES_DB_VARIABLE]))) {
+        $form_state->setError($form['settings'][CDN_ADVANCED_SYNCED_FILES_DB_VARIABLE], t('!name field is required.', [
+          '!name' => $form['settings'][CDN_ADVANCED_SYNCED_FILES_DB_VARIABLE]['#title']
+          ]));
+      }
+    }
+
+    // When in Origin Pull mode, check the CDN mapping for CDNs/reverse proxies.
+    if ($form_state->getValue([CDN_MODE_VARIABLE]) == CDN_MODE_BASIC) {
+      $domains = cdn_get_domains();
+      $token = md5(rand());
+      \Drupal::configFactory()->getEditable('cdn.settings')->set('cdn_reverse_proxy_test', $token)->save();
+      $yays = [];
+      $nays = [];
+      foreach ($domains as $domain) {
+        $url = 'http://' . $domain . base_path() . 'cdn/farfuture/reverse-proxy-test/' . $token;
+        // @FIXME
+        // drupal_http_request() has been replaced by the Guzzle HTTP client, which is bundled
+        // with Drupal core.
+        // 
+        // 
+        // @see https://www.drupal.org/node/1862446
+        // @see http://docs.guzzlephp.org/en/latest
+        // $r1 = drupal_http_request($url);
+
+        // @FIXME
+        // drupal_http_request() has been replaced by the Guzzle HTTP client, which is bundled
+        // with Drupal core.
+        // 
+        // 
+        // @see https://www.drupal.org/node/1862446
+        // @see http://docs.guzzlephp.org/en/latest
+        // $r2 = drupal_http_request($url);
+
+        unset($r1->headers);
+        unset($r2->headers);
+        $args = ['%domain' => $domain];
+        if ($r1 == $r2) {
+          $yays[] = t('%domain is a CDN or a reverse proxy.', $args);
+        }
+        else {
+          if ($r1->code == 404) {
+            $nays[] = t('%domain is a static file server.', $args);
+          }
+          else {
+            $nays[] = t('%domain uses the same web server as this Drupal site.', $args);
+          }
+        }
+      }
+      \Drupal::configFactory()->getEditable('cdn.settings')->set('cdn_reverse_proxy_test', FALSE)->save();
+      if (!empty($yays)) {
+        drupal_set_message(t('Perfect domains: !yay-list', [
+          '!yay-list' => _theme('item_list', [
+            'items' => $yays
+            ])
+          ]));
+      }
+      if (!empty($nays)) {
+        drupal_set_message(t('Potentially problematic domains: !nay-list', [
+          '!nay-list' => _theme('item_list', [
+            'items' => $nays
+            ])
+          ]), 'warning');
+      }
+    }
+      // When in advanced mode, validate the synced files DB.
+    elseif ($form_state->getValue([CDN_MODE_VARIABLE]) == CDN_MODE_ADVANCED) {
+      $synced_files_db = $form_state->getValue([CDN_ADVANCED_SYNCED_FILES_DB_VARIABLE]);
+      _cdn_admin_validate_synced_files_db($synced_files_db, CDN_ADVANCED_SYNCED_FILES_DB_VARIABLE);
+    }
+  }
+
+}
diff --git a/src/Form/CdnAdminGeneralSettingsForm.php b/src/Form/CdnAdminGeneralSettingsForm.php
new file mode 100644
index 0000000..54b3d00
--- /dev/null
+++ b/src/Form/CdnAdminGeneralSettingsForm.php
@@ -0,0 +1,110 @@
+ <?php
+
+/**
+ * @file
+ * Contains \Drupal\cdn\Form\CdnAdminGeneralSettingsForm.
+ */
+
+namespace Drupal\cdn\Form;
+
+use Drupal\Core\Form\ConfigFormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\Element;
+
+class CdnAdminGeneralSettingsForm extends ConfigFormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'cdn_admin_general_settings_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    $config = $this->config('cdn.settings');
+
+    foreach (Element::children($form) as $variable) {
+      $config->set($variable, $form_state->getValue($form[$variable]['#parents']));
+    }
+    $config->save();
+
+    if (method_exists($this, '_submitForm')) {
+      $this->_submitForm($form, $form_state);
+    }
+
+    parent::submitForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getEditableConfigNames() {
+    return ['cdn.settings'];
+  }
+
+  public function buildForm(array $form, \Drupal\Core\Form\FormStateInterface &$form_state) {
+    $form = [];
+    _cdn_settings_form_prepare($form, $form_state);
+
+    $perm_url = \Drupal\Core\Url::fromRoute('user.admin_permissions');
+
+    // @FIXME
+    // // @FIXME
+    // // The correct configuration object could not be determined. You'll need to
+    // // rewrite this call manually.
+    // $form[CDN_STATUS_VARIABLE] = array(
+    //     '#type' => 'radios',
+    //     '#title' => t('Status'),
+    //     '#description' => t(
+    //       "If you don't want to use the CDN to serve files to your visitors yet,
+    //       but you do want to see if it's working well for your site, then enable
+    //       testing mode.<br />Users will only get the files from the CDN if they
+    //       have the <a href=\"!perm-url\">%cdn-testing-mode-permission
+    //       permission</a>.",
+    //       array(
+    //         '!perm-url' => $perm_url,
+    //         '%cdn-testing-mode-permission' => 'access files on CDN when in testing mode',
+    //       )
+    //     ),
+    //     '#required' => TRUE,
+    //     '#options' => array(
+    //       CDN_DISABLED => t('Disabled'),
+    //       CDN_TESTING  => t('Testing mode'),
+    //       CDN_ENABLED  => t('Enabled'),
+    //     ),
+    //     '#default_value' => variable_get(CDN_STATUS_VARIABLE, CDN_DISABLED),
+    //   );
+
+
+    // @FIXME
+    // // @FIXME
+    // // The correct configuration object could not be determined. You'll need to
+    // // rewrite this call manually.
+    // $form[CDN_STATS_VARIABLE] = array(
+    //     '#type' => 'checkbox',
+    //     '#title' => t('Display statistics'),
+    //     '#description' => t(
+    //       'Shows the CDN integration statistics of the current page, to users with
+    //         the <a href="!perm-url">%access-per-page-statistics permission</a>.',
+    //         array(
+    //           '!perm-url' => $perm_url,
+    //           '%access-per-page-statistics' => 'access per-page statistics',
+    //         )
+    //     ),
+    //     '#return_value'  => CDN_ENABLED,
+    //     '#default_value' => variable_get(CDN_STATS_VARIABLE, CDN_DISABLED),
+    //     '#states' => array(
+    //       'invisible' => array(
+    //         ':input[name="' . CDN_STATUS_VARIABLE . '"]' => array('value' => '' . CDN_DISABLED),
+    //       ),
+    //     ),
+    //   );
+
+
+    return parent::buildForm($form, $form_state);
+  }
+
+}
diff --git a/src/Form/CdnAdminOtherSettingsForm.php b/src/Form/CdnAdminOtherSettingsForm.php
new file mode 100644
index 0000000..9af0b48
--- /dev/null
+++ b/src/Form/CdnAdminOtherSettingsForm.php
@@ -0,0 +1,285 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\cdn\Form\CdnAdminOtherSettingsForm.
+ */
+
+namespace Drupal\cdn\Form;
+
+use Drupal\Core\Form\ConfigFormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\Element;
+
+class CdnAdminOtherSettingsForm extends ConfigFormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'cdn_admin_other_settings_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    $config = $this->config('cdn.settings');
+
+    foreach (Element::children($form) as $variable) {
+      $config->set($variable, $form_state->getValue($form[$variable]['#parents']));
+    }
+    $config->save();
+
+    if (method_exists($this, '_submitForm')) {
+      $this->_submitForm($form, $form_state);
+    }
+
+    parent::submitForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getEditableConfigNames() {
+    return ['cdn.settings'];
+  }
+
+  public function buildForm(array $form, \Drupal\Core\Form\FormStateInterface &$form_state) {
+    $form = [];
+    _cdn_settings_form_prepare($form, $form_state);
+
+    // @FIXME
+    // // @FIXME
+    // // The correct configuration object could not be determined. You'll need to
+    // // rewrite this call manually.
+    // if (variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC) == CDN_MODE_ADVANCED) {
+    //     $form[CDN_\Drupal::root()_VARIABLE] = array(
+    //       '#type' => 'textfield',
+    //       '#title' => t('Drupal root directory'),
+    //       '#description' => t(
+    //         'In 99% of the cases the default value is sufficient and correct. In
+    //         some advanced setups that make use of symbolic links however, it is
+    //         possible that the Drupal root directory is incorrectly detected. In
+    //         those cases, you should enter it here.<br />
+    //         <strong>This setting only affects the status report, it does not affect
+    //         the CDN integration itself in any way.</strong>'
+    //       ),
+    //       '#required'      => TRUE,
+    //       '#default_value' => variable_get(CDN_\Drupal::root()_VARIABLE, realpath('.')),
+    //     );
+    //   }
+
+
+    $form['https'] = [
+      '#type' => 'fieldset',
+      '#title' => t('HTTPS'),
+    ];
+    // @FIXME
+    // // @FIXME
+    // // The correct configuration object could not be determined. You'll need to
+    // // rewrite this call manually.
+    // $form['https'][CDN_HTTPS_SUPPORT_VARIABLE] = array(
+    //     '#type'          => 'checkbox',
+    //     '#title'         => t('CDN supports HTTPS'),
+    //     '#default_value' => variable_get(CDN_HTTPS_SUPPORT_VARIABLE, FALSE),
+    //     '#description' => _cdn_help('admin-other-https') . t('Enable if you use HTTPS and your CDN supports it too.'),
+    //   );
+
+    // @FIXME
+    // // @FIXME
+    // // The correct configuration object could not be determined. You'll need to
+    // // rewrite this call manually.
+    // if (variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC) == CDN_MODE_BASIC) {
+    //     $form['https'][CDN_BASIC_MAPPING_HTTPS_VARIABLE] = array(
+    //       '#type'          => 'textarea',
+    //       '#title'         => t('CDN mapping for HTTPS'),
+    //       '#description'   => t('If your CDN supports HTTPS, but requires you to
+    //                             use different URLs, then you can define an
+    //                             alternative CDN mapping here. This overrides the
+    //                             "regular" CDN mapping completely, when using
+    //                             HTTPS.'),
+    //       '#size'          => 35,
+    //       '#default_value' => variable_get(CDN_BASIC_MAPPING_HTTPS_VARIABLE, ''),
+    //       '#states' => array(
+    //         'visible' => array(
+    //           ':input[name="' . CDN_HTTPS_SUPPORT_VARIABLE . '"]' => array('checked' => TRUE),
+    //         )
+    //       ),
+    //     );
+    //   }
+
+
+    $path_explanation = t("Enter one file pattern per line. The '*' character is a wildcard.<br />
+    Example file patterns are <code>*.js</code> for all JavaScript files and
+    <code>mytheme/*.css</code> for all CSS files in the <code>mytheme</code>
+    directory.");
+
+    $form['exceptions'] = [
+      '#type' => 'fieldset',
+      '#title' => t('Exceptions'),
+      '#description' => _cdn_help('admin-other-exceptions') . t('Which files should be served from a CDN is not as
+                         simple as it seems: there are bound to be exceptions.
+                         You can easily define those exceptions here, either
+                         by file URL, Drupal path or by Drupal path for
+                         authenticated users.'),
+    ];
+
+    $form['exceptions']['file_path'] = [
+      '#type' => 'fieldset',
+      '#title' => t('File URL'),
+      '#description' => t("Files that are marked to not be served from the CDN
+    because of a match in the blacklist, can be overridden to be served from
+    the CDN after all, if they have a match in the whitelist."),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+    ];
+    // @FIXME
+    // // @FIXME
+    // // The correct configuration object could not be determined. You'll need to
+    // // rewrite this call manually.
+    // $form['exceptions']['file_path'][CDN_EXCEPTION_FILE_PATH_BLACKLIST_VARIABLE] = array(
+    //     '#type' => 'textarea',
+    //     '#title' => t('Blacklist'),
+    //     '#default_value' => variable_get(CDN_EXCEPTION_FILE_PATH_BLACKLIST_VARIABLE, CDN_EXCEPTION_FILE_PATH_BLACKLIST_DEFAULT),
+    //     '#description' => $path_explanation,
+    //   );
+
+    $blacklist_modules = \Drupal::moduleHandler()->getImplementations('cdn_blacklist');
+    $blacklist_modules = array_unique(array_merge($blacklist_modules, \Drupal::moduleHandler()->getImplementations('cdn_blacklist_alter')));
+    $blacklist_modules_string = '';
+    for ($i = 0; $i < count($blacklist_modules); $i++) {
+      $blacklist_modules_string .= '<code>' . $blacklist_modules[$i] . '</code>';
+      if ($i < count($blacklist_modules) - 1) {
+        $blacklist_modules_string .= ', ';
+      }
+    }
+    $form['exceptions']['file_path']['cdn_hook_blacklist'] = [
+      '#type' => 'textarea',
+      '#title' => t('Blacklist from modules'),
+      '#default_value' => cdn_get_blacklist(TRUE),
+      '#description' => t('Blacklist from <code>hook_cdn_blacklist()</code> and
+                        <code>hook_cdn_blacklist_alter()</code>. Automatically
+                        updated when cron runs. Generated from the following
+                        modules: !module-list.', [
+        '!module-list' => $blacklist_modules_string
+        ]),
+      '#disabled' => TRUE,
+    ];
+    // @FIXME
+    // // @FIXME
+    // // The correct configuration object could not be determined. You'll need to
+    // // rewrite this call manually.
+    // $form['exceptions']['file_path'][CDN_EXCEPTION_FILE_PATH_WHITELIST_VARIABLE] = array(
+    //     '#type' => 'textarea',
+    //     '#title' => t('Whitelist'),
+    //     '#default_value' => variable_get(CDN_EXCEPTION_FILE_PATH_WHITELIST_VARIABLE, CDN_EXCEPTION_FILE_PATH_WHITELIST_DEFAULT),
+    //     '#description' => $path_explanation,
+    //   );
+
+
+    $form['exceptions']['drupal_path'] = [
+      '#type' => 'fieldset',
+      '#title' => t('Drupal path'),
+      '#description' => t("Drupal paths entered in this blacklist will not serve
+                         any files from the CDN. This blacklist is applied for
+                         <em>all</em> users."),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+    ];
+    // @FIXME
+    // // @FIXME
+    // // The correct configuration object could not be determined. You'll need to
+    // // rewrite this call manually.
+    // $form['exceptions']['drupal_path'][CDN_EXCEPTION_DRUPAL_PATH_BLACKLIST_VARIABLE] = array(
+    //     '#type' => 'textarea',
+    //     '#title' => t('Blacklist'),
+    //     '#default_value' => variable_get(CDN_EXCEPTION_DRUPAL_PATH_BLACKLIST_VARIABLE, CDN_EXCEPTION_DRUPAL_PATH_BLACKLIST_DEFAULT),
+    //     '#description' => t(
+    //       "Enter one page per line as Drupal paths. The '*' character is a
+    //       wildcard. Example paths are %blog for the blog page and %blog-wildcard
+    //       for every personal blog. %front is the front page.",
+    //       array(
+    //        '%blog'          => 'blog',
+    //        '%blog-wildcard' => 'blog/*',
+    //        '%front'         => '<front>',
+    //       )
+    //     ),
+    //   );
+
+
+    $form['exceptions']['auth_users'] = [
+      '#type' => 'fieldset',
+      '#title' => t('Drupal path for authenticated users'),
+      '#description' => t("Drupal paths entered in this blacklist will not serve
+                         any files from the CDN. This blacklist is applied for
+                         <em>authenticated users only</em>."),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+    ];
+    // @FIXME
+    // // @FIXME
+    // // The correct configuration object could not be determined. You'll need to
+    // // rewrite this call manually.
+    // $form['exceptions']['auth_users'][CDN_EXCEPTION_AUTH_USERS_BLACKLIST_VARIABLE] = array(
+    //     '#type'          => 'textarea',
+    //     '#title'         => t('Blacklist'),
+    //     '#default_value' => variable_get(CDN_EXCEPTION_AUTH_USERS_BLACKLIST_VARIABLE, CDN_EXCEPTION_AUTH_USERS_BLACKLIST_DEFAULT),
+    //     '#description'   => $path_explanation,
+    //   );
+
+
+
+    $form['cdn_pick_server'] = [
+      '#type' => 'fieldset',
+      '#title' => 'cdn_pick_server()',
+      '#description' => t('It is possible to achieve very advanced types of CDN
+                         integration by implementing the
+                         <code>cdn_pick_server()</code> function (consult the
+                         included README for examples). However, to lower the
+                         barrier to start using it, it has been made possible
+                         to just enter the body of that function right here,
+                         in the settings of the CDN module, so you would not
+                         have to create a small module for it.'),
+    ];
+    if (function_exists('cdn_pick_server')) {
+      $form['cdn_pick_server']['defined_in_code'] = [
+        '#type' => 'item',
+        '#title' => t('Defined in code'),
+        '#markup' => 'The <code>cdn_pick_server()</code> function is already defined in code.',
+      ];
+    }
+    else {
+      // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $php_code = variable_get(CDN_PICK_SERVER_PHP_CODE_VARIABLE, '');
+
+      $form['cdn_pick_server'][CDN_PICK_SERVER_PHP_CODE_VARIABLE] = [
+        '#type' => 'textarea',
+        '#title' => t('PHP code for cdn_pick_server()'),
+        '#description' => _cdn_help('admin-other-cdn-pick-server') . t('PHP code to select the most appropriate CDN server.'),
+        '#cols' => 60,
+        '#rows' => ($php_code != '') ? count(explode("\n", $php_code)) + 1 : 5,
+        '#default_value' => $php_code,
+      ];
+    }
+
+    return parent::buildForm($form, $form_state);
+  }
+
+  public function validateForm(array &$form, \Drupal\Core\Form\FormStateInterface &$form_state) {
+    if (!empty($form_state->getValue([CDN_PICK_SERVER_PHP_CODE_VARIABLE]))) {
+      $php_code = $form_state->getValue([CDN_PICK_SERVER_PHP_CODE_VARIABLE]);
+      $servers = [];
+      if (_cdn_eval_pick_server($php_code, $servers) === FALSE) {
+        $form_state->setError($form['cdn_pick_server'][CDN_PICK_SERVER_PHP_CODE_VARIABLE], t('Your <code>cdn_pick_server()</code> cannot be evaluated. Please correct it or leave it empty.'));
+      }
+    }
+
+    // Remove the non-variable.
+    unset($form_state->getValue(['cdn_hook_blacklist']));
+  }
+
+}
diff --git a/src/Form/CdnTouchFileForm.php b/src/Form/CdnTouchFileForm.php
new file mode 100644
index 0000000..f4c3fbe
--- /dev/null
+++ b/src/Form/CdnTouchFileForm.php
@@ -0,0 +1,73 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\cdn\Form\CdnTouchFileForm.
+ */
+
+namespace Drupal\cdn\Form;
+
+use Drupal\Core\Form\FormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\Element;
+
+class CdnTouchFileForm extends FormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'cdn_touch_file_form';
+  }
+
+  public function buildForm(array $form, \Drupal\Core\Form\FormStateInterface &$form_state) {
+    // All arguments after the first two are in fact the different parts of the
+  // file path that is being passed in.
+    $additional_args = array_slice(func_get_args(), 2);
+    $filepath = implode('/', $additional_args);
+
+    // Store the page we should redirect to after the file has been touched, or
+    // upon cancellation.
+    if (!isset($form_state->getStorage())) {
+      $form_state->setStorage((isset($_SERVER['HTTP_REFERER'])) ? $_SERVER['HTTP_REFERER'] : '<front>');
+    }
+
+    if (!file_exists($filepath)) {
+      drupal_set_message(t('The file %filepath does not exist and thus could not be touched.', [
+        '%filepath' => $filepath
+        ]), 'error');
+      drupal_goto($form_state->getStorage());
+    }
+    else {
+      $form_state->set(['filepath'], $filepath);
+      return confirm_form([
+        'filepath' => [
+          '#type' => 'value',
+          '#markup' => $filepath,
+        ],
+        'redirect' => [
+          '#type' => 'value',
+          '#markup' => $form_state->getStorage(),
+        ],
+      ], t('Are you sure you want to touch %filepath?', [
+        '%filepath' => $filepath
+        ]), $form_state->getStorage(), t('This action cannot be undone, but is completely harmless. Touching a file merely means that its last modification date will be updated to \'right now\'.'), t('Touch file'), t('Cancel'));
+    }
+  }
+
+  public function submitForm(array &$form, \Drupal\Core\Form\FormStateInterface &$form_state) {
+    $filepath = $form_state->get(['filepath']);
+    if (touch(_cdn_get_absolute_path($filepath))) {
+      drupal_set_message(t('Successfully touched %filepath.', [
+        '%filepath' => $filepath
+        ]));
+    }
+    else {
+      drupal_set_message(t('Failed to touch %filepath. Likely you do not have sufficient permissions.', [
+        '%filepath' => $filepath
+        ]));
+    }
+    drupal_goto($form_state->getStorage());
+  }
+
+}
diff --git a/tests/src/Unit/CDNTestCase.php b/tests/src/Unit/CDNTestCase.php
new file mode 100644
index 0000000..4711a63
--- /dev/null
+++ b/tests/src/Unit/CDNTestCase.php
@@ -0,0 +1,138 @@
+<?php
+
+namespace Drupal\Tests\cdn\Unit;
+
+/**
+ * @FIXME
+ * Unit tests are now written for the PHPUnit framework. You will need to refactor
+ * this test in order for it to work properly.
+ */
+
+class CDNTestCase extends \Drupal\Tests\UnitTestCase {
+  function setUp() {
+    parent::setUp();
+
+    // Alter $_SERVER to include some relatively rarely set HTTP headers.
+    $alt_server = array(
+      'HTTP_ACCEPT_ENCODING',
+      'HTTPS' => 'off',
+      'HTTP_X_FORWARDED_PROTO' => 'http',
+    );
+    $alt_server = array_merge($alt_server, $_SERVER);
+    $_SERVER = $alt_server;
+    $this->setRequestProtocol('http');
+
+    // Pretend the CDN module is enabled; this ensures invocations of its own
+    // hook implementations will work as expected.
+    $cdn_module_file = drupal_get_path('module', 'cdn') . '/cdn.module';
+    $module_list = module_list();
+    $module_list['cdn']['filename'] = $cdn_module_file;
+    module_list(TRUE, FALSE, FALSE, $module_list);
+    $implementations = &drupal_static('module_implements');
+    $implementations = array();
+
+    $this->loadFile('cdn.constants.inc');
+    $this->loadFile('cdn.module');
+
+    // Override $conf to be able to use variable_set() and variable_get() in
+    // DrupalUnitTestCase. At the same time, make sure we can restore the
+    // original values.
+    global $conf;
+    $this->originalConfig = $conf;
+    $this->variableSetDefaults();
+  }
+
+  function tearDown() {
+    // Restore the original values that are used by variable_get().
+    global $conf;
+    $conf = $this->originalConfig;
+
+    parent::tearDown();
+  }
+
+  function loadFile($file) {
+    $cdn_path = \Drupal::root() . '/' . drupal_get_path('module', 'cdn');
+    require_once "$cdn_path/$file";
+  }
+
+  /**
+   * Mock function for variable_set().
+   */
+  function variableSet($name, $value) {
+    global $conf;
+    $conf[$name] = $value;
+  }
+
+  /**
+   * Set the default variable values for the CDN module.
+   */
+  function variableSetDefaults() {
+    global $conf;
+    $this->defaultConfig = array(
+      CDN_STATUS_VARIABLE => CDN_ENABLED,
+      CDN_MODE_VARIABLE => FALSE,
+      CDN_HTTPS_SUPPORT_VARIABLE => FALSE,
+      CDN_BASIC_MAPPING_VARIABLE => '',
+      CDN_BASIC_MAPPING_HTTPS_VARIABLE => '',
+      CDN_BASIC_FARFUTURE_VARIABLE => FALSE,
+    );
+    $conf = array_merge($conf, $this->defaultConfig);
+  }
+
+  /**
+   * Set the protocol of the current "request".
+   *
+   * @param $protocol
+   *   'http' or 'https'.
+   */
+  function setRequestProtocol($protocol) {
+    if ($protocol == 'http') {
+      $_SERVER['HTTPS'] = 'off';
+      $_SERVER['HTTP_X_FORWARDED_PROTO'] = 'http';
+    }
+    elseif ($protocol == 'https') {
+      $_SERVER['HTTPS'] = 'on';
+      $_SERVER['HTTP_X_FORWARDED_PROTO'] = 'https';
+    }
+  }
+
+  /**
+   * Configure HTTPS-related settings.
+   *
+   * @param $supported
+   *   Boolean that indicates whether HTTPS is supported by the current CDN
+   *   or not.
+   * @param $mapping
+   *   The CDN mapping to use when the CDN supports HTTPS and the current
+   *   request is happening over HTTPS.
+   */
+  function configureHTTPS($supported, $mapping = '') {
+    $this->variableSet(CDN_HTTPS_SUPPORT_VARIABLE, $supported);
+    $this->variableSet(CDN_BASIC_MAPPING_HTTPS_VARIABLE, $mapping);
+  }
+
+  /**
+   * Given a file URI, get the expanded file path.
+   *
+   * @param $uri
+   *   @see file_stream_wrapper_get_instance_by_uri()
+   * @return
+   *  A Drupal root-relative path.
+   */
+  function getExpandedFilePath($uri) {
+    $wrapper = \Drupal::service("stream_wrapper_manager")->getViaUri($uri);
+    return str_replace($GLOBALS['base_url'] . '/', '', $wrapper->getExternalUrl());
+  }
+
+  /**
+   * Given a file URI, get its path, create the file and ensure it exists.
+   *
+   * @param $uri
+   *   @see getExpandedFilePath()
+   */
+  function touchFile($uri) {
+    $path = $this->getExpandedFilePath($uri);
+    $this->assertTrue(touch(rawurldecode($path)), 'Test file created.');
+    return $path;
+  }
+}
\ No newline at end of file
diff --git a/theme.inc b/theme.inc
index af0bd65..02c06eb 100644
--- a/theme.inc
+++ b/theme.inc
@@ -31,7 +31,12 @@ function theme_cdn_page_stats($variables) {
 
   $output = '';
   $items = array();
-  $mode = variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC);
+  // @FIXME
+// // @FIXME
+// // The correct configuration object could not be determined. You'll need to
+// // rewrite this call manually.
+// $mode = variable_get(CDN_MODE_VARIABLE, CDN_MODE_BASIC);
+
 
   $percentage = 100;
   if ($file_count > 0) {
@@ -64,7 +69,7 @@ function theme_cdn_page_stats($variables) {
   if (count($unsynced_files)) {
     $unsynced_items = array();
     foreach ($unsynced_files as $file) {
-      $unsynced_items[] = theme('cdn_page_stats_file_link', array(
+      $unsynced_items[] = _theme('cdn_page_stats_file_link', array(
         'file'          => $file,
         'absolute_path' => file_create_url($file),
         'synced'        => FALSE,
@@ -73,7 +78,7 @@ function theme_cdn_page_stats($variables) {
       ));
     }
     $item = t('Files not served from the CDN:');
-    $item .= theme('item_list', array(
+    $item .= _theme('item_list', array(
       'items'      => $unsynced_items,
       'attributes' => array('class' => 'file-list'),
     ));
@@ -91,7 +96,7 @@ function theme_cdn_page_stats($variables) {
       if (!isset($synced_items[$server])) {
         $synced_items[$server] = array();
       }
-      $synced_items[$server][] = theme('cdn_page_stats_file_link', array(
+      $synced_items[$server][] = _theme('cdn_page_stats_file_link', array(
         'file'          => $file,
         'absolute_path' => $synced_file['absolute path'],
         'synced'        => TRUE,
@@ -110,21 +115,21 @@ function theme_cdn_page_stats($variables) {
           '!pct'    => number_format($c / $cdn_file_count * 100),
         )
       );
-      $item .= theme('item_list', array(
+      $item .= _theme('item_list', array(
         'items'      => $synced_items[$server],
         'attributes' => array('class' => 'file-list'),
       ));
       $synced_by_server[] = $item;
     }
     $item = t('Files served from the CDN:');
-    $item .= theme('item_list', array('items' => $synced_by_server));
+    $item .= _theme('item_list', array('items' => $synced_by_server));
     $items[] =  $item;
   }
 
   $title = t('CDN integration statistics for %drupal_path', array(
     '%drupal_path' => $_GET['q']
   ));
-  $output .= theme('item_list', array(
+  $output .= _theme('item_list', array(
     'items' => $items,
     'title' => '<strong>' . $title . '</strong>',
   ));
@@ -154,19 +159,25 @@ function theme_cdn_page_stats_file_link($variables) {
   $cdn_url       = $variables['cdn_url'];
   $server        = $variables['server'];
 
-  $file_link = l(
-    t('!file', array('!file' => $file)),
-    $cdn_url,
-    array(
-      'external'   => TRUE,
-      'attributes' => array('title' => $absolute_path),
-    )
-  );
-  $touch_link = l(
-    t('touch'),
-    'admin/cdn/touch/' . $file,
-    array('query' => drupal_get_destination())
-  );
+  // @FIXME
+// l() expects a Url object, created from a route name or external URI.
+// $file_link = l(
+//     t('!file', array('!file' => $file)),
+//     $cdn_url,
+//     array(
+//       'external'   => TRUE,
+//       'attributes' => array('title' => $absolute_path),
+//     )
+//   );
+
+  // @FIXME
+// l() expects a Url object, created from a route name or external URI.
+// $touch_link = l(
+//     t('touch'),
+//     'admin/cdn/touch/' . $file,
+//     array('query' => drupal_get_destination())
+//   );
+
 
   $output = '';
   $output .= '<span class="file-link">' . $file_link;
