<?php
/* Function declaration used by all pages.
*
* Written by: Chris Studholme
* Copyright: GPL (http://www.fsf.org/copyleft/gpl.html)
* $Id: functions.php,v 1.44 2004/01/29 05:26:02 cstudhol Exp $
*/
/**** links and hidden form fields ****/
/* Create a URL with GET type parameters and possibly a target anchor.
* The first argument is the base url.
* If there are several sets of parameters, they are merged using array_merge()
* from left to right (ie. the parameters on the right have higher precidence).
* If the second argument is a string, it is considered a GET parameter string
* (this is for backwards compatibility and is not recommended).
* If the last argument (>=3) is a string, it is a target anchor.
*/
function vpa_link($url/*,$param1,$param2,...,$target*/) {
global $default_lang, $lang;
global $default_typeid, $typeid;
global $admin;
$numargs = func_num_args();
//$url = $numargs>=1 ? func_get_arg(0) : "";
$parameters=array();
if ($typeid>0&&$typeid!=$default_typeid)
$parameters["typeid"] = $typeid;
if ($admin)
$parameters["admin"] = 1;
if ($lang!=$default_lang)
$parameters["lang"] = $lang;
for ($i=1; $i<$numargs; ++$i) {
$arg = func_get_arg($i);
if (is_array($arg))
$parameters = array_merge($parameters,$arg);
}
$parms="";
reset($parameters);
while (list($key,$value)=each($parameters))
if ($value||(is_string($value)&&strlen($value)))
$parms .= ($parms?"&":"").$key."=".$value;
// for backwards compatibility
if ($numargs>=2) {
$arg = func_get_arg(1);
if (is_string($arg)&&strlen($arg))
$parms .= ($parms?"&":"").$arg;
}
if ($parms)
$url .= "?".$parms;
$target = $numargs>=3 ? func_get_arg($numargs-1) : false;
if (is_string($target)&&strlen($target)>0)
$url .= "#".$target;
return $url;
}
/* Create hidden form inputs for the supplied parameters.
* If multiple sets of parameters are supplied, they are merged using
* array_merge() from left to right (ie. parameters on the right have higher
* precidence)
*/
function vpa_hidden(/*$params1, $params2, ...*/) {
global $default_lang, $lang;
global $default_typeid, $typeid;
global $admin;
$parameters=array();
if ($typeid>0&&$typeid!=$default_typeid)
$parameters["typeid"] = $typeid;
if ($admin)
$parameters["admin"] = 1;
if ($lang!=$default_lang)
$parameters["lang"] = $lang;
$numargs = func_num_args();
for ($i=0; $i<$numargs; ++$i) {
$arg = func_get_arg($i);
if (is_array($arg))
$parameters = array_merge($parameters,$arg);
}
$result="";
reset($parameters);
while (list($key,$value)=each($parameters))
if ($value||(is_string($value)&&strlen($value)))
$result .= stag("input",array("type"=>"hidden",
"name"=>$key,"value"=>$value));
return $result;
}
/**** page header and body ****/
/* Start writing out the HTML head section with title and stylesheet.
* $title is an optional override of the default title
* $windowname is an optional name to assign the window
*/
function start_head($title=false,$windowname=false) {
global $config, $path_styles;
$strings = get_strings();
echo "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n";
//echo "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n";
if (!$title)
$title = $strings["title_head"];
if (!$title)
$title = $strings["title_base"];
else if (!ereg("[-]",$title))
$title = $title." - ".$strings["title_base"];
echo btag("html").btag("head").tag("title",$title)."\n";
if ($config["default_style"])
echo stag("link",array("rel"=>"StyleSheet",
"type"=>"text/css",
"href"=>$path_styles."/".$config["default_style"]));
//echo stag("link",array("rel"=>"SHORTCUT ICON","href"=>"images/favicon.png"));
// break out of frames
echo tag("script","if (self!=top) { top.location.href=self.location.href; }")."\n";
// break out of popup (but we might want to be in a popup!)
//echo tag("script","if (window.opener) { window.open(self.location); window.close(); }")."\n";
if ($windowname)
echo tag("script","window.name=\"".$windowname."\";")."\n";
// for use by fatal_error()
global $HEAD_STARTED,$BODY_STARTED;
$HEAD_STARTED=true;
$BODY_STARTED=false;
}
// make html for drop down list of image types
function html_change_image_type($allowed_types,$selected_type) {
global $HTTP_GET_VARS;
$strings = get_strings();
$image_types = get_image_types();
$var = "typeid";
$url = ereg_replace("[?].*$","",getenv("REQUEST_URI"));
$result = btag("form",array("action"=>$url,"method"=>"GET"));
$result .= vpa_hidden($HTTP_GET_VARS,array($var=>false));
$result .= btag("select",array("name"=>$var,
"onChange"=>"this.form.submit();"))."\n";
/*
if ($search) {
$result .= tag("option",array("value"=>""),
$strings["pictures_all"])."\n";
}
*/
reset($image_types);
while(list($typeid,$record)=each($image_types))
if (($typeid>0)&&($allowed_types&(1<<($typeid-1))))
$result .= tag("option",array("value"=>$typeid,
"selected"=>($typeid==$selected_type)),
best_lang($record["name"]))."\n";
$result .= etag("select").etag("form")."\n";
return $result;
}
// finish the html head section and start a body section
function end_head_start_body($popup=false,$show_followed=false) {
global $admin, $admin_allow, $admin_allow_read_only;
global $supported_lang, $lang;
global $HTTP_GET_VARS;
$strings = get_strings();
echo etag("head").btag("body")."\n";
if (!$popup) {
echo btag("table",array("border"=>0,"width"=>"99%",
"style"=>"margin: 0px; padding: 0px;",
"cellspacing"=>"0","cellpadding"=>"0"));
echo btag("tr");
echo tag("td",tag("h1",array("style"=>"margin: 0px; padding: 0px;"),
$strings["title_base"]))."\n";
$url = ereg_replace("[?].*$","",getenv("REQUEST_URI"));
if (count($supported_lang)>1) {
echo btag("td",array("align"=>"right"));
echo btag("form",array("action"=>$url,"method"=>"GET"))."\n";
echo vpa_hidden($HTTP_GET_VARS,array("lang"=>false));
echo btag("select",array("name"=>"lang",
"onChange"=>"this.form.submit();"))."\n";
reset($supported_lang);
while(list($key,$val)=each($supported_lang))
echo tag("option",array("value"=>$key,
"selected"=>($lang==$key)),
$val)."\n";
echo etag("select").etag("form").etag("td")."\n";
}
echo etag("tr").etag("table")."\n".stag("hr")."\n";
// should we use a list of get parameters below?
// $page is supplied without the ".php"
function header_button($page) {
global $strings;
return tag("a",array("href"=>vpa_link($page.".php")),
$strings["title"][$page]["head"]);
}
// display standard header
echo btag("table",array("border"=>0,"width"=>"99%")).btag("tr");
echo btag("td",array("style"=>"width: 100%"))."\n";
echo header_button("about")."\n";
echo "| ".header_button("toc")."\n";
echo "| ".header_button("search")."\n";
echo "| ".header_button("prefs")."\n";
echo "| ".header_button("survey")."\n";
echo "| ".header_button("faq")."\n";
echo etag("td");
// and button to enter admin mode if allowed
if (!$admin&&$admin_allow_read_only) {
$url = ereg_replace("[?].*$","",getenv("REQUEST_URI"));
echo tag("td",array("align"=>"right"),
tag("a",array("href"=>vpa_link($url,$HTTP_GET_VARS,
array("admin"=>"1"))),
$strings["nav_admin_enable"]))."\n";
}
echo etag("tr").etag("table")."\n".stag("hr")."\n";
if ($admin) {
// display special admin menu
echo btag("table",array("border"=>0,"width"=>"99%")).btag("tr");
echo btag("td",array("style"=>"width: 100%"))."Admin:\n";
echo header_button("admin_users")."\n";
echo "| ".header_button("admin_persons")."\n";
echo "| ".header_button("admin_keywords")."\n";
echo "| ".header_button("admin_types")."\n";
echo "| ".header_button("admin_stats")."\n";
echo "| ".header_button("admin_config")."\n";
echo etag("td");
// and button to get out of admin mode
$url = ereg_replace("[?].*$","",getenv("REQUEST_URI"));
echo tag("td",array("align"=>"right"),
tag("a",array("href"=>vpa_link($url,$HTTP_GET_VARS,
array("admin"=>false))),
tag("nobr",$strings["nav_admin_disable"])));
echo etag("tr").etag("table")."\n".stag("hr")."\n";
}
}
// for use by fatal_error()
global $BODY_STARTED;
$BODY_STARTED=true;
}
// end the body section
// if DEBUG_LEVEL>0 then output debugging info
function end_body($show_copyright=false) {
global $config, $conn;
global $DEBUG_LEVEL, $HTML_VERIFIER;
$strings = get_strings();
if ($show_copyright) {
echo tag("p"," ")."\n";
echo stag("hr");
echo tag("p",array("style"=>"font-size: smaller"),
tag("i",$strings["last_modified"].":").
" ".date("F j, Y",getlastmod()).
stag("br").
tag("i",$strings["content"].":")." © 2003 ".
tag("a",array("href"=>"mailto:".$config["copyright_email"]),
$config["copyright_name"]))."\n";
}
$endpage = etag("body").etag("html")."\n";
if ($DEBUG_LEVEL>0) {
// disable debugging to prevent loops
$DEBUG_LEVEL=0;
$verifier = $HTML_VERIFIER;
$HTML_VERIFIER=false;
echo stag("hr");
echo tag("h3",$strings["debug_info"].":")."\n";
if ($verifier)
$verifier->report();
if ($conn) {
$queries = $conn->get_queries();
if ($queries) {
echo $strings["queries"].":".stag("br").btag("ol")."\n";
reset($queries);
while (list($id,$query)=each($queries)) {
$style = $query["time"]>1 ? "color: darkred" : false;
$time = $query["time"]>=0.01 ?
" ".tag("i","(".round($query["time"],2)." seconds)") : "";
echo tag("li",array("style"=>$style),
$query["query"].$time)."\n";
}
echo etag("ol");
}
}
echo stag("hr");
}
echo $endpage;
}
// display an error message
function format_error($error,$reason="") {
global $HEAD_STARTED,$BODY_STARTED;
global $config;
$strings = get_strings();
// make sure we have the appropriate page structure
if (!$BODY_STARTED) {
if (!$HEAD_STARTED)
start_head();
end_head_start_body(true);
}
echo tag("h2",$error."!");
if ($reason) {
if (!ereg("[.!?]$",$reason))
$reason.=".";
echo tag("p",$reason);
}
echo tag("p",
sprintf($strings["error_message"],
antispam_link("mailto:".$config["siteadmin_email"],
$config["siteadmin_name"])))."\n";
}
/* display error message and terminate
* this method will do start_head() and end_head_start_body() if necessary
* before terminating, end_body() is called
*/
function fatal_error($err_type,$close_button=false) {
$strings = get_strings();
if ($strings["err_".$err_type]) {
format_error($strings["err_".$err_type],
$strings["err_".$err_type."_long"]);
}
else {
format_error("Error message not found"); //STRING
}
if ($close_button)
dialog_close_button();
end_body(false);
exit();
}
/* Figure out the path to a photo given the path to the thumbnail.
*/
function photo_path_from_thumb($typeid,$path_thumb) {
$image_types = get_image_types();
$typeid = (int)$typeid;
if ($typeid<=0 || !$image_types[$typeid])
return false;
if (ereg("^(.*)/([^/]*)$",$path_thumb,$regs)) {
$dir = $regs[1];
$file = $regs[2];
}
else {
$dir = false;
$file = $path_thumb;
}
if (ereg("^".$image_types[-1]["filename_prefix"]."(.*)".
$image_types[-1]["filename_suffix"]."$",$file,$regs)) {
$file = $image_types[$typeid]["filename_prefix"].
$regs[1].$image_types[$typeid]["filename_suffix"];
}
else
return false;
return $dir ? $dir."/".$file : $file;
}
/* Compute signature for photo.
*/
function photo_sig($path) {
global $album_secret_key;
if (!$album_secret_key)
fatal_error("bad_parameter");
return substr(md5($path."/".$album_secret_key),0,16);
}
/* Returns url to photo of particular type.
*/
function photo_url($pic_record,$typeid) {
global $path_pictures;
if ($typeid==-1) {
$sig = photo_sig($path_pictures."/".$pic_record["path_thumb"]);
return "photo.php/".$sig."/".$pic_record["path_thumb"];
}
if ($typeid>0) {
$path_photos = $pic_record["path_photos"] ?
unserialize($pic_record["path_photos"]) : array();
if (!$path_photos[$typeid])
$path_photos[$typeid] =
photo_path_from_thumb($typeid,$pic_record["path_thumb"]);
if ($path_photos[$typeid]) {
$sig = photo_sig($path_pictures."/".$path_photos[$typeid]);
return "photo.php/".$sig."/".$path_photos[$typeid];
}
return false; // WHY?
}
fatal_error("bad_parameter");
}
/* Returns size structure (same as GetImageSize()) for photo of specified type.
*/
function photo_size($pic_record,$typeid) {
global $path_pictures;
if ($typeid==-1)
return GetImageSize($path_pictures."/".$pic_record["path_thumb"]);
if ($typeid>0) {
$path_photos = $pic_record["path_photos"] ?
unserialize($pic_record["path_photos"]) : array();
if (!$path_photos[$typeid])
$path_photos[$typeid] =
photo_path_from_thumb($typeid,$pic_record["path_thumb"]);
if (!$path_photos[$typeid])
return false;
return GetImageSize($path_pictures."/".$path_photos[$typeid]);
}
fatal_error("bad_parameter");
}
/* This function is similar to the php function strtotime() (and it makes
* use of strtotime()), but it returns false in the case of failure and
* it understands more date/time formats than strtotime() does.
* If the string is successfully parsed, a UNIX timestamp (an integer) is
* returned. Note that negative timestamps represent dates before 1970.
*/
function vpa_strtotime($date) {
$date = strval($date);
if (!$date)
return false;
// ISO date only
if (ereg("^([12][0-9][0-9][0-9])-([01][0-9])-([0-3][0-9])$",$date,$regs))
return mktime(0,0,0,$regs[2],$regs[3],$regs[1]);
// ISO date and time
if (ereg("^([12][0-9][0-9][0-9])-([01][0-9])-([0-3][0-9]) ([012][0-9]):([0-5][0-9]):([0-5][0-9])[-0-9+.]*$",$date,$regs))
return mktime($regs[4],$regs[5],$regs[6],$regs[2],$regs[3],$regs[1]);
// ISO date and time (with colons)
if (ereg("^([12][0-9][0-9][0-9]):([01][0-9]):([0-3][0-9]) ([012][0-9]):([0-5][0-9]):([0-5][0-9])[-0-9+.]*$",$date,$regs))
return mktime($regs[4],$regs[5],$regs[6],$regs[2],$regs[3],$regs[1]);
// US date only
if (ereg("^([01][0-9])-([0-3][0-9])-([12][0-9][0-9][0-9])$",$date,$regs))
return mktime(0,0,0,$regs[1],$regs[2],$regs[3]);
// US date and time
if (ereg("^[SMTWF][uoehra][neduit] ([JFMASOND][aeucop][nypbtrlvgc]) ([0-3][0-9]) ([012][0-9]):([0-5][0-9]):([0-5][0-9]) ([12][0-9][0-9][0-9]) [A-Z][A-Z][A-Z]$",$date,$regs)) {
$months = array("Jan"=>1, "Feb"=>2, "Mar"=>3, "Apr"=>4,
"May"=>5, "Jun"=>6, "Jul"=>7, "Aug"=>8,
"Sep"=>9, "Oct"=>10, "Nov"=>11, "Dec"=>12);
return mktime($regs[3],$regs[4],$regs[5],$months[$regs[1]],$regs[2],$regs[6]);
}
$result = (int)strtotime($date);
return $result>0||$result<-2 ? $result : false;
}
// display a button to close the current page
function dialog_close_button($text=false) {
$strings = get_strings();
if (!$text)
$text = $strings["close"];
echo tag("form",array("style"=>"text-align: center"),
stag("input",array("type"=>"button",
"value"=>$text,
"onClick"=>"window.close()")));
}
// return concise discription of the date range
function date_range_to_string($start,$end) {
$strings = get_strings();
// dates are the same
if ($start==$end||!$end)
return date("F j, Y",$start);
// years are different
if (date("Y",$start)!=date("Y",$end))
return sprintf($strings["range"],
date("F j, Y",$start),date("F j, Y",$end));
// months are different
if (date("m",$start)!=date("m",$end))
return sprintf($strings["range"],
date("F j",$start),date("F j, Y",$end));
// only day is different
return sprintf($strings["range"],
date("F j",$start),date("j, Y",$end));
}
// create a new cookie and output it to the browser
function create_cookie_and_set($seed) {
global $cookie_expire;
$hash = md5($seed.microtime());
mt_srand(hexdec(substr($hash,0,8))^hexdec(substr($hash,8,8))^
hexdec(substr($hash,16,8))^hexdec(substr($hash,24,8)));
// create new cookie
$AlbumCookie="";
for ($i=0; $i<32; ++$i) {
$r = mt_rand(0,61);
if ($r<26)
$AlbumCookie .= chr(65+$r);
else if ($r<52)
$AlbumCookie .= chr(71+$r);
else
$AlbumCookie .= chr($r-4);
}
SetCookie("AlbumCookie",$AlbumCookie,time()+$cookie_expire);
return $AlbumCookie;
}
/* Something happened on sourceforge.net to break normal exec() behaviour,
* this was needed to fix it.
*/
function vpa_exec($command) {
$result=array();
exec($command,$result);
return $result[0];
}
// returns true if the password matches the supplied hash
function password_check($password,$hash) {
$salt=substr($hash,0,8);
return ($hash==$salt.md5($salt.$password));
}
// hash the supplied password
// $username is for extra entropy in the salt
function password_hash($password,$username=false) {
$salt = substr(md5(microtime().getenv("REMOTE_ADDR").
$username.$password),0,8);
return $salt.md5($salt.$password);
}
// convert CSV list (a string) to an array of positive integers
function CSV2array_int($CSV,$append=array()) {
while (ereg("^([^,]*),(.*)$",$CSV,$regs)) {
if (($v=(int)$regs[1])>0)
$append[] = $v;
$CSV=$regs[2];
}
if (($v=(int)$CSV)>0)
$append[] = $v;
return $append;
}
// convert an array of positive integers to a CSV list (a string)
function array2CSV_int($array) {
if (count($array)<1)
return "";
$result = false;
for ($i=0; $i<count($array); ++$i) {
if (($v=(int)$array[$i])>0)
$result .= ($result?",":"").$v;
else if ($v==-1)
return "";
}
return $result;
}
// convert CSV list (a string) to an array of (non-empty) strings
function CSV2array($CSV,$append=false) {
$result = is_array($append) ? $append : array();
while (ereg("^([^,]*),(.*)$",$CSV,$regs)) {
if (strlen($regs[1])>0)
$result[] = $regs[1];
$CSV=$regs[2];
}
if (strlen($CSV)>0)
$result[] = $CSV;
return $result;
}
// convert an array to a CSV list (a string)
function array2CSV($array) {
if (count($array)<1)
return "";
reset($array);
list($index,$value)=each($array);
$result = strval($value);
while (list($index,$value)=each($array))
$result .= ",".strval($value);
return $result;
}
/* Return new string as $string with following substitutions:
* - \# is replaced by "#"
* - #somevar is replaced by $sub_funct($somevar)
* - {#somevar} is replaced by $sub_funct($somevar)
* somevar must be of the form [a-zA-Z][a-zA-Z0-9_]*
*/
function strsubst($string,$sub_funct) {
$newstring="";
while (ereg("^([^#]*)([#].*)$",$string,$regs)) {
$first=$regs[1];
$last=$regs[2];
// check if we really have a variable to substitute
$key=false;
if (ereg("[\]$",$first)) {
$newstring.=substr($first,0,strlen($first)-1)."#";
$string = substr($last,1);
}
else if (ereg("[\][{]$",$first)) {
$newstring.=substr($first,0,strlen($first)-2)."{";
if (ereg("^[#]([a-zA-Z][a-zA-Z0-9_]*)(.*)$",$last,$r)) {
$key=$r[1];
$string=$r[2];
}
else {
$newstring.="$";
$string=substr($last,1);
}
}
else if (ereg("[{]$",$first)) {
$newstring.=substr($first,0,strlen($first)-1);
if (ereg("^[#]([a-zA-Z][a-zA-Z0-9_]*)[}](.*)$",$last,$r)) {
$key=$r[1];
$string=$r[2];
}
else if (ereg("^[#]([a-zA-Z][a-zA-Z0-9_]*)(.*)$",$last,$r)) {
$newstring.="{";
$key=$r[1];
$string=$r[2];
}
else {
$newstring.="$";
$string=substr($last,1);
}
}
else {
$newstring.=$first;
if (ereg("^[#]([a-zA-Z][a-zA-Z0-9_]*)(.*)$",$last,$r)) {
$key=$r[1];
$string=$r[2];
}
else {
$newstring.="$";
$string=substr($last,1);
}
}
// get replacement
if ($key)
$newstring .= $sub_funct($key);
}
return $newstring.$string;
}
/* Find best place to insert an element. $arr is an ordered associative
* array of elements <0, 0, and >0. The return value is the key of the
* array element _after_ which the new element should be inserted. A
* return value of false indicates that the insert should be made at the
* beginning of the array. An array of size 0 or 1 will always result in
* a return of false.
*/
function best_insert($arr) {
if (count($arr)<2)
return false;
// first, count up's and down's
$total_up=0;
$total_down=0;
reset($arr);
while (list($key,$val)=each($arr)) {
if ($val<0)
++$total_down;
else if ($val>0)
++$total_up;
}
// find best for each possible ordering (all two of them)
$best_val=$total_up>$total_down?$total_up:$total_down;
$best_key=false;
$up=0;
$down=0;
reset($arr);
while (list($key,$val)=each($arr)) {
if ($val<0)
++$down;
else if ($val>0)
++$up;
if ($up+$total_down-$down>$best_val) {
$best_val=$up+$total_down-$down;
$best_key=$key;
}
if ($down+$total_up-$up>$best_val) {
$best_val=$down+$total_up-$up;
$best_key=$key;
}
}
return $best_key;
}
?>