Location: PHPKode > projects > FeedMeLinks, Social BookmarkingSince2002 > feedmelinks.com/modules/utils.inc.php
<%
	if( ! $cached_page_include )
		session_register("cache");
	include( get_root() . "/modules/prep-cache.inc.php" );

	function add_tags_from_request( $u, $newLinkID, $catNums, $con ) {

		if( $debug ) echo "<hr>";

		$newCatNames = Array();

		foreach( $_POST as $paramName => $newCatName ) {
			if( substr( $paramName, 0, strlen( "new_tag" )) == "new_tag" && $newCatName) {
				array_push( $newCatNames, $newCatName );
			}
		}

		foreach( $_GET as $paramName => $newCatName ) {
			if( substr( $paramName, 0, strlen( "new_tag" )) == "new_tag" && $newCatName) {
				array_push( $newCatNames, $newCatName );
			}
		}

		if( $debug ) {
			echo "User entered " . count( $newCatNames ) . " 'new' tags: ";
			print_r( $newCatNames );
			echo "<br>And " . count( $catNums ) . " existing tags: ";
			print_r( $catNums );
			echo "<br>";
		}

		if( count( $newCatNames )) {
			foreach( $newCatNames as $newCategoryName ) {
				if( $debug )
					echo "First we add any tags that are actually new, then we tag the link w/all the remaining existing tags:<br />";
				$categoryAlreadyExists = getIdForFolder( $newCategoryName, $u );
				if( ! $categoryAlreadyExists ) {
					if( $debug )
						echo "User $u correctly claims s/he has no " . getCatName() . " called '$newCategoryName' yet...<br />";
					$newCatNum = addFolder( $newCategoryName, $u );
					if( $debug )
						echo "added $newCategoryName successfully as: \$newCatNum: $newCatNum<br />";
				} else
					# user actually already had this tag, so just push it onto the rest of the existing tags to tag this link with
					array_push( $catNums, $categoryAlreadyExists );
			}
		} else {
			if( $debug )
				echo "no new " . getCatsName() . " to be added, adding to existing " . getCatsName() . "...<br />";
		}

		#starting sentinal value:
		$q = "bogus query";

		foreach( $catNums as $catNum ) {
			if( ! $q || ! $catNum )
				return;
			if( $debug ) echo "<br />";

			$qs = getQuery( "add_new_category_xref", $newLinkID, $catNum );
			if( $debug )
				echo "DEBUG: $qs";
			$q = mysql_query( $qs );
			if( ! $q ) {
				$e = mysql_error($con);
				$tok = get_mysql_dupe_error();
				if( ! strstr( $e, $tok)) {
%>
<div class="attention warning">
Oh no. Tagging link with <%= getCatName() %> #<%= $catNum %> failed.
Error was: <%= $e %>
</div>
<%
					break;
				} else {
					e( "already tagged w/that tag -- no worries!" );
					# fake a real result set so our caller thinks we succeeded, since we did
					$q = 1;
				}
			}
		}
	return $q;
} 


	function get_mysql_dupe_error() {
		return "Duplicate entry";
	}

	function dumpParams() {
	%>
	<%
		foreach( $_GET as $pname => $pval ) { e( $pname . " = " . $pval ); }
		e( "" );
		foreach( $_POST as $pname => $pval ) { e( $pname . " = " . $pval ); }
		%>
		<%
	}

	function users_link_exists( $u, $url ) {
		$url = urlencode( $url );
		$con_users_link_exists = mysql_connect();
		mysql_selectdb( getDBName() );
		$qs = "SELECT COUNT(id) as count FROM links WHERE url = '$url' AND submitter = '$u';"; 
		$q = mysql_query( $qs );
		if( $q )
			$count = mysql_result($q, 0, "count" );
		conClose( $con_users_link_exists );
		return $count;
	}

	function users_tag_exists( $u, $tag ) {
		$tag = urlencode( $tag );
		$con_users_tag_exists = mysql_connect();
		mysql_selectdb( getDBName() );
		$qs = "SELECT COUNT(id) as count FROM linksgroups WHERE name = '$tag' AND userid = '$u';"; 
		$q = mysql_query( $qs );
		if( $q )
			$count = mysql_result($q, 0, "count" );
		conClose( $con_users_tag_exists );
		return $count;
	}

	# can this user import more than max_links?
	function is_privileged_importer( $userId ) {
		$pi = Array();

		$pi["jm3"] = true;
		$pi["pheezy"] = true;
		$pi["gus"] = true;
		$pi["dcnstctr"] = true;
		$pi["formalplay"] = true;
		$pi["testuser"] = true;
		$pi["Madrisa"] = true;

		#$pi["stutes"] = true;
		#$pi["gagliaudo"] = true;
		#$pi["auslander"] = true;

		return $pi[ $userId ];
	}

	class Config {
		function get_import_links_cache_file_name() { return "LINKS.RAW"; }
		function get_deduped_links_cache_file_name() { return "LINKS.READY"; }
		function get_import_tags_cache_file_name() { return "TAGS.RAW"; }
		function get_deduped_tags_cache_file_name() { return "TAGS.READY"; }
		function get_delimeter() { return "___DELIMETER___"; }
		function get_import_tag_name() { return "imported links"; }
	}
	$config = new Config;

	function open_user_file_for_write( $f, $u ) {
		chdir( get_root() );
		$u_dir = "usr/" . ($u ? $u : get_user());
		if( ! is_dir( $u_dir )) {
			$old_umask = umask(0);
			mkdir( $u_dir );
			umask($old_umask);
		}
		if( !is_dir( $u_dir )) 
			fatal( "Your user folder could not be created." );
		else if( ! is_writable( $u_dir ))
			fatal( "Your folder was not writable." );
		else {
			$f = $u_dir . "/" . escapeshellcmd( $f );
			if( is_file( $f ))
				l( "warning: opening existing user $u's file $f for write and erasing it" );
			return fopen( $f, "w" );
		}
	}
	
	# NOTE THAT THE RETURN SEMANTICS OF _for_read ARE VERY DIFFERENT THAN _for_write; WE RETURN AN ARRAY, NOT A FILE_POINTER!!
	function open_user_file_for_read( $f ) {
		chdir( get_root() );
		$u_dir = "usr/" . get_user();
		$f = $u_dir . "/" . escapeshellcmd( $f );
		if( ! is_dir( $u_dir )) 
			fatal( "Your user folder could not be found." );
		else if( !is_file( $f )) 
			l( "the file $f could not be found." );
		else
			return file( $f );
	}

	function get_bookmarks_info( $u ) {
		$b = Array();
		$b["file_name"] = "/imported-favorites.html";
		$b["field_name"] = "bookmarks_file";
		$b["dir"] = get_root() . "/usr/$u";
		$b["path"] = $b["dir"] . $b["file_name"];

		return $b;
	}

	function e( $m ) {
		echo "$m<br>\n";
	}
	
	function croak( $m ) {
		ob_clean();
		exit( $m );
	}

	function l( $m ) {
		trigger_error( $m );
	}
	
	function comment( $m ) {
		echo "\n<!-- $m -->\n";
	}

	function fatal( $m ) {
		l( "FATAL ERROR.", $m );
		return tell( "FATAL ERROR.", $m );
	}

	function warn( $m ) {
		return tell( "Warning.", $m );
	}

	function shout( $t, $m ) {
		tell( $t, $m, $wide = true );
	}


	function startTell( $t = "", $wide = false ) {
%>
<div class="notebox" <%= $wide ? 'style="width: 600px; margin-left: auto; margin-right: auto;"' : ""%>>
	<div class="noteboxHead" <%= $wide ? 'style="font-size: 140%;"' : ""%>><h2><%= $t %></h2></div>
	<div class="noteboxBody" <%= $wide ? 'style="font-size: 140%;"' : ""%>>
		<p>
<%
	}

	function endTell() {
	%>
	</div>
</div>
	<%
	}

	function tell( $t, $m, $wide = false ) {
		startTell( $t, $wide );
		echo $m;
		endTell();
%>
<%
		endTell();
	}

	function num_comments() {
		$args = func_get_args();
		$l = $args[0];
		$u = $args[1];
		return sizeof( file( get_comments_file( $l, $u )));
	}

	function has_comments() {
		$args = func_get_args();
		$l = $args[0];
		$u = $args[1];
	
		return is_readable( get_comments_file( $l, $u ) ) ? true : false;
	}

	function get_comments_file() {
		$args = func_get_args();
		$l = $args[0];
		$u = $args[1];

		$COMMENT_EXT = '.txt';
		$COMMENT_DIR = "_comments/";

		$owner = $u ? $u : getOwnerForLink( $l );
		$folder = escapeshellcmd( $owner ) . "/";
		$linkfolder = $COMMENT_DIR . $folder;
		return( get_root() ."/" . $COMMENT_DIR . $folder . escapeshellcmd( $l ) . $COMMENT_EXT );
	}

	function print_js_folder( $num_links, $is_public, $id, $name, $count) {
		return "taglist[$count] = Array( $id,  '" . preg_replace( "/'/", "", $name ) . (!$is_public ? " (private)" : "") . "' );\n";
	}

	function button( $arg_img, $arg_href ) {
		$id = "btn_" . rand(0,512);
		$arg_img .= ".png";
		$on = str_replace ( ".png", "-on.png", $arg_img);
		ob_start();

%><a href="<%= $arg_href %>" onMouseOver="<%= $id %>.src='/img/<%= $on %>';" onMouseOut="<%= $id %>.src='/img/<%= $arg_img %>';"><img name="<%= $id %>" src="/img/<%= $arg_img %>" border="0" /></a><%
		return ob_get_clean();
	}

	function get_uni_pattern() {
		return "/%u([A-Fa-f0-9]{4}|[A-Fa-f0-9]{2})/";
	}

  function toggle_link_privacy( $arg_user, $arg_link_id ) {
    if( $arg_user && $arg_link_id ) {
      $qs = "SELECT isPrivate FROM links WHERE ID = $arg_link_id AND submitter = '$arg_user'";
			$con_toggle_link_privacy = mysql_connect();
			mysql_selectdb( getDBName() );
			$q = mysql_query( $qs );
			if( $q ) {
				$old = mysql_result($q, 0, "isPrivate" );
				$old = $old ? $old : "NULL";
				$new = $old == 1 ? "NULL" : 1;
				$new_label = $new == 1 ? "private" : "public";

				$qs = "UPDATE links SET isPrivate = $new WHERE id = $arg_link_id AND submitter = '$arg_user';";
				$q = mysql_query( $qs );
				if( $q ) {
					conClose( $con_toggle_link_privacy );
					return "Made link $arg_link_id $new_label.";
				}
			}
			conClose( $con_toggle_link_privacy );
    } else
      return "error!";
  }


	function get_linkpocket( $argUser ) {
		if( $argUser ) {
			$con_getLinkpocket = mysql_connect();
			mysql_selectdb( getDBName() );
			$qs = 
			"SELECT ID FROM linksGroups 
				WHERE 
					(name = 'linkpocket' OR name = 'p/linkpocket' OR name = 'p%2Flinkpocket')
					AND userid = '$argUser';";
			$q = mysql_query( $qs );
			if( $q )
				$id = mysql_result($q, 0, "ID" );
			$qs = "SELECT COUNT(*) AS count FROM linksCategoriesXRef WHERE catID = $id";
			$q = mysql_query( $qs );
			if( $q )
				$count = mysql_result($q, 0, "count" );

			conClose( $con_getLinkpocket );
			return array( "id" => $id, "count" => $count );
		}
	}

	# strips slashes, and converts special characters to HTML equivalents for string defined in $var
	function o( $s ){
		 $chars = array(
				 128 => '&#8364;',
				 130 => '&#8218;',
				 131 => '&#402;',
				 132 => '&#8222;',
				 133 => '&#8230;',
				 134 => '&#8224;',
				 135 => '&#8225;',
				 136 => '&#710;',
				 137 => '&#8240;',
				 138 => '&#352;',
				 139 => '&#8249;',
				 140 => '&#338;',
				 142 => '&#381;',
				 145 => '&#8216;',
				 146 => '&#8217;',
				 147 => '&#8220;',
				 148 => '&#8221;',
				 149 => '&#8226;',
				 150 => '&#8211;',
				 151 => '&#8212;',
				 152 => '&#732;',
				 153 => '&#8482;',
				 154 => '&#353;',
				 155 => '&#8250;',
				 156 => '&#339;',
				 158 => '&#382;',
				 159 => '&#376;');
		 return hateration( unicode_fix( str_replace(array_map('chr', array_keys($chars)), $chars, htmlentities(stripslashes($s)))));
	}

	function hateration( $s ) {
		return unEscapeQuotes( preg_replace( "/&amp;#x/", "&#x", $s ));
	}

	# replace things which look like ghastly php entities with cute lil hex escapes
	function unicode_fix( $s ) {
		return preg_replace( get_uni_pattern(), "&#x$1;", $s );
	}

function get_thumb( $u, $linkUrl ) {
ob_start();
%>
<a href="<%= $linkUrl %>"><img src="http://open.thumbshots.org/image.pxf?url=<%= $u %>" border="2"  /></a>

<%
				return ob_get_clean();

}

function get_flickr_thumb( $argPhotoId ) {
	$key = "91640f92a17280b1953f02c0b79956bf";
	$url = 'www.flickr.com/services/rest/?method=flickr.photos.getSizes&api_key=' . $key . '&photo_id=' . $argPhotoId;
	$lines = xform( "_xsl/flickr.xsl", "http://$url" );
	if( sizeof( $lines == 1 ))
		return $lines[0];
	else
		return "/img/spacer.gif";
}

		function print_css_folder( $argUser, $argNumLinks, $argIsPub, $argId, $argName, $argFlipFlop ) {
			ob_start();

			global $prof;
			#if( isset( $prof )) $prof->startTimer( "print_css_folder_funcall" );

			$n = $argFlipFlop ? 1 : 0;
%>
<% if( $argUser == get_user() || $argIsPub ) { %>
<div class="fr r<%= $n %>">
<div style="float: left;">
<span class="subtle"><%= printLinkCount( $argNumLinks ) %> links </span>
<big><%= makeFolderLink( $argId, $argName ) %></big>
</div>
<% if( $argUser == get_user() ) { %>
<div style="float: right">
	<a href="edit-folder?op=edit&id=<%= $argId %>&name=<%= urlencode( $argIsPub ? makePublicFolderName( $argName ) : $argName) %>" title="edit <%= $argName %>"><img src="img/edit.gif" alt="edit <%= $argName %>" border="0" /></a>
		&nbsp;
		<a href="edit-folder?op=confirmDelete&id=<%= $argId %>&name=<%= 
		urlencode($argName) %>" title="delete <%= $argName %>"><img src="img/trash.gif" 
		alt="delete" border="0" /></a>
		</div>
<% 
		}
%>
</div>
<% 
	} 
%>
<%
			return ob_get_clean();
		}

		function print_folder( $argNumLinks, $argIsPub, $argId, $argName ) {
			ob_start();
%>
<tr>
	<td <%= $bg %>>
		<%= printLinkCount( $argNumLinks ) %> links
	</td>
	<td <%= $bg %> nowrap="nowrap">
	 <%= makeFolderLink( $argId, $argName ) %>
	</td>
	<td <%= $bg %> width="32" align="center">
		<a href="edit-folder?op=edit&id=<%= $argId %>&name=<%= 
		urlencode( $argIsPub ? makePublicFolderName( $argName ) : $argName) %>" 
		title="edit <%= $argName %>"><img src="img/edit.gif" alt="edit" border="0" /></a>
	</td>
	<td <%= $bg %> width="32" align="center">
		<a href="edit-folder?op=confirmDelete&id=<%= $argId %>&name=<%= 
		urlencode($argName) %>" title="delete <%= $argName %>"><img src="img/trash.gif" 
		alt="delete" border="0" /></a>
	</td>
</tr>
<%
			return ob_get_clean();
		}

function get_ownoun() {
	return "your";
}

function get_site() {
	global $site;
	return $site;
}

function get_user() {
	return $_COOKIE["c_uid"];
} 

function get_taglist_query( $argUser ) {
	return "SELECT count(*) as num_links, ID as catID, name FROM linksGroups, linksCategoriesXRef WHERE linksGroups.ID = linksCategoriesXRef.catID AND linksGroups.userid = \"$argUser\" GROUP BY name ORDER BY num_links desc;";
}

function get_category_counts_query( $argUser ) {
	return "SELECT COUNT(*) AS num_links, lxf.catID, g.name FROM linksCategoriesXRef As lxf, linksGroups AS g WHERE g.ID = lxf.catID AND g.userid = \"$argUser\"  GROUP BY catID ORDER BY g.name;";
}

function get_summarized_contacts_links_query( $argContacts ) {
	$users = $argContacts;
	$c = 0;
	foreach( $users as $u => $junk ) {
		$r = ($c == 0) ? " (" : "$r OR ";
		$r .= "submitter = '$u'";
		$c++;
	}
	return "SELECT MAX(ID) as ID, submitter as u FROM links WHERE " .  $r . ") GROUP BY submitter;";
}

function get_contacts_links_query( $argContacts ) {

	$users = $argContacts;
	$c = 0;
	if( $users ) {
		foreach( $users as $u => $junk ) {
			$r = ($c == 0) ? "AND (" : "$r OR ";
			$r .= "submitter = '$u'";
			$c++;
		}
		return getMasterQuery() . $r . ") ORDER BY links.ID DESC limit 15";
	}
}

function row_wrap( $argContent, $argFlop ) {
	$r = $argFlop ? 1 : 0;
	# this is so fucking sketchy....
	return "<div class=\"r$r\">" . $argContent;
	#return "<div class=\"r$r\">" . $argContent . "</div>";
}

function print_link( $argLinkHash, $argFlop, $user_linkstyle = "basic" ) {
	$l = $argLinkHash;
	if( $l ) {

		if( $user_linkstyle == "basic" ) {
			$s .= getBareUserLink( $l["u"] );
			$s .= "'s ";
		} else if( $user_linkstyle == "icons" ) {
			$s .= getUserLink( $l["u"] );
			$s .= "'s ";
		} # else none...
		
		# link
		if( $l["name"] ) {
			$s .= getLink( $l["ID"], urldecode( $l["url"] ), urldecode( $l["name"] ), "", "", "" );
		} else {
			$s .= getLinkOut( $l["ID"] );
		}

		# grab it link
		$s .= " " . getStealItLink( $l["ID"] );
		# link ID
		$s .= " " . getPermaLink( $l["ID"] );

		# tags

		# here we get mad sketchy with the formatting.
		# we write the open here and close it in the calling func.
		# god help us.
		$s .= '<div style="text-align: right;">';
		$s .= " in " . getTagLink( $l["tagID"], $l["tag"] );

		return row_wrap( $s, $argFlop );
	}
}

function get_their_links_html() {
	return get_linklist( getMasterQuery() . " ORDER BY links.ID DESC LIMIT 15",
		array( "get_their_links_header_cb", $u), array( "get_their_links_footer_cb", NULL ), "basic" );
}
function get_their_links_header_cb() { return "THEIR RECENT LINKS"; }
function get_their_links_footer_cb() { return "<div class=\"center\"><a href=\"/link-cruiser\">VIEW MORE LINKS!</a> (<a href=\"/mile-long\">MORE! MORE!</a>)";  }

function get_recent_for_user( $u ) {
	return get_linklist( getQuery( "recent_for_user", $u, 10 ), array( "get_recent_for_user_header_cb", $u), array( "get_recent_for_user_footer_cb", $u ) );
}
function get_recent_for_user_header_cb() { return func_get_arg( 0 ) . "'s RECENT LINKS"; }
function get_recent_for_user_footer_cb() { return "<a href='/u/" . func_get_arg( 0 ) . "'>See more of " . func_get_arg( 0 ) . "'s links...</a>";  }

function get_contacts_links_html( $show_summary ) {
	$cache = get_cache();
	$qs = $show_summary ? get_summarized_contacts_links_query( $cache["contacts"] ) : get_contacts_links_query( $cache["contacts"] );

	return get_linklist( $qs, array( "get_contacts_links_html_header_cb", NULL), array( "get_contacts_links_html_footer_cb", $show_summary), "basic" );
}
function get_contacts_links_html_header_cb() { return get_ownoun() . " peeps' links"; }
function get_contacts_links_html_footer_cb() {
	ob_start();
	if( func_get_arg( 0 )) { 
		%><a href="<%= get_site() %>/contacts/">view all <%= get_ownoun() %> peeps' links</a><%
	} else { 
		%><a href="<%= get_site() %>/contacts/?summarize=1">view just the most recent link from each of <%= get_ownoun() %> peeps</a><%
	}
	return ob_get_clean();
}

function get_linklist() {
  $args = func_get_args();

	$qs = $args[0];
	$header_cb = $args[1];
	$footer_cb = $args[2];
	$user_linkstyle = $args[3];

	$con_getStatsLine = mysql_connect();
	mysql_selectdb( getDBName() );
	
	$q = mysql_query( $qs );
	if( $q && mysql_num_rows($q) ) {
		$c = 0;
		$out = "<div class=\"box\">
	<div class=\"subhead\">" . call_user_func( $header_cb[0], $header_cb[1] ) . "</div>";

		$lastID = "";
		while( $row = mysql_fetch_assoc( $q )) {
			if( $row["ID"] == $last_id ) {
				$out .= ", " . getFolderLink( $row["tagID"], makePrettyFolderName( urldecode( $row["tag"] )));
			} else {
				if( $c != 0 ) {
					$out .= "</div>";
					$out .= "</div>";
					}
				$out .= print_link( $row, $c % 2 == 0 ? 1 : 0, $user_linkstyle );
				$c++;
			}
			$last_id = $row["ID"];
		}
		$out .= "</div>";
		ob_start();
%>
		<div class="r<%= $c % 2 == 0 ? 1 : 0 %> last"> <%= call_user_func( $footer_cb[0], $footer_cb[1] ) %> </div>
<%
		$out .= ob_get_clean();

		$out .= "</div>";
		#$out .= "</div>"; # didnt think we needed this, but i guess we do...?
		mysql_free_result($q);
		return $out;
	}
}

function remove_contact( $argContact, $argUser ) {
	return remove_from_list( $argContact, "contact", "contacts", get_contacts(), get_contacts_file( $argUser ) );
}

function add_contact( $argContact, $argUser ) {
	if( $argContact && $argUser && ($argContact != $argUser )) {
		$cache = get_cache();
		return cache_item( $argUser, $argContact, "contact", $cache["contacts"], get_contacts_file( $argUser ));
	}
}

function remove_from_list( $argItem, $argItemName, $argType, $argCachedItems, $argCacheFile ) {
	if( $debug ) {
		echo " remove_from_list( $argItem, $argType, $argCachedItems )<br>\n";
		if( $argItem && $argType && $argCachedItems )
			echo "removing $argItem from the $argType cache";
		echo( "\ncache_item() called for $argItemName, argItem: $argItem" );
	}
	if( $argItem ) {
		$x = '<' . '?xml version="1.0" encoding="UTF-8" standalone="yes" ?>' . "\n";
		$x .= "<fml>\n";

		if( $debug )
			echo "<br>the $argType cache has " . sizeof( $argCachedItems ) . " items<br>\n";

		foreach( $argCachedItems as $item => $jonk ) {
			$item =ltrim( rtrim( chop( $item )));
			if( $argItem != $item ) {
					$x .= "\t<$argItemName>$item</$argItemName>\n";
			}
		}
		$x .= "</fml>\n";
		#echo "<textarea rows=9 cols=50>$x</textarea>";
		
		if( !$f = fopen( $argCacheFile, "w" )) {
			echo "remove_from_list(): can't open $argCacheFile";
		} else {
			#echo "<br>opened $argCacheFile for write";
			fwrite( $f, $x );
			fclose( $f );
		}
	} 
	return rebuild_cache();
}

function display_cb( $s ) {
	return $s;
}

function link_cb( $s ) {
	return getLinkOut( $s ) . " " . getPermaLink( $s );
}

# DEPRECATED: function footer_cb() { #a href="%= get_site() %/contacts/links"view %= get_ownoun() % peeps' links/a return $s; }

function title_cb() {
	#sizeof( $argUsers ) ? get_ownoun() . " peeps" : get_ownoun() . " list of peeps is empty";
	return $s;
}

function linkTitle_cb() {
	return "Some Examples of Unicode in Feed Me Links:";
}

function get_list( $argItems, $argDisplay_cb, $argTitle_cb, $argFooter_cb ) {
	if( $argDisplay_cb && $argTitle_cb && $argFooter_cb) {
		$c = 0;
		ob_start();
		$header = sizeof( $argItems ) ? call_user_func( $argTitle_cb ) : "";
%>
<div class="box">
	<div class="subhead"> <%= $header %> </div>
<%
		foreach( $argItems as $item => $junk ) {
			$flipper = $c % 2 == 0 ? 1 : 0;
%>
	<div class="r<%= $flipper %>">
		<%= call_user_func( $argDisplay_cb, $item ) %><br />
	</div>
<%
		$c++;
	}
%>
	<div class="r<%= ! $flipper %> last">
		<%= call_user_func( $argFooter_cb ) %>
	</div>
</div>
<%
	return ob_get_clean();
} else {
	l( "get_list() called without argDisplay_cb callback" );
}

}

function get_contactlist_grid() {
	$args = func_get_args();
	$argUsers = $args[0];
	$argTitle = $args[1];
	$argUser  = $args[2];

	$c = 0;
	ob_start();
	if( sizeof( $argUsers )) {
%>

<style type="text/css">
	.peepBox {
		float: left; 
		border: 1px solid #555555; 
		height: 68px;
		width: 64px;
		padding: 1em;
		margin: 0.5em;
		background-color: #FFFFFF;
	}
	.peepBox:hover {
		background-color: #dddddd;
	}
</style>

<h2> &nbsp; <%= $argUser == get_user() ? "Your" : "$argUser's" %> Peeps </h2>

<div>
	<big>
<%
			foreach( $argUsers as $user => $junk ) {
%>
		<div class="peepBox" style="text-align: center">
		<a href="/u/<%= $user %>"><% getSizedUserImage( $user, 58 ) %></a>

			<small><%= getBareUserLink( $user ) %></small><%
			if( $argUser == get_user() ) { %>&nbsp;<small><small>[<a class="subtle" href="remove?user=<%= $user %>">x</a>]</small></small>
			<% } %>
		</div>
<%
			$c++;
			if( $c % 4 == 0 )
				echo '<br clear="all"/>';
		}
	} else {
		if( $argUser != get_user() ) {
%>

<br />
<h2> <%= $argUser %> has no peeps... what a LOSER!  </h2>

<%
		}
	}
%>
	<br clear="all"/>
	</big>
</div>
<%
		return ob_get_clean();
}

function get_contactlist_html( $argUsers, $argTitle ) {
	$c = 0;
	ob_start();
	if( $debug )
		echo "<br>" . sizeof( $argUsers ) . "<br>";
	$header = sizeof( $argUsers ) ? get_ownoun() . " peeps" : get_ownoun() . " list of peeps is empty";
%>
<div class="box">
	<div class="subhead"> <%= $header %> </div>
<%
		if( sizeof( $argUsers )) {
			foreach( $argUsers as $user => $junk ) {
				$flipper = $c % 2 == 0 ? 1 : 0;
%>
	<div class="r<%= $flipper %>">
		<%= makeUserLink( $user ) %>
		(<a href="remove?user=<%= $user %>">remove from your peeps</a>)
		<br />
	</div>
<%
			$c++;
		}
	}
%>
	<div class="r<%= ! $flipper %> last">
<% 
	if( sizeof( $argUsers ))
		echo "(...your peeps love you!)";
	else
		echo "(...you've no peeps yet!)";
%>
	</div>
</div>
<%
		return ob_get_clean();
}

function get_verbose_contact_link( $user ) {
	return get_contact_link_driver( $user, 1 );
}

function get_contact_link( $user ) {
	return get_contact_link_driver( $user, 0 );
}

function get_contact_link_driver( $user, $argVerbose ) {
	if( $user == get_user())
		$r = "<img src=\"" . get_site() . "/img/mebay.gif\" />";
	else {
		$inList = inList( $user, "contacts", get_cache() ) ;
		if( ! $inList ) {
			$r .= "<a href='" . get_site() . "/contacts/add?user=$user'>"
			. "<img src=\"" . get_site() . "/img/plus.gif\" alt=\"+\" border=\"0\" />"
			. ($argVerbose ? " Add <b>$user</b> as " . get_ownoun() . " peep?</a> " : "</a>")
			.  ($argVerbose ? " <a href='/contacts/ignore?user=$user'>Ignore <b>$user</b>?</a>" : "" )
			. ""
			;
			#$r = "<small>(<a href='/contacts/add?user=$user'>add to <b>" . get_ownoun() . " Peeps</b>?</a>)</small>";
		} else {
			$r .= "<a href=\"" . get_site() . "/contacts/\">"
			. "<img src=\"" . get_site() . "/img/happy.png\" alt=\"*\" border=\"0\" class=\"icon\" align=\"middle\" /></a>"
			. ($argVerbose ? " <b>$user</b> is your peep. " : "")
			.  ($argVerbose ? " <a href='/contacts/remove?user=$user'>Remove <b>$user</b>?</a>" : "" )
			.  ($argVerbose ? " <a href='/contacts/ignore?user=$user'>Ignore <b>$user</b>?</a>" : "" )
			;
			#$r = "<small>(" . get_ownoun() . " peep)&#160; (<a href='/contacts/remove?user=$user'>remove?</a>)</small>";
		}
	}
	return $r;
}

function array_to_hash( $a ) {
	if( $a ) {
		$h = array();
		foreach( $a as $item ) {
			$h[$item] = "1";
		}
		return $h;
	}
}

function rebuild_cache( $override_user = false ) {
	$u = $override_user ? $override_user : $_COOKIE["c_uid"];
	$cache[32] = '__anchor';
	$cache["contacts"] = array();
	$cache["contacts"] = array_to_hash( get_xml_cachelist( get_contacts_file( $u )));
	#echo "<!-- found " . sizeof( get_contacts( $u )) . " contacts in disk cachefile -->\n";
	$cache["mailtos"] = array();
	$cache["mailtos"] = array_to_hash( get_xml_cachelist( get_mail_histfile( $u )));
	#echo "<!-- we were told the cache was dirty so we re-populated it -->\n";
	return $cache;
}

# lazy cache prober
function inList( $item, $type ) {
	if( $item && $type ) {
		$cache = get_cache();
		if( $cache &&  $cache[$type] )
			return array_key_exists( $item, $cache[$type] );
	} else
		return 0;
}

function xform( $argXSL, $argXML ) {
	$lines = array();
	$cmd = get_parser() . " $argXSL \"$argXML\"";

	$debug = 0;
	if( $debug )
		echo "<br>$cmd<br>";

	exec( "$cmd", $lines );

	if( $debug ) {
		echo "\$cmd: $cmd<br>";
		print "there are " . sizeof( $lines ) . " lines";
		print_r( $lines );
		foreach ($lines as $line) {
			echo "$line<br>";
		}
	}

	return $lines;
}

function get_xml_cachelist( $argCacheFile ) {
	chdir( get_root() );
	if( ! is_file( $argCacheFile ) || ! is_readable( $argCacheFile ) || ! is_writeable( $argCacheFile )) {
		$u_dir = "usr/" . get_user();
		if( ! is_dir( $u_dir )) {
			if( $debug )
				echo "<br><b>making usr dir..</b><br>";
			$old_umask = umask(0);
			mkdir( $u_dir );
			umask($old_umask);
		}
		if( is_writable( $argCacheFile )) {
			if( !$f = fopen($argCacheFile, "w" )) {
				if( $debug )
					echo "$argCacheFile was jacked";
					fwrite( $f, "<fml></fml>" );
				fclose( $f );
			} else
				fatal( "Could not open " . get_user() . "'s cache file $argCacheFile" );
		}
	}

  if( is_file( $argCacheFile ) && is_readable( $argCacheFile ) && is_writeable( $argCacheFile )) {

		$debug = 0;
		
		$lines = xform( get_root() . "/_xsl/mailtos.xsl", $argCacheFile );

		if( $debug ) {
			echo "\$cmd: $cmd<br>";
			print "there are " . sizeof( $lines ) . " lines";
			print_r( $lines );
			foreach ($lines as $line) {
				echo "$line<br>";
			}
		}

		if( $lines ) {
			$t = array();
			foreach ($lines as $line) {
				$line = ltrim( rtrim( chop( $line )));
				if( $line )
					array_push( $t, $line );
			}
			$lines = $t;
			return $lines;
		}
	} 
}

function cache_item( $argUser, $argItem, $argItemName, $argCachedItems, $argCacheFile ) {
	chdir( get_root() );
	if( $debug ) 
		echo "\ncache_item() called for $argItemName, argItem: $argItem";
	if( $argItem ) {
		$x = '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>' . "\n";
		$x .= "<fml>\n";
		if( $argItem )
			$x .= "\t<$argItemName>$argItem</$argItemName>\n";
		foreach( $argCachedItems as $item => $jonk ) {
			$item =ltrim( rtrim( chop( $item )));
			if( $item ) {
				if( $argItem != $item )
					$x .= "\t<$argItemName>$item</$argItemName>\n";
			}
		}
		$x .= "</fml>\n";
		if( $debug )
			echo "<textarea rows=9 cols=50>$x</textarea>";
		
		if( !$f = fopen( $argCacheFile, "w" )) {
			echo "cache_item(): can't open $argCacheFile";
			exit;
		}
		fwrite( $f, $x );
		fclose( $f );
	} 
}

function get_cache() {
	return !($_SESSION["cache"]) ? rebuild_cache() : $_SESSION["cache"];
}

function get_someone_elses_contacts( $argUser ) {
	$a = array_to_hash( get_xml_cachelist( get_contacts_file( $argUser )));
	return array_to_hash( get_xml_cachelist( get_contacts_file( $argUser )));
}

# pulls from session
function get_cachelist( $argType ) {
	$args = func_get_args();
	$who = $args[1];

	if( $argType ) {
		$cache = get_cache();
		if( $debug ) {
			print_r( $cache );
			echo "checking in the session cache for a $argType array.\n";
			echo "found " . sizeof( $cache[$argType] ) . " $argType in the session cache.\n";
		}
		return $cache[$argType];
	}
}

function get_mail_histfile( $argUser ) {
	return "usr/$argUser/mail-history.xml";
}

function get_contacts_file( $argUser ) {
	return "usr/$argUser/contacts.xml";
}

function get_previous_mailtos() {
	return get_cachelist( "mailtos" );
}

function get_last_mailto() {
	$mailtos = get_cachelist( "mailtos" );
	if( sizeof( $mailtos )) {
		$tmp = array_keys( $mailtos );
		return $tmp[0];
	} else {
		"";
	}
}

function get_contacts() {
	$args = func_get_args();
	$who = $args[0];
	return get_cachelist( "contacts", $who );
}

function cache_mailto( $argUser, $argTo, $argMailtos ) {
	return cache_item( $argUser, $argTo, "email", $argMailtos, get_mail_histfile( $argUser ));
}

function cache_contact( $argUser, $argContact, $argContacts ) {
	return cache_item( $argUser, $argContact, "contact", $argContacts, get_contacts_file( $argUser ));
}

function get_previous_recips_menu( $argRecips ) {
	ob_start();
	if( $argRecips ) {
%>
<select name="to_history" onChange="document.forms[0].to.value = this.options[this.selectedIndex].value;">
	<option value=""> previous recipient: </option>
<%
	ksort($argRecips);
	foreach ($argRecips as $recip => $junk) {
%>
	<option value="<%= hsc($recip) %>"><%= hsc($recip) %></option>
<%
	}
%>
</select>
<%
	} else {
%>
<span class="subtle">no previous recipients</span>
<%
	}
	return ob_get_clean();
}

function d( $s ) {
	return "<div class=\"debug\"><span style=\"color: black;\">DEBUG:</span><br />" . $s . "</div>\n";
}

function bounceBack() {
	return jsWrap( "history.go( -1 );" );
}

function bounceBackWithDelay( $argDelay ) {
	return jsWrap( "var timer = setTimeout( \"history.go( -1 )\", $argDelay * 1000 );" );
}

function bounceTo( $argUrl ) {
	return bounceDriver( $argUrl, 0 );
}

function bounceWithDelay( $argUrl, $argDelay ) {
	return bounceDriver( $argUrl, $argDelay );
}

function bounceDriver( $argUrl, $argDelay ) {
	$r = "";
	$u = $argUrl;

	if( !preg_match("_^" . getSiteUrl() . "|http://www.feedmelinks.com_", $u ) && !preg_match( "_^/_", $u ) )
		$u = getSiteUrl() . "/" . $u;
	if( preg_match( "_^/_", $u ) )
		$u = getSiteUrl() . $u;

  if( isADevice( $HTTP_USER_AGENT )) {
    return jsWrap( "window.location = '" . $u . "';" );
  } else {
    return '<meta http-equiv=Refresh content="' . $argDelay  . '; URL=' . $u . '" />';
  }

}

function jsWrap( $s ) {
	return '
	<script language="javascript">
	<!--

	' . $s
	. '
	// -->
	</script>
	';
}

function isUnfiled( $argID, $argUserId ) {
	$qs = "SELECT * FROM links, linksCategoriesXRef WHERE links.submitter='$argUserId' AND linksCategoriesXRef.linkID = links.ID AND links.ID = $argID;";

	$con_getStatsLine = mysql_connect();
	mysql_selectdb( getDBName() );
	
	$qs = "SELECT COUNT(*) FROM linksUsers;";
	$q = mysql_query( $qs );
	if( $q )
		$numUsers = mysql_result($q,0);
	
	$qs = "SELECT COUNT(*) FROM links;";
	$q = mysql_query( $qs );
	if( $q )
		$numLinks = mysql_result($q,0);
		close_con( $con );
}

function getQuery() {
	$args = func_get_args();
	$argWhichQuery = $args[0];

	if( $argWhichQuery  == "unfiled" ) {
		return "
			SELECT links.* FROM links
			LEFT JOIN linksCategoriesXRef ON links.ID = linksCategoriesXRef.linkID
			WHERE linksCategoriesXRef.linkID IS NULL ";

	} else if( $argWhichQuery  == "tag" ) {
		return "
		SELECT * FROM links, linksGroups AS t, linksCategoriesXRef AS x WHERE x.catID = " . urlencode( $args[1] ) . " AND x.linkID = links.ID AND t.ID = x.catID AND userid = '"
		. urlencode( $args[2] ) ."';";

	} else if( $argWhichQuery  == "recent_for_user" ) {
		$num = $args[2] ? $args[2] : 15;
		return getMasterQuery() . " AND links.submitter = '" . urlencode( $args[1] ) . "' ORDER BY links.ID DESC LIMIT " . $num;

	} else if( $argWhichQuery  == "recent_for_user_pageable" ) {
		return getQuery( "recent_for_user", urlencode( $args[1] ), urlencode( $args[2] )) . ", " . urlencode( $args[3] );

	} else if( $argWhichQuery  == "track_hit" ) {
	  return "
			INSERT INTO linksMetrics (linkID, date, user, source ) VALUES ( " . $args[1] . ", NULL, '" . $args[2] . "', 'unused' ) ";

	} else if( $argWhichQuery  == "delete_tag_refs" ) {
		return "
		DELETE from linksCategoriesXRef where catID = " . $args[1];

	} else if( $argWhichQuery  == "delete_category" ) {
		return "
		DELETE from linksGroups where ID = " . $args[1];

	} else if( $argWhichQuery  == "add_new_category_xref" ) {
		return "
		INSERT INTO linksCategoriesXRef VALUES( " . $args[1] . ", " . $args[2] . " ) ";
	
	} else if( $argWhichQuery  == "tag_by_name" ) {
		return "
		SELECT * FROM linksGroups WHERE userid = '" . $args[1] . "' AND " . $args[2];

	} else if( $argWhichQuery  == "unused_tags" ) {
		return "
		  SELECT linksGroups.* FROM linksGroups LEFT JOIN linksCategoriesXRef on linksGroups.id=linksCategoriesXRef.catID WHERE linksCategoriesXRef.catID is NULL AND linksGroups.userid = '" . $args[1] . "';";

	} else if( $argWhichQuery  == "num_unfiled" ) {
		return "
			SELECT count( * ) FROM links
			LEFT JOIN linksCategoriesXRef ON links.ID = linksCategoriesXRef.linkID
			WHERE linksCategoriesXRef.linkID IS NULL ";
	}
}

function getMasterQuery() {
  return "SELECT 
      links.ID,
      links.submitter as u,
      links.name, 
      links.createDate, 
      links.url,
			linksGroups.name as tag,
			linksCategoriesXRef.catID as tagID,
      TIME_FORMAT(SEC_TO_TIME(TIME_TO_SEC( CURTIME()) - TIME_TO_SEC( createDate )), '%H:%i') AS time_ago
    FROM links 
      LEFT JOIN linksCategoriesXRef 
        ON links.ID = linksCategoriesXRef.linkID 
      LEFT JOIN linksGroups
          ON linksGroups.ID = linksCategoriesXRef.catID
    WHERE
    (links.isPrivate IS NULL
      AND
      (linksGroups.name LIKE 'p/%' OR linksGroups.name LIKE 'p%%F%')
      )";

}

function encodeAmps( $argS ) {
	# replace any unescaped ampersands
	return preg_replace( "/(&)([^(amp;)])/", "&amp;$2", $argS );
}

function newFuncName( $argOne ) {
	#$debug = 1;
	if( $argOne ) {
		if( $debug )
			echo "newFuncName( $argOne ) called<br />";
	} else if( $debug )
		echo "newFuncName( $argOne ) called with bad args<br />";
}

function getCompactString( $argStr ) {
	$args = func_get_args();
	$MAX_LENGTH = $args[1] ? $args[1] : 31;
	$s = unEscapeQuotes( $argStr );
	return ( strlen( $s ) > $MAX_LENGTH ) ? (substr( $s, 0, $MAX_LENGTH ) . "...") : $s; # dum vi fix: < 
}

function getStatsLine() {
	$con_getStatsLine = mysql_connect();
	mysql_selectdb( getDBName() );
	
	$qs = "SELECT COUNT(*) FROM linksUsers;";
	$q = mysql_query( $qs );
	if( $q )
		$numUsers = mysql_result($q,0);
	
	$qs = "SELECT COUNT(*) FROM links;";
	$q = mysql_query( $qs );
	if( $q )
		$numLinks = mysql_result($q,0);

	$qs = "SELECT COUNT(*) FROM links WHERE createDate LIKE DATE_FORMAT( NOW(), '%Y%m%d%%');";
	$q = mysql_query( $qs );
	if( $q )
		$linksToday = mysql_result($q,0);

	conClose( $con_getStatsLine );

	return "<b>$numUsers</b> users, <b>$numLinks</b> links, <b>$linksToday</b> new links today...";
}

function getLinkInfo( $argId ) {
	if( $argId ) {
		if( $debug )
			echo "getLinkInfo( $argId ) called<br />";

		$con_getLinkInfo = mysql_connect();
		mysql_selectdb( getDBName() );
		$qs =  "SELECT * FROM links WHERE ID = $argId;";
		$q = mysql_query( $qs );
		$li = Array();
		if( $q ) {
			$li['id'] = mysql_result($q,$i,"ID" );
			$li['url'] = mysql_result($q,$i,"url" );
			$li['name'] = mysql_result($q,$i,"name" );
			$li['createDate'] = mysql_result($q,$i,"createDate" );
			$li['submitter'] = mysql_result($q,$i,"submitter" );
			$li['isPrivate'] = mysql_result($q,$i,"isPrivate" );
		}
		conClose( $con_getLinkInfo );
		return $li;

	} else if( $debug )
		echo "getLinkInfo( $argId ) called with bad args<br />";
}

# FIXME: not done
function addCategorization( $argId, $argCatId ) {
	if( $argId && $argCatId ) {
		echo "addCategorization( $argId, $argCatId ) called<br />";
	} else {
	if( $debug )
		echo "addCategorization( $argId, $argCatId ) called with bad args<br />";
	}
}

function categorizeLink( $argId, $argCats ) {
	if( $argId && $argCats && count( $argCats ) ) {
		if( $debug )
			echo "categorizelink($argId, $argCats) called<br />";
		
		$con_categorizeLink_categorizeLink = mysql_connect();
		mysql_selectdb( getDBName() );
		foreach( $argCats as $catNum ) {
			$qs =  "INSERT INTO linksCategoriesXRef VALUES( $argId, $catNum );";
			$q = mysql_query( $qs );
			if( ! $q ) {
%>
<div class="attention warning">
<%= getCatVerb() . "ing" %> link failed
</div>
<%
				break;
			} else {
				if( $debug )
					echo "categorizeLink: tagged $argId as $catNum<br />";
			}
		}
		conClose( $con_categorizeLink );
		return 1;
			
	} else {
			echo "categorizelink($argId, $argCats) called with bad args<br />";
			return 0;
	}
}

# needs security wrapper?
function deleteCategorizationForLink( $argId ) {

	if( $argId ) {
		if( $debug )
			echo "deleteCategorizationForLink($argId) called<br />";
		$con_deleteCategorizationForLink = mysql_connect();
		mysql_selectdb( getDBName() );
		$qs = "DELETE FROM linksCategoriesXRef WHERE linkID = $argId;";
		$q = mysql_query( $qs );
		conClose( $con_deleteCategorizationForLink );
		if( $q )
			return 0; # FIXME: real return status
		else
			return 1; # db call failed
	} else
		return 1; # bad arguments
}

function getOldBookmarklet() {
	return "javascript:_ql=window.location;_ln=prompt('Name for this link?',document.title);if(!_ql){void(_ql=prompt('link...',''))};if(_ql&&_ln){window.location='http://feedmelinks.com/folder-funnel?from=toolbar&op=submit&name='+escape(_ln)+'&url='+escape(_ql)+'&ref='+escape(document.referrer)+'&version=0'}else{history.go(0);}";
}

function getBookmarklet() {
	return "javascript:_ql=window.location;_ln=prompt('Name for this link?',document.title);if(!_ql){void(_ql=prompt('link...',''))};if(_ql&&_ln){_ln=new String(_ln.replace(/&apos;/g,'&amp;apos;')).replace(/\\&quot;/g,'&amp;quot;');window.location='http://feedmelinks.com/categorize?from=toolbar&op=submit&name='+escape(_ln)+'&url='+escape(_ql)+'&ref='+escape(document.referrer)+'&version=0.6'}else{history.go(0);}";
}

function getBGColor() {
	# Nb. NO LEADING HEX HASH!!!
	return "C0E3C9";
}

function getCatName() {
	return "tag";
}

function getCatsName() {
	return "tags";
}

function getCatVerb() {
	return "tag";
}

function getUnCattedName() {
	return "not tagged";
}

function getNumSimilarUrls( $argUrl, $ignoreLinkID ) {
	return showSimilarUrlsDriver( $argUrl, 0, $ignoreLinkID, "COUNT" );
}

function getSimilarlyLinkingUsers( $argUrl, $ignoreLinkID, $argMaxUrls ) {
	return showSimilarUrlsDriver( $argUrl, $ignoreLinkID, $argMaxUrls, "USERS" );
}

function showSimilarUrls( $argUrl, $ignoreLinkID, $argMaxUrls ) {
	return showSimilarUrlsDriver( $argUrl, $argMaxUrls, $ignoreLinkID, "LINKS" );
}

function showSimilarUrlsDriver( $argUrl, $ignoreLinkID, $argMaxUrls, $argMode ) {
	#$debug = 1;
	if( !$argMaxUrls )
		$argMaxUrls = 256;
	if( $argUrl ) {
		$con = mysql_connect();
		mysql_selectdb( getDBName() );

		# force this cause the mysql needs it, for some reason...
		if( 
			! preg_match("_http:\/\/_", $argUrl )
			&& ! preg_match("_ftp:\/\/_", $argUrl )
			&& ! preg_match("_news:\/\/_", $argUrl )
			&& ! preg_match("_gopher:\/\/_", $argUrl )
			&& ! preg_match("_telnet:\/\/_", $argUrl )
			)
			$argUrl = "http://$argUrl";

		$up = parse_url( $argUrl );
		$searchUrl = $up['host'] . $up['path'] . $up['query'];

		$qs = 'SELECT ' . ($argMode == "COUNT" ? "COUNT(*)" : "*") . ' FROM links WHERE 
						(url LIKE "%' . urlencode( $searchUrl ) . '%"
						OR url LIKE "%' . urlencode( $up['host'] . $up['path'] ) . '%"
						OR url LIKE "%' . urlencode( $up['host'] ) . '%")
							AND (isPrivate IS NULL)
							AND ID <> ' . $ignoreLinkID . '
								ORDER BY createDate DESC;';
		if( $debug )
			echo "<p>$qs</p>";
		$q = mysql_query( $qs );
		$matchingLinks = $q ? mysql_num_rows($q) : 0;
		$numMatchingLinks = ($q && $argMode == "COUNT") ? (mysql_result($q,0) > 0 ? mysql_result($q,0) - 1 : 0) : 0;
		if( $matchingLinks ) {

		if( $argMode == "LINKS" ) {
%>
<h3>found <%= $matchingLinks %>  <%= ($matchingLinks == 1) ? "link" : "links"  %> like "<%= $argUrl %>"<%= $argMaxUrls && $argMaxUrls < $matchingLinks ? ", showing the first $argMaxUrls.<br />
[<a href='/urls-like?url=" . urlencode( $argUrl ) 
. "'>click to show all</a>]<br />" : ":</h3>" %>
<table cellpadding="5" cellspacing="0" style="border: 1px solid #333333;">
<%
					for( $i = 0; $i < $matchingLinks && ($argMaxUrls ? $i < $argMaxUrls : 1); $i++ ) {
						$id = mysql_result($q,$i,"ID" );
%>
	<tr>
		<td class="r<%= $i % 2 == 0 ? 1 : 0 %>a">
			<%= makeUserLink( getOwnerForLink( $id )) %>'s <%= makeLinkOut( $id ) %> <%= makePermaLink( $id ) %> 
		</td>
	</tr>
<%
					}
%>
</table>
<%
			} else if( $argMode == "USERS" ) {
%>
found <%= $matchingLinks %> similar links by these users:<br />
&#160;&#160;
<%
					for( $i = 0; $i < $matchingLinks && ($argMaxUrls ? $i < $argMaxUrls : 1); $i++ ) {
						$id = mysql_result($q,$i,"ID" );
%>
<%= $i != 0 ? "," : "" %>
			<%= makeUserLink( getOwnerForLink( $id )) %>'s <%= makePermaLink( $id ) %>
<%
					}
					if( $matchingLinks > $argMaxUrls )
						echo ", ... ";
						# FIXME: not working: (<a href=\"/urls-like?id=$id\">show all similar</a>)";

%>
<%
				conClose( $con );
			} else if( $argMode == "COUNT" ) {
				conClose( $con );
				return $numMatchingLinks;
			} else {
				conClose( $con );
				return $matchingLinks;
			}
		}
		conClose( $con );
	}
}

function isABrowser( $ua ) {
	if( ! isADevice( $ua ))
		return preg_match( "/(Opera|Mozilla)/", $ua );
	else
		return 0;
}

function isADevice( $ua ) {
	return preg_match( "/(Nokia|Symbian|PalmOS|BlackBerry|EPOC|WAP|Wap|AvantGo|Danger|Windows CE)/", $ua );
}

function userHasOption( $argUserId, $argOptionId ) {
	if( $argUserId && $argOptionId ) {
		$qs = "SELECT COUNT(*) FROM linksUserOptions WHERE optionID = $argOptionId AND userID = '$argUserId';";
		mysql_connect();
		mysql_selectdb( getDBName() );
		$q = mysql_query( $qs );
		$hasOpt = mysql_result($q,0);
		if( $hasOpt )
			return true;
	} 
	return false;
}

function getDateForSQL() {
	return date( "Y-m-d H:i:s" );
}

function isQueryTrackedHost( $argHost ) {
	$hosts = array( "search.msn.com", "google.com", "search.yahoo.com", "www.google.com", "jm3.net", "feedmelinks.com" );
	foreach ($hosts as $host) {
		if( $host == $argHost )
			return true;
	}
	return false;
}

function prepUrlForTracking( $argReferer ) {
	$debug = 0;

	$url_parts = parse_url($argReferer);
	$host = $url_parts["host"];
	if( $debug ) 
		echo "<br/>host: $host<br/>";

	if( isQueryTrackedHost( $host ) ) {
		parse_str($url_parts["query"],$params);
		$qParam = $params['q'];
		if( $debug ) {
			echo  "params[q]: " . $params['q'] . "<br/>";
			echo  "params[p]: " . $params['p'] . "<br/>";
			echo "q param is $qParam<br/>";
		}
		if( $host == "feedmelinks.com" )
			return ($qParam ? $host . "/search?q=" . $qParam : "");
		else if( $host == "search.yahoo.com" )
			return $host . ($params['p'] ? "/search?p=" . $params['p'] : "");
		else if( $host == "search.msn.com" )
			return $host . ($qParam ? "/results.aspx?q=" . $qParam : "");
		else
			return $host . ($qParam ? "?q=" . $qParam : "");
	} else {
		if( $debug )
			echo "$host is not query tracked<br/>";
		return $host;
	}

}

function trackReferer( $argLinkId, $argUserId, $argReferer ) {
	$debug = 0;
	if( $argLinkId && $argReferer ) {
		mysql_connect();
		mysql_selectdb( getDBName() );
		$userId = urlencode( $argUserId ? $argUserId : getOwnerForLink( $argLinkId ));
		$referer = urlencode( prepUrlForTracking( $argReferer ));
		if( $referer ) {
			$qs = "INSERT INTO linksReferers VALUES( NULL, $argLinkId, '$userId', '$referer', '" . getDateForSQL() . "');";
			$q = mysql_query( $qs );
		}

		if( $debug ) {
			echo "\$q: $q<br/>";
			echo $qs;
		}
		return $q;
	} else 
		return 0;
}

function getReferers( $argId ) {
	if( $argId ) {
		$qs = "SELECT DISTINCT (referer) FROM linksReferers WHERE linkID = " . urlencode( $argId ) . ";";
		mysql_connect();
		mysql_selectdb( getDBName() );
		$q = mysql_query( $qs );
		if( $q ) 
			$numRows = mysql_num_rows($q);
		if( $numRows ) {
			echo "<h4>People found this link via:</h4>";
		}
		while( $i < $numRows ) {
			$referer = urldecode( mysql_result($q, $i, "referer"));
			echo "&#160;&#160;<a href=\"http://$referer\">$referer</a><br />";
			$i++;
		}
		#if( $numRows ) {
			#echo "-----------------<br />";
		#}
	}
}

function getPrivateColor( $u ) {
	return "#dddddd";
}

# no-op, deprecated
function getColorKey() {
	return;
}

function isSuperUser( $u ) {
	if( $u == "jm3" || $u == "pheezy" || $u == "gus" )
		return 1;
	else
		return 0;
}

function isValidUser( $u ) {
	$con = mysql_connect();
	mysql_selectdb( getDBName() );
	$qs = "SELECT userid from linksUsers where userid = '$u';";
	$q = mysql_query( $qs );
	if( $q )
		$userExists = mysql_num_rows($q);
	conClose( $con );
	return $userExists ? true : false;
}

function removeOldProfileImage( $u ) {
		$exts = array( "gif", "jpg", "jpeg", "png" );
		foreach ($exts as $ext) {
			$f = "/usr/home/hirokai/feedmelinks.com/usr/$u/profile.$ext";
			if( is_file( $f )) {
				unlink( $f );
			}
		} # end foreach
	}

function showUserImage( $u ) {
	return getSizedUserImage( $u, 200 );
}

function getSizedUserImage( $u, $pxl_size ) {
ob_start();
		$exts = array( "gif", "jpg", "jpeg", "png" );
		foreach ($exts as $ext) {
			$f = "/usr/home/hirokai/feedmelinks.com/usr/$u/profile.$ext";
			if( is_file( $f )) {
%>
	<img src="/usr/<%= $u %>/profile.<%= $ext %>" height="<%= $pxl_size %>" width="<%= $pxl_size %>" class="profileImage" alt="" border="0" >
<%
				return;
			}
		} # end foreach
%>
	<img src="/usr/NO_PROFILE/profile.jpg" height="<%= $pxl_size %>" class="profileImage" alt="" border="0" >
<%
	$ret = ob_get_clean();
	echo $ret;

	}

function auth( $u, $tok ) {

		if( md5( getPasswdForUser( $u )) == $tok ) {
			session_start();
			session_register("authenticated");
			session_register("sessionUserId");
			$sessionUserId = $u;

			return 1;
		} else
			return 0;

		# i really wish we could put the cookie login code here...
	}

function logout() {

	session_start();

	# clear the category list caches:
	session_unregister( 'sessionCachedGroupCounts' );
	session_unregister( 'sessionCachedGroupPublicFlags' );
	session_unregister( 'sessionCachedGroupList' );
	
	# clear the login cookies
	setCookie( "c_uid",        "", time() + 3000, "/", ".feedmelinks.com" );
	setCookie( "c_pass_token", "", time() + 3000, "/", ".feedmelinks.com" );

	# log the user out:
	$authenticated = 0;
	$sessionUserId = "";
	unset( $_SESSION["cache"] );
	$_SESSION["cache"] = "";
}

function getHomeDir() {
	global $env;
	if( $env == "dev" )
		return "/home/jm3/www";
	else if( $env == "powerbook" )
		return "/Users/erdnase/www/feedmelinks.com";
	else
		return "/usr/www/users/hirokai/feedmelinks.com";
}

function conClose() {
	$args = func_get_args();
	$argCon = $args[0];
	if( $argCon && get_resource_type( $argCon ) == "mysql link" )
		mysql_close( $argCon );
	return 0;
}
	
function getDBName() {
	global $env;
	if( $env == "dev" )
		return "dev_feedmelinks_com_-_dev";
	else if( $env == "powerbook" )
		return "fml";
	else
		return "hirokai_jm3DataMart";
}

function get_parser() {
	global $env;
	if( $env == "powerbook" )
		return "/sw/bin/xsltproc";
	else
		return "/usr/local/bin/xsltproc";
}

function getSiteUrl() {
	global $env;
	if( $env == "dev" )
		return "http://dev.feedmelinks.com";
	else if( $env == "powerbook" )
		return "http://localhost:8080";
	else
		return "http://feedmelinks.com";
}

function getCommentCSS() {
			return '
		<style type="text/css">
			.c  { background-color: #C0E3C9; border: 1px solid #75937E; color: #444444; width: 300px; padding: 5px; padding-left: 15px; margin-top: 6px; }
			.oc { background-color: #ACDEB5; color: #000000; border: 1px solid #333333; }
			.u  { background-color: #C0DEE2; border: 1px solid #578960; }
			.c a {font-weight: bold; text-decoration: underline; }
		</style>
		';
		}

function getAddCommentForm( $argId, $comments_exist, $debug ) {
		return '
		<div class="linkbox" style="margin-top: 10em;">
			<b>Add ' .($comments_exist ? 'another' : 'a ' ) . ' comment to this link:</b>
			<form name="comment_form" action="index.php">
				' . ($debug ? '<input type="hidden" name="debug" value="1"/>' : '') . '
				<input type="hidden" name="op" value="add_comment" />
				<input type="hidden" name="l" value="' . $argId . '" />
				<table cellpadding="0" cellspacing="0" border="0"><tr><td valign="top">
					<textarea name="comment" rows="8" cols="28" class="context"></textarea>
				</td><td style="line-height: 1.1em; color: #586C61;" valign="top">
				<div style="font-weight: bold;">
				Comment Formatting Tips &amp; Tricks:
				</div>
				<small>
				to insert a link, use the link number in [brackets].<br />
				ie. write: <b>[15753]</b> to insert:<br/>
				<a title="view user info" href="/u/jm3">jm3</a>&apos;s 
				<a href="/t/15753" 
				title="http://boingboing.net/2004/04/09/the_truth_about_came.html">the missing camel spider link</a>(<a  title="view link info" href="/15753">15753</a>)<br />

				<br />
				to insert a user link, write: <b>user(<em>username</em>)</b>.<br />
				ie. 
					write: <b>user( <em>pheezy</em> )</b>
					to insert: <a title="view user info" href="/u/pheezy"><b>pheezy</b></a>.<br />

				<br />
					to insert arbitrary links, write:<br />
					<b><code>link(<em>http://url.com, name of link</em>)</code></b><br />
					<br />
					{other HTML tags will be stripped out}<br />
				</small>
					</td></tr></table>
				
				<button accesskey="c" class="default" value="add comment" onClick="document.forms.comment_form.submit();">add <u>c</u>omment</button>
			</form>
			</div>
		';
	}

function getCommentsForLink() {
    $args = func_get_args();
		$argId = $args[0];
		$argUser = $args[1];
		$debug = 0;
		#$debug = $args[2];

		$link = $argId;

		if( $link && isValidLink( $link )) {

			$owner = getOwnerForLink( $link );
			$linkfile = get_comments_file( $link, $owner );
			
			if( file_exists( $linkfile )) {
					if( $debug )
						echo "(COMMENTS FILE $link$COMMENT_EXT  EXISTS AND IS READABLE)<br /><br />"; 
		
					# flock comments file and read into an array
					ignore_user_abort(true);
					$f = fopen( $linkfile, 'r' );
					flock( $f, LOCK_SH );
					$lines = file( $linkfile );
					flock( $f, LOCK_UN );
					fclose( $f );

	%>
	<h4> Comments: </h4>
	<%
	#<p>
	#(comments by link owner have a dark border,<br />
	#&#160;your comments are displayed in blue.)
	#</p>

		
					$comments = false;
					foreach ($lines as $line_num => $line) {
						$comments = true;
						list($user,$date,$comment) = explode(", ",$line, 3);
						if( $line_num )
							echo "then, ";
							$d = formatTS( $date );
						echo "<a href='" . get_site() . "/~$user'>$user</a>, " 
						. ($d != "today" && $d != "yesterday" ? " at " : "" ) 
						.  $d . ", said:";
						switch ($user) {
								case $argUser:
										$class = "c u";
										break;
								case $owner:
										$class = "c oc";
										break;
								default:
										$class = "c";
										break;
						}

						echo "<div class=\"$class\" style=\"width: 40em;\">$comment</div><br />";
					}
			} else {
					$mesg = "COULDNT READ COMMENT FILE $linkfile!";
				if( $debug )
					echo $mesg;
				else
					echo "<!-- $mesg -->";
			}
		} else {
			echo "NO LINK or INVALID LINK ID ($argID)<br />";
		}
		#if( ! $comments )
			#echo "&#160;NO COMMENTS FOR THIS LINK EXIST (YET)<br />";
		if( $argUser && $argUser != "nobody")
			echo getAddCommentForm( $argId, $comments, $debug );
		else if( $argUser == "nobody" && $comments || ($argUser != "nobody"))
			echo "<a href='/login?bounceToPage=$argId'>log in</a> to add your own comments...";
	}

function getCommentersForLink( $argId ) {
	if( $argId ) {
		$debug = 0;

		$COMMENT_EXT = '.txt';
		$COMMENT_DIR = "_comments/";
		$folder = escapeshellcmd( getOwnerForLink( $argId ));
		$cmd = "cat _comments/$folder/$argId.txt | awk '{print $1}' | sed s/,// | sort | uniq | fmt";
		if( $debug ) {
			echo "(DEBUG: getCommentersForLink($argId): \$folder: $folder)<br/>\n";
			echo "(DEBUG: getCommentersForLink($argId): \$cmd:<br/>\n&#160; &#160; $cmd<br/>\n";
		}
			$a = explode( " ", shell_exec( $cmd ));

			# strip the trailing spaces
			$i = 0;
			foreach ($a as $v)
				$a[$i] = rtrim( $a[$i++]);

			return $a;
		}
}

function addUser( $argUserId, $argEmail, $argPassword, $argName ) {
	$userId   = urlencode( $argUserId );
	$email    = urlencode( $argEmail );
	$password = urlencode( $argPassword );
	$name     = urlencode( $argName );

	$qs = "INSERT into linksUsers values(NULL,'$userId','$email', '$password', '$name','');";

	l( "new_user: $argUserId, $argEmail" );

	$con = mysql_connect();
	mysql_selectdb( getDBName() );
	$q = mysql_query( $qs );
	conClose( $con );
	return $q;
}

function addFolder( $argFolderName, $argUserId ) {
	return addFolderDriver( $argFolderName, $argUserId, 0 );
}

function addPrivateFolder( $argFolderName, $argUserId ) {
	return addFolderDriver( $argFolderName, $argUserId, 1 );
}

function addFolderDriver( $argFolderName, $argUserId, $argIsPrivate ) {
$debug=1;
	if( $argFolderName &&  $argUserId ) {

		if( ! $argIsPrivate ) {
			# first make sure the folder is public, 
			# because we want new folders created public by default:
			$folderName = makePublicFolderName( $argFolderName );
		} else
			$folderName = $argFolderName;
		
		$con_addFolderDriver = mysql_connect();
		mysql_selectdb( getDBName() );

		# next we check to make sure that folder does not already exist for this user:
		$qs = "SELECT id, name FROM linksGroups WHERE userid = '$argUserId' AND name = '$folderName';";
		$q = mysql_query( $qs );
		if( $q ) {
			$numRows = mysql_num_rows($q);
			if( $numRows > 0 ) {
				$extant_tag_id = mysql_result($q, 0, "ID");
				if( $debug )
					e( "EXTANT TAG ID: $extant_tag_id" ); 
			}
		}

		if( ! $q || ! $numRows ) {
			if( $debug )
				echo "DEBUG: did not see the folder already<br/>";
			$qs = "INSERT into linksGroups VALUES(NULL,'$argUserId','$folderName','');"; 
			if( $debug )
				echo "$qs<br/>";
			$q = mysql_query( $qs ); 
			if( ! $q ) {
				echo "Sorry, something bad happened and your new folder wasn't created.<br />";
				echo "Please click your back button and choose a different folder, or email hide@address.com<br />\n"; 
				conClose( $con_addFolderDriver ); 
				return 0;
			} 
			$newFolderId = mysql_insert_id(); 
			conClose( $con ); 
			return $newFolderId;
		} else {
			notice( "It seems you already have a folder with that name (it's tag #$extant_tag_id).<br />
			Please pick a new name.<br />" );
			return $extant_tag_id;
		}
	} else {
		echo "ERROR: addFolder( '$argFolderName', '$argUserId') called without \$argFolderName or without \$argUserId";
	}
}

function notice( $mesg ) {
	if( $mesg ) {
%>

<div class="notice">
<b>Notice.</b>
<%= $mesg %>
</div>

<%
	}
}

function deleteLink( $argId, $argUserId ) {
	if( $argId && $argUserId ) {
		mysql_connect();
		mysql_selectdb( getDBName() );

		# delete link:
		$qs = "DELETE from links where ID = $argId AND submitter = '$argUserId';";
		if( $debug )
			echo $qs;
		$q = mysql_query( $qs );

		# delete any category x-refs:
		$qs = "DELETE from linksCategoriesXRef where linkID = $argId;";
		if( $debug )
			echo $qs;
		$q = mysql_query( $qs );

		conClose();
		return $q;
	}
}

function unEscapeQuotes( $argS ) {
	return preg_replace( '/(&quot;|&amp;quot;)/', '"', preg_replace( "/&apos;|&amp;apos;/", "'", $argS ));
}

function escapeQuotes( $s ) {
	if( preg_match( "/'/", $s ) || preg_match( '/"/', $s ))
		return preg_replace( '/("|%22)/', '&quot;', preg_replace( "/('|%27)/", '&apos;', o( $s )));
		else 
		return $s;
}

function addLinkSimple( $argUrl, $argName, $argSubmitter, $isPrivate = "NULL", $debug = 0 ) {
	if(  $argUrl &&  $argName && $argSubmitter ) {
		mysql_connect();
		mysql_selectdb( getDBName() );
		$qs = "INSERT into links values(NULL,'" . urlencode( $argUrl ) . "','" . urlencode(escapeQuotes($argName)) . "', NULL, NULL,'" . urlencode( $argSubmitter ) . "', NULL, $isPrivate );";
		if( $debug ) 
			echo "qs: $qs<br>";
		$q = mysql_query( $qs );
		$id = $q ? mysql_insert_id() : 0;
		conClose();
		return $id;
	} else return 0;
}

function addLink( $argUrl, $argName, $argSubmitter, $argFolderId, $argPrivate, $argOptions ) {
	if(  $argUrl &&  $argName && $argSubmitter ) {
		if( ! $argFolderId || $argFolderId == "NULL" ) {
			$q = addLinkSimple( urldecode( $argUrl ), urldecode( $argName ), urldecode( $argSubmitter ) );
		} else {
			$isPrivate = $argPrivate ? $argPrivate : "NULL";

			mysql_connect();
			mysql_selectdb( getDBName() );

			# check to make sure the folder is not private; if it is, make the link private too:
			$folderName = getNameForFolder( $argFolderId );
			if( $folderName && (! isPublic( $folderName ))) {
				$isPrivate = 1;
			}

			$qs = "INSERT into links values(NULL,'$argUrl','$argName', NULL, NULL,'$argSubmitter', $argFolderId, '$argOptions', $isPrivate );";
			$q = mysql_query( $qs );
			conClose();
			}
			return $q;
		} else return 0;
	}

function addCommentToLink( $argId, $argComment, $commenter, $debug ) {
	$link = $argId;
	$comment = $argComment;
	$MAX_COMMENT_LENGTH = 4096;
	$DATE_FORMAT = "YmdHis";
	$ext = '.txt';
	$dir = get_root() . "/_comments/";

	if( $commenter && $link && $comment && isValidLink( $link ) ) {
		if( ! isValidUser( $commenter )) {
			$e = "$commenter is not a valid user";
			return $e;
		} else {
		if( strlen( $comment ) < $MAX_COMMENT_LENGTH ) {
			$owner = getOwnerForLink( $link );

			$folder = escapeshellcmd( $owner ) . "/";
			$linkfolder = $dir . $folder;
			$linkfile = $dir . $folder . escapeshellcmd( $link ) . $ext;

			if( !is_dir( $linkfolder ) || !is_writable( $linkfolder )) {
				$old_umask = umask(0);
				mkdir( $linkfolder );
				umask($old_umask);
			} else
				if( $debug )
					echo "(DEBUG: FOLDER $folder EXISTS AND IS EXECUTABLE/WRITABLE<br />";
			if( !is_file( $linkfile ) || !is_writable( $linkfile )) {
				if( $debug )
					echo "(DEBUG: COMMENTS FILE FOR LINK $link DOES NOT EXIST OR IS NOT WRITABLE, TRYING TO CREATE...)<br />"; 
			}
			if( $debug )
				echo "(DEBUG: COMMENTS FILE $link$ext NOW EXISTS AND IS WRITABLE)<br />"; 

			# fix the newlines:
			$comment = preg_replace( "/\n/", "___NEWLINE___", $comment );
			$comment = hsc( $comment );
			$comment = preg_replace( "/___NEWLINE___/", "<br />", $comment );


			# FIXME: handle vignette and parened text....

			# convert any arbitrary html links
			$comment = preg_replace( "/link\( *(.+), *(.+)\)/", "<a href=\"\\1\">\\2</a>", $comment );

			# convert any user links
			$comment = preg_replace( "/user\( *([^\)]+) *\)/", "<a href=\"/u/\\1\">\\1</a>", $comment );

			# convert any Cf. footnotes
			function linkReplace_cb( $matches ) {
				ob_start();
				makeUserLink( getOwnerForLink( $matches[1] ));
				echo "'s ";
				makeLinkOut( $matches[1] );
				echo " ";
				makePermaLink( $matches[1] );
				$linkOutHTML = ob_get_clean();
				return $linkOutHTML;
			}

			$comment = 
				preg_replace_callback( 
					"/\[([0-9]+)\]/",
					"linkReplace_cb",
					$comment
				);

			# LOCK HERE:
			ignore_user_abort(true);
			$f = fopen( $linkfile, 'a' );
			flock( $f, LOCK_EX );

			# DO WORK
			if( $bytes_written = fwrite( $f, "$commenter, " . date( $DATE_FORMAT ) . ", $comment\n" )) {
				if( $debug ) 
					echo "(DEBUG: CHMOD-ING $linkfile to world-write)<br/>";
				chmod( $linkfile, 0666 );
				if( $debug )
					echo "(DEBUG: WROTE $bytes_written BYTES TO $linkfile)<br />";
				else
					echo "Adding your comment... done!<br />";
				
				# NOW WE SEND MAIL:

				# for every commenter to this link, past and present...
				$recipients = getCommentersForLink( $link );

				# plus the link owner
				array_push( $recipients, $owner );

				# de-dupe it in case the owner commented in the past...
				$recipients = array_unique( $recipients );

				if( $debug ) {
					echo "(DEBUG: SENDING MAIL...)<br/>\n";
					echo "(DEBUG: all recipients: ";
					print_r( $recipients );
					echo ")<br/>\n";
				}
				foreach ( $recipients as $recipient) {
					if( $debug )
						echo "(DEBUG: &#160; this recipient: |$recipient|)<br/>\n";
					# dont send mail to ourselves...
					if( $recipient != $commenter ) {
							#whose link is being commented:
							$to = getEmailAddressForUser( $recipient );
							if( $to ) {

								$to = "$recipient <$to>";

								$linkName = getTitleForLink( $link );
								$folderName = makePrettyFolderName( getNameForFolder( getFolderForLink( $link )));
							
								$headers = "";
								$pronoun = $recipient == $owner ? "your" : "$owner's";
								$proFolder = $recipient == $owner ? " in your $folderName folder" : "";
								$subject = "$commenter commented on $pronoun link \"$linkName\"";
								$body    = "$commenter just added the comment,

---------------------------------------

$comment

---------------------------------------

to $pronoun link \"$linkName\" $proFolder.

click to respond: http://feedmelinks.com/$link

rock on,

-- Feed Me Links
";

					$headers .= "From: Feed Me Links <" . getEmailAddressForUser( $commenter ) . ">\n";
					$headers .= "X-Mailer: feedmelinks-mailer-daemon\n";
					$mailSuccess = mail( $to, $subject, $body, $headers);
					if( $debug )
						echo "(DEBUG: &#160;  mailSuccess to \"$to\" was: $mailSuccess)<br />\n";
				} else if( $debug )
					echo "(DEBUG: no TO:, not sending.)<br/>";
			} else {
				# we are the user commenting on the link
				if( $debug )
					echo "(DEBUG: $commenter is the user commenting on the link, so we don't need to mail him)<br />\n";
			}
		}

			} else {
				$e = "ERROR: WRITE FAILED!!!<br />";
				echo $e;
				return $e;
			}

			# RELEASE LOCK
			flock( $f, LOCK_UN );

			fclose( $f );
			ignore_user_abort(false);

		} else {
			$e = "<div class='error'>ERROR: COMMENT IS TOO LONG.</div>";
			echo $e;
			return $e;
		}
		}
	} else {
		if( $debug )
			echo "missing args or invalid link: \$commenter: $commenter, \ $link:  $link, \$comment, $comment, isValidLink( $link ): " . isValidLink( $link );
	}
}

function getOwnerForFolder( $argId ) {
	if($debug)
		echo "DEBUG: getOwnerForFolder($argId):<br/>";
	return urldecode( getFieldForFolder( $argId, "userid" ));

}

function getOwnerForLink( $argId ) {
	return getFieldForLink( $argId, "submitter" );
}

function isPrivate( $argId ) {
	return getFieldForLink( $argId, "isPrivate" );
}

function setPrivate( $argId ) {
	togglePrivate( $argId, 1 );
}

function setPublic( $argId ) {
	togglePrivate( $argId, "NULL" );
}

function setFolderOfLinksPrivate( $argId, $argUserId ) {
	toggleFolderOfLinksPrivacy( $argId, $argUserId, 1 );
}

function setFolderOfLinksPublic( $argId, $argUserId ) {
	toggleFolderOfLinksPrivacy( $argId, $argUserId, 0 );
}

function toggleFolderOfLinksPrivacy( $argId, $argUserId, $argToggle ) {
	$debug = 0;
	$toggle = (!$argToggle) ? "NULL" : 1;
	if( $argId && $argUserId ) {
	$con = mysql_connect();
	mysql_selectdb( getDBName() );
	$qs = "UPDATE links SET isPrivate = $toggle WHERE submitter = '$argUserId' AND groupid = $argId;";
	if( $debug )
		echo "DEBUG: qs: $qs<br/>";
	$q = mysql_query( $qs );
	if( $q ) {
		echo "all links made private...<br/>";
	} else {
		echo "ERROR: datbase problem, links may not have been made private...<br/>";
	}
	conClose( $con );
	} else {
		echo "ERROR: toggleFolderOfLinksPrivacy() called with missing args<br />";
	}
}

function togglePrivate( $argId, $toggle ) {
	$debug = 0;
	if( $argId && $toggle) {
		if( $debug )
			echo "setting $argId to private<br/>";
		mysql_connect();
		mysql_selectdb( getDBName() );
		$qs = "UPDATE links SET isPrivate = $toggle WHERE ID = $argId;";
		$q = mysql_query( $qs );
		conClose();
		if( $q )
			return 1;
		else {
			if( $debug )
				echo "$qs failed.";
			return 0;
		}
	} else {
		if( $debug )
			echo "setting $argId to private<br/>";
		return 0;
	}
}

function isInPublicFolder( $argId ) {
	return true;
	#return isPublic( getNameForFolder( getFolderForLink( $id )));
}

function getURLForLink( $argId ) {
	return getFieldForLink( $argId, "url" );
}

function getTitleForLink( $argId ) {
	$s = urldecode( getFieldForLink( $argId, "name" ));
	if( preg_match( get_uni_pattern(), $s ))
		return( o( $s ));
	else
		return $s;
}

function getNameForLink( $argId ) {
	return getTitleForLink( $argId );
}

function getFeatureTypes() {

	mysql_connect();
	mysql_selectdb( getDBName() );
	$featureTypes = array();

	$qs = "SELECT * from linksFeatureTypes;";
	$q = mysql_query( $qs );
	if( $q ) {
		$numRows = mysql_num_rows($q);
		if( ! $numRows ) {
			echo "DEATH - no types found";
		} else while ($i < $numRows) {
			$name = mysql_result($q,$i,"name");
			$id = mysql_result($q,$i,"ID");
			$featureTypes[$id] = $name;
			$i++;
		}
		conClose();
		return $featureTypes;
	} else 
		echo "(no data found)";
	conClose();
}

function getEmailAddressForUser( $argUser ) {
	mysql_connect();
	mysql_selectdb( getDBName() );
	
	$qs = "SELECT email from linksUsers WHERE userid = '$argUser'";
	$q = mysql_query( $qs );
	if( $q )
		$numRows = mysql_num_rows($q);
	conClose();
	if( $numRows )
		return urldecode( mysql_result($q, $i, "email"));
}

function getPasswdForUser( $argUser ) {
	mysql_connect();
	mysql_selectdb( getDBName() );
	
	$qs = "SELECT password from linksUsers WHERE userid = '$argUser'";
	$q = mysql_query( $qs );
	if( $q )
		$numRows = mysql_num_rows($q);
	conClose();
	if( $numRows )
		return urldecode( mysql_result($q, $i, "password"));
	return "THIS IS NOT YOUR PASSWORD, JACKMOUTH";
}

function getIdForFolder( $argName, $argUserId ) {
	$debug = 0;
	if( $argName && $argUserId ) {
		if( $debug )
			echo "getIdForFolder( $argName, $argUserId ) called<br />";
		mysql_connect();
		mysql_selectdb( getDBName() );
		$qs = "SELECT ID FROM linksGroups WHERE USERID = '$argUserId' AND "
		. "(name = 'p%2F$argName' OR name = 'p/$argName' OR name = '$argName' OR name = '" . urlencode( $argName ) . "');";
		$q = mysql_query( $qs );
		if( $q )
			$numRows = mysql_num_rows($q);
		else
			if( $debug ) e( "no q\n" );
		if( $numRows )
			$id = mysql_result($q, 0, 'ID');
		else 
			if( $debug ) e( "cached miss in getIdForFolder( $argName, $argUserId ) - no rows" );
		conClose();
		return $id;

	} else if( $debug )
		echo "getIdForFolder( $argName, $argUserId ) called with bad args<br />";
}

function getNameForFolder( $argId ) {
	if( $argId != "unfiled" )
		return urldecode( getFieldForFolder( $argId, "name" ) );
	else
		return $argId;
}

function getFieldForFolder( $argId, $field ) {
	$my_con = mysql_connect();
	mysql_selectdb( getDBName() );
	$qs = "SELECT $field from linksGroups WHERE ID = $argId";
	$q = mysql_query( $qs );
	if( $q )
		$numRows = mysql_num_rows($q);
	conClose( $my_con );
	if( $numRows )
		return mysql_result($q, $i, $field);
}

function getFieldForLink( $argId, $field ) {
	mysql_connect();
	mysql_selectdb( getDBName() );
	$qs = "SELECT $field from links WHERE ID = $argId";
	$q = mysql_query( $qs );
	if( $q )
		$numRows = mysql_num_rows($q);
	conClose();
	if( $numRows )
		return mysql_result($q, $i, $field);
}

function isValidLink( $argId ) {
	mysql_connect();
	mysql_selectdb( getDBName() );
	$qs = "SELECT name from links WHERE ID = $argId";
	$q = mysql_query( $qs );
	if( $q ) {
		$numRows = mysql_num_rows($q);
		conClose();
		if( $numRows )
			return 1;
	}
}

function getCategoriesForLink( $argId, $argUserId ) {
	$debug = 0;
	if( $argId ) {
		if( $debug ) {
			print "<br />";
			echo "getCategoriesForLink($argId, $argUserId) called<br />";
		}
		if( getOwnerForLink( $argId ) == $argUserId || ! isPrivate( $argId ) ) {
			$con_getCategoriesForLink = mysql_connect();
			mysql_selectdb( getDBName() );
			$qs = "SELECT catID FROM linksCategoriesXRef WHERE linkID = $argId";
			$q = mysql_query( $qs );
			if( $debug )
				echo "getCategoriesForLink: qs : $qs<br />";
			if( $q )
				$numRows = mysql_num_rows($q);
			else if( $debug )
				echo "getCategoriesForLink: DB call failed!<br >";
				
			$cats = Array();
			for( $i = 0; $i < $numRows; $i++ ) {
				if( $debug )
					echo "getCategoriesForLink: found category " . mysql_result($q,$i,"catId") . "<br />";
				if( canSeeCategory( mysql_result($q,$i,"catId"), $argUserId )) {
					if( $debug )
						echo "pushing cat into cats";
					array_push( $cats, mysql_result($q,$i,"catId"));
				} else {
					if( $debug )
						echo "not pushing cat into cats\n";
				}
			}
			if( $debug ) {
				echo "getCategoriesForLink: found " . count( $cats ) . " cats<br />";
				print_r( $cats );
				print "<br />";
				print "<br />";
			}
		} else {
			echo "getCategoriesForLink: permissions issue: $argUserId can't touch $argId<br />";
		}
		conClose( $con_getCategoriesForLink );
		if( sizeof( $cats )) {
			return $cats;
		} else {
			return;
		}
	}
}

function getCategoriesForLinkAsString( $argId, $argUserId ) {
	if( $argId && $argUserId ) {
		return( implode( ", ",  getCategoriesForLink( $argId )));
	}
}

function getShortCategoriesForLinkAsHTML( $argId, $argUserId ) {
	return getCategoriesForLinkAsHTMLDriver( $argId, $argUserId, 0, 0, 0 );
}

function getCategoriesForLinkAsRss( $argId, $argUserId, $showNoun, $showChange ) {
	$cats = getCategoriesForLinkAsHTML( $argId, $argUserId, $showNoun, $showChange );
	$cats = preg_replace( "/^in /", "", $cats );
	$cats = preg_replace( "/^$/", "", $cats ); # kill newlines
	$cats = preg_replace( "/ <a/", "&#160;<a", $cats );
	$cats = preg_replace( "/a> /", "a>&#160;", $cats );
	return $cats;
}

function getCategoriesForLinkAsHTML( $argId, $argUserId, $showNoun, $showChange ) {
	return getCategoriesForLinkAsHTMLDriver( $argId, $argUserId, $showNoun, $showChange, 1 );
}

function getCategoriesForLinkAsHTMLDriver( $argId, $argUserId, $showNoun, $showChange, $showPreposition ) {
	if( $argId ) {
		$cats = getCategoriesForLink( $argId, $argUserId );
		$s = "";
	
		if( $cats ) {
			foreach( $cats as $catNum ) {
				ob_start();
				makeFolderLinkSimple( $catNum );
				$catLinkHTML = ob_get_clean();
				$s = $s ? "$s, $catLinkHTML" : "$catLinkHTML";
			}
		}
		$owner = getOwnerForLink( $argId );
		$owned = $owner == $argUserId ? 1 : 0;
		$noun = $showNoun ? ( sizeof( $cats ) != 1 ? " " . getCatsName() : " " . getCatName() ) : "";

		return 
			sizeof( $cats ) 
				?  ($showPreposition 
					? (!$owned 
						? ("Tagged with: " . getUserLink( $owner ) . "'s ") 
							: "Tagged with: " ) 
					: "") . $s . $noun . ($owned 
						? ($showChange 
								? (".&nbsp; <a href=\"recategorize/$argId\">Click to re-" . getCatName() . "</a>.")
								: ""
							)
						: "." 
					)
				: ( $showChange 
						?  ($owned ? "<a href=\"/recategorize/$argId\">Click to " . getCatVerb() . " this link</a>" : getUnCattedName() )
						: ""
					);
	}
}

function canSeeCategory( $argCatId, $argUserId ) {
	if( $argCatId ) {
		if( isPublicFolder( $argCatId ) || $argUserId == getOwnerForFolder( $argCatId ))
			return true;
		else
			return false;
	}
}

function getLinkToFolder( $argId ) {
	if( $argId ) {
		return "/f/$argId";
	}
}

function getFolderForLink( $argId ) {
	$con = mysql_connect();
	mysql_selectdb( getDBName() );
	$qs = "SELECT groupid from links WHERE ID = $argId";
	$q = mysql_query( $qs );
	if( $q )
		$numRows = mysql_num_rows($q);
	conClose( $con );
	if( $numRows )
		return mysql_result($q,$i,"groupid");
}

function insertBigThumb( $url ) {
	return insertImageLinkIconDriver( $url, 75 );
}

function insertImageLinkIcon( $url ) {
	return insertImageLinkIconDriver( $url, 16 );
}

function insertImageLinkIconDriver( $url, $argSize ) {
	$regex = "/(flickr.com\/photo.gne\?id=|flickr.com\/photos\/|gif|jpg|png)/i";
	$imageLink = "";
	if( preg_match( $regex, $url )) {

		if( preg_match( "/flickr.com\/photo.gne\?id=/", $url )) {
			$id = preg_replace( "/^.+id=/", "", $url ); # parse out the ID
			$thumb = get_flickr_thumb( $id );
		} else if( preg_match( "/flickr.com\/photos\//", $url )) {
			$id = preg_replace( ":^.+photos/[^/]+/:", "", $url ); # parse out the ID
			$id = preg_replace( ":/:", "", $id ); # strip remaining slash
			$thumb = get_flickr_thumb( $id );
		} else {
			$thumb = $url;
		}

	ob_start();
%>
<a href="<%= $url %>"><img height="<%= $argSize %>" width="<%= $argSize %>" src="<%= $thumb %>" class="ii" alt="" border="0" /></a>
<% #<b>[<font color="#ff0000">i</font><font color="#51A168">m</font><font color="#0000ff">g</font>]</b> %>
<%
		$imageLink = ob_get_clean();
	}
	return $imageLink;
	}

function makePrettyFolderName( $name ) {
	return str_replace ( "p/", "", $name);
}

function makePublicFolderName( $name ) {
	if( ! isPublic( $name ))
		return "p/$name";
	else
		return $name;
}

#link drawing functions:
#####################################################

function makeNamedLinkOut( $id, $name ) {
	# replace lsquo with 
	$name = str_replace( "&apos;", "&lsquo;", $name );
	makeLink( $id, "/t/$id", $name, urldecode( getURLForLink( $id )), getClassForLink( $id ), "" );
}

function makeSidebarLinkOut( $id ) {
	makeLink( $id, "/t/$id", getTitleForLink( $id ), urldecode( getURLForLink( $id )), getClassForLink( $id ), "_content" );
}

function makeLinkOut( $id ) {
	makeLink( $id, "/t/$id", getTitleForLink( $id ), urldecode( getURLForLink( $id )), getClassForLink( $id ), "" );
}

function getLinkOut( $id ) {
	return getLink( $id, "/t/$id", getTitleForLink( $id ), urldecode( getURLForLink( $id )), getClassForLink( $id ), "" );
}

function makeExtLinkOut( $id ) {
	makeLink( $id, "/t/$id", getTitleForLink( $id ), "", getClassForLink( $id ), "ext" );
}

function makeLink( $id, $url, $text, $title, $class, $target ) {
	echo getLink( $id, $url, $text, $title, $class, $target );
}

function getLinkLock( $argId ) {
	return '<a href="/toggle-private/' . $argId . '"><img src="/img/lock" border="0" alt="" /></a>';
}

function getLink( $id, $url, $text, $title, $class, $target ) {
	if( $url && $text) {
		ob_start();
		$url = encodeAmps( $url );
		$title = $title ? "title=\"" . encodeAmps( $title ) . "\"" : "";
		$class = $class ? "class=\"$class\"" : "";
		$target = $target ? "target=\"$target\"" : "";
%><a <%= $title ? $title : "" %> href="<%= $url %>" <%= $class %> <%= $target %>><%= $text %></a><%= isPrivate( $id ) ? "&#160;" . getLinkLock( $id ) : "" %><%
		$out = ob_get_clean();
		return $out;
	}
}

function getClassForLink( $argId ) {
	return isPrivate( $argId ) ?  "private" : "";
}

function getBareUserLink( $userId ) {
	return "<a title=\"view user info\" href=\"/u/" . $userId . "\">$userId</a>";
}

function getUserLink( $userId ) {
	$out .= getBareUserLink( $userId );
	$out .= " ";
	$out .= get_contact_link( $userId );
	return $out;
}

function makeUserLink( $argUser ) {
	if( $argUser ) {
		if( $argUser == get_user()) {
%><a title="view <%= get_ownoun() %> info" href="/u/<%= $argUser %>"><img src="/img/mebay.gif" border="0" /></a><%
		} else {
%><a title="view user info" href="/u/<%= $argUser %>"><%= $argUser %></a>
<%= get_contact_link( $argUser ) %><%
		}
	}
}

function getContactsName() {
	return "<%= get_ownoun() %> Peeps";
}

function getFloridUserAgeInDays( $argUserId ) {
	return getUserAgeInDaysDriver( $argUserId, 1 );
}

function getUserAgeInDays( $argUserId ) {
	return getUserAgeInDaysDriver( $argUserId, 0 );
}

function getUserAgeInDaysDriver( $argUserId, $argFlorid ) {
	if( $argUserId ) {
		mysql_connect();
		mysql_selectdb( getDBName() );
		$qs = "SELECT TO_DAYS( CURDATE()) - TO_DAYS( createDate ) AS born_ago FROM links WHERE submitter = '" . urlencode( $argUserId ) . "' ORDER BY ID LIMIT 1;";
		if( $debug )
			echo $qs . "<br/>";
		$q = mysql_query( $qs );
		if( $q )
			$ageInDays = 1 + mysql_result($q,0,"born_ago");
		else
			$ageInDays = 0;
		conClose( );
		return $argFlorid ? ("rocking Feed Me Links for $ageInDays days") : $ageInDays;
	}
}


function makeNamedUserLink( $argUserId, $argName ) {
%><a href="/u/<%= $argUserId %>"><%= $argName %></a><%
	}

function makeEmailUserLink( $userId ) {
%><a title="email <%= $userId %>" href="mailto:<%= getEmailAddressForUser( $userId ) %>"><%= $userId %></a><%
	}

function makeStealItLinkWithText( $id ) {
	echo getStealItLinkWithText( $id );
}

function getStealItLinkWithText( $id ) {
	ob_start();
%><a href="/g/<%= $id %>"><img src="<%= get_site() %>/img/plus.gif" border="0" alt="+" /> Add to your Links?</a><%
	return ob_get_clean();
}

function makeStealItLink( $id ) {
	echo getStealItLink( $id );
}

function getStealItLink( $id ) {
	ob_start();
%><a title="Add to your links?" href="/g/<%= $id %>"><img src="<%= get_site() %>/img/plus.gif" border="0" alt="+" /></a><%
	return ob_get_clean();
	}

function makeFolderLinkSimple( $id ) {
	return makeFolderLink( $id, makePrettyFolderName( $id ? getNameForFolder( $id ) : "unfiled"));
}

function getTagLink( $id, $name ) {
	return getFolderLink( $id, makePrettyFolderName( urldecode( $name )));
}

function getFolderLink( $id, $name ) {
	ob_start();
	makeFolderLink( $id, $name );
	return ob_get_clean();
}

function makeFolderLink( $id, $name ) {
	global $prof;

	#if( isset( $prof )) $prof->startTimer( "makeFolderLink_get_folder_name" );
	#if( isset( $prof )) $prof->stopTimer( "makeFolderLink_get_folder_name" );

	$name = preg_replace( "/&[^a]/", "&amp;", $name );
	$name = preg_replace( "/ /", "&#160;", $name );
	if( ! $id ) {
%><a title="open unfiled" href="/f/unfiled">unfiled</a><%
	} else if( isPublicFolder( $id )) {
%><a rel="tag" title="show <%= getCatName() %> '<%= $name %>'" href="/f/<%= $id %>"><%= $name %></a><%
	} else {
%><a class="private" title="open folder <%= $name %>" href="/f/<%= $id %>"><%= $name %></a>&#160;<img src="/img/lock" alt="" /><%
	}
}

function makeSidebarPermaLink( $id ) {
	$class = getClassForLink( $id );
%>(<a target="_content" <%= $class ? "class=\"$class\"" : "" %> title="view link info" href="/<%= $id %>"><%= $id %></a>)<%
	}

function makePermaLink( $id ) {
	echo getPermaLink( $id );
}

function getPermaLink( $id ) {
	ob_start();
	$class = getClassForLink( $id );
%><small><a class="subtle" title="view link info" href="/<%= $id %>">(info)</a></small><%
	return ob_get_clean();
}

function makeMailLink( $id ) {
	%><a title="Send to a friend" href="javascript:openMailer('<%= $id %>');"><img src="/img/mail.png" alt="mail" border="0" /> Send to a friend?</a><%
}

function makeDeleteLink( $id ) {
	%><a title="Delete this link?" href="javascript:openDelete('<%= $id %>');"><img src="img/trash.gif" alt="delete" border="0" /></a><%
}

function makeEditLink( $id ) {
	%><a title="Edit this link" href="javascript:openEdit('<%= $id %>');"><img src="img/edit.gif" alt="edit" border="0" /></a><%
}

function makeNewWindowLinkWithTitle( $url, $name ) {
%><a target="_blank" title="open <%= $name %> in a new window" href="<%= $url %>"><img src="img/new-window-but.gif" border="0" alt="" /></a><%
}

function makeNewWindowLink( $url ) {
%><a target="_blank" href="<%= $url %>"><img src="img/new-window-but.gif" border="0" alt=""/></a><%
}

function printLinkCount( $argCount ) {
	$a = $argCount < 10   ? "&#160;" : "";
	$b = $argCount < 100  ? "&#160;" : "";
	$c = $argCount < 1000 ? "&#160;" : "";
	return "<code>" . $a . $b . $c . $argCount . "</code>";
}

function makeSafeName( $argName ) {
	#return str_replace( "_PLUS_", "+", urldecode( str_replace( "%26", "%26 ", $argName )));
	return str_replace( "_PLUS_", "+", urldecode( $argName ));
}

function isPublicFolder( $argFolderId ) {
	if( $argFolderId ) {
		$con = mysql_connect();
		mysql_selectdb( getDBName() );
		$qs = "SELECT name FROM linksGroups WHERE id = $argFolderId;";
		if( $debug )
			echo $qs . "<br/>";
		$q = mysql_query( $qs );
		if( $q ) {
			$numRows = mysql_num_rows($q);
			if( ! $numRows ) {
				echo "ERROR: folder id $argFolderId not found";
				return false;
			} else {
				return isPublic( mysql_result($q,0,"name"));
			}
			conClose( $con );
		}
	}
}

function isPublic( $folderName ) {
	if( $folderName )
		if( substr( $folderName, 0, 2 ) == "p/" || substr( $folderName, 0, 4 ) == "p%2F" )
			return true;
	return false;
}

# these next two cleaned up and converted to php from
# original javascript code by tim williams script

function dec2hex( $argDec ) {
	$hexChars = "0123456789ABCDEF";
	$a = ord( $argDec ) % 16;
	$b = (ord($argDec) - $a)/16;
	return ("" . $hexChars[$b] . $hexChars[$a] );
}

function encodeAddress( $argAddr, $argText ) {
		$txt = "";
		$argText = $argText ? $argText : $argAddr;
		for ($i=0; $i<strlen($argAddr); $i++) {
			if( $debug ) echo "$i ";
			if( $debug ) echo $argAddr[$i] . "\n";
			if( $debug ) echo dec2hex($argAddr[$i]) . "\n";
			$txt = $txt . "%" . dec2hex($argAddr[$i] );
		}
		$txt = "<a href=\"mailto:" . $txt . "\">" . $argText . "</a>";
		return $txt;
	}

function formatAsDCDate( $ts ) {
	$ts = (!$ts) ? "20020503154400" : $ts;
	# format the stamp
	# sample: 20011002231722
	#         YYYYMMDDHHMMSS
	#         01234567890123
	# goal:  YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00)

	$date = substr( $ts, 4, 2 ) . "/" . substr( $ts, 6, 2 ) .  "/" . substr( $ts, 0, 4 );
	$rawdate = $date;
	$time = substr( $ts, 8, 2 ) . ":" . substr( $ts, 10, 2 ) . ":" .  substr( $ts, 12, 2 ) ;
	$date = date( "Y-m-d", strtotime( $date . " " . $time )) 
		. "T"
		. $date = date( "H:iO", strtotime( $date . " " . $time ));
	return preg_replace( "/00$/", ":00", $date );
}

function getDBDateFormat() {
	return "YmdHis";
}

function getDefaultDisplayDateFormat() {
	return "F j, Y";
}

function formatTS( $ts ) {
	# set any NULL dates to the FML epoch, thusly:
	$ts = (!$ts) ? "2002-05-03 15:44:00" : $ts;

	# SAMPLE: 2002-07-22 14:58:39

	if(strstr( $ts, "-")) {
		$d = strtotime($ts);
	} else {
		# UNHOLY MESS of date-formatting crap required for coping 
		# with the weird flavor of mysql/php on my dev box...
		$d = substr( $ts, 4, 2 ) . "/" . substr( $ts, 6, 2 ) .  "/" . substr( $ts, 0, 4 );
		$time = substr( $ts, 8, 2 ) . ":" . substr( $ts, 10, 2 ) . ":" .  substr( $ts, 12, 2 ) ;
		$d = strtotime( $d . " " . $time );
	}
	
	# in the event that dates become somehow corrupted or otherwise mangled,
	# dont allow them to slip further than the FML born-on date:
	if( date( "Y", $d ) <  2002 )
		$d = strtotime( "2002-05-03 15:44:00" );

	if( date( "Ymd", $d ) == date( "Ymd" ))
		return "today";
	else if( date( "Ymd", $d ) == date( "Ymd", strtotime("now") - (1 * 24 * 60 * 60)))
		return "yesterday";
	else if( date( "Y", $d ) == date( "Y" ))
		return date( "F j", $d );
	else
		return date( getDefaultDisplayDateFormat(), $d );
}

function prepURLforSubmit( $url ) {
		$tmpurl = $url;
		#if( !ereg( "^http://", $tmpurl) && !ereg( "^https://", $tmpurl) && !ereg( "^ftp://", $tmpurl) && !ereg( "^file://", $tmpurl)) {
			#if( !ereg( "^www.", $tmpurl)) {
				#echo "no http or www, adding http://www.";
				#$tmpurl = "http://www.$tmpurl";
			#} else {
				#echo "no http found, adding http://";
				#$tmpurl = "http://$tmpurl";
			#}
		#}

		return urlencode( $tmpurl );
	}

function prepForDB( $s ) {
	$s = preg_replace( ":\\\':", "'", $s );
	$s = preg_replace( ':\\\":', '"', $s );
	#$s = preg_replace( ":\\\':", "__SQ__", $s );
	#$s = preg_replace( ':\\\":', "__DQ__", $s );
	$s = urlencode( $s );
	#$s = preg_replace( ':__DQ__:', '"', $s );
	#$s = preg_replace( ':__SQ__:', "'", $s );
	return ( $s ); 
}

function hsc( $s ) {
	return htmlspecialchars( $s );
}

function canonicalizeUrl( $url ) {
		$canonicalUrl = "http://www.$url";
		$debug = 0;
		if( ! preg_match( "/www\.jm3\.net/", $url )) {
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script language="javascript">
  location.replace( '<%= $canonicalUrl %>' );
</script>
<% if( $debug ) { %>
<br />
utils.inc.php: canonicalUrl = <b><%= $canonicalUrl %></b>(end utils output)<br />
<% } %>
<noscript>
  feedmelinks.com requires javascript to login and add links, sorry.
</noscript>
</head>
<body></body>
</html>
<%
		}
	}


	include_once( "env.inc.php" );

	$env = getFmlEnv();

	function get_root() {
		include_once( "env.inc.php" );
		$env = getFmlEnv();
		if( $env == "dev" )
			$root = "/home/jm3/www";
		else if( $env == "powerbook" )
			$root = "/Users/erdnase/www/feedmelinks.com";
		else
			$root = "/usr/home/hirokai/feedmelinks.com";
		return $root;
	}

	function get_cookie_domain() {
		global $env;
		if( $env == "powerbook" )
			return "";
		else
			return ".feedmelinks.com";
	}

	# so glad that this function exists...
	function get_lynx() {
		global $env;
		if( $env == "powerbook" )
			return "/sw/bin/lynx";
		else
			return "/usr/local/bin/lynx";
	}

	if( $env == "live" )
		$bin = "/usr/home/hirokai/feedmelinks.com/bin";
	else if( $env == "dev" )
		$bin = get_root() . "/bin";
	else if( $env == "powerbook" )
		$bin = get_root() . "/bin";
	else
		$bin = "/usr/home/hirokai/fml/bin"; # WOW, this was wrong.

	if( $env == "dev" )
		$modules = "/home/virtual/site30/fst/var/www/html/modules";
	else if( $env == "powerbook" )
		$modules = get_root() . "/modules";
	else
		$modules = "/usr/home/hirokai/feedmelinks.com/modules";

	if( $env == "dev" )
		$site = $global_site_url = "http://dev.feedmelinks.com";
	else if( $env == "powerbook" )
		$site = $global_site_url = "http://localhost:8080";
	else
		$site = $global_site_url = "http://feedmelinks.com";

	# accessible so that any page can build links otf (note that QS is removed)
	$page = $QUERY_STRING ? str_replace( "$QUERY_STRING", "", $REQUEST_URI ) : $REQUEST_URI;

	# TODO - NOT USED YET
	if( $env == "dev" )
		$global_db_path = "dev_feedmelinks_com_-_dev";
	else
		$global_db_path = "hirokai_jm3DataMart";

	$hr = "class=\"linkable\" href=";
	$pers_auth = 0;
%>
Return current item: FeedMeLinks, Social BookmarkingSince2002