diff --git a/redirect.admin.inc b/redirect.admin.inc
index 990a22a..7104dff 100644
--- a/redirect.admin.inc
+++ b/redirect.admin.inc
@@ -670,40 +670,78 @@ function redirect_settings_form($form, &$form_state) {
   $form['globals'] = array(
     '#type' => 'fieldset',
     '#title' => t('Always enabled redirections'),
-    '#description' => t('(formerly Global Redirect features)'),
-    '#access' => FALSE,
   );
   $form['globals']['redirect_global_home'] = array(
     '#type' => 'checkbox',
-    '#title' => t('Redirect from paths like index.php and /node to the root directory.'),
+    '#title' => t('Redirect alternative front page URLs to the root directory.'),
     '#default_value' => variable_get('redirect_global_home', 1),
-    '#access' => FALSE,
+    '#description' => t('Includes all aliases for the front page, %root, as well as %node if a default front page is not set.', array('%root' => '/index.php', '%node' => '/node')),
+  );
+  $form['globals']['redirect_global_index'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Remove index.php from all non-front page paths.'),
+    '#default_value' => variable_get('redirect_global_index', 0),
+    '#description' => t('Will remove index.php from paths such as %prepend and %append.', array('%prepend' => '/index.php?q=node/1', '%append' => '/page-alias/index.php')),
   );
   $form['globals']['redirect_global_clean'] = array(
     '#type' => 'checkbox',
     '#title' => t('Redirect from non-clean URLs to clean URLs.'),
     '#default_value' => variable_get('redirect_global_clean', 1),
     '#disabled' => !variable_get('clean_url', 0),
-    '#access' => FALSE,
   );
   $form['globals']['redirect_global_canonical'] = array(
     '#type' => 'checkbox',
     '#title' => t('Redirect from non-canonical URLs to the canonical URLs.'),
     '#default_value' => variable_get('redirect_global_canonical', 1),
   );
+  $form['globals']['redirect_global_canonical_front'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Redirect the front page to its canonical URL.'),
+    '#default_value' => variable_get('redirect_global_canonical_front', 0),
+    '#description' => t('Add a path to a request for the site root. For example, a request for %rootpath will redirect to %canonicalpath if the default front page is set to %defaultfrontpage.', array('%rootpath' => 'http://example.com/', '%canonicalpath' => 'http://example.com/node/1', '%defaultfrontpage' => 'node/1')),
+  );
   $form['globals']['redirect_global_deslash'] = array(
     '#type' => 'checkbox',
     '#title' => t('Remove trailing slashes from paths.'),
-    '#default_value' => variable_get('redirect_global_deslash', 0),
-    '#access' => FALSE,
+    '#default_value' => variable_get('redirect_global_deslash', 1),
+  );
+  $form['globals']['redirect_global_add_slash'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Add trailing slashes to paths.'),
+    '#description' => t('For use with the Trailing Slash module instead of editing the .htaccess file.'),
+    '#default_value' => variable_get('redirect_global_add_slash', 0),
   );
   $form['globals']['redirect_global_admin_paths'] = array(
     '#type' => 'checkbox',
     '#title' => t('Allow redirections on admin paths.'),
     '#default_value' => variable_get('redirect_global_admin_paths', 0),
   );
+  if (module_exists('locale')) {
+    $form['globals']['redirect_global_language_prefix'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Enforce Language Prefix'),
+      '#description' => t('Enforce language prefix in paths.'),
+      '#default_value' => variable_get('redirect_global_language_prefix', 0),
+    );
+
+    $form['globals']['redirect_global_language_prefix_paths'] = array(
+      '#type' => 'textarea',
+      '#title' => t('Language Prefix Exclude Paths'),
+      '#description' => t('Specify pages by using their paths. Enter one path per line. The '*' character is a wildcard. Example paths are blog for the blog page and blog/* for every personal blog. <front> is the front page.'),
+      '#default_value' => variable_get('redirect_global_language_prefix_paths', ''),
+      '#states' => array(
+        'visible' => array(
+          ':input[name="redirect_global_language_prefix"]' => array('checked' => TRUE),
+        ),
+      ),
+    );
+  }
+
+  $form['submit'] = array(
+    '#validate' => array('redirect_settings_form_validate'),
+    '#submit' => array('redirect_settings_form_submit'),
+  );
 
-  $form['#submit'][] = 'redirect_settings_form_submit';
   return system_settings_form($form);
 }
 
@@ -716,6 +754,17 @@ function redirect_settings_form_submit($form, &$form_state) {
   redirect_page_cache_clear();
 }
 
+/**
+ * Form validator; makes sure conflicting settings aren't chosen.
+ *
+ * @see redirect_settings_form()
+ */
+function redirect_settings_form_validate($form, &$form_state) {
+  if ($form_state['values']['redirect_global_deslash'] && $form_state['values']['redirect_global_add_slash']) {
+    form_set_error('info', t('You can not have both %deslash and %add_slash enabled.', array('%deslash' => rtrim($form['globals']['redirect_global_deslash']['#title'], '.'), '%add_slash' => rtrim($form['globals']['redirect_global_add_slash']['#title'], '.'))));
+  }
+}
+
 function redirect_404_list($form = NULL) {
   $destination = drupal_get_destination();
 
diff --git a/redirect.module b/redirect.module
index 5d92399..449ea84 100644
--- a/redirect.module
+++ b/redirect.module
@@ -204,6 +204,8 @@ function redirect_get_current_redirect() {
  * Implements hook_url_inbound_alter().
  */
 function redirect_url_inbound_alter(&$path, $original_path, $path_language) {
+  global $language;
+
   // If the current path global does not exist, then drupal_get_path_alias()
   // will fail. This condition only happens when $path is the front page.
   // @todo Remove when http://drupal.org/node/1329914 is fixed in core.
@@ -226,23 +228,54 @@ function redirect_url_inbound_alter(&$path, $original_path, $path_language) {
     }
   }
 
-  // Redirect to canonical URLs.
-  // Commented out per https://www.drupal.org/node/2048137.
-  //if ($path && variable_get('redirect_canonical', 1)) {
-    //$alias = drupal_get_path_alias($path, $path_language);
-    //if ($alias != $path && $alias != $original_path) {
-      //return redirect_redirect(array('redirect' => $alias, 'type' => 'global'));
-    //}
-
-    // Redirect from default entity paths to the proper entity path.
-    //if ($path_entity = redirect_load_entity_from_path($path)) {
-    //  if ($uri = entity_uri($path_entity['entity_type'], $path_entity['entity'])) {
-    //    if ($path != $uri['path']) {
-    //      return redirect_redirect(array('redirect' => $uri['path'], 'redirect_options' => $uri['options'], 'type' => 'global'));
-    //    }
-    //  }
-    //}
-  //}
+  // Check for empty path.
+  if (empty($path)) {
+    return;
+  }
+  // Do not redirect if $original_path does not match the requested url.
+  if ($original_path != $_GET['q']) {
+    return;
+  }
+  // Do not redirect if disallowed.
+  if (!redirect_can_redirect()) {
+    return;
+  }
+
+  // Determine if front page. drupal_is_front_page() is not accurate here
+  // because drupal_path_initialize() has not executed yet.
+  $is_front_page = ($path == variable_get('site_frontpage', 'node') ? TRUE : FALSE);
+
+  // Remove query string from request uri.
+  $request_uri_parts = explode('?', request_uri());
+  $request_path = urldecode($request_uri_parts[0]);
+
+  // Redirect the front page to the root level.
+  if ($is_front_page
+      && variable_get('redirect_global_home', 1)
+      && !variable_get('redirect_global_canonical_front', 0)
+      && base_path() != $request_path
+      && base_path() . $language->prefix != $request_path) {
+    return redirect_redirect((object)array('redirect' => '', 'type' => 'global'));
+  }
+
+  // Redirect to the canonical URL.
+  $alias = drupal_get_path_alias($path, $path_language);
+  if ((!$is_front_page && variable_get('redirect_global_canonical', 1)
+        || $is_front_page && variable_get('redirect_global_canonical_front', 0))
+      && $alias != $path
+      && $alias != $original_path
+      && base_path() . $alias != $request_path
+      && base_path() . $language->prefix . '/' . $alias != $request_path) {
+    return redirect_redirect((object)array('redirect' => $alias, 'type' => 'global'));
+  }
+
+  // Redirect from default entity paths to the proper entity path.
+  if ($path_entity = redirect_load_entity_from_path($path)) {
+    $uri = entity_uri($path_entity['entity_type'], $path_entity['entity']);
+    if ($path != $uri['path']) {
+      return redirect_redirect((object)array('redirect' => $uri['path'], 'redirect_options' => $uri['options'], 'type' => 'global'));
+    }
+  }
 }
 
 /**
@@ -309,25 +342,65 @@ function redirect_init() {
     redirect_redirect($redirect);
   }
 
-  $redirect_global = FALSE;
-  $request_uri = $original_uri = ltrim(request_uri(), '/');
+  // Get the request URI without the $base_path prefix.
+  if (isset($_GET['q'])) {
+    $unsafe_path = $_GET['q'];
+    if (url_is_external($unsafe_path)) {
+      // We do not allow absolute URLs to be passed via $_GET, as this can be an attack vector.
+      return;
+    }
+    $destination = drupal_parse_url($unsafe_path);
+    $path = $destination['path'];
+  }
+  else {
+    // This is a request using a clean URL. Extract the path from request_uri().
+    $request_path = strtok(request_uri(), '?');
+    $base_path_len = drupal_strlen(rtrim(dirname($_SERVER['SCRIPT_NAME']), '\/'));
+    // Unescape and strip $base_path prefix, leaving q without a leading slash.
+    $path = drupal_substr(urldecode($request_path), $base_path_len + 1);
+  }
+  $request_uri = $original_uri = ltrim($path, '/');
 
   // Redirect from non-clean URLs to clean URLs.
-  if (variable_get('redirect_global_clean', 1) && variable_get('clean_url', 0) && strpos($request_uri, '?q=') !== FALSE) {
-    //$redirect_global = TRUE;
-    //$request_uri = str_replace('?q=', '', $request_uri);
+  if (variable_get('redirect_global_clean', 1)
+      && variable_get('clean_url', 0)
+      && strpos(request_uri(), '?q=') !== FALSE) {
+    redirect_redirect((object)array('redirect' => $request_uri, 'type' => 'global'));
   }
 
-  if (strpos($request_uri, 'index.php') !== FALSE) {
-    //$redirect_global = TRUE;
-    //$request_uri = str_replace('index.php', '', $request_uri);
+  // Strip index.php
+  if (strpos(request_uri(), 'index.php') !== FALSE) {
+    if (!drupal_is_front_page() && variable_get('redirect_global_index', 0)) {
+      $request_uri = str_replace('index.php', '', $request_uri);
+      redirect_redirect((object)array('redirect' => $request_uri, 'type' => 'global'));
+    }
+    elseif (drupal_is_front_page() && variable_get('redirect_global_home', 0)) {
+      redirect_redirect((object)array('redirect' => '', 'type' => 'global'));
+    }
   }
 
-  //$request_uri = ltrim($request_uri, '/');
-  //$parsed = parse_url($request_uri);
+  // Deslash (Remove trailing slashes from paths).
+  $langcode = isset($options['language']->language) ? $options['language']->language : '';
+  $alias = drupal_get_path_alias(current_path(), $langcode);
+  if (variable_get('redirect_global_deslash', 0)
+      && substr($request_uri, -1) == '/'
+      && $request_uri !== $alias) {
+    redirect_redirect((object)array('redirect' => rtrim($request_uri, '/'), 'type' => 'global'));
+  }
+  // Add slash (Add trailing slashes to paths).
+  elseif (variable_get('redirect_global_add_slash', 0)
+          && substr($request_uri, -1) !== '/'
+          && !drupal_is_front_page()) {
+    redirect_redirect((object)array('redirect' => $request_uri . '/', 'type' => 'global'));
+  }
 
-  if ($redirect_global && $request_uri != $original_uri) {
-    redirect_redirect(array(/*'redirect' => $request_uri,*/ 'type' => 'global'));
+  // Force language prefix.
+  if (variable_get('redirect_global_language_prefix', 0) && module_exists('locale')) {
+    require_once DRUPAL_ROOT . '/includes/language.inc';
+    list($language, $raw_path) = language_url_split_prefix($request_uri, language_list());
+    if (!$language && !drupal_match_path($raw_path, variable_get('redirect_global_language_prefix_paths', ''))) {
+      redirect_redirect((object)array('redirect' => $request_uri, 'type' => 'global'));
+    }
   }
 }
 
@@ -740,7 +813,7 @@ function redirect_validate($redirect, $form, &$form_state) {
   }
 }
 
-function redirect_object_prepare($redirect, $defaults = array()) {
+function redirect_object_prepare(stdClass $redirect, $defaults = array()) {
   $defaults += array(
     'rid' => NULL,
     'type' => 'redirect',
@@ -1122,7 +1195,21 @@ function redirect_redirect($redirect = NULL) {
  */
 function redirect_goto($redirect) {
   $redirect->redirect_options['absolute'] = TRUE;
-  $url = url($redirect->redirect, $redirect->redirect_options);
+  // Prevent a path like 'index.php?q=node/1' from redirecting to '?q=path-alias'
+  // if canonical redirection is disabled. This will make url() treat 'node/1'
+  // as if it is already an alias and prevent a drupal_get_path_alias() lookup.
+  if (!variable_get('redirect_global_canonical', 0)) {
+    $redirect->redirect_options['alias'] = TRUE;
+  }
+  if (module_exists('locale')) {
+    // Peel off language prefix if already there.
+    require_once DRUPAL_ROOT . '/includes/language.inc';
+    list($language, $raw_path) = language_url_split_prefix($redirect->redirect, language_list());
+    $url = ($language) ? url($raw_path, $redirect->redirect_options) : url($redirect->redirect, $redirect->redirect_options);
+  }
+  else {
+    $url = url($redirect->redirect, $redirect->redirect_options);
+  }
   drupal_add_http_header('Location', $url);
   drupal_add_http_header('Status', redirect_status_code_options($redirect->status_code));
 
@@ -1405,9 +1492,14 @@ function redirect_variables() {
     'redirect_purge_inactive' => 0,
     'redirect_purge_amount' => 100,
     'redirect_global_home' => 1,
+    'redirect_global_index' => 0,
     'redirect_global_clean' => 1,
     'redirect_global_canonical' => 1,
+    'redirect_global_canonical_front' => 0,
+    'redirect_global_deslash' => 1,
+    'redirect_global_add_slash' => 0,
     'redirect_global_admin_paths' => 0,
+    'redirect_global_language_prefix' => 0,
   );
 }
 
