Index: shorturl.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/shorturl/Attic/shorturl.admin.inc,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 shorturl.admin.inc
--- shorturl.admin.inc	8 Aug 2009 06:52:50 -0000	1.1.2.1
+++ shorturl.admin.inc	26 Sep 2009 18:59:21 -0000
@@ -12,23 +12,56 @@
  */
 function shorturl_admin_settings_form(&$form_state) {
 
-  $form['shorturl_domain'] = array(
+  $form['shorturl_engine'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Engine Options'),
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
+  );
+  $form['shorturl_engine']['shorturl_domain'] = array(
     '#type' => 'textfield',
     '#title' => t('Short Domain:'),
     '#default_value' => variable_get('shorturl_domain', $_SERVER['HTTP_HOST']),
     '#required' => TRUE,
     '#description' => t('The domain to be used in short URLs'),
   );
-
-  $form['shorturl_start_from'] = array(
+  $form['shorturl_engine']['shorturl_start_from'] = array(
     '#type' => 'textfield',
     '#title' => t('Start From ID#:'),
     '#default_value' => variable_get('shorturl_start_from', 3844),
     '#required' => TRUE,
     '#description' => t('3844 is approximately the first 3-characters long short URI. Indicate a number that is less or more, depending on your needs.'),
   );
-  
-  
+  $form['shorturl_engine']['shorturl_allow_duplicates'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Allow duplicate submissions'),
+    '#description' => t('Allows user to create more than one link to the same URL.  This is important for tracking links by users and for targeting different links to different roups for the purpose of comparing metrics.'),
+    '#default_value' => variable_get('shorturl_allow_duplicates', 0),
+    '#return_value' => 1,
+  );
+  $form['shorturl_statistics'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Statistics Options'),
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
+  );
+  $form['shorturl_statistics']['shorturl_date_format'] = array(
+    '#type' => 'select',
+    '#title' => t('Date format'),
+    '#options' => array(
+      'small' => format_date($time, 'small'),
+      'medium' => format_date($time, 'medium'),
+      'large' => format_date($time, 'large'),
+      'custom' => t('Custom'),
+    ),
+    '#default_value' => variable_get('shorturl_date_format', 'small'),
+  );
+  $form['shorturl_statistics']['shorturl_custom_date_format'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Custom date format'),
+    '#description' => t('If "Custom", see <a href="http://us.php.net/manual/en/function.date.php" target="_blank">the PHP docs</a> for date formats.'),
+    '#default_value' => variable_get('shorturl_custom_date_format', ''),
+  );
 
   return system_settings_form($form);
 }
Index: shorturl.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/shorturl/shorturl.install,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 shorturl.install
--- shorturl.install	8 Aug 2009 06:52:50 -0000	1.1.2.1
+++ shorturl.install	27 Sep 2009 22:14:33 -0000
@@ -1,8 +1,6 @@
 <?php
-// $Id: shorturl.install,v 1.1.2.1 2009/08/08 06:52:50 inadarei Exp $
-/*
-* @File shorturl.install
-*/
+// $Id: shorturl.install,v 1.1 2009/05/13 17:41:39 inadarei Exp $
+
 
 /**
  * Implementation of hook_schema().
@@ -13,12 +11,18 @@
     'description' => 'ShortURL Links Table.',
     'fields' => array(
       'lid' => array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE, 'length' => 22),
+      'uid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, 'length' => 22),
       'orig_url' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
+      'title' => array('type' => 'varchar', 'length' => 255, 'not null' => FALSE, 'default' => ''),
+      'description' => array('type' => 'varchar', 'length' => 255, 'not null' => FALSE, 'default' => ''),
+      'keywords' => array('type' => 'varchar', 'length' => 255, 'not null' => FALSE, 'default' => ''),
       'created' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
-      'remote_ip' => array('type' => 'varchar', 'length' => 20, 'not null' => FALSE, 'default' => ''),        
+      'remote_ip' => array('type' => 'varchar', 'length' => 20, 'not null' => FALSE, 'default' => ''),
       ),
     'indexes' => array(
       'shorturl_orig_url' => array('orig_url'),
+      'shorturl_uid' => array('uid'),
+      'shorturl_keywords' => array('keywords'),
       ),
     'primary key' => array('lid'),
     );
@@ -26,34 +30,62 @@
   $schema['shorturl_access'] = array(
     'fields' => array(
       'aid' => array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE, 'length' => 22),
-      'url_id' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, 'length' => 22),      
+      'url_id' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, 'length' => 22),
       'url_key' => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
       'remote_ip' => array('type' => 'varchar', 'length' => 20, 'not null' => TRUE, 'default' => ''),
-      'referer' => array('type' => 'text', 'not null' => TRUE, 'size' => 'normal'),      
-      'browser' => array('type' => 'text', 'not null' => TRUE, 'size' => 'normal'),            
-      'access_time' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),            
+      'referrer' => array('type' => 'text', 'not null' => TRUE, 'size' => 'normal'),
+      'browser' => array('type' => 'text', 'not null' => TRUE, 'size' => 'normal'),
+      'access_time' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
     ),
     'primary key' => array('aid'),
    );
-  
+
   return $schema;
 }
- 
- /**
+
+/**
  * Implementation of hook_install()
  */
 function shorturl_install() {
   drupal_install_schema('shorturl');
-     
+
   // Set this module at the top!
   db_query("UPDATE {system} SET weight = -100 WHERE name = 'shorturl'");
-  
+
 }
 
- /**
+/**
  * Implementation of hook_uninstall().
  */
 function shorturl_uninstall() {
   drupal_uninstall_schema('shorturl');
 }
 
+/**
+ * Add user ID to shorturl links table
+ */
+function shorturl_update_1() {
+  $ret = array();
+  db_add_field($ret, 'shorturl_link', 'uid', array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, 'length' => 22), array('indexes' => array('shorturl_uid' => array('uid'))));
+  return $ret;
+}
+
+/**
+ * Add title, description, and keywords to shorturl links table
+ */
+function shorturl_update_2() {
+  $ret = array();
+  db_add_field($ret, 'shorturl_link', 'title', array('type' => 'varchar', 'length' => 255, 'not null' => FALSE, 'default' => ''));
+  db_add_field($ret, 'shorturl_link', 'description', array('type' => 'varchar', 'length' => 255, 'not null' => FALSE, 'default' => ''));
+  db_add_field($ret, 'shorturl_link', 'keywords', array('type' => 'varchar', 'length' => 255, 'not null' => FALSE, 'default' => ''), array('indexes' => array('shorturl_keywords' => array('keywords'))));
+  return $ret;
+}
+
+/**
+ * Correct typo in field name (referer -> referrer)
+ */
+function shorturl_update_3() {
+  $ret = array();
+  db_change_field($ret, 'shorturl_access', 'referer', 'referrer', array('type' => 'text', 'not null' => TRUE, 'size' => 'normal'));
+  return $ret;
+}
\ No newline at end of file
Index: shorturl.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/shorturl/shorturl.module,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 shorturl.module
--- shorturl.module	8 Aug 2009 06:52:50 -0000	1.1.2.1
+++ shorturl.module	8 Oct 2009 15:53:32 -0000
@@ -1,9 +1,4 @@
 <?php
-//$Id: shorturl.module,v 1.1.2.1 2009/08/08 06:52:50 inadarei Exp $
-/**
-* @File shorturl.module
-*   the module file for shorturl
-*/
 
 // Minimum length of URI: 3 characters (3844 in base10 is equivalent to first 3-char number in base62).
 // This setting is modifyable from settings.php if you don't like it.
@@ -26,25 +21,87 @@
         $orig_url = url($orig_url, array('absolute'=>TRUE)); //Let drupal make relative URLs absolute
       }
       
+      $remote_ip = (empty($_SERVER['REMOTE_ADDR'])) ? '' : $_SERVER['REMOTE_ADDR'];
+      $referrer = (empty($_SERVER['HTTP_REFERER'])) ? '' : $_SERVER['HTTP_REFERER'];
+      $browser = (empty($_SERVER['HTTP_USER_AGENT'])) ? '' : $_SERVER['HTTP_USER_AGENT'];
+      db_query("INSERT INTO {shorturl_access} (`url_id`, `url_key`, `remote_ip`, `referrer`, `browser`, `access_time`) VALUES (%d, '%s', '%s', '%s', '%s', %d) ", $indx, $token, $remote_ip, $referrer, $browser, (int)time());
+      
+      //echo $orig_url;
       drupal_goto($orig_url);
       exit();      
     }
   }
-  
 }
 
-/** 
-* hook_perm implementation
-*/ 
+/**
+ * Implementation of hook_perm().
+ */
 function shorturl_perm() {
-  return array('administer shorturl');
+  return array('view own statistics', 'view all statistics', 'view link details', 'export all statistics', 'export own statistics', 'administer shorturl');
 }
 
 /**
-* hook_menu() implementation
-*/
+ * Implementation of hook_menu().
+ */
 function shorturl_menu() {
-
+  
+  $items = array();
+  $items['shorturl'] = array(
+    'title' => 'Short URL Statistics',
+    'page callback' => 'shorturl_statistics',
+    'access arguments' => array('view all statistics'),
+    'type' => MENU_NORMAL_ITEM
+  );
+  $items['shorturl/all'] = array(
+    'title' => 'All users',
+    'page callback' => 'shorturl_statistics',
+    'page arguments' => array('all'),
+    'access arguments' => array('view all statistics'),
+    'type' => MENU_LOCAL_TASK
+  );
+  $items['shorturl/all/export'] = array(
+		'title'						 => 'Export all to Excel',
+    'description'      => t('Export link details as a CSV file'),
+		'page callback'		 => 'shorturl_statistics_export',
+    'access arguments' => array('export all statistics'),
+    'type' => MENU_CALLBACK
+	);
+  $items['shorturl/user'] = array(
+    'title' => 'Your URLs',
+    'page callback' => 'shorturl_statistics',
+    'page arguments' => array('all'),
+    'access arguments' => array('view own statistics'),
+    'type' => MENU_DEFAULT_LOCAL_TASK
+  );
+  $items['shorturl/user/%user'] = array(
+    'title' => 'Short URL Statistics',
+    'page callback' => 'shorturl_statistics',
+    'page arguments' => array(2),
+    'access arguments' => array('view all statistics'),
+    'type' => MENU_CALLBACK
+  );
+  $items['shorturl/user/%user/export'] = array(
+		'title'						 => 'Export to Excel',
+    'description'      => t('Export link details as a CSV file'),
+		'page callback'		 => 'shorturl_statistics_export',
+    'page arguments'   => array(2),
+    'access arguments' => array('export own statistics'),
+    'type' => MENU_CALLBACK
+	);
+  $items['shorturl/list/%shorturl'] = array(
+    'title' => 'Short URL Statistics',
+    'page callback' => 'shorturl_statistics',
+    'page arguments' => array('all', 2),
+    'access arguments' => array('view own statistics'),
+    'type' => MENU_CALLBACK
+  );
+  $items['shorturl/link/%shorturl'] = array(
+    'title' => 'Short URL Statistics',
+    'page callback' => 'shorturl_statistics_link',
+    'page arguments' => array(2),
+    'access arguments' => array('view link details'),
+    'type' => MENU_CALLBACK
+  );
   $items['admin/settings/shorturl'] = array(
     'title' => 'ShortURL',
     'description' => 'Configure the settings for ShortURL.',
@@ -52,12 +109,238 @@
     'page arguments' => array('shorturl_admin_settings_form'),
     'access arguments' => array('administer shorturl'),
     'file' => 'shorturl.admin.inc',
-    'type' => MENU_NORMAL_ITEM,
   );
-
+  $items['admin/reports/shorturl'] = array(
+    'title' => 'Short URL Statistics',
+    'page callback' => 'shorturl_statistics',
+    'page arguments' => array('all'),
+    'access arguments' => array('administer shorturl'),
+  );
   return $items;
 }
 
+function shorturl_load($lid) {
+  return db_fetch_object(db_query("SELECT * FROM {shorturl_link} WHERE lid = '%d'", $lid));
+}
+
+/**
+ * Implementation of hook_block().
+ */
+function shorturl_block($op = 'list', $delta = 0, $edit = array()) {
+  switch ($op) {
+    case 'list':
+      $block['shorturl_totals']['info'] = t('Short URL Totals');
+      return $block;
+    case 'view':
+      if ($delta == 'shorturl_totals') {
+        $block['subject'] = t('Short URL Totals');
+        
+        $all_links = db_result(db_query('SELECT COUNT(lid) FROM {shorturl_link}'));
+        $all_clicks = db_result(db_query('SELECT COUNT(aid) FROM {shorturl_access}'));
+        
+        $block['content'] = '<p>'. t('!site has shortened !links URLs that have been clicked !clicks times.', array('!site' => variable_get('site_name', 'Drupal'), '!links' => '<strong>'. $all_links .'</strong>', '!clicks' => '<strong>'. $all_clicks .'</strong>')) .'</p>';
+        return $block;
+      }
+  }
+}
+
+function shorturl_statistics($user = NULL, $link = NULL) {
+  if (empty($user)) {
+    global $user;
+    drupal_set_title(($user->uid != 0) ? t('Your recent links') : t('Recently Shortened Links'));
+    $access = 'own';
+  }
+  else {
+    drupal_set_title(is_object($user) ? t("!username's Recent Links", array('!username' => $user->name)) : t('Recently Shortened Links'));
+    $access = 'all';
+  }
+  drupal_add_css(drupal_get_path('module', 'shorturl') .'/shorturl.css', 'module', 'all');
+  $output = '';
+  
+  if (is_object($user) && ($user->uid != 0)) {
+    $sql = "SELECT lid, orig_url, title, description, keywords, count(aid) as clicks, created, uid FROM {shorturl_link} sl LEFT JOIN {shorturl_access} sa ON lid=url_id WHERE sl.uid='$user->uid' GROUP BY lid ORDER BY created DESC";
+    $sql_count = "SELECT COUNT(lid) FROM {shorturl_link} WHERE uid='$user->uid'";
+    $result = pager_query($sql, 25, 0, $sql_count);
+  }
+  else if (is_object($link)) {
+    $sql = "SELECT lid, orig_url, title, description, keywords, count(aid) as clicks, created, uid FROM {shorturl_link} sl LEFT JOIN {shorturl_access} sa ON lid=url_id WHERE sl.orig_url='$link->orig_url' GROUP BY lid ORDER BY clicks DESC";
+    $sql_count = "SELECT COUNT(lid) FROM {shorturl_link} WHERE orig_url='$link->orig_url'";
+    $result = pager_query($sql, 25, 0, $sql_count);
+  }
+  else {
+    $sql = 'SELECT lid, orig_url, title, description, keywords, count(aid) as clicks, count(orig_url) as links, created, uid FROM {shorturl_link} sl LEFT JOIN {shorturl_access} sa ON lid=url_id GROUP BY orig_url ORDER BY clicks DESC LIMIT 25';
+    $result = db_query($sql);
+  }
+
+  $rows = array();
+  while ($link = db_fetch_object($result)) {
+    $key = shorturl_encode_url($link->lid);
+    $target = (is_object($user) && ($user->uid != 0)) ? $link->orig_url : $key;
+    
+    if (!empty($link->title)) {
+      $title = html_entity_decode($link->title, ENT_QUOTES, 'UTF-8');
+      $url = (strlen($link->orig_url) > 65) ? substr($link->orig_url, 0, 65).'...' : $link->orig_url;
+      $title = (strlen($title) > 50) ? substr($title, 0, 50).'...' : $title;
+      $details = '<div class="link">'.l($title, $target).'</div><div class="url">'.htmlspecialchars($url).'</div>';
+    }
+    else {
+      $url = (strlen($link->orig_url) > 45) ? substr($link->orig_url, 0, 45).'...' : $link->orig_url;
+      $details = '<div class="link">'.l($url, $target).'</div>';
+    }
+    
+    /**
+     * We group links by original URL to show aggragated stats, but need to link to a
+     * list of individual links.
+     */
+    $links = (!empty($link->links)) ? $link->links + 1 - $link->clicks : 1;
+    if ($links > 1) {
+      $details .= '<div class="details">'.l(t('view all !links links to this page', array('!links' => $links)), 'shorturl/list/'.$link->lid).'</div>';
+    }
+    else if (user_access('view link details')) {
+      $details .= '<div class="details">'.l(t('details for !shorturl', array('!shorturl' => $key)), 'shorturl/link/'.$link->lid) .' - '. url($key, array('absolute' => TRUE)) .'</div>';
+    }
+    
+    $rows[] = array(
+      array('scope' => 'row', 'class' => 'details', 'data' => $details, 'header' => TRUE),
+      array('class' => 'clicks', 'data' => '<div class="count">'.$link->clicks.'</div>'),
+      array('class' => 'date', 'data' => format_date($link->created, variable_get('shorturl_date_format', 'small'), variable_get('shorturl_custom_date_format', ''))),
+    );
+  }
+
+  if (!$rows) {
+    $rows[] = array(array('data' => t('No links available.'), 'colspan' => '3'));
+  }
+  
+  $header = array(
+    array('scope' => 'col', 'data' => t('Info')),
+    array('scope' => 'col', 'data' => t('Clicks')),
+    array('scope' => 'col', 'data' => t('Date')),
+  );
+
+  if (is_object($user) && ($user->uid != 0) && user_access('export '.$access.' statistics')) {
+    $output .= l(t('Export to CSV'), 'shorturl/user/'. $user->uid .'/export') .' '. t('(Opens in most spreadsheet applications)');
+  }
+  else if (user_access('export all statistics')) {
+    $output .= l(t('Export to CSV'), 'shorturl/all/export') .' '. t('(Opens in most spreadsheet applications)');
+  }
+  $output .= '<div id="shorturl-statistics" class="shorturl">';
+  $output .= theme('table', $header, $rows, array('cellspacing' => '10', 'summary' => 'Information on each shortened URL, including the number of clicks, date it was shortened, and the URL'));
+  $output .= theme('pager', NULL, 25, 0);
+  $output .= '</div>';
+  
+
+  return $output;
+}
+
+function shorturl_statistics_link($link) {
+  $key = shorturl_encode_url($link->lid);
+  drupal_set_title(t('Link details for !key', array('!key' => url($key, array('absolute' => true)))));
+  drupal_add_css(drupal_get_path('module', 'shorturl') .'/shorturl.css', 'module', 'all');
+  $output = '';
+  
+  $user = user_load($link->uid);
+  $link_short = (strlen($link->orig_url) > 150) ? substr($link->orig_url, 0, 150).'...' : $link->orig_url;
+  $clicks = db_result(db_query("SELECT COUNT(aid) FROM {shorturl_access} WHERE url_id='%d'", $link->lid));
+  
+  $output .= '<div id="shorturl-details" class="shorturl">';
+  if (!empty($link->title)) {
+    $output .= '<h3>'. check_plain(html_entity_decode($link->title, ENT_QUOTES, 'UTF-8')).'</h3>';
+  }
+  $output .= '<p>'. l($link_short, $link->orig_url).'<br />Short URL: '.l(url($key, array('absolute' => true)), url($key, array('absolute' => true))).'</p>';
+  $output .= '<p>'. $clicks .' '. t('click throughs') .'. '. t('Posted by !user on !date', array('!user' => l($user->name, 'shorturl/user/'. $user->uid), '!date' => format_date($link->created, 'medium'))) .'</p>';
+  $output .= '<p>'. check_plain($link->description).'</p>';
+  $output .= '</div>';
+  
+  
+  /**
+   * Referal statistics
+   */
+  $output .= '<div id="shorturl-referrers" class="shorturl">';
+  $output .= '<h3>'. t('Referrer Statistics') .'</h3>';
+  
+  
+  /**
+   * List of all refering domains
+   */
+  $output .= '<div id="shorturl-referrers-domains" class="shorturl">';
+  $output .= '<h4>'. t('All Domains') .'</h4>';
+  
+  $sql = "SELECT substring_index(referrer, '/', 3) as domain, count(aid) as clicks FROM {shorturl_access} WHERE url_id = '$link->lid' AND referrer != '' GROUP BY domain ORDER BY clicks DESC";
+  $result = db_query($sql);
+  
+  $rows = array();
+  while ($referrer = db_fetch_object($result)) {
+    $rows[] = array(
+      array('class' => 'referrer', 'data' => l($referrer->domain, $referrer->domain)),
+      array('class' => 'clicks', 'data' => '<div class="count">'.$referrer->clicks.'</div>'),
+    );
+  }
+  if (!$rows) {
+    $rows[] = array(array('data' => t('No referrer data is available.'), 'colspan' => '2'));
+  }
+  $header = array(t('Domain'), t('Clicks'));
+  $output .= theme('table', $header, $rows, array('cellspacing' => '10'));
+  $output .= '</div>';
+  
+  
+  /**
+   * List of top 25 referrers
+   */
+  $output .= '<div id="shorturl-referrers-top" class="shorturl">';
+  $output .= '<h4>'. t('Top 25 Referrers') .'</h4>';
+  
+  $sql = "SELECT count(aid) as clicks, referrer FROM {shorturl_access} WHERE url_id = $link->lid AND referrer != '' GROUP BY referrer ORDER BY clicks DESC LIMIT 25";
+  $result = db_query($sql);
+  
+  $rows = array();
+  while ($referrer = db_fetch_object($result)) {
+    $url = (strlen($referrer->referrer) > 65) ? substr($referrer->referrer, 0, 65).'...' : $referrer->referrer;
+    $rows[] = array(
+      array('class' => 'referrer', 'data' => l($url, $referrer->referrer)),
+      array('class' => 'clicks', 'data' => '<div class="count">'.$referrer->clicks.'</div>'),
+    );
+  }
+  if (!$rows) {
+    $rows[] = array(array('data' => t('No referrer data is available.'), 'colspan' => '2'));
+  }
+  $header = array(t('referrer'), t('Clicks'));
+  $output .= theme('table', $header, $rows, array('cellspacing' => '10'));
+  $output .= '</div>';
+  
+  $output .= '</div>';
+  
+  return $output;
+}
+
+function shorturl_statistics_export($user = NULL) {
+  if (is_object($user) && ($user->uid != 0)) {
+    $sql = "SELECT lid, orig_url, title, description, keywords, count(aid) as clicks, FROM_UNIXTIME(created, '%m.%d.%Y'), uid FROM {shorturl_link} sl LEFT JOIN {shorturl_access} sa ON lid=url_id WHERE sl.uid='$user->uid' GROUP BY lid ORDER BY created ASC";
+    $result = db_query($sql);
+  }
+  else {
+    $sql = "SELECT lid, orig_url, title, description, keywords, count(aid) as clicks, FROM_UNIXTIME(created, '%m.%d.%Y'), uid FROM {shorturl_link} sl LEFT JOIN {shorturl_access} sa ON lid=url_id GROUP BY lid ORDER BY created ASC";
+    $result = db_query($sql);
+  }
+  
+  $headers = array('Content-type' => 'text/octect-stream', 'Content-Disposition' => 'attachment;filename=data.csv');
+  
+  header('Content-Type: text/x-csv'); 
+  header('Expires: '. gmdate('D, d M Y H:i:s') .' GMT');
+  header('Content-Disposition: inline; filename="'.$_SERVER['SERVER_NAME'].'.csv"');
+  header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
+  header('Pragma: public');
+  
+  $source = '"ID","Original URL","Title","Description","Keywords","Clicks","Created","User ID"';
+  $source .= "\n";
+  while ($log = db_fetch_object($result)) {
+    foreach ($log as $cell) {
+      $source .= '"'.$cell.'",';
+    }
+    $source .= "\n";
+  }
+  echo $source;
+}
+
 
 /**
 * Generate unique token for arbitrary URL. Both absolute and relative
@@ -69,28 +352,36 @@
 * @return shortened URI token
 *
 */
-function shorturl_shorten ($long_url) {
+function shorturl_shorten($long_url) {
+  global $user;
 
   //Do we already have this URL?
-  $existing_id = db_result(db_query('SELECT lid FROM {shorturl_link} WHERE orig_url=\'%s\' ', $long_url));
-  if (!empty($existing_id)) {
-    $encoded = shorturl_encode_url($existing_id);
-    return $encoded;
+  if (!variable_get('shorturl_allow_duplicates', 0)) {
+    $existing_id = db_result(db_query('SELECT lid FROM {shorturl_link} WHERE orig_url=\'%s\' ', $long_url));
+    if (!empty($existing_id)) {
+      $encoded = shorturl_encode_url($existing_id);
+      return $encoded;
+    }
   }
   
   $found_vacant = FALSE;
-  $remote_ip = (empty($_SERVER['REMOTE_ADDR'])) ? '' : $_SERVER['REMOTE_ADDR']; 
+  $remote_ip = (empty($_SERVER['REMOTE_ADDR'])) ? '' : $_SERVER['REMOTE_ADDR'];
+  $url_data = _shorturl_urldata($long_url);
 
   $link = new stdClass();
+  $link->uid = $user->uid; 
   $link->orig_url = $long_url; 
   $link->created = (int)time();
   $link->remote_ip = $remote_ip;
+  $link->title = $url_data['title'];
+  $link->description = $url_data['metaTags']['description']['value'];
+  $link->keywords = $url_data['metaTags']['keywords']['value'];
   
-  $last_id = db_result(db_query('SELECT max(lid) FROM {shorturl_link}'));
-  if ($last_id < SHORTURL_START_FROM) {$last_id = SHORTURL_START_FROM;}
+  $last_id = db_result(db_query('SELECT max(lid) FROM {shorturl_link} '));
+  if ($last_id == 0) $last_id = SHORTURL_START_FROM;
   $last_id++;  
   
-  while (! $found_vacant ) {
+  while (!$found_vacant ) {
     $encoded = shorturl_encode_url($last_id);
     $found_vacant = shorturl_check_availability($encoded);
     if (!$found_vacant) {
@@ -107,7 +398,7 @@
       }
     }
   }
-  
+
   return $encoded;                   
 }
 
@@ -137,4 +428,68 @@
   $reserved_system = array('node', 'admin', 'term', 'user');
   
   return $reserved_system + $reserved_settings;
-}
\ No newline at end of file
+}
+
+function _shorturl_urldata($url) {
+  $result = false;
+  $contents = _shorturl_geturl($url);
+
+  if (isset($contents) && is_string($contents)) {
+    $title = '';
+    $metaTags = NULL;
+    
+    preg_match('/<title[^>]*>([^>]*)<\/title>/si', $contents, $match );
+
+    if (isset($match) && is_array($match) && count($match) > 0) {
+      $title = strip_tags($match[1]);
+    }
+    
+    preg_match_all('/<[\s]*meta[\s]*name="?' . '([^>"]*)"?[\s]*' . 'content="?([^>"]*)"?[\s]*[\/]?[\s]*>/si', $contents, $match);
+    
+    if (isset($match) && is_array($match) && count($match) == 3) {
+      $originals = $match[0];
+      $names = $match[1];
+      $values = $match[2];
+      
+      if (count($originals) == count($names) && count($names) == count($values)) {
+        $metaTags = array();
+        
+        for ($i=0, $limiti=count($names); $i < $limiti; $i++) {
+          $metaTags[$names[$i]] = array (
+            'html' => htmlentities($originals[$i]),
+            'value' => $values[$i]
+          );
+        }
+      }
+    }
+    
+    $result = array (
+      'title' => $title,
+      'metaTags' => $metaTags
+    );
+  }
+  
+  return $result;
+}
+
+function _shorturl_geturl($url, $maximumRedirections = null, $currentRedirection = 0) {
+  $result = false;
+  $contents = @file_get_contents($url);
+  
+  // Check if we need to go somewhere else
+  if (isset($contents) && is_string($contents)) {
+    preg_match_all('/<[\s]*meta[\s]*http-equiv="?REFRESH"?' . '[\s]*content="?[0-9]*;[\s]*URL[\s]*=[\s]*([^>"]*)"?' . '[\s]*[\/]?[\s]*>/si', $contents, $match);
+    
+    if (isset($match) && is_array($match) && count($match) == 2 && count($match[1]) == 1) {
+      if (!isset($maximumRedirections) || $currentRedirection < $maximumRedirections) {
+        return _shorturl_geturl($match[1][0], $maximumRedirections, ++$currentRedirection);
+      }
+      $result = false;
+    }
+    else {
+      $result = $contents;
+    }
+  }
+  return $contents;
+}
+?>
\ No newline at end of file

