Fixed race condition on canvas init (caused boxes to appear off by ~320px); fixed JSON response of null when row[img_tags] is NULL
<?php
/*
* Snapr
* Version 0.1 beta 1
* Copyright (C) 2007 Dan Fuhry
*
* This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
*/
/**
* Generates a random filename for Snapr images.
* @param int $length Optional - length of filename
* @return string
*/
function gallery_make_filename($length = 24)
{
$valid_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$valid_chars = enano_str_split($valid_chars);
$ret = '';
for ( $i = 0; $i < $length; $i++ )
{
$ret .= $valid_chars[mt_rand(0, count($valid_chars)-1)];
}
return $ret;
}
/**
* Returns the extension of a file.
* @param string file
* @return string
*/
function get_file_extension($file)
{
return substr($file, ( strrpos($file, '.') + 1 ));
}
/**
* For a given image ID, return the folder hierarchy.
* @param int The image ID
* @return array
*/
function gallery_imgid_to_folder($img_id)
{
global $db, $session, $paths, $template, $plugins; // Common objects
if ( !is_int($img_id) )
return array();
$img_id = strval($img_id);
$ret = array();
$sanity = 0;
$sanity_stack = array();
while(true)
{
$sanity++;
$q = $db->sql_query('SELECT img_title, img_id, folder_parent FROM '.table_prefix.'gallery WHERE img_id=' . $img_id . ';');
if ( !$q )
$db->_die();
$row = $db->fetchrow();
if ( !$row )
{
break;
}
if ( $sanity > 1 )
{
$ret[] = $row['img_title'];
}
if ( !$row['folder_parent'] )
{
break;
}
if ( in_array($row['img_id'], $sanity_stack) )
return array('Infinite loop');
$sanity_stack[] = $row['img_id'];
$img_id = $row['folder_parent'];
}
return $ret;
}
/**
* Generates a hierarchy of Gallery folders.
* @return array
*/
function gallery_folder_hierarchy()
{
global $db, $session, $paths, $template, $plugins; // Common objects
$q = $db->sql_query('SELECT img_id, img_title, folder_parent FROM '.table_prefix.'gallery WHERE is_folder=1');
if ( !$q )
$db->_die();
if ( $db->numrows() < 1 )
{
return array();
}
$lookup_table = array();
$hier = array('_id' => 'NULL');
$orphans = array();
$persist_orphans = array();
while ( $row = $db->fetchrow() )
{
if ( !$row['folder_parent'] )
{
// root-level folder
$hier[ $row['img_title'] ] = array('_id' => $row['img_id']);
$lookup_table[$row['img_id']] =& $hier[ $row['img_title'] ];
}
else if ( $row['folder_parent'] && isset($lookup_table[$row['folder_parent']]) )
{
// child folder, parent is resolved
$lookup_table[ $row['folder_parent'] ][ $row['img_title'] ] = array('_id' => $row['img_id']);
$lookup_table[ $row['img_id'] ] =& $lookup_table[ $row['folder_parent'] ][ $row['img_title'] ];
}
else if ( $row['folder_parent'] && !isset($lookup_table[$row['folder_parent']]) )
{
// child folder, orphan as of yet
$orphans[] = $row;
}
}
// Resolve orphans
do
{
$persist_orphans = array();
while ( count($orphans) > 0 )
{
$orphan =& $orphans[ ( count($orphans) - 1 ) ];
if ( isset($lookup_table[$orphan['folder_parent']]) )
{
$lookup_table[ $orphan['folder_parent'] ][ $orphan['img_title'] ] = array('_id' => $orphan['img_id']);
$lookup_table[ $orphan['img_id'] ] =& $lookup_table[ $orphan['folder_parent'] ][ $orphan['img_title'] ];
}
else
{
$persist_orphans[] = $orphans[ ( count($orphans) - 1 ) ];
//echo 'BUG: ' . htmlspecialchars($orphan['img_title']) . ' (' . $orphan['img_id'] . ') is an orphan folder (parent is ' . $orphan['folder_parent'] . '); placing in root<br />';
// $hier[ $orphan['img_title'] ] = array();
// $lookup_table[$orphan['img_id']] =& $hier[ $orphan['img_title'] ];
}
unset($orphan, $orphans[ ( count($orphans) - 1 ) ]);
}
$orphans = $persist_orphans;
//die('insanity:<pre>'.print_r($hier,true).print_r($lookup_table,true).print_r($persist_orphans,true).'</pre>');
}
while ( count($persist_orphans) > 0 );
return $hier;
}
/**
* Generates HTML for a folder selector.
* @param string The form field name, defaults to folder_id.
* @param bool Whether to auto-select the root or not. Defaults to true.
* @return string
*/
function gallery_hier_formfield($field_name = 'folder_id', $autosel = true)
{
$hier = gallery_folder_hierarchy();
$img_join = scriptPath . '/images/icons/joinbottom.gif';
$img_join_term = scriptPath . '/images/icons/join.gif';
$img_line = scriptPath . '/images/icons/line.gif';
$img_empty = scriptPath . '/images/icons/empty.gif';
$html = _gallery_hier_form_inner($hier, '<Root>', $field_name, -1, array(), $img_join, $img_join_term, $img_line, $img_empty, $autosel);
return $html;
}
//
/**
* Inner loop for form field generator (needs to call itself recursively)
* @access private
*/
function _gallery_hier_form_inner($el, $name, $fname, $depth, $depth_img, $img_join, $img_join_term, $img_line, $img_empty, $sel = false)
{
$html = '';
foreach ( $depth_img as $sw )
$html .= '<img alt=" " src="' . $sw . '" />';
$html .= '<label><input ' . ( $sel ? 'checked="checked"' : '' ) . ' type="radio" name="' . $fname . '" value="' . $el['_id'] . '" /> ' . htmlspecialchars($name) . '</label><br />';
if ( count($el) > 1 )
{
// Writing this image logic sucked.
$count = 0;
foreach ( $el as $key => $el_lower )
{
$count++;
if ( $key == '_id' )
continue;
$depth_mod = $depth_img;
$last = ( $count == count($el) );
for ( $i = 0; $i < count($depth_mod); $i++ )
{
if ( $depth_mod[$i] == $img_join_term || $depth_mod[$i] == $img_empty )
$depth_mod[$i] = $img_empty;
else
$depth_mod[$i] = $img_line;
}
if ( $last )
$depth_mod[] = $img_join_term;
else
$depth_mod[] = $img_join;
$html .= _gallery_hier_form_inner($el_lower, $key, $fname, ( $depth + 1 ), $depth_mod, $img_join, $img_join_term, $img_line, $img_empty);
}
}
return $html;
}
/**
* Returns an array containing the IDs of all of the given folder ID's children. Recursive function.
* @param int ID of folder
*/
function gal_fetch_all_children($id)
{
global $db, $session, $paths, $template, $plugins; // Common objects
if ( !is_int($id) )
{
die('not int');
return false;
}
$children = array();
$q = $db->sql_query('SELECT img_id,is_folder FROM '.table_prefix.'gallery WHERE folder_parent=' . $id . ';');
if ( !$q )
$db->_die();
if ( $db->numrows() < 1 )
{
return $children;
}
$folders = array();
while ( $row = $db->fetchrow() )
{
$children[] = intval($row['img_id']);
if ( $row['is_folder'] == 1 )
$folders[] = intval($row['img_id']);
}
foreach ( $folders as $folder )
{
$grandchildren = gal_fetch_all_children($folder);
if ( $grandchildren === false )
{
return false;
}
$children = array_merge($children, $grandchildren);
}
return $children;
}
/**
* Lists all normal files within a given directory. Recursive function. Can also return the list of directories in the second parameter by reference.
* @param string Directory to search
* @param array Variable in which to store
* @return array Not multi-depth
*/
function gal_dir_recurse($dir, &$dirlist)
{
$dir_handle = opendir($dir);
if ( !$dir_handle )
return false;
$entries = array();
$dirlist = array();
while ( true )
{
$file = readdir($dir_handle);
if ( !$file )
break;
if ( $file == '.' || $file == '..' )
continue;
$file = $dir . '/' . $file;
if ( is_dir($file) )
{
$children = gal_dir_recurse($file, $dirtemp);
$dirlist[] = $file;
$dirlist = array_merge($dirlist, $dirtemp);
$entries = array_merge($entries, $children);
}
else if ( is_file($file) )
{
$entries[] = $file;
}
else
{
die($file . ' is not a file or directory');
}
}
closedir($dir_handle);
return $entries;
}
/**
* Wrapper for JSON decoding that works on Enano 1.0.x and 1.1.x
* @param string JSON datastream...
* @return mixed
*/
function snapr_json_decode($data)
{
if ( defined('ENANO_ATLEAST_1_1') )
{
try
{
$decoded = enano_json_decode($data);
}
catch ( Exception $e )
{
$response = array(
'mode' => 'error',
'error' => 'Exception in JSON parser.'
);
die(enano_json_encode($response));
}
}
else
{
$json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
$decoded = $json->decode($data);
}
return ( isset($decoded) ) ? $decoded : false;
}
/**
* Wrapper for JSON encoding that works on Enano 1.0.x and 1.1.x
* @param mixed Data to encode
* @return string
*/
function snapr_json_encode($data)
{
if ( defined('ENANO_ATLEAST_1_1') )
{
try
{
$encoded = enano_json_encode($data);
}
catch ( Exception $e )
{
$response = array(
'mode' => 'error',
'error' => 'Exception in JSON encoder.'
);
die(enano_json_encode($response));
}
}
else
{
$json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
$encoded = $json->encode($data);
}
return ( isset($encoded) ) ? $encoded : false;
}
?>