| [ Index ] |
|
Code source de Serendipity 1.2 |
1 <?php # $Id: functions_images.inc.php 1816 2007-08-06 10:18:39Z garvinhicking $ 2 # Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team) 3 # All rights reserved. See LICENSE file for licensing details 4 5 if (IN_serendipity !== true) { 6 die ("Don't hack!"); 7 } 8 9 if (defined('S9Y_FRAMEWORK_IMAGES')) { 10 return; 11 } 12 @define('S9Y_FRAMEWORK_IMAGES', true); 13 14 /** 15 * Check if an uploaded file is "evil" 16 * 17 * @access public 18 * @param string Input filename 19 * @return boolean 20 */ 21 function serendipity_isActiveFile($file) { 22 if (preg_match('@^\.@', $file)) { 23 return true; 24 } 25 26 return preg_match('@\.(php[345]?|[psj]html?|aspx?|cgi|jsp|py|pl)$@i', $file); 27 } 28 29 /** 30 * Gets a list of media items from our media database 31 * 32 * LONG 33 * 34 * @access public 35 * @param int The offset to start fetching media files 36 * @param int How many items to fetch 37 * @param int The number (referenced varaible) of fetched items 38 * @param string The "ORDER BY" sql part when fetching items 39 * @param string Order by DESC or ASC 40 * @param string Only fetch files from a specific directory 41 * @param string Only fetch specific filenames 42 * @param string Only fetch media with specific keyword 43 * @param array An array of restricting filter sets 44 * @param boolean Apply strict directory checks, or include subdirectories? 45 * @return array Resultset of images 46 */ 47 function serendipity_fetchImagesFromDatabase($start=0, $limit=0, &$total, $order = false, $ordermode = false, $directory = '', $filename = '', $keywords = '', $filter = array(), $strict_directory = false) { 48 global $serendipity; 49 50 $cond = array( 51 'joinparts' => array(), 52 'parts' => array(), 53 ); 54 55 $orderfields = serendipity_getImageFields(); 56 if (empty($order) || !isset($orderfields[$order])) { 57 $order = 'i.date'; 58 } 59 60 if (!is_array($filter)) { 61 $filter = array(); 62 } 63 64 if (empty($ordermode) || ($ordermode != 'DESC' && $ordermode != 'ASC')) { 65 $ordermode = 'DESC'; 66 } 67 68 if ($order == 'name') { 69 $order = 'realname ' . $ordermode . ', name'; 70 } 71 72 if ($limit != 0) { 73 $limitsql = serendipity_db_limit_sql(serendipity_db_limit($start, $limit)); 74 } 75 76 if ($strict_directory) { 77 $cond['parts']['directory'] = " AND i.path = '" . serendipity_db_escape_string($directory) . "'\n"; 78 } elseif (!empty($directory)) { 79 $cond['parts']['directory'] = " AND i.path LIKE '" . serendipity_db_escape_string($directory) . "%'\n"; 80 } 81 82 if (!empty($filename)) { 83 $cond['parts']['filename'] = " AND (i.name like '%" . serendipity_db_escape_string($filename) . "%' OR 84 i.realname like '%" . serendipity_db_escape_string($filename) . "%')\n"; 85 } 86 87 if (!is_array($keywords)) { 88 if (!empty($keywords)) { 89 $keywords = explode(';', $keywords); 90 } else { 91 $keywords = array(); 92 } 93 } 94 95 if (count($keywords) > 0) { 96 $cond['parts']['keywords'] = " AND (mk.property IN ('" . serendipity_db_implode("', '", $keywords, 'string') . "'))\n"; 97 $cond['joinparts']['keywords'] = true; 98 } 99 100 foreach($filter AS $f => $fval) { 101 if (!isset($orderfields[$f]) || empty($fval)) { 102 continue; 103 } 104 105 if (is_array($fval)) { 106 if (empty($fval['from']) || empty($fval['to'])) { 107 continue; 108 } 109 110 if ($orderfields[$f]['type'] == 'date') { 111 $fval['from'] = serendipity_convertToTimestamp(trim($fval['from'])); 112 $fval['to'] = serendipity_convertToTimestamp(trim($fval['to'])); 113 } 114 115 if (substr($f, 0, 3) === 'bp.') { 116 $realf = substr($f, 3); 117 $cond['parts']['filter'] .= " AND (bp2.property = '$realf' AND bp2.value >= " . (int)$fval['from'] . " AND bp2.value <= " . (int)$fval['to'] . ")\n"; 118 } else { 119 $cond['parts']['filter'] .= " AND ($f >= " . (int)$fval['from'] . " AND $f <= " . (int)$fval['to'] . ")\n"; 120 } 121 } elseif ($f == 'i.authorid') { 122 $cond['parts']['filter'] .= " AND ( 123 (hp.property = 'authorid' AND hp.value = " . (int)$fval . ") 124 OR 125 (i.authorid = " . (int)$fval . ") 126 )\n"; 127 $cond['joinparts']['hiddenproperties'] = true; 128 } elseif ($orderfields[$f]['type'] == 'int') { 129 if (substr($f, 0, 3) === 'bp.') { 130 $realf = substr($f, 3); 131 $cond['parts']['filter'] .= " AND (bp2.property = '$realf' AND bp2.value = '" . serendipity_db_escape_string(trim($fval)) . "')\n"; 132 } else { 133 $cond['parts']['filter'] .= " AND ($f = '" . serendipity_db_escape_string(trim($fval)) . "')\n"; 134 } 135 } else { 136 if (substr($f, 0, 3) === 'bp.') { 137 $realf = substr($f, 3); 138 $cond['parts']['filter'] .= " AND (bp2.property = '$realf' AND bp2.value LIKE '%" . serendipity_db_escape_string(trim($fval)) . "%')\n"; 139 } else { 140 $cond['parts']['filter'] .= " AND ($f LIKE '%" . serendipity_db_escape_string(trim($fval)) . "%')\n"; 141 } 142 } 143 $cond['joinparts']['filterproperties'] = true; 144 } 145 146 if (isset($serendipity['authorid']) && !serendipity_checkPermission('adminImagesViewOthers')) { 147 $cond['parts']['authorid'] .= " AND (i.authorid = 0 OR i.authorid = " . (int)$serendipity['authorid'] . ")\n"; 148 } 149 150 $cond['and'] = 'WHERE 1=1 ' . implode("\n", $cond['parts']); 151 $cond['args'] = func_get_args(); 152 serendipity_plugin_api::hook_event('fetch_images_sql', $cond); 153 serendipity_ACL_SQL($cond, false, 'directory'); 154 155 if ($cond['joinparts']['keywords']) { 156 $cond['joins'] .= "\n LEFT OUTER JOIN {$serendipity['dbPrefix']}mediaproperties AS mk 157 ON (mk.mediaid = i.id AND mk.property_group = 'base_keyword')\n"; 158 } 159 160 if (substr($order, 0, 3) === 'bp.') { 161 $cond['orderproperty'] = substr($order, 3); 162 $cond['orderkey'] = 'bp.value'; 163 $order = 'bp.value'; 164 $cond['joinparts']['properties'] = true; 165 } else { 166 $cond['orderkey'] = "''"; 167 } 168 169 if ($cond['joinparts']['properties']) { 170 $cond['joins'] .= "\n LEFT OUTER JOIN {$serendipity['dbPrefix']}mediaproperties AS bp 171 ON (bp.mediaid = i.id AND bp.property_group = 'base_property' AND bp.property = '{$cond['orderproperty']}')\n"; 172 } 173 174 if ($cond['joinparts']['filterproperties']) { 175 $cond['joins'] .= "\n LEFT OUTER JOIN {$serendipity['dbPrefix']}mediaproperties AS bp2 176 ON (bp2.mediaid = i.id AND bp2.property_group = 'base_property')\n"; 177 } 178 179 if ($cond['joinparts']['hiddenproperties']) { 180 $cond['joins'] .= "\n LEFT OUTER JOIN {$serendipity['dbPrefix']}mediaproperties AS hp 181 ON (hp.mediaid = i.id AND hp.property_group = 'base_hidden')\n"; 182 } 183 184 if ($serendipity['dbType'] == 'postgres' || 185 $serendipity['dbType'] == 'pdo-postgres') { 186 $cond['group'] = ''; 187 $cond['distinct'] = 'DISTINCT'; 188 } else { 189 $cond['group'] = 'GROUP BY i.id'; 190 $cond['distinct'] = ''; 191 } 192 193 $basequery = "FROM {$serendipity['dbPrefix']}images AS i 194 LEFT OUTER JOIN {$serendipity['dbPrefix']}authors AS a 195 ON i.authorid = a.authorid 196 {$cond['joins']} 197 198 {$cond['and']}"; 199 200 $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, 201 a.realname AS authorname 202 $basequery 203 {$cond['group']} 204 ORDER BY $order $ordermode $limitsql"; 205 206 $rs = serendipity_db_query($query, false, 'assoc'); 207 208 if (!is_array($rs) && $rs !== true && $rs !== 1) { 209 echo '<div>' . $rs . '</div>'; 210 return array(); 211 } elseif (!is_array($rs)) { 212 return array(); 213 } 214 215 $total_query = "SELECT count(i.id) 216 $basequery 217 GROUP BY i.id"; 218 $total_rs = serendipity_db_query($total_query, false, 'num'); 219 if (is_array($total_rs)) { 220 $total = count($total_rs); 221 } 222 223 return $rs; 224 } 225 226 /** 227 * Fetch a specific media item from the mediadatabase 228 * 229 * @access public 230 * @param int The ID of an media item 231 * @return array The media info data 232 */ 233 function serendipity_fetchImageFromDatabase($id, $mode = 'read') { 234 global $serendipity; 235 236 if (is_array($id)) { 237 $cond = array( 238 'and' => "WHERE i.id IN (" . serendipity_db_implode(',', $id) . ")" 239 ); 240 $single = false; 241 $assocKey = 'id'; 242 $assocVal = false; 243 } else { 244 $cond = array( 245 'and' => "WHERE i.id = " . (int)$id 246 ); 247 $single = true; 248 $assocKey = false; 249 $assocVal = false; 250 } 251 252 if ($serendipity['dbType'] == 'postgres' || 253 $serendipity['dbType'] == 'pdo-postgres') { 254 $cond['group'] = ''; 255 $cond['distinct'] = 'DISTINCT'; 256 } else { 257 $cond['group'] = 'GROUP BY i.id'; 258 $cond['distinct'] = ''; 259 } 260 261 if ($mode != 'discard') { 262 serendipity_ACL_SQL($cond, false, 'directory', $mode); 263 } 264 265 $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 266 FROM {$serendipity['dbPrefix']}images AS i 267 {$cond['joins']} 268 {$cond['and']} 269 {$cond['group']}", $single, 'assoc', false, $assocKey, $assocVal); 270 return $rs; 271 } 272 273 /** 274 * Update a media item 275 * 276 * @access public 277 * @param array An array of columns to update 278 * @param int The ID of an media item to update 279 * @return boolean 280 */ 281 function serendipity_updateImageInDatabase($updates, $id) { 282 global $serendipity; 283 284 $admin = ''; 285 if (!serendipity_checkPermission('adminImagesAdd')) { 286 $admin = ' AND (authorid = ' . $serendipity['authorid'] . ' OR authorid = 0)'; 287 } 288 289 $i=0; 290 if (sizeof($updates) > 0) { 291 foreach ($updates as $k => $v) { 292 $q[] = $k ." = '" . serendipity_db_escape_string($v) . "'"; 293 } 294 serendipity_db_query("UPDATE {$serendipity['dbPrefix']}images SET ". implode($q, ',') ." WHERE id = " . (int)$id . " $admin"); 295 $i++; 296 } 297 return $i; 298 } 299 300 /** 301 * Delete a media item 302 * 303 * @access public 304 * @param int The ID of a media item to delete 305 * @return 306 */ 307 function serendipity_deleteImage($id) { 308 global $serendipity; 309 $dThumb = array(); 310 311 $file = serendipity_fetchImageFromDatabase($id); 312 313 if (!is_array($file)) { 314 printf(FILE_NOT_FOUND . '<br />', $id); 315 return false; 316 } 317 318 $dFile = $file['path'] . $file['name'] . '.' . $file['extension']; 319 320 $dThumb = array(array( 321 'fthumb' => $file['thumbnail_name'] 322 )); 323 324 if (!serendipity_checkPermission('adminImagesDelete')) { 325 return; 326 } 327 328 if (!serendipity_checkPermission('adminImagesMaintainOthers') && $file['authorid'] != '0' && $file['authorid'] != $serendipity['authorid']) { 329 // A non-admin user may not delete private files from other users. 330 return; 331 } 332 333 if (!$file['hotlink']) { 334 if (file_exists($serendipity['serendipityPath'] . $serendipity['uploadPath'] . $dFile)) { 335 if (@unlink($serendipity['serendipityPath'] . $serendipity['uploadPath'] . $dFile)) { 336 printf(DELETE_FILE . '<br />', $dFile); 337 } else { 338 printf(DELETE_FILE_FAIL . '<br />', $dFile); 339 } 340 341 serendipity_plugin_api::hook_event('backend_media_delete', $dThumb); 342 foreach($dThumb as $thumb) { 343 $dfnThumb = $file['path'] . $file['name'] . (!empty($thumb['fthumb']) ? '.' . $thumb['fthumb'] : '') . '.' . $file['extension']; 344 $dfThumb = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $dfnThumb; 345 346 if (@unlink($dfThumb)) { 347 printf(DELETE_THUMBNAIL . '<br />', $dfnThumb); 348 } 349 } 350 } else { 351 printf(FILE_NOT_FOUND . '<br />', $dFile); 352 } 353 } else { 354 printf(DELETE_HOTLINK_FILE . '<br />', $file['name']); 355 } 356 357 serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}images WHERE id = ". (int)$id); 358 serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}mediaproperties WHERE mediaid = ". (int)$id); 359 } 360 361 /** 362 * Open a directory and fetch all existing media items 363 * 364 * @access public 365 * @param boolean deprecated 366 * @param int deprecated 367 * @param int deprecated 368 * @param array Array list of found items 369 * @param string sub-directory to investigate [recursive use] 370 * @return array List of media items 371 */ 372 function serendipity_fetchImages($group = false, $start = 0, $end = 20, $images = '', $odir = '') { 373 global $serendipity; 374 375 // Open directory 376 $basedir = $serendipity['serendipityPath'] . $serendipity['uploadPath']; 377 $images = array(); 378 if ($dir = @opendir($basedir . $odir)) { 379 $aTempArray = array(); 380 while (($file = @readdir($dir)) !== false) { 381 if ($file == '.svn' || $file == 'CVS' || $file == '.' || $file == '..') { 382 continue; 383 } 384 array_push($aTempArray, $file); 385 } 386 @closedir($dir); 387 sort($aTempArray); 388 foreach($aTempArray as $f) { 389 if (strpos($f, $serendipity['thumbSuffix']) !== false) { 390 // This is a s9y thumbnail, skip it. 391 continue; 392 } 393 394 $cdir = ($odir != '' ? $odir . '/' : ''); 395 if (is_dir($basedir . $odir . '/' . $f)) { 396 $temp = serendipity_fetchImages($group, $start, $end, $images, $cdir . $f); 397 foreach($temp AS $tkey => $tval) { 398 array_push($images, $tval); 399 } 400 } else { 401 array_push($images, $cdir . $f); 402 } 403 } 404 } 405 natsort($images); 406 407 /* BC */ 408 $serendipity['imageList'] = $images; 409 return $images; 410 } 411 412 /** 413 * Inserts a hotlinked media file 414 * 415 * hotlinks are files that are only linked in your database, and not really stored on your server 416 * 417 * @access public 418 * @param string The filename to hotlink 419 * @param string The URL to hotlink with 420 * @param int The owner of the hotlinked media item 421 * @param int The timestamp of insertion (unix second) 422 * @param string A temporary filename for fetching the file to investigate it 423 * @return int The ID of the inserted media item 424 */ 425 function serendipity_insertHotlinkedImageInDatabase($filename, $url, $authorid = 0, $time = NULL, $tempfile = NULL) { 426 global $serendipity; 427 428 if (is_null($time)) { 429 $time = time(); 430 } 431 432 list($filebase, $extension) = serendipity_parseFileName($filename); 433 434 if ($tempfile && file_exists($tempfile)) { 435 $filesize = @filesize($tempfile); 436 $fdim = @serendipity_getimagesize($tempfile, '', $extension); 437 $width = $fdim[0]; 438 $height = $fdim[1]; 439 $mime = $fdim['mime']; 440 @unlink($tempfile); 441 } 442 443 $query = sprintf( 444 "INSERT INTO {$serendipity['dbPrefix']}images ( 445 name, 446 date, 447 authorid, 448 extension, 449 mime, 450 size, 451 dimensions_width, 452 dimensions_height, 453 path, 454 hotlink, 455 realname 456 ) VALUES ( 457 '%s', 458 %s, 459 %s, 460 '%s', 461 '%s', 462 %s, 463 %s, 464 %s, 465 '%s', 466 1, 467 '%s' 468 )", 469 serendipity_db_escape_string($filebase), 470 (int)$time, 471 (int)$authorid, 472 serendipity_db_escape_string($extension), 473 serendipity_db_escape_string($mime), 474 (int)$filesize, 475 (int)$width, 476 (int)$height, 477 serendipity_db_escape_string($url), 478 serendipity_db_escape_string($filename) 479 ); 480 481 $sql = serendipity_db_query($query); 482 if (is_string($sql)) { 483 echo $query . '<br />'; 484 echo $sql . '<br />'; 485 } 486 487 $image_id = serendipity_db_insert_id('images', 'id'); 488 if ($image_id > 0) { 489 return $image_id; 490 } 491 492 return 0; 493 } 494 495 /** 496 * Insert a media item in the database 497 * 498 * @access public 499 * @param string The filename of the media item 500 * @param string The path to the media item 501 * @param int The owner author of the item 502 * @param int The timestamp of when the media item was inserted 503 * @return int The new media ID 504 */ 505 function serendipity_insertImageInDatabase($filename, $directory, $authorid = 0, $time = NULL, $realname = NULL) { 506 global $serendipity; 507 508 if (is_null($time)) { 509 $time = time(); 510 } 511 512 if (is_null($realname)) { 513 $realname = $filename; 514 } 515 516 $filepath = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $directory . $filename; 517 $filesize = @filesize($filepath); 518 519 list($filebase, $extension) = serendipity_parseFileName($filename); 520 521 $thumbpath = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $directory . $filebase . '.'. $serendipity['thumbSuffix'] . '.'. $extension; 522 $thumbnail = (file_exists($thumbpath) ? $serendipity['thumbSuffix'] : ''); 523 524 $fdim = @serendipity_getimagesize($filepath, '', $extension); 525 $width = $fdim[0]; 526 $height = $fdim[1]; 527 $mime = $fdim['mime']; 528 529 530 $query = sprintf( 531 "INSERT INTO {$serendipity['dbPrefix']}images ( 532 name, 533 extension, 534 mime, 535 size, 536 dimensions_width, 537 dimensions_height, 538 thumbnail_name, 539 date, 540 authorid, 541 path, 542 realname 543 ) VALUES ( 544 '%s', 545 '%s', 546 '%s', 547 %s, 548 %s, 549 %s, 550 '%s', 551 %s, 552 %s, 553 '%s', 554 '%s' 555 )", 556 serendipity_db_escape_string($filebase), 557 serendipity_db_escape_string($extension), 558 serendipity_db_escape_string($mime), 559 (int)$filesize, 560 (int)$width, 561 (int)$height, 562 serendipity_db_escape_string($thumbnail), 563 (int)$time, 564 (int)$authorid, 565 serendipity_db_escape_string($directory), 566 serendipity_db_escape_string($realname) 567 ); 568 569 $sql = serendipity_db_query($query); 570 if (is_string($sql)) { 571 echo $query . '<br />'; 572 echo $sql . '<br />'; 573 } 574 575 $image_id = serendipity_db_insert_id('images', 'id'); 576 if ($image_id > 0) { 577 return $image_id; 578 } 579 580 return 0; 581 } 582 583 584 /** 585 * Create a thumbnail for an image 586 * 587 * LONG 588 * 589 * @access public 590 * @param string The input image filename 591 * @param string The directory to the image file 592 * @param string The target size of the thumbnail (2-dimensional array width,height) 593 * @param string Name of the thumbnail 594 * @param bool Store thumbnail in temporary place? 595 * @param bool Force enlarging of small images? 596 * @return array The result size of the thumbnail 597 */ 598 function serendipity_makeThumbnail($file, $directory = '', $size = false, $thumbname = false, $is_temporary = false, $force_resize = false) { 599 global $serendipity; 600 601 if ($size === false) { 602 $size = $serendipity['thumbSize']; 603 } 604 605 if ($thumbname === false) { 606 $thumbname = $serendipity['thumbSuffix']; 607 } 608 609 $t = serendipity_parseFileName($file); 610 $f = $t[0]; 611 $suf = $t[1]; 612 613 614 $infile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $directory . $file; 615 # echo 'From: ' . $infile . '<br />'; 616 if ($is_temporary) { 617 $temppath = dirname($thumbname); 618 if (!is_dir($temppath)) { 619 @mkdir($temppath); 620 } 621 $outfile = $thumbname; 622 } else { 623 $outfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $directory . $f . '.' . $thumbname . '.' . $suf; 624 } 625 $serendipity['last_outfile'] = $outfile; 626 # echo 'To: ' . $outfile . '<br />'; 627 628 $fdim = @serendipity_getimagesize($infile, '', $suf); 629 if (isset($fdim['noimage'])) { 630 $r = array(0, 0); 631 } else { 632 if ($serendipity['magick'] !== true) { 633 if (is_array($size)) { 634 $r = serendipity_resize_image_gd($infile, $outfile, $size['width'], $size['height']); 635 } else { 636 $r = serendipity_resize_image_gd($infile, $outfile, $size); 637 } 638 } else { 639 if (is_array($size)) { 640 $r = $size; 641 } else { 642 $r = array('width' => $size, 'height' => $size); 643 } 644 $newSize = $r['width'] . 'x' . $r['height']; 645 if ($fdim['mime'] == 'application/pdf') { 646 $cmd = escapeshellcmd($serendipity['convert']) . ' -antialias -flatten -scale '. serendipity_escapeshellarg($newSize) .' '. serendipity_escapeshellarg($infile) .' '. serendipity_escapeshellarg($outfile . '.png'); 647 } else { 648 if (!$force_resize && serendipity_ini_bool(ini_get('safe_mode')) === false) { 649 $newSize .= '>'; // Tell imagemagick to not enlarge small images, only works if safe_mode is off (safe_mode turns > in to \>) 650 } 651 $cmd = escapeshellcmd($serendipity['convert']) . ' -antialias -resize '. serendipity_escapeshellarg($newSize) .' '. serendipity_escapeshellarg($infile) .' '. serendipity_escapeshellarg($outfile); 652 } 653 exec($cmd, $output, $result); 654 if ($result != 0) { 655 echo '<div class="serendipityAdminMsgError"><img style="width: 22px; height: 22px; border: 0px; padding-right: 4px; vertical-align: middle" src="' . serendipity_getTemplateFile('admin/img/admin_msg_error.png') . '" alt="" />' . sprintf(IMAGICK_EXEC_ERROR, $cmd, $output[0], $result) .'</div>'; 656 $r = false; // return failure 657 } else { 658 touch($outfile); 659 } 660 unset($output, $result); 661 } 662 } 663 664 return $r; 665 } 666 667 /** 668 * Scale an image 669 * 670 * LONG 671 * 672 * @access public 673 * @param int The ID of an image 674 * @param int The target width 675 * @param int The target height 676 * @return true 677 */ 678 function serendipity_scaleImg($id, $width, $height) { 679 global $serendipity; 680 681 $file = serendipity_fetchImageFromDatabase($id); 682 if (!is_array($file)) { 683 return false; 684 } 685 686 $admin = ''; 687 if (!serendipity_checkPermission('adminImagesMaintainOthers') && $file['authorid'] != '0' && $file['authorid'] != $serendipity['authorid']) { 688 return; 689 } 690 691 $infile = $outfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] . '.' . $file['extension']; 692 693 if ($serendipity['magick'] !== true) { 694 serendipity_resize_image_gd($infile, $outfile, $width, $height); 695 } else { 696 $cmd = escapeshellcmd($serendipity['convert']) . ' -scale ' . serendipity_escapeshellarg($width . 'x' . $height) . ' ' . serendipity_escapeshellarg($infile) . ' ' . serendipity_escapeshellarg($outfile); 697 exec($cmd, $output, $result); 698 if ( $result != 0 ) { 699 echo '<div class="serendipityAdminMsgError"><img style="width: 22px; height: 22px; border: 0px; padding-right: 4px; vertical-align: middle" src="' . serendipity_getTemplateFile('admin/img/admin_msg_error.png') . '" alt="" />' . sprintf(IMAGICK_EXEC_ERROR, $cmd, $output[0], $result) .'</div>'; 700 } 701 unset($output, $result); 702 } 703 704 serendipity_updateImageInDatabase(array('dimensions_width' => $width, 'dimensions_height' => $height, 'size' => @filesize($outfile)), $id); 705 return true; 706 } 707 708 /** 709 * Rotate an image 710 * 711 * LONG 712 * 713 * @access public 714 * @param int The ID of an image 715 * @param int Number of degrees to rotate 716 * @return boolean 717 */ 718 function serendipity_rotateImg($id, $degrees) { 719 global $serendipity; 720 721 $file = serendipity_fetchImageFromDatabase($id); 722 if (!is_array($file)) { 723 return false; 724 } 725 726 $admin = ''; 727 if (!serendipity_checkPermission('adminImagesMaintainOthers') && $file['authorid'] != '0' && $file['authorid'] != $serendipity['authorid']) { 728 // A non-admin user may not delete private files from other users. 729 return false; 730 } 731 732 $infile = $outfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] . '.' . $file['extension']; 733 $infileThumb = $outfileThumb = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] . (!empty($file['thumbnail_name']) ? '.' . $file['thumbnail_name'] : '') . '.' . $file['extension']; 734 735 if ($serendipity['magick'] !== true) { 736 serendipity_rotate_image_gd($infile, $outfile, $degrees); 737 serendipity_rotate_image_gd($infileThumb, $outfileThumb, $degrees); 738 } else { 739 /* Why can't we just all agree on the rotation direction? */ 740 $degrees = (360 - $degrees); 741 742 /* Resize main image */ 743 $cmd = escapeshellcmd($serendipity['convert']) . ' -rotate ' . serendipity_escapeshellarg($degrees) . ' ' . serendipity_escapeshellarg($infile) . ' ' . serendipity_escapeshellarg($outfile); 744 exec($cmd, $output, $result); 745 if ( $result != 0 ) { 746 echo '<div class="serendipityAdminMsgError"><img style="width: 22px; height: 22px; border: 0px; padding-right: 4px; vertical-align: middle" src="' . serendipity_getTemplateFile('admin/img/admin_msg_error.png') . '" alt="" />' . sprintf(IMAGICK_EXEC_ERROR, $cmd, $output[0], $result) .'</div>'; 747 } 748 unset($output, $result); 749 750 /* Resize thumbnail */ 751 $cmd = escapeshellcmd($serendipity['convert']) . ' -rotate ' . serendipity_escapeshellarg($degrees) . ' ' . serendipity_escapeshellarg($infileThumb) . ' ' . serendipity_escapeshellarg($outfileThumb); 752 exec($cmd, $output, $result); 753 if ( $result != 0 ) { 754 echo '<div class="serendipityAdminMsgError"><img style="width: 22px; height: 22px; border: 0px; padding-right: 4px; vertical-align: middle" src="' . serendipity_getTemplateFile('admin/img/admin_msg_error.png') . '" alt="" />'. sprintf(IMAGICK_EXEC_ERROR, $cmd, $output[0], $result) .'</div>'; 755 } 756 unset($output, $result); 757 758 } 759 760 $fdim = @getimagesize($outfile); 761 762 serendipity_updateImageInDatabase(array('dimensions_width' => $fdim[0], 'dimensions_height' => $fdim[1]), $id); 763 764 return true; 765 } 766 767 768 /** 769 * Creates thumbnails for all images in the upload dir 770 * 771 * @access public 772 * @return int Number of created thumbnails 773 */ 774 function serendipity_generateThumbs() { 775 global $serendipity; 776 777 $i=0; 778 $serendipity['imageList'] = serendipity_fetchImagesFromDatabase(0, 0, $total); 779 780 foreach ($serendipity['imageList'] as $k => $file) { 781 $is_image = serendipity_isImage($file); 782 783 if ($is_image && !$file['hotlink']) { 784 $update = false; 785 $filename = $file['path'] . $file['name'] .'.'. $file['extension']; 786 $ffull = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $filename; 787 788 if (!file_exists($ffull)) { 789 serendipity_deleteImage($file['id']); 790 continue; 791 } 792 793 if (empty($file['thumbnail_name'])) { 794 $file['thumbnail_name'] = $serendipity['thumbSuffix']; 795 } 796 797 $oldThumb = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] . '.' . $file['thumbnail_name'] . '.' . $file['extension']; 798 $newThumb = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] . '.' . $serendipity['thumbSuffix'] . '.' . $file['extension']; 799 $fdim = @getimagesize($ffull); 800 801 if (!file_exists($oldThumb) && !file_exists($newThumb) && ($fdim[0] > $serendipity['thumbSize'] || $fdim[1] > $serendipity['thumbSize'])) { 802 $returnsize = serendipity_makeThumbnail($file['name'] . '.' . $file['extension'], $file['path']); 803 if ($returnsize !== false ) { 804 printf(RESIZE_BLAHBLAH, $filename . ': ' . $returnsize[0] . 'x' . $returnsize[1]); 805 if (!file_exists($newThumb)) { 806 printf('<div class="serendipityAdminMsgError"><img style="width: 22px; height: 22px; border: 0px; padding-right: 4px; vertical-align: middle" src="' . serendipity_getTemplateFile('admin/img/admin_msg_error.png') . '" alt="" />' . THUMBNAIL_FAILED_COPY . '</div><br />', $filename); 807 } else { 808 $update = true; 809 } 810 } 811 } elseif (!file_exists($oldThumb) && !file_exists($newThumb) && $fdim[0] <= $serendipity['thumbSize'] && $fdim[1] <= $serendipity['thumbSize']) { 812 $res = @copy($ffull, $newThumb); 813 if (@$res === true) { 814 printf(THUMBNAIL_USING_OWN . '<br />', $filename); 815 $update = true; 816 } else { 817 printf('<div class="serendipityAdminMsgError"><img style="width: 22px; height: 22px; border: 0px; padding-right: 4px; vertical-align: middle" src="' . serendipity_getTemplateFile('admin/img/admin_msg_error.png') . '" alt="" />' . THUMBNAIL_FAILED_COPY . '</div><br />', $filename); 818 } 819 } 820 821 if ($update) { 822 $i++; 823 $updates = array('thumbnail_name' => $serendipity['thumbSuffix']); 824 serendipity_updateImageInDatabase($updates, $file['id']); 825 } 826 } else { 827 // Currently, non-image files have no thumbnail. 828 } 829 } 830 831 return $i; 832 } 833 834 /** 835 * Guess the MIME type of a file 836 * 837 * @access public 838 * @param string Filename extension 839 * @return string Mimetype 840 */ 841 function serendipity_guessMime($extension) { 842 $mime = ''; 843 switch (strtolower($extension)) { 844 case 'jpg': 845 case 'jpeg': 846 $mime = 'image/jpeg'; 847 break; 848 849 case 'aiff': 850 case 'aif': 851 $mime = 'audio/x-aiff'; 852 break; 853 854 case 'gif': 855 $mime = 'image/gif'; 856 break; 857 858 case 'png': 859 $mime = 'image/png'; 860 break; 861 862 case 'pdf': 863 $mime = 'application/pdf'; 864 break; 865 866 case 'doc': 867 $mime = 'application/msword'; 868 break; 869 870 case 'rtf': 871 $mime = 'application/rtf'; 872 break; 873 874 case 'wav': 875 case 'wave': 876 $mime = 'audio/x-wav'; 877 break; 878 879 case 'mp2': 880 case 'mpg': 881 case 'mpeg': 882 $mime = 'video/x-mpeg'; 883 break; 884 885 case 'avi': 886 $mime = 'video/x-msvideo'; 887 break; 888 889 case 'mp3': 890 $mime = 'audio/x-mpeg3'; 891 break; 892 893 case 'xlm': 894 case 'xlb': 895 case 'xll': 896 case 'xla': 897 case 'xlw': 898 case 'xlc': 899 case 'xls': 900 case 'xlt': 901 $mime = 'application/vnd.ms-excel'; 902 break; 903 904 case 'ppt': 905 case 'pps': 906 $mime = 'application/vnd.ms-powerpoint'; 907 break; 908 909 case 'html': 910 case 'htm': 911 $mime = 'text/html'; 912 break; 913 914 case 'xsl': 915 case 'xslt': 916 case 'xml': 917 case 'wsdl': 918 case 'xsd': 919 $mime = 'text/xml'; 920 break; 921 922 case 'zip': 923 $mime = 'application/zip'; 924 break; 925 926 case 'tar': 927 $mime = 'application/x-tar'; 928 break; 929 930 case 'tgz': 931 case 'gz': 932 $mime = 'application/x-gzip'; 933 break; 934 935 case 'swf': 936 $mime = 'application/x-shockwave-flash'; 937 break; 938 939 case 'rm': 940 case 'ra': 941 case 'ram': 942 $mime = 'application/vnd.rn-realaudio'; 943 break; 944 945 case 'exe': 946 $mime = 'application/octet-stream'; 947 break; 948 949 case 'mov': 950 case 'qt': 951 $mime = 'video/x-quicktime'; 952 break; 953 954 case 'midi': 955 case 'mid': 956 $mime = 'audio/x-midi'; 957 break; 958 959 case 'txt': 960 $mime = 'text/plain'; 961 break; 962 963 case 'qcp': 964 $mime = 'audio/vnd.qcelp'; 965 break; 966 967 case 'emf': 968 $mime = 'image/x-emf'; 969 break; 970 971 case 'wmf': 972 $mime = 'image/x-wmf'; 973 break; 974 975 case 'snd': 976 $mime = 'audio/basic'; 977 break; 978 979 case 'pmd': 980 $mime = 'application/x-pmd'; 981 break; 982 983 case 'wbmp': 984 $mime = 'image/vnd.wap.wbmp'; 985 break; 986 987 case 'gcd': 988 $mime = 'text/x-pcs-gcd'; 989 break; 990 991 case 'mms': 992 $mime = 'application/vnd.wap.mms-message'; 993 break; 994 995 case 'ogg': 996 case 'ogm': 997 $mime = 'application/ogg'; 998 break; 999 1000 case 'rv': 1001 $mime = 'video/vnd.rn-realvideo'; 1002 break; 1003 1004 case 'wmv': 1005 $mime = 'video/x-ms-wmv'; 1006 break; 1007 1008 case 'wma': 1009 $mime = 'audio/x-ms-wma'; 1010 break; 1011 1012 case 'qcp': 1013 $mime = 'audio/vnd.qcelp'; 1014 break; 1015 1016 case 'jad': 1017 $mime = 'text/vnd.sun.j2me.app-descriptor'; 1018 break; 1019 1020 case '3g2': 1021 case '3gp': 1022 $mime = 'video/3gpp'; 1023 break; 1024 1025 case 'jar': 1026 $mime = 'application/java-archive'; 1027 break; 1028 1029 case 'ico': 1030 $mime = 'image/x-icon'; 1031 break; 1032 1033 default: 1034 $mime = 'application/octet-stream'; 1035 break; 1036 } 1037 1038 return $mime; 1039 } 1040 1041 /** 1042 * Check all existing thumbnails if they are the right size, insert missing thumbnails 1043 * 1044 * LONG 1045 * 1046 * @access public 1047 * @return int Number of updated thumbnails 1048 */ 1049 function serendipity_syncThumbs() { 1050 global $serendipity; 1051 1052 $i=0; 1053 $files = serendipity_fetchImages(); 1054 1055 $fcount = count($files); 1056 for ($x = 0; $x < $fcount; $x++) { 1057 $update = array(); 1058 $f = serendipity_parseFileName($files[$x]); 1059 if (empty($f[1]) || $f[1] == $files[$x]) { 1060 // No extension means bad file most probably. Skip it. 1061 printf(SKIPPING_FILE_EXTENSION . '<br />', $files[$x]); 1062 continue; 1063 } 1064 1065 $ffull = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $files[$x]; 1066 $fthumb = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $f[0] . '.' . $serendipity['thumbSuffix'] . '.' . $f[1]; 1067 $fbase = basename($f[0]); 1068 $fdir = dirname($f[0]) . '/'; 1069 if ($fdir == './') { 1070 $fdir = ''; 1071 } 1072 1073 if (!is_readable($ffull) || filesize($ffull) == 0) { 1074 printf(SKIPPING_FILE_UNREADABLE . '<br />', $files[$x]); 1075 continue; 1076 } 1077 1078 $ft_mime = serendipity_guessMime($f[1]); 1079 $fdim = serendipity_getimagesize($ffull, $ft_mime); 1080 1081 $cond = array( 1082 'and' => "WHERE name = '" . serendipity_db_escape_string($fbase) . "' 1083 " . ($fdir != '' ? "AND path = '" . serendipity_db_escape_string($fdir) . "'" : '') . " 1084 AND mime = '" . serendipity_db_escape_string($fdim['mime']) . "'" 1085 ); 1086 serendipity_ACL_SQL($cond, false, 'directory'); 1087 1088 $rs = serendipity_db_query("SELECT * 1089 FROM {$serendipity['dbPrefix']}images AS i 1090 {$cond['joins']} 1091 1092 {$cond['and']}", true, 'assoc'); 1093 if (is_array($rs)) { 1094 $update = array(); 1095 $checkfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $rs['path'] . $rs['name'] . '.' . $rs['thumbnail_name'] . '.' . $rs['extension']; 1096 if (isset($fdim[0]) && $rs['dimensions_width'] != $fdim[0]) { 1097 $update['dimensions_width'] = $fdim[0]; 1098 } 1099 1100 if (isset($fdim[1]) && $rs['dimensions_height'] != $fdim[1]) { 1101 $update['dimensions_height'] = $fdim[1]; 1102 } 1103 1104 if ($rs['size'] != filesize($ffull)) { 1105 $update['size'] = filesize($ffull); 1106 } 1107 1108 if (!file_exists($checkfile) && file_exists($fthumb)) { 1109 $update['thumbnail_name'] = $serendipity['thumbSuffix']; 1110 } 1111 1112 /* Do the database update, if needed */ 1113 if (sizeof($update) != 0) { 1114 printf(FOUND_FILE . '<br />', $files[$x]); 1115 serendipity_updateImageInDatabase($update, $rs['id']); 1116 $i++; 1117 } 1118 } else { 1119 printf(FOUND_FILE . '<br />', $files[$x]); 1120 serendipity_insertImageInDatabase($fbase . '.' . $f[1], $fdir, 0, filemtime($ffull)); 1121 $i++; 1122 } 1123 } 1124 return $i; 1125 } 1126 1127 /** 1128 * Wrapper for GDLib functions 1129 * 1130 * @access public 1131 * @param string Filename to operate on 1132 * @return string Functionname to execute 1133 */ 1134 function serendipity_functions_gd($infilename) { 1135 if (!function_exists('imagecopyresampled')) { 1136 return false; 1137 } 1138 1139 $func = array(); 1140 $inf = pathinfo(strtolower($infilename)); 1141 switch ($inf['extension']) { 1142 case 'gif': 1143 $func['load'] = 'imagecreatefromgif'; 1144 $func['save'] = 'imagegif'; 1145 $func['qual'] = 100; 1146 break; 1147 1148 case 'jpeg': 1149 case 'jpg': 1150 case 'jfif': 1151 $func['load'] = 'imagecreatefromjpeg'; 1152 $func['save'] = 'imagejpeg'; 1153 $func['qual'] = 100; 1154 break; 1155 1156 case 'png': 1157 $func['load'] = 'imagecreatefrompng'; 1158 $func['save'] = 'imagepng'; 1159 $func['qual'] = 9; 1160 break; 1161 1162 default: 1163 return false; 1164 } 1165 1166 /* If our loader does not exist, we are doomed */ 1167 if (!function_exists($func['load'])) { 1168 return false; 1169 } 1170 1171 /* If the save function does not exist (i.e. read-only GIF), we want to output it as PNG */ 1172 if (!function_exists($func['save'])) { 1173 if (function_exists('imagepng')) { 1174 $func['save'] = 'imagepng'; 1175 } else { 1176 return false; 1177 } 1178 } 1179 1180 return $func; 1181 } 1182 1183 /** 1184 * Rotate an image (GDlib) 1185 * 1186 * @access public 1187 * @param string Source Filename to rotate 1188 * @param string Target file 1189 * @param int Degress to rotate 1190 * @return array New width/height of the image 1191 */ 1192 function serendipity_rotate_image_gd($infilename, $outfilename, $degrees) 1193 { 1194 $func = serendipity_functions_gd($infilename); 1195 if (!is_array($func)) { 1196 return false; 1197 } 1198 1199 $in = $func['load']($infilename); 1200 1201 $out = imagerotate($in, $degrees, 0); 1202 $func['save']($out, $outfilename, $func['qual']); 1203 1204 $newwidth = imagesx($out); 1205 $newheight = imagesy($out); 1206 1207 $out = null; 1208 $in = null; 1209 1210 return array($newwidth, $newheight); 1211 } 1212 1213 1214 /** 1215 * Resize an image (GDLib) 1216 * 1217 * @access public 1218 * @param string Source Filename to resize 1219 * @param string Target file 1220 * @param int New width 1221 * @return int New height (can be autodetected) 1222 * @return array New image size 1223 */ 1224 function serendipity_resize_image_gd($infilename, $outfilename, $newwidth, $newheight=null) 1225 { 1226 $func = serendipity_functions_gd($infilename); 1227 if (!is_array($func)) { 1228 return false; 1229 } 1230 1231 $in = $func['load']($infilename); 1232 $width = imagesx($in); 1233 $height = imagesy($in); 1234 1235 if (is_null($newheight)) { 1236 $newsizes = serendipity_calculate_aspect_size($width, $height, $newwidth); 1237 $newwidth = $newsizes[0]; 1238 $newheight = $newsizes[1]; 1239 } 1240 1241 if (is_null($newwidth)) { 1242 $newsizes = serendipity_calculate_aspect_size($width, $height, null, $newheight); 1243 $newwidth = $newsizes[0]; 1244 $newheight = $newsizes[1]; 1245 } 1246 1247 $out = imagecreatetruecolor($newwidth, $newheight); 1248 1249 /* Attempt to copy transparency information, this really only works for PNG */ 1250 if (function_exists('imagesavealpha')) { 1251 imagealphablending($out, false); 1252 imagesavealpha($out, true); 1253 } 1254 1255 imagecopyresampled($out, $in, 0, 0, 0, 0, $newwidth, $newheight, $width, $height); 1256 @umask(0000); 1257 touch($outfilename); // safe_mode requirement 1258 $func['save']($out, $outfilename, $func['qual']); 1259 @chmod($outfilename, 0664); 1260 $out = null; 1261 $in = null; 1262 1263 return array($newwidth, $newheight); 1264 } 1265 1266 /** 1267 * Calculate aspect ratio of an image 1268 * 1269 * @access public 1270 * @param int Image width 1271 * @param int Image height 1272 * @param int Target width 1273 * @return int Target height 1274 */ 1275 function serendipity_calculate_aspect_size($width, $height, $orig_newwidth, $orig_newheight = null) { 1276 1277 // calculate aspect ratio 1278 if (!is_null($orig_newheight)) { 1279 $div_width = $width / $orig_newheight; 1280 $div_height = $height / $orig_newheight; 1281 } else { 1282 $div_width = $width / $orig_newwidth; 1283 $div_height = $height / $orig_newwidth; 1284 } 1285 1286 if ($div_width <= 1 && $div_height <= 1) { 1287 // do not scale small images where both sides are smaller than the thumbnail dimensions 1288 $newheight = $height; 1289 $newwidth = $width; 1290 } elseif (is_null($orig_newheight) && $div_width >= $div_height) { 1291 // max width - calculate height, keep width as scaling base 1292 $newheight = round($height / $div_width); 1293 // make sure the height is at least 1 pixel for extreme images 1294 $newheight = ($newheight >= 1 ? $newheight : 1); 1295 $newwidth = $orig_newwidth; 1296 } elseif (is_null($orig_newwidth) && $div_width >= $div_height) { 1297 // max width - calculate height, keep width as scaling base 1298 $newwidth = round($width / $div_height); 1299 // make sure the height is at least 1 pixel for extreme images 1300 $newwidth = ($newwidth >= 1 ? $newwidth : 1); 1301 $newheight = $orig_newheight; 1302 } elseif (is_null($orig_newheight)) { 1303 // max height - calculate width, keep height as scaling base 1304 $newheight = $orig_newwidth; 1305 $newwidth = round($width / $div_height); 1306 // make sure the width is at least 1 pixel for extreme images 1307 $newwidth = ($newwidth >= 1 ? $newwidth : 1); 1308 } else { 1309 // max height - calculate width, keep height as scaling base 1310 $newwidth = $orig_newheight; 1311 $newheight = round($height / $div_width); 1312 // make sure the width is at least 1 pixel for extreme images 1313 $newheight = ($newheight >= 1 ? $newheight : 1); 1314 } 1315 1316 return array($newwidth, $newheight); 1317 } 1318 1319 /** 1320 * Display the list of images in our database 1321 * 1322 * @access public 1323 * @param int The current page number 1324 * @param string The HTML linebreak to use after a row of images 1325 * @param boolean Should the toolbar for editing media files be shown? 1326 * @param string The URL to use for pagination 1327 * @param boolean Show the "upload media item" feature? 1328 * @param boolean Restrict viewing images to a specific directory 1329 * @param boolean If TRUE, will echo Smarty output. 1330 * @return string Smarty block name 1331 */ 1332 function serendipity_displayImageList($page = 0, $lineBreak = NULL, $manage = false, $url = NULL, $show_upload = false, $limit_path = NULL, $smarty_display = true) { 1333 global $serendipity; 1334 static $debug = false; 1335 1336 $sortParams = array('perpage', 'order', 'ordermode'); 1337 $importParams = array('adminModule', 'htmltarget', 'filename_only', 'textarea', 'subpage', 'keywords'); 1338 $extraParems = ''; 1339 $filterParams = array('only_path', 'only_filename'); 1340 1341 foreach($importParams AS $importParam) { 1342 if (isset($serendipity['GET'][$importParam])) { 1343 $extraParems .= 'serendipity[' . $importParam . ']='. $serendipity['GET'][$importParam] .'&'; 1344 } 1345 } 1346 1347 foreach($sortParams AS $sortParam) { 1348 serendipity_restoreVar($serendipity['COOKIE']['sortorder_' . $sortParam], $serendipity['GET']['sortorder'][$sortParam]); 1349 serendipity_JSsetCookie('sortorder_' . $sortParam, $serendipity['GET']['sortorder'][$sortParam]); 1350 $extraParems .= 'serendipity[sortorder]['. $sortParam .']='. $serendipity['GET']['sortorder'][$sortParam] .'&'; 1351 } 1352 1353 foreach($filterParams AS $filterParam) { 1354 serendipity_restoreVar($serendipity['COOKIE'][$filterParam], $serendipity['GET'][$filterParam]); 1355 serendipity_JSsetCookie($filterParam, $serendipity['GET'][$filterParam]); 1356 if (!empty($serendipity['GET'][$filterParam])) { 1357 $extraParems .= 'serendipity[' . $filterParam . ']='. $serendipity['GET'][$filterParam] .'&'; 1358 } 1359 } 1360 1361 $serendipity['GET']['only_path'] = serendipity_uploadSecure($limit_path . $serendipity['GET']['only_path'], true); 1362 $serendipity['GET']['only_filename'] = str_replace(array('*', '?'), array('%', '_'), $serendipity['GET']['only_filename']); 1363 1364 $perPage = (!empty($serendipity['GET']['sortorder']['perpage']) ? $serendipity['GET']['sortorder']['perpage'] : 8); 1365 while ($perPage % $lineBreak !== 0) { 1366 $perPage++; 1367 } 1368 $start = ($page-1) * $perPage; 1369 1370 if ($manage && $limit_path == NULL) { 1371 ## SYNCH START ## 1372 $aExclude = array("CVS" => true, ".svn" => true); 1373 serendipity_plugin_api::hook_event('backend_media_path_exclude_directories', $aExclude); 1374 $paths = array(); 1375 $aFilesOnDisk = array(); 1376 1377 $aResultSet = serendipity_traversePath( 1378 $serendipity['serendipityPath'] . $serendipity['uploadPath']. $limit_path, 1379 '', 1380 false, 1381 NULL, 1382 1, 1383 NULL, 1384 FALSE, 1385 $aExclude 1386 ); 1387 foreach ($aResultSet AS $sKey => $sFile) { 1388 if ($sFile['directory']) { 1389 if ($debug) echo "{$sFile['relpath']} is a directory.<br />"; 1390 array_push($paths, $sFile); 1391 } else { 1392 if ($debug) echo "{$sFile['relpath']} is a file.<br />"; 1393 // Store the file in our array, remove any ending slashes 1394 $aFilesOnDisk[$sFile['relpath']] = 1; 1395 } 1396 unset($aResultSet[$sKey]); 1397 } 1398 1399 usort($paths, 'serendipity_sortPath'); 1400 1401 if ($debug) echo "<p>Got files: <pre>" . print_r($aFilesOnDisk, true) . "</pre></p>"; 1402 $serendipity['current_image_hash'] = md5(serialize($aFilesOnDisk)); 1403 1404 $nTimeStart = microtime_float(); 1405 // MTG 21/01/06: request all images from the database, delete any which don't exist 1406 // on the filesystem, and mark off files from the file list which are already 1407 // in the database 1408 1409 $nCount = 0; 1410 if ($serendipity['onTheFlySynch'] && serendipity_checkPermission('adminImagesSync') && $serendipity['current_image_hash'] != $serendipity['last_image_hash']) { 1411 $aResultSet = serendipity_db_query("SELECT path, name, extension, thumbnail_name, id 1412 FROM {$serendipity['dbPrefix']}images", false, 'assoc'); 1413 if ($debug) echo "<p>Got images: <pre>" . print_r($aResultSet, true) . "</pre></p>"; 1414 if (is_array($aResultSet)) { 1415 foreach ($aResultSet AS $sKey => $sFile) { 1416 serendipity_plugin_api::hook_event('backend_thumbnail_filename_select', $sFile); 1417 $sThumbNailFile = ''; 1418 if (isset($sFile['thumbnail_filename'])) { 1419 $sThumbNailFile = $sFile['thumbnail_filename']; 1420 } else { 1421 $sThumbNailFile = $sFile['path'] . $sFile['name'] . '.' . $sFile['thumbnail_name'] . '.' . $sFile['extension']; 1422 } 1423 1424 $sFileName = $sFile['path'] . $sFile['name'] . '.' . $sFile['extension']; 1425 if ($debug) echo "<p>File name is $sFileName,<br />thumbnail is $sThumbNailFile</p>"; 1426 unset($aResultSet[$sKey]); 1427 1428 if (isset($aFilesOnDisk[$sFileName])) { 1429 unset($aFilesOnDisk[$sFileName]); 1430 } else { 1431 if ($debug) "Deleting Image {$sFile['id']}<br />\n"; 1432 serendipity_deleteImage($sFile['id']); 1433 ++$nCount; 1434 } 1435 unset($aFilesOnDisk[$sThumbNailFile]); 1436 } 1437 } 1438 1439 if ($nCount > 0){ 1440 if ($debug) echo "<p>Cleaned up ".$nCount." database entries</p>"; 1441 } 1442 1443 serendipity_set_config_var('last_image_hash', $serendipity['current_image_hash'], 0); 1444 $aUnmatchedOnDisk = array_keys($aFilesOnDisk); 1445 if ($debug) echo "<p>Got unmatched files: <pre>" . print_r($aUnmatchedOnDisk, true) . "</pre></p>"; 1446 $nCount = 0; 1447 foreach ($aUnmatchedOnDisk AS $sFile) { 1448 if (preg_match('@\.' . $serendipity['thumbSuffix'] . '\.@', $sFile)) { 1449 if ($debug) echo "<p>Skipping thumbnailed file $sFile</p>"; 1450 continue; 1451 } else { 1452 if ($debug) echo "<p>Checking $sFile</p>"; 1453 } 1454 1455 // MTG: 21/01/06: put files which have just 'turned up' into the database 1456 $aImageData = serendipity_getImageData($sFile); 1457 if (serendipity_isImage($aImageData)) { 1458 $nPos = strrpos($sFile, "/"); 1459 if (is_bool($nPos) && !$nPos) { 1460 $sFileName = $sFile; 1461 $sDirectory = ""; 1462 } else { 1463 ++$nPos; 1464 $sFileName = substr($sFile, $nPos); 1465 $sDirectory = substr($sFile, 0, $nPos); 1466 } 1467 if ($debug) echo "<p>Inserting image $sFileName from $sDirectory <pre>" . print_r($aImageData, true) . "</pre> into database</p>"; 1468 # TODO: Check if the thumbnail generation goes fine with Marty's code 1469 serendipity_makeThumbnail($sFileName, $sDirectory); 1470 serendipity_insertImageInDatabase($sFileName, $sDirectory); 1471 ++$nCount; 1472 } 1473 } 1474 1475 if ($nCount > 0) { 1476 if ($debug) echo "<p>Inserted ".$nCount." images into the database</p>"; 1477 } 1478 } else { 1479 if ($debug) echo "<p>Media Gallery database is up to date</p>"; 1480 } 1481 1482 /* 1483 $nTimeEnd = microtime_float ( ); 1484 $nDifference = $nTimeEnd - $nTimeStart; 1485 echo "<p> total time taken was " . $nDifference . "</p>"; 1486 */ 1487 ## SYNCH FINISHED ## 1488 } 1489 1490 ## Aply ACL afterwards: 1491 serendipity_directoryACL($paths, 'read'); 1492 1493 $serendipity['imageList'] = serendipity_fetchImagesFromDatabase( 1494 $start, 1495 $perPage, 1496 $totalImages, // Passed by ref 1497 (isset($serendipity['GET']['sortorder']['order']) ? $serendipity['GET']['sortorder']['order'] : false), 1498 (isset($serendipity['GET']['sortorder']['ordermode']) ? $serendipity['GET']['sortorder']['ordermode'] : false), 1499 (isset($serendipity['GET']['only_path']) ? $serendipity['GET']['only_path'] : ''), 1500 (isset($serendipity['GET']['only_filename']) ? $serendipity['GET']['only_filename'] : ''), 1501 (isset($serendipity['GET']['keywords']) ? $serendipity['GET']['keywords'] : ''), 1502 (isset($serendipity['GET']['filter']) ? $serendipity['GET']['filter'] : '') 1503 ); 1504 1505 $pages = ceil($totalImages / $perPage); 1506 $linkPrevious = '?' . $extraParems . 'serendipity[page]=' . ($page-1); 1507 $linkNext = '?' . $extraParems . 'serendipity[page]=' . ($page+1); 1508 if (is_null($lineBreak)) { 1509 $lineBreak = floor(750 / ($serendipity['thumbSize'] + 20)); 1510 } 1511 1512 $dprops = $keywords = array(); 1513 if ($serendipity['parseMediaOverview']) { 1514 $ids = array(); 1515 foreach ($serendipity['imageList'] as $k => $file) { 1516 $ids[] = $file['id']; 1517 } 1518 $allprops =& serendipity_fetchMediaProperties($ids); 1519 } 1520 1521 if (count($serendipity['imageList']) > 0) { 1522 foreach ($serendipity['imageList'] as $k => $file) { 1523 if (!($serendipity['authorid'] == $file['authorid'] || $file['authorid'] == '0' || serendipity_checkPermission('adminImagesViewOthers'))) { 1524 // This is a fail-safe continue. Basically a non-matching file should already be filtered in SQL. 1525 continue; 1526 } 1527 1528 serendipity_prepareMedia($serendipity['imageList'][$k], $url); 1529 1530 if ($serendipity['parseMediaOverview']) { 1531 $serendipity['imageList'][$k]['props'] =& $allprops[$file['id']]; 1532 if (!is_array($serendipity['imageList'][$k]['props']['base_metadata'])) { 1533 $serendipity['imageList'][$k]['metadata'] =& serendipity_getMetaData($serendipity['imageList'][$k]['realfile'], $serendipity['imageList'][$k]['header']); 1534 } else { 1535 $serendipity['imageList'][$k]['metadata'] = $serendipity['imageList'][$k]['props']['base_metadata']; 1536 serendipity_plugin_api::hook_event('media_getproperties_cached', $serendipity['imageList'][$k]['metadata'], $serendipity['imageList'][$k]['realfile']); 1537 } 1538 serendipity_parseMediaProperties($dprops, $keywords, $serendipity['imageList'][$k], $serendipity['imageList'][$k]['props'], 3, false); 1539 } 1540 } 1541 } 1542 1543 $smarty_vars = array( 1544 'limit_path' => $limit_path, 1545 'perPage' => $perPage, 1546 'show_upload' => $show_upload, 1547 'page' => $page, 1548 'pages' => $pages, 1549 'linkNext' => $linkNext, 1550 'linkPrevious' => $linkPrevious, 1551 'extraParems' => $extraParems 1552 ); 1553 return serendipity_showMedia( 1554 $serendipity['imageList'], 1555 $paths, 1556 $url, 1557 $manage, 1558 $lineBreak, 1559 true, 1560 $smarty_vars, 1561 $smarty_display 1562 ); 1563 } // End serendipity_displayImageList() 1564 1565 /** 1566 * Check if a media item is an image 1567 * 1568 * @access public 1569 * @param array File information 1570 * @param boolean Use a strict check that does not list PDFs as an image? 1571 * @return boolean True if the file is an image 1572 */ 1573 function serendipity_isImage(&$file, $strict = false) { 1574 global $serendipity; 1575 1576 $file['displaymime'] = $file['mime']; 1577 1578 // Strip HTTP path out of imgsrc 1579 $file['location'] = $serendipity['serendipityPath'] . preg_replace('@^(' . preg_quote($serendipity['serendipityHTTPPath']) . ')@i', '', $file['imgsrc']); 1580 1581 // File is PDF -> Thumb is PNG 1582 if ($file['mime'] == 'application/pdf' && file_exists($file['location'] . '.png') && $strict == false) { 1583 $file['imgsrc'] .= '.png'; 1584 $file['displaymime'] = 'image/png'; 1585 } 1586 1587 return (0 === strpos(strtolower($file['displaymime']), 'image/')); 1588 } 1589 1590 /** 1591 * Recursively delete a directory tree 1592 * 1593 * @access public 1594 * @param string The originating directory 1595 * @param string The subdirectory 1596 * @param boolean Force deleting an directory even if there are files left in it? 1597 * @return true 1598 */ 1599 function serendipity_killPath($basedir, $directory = '', $forceDelete = false) { 1600 static $n = "<br />\n"; 1601 static $serious = true; 1602 1603 if ($handle = @opendir($basedir . $directory)) { 1604 while (false !== ($file = @readdir($handle))) { 1605 if ($file != '.' && $file != '..') { 1606 if (is_dir($basedir . $directory . $file)) { 1607 serendipity_killPath($basedir, $directory . $file . '/', $forceDelete); 1608 } else { 1609 $filestack[$file] = $directory . $file; 1610 } 1611 } 1612 } 1613 @closedir($handle); 1614 1615 printf(CHECKING_DIRECTORY . "<br />\n", $directory); 1616 1617 // No, we just don't kill files the easy way. We sort them out properly from the database 1618 // and preserve files not entered therein. 1619 $files = serendipity_fetchImagesFromDatabase(0, 0, $total, false, false, $directory); 1620 if (is_array($files)) { 1621 echo "<ul>\n"; 1622 foreach($files AS $f => $file) { 1623 echo "<li>\n"; 1624 if ($serious) { 1625 serendipity_deleteImage($file['id']); 1626 } else { 1627 echo $file['name'] . '.' . $file['extension']; 1628 } 1629 echo "</li>\n"; 1630 1631 unset($filestack[$file['name'] . '.' . $file['extension']]); 1632 unset($filestack[$file['name'] . (!empty($file['thumbnail_name']) ? '.' . $file['thumbnail_name'] : '') . '.' . $file['extension']]); 1633 } 1634 echo "</ul>\n"; 1635 } 1636 1637 if (count($filestack) > 0) { 1638 if ($forceDelete) { 1639 echo "<ul>\n"; 1640 foreach($filestack AS $f => $file) { 1641 if ($serious && @unlink($basedir . $file)) { 1642 printf('<li>' . DELETING_FILE . $n . DONE . "</li>\n", $file); 1643 } else { 1644 printf('<li>' . DELETING_FILE . $n . ERROR . "</li>\n", $file); 1645 } 1646 } 1647 echo "</ul>\n"; 1648 } else { 1649 echo ERROR_DIRECTORY_NOT_EMPTY . $n; 1650 echo "<ul>\n"; 1651 foreach($filestack AS $f => $file) { 1652 echo '<li>' . $file . "</li>\n"; 1653 } 1654 echo "</ul>\n"; 1655 } 1656 } 1657 1658 echo '<strong>'; 1659 if ($serious && !empty($directory) && !preg_match('@^.?/?$@', $directory) && @rmdir($basedir . $directory)) { 1660 printf(DIRECTORY_DELETE_SUCCESS . $n, $directory); 1661 } else { 1662 printf(DIRECTORY_DELETE_FAILED . $n, $directory); 1663 } 1664 echo '</strong>'; 1665 } 1666 1667 return true; 1668 } 1669 1670 1671 /** 1672 * Recursively walk a directory tree 1673 * 1674 * 1675 * @access public 1676 * @param string The core directory 1677 * @param string The subdirectory 1678 * @param boolean Only return directories instead of files as well? 1679 * @param string A regexp patter to include files 1680 * @param int Level of nesting (recursive use) 1681 * @param int The maximum level of nesting (recursive use) 1682 * @param mixed Toggle whether to apply serendipity_directoryACL (false / 'read' / 'write') 1683 * @param array An array of directories to skip [passed by plugins, for example] 1684 * @return array Array of files/directories 1685 */ 1686 function serendipity_traversePath($basedir, $dir='', $onlyDirs = true, $pattern = NULL, $depth = 1, $max_depth = NULL, $apply_ACL = false, $aExcludeDirs = NULL) { 1687 1688 if ($aExcludeDirs === null) { 1689 $aExcludeDirs = array("CVS" => true, ".svn" => true); 1690 } 1691 1692 $odir = serendipity_dirSlash('end', $basedir) . serendipity_dirSlash('end', $dir); 1693 $dh = @opendir($odir); 1694 if (!$dh) { 1695 return array(); 1696 } 1697 1698 $files = array(); 1699 while (($file = @readdir($dh)) !== false) { 1700 if ($file != '.' && $file != '..') { 1701 $bPatternMatch = (is_null($pattern) || preg_match($pattern, $file)); 1702 $sFullPath = $odir . $file; 1703 $bIsDir = is_dir($sFullPath); 1704 if ($onlyDirs === false || $bIsDir) { 1705 if ($bPatternMatch && 1706 (!$bIsDir || $aExcludeDirs == null || !isset($aExcludeDirs[$file]))) { 1707 $files[] = array( 1708 'name' => $file, 1709 'depth' => $depth, 1710 'relpath' => ltrim(str_replace('\\', '/', serendipity_dirSlash('end', $dir)) . basename($file) . ($bIsDir ? '/' : ''), '/'), 1711 'directory' => $bIsDir 1712 ); 1713 } 1714 } 1715 1716 if ($bIsDir && 1717 ($max_depth === null || $depth < $max_depth) && 1718 ($aExcludeDirs == null || !isset($aExcludeDirs[$file]))) { 1719 $next_dir = serendipity_dirSlash('end', $dir) . basename($file); 1720 $files = array_merge($files, serendipity_traversePath($basedir, $next_dir, $onlyDirs, $pattern, ($depth+1), $max_depth, $apply_ACL, $aExcludeDirs)); 1721 } 1722 } 1723 } 1724 1725 @closedir($dh); 1726 1727 if ($depth == 1 && $apply_ACL !== FALSE) { 1728 serendipity_directoryACL($files, $apply_ACL); 1729 } 1730 1731 return $files; 1732 } 1733 1734 /** 1735 * Custom usort() function that properly sorts a path 1736 * 1737 * @access public 1738 * @param array First array 1739 * @param array Second array 1740 * @return 1741 */ 1742 function serendipity_sortPath($a, $b) { 1743 return strcasecmp($a['relpath'], $b['relpath']); 1744 } 1745 1746 /** 1747 * Delete a directory with all its files 1748 * 1749 * @access public 1750 * @param string The directory to delete 1751 * @return 1752 */ 1753 function serendipity_deletePath($dir) { 1754 $d = dir($dir); 1755 if ($d) { 1756 while ($f = $d->read() ){ 1757 if ($f != '.' && $f != '..') { 1758 if (is_dir($dir . $f)){ 1759 serendipity_deletePath($dir . $f . '/'); 1760 rmdir($dir . $f); 1761 } 1762 1763 if (is_file($dir . $f)) { 1764 unlink($dir . $f); 1765 } 1766 } 1767 } 1768 1769 $d->close(); 1770 } 1771 } 1772 1773 /** 1774 * Check if a entered HTTP upload path is valid 1775 * 1776 * @access public 1777 * @param string The input filename 1778 * @param boolean Shall all paths be stripped? 1779 * @param boolean Shall a trailing slash be appended? 1780 * @return string The condom-wrapped path/file info 1781 */ 1782 function serendipity_uploadSecure($var, $strip_paths = true, $append_slash = false) { 1783 $var = preg_replace('@[^0-9a-z\._/-]@i', '', $var); 1784 if ($strip_paths) { 1785 $var = preg_replace('@(\.+[/\\\\]+)@', '/', $var); 1786 } 1787 1788 $var = preg_replace('@^(/+)@', '', $var); 1789 1790 if ($append_slash) { 1791 if (!empty($var) && substr($var, -1, 1) != '/') { 1792 $var .= '/'; 1793 } 1794 } 1795 1796 return $var; 1797 } 1798 1799 /** 1800 * Get the imagesize for a file 1801 * 1802 * @access public 1803 * @param string The filename of the image 1804 * @param string The mimetype of an image (can be autodetected) 1805 * @param string The file extension of an image 1806 * @return array The width/height of the file 1807 */ 1808 function serendipity_getimagesize($file, $ft_mime = '', $suf = '') { 1809 if (empty($ft_mime) && !empty($suf)) { 1810 $ft_mime = serendipity_guessMime($suf); 1811 } 1812 1813 if ($ft_mime == 'application/pdf') { 1814 $fdim = array(1000,1000,24, '', 'bits'=> 24, 'channels' => '3', 'mime' => 'application/pdf'); 1815 } else { 1816 $fdim = @getimagesize($file); 1817 } 1818 1819 if (is_array($fdim)) { 1820 if (empty($fdim['mime'])) { 1821 $fdim['mime'] = $ft_mime; 1822 } 1823 1824 if ($fdim['mime'] == 'image/vnd.wap.wbmp' && $ft_mime == 'video/x-quicktime') { 1825 // PHP Versions prior to 4.3.9 reported .mov files wrongly as WAP. Fix this and mark the file as 'non-image' with 0x0 dimensions 1826 $fdim['mime'] = $ft_mime; 1827 } 1828 } else { 1829 // The file is no image. Return a fake array so that files are inserted (but without a thumb) 1830 $fdim = array( 1831 0 => 0, 1832 1 => 0, 1833 'mime' => $ft_mime, 1834 'noimage' => true 1835 ); 1836 } 1837 1838 return $fdim; 1839 } 1840 1841 /** 1842 * Get the available fields of the media database 1843 * 1844 * @access public 1845 * @return array Array with available, sortable fields 1846 */ 1847 function serendipity_getImageFields() { 1848 global $serendipity; 1849 1850 $x = array( 1851 'i.date' => array('desc' => SORT_ORDER_DATE, 1852 'type' => 'date' 1853 ), 1854 1855 'i.name' => array('desc' => SORT_ORDER_NAME 1856 ), 1857 1858 'i.authorid' => array('desc' => AUTHOR, 1859 'type' => 'authors' 1860 ), 1861 1862 'i.extension' => array('desc' => SORT_ORDER_EXTENSION 1863 ), 1864 1865 'i.size' => array('desc' => SORT_ORDER_SIZE, 1866 'type' => 'intrange' 1867 ), 1868 1869 'i.dimensions_width' => array('desc' => SORT_ORDER_WIDTH, 1870 'type' => 'intrange' 1871 ), 1872 1873 'i.dimensions_height' => array('desc' => SORT_ORDER_HEIGHT, 1874 'type' => 'intrange' 1875 ) 1876 ); 1877 1878 $addProp = explode(';', $serendipity['mediaProperties']); 1879 foreach($addProp AS $prop) { 1880 $parts = explode(':', $prop); 1881 $name = $parts[0]; 1882 $x['bp.' . $name] = array('desc' => (defined('MEDIA_PROPERTY_' . $name) ? constant('MEDIA_PROPERTY_' . $name) : htmlspecialchars($name))); 1883 if (preg_match('@date@i', $name)) { 1884 $x['bp.' . $name]['type'] = 'date'; 1885 } 1886 if (preg_match('@length@i', $name)) { 1887 $x['bp.' . $name]['type'] = 'intrange'; 1888 } 1889 if (preg_match('@dpi@i', $name)) { 1890 $x['bp.' . $name]['type'] = 'int'; 1891 } 1892 } 1893 1894 return $x; 1895 } 1896 1897 /** 1898 * Escape a shell argument for imagemagick use 1899 * 1900 * @access public 1901 * @param string Input argument 1902 * @return string Output argument 1903 */ 1904 function serendipity_escapeshellarg($string) { 1905 return escapeshellarg(str_replace('%', '', $string)); 1906 } 1907 1908 /** 1909 * Rename a media directory 1910 * 1911 * @access public 1912 * @param string Old directory name 1913 * @param string New directory name 1914 */ 1915 function serendipity_renameDir($old, $new) { 1916 } 1917 1918 /** 1919 * Makes sure a directory begins with or ends with a "/" 1920 * 1921 * @access public 1922 * @param string Type of where to append/prepend slash ('end', 'start', 'both') 1923 * @param string Directory name 1924 * @return string Output argument 1925 */ 1926 function serendipity_dirSlash($type, $dir) { 1927 1928 if ($dir == '') { 1929 return $dir; 1930 } 1931 1932 if ($type == 'start' || $type == 'both') { 1933 if (substr($dir, 0, 1) != '/') { 1934 $dir = '/' . $dir; 1935 } 1936 } 1937 1938 if ($type == 'end' || $type == 'both') { 1939 if (substr($dir, -1) != '/') { 1940 $dir .= '/'; 1941 } 1942 } 1943 1944 return $dir; 1945 } 1946 1947 /** 1948 * Cycle a serendipity_traversePath resultset and apply read/write ACLs. 1949 * 1950 * @access public 1951 * @param array serendipity_traversePath result array 1952 * @param string ACL type ('read', 'write') 1953 */ 1954 function serendipity_directoryACL(&$paths, $type = 'read') { 1955 global $serendipity; 1956 static $debug = false; 1957 1958 if ($debug) { 1959 echo "Applying ACL for mode '$type'.<br />\n"; 1960 } 1961 1962 if (!is_array($paths)) { 1963 return true; 1964 } 1965 1966 $startCount = count($paths); 1967 if (!isset($serendipity['enableACL']) || $serendipity['enableACL'] == true) { 1968 // Check if we are a cool superuser. Bail out if we are. 1969 $logged_in = serendipity_userLoggedIn(); 1970 if ($logged_in && serendipity_checkPermission('adminImagesMaintainOthers') && serendipity_checkPermission('adminImagesDirectories')) { 1971 if (!$debug) { 1972 return true; 1973 } 1974 } 1975 1976 // Get list of all ACLs for directories. 1977 $q = "SELECT a.artifact_index AS directory, 1978 a.groupid 1979 FROM {$serendipity['dbPrefix']}access AS a 1980 WHERE a.artifact_type = 'directory' 1981 AND a.artifact_mode = '" . serendipity_db_escape_string($type) . "'"; 1982 $allowed = serendipity_db_query($q); 1983 if (!is_array($allowed)) { 1984 return true; 1985 } 1986 1987 // Get a list of all the groups for this user. Pipe it into a usable array. 1988 if ($logged_in) { 1989 $my_groups =& serendipity_getGroups($serendipity['authorid']); 1990 $acl_allowed_groups = array(); 1991 foreach($my_groups AS $my_group) { 1992 $acl_allowed_groups[$my_group['id']] = true; 1993 } 1994 } else { 1995 // Only the 'ALL AUTHORS' group is valid for non-logged in authors. 1996 $acl_allowed_groups = array(0 => true); 1997 } 1998 1999 // Iterate every ACL and check if we are allowed to use it. Parse that data into a workable array. 2000 $acl_allowed = array(); 2001 foreach($allowed AS $row) { 2002 $acl_allowed[$row['directory']][$row['groupid']] = true; 2003 } 2004 2005 // Iterate the input path array and check it against ACL. 2006 foreach($paths AS $idx => $info) { 2007 if (!isset($acl_allowed[$info['relpath']])) { 2008 // ACL for directory not set. Assume we are allowed to access. 2009 continue; 2010 } 2011 2012 $granted = false; 2013 foreach($acl_allowed[$info['relpath']] AS $groupid => $set) { 2014 if ($groupid === 0 || isset($acl_allowed_groups[$groupid])) { 2015 // We are allowed to access this element 2016 $granted = true; 2017 break; 2018 } 2019 } 2020 2021 if ($granted === false) { 2022 // We are not allowed to access this element 2023 if ($debug) { 2024 echo "ACL for " . $info['relpath'] . " DENIED.<br />\n"; 2025 } 2026 unset($paths[$idx]); 2027 } else { 2028 if ($debug) { 2029 echo "ACL for " . $info['relpath'] . " granted.<br />\n"; 2030 } 2031 } 2032 } 2033 2034 if (count($paths) < $startCount) { 2035 if ($debug) { 2036 echo "ACL denied all.<br />\n"; 2037 } 2038 return false; 2039 } 2040 } 2041 2042 return true; 2043 } 2044 2045 /** 2046 * Build the name of a thumbnail image file. 2047 * 2048 * @author MTG 2049 * @param string Relative Path 2050 * @param string File name 2051 * @param string File extension 2052 * @param string Thumbnail suffix 2053 * @return array Thumbnail path 2054 * 2055 */ 2056 function serendipity_getThumbNailPath($sRelativePath, $sName, $sExtension, $sThumbName) { 2057 $aTempArray = array('path' => $sRelativePath, 2058 'name' => $sName, 2059 'extension' => $sExtension); 2060 serendipity_plugin_api::hook_event('backend_thumbnail_filename_select', $aTempArray); 2061 2062 if (isset($aTempArray['thumbnail_filename'])) { 2063 $sThumbNailPath = $aTempArray['thumbnail_filename']; 2064 } else { 2065 $sThumbNailPath = $sRelativePath . $sName . (!empty($sThumbName) ? '.' . $sThumbName : '') . '.' . $sExtension; 2066 } 2067 2068 return $sThumbNailPath; 2069 } 2070 2071 /** 2072 * Given a relative path to an image, construct an array containing all 2073 * relevant information about that image in the file structure. 2074 * 2075 * @author MTG 2076 * @param string Relative Path 2077 * @return array Data about image 2078 * 2079 */ 2080 function &serendipity_getImageData($sRelativePath) { 2081 global $serendipity; 2082 2083 // First, peel off the file name from the path 2084 $nPos = strrpos($sRelativePath, '/'); 2085 if (is_bool($nPos) && !$nPos) { 2086 $sFileName = $sRelativePath; 2087 $sDirectory = ''; 2088 } else { 2089 $nLastSlashPos = 1 + $nPos; 2090 $sFileName = substr($sRelativePath, $nLastSlashPos); 2091 $sDirectory = substr($sRelativePath, 0, $nLastSlashPos); 2092 } 2093 2094 list($sName, $sExtension) = serendipity_parseFileName($sFileName); 2095 2096 $sImagePath = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $sRelativePath; 2097 2098 $aSizeData = @serendipity_getimagesize($sImagePath , '', $sExtension); 2099 $nWidth = $aSizeData[0]; 2100 $nHeight = $aSizeData[1]; 2101 $sMime = $aSizeData['mime']; 2102 $nFileSize = @filesize($sImagePath); 2103 2104 $array = array( 2105 'name' => $sName, 2106 'extension' => $sExtension, 2107 'mime' => $sMime, 2108 'size' => $nFileSize, 2109 'dimensions_width' => $nWidth, 2110 'dimensions_height' => $nHeight, 2111 'path' => $sDirectory, 2112 'authorid' => 0, 2113 'hotlink' => 0, 2114 'id' => $sRelativePath, 2115 'realname' => $sFilename 2116 ); 2117 2118 return $array; 2119 } 2120 2121 /** 2122 * Shows the HTML form to add/edit properties of uploaded media items 2123 * 2124 * @param array Associative array holding an array('image_id', 'target', 'created_thumbnail') that points to the uploaded media 2125 * @param int How many keyword checkboxes to display next to each other? 2126 * @param boolean Can existing data be modified? 2127 * @return boolean 2128 * 2129 */ 2130 function serendipity_showPropertyForm(&$new_media, $keywordsPerBlock = 3, $is_edit = true) { 2131 global $serendipity; 2132 2133 if (!is_array($new_media) || count($new_media) < 1) { 2134 return true; 2135 } 2136 2137 $mirror = array(); 2138 serendipity_checkPropertyAccess($new_media, $mirror, 'read'); 2139 2140 $editform_hidden = ''; 2141 if (isset($GLOBALS['image_selector_addvars']) && is_array($GLOBALS['image_selector_addvars'])) { 2142 // These variables may come from serendipity_admin_image_selector.php to show embedded upload form 2143 foreach($GLOBALS['image_selector_addvars'] AS $imgsel_key => $imgsel_val) { 2144 $editform_hidden .= ' <input type="hidden" name="serendipity[' . htmlspecialchars($imgsel_key) . ']" value="' . htmlspecialchars($imgsel_val) . '" />' . "\n"; 2145 } 2146 } 2147 2148 $dprops = explode(';', $serendipity['mediaProperties']); 2149 $keywords = explode(';', $serendipity['mediaKeywords']); 2150 2151 $now = serendipity_serverOffsetHour(); 2152 $show = array(); 2153 foreach($new_media AS $idx => $media) { 2154 $props =& serendipity_fetchMediaProperties($media['image_id']); 2155 2156 $show[$idx] =& $media['internal']; 2157 $show[$idx]['image_id'] = $media['image_id']; 2158 2159 serendipity_prepareMedia($show[$idx]); 2160 if (!is_array($props['base_metadata'])) { 2161 $show[$idx]['metadata'] =& serendipity_getMetaData($show[$idx]['realfile'], $show[$idx]['header']); 2162 } else { 2163 $show[$idx]['metadata'] = $props['base_metadata']; 2164 serendipity_plugin_api::hook_event('media_getproperties_cached', $show[$idx]['metadata'], $show[$idx]['realfile']); 2165 } 2166 2167 serendipity_parseMediaProperties($dprops, $keywords, $show[$idx], $props, $keywordsPerBlock, $is_edit); 2168 } 2169 2170 $smarty_vars = array( 2171 'is_edit' => $is_edit, 2172 'editform_hidden' => $editform_hidden, 2173 'keywordsPerBlock' => $keywordsPerBlock, 2174 'keywords' => $keywords, 2175 'dprops' => $dprops 2176 ); 2177 2178 return serendipity_showMedia( 2179 $show, 2180 $mirror, 2181 $url, 2182 false, 2183 1, 2184 false, 2185 $smarty_vars); 2186 } 2187 2188 /** 2189 * Parse/Convert properties 2190 * 2191 * @param array Holds the property key array 2192 * @param array Holds the keyword key array 2193 * @param int Holds the media metadata 2194 * @param int Holds the media properties 2195 * @param int How many keyword checkboxes to display next to each other? 2196 * @param boolean Can existing data be modified? 2197 * @return boolean 2198 * 2199 */ 2200 function serendipity_parseMediaProperties(&$dprops, &$keywords, &$media, &$props, $keywordsPerBlock, $is_edit) { 2201 global $serendipity; 2202 2203 if (!is_array($dprops)) { 2204 $dprops = explode(';', $serendipity['mediaProperties']); 2205 } 2206 if (!is_array($keywords)) { 2207 $keywords = explode(';', $serendipity['mediaKeywords']); 2208 } 2209 2210 $media['references'] = serendipity_db_query("SELECT link, name 2211 FROM {$serendipity['dbPrefix']}references 2212 WHERE entry_id = " . $media['id'] . " 2213 AND type = 'media' 2214 ORDER BY name DESC 2215 LIMIT 15", false, 'assoc'); 2216 if (!is_array($media['references'])) { 2217 $media['references'] = false; 2218 } 2219 2220 foreach($dprops AS $prop) { 2221 $type = 'input'; 2222 $parts = explode(':', trim($prop)); 2223 2224 if (in_array('MULTI', $parts)) { 2225 $type = 'textarea'; 2226 } 2227 2228 if (preg_match('@(AUDIO|VIDEO|DOCUMENT|IMAGE|ARCHIVE|BINARY)@i', $prop)) { 2229 $show_item = false; 2230 if ($media['mediatype'] == 'video' && in_array('VIDEO', $parts)) { 2231 $show_item = true; 2232 } 2233 2234 if ($media['mediatype'] == 'audio' && in_array('AUDIO', $parts)) { 2235 $show_item = true; 2236 } 2237 2238 if ($media['mediatype'] == 'image' && in_array('IMAGE', $parts)) { 2239 $show_item = true; 2240 } 2241 2242 if ($media['mediatype'] == 'document' && in_array('DOCUMENT', $parts)) { 2243 $show_item = true; 2244 } 2245 2246 if ($media['mediatype'] == 'archive' && in_array('ARCHIVE', $parts)) { 2247 $show_item = true; 2248 } 2249 2250 if ($media['mediatype'] == 'binary' && in_array('BINARY', $parts)) { 2251 $show_item = true; 2252 } 2253 2254 if (!$show_item) { 2255 continue; 2256 } 2257 } 2258 2259 if (!$is_edit) { 2260 $type = 'readonly'; 2261 } 2262 $val =& serendipity_mediaTypeCast($parts[0], $props['base_property'][$parts[0]], true); 2263 2264 $propkey = htmlspecialchars($parts[0]) . $idx; 2265 2266 $media['base_property'][$propkey] = array( 2267 'label' => htmlspecialchars(defined('MEDIA_PROPERTY_' . strtoupper($parts[0])) ? constant('MEDIA_PROPERTY_' . strtoupper($parts[0])) : $parts[0]), 2268 'type' => $type, 2269 'val' => $val, 2270 'title' => htmlspecialchars($parts[0]) 2271 ); 2272 2273 if (empty($val)) { 2274 switch($parts[0]) { 2275 case 'DATE': 2276 $media['base_property'][$propkey]['val'] = serendipity_strftime(DATE_FORMAT_SHORT, serendipity_pickKey($media['metadata'], 'DateCreated', $now)); 2277 break; 2278 2279 case 'RUN_LENGTH': 2280 $media['base_property'][$propkey]['val'] = serendipity_pickKey($media['metadata'], 'RunLength', '00:00:00.00'); 2281 break; 2282 2283 case 'DPI': 2284 $media['base_property'][$propkey]['val'] = serendipity_pickKey($media['metadata'], 'XResolution', 72); 2285 break; 2286 2287 case 'COPYRIGHT': 2288 $media['base_property'][$propkey]['val'] = serendipity_pickKey($media['metadata'], 'Creator', $serendipity['serendipityUser']); 2289 break; 2290 2291 case 'TITLE': 2292 $media['base_property'][$propkey]['val'] = serendipity_pickKey($media['metadata'], 'Title', $media['internal']['realname']); 2293 break; 2294 2295 case 'COMMENT1': 2296 $media['base_property'][$propkey]['val'] = serendipity_pickKey($media['metadata'], 'Keywords', ''); 2297 break; 2298 2299 case 'COMMENT2': 2300 $media['base_property'][$propkey]['val'] = serendipity_pickKey($media['metadata'], 'PhotoLocation', ''); 2301 break; 2302 2303 default: 2304 serendipity_plugin_api::hook_event('media_showproperties', $media, $propkey); 2305 break; 2306 } 2307 } 2308 } 2309 2310 if ($keywordsPerBlock > 0) { 2311 $rows = ceil(count($keywords) / $keywordsPerBlock); 2312 for($i = 0; $i < $rows; $i++) { 2313 for ($j = 0; $j < $keywordsPerBlock; $j++) { 2314 $kidx = ($i*$keywordsPerBlock) + $j; 2315 if (isset($keywords[$kidx])) { 2316 $media['base_keywords'][$i][$j] = array( 2317 'name' => htmlspecialchars($keywords[$kidx]), 2318 'selected' => isset($props['base_keyword'][$keywords[$kidx]]) ? true : false 2319 ); 2320 } else { 2321 $media['base_keywords'][$i][$j] = array(); 2322 } 2323 } 2324 } 2325 } 2326 } 2327 2328 /** 2329 * Tries to auto-convert specific fields into DB-storable values 2330 * 2331 * @param string The keyname 2332 * @param string The value 2333 * @param string Invert? 2334 * @return array array('image_id') holding the last created thumbnail for immediate processing 2335 * 2336 */ 2337 function serendipity_mediaTypeCast($key, $val, $invert = false) { 2338 if (stristr($key, 'date') !== FALSE) { 2339 if ($invert && is_numeric($val)) { 2340 return serendipity_strftime(DATE_FORMAT_SHORT, $val, false); 2341 } elseif ($invert === false) { 2342 $tmp = strtotime($val); 2343 if ($tmp !== FALSE && $tmp > 1) { 2344 return $tmp; 2345 } 2346 } 2347 } elseif ($invert && stristr($key, 'length') !== FALSE) { 2348 $tmp = ''; 2349 2350 $hours = intval(intval($val) / 3600); 2351 $minutes = intval(($val / 60) % 60); 2352 $seconds = intval($val % 60); 2353 $mseconds = intval((($val - $seconds) * 100) % 100); 2354 2355 $tmp .= str_pad($hours, 2, '0', STR_PAD_LEFT) . ':'; 2356 $tmp .= str_pad($minutes, 2, '0', STR_PAD_LEFT). ':'; 2357 $tmp .= str_pad($seconds, 2, '0', STR_PAD_LEFT) . '.'; 2358 $tmp .= str_pad($mseconds, 2, '0', STR_PAD_LEFT); 2359 2360 return $tmp; 2361 } elseif ($invert === false && preg_match('@^([0-9]+):([0-9]+):([0-9]+).([0-9]+)$@i', $val, $m)) { 2362 $tmp = ($m[1] * 3600) 2363 + ($m[2] * 60) 2364 + ($m[3]) 2365 + ($m[4] / 100); 2366 return $tmp; 2367 } 2368 2369 return $val; 2370 } 2371 2372 /** 2373 * Inserts media properties 2374 * 2375 * @param string Property_group 2376 * @return array array('image_id') holding the last created thumbnail for immediate processing 2377 * 2378 */ 2379 function serendipity_insertMediaProperty($property_group, $property_subgroup = '', $image_id, &$media, $use_cast = true) { 2380 global $serendipity; 2381 2382 serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}mediaproperties 2383 WHERE mediaid = " . (int)$image_id . " 2384 " . ($property_subgroup != 'ALL' ? "AND property_subgroup = '" . serendipity_db_escape_string($property_subgroup) . "'" : '') . " 2385 AND property_group = '" . serendipity_db_escape_string($property_group) . "'"); 2386 2387 if (is_array($media)) { 2388 foreach($media AS $key => $val) { 2389 if ($key == 'image_id') continue; 2390 2391 if (is_array($val)) { 2392 $use_property_subgroup = $key; 2393 $use_val = $val; 2394 } else { 2395 $use_property_subgroup = $property_subgroup; 2396 $use_val = array($key => $val); 2397 } 2398 2399 foreach($use_val AS $insert_key => $insert_val) { 2400 if ($use_cast) { 2401 $insert_val = serendipity_mediaTypeCast($insert_key, $insert_val); 2402 } 2403 $q = sprintf("INSERT INTO {$serendipity['dbPrefix']}mediaproperties 2404 (mediaid, property_group, property_subgroup, property, value) 2405 VALUES (%d, '%s', '%s', '%s', '%s')", 2406 $image_id, 2407 serendipity_db_escape_string($property_group), 2408 serendipity_db_escape_string($useproperty_subgroup), 2409 serendipity_db_escape_string($insert_key), 2410 serendipity_db_escape_string($insert_val)); 2411 serendipity_db_query($q); 2412 } 2413 } 2414 } 2415 } 2416 2417 /** 2418 * Inserts the submitted properties of uploaded media items 2419 * 2420 * @return array array('image_id') holding the last created thumbnail for immediate processing 2421 * 2422 */ 2423 function serendipity_parsePropertyForm() { 2424 global $serendipity; 2425 2426 if (!is_array($serendipity['POST']['mediaProperties'])) { 2427 return false; 2428 } 2429 2430 serendipity_checkPropertyAccess($serendipity['POST']['mediaProperties'], $serendipity['POST']['mediaKeywords'], 'write'); 2431 2432 foreach($serendipity['POST']['mediaProperties'] AS $id => $media) { 2433 serendipity_insertMediaProperty('base_property', '', $media['image_id'], $media); 2434 2435 $s9y_img = $media['internal']; 2436 $s9y_img['image_id'] = $media['image_id']; 2437 serendipity_prepareMedia($s9y_img); 2438 $s9y_img['metadata'] =& serendipity_getMetaData($s9y_img['realfile'], $s9y_img['header']); 2439 serendipity_insertMediaProperty('base_metadata', 'ALL', $media['image_id'], $s9y_img['metadata']); 2440 $s9y_img['hidden'] = array( 2441 'author' => $serendipity['serendipityUser'], 2442 'authorid' => $serendipity['authorid'] 2443 ); 2444 serendipity_insertMediaProperty('base_hidden', '', $media['image_id'], $s9y_img['hidden']); 2445 2446 if ($serendipity['POST']['oldDir'][$id] != $serendipity['POST']['newDir'][$id]) { 2447 serendipity_moveMediaDirectory( 2448 serendipity_uploadSecure($serendipity['POST']['oldDir'][$id]), 2449 serendipity_uploadSecure($serendipity['POST']['newDir'][$id]), 2450 'filedir', 2451 $media['image_id']); 2452 } 2453 } 2454 2455 if (is_array($serendipity['POST']['mediaKeywords'])) { 2456 foreach($serendipity['POST']['mediaKeywords'] AS $id => $keywords) { 2457 serendipity_insertMediaProperty('base_keyword', '', $serendipity['POST']['mediaProperties'][$id]['image_id'], $keywords); 2458 } 2459 } 2460 2461 $array = array( 2462 'image_id' => $serendipity['POST']['mediaProperties'][0]['image_id'], 2463 ); 2464 2465 return $array; 2466 } 2467 2468 /** 2469 * Fetches existing Media Properties for images 2470 * 2471 * @param int The media item id 2472 * @return array Array of image metadata 2473 * 2474 */ 2475 function &serendipity_fetchMediaProperties($id) { 2476 global $serendipity; 2477 2478 $sql = "SELECT mediaid, property, property_group, property_subgroup, value 2479 FROM {$serendipity['dbPrefix']}mediaproperties 2480 WHERE mediaid IN (" . (is_array($id) ? serendipity_db_implode(',', $id) : (int)$id) . ")"; 2481 $rows = serendipity_db_query($sql, false, 'assoc'); 2482 $props = array(); 2483 if (is_array($rows)) { 2484 foreach($rows AS $row) { 2485 if (empty($row['property_subgroup'])) { 2486 if (is_array($id)) { 2487 $props[$row['mediaid']][$row['property_group']][$row['property']] = $row['value']; 2488 } else { 2489 $props[$row['property_group']][$row['property']] = $row['value']; 2490 } 2491 } else { 2492 if (is_array($id)) { 2493 $props[$row['mediaid']][$row['property_group']][$row['property_subgroup']][$row['property']] = $row['value']; 2494 } else { 2495 $props[$row['property_group']][$row['property_subgroup']][$row['property']] = $row['value']; 2496 } 2497 } 2498 } 2499 } 2500 return $props; 2501 } 2502 2503 /** 2504 * Checks if properties to a specific image are allowed to be fetched 2505 * 2506 * @param array Array of image metadata 2507 * @param array Array of additional image metadata 2508 * @param string ACL toggle type ('read', 'write') 2509 * @return array Stripped Array of image metadata 2510 * 2511 */ 2512 function serendipity_checkPropertyAccess(&$new_media, &$additional, $mode = 'read') { 2513 global $serendipity; 2514 2515 // Strip out images we don't have access to 2516 $ids = array(); 2517 foreach($new_media AS $id => $item) { 2518 $ids[] = $item['image_id']; 2519 } 2520 2521 $valid_images = serendipity_fetchImageFromDatabase($ids, $mode); 2522 foreach ($new_media AS $id => $media) { 2523 if (!isset($valid_images[$media['image_id']])) { 2524 unset($new_media[$id]); 2525 unset($additional[$id]); 2526 } else { 2527 $new_media[$id]['internal'] = $valid_images[$media['image_id']]; 2528 } 2529 } 2530 2531 return true; 2532 } 2533 2534 /** 2535 * Prepare a media item for showing 2536 * 2537 * @param array Array of image metadata 2538 * @param string URL for maintenance tasks 2539 * @return bool 2540 * 2541 */ 2542 function serendipity_prepareMedia(&$file, $url = '') { 2543 global $serendipity; 2544 static $full_perm = null; 2545 2546 if ($full_perm === null) { 2547 $full_perm = serendipity_checkPermission('adminImagesMaintainOthers'); 2548 } 2549 2550 $sThumbSource = serendipity_getThumbNailPath($file['path'], $file['name'], $file['extension'], $file['thumbnail_name']); 2551 $file['full_thumb'] = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $sThumbSource; 2552 $file['full_thumbHTTP'] = $serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $sThumbSource; 2553 2554 if ($file['hotlink']) { 2555 $file['full_file'] = $file['path']; 2556 $file['show_thumb'] = $file['path']; 2557 if (!isset($file['imgsrc'])) { 2558 $file['imgsrc'] = $file['show_thumb']; 2559 } 2560 } else { 2561 $file['full_file'] = $serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $file['path'] . $file['name'] . '.'. $file['extension']; 2562 $file['show_thumb'] = $file['full_thumbHTTP']; 2563 if (!isset($file['imgsrc'])) { 2564 $file['imgsrc'] = $serendipity['uploadHTTPPath'] . $file['path'] . $file['name'] . (!empty($file['thumbnail_name']) ? '.' . $file['thumbnail_name'] : '') . '.' . $file['extension']; 2565 } 2566 } 2567 2568 if (empty($file['realname'])) { 2569 $file['realname'] = $file['name'] . '.' . $file['extension']; 2570 } 2571 $file['diskname'] = $file['name'] . '.' . $file['extension']; 2572 2573 $file['links'] = array('imagelinkurl' => $file['full_file']); 2574 2575 $file['dim'] = @getimagesize($file['full_thumb'], $file['header']); 2576 $file['is_image'] = serendipity_isImage($file); 2577 2578 if ($file['is_image']) { 2579 $file['mediatype'] = 'image'; 2580 } elseif (0 === strpos(strtolower($file['displaymime']), 'video/') || 0 === strpos(strtolower($file['displaymime']), 'application/x-shockwave')) { 2581 $file['mediatype'] = 'video'; 2582 } elseif (0 === strpos(strtolower($file['displaymime']), 'audio/') || 0 === strpos(strtolower($file['displaymime']), 'application/vnd.rn-') || 0 === strpos(strtolower($file['displaymime']), 'application/ogg')) { 2583 $file['mediatype'] = 'audio'; 2584 } elseif (0 === strpos(strtolower($file['displaymime']), 'text/')) { 2585 $file['mediatype'] = 'document'; 2586 } elseif (preg_match('@application/(pdf|rtf|msword|msexcel|excel|x-excel|mspowerpoint|postscript|vnd\.ms*|powerpoint)@i', $file['displaymime'])) { 2587 $file['mediatype'] = 'document'; 2588 } elseif (preg_match('@application/(java-archive|zip|gzip|arj|x-bzip|x-bzip2|x-compressed|x-gzip|x-stuffit)@i', $file['displaymime'])) { 2589 $file['mediatype'] = 'archive'; 2590 } else { 2591 $file['mediatype'] = 'binary'; 2592 } 2593 2594 $file['realfile'] = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] . '.'. $file['extension']; 2595 2596 if ($full_perm || $serendipity['authorid'] == $file['authorid'] || $file['authorid'] == '0') { 2597 $file['is_editable'] = true; 2598 } else { 2599 $file['is_editable'] = false; 2600 } 2601 2602 /* If it is an image, and the thumbnail exists */ 2603 if ($file['is_image'] && file_exists($file['full_thumb'])) { 2604 $file['thumbWidth'] = $file['dim'][0]; 2605 $file['thumbHeight'] = $file['dim'][1]; 2606 $file['preview'] .= '<img src="' . $serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $sThumbSource . '" border="0" title="' . $file['path'] . $file['name'] . '" alt="'. $file['realname'] . '" />'; 2607 if ($url) { 2608 $file['preview_url'] = $url .'&serendipity[image]='. $file['id']; 2609 $file['preview'] = '<a href="'. $file['preview_url'] .'">'. $file['preview'] .'</a>'; 2610 } 2611 } elseif ($file['is_image'] && $file['hotlink']) { 2612 $sizes = serendipity_calculate_aspect_size($file['dimensions_width'], $file['dimensions_height'], $serendipity['thumbSize']); 2613 $file['thumbWidth'] = $sizes[0]; 2614 $file['thumbHeight'] = $sizes[1]; 2615 $file['preview'] .= '<img src="' . $file['path'] . '" width="' . $sizes[0] . '" height="' . $sizes[1] . '" border="0" title="' . $file['path'] . '" alt="'. $file['realname'] . '" />'; 2616 if ($url) { 2617 $file['preview_url'] = $url .'&serendipity[image]='. $file['id']; 2618 $file['preview'] = '<a href="'. $file['preview_url'] .'">'. $file['preview'] .'</a>'; 2619 } 2620 /* If it's not an image, or the thumbnail does not exist */ 2621 } else { 2622 $mimeicon = serendipity_getTemplateFile('admin/img/mime_' . preg_replace('@[^a-z0-9\-\_]@i', '-', $file['mime']) . '.png'); 2623 if (!$mimeicon) { 2624 $mimeicon = serendipity_getTemplateFile('admin/img/mime_unknown.png'); 2625 } 2626 $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>'; 2627 if ($url) { 2628 $file['preview_url'] = $url .'&serendipity[image]='. $file['id']; 2629 $file['preview'] .= '<br /><a href="' . $file['preview_url'] . '">' . $file['name'] . '.' . $file['extension'] . '</a>'; 2630 } 2631 } 2632 2633 $file['popupWidth'] = ($file['is_image'] ? ($file['dimensions_width'] + 20) : 600); 2634 $file['popupHeight'] = ($file['is_image'] ? ($file['dimensions_height'] + 20) : 500); 2635 if ($file['hotlink']) { 2636 $file['nice_hotlink'] = wordwrap($file['path'], 45, '<br />', 1); 2637 } 2638 $file['nice_size'] = number_format(round($file['size']/1024, 2), NUMBER_FORMAT_DECIMALS, NUMBER_FORMAT_DECPOINT, NUMBER_FORMAT_THOUSANDS); 2639 2640 return true; 2641 } 2642 2643 /** 2644 * Prints a media item 2645 * 2646 * @param array Array of image metadata 2647 * @param string URL for maintenance tasks 2648 * @param boolean Whether to show maintenance task items 2649 * @param int how many media items to display per row 2650 * @param boolean Enclose within a table cell? 2651 * @param array Additional Smarty variables 2652 * @param boolean If TRUE, will echo Smarty output. 2653 * @return string Smarty block name 2654 * 2655 */ 2656 function serendipity_showMedia(&$file, &$paths, $url = '', $manage = false, $lineBreak = 3, $enclose = true, $smarty_vars = array(), $smarty_display = true) { 2657 global $serendipity; 2658 2659 $form_hidden = ''; 2660 foreach($serendipity['GET'] AS $g_key => $g_val) { 2661 if (!is_array($g_val) && $g_key != 'page') { 2662 $form_hidden .= '<input type="hidden" name="serendipity[' . $g_key . ']" value="' . htmlspecialchars($g_val) . '" />'; 2663 } 2664 } 2665 2666 serendipity_smarty_init(); 2667 $media = array( 2668 'manage' => $manage, 2669 'lineBreak' => $lineBreak, 2670 'lineBreakP' => round(1/$lineBreak*100), 2671 'url' => $url, 2672 'enclose' => $enclose, 2673 'zoomIMG' => serendipity_getTemplateFile('admin/img/big_zoom.png'), 2674 'renameIMG' => serendipity_getTemplateFile('admin/img/big_rename.png'), 2675 'resizeIMG' => serendipity_getTemplateFile('admin/img/big_resize.png'), 2676 'rotatecwIMG' => serendipity_getTemplateFile('admin/img/big_rotate_cw.png'), 2677 'rotateccwIMG' => serendipity_getTemplateFile('admin/img/big_rotate_ccw.png'), 2678 'configureIMG' => serendipity_getTemplateFile('admin/img/configure.png'), 2679 'deleteIMG' => serendipity_getTemplateFile('admin/img/big_delete.png'), 2680 'prevIMG' => serendipity_getTemplateFile('admin/img/previous.png'), 2681 'nextIMG' => serendipity_getTemplateFile('admin/img/next.png'), 2682 'token' => serendipity_setFormToken(), 2683 'form_hidden' => $form_hidden, 2684 'blimit_path' => basename($limit_path), 2685 'only_path' => $serendipity['GET']['only_path'], 2686 'only_filename' => $serendipity['GET']['only_filename'], 2687 'sortorder' => $serendipity['GET']['sortorder'], 2688 'keywords_selected' => $serendipity['GET']['keywords'], 2689 'filter' => $serendipity['GET']['filter'], 2690 'sort_order' => serendipity_getImageFields(), 2691 'authors' => serendipity_fetchUsers(), 2692 'sort_row_interval' => array(8, 16, 50, 100), 2693 'nr_files' => count($file), 2694 'keywords' => explode(';', $serendipity['mediaKeywords']), 2695 ); 2696 2697 $media = array_merge($media, $smarty_vars); 2698 $media['files'] =& $file; 2699 if (count($paths) > 0) { 2700 $media['paths'] =& $paths; 2701 } else { 2702 $media['paths'] =& serendipity_getMediaPaths(); 2703 } 2704 2705 $serendipity['smarty']->assign_by_ref('media', $media); 2706 2707 if ($enclose) { 2708 serendipity_smarty_fetch('MEDIA_ITEMS', 'admin/media_items.tpl'); 2709 $block = 'admin/media_pane.tpl'; 2710 if ($smarty_display) { 2711 $serendipity['smarty']->display(serendipity_getTemplateFile('admin/media_pane.tpl', 'serendipityPath')); 2712 } 2713 } else { 2714 serendipity_smarty_fetch('MEDIA_ITEMS', 'admin/media_items.tpl'); 2715 $block = 'admin/media_properties.tpl'; 2716 if ($smarty_display) { 2717 $serendipity['smarty']->display(serendipity_getTemplateFile('admin/media_properties.tpl', 'serendipityPath')); 2718 } 2719 } 2720 2721 return $block; 2722 } 2723 2724 /** 2725 * Convert a IPTC/EXIF/XMP item 2726 * 2727 * @param string The content 2728 * @param string The type of the content 2729 * @return string The converted content 2730 * 2731 */ 2732 function serendipity_metaFieldConvert(&$item, $type) { 2733 switch($type) { 2734 case 'math': 2735 $parts = explode('/', $item); 2736 return ($parts[0] / $parts[1]); 2737 break; 2738 2739 case 'or': 2740 if ($item == '1') { 2741 return 'Landscape'; 2742 } else { 2743 return 'Portrait'; 2744 } 2745 2746 case 'date': 2747 return strtotime($item); 2748 break; 2749 2750 case 'date2': 2751 $parts = explode(':', $item); 2752 return mktime($parts[3], $parts[4], $parts[5], $parts[1], $parts[2], $parts[0]); 2753 break; 2754 2755 case 'rdf': 2756 if (preg_match('@<rdf:li[^>]*>(.*)</rdf:li>@i', $item, $ret)) { 2757 return $ret[1]; 2758 } 2759 break; 2760 2761 case 'text': 2762 default: 2763 return trim($item); 2764 break; 2765 } 2766 2767 return ''; 2768 } 2769 2770 /** 2771 * Get the RAW media header data (XMP) 2772 * 2773 * @param string Filename 2774 * @return array The raw media header data 2775 * 2776 * Inspired, but rewritten, by "PHP JPEG Metadata Toolkit" from http://electronics.ozhiker.com. 2777 * Code is GPL so sadly we couldn't bundle that GREAT library. 2778 */ 2779 function serendipity_getMediaRaw($filename) { 2780 $abort = false; 2781 2782 $f = @fopen($filename, 'rb'); 2783 $ret = array(); 2784 if (!$f) { 2785 return $ret; 2786 } 2787 2788 $filedata = fread($f, 2); 2789 2790 if ($filedata != "\xFF\xD8") { 2791 fclose($f); 2792 return $ret; 2793 } 2794 2795 $filedata = fread($f, 2); 2796 2797 if ($filedata{0} != "\xFF") { 2798 fclose($f); 2799 return $ret; 2800 } 2801 2802 while (!$abort && !feof($f) && $filedata{1} != "\xD9") { 2803 if ((ord($filedata{1}) < 0xD0) || (ord($filedata{1}) > 0xD7)) { 2804 $ordret = fread($f, 2); 2805 $ordstart = ftell($f); 2806 $int = unpack('nsize', $ordret); 2807 2808 if (ord($filedata{1}) == 225) { 2809 $content = fread($f, $int['size'] - 2); 2810 2811 if (substr($content, 0, 24) == 'http://ns.adobe.com/xap/') { 2812 $ret[] = array( 2813 'ord' => ord($filedata{1}), 2814 'ordstart' => $ordstart, 2815 'int' => $int, 2816 'content' => $content 2817 ); 2818 } 2819 } else { 2820 fseek($f, $int['size'] - 2, SEEK_CUR); 2821 } 2822 } 2823 2824 if ($filedata{1} == "\xDA") { 2825 $abort = true; 2826 } else { 2827 $filedata = fread($f, 2); 2828 if ($filedata{0} != "\xFF") { 2829 fclose($f); 2830 return $ret; 2831 } 2832 } 2833 } 2834 2835 fclose($f); 2836 2837 return $ret; 2838 } 2839 2840 /** 2841 * Get the IPTC/EXIF/XMP media metadata 2842 * 2843 * @param string Filename 2844 * @return array The raw media header data 2845 * 2846 */ 2847 function &serendipity_getMetaData($file, &$info) { 2848 global $serendipity; 2849 2850 # Fields taken from: http://demo.imagefolio.com/demo/ImageFolio31_files/skins/cool_blue/images/iptc.html 2851 static $IPTC_Fields = array( 2852 '2#005' => 'ObjectName', 2853 '2#025' => 'Keywords', 2854 '2#026' => 'LocationCode', 2855 '2#027' => 'LocationName', 2856 '2#030' => 'ReleaseDate', 2857 '2#035' => 'ReleaseTime', 2858 '2#037' => 'ExpirationDate', 2859 '2#038' => 'ExpirationTime', 2860 '2#055' => 'DateCreated', 2861 '2#060' => 'TimeCreated', 2862 '2#062' => 'DigitalDateCreated', 2863 '2#063' => 'DigitalTimeCreated', 2864 '2#065' => 'Software', 2865 '2#070' => 'SoftwareVersion', 2866 '2#080' => 'Photographer', 2867 '2#085' => 'Photographer Name', 2868 '2#090' => 'PhotoLocation', 2869 '2#092' => 'PhotoLocation2', 2870 '2#095' => 'PhotoState', 2871 '2#100' => 'PhotoCountryCode', 2872 '2#101' => 'PhotoCountry', 2873 '2#105' => 'Title', 2874 '2#110' => 'Credits', 2875 '2#115' => 'Source', 2876 '2#116' => 'Creator', 2877 '2#118' => 'Contact', 2878 '2#120' => 'Description', 2879 '2#131' => 'Orientation', 2880 '2#150' => 'AudioType', 2881 '2#151' => 'AudioSamplingRate', 2882 '2#152' => 'AudioSamplingResolution', 2883 '2#153' => 'AudioDuration' 2884 ); 2885 2886 static $ExifFields = array( 2887 'IFD0' => array( 2888 'Make' => array('type' => 'text', 'name' => 'CameraMaker'), 2889 'Model' => array('type' => 'text', 'name' => 'CameraModel'), 2890 'Orientation' => array('type' => 'or', 'name' => 'Orientation'), 2891 'XResolution' => array('type' => 'math', 'name' => 'XResolution'), 2892 'YResolution' => array('type' => 'math', 'name' => 'YResolution'), 2893 'Software' => array('type' => 'text', 'name' => 'Software'), 2894 'DateTime' => array('type' => 'date2', 'name' => 'DateCreated'), 2895 'Artist' => array('type' => 'text', 'name' => 'Creator'), 2896 ), 2897 2898 'EXIF' => array( 2899 'ExposureTime' => array('type' => 'math', 'name' => 'ExposureTime'), 2900 'ApertureValue' => array('type' => 'math', 'name' => 'ApertureValue'), 2901 'MaxApertureValue' => array('type' => 'math', 'name' => 'MaxApertureValue'), 2902 'ISOSpeedRatings' => array('type' => 'text', 'name' => 'ISOSpeedRatings'), 2903 'DateTimeOriginal' => array('type' => 'date2', 'name' => 'DateCreated'), 2904 'MeteringMode' => array('type' => 'text', 'name' => 'MeteringMode'), 2905 'FNumber' => array('type' => 'math', 'name' => 'FNumber'), 2906 'ExposureProgram' => array('type' => 'text', 'name' => 'ExposureProgram'), 2907 'FocalLength' => array('type' => 'math', 'name' => 'FocalLength'), 2908 'WhiteBalance' => array('type' => 'text', 'name' => 'WhiteBalance'), 2909 'DigitalZoomRatio' => array('type' => 'math', 'name' => 'DigitalZoomRatio'), 2910 'FocalLengthIn35mmFilm' => array('type' => 'text', 'name' => 'FocalLengthIn35mmFilm'), 2911 'Flash' => array('type' => 'text', 'name' => 'Flash'), 2912 'Fired' => array('type' => 'text', 'name' => 'FlashFired'), 2913 'RedEyeMode' => array('type' => 'text', 'name' => 'RedEyeMode'), 2914 ) 2915 ); 2916 2917 static $xmpPatterns = array( 2918 'tiff:Orientation' => array('type' => 'or', 'name' => 'Orientation'), 2919 'tiff:XResolution' => array('type' => 'math', 'name' => 'XResolution'), 2920 'tiff:YResolution' => array('type' => 'math', 'name' => 'YResolution'), 2921 'tiff:Make' => array('type' => 'text', 'name' => 'CameraMaker'), 2922 'tiff:Model' => array('type' => 'text', 'name' => 'CameraModel'), 2923 'xap:ModifyDate' => array('type' => 'date', 'name' => 'DateModified'), 2924 'xap:CreatorTool' => array('type' => 'text', 'name' => 'Software'), 2925 'xap:CreateDate' => array('type' => 'date', 'name' => 'DateCreated'), 2926 'xap:MetadataDate' => array('type' => 'date', 'name' => 'DateMetadata'), 2927 2928 'exif:ExposureTime' => array('type' => 'math', 'name' => 'ExposureTime'), 2929 'exif:ApertureValue' => array('type' => 'math', 'name' => 'ApertureValue'), 2930 'exif:MaxApertureValue' => array('type' => 'math', 'name' => 'MaxApertureValue'), 2931 'exif:ISOSpeedRatings' => array('type' => 'text', 'name' => 'ISOSpeedRatings'), 2932 'exif:DateTimeOriginal' => array('type' => 'date', 'name' => 'DateCreated'), 2933 'exif:MeteringMode' => array('type' => 'text', 'name' => 'MeteringMode'), 2934 'exif:FNumber' => array('type' => 'math', 'name' => 'FNumber'), 2935 'exif:ExposureProgram' => array('type' => 'text', 'name' => 'ExposureProgram'), 2936 'exif:FocalLength' => array('type' => 'math', 'name' => 'FocalLength'), 2937 'exif:WhiteBalance' => array('type' => 'text', 'name' => 'WhiteBalance'), 2938 'exif:DigitalZoomRatio' => array('type' => 'math', 'name' => 'DigitalZoomRatio'), 2939 'exif:FocalLengthIn35mmFilm' => array('type' => 'text', 'name' => 'FocalLengthIn35mmFilm'), 2940 'exif:Fired' => array('type' => 'text', 'name' => 'FlashFired'), 2941 'exif:RedEyeMode' => array('type' => 'text', 'name' => 'RedEyeMode'), 2942 2943 'dc:title' => array('type' => 'rdf', 'name' => 'Title'), 2944 'dc:creator' => array('type' => 'rdf', 'name' => 'Creator'), 2945 ); 2946 2947 $ret = array(); 2948 2949 if (!$serendipity['mediaExif']) { 2950 return $ret; 2951 } 2952 2953 if (!file_exists($file)) { 2954 return $ret; 2955 } 2956 2957 if (function_exists('iptcparse') && is_array($info) && isset($info['APP13'])) { 2958 $iptc = iptcparse($info['APP13']); 2959 foreach($IPTC_Fields AS $field => $desc) { 2960 if ($iptc[$field]) { 2961 if (is_array($iptc[$field])) { 2962 $ret['IPTC'][$desc] = trim(implode(';', $iptc[$field])); 2963 } else { 2964 $ret['IPTC'][$desc] = trim($iptc[$field]); 2965 } 2966 } 2967 } 2968 } 2969 2970 if (function_exists('exif_read_data') && is_array($info)) { 2971 $exif = @exif_read_data($file, 'FILE,COMPUTED,ANY_TAG,IFD0,COMMENT,EXIF', true, false); 2972 if (is_array($exif)) { 2973 foreach($ExifFields AS $Exifgroup => $ExifField) { 2974 foreach($ExifField AS $ExifName => $ExifItem) { 2975 if (!isset($exif[$Exifgroup][$ExifName])) { 2976 continue; 2977 } 2978 $ret['EXIF'][$ExifItem['name']] = serendipity_metaFieldConvert($exif[$Exifgroup][$ExifName], $ExifItem['type']); 2979 if ($ret['EXIF'][$item['name']] == $ret['IPTC'][$item['name']]) { 2980 unset($ret['IPTC'][$item['name']]); 2981 } 2982 } 2983 } 2984 } 2985 } 2986 2987 $xmp = serendipity_getMediaRaw($file); 2988 foreach($xmp AS $xmp_data) { 2989 if (empty($xmp_data['content'])) { 2990 continue; 2991 } 2992 foreach($xmpPatterns AS $lookup => $item) { 2993 if (preg_match('@<' . $lookup . '>(.*)</' . $lookup . '>@', $xmp_data['content'], $match)) { 2994 $ret['XMP'][$item['name']] = serendipity_metaFieldConvert($match[1], $item['type']); 2995 if ($ret['EXIF'][$item['name']] == $ret['XMP'][$item['name']]) { 2996 unset($ret['EXIF'][$item['name']]); 2997 } 2998 } 2999 } 3000 } 3001 3002 serendipity_plugin_api::hook_event('media_getproperties', $ret, $file); 3003 3004 return $ret; 3005 } 3006 3007 /** 3008 * Parses an existing filename and increases the filecount. 3009 * 3010 * @param string The (duplicate) filename 3011 * @param string The full path to the (duplicate) filename 3012 * @param string The directory of the (duplicate) filename 3013 * @param boolean Show new filename? 3014 * @return string The new filename 3015 * 3016 */ 3017 function serendipity_imageAppend(&$tfile, &$target, $dir, $echo = true) { 3018 static $safe_bail = 20; 3019 3020 $realname = $tfile; 3021 list($filebase, $extension) = serendipity_parseFileName($tfile); 3022 3023 $cnum = 1; 3024 if (preg_match('@^(.*)([0-9]+)$@', $filebase, $match)) { 3025 $cnum = $match[2]; 3026 $filebase = $match[1]; 3027 } 3028 3029 $i = 0; 3030 while ($i <= $safe_bail && file_exists($dir . $filebase . $cnum . '.' . $extension)) { 3031 $cnum++; 3032 } 3033 3034 // Check if the file STILL exists and append a MD5 if that's the case. That should be unique enough. 3035 if (file_exists($dir . $filebase . $cnum . '.' . $extension)) { 3036 $cnum = md5(time() . $filebase); 3037 } 3038 3039 // Those variables are passed by reference! 3040 $tfile = $filebase . $cnum . '.' . $extension; 3041 $target = $dir . $tfile; 3042 3043 if ($echo) { 3044 printf(FILENAME_REASSIGNED . '<br />', htmlspecialchars($tfile)); 3045 } 3046 return $realname; 3047 } 3048 3049 /** 3050 * Checks if an uploaded media item hits any configured limits. 3051 * 3052 * @param string The filename 3053 * @return boolean TRUE when file is okay, FALSE when it is beyond limits 3054 * 3055 */ 3056 function serendipity_checkMediaSize($file) { 3057 global $serendipity; 3058 3059 if (!empty($serendipity['maxFileSize'])) { 3060 if (filesize($file) > $serendipity['maxFileSize']) { 3061 printf(MEDIA_UPLOAD_SIZEERROR . '<br />', (int)$serendipity['maxFileSize']); 3062 return false; 3063 } 3064 } 3065 3066 if (!empty($serendipity['maxImgWidth']) || !empty($serendipity['maxImgHeight'])) { 3067 $dim = serendipity_getimagesize($file); 3068 if (!is_array($dim) || !isset($dim[0])) { 3069 return true; 3070 } 3071 3072 if (!empty($serendipity['maxImgWidth'])) { 3073 if ($dim[0] > $serendipity['maxImgWidth']) { 3074 printf(MEDIA_UPLOAD_DIMERROR . '<br />', (int)$serendipity['maxImgWidth'], (int)$serendipity['maxImgHeight']); 3075 return false; 3076 } 3077 } 3078 3079 if (!empty($serendipity['maxImgHeight'])) { 3080 if ($dim[1] > $serendipity['maxImgHeight']) { 3081 printf(MEDIA_UPLOAD_DIMERROR . '<br />', (int)$serendipity['maxImgWidth'], (int)$serendipity['maxImgHeight']); 3082 return false; 3083 } 3084 } 3085 } 3086 3087 return true; 3088 } 3089 3090 /** 3091 * Moves a media directory 3092 * 3093 * @param string The old directory 3094 * @param string The new directory 3095 * @param string The type of what to remove (dir|file|filedir) 3096 * @param string An item id of a file 3097 * @return boolean 3098 * 3099 */ 3100 function serendipity_moveMediaDirectory($oldDir, $newDir, $type = 'dir', $item_id = null, $file = null) { 3101 global $serendipity; 3102 3103 $real_oldDir = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $oldDir; 3104 $real_newDir = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $newDir; 3105 3106 if ($type == 'dir') { 3107 if (!is_dir($real_oldDir)) { 3108 printf(ERROR_FILE_NOT_EXISTS . '<br />', $oldDir); 3109 return false; 3110 } 3111 3112 if (is_dir($real_newDir)) { 3113 printf(ERROR_FILE_EXISTS . '<br />', $newDir); 3114 return false; 3115 } 3116 3117 if (!rename($real_oldDir, $real_newDir)) { 3118 printf(MEDIA_DIRECTORY_MOVE_ERROR . '<br />', $newDir); 3119 return false; 3120 } 3121 3122 printf(MEDIA_DIRECTORY_MOVED . '<br />', $newDir); 3123 3124 $dirs = serendipity_db_query("SELECT id, path 3125 FROM {$serendipity['dbPrefix']}images 3126 WHERE path LIKE '" . serendipity_db_escape_string($oldDir) . "%'", false, 'assoc'); 3127 if (is_array($dirs)) { 3128 foreach($dirs AS $dir) { 3129 $old = $dir['path']; 3130 $new = preg_replace('@^(' . preg_quote($oldDir) . ')@i', $newDir, $old); 3131 serendipity_db_query("UPDATE {$serendipity['dbPrefix']}images 3132 SET path = '" . serendipity_db_escape_string($new) . "' 3133 WHERE id = {$dir['id']}"); 3134 } 3135 } 3136 3137 $dirs = serendipity_db_query("SELECT groupid, artifact_id, artifact_type, artifact_mode, artifact_index 3138 FROM {$serendipity['dbPrefix']}access 3139 WHERE artifact_type = 'directory' 3140 AND artifact_index LIKE '" . serendipity_db_escape_string($oldDir) . "%'", false, 'assoc'); 3141 if (is_array($dirs)) { 3142 foreach($dirs AS $dir) { 3143 $old = $dir['artifact_index']; 3144 $new = preg_replace('@^(' . preg_quote($oldDir) . ')@i', $newDir, $old); 3145 serendipity_db_query("UPDATE {$serendipity['dbPrefix']}access 3146 SET artifact_index = '" . serendipity_db_escape_string($new) . "' 3147 WHERE groupid = '" . serendipity_db_escape_string($dir['groupid']) . "' 3148 AND artifact_id = '" . serendipity_db_escape_string($dir['artifact_id']) . "' 3149 AND artifact_type = '" . serendipity_db_escape_string($dir['artifact_type']) . "' 3150 AND artifact_mode = '" . serendipity_db_escape_string($dir['artifact_mode']) . "' 3151 AND artifact_index = '" . serendipity_db_escape_string($dir['artifact_index']) . "'"); 3152 } 3153 } 3154 } 3155 3156 if ($type == 'file') { 3157 if (serendipity_isActiveFile(basename($newDir))) { 3158 printf(ERROR_FILE_FORBIDDEN, htmlspecialchars($newDir)); 3159 return false; 3160 } 3161 3162 if ($file['hotlink']) { 3163 serendipity_updateImageInDatabase(array('realname' => $newDir, 'name' => $newDir), $item_id); 3164 } else { 3165 $file_new = $file['path'] . $newDir . '.'; 3166 $file_old = $file['path'] . $file['name'] . '.'; 3167 3168 $newfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file_new . $file['extension']; 3169 $oldfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file_old . $file['extension']; 3170 if ($newDir != '' && file_exists($oldfile) && !file_exists($newfile)) { 3171 $renameValues = array(array( 3172 'from' => $oldfile, 3173 'to' => $newfile, 3174 'thumb' => $serendipity['thumbSuffix'], 3175 'fthumb' => $file['thumbnail_name'], 3176 'oldDir' => $oldDir, 3177 'newDir' => $newDir, 3178 'type' => $type, 3179 'item_id'=> $item_id, 3180 'file' => $file 3181 )); 3182 3183 serendipity_plugin_api::hook_event('backend_media_rename', $renameValues); 3184 3185 // Rename file 3186 rename($renameValues[0]['from'], $renameValues[0]['to']); 3187 3188 foreach($renameValues as $renameData) { 3189 // Rename thumbnail 3190 rename($serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] . (!empty($renameData['fthumb']) ? '.' . $renameData['fthumb'] : '') . '.' . $file['extension'], 3191 $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $newDir . '.' . $renameData['thumb'] . '.' . $file['extension']); 3192 } 3193 3194 serendipity_updateImageInDatabase(array('thumbnail_name' => $renameValues[0]['thumb'], 'realname' => $newDir, 'name' => $newDir), $item_id); 3195 $oldDir = $file_old; 3196 $newDir = $file_new; 3197 $real_oldDir = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $oldDir; 3198 $real_newDir = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $newDir; 3199 // Forward user to overview (we don't want the user's back button to rename things again) 3200 } else { 3201 if (!file_exists($oldfile)) { 3202 echo ERROR_FILE_NOT_EXISTS; 3203 } elseif (file_exists($newfile)) { 3204 echo ERROR_FILE_EXISTS; 3205 } else { 3206 echo ERROR_SOMETHING; 3207 } 3208 3209 return false; 3210 } 3211 } 3212 } elseif ($type == 'filedir') { 3213 serendipity_db_query("UPDATE {$serendipity['dbPrefix']}images 3214 SET path = '" . serendipity_db_escape_string($newDir) . "' 3215 WHERE id = " . (int)$item_id); 3216 $pick = serendipity_db_query("SELECT * FROM {$serendipity['dbPrefix']}images 3217 WHERE id = " . (int)$item_id, true, 'assoc'); 3218 3219 // Move thumbs 3220 $oldfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $oldDir . $pick['name'] . '.' . $pick['extension']; 3221 $newfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $newDir . $pick['name'] . '.' . $pick['extension']; 3222 3223 $renameValues = array(array( 3224 'from' => $oldfile, 3225 'to' => $newfile, 3226 'thumb' => $serendipity['thumbSuffix'], 3227 'fthumb' => $pick['thumbnail_name'], 3228 'oldDir' => $oldDir, 3229 'newDir' => $newDir, 3230 'type' => $type, 3231 'item_id'=> $item_id, 3232 'file' => $file 3233 )); 3234 3235 serendipity_plugin_api::hook_event('backend_media_rename', $renameValues); 3236 3237 // Rename file 3238 rename($renameValues[0]['from'], $renameValues[0]['to']); 3239 3240 foreach($renameValues as $renameData) { 3241 // Rename thumbnail 3242 rename($serendipity['serendipityPath'] . $serendipity['uploadPath'] . $oldDir . $pick['name'] . (!empty($renameData['fthumb']) ? '.' . $renameData['fthumb'] : '') . '.' . $pick['extension'], 3243 $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $newDir . $pick['name'] . '.' . $renameData['thumb'] . '.' . $pick['extension']); 3244 } 3245 3246 $oldDir .= $pick['name']; 3247 $newDir .= $pick['name']; 3248 } elseif ($type == 'dir') { 3249 $renameValues = array(array( 3250 'from' => $oldfile, 3251 'to' => $newfile, 3252 'thumb' => $serendipity['thumbSuffix'], 3253 'fthumb' => $file['thumbnail_name'], 3254 'oldDir' => $oldDir, 3255 'newDir' => $newDir, 3256 'type' => $type, 3257 'item_id'=> $item_id, 3258 'file' => $file 3259 )); 3260 3261 serendipity_plugin_api::hook_event('backend_media_rename', $renameValues); 3262 } 3263 3264 // Only MySQL supported, since I don't know how to use REGEXPs differently. 3265 if ($serendipity['dbType'] != 'mysql' && $serendipity['dbType'] != 'mysqli') { 3266 echo MEDIA_DIRECTORY_MOVE_ENTRY . '<br />'; 3267 return true; 3268 } 3269 3270 $q = "SELECT id, body, extended 3271 FROM {$serendipity['dbPrefix']}entries 3272 WHERE body REGEXP '(src=|href=|window.open.)(\'|\")(" . serendipity_db_escape_String($serendipity['baseURL'] . $serendipity['uploadHTTPPath'] . $oldDir) . "|" . serendipity_db_escape_string($serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $oldDir) . ")' 3273 OR extended REGEXP '(src=|href=|window.open.)(\'|\")(" . serendipity_db_escape_String($serendipity['baseURL'] . $serendipity['uploadHTTPPath'] . $oldDir) . "|" . serendipity_db_escape_string($serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $oldDir) . ")' 3274 "; 3275 3276 $dirs = serendipity_db_query($q); 3277 if (is_array($dirs)) { 3278 foreach($dirs AS $dir) { 3279 $dir['body'] = preg_replace('@(src=|href=|window.open.)(\'|")(' . preg_quote($serendipity['baseURL'] . $serendipity['uploadHTTPPath'] . $oldDir) . '|' . preg_quote($serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $oldDir) . ')@', '\1\2' . $serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $newDir, $dir['body']); 3280 $dir['extended'] = preg_replace('@(src=|href=|window.open.)(\'|")(' . preg_quote($serendipity['baseURL'] . $serendipity['uploadHTTPPath'] . $oldDir) . '|' . preg_quote($serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $oldDir) . ')@', '\1\2' . $serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $newDir, $dir['extended']); 3281 3282 $uq = "UPDATE {$serendipity['dbPrefix']}entries 3283 SET body = '" . serendipity_db_escape_string($dir['body']) . "' , 3284 extended = '" . serendipity_db_escape_string($dir['extended']) . "' 3285 WHERE id = " . serendipity_db_escape_string($dir['id']); 3286 serendipity_db_query($uq); 3287 } 3288 3289 printf(MEDIA_DIRECTORY_MOVE_ENTRIES . '<br />', count($dirs)); 3290 } 3291 3292 return true; 3293 } 3294 3295 /** 3296 * Gets all available media directories 3297 * 3298 * @return array 3299 * 3300 */ 3301 function &serendipity_getMediaPaths() { 3302 global $serendipity; 3303 3304 $aExclude = array("CVS" => true, ".svn" => true); 3305 serendipity_plugin_api::hook_event('backend_media_path_exclude_directories', $aExclude); 3306 $paths = array(); 3307 3308 $aResultSet = serendipity_traversePath( 3309 $serendipity['serendipityPath'] . $serendipity['uploadPath'], 3310 '', 3311 false, 3312 NULL, 3313 1, 3314 NULL, 3315 FALSE, 3316 $aExclude 3317 ); 3318 3319 foreach ($aResultSet AS $sKey => $sFile) { 3320 if ($sFile['directory']) { 3321 array_push($paths, $sFile); 3322 } 3323 unset($aResultSet[$sKey]); 3324 } 3325 serendipity_directoryACL($paths, 'read'); 3326 3327 usort($paths, 'serendipity_sortPath'); 3328 3329 return $paths; 3330 } 3331 3332 /** 3333 * Checks whether a user has access to write into a directory 3334 * 3335 * @access public 3336 * @param string Directory to check 3337 * @return boolean 3338 */ 3339 function serendipity_checkDirUpload($dir) { 3340 global $serendipity; 3341 3342 /* 3343 if (serendipity_checkPermission('adminImagesMaintainOthers')) { 3344 return true; 3345 } 3346 */ 3347 3348 $allowed = serendipity_ACLGet(0, 'directory', 'write', $dir); 3349 $mygroups = serendipity_checkPermission(null, null, true); 3350 3351 // Usergroup "0" always means that access is granted. If no array exists, no ACL restrictions have been set and all is fine. 3352 if (!is_array($allowed) || isset($allowed[0])) { 3353 return true; 3354 } 3355 3356 if (!is_array($mygroups)) { 3357 return true; 3358 } 3359 3360 foreach($mygroups AS $grpid => $grp) { 3361 if (isset($allowed[$grpid])) { 3362 return true; 3363 break; 3364 } 3365 } 3366 3367 return false; 3368 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Sat Nov 24 09:00:37 2007 | par Balluche grâce à PHPXref 0.7 |
|