# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
# All rights reserved. See LICENSE file for licensing details
+if (defined('S9Y_FRAMEWORK_IMAGES')) {
+ return;
+}
+@define('S9Y_FRAMEWORK_IMAGES', true);
+
/**
* Check if an uploaded file is "evil"
*
* @param string Order by DESC or ASC
* @param string Only fetch files from a specific directory
* @param string Only fetch specific filenames
+ * @param string Only fetch media with specific keyword
* @return array Resultset of images
*/
-function serendipity_fetchImagesFromDatabase($start=0, $limit=0, &$total, $order = false, $ordermode = false, $directory = '', $filename = '') {
+function serendipity_fetchImagesFromDatabase($start=0, $limit=0, &$total, $order = false, $ordermode = false, $directory = '', $filename = '', $keywords = '', $filter = array()) {
global $serendipity;
+ $cond = array(
+ 'joinparts' => array(),
+ 'parts' => array(),
+ );
+
$orderfields = serendipity_getImageFields();
if (empty($order) || !isset($orderfields[$order])) {
- $order = 'date';
+ $order = 'i.date';
+ }
+
+ if (!is_array($filter)) {
+ $filter = array();
}
if (empty($ordermode) || ($ordermode != 'DESC' && $ordermode != 'ASC')) {
$ordermode = 'DESC';
}
+ if ($order == 'name') {
+ $order = 'realname ' . $ordermode . ', name';
+ }
+
if ($limit != 0) {
$limitsql = serendipity_db_limit_sql(serendipity_db_limit($start, $limit));
}
if (!empty($directory)) {
- $directorysql = ' WHERE path LIKE \'' . serendipity_db_escape_string($directory) . '%\' ';
+ $cond['parts']['directory'] = " AND i.path LIKE '" . serendipity_db_escape_string($directory) . "%'\n";
}
if (!empty($filename)) {
- if (empty($directorysql)) {
- $directorysql = " WHERE name like '%" . serendipity_db_escape_string($filename) . "%'";
+ $cond['parts']['filename'] = " AND (i.name like '%" . serendipity_db_escape_string($filename) . "%' OR
+ i.realname like '%" . serendipity_db_escape_string($filename) . "%')\n";
+ }
+
+ if (!is_array($keywords)) {
+ if (!empty($keywords)) {
+ $keywords = explode(';', $keywords);
} else {
- $directorysql .= " AND name like '%" . serendipity_db_escape_string($filename) . "%'";
+ $keywords = array();
}
}
- $perm = $permsql = '';
- if (isset($serendipity['authorid']) && !serendipity_checkPermission('adminImagesViewOthers')) {
- $perm = " (i.authorid = 0 OR i.authorid = " . (int)$serendipity['authorid'] . ")";
- if (empty($directorysql)) {
- $directorysql = " WHERE $perm";
+ foreach($keywords AS $i => $keyword) {
+ $keywords[$i] = serendipity_db_escape_string($keyword);
+ }
+
+ if (count($keywords) > 0) {
+ $cond['parts']['keywords'] = " AND (mk.property IN ('" . implode("', '", $keywords) . "'))\n";
+ $cond['joinparts']['keywords'] = true;
+ }
+
+ foreach($filter AS $f => $fval) {
+ if (!isset($orderfields[$f]) || empty($fval)) {
+ continue;
+ }
+
+ if (is_array($fval)) {
+ if (empty($fval['from']) || empty($fval['to'])) {
+ continue;
+ }
+
+ if ($orderfields[$f]['type'] == 'date') {
+ $fval['from'] = serendipity_convertToTimestamp(trim($fval['from']));
+ $fval['to'] = serendipity_convertToTimestamp(trim($fval['to']));
+ }
+
+ if (substr($f, 0, 3) === 'bp.') {
+ $realf = substr($f, 3);
+ $cond['parts']['filter'] .= " AND (bp2.property = '$realf' AND bp2.value >= " . (int)$fval['from'] . " AND bp2.value <= " . (int)$fval['to'] . ")\n";
+ } else {
+ $cond['parts']['filter'] .= " AND ($f >= " . (int)$fval['from'] . " AND $f <= " . (int)$fval['to'] . ")\n";
+ }
+ } elseif ($f == 'i.authorid') {
+ $cond['parts']['filter'] .= " AND (
+ (hp.property = 'authorid' AND hp.value = " . (int)$fval . ")
+ OR
+ (i.authorid = " . (int)$fval . ")
+ )\n";
+ $cond['joinparts']['hiddenproperties'] = true;
+ } elseif ($orderfields[$f]['type'] == 'int') {
+ if (substr($f, 0, 3) === 'bp.') {
+ $realf = substr($f, 3);
+ $cond['parts']['filter'] .= " AND (bp2.property = '$realf' AND bp2.value = '" . serendipity_db_escape_string(trim($fval)) . "')\n";
+ } else {
+ $cond['parts']['filter'] .= " AND ($f = '" . serendipity_db_escape_string(trim($fval)) . "')\n";
+ }
} else {
- $directorysql .= " AND $perm";
+ if (substr($f, 0, 3) === 'bp.') {
+ $realf = substr($f, 3);
+ $cond['parts']['filter'] .= " AND (bp2.property = '$realf' AND bp2.value LIKE '%" . serendipity_db_escape_string(trim($fval)) . "%')\n";
+ } else {
+ $cond['parts']['filter'] .= " AND ($f LIKE '%" . serendipity_db_escape_string(trim($fval)) . "%')\n";
+ }
}
- $permsql = " WHERE $perm";
+ $cond['joinparts']['filterproperties'] = true;
+ }
+
+ if (isset($serendipity['authorid']) && !serendipity_checkPermission('adminImagesViewOthers')) {
+ $cond['parts']['authorid'] .= " AND (i.authorid = 0 OR i.authorid = " . (int)$serendipity['authorid'] . ")\n";
}
- $query = "SELECT i.*, a.realname AS authorname FROM {$serendipity['dbPrefix']}images AS i LEFT OUTER JOIN {$serendipity['dbPrefix']}authors AS a ON i.authorid = a.authorid $directorysql ORDER BY i.$order $ordermode $limitsql";
+ $cond['and'] = 'WHERE 1=1 ' . implode("\n", $cond['parts']);
+ $cond['args'] = func_get_args();
+ serendipity_plugin_api::hook_event('fetch_images_sql', $cond);
+ serendipity_ACL_SQL($cond, false, 'directory');
+
+ if ($cond['joinparts']['keywords']) {
+ $cond['joins'] .= "\n LEFT OUTER JOIN {$serendipity['dbPrefix']}mediaproperties AS mk
+ ON (mk.mediaid = i.id AND mk.property_group = 'base_keyword')\n";
+ }
+
+ if (substr($order, 0, 3) === 'bp.') {
+ $cond['orderproperty'] = substr($order, 3);
+ $cond['orderkey'] = 'bp.value';
+ $order = 'bp.value';
+ $cond['joinparts']['properties'] = true;
+ } else {
+ $cond['orderkey'] = "''";
+ }
+
+ if ($cond['joinparts']['properties']) {
+ $cond['joins'] .= "\n LEFT OUTER JOIN {$serendipity['dbPrefix']}mediaproperties AS bp
+ ON (bp.mediaid = i.id AND bp.property_group = 'base_property' AND bp.property = '{$cond['orderproperty']}')\n";
+ }
+
+ if ($cond['joinparts']['filterproperties']) {
+ $cond['joins'] .= "\n LEFT OUTER JOIN {$serendipity['dbPrefix']}mediaproperties AS bp2
+ ON (bp2.mediaid = i.id AND bp2.property_group = 'base_property')\n";
+ }
+
+ if ($cond['joinparts']['hiddenproperties']) {
+ $cond['joins'] .= "\n LEFT OUTER JOIN {$serendipity['dbPrefix']}mediaproperties AS hp
+ ON (hp.mediaid = i.id AND hp.property_group = 'base_hidden')\n";
+ }
+
+ if ($serendipity['dbType'] == 'postgres') {
+ $cond['group'] = '';
+ $cond['distinct'] = 'DISTINCT';
+ } else {
+ $cond['group'] = 'GROUP BY i.id';
+ $cond['distinct'] = '';
+ }
+
+ $basequery = "FROM {$serendipity['dbPrefix']}images AS i
+ LEFT OUTER JOIN {$serendipity['dbPrefix']}authors AS a
+ ON i.authorid = a.authorid
+ {$cond['joins']}
+
+ {$cond['and']}";
+
+ $query = "SELECT {$cond['distinct']} i.id, {$cond[orderkey]} AS orderkey, i.name, i.extension, i.mime, i.size, i.dimensions_width, i.dimensions_height, i.date, i.thumbnail_name, i.authorid, i.path, i.hotlink, i.realname,
+ a.realname AS authorname
+ $basequery
+ {$cond['group']}
+ ORDER BY $order $ordermode $limitsql";
+
$rs = serendipity_db_query($query, false, 'assoc');
- if (!is_array($rs)) {
+
+ if (!is_array($rs) && $rs !== true && $rs !== 1) {
+ echo '<div>' . $rs . '</div>';
+ return array();
+ } elseif (!is_array($rs)) {
return array();
}
- $total_query = "SELECT count(i.id) FROM {$serendipity['dbPrefix']}images AS i LEFT OUTER JOIN {$serendipity['dbPrefix']}authors AS a on i.authorid = a.authorid $permsql";
- $total_rs = serendipity_db_query($total_query, true, 'num');
+ $total_query = "SELECT count(i.id)
+ $basequery
+ GROUP BY i.id";
+ $total_rs = serendipity_db_query($total_query, false, 'num');
if (is_array($total_rs)) {
- $total = $total_rs[0];
+ $total = count($total_rs);
}
return $rs;
* @param int The ID of an media item
* @return array The media info data
*/
-function serendipity_fetchImageFromDatabase($id) {
+function serendipity_fetchImageFromDatabase($id, $mode = 'read') {
global $serendipity;
- $rs = serendipity_db_query("SELECT * FROM {$serendipity['dbPrefix']}images WHERE id = ". (int)$id, true, 'assoc');
+
+ if (is_array($id)) {
+ $cond = array(
+ 'and' => "WHERE i.id IN (" . implode(',', $id) . ")"
+ );
+ $single = false;
+ $assocKey = 'id';
+ $assocVal = false;
+ } else {
+ $cond = array(
+ 'and' => "WHERE i.id = " . (int)$id
+ );
+ $single = true;
+ $assocKey = false;
+ $assocVal = false;
+ }
+
+ if ($serendipity['dbType'] == 'postgres') {
+ $cond['group'] = '';
+ $cond['distinct'] = 'DISTINCT';
+ } else {
+ $cond['group'] = 'GROUP BY i.id';
+ $cond['distinct'] = '';
+ }
+
+ serendipity_ACL_SQL($cond, false, 'directory', $mode);
+
+ $rs = serendipity_db_query("SELECT {$cond['distinct']} i.id, i.name, i.extension, i.mime, i.size, i.dimensions_width, i.dimensions_height, i.date, i.thumbnail_name, i.authorid, i.path, i.hotlink, i.realname
+ FROM {$serendipity['dbPrefix']}images AS i
+ {$cond['joins']}
+ {$cond['and']}
+ {$cond['group']}", $single, 'assoc', false, $assocKey, $assocVal);
return $rs;
}
$dThumb = array();
$file = serendipity_fetchImageFromDatabase($id);
+
+ if (!is_array($file) || !isset($file['path'])) {
+ printf(FILE_NOT_FOUND . '<br />', $id);
+ return false;
+ }
+
$dFile = $file['path'] . $file['name'] . '.' . $file['extension'];
$dThumb = array(array(
}
serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}images WHERE id = ". (int)$id);
-
+ serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}mediaproperties WHERE mediaid = ". (int)$id);
}
/**
$basedir = $serendipity['serendipityPath'] . $serendipity['uploadPath'];
$images = array();
if ($dir = @opendir($basedir . $odir)) {
- while(false !== ($f = readdir($dir))) {
- if ($f != '.' && $f != '..' && $f != '.svn' && $f != 'CVS' && strpos($f, $serendipity['thumbSuffix']) === false) {
- $cdir = ($odir != '' ? $odir . '/' : '');
- if (is_dir($basedir . $odir . '/' . $f)) {
- $temp = serendipity_fetchImages($group, $start, $end, $images, $cdir . $f);
- foreach($temp AS $tkey => $tval) {
- array_push($images, $tval);
- }
- } else {
- array_push($images, $cdir . $f);
+ $aTempArray = array();
+ while (($file = @readdir($dir)) !== false) {
+ if ($file == '.svn' || $file == 'CVS' || $file == '.' || $file == '..') {
+ continue;
+ }
+ array_push($aTempArray, $file);
+ }
+ @closedir($dir);
+ sort($aTempArray);
+ foreach($aTempArray as $f) {
+ if (strpos($f, $serendipity['thumbSuffix']) !== false) {
+ // This is a s9y thumbnail, skip it.
+ continue;
+ }
+
+ $cdir = ($odir != '' ? $odir . '/' : '');
+ if (is_dir($basedir . $odir . '/' . $f)) {
+ $temp = serendipity_fetchImages($group, $start, $end, $images, $cdir . $f);
+ foreach($temp AS $tkey => $tval) {
+ array_push($images, $tval);
}
+ } else {
+ array_push($images, $cdir . $f);
}
}
}
dimensions_width,
dimensions_height,
path,
- hotlink
+ hotlink,
+ realname
) VALUES (
'%s',
%s,
%s,
%s,
'%s',
- 1
+ 1,
+ '%s'
)",
serendipity_db_escape_string($filebase),
(int)$time,
(int)$filesize,
(int)$width,
(int)$height,
- serendipity_db_escape_string($url)
+ serendipity_db_escape_string($url),
+ serendipity_db_escape_string($filename)
);
$sql = serendipity_db_query($query);
* @param int The timestamp of when the media item was inserted
* @return int The new media ID
*/
-function serendipity_insertImageInDatabase($filename, $directory, $authorid = 0, $time = NULL) {
+function serendipity_insertImageInDatabase($filename, $directory, $authorid = 0, $time = NULL, $realname = NULL) {
global $serendipity;
- if ( is_null($time) ) {
+ if (is_null($time)) {
$time = time();
}
+ if (is_null($realname)) {
+ $realname = $filename;
+ }
+
$filepath = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $directory . $filename;
$filesize = @filesize($filepath);
thumbnail_name,
date,
authorid,
- path
+ path,
+ realname
) VALUES (
'%s',
'%s',
'%s',
%s,
%s,
+ '%s',
'%s'
)",
serendipity_db_escape_string($filebase),
serendipity_db_escape_string($thumbnail),
(int)$time,
(int)$authorid,
- serendipity_db_escape_string($directory)
+ serendipity_db_escape_string($directory),
+ serendipity_db_escape_string($realname)
);
$sql = serendipity_db_query($query);
* @param string The directory to the image file
* @param string The target size of the thumbnail (2-dimensional array width,height)
* @param string Name of the thumbnail
+ * @param bool Store thumbnail in temporary place?
+ * @param bool Force enlarging of small images?
* @return array The result size of the thumbnail
*/
-function serendipity_makeThumbnail($file, $directory = '', $size = false, $thumbname = false) {
+function serendipity_makeThumbnail($file, $directory = '', $size = false, $thumbname = false, $is_temporary = false, $force_resize = false) {
global $serendipity;
if ($size === false) {
$infile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $directory . $file;
- $outfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $directory . $f . '.' . $thumbname . '.' . $suf;
+# echo 'From: ' . $infile . '<br />';
+ if ($is_temporary) {
+ $temppath = dirname($thumbname);
+ if (!is_dir($temppath)) {
+ @mkdir($temppath);
+ }
+ $outfile = $thumbname;
+ } else {
+ $outfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $directory . $f . '.' . $thumbname . '.' . $suf;
+ }
+# echo 'To: ' . $outfile . '<br />';
$fdim = @serendipity_getimagesize($infile, '', $suf);
if (isset($fdim['noimage'])) {
$r = array(0, 0);
} else {
if ($serendipity['magick'] !== true) {
- $r = serendipity_resize_image_gd($infile, $outfile, $size);
+ if (is_array($size)) {
+ $r = serendipity_resize_image_gd($infile, $outfile, $size['width'], $size['height']);
+ } else {
+ $r = serendipity_resize_image_gd($infile, $outfile, $size);
+ }
} else {
- $r = array($size, $size);
- $newSize = $size . 'x' . $size;
+ if (is_array($size)) {
+ $r = $size;
+ } else {
+ $r = array('width' => $size, 'height' => $size);
+ }
+ $newSize = $r['width'] . 'x' . $r['height'];
if ($fdim['mime'] == 'application/pdf') {
$cmd = escapeshellcmd($serendipity['convert']) . ' -antialias -flatten -scale '. serendipity_escapeshellarg($newSize) .' '. serendipity_escapeshellarg($infile) .' '. serendipity_escapeshellarg($outfile . '.png');
} else {
- if ( serendipity_ini_bool(ini_get('safe_mode')) === false ) {
+ if (!$force_resize && serendipity_ini_bool(ini_get('safe_mode')) === false) {
$newSize .= '>'; // Tell imagemagick to not enlarge small images, only works if safe_mode is off (safe_mode turns > in to \>)
}
$cmd = escapeshellcmd($serendipity['convert']) . ' -antialias -resize '. serendipity_escapeshellarg($newSize) .' '. serendipity_escapeshellarg($infile) .' '. serendipity_escapeshellarg($outfile);
}
exec($cmd, $output, $result);
- if ( $result != 0 ) {
+ if ($result != 0) {
echo '<div class="serendipityAdminMsgError">'. sprintf(IMAGICK_EXEC_ERROR, $cmd, $output[0], $result) .'</div>';
$r = false; // return failure
} else {
global $serendipity;
$file = serendipity_fetchImageFromDatabase($id);
+ if (!is_array($file)) {
+ return false;
+ }
$admin = '';
if (!serendipity_checkPermission('adminImagesMaintainOthers') && $file['authorid'] != '0' && $file['authorid'] != $serendipity['authorid']) {
global $serendipity;
$file = serendipity_fetchImageFromDatabase($id);
+ if (!is_array($file)) {
+ return false;
+ }
$admin = '';
if (!serendipity_checkPermission('adminImagesMaintainOthers') && $file['authorid'] != '0' && $file['authorid'] != $serendipity['authorid']) {
$ft_mime = serendipity_guessMime($f[1]);
$fdim = serendipity_getimagesize($ffull, $ft_mime);
- $rs = serendipity_db_query("SELECT * FROM {$serendipity['dbPrefix']}images
- WHERE name = '" . serendipity_db_escape_string($fbase) . "'
- " . ($fdir != '' ? "AND path = '" . serendipity_db_escape_string($fdir) . "'" : '') . "
- AND mime = '" . serendipity_db_escape_string($fdim['mime']) . "'", true, 'assoc');
+ $cond = array(
+ 'and' => "WHERE name = '" . serendipity_db_escape_string($fbase) . "'
+ " . ($fdir != '' ? "AND path = '" . serendipity_db_escape_string($fdir) . "'" : '') . "
+ AND mime = '" . serendipity_db_escape_string($fdim['mime']) . "'"
+ );
+ serendipity_ACL_SQL($cond, false, 'directory');
+
+ $rs = serendipity_db_query("SELECT *
+ FROM {$serendipity['dbPrefix']}images AS i
+ {$cond['joins']}
+
+ {$cond['and']}", true, 'assoc');
if (is_array($rs)) {
$update = array();
$checkfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $rs['path'] . $rs['name'] . '.' . $rs['thumbnail_name'] . '.' . $rs['extension'];
$newheight = $newsizes[1];
}
+ if (is_null($newwidth)) {
+ $newsizes = serendipity_calculate_aspect_size($width, $height, null, $newheight);
+ $newwidth = $newsizes[0];
+ $newheight = $newsizes[1];
+ }
+
$out = imagecreatetruecolor($newwidth, $newheight);
/* Attempt to copy transparency information, this really only works for PNG */
}
imagecopyresampled($out, $in, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
+ @umask(0000);
$func['save']($out, $outfilename, $func['qual']);
+ @chmod($outfilename, 0664);
$out = null;
$in = null;
* @param int Target width
* @return int Target height
*/
-function serendipity_calculate_aspect_size($width, $height, $newwidth) {
+function serendipity_calculate_aspect_size($width, $height, $orig_newwidth, $orig_newheight = null) {
// calculate aspect ratio
- $div_width = $width / $newwidth;
- $div_height = $height / $newwidth;
+ if (!is_null($orig_newheight)) {
+ $div_width = $width / $orig_newheight;
+ $div_height = $height / $orig_newheight;
+ } else {
+ $div_width = $width / $orig_newwidth;
+ $div_height = $height / $orig_newwidth;
+ }
if ($div_width <= 1 && $div_height <= 1) {
// do not scale small images where both sides are smaller than the thumbnail dimensions
$newheight = $height;
$newwidth = $width;
- } elseif ($div_width >= $div_height) {
+ } elseif (is_null($orig_newheight) && $div_width >= $div_height) {
// max width - calculate height, keep width as scaling base
$newheight = round($height / $div_width);
// make sure the height is at least 1 pixel for extreme images
$newheight = ($newheight >= 1 ? $newheight : 1);
- } else {
+ $newwidth = $orig_newwidth;
+ } elseif (is_null($orig_newwidth) && $div_width >= $div_height) {
+ // max width - calculate height, keep width as scaling base
+ $newwidth = round($width / $div_height);
+ // make sure the height is at least 1 pixel for extreme images
+ $newwidth = ($newwidth >= 1 ? $newwidth : 1);
+ $newheight = $orig_newheight;
+ } elseif (is_null($orig_newheight)) {
// max height - calculate width, keep height as scaling base
- $newheight = $newwidth;
+ $newheight = $orig_newwidth;
$newwidth = round($width / $div_height);
// make sure the width is at least 1 pixel for extreme images
$newwidth = ($newwidth >= 1 ? $newwidth : 1);
+ } else {
+ // max height - calculate width, keep height as scaling base
+ $newwidth = $orig_newheight;
+ $newheight = round($height / $div_width);
+ // make sure the width is at least 1 pixel for extreme images
+ $newheight = ($newheight >= 1 ? $newheight : 1);
}
return array($newwidth, $newheight);
* @param string The URL to use for pagination
* @param boolean Show the "upload media item" feature?
* @param boolean Restrict viewing images to a specific directory
- * @return null
+ * @param boolean If TRUE, will echo Smarty output.
+ * @return string Smarty block name
*/
-function serendipity_displayImageList($page = 0, $lineBreak = NULL, $manage = false, $url = NULL, $show_upload = false, $limit_path = NULL) {
+function serendipity_displayImageList($page = 0, $lineBreak = NULL, $manage = false, $url = NULL, $show_upload = false, $limit_path = NULL, $smarty_display = true) {
global $serendipity;
- $sort_row_interval = array(8, 16, 50, 100);
+ static $debug = false;
+
$sortParams = array('perpage', 'order', 'ordermode');
- $importParams = array('adminModule', 'htmltarget', 'filename_only', 'textarea', 'subpage');
+ $importParams = array('adminModule', 'htmltarget', 'filename_only', 'textarea', 'subpage', 'keywords');
$extraParems = '';
$filterParams = array('only_path', 'only_filename');
$serendipity['GET']['only_path'] = serendipity_uploadSecure($limit_path . $serendipity['GET']['only_path'], true);
$serendipity['GET']['only_filename'] = str_replace(array('*', '?'), array('%', '_'), $serendipity['GET']['only_filename']);
- $perPage = (!empty($serendipity['GET']['sortorder']['perpage']) ? $serendipity['GET']['sortorder']['perpage'] : $sort_row_interval[0]);
+ $perPage = (!empty($serendipity['GET']['sortorder']['perpage']) ? $serendipity['GET']['sortorder']['perpage'] : 8);
+ while ($perPage % $lineBreak !== 0) {
+ $perPage++;
+ }
$start = ($page-1) * $perPage;
+ ## SYNCH START ##
+ $aExclude = array("CVS" => true, ".svn" => true);
+ serendipity_plugin_api::hook_event('backend_media_path_exclude_directories', $aExclude);
+ $paths = array();
+ $aFilesOnDisk = array();
+
+ $aResultSet = serendipity_traversePath(
+ $serendipity['serendipityPath'] . $serendipity['uploadPath']. $limit_path,
+ '',
+ false,
+ NULL,
+ 1,
+ NULL,
+ FALSE,
+ $aExclude
+ );
+
+ foreach ($aResultSet AS $sKey => $sFile) {
+ if ($sFile['directory']) {
+ if ($debug) echo "{$sFile['relpath']} is a directory.<br />";
+ array_push($paths, $sFile);
+ } else {
+ if ($debug) echo "{$sFile['relpath']} is a file.<br />";
+ // Store the file in our array, remove any ending slashes
+ $aFilesOnDisk[$sFile['relpath']] = 1;
+ }
+ unset($aResultSet[$sKey]);
+ }
+
+ usort($paths, 'serendipity_sortPath');
+
+ if ($debug) echo "<p>Got files: <pre>" . print_r($aFilesOnDisk, true) . "</pre></p>";
+ $serendipity['current_image_hash'] = md5(serialize($aFilesOnDisk));
+
+ $nTimeStart = microtime_float();
+ // MTG 21/01/06: request all images from the database, delete any which don't exist
+ // on the filesystem, and mark off files from the file list which are already
+ // in the database
+
+ $nCount = 0;
+ if ($serendipity['onTheFlySynch'] && serendipity_checkPermission('adminImagesSync') && $serendipity['current_image_hash'] != $serendipity['last_image_hash']) {
+ $aResultSet = serendipity_db_query("SELECT path, name, extension, thumbnail_name, id
+ FROM {$serendipity['dbPrefix']}images", false, 'assoc');
+ if ($debug) echo "<p>Got images: <pre>" . print_r($aResultSet, true) . "</pre></p>";
+ if (is_array($aResultSet)) {
+ foreach ($aResultSet AS $sKey => $sFile) {
+ serendipity_plugin_api::hook_event('backend_thumbnail_filename_select', $sFile);
+ $sThumbNailFile = '';
+ if (isset($sFile['thumbnail_filename'])) {
+ $sThumbNailFile = $sFile['thumbnail_filename'];
+ } else {
+ $sThumbNailFile = $sFile['path'] . $sFile['name'] . '.' . $sFile['thumbnail_name'] . '.' . $sFile['extension'];
+ }
+
+ $sFileName = $sFile['path'] . $sFile['name'] . '.' . $sFile['extension'];
+ if ($debug) echo "<p>File name is $sFileName,<br />thumbnail is $sThumbNailFile</p>";
+ unset($aResultSet[$sKey]);
+
+ if (isset($aFilesOnDisk[$sFileName])){
+ unset($aFilesOnDisk[$sFileName]);
+ } else {
+ if ($debug) "Deleting Image {$sFile['id']}<br />\n";
+ serendipity_deleteImage($sFile['id']);
+ ++$nCount;
+ }
+
+ unset($aFilesOnDisk[$sThumbNailFile]);
+ }
+ }
+
+ if ($nCount > 0){
+ if ($debug) echo "<p>Cleaned up ".$nCount." database entries</p>";
+ }
+
+ serendipity_set_config_var('last_image_hash', $serendipity['current_image_hash'], 0);
+ $aUnmatchedOnDisk = array_keys($aFilesOnDisk);
+ if ($debug) echo "<p>Got unmatched files: <pre>" . print_r($aUnmatchedOnDisk, true) . "</pre></p>";
+ $nCount = 0;
+ foreach ($aUnmatchedOnDisk AS $sFile) {
+ if (preg_match('@\.' . $serendipity['thumbSuffix'] . '\.@', $sFile)) {
+ if ($debug) echo "<p>Skipping thumbnailed file $sFile</p>";
+ continue;
+ } else {
+ if ($debug) echo "<p>Checking $sFile</p>";
+ }
+
+ // MTG: 21/01/06: put files which have just 'turned up' into the database
+ $aImageData = serendipity_getImageData($sFile);
+ if (serendipity_isImage($aImageData)) {
+ $nPos = strrpos($sFile, "/");
+ if (is_bool($nPos) && !$nPos) {
+ $sFileName = $sFile;
+ $sDirectory = "";
+ } else {
+ ++$nPos;
+ $sFileName = substr($sFile, $nPos);
+ $sDirectory = substr($sFile, 0, $nPos);
+ }
+ if ($debug) echo "<p>Inserting image $sFileName from $sDirectory <pre>" . print_r($aImageData, true) . "</pre> into database</p>";
+ # TODO: Check if the thumbnail generation goes fine with Marty's code
+ serendipity_makeThumbnail($sFileName, $sDirectory);
+ serendipity_insertImageInDatabase($sFileName, $sDirectory);
+ ++$nCount;
+ }
+ }
+
+ if ($nCount > 0) {
+ if ($debug) echo "<p>Inserted ".$nCount." images into the database</p>";
+ }
+ } else {
+ if ($debug) echo "<p>Media Gallery database is up to date</p>";
+ }
+
+ /*
+ $nTimeEnd = microtime_float ( );
+ $nDifference = $nTimeEnd - $nTimeStart;
+ echo "<p> total time taken was " . $nDifference . "</p>";
+ */
+ ## SYNCH FINISHED ##
+
+ ## Aply ACL afterwards:
+ serendipity_directoryACL($paths, 'read');
+
$serendipity['imageList'] = serendipity_fetchImagesFromDatabase(
$start,
$perPage,
(isset($serendipity['GET']['sortorder']['order']) ? $serendipity['GET']['sortorder']['order'] : false),
(isset($serendipity['GET']['sortorder']['ordermode']) ? $serendipity['GET']['sortorder']['ordermode'] : false),
(isset($serendipity['GET']['only_path']) ? $serendipity['GET']['only_path'] : ''),
- (isset($serendipity['GET']['only_filename']) ? $serendipity['GET']['only_filename'] : '')
+ (isset($serendipity['GET']['only_filename']) ? $serendipity['GET']['only_filename'] : ''),
+ (isset($serendipity['GET']['keywords']) ? $serendipity['GET']['keywords'] : ''),
+ (isset($serendipity['GET']['filter']) ? $serendipity['GET']['filter'] : '')
);
$pages = ceil($totalImages / $perPage);
$linkPrevious = '?' . $extraParems . 'serendipity[page]=' . ($page-1);
$linkNext = '?' . $extraParems . 'serendipity[page]=' . ($page+1);
- $sort_order = serendipity_getImageFields();
- $paths = serendipity_traversePath($serendipity['serendipityPath'] . $serendipity['uploadPath']. $limit_path);
-
if (is_null($lineBreak)) {
$lineBreak = floor(750 / ($serendipity['thumbSize'] + 20));
}
-?>
-<form style="display: inline; margin: 0px; padding: 0px;" method="get" action="?">
-<?php
- echo serendipity_setFormToken();
- foreach($serendipity['GET'] AS $g_key => $g_val) {
- if ( !is_array($g_val) && $g_key != 'page' ) {
- echo '<input type="hidden" name="serendipity[' . $g_key . ']" value="' . htmlspecialchars($g_val) . '" />';
- }
- }
-?>
- <table class="serendipity_admin_filters" width="100%">
- <tr>
- <td class="serendipity_admin_filters_headline" colspan="6"><strong><?php echo FILTERS ?></strong> - <?php echo FIND_MEDIA ?></td>
- </tr>
- <tr>
- <td><?php echo FILTER_DIRECTORY ?></td>
- <td><select name="serendipity[only_path]">
- <option value=""> <?php if (!$limit_path) { echo ALL_DIRECTORIES; } else { echo basename($limit_path);}?></option>
- <?php foreach ( $paths as $folder ) { ?>
- <option <?php echo ($serendipity['GET']['only_path'] == $limit_path.$folder['relpath']) ? 'selected="selected"' : '' ?> value="<?php echo $folder['relpath'] ?>"><?php echo str_repeat(' ', $folder['depth']*2) . ' '. $folder['name'] ?></option>
- <?php } ?>
- </select>
- </td>
- <td><?php echo SORT_ORDER_NAME ?></td>
- <td colspan="3"><input type="text" name="serendipity[only_filename]" value="<?php echo htmlspecialchars($serendipity['GET']['only_filename']); ?>" /></td>
- </tr>
- <tr>
- <td class="serendipity_admin_filters_headline" colspan="6"><strong><?php echo SORT_ORDER ?></strong></td>
- </tr>
- <tr>
- <td><?php echo SORT_BY ?></td>
- <td><select name="serendipity[sortorder][order]">
-<?php
- foreach($sort_order AS $so_key => $so_val) {
- echo '<option value="' . $so_key . '" ' . (isset($serendipity['GET']['sortorder']['order']) && $serendipity['GET']['sortorder']['order'] == $so_key ? 'selected="selected"' : '') . '>' . $so_val . '</option>';
- }
-?> </select>
-</td>
- <td><?php echo SORT_ORDER ?></td>
- <td><select name="serendipity[sortorder][ordermode]">
- <option value="DESC" <?php echo (isset($serendipity['GET']['sortorder']['ordermode']) && $serendipity['GET']['sortorder']['ordermode'] == 'DESC' ? 'selected="selected"' : '') ?>><?php echo SORT_ORDER_DESC ?></option>
- <option value="ASC" <?php echo (isset($serendipity['GET']['sortorder']['ordermode']) && $serendipity['GET']['sortorder']['ordermode'] == 'ASC' ? 'selected="selected"' : '') ?>><?php echo SORT_ORDER_ASC ?></option>
- </select>
- </td>
- <td><?php echo FILES_PER_PAGE ?></td>
- <td><select name="serendipity[sortorder][perpage]">
-<?php
- foreach($sort_row_interval AS $so_val) {
- echo '<option value="' . $so_val . '" ' . ($perPage == $so_val ? 'selected="selected"' : '') . '>' . $so_val . '</option>';
- }
-?> </select>
- </td>
- </tr>
- <tr>
- <td align="right" colspan="6">
-<?php
- if ($show_upload) {
-?>
- <input type="button" value="<?php echo htmlspecialchars(ADD_MEDIA); ?>" onclick="location.href='<?php echo $url; ?>&serendipity[adminAction]=addSelect'; return false" class="serendipityPrettyButton" />
-<?php
- }
-?>
- <input type="submit" name="go" value=" - <?php echo GO ?> - " class="serendipityPrettyButton" />
- </td>
- </tr>
-</table>
-</form>
-<?php if ( sizeof($serendipity['imageList']) == 0 ) { ?>
- <div align="center">- <?php echo NO_IMAGES_FOUND ?> -</div>
-<?php } else { ?>
-<table border="0" width="100%">
- <tr>
- <td colspan="<?php echo floor($lineBreak); ?>">
- <table width="100%">
- <tr>
- <td>
- <?php if ( $page != 1 && $page <= $pages ) { ?>
- <a href="<?php echo $linkPrevious ?>" class="serendipityIconLink"><img src="<?php echo serendipity_getTemplateFile('admin/img/previous.png') ?>" /><?php echo PREVIOUS ?></a>
- <?php } ?></td>
- <td align="right">
- <?php if ($page != $pages ) { ?>
- <a href="<?php echo $linkNext ?>" class="serendipityIconLinkRight"><?php echo NEXT ?><img src="<?php echo serendipity_getTemplateFile('admin/img/next.png') ?>" /></a>
- <?php } ?></td>
- </tr>
- </table>
- </td>
- </tr>
- <tr>
-<?php
- $x = 0;
+
+ $dprops = $keywords = array();
+ if ($serendipity['parseMediaOverview']) {
+ $ids = array();
foreach ($serendipity['imageList'] as $k => $file) {
- ++$x; $preview = '';
- $img = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] . (!empty($file['thumbnail_name']) ? '.' . $file['thumbnail_name'] : '') . '.' . $file['extension'];
- $i = @getimagesize($img);
- $file['imgsrc'] = $serendipity['uploadHTTPPath'] . $file['path'] . $file['name'] . (!empty($file['thumbnail_name']) ? '.' . $file['thumbnail_name'] : '') . '.' . $file['extension'];
- $is_image = serendipity_isImage($file);
+ $ids[] = $file['id'];
+ }
+ $allprops =& serendipity_fetchMediaProperties($ids);
+ }
+ if (count($serendipity['imageList']) > 0) {
+ foreach ($serendipity['imageList'] as $k => $file) {
if (!($serendipity['authorid'] == $file['authorid'] || $file['authorid'] == '0' || serendipity_checkPermission('adminImagesViewOthers'))) {
// This is a fail-safe continue. Basically a non-matching file should already be filtered in SQL.
continue;
}
- /* If it is an image, and the thumbnail exists */
- if ($is_image && file_exists($img)) {
- $preview .= '<img src="' . $serendipity['serendipityHTTPPath'] . $file['imgsrc'] . '" border="0" title="' . $file['path'] . $file['name'] . '" alt="'. $file['name'] . '" />';
- if ($url) {
- $preview = '<a href="'. $url .'&serendipity[image]='. $file['id'] .'">'. $preview .'</a>';
- }
- } elseif ($is_image && $file['hotlink']) {
- $sizes = serendipity_calculate_aspect_size($file['dimensions_width'], $file['dimensions_height'], $serendipity['thumbSize']);
- $preview .= '<img src="' . $file['path'] . '" width="' . $sizes[0] . '" height="' . $sizes[1] . '" border="0" title="' . $file['path'] . '" alt="'. $file['name'] . '" />';
- if ($url) {
- $preview = '<a href="'. $url .'&serendipity[image]='. $file['id'] .'">'. $preview .'</a>';
- }
- /* If it's not an image, or the thumbnail does not exist */
- } else {
- $preview .= '<img src="'. serendipity_getTemplateFile('admin/img/mime_unknown.png') .'" title="' . $file['path'] . $file['name'] . ' (' . $file['mime'] . ')" alt="'. $file['mime'] .'" /><br /><span style="font-weight: bold; font-size: 8pt">- ' . (($file['hotlink']) ? MEDIA_HOTLINKED : $file['mime']) .' -</span>';
- if ($url) {
- $preview .= '<br /><a href="' . $url . '&serendipity[image]=' . $file['id'] . '">' . $file['name'] . '.' . $file['extension'] . '</a>';
- }
- $preview .= '</div>';
- }
+ serendipity_prepareMedia($serendipity['imageList'][$k], $url);
-?>
- <td nowrap="nowrap" align="center" valign="<?php echo $manage ? 'top' : 'middle' ?>" width="<?php echo round(1/$lineBreak*100) ?>%" class="serendipity_admin_list_item serendipity_admin_list_item_<?php echo (($i % 2) ? 'even' : 'uneven') ?>">
-<?php
-if ( !$manage ) {
- echo $preview;
-} else { ?>
- <table width="100%" border="0" cellspacing="0" cellpadding="3">
- <tr>
- <td valign="top" width="16" rowspan="3">
-<?php
- if ($serendipity['authorid'] == $file['authorid'] || $file['authorid'] == '0' || serendipity_checkPermission('adminImagesMaintainOthers')) {
- $popupWidth = ($is_image ? ($file['dimensions_width'] + 20) : 600);
- $popupHeight = ($is_image ? ($file['dimensions_height'] + 20) : 500);
-?>
- <img class="serendipityImageButton" title="<?php echo MEDIA_FULLSIZE; ?>" alt="<?php echo MEDIA_FULLSIZE; ?>" src="<?php echo serendipity_getTemplateFile('admin/img/big_zoom.png') ?>" border="0" onclick="F1 = window.open('<?php echo ($file['hotlink'] ? $file['path'] : $serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $file['path'] . $file['name'] . '.'. $file['extension']); ?>','Zoom','height=<?php echo $popupHeight; ?>,width=<?php echo $popupWidth; ?>,top='+ (screen.height-<?php echo $popupHeight ?>)/2 +',left='+ (screen.width-<?php echo $popupWidth ?>)/2 +',toolbar=no,menubar=no,location=no,resize=1,resizable=1<?php echo ($is_image ? '' : ',scrollbars=yes'); ?>');" /><br />
- <img class="serendipityImageButton" title="<?php echo MEDIA_RENAME; ?>" alt="<?php echo MEDIA_RENAME; ?>" src="<?php echo serendipity_getTemplateFile('admin/img/big_rename.png') ?>" border="0" onclick="rename('<?php echo $file['id']; ?>', '<?php echo addslashes($file['name']); ?>')" /><br />
- <?php if ($is_image && !$file['hotlink']) { ?><img class="serendipityImageButton" title="<?php echo IMAGE_RESIZE; ?>" alt="<?php echo IMAGE_RESIZE; ?>" src="<?php echo serendipity_getTemplateFile('admin/img/big_resize.png') ?>" border="0" onclick="location.href='?serendipity[adminModule]=images&serendipity[adminAction]=scaleSelect&serendipity[fid]=<?php echo $file['id']; ?>';" /><br /><?php } ?>
- <?php if ($is_image && !$file['hotlink']) { ?><a href="?serendipity[adminModule]=images&serendipity[adminAction]=rotateCCW&serendipity[fid]=<?php echo $file['id']; ?>"><img class="serendipityImageButton" title="<?php echo IMAGE_ROTATE_LEFT; ?>" alt="<?php echo IMAGE_ROTATE_LEFT; ?>" src="<?php echo serendipity_getTemplateFile('admin/img/big_rotate_ccw.png') ?>" border="0" /><br /><?php } ?>
- <?php if ($is_image && !$file['hotlink']) { ?><a href="?serendipity[adminModule]=images&serendipity[adminAction]=rotateCW&serendipity[fid]=<?php echo $file['id']; ?>"><img class="serendipityImageButton" title="<?php echo IMAGE_ROTATE_RIGHT; ?>" alt="<?php echo IMAGE_ROTATE_RIGHT; ?>" src="<?php echo serendipity_getTemplateFile('admin/img/big_rotate_cw.png') ?>" border="0" /><br /><?php } ?>
- <a href="?serendipity[adminModule]=images&serendipity[adminAction]=delete&serendipity[fid]=<?php echo $file['id']; ?>"><img class="serendipityImageButton" title="<?php echo MEDIA_DELETE; ?>" alt="<?php echo MEDIA_DELETE; ?>" src="<?php echo serendipity_getTemplateFile('admin/img/big_delete.png') ?>" border="0" /><br />
-<?php
- }
-?>
- </td>
- <td height="10" align="left" style="font-weight: bold; font-size: 8pt"><?php echo $file['name'] . '.' . $file['extension']; ?></td>
- <td height="10" align="right" style="font-size: 8pt"><?php echo ($file['authorid'] == '0' ? ALL_AUTHORS : $file['authorname']); ?></td>
- </tr>
- <tr>
- <td align="center" colspan="2"><?php echo $preview ?></td>
- </tr>
- <tr>
- <td colspan="2" height="10" align="center" style="font-size: 8pt">
-<?php
- if ($is_image && !$file['hotlink']) {
- echo ORIGINAL_SHORT . ': ' . $file['dimensions_width'] . 'x' . $file['dimensions_height'] .', ';
- echo THUMBNAIL_SHORT . ': ' . $i[0] . 'x' . $i[1];
- } elseif ($file['hotlink']) {
- echo wordwrap($file['path'], 45, '<br />', 1);
+ if ($serendipity['parseMediaOverview']) {
+ $serendipity['imageList'][$k]['props'] =& $allprops[$file['id']];
+ if (!is_array($serendipity['imageList'][$k]['props']['base_metadata'])) {
+ $serendipity['imageList'][$k]['metadata'] =& serendipity_getMetaData($serendipity['imageList'][$k]['realfile'], $serendipity['imageList'][$k]['header']);
} else {
- echo SORT_ORDER_SIZE . ': ' . number_format(round($file['size']/1024, 2), NUMBER_FORMAT_DECIMALS, NUMBER_FORMAT_DECPOINT, NUMBER_FORMAT_THOUSANDS) . 'kb';
+ $serendipity['imageList'][$k]['metadata'] = $serendipity['imageList'][$k]['props']['base_metadata'];
+ serendipity_plugin_api::hook_event('media_getproperties_cached', $serendipity['imageList'][$k]['metadata'], $serendipity['imageList'][$k]['realfile']);
}
-?>
- </td>
- </tr>
- </table>
-<?php } ?>
- </td>
-<?php
- // Newline?
- if ($x % $lineBreak == 0) {
-?>
- </tr>
- <tr>
-<?php
- }
- }
-?>
- </tr>
-</table>
-<?php
-}
+ serendipity_parseMediaProperties($dprops, $keywords, $serendipity['imageList'][$k], $serendipity['imageList'][$k]['props'], 3, false);
+ }
+ }
+ }
+
+ $smarty_vars = array(
+ 'limit_path' => $limit_path,
+ 'perPage' => $perPage,
+ 'show_upload' => $show_upload,
+ 'page' => $page,
+ 'pages' => $pages,
+ 'linkNext' => $linkNext,
+ 'linkPrevious' => $linkPrevious,
+ 'extraParems' => $extraParems
+ );
+ return serendipity_showMedia(
+ $serendipity['imageList'],
+ $paths,
+ $url,
+ $manage,
+ $lineBreak,
+ true,
+ $smarty_vars,
+ $smarty_display
+ );
} // End serendipity_displayImageList()
/**
/**
* Recursively walk a directory tree
*
+ *
* @access public
* @param string The core directory
* @param string The subdirectory
* @param string A regexp patter to include files
* @param int Level of nesting (recursive use)
* @param int The maximum level of nesting (recursive use)
+ * @param mixed Toggle whether to apply serendipity_directoryACL (false / 'read' / 'write')
+ * @param array An array of directories to skip [passed by plugins, for example]
* @return array Array of files/directories
*/
-function serendipity_traversePath($basedir, $dir='', $onlyDirs=true, $pattern = NULL, $depth = 1, $max_depth = null) {
+function serendipity_traversePath($basedir, $dir='', $onlyDirs = true, $pattern = NULL, $depth = 1, $max_depth = NULL, $apply_ACL = false, $aExcludeDirs = NULL) {
+ if ($aExcludeDirs === null) {
+ $aExcludeDirs = array("CVS" => true, ".svn" => true);
+ }
- $dh = @opendir($basedir . '/' . $dir);
- if ( !$dh ) {
+ $odir = serendipity_dirSlash('end', $basedir) . serendipity_dirSlash('end', $dir);
+ $dh = @opendir($odir);
+ if (!$dh) {
return array();
}
$files = array();
while (($file = @readdir($dh)) !== false) {
- if ( $file != '.' && $file != '..' ) {
- if ( $onlyDirs === false || ($onlyDirs === true && is_dir($basedir . '/' . $dir . '/' . $file)) ) {
- if ( is_null($pattern) || preg_match($pattern, $file) ) {
+ if ($file != '.' && $file != '..') {
+ $bPatternMatch = (is_null($pattern) || preg_match($pattern, $file));
+ $sFullPath = $odir . $file;
+ $bIsDir = is_dir($sFullPath);
+ if ($onlyDirs === false || $bIsDir) {
+ if ($bPatternMatch &&
+ (!$bIsDir || $aExcludeDirs == null || !isset($aExcludeDirs[$file]))) {
$files[] = array(
- 'name' => $file,
- 'depth' => $depth,
- 'relpath' => ltrim(str_replace('\\', '/', $dir) . basename($file) . '/', '/')
+ 'name' => $file,
+ 'depth' => $depth,
+ 'relpath' => ltrim(str_replace('\\', '/', serendipity_dirSlash('end', $dir)) . basename($file) . ($bIsDir ? '/' : ''), '/'),
+ 'directory' => $bIsDir
);
}
}
- if ( is_dir($basedir . '/' . $dir . '/' . $file) && ($max_depth === null || $depth < $max_depth)) {
- $files = array_merge($files, serendipity_traversePath($basedir, $dir . '/' . basename($file) . '/', $onlyDirs, $pattern, ($depth+1), $max_depth));
+
+ if ($bIsDir &&
+ ($max_depth === null || $depth < $max_depth) &&
+ ($aExcludeDirs == null || !isset($aExcludeDirs[$file]))) {
+ $next_dir = serendipity_dirSlash('end', $dir) . basename($file);
+ $files = array_merge($files, serendipity_traversePath($basedir, $next_dir, $onlyDirs, $pattern, ($depth+1), $max_depth, $apply_ACL, $aExcludeDirs));
}
}
}
@closedir($dh);
+
+ if ($depth == 1 && $apply_ACL !== FALSE) {
+ serendipity_directoryACL($files, $apply_ACL);
+ }
+
return $files;
}
+/**
+ * Custom usort() function that properly sorts a path
+ *
+ * @access public
+ * @param array First array
+ * @param array Second array
+ * @return
+ */
+function serendipity_sortPath($a, $b) {
+ return strcasecmp($a['relpath'], $b['relpath']);
+}
+
/**
* Delete a directory with all its files
*
* @return array Array with available, sortable fields
*/
function serendipity_getImageFields() {
- return array(
- 'date' => SORT_ORDER_DATE,
- 'name' => SORT_ORDER_NAME,
- 'authorid' => AUTHOR,
- 'extension' => SORT_ORDER_EXTENSION,
- 'size' => SORT_ORDER_SIZE,
- 'dimensions_width' => SORT_ORDER_WIDTH,
- 'dimensions_height' => SORT_ORDER_HEIGHT
+ global $serendipity;
+
+ $x = array(
+ 'i.date' => array('desc' => SORT_ORDER_DATE,
+ 'type' => 'date'
+ ),
+
+ 'i.name' => array('desc' => SORT_ORDER_NAME
+ ),
+
+ 'i.authorid' => array('desc' => AUTHOR,
+ 'type' => 'authors'
+ ),
+
+ 'i.extension' => array('desc' => SORT_ORDER_EXTENSION
+ ),
+
+ 'i.size' => array('desc' => SORT_ORDER_SIZE,
+ 'type' => 'intrange'
+ ),
+
+ 'i.dimensions_width' => array('desc' => SORT_ORDER_WIDTH,
+ 'type' => 'intrange'
+ ),
+
+ 'i.dimensions_height' => array('desc' => SORT_ORDER_HEIGHT,
+ 'type' => 'intrange'
+ )
);
+
+ $addProp = explode(';', $serendipity['mediaProperties']);
+ foreach($addProp AS $prop) {
+ $parts = explode(':', $prop);
+ $name = $parts[0];
+ $x['bp.' . $name] = array('desc' => (defined('MEDIA_PROPERTY_' . $name) ? constant('MEDIA_PROPERTY_' . $name) : htmlspecialchars($name)));
+ if (preg_match('@date@i', $name)) {
+ $x['bp.' . $name]['type'] = 'date';
+ }
+ if (preg_match('@length@i', $name)) {
+ $x['bp.' . $name]['type'] = 'intrange';
+ }
+ if (preg_match('@dpi@i', $name)) {
+ $x['bp.' . $name]['type'] = 'int';
+ }
+ }
+
+ return $x;
}
/**
function serendipity_escapeshellarg($string) {
return escapeshellarg(str_replace('%', '', $string));
}
+
+/**
+ * Rename a media directory
+ *
+ * @access public
+ * @param string Old directory name
+ * @param string New directory name
+ */
+function serendipity_renameDir($old, $new) {
+}
+
+/**
+ * Makes sure a directory begins with or ends with a "/"
+ *
+ * @access public
+ * @param string Type of where to append/prepend slash ('end', 'start', 'both')
+ * @param string Directory name
+ * @return string Output argument
+ */
+function serendipity_dirSlash($type, $dir) {
+
+ if ($dir == '') {
+ return $dir;
+ }
+
+ if ($type == 'start' || $type == 'both') {
+ if (substr($dir, 0, 1) != '/') {
+ $dir = '/' . $dir;
+ }
+ }
+
+ if ($type == 'end' || $type == 'both') {
+ if (substr($dir, -1) != '/') {
+ $dir .= '/';
+ }
+ }
+
+ return $dir;
+}
+
+/**
+ * Cycle a serendipity_traversePath resultset and apply read/write ACLs.
+ *
+ * @access public
+ * @param array serendipity_traversePath result array
+ * @param string ACL type ('read', 'write')
+ */
+function serendipity_directoryACL(&$paths, $type = 'read') {
+ global $serendipity;
+ static $debug = false;
+
+ if ($debug) {
+ echo "Applying ACL for mode '$type'.<br />\n";
+ }
+
+ if (!is_array($paths)) {
+ return true;
+ }
+
+ $startCount = count($paths);
+ if (serendipity_userLoggedIn() && (!isset($serendipity['enableACL']) || $serendipity['enableACL'] == true)) {
+ // Check if we are a cool superuser. Bail out if we are.
+ if (serendipity_checkPermission('adminImagesMaintainOthers') && serendipity_checkPermission('adminImagesDirectories')) {
+ if (!$debug) {
+ return true;
+ }
+ }
+
+ // Get list of all ACLs for directories.
+ $q = "SELECT a.artifact_index AS directory,
+ a.groupid
+ FROM {$serendipity['dbPrefix']}access AS a
+ WHERE a.artifact_type = 'directory'
+ AND a.artifact_mode = '" . serendipity_db_escape_string($type) . "'";
+ $allowed = serendipity_db_query($q);
+ if (!is_array($allowed)) {
+ return true;
+ }
+
+ // Get a list of all the groups for this user. Pipe it into a usable array.
+ $my_groups =& serendipity_getGroups($serendipity['authorid']);
+ $acl_allowed_groups = array();
+ foreach($my_groups AS $my_group) {
+ $acl_allowed_groups[$my_group['id']] = true;
+ }
+
+ // Iterate every ACL and check if we are allowed to use it.
+ $acl_allowed = array();
+ foreach($allowed AS $row) {
+ $acl_allowed[$row['directory']][$row['groupid']] = true;
+ }
+
+ // Iterate the input path array and check it against ACL.
+ foreach($paths AS $idx => $info) {
+ if (!isset($acl_allowed[$info['relpath']])) {
+ // ACL for directory not set. Assume we are allowed to access.
+ continue;
+ }
+
+ $granted = false;
+ foreach($acl_allowed[$info['relpath']] AS $groupid => $set) {
+ if ($groupid === 0 || isset($acl_allowed_groups[$groupid])) {
+ // We are allowed to access this element
+ $granted = true;
+ break;
+ }
+ }
+
+ if ($granted === false) {
+ // We are not allowed to access this element
+ if ($debug) {
+ echo "ACL for " . $info['relpath'] . " DENIED.<br />\n";
+ }
+ unset($paths[$idx]);
+ } else {
+ if ($debug) {
+ echo "ACL for " . $info['relpath'] . " granted.<br />\n";
+ }
+ }
+ }
+
+ if (count($paths) < $startCount) {
+ if ($debug) {
+ echo "ACL denied all.<br />\n";
+ }
+ return false;
+ }
+ }
+
+ return true;
+}
+
+ /**
+ * Build the name of a thumbnail image file.
+ *
+ * @author MTG
+ * @param string Relative Path
+ * @param string File name
+ * @param string File extension
+ * @param string Thumbnail suffix
+ * @return array Thumbnail path
+ *
+ */
+function serendipity_getThumbNailPath($sRelativePath, $sName, $sExtension, $sThumbName) {
+ $aTempArray = array('path' => $sRelativePath,
+ 'name' => $sName,
+ 'extension' => $sExtension);
+ serendipity_plugin_api::hook_event('backend_thumbnail_filename_select', $aTempArray);
+
+ if (isset($aTempArray['thumbnail_filename'])) {
+ $sThumbNailPath = $aTempArray['thumbnail_filename'];
+ } else {
+ $sThumbNailPath = $sRelativePath . $sName . (!empty($sThumbName) ? '.' . $sThumbName : '') . '.' . $sExtension;
+ }
+
+ return $sThumbNailPath;
+}
+
+ /**
+ * Given a relative path to an image, construct an array containing all
+ * relevant information about that image in the file structure.
+ *
+ * @author MTG
+ * @param string Relative Path
+ * @return array Data about image
+ *
+ */
+function &serendipity_getImageData($sRelativePath) {
+ global $serendipity;
+
+ // First, peel off the file name from the path
+ $nPos = strrpos($sRelativePath, '/');
+ if (is_bool($nPos) && !$nPos) {
+ $sFileName = $sRelativePath;
+ $sDirectory = '';
+ } else {
+ $nLastSlashPos = 1 + $nPos;
+ $sFileName = substr($sRelativePath, $nLastSlashPos);
+ $sDirectory = substr($sRelativePath, 0, $nLastSlashPos);
+ }
+
+ list($sName, $sExtension) = serendipity_parseFileName($sFileName);
+
+ $sImagePath = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $sRelativePath;
+
+ $aSizeData = @serendipity_getimagesize($sImagePath , '', $sExtension);
+ $nWidth = $aSizeData[0];
+ $nHeight = $aSizeData[1];
+ $sMime = $aSizeData['mime'];
+ $nFileSize = @filesize($sImagePath);
+
+ $array = array(
+ 'name' => $sName,
+ 'extension' => $sExtension,
+ 'mime' => $sMime,
+ 'size' => $nFileSize,
+ 'dimensions_width' => $nWidth,
+ 'dimensions_height' => $nHeight,
+ 'path' => $sDirectory,
+ 'authorid' => 0,
+ 'hotlink' => 0,
+ 'id' => $sRelativePath,
+ 'realname' => $sFilename
+ );
+
+ return $array;
+}
+
+/**
+ * Shows the HTML form to add/edit properties of uploaded media items
+ *
+ * @param array Associative array holding an array('image_id', 'target', 'created_thumbnail') that points to the uploaded media
+ * @param int How many keyword checkboxes to display next to each other?
+ * @param boolean Can existing data be modified?
+ * @return boolean
+ *
+ */
+function serendipity_showPropertyForm(&$new_media, $keywordsPerBlock = 3, $is_edit = true) {
+ global $serendipity;
+
+ if (!is_array($new_media) || count($new_media) < 1) {
+ return true;
+ }
+
+ $mirror = array();
+ serendipity_checkPropertyAccess($new_media, $mirror, 'read');
+
+ $editform_hidden = '';
+ if (isset($GLOBALS['image_selector_addvars']) && is_array($GLOBALS['image_selector_addvars'])) {
+ // These variables may come from serendipity_admin_image_selector.php to show embedded upload form
+ foreach($GLOBALS['image_selector_addvars'] AS $imgsel_key => $imgsel_val) {
+ $editform_hidden .= ' <input type="hidden" name="serendipity[' . htmlspecialchars($imgsel_key) . ']" value="' . htmlspecialchars($imgsel_val) . '" />' . "\n";
+ }
+ }
+
+ $dprops = explode(';', $serendipity['mediaProperties']);
+ $keywords = explode(';', $serendipity['mediaKeywords']);
+
+ $now = serendipity_serverOffsetHour();
+ $show = array();
+ foreach($new_media AS $idx => $media) {
+ $props =& serendipity_fetchMediaProperties($media['image_id']);
+
+ $show[$idx] =& $media['internal'];
+ $show[$idx]['image_id'] = $media['image_id'];
+
+ serendipity_prepareMedia($show[$idx]);
+ if (!is_array($props['base_metadata'])) {
+ $show[$idx]['metadata'] =& serendipity_getMetaData($show[$idx]['realfile'], $show[$idx]['header']);
+ } else {
+ $show[$idx]['metadata'] = $props['base_metadata'];
+ serendipity_plugin_api::hook_event('media_getproperties_cached', $show[$idx]['metadata'], $show[$idx]['realfile']);
+ }
+
+ serendipity_parseMediaProperties($dprops, $keywords, $show[$idx], $props, $keywordsPerBlock, $is_edit);
+ }
+
+ $smarty_vars = array(
+ 'is_edit' => $is_edit,
+ 'editform_hidden' => $editform_hidden,
+ 'keywordsPerBlock' => $keywordsPerBlock,
+ 'keywords' => $keywords,
+ 'dprops' => $dprops
+ );
+
+ return serendipity_showMedia(
+ $show,
+ $mirror,
+ $url,
+ false,
+ 1,
+ false,
+ $smarty_vars);
+}
+
+/**
+ * Parse/Convert properties
+ *
+ * @param array Holds the property key array
+ * @param array Holds the keyword key array
+ * @param int Holds the media metadata
+ * @param int Holds the media properties
+ * @param int How many keyword checkboxes to display next to each other?
+ * @param boolean Can existing data be modified?
+ * @return boolean
+ *
+ */
+function serendipity_parseMediaProperties(&$dprops, &$keywords, &$media, &$props, $keywordsPerBlock, $is_edit) {
+ global $serendipity;
+
+ if (!is_array($dprops)) {
+ $dprops = explode(';', $serendipity['mediaProperties']);
+ }
+ if (!is_array($keywords)) {
+ $keywords = explode(';', $serendipity['mediaKeywords']);
+ }
+
+ $media['references'] = serendipity_db_query("SELECT link, name
+ FROM {$serendipity['dbPrefix']}references
+ WHERE entry_id = " . $media['id'] . "
+ AND type = 'media'
+ ORDER BY name DESC
+ LIMIT 15", false, 'assoc');
+ if (!is_array($media['references'])) {
+ $media['references'] = false;
+ }
+
+ foreach($dprops AS $prop) {
+ $type = 'input';
+ $parts = explode(':', trim($prop));
+
+ if (in_array('MULTI', $parts)) {
+ $type = 'textarea';
+ }
+
+ if (preg_match('@(AUDIO|VIDEO|DOCUMENT|IMAGE|ARCHIVE|BINARY)@i', $prop)) {
+ $show_item = false;
+ if ($media['mediatype'] == 'video' && in_array('VIDEO', $parts)) {
+ $show_item = true;
+ }
+
+ if ($media['mediatype'] == 'audio' && in_array('AUDIO', $parts)) {
+ $show_item = true;
+ }
+
+ if ($media['mediatype'] == 'image' && in_array('IMAGE', $parts)) {
+ $show_item = true;
+ }
+
+ if ($media['mediatype'] == 'document' && in_array('DOCUMENT', $parts)) {
+ $show_item = true;
+ }
+
+ if ($media['mediatype'] == 'archive' && in_array('ARCHIVE', $parts)) {
+ $show_item = true;
+ }
+
+ if ($media['mediatype'] == 'binary' && in_array('BINARY', $parts)) {
+ $show_item = true;
+ }
+
+ if (!$show_item) {
+ continue;
+ }
+ }
+
+ if (!$is_edit) {
+ $type = 'readonly';
+ }
+ $val =& serendipity_mediaTypeCast($parts[0], $props['base_property'][$parts[0]], true);
+
+ $propkey = htmlspecialchars($parts[0]) . $idx;
+
+ $media['base_property'][$propkey] = array(
+ 'label' => htmlspecialchars(defined('MEDIA_PROPERTY_' . strtoupper($parts[0])) ? constant('MEDIA_PROPERTY_' . strtoupper($parts[0])) : $parts[0]),
+ 'type' => $type,
+ 'val' => $val,
+ 'title' => htmlspecialchars($parts[0])
+ );
+
+ if (empty($val)) {
+ switch($parts[0]) {
+ case 'DATE':
+ $media['base_property'][$propkey]['val'] = serendipity_strftime(DATE_FORMAT_SHORT, serendipity_pickKey($media['metadata'], 'DateCreated', $now));
+ break;
+
+ case 'RUN_LENGTH':
+ $media['base_property'][$propkey]['val'] = serendipity_pickKey($media['metadata'], 'RunLength', '00:00:00.00');
+ break;
+
+ case 'DPI':
+ $media['base_property'][$propkey]['val'] = serendipity_pickKey($media['metadata'], 'XResolution', 72);
+ break;
+
+ case 'COPYRIGHT':
+ $media['base_property'][$propkey]['val'] = serendipity_pickKey($media['metadata'], 'Creator', $serendipity['serendipityUser']);
+ break;
+
+ case 'TITLE':
+ $media['base_property'][$propkey]['val'] = serendipity_pickKey($media['metadata'], 'Title', $media['internal']['realname']);
+ break;
+
+ case 'COMMENT1':
+ $media['base_property'][$propkey]['val'] = serendipity_pickKey($media['metadata'], 'Keywords', '');
+ break;
+
+ case 'COMMENT2':
+ $media['base_property'][$propkey]['val'] = serendipity_pickKey($media['metadata'], 'PhotoLocation', '');
+ break;
+
+ default:
+ serendipity_plugin_api::hook_event('media_showproperties', $media, $propkey);
+ break;
+ }
+ }
+ }
+
+ if ($keywordsPerBlock > 0) {
+ $rows = ceil(count($keywords) / $keywordsPerBlock);
+ for($i = 0; $i < $rows; $i++) {
+ for ($j = 0; $j < $keywordsPerBlock; $j++) {
+ $kidx = ($i*$keywordsPerBlock) + $j;
+ if (isset($keywords[$kidx])) {
+ $media['base_keywords'][$i][$j] = array(
+ 'name' => htmlspecialchars($keywords[$kidx]),
+ 'selected' => isset($props['base_keyword'][$keywords[$kidx]]) ? true : false
+ );
+ } else {
+ $media['base_keywords'][$i][$j] = array();
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Tries to auto-convert specific fields into DB-storable values
+ *
+ * @param string The keyname
+ * @param string The value
+ * @param string Invert?
+ * @return array array('image_id') holding the last created thumbnail for immediate processing
+ *
+ */
+function serendipity_mediaTypeCast($key, $val, $invert = false) {
+ if (stristr($key, 'date') !== FALSE) {
+ if ($invert && is_numeric($val)) {
+ return serendipity_strftime(DATE_FORMAT_SHORT, $val, false);
+ } elseif ($invert === false) {
+ $tmp = strtotime($val);
+ if ($tmp !== FALSE && $tmp > 1) {
+ return $tmp;
+ }
+ }
+ } elseif ($invert && stristr($key, 'length') !== FALSE) {
+ $tmp = '';
+
+ $hours = intval(intval($val) / 3600);
+ $minutes = intval(($val / 60) % 60);
+ $seconds = intval($val % 60);
+ $mseconds = intval((($val - $seconds) * 100) % 100);
+
+ $tmp .= str_pad($hours, 2, '0', STR_PAD_LEFT) . ':';
+ $tmp .= str_pad($minutes, 2, '0', STR_PAD_LEFT). ':';
+ $tmp .= str_pad($seconds, 2, '0', STR_PAD_LEFT) . '.';
+ $tmp .= str_pad($mseconds, 2, '0', STR_PAD_LEFT);
+
+ return $tmp;
+ } elseif ($invert === false && preg_match('@^([0-9]+):([0-9]+):([0-9]+).([0-9]+)$@i', $val, $m)) {
+ $tmp = ($m[1] * 3600)
+ + ($m[2] * 60)
+ + ($m[3])
+ + ($m[4] / 100);
+ return $tmp;
+ }
+
+ return $val;
+}
+
+/**
+ * Inserts media properties
+ *
+ * @param string Property_group
+ * @return array array('image_id') holding the last created thumbnail for immediate processing
+ *
+ */
+function serendipity_insertMediaProperty($property_group, $property_subgroup = '', $image_id, &$media, $use_cast = true) {
+ global $serendipity;
+
+ serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}mediaproperties
+ WHERE mediaid = " . (int)$image_id . "
+ " . ($property_subgroup != 'ALL' ? "AND property_subgroup = '" . serendipity_db_escape_string($property_subgroup) . "'" : '') . "
+ AND property_group = '" . serendipity_db_escape_string($property_group) . "'");
+
+ if (is_array($media)) {
+ foreach($media AS $key => $val) {
+ if ($key == 'image_id') continue;
+
+ if (is_array($val)) {
+ $use_property_subgroup = $key;
+ $use_val = $val;
+ } else {
+ $use_property_subgroup = $property_subgroup;
+ $use_val = array($key => $val);
+ }
+
+ foreach($use_val AS $insert_key => $insert_val) {
+ if ($use_cast) {
+ $insert_val = serendipity_mediaTypeCast($insert_key, $insert_val);
+ }
+ $q = sprintf("INSERT INTO {$serendipity['dbPrefix']}mediaproperties
+ (mediaid, property_group, property_subgroup, property, value)
+ VALUES (%d, '%s', '%s', '%s', '%s')",
+ $image_id,
+ serendipity_db_escape_string($property_group),
+ serendipity_db_escape_string($useproperty_subgroup),
+ serendipity_db_escape_string($insert_key),
+ serendipity_db_escape_string($insert_val));
+ serendipity_db_query($q);
+ }
+ }
+ }
+}
+
+/**
+ * Inserts the submitted properties of uploaded media items
+ *
+ * @return array array('image_id') holding the last created thumbnail for immediate processing
+ *
+ */
+function serendipity_parsePropertyForm() {
+ global $serendipity;
+
+ if (!is_array($serendipity['POST']['mediaProperties'])) {
+ return false;
+ }
+
+ serendipity_checkPropertyAccess($serendipity['POST']['mediaProperties'], $serendipity['POST']['mediaKeywords'], 'write');
+
+ foreach($serendipity['POST']['mediaProperties'] AS $id => $media) {
+ serendipity_insertMediaProperty('base_property', '', $media['image_id'], $media);
+
+ $s9y_img = $media['internal'];
+ $s9y_img['image_id'] = $media['image_id'];
+ serendipity_prepareMedia($s9y_img);
+ $s9y_img['metadata'] =& serendipity_getMetaData($s9y_img['realfile'], $s9y_img['header']);
+ serendipity_insertMediaProperty('base_metadata', 'ALL', $media['image_id'], $s9y_img['metadata']);
+ $s9y_img['hidden'] = array(
+ 'author' => $serendipity['serendipityUser'],
+ 'authorid' => $serendipity['authorid']
+ );
+ serendipity_insertMediaProperty('base_hidden', '', $media['image_id'], $s9y_img['hidden']);
+
+ if ($serendipity['POST']['oldDir'][$id] != $serendipity['POST']['newDir'][$id]) {
+ serendipity_moveMediaDirectory(
+ serendipity_uploadSecure($serendipity['POST']['oldDir'][$id]),
+ serendipity_uploadSecure($serendipity['POST']['newDir'][$id]),
+ 'filedir',
+ $media['image_id']);
+ }
+ }
+
+ foreach($serendipity['POST']['mediaKeywords'] AS $id => $keywords) {
+ serendipity_insertMediaProperty('base_keyword', '', $serendipity['POST']['mediaProperties'][$id]['image_id'], $keywords);
+ }
+
+ $array = array(
+ 'image_id' => $serendipity['POST']['mediaProperties'][0]['image_id'],
+ );
+
+ return $array;
+}
+
+/**
+ * Fetches existing Media Properties for images
+ *
+ * @param int The media item id
+ * @return array Array of image metadata
+ *
+ */
+function &serendipity_fetchMediaProperties($id) {
+ global $serendipity;
+
+ $sql = "SELECT mediaid, property, property_group, property_subgroup, value
+ FROM {$serendipity['dbPrefix']}mediaproperties
+ WHERE mediaid IN (" . (is_array($id) ? implode(',', $id) : (int)$id) . ")";
+ $rows = serendipity_db_query($sql, false, 'assoc');
+ $props = array();
+ if (is_array($rows)) {
+ foreach($rows AS $row) {
+ if (empty($row['property_subgroup'])) {
+ if (is_array($id)) {
+ $props[$row['mediaid']][$row['property_group']][$row['property']] = $row['value'];
+ } else {
+ $props[$row['property_group']][$row['property']] = $row['value'];
+ }
+ } else {
+ if (is_array($id)) {
+ $props[$row['mediaid']][$row['property_group']][$row['property_subgroup']][$row['property']] = $row['value'];
+ } else {
+ $props[$row['property_group']][$row['property_subgroup']][$row['property']] = $row['value'];
+ }
+ }
+ }
+ }
+ return $props;
+}
+
+/**
+ * Checks if properties to a specific image are allowed to be fetched
+ *
+ * @param array Array of image metadata
+ * @param array Array of additional image metadata
+ * @param string ACL toggle type ('read', 'write')
+ * @return array Stripped Array of image metadata
+ *
+ */
+function serendipity_checkPropertyAccess(&$new_media, &$additional, $mode = 'read') {
+ global $serendipity;
+
+ // Strip out images we don't have access to
+ $ids = array();
+ foreach($new_media AS $id => $item) {
+ $ids[] = $item['image_id'];
+ }
+
+ $valid_images = serendipity_fetchImageFromDatabase($ids, $mode);
+ foreach ($new_media AS $id => $media) {
+ if (!isset($valid_images[$media['image_id']])) {
+ unset($new_media[$id]);
+ unset($additional[$id]);
+ } else {
+ $new_media[$id]['internal'] = $valid_images[$media['image_id']];
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Prepare a media item for showing
+ *
+ * @param array Array of image metadata
+ * @param string URL for maintenance tasks
+ * @return bool
+ *
+ */
+function serendipity_prepareMedia(&$file, $url = '') {
+ global $serendipity;
+ static $full_perm = null;
+
+ if ($full_perm === null) {
+ $full_perm = serendipity_checkPermission('adminImagesMaintainOthers');
+ }
+
+ $sThumbSource = serendipity_getThumbNailPath($file['path'], $file['name'], $file['extension'], $file['thumbnail_name']);
+ $file['full_thumb'] = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $sThumbSource;
+ $file['full_thumbHTTP'] = $serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $sThumbSource;
+
+ if ($file['hotlink']) {
+ $file['full_file'] = $file['path'];
+ $file['show_thumb'] = $file['path'];
+ if (!isset($file['imgsrc'])) {
+ $file['imgsrc'] = $file['show_thumb'];
+ }
+ } else {
+ $file['full_file'] = $serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $file['path'] . $file['name'] . '.'. $file['extension'];
+ $file['show_thumb'] = $file['full_thumbHTTP'];
+ if (!isset($file['imgsrc'])) {
+ $file['imgsrc'] = $serendipity['uploadHTTPPath'] . $file['path'] . $file['name'] . (!empty($file['thumbnail_name']) ? '.' . $file['thumbnail_name'] : '') . '.' . $file['extension'];
+ }
+ }
+
+ if (empty($file['realname'])) {
+ $file['realname'] = $file['name'] . '.' . $file['extension'];
+ }
+ $file['diskname'] = $file['name'] . '.' . $file['extension'];
+
+ $file['links'] = array('imagelinkurl' => $file['full_file']);
+
+ $file['dim'] = @getimagesize($file['full_thumb'], $file['header']);
+ $file['is_image'] = serendipity_isImage($file);
+
+ if ($file['is_image']) {
+ $file['mediatype'] = 'image';
+ } elseif (0 === strpos(strtolower($file['displaymime']), 'video/') || 0 === strpos(strtolower($file['displaymime']), 'application/x-shockwave')) {
+ $file['mediatype'] = 'video';
+ } elseif (0 === strpos(strtolower($file['displaymime']), 'audio/') || 0 === strpos(strtolower($file['displaymime']), 'application/vnd.rn-') || 0 === strpos(strtolower($file['displaymime']), 'application/ogg')) {
+ $file['mediatype'] = 'audio';
+ } elseif (0 === strpos(strtolower($file['displaymime']), 'text/')) {
+ $file['mediatype'] = 'document';
+ } elseif (preg_match('@application/(pdf|rtf|msword|msexcel|excel|x-excel|mspowerpoint|postscript|vnd\.ms*|powerpoint)@i', $file['displaymime'])) {
+ $file['mediatype'] = 'document';
+ } elseif (preg_match('@application/(java-archive|zip|gzip|arj|x-bzip|x-bzip2|x-compressed|x-gzip|x-stuffit)@i', $file['displaymime'])) {
+ $file['mediatype'] = 'archive';
+ } else {
+ $file['mediatype'] = 'binary';
+ }
+
+ $file['realfile'] = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] . '.'. $file['extension'];
+
+ if ($full_perm || $serendipity['authorid'] == $file['authorid'] || $file['authorid'] == '0') {
+ $file['is_editable'] = true;
+ } else {
+ $file['is_editable'] = false;
+ }
+
+ /* If it is an image, and the thumbnail exists */
+ if ($file['is_image'] && file_exists($file['full_thumb'])) {
+ $file['thumbWidth'] = $file['dim'][0];
+ $file['thumbHeight'] = $file['dim'][1];
+ $file['preview'] .= '<img src="' . $serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $sThumbSource . '" border="0" title="' . $file['path'] . $file['name'] . '" alt="'. $file['realname'] . '" />';
+ if ($url) {
+ $file['preview_url'] = $url .'&serendipity[image]='. $file['id'];
+ $file['preview'] = '<a href="'. $file['preview_url'] .'">'. $file['preview'] .'</a>';
+ }
+ } elseif ($file['is_image'] && $file['hotlink']) {
+ $sizes = serendipity_calculate_aspect_size($file['dimensions_width'], $file['dimensions_height'], $serendipity['thumbSize']);
+ $file['thumbWidth'] = $sizes[0];
+ $file['thumbHeight'] = $sizes[1];
+ $file['preview'] .= '<img src="' . $file['path'] . '" width="' . $sizes[0] . '" height="' . $sizes[1] . '" border="0" title="' . $file['path'] . '" alt="'. $file['realname'] . '" />';
+ if ($url) {
+ $file['preview_url'] = $url .'&serendipity[image]='. $file['id'];
+ $file['preview'] = '<a href="'. $file['preview_url'] .'">'. $file['preview'] .'</a>';
+ }
+ /* If it's not an image, or the thumbnail does not exist */
+ } else {
+ $mimeicon = serendipity_getTemplateFile('admin/img/mime_' . preg_replace('@[^a-z0-9\-\_]@i', '-', $file['mime']) . '.png');
+ if (!$mimeicon) {
+ $mimeicon = serendipity_getTemplateFile('admin/img/mime_unknown.png');
+ }
+ $file['preview'] .= '<img src="'. $mimeicon .'" title="' . $file['path'] . $file['name'] . ' (' . $file['mime'] . ')" alt="'. $file['mime'] .'" /><br /><span style="font-weight: bold; font-size: 8pt">- ' . (($file['hotlink']) ? MEDIA_HOTLINKED : $file['mime']) .' -</span>';
+ if ($url) {
+ $file['preview_url'] = $url .'&serendipity[image]='. $file['id'];
+ $file['preview'] .= '<br /><a href="' . $file['preview_url'] . '">' . $file['name'] . '.' . $file['extension'] . '</a>';
+ }
+ }
+
+ $file['popupWidth'] = ($file['is_image'] ? ($file['dimensions_width'] + 20) : 600);
+ $file['popupHeight'] = ($file['is_image'] ? ($file['dimensions_height'] + 20) : 500);
+ if ($file['hotlink']) {
+ $file['nice_hotlink'] = wordwrap($file['path'], 45, '<br />', 1);
+ }
+ $file['nice_size'] = number_format(round($file['size']/1024, 2), NUMBER_FORMAT_DECIMALS, NUMBER_FORMAT_DECPOINT, NUMBER_FORMAT_THOUSANDS);
+
+ return true;
+}
+
+/**
+ * Prints a media item
+ *
+ * @param array Array of image metadata
+ * @param string URL for maintenance tasks
+ * @param boolean Whether to show maintenance task items
+ * @param int how many media items to display per row
+ * @param boolean Enclose within a table cell?
+ * @param array Additional Smarty variables
+ * @param boolean If TRUE, will echo Smarty output.
+ * @return string Smarty block name
+ *
+ */
+function serendipity_showMedia(&$file, &$paths, $url = '', $manage = false, $lineBreak = 3, $enclose = true, $smarty_vars = array(), $smarty_display = true) {
+ global $serendipity;
+
+ $form_hidden = '';
+ foreach($serendipity['GET'] AS $g_key => $g_val) {
+ if (!is_array($g_val) && $g_key != 'page') {
+ $form_hidden .= '<input type="hidden" name="serendipity[' . $g_key . ']" value="' . htmlspecialchars($g_val) . '" />';
+ }
+ }
+
+ serendipity_smarty_init();
+ $media = array(
+ 'manage' => $manage,
+ 'lineBreak' => $lineBreak,
+ 'lineBreakP' => round(1/$lineBreak*100),
+ 'url' => $url,
+ 'enclose' => $enclose,
+ 'zoomIMG' => serendipity_getTemplateFile('admin/img/big_zoom.png'),
+ 'renameIMG' => serendipity_getTemplateFile('admin/img/big_rename.png'),
+ 'resizeIMG' => serendipity_getTemplateFile('admin/img/big_resize.png'),
+ 'rotatecwIMG' => serendipity_getTemplateFile('admin/img/big_rotate_cw.png'),
+ 'rotateccwIMG' => serendipity_getTemplateFile('admin/img/big_rotate_ccw.png'),
+ 'configureIMG' => serendipity_getTemplateFile('admin/img/configure.png'),
+ 'deleteIMG' => serendipity_getTemplateFile('admin/img/big_delete.png'),
+ 'prevIMG' => serendipity_getTemplateFile('admin/img/previous.png'),
+ 'nextIMG' => serendipity_getTemplateFile('admin/img/next.png'),
+ 'token' => serendipity_setFormToken(),
+ 'form_hidden' => $form_hidden,
+ 'blimit_path' => basename($limit_path),
+ 'only_path' => $serendipity['GET']['only_path'],
+ 'only_filename' => $serendipity['GET']['only_filename'],
+ 'sortorder' => $serendipity['GET']['sortorder'],
+ 'keywords_selected' => $serendipity['GET']['keywords'],
+ 'filter' => $serendipity['GET']['filter'],
+ 'sort_order' => serendipity_getImageFields(),
+ 'authors' => serendipity_fetchUsers(),
+ 'sort_row_interval' => array(8, 16, 50, 100),
+ 'nr_files' => count($file),
+ 'keywords' => explode(';', $serendipity['mediaKeywords']),
+ );
+
+ $media = array_merge($media, $smarty_vars);
+ $media['files'] =& $file;
+ if (count($paths) > 0) {
+ $media['paths'] =& $paths;
+ } else {
+ $media['paths'] =& serendipity_getMediaPaths();
+ }
+
+ $serendipity['smarty']->assign_by_ref('media', $media);
+
+ if ($enclose) {
+ serendipity_smarty_fetch('MEDIA_ITEMS', 'admin/media_items.tpl');
+ $block = 'admin/media_pane.tpl';
+ if ($smarty_display) {
+ $serendipity['smarty']->display(serendipity_getTemplateFile('admin/media_pane.tpl', 'serendipityPath'));
+ }
+ } else {
+ serendipity_smarty_fetch('MEDIA_ITEMS', 'admin/media_items.tpl');
+ $block = 'admin/media_properties.tpl';
+ if ($smarty_display) {
+ $serendipity['smarty']->display(serendipity_getTemplateFile('admin/media_properties.tpl', 'serendipityPath'));
+ }
+ }
+
+ return $block;
+}
+
+/**
+ * Convert a IPTC/EXIF/XMP item
+ *
+ * @param string The content
+ * @param string The type of the content
+ * @return string The converted content
+ *
+ */
+function serendipity_metaFieldConvert(&$item, $type) {
+ switch($type) {
+ case 'math':
+ $parts = explode('/', $item);
+ return ($parts[0] / $parts[1]);
+ break;
+
+ case 'or':
+ if ($item == '1') {
+ return 'Landscape';
+ } else {
+ return 'Portrait';
+ }
+
+ case 'date':
+ return strtotime($item);
+ break;
+
+ case 'date2':
+ $parts = explode(':', $item);
+ return mktime($parts[3], $parts[4], $parts[5], $parts[1], $parts[2], $parts[0]);
+ break;
+
+ case 'rdf':
+ if (preg_match('@<rdf:li[^>]*>(.*)</rdf:li>@i', $item, $ret)) {
+ return $ret[1];
+ }
+ break;
+
+ case 'text':
+ default:
+ return trim($item);
+ break;
+ }
+
+ return '';
+}
+
+/**
+ * Get the RAW media header data (XMP)
+ *
+ * @param string Filename
+ * @return array The raw media header data
+ *
+ * Inspired, but rewritten, by "PHP JPEG Metadata Toolkit" from http://electronics.ozhiker.com.
+ * Code is GPL so sadly we couldn't bundle that GREAT library.
+ */
+function serendipity_getMediaRaw($filename) {
+ $abort = false;
+
+ $f = @fopen($filename, 'rb');
+ $ret = array();
+ if (!$f) {
+ return $ret;
+ }
+
+ $filedata = fread($f, 2);
+
+ if ($filedata != "\xFF\xD8") {
+ fclose($f);
+ return $ret;
+ }
+
+ $filedata = fread($f, 2);
+
+ if ($filedata{0} != "\xFF") {
+ fclose($f);
+ return $ret;
+ }
+
+ while (!$abort && !feof($f) && $filedata{1} != "\xD9") {
+ if ((ord($filedata{1}) < 0xD0) || (ord($filedata{1}) > 0xD7)) {
+ $ordret = fread($f, 2);
+ $ordstart = ftell($f);
+ $int = unpack('nsize', $ordret);
+
+ if (ord($filedata{1}) == 225) {
+ $content = fread($f, $int['size'] - 2);
+
+ if (substr($content, 0, 24) == 'http://ns.adobe.com/xap/') {
+ $ret[] = array(
+ 'ord' => ord($filedata{1}),
+ 'ordstart' => $ordstart,
+ 'int' => $int,
+ 'content' => $content
+ );
+ }
+ } else {
+ fseek($f, $int['size'] - 2, SEEK_CUR);
+ }
+ }
+
+ if ($filedata{1} == "\xDA") {
+ $abort = true;
+ } else {
+ $filedata = fread($f, 2);
+ if ($filedata{0} != "\xFF") {
+ fclose($f);
+ return $ret;
+ }
+ }
+ }
+
+ fclose($f);
+
+ return $ret;
+}
+
+/**
+ * Get the IPTC/EXIF/XMP media metadata
+ *
+ * @param string Filename
+ * @return array The raw media header data
+ *
+ */
+function &serendipity_getMetaData($file, &$info) {
+ global $serendipity;
+
+ # Fields taken from: http://demo.imagefolio.com/demo/ImageFolio31_files/skins/cool_blue/images/iptc.html
+ static $IPTC_Fields = array(
+ '2#005' => 'ObjectName',
+ '2#025' => 'Keywords',
+ '2#026' => 'LocationCode',
+ '2#027' => 'LocationName',
+ '2#030' => 'ReleaseDate',
+ '2#035' => 'ReleaseTime',
+ '2#037' => 'ExpirationDate',
+ '2#038' => 'ExpirationTime',
+ '2#055' => 'DateCreated',
+ '2#060' => 'TimeCreated',
+ '2#062' => 'DigitalDateCreated',
+ '2#063' => 'DigitalTimeCreated',
+ '2#065' => 'Software',
+ '2#070' => 'SoftwareVersion',
+ '2#080' => 'Photographer',
+ '2#085' => 'Photographer Name',
+ '2#090' => 'PhotoLocation',
+ '2#092' => 'PhotoLocation2',
+ '2#095' => 'PhotoState',
+ '2#100' => 'PhotoCountryCode',
+ '2#101' => 'PhotoCountry',
+ '2#105' => 'Title',
+ '2#110' => 'Credits',
+ '2#115' => 'Source',
+ '2#116' => 'Creator',
+ '2#118' => 'Contact',
+ '2#120' => 'Description',
+ '2#131' => 'Orientation',
+ '2#150' => 'AudioType',
+ '2#151' => 'AudioSamplingRate',
+ '2#152' => 'AudioSamplingResolution',
+ '2#153' => 'AudioDuration'
+ );
+
+ static $ExifFields = array(
+ 'IFD0' => array(
+ 'Make' => array('type' => 'text', 'name' => 'CameraMaker'),
+ 'Model' => array('type' => 'text', 'name' => 'CameraModel'),
+ 'Orientation' => array('type' => 'or', 'name' => 'Orientation'),
+ 'XResolution' => array('type' => 'math', 'name' => 'XResolution'),
+ 'YResolution' => array('type' => 'math', 'name' => 'YResolution'),
+ 'Software' => array('type' => 'text', 'name' => 'Software'),
+ 'DateTime' => array('type' => 'date2', 'name' => 'DateCreated'),
+ 'Artist' => array('type' => 'text', 'name' => 'Creator'),
+ ),
+
+ 'EXIF' => array(
+ 'ExposureTime' => array('type' => 'math', 'name' => 'ExposureTime'),
+ 'ApertureValue' => array('type' => 'math', 'name' => 'ApertureValue'),
+ 'MaxApertureValue' => array('type' => 'math', 'name' => 'MaxApertureValue'),
+ 'ISOSpeedRatings' => array('type' => 'text', 'name' => 'ISOSpeedRatings'),
+ 'DateTimeOriginal' => array('type' => 'date2', 'name' => 'DateCreated'),
+ 'MeteringMode' => array('type' => 'text', 'name' => 'MeteringMode'),
+ 'FNumber' => array('type' => 'math', 'name' => 'FNumber'),
+ 'ExposureProgram' => array('type' => 'text', 'name' => 'ExposureProgram'),
+ 'FocalLength' => array('type' => 'math', 'name' => 'FocalLength'),
+ 'WhiteBalance' => array('type' => 'text', 'name' => 'WhiteBalance'),
+ 'DigitalZoomRatio' => array('type' => 'math', 'name' => 'DigitalZoomRatio'),
+ 'FocalLengthIn35mmFilm' => array('type' => 'text', 'name' => 'FocalLengthIn35mmFilm'),
+ 'Flash' => array('type' => 'text', 'name' => 'Flash'),
+ 'Fired' => array('type' => 'text', 'name' => 'FlashFired'),
+ 'RedEyeMode' => array('type' => 'text', 'name' => 'RedEyeMode'),
+ )
+ );
+
+ static $xmpPatterns = array(
+ 'tiff:Orientation' => array('type' => 'or', 'name' => 'Orientation'),
+ 'tiff:XResolution' => array('type' => 'math', 'name' => 'XResolution'),
+ 'tiff:YResolution' => array('type' => 'math', 'name' => 'YResolution'),
+ 'tiff:Make' => array('type' => 'text', 'name' => 'CameraMaker'),
+ 'tiff:Model' => array('type' => 'text', 'name' => 'CameraModel'),
+ 'xap:ModifyDate' => array('type' => 'date', 'name' => 'DateModified'),
+ 'xap:CreatorTool' => array('type' => 'text', 'name' => 'Software'),
+ 'xap:CreateDate' => array('type' => 'date', 'name' => 'DateCreated'),
+ 'xap:MetadataDate' => array('type' => 'date', 'name' => 'DateMetadata'),
+
+ 'exif:ExposureTime' => array('type' => 'math', 'name' => 'ExposureTime'),
+ 'exif:ApertureValue' => array('type' => 'math', 'name' => 'ApertureValue'),
+ 'exif:MaxApertureValue' => array('type' => 'math', 'name' => 'MaxApertureValue'),
+ 'exif:ISOSpeedRatings' => array('type' => 'text', 'name' => 'ISOSpeedRatings'),
+ 'exif:DateTimeOriginal' => array('type' => 'date', 'name' => 'DateCreated'),
+ 'exif:MeteringMode' => array('type' => 'text', 'name' => 'MeteringMode'),
+ 'exif:FNumber' => array('type' => 'math', 'name' => 'FNumber'),
+ 'exif:ExposureProgram' => array('type' => 'text', 'name' => 'ExposureProgram'),
+ 'exif:FocalLength' => array('type' => 'math', 'name' => 'FocalLength'),
+ 'exif:WhiteBalance' => array('type' => 'text', 'name' => 'WhiteBalance'),
+ 'exif:DigitalZoomRatio' => array('type' => 'math', 'name' => 'DigitalZoomRatio'),
+ 'exif:FocalLengthIn35mmFilm' => array('type' => 'text', 'name' => 'FocalLengthIn35mmFilm'),
+ 'exif:Fired' => array('type' => 'text', 'name' => 'FlashFired'),
+ 'exif:RedEyeMode' => array('type' => 'text', 'name' => 'RedEyeMode'),
+
+ 'dc:title' => array('type' => 'rdf', 'name' => 'Title'),
+ 'dc:creator' => array('type' => 'rdf', 'name' => 'Creator'),
+ );
+
+ $ret = array();
+
+ if (!$serendipity['mediaExif']) {
+ return $ret;
+ }
+
+ if (!file_exists($file)) {
+ return $ret;
+ }
+
+ if (function_exists('iptcparse') && is_array($info) && isset($info['APP13'])) {
+ $iptc = iptcparse($info['APP13']);
+ foreach($IPTC_Fields AS $field => $desc) {
+ if ($iptc[$field]) {
+ if (is_array($iptc[$field])) {
+ $ret['IPTC'][$desc] = trim(implode(';', $iptc[$field]));
+ } else {
+ $ret['IPTC'][$desc] = trim($iptc[$field]);
+ }
+ }
+ }
+ }
+
+ if (function_exists('exif_read_data') && is_array($info)) {
+ $exif = @exif_read_data($file, 'FILE,COMPUTED,ANY_TAG,IFD0,COMMENT,EXIF', true, false);
+ if (is_array($exif)) {
+ foreach($ExifFields AS $Exifgroup => $ExifField) {
+ foreach($ExifField AS $ExifName => $ExifItem) {
+ if (!isset($exif[$Exifgroup][$ExifName])) {
+ continue;
+ }
+ $ret['EXIF'][$ExifItem['name']] = serendipity_metaFieldConvert($exif[$Exifgroup][$ExifName], $ExifItem['type']);
+ if ($ret['EXIF'][$item['name']] == $ret['IPTC'][$item['name']]) {
+ unset($ret['IPTC'][$item['name']]);
+ }
+ }
+ }
+ }
+ }
+
+ $xmp = serendipity_getMediaRaw($file);
+ foreach($xmp AS $xmp_data) {
+ if (empty($xmp_data['content'])) {
+ continue;
+ }
+ foreach($xmpPatterns AS $lookup => $item) {
+ if (preg_match('@<' . $lookup . '>(.*)</' . $lookup . '>@', $xmp_data['content'], $match)) {
+ $ret['XMP'][$item['name']] = serendipity_metaFieldConvert($match[1], $item['type']);
+ if ($ret['EXIF'][$item['name']] == $ret['XMP'][$item['name']]) {
+ unset($ret['EXIF'][$item['name']]);
+ }
+ }
+ }
+ }
+
+ serendipity_plugin_api::hook_event('media_getproperties', $ret, $file);
+
+ return $ret;
+}
+
+/**
+ * Parses an existing filename and increases the filecount.
+ *
+ * @param string The (duplicate) filename
+ * @param string The full path to the (duplicate) filename
+ * @param string The directory of the (duplicate) filename
+ * @param boolean Show new filename?
+ * @return string The new filename
+ *
+ */
+function serendipity_imageAppend(&$tfile, &$target, $dir, $echo = true) {
+ static $safe_bail = 20;
+
+ $realname = $tfile;
+ list($filebase, $extension) = serendipity_parseFileName($tfile);
+
+ $cnum = 1;
+ if (preg_match('@^(.*)([0-9]+)$@', $filebase, $match)) {
+ $cnum = $match[2];
+ $filebase = $match[1];
+ }
+
+ $i = 0;
+ while ($i <= $safe_bail && file_exists($dir . $filebase . $cnum . '.' . $extension)) {
+ $cnum++;
+ }
+
+ // Check if the file STILL exists and append a MD5 if that's the case. That should be unique enough.
+ if (file_exists($dir . $filebase . $cnum . '.' . $extension)) {
+ $cnum = md5(time() . $filebase);
+ }
+
+ // Those variables are passed by reference!
+ $tfile = $filebase . $cnum . '.' . $extension;
+ $target = $dir . $tfile;
+
+ if ($echo) {
+ printf(FILENAME_REASSIGNED . '<br />', htmlspecialchars($tfile));
+ }
+ return $realname;
+}
+
+/**
+ * Checks if an uploaded media item hits any configured limits.
+ *
+ * @param string The filename
+ * @return boolean TRUE when file is okay, FALSE when it is beyond limits
+ *
+ */
+function serendipity_checkMediaSize($file) {
+ global $serendipity;
+
+ if (!empty($serendipity['maxFileSize'])) {
+ if (filesize($file) > $serendipity['maxFileSize']) {
+ printf(MEDIA_UPLOAD_SIZEERROR . '<br />', (int)$serendipity['maxFileSize']);
+ return false;
+ }
+ }
+
+ if (!empty($serendipity['maxImgWidth']) || !empty($serendipity['maxImgHeight'])) {
+ $dim = serendipity_getimagesize($file);
+ if (!is_array($dim) || !isset($dim[0])) {
+ return true;
+ }
+
+ if (!empty($serendipity['maxImgWidth'])) {
+ if ($dim[0] > $serendipity['maxImgWidth']) {
+ printf(MEDIA_UPLOAD_DIMERROR . '<br />', (int)$serendipity['maxImgWidth'], (int)$serendipity['maxImgHeight']);
+ return false;
+ }
+ }
+
+ if (!empty($serendipity['maxImgHeight'])) {
+ if ($dim[1] > $serendipity['maxImgHeight']) {
+ printf(MEDIA_UPLOAD_DIMERROR . '<br />', (int)$serendipity['maxImgWidth'], (int)$serendipity['maxImgHeight']);
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Moves a media directory
+ *
+ * @param string The old directory
+ * @param string The new directory
+ * @param string The type of what to remove (dir|file|filedir)
+ * @param string An item id of a file
+ * @return boolean
+ *
+ */
+function serendipity_moveMediaDirectory($oldDir, $newDir, $type = 'dir', $item_id = null, $file = null) {
+ global $serendipity;
+
+ $real_oldDir = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $oldDir;
+ $real_newDir = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $newDir;
+
+ if ($type == 'dir') {
+ if (!is_dir($real_oldDir)) {
+ printf(ERROR_FILE_NOT_EXISTS . '<br />', $oldDir);
+ return false;
+ }
+
+ if (is_dir($real_newDir)) {
+ printf(ERROR_FILE_EXISTS . '<br />', $newDir);
+ return false;
+ }
+
+ if (!rename($real_oldDir, $real_newDir)) {
+ printf(MEDIA_DIRECTORY_MOVE_ERROR . '<br />', $newDir);
+ return false;
+ }
+
+ printf(MEDIA_DIRECTORY_MOVED . '<br />', $newDir);
+
+ $dirs = serendipity_db_query("SELECT id, path
+ FROM {$serendipity['dbPrefix']}images
+ WHERE path LIKE '" . serendipity_db_escape_string($oldDir) . "%'", false, 'assoc');
+ if (is_array($dirs)) {
+ foreach($dirs AS $dir) {
+ $old = $dir['path'];
+ $new = preg_replace('@^(' . preg_quote($oldDir) . ')@i', $newDir, $old);
+ serendipity_db_query("UPDATE {$serendipity['dbPrefix']}images
+ SET path = '" . serendipity_db_escape_string($new) . "'
+ WHERE id = {$dir['id']}");
+ }
+ }
+
+ $dirs = serendipity_db_query("SELECT groupid, artifact_id, artifact_type, artifact_mode, artifact_index
+ FROM {$serendipity['dbPrefix']}access
+ WHERE artifact_type = 'directory'
+ AND artifact_index LIKE '" . serendipity_db_escape_string($oldDir) . "%'", false, 'assoc');
+ if (is_array($dirs)) {
+ foreach($dirs AS $dir) {
+ $old = $dir['artifact_index'];
+ $new = preg_replace('@^(' . preg_quote($oldDir) . ')@i', $newDir, $old);
+ serendipity_db_query("UPDATE {$serendipity['dbPrefix']}access
+ SET artifact_index = '" . serendipity_db_escape_string($new) . "'
+ WHERE groupid = '" . serendipity_db_escape_string($dir['groupid']) . "'
+ AND artifact_id = '" . serendipity_db_escape_string($dir['artifact_id']) . "'
+ AND artifact_type = '" . serendipity_db_escape_string($dir['artifact_type']) . "'
+ AND artifact_mode = '" . serendipity_db_escape_string($dir['artifact_mode']) . "'
+ AND artifact_index = '" . serendipity_db_escape_string($dir['artifact_index']) . "'");
+ }
+ }
+ }
+
+ if ($type == 'file') {
+ if (serendipity_isActiveFile(basename($newDir))) {
+ printf(ERROR_FILE_FORBIDDEN, htmlspecialchars($newDir));
+ return false;
+ }
+
+ if ($file['hotlink']) {
+ serendipity_updateImageInDatabase(array('name' => $newDir), $item_id);
+ } else {
+ $file_new = $file['path'] . $newDir . '.';
+ $file_old = $file['path'] . $file['name'] . '.';
+
+ $newfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file_new . $file['extension'];
+ $oldfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file_old . $file['extension'];
+ if ($newDir != '' && file_exists($oldfile) && !file_exists($newfile)) {
+ $renameValues = array(array(
+ 'from' => $oldfile,
+ 'to' => $newfile,
+ 'thumb' => $serendipity['thumbSuffix'],
+ 'fthumb' => $file['thumbnail_name']
+ ));
+
+ serendipity_plugin_api::hook_event('backend_media_rename', $renameValues);
+
+ // Rename file
+ rename($renameValues[0]['from'], $renameValues[0]['to']);
+
+ foreach($renameValues as $renameData) {
+ // Rename thumbnail
+ rename($serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] . (!empty($renameData['fthumb']) ? '.' . $renameData['fthumb'] : '') . '.' . $file['extension'],
+ $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $newDir . '.' . $renameData['thumb'] . '.' . $file['extension']);
+ }
+
+ serendipity_updateImageInDatabase(array('thumbnail_name' => $renameValues[0]['thumb'], 'name' => $newDir), $item_id);
+ $oldDir = $file_old;
+ $newDir = $file_new;
+ $real_oldDir = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $oldDir;
+ $real_newDir = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $newDir;
+ // Forward user to overview (we don't want the user's back button to rename things again)
+ } else {
+ if (!file_exists($oldfile)) {
+ echo ERROR_FILE_NOT_EXISTS;
+ } elseif (file_exists($newfile)) {
+ echo ERROR_FILE_EXISTS;
+ } else {
+ echo ERROR_SOMETHING;
+ }
+
+ return false;
+ }
+ }
+ }
+
+ if ($type == 'filedir') {
+ serendipity_db_query("UPDATE {$serendipity['dbPrefix']}images
+ SET path = '" . serendipity_db_escape_string($newDir) . "'
+ WHERE id = " . (int)$item_id);
+ $pick = serendipity_db_query("SELECT * FROM {$serendipity['dbPrefix']}images
+ WHERE id = " . (int)$item_id, true, 'assoc');
+
+ // Move thumbs
+ $oldfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $oldDir . $pick['name'] . '.' . $pick['extension'];
+ $newfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $newDir . $pick['name'] . '.' . $pick['extension'];
+
+ $renameValues = array(array(
+ 'from' => $oldfile,
+ 'to' => $newfile,
+ 'thumb' => $serendipity['thumbSuffix'],
+ 'fthumb' => $pick['thumbnail_name']
+ ));
+
+ serendipity_plugin_api::hook_event('backend_media_rename', $renameValues);
+
+ // Rename file
+ rename($renameValues[0]['from'], $renameValues[0]['to']);
+
+ foreach($renameValues as $renameData) {
+ // Rename thumbnail
+ rename($serendipity['serendipityPath'] . $serendipity['uploadPath'] . $oldDir . $pick['name'] . (!empty($renameData['fthumb']) ? '.' . $renameData['fthumb'] : '') . '.' . $pick['extension'],
+ $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $newDir . $pick['name'] . '.' . $renameData['thumb'] . '.' . $pick['extension']);
+ }
+
+ $oldDir .= $pick['name'];
+ $newDir .= $pick['name'];
+ }
+
+ // Only MySQL supported, since I don't know how to use REGEXPs differently.
+ if ($serendipity['dbType'] != 'mysql' && $serendipity['dbType'] != 'mysqli') {
+ echo MEDIA_DIRECTORY_MOVE_ENTRY . '<br />';
+ return true;
+ }
+
+ $q = "SELECT id, body, extended
+ FROM {$serendipity['dbPrefix']}entries
+ WHERE body REGEXP '(src|href)=(\'|\")" . serendipity_db_escape_string($serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $oldDir) . "'
+ OR extended REGEXP '(src|href)=(\'|\")" . serendipity_db_escape_string($serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $oldDir) . "'
+ ";
+
+ $dirs = serendipity_db_query($q);
+ if (is_array($dirs)) {
+ foreach($dirs AS $dir) {
+ $dir['body'] = preg_replace('@(src|href)=(\'|")' . preg_quote($serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $oldDir) . '@', '\1=\2' . $serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $newDir, $dir['body']);
+ $dir['extended'] = preg_replace('@(src|href)=(\'|")' . preg_quote($serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $oldDir) . '@', '\1=\2' . $serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $newDir, $dir['extended']);
+
+ $uq = "UPDATE {$serendipity['dbPrefix']}entries
+ SET body = '" . serendipity_db_escape_string($dir['body']) . "' ,
+ extended = '" . serendipity_db_escape_string($dir['extended']) . "'
+ WHERE id = " . serendipity_db_escape_string($dir['id']);
+ serendipity_db_query($uq);
+ }
+
+ printf(MEDIA_DIRECTORY_MOVE_ENTRIES . '<br />', count($dirs));
+ }
+
+ return true;
+}
+
+/**
+ * Gets all available media directories
+ *
+ * @return array
+ *
+ */
+function &serendipity_getMediaPaths() {
+ global $serendipity;
+
+ $aExclude = array("CVS" => true, ".svn" => true);
+ serendipity_plugin_api::hook_event('backend_media_path_exclude_directories', $aExclude);
+ $paths = array();
+
+ $aResultSet = serendipity_traversePath(
+ $serendipity['serendipityPath'] . $serendipity['uploadPath'],
+ '',
+ false,
+ NULL,
+ 1,
+ NULL,
+ FALSE,
+ $aExclude
+ );
+
+ foreach ($aResultSet AS $sKey => $sFile) {
+ if ($sFile['directory']) {
+ array_push($paths, $sFile);
+ }
+ unset($aResultSet[$sKey]);
+ }
+ serendipity_directoryACL($paths, 'read');
+
+ usort($paths, 'serendipity_sortPath');
+
+ return $paths;
+}
\ No newline at end of file