cfg = new PHPFSPOT_CFG;
/* verify config settings */
if($this->check_config_options()) {
exit(1);
}
/* set application name and version information */
$this->cfg->product = "phpfspot";
$this->cfg->version = "1.7";
$this->cfg->db_version = 2;
$this->sort_orders= array(
'date_asc' => 'Date ↑',
'date_desc' => 'Date ↓',
'name_asc' => 'Name ↑',
'name_desc' => 'Name ↓',
'tags_asc' => 'Tags ↑',
'tags_desc' => 'Tags ↓',
);
/* Check necessary requirements */
if(!$this->check_requirements()) {
exit(1);
}
/******* Opening F-Spot's sqlite database *********/
/* Check if database file exists and is readable */
if(!file_exists($this->cfg->fspot_db) || !is_readable($this->cfg->fspot_db)) {
print "Error: ". $this->cfg->fspot_db ." does not exist or is not readable for user ". $this->getuid() .".\n";
exit(1);
}
/* Check if database file is writeable */
if(!is_writeable($this->cfg->fspot_db)) {
print "Error: ". $this->cfg->fspot_db ." is not writeable for user ". $this->getuid() .".\n";
print "Please fix permissions so phpfspot can create indices within the F-Spot database to"
." speed up some database operations.\n";
exit(1);
}
/* open the database */
$this->db = new PHPFSPOT_DB($this, $this->cfg->fspot_db);
/* change sqlite temp directory, if requested */
if(isset($this->cfg->sqlite_temp_dir)) {
$this->db->db_exec("
PRAGMA
temp_store_directory = '". $this->cfg->sqlite_temp_dir ."'
");
}
/* get F-Spot database version */
$this->dbver = $this->getFspotDBVersion();
if(!is_writeable($this->cfg->base_path ."/templates_c")) {
print $this->cfg->base_path ."/templates_c: directory is not writeable for user ". $this->getuid() ."\n";
exit(1);
}
if(!is_writeable($this->cfg->thumb_path)) {
print $this->cfg->thumb_path .": directory is not writeable for user ". $this->getuid() ."\n";
exit(1);
}
/******* Opening phpfspot's sqlite database *********/
/* Check if directory where the database file is stored is writeable */
if(!is_writeable(dirname($this->cfg->phpfspot_db))) {
print "Error: ". dirname($this->cfg->phpfspot_db) .": directory is not writeable for user ". $this->getuid() .".\n";
print "Please fix permissions so phpfspot can create its own sqlite database to store some settings.\n";
exit(1);
}
/* Check if database file is writeable */
if(file_exists($this->cfg->phpfspot_db) && !is_writeable($this->cfg->phpfspot_db)) {
print "Error: ". $this->cfg->phpfspot_db ." is not writeable for user ". $this->getuid() .".\n";
print "Please fix permissions so phpfspot can create its own sqlite database to store some settings.\n";
exit(1);
}
/* open the database */
$this->cfg_db = new PHPFSPOT_DB($this, $this->cfg->phpfspot_db);
/* change sqlite temp directory, if requested */
if(isset($this->cfg->sqlite_temp_dir)) {
$this->cfg_db->db_exec("
PRAGMA
temp_store_directory = '". $this->cfg->sqlite_temp_dir ."'
");
}
/* Check if some tables need to be created */
$this->check_phpfspot_db();
/* overload Smarty class with our own template handler */
require_once "phpfspot_tmpl.php";
$this->tmpl = new PHPFSPOT_TMPL();
/* pre-set some template variables */
$this->tmpl->assign('web_path', $this->cfg->web_path);
/* Starting with F-Spot 0.4.2, the rating-feature was available */
if($this->dbver > 10) {
$this->tmpl->assign('has_rating', true);
$this->sort_orders = array_merge($this->sort_orders, array(
'rate_asc' => 'Rate ↑',
'rate_desc' => 'Rate ↓',
));
}
/* check if all necessary indices exist */
$this->checkDbIndices();
/* if session is not yet started, do it now */
if(session_id() == "")
session_start();
if(!isset($_SESSION['tag_condition']))
$_SESSION['tag_condition'] = 'or';
/* if sort-order has not been set yet, get the one specified in the config */
if(!isset($_SESSION['sort_order']))
$_SESSION['sort_order'] = $this->cfg->sort_order;
if(!isset($_SESSION['searchfor_tag']))
$_SESSION['searchfor_tag'] = '';
// if begin_with is still set but thumbs_per_page is now 0, unset it
if(isset($_SESSION['begin_with']) && $this->cfg->thumbs_per_page == 0)
unset($_SESSION['begin_with']);
// if user-friendly-url's are enabled, set also a flag for the template handler
if($this->is_user_friendly_url()) {
$this->tmpl->assign('user_friendly_url', 'true');
}
} // __construct()
public function __destruct()
{
} // __destruct()
/**
* show - generate html output
*
* this function can be called after the constructor has
* prepared everyhing. it will load the index.tpl smarty
* template. if necessary it will registere pre-selects
* (photo index, photo, tag search, date search) into
* users session.
*/
public function show()
{
$this->tmpl->assign('searchfor_tag', $_SESSION['searchfor_tag']);
$this->tmpl->assign('page_title', $this->cfg->page_title);
$this->tmpl->assign('current_condition', $_SESSION['tag_condition']);
$this->tmpl->assign('template_path', 'themes/'. $this->cfg->theme_name);
/* parse URL */
if($this->is_user_friendly_url()) {
$content = $this->parse_user_friendly_url($_SERVER['REQUEST_URI']);
}
if(isset($_GET['mode'])) {
$_SESSION['start_action'] = $_GET['mode'];
switch($_GET['mode']) {
case 'showpi':
if(isset($_GET['tags'])) {
$_SESSION['selected_tags'] = $this->extractTags($_GET['tags']);
}
if(isset($_GET['from_date']) && $this->isValidDate($_GET['from_date'])) {
$_SESSION['from_date'] = strtotime($_GET['from_date'] ." 00:00:00");
}
if(isset($_GET['to_date']) && $this->isValidDate($_GET['to_date'])) {
$_SESSION['to_date'] = strtotime($_GET['to_date'] ." 23:59:59");
}
break;
case 'showp':
if(isset($_GET['tags'])) {
$_SESSION['selected_tags'] = $this->extractTags($_GET['tags']);
$_SESSION['start_action'] = 'showp';
}
if(isset($_GET['id']) && is_numeric($_GET['id'])) {
if($_SESSION['current_photo'] != $_GET['id'])
unset($_SESSION['current_version']);
$_SESSION['current_photo'] = $_GET['id'];
$_SESSION['start_action'] = 'showp';
}
if(isset($_GET['from_date']) && $this->isValidDate($_GET['from_date'])) {
$_SESSION['from_date'] = strtotime($_GET['from_date'] ." 00:00:00");
}
if(isset($_GET['to_date']) && $this->isValidDate($_GET['to_date'])) {
$_SESSION['to_date'] = strtotime($_GET['to_date'] ." 23:59:59");
}
break;
case 'export':
/* fetch export template */
print $this->tmpl->fetch("export.tpl");
/* no further execution necessary. */
return;
break;
case 'slideshow':
/* fetch slideshow template */
print $this->tmpl->show("slideshow.tpl");
/* no further execution necessary. */
return;
break;
case 'rss':
if(isset($_GET['tags'])) {
$_SESSION['selected_tags'] = $this->extractTags($_GET['tags']);
}
if(isset($_GET['from_date']) && $this->isValidDate($_GET['from_date'])) {
$_SESSION['from_date'] = strtotime($_GET['from_date'] ." 00:00:00");
}
if(isset($_GET['to_date']) && $this->isValidDate($_GET['to_date'])) {
$_SESSION['to_date'] = strtotime($_GET['to_date'] ." 23:59:59");
}
$this->getRSSFeed();
return;
break;
}
}
/* if date-search variables are registered in the session, set the check
for "consider date-range" in the html output
*/
if(isset($_SESSION['from_date']) && isset($_SESSION['to_date']))
$this->tmpl->assign('date_search_enabled', true);
/* if rate-search variables are registered in the session, set the check
for "consider rate-range" in the html output
*/
if(isset($_SESSION['rate_from']) && isset($_SESSION['rate_to'])) {
$this->tmpl->assign('rate_search_enabled', true);
}
$this->tmpl->register_function("sort_select_list", array(&$this, "smarty_sort_select_list"), false);
$this->tmpl->assign('search_from_date', $this->get_date_text_field('from'));
$this->tmpl->assign('search_to_date', $this->get_date_text_field('to'));
$this->tmpl->assign('preset_selected_tags', $this->getSelectedTags());
$this->tmpl->assign('preset_available_tags', $this->getAvailableTags());
$this->tmpl->assign('rate_search', $this->get_rate_search());
/* if no site-content has been set yet... */
if(!isset($content)) {
/* if tags are already selected, we can immediately display photo-index */
if((isset($_SESSION['selected_tags']) && !empty($_SESSION['selected_tags']) &&
isset($_SESSION['start_action']) && $_SESSION['start_action'] != 'showp') ||
(isset($_SESSION['start_action']) && $_SESSION['start_action'] == 'showpi'))
$this->tmpl->assign('initial_content', $this->showPhotoIndex());
else {
/* if a photo is already selected, we can immediately display single-photo */
if(isset($_SESSION['current_photo']) && !empty($_SESSION['current_photo']))
$this->tmpl->assign('initial_content', $this->showPhoto($_SESSION['current_photo']));
else {
/* ok, then let us show the welcome page... */
$this->tmpl->assign('initial_content', $this->tmpl->fetch('welcome.tpl'));
}
}
}
else
$this->tmpl->assign('initial_content', $content);
$this->tmpl->show("index.tpl");
} // show()
/**
* get_tags - grab all tags of f-spot's database
*
* this function will get all available tags from
* the f-spot database and store them within two
* arrays within this class for later usage. in
* fact, if the user requests (hide_tags) it will
* opt-out some of them.
*
* this function is getting called once by show()
*/
private function get_tags()
{
$this->avail_tags = Array();
$count = 0;
/* if show_tags has been set in the configuration (only show photos
which are tagged by these tags) they following will take care,
that only these other tags are displayed where the photo is also
tagged with one of show_tags.
*/
if(isset($this->cfg->show_tags) && !empty($this->cfg->show_tags)) {
$query_str="
SELECT
DISTINCT t1.id as id, t1.name as name
FROM
photo_tags pt1
INNER JOIN photo_tags
pt2 ON pt1.photo_id=pt2.photo_id
INNER JOIN tags t1
ON t1.id=pt1.tag_id
INNER JOIN tags t2
ON t2.id=pt2.tag_id
WHERE
t2.name IN ('".implode("','",$this->cfg->show_tags)."')
ORDER BY
t1.sort_priority ASC";
$result = $this->db->db_query($query_str);
}
else
{
$result = $this->db->db_query("
SELECT id as id,name as name
FROM tags
ORDER BY sort_priority ASC
");
}
while($row = $this->db->db_fetch_object($result)) {
$tag_id = $row['id'];
$tag_name = $row['name'];
/* if the user has specified to ignore this tag in phpfspot's
configuration, ignore it here so it does not get added to
the tag list.
*/
if(in_array($row['name'], $this->cfg->hide_tags))
continue;
/* if you include the following if-clause and the user has specified
to only show certain tags which are specified in phpfspot's
configuration, ignore all others so they will not be added to the
tag list.
if(isset($this->cfg->show_tags) && !empty($this->cfg->show_tags) &&
!in_array($row['name'], $this->cfg->show_tags))
continue;
*/
$this->tags[$tag_id] = $tag_name;
$this->avail_tags[$count] = $tag_id;
$count++;
}
} // get_tags()
/**
* get all photo details from F-Spot database
*
* this function queries the F-Spot database for all available
* details of the requested photo. It returns them as a object.
*
* Furthermore it takes care of the photo version to be requested.
* If photo version is not yet, it queries information for the
* original photo.
*
* @param integer $idx
* @return object|null
*/
public function get_photo_details($idx, $version_idx = NULL)
{
/* ~ F-Spot version 0.3.x */
if($this->dbver < 9) {
$query_str = "
SELECT
p.id as id,
p.name as name,
p.time as time,
p.directory_path as directory_path,
p.description as description
FROM
photos p
";
}
else {
/* till F-Spot version 0.4.1 */
if($this->dbver < 11) {
$query_str = "
SELECT
p.id as id,
p.uri as uri,
p.time as time,
p.description as description
FROM
photos p
";
}
else {
/* rating value got introduced */
$query_str = "
SELECT
p.id as id,
p.uri as uri,
p.time as time,
p.description as description,
p.rating as rating
FROM
photos p
";
}
}
/* if show_tags is set, only return details of photos which are
tagged with a tag that has been specified to be shown.
*/
if(isset($this->cfg->show_tags) && !empty($this->cfg->show_tags)) {
$query_str.= "
INNER JOIN photo_tags pt
ON p.id=pt.photo_id
INNER JOIN tags t
ON pt.tag_id=t.id
WHERE p.id='". $idx ."'
AND t.name IN ('".implode("','",$this->cfg->show_tags)."')";
}
else {
$query_str.= "
WHERE p.id='". $idx ."'
";
}
if($row = $this->db->db_fetchSingleRow($query_str)) {
/* before F-Spot db version 9 there was no uri column but
seperated fields for directory_path and name (= filename).
*/
if($this->dbver < 9) {
$row['uri'] = "file://". $row['directory_path'] ."/". $row['name'];
}
/* if version-idx has not yet been set, get the latest photo version */
if(!isset($version_idx) || !$this->is_valid_version($idx, $version_idx))
$version_idx = $this->get_latest_version($idx);
/* if an alternative version has been requested. But we
support this only for F-Spot database versions from
v9.
*/
if($version_idx > 0 && $this->dbver >= 9) {
/* check for alternative versions */
if($version = $this->db->db_fetchSingleRow("
SELECT
version_id, name, uri
FROM
photo_versions
WHERE
photo_id LIKE '". $idx ."'
AND
version_id LIKE '". $version_idx ."'")) {
$row['name'] = $version['name'];
$row['uri'] = $version['uri'];
}
}
return $row;
}
return null;
} // get_photo_details()
/**
* returns aligned photo names
*
* this function returns aligned (length) names for a specific photo.
* If the length of the name exceeds $limit the name will bei
* shrinked (...).
*
* @param integer $idx
* @param integer $limit
* @return string|null
*/
public function getPhotoName($idx, $limit = 0)
{
if($details = $this->get_photo_details($idx)) {
if($long_name = $this->parse_uri($details['uri'], 'filename')) {
$name = $this->shrink_text($long_name, $limit);
return $name;
}
}
return null;
} // getPhotoName()
/**
* get photo rating level
*
* this function will return the integer-based rating level of a
* photo. This can only be done, if the F-Spot database is at a
* specific version. If rating value can not be found, zero will
* be returned indicating no rating value is available.
*
* @param integer idx
* @return integer
*/
public function get_photo_rating($idx)
{
if($detail = $this->get_photo_details($idx)) {
if(isset($detail['rating']))
return $detail['rating'];
}
return 0;
} // get_photo_rating()
/**
* get rate-search bars
*
* this function will return the rating-bars for the search field.
*
* @return string
*/
public function get_rate_search()
{
$bar = "";
for($i = 1; $i <= 5; $i++) {
$bar.= "cfg->web_path ."/resources/star.png";
else
$bar.= $this->cfg->web_path ."/resources/empty_rate.png";
$bar.= "\"
onmouseover=\"show_rate('from', ". $i .");\"
onmouseout=\"reset_rate('from');\"
onclick=\"set_rate('from', ". $i .")\" />";
}
$bar.= " \n";
for($i = 1; $i <= 5; $i++) {
$bar.= "cfg->web_path ."/resources/star.png";
else
$bar.= $this->cfg->web_path ."/resources/empty_rate.png";
$bar.= "\"
onmouseover=\"show_rate('to', ". $i .");\"
onmouseout=\"reset_rate('to');\"
onclick=\"set_rate('to', ". $i .");\" />";
}
return $bar;
} // get_rate_search()
/**
* shrink text according provided limit
*
* If the length of the name exceeds $limit, text will be shortend
* and inner content will be replaced with "...".
*
* @param string $ext
* @param integer $limit
* @return string
*/
private function shrink_text($text, $limit)
{
if($limit != 0 && strlen($text) > $limit) {
$text = substr($text, 0, $limit-5) ."...". substr($text, -($limit-5));
}
return $text;
} // shrink_text();
/**
* translate f-spoth photo path
*
* as the full-qualified path recorded in the f-spot database
* is usally not the same as on the webserver, this function
* will replace the path with that one specified in the cfg
* @param string $path
* @return string
*/
public function translate_path($path)
{
if($this->cfg->enable_replace_path == true)
return str_replace(
$this->cfg->path_replace_from,
$this->cfg->path_replace_to, $path);
return $path;
} // translate_path
/**
* control HTML ouput for a single photo
*
* this function provides all the necessary information
* for the single photo template.
* @param integer photo
*/
public function showPhoto($photo)
{
/* get all photos from the current photo selection */
$all_photos = $this->getPhotoSelection();
$count = count($all_photos);
for($i = 0; $i < $count; $i++) {
// $get_next will be set, when the photo which has to
// be displayed has been found - this means that the
// next available is in fact the NEXT image (for the
// navigation icons)
if(isset($get_next)) {
$next_img = $all_photos[$i];
break;
}
/* the next photo is our NEXT photo */
if($all_photos[$i] == $photo) {
$get_next = 1;
}
else {
$previous_img = $all_photos[$i];
}
if($photo == $all_photos[$i]) {
$current = $i;
}
}
$details = $this->get_photo_details($photo);
if(!$details) {
print "error";
return;
}
$orig_path = $this->translate_path($this->parse_uri($details['uri'], 'fullpath'));
/* if current version is already set, use it */
if($this->get_current_version() !== false)
$version = $this->get_current_version();
/* if version not set yet, we assume to display the latest version */
if(!isset($version) || !$this->is_valid_version($photo, $version))
$version = $this->get_latest_version($photo);
$thumb_path = $this->get_thumb_path($this->cfg->photo_width, $photo, $version);
if(!file_exists($orig_path)) {
$this->_error("Photo ". $orig_path ." does not exist! \n");
return;
}
if(!is_readable($orig_path)) {
$this->_error("Photo ". $orig_path ." is not readable for user ". $this->getuid() ." \n");
return;
}
/* If the thumbnail doesn't exist yet, try to create it */
if(!file_exists($thumb_path)) {
$this->gen_thumb($photo, true);
$thumb_path = $this->get_thumb_path($this->cfg->photo_width, $photo, $version);
}
/* get mime-type, height and width from the original photo */
$info = getimagesize($orig_path);
/* get EXIF information if JPEG */
if(isset($info['mime']) && $info['mime'] == "image/jpeg") {
$meta = $this->get_meta_informations($orig_path);
}
/* If EXIF data are available, use them */
if(isset($meta['ExifImageWidth'])) {
$meta_res = $meta['ExifImageWidth'] ."x". $meta['ExifImageLength'];
} else {
$meta_res = $info[0] ."x". $info[1];
}
$meta_make = isset($meta['Make']) ? $meta['Make'] ." / ". $meta['Model'] : "n/a";
$meta_size = isset($meta['FileSize']) ? round($meta['FileSize']/1024, 1) ."kbyte" : "n/a";
$extern_link = "index.php?mode=showp&id=". $photo;
$current_tags = $this->getCurrentTags();
if($current_tags != "") {
$extern_link.= "&tags=". $current_tags;
}
if(isset($_SESSION['from_date']) && isset($_SESSION['to_date'])) {
$extern_link.= "&from_date=". $this->ts2str($_SESSION['from_date']) ."&to_date=". $this->ts2str($_SESSION['to_date']);
}
$this->tmpl->assign('extern_link', $extern_link);
if(!file_exists($thumb_path)) {
$this->_error("Can't open file ". $thumb_path ."\n");
return;
}
$info_thumb = getimagesize($thumb_path);
$this->tmpl->assign('description', $details['description']);
$this->tmpl->assign('image_name', $this->parse_uri($details['uri'], 'filename'));
$this->tmpl->assign('image_rating', $this->get_photo_rating($photo));
$this->tmpl->assign('width', $info_thumb[0]);
$this->tmpl->assign('height', $info_thumb[1]);
$this->tmpl->assign('ExifMadeOn', strftime("%a %x %X", $details['time']));
$this->tmpl->assign('ExifMadeWith', $meta_make);
$this->tmpl->assign('ExifOrigResolution', $meta_res);
$this->tmpl->assign('ExifFileSize', $meta_size);
if($this->is_user_friendly_url()) {
$this->tmpl->assign('image_url', '/photo/'. $photo ."/". $this->cfg->photo_width .'/'. $version);
$this->tmpl->assign('image_url_full', '/photo/'. $photo);
}
else {
$this->tmpl->assign('image_url', 'phpfspot_img.php?idx='. $photo ."&width=". $this->cfg->photo_width ."&version=". $version);
$this->tmpl->assign('image_url_full', 'phpfspot_img.php?idx='. $photo);
}
$this->tmpl->assign('image_filename', $this->parse_uri($details['uri'], 'filename'));
$this->tmpl->assign('tags', $this->get_photo_tags($photo));
$this->tmpl->assign('current_page', $this->getCurrentPage($current, $count));
$this->tmpl->assign('current_img', $photo);
if(isset($previous_img)) {
$this->tmpl->assign('previous_url', "javascript:showPhoto(". $previous_img .");");
$this->tmpl->assign('prev_img', $previous_img);
}
if(isset($next_img)) {
$this->tmpl->assign('next_url', "javascript:showPhoto(". $next_img .");");
$this->tmpl->assign('next_img', $next_img);
}
$this->tmpl->assign('mini_width', $this->cfg->mini_width);
$this->tmpl->assign('photo_width', $this->cfg->photo_width);
$this->tmpl->assign('photo_number', $i);
$this->tmpl->assign('photo_count', count($all_photos));
$this->tmpl->assign('photo', $photo);
$this->tmpl->assign('version', $version);
/* if the photo as alternative versions, set a flag for the template */
if($this->get_photo_versions($photo))
$this->tmpl->assign('has_versions', true);
$this->tmpl->register_function("photo_version_select_list", array(&$this, "smarty_photo_version_select_list"), false);
return $this->tmpl->fetch("single_photo.tpl");
} // showPhoto()
/**
* all available tags and tag cloud
*
* this function outputs all available tags (time ordered)
* and in addition output them as tag cloud (tags which have
* many photos will appears more then others)
*/
public function getAvailableTags()
{
/* retrive tags from database */
$this->get_tags();
$output = "";
$result = $this->db->db_query("
SELECT tag_id as id, count(tag_id) as quantity
FROM photo_tags
INNER JOIN tags t
ON t.id = tag_id
GROUP BY tag_id
ORDER BY t.name ASC
");
$tags = Array();
while($row = $this->db->db_fetch_object($result)) {
$tags[$row['id']] = $row['quantity'];
}
// change these font sizes if you will
$max_size = 125; // max font size in %
$min_size = 75; // min font size in %
// color
$max_sat = hexdec('cc');
$min_sat = hexdec('44');
// get the largest and smallest array values
$max_qty = max(array_values($tags));
$min_qty = min(array_values($tags));
// find the range of values
$spread = $max_qty - $min_qty;
if (0 == $spread) { // we don't want to divide by zero
$spread = 1;
}
// determine the font-size increment
// this is the increase per tag quantity (times used)
$step = ($max_size - $min_size)/($spread);
$step_sat = ($max_sat - $min_sat)/($spread);
// loop through our tag array
foreach ($tags as $key => $value) {
/* has the currently processed tag already been added to
the selected tag list? if so, ignore it here...
*/
if(isset($_SESSION['selected_tags']) && in_array($key, $_SESSION['selected_tags']))
continue;
// calculate CSS font-size
// find the $value in excess of $min_qty
// multiply by the font-size increment ($size)
// and add the $min_size set above
$size = $min_size + (($value - $min_qty) * $step);
// uncomment if you want sizes in whole %:
$size = ceil($size);
$color = $min_sat + ($value - $min_qty) * $step_sat;
$r = '44';
$g = dechex($color);
$b = '88';
if(isset($this->tags[$key])) {
if($this->is_user_friendly_url()) {
$output.= "cfg->web_path ."/tag/". $key ."\"
onclick=\"Tags('add', ". $key ."); return false;\"
class=\"tag\"
style=\"font-size: ". $size ."%; color: #". $r.$g.$b .";\"
title=\"Tag ". $this->tags[$key] .", ". $tags[$key] ." picture(s)\">". $this->tags[$key] .", ";
}
else {
$output.= "cfg->web_path ."/index.php?mode=showpi\"
onclick=\"Tags('add', ". $key ."); return false;\"
class=\"tag\"
style=\"font-size: ". $size ."%; color: #". $r.$g.$b .";\"
title=\"Tag ". $this->tags[$key] .", ". $tags[$key] ." picture(s)\">". $this->tags[$key] .", ";
}
}
}
$output = substr($output, 0, strlen($output)-2);
return $output;
} // getAvailableTags()
/**
* output all selected tags
*
* this function output all tags which have been selected
* by the user. the selected tags are stored in the
* session-variable $_SESSION['selected_tags']
* @return string
*/
public function getSelectedTags($type = 'link')
{
/* retrive tags from database */
$this->get_tags();
$output = "";
foreach($this->avail_tags as $tag)
{
// return all selected tags
if(isset($_SESSION['selected_tags']) && in_array($tag, $_SESSION['selected_tags'])) {
switch($type) {
default:
case 'link':
$output.= "". $this->tags[$tag] .", ";
break;
case 'img':
$output.= "
\n";
}
// isLast() to find end of week
if ( $day->isLast() )
$string.= "
\n";
$matrix[$rows][$cols] = $string;
$cols++;
if($cols > 7) {
$cols = 1;
$rows++;
}
}
$this->tmpl->assign('matrix', $matrix);
$this->tmpl->assign('rows', $rows);
$this->tmpl->show("calendar.tpl");
} // get_calendar_matrix()
/**
* output export page
* @param string $mode
*/
public function getExport($mode)
{
$pictures = $this->getPhotoSelection();
$current_tags = $this->getCurrentTags();
foreach($pictures as $picture) {
$orig_url = $this->get_phpfspot_url() ."/index.php?mode=showp&id=". $picture;
if($current_tags != "") {
$orig_url.= "&tags=". $current_tags;
}
if(isset($_SESSION['from_date']) && isset($_SESSION['to_date'])) {
$orig_url.= "&from_date=". $_SESSION['from_date'] ."&to_date=". $_SESSION['to_date'];
}
if($this->is_user_friendly_url()) {
$thumb_url = $this->get_phpfspot_url() ."/photo/". $picture ."/". $this->cfg->thumb_width;
}
else {
$thumb_url = $this->get_phpfspot_url() ."/phpfspot_img.php?idx=". $picture ."&width=". $this->cfg->thumb_width;
}
switch($mode) {
case 'HTML':
//
print htmlspecialchars("") ." \n";
break;
case 'MoinMoin':
// "[%pictureurl% %thumbnailurl%]"
print htmlspecialchars("[".$orig_url." ".$thumb_url."&fake=1.jpg]") ." \n";
break;
case 'MoinMoinList':
// " * [%pictureurl% %thumbnailurl%]"
print " " . htmlspecialchars("* [".$orig_url." ".$thumb_url."&fake=1.jpg]") ." \n";
break;
}
}
} // getExport()
/**
* output RSS feed
*/
public function getRSSFeed()
{
Header("Content-type: text/xml; charset=utf-8");
print "\n";
?>
phpfspotphpfspot RSS feed
get_phpfspot_url()); ?>
phpfspot
getPhotoSelection();
$current_tags = $this->getCurrentTags();
foreach($pictures as $picture) {
$orig_url = $this->get_phpfspot_url() ."/index.php?mode=showp&id=". $picture;
if($current_tags != "") {
$orig_url.= "&tags=". $current_tags;
}
if(isset($_SESSION['from_date']) && isset($_SESSION['to_date'])) {
$orig_url.= "&from_date=". $_SESSION['from_date'] ."&to_date=". $_SESSION['to_date'];
}
$details = $this->get_photo_details($picture);
if($this->is_user_friendly_url()) {
$thumb_url = $this->get_phpfspot_url() ."/photo/". $picture ."/". $this->cfg->thumb_width;
}
else {
$thumb_url = $this->get_phpfspot_url() ."/phpfspot_img.php?idx=". $picture ."&width=". $this->cfg->thumb_width;
}
$thumb_html = htmlspecialchars("
". $details['description']);
$orig_path = $this->translate_path($this->parse_uri($details['uri'], 'fullpath'));
/* get EXIF information if JPEG */
if(isset($details['mime']) && $details['mime'] == "image/jpeg") {
$meta = $this->get_meta_informations($orig_path);
}
?>
parse_uri($details['uri'], 'filename')); ?>
get_photo_versions($photo_idx))
return $versions[count($versions)-1];
/* if no alternative version were found, return original version */
return 0;
} // get_current_version()
/**
* tells the client browser what to do
*
* this function is getting called via AJAX by the
* client browsers. it will tell them what they have
* to do next. This is necessary for directly jumping
* into photo index or single photo view when the are
* requested with specific URLs
* @return string
*/
public function whatToDo()
{
if(isset($_SESSION['current_photo']) && $_SESSION['start_action'] == 'showp') {
}
elseif(isset($_SESSION['selected_tags']) && !empty($_SESSION['selected_tags'])) {
return "showpi_tags";
}
elseif(isset($_SESSION['start_action']) && $_SESSION['start_action'] == 'showpi') {
return "showpi";
}
} // whatToDo()
/**
* return the current process-user
* @return string
*/
private function getuid()
{
if($uid = posix_getuid()) {
if($user = posix_getpwuid($uid)) {
return $user['name'];
}
}
return 'n/a';
} // getuid()
/**
* photo version select list
*
* this function returns a HTML select list (drop down)
* to select a alternative photo version of the original photo.
*
* @param array $params
* @param smarty $smarty
* @return string
*/
public function smarty_photo_version_select_list($params, &$smarty)
{
if(!isset($params['photo']) || !isset($params['current']))
return NULL;
$output = "";
$versions = $this->get_photo_versions($params['photo']);
foreach($versions as $version) {
$output.= "";
}
return $output;
} // smarty_photo_version_select_list()
/**
* returns a select-dropdown box to select photo index sort parameters
* @param array $params
* @param smarty $smarty
* @return string
*/
public function smarty_sort_select_list($params, &$smarty)
{
$output = "";
foreach($this->sort_orders as $key => $value) {
$output.= "";
}
return $output;
} // smarty_sort_select_list()
/**
* returns the currently selected sort order
* @return string
*/
private function get_sort_order()
{
switch($_SESSION['sort_order']) {
case 'date_asc':
return " ORDER BY p.time ASC";
break;
case 'date_desc':
return " ORDER BY p.time DESC";
break;
case 'name_asc':
if($this->dbver < 9) {
return " ORDER BY p.name ASC";
}
else {
return " ORDER BY basename(p.uri) ASC";
}
break;
case 'name_desc':
if($this->dbver < 9) {
return " ORDER BY p.name DESC";
}
else {
return " ORDER BY basename(p.uri) DESC";
}
break;
case 'tags_asc':
return " ORDER BY t.name ASC ,p.time ASC";
break;
case 'tags_desc':
return " ORDER BY t.name DESC ,p.time ASC";
break;
case 'rate_asc':
return " ORDER BY p.rating ASC, t.name ASC";
break;
case 'rate_desc':
return " ORDER BY p.rating DESC, t.name ASC";
break;
}
} // get_sort_order()
/**
* return the next to be shown slide show image
*
* this function returns the URL of the next image
* in the slideshow sequence.
* @return string
*/
public function getNextSlideShowImage()
{
$all_photos = $this->getPhotoSelection();
if(!isset($_SESSION['slideshow_img']) || $_SESSION['slideshow_img'] == count($all_photos)-1)
$_SESSION['slideshow_img'] = 0;
else
$_SESSION['slideshow_img']++;
if($this->is_user_friendly_url()) {
return $this->get_phpfspot_url() ."/photo/". $all_photos[$_SESSION['slideshow_img']] ."/". $this->cfg->photo_width;
}
return $this->get_phpfspot_url() ."/phpfspot_img.php?idx=". $all_photos[$_SESSION['slideshow_img']] ."&width=". $this->cfg->photo_width;
} // getNextSlideShowImage()
/**
* return the previous to be shown slide show image
*
* this function returns the URL of the previous image
* in the slideshow sequence.
* @return string
*/
public function getPrevSlideShowImage()
{
$all_photos = $this->getPhotoSelection();
if(!isset($_SESSION['slideshow_img']) || $_SESSION['slideshow_img'] == 0)
$_SESSION['slideshow_img'] = 0;
else
$_SESSION['slideshow_img']--;
if($this->is_user_friendly_url()) {
return $this->get_phpfspot_url() ."/photo/". $all_photos[$_SESSION['slideshow_img']] ."/". $this->cfg->photo_width;
}
return $this->get_phpfspot_url() ."/phpfspot_img.php?idx=". $all_photos[$_SESSION['slideshow_img']] ."&width=". $this->cfg->photo_width;
} // getPrevSlideShowImage()
public function resetSlideShow()
{
if(isset($_SESSION['slideshow_img']))
unset($_SESSION['slideshow_img']);
} // resetSlideShow()
/**
* get random photo
*
* this function will get all photos from the fspot
* database and randomly return ONE entry
*
* saddly there is yet no sqlite3 function which returns
* the bulk result in array, so we have to fill up our
* own here.
* @return array
*/
public function get_random_photo()
{
$all = Array();
$query_str = "
SELECT p.id as id
FROM photos p
";
/* if show_tags is set, only return details for photos which
are specified to be shown
*/
if(isset($this->cfg->show_tags) && !empty($this->cfg->show_tags)) {
$query_str.= "
INNER JOIN photo_tags pt
ON p.id=pt.photo_id
INNER JOIN tags t
ON pt.tag_id=t.id
WHERE
t.name IN ('".implode("','",$this->cfg->show_tags)."')";
}
$result = $this->db->db_query($query_str);
while($row = $this->db->db_fetch_object($result)) {
array_push($all, $row['id']);
}
return $all[array_rand($all)];
} // get_random_photo()
/**
* get random photo tag photo
*
* this function will get all photos tagged with the requested
* tag from the fspot database and randomly return ONE entry
*
* saddly there is yet no sqlite3 function which returns
* the bulk result in array, so we have to fill up our
* own here.
* @return array
*/
public function get_random_tag_photo($tagidx)
{
$all = Array();
if(isset($this->cfg->show_tags) && !empty($this->cfg->show_tags)) {
$query_str.= "
SELECT
DISTINCT pt1.photo_id as id
FROM
photo_tags pt1
INNER JOIN photo_tags
pt2 ON pt1.photo_id=pt2.photo_id
INNER JOIN tags t1
ON t1.id=pt1.tag_id
INNER JOIN tags t2
ON t2.id=pt2.tag_id
WHERE
pt1.tag_id LIKE '". $tagidx ."'
AND
t2.name IN ('".implode("','",$this->cfg->show_tags)."')
ORDER BY
t1.sort_priority ASC";
}
else {
$query_str = "
SELECT
p.id as id
FROM
photos p
INNER JOIN photo_tags pt
ON p.id=pt.photo_id
WHERE
pt.tag_id LIKE '". $tagidx ."'";
}
$result = $this->db->db_query($query_str);
while($row = $this->db->db_fetch_object($result)) {
array_push($all, $row['id']);
}
return $all[array_rand($all)];
} // get_random_tag_photo()
/**
* validates provided date
*
* this function validates if the provided date
* contains a valid date and will return true
* if it is.
* @param string $date_str
* @return boolean
*/
public function isValidDate($date_str)
{
$timestamp = strtotime($date_str);
if(is_numeric($timestamp))
return true;
return false;
} // isValidDate()
/**
* timestamp to string conversion
* @param integer $timestamp
* @return string
*/
private function ts2str($timestamp)
{
if(!empty($timestamp) && is_numeric($timestamp))
return strftime("%Y-%m-%d", $timestamp);
} // ts2str()
/**
* extract tag-names from $_GET['tags']
* @param string $tags_str
* @return string
*/
private function extractTags($tags_str)
{
$not_validated = split(',', $tags_str);
$validated = array();
foreach($not_validated as $tag) {
if(is_numeric($tag))
array_push($validated, $tag);
}
return $validated;
} // extractTags()
/**
* returns the full path to a thumbnail
* @param integer $width
* @param integer $photo
* @return string
*/
public function get_thumb_path($width, $photo_idx, $version_idx)
{
$md5 = $this->getMD5($photo_idx, $version_idx);
$sub_path = substr($md5, 0, 2);
return $this->cfg->thumb_path
. "/"
. $sub_path
. "/"
. $width
. "_"
. $md5;
} // get_thumb_path()
/**
* returns server's virtual host name
* @return string
*/
private function get_server_name()
{
return $_SERVER['SERVER_NAME'];
} // get_server_name()
/**
* returns type of webprotocol which is currently used
* @return string
*/
private function get_web_protocol()
{
if(!isset($_SERVER['HTTPS']))
return "http";
else
return "https";
} // get_web_protocol()
/**
* return url to this phpfspot installation
* @return string
*/
private function get_phpfspot_url()
{
return $this->get_web_protocol() ."://". $this->get_server_name() . $this->cfg->web_path;
} // get_phpfspot_url()
/**
* returns the number of photos which are tagged with $tag_id
* @param integer $tag_id
* @return integer
*/
public function get_num_photos($tag_id)
{
if($result = $this->db->db_fetchSingleRow("
SELECT count(*) as number
FROM photo_tags
WHERE
tag_id LIKE '". $tag_id ."'")) {
return $result['number'];
}
return 0;
} // get_num_photos()
/**
* check file exists and is readable
*
* returns true, if everything is ok, otherwise false
* if $silent is not set, this function will output and
* error message
* @param string $file
* @param boolean $silent
* @return boolean
*/
private function check_readable($file, $silent = null)
{
if(!file_exists($file)) {
if(!isset($silent))
print "File \"". $file ."\" does not exist.\n";
return false;
}
if(!is_readable($file)) {
if(!isset($silent))
print "File \"". $file ."\" is not reachable for user ". $this->getuid() ."\n";
return false;
}
return true;
} // check_readable()
/**
* check if all needed indices are present
*
* this function checks, if some needed indices are already
* present, or if not, create them on the fly. they are
* necessary to speed up some queries like that one look for
* all tags, when show_tags is specified in the configuration.
*/
private function checkDbIndices()
{
$result = $this->db->db_exec("
CREATE INDEX IF NOT EXISTS
phototag
ON
photo_tags
(photo_id, tag_id)
");
} // checkDbIndices()
/**
* retrive F-Spot database version
*
* this function will return the F-Spot database version number
* It is stored within the sqlite3 database in the table meta
* @return string|null
*/
public function getFspotDBVersion()
{
if($result = $this->db->db_fetchSingleRow("
SELECT data as version
FROM meta
WHERE
name LIKE 'F-Spot Database Version'
"))
return $result['version'];
return null;
} // getFspotDBVersion()
/**
* parse the provided URI and will returned the requested chunk
* @param string $uri
* @param string $mode
* @return string
*/
public function parse_uri($uri, $mode)
{
if(($components = parse_url($uri)) !== false) {
switch($mode) {
case 'filename':
return basename($components['path']);
break;
case 'dirname':
return dirname($components['path']);
break;
case 'fullpath':
return $components['path'];
break;
}
}
return $uri;
} // parse_uri()
/**
* validate config options
*
* this function checks if all necessary configuration options are
* specified and set.
* @return boolean
*/
private function check_config_options()
{
if(!isset($this->cfg->page_title) || $this->cfg->page_title == "")
$this->_error("Please set \$page_title in phpfspot_cfg");
if(!isset($this->cfg->base_path) || $this->cfg->base_path == "")
$this->_error("Please set \$base_path in phpfspot_cfg");
if(!isset($this->cfg->web_path) || $this->cfg->web_path == "")
$this->_error("Please set \$web_path in phpfspot_cfg");
if(!isset($this->cfg->thumb_path) || $this->cfg->thumb_path == "")
$this->_error("Please set \$thumb_path in phpfspot_cfg");
if(!isset($this->cfg->smarty_path) || $this->cfg->smarty_path == "")
$this->_error("Please set \$smarty_path in phpfspot_cfg");
if(!isset($this->cfg->fspot_db) || $this->cfg->fspot_db == "")
$this->_error("Please set \$fspot_db in phpfspot_cfg");
if(!isset($this->cfg->db_access) || $this->cfg->db_access == "")
$this->_error("Please set \$db_access in phpfspot_cfg");
if(!isset($this->cfg->phpfspot_db) || $this->cfg->phpfspot_db == "")
$this->_error("Please set \$phpfspot_db in phpfspot_cfg");
if(!isset($this->cfg->thumb_width) || $this->cfg->thumb_width == "")
$this->_error("Please set \$thumb_width in phpfspot_cfg");
if(!isset($this->cfg->thumb_height) || $this->cfg->thumb_height == "")
$this->_error("Please set \$thumb_height in phpfspot_cfg");
if(!isset($this->cfg->photo_width) || $this->cfg->photo_width == "")
$this->_error("Please set \$photo_width in phpfspot_cfg");
if(!isset($this->cfg->mini_width) || $this->cfg->mini_width == "")
$this->_error("Please set \$mini_width in phpfspot_cfg");
if(!isset($this->cfg->thumbs_per_page))
$this->_error("Please set \$thumbs_per_page in phpfspot_cfg");
if(!isset($this->cfg->enable_replace_path))
$this->_error("Please set \$enable_replace_path in phpfspot_cfg");
if($this->cfg->enable_replace_path == true) {
if(!isset($this->cfg->path_replace_from) || $this->cfg->path_replace_from == "")
$this->_error("Please set \$path_replace_from in phpfspot_cfg");
if(!isset($this->cfg->path_replace_to) || $this->cfg->path_replace_to == "")
$this->_error("Please set \$path_replace_to in phpfspot_cfg");
}
if(!isset($this->cfg->hide_tags))
$this->_error("Please set \$hide_tags in phpfspot_cfg");
if(!isset($this->cfg->theme_name))
$this->_error("Please set \$theme_name in phpfspot_cfg");
if(!isset($this->cfg->logging))
$this->_error("Please set \$logging in phpfspot_cfg");
if(isset($this->cfg->logging) && $this->cfg->logging == 'logfile') {
if(!isset($this->cfg->log_file))
$this->_error("Please set \$log_file because you set logging = log_file in phpfspot_cfg");
if(!is_writeable($this->cfg->log_file))
$this->_error("The specified \$log_file ". $log_file ." is not writeable!");
}
/* remove trailing slash, if set */
if($this->cfg->web_path == "/")
$this->cfg->web_path = "";
elseif(preg_match('/\/$/', $this->cfg->web_path))
$this->cfg->web_path = preg_replace('/\/$/', '', $this->cfg->web_path);
return $this->runtime_error;
} // check_config_options()
/**
* cleanup phpfspot own database
*
* When photos are getting delete from F-Spot, there will remain
* remain some residues in phpfspot own database. This function
* will try to wipe them out.
*/
public function cleanup_phpfspot_db()
{
$to_delete = Array();
$result = $this->cfg_db->db_query("
SELECT img_idx as img_idx
FROM images
ORDER BY img_idx ASC
");
while($row = $this->cfg_db->db_fetch_object($result)) {
if(!$this->db->db_fetchSingleRow("
SELECT id as id
FROM photos
WHERE id='". $row['img_idx'] ."'")) {
array_push($to_delete, $row['img_idx'], ',');
}
}
print count($to_delete) ." unnecessary objects will be removed from phpfspot's database.\n";
$this->cfg_db->db_exec("
DELETE FROM images
WHERE img_idx IN (". implode($to_delete) .")
");
} // cleanup_phpfspot_db()
/**
* return first image of the page, the $current photo
* lies in.
*
* this function is used to find out the first photo of the
* current page, in which the $current photo lies. this is
* used to display the correct photo, when calling showPhotoIndex()
* from showImage()
* @param integer $current
* @param integer $max
* @return integer
*/
private function getCurrentPage($current, $max)
{
if(isset($this->cfg->thumbs_per_page) && !empty($this->cfg->thumbs_per_page)) {
for($page_start = 0; $page_start <= $max; $page_start+=$this->cfg->thumbs_per_page) {
if($current >= $page_start && $current < ($page_start+$this->cfg->thumbs_per_page))
return $page_start;
}
}
return 0;
} // getCurrentPage()
/**
* return mime info
*
* this function tries to find out the correct mime-type
* for the provided file.
* @param string $file
* @return string
*/
public function get_mime_info($file)
{
$details = getimagesize($file);
/* if getimagesize() returns empty, try at least to find out the
mime type.
*/
if(empty($details) && function_exists('mime_content_type')) {
// mime_content_type is marked as deprecated in the documentation,
// but is it really necessary to force users to install a PECL
// extension?
$details['mime'] = mime_content_type($file);
}
return $details['mime'];
} // get_mime_info()
/**
* return tag-name by tag-idx
*
* this function returns the tag-name for the requested
* tag specified by tag-idx.
* @param integer $idx
* @return string
*/
public function get_tag_name($idx)
{
if($result = $this->db->db_fetchSingleRow("
SELECT name as name
FROM tags
WHERE
id LIKE '". $idx ."'")) {
return $result['name'];
}
return 0;
} // get_tag_name()
/**
* parse user friendly url which got rewritten by the websever
* @param string $request_uri
* @return string
*/
private function parse_user_friendly_url($request_uri)
{
if(preg_match('/\/photoview\/|\/photo\/|\/tag\//', $request_uri)) {
$options = explode('/', $request_uri);
switch($options[1]) {
case 'photoview':
if(is_numeric($options[2])) {
$this->session_cleanup();
//unset($_SESSION['start_action']);
//unset($_SESSION['selected_tags']);
$_GET['mode'] = 'showp';
return $this->showPhoto($options[2]);
}
break;
case 'photo':
if(is_numeric($options[2])) {
$width = NULL;
$version = NULL;
if(isset($options[3]) && is_numeric($options[3]))
$width = $options[3];
if(isset($options[4]) && is_numeric($options[4]))
$version = $options[4];
require_once "phpfspot_img.php";
$img = new PHPFSPOT_IMG;
$img->showImg($options[2], $width, $version);
}
exit;
break;
case 'tag':
if(is_numeric($options[2])) {
$this->session_cleanup();
$_GET['tags'] = $options[2];
$_SESSION['selected_tags'] = Array($options[2]);
if(isset($options[3]) && is_numeric($options[3]))
$_SESSION['begin_with'] = $options[3];
return $this->showPhotoIndex();
}
break;
}
}
} // parse_user_friendly_url()
/**
* check if user-friendly-urls are enabled
*
* this function will return true, if the config option
* $user_friendly_url has been set. Otherwise false.
* @return boolean
*/
private function is_user_friendly_url()
{
if(isset($this->cfg->user_friendly_url) && $this->cfg->user_friendly_url)
return true;
return false;
} // is_user_friendly_url()
/**
* session cleanup
*
* this function will cleanup user's session information
*/
private function session_cleanup()
{
unset($_SESSION['begin_with']);
$this->resetDateSearch();
$this->resetPhotoView();
$this->resetTagSearch();
$this->resetNameSearch();
$this->resetDateSearch();
$this->resetTags();
} // session_cleanup()
/**
* get database version
*
* this function queries the meta table
* and returns the current database version.
*
* @return integer
*/
public function get_db_version()
{
if($row = $this->cfg_db->db_fetchSingleRow("
SELECT meta_value as meta_value
FROM
meta
WHERE
meta_key LIKE 'phpfspot Database Version'
")) {
return $row['meta_value'];
}
return 0;
} // get_db_version()
/**
* get photo versions
*
* this function returns an array of all available
* alterntaive versions of the provided photo id.
* has alternative photo versions available
*
* @param int $idx
* @return array
*/
public function get_photo_versions($idx)
{
$versions = Array();
$result = $this->db->db_query("
SELECT
version_id
FROM
photo_versions
WHERE
photo_id LIKE '". $idx ."'");
while($row = $this->cfg_db->db_fetch_object($result)) {
array_push($versions, $row['version_id']);
}
return $versions;
} // get_photo_versions()
/**
* check for invalid version of photo
*
* this function validates the provided photo-id and version-id
*
* @param int $photo_idx
* @param int $version_idx
* @return bool
*/
public function is_valid_version($photo_idx, $version_idx)
{
/* the original version is always valid */
if($version_idx == 0)
return true;
if($versions = $this->get_photo_versions($photo_idx)) {
if(in_array($version_idx, $versions))
return true;
}
return false;
} // is_valid_version()
/**
* get photo version name
*
* this function returns the name of the version
* identified by the photo-id and version-id.
*
* @param int $photo_idx
* @param int $version_idx
* @return string
*/
public function get_photo_version_name($photo_idx, $version_idx)
{
if($row = $this->db->db_fetchSingleRow("
SELECT
name
FROM
photo_versions
WHERE
photo_id LIKE '". $photo_idx ."'
AND
version_id LIKE '". $version_idx ."'")) {
return $row['name'];
}
return false;
} // get_photo_version_name()
/**
*/
public function is_valid_width($image_width)
{
if(in_array($image_width,
Array($this->cfg->thumb_width,
$this->cfg->photo_width,
$this->cfg->mini_width,
30)))
return true;
return false;
} // is_valid_width()
} // class PHPFSPOT
?>