# HG changeset patch # User Dan # Date 1185395786 14400 # Node ID 7caf561c50ee51c2b94db5b80098adbf5a820db2 Initial population; browser, viewer, uploader, and security are working diff -r 000000000000 -r 7caf561c50ee README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README Wed Jul 25 16:36:26 2007 -0400 @@ -0,0 +1,45 @@ +Snapr - Image gallery in a snap! +Another fine plugin for Enano CMS +-------------------------------------------------- + +Welcome and thanks for downloading Snapr, the Enano plugin designed to make +turning your site into a photo or image gallery a snap. + +Copyright +-------------------------------------------------- + +Snapr is Free Software; you can redistribute it 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. + +Snapr is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranties of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. See the GNU General Public License for details. + +You should have received a copy of the GNU General Public License along with +this package; if not, please consult the Enano CMS website at +, or view a copy of the GNU General Public license with +the GPL file included with the official Enano distribution files. + +Installing Snapr +-------------------------------------------------- + +To install the Snapr plugin on your site, just extract the zip or tarball file +into your Enano root folder. If you need to upload Snapr manually, upload the +file plugins/Gallery.php and the entire folder plugins/gallery/ to the +plugins/ folder inside your Enano root. + +To enable Snapr plugin, go to the Administration panel, expand General, click +Manage Plugins, and click Enable in the row showing the Snapr plugin. + +Obtaining support +-------------------------------------------------- + +Support for Snapr is available via the same support channels as Enano, as it +is developed and maintained by the official Enano team. For support options, +both free and commercial, please see . + +Have fun! + +-- The Enano team diff -r 000000000000 -r 7caf561c50ee TODO --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TODO Wed Jul 25 16:36:26 2007 -0400 @@ -0,0 +1,8 @@ +Snapr - Image gallery in a snap! +Another fine plugin for Enano CMS + +TODO: +-------------------------------------------------- + +[ ] Figure out a PageProcessor hack to make ACLs work for folders as well as images +[ ] Possibly rename Special:GalleryUpload to something more accurate, as it's become a one-for-everything administration center for the gallery diff -r 000000000000 -r 7caf561c50ee plugins/Gallery.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/Gallery.php Wed Jul 25 16:36:26 2007 -0400 @@ -0,0 +1,50 @@ +sql_query('CREATE TABLE '.table_prefix.'gallery( + img_id int(12) NOT NULL auto_increment, + is_folder tinyint(1) NOT NULL DEFAULT 0, + folder_parent int(12) DEFAULT NULL, + img_title varchar(255) NOT NULL DEFAULT \'\', + img_desc longtext NOT NULL DEFAULT \'\', + print_sizes longtext NOT NULL DEFAULT \'\', + img_filename varchar(255) NOT NULL, + img_time_upload int(12) NOT NULL DEFAULT 0, + img_time_mod int(12) NOT NULL DEFAULT 0, + PRIMARY KEY ( img_id ) + );'); + if ( !$q ) + $db->_die(); + + setConfig('gallery_version', GALLERY_VERSION); +} + +require( ENANO_ROOT . '/plugins/gallery/functions.php' ); +require( ENANO_ROOT . '/plugins/gallery/nssetup.php' ); +require( ENANO_ROOT . '/plugins/gallery/viewimage.php' ); +require( ENANO_ROOT . '/plugins/gallery/browser.php' ); +require( ENANO_ROOT . '/plugins/gallery/upload.php' ); +require( ENANO_ROOT . '/plugins/gallery/fetcher.php' ); + +?> diff -r 000000000000 -r 7caf561c50ee plugins/gallery/.upload.php.marks --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/gallery/.upload.php.marks Wed Jul 25 16:36:26 2007 -0400 @@ -0,0 +1,4 @@ +!u;8818;8818 +!e;12994;12994 +!z;22686;22686 +!f;35274;35274 diff -r 000000000000 -r 7caf561c50ee plugins/gallery/browser.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/gallery/browser.css Wed Jul 25 16:36:26 2007 -0400 @@ -0,0 +1,24 @@ +/* + * CSS for gallery browser + */ + +div.gallery_icon { + border-width: 1px; + border-style: solid; + border-color: #FFFFFF; + cursor: pointer; + text-align: center; + display: table; + margin: 0 auto; + padding: 4px; +} + +div.gallery_icon:hover { + border-color: #CCCCCC; +} + +div.gallery_icon img.gallery_thumb { + display: block; + border-width: 0; + margin: 0 auto 6px auto; +} diff -r 000000000000 -r 7caf561c50ee plugins/gallery/browser.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/gallery/browser.php Wed Jul 25 16:36:26 2007 -0400 @@ -0,0 +1,455 @@ +attachHook('base_classes_initted', ' + global $paths; + $paths->add_page(Array( + \'name\'=>\'Image gallery\', + \'urlname\'=>\'Gallery\', + \'namespace\'=>\'Special\', + \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\', + )); + '); + +/** + * Class to handle building the HTML for gallery pages. Called by the pagination function. + * @package Enano + * @subpackage Snapr + * @access private + */ + +class SnaprFormatter +{ + + /** + * Counter for how many cells we've printed out in this row. + * @var int + */ + + var $cell_count = 0; + + /** + * Icons to print per row. + * @var int + */ + + var $icons_per_row = 5; + + /** + * Main render method, called from pagination function + * @access private + */ + + function render($column_crap, $row, $row_crap) + { + global $db, $session, $paths, $template, $plugins; // Common objects + + $out = ''; + + if ( $this->cell_count == $this->icons_per_row ) + { + $out .= ''; + $this->cell_count = 0; + } + $this->cell_count++; + + $title_safe = $row['img_title']; + $title_safe = htmlspecialchars($title_safe); + + if ( $row['is_folder'] == 1 ) + { + // It's a folder, show the icon + $f_url_particle = sanitize_page_id($row['img_title']); + $f_url_particle = htmlspecialchars($f_url_particle); + $image_link = makeUrl( $paths->fullpage . '/' . $f_url_particle ); + $image_url = scriptPath . '/plugins/gallery/folder.png'; + } + else + { + // It's an image, show a thumbnail + $image_link = makeUrlNS('Gallery', $row['img_id']); + $image_url = makeUrlNS('Special', 'GalleryFetcher/thumb/' . $row['img_id']); + } + + $image_url_js = addslashes($image_link); + $jsclick = ( $session->user_level < USER_LEVEL_ADMIN ) ? ' onclick="window.location=\'' . $image_url_js . '\'"' : ''; + + $out .= ' + '; + + $out .= ''; + + return $out; + } + +} + +function page_Special_Gallery() +{ + global $db, $session, $paths, $template, $plugins; // Common objects + + // die('
' . print_r(gallery_folder_hierarchy(), true) . '
'); + + $sort_column = ( isset($_GET['sort']) && in_array($_GET['sort'], array('img_title', 'img_time_upload', 'img_time_mod')) ) ? $_GET['sort'] : 'img_title'; + $sort_order = ( isset($_GET['order']) && in_array($_GET['order'], array('ASC', 'DESC')) ) ? $_GET['order'] : 'ASC'; + + // Determine number of pictures per page + $template->load_theme(); + + global $theme; + $fn = ENANO_ROOT . '/themes/' . $template->theme . '/theme.cfg'; + require( $fn ); + if ( isset($theme['snapr_gallery_rows']) ) + { + $rows_in_browser = intval($theme['snapr_gallery_rows']); + if ( empty($rows_in_browser) ) + { + $rows_in_browser = 5; + } + } + else + { + $rows_in_browser = 5; + } + + $where = 'WHERE folder_parent IS NULL ' . "\n ORDER BY is_folder DESC, $sort_column $sort_order, img_title ASC"; + $parms = $paths->getAllParams(); + + $sql = "SELECT img_id, img_title, is_folder FROM ".table_prefix."gallery $where;"; + + // Breadcrumb browser + $breadcrumbs = array(); + $breadcrumbs[] = 'Gallery index'; + + $breadcrumb_urlcache = ''; + + // CSS for gallery browser + $template->add_header(''); + $template->add_header(''); + + $header = $template->getHeader(); + + if ( !empty($parms) ) + { + $parms = dirtify_page_id($parms); + if ( strstr($parms, '/') ) + { + $folders = explode('/', $parms); + } + else + { + $folders = array(0 => $parms); + } + foreach ( $folders as $i => $_crap ) + { + $folder =& $folders[$i]; + + $f_url = sanitize_page_id($folder); + $breadcrumb_urlcache .= '/' . $f_url; + $breadcrumb_url = makeUrlNS('Special', 'Gallery' . $breadcrumb_urlcache); + + $folder = str_replace('_', ' ', $folder); + + if ( $i == ( count($folders) - 1 ) ) + { + $breadcrumbs[] = htmlspecialchars($folder); + } + else + { + $breadcrumbs[] = '' . htmlspecialchars($folder) . ''; + } + } + unset($folder); + $folders = array_reverse($folders); + // This is one of the best MySQL tricks on the market. We're going to reverse-travel a folder path using LEFT JOIN and the incredible power of metacoded SQL + $sql = 'SELECT gm.img_id, gm.img_title, gm.is_folder, g0.img_title AS folder_name, g0.img_id AS folder_id FROM '.table_prefix.'gallery AS gm' . "\n " . 'LEFT JOIN '.table_prefix.'gallery AS g0' . "\n " . 'ON ( gm.folder_parent = g0.img_id )'; + $where = "\n " . 'WHERE g0.img_title=\'' . $db->escape($folders[0]) . '\''; + foreach ( $folders as $i => $folder ) + { + if ( $i == 0 ) + continue; + $i_dec = $i - 1; + $folder = $db->escape($folder); + $sql .= "\n LEFT JOIN ".table_prefix."gallery AS g{$i}\n ON ( g{$i}.img_id=g{$i_dec}.folder_parent AND g{$i}.img_title='$folder' )"; + $where .= "\n ".'AND g'.$i.'.img_id IS NOT NULL'; + } + $where .= "\n AND g{$i}.folder_parent IS NULL"; + $sql .= $where . "\n ORDER BY is_folder DESC, gm.$sort_column $sort_order, gm.img_title ASC" . ';'; + } + + $img_query = $db->sql_query($sql); + if ( !$img_query ) + $db->_die('The folder ID could not be selected.'); + + if ( $db->numrows() < 1 ) + { + // Nothing in this folder, for one of two reasons: + // 1) The folder doesn't exist + // 2) The folder exists but doesn't have any images in it + + /* + $folders_old = $folders; + $folders = array( + 0 => $folders_old[0] + ); + $x = $folders_old; + unset($x[0]); + $folders = array_merge($folders, $x); + unset($x); + */ + // die('
' . print_r($folders, true) . '
'); + + // This next query will try to determine if the folder itself exists + $sql = 'SELECT g0.img_id, g0.img_title FROM '.table_prefix.'gallery AS g0'; + $where = "\n " . 'WHERE g0.img_title=\'' . $db->escape($folders[0]) . '\''; + foreach ( $folders as $i => $folder ) + { + if ( $i == 0 ) + continue; + $i_dec = $i - 1; + $folder = $db->escape($folder); + $sql .= "\n LEFT JOIN ".table_prefix."gallery AS g{$i}\n ON ( g{$i}.img_id=g{$i_dec}.folder_parent AND g{$i}.img_title='$folder' )"; + $where .= "\n ".'AND g'.$i.'.img_id IS NOT NULL'; + } + $where .= "\n AND g{$i}.folder_parent IS NULL"; + $where .= "\n AND g0.is_folder=1"; + $sql .= $where . ';'; + + $nameq = $db->sql_query($sql); + if ( !$nameq ) + $db->_die(); + + if ( $db->numrows($nameq) < 1 ) + { + die_friendly('Folder not found', '

The folder you requested doesn\'t exist. Please check the URL and try again, or return to the gallery index.

'); + } + + $row = $db->fetchrow($nameq); + + // Generate title + $title = dirtify_page_id($row['img_title']); + $title = str_replace('_', ' ', $title); + $title = htmlspecialchars($title); + + $template->tpl_strings['PAGE_NAME'] = $title; + + $first_row = $row; + + $db->sql_data_seek(0, $img_query); + + /* $folders = $folders_old; */ + } + else if ( !empty($parms) ) + { + $row = $db->fetchrow($img_query); + $first_row = $row; + + // Generate title + $title = htmlspecialchars($row['folder_name']); + + $template->tpl_strings['PAGE_NAME'] = $title; + + $db->sql_data_seek(0, $img_query); + } + else + { + $row = $db->fetchrow($img_query); + $first_row = $row; + + $template->tpl_strings['PAGE_NAME'] = 'Image Gallery'; + $breadcrumbs = array('Gallery index'); + + $db->sql_data_seek(0, $img_query); + } + + $f_errors = array(); + + if ( $session->user_level >= USER_LEVEL_ADMIN && isset($_POST['create_folder']) && isset($first_row['folder_id']) ) + { + if ( empty($_POST['create_folder']) ) + { + $f_errors[] = 'Please enter a folder name.'; + } + if ( $_POST['create_folder'] == '_id' ) + { + $f_errors[] = 'The name "_id" is reserved for internal functions and cannot be used on any image or folder.'; + } + if ( count($f_errors) < 1 ) + { + $q = $db->sql_query('INSERT INTO '.table_prefix.'gallery(img_title, is_folder, folder_parent) VALUES(\'' . $db->escape($_POST['create_folder']) . '\', 1, ' . $first_row['folder_id'] . ');'); + if ( !$q ) + $db->_die(); + redirect(makeUrl($paths->fullpage), 'Folder created', 'The folder "' . htmlspecialchars($_POST['create_folder']) . '" has been created. Redirecting to last viewed folder...', 2); + } + } + + echo $header; + + if ( count($f_errors) > 0 ) + { + echo '
Error creating folder:
  • ' . implode('
  • ', $f_errors) . '
'; + } + + // From here, this breadcrumb stuff is a piece of... sourdough French bread :-) *smacks lips* + echo '
'; + // Upload image link for admins + if ( $session->user_level >= USER_LEVEL_ADMIN ) + { + echo '
'; + echo 'Upload new image(s)'; + echo '
'; + } + // The actual breadcrumbs + echo '' . implode(' » ', $breadcrumbs) . ''; + echo '
'; + + // "Edit all" link + if ( $row = $db->fetchrow($img_query) && $session->user_level >= USER_LEVEL_ADMIN ) + { + $img_list = array(); + $fol_list = array(); + $all_list = array(); + do + { + if ( $row === true && isset($first_row) ) + { + $row = $first_row; + } + // die('
' . var_dump($row) . $db->sql_backtrace() . '
'); + if ( !$row['img_id'] ) + break; + $all_list[] = $row['img_id']; + if ( $row['is_folder'] == 1 ) + $fol_list[] = $row['img_id']; + else + $img_list[] = $row['img_id']; + } + while ( $row = $db->fetchrow($img_query) ); + + $all_list = implode(',', $all_list); + $fol_list = implode(',', $fol_list); + $img_list = implode(',', $img_list); + + if ( !empty($all_list) ) + { + echo '
+ Edit all in this folder: '; + if ( !empty($img_list) ) + { + $edit_link = makeUrlNS('Special', 'GalleryUpload', 'edit_img=' . $img_list, true); + echo "images "; + } + if ( !empty($fol_list) ) + { + $edit_link = makeUrlNS('Special', 'GalleryUpload', 'edit_img=' . $fol_list, true); + echo "folders "; + } + if ( !empty($img_list) && !empty($fol_list) ) + { + $edit_link = makeUrlNS('Special', 'GalleryUpload', 'edit_img=' . $all_list, true); + echo "both "; + } + // " Bypass stupid jEdit bug + echo '
'; + } + } + + $url_sort_name_asc = makeUrl($paths->fullpage, 'sort=img_title&order=ASC', true); + $url_sort_name_desc = makeUrl($paths->fullpage, 'sort=img_title&order=DESC', true); + $url_sort_upl_asc = makeUrl($paths->fullpage, 'sort=img_time_upload&order=ASC', true); + $url_sort_mod_asc = makeUrl($paths->fullpage, 'sort=img_time_mod&order=ASC', true); + $url_sort_upl_desc = makeUrl($paths->fullpage, 'sort=img_time_upload&order=DESC', true); + $url_sort_mod_desc = makeUrl($paths->fullpage, 'sort=img_time_mod&order=DESC', true); + + // "Sort by" selector (pure CSS!) + echo ' +
 
'; + + $db->sql_data_seek(0, $img_query); + + // + // Main fetcher + // + + $renderer = new SnaprFormatter(); + $callers = array( + 'img_id' => array($renderer, 'render') + ); + + $renderer->icons_per_row = $rows_in_browser; + + $start = 0; + if ( isset($_GET['start']) && preg_match('/^[0-9]+$/', $_GET['start']) ) + { + $start = intval($_GET['start']); + } + + $per_page = $rows_in_browser * 5; + + $html = paginate($img_query, '{img_id}', $db->numrows($img_query), makeUrl($paths->fullpage, 'start=%s', true), $start, $per_page, $callers, '', '
'); + echo $html; + + if ( $session->user_level >= USER_LEVEL_ADMIN ) + { + echo '
Create new folder'; + echo '
'; + echo '
'; + echo ' '; + echo '
'; + echo '
 

'; + } + + $template->footer(); + +} + +?> diff -r 000000000000 -r 7caf561c50ee plugins/gallery/chevron-prelight.gif Binary file plugins/gallery/chevron-prelight.gif has changed diff -r 000000000000 -r 7caf561c50ee plugins/gallery/chevron.gif Binary file plugins/gallery/chevron.gif has changed diff -r 000000000000 -r 7caf561c50ee plugins/gallery/denied.png Binary file plugins/gallery/denied.png has changed diff -r 000000000000 -r 7caf561c50ee plugins/gallery/dropdown.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/gallery/dropdown.css Wed Jul 25 16:36:26 2007 -0400 @@ -0,0 +1,76 @@ +div.select-outer { + border-width: 1px; + border-style: solid; + border-color: #FFFFFF; + padding: 3px 21px 3px 3px !important; + cursor: pointer; + display: table; + background-image: url(chevron.gif); + background-position: 95% 8px; + background-repeat: no-repeat; + background-color: #FFFFFF; + position: absolute; + font-family: arial, sans-serif; + font-size: 8pt; + margin: 4px 0 0 0 !important; + text-align: left; +} +div.select-outer:hover { + border-color: #CCCCCC; + background-image: url(chevron-prelight.gif); +} +div.select-inner { + display: none; + background-color: #FFFFFF; + margin-right: -18px; +} +div.select-outer:hover div.select-inner { + display: block; +} +div.select-inner a { + display: block; + padding: 2px; + color: #000000; +} +div.select-inner a:hover { + display: block; + color: #0000FF; + background-color: #F0F0FF; +} + +div.toggle { + border: 1px solid #2c458a; + background-color: #F0FDFF; + padding: 1px; + margin: 10px 0; +} + +div.toggle div.head { + line-height: 22px; + background-image: url(toggle-head-bg.gif); + padding: 2px 7px 0 7px; + margin: 0; + color: #FFFFFF; + cursor: pointer; +} + +div.toggle div.head img.toggler { + float: right; + margin: 3px; + display: block; +} + +div.toggle div.body { + background-color: #e3e7f3; + border: 1px solid #849ad6; + padding: 10px; + margin: 1px 0 0 0; + display: none; + max-height: 300px; + clip: rect(0px,auto,auto,0px); + overflow: auto; +} + +div.toggle div.body label:hover { + background-color: #f3f7ff; +} diff -r 000000000000 -r 7caf561c50ee plugins/gallery/fetcher.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/gallery/fetcher.php Wed Jul 25 16:36:26 2007 -0400 @@ -0,0 +1,116 @@ +attachHook('base_classes_initted', ' + global $paths; + $paths->add_page(Array( + \'name\'=>\'Image fetcher pagelet\', + \'urlname\'=>\'GalleryFetcher\', + \'namespace\'=>\'Special\', + \'special\'=>0,\'visible\'=>0,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\', + )); + '); + +function page_Special_GalleryFetcher() +{ + global $db, $session, $paths, $template, $plugins; // Common objects + + $type = $paths->getParam(0); + if ( !in_array($type, array('thumb', 'preview', 'full')) ) + { + die('Hack attempt'); + } + + $id = intval($paths->getParam(1)); + if ( !$id ) + { + die('Hack attempt'); + } + + // Permissions object + $perms = $session->fetch_page_acl($id, 'Gallery'); + + if ( !$perms->get_permissions('gal_full_res') && $type == 'full' ) + { + $type = 'preview'; + } + + $q = $db->sql_query('SELECT img_filename, img_time_mod, is_folder FROM '.table_prefix.'gallery WHERE img_id=' . $id . ';'); + if ( !$q ) + $db->_die(); + + if ( $db->numrows() < 1 ) + die('Image not found'); + + $row = $db->fetchrow(); + + switch ( $type ) + { + case 'thumb': + $filename = ENANO_ROOT . '/cache/' . $row['img_filename'] . '-thumb.jpg'; + $mimetype = 'image/jpeg'; + break; + case 'preview': + $filename = ENANO_ROOT . '/cache/' . $row['img_filename'] . '-preview.jpg'; + $mimetype = 'image/jpeg'; + break; + case 'full': + $filename = ENANO_ROOT . '/files/' . $row['img_filename']; + $ext = get_file_extension($filename); + switch($ext) + { + case 'png': $mimetype = 'image/png'; break; + case 'gif': $mimetype = 'image/gif'; break; + case 'bmp': $mimetype = 'image/bmp'; break; + case 'jpg': case 'jpeg': $mimetype = 'image/jpeg'; break; + case 'tif': case 'tiff': $mimetype = 'image/tiff'; break; + default: $mimetype = 'application/octet-stream'; + } + break; + default: + die('PHP...insane...'); + break; + } + + // Make sure we have permission to read this image + if ( !$perms->get_permissions('read') ) + { + $filename = ENANO_ROOT . '/plugins/gallery/denied.png'; + $mimetype = 'image/png'; + } + + if ( $row['is_folder'] == '1' ) + { + $filename = ENANO_ROOT . '/plugins/gallery/folder.png'; + $mimetype = 'image/png'; + } + + if ( !file_exists($filename) ) + die('Can\'t retrieve image file ' . $filename); + + $contents = file_get_contents($filename); + + header('Content-type: ' . $mimetype); + header('Content-length: ' . strlen($contents)); + header('Last-Modified: ' . date('r', $row['img_time_mod'])); + + echo $contents; + +} + +?> diff -r 000000000000 -r 7caf561c50ee plugins/gallery/folder.png Binary file plugins/gallery/folder.png has changed diff -r 000000000000 -r 7caf561c50ee plugins/gallery/functions.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/gallery/functions.php Wed Jul 25 16:36:26 2007 -0400 @@ -0,0 +1,317 @@ +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
'; + // $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:
'.print_r($hier,true).print_r($lookup_table,true).print_r($persist_orphans,true).'
'); + } + 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, '', $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 .= '  '; + + $html .= '
'; + + 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; +} + +?> diff -r 000000000000 -r 7caf561c50ee plugins/gallery/gallery-bits.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/gallery/gallery-bits.js Wed Jul 25 16:36:26 2007 -0400 @@ -0,0 +1,24 @@ +/* + * Misc functions for Enano.Img Gallery. + */ + +function gal_toggle(elem, img, img_open, img_close) +{ + if ( !img_close || !img_open ) + { + img_close = scriptPath + '/plugins/gallery/toggle-closed.png'; + img_open = scriptPath + '/plugins/gallery/toggle-open.png'; + } + if ( elem.style.display == 'block' ) + { + elem.style.display = 'none'; + img.src = img_close; + } + else + { + elem.style.display = 'block'; + img.src = img_open; + } +} + + diff -r 000000000000 -r 7caf561c50ee plugins/gallery/next-prelight.gif Binary file plugins/gallery/next-prelight.gif has changed diff -r 000000000000 -r 7caf561c50ee plugins/gallery/next.gif Binary file plugins/gallery/next.gif has changed diff -r 000000000000 -r 7caf561c50ee plugins/gallery/nssetup.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/gallery/nssetup.php Wed Jul 25 16:36:26 2007 -0400 @@ -0,0 +1,31 @@ +attachHook('acl_rule_init', 'gallery_setup_namespace($this);'); + +function gallery_setup_namespace(&$paths) +{ + global $db, $session, $paths, $template, $plugins; // Common objects + + $paths->create_namespace('Gallery', 'Image:'); + + $session->register_acl_type('gal_full_res', AUTH_ALLOW, 'View image at full resolution', array('read'), 'Gallery'); + + $session->acl_extend_scope('read', 'Gallery', $paths); + $session->acl_extend_scope('post_comments', 'Gallery', $paths); + $session->acl_extend_scope('edit_comments', 'Gallery', $paths); + $session->acl_extend_scope('mod_comments', 'Gallery', $paths); +} + +?> diff -r 000000000000 -r 7caf561c50ee plugins/gallery/prev-prelight.gif Binary file plugins/gallery/prev-prelight.gif has changed diff -r 000000000000 -r 7caf561c50ee plugins/gallery/prev.gif Binary file plugins/gallery/prev.gif has changed diff -r 000000000000 -r 7caf561c50ee plugins/gallery/toggle-closed.png Binary file plugins/gallery/toggle-closed.png has changed diff -r 000000000000 -r 7caf561c50ee plugins/gallery/toggle-head-bg.gif Binary file plugins/gallery/toggle-head-bg.gif has changed diff -r 000000000000 -r 7caf561c50ee plugins/gallery/toggle-open.png Binary file plugins/gallery/toggle-open.png has changed diff -r 000000000000 -r 7caf561c50ee plugins/gallery/upload.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/gallery/upload.php Wed Jul 25 16:36:26 2007 -0400 @@ -0,0 +1,1063 @@ +attachHook('base_classes_initted', ' + global $paths; + $paths->add_page(Array( + \'name\'=>\'Image gallery upload\', + \'urlname\'=>\'GalleryUpload\', + \'namespace\'=>\'Special\', + \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\', + )); + '); + +function page_Special_GalleryUpload() +{ + global $db, $session, $paths, $template, $plugins; // Common objects + + if ( $session->user_level < USER_LEVEL_ADMIN ) + { + die_friendly('Access denied', '

You need to have administrative rights to use the gallery\'s upload features.

'); + } + + $zip_support = ( class_exists('ZipArchive') || ( file_exists('/usr/bin/unzip') && is_executable('/usr/bin/unzip') ) ); + + $errors = array(); + $template->add_header(''); + $template->add_header(''); + + if ( isset($_GET['edit_img']) ) + { + $edit_parms = $_GET['edit_img']; + $regex = '/^((([0-9]+),)*)?([0-9]+?)$/'; + if ( !preg_match($regex, $edit_parms) ) + { + die_friendly('Bad request', '

$_GET[\'edit_img\'] must be a comma-separated list of image IDs.

'); + } + + $idlist = explode(',', $edit_parms); + $num_edit = count($idlist); + $idlist = "SELECT img_id,img_title,img_desc,img_filename,is_folder FROM ".table_prefix."gallery WHERE img_id=" . implode(' OR img_id=', $idlist) . ';'; + + if ( !$e = $db->sql_query($idlist) ) + $db->_die(); + + $template->header(); + + if ( isset($_POST['edit_do_save']) ) + { + @set_time_limit(0); + + $arr_img_data = array(); + while ( $row = $db->fetchrow($e) ) + $arr_img_data[$row['img_id']] = $row; + + // Allow breaking out + switch(true):case true: + + if ( !is_array($_POST['img']) ) + { + $errors[] = 'No images passed to processor.'; + break; + } + + // Main updater loop + foreach ( $_POST['img'] as $img_id => $img_data ) + { + + if ( !preg_match('/^[0-9]+$/', $img_id) ) + { + $errors[] = 'SQL injection attempted!'; + break 2; + } + + // Array of columns to update + $to_update = array(); + + $key = 'reupload_' . $img_data['id']; + if ( isset($_FILES[$key]) ) + { + $file =& $_FILES[ $key ]; + if ( $file['tmp_name'] != '' ) + { + // Reupload + $filename = ENANO_ROOT . '/files/' . $arr_img_data[ $img_data['id'] ]['img_filename']; + if ( !unlink($filename) ) + { + $errors[] = "Could not delete $filename"; + break 2; + } + if ( !@move_uploaded_file($file['tmp_name'], $filename) ) + { + $errors[] = "Could not move uploaded file to $filename"; + break 2; + } + + // + // Create scaled images + // + + // Create thumbnail image + $thumb_filename = ENANO_ROOT . '/cache/' . $arr_img_data[ $img_data['id'] ]['img_filename'] . '-thumb.jpg'; + if ( !unlink($thumb_filename) ) + { + $errors[] = "Could not delete $thumb_filename"; + break 2; + } + $magick = getConfig('imagemagick_path'); + $command = "$magick '{$filename}' -resize ".'"'."80x80>".'"'." -quality 85 $thumb_filename"; + + @system($command, $stat); + + if ( !file_exists($thumb_filename) ) + { + $errors[] = 'Couldn\'t scale image '.$i.': ImageMagick failed us'; + break 2; + } + + // Create preview image + $preview_filename = ENANO_ROOT . '/cache/' . $arr_img_data[ $img_data['id'] ]['img_filename'] . '-preview.jpg'; + if ( !unlink($preview_filename) ) + { + $errors[] = "Could not delete $preview_filename"; + break 2; + } + $magick = getConfig('imagemagick_path'); + $command = "$magick '{$filename}' -resize ".'"'."640x640>".'"'." -quality 85 $preview_filename"; + + @system($command, $stat); + + if ( !file_exists($preview_filename) ) + { + $errors[] = 'Couldn\'t scale image '.$i.': ImageMagick failed us'; + break 2; + } + $to_update['img_time_mod'] = strval(time()); + } + } + + $vars = array( + 'year' => date('Y'), + 'month' => date('F'), + 'day' => date('d'), + 'time12' => date('g:i A'), + 'time24' => date('G:i') + ); + + // Image name/title + + $title = $template->makeParserText($img_data['title']); + $title->assign_vars($vars); + $executed = $title->run(); + if ( $executed == '_id' ) + { + $errors[] = 'You cannot name an image or folder "_id", this name is reserved for internal functions.'; + break 2; + } + if ( $executed == '' ) + { + $errors[] = 'Please enter a name for the item with unique ID ' . $img_data['id'] . '.
' . print_r($_POST,true) . '
'; + break 2; + } + $to_update['img_title'] = $executed; + + // Image description + + if ( isset($img_data['desc']) ) + { + $desc = $template->makeParserText($img_data['desc']); + $desc->assign_vars($vars); + $executed = $desc->run(); + $executed = RenderMan::preprocess_text($executed, false, false); + $to_update['img_desc'] = $executed; + } + + // Folder + $target_folder = false; + + if ( !empty($_POST['override_folder']) ) + { + if ( $_POST['override_folder'] == 'NULL' || preg_match('/^[0-9]+$/', $_POST['override_folder']) ) + { + $target_folder = $_POST['override_folder']; + } + } + + if ( !empty($img_data['folder']) ) + { + if ( $img_data['folder'] == 'NULL' || preg_match('/^[0-9]+$/', $img_data['folder']) ) + { + $target_folder = $img_data['folder']; + } + } + + if ( $target_folder ) + { + $to_update['folder_parent'] = $target_folder; + } + + if ( count($to_update) > 0 ) + { + $up_keys = array_keys($to_update); + $up_vals = array_values($to_update); + + $bin_cols = array('folder_parent'); + + $sql = 'UPDATE ' . table_prefix.'gallery SET '; + + foreach ( $up_keys as $i => $key ) + { + if ( in_array($key, $bin_cols) ) + { + $sql .= $key . '=' . $up_vals[$i] . ','; + } + else + { + $sql .= $key . '=\'' . $db->escape($up_vals[$i]) . '\','; + } + } + + $sql = preg_replace('/,$/i', '', $sql) . ' WHERE img_id=' . $img_data['id'] . ';'; + + if ( !$db->sql_query($sql) ) + { + $db->_die(); + } + + } + + } + + echo '
Your changes have been saved.
'; + + endswitch; + + // Rerun select query to make sure information in PHP memory is up-to-date + if ( !$e = $db->sql_query($idlist) ) + $db->_die(); + + } + + if ( count($errors) > 0 ) + { + echo '
+ The following errors were encountered while updating the image data:
+
    +
  • ' . implode("
  • \n
  • ", $errors) . '
  • +
+
'; + } + + ?> + + '; + + if ( $row = $db->fetchrow($e) ) + { + + echo '
+ '; + echo ' '; + echo ' '; + echo '
Information
+ As with the upload form, the following variables can be used. Note that when editing images, the {id} and {autotitle} variables will be ignored.'; + ?> +
    +
  • {year}: The current year ()
  • +
  • {month}: The current month ()
  • +
  • {day}: The day of the month ()
  • +
  • {time12}: 12-hour time ()
  • +
  • {time24}: 24-hour time ()
  • +
+
+
'; + + $i = 0; + do + { + $thumb_url = makeUrlNS('Special', 'GalleryFetcher/thumb/' . $row['img_id'], false, true); + + # Type: folder + if ( $row['is_folder'] == 1 ): + + // Image ID tracker + echo ''; + + // + // Editor table + // + + $folders = gallery_imgid_to_folder(intval($row['img_id'])); + foreach ( $folders as $j => $xxx ) + { + $folder =& $folders[$j]; + $folder = sanitize_page_id($folder); + } + $folders = array_reverse($folders); + $gal_href = implode('/', $folders) . '/' . sanitize_page_id($row['img_title']); + + echo '
+ '; + + echo ''; + + // Primary key + echo ' + + + '; + + // Path info + echo ' + + + '; + + // Image name + + echo ' + + + '; + + // Mover widget + ?> + + + + + '; + echo ''; + + # Type: image + else: + + // Image ID tracker + echo ''; + + // + // Editor table + // + + echo '
+
Folder: ' . htmlspecialchars($row['img_title']) . '
Unique ID:' . $row['img_id'] . ' (view folder contents)
Parent folders:' . /* Yeah it's dirty, but hey, it gets the job done ;-) */ ( ( $x = str_replace('&raquo;', '»', htmlspecialchars(str_replace('_', ' ', implode(' » ', $folders)))) ) ? $x : '<in root>' ) . '
Folder name:
Move to folder: +
+
+ >> + Select folder +
+
+ +
+ Unselect field +
+
+
'; + + echo ''; + + // Primary key + echo ' + + + '; + + // Thumbnail + + echo ' + + + '; + + // Image name + + echo ' + + + '; + + // Image description + + echo ' + + + '; + + // ACL editor trigger + + echo ' + + + '; + + // Mover widget + ?> + + + + + + + + '; + + // Finish table + echo '
Image: ' . htmlspecialchars($row['img_title']) . '
Unique ID:' . $row['img_id'] . ' (view image\'s page)
Thumbnail:Thumbnail image
Image title:
Image description:
Permissions:
Only works in Firefox 1.5 or later, Safari 3.x or later, or Opera 9.0 or later.
Move to folder: +
+
+ >> + Select folder +
+
+ +
+ Unselect field +
+
+
Upload new version:
'; + echo '
'; + + endif; + + $i++; + } + while ( $row = $db->fetchrow($e) ); + $db->free_result(); + + echo '
+ '; + // Mover widget + if ( $num_edit > 1 ): + ?> + + + + + '; + echo '
Move all to folder:
Other folder fields on this page can override this for individual images.
+
+
+ >> + Select folder +
+ +
+
+
'; + + } + else + { + echo '

No images that matched the ID list could be found.

'; + } + + echo ''; + + $template->footer(); + return; + } + + if ( isset($_GET['rm']) ) + { + $warnings = array(); + + if ( !preg_match('/^[0-9]+$/', $_GET['rm']) ) + die_friendly('Bad Request', '

$_GET[rm] needs to be an integer.

'); + + $rm_id = intval($_GET['rm']); + + if ( isset($_POST['confirmed']) ) + { + // The user confirmed the request. Start plowing through data to decide what to delete. + + // Array of images and folder rows to delete + $del_imgs = array($rm_id); + // Array of files to delete + $del_files = array(); + // Array of comment entries to delete + $del_comments = array(); + + $all_children = gal_fetch_all_children($rm_id); + $del_imgs = array_merge($del_imgs, $all_children); + + $imglist = 'img_id=' . implode(' OR img_id=', $del_imgs); + $sql = "SELECT img_id, img_filename FROM ".table_prefix."gallery WHERE ( $imglist ) AND is_folder!=1;"; + + if ( !$db->sql_query($sql) ) + { + $db->_die(); + } + + while ( $row = $db->fetchrow() ) + { + $files = array( + ENANO_ROOT . '/files/' . $row['img_filename'], + ENANO_ROOT . '/cache/' . $row['img_filename'] . '-thumb.jpg', + ENANO_ROOT . '/cache/' . $row['img_filename'] . '-preview.jpg' + ); + $del_files = array_merge($del_files, $files); + + $del_comments[] = intval($row['img_id']); + } + + $commentlist = 'page_id=\'' . implode('\' OR page_id=\'', $del_imgs) . '\''; + + // Main deletion cycle + + foreach ( $del_files as $file ) + { + @unlink($file) or $warnings[] = 'Could not delete file ' . $file; + } + + if ( !$db->sql_query('DELETE FROM '.table_prefix.'gallery WHERE ' . $imglist . ';') ) + { + $warnings[] = 'Main delete query failed: ' . $db->get_error(); + } + + if ( !$db->sql_query('DELETE FROM '.table_prefix.'comments WHERE ( ' . $commentlist . ' ) AND namespace=\'Gallery\';') ) + { + $warnings[] = 'Comment delete query failed: ' . $db->get_error(); + } + + if ( count($warnings) > 0 ) + { + $template->header(); + + echo '

Error during deletion process

'; + echo '

The deletion process generated some warnings which are shown below.

'; + echo '
  • ' . implode('
  • ', $warnings) . '
'; + + $template->footer(); + } + else + { + redirect(makeUrlNS('Special', 'Gallery'), 'Deletion successful', 'The selected item has been deleted from the gallery. You will now be transferred to the gallery index.', 2); + } + + } + else + { + // Removal form + $template->header(); + + echo '
'; + + echo '

Are you sure you want to delete this item?

'; + echo '

If you continue, this item will be permanently deleted from the gallery – no rollbacks.

'; + echo '

If this is an image, the image files will be removed from the filesystem, and all comments associated with the image will be deleted, as well as the image\'s title, description, and location.

'; + echo '

If this is a folder, all of its contents will be removed. Any images will be removed from the filesystem and all comments and metadata associated with images in this folder or any folders in it will be permanently deleted.

'; + + echo '

'; + + echo '
'; + + $template->footer(); + } + return; + } + + if ( isset($_POST['do_stage2']) ) + { + // Allow breaking out of the validation in the case of an error + switch(true):case true: + + if ( empty($_POST['img_name']) ) + { + $errors[] = 'Please enter an image name.'; + } + + // Validate files + $n_files = intval($_POST['img_count']); + if ( $n_files < 1 ) + { + $errors[] = 'Cannot get image count'; + break; + } + + $files = array(); + + for ( $i = 0; $i < $n_files; $i++ ) + { + $key = "img_$i"; + if ( isset($_FILES[$key]) && !empty($_FILES[$key]['name']) ) + { + $files[] =& $_FILES[$key]; + } + } + + if ( count($files) < 1 ) + { + $errors[] = 'No files specified.'; + break; + } + + $allowed = array('png', 'jpg', 'jpeg', 'tiff', 'tif', 'bmp', 'gif'); + $is_zip = false; + foreach ( $files as $i => $file ) + { + $ext = substr($file['name'], ( strrpos($file['name'], '.') + 1 )); + $ext = strtolower($ext); + if ( !in_array($ext, $allowed) && ( !$zip_support || ( $ext != 'zip' || $i > 0 ) ) ) + { + $errors[] = htmlspecialchars($file['name']) . ' is an invalid extension (' . htmlspecialchars($ext) . ').'; + } + else if ( $ext == 'zip' && $i == 0 && $zip_support ) + { + $is_zip = true; + } + } + + if ( count($errors) > 0 ) + { + // Send error messages + break; + } + + // Parent folder + $folder = $_POST['folder_id']; + if ( $folder != 'NULL' && !preg_match('/^[0-9]+$/', $folder) ) + { + $folder = 'NULL'; + } + + // Format title and description fields + $title = $template->makeParserText($_POST['img_name']); + $desc = $template->makeParserText($_POST['img_desc']); + + $vars = array( + 'year' => date('Y'), + 'month' => date('F'), + 'day' => date('d'), + 'time12' => date('g:i A'), + 'time24' => date('G:i') + ); + + $title->assign_vars($vars); + $desc->assign_vars($vars); + + $idlist = array(); + + // Try to disable the time limit + @set_time_limit(0); + + // Move uploaded files to the files/ directory + foreach ( $files as $i => $__trash ) + { + $file =& $files[$i]; + $ext = substr($file['name'], ( strrpos($file['name'], '.') + 1 )); + $ext = strtolower($ext); + if ( $ext == 'zip' && $is_zip && $zip_support ) + { + // + // Time for some unzipping fun. + // + + // for debugging only + system('rm -fr ' . ENANO_ROOT . '/cache/temp'); + + error_reporting(E_ALL); + + mkdir(ENANO_ROOT . '/cache/temp') or $errors[] = 'Could not create temporary directory for extraction.'; + if ( count($errors) > 0 ) + break 2; + $temp_dir = tempnam(ENANO_ROOT . '/cache/temp', 'galunz'); + if ( file_exists($temp_dir) ) + unlink($temp_dir); + @mkdir($temp_dir); + + // Extract the zip file + if ( class_exists('ZipArchive') ) + { + $zip = new ZipArchive(); + $op = $zip->open($file['tmp_name']); + if ( !$op ) + { + $errors[] = 'Could not open the zip file.'; + break 2; + } + $op = $zip->extractTo($temp_dir); + if ( !$op ) + { + $errors[] = 'Could not extract the zip file.'; + break 2; + } + } + else if ( file_exists('/usr/bin/unzip') ) + { + $cmd = "/usr/bin/unzip -qq -d $temp_dir {$file['tmp_name']}"; + system($cmd); + } + + // Any files? + $file_list = gal_dir_recurse($temp_dir, $dirs); + if ( !$file_list ) + { + $errors[] = 'Could not get file list for temp directory.'; + break 2; + } + if ( count($file_list) < 1 ) + { + $errors[] = 'There weren\'t any files in the uploaded zip file.'; + } + + $dirs = array_reverse($dirs); + $img_files = array(); + + // Loop through and add files + foreach ( $file_list as $file ) + { + $ext = get_file_extension($file); + + if ( in_array($ext, $allowed) ) + { + $img_files[] = $file; + } + else + { + unlink($file); + } + } + + // Main storage loop + $j = 0; + foreach ( $img_files as $file ) + { + $ext = get_file_extension($file); + $stored_name = gallery_make_filename() . ".$ext"; + $store = ENANO_ROOT . '/files/' . $stored_name; + if ( !rename($file, $store) ) + { + $errors[] = 'Could not move file ' . $file . ' to permanent storage location ' . $store . '.'; + break 3; + } + + $autotitle = capitalize_first_letter(basename($file)); + $autotitle = substr($autotitle, 0, ( strrpos($autotitle, '.') )); + $autotitle = str_replace('_', ' ', $autotitle); + + $title->assign_vars(array('id' => ( $j + 1 ), 'autotitle' => $autotitle)); + $desc->assign_vars(array('id' => ( $j + 1 ), 'autotitle' => $autotitle)); + + $local_t = $title->run(); + $local_t = RenderMan::preprocess_text($local_t, true, false); + + $local_d = $desc->run(); + $local_d = RenderMan::preprocess_text($local_d, true, false); + + $subq = '(\'' . $stored_name . '\', \'' . $db->escape($local_t) . '\', \'' . $db->escape($local_d) . '\',\'a:0:{}\', UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), ' . $folder . ')'; + $sql = "INSERT INTO ".table_prefix."gallery(img_filename,img_title,img_desc,print_sizes,img_time_upload,img_time_mod,folder_parent) VALUES{$subq};"; + + if ( !$db->sql_query($sql) ) + $db->_die(); + + $idlist[] = $db->insert_id(); + + // Create thumbnail image + $thumb_filename = ENANO_ROOT . '/cache/' . $stored_name . '-thumb.jpg'; + $magick = getConfig('imagemagick_path'); + $command = "$magick '{$store}' -resize ".'"'."80x80>".'"'." -quality 85 $thumb_filename"; + + @system($command, $stat); + + if ( !file_exists($thumb_filename) ) + { + $errors[] = 'Couldn\'t scale image '.$i.': ImageMagick failed us'; + break 2; + } + + // Create preview image + $preview_filename = ENANO_ROOT . '/cache/' . $stored_name . '-preview.jpg'; + $magick = getConfig('imagemagick_path'); + $command = "$magick '{$store}' -resize ".'"'."640x640>".'"'." -quality 85 $preview_filename"; + + @system($command, $stat); + + if ( !file_exists($preview_filename) ) + { + $errors[] = 'Couldn\'t scale image '.$i.': ImageMagick failed us'; + break 2; + } + + $j++; + } + + // clean up + foreach ( $dirs as $dir ) + { + rmdir($dir); + } + + rmdir( $temp_dir ) or $errors[] = 'Couldn\'t delete the unzip directory.'; + rmdir( ENANO_ROOT . '/cache/temp' ) or $errors[] = 'Couldn\'t delete the temp directory.'; + if ( count($errors) > 0 ) + break 2; + + $idlist = implode(',', $idlist); + $url = makeUrlNS('Special', 'GalleryUpload', "edit_img=$idlist"); + + redirect($url, 'Upload successful', 'Your images have been uploaded successfully. Please wait while you are transferred...', 2); + + break 2; + } + $file['stored_name'] = gallery_make_filename() . '.' . $ext; + $store = ENANO_ROOT . '/files/' . $file['stored_name']; + if ( !@move_uploaded_file($file['tmp_name'], $store) ) + { + $errors[] = "[Internal] Couldn't move temporary file {$file['tmp_name']} to permanently stored file $store"; + break 2; + } + + $autotitle = capitalize_first_letter(basename($file['name'])); + $autotitle = substr($autotitle, 0, ( strrpos($autotitle, '.') )); + $autotitle = str_replace('_', ' ', $autotitle); + + $title->assign_vars(array('id' => ( $i + 1 ), 'autotitle' => $autotitle)); + $desc->assign_vars (array('id' => ( $i + 1 ), 'autotitle' => $autotitle)); + + $local_t = $title->run(); + $local_t = RenderMan::preprocess_text($local_t, true, false); + + $local_d = $desc->run(); + $local_d = RenderMan::preprocess_text($local_d, true, false); + + $subq = '(\'' . $file['stored_name'] . '\', \'' . $db->escape($local_t) . '\', \'' . $db->escape($local_d) . '\',\'a:0:{}\', UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), ' . $folder . ')'; + $sql = "INSERT INTO ".table_prefix."gallery(img_filename,img_title,img_desc,print_sizes,img_time_upload,img_time_mod,folder_parent) VALUES{$subq};"; + + if ( !$db->sql_query($sql) ) + $db->_die(); + + $idlist[] = $db->insert_id(); + + // Create thumbnail image + $thumb_filename = ENANO_ROOT . '/cache/' . $file['stored_name'] . '-thumb.jpg'; + $magick = getConfig('imagemagick_path'); + $command = "$magick '{$store}' -resize ".'"'."80x80>".'"'." -quality 85 $thumb_filename"; + + @system($command, $stat); + + if ( !file_exists($thumb_filename) ) + { + $errors[] = 'Couldn\'t scale image '.$i.': ImageMagick failed us'; + break 2; + } + + // Create preview image + $preview_filename = ENANO_ROOT . '/cache/' . $file['stored_name'] . '-preview.jpg'; + $magick = getConfig('imagemagick_path'); + $command = "$magick '{$store}' -resize ".'"'."640x640>".'"'." -quality 85 $preview_filename"; + + @system($command, $stat); + + if ( !file_exists($preview_filename) ) + { + $errors[] = 'Couldn\'t scale image '.$i.': ImageMagick failed us'; + break 2; + } + + } + + $idlist = implode(',', $idlist); + $url = makeUrlNS('Special', 'GalleryUpload', "edit_img=$idlist"); + + redirect($url, 'Upload successful', 'Your images have been uploaded successfully. Please wait while you are transferred...', 2); + + return; + + endswitch; + } + + // Smart batch-upload interface + $template->header(); + + ?> + + + '; + if ( count($errors) > 0 ) + { + echo '
+ The following errors were encountered during the upload:
+
    +
  • ' . implode("
  • \n
  • ", $errors) . '
  • +
+
'; + } + ?> +
+ + + + + + + + + + + + + + + + + + + + + + + +
Upload images to gallery
Image name template:
Image description template:
+

The name and description templates can contain the following variables:

+
    +
  • {id}: The number of the image (different for each image)
  • +
  • {autotitle}: Let the uploader automatically generate a title, based on the filename (david_in_the_barn.jpg will become "David in the barn"). Sometimes this process can be very dumb (mtrooper2k5.jpg will become "Mtrooper2k5").
  • +
  • {year}: The current year ()
  • +
  • {month}: The current month ()
  • +
  • {day}: The day of the month ()
  • +
  • {time12}: 12-hour time ()
  • +
  • {time24}: 24-hour time ()
  • +
+

Example:

+
+ Image files: + +
+ Your server has support for zip files. + Instead of uploading many image files, you can upload a single zip file here. Note that if you send a zip file through, + it must be the first and only file or it will be ignored. Any files in the zip archive that are not supported image + files will be ignored. + The maximum file size is {$sz}B."; + } + ?> + + +
+
+
+
+
+
+ + +
Upload to folder: +
+
+ >> + Select folder +
+
+ +
+
+
+ + + + + +
+ Please press the Upload button only once! Depending on the size of your image files and the speed of your connection, the upload may take several minutes. + +
+
+
+ '; + + $template->footer(); + +} + +?> diff -r 000000000000 -r 7caf561c50ee plugins/gallery/viewimage.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/gallery/viewimage.php Wed Jul 25 16:36:26 2007 -0400 @@ -0,0 +1,270 @@ +attachHook('page_not_found', 'gallery_namespace_handler($this);'); + +function gallery_namespace_handler(&$page) +{ + global $db, $session, $paths, $template, $plugins; // Common objects + + if ( $page->namespace != 'Gallery' ) + return false; + + if ( $page->page_id == 'Root' ) + { + page_Special_Gallery(); + return true; + } + + if ( preg_match('/^[0-9]+$/', $page->page_id) ) + { + $img_id = intval($page->page_id); + if ( !$img_id ) + return false; + $q = $db->sql_query('SELECT img_id, img_title, img_desc, print_sizes, img_time_upload, img_time_mod, folder_parent FROM '.table_prefix.'gallery WHERE img_id=' . $img_id . ';'); + if ( !$q ) + $db->_die(); + } + else + { + // Ech... he sent us a string... parse it and see what we get + if ( strstr($page->page_id, '/') ) + { + $folders = explode('/', $page->page_id); + } + else + { + $folders = array($page->page_id); + } + foreach ( $folders as $i => $_crap ) + { + $folder =& $folders[$i]; + $folder = dirtify_page_id($folder); + $folder = str_replace('_', ' ', $folder); + } + unset($folder); + + $folders = array_reverse($folders); + // This is one of the best MySQL tricks on the market. We're going to reverse-travel a folder path using LEFT JOIN and the incredible power of metacoded SQL + $sql = 'SELECT g0.img_id, g0.img_title, g0.img_desc, g0.print_sizes, g0.img_time_upload, g0.img_time_mod, g0.folder_parent FROM '.table_prefix.'gallery AS g0'; + $where = "\n " . 'WHERE g0.img_title=\'' . $db->escape($folders[0]) . '\''; + foreach ( $folders as $i => $folder ) + { + if ( $i == 0 ) + continue; + $i_dec = $i - 1; + $folder = $db->escape($folder); + $sql .= "\n LEFT JOIN ".table_prefix."gallery AS g{$i}\n ON ( g{$i}.img_id=g{$i_dec}.folder_parent AND g{$i}.img_title='$folder' )"; + $where .= "\n ".'AND g'.$i.'.img_id IS NOT NULL'; + } + $where .= "\n AND g{$i}.folder_parent IS NULL"; + $sql .= $where . ';'; + + if ( !$db->sql_query($sql) ) + { + $db->_die('The image metadata could not be loaded.'); + } + + // Now that the folder data is no longer needed, we can fool around with it a little + $folders = $page->page_id; + if ( !strstr($folders, '/') ) + { + $hier = '/'; + } + else + { + $hier = preg_replace('/\/([^\/]+)$/', '/', $folders); + $hier = sanitize_page_id($hier); + } + + } + if ( $db->numrows() < 1 ) + { + // Image not found - show custom error message + $template->header(); + echo '

There is no image in the gallery with this ID.

'; + echo '

You have requested an image that couldn\'t be looked up. Please check the URL and try again, or visit the Gallery index.

'; + $template->footer(); + return false; + } + $row = $db->fetchrow(); + + $db->free_result(); + + $img_id = $row['img_id']; + + if ( !$row['folder_parent'] ) + $row['folder_parent'] = ' IS NULL'; + else + $row['folder_parent'] = '=' . $row['folder_parent']; + + // Fetch image parent properties + $q = $db->sql_query('SELECT img_id, img_title FROM '.table_prefix.'gallery WHERE folder_parent' . $row['folder_parent'] . ' AND is_folder!=1 ORDER BY img_title ASC;'); + if ( !$q ) + $db->_die(); + + $folder_total = $db->numrows(); + $folder_this = 0; + $prev = false; + $next = false; + $next_title = ''; + $prev_title = ''; + + $i = 0; + + while ( $r = $db->fetchrow() ) + { + $i++; + if ( $i == $folder_total && $r['img_id'] == $img_id ) + { + $folder_this = $i; + $next = false; + } + else if ( $i < $folder_total && $r['img_id'] == $img_id ) + { + $folder_this = $i; + $next = true; + } + else + { + if ( $next ) + { + $next = $r['img_id']; + $next_title = $r['img_title']; + break; + } + $prev = $r['img_id']; + $prev_title = $r['img_title']; + } + } + + if ( $next ) + { + $next_sanitized = sanitize_page_id($next_title); + $next_url = ( isset($hier) ) ? makeUrlNS('Gallery', $hier . $next_sanitized ) : makeUrlNS('Gallery', $next); + } + if ( $prev ) + { + $prev_sanitized = sanitize_page_id($prev_title); + $prev_url = ( isset($hier) ) ? makeUrlNS('Gallery', $hier . $prev_sanitized ) : makeUrlNS('Gallery', $prev); + } + + $db->free_result(); + + $template->tpl_strings['PAGE_NAME'] = 'Gallery image: ' . htmlspecialchars($row['img_title']); + $title_spacey = strtolower(htmlspecialchars($row['img_title'])); + + $perms = $session->fetch_page_acl(strval($img_id), 'Gallery'); + + $template->header(); + + $img_id = intval($img_id); + $bc_folders = gallery_imgid_to_folder($img_id); + $bc_folders = array_reverse($bc_folders); + $bc_url = ''; + $breadcrumbs = array(); + $breadcrumbs[] = 'Gallery index'; + + foreach ( $bc_folders as $folder ) + { + $bc_url .= '/' . dirtify_page_id($folder); + $breadcrumbs[] = '' . htmlspecialchars($folder) . ''; + } + + $breadcrumbs[] = htmlspecialchars($row['img_title']); + + // From here, this breadcrumb stuff is a piece of... sourdough French bread :-) *smacks lips* + echo '
'; + // The actual breadcrumbs + echo '' . implode(' » ', $breadcrumbs) . ''; + echo '
'; + + echo '
'; + $img_url = makeUrlNS('Special', 'GalleryFetcher/preview/' . $img_id); + $img_href = makeUrlNS('Special', 'GalleryFetcher/full/' . $img_id); + + if ( $perms->get_permissions('gal_full_res') ) + { + echo ''; + } + + echo 'Image preview (640px max width)'; + + if ( $perms->get_permissions('gal_full_res') ) + { + echo ''; + } + + echo ''; + echo ''; + echo '
'; + + // Prev button + if ( $prev ) + echo '< Previous'; + //echo ''; + // if ( $prev ) + // echo 'previous image'; + + echo ''; + + // Image title + echo $title_spacey; + + echo ''; + + // Next button + if ( $next ) + // echo 'next image'; + //echo ''; + if ( $next ) + echo '< Previous'; + + echo '
' . "image $folder_this of $folder_total" . '
'; + echo '
'; + + if ( $session->user_level >= USER_LEVEL_ADMIN ) + { + echo '
[ edit image ]
'; + } + + if ( !empty($row['img_desc']) ) + { + echo '

Image description

'; + + $desc = RenderMan::render($row['img_desc']); + echo $desc; + } + + echo '
+ '; + + // By the time I got to this point, it was 1:32AM (I was on vacation) and my 5-hour playlist on my iPod had been around about 3 times today. + // So I'm glad this is like the last thing on the list tonight. + + echo ''; + echo ''; + echo ''; + + echo '
Image details
Uploaded:' . date('F d, Y h:i a', $row['img_time_upload']) . '
Last modified:' . date('F d, Y h:i a', $row['img_time_mod']) . '
'; + + $template->footer(); + +} + +?>