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.6";
$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 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(!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_config_table();
/* overload Smarty class with our own template handler */
require_once "phpfspot_tmpl.php";
$this->tmpl = new PHPFSPOT_TMPL();
$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'])) {
$_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,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()
/**
* extract all photo details
*
* retrieve all available details from f-spot's
* database and return them as object
* @param integer $idx
* @return object|null
*/
public function get_photo_details($idx)
{
/* ~ F-Spot version 0.3.x */
if($this->dbver < 9) {
$query_str = "
SELECT p.id, p.name, p.time, p.directory_path, p.description
FROM photos p
";
}
else {
/* till F-Spot version 0.4.1 */
if($this->dbver < 11) {
$query_str = "
SELECT p.id, p.uri, p.time, p.description
FROM photos p
";
}
else {
$query_str = "
SELECT p.id, p.uri, p.time, p.description, p.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($result = $this->db->db_query($query_str)) {
$row = $this->db->db_fetch_object($result);
/* before F-Spot db version 9 there was no uri column but seperated
columns for directory_path and name (= filename).
*/
if($this->dbver < 9) {
$row['uri'] = "file://". $row['directory_path'] ."/". $row['name'];
}
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)
{
return str_replace($this->cfg->path_replace_from, $this->cfg->path_replace_to, $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'));
$thumb_path = $this->get_thumb_path($this->cfg->photo_width, $photo);
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);
}
/* 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);
$this->tmpl->assign('image_url_full', '/photo/'. $photo);
}
else {
$this->tmpl->assign('image_url', 'phpfspot_img.php?idx='. $photo ."&width=". $this->cfg->photo_width);
$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));
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')); ?>
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
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();
$query_str = "
SELECT p.id
FROM photos p
INNER JOIN photo_tags pt
ON p.id=pt.photo_id
";
if(isset($this->cfg->show_tags) && !empty($this->cfg->show_tags)) {
$query_str.= "
INNER JOIN tags t
ON pt.tag_id=t.id
";
}
$query_str.= "
WHERE
pt.tag_id LIKE '". $tagidx ."'
";
/*if(isset($this->cfg->show_tags) && !empty($this->cfg->show_tags)) {
$query_str.= "
AND
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_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)
{
$md5 = $this->getMD5($photo);
$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->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
FROM images
ORDER BY img_idx ASC
");
while($row = $this->cfg_db->db_fetch_object($result)) {
if(!$this->db->db_fetchSingleRow("
SELECT 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
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])) {
require_once "phpfspot_img.php";
$img = new PHPFSPOT_IMG;
if(isset($options[3]) && is_numeric($options[3]))
$img->showImg($options[2], $options[3]);
else
$img->showImg($options[2]);
}
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()
} // class PHPFSPOT
?>