? follow-validation-538172-13.patch
Index: follow.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/follow/follow.install,v
retrieving revision 1.3
diff -u -p -r1.3 follow.install
--- follow.install	2 Nov 2009 20:25:53 -0000	1.3
+++ follow.install	2 Nov 2009 21:51:53 -0000
@@ -10,8 +10,7 @@
  * Implementation of hook_install().
  */
 function follow_install() {
-  return;
-  // @todo: Add a default link to this site's node RSS feed.
+  // Add a default link to this site's node RSS feed.
   db_insert('follow_links')
     ->fields(array(
       'name' => 'self',
Index: follow.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/follow/follow.module,v
retrieving revision 1.6
diff -u -p -r1.6 follow.module
--- follow.module	2 Nov 2009 20:25:53 -0000	1.6
+++ follow.module	2 Nov 2009 21:51:53 -0000
@@ -232,7 +232,7 @@ function follow_link_title($uid = 0) {
     if ($setting == FOLLOW_NAME) {
       $account = user_load($uid);
       // Set plain to TRUE for realname module support.
-      return t('Follow !name on', array('!name' => theme('username', $account, array('plain' => TRUE))));
+      return t('Follow !name on', array('!name' => theme('username', array('account' => $account))));
     }
     return t('Follow me on');
   }
@@ -282,7 +282,7 @@ function theme_follow_links($variables) 
   $output = '<div class="follow-links clearfix">';
 
   foreach($links as $link) {
-    $title = $networks[$link->name];
+    $title = $networks[$link->name]['title'];
     $output .= theme('follow_link', array('link' => $link, 'title' => $title));
   }
 
@@ -375,16 +375,17 @@ function follow_links_form($form, &$form
   // Put all our existing links at the top, sorted by weight.
   if (is_array($links)) {
     foreach ($links as $name => $link) {
-      $title = $networks[$name];
-      $form['follow_links'][$name] = _follow_links_form_link($link, $title);
+      $title = $networks[$name]['title'];
+      $form['follow_links'][$name] = _follow_links_form_link($link, $title, $uid);
       // Unset this specific network so we don't add the same one again below.
       unset($networks[$name]);
     }
   }
   // Now add all the empty ones.
-  foreach ($networks as $name => $title) {
+  foreach ($networks as $name => $info) {
     $link = new stdClass();
-    $form['follow_links'][$name] = _follow_links_form_link($link, $title);
+    $link->name = $name;
+    $form['follow_links'][$name] = _follow_links_form_link($link, $info['title'], $uid);
   }
 
   $form['submit'] = array('#type' => 'submit', '#value' => t('Submit'));
@@ -395,7 +396,7 @@ function follow_links_form($form, &$form
 /**
  * Helper function to create an individual link form element.
  */
-function _follow_links_form_link($link, $title) {
+function _follow_links_form_link($link, $title, $uid) {
   $elements = array();
 
   $elements['name'] = array(
@@ -413,6 +414,8 @@ function _follow_links_form_link($link, 
   }
   $elements['url'] = array(
     '#type' => 'textfield',
+    '#follow_network' => $link->name,
+    '#follow_uid' => $uid,
     '#default_value' => isset($link->url) ? $link->url : '',
     '#element_validate' => array('follow_url_validate'),
   );
@@ -425,12 +428,34 @@ function _follow_links_form_link($link, 
  */
 function follow_url_validate($form) {
   $url = trim($form['#value']);
-  if($url && !preg_match("/^[a-zA-Z]+[:\/\/]+[A-Za-z0-9\-_]+\\.+[A-Za-z0-9\.\/%&=\?\-_]+$/i", $url)) {
-    form_error($form, t('The specified url is invalid.'));
+  $networks = follow_networks_load($form['#follow_uid']);
+  $info = $networks[$form['#follow_network']];
+  $regex = follow_build_url_regex($info);
+  if($url && !preg_match($regex, $url)) {
+    if (!empty($info['domain'])) {
+      $message = t('The specified url is invalid for the domain %domain.  Make sure you use http:// and a trailing slash if needed.', array('%domain' => $info['domain']));
+    }
+    else {
+      $message = t('The specified path is invalid.  Please enter a path on this site.');
+    }
+    form_error($form, $message);
   }
 }
 
 /**
+ * Build a regex to validate the url based on a known service url.
+ */
+function follow_build_url_regex($network_info) {
+  $regex = '@^';
+  if (!empty($network_info['domain'])) {
+    // An external link.
+    $regex .= 'https?://([a-z0-9\-_.]+\\.|)' . str_replace('.', '\\.', $network_info['domain']) . '/';
+  }
+  $regex .= '[A-Za-z0-9./%&=\?\-_]*$@i';
+  return $regex;
+}
+
+/**
  * Submit handler for the follow_links_form.
  */
 function follow_links_form_submit($form, &$form_state) {
@@ -608,22 +633,64 @@ function follow_networks_load($uid, $res
  */
 function follow_default_networks($uid) {
   $networks = array(
-    'facebook'  => t('Facebook'),
-    'virb'      => t('Virb'),
-    'myspace'   => t('MySpace'),
-    'twitter'   => t('Twitter'),
-    'picasa'    => t('Picasa'),
-    'flickr'    => t('Flickr'),
-    'youtube'   => t('YouTube'),
-    'vimeo'     => t('Vimeo'),
-    'bliptv'    => t('blip.tv'),
-    'lastfm'    => t('last.fm'),
-    'linkedin'  => t('LinkedIn'),
-    'delicious' => t('Delicious'),
-    'tumblr'    => t('Tumblr'),
+    'facebook'  => array(
+      'title' => t('Facebook'),
+      'domain' => 'facebook.com',
+    ),
+    'virb'      => array(
+      'title' => t('Virb'),
+      'domain' => 'virb.com',
+    ),
+    'myspace'   => array(
+      'title' => t('MySpace'),
+      'domain' => 'myspace.com',
+    ),
+    'twitter'   => array(
+      'title' => t('Twitter'),
+      'domain' => 'twitter.com',
+    ),
+    'picasa'    => array(
+      'title' => t('Picasa'),
+      'domain' => 'picasaweb.google.com',
+    ),
+    'flickr'    => array(
+      'title' => t('Flickr'),
+      'domain' => 'flickr.com',
+    ),
+    'youtube'   => array(
+      'title' => t('YouTube'),
+      'domain' => 'youtube.com',
+    ),
+    'vimeo'     => array(
+      'title' => t('Vimeo'),
+      'domain' => 'vimeo.com',
+    ),
+    'bliptv'    => array(
+      'title' => t('blip.tv'),
+      'domain' => 'blip.tv',
+    ),
+    'lastfm'    => array(
+      'title' => t('last.fm'),
+      'domain' => 'last.fm',
+    ),
+    'linkedin'  => array(
+      'title' => t('LinkedIn'),
+      'domain' => 'linkedin.com',
+    ),
+    'delicious' => array(
+      'title' => t('Delicious'),
+      'domain' => 'delicious.com',
+    ),
+    'tumblr'    => array(
+      'title' => t('Tumblr'),
+      'domain' => 'tumblr.com',
+    ),
   );
   if ($uid == 0) {
-    $networks['self'] = t('This site');
+    $networks['self'] = array(
+      'title' => t('This site'),
+      'domain' => '',
+    );
   }
   return $networks;
 }
