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 */ 44function media_metasave($id,$auth,$data){ 45 if($auth < AUTH_UPLOAD) return false; 46 if(!checkSecurityToken()) return false; 47 global $lang; 48 global $conf; 49 $src = mediaFN($id); 50 51 $meta = new JpegMeta($src); 52 $meta->_parseAll(); 53 54 foreach($data as $key => $val){ 55 $val=trim($val); 56 if(empty($val)){ 57 $meta->deleteField($key); 58 }else{ 59 $meta->setField($key,$val); 60 } 61 } 62 63 if($meta->save()){ 64 if($conf['fperm']) chmod($src, $conf['fperm']); 65 msg($lang['metasaveok'],1); 66 return $id; 67 }else{ 68 msg($lang['metasaveerr'],-1); 69 return false; 70 } 71} 72 73/** 74 * Display the form to edit image meta data 75 * 76 * @author Andreas Gohr <andi@splitbrain.org> 77 * @author Kate Arzamastseva <pshns@ukr.net> 78 */ 79function media_metaform($id,$auth,$fullscreen = false){ 80 if($auth < AUTH_UPLOAD) return false; 81 global $lang, $config_cascade; 82 83 // load the field descriptions 84 static $fields = null; 85 if(is_null($fields)){ 86 87 foreach (array('default','local') as $config_group) { 88 if (empty($config_cascade['mediameta'][$config_group])) continue; 89 foreach ($config_cascade['mediameta'][$config_group] as $config_file) { 90 if(@file_exists($config_file)){ 91 include($config_file); 92 } 93 } 94 } 95 } 96 97 $src = mediaFN($id); 98 99 // output 100 if (!$fullscreen) { 101 echo '<h1>'.hsc(noNS($id)).'</h1>'.NL; 102 echo '<form action="'.DOKU_BASE.'lib/exe/mediamanager.php" accept-charset="utf-8" method="post" class="meta">'.NL; 103 } else { 104 echo '<form action="'.media_managerURL(array('tab_details' => 'view')). 105 '" accept-charset="utf-8" method="post" class="meta">'.NL; 106 } 107 formSecurityToken(); 108 foreach($fields as $key => $field){ 109 // get current value 110 $tags = array($field[0]); 111 if(is_array($field[3])) $tags = array_merge($tags,$field[3]); 112 $value = tpl_img_getTag($tags,'',$src); 113 $value = cleanText($value); 114 115 // prepare attributes 116 $p = array(); 117 $p['class'] = 'edit'; 118 $p['id'] = 'meta__'.$key; 119 $p['name'] = 'meta['.$field[0].']'; 120 121 // put label 122 echo '<div class="metafield">'; 123 echo '<label for="meta__'.$key.'">'; 124 echo ($lang[$field[1]]) ? $lang[$field[1]] : $field[1]; 125 echo ':</label>'; 126 127 // put input field 128 if($field[2] == 'text'){ 129 $p['value'] = $value; 130 $p['type'] = 'text'; 131 $att = buildAttributes($p); 132 echo "<input $att/>".NL; 133 }else{ 134 $att = buildAttributes($p); 135 echo "<textarea $att rows=\"6\" cols=\"50\">".formText($value).'</textarea>'.NL; 136 } 137 echo '</div>'.NL; 138 } 139 echo '<div class="buttons">'.NL; 140 echo '<input type="hidden" name="img" value="'.hsc($id).'" />'.NL; 141 if (!$fullscreen) $do = 'do'; 142 else $do = 'mediado'; 143 echo '<input name="'.$do.'[save]" type="submit" value="'.$lang['btn_save']. 144 '" title="'.$lang['btn_save'].' [S]" accesskey="s" class="button" />'.NL; 145 if (!$fullscreen) 146 echo '<input name="do[cancel]" type="submit" value="'.$lang['btn_cancel']. 147 '" title="'.$lang['btn_cancel'].' [C]" accesskey="c" class="button" />'.NL; 148 echo '</div>'.NL; 149 echo '</form>'.NL; 150} 151 152/** 153 * Convenience function to check if a media file is still in use 154 * 155 * @author Michael Klier <chi@chimeric.de> 156 */ 157function media_inuse($id) { 158 global $conf; 159 $mediareferences = array(); 160 if($conf['refcheck']){ 161 $mediareferences = ft_mediause($id,$conf['refshow']); 162 if(!count($mediareferences)) { 163 return false; 164 } else { 165 return $mediareferences; 166 } 167 } else { 168 return false; 169 } 170} 171 172define('DOKU_MEDIA_DELETED', 1); 173define('DOKU_MEDIA_NOT_AUTH', 2); 174define('DOKU_MEDIA_INUSE', 4); 175define('DOKU_MEDIA_EMPTY_NS', 8); 176 177/** 178 * Handles media file deletions 179 * 180 * If configured, checks for media references before deletion 181 * 182 * @author Andreas Gohr <andi@splitbrain.org> 183 * @return int One of: 0, 184 DOKU_MEDIA_DELETED, 185 DOKU_MEDIA_DELETED | DOKU_MEDIA_EMPTY_NS, 186 DOKU_MEDIA_NOT_AUTH, 187 DOKU_MEDIA_INUSE 188 */ 189function media_delete($id,$auth){ 190 if($auth < AUTH_DELETE) return DOKU_MEDIA_NOT_AUTH; 191 if(media_inuse($id)) return DOKU_MEDIA_INUSE; 192 193 $file = mediaFN($id); 194 195 // trigger an event - MEDIA_DELETE_FILE 196 $data['id'] = $id; 197 $data['name'] = basename($file); 198 $data['path'] = $file; 199 $data['size'] = (@file_exists($file)) ? filesize($file) : 0; 200 201 $data['unl'] = false; 202 $data['del'] = false; 203 $evt = new Doku_Event('MEDIA_DELETE_FILE',$data); 204 if ($evt->advise_before()) { 205 $data['unl'] = @unlink($file); 206 if($data['unl']){ 207 addMediaLogEntry(time(), $id, DOKU_CHANGE_TYPE_DELETE); 208 $data['del'] = io_sweepNS($id,'mediadir'); 209 } 210 } 211 $evt->advise_after(); 212 unset($evt); 213 214 if($data['unl'] && $data['del']){ 215 return DOKU_MEDIA_DELETED | DOKU_MEDIA_EMPTY_NS; 216 } 217 218 return $data['unl'] ? DOKU_MEDIA_DELETED : 0; 219} 220 221/** 222 * Handles media file uploads 223 * 224 * @author Andreas Gohr <andi@splitbrain.org> 225 * @author Michael Klier <chi@chimeric.de> 226 * @return mixed false on error, id of the new file on success 227 */ 228function media_upload($ns,$auth){ 229 if(!checkSecurityToken()) return false; 230 global $lang; 231 232 // get file and id 233 $id = $_POST['id']; 234 $file = $_FILES['upload']; 235 if(empty($id)) $id = $file['name']; 236 237 // check for errors (messages are done in lib/exe/mediamanager.php) 238 if($file['error']) return false; 239 240 // check extensions 241 list($fext,$fmime,$dl) = mimetype($file['name']); 242 list($iext,$imime,$dl) = mimetype($id); 243 if($fext && !$iext){ 244 // no extension specified in id - read original one 245 $id .= '.'.$fext; 246 $imime = $fmime; 247 }elseif($fext && $fext != $iext){ 248 // extension was changed, print warning 249 msg(sprintf($lang['mediaextchange'],$fext,$iext)); 250 } 251 252 $res = media_save(array('name' => $file['tmp_name'], 253 'mime' => $imime, 254 'ext' => $iext), $ns.':'.$id, 255 $_REQUEST['ow'], $auth, 'move_uploaded_file'); 256 if (is_array($res)) { 257 msg($res[0], $res[1]); 258 return false; 259 } 260 return $res; 261} 262 263/** 264 * This generates an action event and delegates to _media_upload_action(). 265 * Action plugins are allowed to pre/postprocess the uploaded file. 266 * (The triggered event is preventable.) 267 * 268 * Event data: 269 * $data[0] fn_tmp: the temporary file name (read from $_FILES) 270 * $data[1] fn: the file name of the uploaded file 271 * $data[2] id: the future directory id of the uploaded file 272 * $data[3] imime: the mimetype of the uploaded file 273 * $data[4] overwrite: if an existing file is going to be overwritten 274 * 275 * @triggers MEDIA_UPLOAD_FINISH 276 */ 277function media_save($file, $id, $ow, $auth, $move) { 278 if($auth < AUTH_UPLOAD) { 279 return array("You don't have permissions to upload files.", -1); 280 } 281 282 if (!isset($file['mime']) || !isset($file['ext'])) { 283 list($ext, $mime) = mimetype($id); 284 if (!isset($file['mime'])) { 285 $file['mime'] = $mime; 286 } 287 if (!isset($file['ext'])) { 288 $file['ext'] = $ext; 289 } 290 } 291 292 global $lang; 293 294 // get filename 295 $id = cleanID($id,false,true); 296 $fn = mediaFN($id); 297 298 // get filetype regexp 299 $types = array_keys(getMimeTypes()); 300 $types = array_map(create_function('$q','return preg_quote($q,"/");'),$types); 301 $regex = join('|',$types); 302 303 // because a temp file was created already 304 if(!preg_match('/\.('.$regex.')$/i',$fn)) { 305 return array($lang['uploadwrong'],-1); 306 } 307 308 //check for overwrite 309 $overwrite = @file_exists($fn); 310 if($overwrite && (!$ow || $auth < AUTH_DELETE)) { 311 return array($lang['uploadexist'], 0); 312 } 313 // check for valid content 314 $ok = media_contentcheck($file['name'], $file['mime']); 315 if($ok == -1){ 316 return array(sprintf($lang['uploadbadcontent'],'.' . $file['ext']),-1); 317 }elseif($ok == -2){ 318 return array($lang['uploadspam'],-1); 319 }elseif($ok == -3){ 320 return array($lang['uploadxss'],-1); 321 } 322 323 // prepare event data 324 $data[0] = $file['name']; 325 $data[1] = $fn; 326 $data[2] = $id; 327 $data[3] = $file['mime']; 328 $data[4] = $overwrite; 329 $data[5] = $move; 330 331 // trigger event 332 return trigger_event('MEDIA_UPLOAD_FINISH', $data, '_media_upload_action', true); 333} 334 335/** 336 * Callback adapter for media_upload_finish() 337 * @author Michael Klier <chi@chimeric.de> 338 */ 339function _media_upload_action($data) { 340 // fixme do further sanity tests of given data? 341 if(is_array($data) && count($data)===6) { 342 return media_upload_finish($data[0], $data[1], $data[2], $data[3], $data[4], $data[5]); 343 } else { 344 return false; //callback error 345 } 346} 347 348/** 349 * Saves an uploaded media file 350 * 351 * @author Andreas Gohr <andi@splitbrain.org> 352 * @author Michael Klier <chi@chimeric.de> 353 * @author Kate Arzamastseva <pshns@ukr.net> 354 */ 355function media_upload_finish($fn_tmp, $fn, $id, $imime, $overwrite, $move = 'move_uploaded_file') { 356 global $conf; 357 global $lang; 358 359 $old = @filemtime($fn); 360 if(!@file_exists(mediaFN($id, $old)) && @file_exists($fn)) { 361 // add old revision to the attic if missing 362 media_saveOldRevision($id); 363 } 364 365 // prepare directory 366 io_createNamespace($id, 'media'); 367 368 if($move($fn_tmp, $fn)) { 369 // Set the correct permission here. 370 // Always chmod media because they may be saved with different permissions than expected from the php umask. 371 // (Should normally chmod to $conf['fperm'] only if $conf['fperm'] is set.) 372 chmod($fn, $conf['fmode']); 373 msg($lang['uploadsucc'],1); 374 media_notify($id,$fn,$imime); 375 // add a log entry to the media changelog 376 if ($overwrite) { 377 addMediaLogEntry(time(), $id, DOKU_CHANGE_TYPE_EDIT); 378 } else { 379 addMediaLogEntry(time(), $id, DOKU_CHANGE_TYPE_CREATE); 380 } 381 return $id; 382 }else{ 383 return array($lang['uploadfail'],-1); 384 } 385} 386 387/** 388 * Moves the current version of media file to the media_attic 389 * directory 390 * 391 * @author Kate Arzamastseva <pshns@ukr.net> 392 * @param string $id 393 * @return int - revision date 394 */ 395function media_saveOldRevision($id){ 396 global $conf; 397 $oldf = mediaFN($id); 398 if(!@file_exists($oldf)) return ''; 399 $date = filemtime($oldf); 400 $newf = mediaFN($id,$date); 401 io_makeFileDir($newf); 402 if(copy($oldf, $newf)) { 403 // Set the correct permission here. 404 // Always chmod media because they may be saved with different permissions than expected from the php umask. 405 // (Should normally chmod to $conf['fperm'] only if $conf['fperm'] is set.) 406 chmod($newf, $conf['fmode']); 407 } 408 return $date; 409} 410 411/** 412 * This function checks if the uploaded content is really what the 413 * mimetype says it is. We also do spam checking for text types here. 414 * 415 * We need to do this stuff because we can not rely on the browser 416 * to do this check correctly. Yes, IE is broken as usual. 417 * 418 * @author Andreas Gohr <andi@splitbrain.org> 419 * @link http://www.splitbrain.org/blog/2007-02/12-internet_explorer_facilitates_cross_site_scripting 420 * @fixme check all 26 magic IE filetypes here? 421 */ 422function media_contentcheck($file,$mime){ 423 global $conf; 424 if($conf['iexssprotect']){ 425 $fh = @fopen($file, 'rb'); 426 if($fh){ 427 $bytes = fread($fh, 256); 428 fclose($fh); 429 if(preg_match('/<(script|a|img|html|body|iframe)[\s>]/i',$bytes)){ 430 return -3; 431 } 432 } 433 } 434 if(substr($mime,0,6) == 'image/'){ 435 $info = @getimagesize($file); 436 if($mime == 'image/gif' && $info[2] != 1){ 437 return -1; 438 }elseif($mime == 'image/jpeg' && $info[2] != 2){ 439 return -1; 440 }elseif($mime == 'image/png' && $info[2] != 3){ 441 return -1; 442 } 443 # fixme maybe check other images types as well 444 }elseif(substr($mime,0,5) == 'text/'){ 445 global $TEXT; 446 $TEXT = io_readFile($file); 447 if(checkwordblock()){ 448 return -2; 449 } 450 } 451 return 0; 452} 453 454/** 455 * Send a notify mail on uploads 456 * 457 * @author Andreas Gohr <andi@splitbrain.org> 458 */ 459function media_notify($id,$file,$mime){ 460 global $lang; 461 global $conf; 462 global $INFO; 463 if(empty($conf['notify'])) return; //notify enabled? 464 465 $ip = clientIP(); 466 467 $text = rawLocale('uploadmail'); 468 $text = str_replace('@DATE@',dformat(),$text); 469 $text = str_replace('@BROWSER@',$_SERVER['HTTP_USER_AGENT'],$text); 470 $text = str_replace('@IPADDRESS@',$ip,$text); 471 $text = str_replace('@HOSTNAME@',gethostsbyaddrs($ip),$text); 472 $text = str_replace('@DOKUWIKIURL@',DOKU_URL,$text); 473 $text = str_replace('@USER@',$_SERVER['REMOTE_USER'],$text); 474 $text = str_replace('@MIME@',$mime,$text); 475 $text = str_replace('@MEDIA@',ml($id,'',true,'&',true),$text); 476 $text = str_replace('@SIZE@',filesize_h(filesize($file)),$text); 477 478 $subject = '['.$conf['title'].'] '.$lang['mail_upload'].' '.$id; 479 480 mail_send($conf['notify'],$subject,$text,$conf['mailfrom']); 481} 482 483/** 484 * List all files in a given Media namespace 485 */ 486function media_filelist($ns,$auth=null,$jump='',$fullscreenview=false){ 487 global $conf; 488 global $lang; 489 $ns = cleanID($ns); 490 491 // check auth our self if not given (needed for ajax calls) 492 if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 493 494 if (!$fullscreenview) echo '<h1 id="media__ns">:'.hsc($ns).'</h1>'.NL; 495 496 if($auth < AUTH_READ){ 497 // FIXME: print permission warning here instead? 498 echo '<div class="nothing">'.$lang['nothingfound'].'</div>'.NL; 499 }else{ 500 if (!$fullscreenview) media_uploadform($ns, $auth); 501 502 $dir = utf8_encodeFN(str_replace(':','/',$ns)); 503 $data = array(); 504 search($data,$conf['mediadir'],'search_media', 505 array('showmsg'=>true,'depth'=>1),$dir); 506 507 if(!count($data)){ 508 echo '<div class="nothing">'.$lang['nothingfound'].'</div>'.NL; 509 }else foreach($data as $item){ 510 if (!$fullscreenview) media_printfile($item,$auth,$jump); 511 else if ($fullscreenview == 'thumbs') media_printfile_thumbs($item,$auth,$jump); 512 } 513 } 514 if (!$fullscreenview) media_searchform($ns); 515} 516 517/** 518 * Prints tabs for files list actions 519 * 520 * @author Kate Arzamastseva <pshns@ukr.net> 521 * @param string $selected - opened tab 522 */ 523function media_tabs_files($selected=false){ 524 global $lang; 525 526 echo '<div class="mediamanager-tabs" id="id-mediamanager-tabs">'; 527 $tab = '<a href="'.media_managerURL(array('tab_files' => 'files')). 528 '" rel=".mediamanager-tab-files"'; 529 if (!empty($selected) && $selected == 'files') $class = 'files selected'; 530 else $class = 'files'; 531 $tab .= ' class="'.$class.'" >'.$lang['mediaselect'].'</a>'; 532 echo $tab; 533 534 $tab = '<a href="'.media_managerURL(array('tab_files' => 'upload')). 535 '" rel=".mediamanager-tab-upload"'; 536 if (!empty($selected) && $selected == 'upload') $class = 'upload selected'; 537 else $class = 'upload'; 538 $tab .= ' class="'.$class.'" >'.$lang['media_uploadtab'].'</a>'; 539 echo $tab; 540 541 $tab = '<a href="'.media_managerURL(array('tab_files' => 'search')). 542 '" rel=".mediamanager-tab-search"'; 543 if (!empty($selected) && $selected == 'search') $class = 'search selected'; 544 else $class = 'search'; 545 $tab .= ' class="'.$class.'" >'.$lang['media_searchtab'].'</a>'; 546 echo $tab; 547 548 echo '<div class="mediamanager-clear"> </div>'; 549 echo '</div>'; 550} 551 552/** 553 * Prints tabs for files details actions 554 * 555 * @author Kate Arzamastseva <pshns@ukr.net> 556 * @param string $selected - opened tab 557 */ 558function media_tabs_details($selected=false){ 559 global $lang; 560 561 echo '<div class="mediamanager-tabs" id="id-mediamanager-tabs-detail">'; 562 $tab = '<a href="'.media_managerURL(array('tab_details' => 'view')). 563 '" rel=".mediamanager-tab-view"'; 564 if (!empty($selected) && $selected == 'view') $class = 'view selected'; 565 else $class = 'view'; 566 $tab .= ' class="'.$class.'" >'.$lang['media_viewtab'].'</a>'; 567 echo $tab; 568 569 $tab = '<a href="'.media_managerURL(array('tab_details' => 'edit')). 570 '" rel=".mediamanager-tab-edit"'; 571 if (!empty($selected) && $selected == 'edit') $class = 'edit selected'; 572 else $class = 'edit'; 573 $tab .= ' class="'.$class.'" >'.$lang['media_edittab'].'</a>'; 574 echo $tab; 575 576 $tab = '<a href="'.media_managerURL(array('tab_details' => 'history')). 577 '" rel=".mediamanager-tab-history"'; 578 if (!empty($selected) && $selected == 'history') $class = 'history selected'; 579 else $class = 'history'; 580 $tab .= ' class="'.$class.'" >'.$lang['media_historytab'].'</a>'; 581 echo $tab; 582 583 echo '<div class="mediamanager-clear"> </div>'; 584 echo '</div>'; 585} 586 587/** 588 * Prints options for the tab that displays a list of all files 589 * 590 * @author Kate Arzamastseva <pshns@ukr.net> 591 */ 592function media_tab_files_options(){ 593 global $lang; 594 595 echo '<div class="background-container">'; 596 echo '<div id="id-mediamanager-tabs-files" style="display: inline;">'; 597 echo '<a href="'.media_managerURL(array('view' => 'thumbs')).'" 598 rel=".mediamanager-files-thumbnails-tab" class="mediamanager-link-thumbnails">'. 599 $lang['media_thumbsview'].'</a>'; 600 echo '<a href="'.media_managerURL(array('view' => 'list')).'" 601 rel=".mediamanager-files-list-tab" class="mediamanager-link-list" 602 title="View as list">'.$lang['media_listview'].'</a>'; 603 604 echo '</div>'; 605 echo '<div class="mediamanager-block-sort">'.$lang['media_sort']; 606 //select 607 echo '</div>'; 608 echo '<div class="mediamanager-clear"> </div>'; 609 echo '</div>'; 610} 611 612/** 613 * Prints tab that displays a list of all files 614 * 615 * @author Kate Arzamastseva <pshns@ukr.net> 616 */ 617function media_tab_files($ns,$auth=null,$jump='') { 618 global $lang; 619 if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 620 621 echo '<div class="mediamanager-tab-files">'; 622 media_tab_files_options(); 623 echo '<div class="scroll-container">'; 624 625 $view = $_REQUEST['view']; 626 if($auth < AUTH_READ){ 627 echo '<div class="nothing">'.$lang['nothingfound'].'</div>'.NL; 628 }else{ 629 if ($view == 'list') { 630 echo '<div class="mediamanager-files-list-tab">'; 631 echo '</div>'; 632 } else { 633 echo '<div class="mediamanager-files-thumbnails-tab">'; 634 media_filelist($ns,$auth,$jump,'thumbs'); 635 echo '</div>'; 636 } 637 } 638 echo '</div>'; 639 echo '</div>'; 640} 641 642/** 643 * Prints tab that displays uploading form 644 * 645 * @author Kate Arzamastseva <pshns@ukr.net> 646 */ 647function media_tab_upload($ns,$auth=null,$jump='') { 648 global $lang; 649 if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 650 651 echo '<div class="mediamanager-tab-upload"">'; 652 echo '<div class="background-container">'; 653 echo $lang['mediaupload']; 654 echo '</div>'; 655 656 echo '<div class="scroll-container">'; 657 media_uploadform($ns, $auth, true); 658 echo '</div>'; 659 echo '</div>'; 660} 661 662/** 663 * Prints tab that displays search form 664 * 665 * @author Kate Arzamastseva <pshns@ukr.net> 666 */ 667function media_tab_search($ns,$auth=null) { 668 global $lang; 669 670 $do = $_REQUEST['mediado']; 671 $query = $_REQUEST['q']; 672 if (!$query) $query = ''; 673 674 echo '<div class="mediamanager-tab-search">'; 675 echo '<div class="background-container">'; 676 echo $lang['media_search']; 677 echo'</div>'; 678 679 echo '<div class="scroll-container">'; 680 media_searchform($ns, $query, true); 681 682 if($do == 'searchlist'){ 683 media_searchlist($query,$ns,$auth,true); 684 } 685 echo '</div>'; 686 echo '</div>'; 687} 688 689/** 690 * Prints tab that displays mediafile details 691 * 692 * @author Kate Arzamastseva <pshns@ukr.net> 693 */ 694function media_tab_view($image, $ns, $auth=null) { 695 global $lang, $conf; 696 if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 697 698 echo '<div class="mediamanager-tab-detail-view">'; 699 echo '<div class="background-container">'; 700 echo $lang['media_view']; 701 echo '</div>'; 702 703 echo '<div class="scroll-container">'; 704 if ($auth >= AUTH_READ && $image) { 705 $info = new JpegMeta(mediaFN($image)); 706 $w = (int) $info->getField('File.Width'); 707 $src = ml($image); 708 echo '<img src="'.$src.'" alt="" width="99%" style="max-width: '.$w.'px;" />'; 709 } 710 echo '</div>'; 711 echo '</div>'; 712} 713 714/** 715 * Prints tab that displays form for editing mediafile metadata 716 * 717 * @author Kate Arzamastseva <pshns@ukr.net> 718 */ 719function media_tab_edit($image, $ns, $auth=null) { 720 global $lang; 721 if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 722 723 echo '<div class="mediamanager-tab-detail-edit">'; 724 echo '<div class="background-container">'; 725 echo $lang['media_edit']; 726 echo '</div>'; 727 728 echo '<div class="scroll-container">'; 729 if ($image) media_metaform($image,$auth,true); 730 echo '</div>'; 731 echo '</div>'; 732} 733 734/** 735 * Prints tab that displays mediafile revisions 736 * 737 * @author Kate Arzamastseva <pshns@ukr.net> 738 */ 739function media_tab_history($image, $ns, $auth=null) { 740 global $lang; 741 if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 742 743 echo '<div class="mediamanager-tab-detail-history">'; 744 echo '<div class="background-container">'; 745 echo $lang['media_history']; 746 echo '</div>'; 747 748 echo '<div class="scroll-container">'; 749 $first = isset($_REQUEST['first']) ? intval($_REQUEST['first']) : 0; 750 html_revisions($first, $image); 751 echo '</div>'; 752 echo '</div>'; 753} 754 755/** 756 * List all files found by the search request 757 * 758 * @author Tobias Sarnowski <sarnowski@cosmocode.de> 759 * @author Andreas Gohr <gohr@cosmocode.de> 760 * @author Kate Arzamastseva <pshns@ukr.net> 761 * @triggers MEDIA_SEARCH 762 */ 763function media_searchlist($query,$ns,$auth=null,$fullscreen=false){ 764 global $conf; 765 global $lang; 766 767 $ns = cleanID($ns); 768 769 if ($query) { 770 $evdata = array( 771 'ns' => $ns, 772 'data' => array(), 773 'query' => $query 774 ); 775 $evt = new Doku_Event('MEDIA_SEARCH', $evdata); 776 if ($evt->advise_before()) { 777 $dir = utf8_encodeFN(str_replace(':','/',$evdata['ns'])); 778 $pattern = '/'.preg_quote($evdata['query'],'/').'/i'; 779 search($evdata['data'], 780 $conf['mediadir'], 781 'search_media', 782 array('showmsg'=>false,'pattern'=>$pattern), 783 $dir); 784 } 785 $evt->advise_after(); 786 unset($evt); 787 } 788 789 if (!$fullscreen) { 790 echo '<h1 id="media__ns">'.sprintf($lang['searchmedia_in'],hsc($ns).':*').'</h1>'.NL; 791 media_searchform($ns,$query); 792 } 793 794 if(!count($evdata['data'])){ 795 echo '<div class="nothing">'.$lang['nothingfound'].'</div>'.NL; 796 }else foreach($evdata['data'] as $item){ 797 if (!$fullscreen) media_printfile($item,$item['perm'],'',true); 798 else media_printfile_thumbs($item,$item['perm'],'',true); 799 } 800} 801 802/** 803 * Print action links for a file depending on filetype 804 * and available permissions 805 */ 806function media_fileactions($item,$auth,$fullscreen=false){ 807 global $lang; 808 809 // view button 810 $link = ml($item['id'],'',true); 811 echo ' <a href="'.$link.'" target="_blank"><img src="'.DOKU_BASE.'lib/images/magnifier.png" '. 812 'alt="'.$lang['mediaview'].'" title="'.$lang['mediaview'].'" class="btn" /></a>'; 813 814 // no further actions if not writable 815 if(!$item['writable']) return; 816 817 // delete button 818 if($auth >= AUTH_DELETE){ 819 if (!$fullscreen) $link = DOKU_BASE.'lib/exe/mediamanager.php?delete='.rawurlencode($item['id']). 820 '&sectok='.getSecurityToken(); 821 else $link = media_managerURL(array('delete' => $item['id'], 822 'sectok' => getSecurityToken())); 823 echo ' <a href="'.$link.'" class="btn_media_delete" title="'.$item['id'].'">'. 824 '<img src="'.DOKU_BASE.'lib/images/trash.png" alt="'.$lang['btn_delete'].'" '. 825 'title="'.$lang['btn_delete'].'" class="btn" /></a>'; 826 } 827 828 // edit button 829 if($auth >= AUTH_UPLOAD && $item['isimg'] && $item['meta']->getField('File.Mime') == 'image/jpeg'){ 830 if (!$fullscreen) $link = DOKU_BASE.'lib/exe/mediamanager.php?edit='.rawurlencode($item['id']); 831 else $link = media_managerURL(array('edit' => $item['id'])); 832 echo ' <a href="'.$link.'">'. 833 '<img src="'.DOKU_BASE.'lib/images/pencil.png" alt="'.$lang['metaedit'].'" '. 834 'title="'.$lang['metaedit'].'" class="btn" /></a>'; 835 } 836 837} 838 839/** 840 * Formats and prints one file in the list 841 */ 842function media_printfile($item,$auth,$jump,$display_namespace=false){ 843 global $lang; 844 global $conf; 845 846 // Prepare zebra coloring 847 // I always wanted to use this variable name :-D 848 static $twibble = 1; 849 $twibble *= -1; 850 $zebra = ($twibble == -1) ? 'odd' : 'even'; 851 852 // Automatically jump to recent action 853 if($jump == $item['id']) { 854 $jump = ' id="scroll__here" '; 855 }else{ 856 $jump = ''; 857 } 858 859 // Prepare fileicons 860 list($ext,$mime,$dl) = mimetype($item['file'],false); 861 $class = preg_replace('/[^_\-a-z0-9]+/i','_',$ext); 862 $class = 'select mediafile mf_'.$class; 863 864 // Prepare filename 865 $file = utf8_decodeFN($item['file']); 866 867 // Prepare info 868 $info = ''; 869 if($item['isimg']){ 870 $info .= (int) $item['meta']->getField('File.Width'); 871 $info .= '×'; 872 $info .= (int) $item['meta']->getField('File.Height'); 873 $info .= ' '; 874 } 875 $info .= '<i>'.dformat($item['mtime']).'</i>'; 876 $info .= ' '; 877 $info .= filesize_h($item['size']); 878 879 // output 880 echo '<div class="'.$zebra.'"'.$jump.'>'.NL; 881 if (!$display_namespace) { 882 echo '<a name="h_:'.$item['id'].'" class="'.$class.'">'.hsc($file).'</a> '; 883 } else { 884 echo '<a name="h_:'.$item['id'].'" class="'.$class.'">'.hsc($item['id']).'</a><br/>'; 885 } 886 echo '<span class="info">('.$info.')</span>'.NL; 887 media_fileactions($item,$auth); 888 echo '<div class="example" id="ex_'.str_replace(':','_',$item['id']).'">'; 889 echo $lang['mediausage'].' <code>{{:'.$item['id'].'}}</code>'; 890 echo '</div>'; 891 if($item['isimg']) media_printimgdetail($item); 892 echo '<div class="clearer"></div>'.NL; 893 echo '</div>'.NL; 894} 895 896/** 897 * Formats and prints one file in the list in the thumbnails view 898 * 899 * @author Kate Arzamastseva <pshns@ukr.net> 900 */ 901function media_printfile_thumbs($item,$auth,$jump){ 902 global $lang; 903 global $conf; 904 905 // Prepare filename 906 $file = utf8_decodeFN($item['file']); 907 908 // Prepare info 909 $info = ''; 910 if($item['isimg']){ 911 $info .= (int) $item['meta']->getField('File.Width'); 912 $info .= '×'; 913 $info .= (int) $item['meta']->getField('File.Height'); 914 $info .= '<br/>'; 915 } 916 $info .= '<i>'.dformat($item['mtime']).'</i><br/>'; 917 $info .= filesize_h($item['size']); 918 919 // output 920 echo '<div class="float-image" >'; 921 if($item['isimg']) media_printimgdetail($item, true); 922 echo '<br/><a href="'.media_managerURL(array('image' => hsc($item['id']))).'" name= 923 "h_:'.$item['id'].'" >'.hsc($file).'</a><br/>'; 924 echo '<span>'.$info.'</span><br/>'; 925 media_fileactions($item,$auth,true); 926 echo '</div>'.NL; 927} 928 929/** 930 * Prints a thumbnail and metainfos 931 */ 932function media_printimgdetail($item, $fullscreen=false){ 933 // prepare thumbnail 934 if (!$fullscreen) $size = 120; 935 else $size = 90; 936 $w = (int) $item['meta']->getField('File.Width'); 937 $h = (int) $item['meta']->getField('File.Height'); 938 if($w>$size || $h>$size){ 939 $ratio = $item['meta']->getResizeRatio($size); 940 $w = floor($w * $ratio); 941 $h = floor($h * $ratio); 942 } 943 $src = ml($item['id'],array('w'=>$w,'h'=>$h)); 944 $p = array(); 945 $p['width'] = $w; 946 $p['height'] = $h; 947 $p['alt'] = $item['id']; 948 $p['class'] = 'thumb'; 949 $att = buildAttributes($p); 950 951 // output 952 if ($fullscreen) { 953 echo '<a name="d_:'.$item['id'].'" >'; 954 echo '<img src="'.$src.'" '.$att.' />'; 955 echo '</a>'; 956 return 1; 957 } 958 959 echo '<div class="detail">'; 960 echo '<div class="thumb">'; 961 echo '<a name="d_:'.$item['id'].'" class="select">'; 962 echo '<img src="'.$src.'" '.$att.' />'; 963 echo '</a>'; 964 echo '</div>'; 965 966 // read EXIF/IPTC data 967 $t = $item['meta']->getField(array('IPTC.Headline','xmp.dc:title')); 968 $d = $item['meta']->getField(array('IPTC.Caption','EXIF.UserComment', 969 'EXIF.TIFFImageDescription', 970 'EXIF.TIFFUserComment')); 971 if(utf8_strlen($d) > 250) $d = utf8_substr($d,0,250).'...'; 972 $k = $item['meta']->getField(array('IPTC.Keywords','IPTC.Category','xmp.dc:subject')); 973 974 // print EXIF/IPTC data 975 if($t || $d || $k ){ 976 echo '<p>'; 977 if($t) echo '<strong>'.htmlspecialchars($t).'</strong><br />'; 978 if($d) echo htmlspecialchars($d).'<br />'; 979 if($t) echo '<em>'.htmlspecialchars($k).'</em>'; 980 echo '</p>'; 981 } 982 echo '</div>'; 983} 984 985/** 986 * Build link based on the current, adding/rewriting 987 * parameters 988 * 989 * @author Kate Arzamastseva <pshns@ukr.net> 990 * @param array $params 991 * @param string $amp - separator 992 * @return string - link 993 */ 994function media_managerURL($params=false, $amp='&') { 995 global $conf; 996 global $ID; 997 998 $url = $_SERVER['REQUEST_URI']; 999 1000 $urlArray = explode('?', $url, 2); 1001 $gets = @$urlArray[1]; 1002 parse_str($gets, $gets); 1003 1004 if ($gets['edit']) $gets['image'] = $gets['edit']; 1005 unset($gets['edit']); 1006 unset($gets['sectok']); 1007 unset($gets['delete']); 1008 1009 if ($params) { 1010 foreach ($params as $k => $v) { 1011 $gets[$k] = $v; 1012 } 1013 } 1014 unset($gets['id']); 1015 1016 return wl($ID,$gets,false,$amp); 1017} 1018 1019/** 1020 * Print the media upload form if permissions are correct 1021 * 1022 * @author Andreas Gohr <andi@splitbrain.org> 1023 * @author Kate Arzamastseva <pshns@ukr.net> 1024 */ 1025function media_uploadform($ns, $auth, $fullscreen = false){ 1026 global $lang; 1027 1028 if($auth < AUTH_UPLOAD) return; //fixme print info on missing permissions? 1029 1030 // The default HTML upload form 1031 $params = array('id' => 'dw__upload', 1032 'enctype' => 'multipart/form-data'); 1033 if (!$fullscreen) $params['action'] = DOKU_BASE.'lib/exe/mediamanager.php'; 1034 else $params['action'] = media_managerURL(array('tab_files' => 'files')); 1035 1036 $form = new Doku_Form($params); 1037 if (!$fullscreen) $form->addElement('<div class="upload">' . $lang['mediaupload'] . '</div>'); 1038 $form->addElement(formSecurityToken()); 1039 $form->addHidden('ns', hsc($ns)); 1040 $form->addElement(form_makeOpenTag('p')); 1041 $form->addElement(form_makeFileField('upload', $lang['txt_upload'].':', 'upload__file')); 1042 $form->addElement(form_makeCloseTag('p')); 1043 $form->addElement(form_makeOpenTag('p')); 1044 $form->addElement(form_makeTextField('id', '', $lang['txt_filename'].':', 'upload__name')); 1045 $form->addElement(form_makeButton('submit', '', $lang['btn_upload'])); 1046 $form->addElement(form_makeCloseTag('p')); 1047 1048 if($auth >= AUTH_DELETE){ 1049 $form->addElement(form_makeOpenTag('p')); 1050 $form->addElement(form_makeCheckboxField('ow', 1, $lang['txt_overwrt'], 'dw__ow', 'check')); 1051 $form->addElement(form_makeCloseTag('p')); 1052 } 1053 html_form('upload', $form); 1054 1055 // prepare flashvars for multiupload 1056 $opt = array( 1057 'L_gridname' => $lang['mu_gridname'] , 1058 'L_gridsize' => $lang['mu_gridsize'] , 1059 'L_gridstat' => $lang['mu_gridstat'] , 1060 'L_namespace' => $lang['mu_namespace'] , 1061 'L_overwrite' => $lang['txt_overwrt'], 1062 'L_browse' => $lang['mu_browse'], 1063 'L_upload' => $lang['btn_upload'], 1064 'L_toobig' => $lang['mu_toobig'], 1065 'L_ready' => $lang['mu_ready'], 1066 'L_done' => $lang['mu_done'], 1067 'L_fail' => $lang['mu_fail'], 1068 'L_authfail' => $lang['mu_authfail'], 1069 'L_progress' => $lang['mu_progress'], 1070 'L_filetypes' => $lang['mu_filetypes'], 1071 'L_info' => $lang['mu_info'], 1072 'L_lasterr' => $lang['mu_lasterr'], 1073 1074 'O_ns' => ":$ns", 1075 'O_backend' => 'mediamanager.php?'.session_name().'='.session_id(), 1076 'O_maxsize' => php_to_byte(ini_get('upload_max_filesize')), 1077 'O_extensions'=> join('|',array_keys(getMimeTypes())), 1078 'O_overwrite' => ($auth >= AUTH_DELETE), 1079 'O_sectok' => getSecurityToken(), 1080 'O_authtok' => auth_createToken(), 1081 ); 1082 $var = buildURLparams($opt); 1083 // output the flash uploader 1084 ?> 1085 <div id="dw__flashupload" style="display:none"> 1086 <div class="upload"><?php echo $lang['mu_intro']?></div> 1087 <?php echo html_flashobject('multipleUpload.swf','500','190',null,$opt); ?> 1088 </div> 1089 <?php 1090} 1091 1092/** 1093 * Print the search field form 1094 * 1095 * @author Tobias Sarnowski <sarnowski@cosmocode.de> 1096 * @author Kate Arzamastseva <pshns@ukr.net> 1097 */ 1098function media_searchform($ns,$query='',$fullscreen=false){ 1099 global $lang; 1100 1101 // The default HTML search form 1102 $params = array('id' => 'dw__mediasearch'); 1103 if (!$fullscreen) $params['action'] = DOKU_BASE.'lib/exe/mediamanager.php'; 1104 else $params['action'] = media_managerURL(); 1105 $form = new Doku_Form($params); 1106 if (!$fullscreen) $form->addElement('<div class="upload">' . $lang['mediasearch'] . '</div>'); 1107 $form->addElement(formSecurityToken()); 1108 $form->addHidden('ns', $ns); 1109 if (!$fullscreen) $form->addHidden('do', 'searchlist'); 1110 else $form->addHidden('mediado', 'searchlist'); 1111 $form->addElement(form_makeOpenTag('p')); 1112 $form->addElement(form_makeTextField('q', $query,$lang['searchmedia'],'','',array('title'=>sprintf($lang['searchmedia_in'],hsc($ns).':*')))); 1113 $form->addElement(form_makeButton('submit', '', $lang['btn_search'])); 1114 $form->addElement(form_makeCloseTag('p')); 1115 html_form('searchmedia', $form); 1116} 1117 1118/** 1119 * Build a tree outline of available media namespaces 1120 * 1121 * @author Andreas Gohr <andi@splitbrain.org> 1122 */ 1123function media_nstree($ns){ 1124 global $conf; 1125 global $lang; 1126 1127 // currently selected namespace 1128 $ns = cleanID($ns); 1129 if(empty($ns)){ 1130 global $ID; 1131 $ns = dirname(str_replace(':','/',$ID)); 1132 if($ns == '.') $ns =''; 1133 } 1134 $ns = utf8_encodeFN(str_replace(':','/',$ns)); 1135 1136 $data = array(); 1137 search($data,$conf['mediadir'],'search_index',array('ns' => $ns, 'nofiles' => true)); 1138 1139 // wrap a list with the root level around the other namespaces 1140 $item = array( 'level' => 0, 'id' => '', 1141 'open' =>'true', 'label' => '['.$lang['mediaroot'].']'); 1142 1143 echo '<ul class="idx">'; 1144 echo media_nstree_li($item); 1145 echo media_nstree_item($item); 1146 echo html_buildlist($data,'idx','media_nstree_item','media_nstree_li'); 1147 echo '</li>'; 1148 echo '</ul>'; 1149} 1150 1151/** 1152 * Userfunction for html_buildlist 1153 * 1154 * Prints a media namespace tree item 1155 * 1156 * @author Andreas Gohr <andi@splitbrain.org> 1157 */ 1158function media_nstree_item($item){ 1159 $pos = strrpos($item['id'], ':'); 1160 $label = substr($item['id'], $pos > 0 ? $pos + 1 : 0); 1161 if(!$item['label']) $item['label'] = $label; 1162 1163 $ret = ''; 1164 if (!($_REQUEST['do'] == 'media')) 1165 $ret .= '<a href="'.DOKU_BASE.'lib/exe/mediamanager.php?ns='.idfilter($item['id']).'" class="idx_dir">'; 1166 else $ret .= '<a href="'.media_managerURL(array('ns' => idfilter($item['id']))).'" class="idx_dir">'; 1167 $ret .= $item['label']; 1168 $ret .= '</a>'; 1169 return $ret; 1170} 1171 1172/** 1173 * Userfunction for html_buildlist 1174 * 1175 * Prints a media namespace tree item opener 1176 * 1177 * @author Andreas Gohr <andi@splitbrain.org> 1178 */ 1179function media_nstree_li($item){ 1180 $class='media level'.$item['level']; 1181 if($item['open']){ 1182 $class .= ' open'; 1183 $img = DOKU_BASE.'lib/images/minus.gif'; 1184 $alt = '−'; 1185 }else{ 1186 $class .= ' closed'; 1187 $img = DOKU_BASE.'lib/images/plus.gif'; 1188 $alt = '+'; 1189 } 1190 // TODO: only deliver an image if it actually has a subtree... 1191 return '<li class="'.$class.'">'. 1192 '<img src="'.$img.'" alt="'.$alt.'" />'; 1193} 1194 1195/** 1196 * Resizes the given image to the given size 1197 * 1198 * @author Andreas Gohr <andi@splitbrain.org> 1199 */ 1200function media_resize_image($file, $ext, $w, $h=0){ 1201 global $conf; 1202 1203 $info = @getimagesize($file); //get original size 1204 if($info == false) return $file; // that's no image - it's a spaceship! 1205 1206 if(!$h) $h = round(($w * $info[1]) / $info[0]); 1207 1208 // we wont scale up to infinity 1209 if($w > 2000 || $h > 2000) return $file; 1210 1211 //cache 1212 $local = getCacheName($file,'.media.'.$w.'x'.$h.'.'.$ext); 1213 $mtime = @filemtime($local); // 0 if not exists 1214 1215 if( $mtime > filemtime($file) || 1216 media_resize_imageIM($ext,$file,$info[0],$info[1],$local,$w,$h) || 1217 media_resize_imageGD($ext,$file,$info[0],$info[1],$local,$w,$h) ){ 1218 if($conf['fperm']) chmod($local, $conf['fperm']); 1219 return $local; 1220 } 1221 //still here? resizing failed 1222 return $file; 1223} 1224 1225/** 1226 * Crops the given image to the wanted ratio, then calls media_resize_image to scale it 1227 * to the wanted size 1228 * 1229 * Crops are centered horizontally but prefer the upper third of an vertical 1230 * image because most pics are more interesting in that area (rule of thirds) 1231 * 1232 * @author Andreas Gohr <andi@splitbrain.org> 1233 */ 1234function media_crop_image($file, $ext, $w, $h=0){ 1235 global $conf; 1236 1237 if(!$h) $h = $w; 1238 $info = @getimagesize($file); //get original size 1239 if($info == false) return $file; // that's no image - it's a spaceship! 1240 1241 // calculate crop size 1242 $fr = $info[0]/$info[1]; 1243 $tr = $w/$h; 1244 if($tr >= 1){ 1245 if($tr > $fr){ 1246 $cw = $info[0]; 1247 $ch = (int) $info[0]/$tr; 1248 }else{ 1249 $cw = (int) $info[1]*$tr; 1250 $ch = $info[1]; 1251 } 1252 }else{ 1253 if($tr < $fr){ 1254 $cw = (int) $info[1]*$tr; 1255 $ch = $info[1]; 1256 }else{ 1257 $cw = $info[0]; 1258 $ch = (int) $info[0]/$tr; 1259 } 1260 } 1261 // calculate crop offset 1262 $cx = (int) ($info[0]-$cw)/2; 1263 $cy = (int) ($info[1]-$ch)/3; 1264 1265 //cache 1266 $local = getCacheName($file,'.media.'.$cw.'x'.$ch.'.crop.'.$ext); 1267 $mtime = @filemtime($local); // 0 if not exists 1268 1269 if( $mtime > filemtime($file) || 1270 media_crop_imageIM($ext,$file,$info[0],$info[1],$local,$cw,$ch,$cx,$cy) || 1271 media_resize_imageGD($ext,$file,$cw,$ch,$local,$cw,$ch,$cx,$cy) ){ 1272 if($conf['fperm']) chmod($local, $conf['fperm']); 1273 return media_resize_image($local,$ext, $w, $h); 1274 } 1275 1276 //still here? cropping failed 1277 return media_resize_image($file,$ext, $w, $h); 1278} 1279 1280/** 1281 * Download a remote file and return local filename 1282 * 1283 * returns false if download fails. Uses cached file if available and 1284 * wanted 1285 * 1286 * @author Andreas Gohr <andi@splitbrain.org> 1287 * @author Pavel Vitis <Pavel.Vitis@seznam.cz> 1288 */ 1289function media_get_from_URL($url,$ext,$cache){ 1290 global $conf; 1291 1292 // if no cache or fetchsize just redirect 1293 if ($cache==0) return false; 1294 if (!$conf['fetchsize']) return false; 1295 1296 $local = getCacheName(strtolower($url),".media.$ext"); 1297 $mtime = @filemtime($local); // 0 if not exists 1298 1299 //decide if download needed: 1300 if( ($mtime == 0) || // cache does not exist 1301 ($cache != -1 && $mtime < time()-$cache) // 'recache' and cache has expired 1302 ){ 1303 if(media_image_download($url,$local)){ 1304 return $local; 1305 }else{ 1306 return false; 1307 } 1308 } 1309 1310 //if cache exists use it else 1311 if($mtime) return $local; 1312 1313 //else return false 1314 return false; 1315} 1316 1317/** 1318 * Download image files 1319 * 1320 * @author Andreas Gohr <andi@splitbrain.org> 1321 */ 1322function media_image_download($url,$file){ 1323 global $conf; 1324 $http = new DokuHTTPClient(); 1325 $http->max_bodysize = $conf['fetchsize']; 1326 $http->timeout = 25; //max. 25 sec 1327 $http->header_regexp = '!\r\nContent-Type: image/(jpe?g|gif|png)!i'; 1328 1329 $data = $http->get($url); 1330 if(!$data) return false; 1331 1332 $fileexists = @file_exists($file); 1333 $fp = @fopen($file,"w"); 1334 if(!$fp) return false; 1335 fwrite($fp,$data); 1336 fclose($fp); 1337 if(!$fileexists and $conf['fperm']) chmod($file, $conf['fperm']); 1338 1339 // check if it is really an image 1340 $info = @getimagesize($file); 1341 if(!$info){ 1342 @unlink($file); 1343 return false; 1344 } 1345 1346 return true; 1347} 1348 1349/** 1350 * resize images using external ImageMagick convert program 1351 * 1352 * @author Pavel Vitis <Pavel.Vitis@seznam.cz> 1353 * @author Andreas Gohr <andi@splitbrain.org> 1354 */ 1355function media_resize_imageIM($ext,$from,$from_w,$from_h,$to,$to_w,$to_h){ 1356 global $conf; 1357 1358 // check if convert is configured 1359 if(!$conf['im_convert']) return false; 1360 1361 // prepare command 1362 $cmd = $conf['im_convert']; 1363 $cmd .= ' -resize '.$to_w.'x'.$to_h.'!'; 1364 if ($ext == 'jpg' || $ext == 'jpeg') { 1365 $cmd .= ' -quality '.$conf['jpg_quality']; 1366 } 1367 $cmd .= " $from $to"; 1368 1369 @exec($cmd,$out,$retval); 1370 if ($retval == 0) return true; 1371 return false; 1372} 1373 1374/** 1375 * crop images using external ImageMagick convert program 1376 * 1377 * @author Andreas Gohr <andi@splitbrain.org> 1378 */ 1379function media_crop_imageIM($ext,$from,$from_w,$from_h,$to,$to_w,$to_h,$ofs_x,$ofs_y){ 1380 global $conf; 1381 1382 // check if convert is configured 1383 if(!$conf['im_convert']) return false; 1384 1385 // prepare command 1386 $cmd = $conf['im_convert']; 1387 $cmd .= ' -crop '.$to_w.'x'.$to_h.'+'.$ofs_x.'+'.$ofs_y; 1388 if ($ext == 'jpg' || $ext == 'jpeg') { 1389 $cmd .= ' -quality '.$conf['jpg_quality']; 1390 } 1391 $cmd .= " $from $to"; 1392 1393 @exec($cmd,$out,$retval); 1394 if ($retval == 0) return true; 1395 return false; 1396} 1397 1398/** 1399 * resize or crop images using PHP's libGD support 1400 * 1401 * @author Andreas Gohr <andi@splitbrain.org> 1402 * @author Sebastian Wienecke <s_wienecke@web.de> 1403 */ 1404function media_resize_imageGD($ext,$from,$from_w,$from_h,$to,$to_w,$to_h,$ofs_x=0,$ofs_y=0){ 1405 global $conf; 1406 1407 if($conf['gdlib'] < 1) return false; //no GDlib available or wanted 1408 1409 // check available memory 1410 if(!is_mem_available(($from_w * $from_h * 4) + ($to_w * $to_h * 4))){ 1411 return false; 1412 } 1413 1414 // create an image of the given filetype 1415 if ($ext == 'jpg' || $ext == 'jpeg'){ 1416 if(!function_exists("imagecreatefromjpeg")) return false; 1417 $image = @imagecreatefromjpeg($from); 1418 }elseif($ext == 'png') { 1419 if(!function_exists("imagecreatefrompng")) return false; 1420 $image = @imagecreatefrompng($from); 1421 1422 }elseif($ext == 'gif') { 1423 if(!function_exists("imagecreatefromgif")) return false; 1424 $image = @imagecreatefromgif($from); 1425 } 1426 if(!$image) return false; 1427 1428 if(($conf['gdlib']>1) && function_exists("imagecreatetruecolor") && $ext != 'gif'){ 1429 $newimg = @imagecreatetruecolor ($to_w, $to_h); 1430 } 1431 if(!$newimg) $newimg = @imagecreate($to_w, $to_h); 1432 if(!$newimg){ 1433 imagedestroy($image); 1434 return false; 1435 } 1436 1437 //keep png alpha channel if possible 1438 if($ext == 'png' && $conf['gdlib']>1 && function_exists('imagesavealpha')){ 1439 imagealphablending($newimg, false); 1440 imagesavealpha($newimg,true); 1441 } 1442 1443 //keep gif transparent color if possible 1444 if($ext == 'gif' && function_exists('imagefill') && function_exists('imagecolorallocate')) { 1445 if(function_exists('imagecolorsforindex') && function_exists('imagecolortransparent')) { 1446 $transcolorindex = @imagecolortransparent($image); 1447 if($transcolorindex >= 0 ) { //transparent color exists 1448 $transcolor = @imagecolorsforindex($image, $transcolorindex); 1449 $transcolorindex = @imagecolorallocate($newimg, $transcolor['red'], $transcolor['green'], $transcolor['blue']); 1450 @imagefill($newimg, 0, 0, $transcolorindex); 1451 @imagecolortransparent($newimg, $transcolorindex); 1452 }else{ //filling with white 1453 $whitecolorindex = @imagecolorallocate($newimg, 255, 255, 255); 1454 @imagefill($newimg, 0, 0, $whitecolorindex); 1455 } 1456 }else{ //filling with white 1457 $whitecolorindex = @imagecolorallocate($newimg, 255, 255, 255); 1458 @imagefill($newimg, 0, 0, $whitecolorindex); 1459 } 1460 } 1461 1462 //try resampling first 1463 if(function_exists("imagecopyresampled")){ 1464 if(!@imagecopyresampled($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h)) { 1465 imagecopyresized($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h); 1466 } 1467 }else{ 1468 imagecopyresized($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h); 1469 } 1470 1471 $okay = false; 1472 if ($ext == 'jpg' || $ext == 'jpeg'){ 1473 if(!function_exists('imagejpeg')){ 1474 $okay = false; 1475 }else{ 1476 $okay = imagejpeg($newimg, $to, $conf['jpg_quality']); 1477 } 1478 }elseif($ext == 'png') { 1479 if(!function_exists('imagepng')){ 1480 $okay = false; 1481 }else{ 1482 $okay = imagepng($newimg, $to); 1483 } 1484 }elseif($ext == 'gif') { 1485 if(!function_exists('imagegif')){ 1486 $okay = false; 1487 }else{ 1488 $okay = imagegif($newimg, $to); 1489 } 1490 } 1491 1492 // destroy GD image ressources 1493 if($image) imagedestroy($image); 1494 if($newimg) imagedestroy($newimg); 1495 1496 return $okay; 1497} 1498 1499/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 1500