13df72098SAndreas Gohr<?php 23df72098SAndreas Gohr/** 33df72098SAndreas Gohr * All output and handler function needed for the media management popup 43df72098SAndreas Gohr * 53df72098SAndreas Gohr * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 63df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 73df72098SAndreas Gohr */ 824870174SAndreas Gohruse dokuwiki\Ui\MediaRevisions; 924870174SAndreas Gohruse dokuwiki\Cache\CacheImageMod; 1024870174SAndreas Gohruse splitbrain\slika\Exception; 1124870174SAndreas Gohruse dokuwiki\PassHash; 120c3a5702SAndreas Gohruse dokuwiki\ChangeLog\MediaChangeLog; 13b021f0b4SAndreas Gohruse dokuwiki\Extension\Event; 14b021f0b4SAndreas Gohruse dokuwiki\Form\Form; 155a8d6e48SMichael Großeuse dokuwiki\HTTP\DokuHTTPClient; 1679a2d784SGerrit Uitslaguse dokuwiki\Logger; 17704a815fSMichael Großeuse dokuwiki\Subscriptions\MediaSubscriptionSender; 1879a2d784SGerrit Uitslaguse dokuwiki\Ui\Media\DisplayRow; 1979a2d784SGerrit Uitslaguse dokuwiki\Ui\Media\DisplayTile; 2079a2d784SGerrit Uitslaguse dokuwiki\Ui\MediaDiff; 2179a2d784SGerrit Uitslaguse dokuwiki\Utf8\PhpString; 222d85e841SAndreas Gohruse dokuwiki\Utf8\Sort; 2379a2d784SGerrit Uitslaguse splitbrain\slika\Slika; 240c3a5702SAndreas Gohr 253df72098SAndreas Gohr/** 263df72098SAndreas Gohr * Lists pages which currently use a media file selected for deletion 273df72098SAndreas Gohr * 283df72098SAndreas Gohr * References uses the same visual as search results and share 293df72098SAndreas Gohr * their CSS tags except pagenames won't be links. 303df72098SAndreas Gohr * 313df72098SAndreas Gohr * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net> 3242ea7f44SGerrit Uitslag * 3342ea7f44SGerrit Uitslag * @param array $data 3442ea7f44SGerrit Uitslag * @param string $id 353df72098SAndreas Gohr */ 36d868eb89SAndreas Gohrfunction media_filesinuse($data, $id) 37d868eb89SAndreas Gohr{ 383df72098SAndreas Gohr global $lang; 393df72098SAndreas Gohr echo '<h1>'.$lang['reference'].' <code>'.hsc(noNS($id)).'</code></h1>'; 403df72098SAndreas Gohr echo '<p>'.hsc($lang['ref_inuse']).'</p>'; 413df72098SAndreas Gohr 423df72098SAndreas Gohr $hidden=0; //count of hits without read permission 433df72098SAndreas Gohr foreach($data as $row){ 44a05e297aSAndreas Gohr if(auth_quickaclcheck($row) >= AUTH_READ && isVisiblePage($row)){ 453df72098SAndreas Gohr echo '<div class="search_result">'; 46a05e297aSAndreas Gohr echo '<span class="mediaref_ref">'.hsc($row).'</span>'; 473df72098SAndreas Gohr echo '</div>'; 483df72098SAndreas Gohr }else 493df72098SAndreas Gohr $hidden++; 503df72098SAndreas Gohr } 513df72098SAndreas Gohr if ($hidden){ 523df72098SAndreas Gohr print '<div class="mediaref_hidden">'.$lang['ref_hidden'].'</div>'; 533df72098SAndreas Gohr } 543df72098SAndreas Gohr} 553df72098SAndreas Gohr 563df72098SAndreas Gohr/** 573df72098SAndreas Gohr * Handles the saving of image meta data 583df72098SAndreas Gohr * 593df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 60cf832786SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 61e0c26282SGerrit Uitslag * 62e0c26282SGerrit Uitslag * @param string $id media id 63e0c26282SGerrit Uitslag * @param int $auth permission level 64e0c26282SGerrit Uitslag * @param array $data 6542ea7f44SGerrit Uitslag * @return false|string 663df72098SAndreas Gohr */ 67d868eb89SAndreas Gohrfunction media_metasave($id, $auth, $data) 68d868eb89SAndreas Gohr{ 693df72098SAndreas Gohr if($auth < AUTH_UPLOAD) return false; 70f2ea8432SAndreas Gohr if(!checkSecurityToken()) return false; 713df72098SAndreas Gohr global $lang; 720b308644SOtto Vainio global $conf; 733df72098SAndreas Gohr $src = mediaFN($id); 743df72098SAndreas Gohr 753df72098SAndreas Gohr $meta = new JpegMeta($src); 763df72098SAndreas Gohr $meta->_parseAll(); 773df72098SAndreas Gohr 783df72098SAndreas Gohr foreach($data as $key => $val){ 793df72098SAndreas Gohr $val=trim($val); 803df72098SAndreas Gohr if(empty($val)){ 813df72098SAndreas Gohr $meta->deleteField($key); 823df72098SAndreas Gohr }else{ 833df72098SAndreas Gohr $meta->setField($key, $val); 843df72098SAndreas Gohr } 853df72098SAndreas Gohr } 863df72098SAndreas Gohr 87cf832786SKate Arzamastseva $old = @filemtime($src); 8879e79377SAndreas Gohr if(!file_exists(mediaFN($id, $old)) && file_exists($src)) { 89cf832786SKate Arzamastseva // add old revision to the attic 90cf832786SKate Arzamastseva media_saveOldRevision($id); 91cf832786SKate Arzamastseva } 92ac3ed4afSGerrit Uitslag $filesize_old = filesize($src); 933df72098SAndreas Gohr if($meta->save()){ 940b308644SOtto Vainio if($conf['fperm']) chmod($src, $conf['fperm']); 95ac3ed4afSGerrit Uitslag @clearstatcache(true, $src); 96cf832786SKate Arzamastseva $new = @filemtime($src); 97ac3ed4afSGerrit Uitslag $filesize_new = filesize($src); 98ac3ed4afSGerrit Uitslag $sizechange = $filesize_new - $filesize_old; 99ac3ed4afSGerrit Uitslag 100cf832786SKate Arzamastseva // add a log entry to the media changelog 101ac3ed4afSGerrit Uitslag addMediaLogEntry($new, $id, DOKU_CHANGE_TYPE_EDIT, $lang['media_meta_edited'], '', null, $sizechange); 102cf832786SKate Arzamastseva 1033df72098SAndreas Gohr msg($lang['metasaveok'], 1); 1043df72098SAndreas Gohr return $id; 1053df72098SAndreas Gohr }else{ 1063df72098SAndreas Gohr msg($lang['metasaveerr'], -1); 1073df72098SAndreas Gohr return false; 1083df72098SAndreas Gohr } 1093df72098SAndreas Gohr} 1103df72098SAndreas Gohr 1113df72098SAndreas Gohr/** 112d54f7963SKlap-in * check if a media is external source 113d54f7963SKlap-in * 114d54f7963SKlap-in * @author Gerrit Uitslag <klapinklapin@gmail.com> 11542ea7f44SGerrit Uitslag * 116d54f7963SKlap-in * @param string $id the media ID or URL 117d54f7963SKlap-in * @return bool 118d54f7963SKlap-in */ 119d868eb89SAndreas Gohrfunction media_isexternal($id) 120d868eb89SAndreas Gohr{ 121fe578fe9SElan Ruusamäe if (preg_match('#^(?:https?|ftp)://#i', $id)) return true; 122d54f7963SKlap-in return false; 123d54f7963SKlap-in} 124d54f7963SKlap-in 125d54f7963SKlap-in/** 126add8678fSAndreas Gohr * Check if a media item is public (eg, external URL or readable by @ALL) 127add8678fSAndreas Gohr * 128add8678fSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 12942ea7f44SGerrit Uitslag * 130add8678fSAndreas Gohr * @param string $id the media ID or URL 131add8678fSAndreas Gohr * @return bool 132add8678fSAndreas Gohr */ 133d868eb89SAndreas Gohrfunction media_ispublic($id) 134d868eb89SAndreas Gohr{ 135d54f7963SKlap-in if(media_isexternal($id)) return true; 136add8678fSAndreas Gohr $id = cleanID($id); 13724870174SAndreas Gohr if(auth_aclcheck(getNS($id).':*', '', []) >= AUTH_READ) return true; 138add8678fSAndreas Gohr return false; 139add8678fSAndreas Gohr} 140add8678fSAndreas Gohr 141add8678fSAndreas Gohr/** 1423df72098SAndreas Gohr * Display the form to edit image meta data 1433df72098SAndreas Gohr * 1443df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 145d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 146e0c26282SGerrit Uitslag * 147e0c26282SGerrit Uitslag * @param string $id media id 148e0c26282SGerrit Uitslag * @param int $auth permission level 149e0c26282SGerrit Uitslag * @return bool 1503df72098SAndreas Gohr */ 151d868eb89SAndreas Gohrfunction media_metaform($id, $auth) 152d868eb89SAndreas Gohr{ 153ebc28e69SAndreas Gohr global $lang; 1543df72098SAndreas Gohr 15588a71175SKate Arzamastseva if ($auth < AUTH_UPLOAD) { 156b960c74fSSatoshi Sahara echo '<div class="nothing">'.$lang['media_perm_upload'].'</div>'.DOKU_LF; 15788a71175SKate Arzamastseva return false; 15888a71175SKate Arzamastseva } 15988a71175SKate Arzamastseva 1603df72098SAndreas Gohr // load the field descriptions 1613df72098SAndreas Gohr static $fields = null; 162b960c74fSSatoshi Sahara if ($fields === null) { 1633e98e685SKate Arzamastseva $config_files = getConfigFiles('mediameta'); 1643e98e685SKate Arzamastseva foreach ($config_files as $config_file) { 16579e79377SAndreas Gohr if (file_exists($config_file)) include($config_file); 1663df72098SAndreas Gohr } 1673df72098SAndreas Gohr } 1683df72098SAndreas Gohr 1693df72098SAndreas Gohr $src = mediaFN($id); 1703df72098SAndreas Gohr 1713df72098SAndreas Gohr // output 172b960c74fSSatoshi Sahara $form = new Form([ 173b960c74fSSatoshi Sahara 'action' => media_managerURL(['tab_details' => 'view'], '&'), 174b960c74fSSatoshi Sahara 'class' => 'meta' 175b960c74fSSatoshi Sahara ]); 176b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 177b960c74fSSatoshi Sahara $form->setHiddenField('img', $id); 178b960c74fSSatoshi Sahara $form->setHiddenField('mediado', 'save'); 1793df72098SAndreas Gohr foreach ($fields as $key => $field) { 1803df72098SAndreas Gohr // get current value 1813e98e685SKate Arzamastseva if (empty($field[0])) continue; 18224870174SAndreas Gohr $tags = [$field[0]]; 1833df72098SAndreas Gohr if (is_array($field[3])) $tags = array_merge($tags, $field[3]); 1843df72098SAndreas Gohr $value = tpl_img_getTag($tags, '', $src); 185ca6a0701SAndreas Gohr $value = cleanText($value); 1863df72098SAndreas Gohr 1873df72098SAndreas Gohr // prepare attributes 18824870174SAndreas Gohr $p = [ 189b960c74fSSatoshi Sahara 'class' => 'edit', 190b960c74fSSatoshi Sahara 'id' => 'meta__'.$key, 19124870174SAndreas Gohr 'name' => 'meta['.$field[0].']' 19224870174SAndreas Gohr ]; 1933df72098SAndreas Gohr 194b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('row'); 1953df72098SAndreas Gohr if ($field[2] == 'text') { 196bde2a644SSatoshi Sahara $form->addTextInput( 19764159a61SAndreas Gohr $p['name'], 19879a2d784SGerrit Uitslag ($lang[$field[1]] ?: $field[1] . ':') 199b960c74fSSatoshi Sahara )->id($p['id'])->addClass($p['class'])->val($value); 2003df72098SAndreas Gohr } else { 201b960c74fSSatoshi Sahara $form->addTextarea($p['name'], $lang[$field[1]])->id($p['id']) 202b960c74fSSatoshi Sahara ->val(formText($value)) 203b960c74fSSatoshi Sahara ->addClass($p['class']) 204b960c74fSSatoshi Sahara ->attr('rows', '6')->attr('cols', '50'); 2053df72098SAndreas Gohr } 206b960c74fSSatoshi Sahara $form->addTagClose('div'); 2073df72098SAndreas Gohr } 208b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('buttons'); 209b960c74fSSatoshi Sahara $form->addButton('mediado[save]', $lang['btn_save'])->attr('type', 'submit') 210b960c74fSSatoshi Sahara ->attrs(['accesskey' => 's']); 211b960c74fSSatoshi Sahara $form->addTagClose('div'); 212ebc28e69SAndreas Gohr 213b960c74fSSatoshi Sahara $form->addTagClose('div'); 214b960c74fSSatoshi Sahara echo $form->toHTML(); 215ebc28e69SAndreas Gohr return true; 2163df72098SAndreas Gohr} 2173df72098SAndreas Gohr 218666cdec5SMichael Klier/** 21987229c84SAdrian Lang * Convenience function to check if a media file is still in use 220666cdec5SMichael Klier * 221666cdec5SMichael Klier * @author Michael Klier <chi@chimeric.de> 222e0c26282SGerrit Uitslag * 223e0c26282SGerrit Uitslag * @param string $id media id 224e0c26282SGerrit Uitslag * @return array|bool 225666cdec5SMichael Klier */ 226d868eb89SAndreas Gohrfunction media_inuse($id) 227d868eb89SAndreas Gohr{ 228666cdec5SMichael Klier global $conf; 229ebc28e69SAndreas Gohr 230666cdec5SMichael Klier if($conf['refcheck']){ 231ffec1009SMichael Hamann $mediareferences = ft_mediause($id, true); 23224870174SAndreas Gohr if($mediareferences === []) { 2336dae2464SAndreas Gohr return false; 234666cdec5SMichael Klier } else { 235666cdec5SMichael Klier return $mediareferences; 236666cdec5SMichael Klier } 237666cdec5SMichael Klier } else { 238666cdec5SMichael Klier return false; 239666cdec5SMichael Klier } 240666cdec5SMichael Klier} 241a05e297aSAndreas Gohr 2423df72098SAndreas Gohr/** 2433df72098SAndreas Gohr * Handles media file deletions 2443df72098SAndreas Gohr * 2453df72098SAndreas Gohr * If configured, checks for media references before deletion 2463df72098SAndreas Gohr * 2473df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 24842ea7f44SGerrit Uitslag * 249ebc28e69SAndreas Gohr * @param string $id media id 25022db8df7SAndreas Gohr * @param int $auth no longer used 25187229c84SAdrian Lang * @return int One of: 0, 25263703ba5SAndreas Gohr * DOKU_MEDIA_DELETED, 25363703ba5SAndreas Gohr * DOKU_MEDIA_DELETED | DOKU_MEDIA_EMPTY_NS, 25463703ba5SAndreas Gohr * DOKU_MEDIA_NOT_AUTH, 25563703ba5SAndreas Gohr * DOKU_MEDIA_INUSE 2563df72098SAndreas Gohr */ 257d868eb89SAndreas Gohrfunction media_delete($id, $auth) 258d868eb89SAndreas Gohr{ 2596183fb05SKate Arzamastseva global $lang; 260ff04e8b7SAndreas Gohr $auth = auth_quickaclcheck(ltrim(getNS($id).':*', ':')); 26187229c84SAdrian Lang if($auth < AUTH_DELETE) return DOKU_MEDIA_NOT_AUTH; 26287229c84SAdrian Lang if(media_inuse($id)) return DOKU_MEDIA_INUSE; 2633df72098SAndreas Gohr 2643df72098SAndreas Gohr $file = mediaFN($id); 2654a961e72SMichal Kolodziejski 2664a961e72SMichal Kolodziejski // trigger an event - MEDIA_DELETE_FILE 26724870174SAndreas Gohr $data = []; 268666cdec5SMichael Klier $data['id'] = $id; 26979a2d784SGerrit Uitslag $data['name'] = PhpString::basename($file); 2704a961e72SMichal Kolodziejski $data['path'] = $file; 27179e79377SAndreas Gohr $data['size'] = (file_exists($file)) ? filesize($file) : 0; 272666cdec5SMichael Klier 273666cdec5SMichael Klier $data['unl'] = false; 274666cdec5SMichael Klier $data['del'] = false; 275e1d9dcc8SAndreas Gohr $evt = new Event('MEDIA_DELETE_FILE', $data); 2764a961e72SMichal Kolodziejski if ($evt->advise_before()) { 2776183fb05SKate Arzamastseva $old = @filemtime($file); 27879e79377SAndreas Gohr if(!file_exists(mediaFN($id, $old)) && file_exists($file)) { 2796183fb05SKate Arzamastseva // add old revision to the attic 2806183fb05SKate Arzamastseva media_saveOldRevision($id); 2816183fb05SKate Arzamastseva } 2826183fb05SKate Arzamastseva 283666cdec5SMichael Klier $data['unl'] = @unlink($file); 284666cdec5SMichael Klier if($data['unl']) { 285ac3ed4afSGerrit Uitslag $sizechange = 0 - $data['size']; 286ac3ed4afSGerrit Uitslag addMediaLogEntry(time(), $id, DOKU_CHANGE_TYPE_DELETE, $lang['deleted'], '', null, $sizechange); 287ac3ed4afSGerrit Uitslag 288666cdec5SMichael Klier $data['del'] = io_sweepNS($id, 'mediadir'); 2893df72098SAndreas Gohr } 2904a961e72SMichal Kolodziejski } 2914a961e72SMichal Kolodziejski $evt->advise_after(); 2924a961e72SMichal Kolodziejski unset($evt); 2934a961e72SMichal Kolodziejski 294666cdec5SMichael Klier if($data['unl'] && $data['del']){ 29587229c84SAdrian Lang return DOKU_MEDIA_DELETED | DOKU_MEDIA_EMPTY_NS; 2963df72098SAndreas Gohr } 2973df72098SAndreas Gohr 29887229c84SAdrian Lang return $data['unl'] ? DOKU_MEDIA_DELETED : 0; 2993df72098SAndreas Gohr} 3003df72098SAndreas Gohr 3013df72098SAndreas Gohr/** 3022d6cc64fSKate Arzamastseva * Handle file uploads via XMLHttpRequest 3032d6cc64fSKate Arzamastseva * 304ebc28e69SAndreas Gohr * @param string $ns target namespace 305ebc28e69SAndreas Gohr * @param int $auth current auth check result 30642ea7f44SGerrit Uitslag * @return false|string false on error, id of the new file on success 3072d6cc64fSKate Arzamastseva */ 308d868eb89SAndreas Gohrfunction media_upload_xhr($ns, $auth) 309d868eb89SAndreas Gohr{ 310da45d883SKate Arzamastseva if(!checkSecurityToken()) return false; 3118108113cSTom N Harris global $INPUT; 312da45d883SKate Arzamastseva 3138108113cSTom N Harris $id = $INPUT->get->str('qqfile'); 31424870174SAndreas Gohr [$ext, $mime] = mimetype($id); 3152d6cc64fSKate Arzamastseva $input = fopen("php://input", "r"); 3162d6cc64fSKate Arzamastseva if (!($tmp = io_mktmpdir())) return false; 31762231793SKate Arzamastseva $path = $tmp.'/'.md5($id); 3182d6cc64fSKate Arzamastseva $target = fopen($path, "w"); 319063fb5b5SAndreas Gohr $realSize = stream_copy_to_stream($input, $target); 3202d6cc64fSKate Arzamastseva fclose($target); 321063fb5b5SAndreas Gohr fclose($input); 3222b9be456SAndreas Gohr if ($INPUT->server->has('CONTENT_LENGTH') && ($realSize != $INPUT->server->int('CONTENT_LENGTH'))) { 323063fb5b5SAndreas Gohr unlink($path); 324063fb5b5SAndreas Gohr return false; 325063fb5b5SAndreas Gohr } 326063fb5b5SAndreas Gohr 3272d6cc64fSKate Arzamastseva $res = media_save( 32824870174SAndreas Gohr ['name' => $path, 'mime' => $mime, 'ext' => $ext], 3292d6cc64fSKate Arzamastseva $ns.':'.$id, 33079a2d784SGerrit Uitslag ($INPUT->get->str('ow') == 'true'), 3312d6cc64fSKate Arzamastseva $auth, 3322d6cc64fSKate Arzamastseva 'copy' 3332d6cc64fSKate Arzamastseva ); 3342d6cc64fSKate Arzamastseva unlink($path); 335900a9e9eSGerrit Uitslag if ($tmp) io_rmdir($tmp, true); 3362d6cc64fSKate Arzamastseva if (is_array($res)) { 3372d6cc64fSKate Arzamastseva msg($res[0], $res[1]); 3382d6cc64fSKate Arzamastseva return false; 3392d6cc64fSKate Arzamastseva } 3402d6cc64fSKate Arzamastseva return $res; 3412d6cc64fSKate Arzamastseva} 3422d6cc64fSKate Arzamastseva 3432d6cc64fSKate Arzamastseva/** 3443df72098SAndreas Gohr * Handles media file uploads 3453df72098SAndreas Gohr * 3463df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 34711d9dfa5SMichael Klier * @author Michael Klier <chi@chimeric.de> 34842ea7f44SGerrit Uitslag * 349ebc28e69SAndreas Gohr * @param string $ns target namespace 350ebc28e69SAndreas Gohr * @param int $auth current auth check result 351ebc28e69SAndreas Gohr * @param bool|array $file $_FILES member, $_FILES['upload'] if false 35242ea7f44SGerrit Uitslag * @return false|string false on error, id of the new file on success 3533df72098SAndreas Gohr */ 354d868eb89SAndreas Gohrfunction media_upload($ns, $auth, $file = false) 355d868eb89SAndreas Gohr{ 356f2ea8432SAndreas Gohr if(!checkSecurityToken()) return false; 3573df72098SAndreas Gohr global $lang; 3588108113cSTom N Harris global $INPUT; 3593df72098SAndreas Gohr 36044409c3dSAndreas Gohr // get file and id 3618108113cSTom N Harris $id = $INPUT->post->str('mediaid'); 3622d6cc64fSKate Arzamastseva if (!$file) $file = $_FILES['upload']; 3633df72098SAndreas Gohr if(empty($id)) $id = $file['name']; 36444409c3dSAndreas Gohr 36599766eefSAndreas Gohr // check for errors (messages are done in lib/exe/mediamanager.php) 36699766eefSAndreas Gohr if($file['error']) return false; 3679676dc23SAndreas Gohr 36844409c3dSAndreas Gohr // check extensions 36924870174SAndreas Gohr [$fext, $fmime] = mimetype($file['name']); 37024870174SAndreas Gohr [$iext, $imime] = mimetype($id); 37144409c3dSAndreas Gohr if($fext && !$iext){ 3728cb1eb01SAndreas Gohr // no extension specified in id - read original one 37344409c3dSAndreas Gohr $id .= '.'.$fext; 3748cb1eb01SAndreas Gohr $imime = $fmime; 37544409c3dSAndreas Gohr }elseif($fext && $fext != $iext){ 37644409c3dSAndreas Gohr // extension was changed, print warning 37744409c3dSAndreas Gohr msg(sprintf($lang['mediaextchange'], $fext, $iext)); 37844409c3dSAndreas Gohr } 37944409c3dSAndreas Gohr 38024870174SAndreas Gohr $res = media_save( 38124870174SAndreas Gohr [ 38224870174SAndreas Gohr 'name' => $file['tmp_name'], 383ffb291f2SAdrian Lang 'mime' => $imime, 38424870174SAndreas Gohr 'ext' => $iext 38524870174SAndreas Gohr ], 38624870174SAndreas Gohr $ns . ':' . $id, 38724870174SAndreas Gohr $INPUT->post->bool('ow'), 38824870174SAndreas Gohr $auth, 38924870174SAndreas Gohr 'copy_uploaded_file' 39024870174SAndreas Gohr ); 391ffb291f2SAdrian Lang if (is_array($res)) { 392ffb291f2SAdrian Lang msg($res[0], $res[1]); 393ffb291f2SAdrian Lang return false; 394ffb291f2SAdrian Lang } 395ffb291f2SAdrian Lang return $res; 396ffb291f2SAdrian Lang} 397ffb291f2SAdrian Lang 398ffb291f2SAdrian Lang/** 39971f17ac4SAndreas Gohr * An alternative to move_uploaded_file that copies 40071f17ac4SAndreas Gohr * 40171f17ac4SAndreas Gohr * Using copy, makes sure any setgid bits on the media directory are honored 40271f17ac4SAndreas Gohr * 40371f17ac4SAndreas Gohr * @see move_uploaded_file() 40442ea7f44SGerrit Uitslag * 40571f17ac4SAndreas Gohr * @param string $from 40671f17ac4SAndreas Gohr * @param string $to 40771f17ac4SAndreas Gohr * @return bool 40871f17ac4SAndreas Gohr */ 409d868eb89SAndreas Gohrfunction copy_uploaded_file($from, $to) 410d868eb89SAndreas Gohr{ 41171f17ac4SAndreas Gohr if(!is_uploaded_file($from)) return false; 41271f17ac4SAndreas Gohr $ok = copy($from, $to); 41371f17ac4SAndreas Gohr @unlink($from); 41471f17ac4SAndreas Gohr return $ok; 41571f17ac4SAndreas Gohr} 41671f17ac4SAndreas Gohr 41771f17ac4SAndreas Gohr/** 418ffb291f2SAdrian Lang * This generates an action event and delegates to _media_upload_action(). 419ffb291f2SAdrian Lang * Action plugins are allowed to pre/postprocess the uploaded file. 420ffb291f2SAdrian Lang * (The triggered event is preventable.) 421ffb291f2SAdrian Lang * 422ffb291f2SAdrian Lang * Event data: 423ffb291f2SAdrian Lang * $data[0] fn_tmp: the temporary file name (read from $_FILES) 424ffb291f2SAdrian Lang * $data[1] fn: the file name of the uploaded file 425ffb291f2SAdrian Lang * $data[2] id: the future directory id of the uploaded file 426ffb291f2SAdrian Lang * $data[3] imime: the mimetype of the uploaded file 427ffb291f2SAdrian Lang * $data[4] overwrite: if an existing file is going to be overwritten 42852a281e8SGerrit Uitslag * $data[5] move: name of function that performs move/copy/.. 429ffb291f2SAdrian Lang * 430ffb291f2SAdrian Lang * @triggers MEDIA_UPLOAD_FINISH 43142ea7f44SGerrit Uitslag * 432e0c26282SGerrit Uitslag * @param array $file 43352a281e8SGerrit Uitslag * @param string $id media id 43442ea7f44SGerrit Uitslag * @param bool $ow overwrite? 435e0c26282SGerrit Uitslag * @param int $auth permission level 43652a281e8SGerrit Uitslag * @param string $move name of functions that performs move/copy/.. 43742ea7f44SGerrit Uitslag * @return false|array|string 438e0c26282SGerrit Uitslag */ 439d868eb89SAndreas Gohrfunction media_save($file, $id, $ow, $auth, $move) 440d868eb89SAndreas Gohr{ 441ffb291f2SAdrian Lang if($auth < AUTH_UPLOAD) { 44224870174SAndreas Gohr return ["You don't have permissions to upload files.", -1]; 443ffb291f2SAdrian Lang } 444ffb291f2SAdrian Lang 445ffb291f2SAdrian Lang if (!isset($file['mime']) || !isset($file['ext'])) { 44624870174SAndreas Gohr [$ext, $mime] = mimetype($id); 447ffb291f2SAdrian Lang if (!isset($file['mime'])) { 448ffb291f2SAdrian Lang $file['mime'] = $mime; 449ffb291f2SAdrian Lang } 450ffb291f2SAdrian Lang if (!isset($file['ext'])) { 451ffb291f2SAdrian Lang $file['ext'] = $ext; 452ffb291f2SAdrian Lang } 453ffb291f2SAdrian Lang } 454ffb291f2SAdrian Lang 45592cac9a9SKate Arzamastseva global $lang, $conf; 456ffb291f2SAdrian Lang 4573df72098SAndreas Gohr // get filename 4583543c6deSAndreas Gohr $id = cleanID($id); 4593df72098SAndreas Gohr $fn = mediaFN($id); 4603df72098SAndreas Gohr 4613df72098SAndreas Gohr // get filetype regexp 4623df72098SAndreas Gohr $types = array_keys(getMimeTypes()); 463bad6fc0dSAndreas Gohr $types = array_map( 46424870174SAndreas Gohr static fn($q) => preg_quote($q, "/"), 465bad6fc0dSAndreas Gohr $types 466bad6fc0dSAndreas Gohr ); 46724870174SAndreas Gohr $regex = implode('|', $types); 4683df72098SAndreas Gohr 4693df72098SAndreas Gohr // because a temp file was created already 470ffb291f2SAdrian Lang if(!preg_match('/\.('.$regex.')$/i', $fn)) { 47124870174SAndreas Gohr return [$lang['uploadwrong'], -1]; 472ffb291f2SAdrian Lang } 473ffb291f2SAdrian Lang 4743df72098SAndreas Gohr //check for overwrite 47579e79377SAndreas Gohr $overwrite = file_exists($fn); 476e5d185e1SKate Arzamastseva $auth_ow = (($conf['mediarevisions']) ? AUTH_UPLOAD : AUTH_DELETE); 477e5d185e1SKate Arzamastseva if($overwrite && (!$ow || $auth < $auth_ow)) { 47824870174SAndreas Gohr return [$lang['uploadexist'], 0]; 4793df72098SAndreas Gohr } 4808cb1eb01SAndreas Gohr // check for valid content 481ffb291f2SAdrian Lang $ok = media_contentcheck($file['name'], $file['mime']); 4828cb1eb01SAndreas Gohr if($ok == -1){ 48324870174SAndreas Gohr return [sprintf($lang['uploadbadcontent'], '.' . $file['ext']), -1]; 4848cb1eb01SAndreas Gohr }elseif($ok == -2){ 48524870174SAndreas Gohr return [$lang['uploadspam'], -1]; 48626ceae18SAndreas Gohr }elseif($ok == -3){ 48724870174SAndreas Gohr return [$lang['uploadxss'], -1]; 4888cb1eb01SAndreas Gohr } 4898cb1eb01SAndreas Gohr 49011d9dfa5SMichael Klier // prepare event data 49124870174SAndreas Gohr $data = []; 492ffb291f2SAdrian Lang $data[0] = $file['name']; 49311d9dfa5SMichael Klier $data[1] = $fn; 49411d9dfa5SMichael Klier $data[2] = $id; 495ffb291f2SAdrian Lang $data[3] = $file['mime']; 49699c8d7f2Smichael $data[4] = $overwrite; 497ffb291f2SAdrian Lang $data[5] = $move; 49811d9dfa5SMichael Klier 49911d9dfa5SMichael Klier // trigger event 500cbb44eabSAndreas Gohr return Event::createAndTrigger('MEDIA_UPLOAD_FINISH', $data, '_media_upload_action', true); 50111d9dfa5SMichael Klier} 50211d9dfa5SMichael Klier 50311d9dfa5SMichael Klier/** 50442ea7f44SGerrit Uitslag * Callback adapter for media_upload_finish() triggered by MEDIA_UPLOAD_FINISH 50542ea7f44SGerrit Uitslag * 50611d9dfa5SMichael Klier * @author Michael Klier <chi@chimeric.de> 50742ea7f44SGerrit Uitslag * 50842ea7f44SGerrit Uitslag * @param array $data event data 50942ea7f44SGerrit Uitslag * @return false|array|string 51011d9dfa5SMichael Klier */ 511d868eb89SAndreas Gohrfunction _media_upload_action($data) 512d868eb89SAndreas Gohr{ 51311d9dfa5SMichael Klier // fixme do further sanity tests of given data? 514ffb291f2SAdrian Lang if(is_array($data) && count($data)===6) { 515ffb291f2SAdrian Lang return media_upload_finish($data[0], $data[1], $data[2], $data[3], $data[4], $data[5]); 51611d9dfa5SMichael Klier } else { 51711d9dfa5SMichael Klier return false; //callback error 51811d9dfa5SMichael Klier } 51911d9dfa5SMichael Klier} 52011d9dfa5SMichael Klier 52111d9dfa5SMichael Klier/** 52211d9dfa5SMichael Klier * Saves an uploaded media file 52311d9dfa5SMichael Klier * 52411d9dfa5SMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 52511d9dfa5SMichael Klier * @author Michael Klier <chi@chimeric.de> 526cbe26ad6SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 52742ea7f44SGerrit Uitslag * 52842ea7f44SGerrit Uitslag * @param string $fn_tmp 52942ea7f44SGerrit Uitslag * @param string $fn 53042ea7f44SGerrit Uitslag * @param string $id media id 53142ea7f44SGerrit Uitslag * @param string $imime mime type 53242ea7f44SGerrit Uitslag * @param bool $overwrite overwrite existing? 53342ea7f44SGerrit Uitslag * @param string $move function name 53442ea7f44SGerrit Uitslag * @return array|string 53511d9dfa5SMichael Klier */ 536d868eb89SAndreas Gohrfunction media_upload_finish($fn_tmp, $fn, $id, $imime, $overwrite, $move = 'move_uploaded_file') 537d868eb89SAndreas Gohr{ 53811d9dfa5SMichael Klier global $conf; 53911d9dfa5SMichael Klier global $lang; 5409c1bd4bcSKate Arzamastseva global $REV; 54111d9dfa5SMichael Klier 542e4f389efSKate Arzamastseva $old = @filemtime($fn); 54379e79377SAndreas Gohr if(!file_exists(mediaFN($id, $old)) && file_exists($fn)) { 544e4f389efSKate Arzamastseva // add old revision to the attic if missing 545cbe26ad6SKate Arzamastseva media_saveOldRevision($id); 546e4f389efSKate Arzamastseva } 547e4f389efSKate Arzamastseva 5483df72098SAndreas Gohr // prepare directory 549cc7d0c94SBen Coburn io_createNamespace($id, 'media'); 55011d9dfa5SMichael Klier 551ac3ed4afSGerrit Uitslag $filesize_old = file_exists($fn) ? filesize($fn) : 0; 552ac3ed4afSGerrit Uitslag 553ffb291f2SAdrian Lang if($move($fn_tmp, $fn)) { 55423846a98SKate Arzamastseva @clearstatcache(true, $fn); 555dad6764eSKate Arzamastseva $new = @filemtime($fn); 55674400ea5SBen Coburn // Set the correct permission here. 55774400ea5SBen Coburn // Always chmod media because they may be saved with different permissions than expected from the php umask. 55874400ea5SBen Coburn // (Should normally chmod to $conf['fperm'] only if $conf['fperm'] is set.) 55974400ea5SBen Coburn chmod($fn, $conf['fmode']); 5603df72098SAndreas Gohr msg($lang['uploadsucc'], 1); 56183734cddSPhy media_notify($id, $fn, $imime, $old, $new); 56299c8d7f2Smichael // add a log entry to the media changelog 563ac3ed4afSGerrit Uitslag $filesize_new = filesize($fn); 564ac3ed4afSGerrit Uitslag $sizechange = $filesize_new - $filesize_old; 5659c1bd4bcSKate Arzamastseva if($REV) { 56664159a61SAndreas Gohr addMediaLogEntry( 56764159a61SAndreas Gohr $new, 56864159a61SAndreas Gohr $id, 56964159a61SAndreas Gohr DOKU_CHANGE_TYPE_REVERT, 57064159a61SAndreas Gohr sprintf($lang['restored'], dformat($REV)), 57164159a61SAndreas Gohr $REV, 57264159a61SAndreas Gohr null, 57364159a61SAndreas Gohr $sizechange 57464159a61SAndreas Gohr ); 5759c1bd4bcSKate Arzamastseva } elseif($overwrite) { 576ac3ed4afSGerrit Uitslag addMediaLogEntry($new, $id, DOKU_CHANGE_TYPE_EDIT, '', '', null, $sizechange); 57799c8d7f2Smichael } else { 578ac3ed4afSGerrit Uitslag addMediaLogEntry($new, $id, DOKU_CHANGE_TYPE_CREATE, $lang['created'], '', null, $sizechange); 57999c8d7f2Smichael } 5803df72098SAndreas Gohr return $id; 5813df72098SAndreas Gohr }else{ 58224870174SAndreas Gohr return [$lang['uploadfail'], -1]; 5833df72098SAndreas Gohr } 5843df72098SAndreas Gohr} 5853df72098SAndreas Gohr 5868cb1eb01SAndreas Gohr/** 587cbe26ad6SKate Arzamastseva * Moves the current version of media file to the media_attic 588cbe26ad6SKate Arzamastseva * directory 589cbe26ad6SKate Arzamastseva * 590cbe26ad6SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 59142ea7f44SGerrit Uitslag * 592cbe26ad6SKate Arzamastseva * @param string $id 593cbe26ad6SKate Arzamastseva * @return int - revision date 594e4f389efSKate Arzamastseva */ 595d868eb89SAndreas Gohrfunction media_saveOldRevision($id) 596d868eb89SAndreas Gohr{ 597dbf57c96SKate Arzamastseva global $conf, $lang; 598dbf57c96SKate Arzamastseva 599e4f389efSKate Arzamastseva $oldf = mediaFN($id); 60079e79377SAndreas Gohr if (!file_exists($oldf)) return ''; 601e4f389efSKate Arzamastseva $date = filemtime($oldf); 602e5d185e1SKate Arzamastseva if (!$conf['mediarevisions']) return $date; 603e5d185e1SKate Arzamastseva 604047bad06SGerrit Uitslag $medialog = new MediaChangeLog($id); 605047bad06SGerrit Uitslag if (!$medialog->getRevisionInfo($date)) { 606dbf57c96SKate Arzamastseva // there was an external edit, 607dbf57c96SKate Arzamastseva // there is no log entry for current version of file 608ac3ed4afSGerrit Uitslag $sizechange = filesize($oldf); 60979e79377SAndreas Gohr if(!file_exists(mediaMetaFN($id, '.changes'))) { 610ac3ed4afSGerrit Uitslag addMediaLogEntry($date, $id, DOKU_CHANGE_TYPE_CREATE, $lang['created'], '', null, $sizechange); 611dbf57c96SKate Arzamastseva } else { 612ac3ed4afSGerrit Uitslag $oldRev = $medialog->getRevisions(-1, 1); // from changelog 613ac3ed4afSGerrit Uitslag $oldRev = (int) (empty($oldRev) ? 0 : $oldRev[0]); 614ac3ed4afSGerrit Uitslag $filesize_old = filesize(mediaFN($id, $oldRev)); 61524870174SAndreas Gohr $sizechange -= $filesize_old; 616ac3ed4afSGerrit Uitslag 617ac3ed4afSGerrit Uitslag addMediaLogEntry($date, $id, DOKU_CHANGE_TYPE_EDIT, '', '', null, $sizechange); 618dbf57c96SKate Arzamastseva } 619dbf57c96SKate Arzamastseva } 620dbf57c96SKate Arzamastseva 621e4f389efSKate Arzamastseva $newf = mediaFN($id, $date); 622e4f389efSKate Arzamastseva io_makeFileDir($newf); 623cbe26ad6SKate Arzamastseva if (copy($oldf, $newf)) { 624e4f389efSKate Arzamastseva // Set the correct permission here. 625e4f389efSKate Arzamastseva // Always chmod media because they may be saved with different permissions than expected from the php umask. 626e4f389efSKate Arzamastseva // (Should normally chmod to $conf['fperm'] only if $conf['fperm'] is set.) 627e4f389efSKate Arzamastseva chmod($newf, $conf['fmode']); 628e4f389efSKate Arzamastseva } 629e4f389efSKate Arzamastseva return $date; 630e4f389efSKate Arzamastseva} 631e4f389efSKate Arzamastseva 632e4f389efSKate Arzamastseva/** 6338cb1eb01SAndreas Gohr * This function checks if the uploaded content is really what the 63426ceae18SAndreas Gohr * mimetype says it is. We also do spam checking for text types here. 6358cb1eb01SAndreas Gohr * 6368cb1eb01SAndreas Gohr * We need to do this stuff because we can not rely on the browser 6378cb1eb01SAndreas Gohr * to do this check correctly. Yes, IE is broken as usual. 6388cb1eb01SAndreas Gohr * 6398cb1eb01SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 64026ceae18SAndreas Gohr * @link http://www.splitbrain.org/blog/2007-02/12-internet_explorer_facilitates_cross_site_scripting 6418cb1eb01SAndreas Gohr * @fixme check all 26 magic IE filetypes here? 64242ea7f44SGerrit Uitslag * 64342ea7f44SGerrit Uitslag * @param string $file path to file 64442ea7f44SGerrit Uitslag * @param string $mime mimetype 64542ea7f44SGerrit Uitslag * @return int 6468cb1eb01SAndreas Gohr */ 647d868eb89SAndreas Gohrfunction media_contentcheck($file, $mime) 648d868eb89SAndreas Gohr{ 64926ceae18SAndreas Gohr global $conf; 65026ceae18SAndreas Gohr if($conf['iexssprotect']){ 65126ceae18SAndreas Gohr $fh = @fopen($file, 'rb'); 65226ceae18SAndreas Gohr if($fh){ 65326ceae18SAndreas Gohr $bytes = fread($fh, 256); 65426ceae18SAndreas Gohr fclose($fh); 65526ceae18SAndreas Gohr if(preg_match('/<(script|a|img|html|body|iframe)[\s>]/i', $bytes)){ 65642ea7f44SGerrit Uitslag return -3; //XSS: possibly malicious content 65726ceae18SAndreas Gohr } 65826ceae18SAndreas Gohr } 65926ceae18SAndreas Gohr } 6608cb1eb01SAndreas Gohr if(substr($mime, 0, 6) == 'image/'){ 6618cb1eb01SAndreas Gohr $info = @getimagesize($file); 6628cb1eb01SAndreas Gohr if($mime == 'image/gif' && $info[2] != 1){ 66342ea7f44SGerrit Uitslag return -1; // uploaded content did not match the file extension 6648cb1eb01SAndreas Gohr }elseif($mime == 'image/jpeg' && $info[2] != 2){ 6658cb1eb01SAndreas Gohr return -1; 6668cb1eb01SAndreas Gohr }elseif($mime == 'image/png' && $info[2] != 3){ 6678cb1eb01SAndreas Gohr return -1; 6688cb1eb01SAndreas Gohr } 6698cb1eb01SAndreas Gohr # fixme maybe check other images types as well 6708cb1eb01SAndreas Gohr }elseif(substr($mime, 0, 5) == 'text/'){ 6718cb1eb01SAndreas Gohr global $TEXT; 6728cb1eb01SAndreas Gohr $TEXT = io_readFile($file); 6738cb1eb01SAndreas Gohr if(checkwordblock()){ 67442ea7f44SGerrit Uitslag return -2; //blocked by the spam blacklist 6758cb1eb01SAndreas Gohr } 6768cb1eb01SAndreas Gohr } 6778cb1eb01SAndreas Gohr return 0; 6788cb1eb01SAndreas Gohr} 6793df72098SAndreas Gohr 6803df72098SAndreas Gohr/** 68175030359SAndreas Gohr * Send a notify mail on uploads 68275030359SAndreas Gohr * 68375030359SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 68442ea7f44SGerrit Uitslag * 68542ea7f44SGerrit Uitslag * @param string $id media id 68642ea7f44SGerrit Uitslag * @param string $file path to file 68742ea7f44SGerrit Uitslag * @param string $mime mime type 68842ea7f44SGerrit Uitslag * @param bool|int $old_rev revision timestamp or false 68975030359SAndreas Gohr */ 690d868eb89SAndreas Gohrfunction media_notify($id, $file, $mime, $old_rev = false, $current_rev = false) 691d868eb89SAndreas Gohr{ 69275030359SAndreas Gohr global $conf; 69379a2d784SGerrit Uitslag if(empty($conf['notify'])) return; //notify enabled? 69475030359SAndreas Gohr 695704a815fSMichael Große $subscription = new MediaSubscriptionSender(); 69679a2d784SGerrit Uitslag $subscription->sendMediaDiff($conf['notify'], 'uploadmail', $id, $old_rev, $current_rev); 69775030359SAndreas Gohr} 69875030359SAndreas Gohr 69975030359SAndreas Gohr/** 7003df72098SAndreas Gohr * List all files in a given Media namespace 70142ea7f44SGerrit Uitslag * 70221d806cdSGerrit Uitslag * @param string $ns namespace 70342ea7f44SGerrit Uitslag * @param null|int $auth permission level 70442ea7f44SGerrit Uitslag * @param string $jump id 70542ea7f44SGerrit Uitslag * @param bool $fullscreenview 7068702de7fSGerrit Uitslag * @param bool|string $sort sorting order, false skips sorting 7073df72098SAndreas Gohr */ 708d868eb89SAndreas Gohrfunction media_filelist($ns, $auth = null, $jump = '', $fullscreenview = false, $sort = false) 709d868eb89SAndreas Gohr{ 7103df72098SAndreas Gohr global $conf; 7113df72098SAndreas Gohr global $lang; 7123df72098SAndreas Gohr $ns = cleanID($ns); 7133df72098SAndreas Gohr 7143df72098SAndreas Gohr // check auth our self if not given (needed for ajax calls) 7153df72098SAndreas Gohr if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 7163df72098SAndreas Gohr 717d9162c6cSKate Arzamastseva if (!$fullscreenview) echo '<h1 id="media__ns">:'.hsc($ns).'</h1>'.NL; 7183df72098SAndreas Gohr 7193df72098SAndreas Gohr if($auth < AUTH_READ){ 7203df72098SAndreas Gohr // FIXME: print permission warning here instead? 7213df72098SAndreas Gohr echo '<div class="nothing">'.$lang['nothingfound'].'</div>'.NL; 72256fe6664SAndreas Gohr }else{ 72389274c0dSChristopher Smith if (!$fullscreenview) { 72489274c0dSChristopher Smith media_uploadform($ns, $auth); 72589274c0dSChristopher Smith media_searchform($ns); 72689274c0dSChristopher Smith } 7273df72098SAndreas Gohr 7283df72098SAndreas Gohr $dir = utf8_encodeFN(str_replace(':', '/', $ns)); 72924870174SAndreas Gohr $data = []; 7304f33babfSAndreas Gohr search($data, $conf['mediadir'], 'search_mediafiles', 73124870174SAndreas Gohr ['showmsg'=>true, 'depth'=>1], $dir, 1, $sort); 7323df72098SAndreas Gohr 7333df72098SAndreas Gohr if(!count($data)){ 7343df72098SAndreas Gohr echo '<div class="nothing">'.$lang['nothingfound'].'</div>'.NL; 7355b9353faSKate Arzamastseva }else { 7365b9353faSKate Arzamastseva if ($fullscreenview) { 737554a8c9fSAdrian Lang echo '<ul class="' . _media_get_list_type() . '">'; 7385b9353faSKate Arzamastseva } 7395b9353faSKate Arzamastseva foreach($data as $item){ 7405b9353faSKate Arzamastseva if (!$fullscreenview) { 7414f33babfSAndreas Gohr //FIXME old call: media_printfile($item,$auth,$jump); 74279a2d784SGerrit Uitslag $display = new DisplayRow($item); 7439453716dSAndreas Gohr $display->scrollIntoView($jump == $item->getID()); 7444f33babfSAndreas Gohr $display->show(); 7455b9353faSKate Arzamastseva } else { 7464f33babfSAndreas Gohr //FIXME old call: media_printfile_thumbs($item,$auth,$jump); 7474f33babfSAndreas Gohr echo '<li>'; 74879a2d784SGerrit Uitslag $display = new DisplayTile($item); 7499453716dSAndreas Gohr $display->scrollIntoView($jump == $item->getID()); 7504f33babfSAndreas Gohr $display->show(); 7514f33babfSAndreas Gohr echo '</li>'; 7525b9353faSKate Arzamastseva } 7535b9353faSKate Arzamastseva } 75494add303SAnika Henke if ($fullscreenview) echo '</ul>'.NL; 7553df72098SAndreas Gohr } 75656fe6664SAndreas Gohr } 757d9162c6cSKate Arzamastseva} 758d9162c6cSKate Arzamastseva 759d9162c6cSKate Arzamastseva/** 760d9162c6cSKate Arzamastseva * Prints tabs for files list actions 761d9162c6cSKate Arzamastseva * 762d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 76395b451bcSAdrian Lang * @author Adrian Lang <mail@adrianlang.de> 76495b451bcSAdrian Lang * 765035e07f1SKate Arzamastseva * @param string $selected_tab - opened tab 766d9162c6cSKate Arzamastseva */ 76795b451bcSAdrian Lang 768d868eb89SAndreas Gohrfunction media_tabs_files($selected_tab = '') 769d868eb89SAndreas Gohr{ 770d9162c6cSKate Arzamastseva global $lang; 77124870174SAndreas Gohr $tabs = []; 77224870174SAndreas Gohr foreach([ 77324870174SAndreas Gohr 'files' => 'mediaselect', 77495b451bcSAdrian Lang 'upload' => 'media_uploadtab', 77524870174SAndreas Gohr 'search' => 'media_searchtab' 77624870174SAndreas Gohr ] as $tab => $caption) { 77724870174SAndreas Gohr $tabs[$tab] = [ 77824870174SAndreas Gohr 'href' => media_managerURL(['tab_files' => $tab], '&'), 77924870174SAndreas Gohr 'caption' => $lang[$caption] 78024870174SAndreas Gohr ]; 78195b451bcSAdrian Lang } 782d9162c6cSKate Arzamastseva 78395b451bcSAdrian Lang html_tabs($tabs, $selected_tab); 784d9162c6cSKate Arzamastseva} 785d9162c6cSKate Arzamastseva 786d9162c6cSKate Arzamastseva/** 787d9162c6cSKate Arzamastseva * Prints tabs for files details actions 788d9162c6cSKate Arzamastseva * 789d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 790ebc28e69SAndreas Gohr * @param string $image filename of the current image 791ebc28e69SAndreas Gohr * @param string $selected_tab opened tab 792d9162c6cSKate Arzamastseva */ 793d868eb89SAndreas Gohrfunction media_tabs_details($image, $selected_tab = '') 794d868eb89SAndreas Gohr{ 795e5d185e1SKate Arzamastseva global $lang, $conf; 796d9162c6cSKate Arzamastseva 79724870174SAndreas Gohr $tabs = []; 79824870174SAndreas Gohr $tabs['view'] = [ 79924870174SAndreas Gohr 'href' => media_managerURL(['tab_details' => 'view'], '&'), 80024870174SAndreas Gohr 'caption' => $lang['media_viewtab'] 80124870174SAndreas Gohr ]; 802d9162c6cSKate Arzamastseva 80324870174SAndreas Gohr [, $mime] = mimetype($image); 80479e79377SAndreas Gohr if ($mime == 'image/jpeg' && file_exists(mediaFN($image))) { 80524870174SAndreas Gohr $tabs['edit'] = [ 80624870174SAndreas Gohr 'href' => media_managerURL(['tab_details' => 'edit'], '&'), 80724870174SAndreas Gohr 'caption' => $lang['media_edittab'] 80824870174SAndreas Gohr ]; 809dd9ba38eSKate Arzamastseva } 810e5d185e1SKate Arzamastseva if ($conf['mediarevisions']) { 81124870174SAndreas Gohr $tabs['history'] = [ 81224870174SAndreas Gohr 'href' => media_managerURL(['tab_details' => 'history'], '&'), 81324870174SAndreas Gohr 'caption' => $lang['media_historytab'] 81424870174SAndreas Gohr ]; 815e5d185e1SKate Arzamastseva } 816d9162c6cSKate Arzamastseva 81795b451bcSAdrian Lang html_tabs($tabs, $selected_tab); 818d9162c6cSKate Arzamastseva} 819d9162c6cSKate Arzamastseva 820d9162c6cSKate Arzamastseva/** 821d9162c6cSKate Arzamastseva * Prints options for the tab that displays a list of all files 822d9162c6cSKate Arzamastseva * 823d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 824d9162c6cSKate Arzamastseva */ 825d868eb89SAndreas Gohrfunction media_tab_files_options() 826d868eb89SAndreas Gohr{ 8278108113cSTom N Harris global $lang; 8288108113cSTom N Harris global $INPUT; 829b7e5821dSAndreas Gohr global $ID; 830b960c74fSSatoshi Sahara 831b960c74fSSatoshi Sahara $form = new Form([ 832b960c74fSSatoshi Sahara 'method' => 'get', 833b960c74fSSatoshi Sahara 'action' => wl($ID), 834b960c74fSSatoshi Sahara 'class' => 'options' 835b960c74fSSatoshi Sahara ]); 836b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 837b960c74fSSatoshi Sahara $form->setHiddenField('sectok', null); 838b960c74fSSatoshi Sahara $media_manager_params = media_managerURL([], '', false, true); 83938b2bf35SAnika Henke foreach ($media_manager_params as $pKey => $pVal) { 840b960c74fSSatoshi Sahara $form->setHiddenField($pKey, $pVal); 84138b2bf35SAnika Henke } 8428108113cSTom N Harris if ($INPUT->has('q')) { 843b960c74fSSatoshi Sahara $form->setHiddenField('q', $INPUT->str('q')); 844554a8c9fSAdrian Lang } 845b960c74fSSatoshi Sahara $form->addHTML('<ul>'.NL); 84624870174SAndreas Gohr foreach ([ 84724870174SAndreas Gohr 'list' => ['listType', ['thumbs', 'rows']], 84824870174SAndreas Gohr 'sort' => ['sortBy', ['name', 'date']] 84924870174SAndreas Gohr ] as $group => $content) { 850ec88e837SAndreas Gohr $checked = "_media_get_{$group}_type"; 851554a8c9fSAdrian Lang $checked = $checked(); 852d9162c6cSKate Arzamastseva 853b960c74fSSatoshi Sahara $form->addHTML('<li class="'. $content[0] .'">'); 85495b451bcSAdrian Lang foreach ($content[1] as $option) { 85524870174SAndreas Gohr $attrs = []; 856554a8c9fSAdrian Lang if ($checked == $option) { 85795b451bcSAdrian Lang $attrs['checked'] = 'checked'; 85895b451bcSAdrian Lang } 859b960c74fSSatoshi Sahara $radio = $form->addRadioButton( 860b960c74fSSatoshi Sahara $group.'_dwmedia', 861b960c74fSSatoshi Sahara $lang['media_'.$group.'_'.$option] 862b960c74fSSatoshi Sahara )->val($option)->id($content[0].'__'.$option)->addClass($option); 863b960c74fSSatoshi Sahara $radio->attrs($attrs); 86495b451bcSAdrian Lang } 865b960c74fSSatoshi Sahara $form->addHTML('</li>'.NL); 86695b451bcSAdrian Lang } 867b960c74fSSatoshi Sahara $form->addHTML('<li>'); 868b960c74fSSatoshi Sahara $form->addButton('', $lang['btn_apply'])->attr('type', 'submit'); 869b960c74fSSatoshi Sahara $form->addHTML('</li>'.NL); 870b960c74fSSatoshi Sahara $form->addHTML('</ul>'.NL); 871b960c74fSSatoshi Sahara $form->addTagClose('div'); 872b960c74fSSatoshi Sahara print $form->toHTML(); 873d9162c6cSKate Arzamastseva} 874d9162c6cSKate Arzamastseva 875d9162c6cSKate Arzamastseva/** 87687deddfaSKate Arzamastseva * Returns type of sorting for the list of files in media manager 87787deddfaSKate Arzamastseva * 87887deddfaSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 87942ea7f44SGerrit Uitslag * 88087deddfaSKate Arzamastseva * @return string - sort type 88187deddfaSKate Arzamastseva */ 882d868eb89SAndreas Gohrfunction _media_get_sort_type() 883d868eb89SAndreas Gohr{ 88424870174SAndreas Gohr return _media_get_display_param('sort', ['default' => 'name', 'date']); 88587deddfaSKate Arzamastseva} 886554a8c9fSAdrian Lang 8876ffaeda9SGerrit Uitslag/** 8886ffaeda9SGerrit Uitslag * Returns type of listing for the list of files in media manager 8896ffaeda9SGerrit Uitslag * 8906ffaeda9SGerrit Uitslag * @author Kate Arzamastseva <pshns@ukr.net> 89142ea7f44SGerrit Uitslag * 8926ffaeda9SGerrit Uitslag * @return string - list type 8936ffaeda9SGerrit Uitslag */ 894d868eb89SAndreas Gohrfunction _media_get_list_type() 895d868eb89SAndreas Gohr{ 89624870174SAndreas Gohr return _media_get_display_param('list', ['default' => 'thumbs', 'rows']); 89787deddfaSKate Arzamastseva} 898554a8c9fSAdrian Lang 8996ffaeda9SGerrit Uitslag/** 9006ffaeda9SGerrit Uitslag * Get display parameters 9016ffaeda9SGerrit Uitslag * 9026ffaeda9SGerrit Uitslag * @param string $param name of parameter 9036ffaeda9SGerrit Uitslag * @param array $values allowed values, where default value has index key 'default' 9046ffaeda9SGerrit Uitslag * @return string the parameter value 9056ffaeda9SGerrit Uitslag */ 906d868eb89SAndreas Gohrfunction _media_get_display_param($param, $values) 907d868eb89SAndreas Gohr{ 9088108113cSTom N Harris global $INPUT; 9098108113cSTom N Harris if (in_array($INPUT->str($param), $values)) { 910554a8c9fSAdrian Lang // FIXME: Set cookie 9118108113cSTom N Harris return $INPUT->str($param); 912554a8c9fSAdrian Lang } else { 9133629bc8cSAdrian Lang $val = get_doku_pref($param, $values['default']); 9143629bc8cSAdrian Lang if (!in_array($val, $values)) { 9153629bc8cSAdrian Lang $val = $values['default']; 9163629bc8cSAdrian Lang } 9173629bc8cSAdrian Lang return $val; 918554a8c9fSAdrian Lang } 91987deddfaSKate Arzamastseva} 92087deddfaSKate Arzamastseva 92187deddfaSKate Arzamastseva/** 922d9162c6cSKate Arzamastseva * Prints tab that displays a list of all files 923d9162c6cSKate Arzamastseva * 924d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 92542ea7f44SGerrit Uitslag * 92642ea7f44SGerrit Uitslag * @param string $ns 92742ea7f44SGerrit Uitslag * @param null|int $auth permission level 92842ea7f44SGerrit Uitslag * @param string $jump item id 929d9162c6cSKate Arzamastseva */ 930d868eb89SAndreas Gohrfunction media_tab_files($ns, $auth = null, $jump = '') 931d868eb89SAndreas Gohr{ 932d9162c6cSKate Arzamastseva global $lang; 933d9162c6cSKate Arzamastseva if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 934d9162c6cSKate Arzamastseva 935d9162c6cSKate Arzamastseva if($auth < AUTH_READ){ 93688a71175SKate Arzamastseva echo '<div class="nothing">'.$lang['media_perm_read'].'</div>'.NL; 937d9162c6cSKate Arzamastseva }else{ 93895b451bcSAdrian Lang media_filelist($ns, $auth, $jump, true, _media_get_sort_type()); 939d9162c6cSKate Arzamastseva } 940d9162c6cSKate Arzamastseva} 941d9162c6cSKate Arzamastseva 942d9162c6cSKate Arzamastseva/** 943d9162c6cSKate Arzamastseva * Prints tab that displays uploading form 944d9162c6cSKate Arzamastseva * 945d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 94642ea7f44SGerrit Uitslag * 94742ea7f44SGerrit Uitslag * @param string $ns 94842ea7f44SGerrit Uitslag * @param null|int $auth permission level 94942ea7f44SGerrit Uitslag * @param string $jump item id 950d9162c6cSKate Arzamastseva */ 951d868eb89SAndreas Gohrfunction media_tab_upload($ns, $auth = null, $jump = '') 952d868eb89SAndreas Gohr{ 953d9162c6cSKate Arzamastseva global $lang; 954d9162c6cSKate Arzamastseva if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 955d9162c6cSKate Arzamastseva 95694add303SAnika Henke echo '<div class="upload">'.NL; 95795b451bcSAdrian Lang if ($auth >= AUTH_UPLOAD) { 95895b451bcSAdrian Lang echo '<p>' . $lang['mediaupload'] . '</p>'; 95995b451bcSAdrian Lang } 960d9162c6cSKate Arzamastseva media_uploadform($ns, $auth, true); 96194add303SAnika Henke echo '</div>'.NL; 962d9162c6cSKate Arzamastseva} 963d9162c6cSKate Arzamastseva 964d9162c6cSKate Arzamastseva/** 965d9162c6cSKate Arzamastseva * Prints tab that displays search form 966d9162c6cSKate Arzamastseva * 967d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 96842ea7f44SGerrit Uitslag * 96942ea7f44SGerrit Uitslag * @param string $ns 97042ea7f44SGerrit Uitslag * @param null|int $auth permission level 971d9162c6cSKate Arzamastseva */ 972d868eb89SAndreas Gohrfunction media_tab_search($ns, $auth = null) 973d868eb89SAndreas Gohr{ 9748108113cSTom N Harris global $INPUT; 975d9162c6cSKate Arzamastseva 9768108113cSTom N Harris $do = $INPUT->str('mediado'); 9778108113cSTom N Harris $query = $INPUT->str('q'); 97894add303SAnika Henke echo '<div class="search">'.NL; 979d9162c6cSKate Arzamastseva 980d9162c6cSKate Arzamastseva media_searchform($ns, $query, true); 9812dba8df4SAdrian Lang if ($do == 'searchlist' || $query) { 98295b451bcSAdrian Lang media_searchlist($query, $ns, $auth, true, _media_get_sort_type()); 98395b451bcSAdrian Lang } 98494add303SAnika Henke echo '</div>'.NL; 985d9162c6cSKate Arzamastseva} 986d9162c6cSKate Arzamastseva 987d9162c6cSKate Arzamastseva/** 988d9162c6cSKate Arzamastseva * Prints tab that displays mediafile details 989d9162c6cSKate Arzamastseva * 990d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 991e0c26282SGerrit Uitslag * 992e0c26282SGerrit Uitslag * @param string $image media id 993e0c26282SGerrit Uitslag * @param string $ns 994e0c26282SGerrit Uitslag * @param null|int $auth permission level 99542ea7f44SGerrit Uitslag * @param string|int $rev revision timestamp or empty string 996d9162c6cSKate Arzamastseva */ 997d868eb89SAndreas Gohrfunction media_tab_view($image, $ns, $auth = null, $rev = '') 998d868eb89SAndreas Gohr{ 999ebc28e69SAndreas Gohr global $lang; 1000d9162c6cSKate Arzamastseva if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 1001d9162c6cSKate Arzamastseva 1002e136d6ccSKate Arzamastseva if ($image && $auth >= AUTH_READ) { 1003dd9ba38eSKate Arzamastseva $meta = new JpegMeta(mediaFN($image, $rev)); 1004dd9ba38eSKate Arzamastseva media_preview($image, $auth, $rev, $meta); 1005e136d6ccSKate Arzamastseva media_preview_buttons($image, $auth, $rev); 1006dd9ba38eSKate Arzamastseva media_details($image, $auth, $rev, $meta); 1007e136d6ccSKate Arzamastseva 1008e136d6ccSKate Arzamastseva } else { 100994add303SAnika Henke echo '<div class="nothing">'.$lang['media_perm_read'].'</div>'.NL; 1010e136d6ccSKate Arzamastseva } 1011d9162c6cSKate Arzamastseva} 1012d9162c6cSKate Arzamastseva 1013d9162c6cSKate Arzamastseva/** 1014d9162c6cSKate Arzamastseva * Prints tab that displays form for editing mediafile metadata 1015d9162c6cSKate Arzamastseva * 1016d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1017e0c26282SGerrit Uitslag * 1018e0c26282SGerrit Uitslag * @param string $image media id 1019e0c26282SGerrit Uitslag * @param string $ns 1020e0c26282SGerrit Uitslag * @param null|int $auth permission level 1021d9162c6cSKate Arzamastseva */ 1022d868eb89SAndreas Gohrfunction media_tab_edit($image, $ns, $auth = null) 1023d868eb89SAndreas Gohr{ 1024d9162c6cSKate Arzamastseva if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 1025d9162c6cSKate Arzamastseva 10261eeeced2SKate Arzamastseva if ($image) { 102724870174SAndreas Gohr [, $mime] = mimetype($image); 102830fd72fbSKate Arzamastseva if ($mime == 'image/jpeg') media_metaform($image, $auth); 10291eeeced2SKate Arzamastseva } 1030d9162c6cSKate Arzamastseva} 1031d9162c6cSKate Arzamastseva 1032d9162c6cSKate Arzamastseva/** 1033d9162c6cSKate Arzamastseva * Prints tab that displays mediafile revisions 1034d9162c6cSKate Arzamastseva * 1035d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1036e0c26282SGerrit Uitslag * 1037e0c26282SGerrit Uitslag * @param string $image media id 1038e0c26282SGerrit Uitslag * @param string $ns 1039e0c26282SGerrit Uitslag * @param null|int $auth permission level 1040d9162c6cSKate Arzamastseva */ 1041d868eb89SAndreas Gohrfunction media_tab_history($image, $ns, $auth = null) 1042d868eb89SAndreas Gohr{ 1043d9162c6cSKate Arzamastseva global $lang; 10448108113cSTom N Harris global $INPUT; 10458108113cSTom N Harris 1046d9162c6cSKate Arzamastseva if(is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 10478108113cSTom N Harris $do = $INPUT->str('mediado'); 1048d9162c6cSKate Arzamastseva 10492e55802cSKate Arzamastseva if ($auth >= AUTH_READ && $image) { 10502e55802cSKate Arzamastseva if ($do == 'diff'){ 105124870174SAndreas Gohr (new MediaDiff($image))->show(); //media_diff($image, $ns, $auth); 10522e55802cSKate Arzamastseva } else { 1053a46cc3dcSAndreas Gohr $first = $INPUT->int('first', -1); 105424870174SAndreas Gohr (new MediaRevisions($image))->show($first); 10552e55802cSKate Arzamastseva } 105688a71175SKate Arzamastseva } else { 105788a71175SKate Arzamastseva echo '<div class="nothing">'.$lang['media_perm_read'].'</div>'.NL; 10582e55802cSKate Arzamastseva } 10593df72098SAndreas Gohr} 10603df72098SAndreas Gohr 10613df72098SAndreas Gohr/** 10621eeeced2SKate Arzamastseva * Prints mediafile details 10631eeeced2SKate Arzamastseva * 10646ffaeda9SGerrit Uitslag * @param string $image media id 1065e0c26282SGerrit Uitslag * @param int $auth permission level 106659bc3b48SGerrit Uitslag * @param int|string $rev revision timestamp or empty string 10676ffaeda9SGerrit Uitslag * @param JpegMeta|bool $meta 106842ea7f44SGerrit Uitslag * 10691eeeced2SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 10701eeeced2SKate Arzamastseva */ 1071d868eb89SAndreas Gohrfunction media_preview($image, $auth, $rev = '', $meta = false) 1072d868eb89SAndreas Gohr{ 1073e136d6ccSKate Arzamastseva 1074e136d6ccSKate Arzamastseva $size = media_image_preview_size($image, $rev, $meta); 1075e136d6ccSKate Arzamastseva 1076e136d6ccSKate Arzamastseva if ($size) { 107759f3611bSAnika Henke global $lang; 107894add303SAnika Henke echo '<div class="image">'; 107994add303SAnika Henke 108024870174SAndreas Gohr $more = []; 1081e136d6ccSKate Arzamastseva if ($rev) { 10825b9353faSKate Arzamastseva $more['rev'] = $rev; 1083e136d6ccSKate Arzamastseva } else { 1084e136d6ccSKate Arzamastseva $t = @filemtime(mediaFN($image)); 10855b9353faSKate Arzamastseva $more['t'] = $t; 108688a71175SKate Arzamastseva } 108723786fd7SKate Arzamastseva 10885b9353faSKate Arzamastseva $more['w'] = $size[0]; 10895b9353faSKate Arzamastseva $more['h'] = $size[1]; 1090e136d6ccSKate Arzamastseva $src = ml($image, $more); 109159f3611bSAnika Henke 109259f3611bSAnika Henke echo '<a href="'.$src.'" target="_blank" title="'.$lang['mediaview'].'">'; 109395b451bcSAdrian Lang echo '<img src="'.$src.'" alt="" style="max-width: '.$size[0].'px;" />'; 109459f3611bSAnika Henke echo '</a>'; 1095e136d6ccSKate Arzamastseva 1096871895a7SSatoshi Sahara echo '</div>'; 109794add303SAnika Henke } 1098e136d6ccSKate Arzamastseva} 1099e136d6ccSKate Arzamastseva 1100e136d6ccSKate Arzamastseva/** 1101e136d6ccSKate Arzamastseva * Prints mediafile action buttons 1102e136d6ccSKate Arzamastseva * 1103e136d6ccSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1104e0c26282SGerrit Uitslag * 1105e0c26282SGerrit Uitslag * @param string $image media id 1106e0c26282SGerrit Uitslag * @param int $auth permission level 1107871895a7SSatoshi Sahara * @param int|string $rev revision timestamp, or empty string 1108e136d6ccSKate Arzamastseva */ 1109d868eb89SAndreas Gohrfunction media_preview_buttons($image, $auth, $rev = '') 1110d868eb89SAndreas Gohr{ 1111e5d185e1SKate Arzamastseva global $lang, $conf; 1112e136d6ccSKate Arzamastseva 1113871895a7SSatoshi Sahara echo '<ul class="actions">'; 11141eeeced2SKate Arzamastseva 111579e79377SAndreas Gohr if ($auth >= AUTH_DELETE && !$rev && file_exists(mediaFN($image))) { 1116e136d6ccSKate Arzamastseva 1117e136d6ccSKate Arzamastseva // delete button 1118b960c74fSSatoshi Sahara $form = new Form([ 1119b960c74fSSatoshi Sahara 'id' => 'mediamanager__btn_delete', 1120b960c74fSSatoshi Sahara 'action' => media_managerURL(['delete' => $image], '&'), 1121b960c74fSSatoshi Sahara ]); 1122b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1123b960c74fSSatoshi Sahara $form->addButton('', $lang['btn_delete'])->attr('type', 'submit'); 1124b960c74fSSatoshi Sahara $form->addTagClose('div'); 112595b451bcSAdrian Lang echo '<li>'; 1126b960c74fSSatoshi Sahara echo $form->toHTML(); 1127871895a7SSatoshi Sahara echo '</li>'; 1128e5d185e1SKate Arzamastseva } 1129e5d185e1SKate Arzamastseva 1130e5d185e1SKate Arzamastseva $auth_ow = (($conf['mediarevisions']) ? AUTH_UPLOAD : AUTH_DELETE); 1131e5d185e1SKate Arzamastseva if ($auth >= $auth_ow && !$rev) { 1132e5d185e1SKate Arzamastseva 1133e136d6ccSKate Arzamastseva // upload new version button 1134b960c74fSSatoshi Sahara $form = new Form([ 1135b960c74fSSatoshi Sahara 'id' => 'mediamanager__btn_update', 1136b960c74fSSatoshi Sahara 'action' => media_managerURL(['image' => $image, 'mediado' => 'update'], '&'), 1137b960c74fSSatoshi Sahara ]); 1138b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1139b960c74fSSatoshi Sahara $form->addButton('', $lang['media_update'])->attr('type', 'submit'); 1140b960c74fSSatoshi Sahara $form->addTagClose('div'); 114195b451bcSAdrian Lang echo '<li>'; 1142b960c74fSSatoshi Sahara echo $form->toHTML(); 1143871895a7SSatoshi Sahara echo '</li>'; 114470c3cc9aSKate Arzamastseva } 1145e136d6ccSKate Arzamastseva 114679e79377SAndreas Gohr if ($auth >= AUTH_UPLOAD && $rev && $conf['mediarevisions'] && file_exists(mediaFN($image, $rev))) { 1147e136d6ccSKate Arzamastseva 1148e136d6ccSKate Arzamastseva // restore button 1149b960c74fSSatoshi Sahara $form = new Form([ 1150b960c74fSSatoshi Sahara 'id' => 'mediamanager__btn_restore', 1151b960c74fSSatoshi Sahara 'action'=>media_managerURL(['image' => $image], '&'), 1152b960c74fSSatoshi Sahara ]); 1153b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1154b960c74fSSatoshi Sahara $form->setHiddenField('mediado', 'restore'); 1155b960c74fSSatoshi Sahara $form->setHiddenField('rev', $rev); 1156b960c74fSSatoshi Sahara $form->addButton('', $lang['media_restore'])->attr('type', 'submit'); 1157b960c74fSSatoshi Sahara $form->addTagClose('div'); 115895b451bcSAdrian Lang echo '<li>'; 1159b960c74fSSatoshi Sahara echo $form->toHTML(); 1160871895a7SSatoshi Sahara echo '</li>'; 11619c1bd4bcSKate Arzamastseva } 1162e136d6ccSKate Arzamastseva 1163871895a7SSatoshi Sahara echo '</ul>'; 11642e55802cSKate Arzamastseva} 11652e55802cSKate Arzamastseva 11662e55802cSKate Arzamastseva/** 1167fa8e5c77SKate Arzamastseva * Returns image width and height for mediamanager preview panel 1168fa8e5c77SKate Arzamastseva * 1169fa8e5c77SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1170fa8e5c77SKate Arzamastseva * @param string $image 1171e0c26282SGerrit Uitslag * @param int|string $rev 117259bc3b48SGerrit Uitslag * @param JpegMeta|bool $meta 1173ebc28e69SAndreas Gohr * @param int $size 1174871895a7SSatoshi Sahara * @return array 1175fa8e5c77SKate Arzamastseva */ 1176d868eb89SAndreas Gohrfunction media_image_preview_size($image, $rev, $meta = false, $size = 500) 1177d868eb89SAndreas Gohr{ 1178871895a7SSatoshi Sahara if (!preg_match("/\.(jpe?g|gif|png)$/", $image) 1179871895a7SSatoshi Sahara || !file_exists($filename = mediaFN($image, $rev)) 118024870174SAndreas Gohr ) return []; 1181fa8e5c77SKate Arzamastseva 1182871895a7SSatoshi Sahara $info = getimagesize($filename); 118324870174SAndreas Gohr $w = $info[0]; 118424870174SAndreas Gohr $h = $info[1]; 1185fa8e5c77SKate Arzamastseva 1186fa8e5c77SKate Arzamastseva if ($meta && ($w > $size || $h > $size)) { 1187fa8e5c77SKate Arzamastseva $ratio = $meta->getResizeRatio($size, $size); 1188fa8e5c77SKate Arzamastseva $w = floor($w * $ratio); 1189fa8e5c77SKate Arzamastseva $h = floor($h * $ratio); 1190fa8e5c77SKate Arzamastseva } 119124870174SAndreas Gohr return [$w, $h]; 1192fa8e5c77SKate Arzamastseva} 1193fa8e5c77SKate Arzamastseva 1194fa8e5c77SKate Arzamastseva/** 1195fa8e5c77SKate Arzamastseva * Returns the requested EXIF/IPTC tag from the image meta 1196fa8e5c77SKate Arzamastseva * 1197fa8e5c77SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1198e0c26282SGerrit Uitslag * 119942ea7f44SGerrit Uitslag * @param array $tags array with tags, first existing is returned 1200fa8e5c77SKate Arzamastseva * @param JpegMeta $meta 120142ea7f44SGerrit Uitslag * @param string $alt alternative value 1202fa8e5c77SKate Arzamastseva * @return string 1203fa8e5c77SKate Arzamastseva */ 1204d868eb89SAndreas Gohrfunction media_getTag($tags, $meta = false, $alt = '') 1205d868eb89SAndreas Gohr{ 1206871895a7SSatoshi Sahara if (!$meta) return $alt; 1207fa8e5c77SKate Arzamastseva $info = $meta->getField($tags); 1208871895a7SSatoshi Sahara if (!$info) return $alt; 1209fa8e5c77SKate Arzamastseva return $info; 1210fa8e5c77SKate Arzamastseva} 1211fa8e5c77SKate Arzamastseva 1212fa8e5c77SKate Arzamastseva/** 1213e136d6ccSKate Arzamastseva * Returns mediafile tags 12142e55802cSKate Arzamastseva * 12152e55802cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1216e0c26282SGerrit Uitslag * 1217e136d6ccSKate Arzamastseva * @param JpegMeta $meta 121842ea7f44SGerrit Uitslag * @return array list of tags of the mediafile 12192e55802cSKate Arzamastseva */ 1220d868eb89SAndreas Gohrfunction media_file_tags($meta) 1221d868eb89SAndreas Gohr{ 1222532850edSKate Arzamastseva // load the field descriptions 12233e98e685SKate Arzamastseva static $fields = null; 12243e98e685SKate Arzamastseva if (is_null($fields)) { 12253e98e685SKate Arzamastseva $config_files = getConfigFiles('mediameta'); 12263e98e685SKate Arzamastseva foreach ($config_files as $config_file) { 122779e79377SAndreas Gohr if (file_exists($config_file)) include($config_file); 1228532850edSKate Arzamastseva } 1229532850edSKate Arzamastseva } 12301eeeced2SKate Arzamastseva 123124870174SAndreas Gohr $tags = []; 1232dd9ba38eSKate Arzamastseva 123324870174SAndreas Gohr foreach ($fields as $tag) { 123424870174SAndreas Gohr $t = []; 123524870174SAndreas Gohr if (!empty($tag[0])) $t = [$tag[0]]; 12360e80bb5eSChristopher Smith if (isset($tag[3]) && is_array($tag[3])) $t = array_merge($t, $tag[3]); 1237e136d6ccSKate Arzamastseva $value = media_getTag($t, $meta); 123824870174SAndreas Gohr $tags[] = ['tag' => $tag, 'value' => $value]; 1239e136d6ccSKate Arzamastseva } 1240e136d6ccSKate Arzamastseva 1241e136d6ccSKate Arzamastseva return $tags; 1242e136d6ccSKate Arzamastseva} 1243e136d6ccSKate Arzamastseva 1244e136d6ccSKate Arzamastseva/** 1245e136d6ccSKate Arzamastseva * Prints mediafile tags 1246e136d6ccSKate Arzamastseva * 1247e136d6ccSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 124842ea7f44SGerrit Uitslag * 1249e0c26282SGerrit Uitslag * @param string $image image id 1250e0c26282SGerrit Uitslag * @param int $auth permission level 1251e0c26282SGerrit Uitslag * @param string|int $rev revision timestamp, or empty string 1252e0c26282SGerrit Uitslag * @param bool|JpegMeta $meta image object, or create one if false 1253e0c26282SGerrit Uitslag */ 1254d868eb89SAndreas Gohrfunction media_details($image, $auth, $rev = '', $meta = false) 1255d868eb89SAndreas Gohr{ 1256e136d6ccSKate Arzamastseva global $lang; 1257e136d6ccSKate Arzamastseva 1258e136d6ccSKate Arzamastseva if (!$meta) $meta = new JpegMeta(mediaFN($image, $rev)); 1259e136d6ccSKate Arzamastseva $tags = media_file_tags($meta); 1260e136d6ccSKate Arzamastseva 126194add303SAnika Henke echo '<dl>'.NL; 1262e136d6ccSKate Arzamastseva foreach($tags as $tag){ 1263e136d6ccSKate Arzamastseva if ($tag['value']) { 1264e136d6ccSKate Arzamastseva $value = cleanText($tag['value']); 1265fde860beSGerrit Uitslag echo '<dt>'.$lang[$tag['tag'][1]].'</dt><dd>'; 1266e136d6ccSKate Arzamastseva if ($tag['tag'][2] == 'date') echo dformat($value); 12673e98e685SKate Arzamastseva else echo hsc($value); 126894add303SAnika Henke echo '</dd>'.NL; 12691eeeced2SKate Arzamastseva } 1270e136d6ccSKate Arzamastseva } 127194add303SAnika Henke echo '</dl>'.NL; 127222e68399Sflammy echo '<dl>'.NL; 127322e68399Sflammy echo '<dt>'.$lang['reference'].':</dt>'; 127422e68399Sflammy $media_usage = ft_mediause($image, true); 127524870174SAndreas Gohr if($media_usage !== []){ 127622e68399Sflammy foreach($media_usage as $path){ 127722e68399Sflammy echo '<dd>'.html_wikilink($path).'</dd>'; 127822e68399Sflammy } 127922e68399Sflammy }else{ 128022e68399Sflammy echo '<dd>'.$lang['nothingfound'].'</dd>'; 128122e68399Sflammy } 128222e68399Sflammy echo '</dl>'.NL; 128322e68399Sflammy 12841eeeced2SKate Arzamastseva} 12852e55802cSKate Arzamastseva 12862e55802cSKate Arzamastseva/** 12872e55802cSKate Arzamastseva * Shows difference between two revisions of file 12882e55802cSKate Arzamastseva * 12892e55802cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 129042ea7f44SGerrit Uitslag * 1291e0c26282SGerrit Uitslag * @param string $image image id 1292e0c26282SGerrit Uitslag * @param string $ns 1293e0c26282SGerrit Uitslag * @param int $auth permission level 1294e0c26282SGerrit Uitslag * @param bool $fromajax 129579a2d784SGerrit Uitslag * 1296297071beSSatoshi Sahara * @deprecated 2020-12-31 1297e0c26282SGerrit Uitslag */ 1298d868eb89SAndreas Gohrfunction media_diff($image, $ns, $auth, $fromajax = false) 1299d868eb89SAndreas Gohr{ 130079a2d784SGerrit Uitslag dbg_deprecated('see '. MediaDiff::class .'::show()'); 130159e81a43SKate Arzamastseva} 130259e81a43SKate Arzamastseva 13036ffaeda9SGerrit Uitslag/** 13046ffaeda9SGerrit Uitslag * Callback for media file diff 13056ffaeda9SGerrit Uitslag * 130642ea7f44SGerrit Uitslag * @param array $data event data 130779a2d784SGerrit Uitslag * 1308297071beSSatoshi Sahara * @deprecated 2020-12-31 13096ffaeda9SGerrit Uitslag */ 1310d868eb89SAndreas Gohrfunction _media_file_diff($data) 1311d868eb89SAndreas Gohr{ 131279a2d784SGerrit Uitslag dbg_deprecated('see '. MediaDiff::class .'::show()'); 131359e81a43SKate Arzamastseva} 131459e81a43SKate Arzamastseva 131559e81a43SKate Arzamastseva/** 131659e81a43SKate Arzamastseva * Shows difference between two revisions of image 131759e81a43SKate Arzamastseva * 131859e81a43SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1319e0c26282SGerrit Uitslag * 1320e0c26282SGerrit Uitslag * @param string $image 1321e0c26282SGerrit Uitslag * @param string|int $l_rev revision timestamp, or empty string 1322e0c26282SGerrit Uitslag * @param string|int $r_rev revision timestamp, or empty string 1323e0c26282SGerrit Uitslag * @param string $ns 1324e0c26282SGerrit Uitslag * @param int $auth permission level 1325e0c26282SGerrit Uitslag * @param bool $fromajax 1326297071beSSatoshi Sahara * @deprecated 2020-12-31 132759e81a43SKate Arzamastseva */ 1328d868eb89SAndreas Gohrfunction media_file_diff($image, $l_rev, $r_rev, $ns, $auth, $fromajax) 1329d868eb89SAndreas Gohr{ 133079a2d784SGerrit Uitslag dbg_deprecated('see '. MediaDiff::class .'::showFileDiff()'); 1331e136d6ccSKate Arzamastseva} 1332e136d6ccSKate Arzamastseva 1333e136d6ccSKate Arzamastseva/** 1334e136d6ccSKate Arzamastseva * Prints two images side by side 1335fa8e5c77SKate Arzamastseva * and slider 1336e136d6ccSKate Arzamastseva * 1337e136d6ccSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 133842ea7f44SGerrit Uitslag * 133942ea7f44SGerrit Uitslag * @param string $image image id 1340e0c26282SGerrit Uitslag * @param int $l_rev revision timestamp, or empty string 1341e0c26282SGerrit Uitslag * @param int $r_rev revision timestamp, or empty string 134242ea7f44SGerrit Uitslag * @param array $l_size array with width and height 134342ea7f44SGerrit Uitslag * @param array $r_size array with width and height 134450fc55feSKate Arzamastseva * @param string $type 1345297071beSSatoshi Sahara * @deprecated 2020-12-31 1346e136d6ccSKate Arzamastseva */ 1347d868eb89SAndreas Gohrfunction media_image_diff($image, $l_rev, $r_rev, $l_size, $r_size, $type) 1348d868eb89SAndreas Gohr{ 134979a2d784SGerrit Uitslag dbg_deprecated('see '. MediaDiff::class .'::showImageDiff()'); 13501eeeced2SKate Arzamastseva} 13511eeeced2SKate Arzamastseva 13521eeeced2SKate Arzamastseva/** 13539c1bd4bcSKate Arzamastseva * Restores an old revision of a media file 13549c1bd4bcSKate Arzamastseva * 135542ea7f44SGerrit Uitslag * @param string $image media id 135642ea7f44SGerrit Uitslag * @param int $rev revision timestamp or empty string 13579c1bd4bcSKate Arzamastseva * @param int $auth 13589c1bd4bcSKate Arzamastseva * @return string - file's id 135942ea7f44SGerrit Uitslag * 13609c1bd4bcSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 13619c1bd4bcSKate Arzamastseva */ 1362d868eb89SAndreas Gohrfunction media_restore($image, $rev, $auth) 1363d868eb89SAndreas Gohr{ 1364e5d185e1SKate Arzamastseva global $conf; 136580525638SKate Arzamastseva if ($auth < AUTH_UPLOAD || !$conf['mediarevisions']) return false; 136692cac9a9SKate Arzamastseva $removed = (!file_exists(mediaFN($image)) && file_exists(mediaMetaFN($image, '.changes'))); 136792cac9a9SKate Arzamastseva if (!$image || (!file_exists(mediaFN($image)) && !$removed)) return false; 13689c1bd4bcSKate Arzamastseva if (!$rev || !file_exists(mediaFN($image, $rev))) return false; 136924870174SAndreas Gohr [, $imime, ] = mimetype($image); 13709c1bd4bcSKate Arzamastseva $res = media_upload_finish(mediaFN($image, $rev), 13719c1bd4bcSKate Arzamastseva mediaFN($image), 13729c1bd4bcSKate Arzamastseva $image, 13739c1bd4bcSKate Arzamastseva $imime, 13749c1bd4bcSKate Arzamastseva true, 13759c1bd4bcSKate Arzamastseva 'copy'); 13769c1bd4bcSKate Arzamastseva if (is_array($res)) { 13779c1bd4bcSKate Arzamastseva msg($res[0], $res[1]); 13789c1bd4bcSKate Arzamastseva return false; 13799c1bd4bcSKate Arzamastseva } 13809c1bd4bcSKate Arzamastseva return $res; 13819c1bd4bcSKate Arzamastseva} 13829c1bd4bcSKate Arzamastseva 13839c1bd4bcSKate Arzamastseva/** 1384bf1f3ac4Ssarnowski * List all files found by the search request 1385c9f56829SAndreas Gohr * 1386c9f56829SAndreas Gohr * @author Tobias Sarnowski <sarnowski@cosmocode.de> 1387c9f56829SAndreas Gohr * @author Andreas Gohr <gohr@cosmocode.de> 1388d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1389c9f56829SAndreas Gohr * @triggers MEDIA_SEARCH 1390e0c26282SGerrit Uitslag * 1391e0c26282SGerrit Uitslag * @param string $query 1392e0c26282SGerrit Uitslag * @param string $ns 1393e0c26282SGerrit Uitslag * @param null|int $auth 1394e0c26282SGerrit Uitslag * @param bool $fullscreen 1395e0c26282SGerrit Uitslag * @param string $sort 1396bf1f3ac4Ssarnowski */ 1397d868eb89SAndreas Gohrfunction media_searchlist($query, $ns, $auth = null, $fullscreen = false, $sort = 'natural') 1398d868eb89SAndreas Gohr{ 1399bf1f3ac4Ssarnowski global $conf; 1400bf1f3ac4Ssarnowski global $lang; 14018e69fd30SKate Arzamastseva 1402bf1f3ac4Ssarnowski $ns = cleanID($ns); 140324870174SAndreas Gohr $evdata = [ 140456fe6664SAndreas Gohr 'ns' => $ns, 140524870174SAndreas Gohr 'data' => [], 140656fe6664SAndreas Gohr 'query' => $query 140724870174SAndreas Gohr ]; 14087ed31746SSzymon Olewniczak if (!blank($query)) { 1409e1d9dcc8SAndreas Gohr $evt = new Event('MEDIA_SEARCH', $evdata); 1410bf1f3ac4Ssarnowski if ($evt->advise_before()) { 141156fe6664SAndreas Gohr $dir = utf8_encodeFN(str_replace(':', '/', $evdata['ns'])); 141276472096SSzymon Olewniczak $quoted = preg_quote($evdata['query'], '/'); 141376472096SSzymon Olewniczak //apply globbing 141424870174SAndreas Gohr $quoted = str_replace(['\*', '\?'], ['.*', '.'], $quoted, $count); 141523e31e76SSzymon Olewniczak 141623e31e76SSzymon Olewniczak //if we use globbing file name must match entirely but may be preceded by arbitrary namespace 141723e31e76SSzymon Olewniczak if ($count > 0) $quoted = '^([^:]*:)*'.$quoted.'$'; 141823e31e76SSzymon Olewniczak 141976472096SSzymon Olewniczak $pattern = '/'.$quoted.'/i'; 142056fe6664SAndreas Gohr search($evdata['data'], 142156fe6664SAndreas Gohr $conf['mediadir'], 14224f33babfSAndreas Gohr 'search_mediafiles', 142324870174SAndreas Gohr ['showmsg'=>false, 'pattern'=>$pattern], 142400e3e394SChristopher Smith $dir, 142500e3e394SChristopher Smith 1, 142600e3e394SChristopher Smith $sort); 1427bf1f3ac4Ssarnowski } 1428bf1f3ac4Ssarnowski $evt->advise_after(); 1429bf1f3ac4Ssarnowski unset($evt); 143056fe6664SAndreas Gohr } 1431bf1f3ac4Ssarnowski 1432d9162c6cSKate Arzamastseva if (!$fullscreen) { 143356fe6664SAndreas Gohr echo '<h1 id="media__ns">'.sprintf($lang['searchmedia_in'], hsc($ns).':*').'</h1>'.NL; 143456fe6664SAndreas Gohr media_searchform($ns, $query); 1435d9162c6cSKate Arzamastseva } 143656fe6664SAndreas Gohr 143756fe6664SAndreas Gohr if(!count($evdata['data'])){ 1438bf1f3ac4Ssarnowski echo '<div class="nothing">'.$lang['nothingfound'].'</div>'.NL; 14395b9353faSKate Arzamastseva }else { 14405b9353faSKate Arzamastseva if ($fullscreen) { 1441554a8c9fSAdrian Lang echo '<ul class="' . _media_get_list_type() . '">'; 14425b9353faSKate Arzamastseva } 14435b9353faSKate Arzamastseva foreach($evdata['data'] as $item){ 14444f33babfSAndreas Gohr if (!$fullscreen) { 14454f33babfSAndreas Gohr // FIXME old call: media_printfile($item,$item['perm'],'',true); 144679a2d784SGerrit Uitslag $display = new DisplayRow($item); 144779b00823SAndreas Gohr $display->relativeDisplay($ns); 14484f33babfSAndreas Gohr $display->show(); 14494f33babfSAndreas Gohr } else { 14504f33babfSAndreas Gohr // FIXME old call: media_printfile_thumbs($item,$item['perm'],false,true); 145179a2d784SGerrit Uitslag $display = new DisplayTile($item); 145279b00823SAndreas Gohr $display->relativeDisplay($ns); 14534f33babfSAndreas Gohr echo '<li>'; 14544f33babfSAndreas Gohr $display->show(); 14554f33babfSAndreas Gohr echo '</li>'; 14564f33babfSAndreas Gohr } 1457bf1f3ac4Ssarnowski } 145894add303SAnika Henke if ($fullscreen) echo '</ul>'.NL; 14595b9353faSKate Arzamastseva } 1460bf1f3ac4Ssarnowski} 1461bf1f3ac4Ssarnowski 1462bf1f3ac4Ssarnowski/** 1463c6571d58SAndreas Gohr * Display a media icon 1464c6571d58SAndreas Gohr * 146542ea7f44SGerrit Uitslag * @param string $filename media id 1466c6571d58SAndreas Gohr * @param string $size the size subfolder, if not specified 16x16 is used 146742ea7f44SGerrit Uitslag * @return string html 1468c6571d58SAndreas Gohr */ 1469d868eb89SAndreas Gohrfunction media_printicon($filename, $size = '') 1470d868eb89SAndreas Gohr{ 147124870174SAndreas Gohr [$ext] = mimetype(mediaFN($filename), false); 147223786fd7SKate Arzamastseva 147379e79377SAndreas Gohr if (file_exists(DOKU_INC.'lib/images/fileicons/'.$size.'/'.$ext.'.png')) { 1474c6571d58SAndreas Gohr $icon = DOKU_BASE.'lib/images/fileicons/'.$size.'/'.$ext.'.png'; 147523786fd7SKate Arzamastseva } else { 1476c6571d58SAndreas Gohr $icon = DOKU_BASE.'lib/images/fileicons/'.$size.'/file.png'; 147723786fd7SKate Arzamastseva } 147823786fd7SKate Arzamastseva 1479421ec38eSKate Arzamastseva return '<img src="'.$icon.'" alt="'.$filename.'" class="icon" />'; 148023786fd7SKate Arzamastseva} 148123786fd7SKate Arzamastseva 14823df72098SAndreas Gohr/** 148342ea7f44SGerrit Uitslag * Build link based on the current, adding/rewriting parameters 1484d9162c6cSKate Arzamastseva * 1485d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 148642ea7f44SGerrit Uitslag * 1487ebc28e69SAndreas Gohr * @param array|bool $params 148842ea7f44SGerrit Uitslag * @param string $amp separator 148942ea7f44SGerrit Uitslag * @param bool $abs absolute url? 149042ea7f44SGerrit Uitslag * @param bool $params_array return the parmeters array? 149142ea7f44SGerrit Uitslag * @return string|array - link or link parameters 1492d9162c6cSKate Arzamastseva */ 1493d868eb89SAndreas Gohrfunction media_managerURL($params = false, $amp = '&', $abs = false, $params_array = false) 1494d868eb89SAndreas Gohr{ 1495d9162c6cSKate Arzamastseva global $ID; 14968108113cSTom N Harris global $INPUT; 1497d9162c6cSKate Arzamastseva 149824870174SAndreas Gohr $gets = ['do' => 'media']; 149924870174SAndreas Gohr $media_manager_params = ['tab_files', 'tab_details', 'image', 'ns', 'list', 'sort']; 150023846a98SKate Arzamastseva foreach ($media_manager_params as $x) { 15018108113cSTom N Harris if ($INPUT->has($x)) $gets[$x] = $INPUT->str($x); 150223846a98SKate Arzamastseva } 1503d9162c6cSKate Arzamastseva 1504d9162c6cSKate Arzamastseva if ($params) { 1505554a8c9fSAdrian Lang $gets = $params + $gets; 1506d9162c6cSKate Arzamastseva } 1507d9162c6cSKate Arzamastseva unset($gets['id']); 1508554a8c9fSAdrian Lang if (isset($gets['delete'])) { 15091eeeced2SKate Arzamastseva unset($gets['image']); 15101eeeced2SKate Arzamastseva unset($gets['tab_details']); 15111eeeced2SKate Arzamastseva } 1512d9162c6cSKate Arzamastseva 1513035e07f1SKate Arzamastseva if ($params_array) return $gets; 1514035e07f1SKate Arzamastseva 15156dd095f5SKate Arzamastseva return wl($ID, $gets, $abs, $amp); 1516d9162c6cSKate Arzamastseva} 1517d9162c6cSKate Arzamastseva 1518d9162c6cSKate Arzamastseva/** 15193df72098SAndreas Gohr * Print the media upload form if permissions are correct 15203df72098SAndreas Gohr * 15213df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 1522d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1523e0c26282SGerrit Uitslag * 1524e0c26282SGerrit Uitslag * @param string $ns 1525e0c26282SGerrit Uitslag * @param int $auth permission level 1526e0c26282SGerrit Uitslag * @param bool $fullscreen 15273df72098SAndreas Gohr */ 1528d868eb89SAndreas Gohrfunction media_uploadform($ns, $auth, $fullscreen = false) 1529d868eb89SAndreas Gohr{ 15308108113cSTom N Harris global $lang; 15318108113cSTom N Harris global $conf; 15328108113cSTom N Harris global $INPUT; 15333df72098SAndreas Gohr 153488a71175SKate Arzamastseva if ($auth < AUTH_UPLOAD) { 153588a71175SKate Arzamastseva echo '<div class="nothing">'.$lang['media_perm_upload'].'</div>'.NL; 153688a71175SKate Arzamastseva return; 153788a71175SKate Arzamastseva } 153892cac9a9SKate Arzamastseva $auth_ow = (($conf['mediarevisions']) ? AUTH_UPLOAD : AUTH_DELETE); 15393df72098SAndreas Gohr 154070c3cc9aSKate Arzamastseva $update = false; 154170c3cc9aSKate Arzamastseva $id = ''; 15428108113cSTom N Harris if ($auth >= $auth_ow && $fullscreen && $INPUT->str('mediado') == 'update') { 154370c3cc9aSKate Arzamastseva $update = true; 15448108113cSTom N Harris $id = cleanID($INPUT->str('image')); 154570c3cc9aSKate Arzamastseva } 154670c3cc9aSKate Arzamastseva 1547d00ec455SAndreas Gohr // The default HTML upload form 1548b960c74fSSatoshi Sahara $form = new Form([ 1549b960c74fSSatoshi Sahara 'id' => 'dw__upload', 1550b960c74fSSatoshi Sahara 'enctype' => 'multipart/form-data', 1551b960c74fSSatoshi Sahara 'action' => ($fullscreen) 1552b960c74fSSatoshi Sahara ? media_managerURL(['tab_files' => 'files', 'tab_details' => 'view'], '&') 1553b960c74fSSatoshi Sahara : DOKU_BASE.'lib/exe/mediamanager.php', 1554b960c74fSSatoshi Sahara ]); 1555b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1556b960c74fSSatoshi Sahara $form->setHiddenField('ns', hsc($ns)); // FIXME hsc required? 1557b960c74fSSatoshi Sahara $form->addTagOpen('p'); 1558b960c74fSSatoshi Sahara $form->addTextInput('upload', $lang['txt_upload'])->id('upload__file') 1559b960c74fSSatoshi Sahara ->attrs(['type' => 'file']); 1560b960c74fSSatoshi Sahara $form->addTagClose('p'); 1561b960c74fSSatoshi Sahara $form->addTagOpen('p'); 1562b960c74fSSatoshi Sahara $form->addTextInput('mediaid', $lang['txt_filename'])->id('upload__name') 1563b960c74fSSatoshi Sahara ->val(noNS($id)); 1564b960c74fSSatoshi Sahara $form->addButton('', $lang['btn_upload'])->attr('type', 'submit'); 1565b960c74fSSatoshi Sahara $form->addTagClose('p'); 156692cac9a9SKate Arzamastseva if ($auth >= $auth_ow){ 1567b960c74fSSatoshi Sahara $form->addTagOpen('p'); 156824870174SAndreas Gohr $attrs = []; 156970c3cc9aSKate Arzamastseva if ($update) $attrs['checked'] = 'checked'; 1570b960c74fSSatoshi Sahara $form->addCheckbox('ow', $lang['txt_overwrt'])->id('dw__ow')->val('1') 1571b960c74fSSatoshi Sahara ->addClass('check')->attrs($attrs); 1572b960c74fSSatoshi Sahara $form->addTagClose('p'); 1573b960c74fSSatoshi Sahara } 1574b960c74fSSatoshi Sahara $form->addTagClose('div'); 1575b960c74fSSatoshi Sahara 1576b960c74fSSatoshi Sahara if (!$fullscreen) { 1577b960c74fSSatoshi Sahara echo '<div class="upload">'. $lang['mediaupload'] .'</div>'.DOKU_LF; 1578b960c74fSSatoshi Sahara } else { 1579b960c74fSSatoshi Sahara echo DOKU_LF; 15803df72098SAndreas Gohr } 1581c472bad9SKate Arzamastseva 1582b960c74fSSatoshi Sahara echo '<div id="mediamanager__uploader">'.DOKU_LF; 1583c6977b3aSSatoshi Sahara echo $form->toHTML('Upload'); 1584b960c74fSSatoshi Sahara echo '</div>'.DOKU_LF; 1585f940e4a0SAndreas Gohr 1586f940e4a0SAndreas Gohr echo '<p class="maxsize">'; 1587f940e4a0SAndreas Gohr printf($lang['maxuploadsize'], filesize_h(media_getuploadsize())); 158856fc6b15SAnna Dabrowska echo ' <a class="allowedmime" href="#">'. $lang['allowedmime'] .'</a>'; 1589499d9bcdSAndreas Gohr echo ' <span>'. implode(', ', array_keys(getMimeTypes())) .'</span>'; 1590b960c74fSSatoshi Sahara echo '</p>'.DOKU_LF; 1591f940e4a0SAndreas Gohr} 1592f940e4a0SAndreas Gohr 1593f940e4a0SAndreas Gohr/** 1594f940e4a0SAndreas Gohr * Returns the size uploaded files may have 1595f940e4a0SAndreas Gohr * 1596f940e4a0SAndreas Gohr * This uses a conservative approach using the lowest number found 1597f940e4a0SAndreas Gohr * in any of the limiting ini settings 1598f940e4a0SAndreas Gohr * 1599f940e4a0SAndreas Gohr * @returns int size in bytes 1600f940e4a0SAndreas Gohr */ 1601d868eb89SAndreas Gohrfunction media_getuploadsize() 1602d868eb89SAndreas Gohr{ 1603f940e4a0SAndreas Gohr $okay = 0; 1604f940e4a0SAndreas Gohr 160524870174SAndreas Gohr $post = php_to_byte(@ini_get('post_max_size')); 160624870174SAndreas Gohr $suho = php_to_byte(@ini_get('suhosin.post.max_value_length')); 160724870174SAndreas Gohr $upld = php_to_byte(@ini_get('upload_max_filesize')); 1608f940e4a0SAndreas Gohr 160924870174SAndreas Gohr if($post && ($post < $okay || $okay === 0)) $okay = $post; 1610f940e4a0SAndreas Gohr if($suho && ($suho < $okay || $okay == 0)) $okay = $suho; 1611f940e4a0SAndreas Gohr if($upld && ($upld < $okay || $okay == 0)) $okay = $upld; 1612f940e4a0SAndreas Gohr 1613f940e4a0SAndreas Gohr return $okay; 16149f5dde7fSMichael Klier} 16153df72098SAndreas Gohr 16163df72098SAndreas Gohr/** 1617bf1f3ac4Ssarnowski * Print the search field form 1618bf1f3ac4Ssarnowski * 1619bf1f3ac4Ssarnowski * @author Tobias Sarnowski <sarnowski@cosmocode.de> 1620d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1621e0c26282SGerrit Uitslag * 1622e0c26282SGerrit Uitslag * @param string $ns 1623e0c26282SGerrit Uitslag * @param string $query 1624e0c26282SGerrit Uitslag * @param bool $fullscreen 1625bf1f3ac4Ssarnowski */ 1626d868eb89SAndreas Gohrfunction media_searchform($ns, $query = '', $fullscreen = false) 1627d868eb89SAndreas Gohr{ 1628bf1f3ac4Ssarnowski global $lang; 1629bf1f3ac4Ssarnowski 1630bf1f3ac4Ssarnowski // The default HTML search form 1631b960c74fSSatoshi Sahara $form = new Form([ 1632b960c74fSSatoshi Sahara 'id' => 'dw__mediasearch', 1633b960c74fSSatoshi Sahara 'action' => ($fullscreen) 1634b960c74fSSatoshi Sahara ? media_managerURL([], '&') 1635b960c74fSSatoshi Sahara : DOKU_BASE.'lib/exe/mediamanager.php', 1636b960c74fSSatoshi Sahara ]); 1637b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1638b960c74fSSatoshi Sahara $form->setHiddenField('ns', $ns); 1639b960c74fSSatoshi Sahara $form->setHiddenField($fullscreen ? 'mediado' : 'do', 'searchlist'); 1640554a8c9fSAdrian Lang 1641b960c74fSSatoshi Sahara $form->addTagOpen('p'); 1642bde2a644SSatoshi Sahara $form->addTextInput('q', $lang['searchmedia']) 1643b960c74fSSatoshi Sahara ->attr('title', sprintf($lang['searchmedia_in'], hsc($ns) .':*')) 1644b960c74fSSatoshi Sahara ->val($query); 1645bde2a644SSatoshi Sahara $form->addHTML(' '); 1646b960c74fSSatoshi Sahara $form->addButton('', $lang['btn_search'])->attr('type', 'submit'); 1647b960c74fSSatoshi Sahara $form->addTagClose('p'); 1648b960c74fSSatoshi Sahara $form->addTagClose('div'); 1649c6977b3aSSatoshi Sahara print $form->toHTML('SearchMedia'); 1650bf1f3ac4Ssarnowski} 1651bf1f3ac4Ssarnowski 1652bf1f3ac4Ssarnowski/** 16533df72098SAndreas Gohr * Build a tree outline of available media namespaces 16543df72098SAndreas Gohr * 16553df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 1656e0c26282SGerrit Uitslag * 1657e0c26282SGerrit Uitslag * @param string $ns 16583df72098SAndreas Gohr */ 1659d868eb89SAndreas Gohrfunction media_nstree($ns) 1660d868eb89SAndreas Gohr{ 16613df72098SAndreas Gohr global $conf; 1662256ca81eSAndreas Gohr global $lang; 16633df72098SAndreas Gohr 16643df72098SAndreas Gohr // currently selected namespace 16653df72098SAndreas Gohr $ns = cleanID($ns); 16663df72098SAndreas Gohr if(empty($ns)){ 1667de3eb1d7SAdrian Lang global $ID; 1668dd90013aSMichael Hamann $ns = (string)getNS($ID); 16693df72098SAndreas Gohr } 1670dd90013aSMichael Hamann 1671dd90013aSMichael Hamann $ns_dir = utf8_encodeFN(str_replace(':', '/', $ns)); 16723df72098SAndreas Gohr 167324870174SAndreas Gohr $data = []; 167424870174SAndreas Gohr search($data, $conf['mediadir'], 'search_index', ['ns' => $ns_dir, 'nofiles' => true]); 16753df72098SAndreas Gohr 16763df72098SAndreas Gohr // wrap a list with the root level around the other namespaces 167724870174SAndreas Gohr array_unshift($data, ['level' => 0, 'id' => '', 'open' =>'true', 'label' => '['.$lang['mediaroot'].']']); 16783df72098SAndreas Gohr 1679dd90013aSMichael Hamann // insert the current ns into the hierarchy if it isn't already part of it 1680dd90013aSMichael Hamann $ns_parts = explode(':', $ns); 1681dd90013aSMichael Hamann $tmp_ns = ''; 1682dd90013aSMichael Hamann $pos = 0; 1683dd90013aSMichael Hamann foreach ($ns_parts as $level => $part) { 1684dd90013aSMichael Hamann if ($tmp_ns) $tmp_ns .= ':'.$part; 1685dd90013aSMichael Hamann else $tmp_ns = $part; 1686dd90013aSMichael Hamann 1687dd90013aSMichael Hamann // find the namespace parts or insert them 1688dd90013aSMichael Hamann while ($data[$pos]['id'] != $tmp_ns) { 168964159a61SAndreas Gohr if ( 169064159a61SAndreas Gohr $pos >= count($data) || 16912d85e841SAndreas Gohr ($data[$pos]['level'] <= $level+1 && Sort::strcmp($data[$pos]['id'], $tmp_ns) > 0) 169264159a61SAndreas Gohr ) { 169324870174SAndreas Gohr array_splice($data, $pos, 0, [['level' => $level+1, 'id' => $tmp_ns, 'open' => 'true']]); 1694dd90013aSMichael Hamann break; 1695dd90013aSMichael Hamann } 1696dd90013aSMichael Hamann ++$pos; 1697dd90013aSMichael Hamann } 1698dd90013aSMichael Hamann } 1699dd90013aSMichael Hamann 17003df72098SAndreas Gohr echo html_buildlist($data, 'idx', 'media_nstree_item', 'media_nstree_li'); 17013df72098SAndreas Gohr} 17023df72098SAndreas Gohr 17033df72098SAndreas Gohr/** 17043df72098SAndreas Gohr * Userfunction for html_buildlist 17053df72098SAndreas Gohr * 17063df72098SAndreas Gohr * Prints a media namespace tree item 17073df72098SAndreas Gohr * 17083df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 170942ea7f44SGerrit Uitslag * 171042ea7f44SGerrit Uitslag * @param array $item 171142ea7f44SGerrit Uitslag * @return string html 17123df72098SAndreas Gohr */ 1713d868eb89SAndreas Gohrfunction media_nstree_item($item) 1714d868eb89SAndreas Gohr{ 17158108113cSTom N Harris global $INPUT; 17163df72098SAndreas Gohr $pos = strrpos($item['id'], ':'); 17173df72098SAndreas Gohr $label = substr($item['id'], $pos > 0 ? $pos + 1 : 0); 17180e80bb5eSChristopher Smith if(empty($item['label'])) $item['label'] = $label; 17193df72098SAndreas Gohr 17203df72098SAndreas Gohr $ret = ''; 172124870174SAndreas Gohr if ($INPUT->str('do') != 'media') 17223df72098SAndreas Gohr $ret .= '<a href="'.DOKU_BASE.'lib/exe/mediamanager.php?ns='.idfilter($item['id']).'" class="idx_dir">'; 1723b960c74fSSatoshi Sahara else $ret .= '<a href="'.media_managerURL(['ns' => idfilter($item['id'], false), 'tab_files' => 'files']) 172423846a98SKate Arzamastseva .'" class="idx_dir">'; 17253df72098SAndreas Gohr $ret .= $item['label']; 17263df72098SAndreas Gohr $ret .= '</a>'; 17273df72098SAndreas Gohr return $ret; 17283df72098SAndreas Gohr} 17293df72098SAndreas Gohr 17303df72098SAndreas Gohr/** 17313df72098SAndreas Gohr * Userfunction for html_buildlist 17323df72098SAndreas Gohr * 17333df72098SAndreas Gohr * Prints a media namespace tree item opener 17343df72098SAndreas Gohr * 17353df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 173642ea7f44SGerrit Uitslag * 173742ea7f44SGerrit Uitslag * @param array $item 173842ea7f44SGerrit Uitslag * @return string html 17393df72098SAndreas Gohr */ 1740d868eb89SAndreas Gohrfunction media_nstree_li($item) 1741d868eb89SAndreas Gohr{ 17423df72098SAndreas Gohr $class='media level'.$item['level']; 17433df72098SAndreas Gohr if($item['open']){ 17443df72098SAndreas Gohr $class .= ' open'; 17453df72098SAndreas Gohr $img = DOKU_BASE.'lib/images/minus.gif'; 1746e260f93bSAnika Henke $alt = '−'; 17473df72098SAndreas Gohr }else{ 17483df72098SAndreas Gohr $class .= ' closed'; 17493df72098SAndreas Gohr $img = DOKU_BASE.'lib/images/plus.gif'; 17507af1b404SAnika Henke $alt = '+'; 17513df72098SAndreas Gohr } 1752231b8c34SPierre Spring // TODO: only deliver an image if it actually has a subtree... 17533df72098SAndreas Gohr return '<li class="'.$class.'">'. 17547af1b404SAnika Henke '<img src="'.$img.'" alt="'.$alt.'" />'; 17553df72098SAndreas Gohr} 175613c08e2fSMichael Klier 175713c08e2fSMichael Klier/** 1758b021f0b4SAndreas Gohr * Resizes or crop the given image to the given size 1759b021f0b4SAndreas Gohr * 1760b021f0b4SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 1761b021f0b4SAndreas Gohr * 1762b021f0b4SAndreas Gohr * @param string $file filename, path to file 1763b021f0b4SAndreas Gohr * @param string $ext extension 1764b021f0b4SAndreas Gohr * @param int $w desired width 1765b021f0b4SAndreas Gohr * @param int $h desired height 1766b021f0b4SAndreas Gohr * @param bool $crop should a center crop be used? 1767b021f0b4SAndreas Gohr * @return string path to resized or original size if failed 1768b021f0b4SAndreas Gohr */ 1769b021f0b4SAndreas Gohrfunction media_mod_image($file, $ext, $w, $h = 0, $crop = false) 1770b021f0b4SAndreas Gohr{ 1771b021f0b4SAndreas Gohr global $conf; 1772d967ecd8SAndreas Gohr if(!$h) $h = 0; 1773b021f0b4SAndreas Gohr // we wont scale up to infinity 1774b021f0b4SAndreas Gohr if($w > 2000 || $h > 2000) return $file; 1775b021f0b4SAndreas Gohr 1776b021f0b4SAndreas Gohr $operation = $crop ? 'crop' : 'resize'; 1777b021f0b4SAndreas Gohr 1778b021f0b4SAndreas Gohr $options = [ 1779b021f0b4SAndreas Gohr 'quality' => $conf['jpg_quality'], 1780b021f0b4SAndreas Gohr 'imconvert' => $conf['im_convert'], 1781b021f0b4SAndreas Gohr ]; 1782b021f0b4SAndreas Gohr 178324870174SAndreas Gohr $cache = new CacheImageMod($file, $w, $h, $ext, $crop); 1784b021f0b4SAndreas Gohr if(!$cache->useCache()) { 1785b021f0b4SAndreas Gohr try { 1786b021f0b4SAndreas Gohr Slika::run($file, $options) 1787b021f0b4SAndreas Gohr ->autorotate() 1788b021f0b4SAndreas Gohr ->$operation($w, $h) 1789b021f0b4SAndreas Gohr ->save($cache->cache, $ext); 1790b021f0b4SAndreas Gohr if($conf['fperm']) @chmod($cache->cache, $conf['fperm']); 179124870174SAndreas Gohr } catch (Exception $e) { 1792b021f0b4SAndreas Gohr Logger::debug($e->getMessage()); 1793b021f0b4SAndreas Gohr return $file; 1794b021f0b4SAndreas Gohr } 1795b021f0b4SAndreas Gohr } 1796b021f0b4SAndreas Gohr 1797b021f0b4SAndreas Gohr return $cache->cache; 1798b021f0b4SAndreas Gohr} 1799b021f0b4SAndreas Gohr 1800b021f0b4SAndreas Gohr/** 180113c08e2fSMichael Klier * Resizes the given image to the given size 180213c08e2fSMichael Klier * 180313c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 180442ea7f44SGerrit Uitslag * 180542ea7f44SGerrit Uitslag * @param string $file filename, path to file 180642ea7f44SGerrit Uitslag * @param string $ext extension 180742ea7f44SGerrit Uitslag * @param int $w desired width 180842ea7f44SGerrit Uitslag * @param int $h desired height 180942ea7f44SGerrit Uitslag * @return string path to resized or original size if failed 181013c08e2fSMichael Klier */ 1811b021f0b4SAndreas Gohrfunction media_resize_image($file, $ext, $w, $h = 0) 1812b021f0b4SAndreas Gohr{ 1813b021f0b4SAndreas Gohr return media_mod_image($file, $ext, $w, $h, false); 1814d2bd34a5SAndreas Gohr} 181513c08e2fSMichael Klier 181613c08e2fSMichael Klier/** 1817d2bd34a5SAndreas Gohr * Center crops the given image to the wanted size 181813c08e2fSMichael Klier * 181913c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 182042ea7f44SGerrit Uitslag * 182142ea7f44SGerrit Uitslag * @param string $file filename, path to file 182242ea7f44SGerrit Uitslag * @param string $ext extension 182342ea7f44SGerrit Uitslag * @param int $w desired width 182442ea7f44SGerrit Uitslag * @param int $h desired height 182542ea7f44SGerrit Uitslag * @return string path to resized or original size if failed 182613c08e2fSMichael Klier */ 1827b021f0b4SAndreas Gohrfunction media_crop_image($file, $ext, $w, $h = 0) 1828b021f0b4SAndreas Gohr{ 1829b021f0b4SAndreas Gohr return media_mod_image($file, $ext, $w, $h, true); 183013c08e2fSMichael Klier} 183113c08e2fSMichael Klier 183213c08e2fSMichael Klier/** 18330f4e0092SChristopher Smith * Calculate a token to be used to verify fetch requests for resized or 18340f4e0092SChristopher Smith * cropped images have been internally generated - and prevent external 18350f4e0092SChristopher Smith * DDOS attacks via fetch 18360f4e0092SChristopher Smith * 18373c124064SAndreas Gohr * @author Christopher Smith <chris@jalakai.co.uk> 18383c124064SAndreas Gohr * 18390f4e0092SChristopher Smith * @param string $id id of the image 18400f4e0092SChristopher Smith * @param int $w resize/crop width 18410f4e0092SChristopher Smith * @param int $h resize/crop height 184242ea7f44SGerrit Uitslag * @return string token or empty string if no token required 18430f4e0092SChristopher Smith */ 1844d868eb89SAndreas Gohrfunction media_get_token($id, $w, $h) 1845d868eb89SAndreas Gohr{ 18460f4e0092SChristopher Smith // token is only required for modified images 1847cc036f74SKlap-in if ($w || $h || media_isexternal($id)) { 18483c124064SAndreas Gohr $token = $id; 18490f4e0092SChristopher Smith if ($w) $token .= '.'.$w; 18500f4e0092SChristopher Smith if ($h) $token .= '.'.$h; 18510f4e0092SChristopher Smith 185224870174SAndreas Gohr return substr(PassHash::hmac('md5', $token, auth_cookiesalt()), 0, 6); 18530f4e0092SChristopher Smith } 18540f4e0092SChristopher Smith 18550f4e0092SChristopher Smith return ''; 18560f4e0092SChristopher Smith} 18570f4e0092SChristopher Smith 18580f4e0092SChristopher Smith/** 185913c08e2fSMichael Klier * Download a remote file and return local filename 186013c08e2fSMichael Klier * 186113c08e2fSMichael Klier * returns false if download fails. Uses cached file if available and 186213c08e2fSMichael Klier * wanted 186313c08e2fSMichael Klier * 186413c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 186513c08e2fSMichael Klier * @author Pavel Vitis <Pavel.Vitis@seznam.cz> 186642ea7f44SGerrit Uitslag * 186742ea7f44SGerrit Uitslag * @param string $url 186842ea7f44SGerrit Uitslag * @param string $ext extension 186942ea7f44SGerrit Uitslag * @param int $cache cachetime in seconds 187042ea7f44SGerrit Uitslag * @return false|string path to cached file 187113c08e2fSMichael Klier */ 1872d868eb89SAndreas Gohrfunction media_get_from_URL($url, $ext, $cache) 1873d868eb89SAndreas Gohr{ 187413c08e2fSMichael Klier global $conf; 187513c08e2fSMichael Klier 187613c08e2fSMichael Klier // if no cache or fetchsize just redirect 187713c08e2fSMichael Klier if ($cache==0) return false; 187813c08e2fSMichael Klier if (!$conf['fetchsize']) return false; 187913c08e2fSMichael Klier 188013c08e2fSMichael Klier $local = getCacheName(strtolower($url), ".media.$ext"); 188113c08e2fSMichael Klier $mtime = @filemtime($local); // 0 if not exists 188213c08e2fSMichael Klier 188313c08e2fSMichael Klier //decide if download needed: 188413c08e2fSMichael Klier if(($mtime == 0) || // cache does not exist 188513c08e2fSMichael Klier ($cache != -1 && $mtime < time() - $cache) // 'recache' and cache has expired 188613c08e2fSMichael Klier ) { 188713c08e2fSMichael Klier if(media_image_download($url, $local)) { 188813c08e2fSMichael Klier return $local; 188913c08e2fSMichael Klier } else { 189013c08e2fSMichael Klier return false; 189113c08e2fSMichael Klier } 189213c08e2fSMichael Klier } 189313c08e2fSMichael Klier 189413c08e2fSMichael Klier //if cache exists use it else 189513c08e2fSMichael Klier if($mtime) return $local; 189613c08e2fSMichael Klier 189713c08e2fSMichael Klier //else return false 189813c08e2fSMichael Klier return false; 189913c08e2fSMichael Klier} 190013c08e2fSMichael Klier 190113c08e2fSMichael Klier/** 190213c08e2fSMichael Klier * Download image files 190313c08e2fSMichael Klier * 190413c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 190542ea7f44SGerrit Uitslag * 190642ea7f44SGerrit Uitslag * @param string $url 190742ea7f44SGerrit Uitslag * @param string $file path to file in which to put the downloaded content 190842ea7f44SGerrit Uitslag * @return bool 190913c08e2fSMichael Klier */ 1910d868eb89SAndreas Gohrfunction media_image_download($url, $file) 1911d868eb89SAndreas Gohr{ 191213c08e2fSMichael Klier global $conf; 191313c08e2fSMichael Klier $http = new DokuHTTPClient(); 1914a5951419SAndreas Gohr $http->keep_alive = false; // we do single ops here, no need for keep-alive 1915a5951419SAndreas Gohr 191613c08e2fSMichael Klier $http->max_bodysize = $conf['fetchsize']; 191713c08e2fSMichael Klier $http->timeout = 25; //max. 25 sec 191813c08e2fSMichael Klier $http->header_regexp = '!\r\nContent-Type: image/(jpe?g|gif|png)!i'; 191913c08e2fSMichael Klier 192013c08e2fSMichael Klier $data = $http->get($url); 192113c08e2fSMichael Klier if(!$data) return false; 192213c08e2fSMichael Klier 192379e79377SAndreas Gohr $fileexists = file_exists($file); 192413c08e2fSMichael Klier $fp = @fopen($file, "w"); 192513c08e2fSMichael Klier if(!$fp) return false; 192613c08e2fSMichael Klier fwrite($fp, $data); 192713c08e2fSMichael Klier fclose($fp); 192824870174SAndreas Gohr if(!$fileexists && $conf['fperm']) chmod($file, $conf['fperm']); 192913c08e2fSMichael Klier 193013c08e2fSMichael Klier // check if it is really an image 193113c08e2fSMichael Klier $info = @getimagesize($file); 193213c08e2fSMichael Klier if(!$info){ 193313c08e2fSMichael Klier @unlink($file); 193413c08e2fSMichael Klier return false; 193513c08e2fSMichael Klier } 193613c08e2fSMichael Klier 193713c08e2fSMichael Klier return true; 193813c08e2fSMichael Klier} 193913c08e2fSMichael Klier 194013c08e2fSMichael Klier/** 194113c08e2fSMichael Klier * resize images using external ImageMagick convert program 194213c08e2fSMichael Klier * 194313c08e2fSMichael Klier * @author Pavel Vitis <Pavel.Vitis@seznam.cz> 194413c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 194542ea7f44SGerrit Uitslag * 194642ea7f44SGerrit Uitslag * @param string $ext extension 194742ea7f44SGerrit Uitslag * @param string $from filename path to file 194842ea7f44SGerrit Uitslag * @param int $from_w original width 194942ea7f44SGerrit Uitslag * @param int $from_h original height 195042ea7f44SGerrit Uitslag * @param string $to path to resized file 195142ea7f44SGerrit Uitslag * @param int $to_w desired width 195242ea7f44SGerrit Uitslag * @param int $to_h desired height 195342ea7f44SGerrit Uitslag * @return bool 195413c08e2fSMichael Klier */ 1955d868eb89SAndreas Gohrfunction media_resize_imageIM($ext, $from, $from_w, $from_h, $to, $to_w, $to_h) 1956d868eb89SAndreas Gohr{ 195713c08e2fSMichael Klier global $conf; 195813c08e2fSMichael Klier 195913c08e2fSMichael Klier // check if convert is configured 196013c08e2fSMichael Klier if(!$conf['im_convert']) return false; 196113c08e2fSMichael Klier 196213c08e2fSMichael Klier // prepare command 196313c08e2fSMichael Klier $cmd = $conf['im_convert']; 196413c08e2fSMichael Klier $cmd .= ' -resize '.$to_w.'x'.$to_h.'!'; 196513c08e2fSMichael Klier if ($ext == 'jpg' || $ext == 'jpeg') { 196613c08e2fSMichael Klier $cmd .= ' -quality '.$conf['jpg_quality']; 196713c08e2fSMichael Klier } 196813c08e2fSMichael Klier $cmd .= " $from $to"; 196913c08e2fSMichael Klier 197013c08e2fSMichael Klier @exec($cmd, $out, $retval); 197113c08e2fSMichael Klier if ($retval == 0) return true; 197213c08e2fSMichael Klier return false; 197313c08e2fSMichael Klier} 197413c08e2fSMichael Klier 197513c08e2fSMichael Klier/** 197613c08e2fSMichael Klier * crop images using external ImageMagick convert program 197713c08e2fSMichael Klier * 197813c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 197942ea7f44SGerrit Uitslag * 198042ea7f44SGerrit Uitslag * @param string $ext extension 198142ea7f44SGerrit Uitslag * @param string $from filename path to file 198242ea7f44SGerrit Uitslag * @param int $from_w original width 198342ea7f44SGerrit Uitslag * @param int $from_h original height 198442ea7f44SGerrit Uitslag * @param string $to path to resized file 198542ea7f44SGerrit Uitslag * @param int $to_w desired width 198642ea7f44SGerrit Uitslag * @param int $to_h desired height 198742ea7f44SGerrit Uitslag * @param int $ofs_x offset of crop centre 198842ea7f44SGerrit Uitslag * @param int $ofs_y offset of crop centre 198942ea7f44SGerrit Uitslag * @return bool 1990d2bd34a5SAndreas Gohr * @deprecated 2020-09-01 199113c08e2fSMichael Klier */ 1992d868eb89SAndreas Gohrfunction media_crop_imageIM($ext, $from, $from_w, $from_h, $to, $to_w, $to_h, $ofs_x, $ofs_y) 1993d868eb89SAndreas Gohr{ 199413c08e2fSMichael Klier global $conf; 1995d2bd34a5SAndreas Gohr dbg_deprecated('splitbrain\\Slika'); 199613c08e2fSMichael Klier 199713c08e2fSMichael Klier // check if convert is configured 199813c08e2fSMichael Klier if(!$conf['im_convert']) return false; 199913c08e2fSMichael Klier 200013c08e2fSMichael Klier // prepare command 200113c08e2fSMichael Klier $cmd = $conf['im_convert']; 200213c08e2fSMichael Klier $cmd .= ' -crop '.$to_w.'x'.$to_h.'+'.$ofs_x.'+'.$ofs_y; 200313c08e2fSMichael Klier if ($ext == 'jpg' || $ext == 'jpeg') { 200413c08e2fSMichael Klier $cmd .= ' -quality '.$conf['jpg_quality']; 200513c08e2fSMichael Klier } 200613c08e2fSMichael Klier $cmd .= " $from $to"; 200713c08e2fSMichael Klier 200813c08e2fSMichael Klier @exec($cmd, $out, $retval); 200913c08e2fSMichael Klier if ($retval == 0) return true; 201013c08e2fSMichael Klier return false; 201113c08e2fSMichael Klier} 201213c08e2fSMichael Klier 201313c08e2fSMichael Klier/** 201413c08e2fSMichael Klier * resize or crop images using PHP's libGD support 201513c08e2fSMichael Klier * 201613c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 201713c08e2fSMichael Klier * @author Sebastian Wienecke <s_wienecke@web.de> 201842ea7f44SGerrit Uitslag * 201942ea7f44SGerrit Uitslag * @param string $ext extension 202042ea7f44SGerrit Uitslag * @param string $from filename path to file 202142ea7f44SGerrit Uitslag * @param int $from_w original width 202242ea7f44SGerrit Uitslag * @param int $from_h original height 202342ea7f44SGerrit Uitslag * @param string $to path to resized file 202442ea7f44SGerrit Uitslag * @param int $to_w desired width 202542ea7f44SGerrit Uitslag * @param int $to_h desired height 202642ea7f44SGerrit Uitslag * @param int $ofs_x offset of crop centre 202742ea7f44SGerrit Uitslag * @param int $ofs_y offset of crop centre 202842ea7f44SGerrit Uitslag * @return bool 2029d2bd34a5SAndreas Gohr * @deprecated 2020-09-01 203013c08e2fSMichael Klier */ 2031d868eb89SAndreas Gohrfunction media_resize_imageGD($ext, $from, $from_w, $from_h, $to, $to_w, $to_h, $ofs_x = 0, $ofs_y = 0) 2032d868eb89SAndreas Gohr{ 203313c08e2fSMichael Klier global $conf; 2034d2bd34a5SAndreas Gohr dbg_deprecated('splitbrain\\Slika'); 203513c08e2fSMichael Klier 203613c08e2fSMichael Klier if($conf['gdlib'] < 1) return false; //no GDlib available or wanted 203713c08e2fSMichael Klier 203813c08e2fSMichael Klier // check available memory 203913c08e2fSMichael Klier if(!is_mem_available(($from_w * $from_h * 4) + ($to_w * $to_h * 4))){ 204013c08e2fSMichael Klier return false; 204113c08e2fSMichael Klier } 204213c08e2fSMichael Klier 204313c08e2fSMichael Klier // create an image of the given filetype 204459bc3b48SGerrit Uitslag $image = false; 204513c08e2fSMichael Klier if ($ext == 'jpg' || $ext == 'jpeg'){ 204613c08e2fSMichael Klier if(!function_exists("imagecreatefromjpeg")) return false; 204713c08e2fSMichael Klier $image = @imagecreatefromjpeg($from); 204813c08e2fSMichael Klier }elseif($ext == 'png') { 204913c08e2fSMichael Klier if(!function_exists("imagecreatefrompng")) return false; 205013c08e2fSMichael Klier $image = @imagecreatefrompng($from); 205113c08e2fSMichael Klier 205213c08e2fSMichael Klier }elseif($ext == 'gif') { 205313c08e2fSMichael Klier if(!function_exists("imagecreatefromgif")) return false; 205413c08e2fSMichael Klier $image = @imagecreatefromgif($from); 205513c08e2fSMichael Klier } 205613c08e2fSMichael Klier if(!$image) return false; 205713c08e2fSMichael Klier 205859bc3b48SGerrit Uitslag $newimg = false; 205913c08e2fSMichael Klier if(($conf['gdlib']>1) && function_exists("imagecreatetruecolor") && $ext != 'gif'){ 206013c08e2fSMichael Klier $newimg = @imagecreatetruecolor ($to_w, $to_h); 206113c08e2fSMichael Klier } 206213c08e2fSMichael Klier if(!$newimg) $newimg = @imagecreate($to_w, $to_h); 206313c08e2fSMichael Klier if(!$newimg){ 206413c08e2fSMichael Klier imagedestroy($image); 206513c08e2fSMichael Klier return false; 206613c08e2fSMichael Klier } 206713c08e2fSMichael Klier 206813c08e2fSMichael Klier //keep png alpha channel if possible 206913c08e2fSMichael Klier if($ext == 'png' && $conf['gdlib']>1 && function_exists('imagesavealpha')){ 207013c08e2fSMichael Klier imagealphablending($newimg, false); 207113c08e2fSMichael Klier imagesavealpha($newimg, true); 207213c08e2fSMichael Klier } 207313c08e2fSMichael Klier 207413c08e2fSMichael Klier //keep gif transparent color if possible 207513c08e2fSMichael Klier if($ext == 'gif' && function_exists('imagefill') && function_exists('imagecolorallocate')) { 207613c08e2fSMichael Klier if(function_exists('imagecolorsforindex') && function_exists('imagecolortransparent')) { 207713c08e2fSMichael Klier $transcolorindex = @imagecolortransparent($image); 207813c08e2fSMichael Klier if($transcolorindex >= 0 ) { //transparent color exists 207913c08e2fSMichael Klier $transcolor = @imagecolorsforindex($image, $transcolorindex); 208064159a61SAndreas Gohr $transcolorindex = @imagecolorallocate( 208164159a61SAndreas Gohr $newimg, 208264159a61SAndreas Gohr $transcolor['red'], 208364159a61SAndreas Gohr $transcolor['green'], 208464159a61SAndreas Gohr $transcolor['blue'] 208564159a61SAndreas Gohr ); 208613c08e2fSMichael Klier @imagefill($newimg, 0, 0, $transcolorindex); 208713c08e2fSMichael Klier @imagecolortransparent($newimg, $transcolorindex); 208813c08e2fSMichael Klier }else{ //filling with white 208913c08e2fSMichael Klier $whitecolorindex = @imagecolorallocate($newimg, 255, 255, 255); 209013c08e2fSMichael Klier @imagefill($newimg, 0, 0, $whitecolorindex); 209113c08e2fSMichael Klier } 209213c08e2fSMichael Klier }else{ //filling with white 209313c08e2fSMichael Klier $whitecolorindex = @imagecolorallocate($newimg, 255, 255, 255); 209413c08e2fSMichael Klier @imagefill($newimg, 0, 0, $whitecolorindex); 209513c08e2fSMichael Klier } 209613c08e2fSMichael Klier } 209713c08e2fSMichael Klier 209813c08e2fSMichael Klier //try resampling first 209913c08e2fSMichael Klier if(function_exists("imagecopyresampled")){ 210013c08e2fSMichael Klier if(!@imagecopyresampled($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h)) { 210113c08e2fSMichael Klier imagecopyresized($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h); 210213c08e2fSMichael Klier } 210313c08e2fSMichael Klier }else{ 210413c08e2fSMichael Klier imagecopyresized($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h); 210513c08e2fSMichael Klier } 210613c08e2fSMichael Klier 210713c08e2fSMichael Klier $okay = false; 210813c08e2fSMichael Klier if ($ext == 'jpg' || $ext == 'jpeg'){ 210913c08e2fSMichael Klier if(!function_exists('imagejpeg')){ 211013c08e2fSMichael Klier $okay = false; 211113c08e2fSMichael Klier }else{ 211213c08e2fSMichael Klier $okay = imagejpeg($newimg, $to, $conf['jpg_quality']); 211313c08e2fSMichael Klier } 211413c08e2fSMichael Klier }elseif($ext == 'png') { 211513c08e2fSMichael Klier if(!function_exists('imagepng')){ 211613c08e2fSMichael Klier $okay = false; 211713c08e2fSMichael Klier }else{ 211813c08e2fSMichael Klier $okay = imagepng($newimg, $to); 211913c08e2fSMichael Klier } 212013c08e2fSMichael Klier }elseif($ext == 'gif') { 212113c08e2fSMichael Klier if(!function_exists('imagegif')){ 212213c08e2fSMichael Klier $okay = false; 212313c08e2fSMichael Klier }else{ 212413c08e2fSMichael Klier $okay = imagegif($newimg, $to); 212513c08e2fSMichael Klier } 212613c08e2fSMichael Klier } 212713c08e2fSMichael Klier 212879a2d784SGerrit Uitslag // destroy GD image resources 212979a2d784SGerrit Uitslag imagedestroy($image); 213079a2d784SGerrit Uitslag imagedestroy($newimg); 213113c08e2fSMichael Klier 213213c08e2fSMichael Klier return $okay; 213313c08e2fSMichael Klier} 213413c08e2fSMichael Klier 21353d7a9e0aSAnika Henke/** 21363d7a9e0aSAnika Henke * Return other media files with the same base name 213779e53fe5SAnika Henke * but different extensions. 21383d7a9e0aSAnika Henke * 21393d7a9e0aSAnika Henke * @param string $src - ID of media file 214042ea7f44SGerrit Uitslag * @param string[] $exts - alternative extensions to find other files for 214142ea7f44SGerrit Uitslag * @return array - array(mime type => file ID) 21423d7a9e0aSAnika Henke * 21433d7a9e0aSAnika Henke * @author Anika Henke <anika@selfthinker.org> 21443d7a9e0aSAnika Henke */ 2145d868eb89SAndreas Gohrfunction media_alternativefiles($src, $exts) 2146d868eb89SAndreas Gohr{ 21473d7a9e0aSAnika Henke 214824870174SAndreas Gohr $files = []; 214924870174SAndreas Gohr [$srcExt, ] = mimetype($src); 21503d7a9e0aSAnika Henke $filebase = substr($src, 0, -1 * (strlen($srcExt)+1)); 21513d7a9e0aSAnika Henke 21523d7a9e0aSAnika Henke foreach($exts as $ext) { 21533d7a9e0aSAnika Henke $fileid = $filebase.'.'.$ext; 21543d7a9e0aSAnika Henke $file = mediaFN($fileid); 21553d7a9e0aSAnika Henke if(file_exists($file)) { 215624870174SAndreas Gohr [, $fileMime] = mimetype($file); 215779e53fe5SAnika Henke $files[$fileMime] = $fileid; 215899f943f6SAnika Henke } 21593d7a9e0aSAnika Henke } 21603d7a9e0aSAnika Henke return $files; 21613d7a9e0aSAnika Henke} 21623d7a9e0aSAnika Henke 2163f50634f0SAnika Henke/** 2164f50634f0SAnika Henke * Check if video/audio is supported to be embedded. 2165f50634f0SAnika Henke * 2166b83a74f1SAnika Henke * @param string $mime - mimetype of media file 216742ea7f44SGerrit Uitslag * @param string $type - type of media files to check ('video', 'audio', or null for all) 2168f50634f0SAnika Henke * @return boolean 2169f50634f0SAnika Henke * 2170f50634f0SAnika Henke * @author Anika Henke <anika@selfthinker.org> 2171f50634f0SAnika Henke */ 2172*ed823bcdSAndreas Gohrfunction media_supportedav($mime, $type = null) 2173d868eb89SAndreas Gohr{ 217424870174SAndreas Gohr $supportedAudio = [ 2175f50634f0SAnika Henke 'ogg' => 'audio/ogg', 2176f50634f0SAnika Henke 'mp3' => 'audio/mpeg', 217724870174SAndreas Gohr 'wav' => 'audio/wav' 217824870174SAndreas Gohr ]; 217924870174SAndreas Gohr $supportedVideo = [ 2180f50634f0SAnika Henke 'webm' => 'video/webm', 2181f50634f0SAnika Henke 'ogv' => 'video/ogg', 218224870174SAndreas Gohr 'mp4' => 'video/mp4' 218324870174SAndreas Gohr ]; 2184f50634f0SAnika Henke if ($type == 'audio') { 2185f50634f0SAnika Henke $supportedAv = $supportedAudio; 2186f50634f0SAnika Henke } elseif ($type == 'video') { 2187f50634f0SAnika Henke $supportedAv = $supportedVideo; 2188f50634f0SAnika Henke } else { 2189f50634f0SAnika Henke $supportedAv = array_merge($supportedAudio, $supportedVideo); 2190f50634f0SAnika Henke } 2191f50634f0SAnika Henke return in_array($mime, $supportedAv); 2192f50634f0SAnika Henke} 2193f50634f0SAnika Henke 21940877a1f1SSchplurtz le Déboulonné/** 21950877a1f1SSchplurtz le Déboulonné * Return track media files with the same base name 21960877a1f1SSchplurtz le Déboulonné * but extensions that indicate kind and lang. 21970877a1f1SSchplurtz le Déboulonné * ie for foo.webm search foo.sub.lang.vtt, foo.cap.lang.vtt... 21980877a1f1SSchplurtz le Déboulonné * 21990877a1f1SSchplurtz le Déboulonné * @param string $src - ID of media file 220001299338SSchplurtz le Déboulonné * @return array - array(mediaID => array( kind, srclang )) 22010877a1f1SSchplurtz le Déboulonné * 22020877a1f1SSchplurtz le Déboulonné * @author Schplurtz le Déboulonné <Schplurtz@laposte.net> 22030877a1f1SSchplurtz le Déboulonné */ 2204d868eb89SAndreas Gohrfunction media_trackfiles($src) 2205d868eb89SAndreas Gohr{ 220624870174SAndreas Gohr $kinds=[ 22070877a1f1SSchplurtz le Déboulonné 'sub' => 'subtitles', 22080877a1f1SSchplurtz le Déboulonné 'cap' => 'captions', 22090877a1f1SSchplurtz le Déboulonné 'des' => 'descriptions', 22100877a1f1SSchplurtz le Déboulonné 'cha' => 'chapters', 22110877a1f1SSchplurtz le Déboulonné 'met' => 'metadata' 221224870174SAndreas Gohr ]; 22130877a1f1SSchplurtz le Déboulonné 221424870174SAndreas Gohr $files = []; 22150877a1f1SSchplurtz le Déboulonné $re='/\\.(sub|cap|des|cha|met)\\.([^.]+)\\.vtt$/'; 22160877a1f1SSchplurtz le Déboulonné $baseid=pathinfo($src, PATHINFO_FILENAME); 22170877a1f1SSchplurtz le Déboulonné $pattern=mediaFN($baseid).'.*.*.vtt'; 22180877a1f1SSchplurtz le Déboulonné $list=glob($pattern); 22190877a1f1SSchplurtz le Déboulonné foreach($list as $track) { 22200877a1f1SSchplurtz le Déboulonné if(preg_match($re, $track, $matches)){ 222124870174SAndreas Gohr $files[$baseid.'.'.$matches[1].'.'.$matches[2].'.vtt']=[$kinds[$matches[1]], $matches[2]]; 22220877a1f1SSchplurtz le Déboulonné } 22230877a1f1SSchplurtz le Déboulonné } 22240877a1f1SSchplurtz le Déboulonné return $files; 22250877a1f1SSchplurtz le Déboulonné} 22260877a1f1SSchplurtz le Déboulonné 2227365be586SAndreas Gohr/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 2228