diff --git a/includes/common.inc b/includes/common.inc
index ceac115..ed065ae 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -2492,6 +2492,7 @@ function l($text, $path, array $options = array()) {
   if (isset($options['attributes']['title']) && strpos($options['attributes']['title'], '<') !== FALSE) {
     $options['attributes']['title'] = strip_tags($options['attributes']['title']);
   }
+  drupal_alter('link', $text, $path, $options);
 
   // Determine if rendering of the link is to be done with a theme function
   // or the inline default. Inline is faster, but if the theme system has been
diff --git a/modules/system/system.api.php b/modules/system/system.api.php
index d6cbc76..fa12ae3 100644
--- a/modules/system/system.api.php
+++ b/modules/system/system.api.php
@@ -4331,6 +4331,53 @@ function hook_url_outbound_alter(&$path, &$options, $original_path) {
 }
 
 /**
+ * Alters outbound links.
+ *
+ * @param string $text
+ *   The translated link text for the anchor tag.
+ * @param string $path
+ *   The internal path or external URL being linked to, such as "node/34" or
+ *   "http://example.com/foo". After the url() function is called to construct
+ *   the URL from $path and $options, the resulting URL is passed through
+ *   check_plain() before it is inserted into the HTML anchor tag, to ensure
+ *   well-formed HTML. See url() for more information and notes.
+ * @param array $options
+ *   An associative array of additional options. Defaults to an empty array. It
+ *   may contain the following elements.
+ *   - 'attributes': An associative array of HTML attributes to apply to the
+ *     anchor tag. If element 'class' is included, it must be an array; 'title'
+ *     must be a string; other elements are more flexible, as they just need
+ *     to work in a call to drupal_attributes($options['attributes']).
+ *   - 'html' (default FALSE): Whether $text is HTML or just plain-text. For
+ *     example, to make an image tag into a link, this must be set to TRUE, or
+ *     you will see the escaped HTML image tag. $text is not sanitized if
+ *     'html' is TRUE. The calling function must ensure that $text is already
+ *     safe.
+ *   - 'language': An optional language object. If the path being linked to is
+ *     internal to the site, $options['language'] is used to determine whether
+ *     the link is "active", or pointing to the current page (the language as
+ *     well as the path must match). This element is also used by url().
+ *   - Additional $options elements used by the url() function.
+ *
+ * @see url()
+ */
+function hook_link_alter($text, &$path, &$options) {
+  // Use an external RSS feed rather than the Drupal one.
+  if ($path == 'rss.xml') {
+    $path = 'http://example.com/rss.xml';
+    $options['external'] = TRUE;
+  }
+
+  // Instead of pointing to user/[uid]/edit, point to user/me/edit.
+  if (preg_match('|^user/([0-9]*)/edit(/.*)?|', $path, $matches)) {
+    global $user;
+    if ($user->uid == $matches[1]) {
+      $path = 'user/me/edit' . $matches[2];
+    }
+  }
+}
+
+/**
  * Alter the username that is displayed for a user.
  *
  * Called by format_username() to allow modules to alter the username that's
