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 $oldRev = getRevisions($id, -1, 1, 1024, true); // from changelog 361 $oldRev = (int)(empty($oldRev)?0:$oldRev[0]); 362 if(!@file_exists(mediaFN($id, $old)) && @file_exists($fn) && $old>=$oldRev) { 363 // add old revision to the attic if missing 364 media_saveOldRevision($id); 365 } 366 367 // prepare directory 368 io_createNamespace($id, 'media'); 369 370 if($move($fn_tmp, $fn)) { 371 // Set the correct permission here. 372 // Always chmod media because they may be saved with different permissions than expected from the php umask. 373 // (Should normally chmod to $conf['fperm'] only if $conf['fperm'] is set.) 374 chmod($fn, $conf['fmode']); 375 msg($lang['uploadsucc'],1); 376 media_notify($id,$fn,$imime); 377 // add a log entry to the media changelog 378 if ($overwrite) { 379 addMediaLogEntry(time(), $id, DOKU_CHANGE_TYPE_EDIT); 380 } else { 381 addMediaLogEntry(time(), $id, DOKU_CHANGE_TYPE_CREATE); 382 } 383 return $id; 384 }else{ 385 return array($lang['uploadfail'],-1); 386 } 387} 388 389/** 390 * Moves the current version of media file to the media_attic 391 * directory 392 * 393 * @author Kate Arzamastseva <pshns@ukr.net> 394 * @param string $id 395 * @return int - revision date 396 */ 397function media_saveOldRevision($id){ 398 global $conf; 399 $oldf = mediaFN($id); 400 if(!@file_exists($oldf)) return ''; 401 $date = filemtime($oldf); 402 $newf = mediaFN($id,$date); 403 io_makeFileDir($newf); 404 if(copy($oldf, $newf)) { 405 // Set the correct permission here. 406 // Always chmod media because they may be saved with different permissions than expected from the php umask. 407 // (Should normally chmod to $conf['fperm'] only if $conf['fperm'] is set.) 408 chmod($newf, $conf['fmode']); 409 } 410 return $date; 411} 412 413/** 414 * This function checks if the uploaded content is really what the 415 * mimetype says it is. We also do spam checking for text types here. 416 * 417 * We need to do this stuff because we can not rely on the browser 418 * to do this check correctly. Yes, IE is broken as usual. 419 * 420 * @author Andreas Gohr <andi@splitbrain.org> 421 * @link http://www.splitbrain.org/blog/2007-02/12-internet_explorer_facilitates_cross_site_scripting 422 * @fixme check all 26 magic IE filetypes here? 423 */ 424function media_contentcheck($file,$mime){ 425 global $conf; 426 if($conf['iexssprotect']){ 427 $fh = @fopen($file, 'rb'); 428 if($fh){ 429 $bytes = fread($fh, 256); 430 fclose($fh); 431 if(preg_match('/<(script|a|img|html|body|iframe)[\s>]/i',$bytes)){ 432 return -3; 433 } 434 } 435 } 436 if(substr($mime,0,6) == 'image/'){ 437 $info = @getimagesize($file); 438 if($mime == 'image/gif' && $info[2] != 1){ 439 return -1; 440 }elseif($mime == 'image/jpeg' && $info[2] != 2){ 441 return -1; 442 }elseif($mime == 'image/png' && $info[2] != 3){ 443 return -1; 444 } 445 # fixme maybe check other images types as well 446 }elseif(substr($mime,0,5) == 'text/'){ 447 global $TEXT; 448 $TEXT = io_readFile($file); 449 if(checkwordblock()){ 450 return -2; 451 } 452 } 453 return 0; 454} 455 456/** 457 * Send a notify mail on uploads 458 * 459 * @author Andreas Gohr <andi@splitbrain.org> 460 */ 461function media_notify($id,$file,$mime){ 462 global $lang; 463 global $conf; 464 global $INFO; 465 if(empty($conf['notify'])) return; //notify enabled? 466 467 $ip = clientIP(); 468 469 $text = rawLocale('uploadmail'); 470 $text = str_replace('@DATE@',dformat(),$text); 471 $text = str_replace('@BROWSER@',$_SERVER['HTTP_USER_AGENT'],$text); 472 $text = str_replace('@IPADDRESS@',$ip,$text); 473 $text = str_replace('@HOSTNAME@',gethostsbyaddrs($ip),$text); 474 $text = str_replace('@DOKUWIKIURL@',DOKU_URL,$text); 475 $text = str_replace('@USER@',$_SERVER['REMOTE_USER'],$text); 476 $text = str_replace('@MIME@',$mime,$text); 477 $text = str_replace('@MEDIA@',ml($id,'',true,'&',true),$text); 478 $text = str_replace('@SIZE@',filesize_h(filesize($file)),$text); 479 480 $subject = '['.$conf['title'].'] '.$lang['mail_upload'].' '.$id; 481 482 mail_send($conf['notify'],$subject,$text,$conf['mailfrom']); 483} 484 485/** 486 * List all files in a given Media namespace 487 */ 488function media_filelist($ns,$auth=null,$jump='',$fullscreenview=false){ 489 global $conf; 490 global $lang; 491 $ns = cleanID($ns); 492 493 // check auth our self if not given (needed for ajax calls) 494 if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 495 496 if (!$fullscreenview) echo '<h1 id="media__ns">:'.hsc($ns).'</h1>'.NL; 497 498 if($auth < AUTH_READ){ 499 // FIXME: print permission warning here instead? 500 echo '<div class="nothing">'.$lang['nothingfound'].'</div>'.NL; 501 }else{ 502 if (!$fullscreenview) media_uploadform($ns, $auth); 503 504 $dir = utf8_encodeFN(str_replace(':','/',$ns)); 505 $data = array(); 506 search($data,$conf['mediadir'],'search_media', 507 array('showmsg'=>true,'depth'=>1),$dir); 508 509 if(!count($data)){ 510 echo '<div class="nothing">'.$lang['nothingfound'].'</div>'.NL; 511 }else foreach($data as $item){ 512 if (!$fullscreenview) media_printfile($item,$auth,$jump); 513 else if ($fullscreenview == 'thumbs') media_printfile_thumbs($item,$auth,$jump); 514 } 515 } 516 if (!$fullscreenview) media_searchform($ns); 517} 518 519/** 520 * Prints tabs for files list actions 521 * 522 * @author Kate Arzamastseva <pshns@ukr.net> 523 * @param string $selected - opened tab 524 */ 525function media_tabs_files($selected=false){ 526 global $lang; 527 528 echo '<div class="mediamanager-tabs" id="id-mediamanager-tabs">'; 529 $tab = '<a href="'.media_managerURL(array('tab_files' => 'files')). 530 '" rel=".mediamanager-tab-files"'; 531 if (!empty($selected) && $selected == 'files') $class = 'files selected'; 532 else $class = 'files'; 533 $tab .= ' class="'.$class.'" >Files</a>'; 534 echo $tab; 535 536 $tab = '<a href="'.media_managerURL(array('tab_files' => 'upload')). 537 '" rel=".mediamanager-tab-upload"'; 538 if (!empty($selected) && $selected == 'upload') $class = 'upload selected'; 539 else $class = 'upload'; 540 $tab .= ' class="'.$class.'" >Upload</a>'; 541 echo $tab; 542 543 $tab = '<a href="'.media_managerURL(array('tab_files' => 'search')). 544 '" rel=".mediamanager-tab-search"'; 545 if (!empty($selected) && $selected == 'search') $class = 'search selected'; 546 else $class = 'search'; 547 $tab .= ' class="'.$class.'" >Search</a>'; 548 echo $tab; 549 550 echo '<div class="mediamanager-clear"> </div>'; 551 echo '</div>'; 552} 553 554/** 555 * Prints tabs for files details actions 556 * 557 * @author Kate Arzamastseva <pshns@ukr.net> 558 * @param string $selected - opened tab 559 */ 560function media_tabs_details($selected=false){ 561 global $lang; 562 563 echo '<div class="mediamanager-tabs" id="id-mediamanager-tabs-detail">'; 564 $tab = '<a href="'.media_managerURL(array('tab_details' => 'view')). 565 '" rel=".mediamanager-tab-view"'; 566 if (!empty($selected) && $selected == 'view') $class = 'view selected'; 567 else $class = 'view'; 568 $tab .= ' class="'.$class.'" >View</a>'; 569 echo $tab; 570 571 $tab = '<a href="'.media_managerURL(array('tab_details' => 'edit')). 572 '" rel=".mediamanager-tab-edit"'; 573 if (!empty($selected) && $selected == 'edit') $class = 'edit selected'; 574 else $class = 'edit'; 575 $tab .= ' class="'.$class.'" >Edit</a>'; 576 echo $tab; 577 578 $tab = '<a href="'.media_managerURL(array('tab_details' => 'history')). 579 '" rel=".mediamanager-tab-history"'; 580 if (!empty($selected) && $selected == 'history') $class = 'history selected'; 581 else $class = 'history'; 582 $tab .= ' class="'.$class.'" >History</a>'; 583 echo $tab; 584 585 echo '<div class="mediamanager-clear"> </div>'; 586 echo '</div>'; 587} 588 589/** 590 * Prints options for the tab that displays a list of all files 591 * 592 * @author Kate Arzamastseva <pshns@ukr.net> 593 */ 594function media_tab_files_options(){ 595 global $lang; 596 597 echo '<div class="background-container">'; 598 echo '<div id="id-mediamanager-tabs-files" style="display: inline;">'; 599 echo '<a href="'.media_managerURL(array('view' => 'thumbs')).'" 600 rel=".mediamanager-files-thumbnails-tab" class="mediamanager-link-thumbnails"> 601 Thumbs</a>'; 602 echo '<a href="'.media_managerURL(array('view' => 'list')).'" 603 rel=".mediamanager-files-list-tab" class="mediamanager-link-list" 604 title="View as list">List</a>'; 605 606 echo '</div>'; 607 echo '<div class="mediamanager-block-sort">Sort'; 608 //select 609 echo '</div>'; 610 echo '<div class="mediamanager-clear"> </div>'; 611 echo '</div>'; 612} 613 614/** 615 * Prints tab that displays a list of all files 616 * 617 * @author Kate Arzamastseva <pshns@ukr.net> 618 */ 619function media_tab_files($ns,$auth=null,$jump='') { 620 global $lang; 621 if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 622 623 echo '<div class="mediamanager-tab-files">'; 624 media_tab_files_options(); 625 echo '<div class="scroll-container">'; 626 627 $view = $_REQUEST['view']; 628 if($auth < AUTH_READ){ 629 echo '<div class="nothing">'.$lang['nothingfound'].'</div>'.NL; 630 }else{ 631 if ($view == 'list') { 632 echo '<div class="mediamanager-files-list-tab">'; 633 echo '</div>'; 634 } else { 635 echo '<div class="mediamanager-files-thumbnails-tab">'; 636 media_filelist($ns,$auth,$jump,'thumbs'); 637 echo '</div>'; 638 } 639 } 640 echo '</div>'; 641 echo '</div>'; 642} 643 644/** 645 * Prints tab that displays uploading form 646 * 647 * @author Kate Arzamastseva <pshns@ukr.net> 648 */ 649function media_tab_upload($ns,$auth=null,$jump='') { 650 global $lang; 651 if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 652 653 echo '<div class="mediamanager-tab-upload"">'; 654 echo '<div class="background-container">'; 655 echo $lang['mediaupload']; 656 echo '</div>'; 657 658 echo '<div class="scroll-container">'; 659 media_uploadform($ns, $auth, true); 660 echo '</div>'; 661 echo '</div>'; 662} 663 664/** 665 * Prints tab that displays search form 666 * 667 * @author Kate Arzamastseva <pshns@ukr.net> 668 */ 669function media_tab_search($ns,$auth=null) { 670 global $lang; 671 672 $do = $_REQUEST['mediado']; 673 $query = $_REQUEST['q']; 674 if (!$query) $query = ''; 675 676 echo '<div class="mediamanager-tab-search">'; 677 echo '<div class="background-container">'; 678 echo 'Search'; 679 echo'</div>'; 680 681 echo '<div class="scroll-container">'; 682 media_searchform($ns, $query, true); 683 684 if($do == 'searchlist'){ 685 media_searchlist($query,$ns,$auth,true); 686 } 687 echo '</div>'; 688 echo '</div>'; 689} 690 691/** 692 * Prints tab that displays mediafile details 693 * 694 * @author Kate Arzamastseva <pshns@ukr.net> 695 */ 696function media_tab_view($image, $ns, $auth=null) { 697 global $lang, $conf; 698 if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 699 700 echo '<div class="mediamanager-tab-detail-view">'; 701 echo '<div class="background-container">'; 702 echo 'Preview of image'; 703 echo '</div>'; 704 705 echo '<div class="scroll-container">'; 706 if($auth < AUTH_READ) return false; 707 708 $info = new JpegMeta(mediaFN($image)); 709 $w = (int) $info->getField('File.Width'); 710 $src = ml($image); 711 echo '<img src="'.$src.'" alt="" width="99%" style="max-width: '.$w.'px;" />'; 712 echo '</div>'; 713 echo '</div>'; 714} 715 716/** 717 * Prints tab that displays form for editing mediafile metadata 718 * 719 * @author Kate Arzamastseva <pshns@ukr.net> 720 */ 721function media_tab_edit($image, $ns, $auth=null) { 722 global $lang; 723 if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 724 725 echo '<div class="mediamanager-tab-detail-edit">'; 726 echo '<div class="background-container">'; 727 echo 'Edit'; 728 echo '</div>'; 729 730 echo '<div class="scroll-container">'; 731 media_metaform($image,$auth,true); 732 echo '</div>'; 733 echo '</div>'; 734} 735 736/** 737 * Prints tab that displays mediafile revisions 738 * 739 * @author Kate Arzamastseva <pshns@ukr.net> 740 */ 741function media_tab_history($image, $ns, $auth=null) { 742 global $lang; 743 if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 744 745 echo '<div class="mediamanager-tab-detail-history">'; 746 echo '<div class="background-container">'; 747 echo 'History'; 748 echo '</div>'; 749 750 echo '<div class="scroll-container">'; 751 752 echo '</div>'; 753 echo '</div>'; 754} 755 756/** 757 * List all files found by the search request 758 * 759 * @author Tobias Sarnowski <sarnowski@cosmocode.de> 760 * @author Andreas Gohr <gohr@cosmocode.de> 761 * @author Kate Arzamastseva <pshns@ukr.net> 762 * @triggers MEDIA_SEARCH 763 */ 764function media_searchlist($query,$ns,$auth=null,$fullscreen=false){ 765 global $conf; 766 global $lang; 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