1<?php 2/** 3 * All output and handler function needed for the media management popup 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Andreas Gohr <andi@splitbrain.org> 7 */ 8 9if(!defined('DOKU_INC')) die('meh.'); 10if(!defined('NL')) define('NL',"\n"); 11 12/** 13 * Lists pages which currently use a media file selected for deletion 14 * 15 * References uses the same visual as search results and share 16 * their CSS tags except pagenames won't be links. 17 * 18 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net> 19 */ 20function media_filesinuse($data,$id){ 21 global $lang; 22 echo '<h1>'.$lang['reference'].' <code>'.hsc(noNS($id)).'</code></h1>'; 23 echo '<p>'.hsc($lang['ref_inuse']).'</p>'; 24 25 $hidden=0; //count of hits without read permission 26 foreach($data as $row){ 27 if(auth_quickaclcheck($row) >= AUTH_READ && isVisiblePage($row)){ 28 echo '<div class="search_result">'; 29 echo '<span class="mediaref_ref">'.hsc($row).'</span>'; 30 echo '</div>'; 31 }else 32 $hidden++; 33 } 34 if ($hidden){ 35 print '<div class="mediaref_hidden">'.$lang['ref_hidden'].'</div>'; 36 } 37} 38 39/** 40 * Handles the saving of image meta data 41 * 42 * @author Andreas Gohr <andi@splitbrain.org> 43 * @author Kate Arzamastseva <pshns@ukr.net> 44 */ 45function media_metasave($id,$auth,$data){ 46 if($auth < AUTH_UPLOAD) return false; 47 if(!checkSecurityToken()) return false; 48 global $lang; 49 global $conf; 50 $src = mediaFN($id); 51 52 $meta = new JpegMeta($src); 53 $meta->_parseAll(); 54 55 foreach($data as $key => $val){ 56 $val=trim($val); 57 if(empty($val)){ 58 $meta->deleteField($key); 59 }else{ 60 $meta->setField($key,$val); 61 } 62 } 63 64 $old = @filemtime($src); 65 if(!@file_exists(mediaFN($id, $old)) && @file_exists($src)) { 66 // add old revision to the attic 67 media_saveOldRevision($id); 68 } 69 70 if($meta->save()){ 71 if($conf['fperm']) chmod($src, $conf['fperm']); 72 73 $new = @filemtime($src); 74 // add a log entry to the media changelog 75 addMediaLogEntry($new, $id, DOKU_CHANGE_TYPE_EDIT, $lang['media_meta_edited']); 76 77 msg($lang['metasaveok'],1); 78 return $id; 79 }else{ 80 msg($lang['metasaveerr'],-1); 81 return false; 82 } 83} 84 85/** 86 * Display the form to edit image meta data 87 * 88 * @author Andreas Gohr <andi@splitbrain.org> 89 * @author Kate Arzamastseva <pshns@ukr.net> 90 */ 91function media_metaform($id,$auth,$fullscreen = false){ 92 global $lang, $config_cascade; 93 94 if($auth < AUTH_UPLOAD) { 95 echo '<div class="nothing">'.$lang['media_perm_upload'].'</div>'.NL; 96 return false; 97 } 98 99 // load the field descriptions 100 static $fields = null; 101 if(is_null($fields)){ 102 $config_files = getConfigFiles('mediameta'); 103 foreach ($config_files as $config_file) { 104 if(@file_exists($config_file)) include($config_file); 105 } 106 } 107 108 $src = mediaFN($id); 109 110 // output 111 if (!$fullscreen) { 112 echo '<h1>'.hsc(noNS($id)).'</h1>'.NL; 113 $action = DOKU_BASE.'lib/exe/mediamanager.php'; 114 } else { 115 $action = media_managerURL(array('tab_details' => 'view'), '&'); 116 } 117 echo '<form action="'.$action.'" id="mediamanager__save_meta" accept-charset="utf-8" method="post" class="meta">'.NL; 118 119 formSecurityToken(); 120 foreach($fields as $key => $field){ 121 // get current value 122 if (empty($field[0])) continue; 123 $tags = array($field[0]); 124 if(is_array($field[3])) $tags = array_merge($tags,$field[3]); 125 $value = tpl_img_getTag($tags,'',$src); 126 $value = cleanText($value); 127 128 // prepare attributes 129 $p = array(); 130 $p['class'] = 'edit'; 131 $p['id'] = 'meta__'.$key; 132 $p['name'] = 'meta['.$field[0].']'; 133 134 // put label 135 echo '<div class="metafield">'; 136 echo '<label for="meta__'.$key.'">'; 137 echo ($lang[$field[1]]) ? $lang[$field[1]] : $field[1]; 138 echo ':</label>'; 139 140 // put input field 141 if($field[2] == 'text'){ 142 $p['value'] = $value; 143 $p['type'] = 'text'; 144 $att = buildAttributes($p); 145 echo "<input $att/>".NL; 146 }else{ 147 $att = buildAttributes($p); 148 echo "<textarea $att rows=\"6\" cols=\"50\">".formText($value).'</textarea>'.NL; 149 } 150 echo '</div>'.NL; 151 } 152 echo '<div class="buttons">'.NL; 153 echo '<input type="hidden" name="img" value="'.hsc($id).'" />'.NL; 154 if (!$fullscreen) { 155 $do = 'do'; 156 } else { 157 echo '<input type="hidden" name="mediado" value="save" />'; 158 $do = 'mediado'; 159 } 160 echo '<input name="'.$do.'[save]" type="submit" value="'.$lang['btn_save']. 161 '" title="'.$lang['btn_save'].' [S]" accesskey="s" class="button" />'.NL; 162 if (!$fullscreen) 163 echo '<input name="do[cancel]" type="submit" value="'.$lang['btn_cancel']. 164 '" title="'.$lang['btn_cancel'].' [C]" accesskey="c" class="button" />'.NL; 165 echo '</div>'.NL; 166 echo '</form>'.NL; 167} 168 169/** 170 * Convenience function to check if a media file is still in use 171 * 172 * @author Michael Klier <chi@chimeric.de> 173 */ 174function media_inuse($id) { 175 global $conf; 176 $mediareferences = array(); 177 if($conf['refcheck']){ 178 $mediareferences = ft_mediause($id,$conf['refshow']); 179 if(!count($mediareferences)) { 180 return false; 181 } else { 182 return $mediareferences; 183 } 184 } else { 185 return false; 186 } 187} 188 189define('DOKU_MEDIA_DELETED', 1); 190define('DOKU_MEDIA_NOT_AUTH', 2); 191define('DOKU_MEDIA_INUSE', 4); 192define('DOKU_MEDIA_EMPTY_NS', 8); 193 194/** 195 * Handles media file deletions 196 * 197 * If configured, checks for media references before deletion 198 * 199 * @author Andreas Gohr <andi@splitbrain.org> 200 * @return int One of: 0, 201 DOKU_MEDIA_DELETED, 202 DOKU_MEDIA_DELETED | DOKU_MEDIA_EMPTY_NS, 203 DOKU_MEDIA_NOT_AUTH, 204 DOKU_MEDIA_INUSE 205 */ 206function media_delete($id,$auth){ 207 global $lang; 208 if($auth < AUTH_DELETE) return DOKU_MEDIA_NOT_AUTH; 209 if(media_inuse($id)) return DOKU_MEDIA_INUSE; 210 211 $file = mediaFN($id); 212 213 // trigger an event - MEDIA_DELETE_FILE 214 $data['id'] = $id; 215 $data['name'] = basename($file); 216 $data['path'] = $file; 217 $data['size'] = (@file_exists($file)) ? filesize($file) : 0; 218 219 $data['unl'] = false; 220 $data['del'] = false; 221 $evt = new Doku_Event('MEDIA_DELETE_FILE',$data); 222 if ($evt->advise_before()) { 223 $old = @filemtime($file); 224 if(!@file_exists(mediaFN($id, $old)) && @file_exists($file)) { 225 // add old revision to the attic 226 media_saveOldRevision($id); 227 } 228 229 $data['unl'] = @unlink($file); 230 if($data['unl']){ 231 addMediaLogEntry(time(), $id, DOKU_CHANGE_TYPE_DELETE, $lang['deleted']); 232 $data['del'] = io_sweepNS($id,'mediadir'); 233 } 234 } 235 $evt->advise_after(); 236 unset($evt); 237 238 if($data['unl'] && $data['del']){ 239 return DOKU_MEDIA_DELETED | DOKU_MEDIA_EMPTY_NS; 240 } 241 242 return $data['unl'] ? DOKU_MEDIA_DELETED : 0; 243} 244 245/** 246 * Handle file uploads via XMLHttpRequest 247 * 248 * @return mixed false on error, id of the new file on success 249 */ 250function media_upload_xhr($ns,$auth){ 251 if(!checkSecurityToken()) return false; 252 253 $id = $_GET['qqfile']; 254 list($ext,$mime,$dl) = mimetype($id); 255 $input = fopen("php://input", "r"); 256 $temp = tmpfile(); 257 $realSize = stream_copy_to_stream($input, $temp); 258 fclose($input); 259 if ($realSize != (int)$_SERVER["CONTENT_LENGTH"]) return false; 260 if (!($tmp = io_mktmpdir())) return false; 261 $path = $tmp.'/'.$id; 262 $target = fopen($path, "w"); 263 fseek($temp, 0, SEEK_SET); 264 stream_copy_to_stream($temp, $target); 265 fclose($target); 266 $res = media_save( 267 array('name' => $path, 268 'mime' => $mime, 269 'ext' => $ext), 270 $ns.':'.$id, 271 (($_REQUEST['ow'] == 'checked') ? true : false), 272 $auth, 273 'copy' 274 ); 275 unlink($path); 276 if ($tmp) dir_delete($tmp); 277 if (is_array($res)) { 278 msg($res[0], $res[1]); 279 return false; 280 } 281 return $res; 282} 283 284/** 285 * Handles media file uploads 286 * 287 * @author Andreas Gohr <andi@splitbrain.org> 288 * @author Michael Klier <chi@chimeric.de> 289 * @return mixed false on error, id of the new file on success 290 */ 291function media_upload($ns,$auth,$file=false){ 292 if(!checkSecurityToken()) return false; 293 global $lang; 294 295 // get file and id 296 $id = $_POST['mediaid']; 297 if (!$file) $file = $_FILES['upload']; 298 if(empty($id)) $id = $file['name']; 299 300 // check for errors (messages are done in lib/exe/mediamanager.php) 301 if($file['error']) return false; 302 303 // check extensions 304 list($fext,$fmime,$dl) = mimetype($file['name']); 305 list($iext,$imime,$dl) = mimetype($id); 306 if($fext && !$iext){ 307 // no extension specified in id - read original one 308 $id .= '.'.$fext; 309 $imime = $fmime; 310 }elseif($fext && $fext != $iext){ 311 // extension was changed, print warning 312 msg(sprintf($lang['mediaextchange'],$fext,$iext)); 313 } 314 315 $res = media_save(array('name' => $file['tmp_name'], 316 'mime' => $imime, 317 'ext' => $iext), $ns.':'.$id, 318 $_REQUEST['ow'], $auth, 'move_uploaded_file'); 319 if (is_array($res)) { 320 msg($res[0], $res[1]); 321 return false; 322 } 323 return $res; 324} 325 326/** 327 * This generates an action event and delegates to _media_upload_action(). 328 * Action plugins are allowed to pre/postprocess the uploaded file. 329 * (The triggered event is preventable.) 330 * 331 * Event data: 332 * $data[0] fn_tmp: the temporary file name (read from $_FILES) 333 * $data[1] fn: the file name of the uploaded file 334 * $data[2] id: the future directory id of the uploaded file 335 * $data[3] imime: the mimetype of the uploaded file 336 * $data[4] overwrite: if an existing file is going to be overwritten 337 * 338 * @triggers MEDIA_UPLOAD_FINISH 339 */ 340function media_save($file, $id, $ow, $auth, $move) { 341 if($auth < AUTH_UPLOAD) { 342 return array("You don't have permissions to upload files.", -1); 343 } 344 345 if (!isset($file['mime']) || !isset($file['ext'])) { 346 list($ext, $mime) = mimetype($id); 347 if (!isset($file['mime'])) { 348 $file['mime'] = $mime; 349 } 350 if (!isset($file['ext'])) { 351 $file['ext'] = $ext; 352 } 353 } 354 355 global $lang, $conf; 356 357 // get filename 358 $id = cleanID($id,false,true); 359 $fn = mediaFN($id); 360 361 // get filetype regexp 362 $types = array_keys(getMimeTypes()); 363 $types = array_map(create_function('$q','return preg_quote($q,"/");'),$types); 364 $regex = join('|',$types); 365 366 // because a temp file was created already 367 if(!preg_match('/\.('.$regex.')$/i',$fn)) { 368 return array($lang['uploadwrong'],-1); 369 } 370 371 //check for overwrite 372 $overwrite = @file_exists($fn); 373 $auth_ow = (($conf['mediarevisions']) ? AUTH_UPLOAD : AUTH_DELETE); 374 if($overwrite && (!$ow || $auth < $auth_ow)) { 375 return array($lang['uploadexist'], 0); 376 } 377 // check for valid content 378 $ok = media_contentcheck($file['name'], $file['mime']); 379 if($ok == -1){ 380 return array(sprintf($lang['uploadbadcontent'],'.' . $file['ext']),-1); 381 }elseif($ok == -2){ 382 return array($lang['uploadspam'],-1); 383 }elseif($ok == -3){ 384 return array($lang['uploadxss'],-1); 385 } 386 387 // prepare event data 388 $data[0] = $file['name']; 389 $data[1] = $fn; 390 $data[2] = $id; 391 $data[3] = $file['mime']; 392 $data[4] = $overwrite; 393 $data[5] = $move; 394 395 // trigger event 396 return trigger_event('MEDIA_UPLOAD_FINISH', $data, '_media_upload_action', true); 397} 398 399/** 400 * Callback adapter for media_upload_finish() 401 * @author Michael Klier <chi@chimeric.de> 402 */ 403function _media_upload_action($data) { 404 // fixme do further sanity tests of given data? 405 if(is_array($data) && count($data)===6) { 406 return media_upload_finish($data[0], $data[1], $data[2], $data[3], $data[4], $data[5]); 407 } else { 408 return false; //callback error 409 } 410} 411 412/** 413 * Saves an uploaded media file 414 * 415 * @author Andreas Gohr <andi@splitbrain.org> 416 * @author Michael Klier <chi@chimeric.de> 417 * @author Kate Arzamastseva <pshns@ukr.net> 418 */ 419function media_upload_finish($fn_tmp, $fn, $id, $imime, $overwrite, $move = 'move_uploaded_file') { 420 global $conf; 421 global $lang; 422 global $REV; 423 424 $old = @filemtime($fn); 425 if(!@file_exists(mediaFN($id, $old)) && @file_exists($fn)) { 426 // add old revision to the attic if missing 427 media_saveOldRevision($id); 428 } 429 430 // prepare directory 431 io_createNamespace($id, 'media'); 432 433 if($move($fn_tmp, $fn)) { 434 @clearstatcache(true,$fn); 435 $new = @filemtime($fn); 436 // Set the correct permission here. 437 // Always chmod media because they may be saved with different permissions than expected from the php umask. 438 // (Should normally chmod to $conf['fperm'] only if $conf['fperm'] is set.) 439 chmod($fn, $conf['fmode']); 440 msg($lang['uploadsucc'],1); 441 media_notify($id,$fn,$imime,$old); 442 // add a log entry to the media changelog 443 if ($REV){ 444 addMediaLogEntry($new, $id, DOKU_CHANGE_TYPE_REVERT, $lang['restored'], $REV); 445 } elseif ($overwrite) { 446 addMediaLogEntry($new, $id, DOKU_CHANGE_TYPE_EDIT); 447 } else { 448 addMediaLogEntry($new, $id, DOKU_CHANGE_TYPE_CREATE, $lang['created']); 449 } 450 return $id; 451 }else{ 452 return array($lang['uploadfail'],-1); 453 } 454} 455 456/** 457 * Moves the current version of media file to the media_attic 458 * directory 459 * 460 * @author Kate Arzamastseva <pshns@ukr.net> 461 * @param string $id 462 * @return int - revision date 463 */ 464function media_saveOldRevision($id){ 465 global $conf, $lang; 466 467 $oldf = mediaFN($id); 468 if(!@file_exists($oldf)) return ''; 469 $date = filemtime($oldf); 470 if (!$conf['mediarevisions']) return $date; 471 472 if (!getRevisionInfo($id, $date, 8192, true)) { 473 // there was an external edit, 474 // there is no log entry for current version of file 475 if (!@file_exists(mediaMetaFN($id,'.changes'))) { 476 addMediaLogEntry($date, $id, DOKU_CHANGE_TYPE_CREATE, $lang['created']); 477 } else { 478 addMediaLogEntry($date, $id, DOKU_CHANGE_TYPE_EDIT); 479 } 480 } 481 482 $newf = mediaFN($id,$date); 483 io_makeFileDir($newf); 484 if(copy($oldf, $newf)) { 485 // Set the correct permission here. 486 // Always chmod media because they may be saved with different permissions than expected from the php umask. 487 // (Should normally chmod to $conf['fperm'] only if $conf['fperm'] is set.) 488 chmod($newf, $conf['fmode']); 489 } 490 return $date; 491} 492 493/** 494 * This function checks if the uploaded content is really what the 495 * mimetype says it is. We also do spam checking for text types here. 496 * 497 * We need to do this stuff because we can not rely on the browser 498 * to do this check correctly. Yes, IE is broken as usual. 499 * 500 * @author Andreas Gohr <andi@splitbrain.org> 501 * @link http://www.splitbrain.org/blog/2007-02/12-internet_explorer_facilitates_cross_site_scripting 502 * @fixme check all 26 magic IE filetypes here? 503 */ 504function media_contentcheck($file,$mime){ 505 global $conf; 506 if($conf['iexssprotect']){ 507 $fh = @fopen($file, 'rb'); 508 if($fh){ 509 $bytes = fread($fh, 256); 510 fclose($fh); 511 if(preg_match('/<(script|a|img|html|body|iframe)[\s>]/i',$bytes)){ 512 return -3; 513 } 514 } 515 } 516 if(substr($mime,0,6) == 'image/'){ 517 $info = @getimagesize($file); 518 if($mime == 'image/gif' && $info[2] != 1){ 519 return -1; 520 }elseif($mime == 'image/jpeg' && $info[2] != 2){ 521 return -1; 522 }elseif($mime == 'image/png' && $info[2] != 3){ 523 return -1; 524 } 525 # fixme maybe check other images types as well 526 }elseif(substr($mime,0,5) == 'text/'){ 527 global $TEXT; 528 $TEXT = io_readFile($file); 529 if(checkwordblock()){ 530 return -2; 531 } 532 } 533 return 0; 534} 535 536/** 537 * Send a notify mail on uploads 538 * 539 * @author Andreas Gohr <andi@splitbrain.org> 540 */ 541function media_notify($id,$file,$mime,$old_rev=false){ 542 global $lang; 543 global $conf; 544 global $INFO; 545 if(empty($conf['notify'])) return; //notify enabled? 546 547 $ip = clientIP(); 548 549 $text = rawLocale('uploadmail'); 550 $text = str_replace('@DATE@',dformat(),$text); 551 $text = str_replace('@BROWSER@',$_SERVER['HTTP_USER_AGENT'],$text); 552 $text = str_replace('@IPADDRESS@',$ip,$text); 553 $text = str_replace('@HOSTNAME@',gethostsbyaddrs($ip),$text); 554 $text = str_replace('@DOKUWIKIURL@',DOKU_URL,$text); 555 $text = str_replace('@USER@',$_SERVER['REMOTE_USER'],$text); 556 $text = str_replace('@MIME@',$mime,$text); 557 $text = str_replace('@MEDIA@',ml($id,'',true,'&',true),$text); 558 $text = str_replace('@SIZE@',filesize_h(filesize($file)),$text); 559 if ($old_rev && $conf['mediarevisions']) { 560 $text = str_replace('@OLD@', ml($id, "rev=$old_rev", true, '&', true), $text); 561 } else { 562 $text = str_replace('@OLD@', '', $text); 563 } 564 565 if(empty($conf['mailprefix'])) { 566 $subject = '['.$conf['title'].'] '.$lang['mail_upload'].' '.$id; 567 } else { 568 $subject = '['.$conf['mailprefix'].'] '.$lang['mail_upload'].' '.$id; 569 } 570 571 mail_send($conf['notify'],$subject,$text,$conf['mailfrom']); 572} 573 574/** 575 * List all files in a given Media namespace 576 */ 577function media_filelist($ns,$auth=null,$jump='',$fullscreenview=false,$sort=false){ 578 global $conf; 579 global $lang; 580 $ns = cleanID($ns); 581 582 // check auth our self if not given (needed for ajax calls) 583 if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 584 585 if (!$fullscreenview) echo '<h1 id="media__ns">:'.hsc($ns).'</h1>'.NL; 586 587 if($auth < AUTH_READ){ 588 // FIXME: print permission warning here instead? 589 echo '<div class="nothing">'.$lang['nothingfound'].'</div>'.NL; 590 }else{ 591 if (!$fullscreenview) media_uploadform($ns, $auth); 592 593 $dir = utf8_encodeFN(str_replace(':','/',$ns)); 594 $data = array(); 595 search($data,$conf['mediadir'],'search_media', 596 array('showmsg'=>true,'depth'=>1),$dir,1,$sort); 597 598 if(!count($data)){ 599 echo '<div class="nothing">'.$lang['nothingfound'].'</div>'.NL; 600 }else { 601 if ($fullscreenview) { 602 $view = $_REQUEST['view']; 603 if ($view == 'list') { 604 echo '<ul class="mediamanager-list" id="mediamanager__file_list">'; 605 } else { 606 echo '<ul class="mediamanager-thumbs" id="mediamanager__file_list">'; 607 } 608 } 609 foreach($data as $item){ 610 if (!$fullscreenview) { 611 media_printfile($item,$auth,$jump); 612 } else { 613 media_printfile_thumbs($item,$auth,$jump); 614 } 615 } 616 if ($fullscreenview) echo '</ul>'; 617 } 618 } 619 if (!$fullscreenview) media_searchform($ns); 620} 621 622/** 623 * Prints mediamanager tab 624 * 625 * @author Kate Arzamastseva <pshns@ukr.net> 626 * @param string $link 627 * @param string $class 628 * @param string $name 629 * @param string $selected 630 */ 631function media_tab($link, $class, $name, $selected=false) { 632 if (!empty($selected) && $selected == $class) $class .= ' selected'; 633 $tab = '<a href="'.$link.'" class="'.$class.'" >'.$name.'</a>'; 634 echo $tab; 635} 636 637/** 638 * Prints tabs for files list actions 639 * 640 * @author Kate Arzamastseva <pshns@ukr.net> 641 * @param string $selected - opened tab 642 */ 643function media_tabs_files($selected=false){ 644 global $lang; 645 646 echo '<div class="mediamanager-tabs" id="mediamanager__tabs_files">'; 647 648 media_tab(media_managerURL(array('tab_files' => 'files')), 'files', $lang['mediaselect'], $selected); 649 media_tab(media_managerURL(array('tab_files' => 'upload')), 'upload', $lang['media_uploadtab'], $selected); 650 media_tab(media_managerURL(array('tab_files' => 'search')), 'search', $lang['media_searchtab'], $selected); 651 652 echo '<div class="clearer"></div>'; 653 echo '</div>'; 654} 655 656/** 657 * Prints tabs for files details actions 658 * 659 * @author Kate Arzamastseva <pshns@ukr.net> 660 * @param string $selected - opened tab 661 */ 662function media_tabs_details($image, $selected=false){ 663 global $lang, $conf; 664 665 echo '<div class="mediamanager-tabs" id="mediamanager__tabs_details">'; 666 667 media_tab(media_managerURL(array('tab_details' => 'view')), 'view', $lang['media_viewtab'], $selected); 668 669 list($ext, $mime) = mimetype($image); 670 if ($mime == 'image/jpeg' && @file_exists(mediaFN($image))) { 671 media_tab(media_managerURL(array('tab_details' => 'edit')), 'edit', $lang['media_edittab'], $selected); 672 } 673 if ($conf['mediarevisions']) { 674 media_tab(media_managerURL(array('tab_details' => 'history')), 'history', $lang['media_historytab'], $selected); 675 } 676 677 echo '<div class="clearer"></div>'; 678 echo '</div>'; 679} 680 681/** 682 * Prints options for the tab that displays a list of all files 683 * 684 * @author Kate Arzamastseva <pshns@ukr.net> 685 */ 686function media_tab_files_options($ns, $sort){ 687 global $lang; 688 689 echo '<div class="background-container">'; 690 echo $ns ? $ns : '['.$lang['mediaroot'].']'; 691 692 echo '<div id="mediamanager__tabs_list">'; 693 694 echo '<a href="'.media_managerURL(array('view' => 'thumbs')).'" id="mediamanager__link_thumbs" >'; 695 echo $lang['media_thumbsview']; 696 echo '</a>'; 697 698 echo '<a href="'.media_managerURL(array('view' => 'list')).'" id="mediamanager__link_list" >'; 699 echo $lang['media_listview']; 700 echo '</a>'; 701 702 echo '</div>'; 703 704 echo '<div id="mediamanager__sort">'; 705 $form = new Doku_Form(array('action'=>media_managerURL(array(), '&'), 'id' => 'mediamanager__form_sort')); 706 $form->addElement(form_makeListboxField( 707 'sort', 708 array( 709 'name' => $lang['media_sort_name'], 710 'date' => $lang['media_sort_date']), 711 $sort, 712 $lang['media_sort'])); 713 $form->addElement(form_makeButton('submit', '', $lang['btn_apply'])); 714 $form->printForm(); 715 echo '</div>'; 716 717 echo '<div class="clearer"></div>'; 718 echo '</div>'; 719} 720 721/** 722 * Prints tab that displays a list of all files 723 * 724 * @author Kate Arzamastseva <pshns@ukr.net> 725 */ 726function media_tab_files($ns,$auth=null,$jump='') { 727 global $lang; 728 if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 729 730 $sort = $_REQUEST['sort']; 731 if (!$sort && @strpos($_COOKIE['DOKU_PREFS'], 'sort')) { 732 $parts = explode('#', $_COOKIE['DOKU_PREFS']); 733 for ($i = 0; $i < count($parts); $i+=2){ 734 if ($parts[$i] == 'sort') $sort = $parts[$i+1]; 735 } 736 } 737 media_tab_files_options($ns, $sort); 738 739 echo '<div class="scroll-container" >'; 740 if($auth < AUTH_READ){ 741 echo '<div class="nothing">'.$lang['media_perm_read'].'</div>'.NL; 742 }else{ 743 media_filelist($ns,$auth,$jump,true,$sort); 744 } 745 echo '</div>'; 746} 747 748/** 749 * Prints tab that displays uploading form 750 * 751 * @author Kate Arzamastseva <pshns@ukr.net> 752 */ 753function media_tab_upload($ns,$auth=null,$jump='') { 754 global $lang; 755 if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 756 757 echo '<div class="background-container">'; 758 echo sprintf($lang['media_upload'], $ns ? $ns : '['.$lang['mediaroot'].']'); 759 echo '</div>'; 760 761 echo '<div class="scroll-container">'; 762 if ($auth >= AUTH_UPLOAD) echo '<div class="upload">' . $lang['mediaupload'] . '</div>'; 763 media_uploadform($ns, $auth, true); 764 echo '</div>'; 765} 766 767/** 768 * Prints tab that displays search form 769 * 770 * @author Kate Arzamastseva <pshns@ukr.net> 771 */ 772function media_tab_search($ns,$auth=null) { 773 global $lang; 774 775 $do = $_REQUEST['mediado']; 776 $query = $_REQUEST['q']; 777 if (!$query) $query = ''; 778 779 echo '<div class="background-container">'; 780 echo sprintf($lang['media_search'], $ns ? $ns : '['.$lang['mediaroot'].']'); 781 echo'</div>'; 782 783 echo '<div class="scroll-container">'; 784 media_searchform($ns, $query, true); 785 if ($do == 'searchlist') media_searchlist($query,$ns,$auth,true); 786 echo '</div>'; 787} 788 789/** 790 * Prints tab that displays mediafile details 791 * 792 * @author Kate Arzamastseva <pshns@ukr.net> 793 */ 794function media_tab_view($image, $ns, $auth=null, $rev=false) { 795 global $lang, $conf; 796 if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 797 798 echo '<div class="background-container">'; 799 list($ext,$mime,$dl) = mimetype($image,false); 800 $class = preg_replace('/[^_\-a-z0-9]+/i','_',$ext); 801 $class = 'select mediafile mf_'.$class; 802 echo '<a class="'.$class.'" >'.$image.'</a>'; 803 echo '</div>'; 804 805 echo '<div class="scroll-container">'; 806 if ($image && $auth >= AUTH_READ) { 807 $meta = new JpegMeta(mediaFN($image, $rev)); 808 media_preview($image, $auth, $rev, $meta); 809 media_preview_buttons($image, $auth, $rev); 810 media_details($image, $auth, $rev, $meta); 811 812 } else { 813 echo '<div class="nothing">'.$lang['media_perm_read'].'</div>'; 814 } 815 echo '</div>'; 816} 817 818/** 819 * Prints tab that displays form for editing mediafile metadata 820 * 821 * @author Kate Arzamastseva <pshns@ukr.net> 822 */ 823function media_tab_edit($image, $ns, $auth=null) { 824 global $lang; 825 if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 826 827 echo '<div class="background-container">'; 828 echo $lang['media_edit']; 829 echo '</div>'; 830 831 echo '<div class="scroll-container">'; 832 if ($image) { 833 list($ext, $mime) = mimetype($image); 834 if ($mime == 'image/jpeg') media_metaform($image,$auth,true); 835 } 836 echo '</div>'; 837} 838 839/** 840 * Prints tab that displays mediafile revisions 841 * 842 * @author Kate Arzamastseva <pshns@ukr.net> 843 */ 844function media_tab_history($image, $ns, $auth=null) { 845 global $lang; 846 if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 847 $do = $_REQUEST['mediado']; 848 849 echo '<div class="background-container">'; 850 echo $lang['media_history']; 851 echo '</div>'; 852 853 echo '<div class="scroll-container">'; 854 if ($auth >= AUTH_READ && $image) { 855 if ($do == 'diff'){ 856 media_diff($image, $ns, $auth); 857 } else { 858 $first = isset($_REQUEST['first']) ? intval($_REQUEST['first']) : 0; 859 html_revisions($first, $image); 860 } 861 } else { 862 echo '<div class="nothing">'.$lang['media_perm_read'].'</div>'.NL; 863 } 864 echo '</div>'; 865} 866 867/** 868 * Prints mediafile details 869 * 870 * @author Kate Arzamastseva <pshns@ukr.net> 871 */ 872function media_preview($image, $auth, $rev=false, $meta=false) { 873 global $lang; 874 875 echo '<div class="mediamanager__preview">'; 876 877 $size = media_image_preview_size($image, $rev, $meta); 878 879 if ($size) { 880 $more = array(); 881 if ($rev) { 882 $more['rev'] = $rev; 883 } else { 884 $t = @filemtime(mediaFN($image)); 885 $more['t'] = $t; 886 } 887 888 $more['w'] = $size[0]; 889 $more['h'] = $size[1]; 890 $src = ml($image, $more); 891 echo '<img src="'.$src.'" alt="'.$image.'" style="max-width: '.$size[0].'px;" />'; 892 } 893 894 echo '</div>'; 895} 896 897/** 898 * Prints mediafile action buttons 899 * 900 * @author Kate Arzamastseva <pshns@ukr.net> 901 */ 902function media_preview_buttons($image, $auth, $rev=false) { 903 global $lang, $conf; 904 905 echo '<div class="mediamanager__preview_buttons">'; 906 907 $more = ''; 908 if ($rev) { 909 $more = "rev=$rev"; 910 } else { 911 $t = @filemtime(mediaFN($image)); 912 $more = "t=$t"; 913 } 914 $link = ml($image,$more,true,'&'); 915 916 if (@file_exists(mediaFN($image, $rev))) { 917 918 // view original file button 919 $form = new Doku_Form(array('action'=>$link, 'target'=>'_blank')); 920 $form->addElement(form_makeButton('submit','',$lang['mediaview'])); 921 $form->printForm(); 922 } 923 924 if($auth >= AUTH_DELETE && !$rev && @file_exists(mediaFN($image))){ 925 926 // delete button 927 $form = new Doku_Form(array('id' => 'mediamanager__btn_delete', 928 'action'=>media_managerURL(array('delete' => $image), '&'))); 929 $form->addElement(form_makeButton('submit','',$lang['btn_delete'])); 930 $form->printForm(); 931 932 } 933 934 $auth_ow = (($conf['mediarevisions']) ? AUTH_UPLOAD : AUTH_DELETE); 935 if($auth >= $auth_ow && !$rev){ 936 937 // upload new version button 938 $form = new Doku_Form(array('id' => 'mediamanager__btn_update', 939 'action'=>media_managerURL(array('image' => $image, 'mediado' => 'update'), '&'))); 940 $form->addElement(form_makeButton('submit','',$lang['media_update'])); 941 $form->printForm(); 942 } 943 944 if($auth >= AUTH_DELETE && $rev && $conf['mediarevisions'] && @file_exists(mediaFN($image, $rev))){ 945 946 // restore button 947 $form = new Doku_Form(array('id' => 'mediamanager__btn_restore', 948 'action'=>media_managerURL(array('image' => $image), '&'))); 949 $form->addHidden('mediado','restore'); 950 $form->addHidden('rev',$rev); 951 $form->addElement(form_makeButton('submit','',$lang['media_restore'])); 952 $form->printForm(); 953 } 954 955 echo '</div>'; 956} 957 958/** 959 * Returns image width and height for mediamanager preview panel 960 * 961 * @author Kate Arzamastseva <pshns@ukr.net> 962 * @param string $image 963 * @param int $rev 964 * @param JpegMeta $meta 965 * @return array 966 */ 967function media_image_preview_size($image, $rev, $meta, $size = 500) { 968 if (!preg_match("/\.(jpe?g|gif|png)$/", $image) || !file_exists(mediaFN($image, $rev))) return false; 969 970 $info = getimagesize(mediaFN($image, $rev)); 971 $w = (int) $info[0]; 972 $h = (int) $info[1]; 973 974 if($meta && ($w > $size || $h > $size)){ 975 $ratio = $meta->getResizeRatio($size, $size); 976 $w = floor($w * $ratio); 977 $h = floor($h * $ratio); 978 } 979 return array($w, $h); 980} 981 982/** 983 * Returns the requested EXIF/IPTC tag from the image meta 984 * 985 * @author Kate Arzamastseva <pshns@ukr.net> 986 * @param array $tags 987 * @param JpegMeta $meta 988 * @param string $alt 989 * @return string 990 */ 991function media_getTag($tags,$meta,$alt=''){ 992 if($meta === false) return $alt; 993 $info = $meta->getField($tags); 994 if($info == false) return $alt; 995 return $info; 996} 997 998/** 999 * Returns mediafile tags 1000 * 1001 * @author Kate Arzamastseva <pshns@ukr.net> 1002 * @param JpegMeta $meta 1003 * @return array 1004 */ 1005function media_file_tags($meta) { 1006 global $config_cascade; 1007 1008 // load the field descriptions 1009 static $fields = null; 1010 if(is_null($fields)){ 1011 $config_files = getConfigFiles('mediameta'); 1012 foreach ($config_files as $config_file) { 1013 if(@file_exists($config_file)) include($config_file); 1014 } 1015 } 1016 1017 $tags = array(); 1018 1019 foreach($fields as $key => $tag){ 1020 $t = array(); 1021 if (!empty($tag[0])) $t = array($tag[0]); 1022 if(is_array($tag[3])) $t = array_merge($t,$tag[3]); 1023 $value = media_getTag($t, $meta); 1024 $tags[] = array('tag' => $tag, 'value' => $value); 1025 } 1026 1027 return $tags; 1028} 1029 1030/** 1031 * Prints mediafile tags 1032 * 1033 * @author Kate Arzamastseva <pshns@ukr.net> 1034 */ 1035function media_details($image, $auth, $rev=false, $meta=false) { 1036 global $lang; 1037 1038 if (!$meta) $meta = new JpegMeta(mediaFN($image, $rev)); 1039 $tags = media_file_tags($meta); 1040 1041 echo '<dl class="img_tags">'; 1042 foreach($tags as $tag){ 1043 if ($tag['value']) { 1044 $value = cleanText($tag['value']); 1045 echo '<dt>'.$lang[$tag['tag'][1]].':</dt><dd>'; 1046 if ($tag['tag'][2] == 'date') echo dformat($value); 1047 else echo hsc($value); 1048 echo '</dd>'; 1049 } 1050 } 1051 echo '</dl>'; 1052} 1053 1054/** 1055 * Shows difference between two revisions of file 1056 * 1057 * @author Kate Arzamastseva <pshns@ukr.net> 1058 */ 1059function media_diff($image, $ns, $auth, $fromajax = false) { 1060 global $lang; 1061 global $conf; 1062 1063 if ($auth < AUTH_READ || !$image || !$conf['mediarevisions']) return ''; 1064 1065 $rev1 = (int) $_REQUEST['rev']; 1066 1067 if(is_array($_REQUEST['rev2'])){ 1068 $rev1 = (int) $_REQUEST['rev2'][0]; 1069 $rev2 = (int) $_REQUEST['rev2'][1]; 1070 1071 if(!$rev1){ 1072 $rev1 = $rev2; 1073 unset($rev2); 1074 } 1075 }else{ 1076 $rev2 = (int) $_REQUEST['rev2']; 1077 } 1078 1079 if ($rev1 && !file_exists(mediaFN($image, $rev1))) $rev1 = false; 1080 if ($rev2 && !file_exists(mediaFN($image, $rev2))) $rev2 = false; 1081 1082 if($rev1 && $rev2){ // two specific revisions wanted 1083 // make sure order is correct (older on the left) 1084 if($rev1 < $rev2){ 1085 $l_rev = $rev1; 1086 $r_rev = $rev2; 1087 }else{ 1088 $l_rev = $rev2; 1089 $r_rev = $rev1; 1090 } 1091 }elseif($rev1){ // single revision given, compare to current 1092 $r_rev = ''; 1093 $l_rev = $rev1; 1094 }else{ // no revision was given, compare previous to current 1095 $r_rev = ''; 1096 $revs = getRevisions($image, 0, 1, 8192, true); 1097 if (file_exists(mediaFN($image, $revs[0]))) { 1098 $l_rev = $revs[0]; 1099 } else { 1100 $l_rev = ''; 1101 } 1102 } 1103 1104 // prepare event data 1105 $data[0] = $image; 1106 $data[1] = $l_rev; 1107 $data[2] = $r_rev; 1108 $data[3] = $ns; 1109 $data[4] = $auth; 1110 $data[5] = $fromajax; 1111 1112 // trigger event 1113 return trigger_event('MEDIA_DIFF', $data, '_media_file_diff', true); 1114 1115} 1116 1117function _media_file_diff($data) { 1118 if(is_array($data) && count($data)===6) { 1119 return media_file_diff($data[0], $data[1], $data[2], $data[3], $data[4], $data[5]); 1120 } else { 1121 return false; 1122 } 1123} 1124 1125/** 1126 * Shows difference between two revisions of image 1127 * 1128 * @author Kate Arzamastseva <pshns@ukr.net> 1129 */ 1130function media_file_diff($image, $l_rev, $r_rev, $ns, $auth, $fromajax){ 1131 global $lang, $config_cascade; 1132 1133 $l_meta = new JpegMeta(mediaFN($image, $l_rev)); 1134 $r_meta = new JpegMeta(mediaFN($image, $r_rev)); 1135 1136 $is_img = preg_match("/\.(jpe?g|gif|png)$/", $image); 1137 if ($is_img) { 1138 $l_size = media_image_preview_size($image, $l_rev, $l_meta); 1139 $r_size = media_image_preview_size($image, $r_rev, $r_meta); 1140 $is_img = ($l_size && $r_size && ($l_size[0] >= 30 || $r_size[0] >= 30)); 1141 1142 $difftype = $_REQUEST['difftype']; 1143 1144 if (!$fromajax) { 1145 $form = new Doku_Form(array('action'=>media_managerURL(array(), '&'), 1146 'id' => 'mediamanager__form_diffview')); 1147 $form->addElement('<input type="hidden" name="rev2[]" value="'.$l_rev.'" ></input>'); 1148 $form->addElement('<input type="hidden" name="rev2[]" value="'.$r_rev.'" ></input>'); 1149 $form->addHidden('mediado', 'diff'); 1150 $form->printForm(); 1151 1152 echo '<div id="mediamanager__diff" >'; 1153 } 1154 1155 if ($difftype == 'opacity' || $difftype == 'portions') { 1156 media_image_diff($image, $l_rev, $r_rev, $l_size, $r_size, $difftype); 1157 if (!$fromajax) echo '</div>'; 1158 return ''; 1159 } 1160 } 1161 1162 echo '<div class="mediamanager-preview">'; 1163 echo '<ul id="mediamanager__diff_table">'; 1164 1165 echo '<li>'; 1166 media_preview($image, $auth, $l_rev, $l_meta); 1167 echo '</li>'; 1168 1169 echo '<li>'; 1170 media_preview($image, $auth, $r_rev, $r_meta); 1171 echo '</li>'; 1172 1173 echo '<li>'; 1174 media_preview_buttons($image, $auth, $l_rev); 1175 echo '</li>'; 1176 1177 echo '<li>'; 1178 media_preview_buttons($image, $auth, $r_rev); 1179 echo '</li>'; 1180 1181 $l_tags = media_file_tags($l_meta); 1182 $r_tags = media_file_tags($r_meta); 1183 foreach ($l_tags as $key => $l_tag) { 1184 if ($l_tag['value'] != $r_tags[$key]['value']) { 1185 $r_tags[$key]['class'] = 'highlighted'; 1186 $l_tags[$key]['class'] = 'highlighted'; 1187 } else if (!$l_tag['value'] || !$r_tags[$key]['value']) { 1188 unset($r_tags[$key]); 1189 unset($l_tags[$key]); 1190 } 1191 } 1192 1193 foreach(array($l_tags,$r_tags) as $tags){ 1194 echo '<li><div>'; 1195 1196 echo '<dl class="img_tags">'; 1197 foreach($tags as $tag){ 1198 $value = cleanText($tag['value']); 1199 if (!$value) $value = '-'; 1200 echo '<dt>'.$lang[$tag['tag'][1]].':</dt>'; 1201 echo '<dd class="'.$tag['class'].'" >'; 1202 if ($tag['tag'][2] == 'date') echo dformat($value); 1203 else echo hsc($value); 1204 echo '</dd>'; 1205 } 1206 echo '</dl>'; 1207 1208 echo '</div></li>'; 1209 } 1210 1211 echo '</ul>'; 1212 echo '</div>'; 1213 1214 if ($is_img && !$fromajax) echo '</div>'; 1215} 1216 1217/** 1218 * Prints two images side by side 1219 * and slider 1220 * 1221 * @author Kate Arzamastseva <pshns@ukr.net> 1222 * @param string $image 1223 * @param int $l_rev 1224 * @param int $r_rev 1225 * @param array $l_size 1226 * @param array $r_size 1227 * @param string $type 1228 */ 1229function media_image_diff($image, $l_rev, $r_rev, $l_size, $r_size, $type) { 1230 if ($l_size != $r_size) { 1231 if ($r_size[0] > $l_size[0]) { 1232 $l_size = $r_size; 1233 } 1234 } 1235 1236 echo '<div class="mediamanager-preview">'; 1237 1238 $l_more = array('rev' => $l_rev, 'h' => $l_size[1], 'w' => $l_size[0]); 1239 $r_more = array('rev' => $r_rev, 'h' => $l_size[1], 'w' => $l_size[0]); 1240 1241 $l_src = ml($image, $l_more); 1242 $r_src = ml($image, $r_more); 1243 1244 // slider 1245 echo '<div id="mediamanager__'.$type.'_slider" style="max-width: '.($l_size[0]-20).'px;" ></div>'; 1246 1247 // two image's in div's 1248 echo '<div id="mediamanager__diff_layout">'; 1249 echo '<div id="mediamanager__diff_'.$type.'_image1" style="max-width: '.$l_size[0].'px;">'; 1250 echo '<img src="'.$l_src.'" alt="" />'; 1251 echo '</div>'; 1252 echo '<div id="mediamanager__diff_'.$type.'_image2" style="max-width: '.$l_size[0].'px;">'; 1253 echo '<img src="'.$r_src.'" alt="" />'; 1254 echo '</div>'; 1255 echo '</div>'; 1256 1257 echo '</div>'; 1258} 1259 1260/** 1261 * Restores an old revision of a media file 1262 * 1263 * @param string $image 1264 * @param int $rev 1265 * @param int $auth 1266 * @return string - file's id 1267 * @author Kate Arzamastseva <pshns@ukr.net> 1268 */ 1269function media_restore($image, $rev, $auth){ 1270 global $conf; 1271 if ($auth < AUTH_DELETE || !$conf['mediarevisions']) return false; 1272 $removed = (!file_exists(mediaFN($image)) && file_exists(mediaMetaFN($image, '.changes'))); 1273 if (!$image || (!file_exists(mediaFN($image)) && !$removed)) return false; 1274 if (!$rev || !file_exists(mediaFN($image, $rev))) return false; 1275 list($iext,$imime,$dl) = mimetype($image); 1276 $res = media_upload_finish(mediaFN($image, $rev), 1277 mediaFN($image), 1278 $image, 1279 $imime, 1280 true, 1281 'copy'); 1282 if (is_array($res)) { 1283 msg($res[0], $res[1]); 1284 return false; 1285 } 1286 return $res; 1287} 1288 1289/** 1290 * List all files found by the search request 1291 * 1292 * @author Tobias Sarnowski <sarnowski@cosmocode.de> 1293 * @author Andreas Gohr <gohr@cosmocode.de> 1294 * @author Kate Arzamastseva <pshns@ukr.net> 1295 * @triggers MEDIA_SEARCH 1296 */ 1297function media_searchlist($query,$ns,$auth=null,$fullscreen=false){ 1298 global $conf; 1299 global $lang; 1300 1301 $ns = cleanID($ns); 1302 1303 if ($query) { 1304 $evdata = array( 1305 'ns' => $ns, 1306 'data' => array(), 1307 'query' => $query 1308 ); 1309 $evt = new Doku_Event('MEDIA_SEARCH', $evdata); 1310 if ($evt->advise_before()) { 1311 $dir = utf8_encodeFN(str_replace(':','/',$evdata['ns'])); 1312 $pattern = '/'.preg_quote($evdata['query'],'/').'/i'; 1313 search($evdata['data'], 1314 $conf['mediadir'], 1315 'search_media', 1316 array('showmsg'=>false,'pattern'=>$pattern), 1317 $dir); 1318 } 1319 $evt->advise_after(); 1320 unset($evt); 1321 } 1322 1323 if (!$fullscreen) { 1324 echo '<h1 id="media__ns">'.sprintf($lang['searchmedia_in'],hsc($ns).':*').'</h1>'.NL; 1325 media_searchform($ns,$query); 1326 } 1327 1328 if(!count($evdata['data'])){ 1329 echo '<div class="nothing">'.$lang['nothingfound'].'</div>'.NL; 1330 }else { 1331 if ($fullscreen) { 1332 $view = $_REQUEST['view']; 1333 if ($view == 'list') { 1334 echo '<ul class="mediamanager-list" id="mediamanager__file_list">'; 1335 } else { 1336 echo '<ul class="mediamanager-thumbs" id="mediamanager__file_list">'; 1337 } 1338 } 1339 foreach($evdata['data'] as $item){ 1340 if (!$fullscreen) media_printfile($item,$item['perm'],'',true); 1341 else media_printfile_thumbs($item,$item['perm'],false,true); 1342 } 1343 if ($fullscreen) echo '</ul>'; 1344 } 1345} 1346 1347/** 1348 * Print action links for a file depending on filetype 1349 * and available permissions 1350 */ 1351function media_fileactions($item,$auth){ 1352 global $lang; 1353 1354 // view button 1355 $link = ml($item['id'],'',true); 1356 echo ' <a href="'.$link.'" target="_blank"><img src="'.DOKU_BASE.'lib/images/magnifier.png" '. 1357 'alt="'.$lang['mediaview'].'" title="'.$lang['mediaview'].'" class="btn" /></a>'; 1358 1359 // no further actions if not writable 1360 if(!$item['writable']) return; 1361 1362 // delete button 1363 if($auth >= AUTH_DELETE){ 1364 $link = DOKU_BASE.'lib/exe/mediamanager.php?delete='.rawurlencode($item['id']). 1365 '&sectok='.getSecurityToken(); 1366 echo ' <a href="'.$link.'" class="btn_media_delete" title="'.$item['id'].'">'. 1367 '<img src="'.DOKU_BASE.'lib/images/trash.png" alt="'.$lang['btn_delete'].'" '. 1368 'title="'.$lang['btn_delete'].'" class="btn" /></a>'; 1369 } 1370 1371 // edit button 1372 if($auth >= AUTH_UPLOAD && $item['isimg'] && $item['meta']->getField('File.Mime') == 'image/jpeg'){ 1373 $link = DOKU_BASE.'lib/exe/mediamanager.php?edit='.rawurlencode($item['id']); 1374 echo ' <a href="'.$link.'">'. 1375 '<img src="'.DOKU_BASE.'lib/images/pencil.png" alt="'.$lang['metaedit'].'" '. 1376 'title="'.$lang['metaedit'].'" class="btn" /></a>'; 1377 } 1378 1379} 1380 1381/** 1382 * Formats and prints one file in the list 1383 */ 1384function media_printfile($item,$auth,$jump,$display_namespace=false){ 1385 global $lang; 1386 global $conf; 1387 1388 // Prepare zebra coloring 1389 // I always wanted to use this variable name :-D 1390 static $twibble = 1; 1391 $twibble *= -1; 1392 $zebra = ($twibble == -1) ? 'odd' : 'even'; 1393 1394 // Automatically jump to recent action 1395 if($jump == $item['id']) { 1396 $jump = ' id="scroll__here" '; 1397 }else{ 1398 $jump = ''; 1399 } 1400 1401 // Prepare fileicons 1402 list($ext,$mime,$dl) = mimetype($item['file'],false); 1403 $class = preg_replace('/[^_\-a-z0-9]+/i','_',$ext); 1404 $class = 'select mediafile mf_'.$class; 1405 1406 // Prepare filename 1407 $file = utf8_decodeFN($item['file']); 1408 1409 // Prepare info 1410 $info = ''; 1411 if($item['isimg']){ 1412 $info .= (int) $item['meta']->getField('File.Width'); 1413 $info .= '×'; 1414 $info .= (int) $item['meta']->getField('File.Height'); 1415 $info .= ' '; 1416 } 1417 $info .= '<i>'.dformat($item['mtime']).'</i>'; 1418 $info .= ' '; 1419 $info .= filesize_h($item['size']); 1420 1421 // output 1422 echo '<div class="'.$zebra.'"'.$jump.'>'.NL; 1423 if (!$display_namespace) { 1424 echo '<a name="h_:'.$item['id'].'" class="'.$class.'">'.hsc($file).'</a> '; 1425 } else { 1426 echo '<a name="h_:'.$item['id'].'" class="'.$class.'">'.hsc($item['id']).'</a><br/>'; 1427 } 1428 echo '<span class="info">('.$info.')</span>'.NL; 1429 media_fileactions($item,$auth); 1430 echo '<div class="example" id="ex_'.str_replace(':','_',$item['id']).'">'; 1431 echo $lang['mediausage'].' <code>{{:'.$item['id'].'}}</code>'; 1432 echo '</div>'; 1433 if($item['isimg']) media_printimgdetail($item); 1434 echo '<div class="clearer"></div>'.NL; 1435 echo '</div>'.NL; 1436} 1437 1438function media_printicon($filename){ 1439 list($ext,$mime,$dl) = mimetype(mediaFN($filename),false); 1440 1441 if (@file_exists(DOKU_INC.'lib/images/fileicons/'.$ext.'.png')) { 1442 $icon = DOKU_BASE.'lib/images/fileicons/'.$ext.'.png'; 1443 } else { 1444 $icon = DOKU_BASE.'lib/images/fileicons/file.png'; 1445 } 1446 1447 return '<img src="'.$icon.'" alt="'.$filename.'" class="icon" />'; 1448 1449} 1450 1451/** 1452 * Formats and prints one file in the list in the thumbnails view 1453 * 1454 * @author Kate Arzamastseva <pshns@ukr.net> 1455 */ 1456function media_printfile_thumbs($item,$auth,$jump=false,$display_namespace=false){ 1457 global $lang; 1458 global $conf; 1459 1460 // Prepare filename 1461 $file = utf8_decodeFN($item['file']); 1462 1463 // output 1464 echo '<li><div>'; 1465 1466 if($item['isimg']) { 1467 media_printimgdetail($item, true); 1468 1469 } else { 1470 echo '<a name="d_:'.$item['id'].'" class="image" title="'.$item['id'].'" href="'. 1471 media_managerURL(array('image' => hsc($item['id']), 'ns' => getNS($item['id']))).'"><span>'; 1472 echo media_printicon($item['id']); 1473 echo '</span></a>'; 1474 } 1475 //echo '<input type=checkbox />'; 1476 if (!$display_namespace) { 1477 $name = hsc($file); 1478 } else { 1479 $name = hsc($item['id']); 1480 } 1481 echo '<a href="'.media_managerURL(array('image' => hsc($item['id']), 'ns' => getNS($item['id']))).'" name= 1482 "h_:'.$item['id'].'" class="name">'.$name.'</a>'; 1483 1484 if($item['isimg']){ 1485 $size = ''; 1486 $size .= (int) $item['meta']->getField('File.Width'); 1487 $size .= '×'; 1488 $size .= (int) $item['meta']->getField('File.Height'); 1489 echo '<span class="size">'.$size.'</span>'; 1490 } else { 1491 echo '<span class="size"> </span>'; 1492 } 1493 $date = dformat($item['mtime']); 1494 echo '<span class="date">'.$date.'</span>'; 1495 $filesize = filesize_h($item['size']); 1496 echo '<span class="filesize">'.$filesize.'</span>'; 1497 echo '<div class="clearer"></div>'; 1498 echo '</div></li>'.NL; 1499} 1500 1501/** 1502 * Prints a thumbnail and metainfos 1503 */ 1504function media_printimgdetail($item, $fullscreen=false){ 1505 // prepare thumbnail 1506 if (!$fullscreen) { 1507 $size_array[] = 120; 1508 } else { 1509 $size_array = array(90, 40); 1510 } 1511 foreach ($size_array as $index => $size) { 1512 $w = (int) $item['meta']->getField('File.Width'); 1513 $h = (int) $item['meta']->getField('File.Height'); 1514 if($w>$size || $h>$size){ 1515 if (!$fullscreen) { 1516 $ratio = $item['meta']->getResizeRatio($size); 1517 } else { 1518 $ratio = $item['meta']->getResizeRatio($size,$size); 1519 } 1520 $w = floor($w * $ratio); 1521 $h = floor($h * $ratio); 1522 } 1523 $src = ml($item['id'],array('w'=>$w,'h'=>$h,'t'=>$item['mtime'])); 1524 $p = array(); 1525 if (!$fullscreen) { 1526 $p['width'] = $w; 1527 $p['height'] = $h; 1528 } 1529 $p['alt'] = $item['id']; 1530 $p['class'] = 'thumb'; 1531 $att = buildAttributes($p); 1532 1533 // output 1534 if ($fullscreen) { 1535 echo '<a name="d_:'.$item['id'].'" class="image'.$index.'" title="'.$item['id'].'" href="'. 1536 media_managerURL(array('image' => hsc($item['id']), 'ns' => getNS($item['id']))).'">'; 1537 echo '<span><img src="'.$src.'" '.$att.' /></span>'; 1538 echo '</a>'; 1539 } 1540 } 1541 1542 if ($fullscreen) return ''; 1543 1544 echo '<div class="detail">'; 1545 echo '<div class="thumb">'; 1546 echo '<a name="d_:'.$item['id'].'" class="select">'; 1547 echo '<img src="'.$src.'" '.$att.' />'; 1548 echo '</a>'; 1549 echo '</div>'; 1550 1551 // read EXIF/IPTC data 1552 $t = $item['meta']->getField(array('IPTC.Headline','xmp.dc:title')); 1553 $d = $item['meta']->getField(array('IPTC.Caption','EXIF.UserComment', 1554 'EXIF.TIFFImageDescription', 1555 'EXIF.TIFFUserComment')); 1556 if(utf8_strlen($d) > 250) $d = utf8_substr($d,0,250).'...'; 1557 $k = $item['meta']->getField(array('IPTC.Keywords','IPTC.Category','xmp.dc:subject')); 1558 1559 // print EXIF/IPTC data 1560 if($t || $d || $k ){ 1561 echo '<p>'; 1562 if($t) echo '<strong>'.htmlspecialchars($t).'</strong><br />'; 1563 if($d) echo htmlspecialchars($d).'<br />'; 1564 if($t) echo '<em>'.htmlspecialchars($k).'</em>'; 1565 echo '</p>'; 1566 } 1567 echo '</div>'; 1568} 1569 1570/** 1571 * Build link based on the current, adding/rewriting 1572 * parameters 1573 * 1574 * @author Kate Arzamastseva <pshns@ukr.net> 1575 * @param array $params 1576 * @param string $amp - separator 1577 * @return string - link 1578 */ 1579function media_managerURL($params=false, $amp='&', $abs=false) { 1580 global $conf; 1581 global $ID; 1582 1583 $gets = array('do' => 'media'); 1584 $media_manager_params = array('tab_files', 'tab_details', 'image', 'ns', 'view'); 1585 foreach ($media_manager_params as $x) { 1586 if (isset($_REQUEST[$x])) $gets[$x] = $_REQUEST[$x]; 1587 } 1588 1589 if ($params) { 1590 foreach ($params as $k => $v) { 1591 $gets[$k] = $v; 1592 } 1593 } 1594 unset($gets['id']); 1595 if ($gets['delete']) { 1596 unset($gets['image']); 1597 unset($gets['tab_details']); 1598 } 1599 1600 return wl($ID,$gets,$abs,$amp); 1601} 1602 1603/** 1604 * Print the media upload form if permissions are correct 1605 * 1606 * @author Andreas Gohr <andi@splitbrain.org> 1607 * @author Kate Arzamastseva <pshns@ukr.net> 1608 */ 1609function media_uploadform($ns, $auth, $fullscreen = false){ 1610 global $lang, $conf; 1611 1612 if($auth < AUTH_UPLOAD) { 1613 echo '<div class="nothing">'.$lang['media_perm_upload'].'</div>'.NL; 1614 return; 1615 } 1616 $auth_ow = (($conf['mediarevisions']) ? AUTH_UPLOAD : AUTH_DELETE); 1617 1618 $update = false; 1619 $id = ''; 1620 if ($auth >= $auth_ow && $fullscreen && $_REQUEST['mediado'] == 'update') { 1621 $update = true; 1622 $id = cleanID($_REQUEST['image']); 1623 } 1624 1625 // The default HTML upload form 1626 $params = array('id' => 'dw__upload', 1627 'enctype' => 'multipart/form-data'); 1628 if (!$fullscreen) { 1629 $params['action'] = DOKU_BASE.'lib/exe/mediamanager.php'; 1630 } else { 1631 $params['action'] = media_managerURL(array('tab_files' => 'files', 1632 'tab_details' => 'view'), '&'); 1633 } 1634 1635 $form = new Doku_Form($params); 1636 if (!$fullscreen) echo '<div class="upload">' . $lang['mediaupload'] . '</div>'; 1637 $form->addElement(formSecurityToken()); 1638 $form->addHidden('ns', hsc($ns)); 1639 $form->addElement(form_makeOpenTag('p')); 1640 $form->addElement(form_makeFileField('upload', $lang['txt_upload'].':', 'upload__file')); 1641 $form->addElement(form_makeCloseTag('p')); 1642 $form->addElement(form_makeOpenTag('p')); 1643 $form->addElement(form_makeTextField('mediaid', noNS($id), $lang['txt_filename'].':', 'upload__name')); 1644 $form->addElement(form_makeButton('submit', '', $lang['btn_upload'])); 1645 $form->addElement(form_makeCloseTag('p')); 1646 1647 if($auth >= $auth_ow){ 1648 $form->addElement(form_makeOpenTag('p')); 1649 $attrs = array(); 1650 if ($update) $attrs['checked'] = 'checked'; 1651 $form->addElement(form_makeCheckboxField('ow', 1, $lang['txt_overwrt'], 'dw__ow', 'check', $attrs)); 1652 $form->addElement(form_makeCloseTag('p')); 1653 } 1654 1655 echo '<div id="mediamanager__uploader">'; 1656 html_form('upload', $form); 1657 echo '</div>'; 1658} 1659 1660/** 1661 * Print the search field form 1662 * 1663 * @author Tobias Sarnowski <sarnowski@cosmocode.de> 1664 * @author Kate Arzamastseva <pshns@ukr.net> 1665 */ 1666function media_searchform($ns,$query='',$fullscreen=false){ 1667 global $lang; 1668 1669 // The default HTML search form 1670 $params = array('id' => 'dw__mediasearch'); 1671 if (!$fullscreen) $params['action'] = DOKU_BASE.'lib/exe/mediamanager.php'; 1672 else $params['action'] = media_managerURL(array(), '&'); 1673 $form = new Doku_Form($params); 1674 if (!$fullscreen) $form->addElement('<div class="upload">' . $lang['mediasearch'] . '</div>'); 1675 $form->addElement(formSecurityToken()); 1676 $form->addHidden('ns', $ns); 1677 if (!$fullscreen) $form->addHidden('do', 'searchlist'); 1678 else $form->addHidden('mediado', 'searchlist'); 1679 $form->addElement(form_makeOpenTag('p')); 1680 $form->addElement(form_makeTextField('q', $query,$lang['searchmedia'],'','',array('title'=>sprintf($lang['searchmedia_in'],hsc($ns).':*')))); 1681 $form->addElement(form_makeButton('submit', '', $lang['btn_search'])); 1682 $form->addElement(form_makeCloseTag('p')); 1683 html_form('searchmedia', $form); 1684} 1685 1686/** 1687 * Build a tree outline of available media namespaces 1688 * 1689 * @author Andreas Gohr <andi@splitbrain.org> 1690 */ 1691function media_nstree($ns){ 1692 global $conf; 1693 global $lang; 1694 1695 // currently selected namespace 1696 $ns = cleanID($ns); 1697 if(empty($ns)){ 1698 global $ID; 1699 $ns = dirname(str_replace(':','/',$ID)); 1700 if($ns == '.') $ns =''; 1701 } 1702 $ns = utf8_encodeFN(str_replace(':','/',$ns)); 1703 1704 $data = array(); 1705 search($data,$conf['mediadir'],'search_index',array('ns' => $ns, 'nofiles' => true)); 1706 1707 // wrap a list with the root level around the other namespaces 1708 array_unshift($data, array('level' => 0, 'id' => '', 'open' =>'true', 1709 'label' => '['.$lang['mediaroot'].']')); 1710 1711 echo html_buildlist($data,'idx','media_nstree_item','media_nstree_li'); 1712 echo '</li>'; 1713 1714 echo '</ul>'; 1715} 1716 1717/** 1718 * Userfunction for html_buildlist 1719 * 1720 * Prints a media namespace tree item 1721 * 1722 * @author Andreas Gohr <andi@splitbrain.org> 1723 */ 1724function media_nstree_item($item){ 1725 $pos = strrpos($item['id'], ':'); 1726 $label = substr($item['id'], $pos > 0 ? $pos + 1 : 0); 1727 if(!$item['label']) $item['label'] = $label; 1728 1729 $ret = ''; 1730 if (!($_REQUEST['do'] == 'media')) 1731 $ret .= '<a href="'.DOKU_BASE.'lib/exe/mediamanager.php?ns='.idfilter($item['id']).'" class="idx_dir">'; 1732 else $ret .= '<a href="'.media_managerURL(array('ns' => idfilter($item['id']), 'tab_files' => 'files')) 1733 .'" class="idx_dir">'; 1734 $ret .= $item['label']; 1735 $ret .= '</a>'; 1736 return $ret; 1737} 1738 1739/** 1740 * Userfunction for html_buildlist 1741 * 1742 * Prints a media namespace tree item opener 1743 * 1744 * @author Andreas Gohr <andi@splitbrain.org> 1745 */ 1746function media_nstree_li($item){ 1747 $class='media level'.$item['level']; 1748 if($item['open']){ 1749 $class .= ' open'; 1750 $img = DOKU_BASE.'lib/images/minus.gif'; 1751 $alt = '−'; 1752 }else{ 1753 $class .= ' closed'; 1754 $img = DOKU_BASE.'lib/images/plus.gif'; 1755 $alt = '+'; 1756 } 1757 // TODO: only deliver an image if it actually has a subtree... 1758 return '<li class="'.$class.'">'. 1759 '<img src="'.$img.'" alt="'.$alt.'" />'; 1760} 1761 1762/** 1763 * Resizes the given image to the given size 1764 * 1765 * @author Andreas Gohr <andi@splitbrain.org> 1766 */ 1767function media_resize_image($file, $ext, $w, $h=0){ 1768 global $conf; 1769 1770 $info = @getimagesize($file); //get original size 1771 if($info == false) return $file; // that's no image - it's a spaceship! 1772 1773 if(!$h) $h = round(($w * $info[1]) / $info[0]); 1774 1775 // we wont scale up to infinity 1776 if($w > 2000 || $h > 2000) return $file; 1777 1778 //cache 1779 $local = getCacheName($file,'.media.'.$w.'x'.$h.'.'.$ext); 1780 $mtime = @filemtime($local); // 0 if not exists 1781 1782 if( $mtime > filemtime($file) || 1783 media_resize_imageIM($ext,$file,$info[0],$info[1],$local,$w,$h) || 1784 media_resize_imageGD($ext,$file,$info[0],$info[1],$local,$w,$h) ){ 1785 if($conf['fperm']) chmod($local, $conf['fperm']); 1786 return $local; 1787 } 1788 //still here? resizing failed 1789 return $file; 1790} 1791 1792/** 1793 * Crops the given image to the wanted ratio, then calls media_resize_image to scale it 1794 * to the wanted size 1795 * 1796 * Crops are centered horizontally but prefer the upper third of an vertical 1797 * image because most pics are more interesting in that area (rule of thirds) 1798 * 1799 * @author Andreas Gohr <andi@splitbrain.org> 1800 */ 1801function media_crop_image($file, $ext, $w, $h=0){ 1802 global $conf; 1803 1804 if(!$h) $h = $w; 1805 $info = @getimagesize($file); //get original size 1806 if($info == false) return $file; // that's no image - it's a spaceship! 1807 1808 // calculate crop size 1809 $fr = $info[0]/$info[1]; 1810 $tr = $w/$h; 1811 if($tr >= 1){ 1812 if($tr > $fr){ 1813 $cw = $info[0]; 1814 $ch = (int) $info[0]/$tr; 1815 }else{ 1816 $cw = (int) $info[1]*$tr; 1817 $ch = $info[1]; 1818 } 1819 }else{ 1820 if($tr < $fr){ 1821 $cw = (int) $info[1]*$tr; 1822 $ch = $info[1]; 1823 }else{ 1824 $cw = $info[0]; 1825 $ch = (int) $info[0]/$tr; 1826 } 1827 } 1828 // calculate crop offset 1829 $cx = (int) ($info[0]-$cw)/2; 1830 $cy = (int) ($info[1]-$ch)/3; 1831 1832 //cache 1833 $local = getCacheName($file,'.media.'.$cw.'x'.$ch.'.crop.'.$ext); 1834 $mtime = @filemtime($local); // 0 if not exists 1835 1836 if( $mtime > filemtime($file) || 1837 media_crop_imageIM($ext,$file,$info[0],$info[1],$local,$cw,$ch,$cx,$cy) || 1838 media_resize_imageGD($ext,$file,$cw,$ch,$local,$cw,$ch,$cx,$cy) ){ 1839 if($conf['fperm']) chmod($local, $conf['fperm']); 1840 return media_resize_image($local,$ext, $w, $h); 1841 } 1842 1843 //still here? cropping failed 1844 return media_resize_image($file,$ext, $w, $h); 1845} 1846 1847/** 1848 * Download a remote file and return local filename 1849 * 1850 * returns false if download fails. Uses cached file if available and 1851 * wanted 1852 * 1853 * @author Andreas Gohr <andi@splitbrain.org> 1854 * @author Pavel Vitis <Pavel.Vitis@seznam.cz> 1855 */ 1856function media_get_from_URL($url,$ext,$cache){ 1857 global $conf; 1858 1859 // if no cache or fetchsize just redirect 1860 if ($cache==0) return false; 1861 if (!$conf['fetchsize']) return false; 1862 1863 $local = getCacheName(strtolower($url),".media.$ext"); 1864 $mtime = @filemtime($local); // 0 if not exists 1865 1866 //decide if download needed: 1867 if( ($mtime == 0) || // cache does not exist 1868 ($cache != -1 && $mtime < time()-$cache) // 'recache' and cache has expired 1869 ){ 1870 if(media_image_download($url,$local)){ 1871 return $local; 1872 }else{ 1873 return false; 1874 } 1875 } 1876 1877 //if cache exists use it else 1878 if($mtime) return $local; 1879 1880 //else return false 1881 return false; 1882} 1883 1884/** 1885 * Download image files 1886 * 1887 * @author Andreas Gohr <andi@splitbrain.org> 1888 */ 1889function media_image_download($url,$file){ 1890 global $conf; 1891 $http = new DokuHTTPClient(); 1892 $http->max_bodysize = $conf['fetchsize']; 1893 $http->timeout = 25; //max. 25 sec 1894 $http->header_regexp = '!\r\nContent-Type: image/(jpe?g|gif|png)!i'; 1895 1896 $data = $http->get($url); 1897 if(!$data) return false; 1898 1899 $fileexists = @file_exists($file); 1900 $fp = @fopen($file,"w"); 1901 if(!$fp) return false; 1902 fwrite($fp,$data); 1903 fclose($fp); 1904 if(!$fileexists and $conf['fperm']) chmod($file, $conf['fperm']); 1905 1906 // check if it is really an image 1907 $info = @getimagesize($file); 1908 if(!$info){ 1909 @unlink($file); 1910 return false; 1911 } 1912 1913 return true; 1914} 1915 1916/** 1917 * resize images using external ImageMagick convert program 1918 * 1919 * @author Pavel Vitis <Pavel.Vitis@seznam.cz> 1920 * @author Andreas Gohr <andi@splitbrain.org> 1921 */ 1922function media_resize_imageIM($ext,$from,$from_w,$from_h,$to,$to_w,$to_h){ 1923 global $conf; 1924 1925 // check if convert is configured 1926 if(!$conf['im_convert']) return false; 1927 1928 // prepare command 1929 $cmd = $conf['im_convert']; 1930 $cmd .= ' -resize '.$to_w.'x'.$to_h.'!'; 1931 if ($ext == 'jpg' || $ext == 'jpeg') { 1932 $cmd .= ' -quality '.$conf['jpg_quality']; 1933 } 1934 $cmd .= " $from $to"; 1935 1936 @exec($cmd,$out,$retval); 1937 if ($retval == 0) return true; 1938 return false; 1939} 1940 1941/** 1942 * crop images using external ImageMagick convert program 1943 * 1944 * @author Andreas Gohr <andi@splitbrain.org> 1945 */ 1946function media_crop_imageIM($ext,$from,$from_w,$from_h,$to,$to_w,$to_h,$ofs_x,$ofs_y){ 1947 global $conf; 1948 1949 // check if convert is configured 1950 if(!$conf['im_convert']) return false; 1951 1952 // prepare command 1953 $cmd = $conf['im_convert']; 1954 $cmd .= ' -crop '.$to_w.'x'.$to_h.'+'.$ofs_x.'+'.$ofs_y; 1955 if ($ext == 'jpg' || $ext == 'jpeg') { 1956 $cmd .= ' -quality '.$conf['jpg_quality']; 1957 } 1958 $cmd .= " $from $to"; 1959 1960 @exec($cmd,$out,$retval); 1961 if ($retval == 0) return true; 1962 return false; 1963} 1964 1965/** 1966 * resize or crop images using PHP's libGD support 1967 * 1968 * @author Andreas Gohr <andi@splitbrain.org> 1969 * @author Sebastian Wienecke <s_wienecke@web.de> 1970 */ 1971function media_resize_imageGD($ext,$from,$from_w,$from_h,$to,$to_w,$to_h,$ofs_x=0,$ofs_y=0){ 1972 global $conf; 1973 1974 if($conf['gdlib'] < 1) return false; //no GDlib available or wanted 1975 1976 // check available memory 1977 if(!is_mem_available(($from_w * $from_h * 4) + ($to_w * $to_h * 4))){ 1978 return false; 1979 } 1980 1981 // create an image of the given filetype 1982 if ($ext == 'jpg' || $ext == 'jpeg'){ 1983 if(!function_exists("imagecreatefromjpeg")) return false; 1984 $image = @imagecreatefromjpeg($from); 1985 }elseif($ext == 'png') { 1986 if(!function_exists("imagecreatefrompng")) return false; 1987 $image = @imagecreatefrompng($from); 1988 1989 }elseif($ext == 'gif') { 1990 if(!function_exists("imagecreatefromgif")) return false; 1991 $image = @imagecreatefromgif($from); 1992 } 1993 if(!$image) return false; 1994 1995 if(($conf['gdlib']>1) && function_exists("imagecreatetruecolor") && $ext != 'gif'){ 1996 $newimg = @imagecreatetruecolor ($to_w, $to_h); 1997 } 1998 if(!$newimg) $newimg = @imagecreate($to_w, $to_h); 1999 if(!$newimg){ 2000 imagedestroy($image); 2001 return false; 2002 } 2003 2004 //keep png alpha channel if possible 2005 if($ext == 'png' && $conf['gdlib']>1 && function_exists('imagesavealpha')){ 2006 imagealphablending($newimg, false); 2007 imagesavealpha($newimg,true); 2008 } 2009 2010 //keep gif transparent color if possible 2011 if($ext == 'gif' && function_exists('imagefill') && function_exists('imagecolorallocate')) { 2012 if(function_exists('imagecolorsforindex') && function_exists('imagecolortransparent')) { 2013 $transcolorindex = @imagecolortransparent($image); 2014 if($transcolorindex >= 0 ) { //transparent color exists 2015 $transcolor = @imagecolorsforindex($image, $transcolorindex); 2016 $transcolorindex = @imagecolorallocate($newimg, $transcolor['red'], $transcolor['green'], $transcolor['blue']); 2017 @imagefill($newimg, 0, 0, $transcolorindex); 2018 @imagecolortransparent($newimg, $transcolorindex); 2019 }else{ //filling with white 2020 $whitecolorindex = @imagecolorallocate($newimg, 255, 255, 255); 2021 @imagefill($newimg, 0, 0, $whitecolorindex); 2022 } 2023 }else{ //filling with white 2024 $whitecolorindex = @imagecolorallocate($newimg, 255, 255, 255); 2025 @imagefill($newimg, 0, 0, $whitecolorindex); 2026 } 2027 } 2028 2029 //try resampling first 2030 if(function_exists("imagecopyresampled")){ 2031 if(!@imagecopyresampled($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h)) { 2032 imagecopyresized($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h); 2033 } 2034 }else{ 2035 imagecopyresized($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h); 2036 } 2037 2038 $okay = false; 2039 if ($ext == 'jpg' || $ext == 'jpeg'){ 2040 if(!function_exists('imagejpeg')){ 2041 $okay = false; 2042 }else{ 2043 $okay = imagejpeg($newimg, $to, $conf['jpg_quality']); 2044 } 2045 }elseif($ext == 'png') { 2046 if(!function_exists('imagepng')){ 2047 $okay = false; 2048 }else{ 2049 $okay = imagepng($newimg, $to); 2050 } 2051 }elseif($ext == 'gif') { 2052 if(!function_exists('imagegif')){ 2053 $okay = false; 2054 }else{ 2055 $okay = imagegif($newimg, $to); 2056 } 2057 } 2058 2059 // destroy GD image ressources 2060 if($image) imagedestroy($image); 2061 if($newimg) imagedestroy($newimg); 2062 2063 return $okay; 2064} 2065 2066/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 2067