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>'; 48*177d6836SAndreas Gohr } else $hidden++; 493df72098SAndreas Gohr } 503df72098SAndreas Gohr if ($hidden) { 513df72098SAndreas Gohr print '<div class="mediaref_hidden">'.$lang['ref_hidden'].'</div>'; 523df72098SAndreas Gohr } 533df72098SAndreas Gohr} 543df72098SAndreas Gohr 553df72098SAndreas Gohr/** 563df72098SAndreas Gohr * Handles the saving of image meta data 573df72098SAndreas Gohr * 583df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 59cf832786SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 60e0c26282SGerrit Uitslag * 61e0c26282SGerrit Uitslag * @param string $id media id 62e0c26282SGerrit Uitslag * @param int $auth permission level 63e0c26282SGerrit Uitslag * @param array $data 6442ea7f44SGerrit Uitslag * @return false|string 653df72098SAndreas Gohr */ 66d868eb89SAndreas Gohrfunction media_metasave($id, $auth, $data) 67d868eb89SAndreas Gohr{ 683df72098SAndreas Gohr if ($auth < AUTH_UPLOAD) return false; 69f2ea8432SAndreas Gohr if (!checkSecurityToken()) return false; 703df72098SAndreas Gohr global $lang; 710b308644SOtto Vainio global $conf; 723df72098SAndreas Gohr $src = mediaFN($id); 733df72098SAndreas Gohr 743df72098SAndreas Gohr $meta = new JpegMeta($src); 753df72098SAndreas Gohr $meta->_parseAll(); 763df72098SAndreas Gohr 773df72098SAndreas Gohr foreach ($data as $key => $val) { 783df72098SAndreas Gohr $val=trim($val); 793df72098SAndreas Gohr if (empty($val)) { 803df72098SAndreas Gohr $meta->deleteField($key); 813df72098SAndreas Gohr } else { 823df72098SAndreas Gohr $meta->setField($key, $val); 833df72098SAndreas Gohr } 843df72098SAndreas Gohr } 853df72098SAndreas Gohr 86cf832786SKate Arzamastseva $old = @filemtime($src); 8779e79377SAndreas Gohr if (!file_exists(mediaFN($id, $old)) && file_exists($src)) { 88cf832786SKate Arzamastseva // add old revision to the attic 89cf832786SKate Arzamastseva media_saveOldRevision($id); 90cf832786SKate Arzamastseva } 91ac3ed4afSGerrit Uitslag $filesize_old = filesize($src); 923df72098SAndreas Gohr if ($meta->save()) { 930b308644SOtto Vainio if ($conf['fperm']) chmod($src, $conf['fperm']); 94ac3ed4afSGerrit Uitslag @clearstatcache(true, $src); 95cf832786SKate Arzamastseva $new = @filemtime($src); 96ac3ed4afSGerrit Uitslag $filesize_new = filesize($src); 97ac3ed4afSGerrit Uitslag $sizechange = $filesize_new - $filesize_old; 98ac3ed4afSGerrit Uitslag 99cf832786SKate Arzamastseva // add a log entry to the media changelog 100ac3ed4afSGerrit Uitslag addMediaLogEntry($new, $id, DOKU_CHANGE_TYPE_EDIT, $lang['media_meta_edited'], '', null, $sizechange); 101cf832786SKate Arzamastseva 1023df72098SAndreas Gohr msg($lang['metasaveok'], 1); 1033df72098SAndreas Gohr return $id; 1043df72098SAndreas Gohr } else { 1053df72098SAndreas Gohr msg($lang['metasaveerr'], -1); 1063df72098SAndreas Gohr return false; 1073df72098SAndreas Gohr } 1083df72098SAndreas Gohr} 1093df72098SAndreas Gohr 1103df72098SAndreas Gohr/** 111d54f7963SKlap-in * check if a media is external source 112d54f7963SKlap-in * 113d54f7963SKlap-in * @author Gerrit Uitslag <klapinklapin@gmail.com> 11442ea7f44SGerrit Uitslag * 115d54f7963SKlap-in * @param string $id the media ID or URL 116d54f7963SKlap-in * @return bool 117d54f7963SKlap-in */ 118d868eb89SAndreas Gohrfunction media_isexternal($id) 119d868eb89SAndreas Gohr{ 120fe578fe9SElan Ruusamäe if (preg_match('#^(?:https?|ftp)://#i', $id)) return true; 121d54f7963SKlap-in return false; 122d54f7963SKlap-in} 123d54f7963SKlap-in 124d54f7963SKlap-in/** 125add8678fSAndreas Gohr * Check if a media item is public (eg, external URL or readable by @ALL) 126add8678fSAndreas Gohr * 127add8678fSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 12842ea7f44SGerrit Uitslag * 129add8678fSAndreas Gohr * @param string $id the media ID or URL 130add8678fSAndreas Gohr * @return bool 131add8678fSAndreas Gohr */ 132d868eb89SAndreas Gohrfunction media_ispublic($id) 133d868eb89SAndreas Gohr{ 134d54f7963SKlap-in if (media_isexternal($id)) return true; 135add8678fSAndreas Gohr $id = cleanID($id); 13624870174SAndreas Gohr if (auth_aclcheck(getNS($id).':*', '', []) >= AUTH_READ) return true; 137add8678fSAndreas Gohr return false; 138add8678fSAndreas Gohr} 139add8678fSAndreas Gohr 140add8678fSAndreas Gohr/** 1413df72098SAndreas Gohr * Display the form to edit image meta data 1423df72098SAndreas Gohr * 1433df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 144d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 145e0c26282SGerrit Uitslag * 146e0c26282SGerrit Uitslag * @param string $id media id 147e0c26282SGerrit Uitslag * @param int $auth permission level 148e0c26282SGerrit Uitslag * @return bool 1493df72098SAndreas Gohr */ 150d868eb89SAndreas Gohrfunction media_metaform($id, $auth) 151d868eb89SAndreas Gohr{ 152ebc28e69SAndreas Gohr global $lang; 1533df72098SAndreas Gohr 15488a71175SKate Arzamastseva if ($auth < AUTH_UPLOAD) { 155b960c74fSSatoshi Sahara echo '<div class="nothing">'.$lang['media_perm_upload'].'</div>'.DOKU_LF; 15688a71175SKate Arzamastseva return false; 15788a71175SKate Arzamastseva } 15888a71175SKate Arzamastseva 1593df72098SAndreas Gohr // load the field descriptions 1603df72098SAndreas Gohr static $fields = null; 161b960c74fSSatoshi Sahara if ($fields === null) { 1623e98e685SKate Arzamastseva $config_files = getConfigFiles('mediameta'); 1633e98e685SKate Arzamastseva foreach ($config_files as $config_file) { 16479e79377SAndreas Gohr if (file_exists($config_file)) include($config_file); 1653df72098SAndreas Gohr } 1663df72098SAndreas Gohr } 1673df72098SAndreas Gohr 1683df72098SAndreas Gohr $src = mediaFN($id); 1693df72098SAndreas Gohr 1703df72098SAndreas Gohr // output 171b960c74fSSatoshi Sahara $form = new Form([ 172b960c74fSSatoshi Sahara 'action' => media_managerURL(['tab_details' => 'view'], '&'), 173b960c74fSSatoshi Sahara 'class' => 'meta' 174b960c74fSSatoshi Sahara ]); 175b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 176b960c74fSSatoshi Sahara $form->setHiddenField('img', $id); 177b960c74fSSatoshi Sahara $form->setHiddenField('mediado', 'save'); 1783df72098SAndreas Gohr foreach ($fields as $key => $field) { 1793df72098SAndreas Gohr // get current value 1803e98e685SKate Arzamastseva if (empty($field[0])) continue; 18124870174SAndreas Gohr $tags = [$field[0]]; 1823df72098SAndreas Gohr if (is_array($field[3])) $tags = array_merge($tags, $field[3]); 1833df72098SAndreas Gohr $value = tpl_img_getTag($tags, '', $src); 184ca6a0701SAndreas Gohr $value = cleanText($value); 1853df72098SAndreas Gohr 1863df72098SAndreas Gohr // prepare attributes 18724870174SAndreas Gohr $p = [ 188b960c74fSSatoshi Sahara 'class' => 'edit', 189b960c74fSSatoshi Sahara 'id' => 'meta__'.$key, 19024870174SAndreas Gohr 'name' => 'meta['.$field[0].']' 19124870174SAndreas Gohr ]; 1923df72098SAndreas Gohr 193b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('row'); 1943df72098SAndreas Gohr if ($field[2] == 'text') { 195bde2a644SSatoshi Sahara $form->addTextInput( 19664159a61SAndreas Gohr $p['name'], 19779a2d784SGerrit Uitslag ($lang[$field[1]] ?: $field[1] . ':') 198b960c74fSSatoshi Sahara )->id($p['id'])->addClass($p['class'])->val($value); 1993df72098SAndreas Gohr } else { 200b960c74fSSatoshi Sahara $form->addTextarea($p['name'], $lang[$field[1]])->id($p['id']) 201b960c74fSSatoshi Sahara ->val(formText($value)) 202b960c74fSSatoshi Sahara ->addClass($p['class']) 203b960c74fSSatoshi Sahara ->attr('rows', '6')->attr('cols', '50'); 2043df72098SAndreas Gohr } 205b960c74fSSatoshi Sahara $form->addTagClose('div'); 2063df72098SAndreas Gohr } 207b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('buttons'); 208b960c74fSSatoshi Sahara $form->addButton('mediado[save]', $lang['btn_save'])->attr('type', 'submit') 209b960c74fSSatoshi Sahara ->attrs(['accesskey' => 's']); 210b960c74fSSatoshi Sahara $form->addTagClose('div'); 211ebc28e69SAndreas Gohr 212b960c74fSSatoshi Sahara $form->addTagClose('div'); 213b960c74fSSatoshi Sahara echo $form->toHTML(); 214ebc28e69SAndreas Gohr return true; 2153df72098SAndreas Gohr} 2163df72098SAndreas Gohr 217666cdec5SMichael Klier/** 21887229c84SAdrian Lang * Convenience function to check if a media file is still in use 219666cdec5SMichael Klier * 220666cdec5SMichael Klier * @author Michael Klier <chi@chimeric.de> 221e0c26282SGerrit Uitslag * 222e0c26282SGerrit Uitslag * @param string $id media id 223e0c26282SGerrit Uitslag * @return array|bool 224666cdec5SMichael Klier */ 225d868eb89SAndreas Gohrfunction media_inuse($id) 226d868eb89SAndreas Gohr{ 227666cdec5SMichael Klier global $conf; 228ebc28e69SAndreas Gohr 229666cdec5SMichael Klier if ($conf['refcheck']) { 230ffec1009SMichael Hamann $mediareferences = ft_mediause($id, true); 23124870174SAndreas Gohr if ($mediareferences === []) { 2326dae2464SAndreas Gohr return false; 233666cdec5SMichael Klier } else { 234666cdec5SMichael Klier return $mediareferences; 235666cdec5SMichael Klier } 236666cdec5SMichael Klier } else { 237666cdec5SMichael Klier return false; 238666cdec5SMichael Klier } 239666cdec5SMichael Klier} 240a05e297aSAndreas Gohr 2413df72098SAndreas Gohr/** 2423df72098SAndreas Gohr * Handles media file deletions 2433df72098SAndreas Gohr * 2443df72098SAndreas Gohr * If configured, checks for media references before deletion 2453df72098SAndreas Gohr * 2463df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 24742ea7f44SGerrit Uitslag * 248ebc28e69SAndreas Gohr * @param string $id media id 24922db8df7SAndreas Gohr * @param int $auth no longer used 25087229c84SAdrian Lang * @return int One of: 0, 25163703ba5SAndreas Gohr * DOKU_MEDIA_DELETED, 25263703ba5SAndreas Gohr * DOKU_MEDIA_DELETED | DOKU_MEDIA_EMPTY_NS, 25363703ba5SAndreas Gohr * DOKU_MEDIA_NOT_AUTH, 25463703ba5SAndreas Gohr * DOKU_MEDIA_INUSE 2553df72098SAndreas Gohr */ 256d868eb89SAndreas Gohrfunction media_delete($id, $auth) 257d868eb89SAndreas Gohr{ 2586183fb05SKate Arzamastseva global $lang; 259ff04e8b7SAndreas Gohr $auth = auth_quickaclcheck(ltrim(getNS($id).':*', ':')); 26087229c84SAdrian Lang if ($auth < AUTH_DELETE) return DOKU_MEDIA_NOT_AUTH; 26187229c84SAdrian Lang if (media_inuse($id)) return DOKU_MEDIA_INUSE; 2623df72098SAndreas Gohr 2633df72098SAndreas Gohr $file = mediaFN($id); 2644a961e72SMichal Kolodziejski 2654a961e72SMichal Kolodziejski // trigger an event - MEDIA_DELETE_FILE 26624870174SAndreas Gohr $data = []; 267666cdec5SMichael Klier $data['id'] = $id; 26879a2d784SGerrit Uitslag $data['name'] = PhpString::basename($file); 2694a961e72SMichal Kolodziejski $data['path'] = $file; 27079e79377SAndreas Gohr $data['size'] = (file_exists($file)) ? filesize($file) : 0; 271666cdec5SMichael Klier 272666cdec5SMichael Klier $data['unl'] = false; 273666cdec5SMichael Klier $data['del'] = false; 274e1d9dcc8SAndreas Gohr $evt = new Event('MEDIA_DELETE_FILE', $data); 2754a961e72SMichal Kolodziejski if ($evt->advise_before()) { 2766183fb05SKate Arzamastseva $old = @filemtime($file); 27779e79377SAndreas Gohr if (!file_exists(mediaFN($id, $old)) && file_exists($file)) { 2786183fb05SKate Arzamastseva // add old revision to the attic 2796183fb05SKate Arzamastseva media_saveOldRevision($id); 2806183fb05SKate Arzamastseva } 2816183fb05SKate Arzamastseva 282666cdec5SMichael Klier $data['unl'] = @unlink($file); 283666cdec5SMichael Klier if ($data['unl']) { 284ac3ed4afSGerrit Uitslag $sizechange = 0 - $data['size']; 285ac3ed4afSGerrit Uitslag addMediaLogEntry(time(), $id, DOKU_CHANGE_TYPE_DELETE, $lang['deleted'], '', null, $sizechange); 286ac3ed4afSGerrit Uitslag 287666cdec5SMichael Klier $data['del'] = io_sweepNS($id, 'mediadir'); 2883df72098SAndreas Gohr } 2894a961e72SMichal Kolodziejski } 2904a961e72SMichal Kolodziejski $evt->advise_after(); 2914a961e72SMichal Kolodziejski unset($evt); 2924a961e72SMichal Kolodziejski 293666cdec5SMichael Klier if ($data['unl'] && $data['del']) { 29487229c84SAdrian Lang return DOKU_MEDIA_DELETED | DOKU_MEDIA_EMPTY_NS; 2953df72098SAndreas Gohr } 2963df72098SAndreas Gohr 29787229c84SAdrian Lang return $data['unl'] ? DOKU_MEDIA_DELETED : 0; 2983df72098SAndreas Gohr} 2993df72098SAndreas Gohr 3003df72098SAndreas Gohr/** 3012d6cc64fSKate Arzamastseva * Handle file uploads via XMLHttpRequest 3022d6cc64fSKate Arzamastseva * 303ebc28e69SAndreas Gohr * @param string $ns target namespace 304ebc28e69SAndreas Gohr * @param int $auth current auth check result 30542ea7f44SGerrit Uitslag * @return false|string false on error, id of the new file on success 3062d6cc64fSKate Arzamastseva */ 307d868eb89SAndreas Gohrfunction media_upload_xhr($ns, $auth) 308d868eb89SAndreas Gohr{ 309da45d883SKate Arzamastseva if (!checkSecurityToken()) return false; 3108108113cSTom N Harris global $INPUT; 311da45d883SKate Arzamastseva 3128108113cSTom N Harris $id = $INPUT->get->str('qqfile'); 31324870174SAndreas Gohr [$ext, $mime] = mimetype($id); 3142d6cc64fSKate Arzamastseva $input = fopen("php://input", "r"); 3152d6cc64fSKate Arzamastseva if (!($tmp = io_mktmpdir())) return false; 31662231793SKate Arzamastseva $path = $tmp.'/'.md5($id); 3172d6cc64fSKate Arzamastseva $target = fopen($path, "w"); 318063fb5b5SAndreas Gohr $realSize = stream_copy_to_stream($input, $target); 3192d6cc64fSKate Arzamastseva fclose($target); 320063fb5b5SAndreas Gohr fclose($input); 3212b9be456SAndreas Gohr if ($INPUT->server->has('CONTENT_LENGTH') && ($realSize != $INPUT->server->int('CONTENT_LENGTH'))) { 322063fb5b5SAndreas Gohr unlink($path); 323063fb5b5SAndreas Gohr return false; 324063fb5b5SAndreas Gohr } 325063fb5b5SAndreas Gohr 3262d6cc64fSKate Arzamastseva $res = media_save( 32724870174SAndreas Gohr ['name' => $path, 'mime' => $mime, 'ext' => $ext], 3282d6cc64fSKate Arzamastseva $ns.':'.$id, 32979a2d784SGerrit Uitslag ($INPUT->get->str('ow') == 'true'), 3302d6cc64fSKate Arzamastseva $auth, 3312d6cc64fSKate Arzamastseva 'copy' 3322d6cc64fSKate Arzamastseva ); 3332d6cc64fSKate Arzamastseva unlink($path); 334900a9e9eSGerrit Uitslag if ($tmp) io_rmdir($tmp, true); 3352d6cc64fSKate Arzamastseva if (is_array($res)) { 3362d6cc64fSKate Arzamastseva msg($res[0], $res[1]); 3372d6cc64fSKate Arzamastseva return false; 3382d6cc64fSKate Arzamastseva } 3392d6cc64fSKate Arzamastseva return $res; 3402d6cc64fSKate Arzamastseva} 3412d6cc64fSKate Arzamastseva 3422d6cc64fSKate Arzamastseva/** 3433df72098SAndreas Gohr * Handles media file uploads 3443df72098SAndreas Gohr * 3453df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 34611d9dfa5SMichael Klier * @author Michael Klier <chi@chimeric.de> 34742ea7f44SGerrit Uitslag * 348ebc28e69SAndreas Gohr * @param string $ns target namespace 349ebc28e69SAndreas Gohr * @param int $auth current auth check result 350ebc28e69SAndreas Gohr * @param bool|array $file $_FILES member, $_FILES['upload'] if false 35142ea7f44SGerrit Uitslag * @return false|string false on error, id of the new file on success 3523df72098SAndreas Gohr */ 353d868eb89SAndreas Gohrfunction media_upload($ns, $auth, $file = false) 354d868eb89SAndreas Gohr{ 355f2ea8432SAndreas Gohr if (!checkSecurityToken()) return false; 3563df72098SAndreas Gohr global $lang; 3578108113cSTom N Harris global $INPUT; 3583df72098SAndreas Gohr 35944409c3dSAndreas Gohr // get file and id 3608108113cSTom N Harris $id = $INPUT->post->str('mediaid'); 3612d6cc64fSKate Arzamastseva if (!$file) $file = $_FILES['upload']; 3623df72098SAndreas Gohr if (empty($id)) $id = $file['name']; 36344409c3dSAndreas Gohr 36499766eefSAndreas Gohr // check for errors (messages are done in lib/exe/mediamanager.php) 36599766eefSAndreas Gohr if ($file['error']) return false; 3669676dc23SAndreas Gohr 36744409c3dSAndreas Gohr // check extensions 36824870174SAndreas Gohr [$fext, $fmime] = mimetype($file['name']); 36924870174SAndreas Gohr [$iext, $imime] = mimetype($id); 37044409c3dSAndreas Gohr if ($fext && !$iext) { 3718cb1eb01SAndreas Gohr // no extension specified in id - read original one 37244409c3dSAndreas Gohr $id .= '.'.$fext; 3738cb1eb01SAndreas Gohr $imime = $fmime; 37444409c3dSAndreas Gohr } elseif ($fext && $fext != $iext) { 37544409c3dSAndreas Gohr // extension was changed, print warning 37644409c3dSAndreas Gohr msg(sprintf($lang['mediaextchange'], $fext, $iext)); 37744409c3dSAndreas Gohr } 37844409c3dSAndreas Gohr 37924870174SAndreas Gohr $res = media_save( 38024870174SAndreas Gohr [ 38124870174SAndreas Gohr 'name' => $file['tmp_name'], 382ffb291f2SAdrian Lang 'mime' => $imime, 38324870174SAndreas Gohr 'ext' => $iext 38424870174SAndreas Gohr ], 38524870174SAndreas Gohr $ns . ':' . $id, 38624870174SAndreas Gohr $INPUT->post->bool('ow'), 38724870174SAndreas Gohr $auth, 38824870174SAndreas Gohr 'copy_uploaded_file' 38924870174SAndreas Gohr ); 390ffb291f2SAdrian Lang if (is_array($res)) { 391ffb291f2SAdrian Lang msg($res[0], $res[1]); 392ffb291f2SAdrian Lang return false; 393ffb291f2SAdrian Lang } 394ffb291f2SAdrian Lang return $res; 395ffb291f2SAdrian Lang} 396ffb291f2SAdrian Lang 397ffb291f2SAdrian Lang/** 39871f17ac4SAndreas Gohr * An alternative to move_uploaded_file that copies 39971f17ac4SAndreas Gohr * 40071f17ac4SAndreas Gohr * Using copy, makes sure any setgid bits on the media directory are honored 40171f17ac4SAndreas Gohr * 40271f17ac4SAndreas Gohr * @see move_uploaded_file() 40342ea7f44SGerrit Uitslag * 40471f17ac4SAndreas Gohr * @param string $from 40571f17ac4SAndreas Gohr * @param string $to 40671f17ac4SAndreas Gohr * @return bool 40771f17ac4SAndreas Gohr */ 408d868eb89SAndreas Gohrfunction copy_uploaded_file($from, $to) 409d868eb89SAndreas Gohr{ 41071f17ac4SAndreas Gohr if (!is_uploaded_file($from)) return false; 41171f17ac4SAndreas Gohr $ok = copy($from, $to); 41271f17ac4SAndreas Gohr @unlink($from); 41371f17ac4SAndreas Gohr return $ok; 41471f17ac4SAndreas Gohr} 41571f17ac4SAndreas Gohr 41671f17ac4SAndreas Gohr/** 417ffb291f2SAdrian Lang * This generates an action event and delegates to _media_upload_action(). 418ffb291f2SAdrian Lang * Action plugins are allowed to pre/postprocess the uploaded file. 419ffb291f2SAdrian Lang * (The triggered event is preventable.) 420ffb291f2SAdrian Lang * 421ffb291f2SAdrian Lang * Event data: 422ffb291f2SAdrian Lang * $data[0] fn_tmp: the temporary file name (read from $_FILES) 423ffb291f2SAdrian Lang * $data[1] fn: the file name of the uploaded file 424ffb291f2SAdrian Lang * $data[2] id: the future directory id of the uploaded file 425ffb291f2SAdrian Lang * $data[3] imime: the mimetype of the uploaded file 426ffb291f2SAdrian Lang * $data[4] overwrite: if an existing file is going to be overwritten 42752a281e8SGerrit Uitslag * $data[5] move: name of function that performs move/copy/.. 428ffb291f2SAdrian Lang * 429ffb291f2SAdrian Lang * @triggers MEDIA_UPLOAD_FINISH 43042ea7f44SGerrit Uitslag * 431e0c26282SGerrit Uitslag * @param array $file 43252a281e8SGerrit Uitslag * @param string $id media id 43342ea7f44SGerrit Uitslag * @param bool $ow overwrite? 434e0c26282SGerrit Uitslag * @param int $auth permission level 43552a281e8SGerrit Uitslag * @param string $move name of functions that performs move/copy/.. 43642ea7f44SGerrit Uitslag * @return false|array|string 437e0c26282SGerrit Uitslag */ 438d868eb89SAndreas Gohrfunction media_save($file, $id, $ow, $auth, $move) 439d868eb89SAndreas Gohr{ 440ffb291f2SAdrian Lang if ($auth < AUTH_UPLOAD) { 44124870174SAndreas Gohr return ["You don't have permissions to upload files.", -1]; 442ffb291f2SAdrian Lang } 443ffb291f2SAdrian Lang 444ffb291f2SAdrian Lang if (!isset($file['mime']) || !isset($file['ext'])) { 44524870174SAndreas Gohr [$ext, $mime] = mimetype($id); 446ffb291f2SAdrian Lang if (!isset($file['mime'])) { 447ffb291f2SAdrian Lang $file['mime'] = $mime; 448ffb291f2SAdrian Lang } 449ffb291f2SAdrian Lang if (!isset($file['ext'])) { 450ffb291f2SAdrian Lang $file['ext'] = $ext; 451ffb291f2SAdrian Lang } 452ffb291f2SAdrian Lang } 453ffb291f2SAdrian Lang 45492cac9a9SKate Arzamastseva global $lang, $conf; 455ffb291f2SAdrian Lang 4563df72098SAndreas Gohr // get filename 4573543c6deSAndreas Gohr $id = cleanID($id); 4583df72098SAndreas Gohr $fn = mediaFN($id); 4593df72098SAndreas Gohr 4603df72098SAndreas Gohr // get filetype regexp 4613df72098SAndreas Gohr $types = array_keys(getMimeTypes()); 462bad6fc0dSAndreas Gohr $types = array_map( 46324870174SAndreas Gohr static fn($q) => preg_quote($q, "/"), 464bad6fc0dSAndreas Gohr $types 465bad6fc0dSAndreas Gohr ); 46624870174SAndreas Gohr $regex = implode('|', $types); 4673df72098SAndreas Gohr 4683df72098SAndreas Gohr // because a temp file was created already 469ffb291f2SAdrian Lang if (!preg_match('/\.('.$regex.')$/i', $fn)) { 47024870174SAndreas Gohr return [$lang['uploadwrong'], -1]; 471ffb291f2SAdrian Lang } 472ffb291f2SAdrian Lang 4733df72098SAndreas Gohr //check for overwrite 47479e79377SAndreas Gohr $overwrite = file_exists($fn); 475e5d185e1SKate Arzamastseva $auth_ow = (($conf['mediarevisions']) ? AUTH_UPLOAD : AUTH_DELETE); 476e5d185e1SKate Arzamastseva if ($overwrite && (!$ow || $auth < $auth_ow)) { 47724870174SAndreas Gohr return [$lang['uploadexist'], 0]; 4783df72098SAndreas Gohr } 4798cb1eb01SAndreas Gohr // check for valid content 480ffb291f2SAdrian Lang $ok = media_contentcheck($file['name'], $file['mime']); 4818cb1eb01SAndreas Gohr if ($ok == -1) { 48224870174SAndreas Gohr return [sprintf($lang['uploadbadcontent'], '.' . $file['ext']), -1]; 4838cb1eb01SAndreas Gohr } elseif ($ok == -2) { 48424870174SAndreas Gohr return [$lang['uploadspam'], -1]; 48526ceae18SAndreas Gohr } elseif ($ok == -3) { 48624870174SAndreas Gohr return [$lang['uploadxss'], -1]; 4878cb1eb01SAndreas Gohr } 4888cb1eb01SAndreas Gohr 48911d9dfa5SMichael Klier // prepare event data 49024870174SAndreas Gohr $data = []; 491ffb291f2SAdrian Lang $data[0] = $file['name']; 49211d9dfa5SMichael Klier $data[1] = $fn; 49311d9dfa5SMichael Klier $data[2] = $id; 494ffb291f2SAdrian Lang $data[3] = $file['mime']; 49599c8d7f2Smichael $data[4] = $overwrite; 496ffb291f2SAdrian Lang $data[5] = $move; 49711d9dfa5SMichael Klier 49811d9dfa5SMichael Klier // trigger event 499cbb44eabSAndreas Gohr return Event::createAndTrigger('MEDIA_UPLOAD_FINISH', $data, '_media_upload_action', true); 50011d9dfa5SMichael Klier} 50111d9dfa5SMichael Klier 50211d9dfa5SMichael Klier/** 50342ea7f44SGerrit Uitslag * Callback adapter for media_upload_finish() triggered by MEDIA_UPLOAD_FINISH 50442ea7f44SGerrit Uitslag * 50511d9dfa5SMichael Klier * @author Michael Klier <chi@chimeric.de> 50642ea7f44SGerrit Uitslag * 50742ea7f44SGerrit Uitslag * @param array $data event data 50842ea7f44SGerrit Uitslag * @return false|array|string 50911d9dfa5SMichael Klier */ 510d868eb89SAndreas Gohrfunction _media_upload_action($data) 511d868eb89SAndreas Gohr{ 51211d9dfa5SMichael Klier // fixme do further sanity tests of given data? 513ffb291f2SAdrian Lang if (is_array($data) && count($data)===6) { 514ffb291f2SAdrian Lang return media_upload_finish($data[0], $data[1], $data[2], $data[3], $data[4], $data[5]); 51511d9dfa5SMichael Klier } else { 51611d9dfa5SMichael Klier return false; //callback error 51711d9dfa5SMichael Klier } 51811d9dfa5SMichael Klier} 51911d9dfa5SMichael Klier 52011d9dfa5SMichael Klier/** 52111d9dfa5SMichael Klier * Saves an uploaded media file 52211d9dfa5SMichael Klier * 52311d9dfa5SMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 52411d9dfa5SMichael Klier * @author Michael Klier <chi@chimeric.de> 525cbe26ad6SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 52642ea7f44SGerrit Uitslag * 52742ea7f44SGerrit Uitslag * @param string $fn_tmp 52842ea7f44SGerrit Uitslag * @param string $fn 52942ea7f44SGerrit Uitslag * @param string $id media id 53042ea7f44SGerrit Uitslag * @param string $imime mime type 53142ea7f44SGerrit Uitslag * @param bool $overwrite overwrite existing? 53242ea7f44SGerrit Uitslag * @param string $move function name 53342ea7f44SGerrit Uitslag * @return array|string 53411d9dfa5SMichael Klier */ 535d868eb89SAndreas Gohrfunction media_upload_finish($fn_tmp, $fn, $id, $imime, $overwrite, $move = 'move_uploaded_file') 536d868eb89SAndreas Gohr{ 53711d9dfa5SMichael Klier global $conf; 53811d9dfa5SMichael Klier global $lang; 5399c1bd4bcSKate Arzamastseva global $REV; 54011d9dfa5SMichael Klier 541e4f389efSKate Arzamastseva $old = @filemtime($fn); 54279e79377SAndreas Gohr if (!file_exists(mediaFN($id, $old)) && file_exists($fn)) { 543e4f389efSKate Arzamastseva // add old revision to the attic if missing 544cbe26ad6SKate Arzamastseva media_saveOldRevision($id); 545e4f389efSKate Arzamastseva } 546e4f389efSKate Arzamastseva 5473df72098SAndreas Gohr // prepare directory 548cc7d0c94SBen Coburn io_createNamespace($id, 'media'); 54911d9dfa5SMichael Klier 550ac3ed4afSGerrit Uitslag $filesize_old = file_exists($fn) ? filesize($fn) : 0; 551ac3ed4afSGerrit Uitslag 552ffb291f2SAdrian Lang if ($move($fn_tmp, $fn)) { 55323846a98SKate Arzamastseva @clearstatcache(true, $fn); 554dad6764eSKate Arzamastseva $new = @filemtime($fn); 55574400ea5SBen Coburn // Set the correct permission here. 55674400ea5SBen Coburn // Always chmod media because they may be saved with different permissions than expected from the php umask. 55774400ea5SBen Coburn // (Should normally chmod to $conf['fperm'] only if $conf['fperm'] is set.) 55874400ea5SBen Coburn chmod($fn, $conf['fmode']); 5593df72098SAndreas Gohr msg($lang['uploadsucc'], 1); 56083734cddSPhy media_notify($id, $fn, $imime, $old, $new); 56199c8d7f2Smichael // add a log entry to the media changelog 562ac3ed4afSGerrit Uitslag $filesize_new = filesize($fn); 563ac3ed4afSGerrit Uitslag $sizechange = $filesize_new - $filesize_old; 5649c1bd4bcSKate Arzamastseva if ($REV) { 56564159a61SAndreas Gohr addMediaLogEntry( 56664159a61SAndreas Gohr $new, 56764159a61SAndreas Gohr $id, 56864159a61SAndreas Gohr DOKU_CHANGE_TYPE_REVERT, 56964159a61SAndreas Gohr sprintf($lang['restored'], dformat($REV)), 57064159a61SAndreas Gohr $REV, 57164159a61SAndreas Gohr null, 57264159a61SAndreas Gohr $sizechange 57364159a61SAndreas Gohr ); 5749c1bd4bcSKate Arzamastseva } elseif ($overwrite) { 575ac3ed4afSGerrit Uitslag addMediaLogEntry($new, $id, DOKU_CHANGE_TYPE_EDIT, '', '', null, $sizechange); 57699c8d7f2Smichael } else { 577ac3ed4afSGerrit Uitslag addMediaLogEntry($new, $id, DOKU_CHANGE_TYPE_CREATE, $lang['created'], '', null, $sizechange); 57899c8d7f2Smichael } 5793df72098SAndreas Gohr return $id; 5803df72098SAndreas Gohr } else { 58124870174SAndreas Gohr return [$lang['uploadfail'], -1]; 5823df72098SAndreas Gohr } 5833df72098SAndreas Gohr} 5843df72098SAndreas Gohr 5858cb1eb01SAndreas Gohr/** 586cbe26ad6SKate Arzamastseva * Moves the current version of media file to the media_attic 587cbe26ad6SKate Arzamastseva * directory 588cbe26ad6SKate Arzamastseva * 589cbe26ad6SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 59042ea7f44SGerrit Uitslag * 591cbe26ad6SKate Arzamastseva * @param string $id 592cbe26ad6SKate Arzamastseva * @return int - revision date 593e4f389efSKate Arzamastseva */ 594d868eb89SAndreas Gohrfunction media_saveOldRevision($id) 595d868eb89SAndreas Gohr{ 596dbf57c96SKate Arzamastseva global $conf, $lang; 597dbf57c96SKate Arzamastseva 598e4f389efSKate Arzamastseva $oldf = mediaFN($id); 59979e79377SAndreas Gohr if (!file_exists($oldf)) return ''; 600e4f389efSKate Arzamastseva $date = filemtime($oldf); 601e5d185e1SKate Arzamastseva if (!$conf['mediarevisions']) return $date; 602e5d185e1SKate Arzamastseva 603047bad06SGerrit Uitslag $medialog = new MediaChangeLog($id); 604047bad06SGerrit Uitslag if (!$medialog->getRevisionInfo($date)) { 605dbf57c96SKate Arzamastseva // there was an external edit, 606dbf57c96SKate Arzamastseva // there is no log entry for current version of file 607ac3ed4afSGerrit Uitslag $sizechange = filesize($oldf); 60879e79377SAndreas Gohr if (!file_exists(mediaMetaFN($id, '.changes'))) { 609ac3ed4afSGerrit Uitslag addMediaLogEntry($date, $id, DOKU_CHANGE_TYPE_CREATE, $lang['created'], '', null, $sizechange); 610dbf57c96SKate Arzamastseva } else { 611ac3ed4afSGerrit Uitslag $oldRev = $medialog->getRevisions(-1, 1); // from changelog 612ac3ed4afSGerrit Uitslag $oldRev = (int) (empty($oldRev) ? 0 : $oldRev[0]); 613ac3ed4afSGerrit Uitslag $filesize_old = filesize(mediaFN($id, $oldRev)); 61424870174SAndreas Gohr $sizechange -= $filesize_old; 615ac3ed4afSGerrit Uitslag 616ac3ed4afSGerrit Uitslag addMediaLogEntry($date, $id, DOKU_CHANGE_TYPE_EDIT, '', '', null, $sizechange); 617dbf57c96SKate Arzamastseva } 618dbf57c96SKate Arzamastseva } 619dbf57c96SKate Arzamastseva 620e4f389efSKate Arzamastseva $newf = mediaFN($id, $date); 621e4f389efSKate Arzamastseva io_makeFileDir($newf); 622cbe26ad6SKate Arzamastseva if (copy($oldf, $newf)) { 623e4f389efSKate Arzamastseva // Set the correct permission here. 624e4f389efSKate Arzamastseva // Always chmod media because they may be saved with different permissions than expected from the php umask. 625e4f389efSKate Arzamastseva // (Should normally chmod to $conf['fperm'] only if $conf['fperm'] is set.) 626e4f389efSKate Arzamastseva chmod($newf, $conf['fmode']); 627e4f389efSKate Arzamastseva } 628e4f389efSKate Arzamastseva return $date; 629e4f389efSKate Arzamastseva} 630e4f389efSKate Arzamastseva 631e4f389efSKate Arzamastseva/** 6328cb1eb01SAndreas Gohr * This function checks if the uploaded content is really what the 63326ceae18SAndreas Gohr * mimetype says it is. We also do spam checking for text types here. 6348cb1eb01SAndreas Gohr * 6358cb1eb01SAndreas Gohr * We need to do this stuff because we can not rely on the browser 6368cb1eb01SAndreas Gohr * to do this check correctly. Yes, IE is broken as usual. 6378cb1eb01SAndreas Gohr * 6388cb1eb01SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 63926ceae18SAndreas Gohr * @link http://www.splitbrain.org/blog/2007-02/12-internet_explorer_facilitates_cross_site_scripting 6408cb1eb01SAndreas Gohr * @fixme check all 26 magic IE filetypes here? 64142ea7f44SGerrit Uitslag * 64242ea7f44SGerrit Uitslag * @param string $file path to file 64342ea7f44SGerrit Uitslag * @param string $mime mimetype 64442ea7f44SGerrit Uitslag * @return int 6458cb1eb01SAndreas Gohr */ 646d868eb89SAndreas Gohrfunction media_contentcheck($file, $mime) 647d868eb89SAndreas Gohr{ 64826ceae18SAndreas Gohr global $conf; 64926ceae18SAndreas Gohr if ($conf['iexssprotect']) { 65026ceae18SAndreas Gohr $fh = @fopen($file, 'rb'); 65126ceae18SAndreas Gohr if ($fh) { 65226ceae18SAndreas Gohr $bytes = fread($fh, 256); 65326ceae18SAndreas Gohr fclose($fh); 65426ceae18SAndreas Gohr if (preg_match('/<(script|a|img|html|body|iframe)[\s>]/i', $bytes)) { 65542ea7f44SGerrit Uitslag return -3; //XSS: possibly malicious content 65626ceae18SAndreas Gohr } 65726ceae18SAndreas Gohr } 65826ceae18SAndreas Gohr } 6598cb1eb01SAndreas Gohr if (substr($mime, 0, 6) == 'image/') { 6608cb1eb01SAndreas Gohr $info = @getimagesize($file); 6618cb1eb01SAndreas Gohr if ($mime == 'image/gif' && $info[2] != 1) { 66242ea7f44SGerrit Uitslag return -1; // uploaded content did not match the file extension 6638cb1eb01SAndreas Gohr } elseif ($mime == 'image/jpeg' && $info[2] != 2) { 6648cb1eb01SAndreas Gohr return -1; 6658cb1eb01SAndreas Gohr } elseif ($mime == 'image/png' && $info[2] != 3) { 6668cb1eb01SAndreas Gohr return -1; 6678cb1eb01SAndreas Gohr } 6688cb1eb01SAndreas Gohr # fixme maybe check other images types as well 6698cb1eb01SAndreas Gohr } elseif (substr($mime, 0, 5) == 'text/') { 6708cb1eb01SAndreas Gohr global $TEXT; 6718cb1eb01SAndreas Gohr $TEXT = io_readFile($file); 6728cb1eb01SAndreas Gohr if (checkwordblock()) { 67342ea7f44SGerrit Uitslag return -2; //blocked by the spam blacklist 6748cb1eb01SAndreas Gohr } 6758cb1eb01SAndreas Gohr } 6768cb1eb01SAndreas Gohr return 0; 6778cb1eb01SAndreas Gohr} 6783df72098SAndreas Gohr 6793df72098SAndreas Gohr/** 68075030359SAndreas Gohr * Send a notify mail on uploads 68175030359SAndreas Gohr * 68275030359SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 68342ea7f44SGerrit Uitslag * 68442ea7f44SGerrit Uitslag * @param string $id media id 68542ea7f44SGerrit Uitslag * @param string $file path to file 68642ea7f44SGerrit Uitslag * @param string $mime mime type 68742ea7f44SGerrit Uitslag * @param bool|int $old_rev revision timestamp or false 68875030359SAndreas Gohr */ 689d868eb89SAndreas Gohrfunction media_notify($id, $file, $mime, $old_rev = false, $current_rev = false) 690d868eb89SAndreas Gohr{ 69175030359SAndreas Gohr global $conf; 69279a2d784SGerrit Uitslag if (empty($conf['notify'])) return; //notify enabled? 69375030359SAndreas Gohr 694704a815fSMichael Große $subscription = new MediaSubscriptionSender(); 69579a2d784SGerrit Uitslag $subscription->sendMediaDiff($conf['notify'], 'uploadmail', $id, $old_rev, $current_rev); 69675030359SAndreas Gohr} 69775030359SAndreas Gohr 69875030359SAndreas Gohr/** 6993df72098SAndreas Gohr * List all files in a given Media namespace 70042ea7f44SGerrit Uitslag * 70121d806cdSGerrit Uitslag * @param string $ns namespace 70242ea7f44SGerrit Uitslag * @param null|int $auth permission level 70342ea7f44SGerrit Uitslag * @param string $jump id 70442ea7f44SGerrit Uitslag * @param bool $fullscreenview 7058702de7fSGerrit Uitslag * @param bool|string $sort sorting order, false skips sorting 7063df72098SAndreas Gohr */ 707d868eb89SAndreas Gohrfunction media_filelist($ns, $auth = null, $jump = '', $fullscreenview = false, $sort = false) 708d868eb89SAndreas Gohr{ 7093df72098SAndreas Gohr global $conf; 7103df72098SAndreas Gohr global $lang; 7113df72098SAndreas Gohr $ns = cleanID($ns); 7123df72098SAndreas Gohr 7133df72098SAndreas Gohr // check auth our self if not given (needed for ajax calls) 7143df72098SAndreas Gohr if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 7153df72098SAndreas Gohr 716d9162c6cSKate Arzamastseva if (!$fullscreenview) echo '<h1 id="media__ns">:'.hsc($ns).'</h1>'.NL; 7173df72098SAndreas Gohr 7183df72098SAndreas Gohr if ($auth < AUTH_READ) { 7193df72098SAndreas Gohr // FIXME: print permission warning here instead? 7203df72098SAndreas Gohr echo '<div class="nothing">'.$lang['nothingfound'].'</div>'.NL; 72156fe6664SAndreas Gohr } else { 72289274c0dSChristopher Smith if (!$fullscreenview) { 72389274c0dSChristopher Smith media_uploadform($ns, $auth); 72489274c0dSChristopher Smith media_searchform($ns); 72589274c0dSChristopher Smith } 7263df72098SAndreas Gohr 7273df72098SAndreas Gohr $dir = utf8_encodeFN(str_replace(':', '/', $ns)); 72824870174SAndreas Gohr $data = []; 729dccd6b2bSAndreas Gohr search( 730dccd6b2bSAndreas Gohr $data, 731dccd6b2bSAndreas Gohr $conf['mediadir'], 732dccd6b2bSAndreas Gohr 'search_mediafiles', 733dccd6b2bSAndreas Gohr ['showmsg'=>true, 'depth'=>1], 734dccd6b2bSAndreas Gohr $dir, 735dccd6b2bSAndreas Gohr 1, 736dccd6b2bSAndreas Gohr $sort 737dccd6b2bSAndreas Gohr ); 7383df72098SAndreas Gohr 7393df72098SAndreas Gohr if (!count($data)) { 7403df72098SAndreas Gohr echo '<div class="nothing">'.$lang['nothingfound'].'</div>'.NL; 7415b9353faSKate Arzamastseva } else { 7425b9353faSKate Arzamastseva if ($fullscreenview) { 743554a8c9fSAdrian Lang echo '<ul class="' . _media_get_list_type() . '">'; 7445b9353faSKate Arzamastseva } 7455b9353faSKate Arzamastseva foreach ($data as $item) { 7465b9353faSKate Arzamastseva if (!$fullscreenview) { 7474f33babfSAndreas Gohr //FIXME old call: media_printfile($item,$auth,$jump); 74879a2d784SGerrit Uitslag $display = new DisplayRow($item); 7499453716dSAndreas Gohr $display->scrollIntoView($jump == $item->getID()); 7504f33babfSAndreas Gohr $display->show(); 7515b9353faSKate Arzamastseva } else { 7524f33babfSAndreas Gohr //FIXME old call: media_printfile_thumbs($item,$auth,$jump); 7534f33babfSAndreas Gohr echo '<li>'; 75479a2d784SGerrit Uitslag $display = new DisplayTile($item); 7559453716dSAndreas Gohr $display->scrollIntoView($jump == $item->getID()); 7564f33babfSAndreas Gohr $display->show(); 7574f33babfSAndreas Gohr echo '</li>'; 7585b9353faSKate Arzamastseva } 7595b9353faSKate Arzamastseva } 76094add303SAnika Henke if ($fullscreenview) echo '</ul>'.NL; 7613df72098SAndreas Gohr } 76256fe6664SAndreas Gohr } 763d9162c6cSKate Arzamastseva} 764d9162c6cSKate Arzamastseva 765d9162c6cSKate Arzamastseva/** 766d9162c6cSKate Arzamastseva * Prints tabs for files list actions 767d9162c6cSKate Arzamastseva * 768d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 76995b451bcSAdrian Lang * @author Adrian Lang <mail@adrianlang.de> 77095b451bcSAdrian Lang * 771035e07f1SKate Arzamastseva * @param string $selected_tab - opened tab 772d9162c6cSKate Arzamastseva */ 77395b451bcSAdrian Lang 774d868eb89SAndreas Gohrfunction media_tabs_files($selected_tab = '') 775d868eb89SAndreas Gohr{ 776d9162c6cSKate Arzamastseva global $lang; 77724870174SAndreas Gohr $tabs = []; 77824870174SAndreas Gohr foreach ([ 77924870174SAndreas Gohr 'files' => 'mediaselect', 78095b451bcSAdrian Lang 'upload' => 'media_uploadtab', 78124870174SAndreas Gohr 'search' => 'media_searchtab' 78224870174SAndreas Gohr ] as $tab => $caption) { 78324870174SAndreas Gohr $tabs[$tab] = [ 78424870174SAndreas Gohr 'href' => media_managerURL(['tab_files' => $tab], '&'), 78524870174SAndreas Gohr 'caption' => $lang[$caption] 78624870174SAndreas Gohr ]; 78795b451bcSAdrian Lang } 788d9162c6cSKate Arzamastseva 78995b451bcSAdrian Lang html_tabs($tabs, $selected_tab); 790d9162c6cSKate Arzamastseva} 791d9162c6cSKate Arzamastseva 792d9162c6cSKate Arzamastseva/** 793d9162c6cSKate Arzamastseva * Prints tabs for files details actions 794d9162c6cSKate Arzamastseva * 795d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 796ebc28e69SAndreas Gohr * @param string $image filename of the current image 797ebc28e69SAndreas Gohr * @param string $selected_tab opened tab 798d9162c6cSKate Arzamastseva */ 799d868eb89SAndreas Gohrfunction media_tabs_details($image, $selected_tab = '') 800d868eb89SAndreas Gohr{ 801e5d185e1SKate Arzamastseva global $lang, $conf; 802d9162c6cSKate Arzamastseva 80324870174SAndreas Gohr $tabs = []; 80424870174SAndreas Gohr $tabs['view'] = [ 80524870174SAndreas Gohr 'href' => media_managerURL(['tab_details' => 'view'], '&'), 80624870174SAndreas Gohr 'caption' => $lang['media_viewtab'] 80724870174SAndreas Gohr ]; 808d9162c6cSKate Arzamastseva 80924870174SAndreas Gohr [, $mime] = mimetype($image); 81079e79377SAndreas Gohr if ($mime == 'image/jpeg' && file_exists(mediaFN($image))) { 81124870174SAndreas Gohr $tabs['edit'] = [ 81224870174SAndreas Gohr 'href' => media_managerURL(['tab_details' => 'edit'], '&'), 81324870174SAndreas Gohr 'caption' => $lang['media_edittab'] 81424870174SAndreas Gohr ]; 815dd9ba38eSKate Arzamastseva } 816e5d185e1SKate Arzamastseva if ($conf['mediarevisions']) { 81724870174SAndreas Gohr $tabs['history'] = [ 81824870174SAndreas Gohr 'href' => media_managerURL(['tab_details' => 'history'], '&'), 81924870174SAndreas Gohr 'caption' => $lang['media_historytab'] 82024870174SAndreas Gohr ]; 821e5d185e1SKate Arzamastseva } 822d9162c6cSKate Arzamastseva 82395b451bcSAdrian Lang html_tabs($tabs, $selected_tab); 824d9162c6cSKate Arzamastseva} 825d9162c6cSKate Arzamastseva 826d9162c6cSKate Arzamastseva/** 827d9162c6cSKate Arzamastseva * Prints options for the tab that displays a list of all files 828d9162c6cSKate Arzamastseva * 829d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 830d9162c6cSKate Arzamastseva */ 831d868eb89SAndreas Gohrfunction media_tab_files_options() 832d868eb89SAndreas Gohr{ 8338108113cSTom N Harris global $lang; 8348108113cSTom N Harris global $INPUT; 835b7e5821dSAndreas Gohr global $ID; 836b960c74fSSatoshi Sahara 837b960c74fSSatoshi Sahara $form = new Form([ 838b960c74fSSatoshi Sahara 'method' => 'get', 839b960c74fSSatoshi Sahara 'action' => wl($ID), 840b960c74fSSatoshi Sahara 'class' => 'options' 841b960c74fSSatoshi Sahara ]); 842b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 843b960c74fSSatoshi Sahara $form->setHiddenField('sectok', null); 844b960c74fSSatoshi Sahara $media_manager_params = media_managerURL([], '', false, true); 84538b2bf35SAnika Henke foreach ($media_manager_params as $pKey => $pVal) { 846b960c74fSSatoshi Sahara $form->setHiddenField($pKey, $pVal); 84738b2bf35SAnika Henke } 8488108113cSTom N Harris if ($INPUT->has('q')) { 849b960c74fSSatoshi Sahara $form->setHiddenField('q', $INPUT->str('q')); 850554a8c9fSAdrian Lang } 851b960c74fSSatoshi Sahara $form->addHTML('<ul>'.NL); 85224870174SAndreas Gohr foreach ([ 85324870174SAndreas Gohr 'list' => ['listType', ['thumbs', 'rows']], 85424870174SAndreas Gohr 'sort' => ['sortBy', ['name', 'date']] 85524870174SAndreas Gohr ] as $group => $content) { 856ec88e837SAndreas Gohr $checked = "_media_get_{$group}_type"; 857554a8c9fSAdrian Lang $checked = $checked(); 858d9162c6cSKate Arzamastseva 859b960c74fSSatoshi Sahara $form->addHTML('<li class="'. $content[0] .'">'); 86095b451bcSAdrian Lang foreach ($content[1] as $option) { 86124870174SAndreas Gohr $attrs = []; 862554a8c9fSAdrian Lang if ($checked == $option) { 86395b451bcSAdrian Lang $attrs['checked'] = 'checked'; 86495b451bcSAdrian Lang } 865b960c74fSSatoshi Sahara $radio = $form->addRadioButton( 866b960c74fSSatoshi Sahara $group.'_dwmedia', 867b960c74fSSatoshi Sahara $lang['media_'.$group.'_'.$option] 868b960c74fSSatoshi Sahara )->val($option)->id($content[0].'__'.$option)->addClass($option); 869b960c74fSSatoshi Sahara $radio->attrs($attrs); 87095b451bcSAdrian Lang } 871b960c74fSSatoshi Sahara $form->addHTML('</li>'.NL); 87295b451bcSAdrian Lang } 873b960c74fSSatoshi Sahara $form->addHTML('<li>'); 874b960c74fSSatoshi Sahara $form->addButton('', $lang['btn_apply'])->attr('type', 'submit'); 875b960c74fSSatoshi Sahara $form->addHTML('</li>'.NL); 876b960c74fSSatoshi Sahara $form->addHTML('</ul>'.NL); 877b960c74fSSatoshi Sahara $form->addTagClose('div'); 878b960c74fSSatoshi Sahara print $form->toHTML(); 879d9162c6cSKate Arzamastseva} 880d9162c6cSKate Arzamastseva 881d9162c6cSKate Arzamastseva/** 88287deddfaSKate Arzamastseva * Returns type of sorting for the list of files in media manager 88387deddfaSKate Arzamastseva * 88487deddfaSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 88542ea7f44SGerrit Uitslag * 88687deddfaSKate Arzamastseva * @return string - sort type 88787deddfaSKate Arzamastseva */ 888d868eb89SAndreas Gohrfunction _media_get_sort_type() 889d868eb89SAndreas Gohr{ 89024870174SAndreas Gohr return _media_get_display_param('sort', ['default' => 'name', 'date']); 89187deddfaSKate Arzamastseva} 892554a8c9fSAdrian Lang 8936ffaeda9SGerrit Uitslag/** 8946ffaeda9SGerrit Uitslag * Returns type of listing for the list of files in media manager 8956ffaeda9SGerrit Uitslag * 8966ffaeda9SGerrit Uitslag * @author Kate Arzamastseva <pshns@ukr.net> 89742ea7f44SGerrit Uitslag * 8986ffaeda9SGerrit Uitslag * @return string - list type 8996ffaeda9SGerrit Uitslag */ 900d868eb89SAndreas Gohrfunction _media_get_list_type() 901d868eb89SAndreas Gohr{ 90224870174SAndreas Gohr return _media_get_display_param('list', ['default' => 'thumbs', 'rows']); 90387deddfaSKate Arzamastseva} 904554a8c9fSAdrian Lang 9056ffaeda9SGerrit Uitslag/** 9066ffaeda9SGerrit Uitslag * Get display parameters 9076ffaeda9SGerrit Uitslag * 9086ffaeda9SGerrit Uitslag * @param string $param name of parameter 9096ffaeda9SGerrit Uitslag * @param array $values allowed values, where default value has index key 'default' 9106ffaeda9SGerrit Uitslag * @return string the parameter value 9116ffaeda9SGerrit Uitslag */ 912d868eb89SAndreas Gohrfunction _media_get_display_param($param, $values) 913d868eb89SAndreas Gohr{ 9148108113cSTom N Harris global $INPUT; 9158108113cSTom N Harris if (in_array($INPUT->str($param), $values)) { 916554a8c9fSAdrian Lang // FIXME: Set cookie 9178108113cSTom N Harris return $INPUT->str($param); 918554a8c9fSAdrian Lang } else { 9193629bc8cSAdrian Lang $val = get_doku_pref($param, $values['default']); 9203629bc8cSAdrian Lang if (!in_array($val, $values)) { 9213629bc8cSAdrian Lang $val = $values['default']; 9223629bc8cSAdrian Lang } 9233629bc8cSAdrian Lang return $val; 924554a8c9fSAdrian Lang } 92587deddfaSKate Arzamastseva} 92687deddfaSKate Arzamastseva 92787deddfaSKate Arzamastseva/** 928d9162c6cSKate Arzamastseva * Prints tab that displays a list of all files 929d9162c6cSKate Arzamastseva * 930d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 93142ea7f44SGerrit Uitslag * 93242ea7f44SGerrit Uitslag * @param string $ns 93342ea7f44SGerrit Uitslag * @param null|int $auth permission level 93442ea7f44SGerrit Uitslag * @param string $jump item id 935d9162c6cSKate Arzamastseva */ 936d868eb89SAndreas Gohrfunction media_tab_files($ns, $auth = null, $jump = '') 937d868eb89SAndreas Gohr{ 938d9162c6cSKate Arzamastseva global $lang; 939d9162c6cSKate Arzamastseva if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 940d9162c6cSKate Arzamastseva 941d9162c6cSKate Arzamastseva if ($auth < AUTH_READ) { 94288a71175SKate Arzamastseva echo '<div class="nothing">'.$lang['media_perm_read'].'</div>'.NL; 943d9162c6cSKate Arzamastseva } else { 94495b451bcSAdrian Lang media_filelist($ns, $auth, $jump, true, _media_get_sort_type()); 945d9162c6cSKate Arzamastseva } 946d9162c6cSKate Arzamastseva} 947d9162c6cSKate Arzamastseva 948d9162c6cSKate Arzamastseva/** 949d9162c6cSKate Arzamastseva * Prints tab that displays uploading form 950d9162c6cSKate Arzamastseva * 951d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 95242ea7f44SGerrit Uitslag * 95342ea7f44SGerrit Uitslag * @param string $ns 95442ea7f44SGerrit Uitslag * @param null|int $auth permission level 95542ea7f44SGerrit Uitslag * @param string $jump item id 956d9162c6cSKate Arzamastseva */ 957d868eb89SAndreas Gohrfunction media_tab_upload($ns, $auth = null, $jump = '') 958d868eb89SAndreas Gohr{ 959d9162c6cSKate Arzamastseva global $lang; 960d9162c6cSKate Arzamastseva if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 961d9162c6cSKate Arzamastseva 96294add303SAnika Henke echo '<div class="upload">'.NL; 96395b451bcSAdrian Lang if ($auth >= AUTH_UPLOAD) { 96495b451bcSAdrian Lang echo '<p>' . $lang['mediaupload'] . '</p>'; 96595b451bcSAdrian Lang } 966d9162c6cSKate Arzamastseva media_uploadform($ns, $auth, true); 96794add303SAnika Henke echo '</div>'.NL; 968d9162c6cSKate Arzamastseva} 969d9162c6cSKate Arzamastseva 970d9162c6cSKate Arzamastseva/** 971d9162c6cSKate Arzamastseva * Prints tab that displays search form 972d9162c6cSKate Arzamastseva * 973d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 97442ea7f44SGerrit Uitslag * 97542ea7f44SGerrit Uitslag * @param string $ns 97642ea7f44SGerrit Uitslag * @param null|int $auth permission level 977d9162c6cSKate Arzamastseva */ 978d868eb89SAndreas Gohrfunction media_tab_search($ns, $auth = null) 979d868eb89SAndreas Gohr{ 9808108113cSTom N Harris global $INPUT; 981d9162c6cSKate Arzamastseva 9828108113cSTom N Harris $do = $INPUT->str('mediado'); 9838108113cSTom N Harris $query = $INPUT->str('q'); 98494add303SAnika Henke echo '<div class="search">'.NL; 985d9162c6cSKate Arzamastseva 986d9162c6cSKate Arzamastseva media_searchform($ns, $query, true); 9872dba8df4SAdrian Lang if ($do == 'searchlist' || $query) { 98895b451bcSAdrian Lang media_searchlist($query, $ns, $auth, true, _media_get_sort_type()); 98995b451bcSAdrian Lang } 99094add303SAnika Henke echo '</div>'.NL; 991d9162c6cSKate Arzamastseva} 992d9162c6cSKate Arzamastseva 993d9162c6cSKate Arzamastseva/** 994d9162c6cSKate Arzamastseva * Prints tab that displays mediafile details 995d9162c6cSKate Arzamastseva * 996d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 997e0c26282SGerrit Uitslag * 998e0c26282SGerrit Uitslag * @param string $image media id 999e0c26282SGerrit Uitslag * @param string $ns 1000e0c26282SGerrit Uitslag * @param null|int $auth permission level 100142ea7f44SGerrit Uitslag * @param string|int $rev revision timestamp or empty string 1002d9162c6cSKate Arzamastseva */ 1003d868eb89SAndreas Gohrfunction media_tab_view($image, $ns, $auth = null, $rev = '') 1004d868eb89SAndreas Gohr{ 1005ebc28e69SAndreas Gohr global $lang; 1006d9162c6cSKate Arzamastseva if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 1007d9162c6cSKate Arzamastseva 1008e136d6ccSKate Arzamastseva if ($image && $auth >= AUTH_READ) { 1009dd9ba38eSKate Arzamastseva $meta = new JpegMeta(mediaFN($image, $rev)); 1010dd9ba38eSKate Arzamastseva media_preview($image, $auth, $rev, $meta); 1011e136d6ccSKate Arzamastseva media_preview_buttons($image, $auth, $rev); 1012dd9ba38eSKate Arzamastseva media_details($image, $auth, $rev, $meta); 1013e136d6ccSKate Arzamastseva } else { 101494add303SAnika Henke echo '<div class="nothing">'.$lang['media_perm_read'].'</div>'.NL; 1015e136d6ccSKate Arzamastseva } 1016d9162c6cSKate Arzamastseva} 1017d9162c6cSKate Arzamastseva 1018d9162c6cSKate Arzamastseva/** 1019d9162c6cSKate Arzamastseva * Prints tab that displays form for editing mediafile metadata 1020d9162c6cSKate Arzamastseva * 1021d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1022e0c26282SGerrit Uitslag * 1023e0c26282SGerrit Uitslag * @param string $image media id 1024e0c26282SGerrit Uitslag * @param string $ns 1025e0c26282SGerrit Uitslag * @param null|int $auth permission level 1026d9162c6cSKate Arzamastseva */ 1027d868eb89SAndreas Gohrfunction media_tab_edit($image, $ns, $auth = null) 1028d868eb89SAndreas Gohr{ 1029d9162c6cSKate Arzamastseva if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 1030d9162c6cSKate Arzamastseva 10311eeeced2SKate Arzamastseva if ($image) { 103224870174SAndreas Gohr [, $mime] = mimetype($image); 103330fd72fbSKate Arzamastseva if ($mime == 'image/jpeg') media_metaform($image, $auth); 10341eeeced2SKate Arzamastseva } 1035d9162c6cSKate Arzamastseva} 1036d9162c6cSKate Arzamastseva 1037d9162c6cSKate Arzamastseva/** 1038d9162c6cSKate Arzamastseva * Prints tab that displays mediafile revisions 1039d9162c6cSKate Arzamastseva * 1040d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1041e0c26282SGerrit Uitslag * 1042e0c26282SGerrit Uitslag * @param string $image media id 1043e0c26282SGerrit Uitslag * @param string $ns 1044e0c26282SGerrit Uitslag * @param null|int $auth permission level 1045d9162c6cSKate Arzamastseva */ 1046d868eb89SAndreas Gohrfunction media_tab_history($image, $ns, $auth = null) 1047d868eb89SAndreas Gohr{ 1048d9162c6cSKate Arzamastseva global $lang; 10498108113cSTom N Harris global $INPUT; 10508108113cSTom N Harris 1051d9162c6cSKate Arzamastseva if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 10528108113cSTom N Harris $do = $INPUT->str('mediado'); 1053d9162c6cSKate Arzamastseva 10542e55802cSKate Arzamastseva if ($auth >= AUTH_READ && $image) { 10552e55802cSKate Arzamastseva if ($do == 'diff') { 105624870174SAndreas Gohr (new MediaDiff($image))->show(); //media_diff($image, $ns, $auth); 10572e55802cSKate Arzamastseva } else { 1058a46cc3dcSAndreas Gohr $first = $INPUT->int('first', -1); 105924870174SAndreas Gohr (new MediaRevisions($image))->show($first); 10602e55802cSKate Arzamastseva } 106188a71175SKate Arzamastseva } else { 106288a71175SKate Arzamastseva echo '<div class="nothing">'.$lang['media_perm_read'].'</div>'.NL; 10632e55802cSKate Arzamastseva } 10643df72098SAndreas Gohr} 10653df72098SAndreas Gohr 10663df72098SAndreas Gohr/** 10671eeeced2SKate Arzamastseva * Prints mediafile details 10681eeeced2SKate Arzamastseva * 10696ffaeda9SGerrit Uitslag * @param string $image media id 1070e0c26282SGerrit Uitslag * @param int $auth permission level 107159bc3b48SGerrit Uitslag * @param int|string $rev revision timestamp or empty string 10726ffaeda9SGerrit Uitslag * @param JpegMeta|bool $meta 107342ea7f44SGerrit Uitslag * 10741eeeced2SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 10751eeeced2SKate Arzamastseva */ 1076d868eb89SAndreas Gohrfunction media_preview($image, $auth, $rev = '', $meta = false) 1077d868eb89SAndreas Gohr{ 1078e136d6ccSKate Arzamastseva 1079e136d6ccSKate Arzamastseva $size = media_image_preview_size($image, $rev, $meta); 1080e136d6ccSKate Arzamastseva 1081e136d6ccSKate Arzamastseva if ($size) { 108259f3611bSAnika Henke global $lang; 108394add303SAnika Henke echo '<div class="image">'; 108494add303SAnika Henke 108524870174SAndreas Gohr $more = []; 1086e136d6ccSKate Arzamastseva if ($rev) { 10875b9353faSKate Arzamastseva $more['rev'] = $rev; 1088e136d6ccSKate Arzamastseva } else { 1089e136d6ccSKate Arzamastseva $t = @filemtime(mediaFN($image)); 10905b9353faSKate Arzamastseva $more['t'] = $t; 109188a71175SKate Arzamastseva } 109223786fd7SKate Arzamastseva 10935b9353faSKate Arzamastseva $more['w'] = $size[0]; 10945b9353faSKate Arzamastseva $more['h'] = $size[1]; 1095e136d6ccSKate Arzamastseva $src = ml($image, $more); 109659f3611bSAnika Henke 109759f3611bSAnika Henke echo '<a href="'.$src.'" target="_blank" title="'.$lang['mediaview'].'">'; 109895b451bcSAdrian Lang echo '<img src="'.$src.'" alt="" style="max-width: '.$size[0].'px;" />'; 109959f3611bSAnika Henke echo '</a>'; 1100e136d6ccSKate Arzamastseva 1101871895a7SSatoshi Sahara echo '</div>'; 110294add303SAnika Henke } 1103e136d6ccSKate Arzamastseva} 1104e136d6ccSKate Arzamastseva 1105e136d6ccSKate Arzamastseva/** 1106e136d6ccSKate Arzamastseva * Prints mediafile action buttons 1107e136d6ccSKate Arzamastseva * 1108e136d6ccSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1109e0c26282SGerrit Uitslag * 1110e0c26282SGerrit Uitslag * @param string $image media id 1111e0c26282SGerrit Uitslag * @param int $auth permission level 1112871895a7SSatoshi Sahara * @param int|string $rev revision timestamp, or empty string 1113e136d6ccSKate Arzamastseva */ 1114d868eb89SAndreas Gohrfunction media_preview_buttons($image, $auth, $rev = '') 1115d868eb89SAndreas Gohr{ 1116e5d185e1SKate Arzamastseva global $lang, $conf; 1117e136d6ccSKate Arzamastseva 1118871895a7SSatoshi Sahara echo '<ul class="actions">'; 11191eeeced2SKate Arzamastseva 112079e79377SAndreas Gohr if ($auth >= AUTH_DELETE && !$rev && file_exists(mediaFN($image))) { 1121e136d6ccSKate Arzamastseva // delete button 1122b960c74fSSatoshi Sahara $form = new Form([ 1123b960c74fSSatoshi Sahara 'id' => 'mediamanager__btn_delete', 1124b960c74fSSatoshi Sahara 'action' => media_managerURL(['delete' => $image], '&'), 1125b960c74fSSatoshi Sahara ]); 1126b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1127b960c74fSSatoshi Sahara $form->addButton('', $lang['btn_delete'])->attr('type', 'submit'); 1128b960c74fSSatoshi Sahara $form->addTagClose('div'); 112995b451bcSAdrian Lang echo '<li>'; 1130b960c74fSSatoshi Sahara echo $form->toHTML(); 1131871895a7SSatoshi Sahara echo '</li>'; 1132e5d185e1SKate Arzamastseva } 1133e5d185e1SKate Arzamastseva 1134e5d185e1SKate Arzamastseva $auth_ow = (($conf['mediarevisions']) ? AUTH_UPLOAD : AUTH_DELETE); 1135e5d185e1SKate Arzamastseva if ($auth >= $auth_ow && !$rev) { 1136e136d6ccSKate Arzamastseva // upload new version button 1137b960c74fSSatoshi Sahara $form = new Form([ 1138b960c74fSSatoshi Sahara 'id' => 'mediamanager__btn_update', 1139b960c74fSSatoshi Sahara 'action' => media_managerURL(['image' => $image, 'mediado' => 'update'], '&'), 1140b960c74fSSatoshi Sahara ]); 1141b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1142b960c74fSSatoshi Sahara $form->addButton('', $lang['media_update'])->attr('type', 'submit'); 1143b960c74fSSatoshi Sahara $form->addTagClose('div'); 114495b451bcSAdrian Lang echo '<li>'; 1145b960c74fSSatoshi Sahara echo $form->toHTML(); 1146871895a7SSatoshi Sahara echo '</li>'; 114770c3cc9aSKate Arzamastseva } 1148e136d6ccSKate Arzamastseva 114979e79377SAndreas Gohr if ($auth >= AUTH_UPLOAD && $rev && $conf['mediarevisions'] && file_exists(mediaFN($image, $rev))) { 1150e136d6ccSKate Arzamastseva // restore button 1151b960c74fSSatoshi Sahara $form = new Form([ 1152b960c74fSSatoshi Sahara 'id' => 'mediamanager__btn_restore', 1153b960c74fSSatoshi Sahara 'action'=>media_managerURL(['image' => $image], '&'), 1154b960c74fSSatoshi Sahara ]); 1155b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1156b960c74fSSatoshi Sahara $form->setHiddenField('mediado', 'restore'); 1157b960c74fSSatoshi Sahara $form->setHiddenField('rev', $rev); 1158b960c74fSSatoshi Sahara $form->addButton('', $lang['media_restore'])->attr('type', 'submit'); 1159b960c74fSSatoshi Sahara $form->addTagClose('div'); 116095b451bcSAdrian Lang echo '<li>'; 1161b960c74fSSatoshi Sahara echo $form->toHTML(); 1162871895a7SSatoshi Sahara echo '</li>'; 11639c1bd4bcSKate Arzamastseva } 1164e136d6ccSKate Arzamastseva 1165871895a7SSatoshi Sahara echo '</ul>'; 11662e55802cSKate Arzamastseva} 11672e55802cSKate Arzamastseva 11682e55802cSKate Arzamastseva/** 1169fa8e5c77SKate Arzamastseva * Returns image width and height for mediamanager preview panel 1170fa8e5c77SKate Arzamastseva * 1171fa8e5c77SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1172fa8e5c77SKate Arzamastseva * @param string $image 1173e0c26282SGerrit Uitslag * @param int|string $rev 117459bc3b48SGerrit Uitslag * @param JpegMeta|bool $meta 1175ebc28e69SAndreas Gohr * @param int $size 1176871895a7SSatoshi Sahara * @return array 1177fa8e5c77SKate Arzamastseva */ 1178d868eb89SAndreas Gohrfunction media_image_preview_size($image, $rev, $meta = false, $size = 500) 1179d868eb89SAndreas Gohr{ 1180871895a7SSatoshi Sahara if (!preg_match("/\.(jpe?g|gif|png)$/", $image) 1181871895a7SSatoshi Sahara || !file_exists($filename = mediaFN($image, $rev)) 118224870174SAndreas Gohr ) return []; 1183fa8e5c77SKate Arzamastseva 1184871895a7SSatoshi Sahara $info = getimagesize($filename); 118524870174SAndreas Gohr $w = $info[0]; 118624870174SAndreas Gohr $h = $info[1]; 1187fa8e5c77SKate Arzamastseva 1188fa8e5c77SKate Arzamastseva if ($meta && ($w > $size || $h > $size)) { 1189fa8e5c77SKate Arzamastseva $ratio = $meta->getResizeRatio($size, $size); 1190fa8e5c77SKate Arzamastseva $w = floor($w * $ratio); 1191fa8e5c77SKate Arzamastseva $h = floor($h * $ratio); 1192fa8e5c77SKate Arzamastseva } 119324870174SAndreas Gohr return [$w, $h]; 1194fa8e5c77SKate Arzamastseva} 1195fa8e5c77SKate Arzamastseva 1196fa8e5c77SKate Arzamastseva/** 1197fa8e5c77SKate Arzamastseva * Returns the requested EXIF/IPTC tag from the image meta 1198fa8e5c77SKate Arzamastseva * 1199fa8e5c77SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1200e0c26282SGerrit Uitslag * 120142ea7f44SGerrit Uitslag * @param array $tags array with tags, first existing is returned 1202fa8e5c77SKate Arzamastseva * @param JpegMeta $meta 120342ea7f44SGerrit Uitslag * @param string $alt alternative value 1204fa8e5c77SKate Arzamastseva * @return string 1205fa8e5c77SKate Arzamastseva */ 1206d868eb89SAndreas Gohrfunction media_getTag($tags, $meta = false, $alt = '') 1207d868eb89SAndreas Gohr{ 1208871895a7SSatoshi Sahara if (!$meta) return $alt; 1209fa8e5c77SKate Arzamastseva $info = $meta->getField($tags); 1210871895a7SSatoshi Sahara if (!$info) return $alt; 1211fa8e5c77SKate Arzamastseva return $info; 1212fa8e5c77SKate Arzamastseva} 1213fa8e5c77SKate Arzamastseva 1214fa8e5c77SKate Arzamastseva/** 1215e136d6ccSKate Arzamastseva * Returns mediafile tags 12162e55802cSKate Arzamastseva * 12172e55802cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1218e0c26282SGerrit Uitslag * 1219e136d6ccSKate Arzamastseva * @param JpegMeta $meta 122042ea7f44SGerrit Uitslag * @return array list of tags of the mediafile 12212e55802cSKate Arzamastseva */ 1222d868eb89SAndreas Gohrfunction media_file_tags($meta) 1223d868eb89SAndreas Gohr{ 1224532850edSKate Arzamastseva // load the field descriptions 12253e98e685SKate Arzamastseva static $fields = null; 12263e98e685SKate Arzamastseva if (is_null($fields)) { 12273e98e685SKate Arzamastseva $config_files = getConfigFiles('mediameta'); 12283e98e685SKate Arzamastseva foreach ($config_files as $config_file) { 122979e79377SAndreas Gohr if (file_exists($config_file)) include($config_file); 1230532850edSKate Arzamastseva } 1231532850edSKate Arzamastseva } 12321eeeced2SKate Arzamastseva 123324870174SAndreas Gohr $tags = []; 1234dd9ba38eSKate Arzamastseva 123524870174SAndreas Gohr foreach ($fields as $tag) { 123624870174SAndreas Gohr $t = []; 123724870174SAndreas Gohr if (!empty($tag[0])) $t = [$tag[0]]; 12380e80bb5eSChristopher Smith if (isset($tag[3]) && is_array($tag[3])) $t = array_merge($t, $tag[3]); 1239e136d6ccSKate Arzamastseva $value = media_getTag($t, $meta); 124024870174SAndreas Gohr $tags[] = ['tag' => $tag, 'value' => $value]; 1241e136d6ccSKate Arzamastseva } 1242e136d6ccSKate Arzamastseva 1243e136d6ccSKate Arzamastseva return $tags; 1244e136d6ccSKate Arzamastseva} 1245e136d6ccSKate Arzamastseva 1246e136d6ccSKate Arzamastseva/** 1247e136d6ccSKate Arzamastseva * Prints mediafile tags 1248e136d6ccSKate Arzamastseva * 1249e136d6ccSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 125042ea7f44SGerrit Uitslag * 1251e0c26282SGerrit Uitslag * @param string $image image id 1252e0c26282SGerrit Uitslag * @param int $auth permission level 1253e0c26282SGerrit Uitslag * @param string|int $rev revision timestamp, or empty string 1254e0c26282SGerrit Uitslag * @param bool|JpegMeta $meta image object, or create one if false 1255e0c26282SGerrit Uitslag */ 1256d868eb89SAndreas Gohrfunction media_details($image, $auth, $rev = '', $meta = false) 1257d868eb89SAndreas Gohr{ 1258e136d6ccSKate Arzamastseva global $lang; 1259e136d6ccSKate Arzamastseva 1260e136d6ccSKate Arzamastseva if (!$meta) $meta = new JpegMeta(mediaFN($image, $rev)); 1261e136d6ccSKate Arzamastseva $tags = media_file_tags($meta); 1262e136d6ccSKate Arzamastseva 126394add303SAnika Henke echo '<dl>'.NL; 1264e136d6ccSKate Arzamastseva foreach ($tags as $tag) { 1265e136d6ccSKate Arzamastseva if ($tag['value']) { 1266e136d6ccSKate Arzamastseva $value = cleanText($tag['value']); 1267fde860beSGerrit Uitslag echo '<dt>'.$lang[$tag['tag'][1]].'</dt><dd>'; 1268e136d6ccSKate Arzamastseva if ($tag['tag'][2] == 'date') echo dformat($value); 12693e98e685SKate Arzamastseva else echo hsc($value); 127094add303SAnika Henke echo '</dd>'.NL; 12711eeeced2SKate Arzamastseva } 1272e136d6ccSKate Arzamastseva } 127394add303SAnika Henke echo '</dl>'.NL; 127422e68399Sflammy echo '<dl>'.NL; 127522e68399Sflammy echo '<dt>'.$lang['reference'].':</dt>'; 127622e68399Sflammy $media_usage = ft_mediause($image, true); 127724870174SAndreas Gohr if ($media_usage !== []) { 127822e68399Sflammy foreach ($media_usage as $path) { 127922e68399Sflammy echo '<dd>'.html_wikilink($path).'</dd>'; 128022e68399Sflammy } 128122e68399Sflammy } else { 128222e68399Sflammy echo '<dd>'.$lang['nothingfound'].'</dd>'; 128322e68399Sflammy } 128422e68399Sflammy echo '</dl>'.NL; 128522e68399Sflammy 12861eeeced2SKate Arzamastseva} 12872e55802cSKate Arzamastseva 12882e55802cSKate Arzamastseva/** 12892e55802cSKate Arzamastseva * Shows difference between two revisions of file 12902e55802cSKate Arzamastseva * 12912e55802cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 129242ea7f44SGerrit Uitslag * 1293e0c26282SGerrit Uitslag * @param string $image image id 1294e0c26282SGerrit Uitslag * @param string $ns 1295e0c26282SGerrit Uitslag * @param int $auth permission level 1296e0c26282SGerrit Uitslag * @param bool $fromajax 129779a2d784SGerrit Uitslag * 1298297071beSSatoshi Sahara * @deprecated 2020-12-31 1299e0c26282SGerrit Uitslag */ 1300d868eb89SAndreas Gohrfunction media_diff($image, $ns, $auth, $fromajax = false) 1301d868eb89SAndreas Gohr{ 130279a2d784SGerrit Uitslag dbg_deprecated('see '. MediaDiff::class .'::show()'); 130359e81a43SKate Arzamastseva} 130459e81a43SKate Arzamastseva 13056ffaeda9SGerrit Uitslag/** 13066ffaeda9SGerrit Uitslag * Callback for media file diff 13076ffaeda9SGerrit Uitslag * 130842ea7f44SGerrit Uitslag * @param array $data event data 130979a2d784SGerrit Uitslag * 1310297071beSSatoshi Sahara * @deprecated 2020-12-31 13116ffaeda9SGerrit Uitslag */ 1312d868eb89SAndreas Gohrfunction _media_file_diff($data) 1313d868eb89SAndreas Gohr{ 131479a2d784SGerrit Uitslag dbg_deprecated('see '. MediaDiff::class .'::show()'); 131559e81a43SKate Arzamastseva} 131659e81a43SKate Arzamastseva 131759e81a43SKate Arzamastseva/** 131859e81a43SKate Arzamastseva * Shows difference between two revisions of image 131959e81a43SKate Arzamastseva * 132059e81a43SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1321e0c26282SGerrit Uitslag * 1322e0c26282SGerrit Uitslag * @param string $image 1323e0c26282SGerrit Uitslag * @param string|int $l_rev revision timestamp, or empty string 1324e0c26282SGerrit Uitslag * @param string|int $r_rev revision timestamp, or empty string 1325e0c26282SGerrit Uitslag * @param string $ns 1326e0c26282SGerrit Uitslag * @param int $auth permission level 1327e0c26282SGerrit Uitslag * @param bool $fromajax 1328297071beSSatoshi Sahara * @deprecated 2020-12-31 132959e81a43SKate Arzamastseva */ 1330d868eb89SAndreas Gohrfunction media_file_diff($image, $l_rev, $r_rev, $ns, $auth, $fromajax) 1331d868eb89SAndreas Gohr{ 133279a2d784SGerrit Uitslag dbg_deprecated('see '. MediaDiff::class .'::showFileDiff()'); 1333e136d6ccSKate Arzamastseva} 1334e136d6ccSKate Arzamastseva 1335e136d6ccSKate Arzamastseva/** 1336e136d6ccSKate Arzamastseva * Prints two images side by side 1337fa8e5c77SKate Arzamastseva * and slider 1338e136d6ccSKate Arzamastseva * 1339e136d6ccSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 134042ea7f44SGerrit Uitslag * 134142ea7f44SGerrit Uitslag * @param string $image image id 1342e0c26282SGerrit Uitslag * @param int $l_rev revision timestamp, or empty string 1343e0c26282SGerrit Uitslag * @param int $r_rev revision timestamp, or empty string 134442ea7f44SGerrit Uitslag * @param array $l_size array with width and height 134542ea7f44SGerrit Uitslag * @param array $r_size array with width and height 134650fc55feSKate Arzamastseva * @param string $type 1347297071beSSatoshi Sahara * @deprecated 2020-12-31 1348e136d6ccSKate Arzamastseva */ 1349d868eb89SAndreas Gohrfunction media_image_diff($image, $l_rev, $r_rev, $l_size, $r_size, $type) 1350d868eb89SAndreas Gohr{ 135179a2d784SGerrit Uitslag dbg_deprecated('see '. MediaDiff::class .'::showImageDiff()'); 13521eeeced2SKate Arzamastseva} 13531eeeced2SKate Arzamastseva 13541eeeced2SKate Arzamastseva/** 13559c1bd4bcSKate Arzamastseva * Restores an old revision of a media file 13569c1bd4bcSKate Arzamastseva * 135742ea7f44SGerrit Uitslag * @param string $image media id 135842ea7f44SGerrit Uitslag * @param int $rev revision timestamp or empty string 13599c1bd4bcSKate Arzamastseva * @param int $auth 13609c1bd4bcSKate Arzamastseva * @return string - file's id 136142ea7f44SGerrit Uitslag * 13629c1bd4bcSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 13639c1bd4bcSKate Arzamastseva */ 1364d868eb89SAndreas Gohrfunction media_restore($image, $rev, $auth) 1365d868eb89SAndreas Gohr{ 1366e5d185e1SKate Arzamastseva global $conf; 136780525638SKate Arzamastseva if ($auth < AUTH_UPLOAD || !$conf['mediarevisions']) return false; 136892cac9a9SKate Arzamastseva $removed = (!file_exists(mediaFN($image)) && file_exists(mediaMetaFN($image, '.changes'))); 136992cac9a9SKate Arzamastseva if (!$image || (!file_exists(mediaFN($image)) && !$removed)) return false; 13709c1bd4bcSKate Arzamastseva if (!$rev || !file_exists(mediaFN($image, $rev))) return false; 137124870174SAndreas Gohr [, $imime, ] = mimetype($image); 1372dccd6b2bSAndreas Gohr $res = media_upload_finish( 1373dccd6b2bSAndreas Gohr mediaFN($image, $rev), 13749c1bd4bcSKate Arzamastseva mediaFN($image), 13759c1bd4bcSKate Arzamastseva $image, 13769c1bd4bcSKate Arzamastseva $imime, 13779c1bd4bcSKate Arzamastseva true, 1378dccd6b2bSAndreas Gohr 'copy' 1379dccd6b2bSAndreas Gohr ); 13809c1bd4bcSKate Arzamastseva if (is_array($res)) { 13819c1bd4bcSKate Arzamastseva msg($res[0], $res[1]); 13829c1bd4bcSKate Arzamastseva return false; 13839c1bd4bcSKate Arzamastseva } 13849c1bd4bcSKate Arzamastseva return $res; 13859c1bd4bcSKate Arzamastseva} 13869c1bd4bcSKate Arzamastseva 13879c1bd4bcSKate Arzamastseva/** 1388bf1f3ac4Ssarnowski * List all files found by the search request 1389c9f56829SAndreas Gohr * 1390c9f56829SAndreas Gohr * @author Tobias Sarnowski <sarnowski@cosmocode.de> 1391c9f56829SAndreas Gohr * @author Andreas Gohr <gohr@cosmocode.de> 1392d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1393c9f56829SAndreas Gohr * @triggers MEDIA_SEARCH 1394e0c26282SGerrit Uitslag * 1395e0c26282SGerrit Uitslag * @param string $query 1396e0c26282SGerrit Uitslag * @param string $ns 1397e0c26282SGerrit Uitslag * @param null|int $auth 1398e0c26282SGerrit Uitslag * @param bool $fullscreen 1399e0c26282SGerrit Uitslag * @param string $sort 1400bf1f3ac4Ssarnowski */ 1401d868eb89SAndreas Gohrfunction media_searchlist($query, $ns, $auth = null, $fullscreen = false, $sort = 'natural') 1402d868eb89SAndreas Gohr{ 1403bf1f3ac4Ssarnowski global $conf; 1404bf1f3ac4Ssarnowski global $lang; 14058e69fd30SKate Arzamastseva 1406bf1f3ac4Ssarnowski $ns = cleanID($ns); 140724870174SAndreas Gohr $evdata = [ 140856fe6664SAndreas Gohr 'ns' => $ns, 140924870174SAndreas Gohr 'data' => [], 141056fe6664SAndreas Gohr 'query' => $query 141124870174SAndreas Gohr ]; 14127ed31746SSzymon Olewniczak if (!blank($query)) { 1413e1d9dcc8SAndreas Gohr $evt = new Event('MEDIA_SEARCH', $evdata); 1414bf1f3ac4Ssarnowski if ($evt->advise_before()) { 141556fe6664SAndreas Gohr $dir = utf8_encodeFN(str_replace(':', '/', $evdata['ns'])); 141676472096SSzymon Olewniczak $quoted = preg_quote($evdata['query'], '/'); 141776472096SSzymon Olewniczak //apply globbing 141824870174SAndreas Gohr $quoted = str_replace(['\*', '\?'], ['.*', '.'], $quoted, $count); 141923e31e76SSzymon Olewniczak 142023e31e76SSzymon Olewniczak //if we use globbing file name must match entirely but may be preceded by arbitrary namespace 142123e31e76SSzymon Olewniczak if ($count > 0) $quoted = '^([^:]*:)*'.$quoted.'$'; 142223e31e76SSzymon Olewniczak 142376472096SSzymon Olewniczak $pattern = '/'.$quoted.'/i'; 1424dccd6b2bSAndreas Gohr search( 1425dccd6b2bSAndreas Gohr $evdata['data'], 142656fe6664SAndreas Gohr $conf['mediadir'], 14274f33babfSAndreas Gohr 'search_mediafiles', 142824870174SAndreas Gohr ['showmsg'=>false, 'pattern'=>$pattern], 142900e3e394SChristopher Smith $dir, 143000e3e394SChristopher Smith 1, 1431dccd6b2bSAndreas Gohr $sort 1432dccd6b2bSAndreas Gohr ); 1433bf1f3ac4Ssarnowski } 1434bf1f3ac4Ssarnowski $evt->advise_after(); 1435bf1f3ac4Ssarnowski unset($evt); 143656fe6664SAndreas Gohr } 1437bf1f3ac4Ssarnowski 1438d9162c6cSKate Arzamastseva if (!$fullscreen) { 143956fe6664SAndreas Gohr echo '<h1 id="media__ns">'.sprintf($lang['searchmedia_in'], hsc($ns).':*').'</h1>'.NL; 144056fe6664SAndreas Gohr media_searchform($ns, $query); 1441d9162c6cSKate Arzamastseva } 144256fe6664SAndreas Gohr 144356fe6664SAndreas Gohr if (!count($evdata['data'])) { 1444bf1f3ac4Ssarnowski echo '<div class="nothing">'.$lang['nothingfound'].'</div>'.NL; 14455b9353faSKate Arzamastseva } else { 14465b9353faSKate Arzamastseva if ($fullscreen) { 1447554a8c9fSAdrian Lang echo '<ul class="' . _media_get_list_type() . '">'; 14485b9353faSKate Arzamastseva } 14495b9353faSKate Arzamastseva foreach ($evdata['data'] as $item) { 14504f33babfSAndreas Gohr if (!$fullscreen) { 14514f33babfSAndreas Gohr // FIXME old call: media_printfile($item,$item['perm'],'',true); 145279a2d784SGerrit Uitslag $display = new DisplayRow($item); 145379b00823SAndreas Gohr $display->relativeDisplay($ns); 14544f33babfSAndreas Gohr $display->show(); 14554f33babfSAndreas Gohr } else { 14564f33babfSAndreas Gohr // FIXME old call: media_printfile_thumbs($item,$item['perm'],false,true); 145779a2d784SGerrit Uitslag $display = new DisplayTile($item); 145879b00823SAndreas Gohr $display->relativeDisplay($ns); 14594f33babfSAndreas Gohr echo '<li>'; 14604f33babfSAndreas Gohr $display->show(); 14614f33babfSAndreas Gohr echo '</li>'; 14624f33babfSAndreas Gohr } 1463bf1f3ac4Ssarnowski } 146494add303SAnika Henke if ($fullscreen) echo '</ul>'.NL; 14655b9353faSKate Arzamastseva } 1466bf1f3ac4Ssarnowski} 1467bf1f3ac4Ssarnowski 1468bf1f3ac4Ssarnowski/** 1469c6571d58SAndreas Gohr * Display a media icon 1470c6571d58SAndreas Gohr * 147142ea7f44SGerrit Uitslag * @param string $filename media id 1472c6571d58SAndreas Gohr * @param string $size the size subfolder, if not specified 16x16 is used 147342ea7f44SGerrit Uitslag * @return string html 1474c6571d58SAndreas Gohr */ 1475d868eb89SAndreas Gohrfunction media_printicon($filename, $size = '') 1476d868eb89SAndreas Gohr{ 147724870174SAndreas Gohr [$ext] = mimetype(mediaFN($filename), false); 147823786fd7SKate Arzamastseva 147979e79377SAndreas Gohr if (file_exists(DOKU_INC.'lib/images/fileicons/'.$size.'/'.$ext.'.png')) { 1480c6571d58SAndreas Gohr $icon = DOKU_BASE.'lib/images/fileicons/'.$size.'/'.$ext.'.png'; 148123786fd7SKate Arzamastseva } else { 1482c6571d58SAndreas Gohr $icon = DOKU_BASE.'lib/images/fileicons/'.$size.'/file.png'; 148323786fd7SKate Arzamastseva } 148423786fd7SKate Arzamastseva 1485421ec38eSKate Arzamastseva return '<img src="'.$icon.'" alt="'.$filename.'" class="icon" />'; 148623786fd7SKate Arzamastseva} 148723786fd7SKate Arzamastseva 14883df72098SAndreas Gohr/** 148942ea7f44SGerrit Uitslag * Build link based on the current, adding/rewriting parameters 1490d9162c6cSKate Arzamastseva * 1491d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 149242ea7f44SGerrit Uitslag * 1493ebc28e69SAndreas Gohr * @param array|bool $params 149442ea7f44SGerrit Uitslag * @param string $amp separator 149542ea7f44SGerrit Uitslag * @param bool $abs absolute url? 149642ea7f44SGerrit Uitslag * @param bool $params_array return the parmeters array? 149742ea7f44SGerrit Uitslag * @return string|array - link or link parameters 1498d9162c6cSKate Arzamastseva */ 1499d868eb89SAndreas Gohrfunction media_managerURL($params = false, $amp = '&', $abs = false, $params_array = false) 1500d868eb89SAndreas Gohr{ 1501d9162c6cSKate Arzamastseva global $ID; 15028108113cSTom N Harris global $INPUT; 1503d9162c6cSKate Arzamastseva 150424870174SAndreas Gohr $gets = ['do' => 'media']; 150524870174SAndreas Gohr $media_manager_params = ['tab_files', 'tab_details', 'image', 'ns', 'list', 'sort']; 150623846a98SKate Arzamastseva foreach ($media_manager_params as $x) { 15078108113cSTom N Harris if ($INPUT->has($x)) $gets[$x] = $INPUT->str($x); 150823846a98SKate Arzamastseva } 1509d9162c6cSKate Arzamastseva 1510d9162c6cSKate Arzamastseva if ($params) { 1511554a8c9fSAdrian Lang $gets = $params + $gets; 1512d9162c6cSKate Arzamastseva } 1513d9162c6cSKate Arzamastseva unset($gets['id']); 1514554a8c9fSAdrian Lang if (isset($gets['delete'])) { 15151eeeced2SKate Arzamastseva unset($gets['image']); 15161eeeced2SKate Arzamastseva unset($gets['tab_details']); 15171eeeced2SKate Arzamastseva } 1518d9162c6cSKate Arzamastseva 1519035e07f1SKate Arzamastseva if ($params_array) return $gets; 1520035e07f1SKate Arzamastseva 15216dd095f5SKate Arzamastseva return wl($ID, $gets, $abs, $amp); 1522d9162c6cSKate Arzamastseva} 1523d9162c6cSKate Arzamastseva 1524d9162c6cSKate Arzamastseva/** 15253df72098SAndreas Gohr * Print the media upload form if permissions are correct 15263df72098SAndreas Gohr * 15273df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 1528d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1529e0c26282SGerrit Uitslag * 1530e0c26282SGerrit Uitslag * @param string $ns 1531e0c26282SGerrit Uitslag * @param int $auth permission level 1532e0c26282SGerrit Uitslag * @param bool $fullscreen 15333df72098SAndreas Gohr */ 1534d868eb89SAndreas Gohrfunction media_uploadform($ns, $auth, $fullscreen = false) 1535d868eb89SAndreas Gohr{ 15368108113cSTom N Harris global $lang; 15378108113cSTom N Harris global $conf; 15388108113cSTom N Harris global $INPUT; 15393df72098SAndreas Gohr 154088a71175SKate Arzamastseva if ($auth < AUTH_UPLOAD) { 154188a71175SKate Arzamastseva echo '<div class="nothing">'.$lang['media_perm_upload'].'</div>'.NL; 154288a71175SKate Arzamastseva return; 154388a71175SKate Arzamastseva } 154492cac9a9SKate Arzamastseva $auth_ow = (($conf['mediarevisions']) ? AUTH_UPLOAD : AUTH_DELETE); 15453df72098SAndreas Gohr 154670c3cc9aSKate Arzamastseva $update = false; 154770c3cc9aSKate Arzamastseva $id = ''; 15488108113cSTom N Harris if ($auth >= $auth_ow && $fullscreen && $INPUT->str('mediado') == 'update') { 154970c3cc9aSKate Arzamastseva $update = true; 15508108113cSTom N Harris $id = cleanID($INPUT->str('image')); 155170c3cc9aSKate Arzamastseva } 155270c3cc9aSKate Arzamastseva 1553d00ec455SAndreas Gohr // The default HTML upload form 1554b960c74fSSatoshi Sahara $form = new Form([ 1555b960c74fSSatoshi Sahara 'id' => 'dw__upload', 1556b960c74fSSatoshi Sahara 'enctype' => 'multipart/form-data', 1557b960c74fSSatoshi Sahara 'action' => ($fullscreen) 1558b960c74fSSatoshi Sahara ? media_managerURL(['tab_files' => 'files', 'tab_details' => 'view'], '&') 1559b960c74fSSatoshi Sahara : DOKU_BASE.'lib/exe/mediamanager.php', 1560b960c74fSSatoshi Sahara ]); 1561b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1562b960c74fSSatoshi Sahara $form->setHiddenField('ns', hsc($ns)); // FIXME hsc required? 1563b960c74fSSatoshi Sahara $form->addTagOpen('p'); 1564b960c74fSSatoshi Sahara $form->addTextInput('upload', $lang['txt_upload'])->id('upload__file') 1565b960c74fSSatoshi Sahara ->attrs(['type' => 'file']); 1566b960c74fSSatoshi Sahara $form->addTagClose('p'); 1567b960c74fSSatoshi Sahara $form->addTagOpen('p'); 1568b960c74fSSatoshi Sahara $form->addTextInput('mediaid', $lang['txt_filename'])->id('upload__name') 1569b960c74fSSatoshi Sahara ->val(noNS($id)); 1570b960c74fSSatoshi Sahara $form->addButton('', $lang['btn_upload'])->attr('type', 'submit'); 1571b960c74fSSatoshi Sahara $form->addTagClose('p'); 157292cac9a9SKate Arzamastseva if ($auth >= $auth_ow) { 1573b960c74fSSatoshi Sahara $form->addTagOpen('p'); 157424870174SAndreas Gohr $attrs = []; 157570c3cc9aSKate Arzamastseva if ($update) $attrs['checked'] = 'checked'; 1576b960c74fSSatoshi Sahara $form->addCheckbox('ow', $lang['txt_overwrt'])->id('dw__ow')->val('1') 1577b960c74fSSatoshi Sahara ->addClass('check')->attrs($attrs); 1578b960c74fSSatoshi Sahara $form->addTagClose('p'); 1579b960c74fSSatoshi Sahara } 1580b960c74fSSatoshi Sahara $form->addTagClose('div'); 1581b960c74fSSatoshi Sahara 1582b960c74fSSatoshi Sahara if (!$fullscreen) { 1583b960c74fSSatoshi Sahara echo '<div class="upload">'. $lang['mediaupload'] .'</div>'.DOKU_LF; 1584b960c74fSSatoshi Sahara } else { 1585b960c74fSSatoshi Sahara echo DOKU_LF; 15863df72098SAndreas Gohr } 1587c472bad9SKate Arzamastseva 1588b960c74fSSatoshi Sahara echo '<div id="mediamanager__uploader">'.DOKU_LF; 1589c6977b3aSSatoshi Sahara echo $form->toHTML('Upload'); 1590b960c74fSSatoshi Sahara echo '</div>'.DOKU_LF; 1591f940e4a0SAndreas Gohr 1592f940e4a0SAndreas Gohr echo '<p class="maxsize">'; 1593f940e4a0SAndreas Gohr printf($lang['maxuploadsize'], filesize_h(media_getuploadsize())); 159456fc6b15SAnna Dabrowska echo ' <a class="allowedmime" href="#">'. $lang['allowedmime'] .'</a>'; 1595499d9bcdSAndreas Gohr echo ' <span>'. implode(', ', array_keys(getMimeTypes())) .'</span>'; 1596b960c74fSSatoshi Sahara echo '</p>'.DOKU_LF; 1597f940e4a0SAndreas Gohr} 1598f940e4a0SAndreas Gohr 1599f940e4a0SAndreas Gohr/** 1600f940e4a0SAndreas Gohr * Returns the size uploaded files may have 1601f940e4a0SAndreas Gohr * 1602f940e4a0SAndreas Gohr * This uses a conservative approach using the lowest number found 1603f940e4a0SAndreas Gohr * in any of the limiting ini settings 1604f940e4a0SAndreas Gohr * 1605f940e4a0SAndreas Gohr * @returns int size in bytes 1606f940e4a0SAndreas Gohr */ 1607d868eb89SAndreas Gohrfunction media_getuploadsize() 1608d868eb89SAndreas Gohr{ 1609f940e4a0SAndreas Gohr $okay = 0; 1610f940e4a0SAndreas Gohr 161124870174SAndreas Gohr $post = php_to_byte(@ini_get('post_max_size')); 161224870174SAndreas Gohr $suho = php_to_byte(@ini_get('suhosin.post.max_value_length')); 161324870174SAndreas Gohr $upld = php_to_byte(@ini_get('upload_max_filesize')); 1614f940e4a0SAndreas Gohr 161524870174SAndreas Gohr if ($post && ($post < $okay || $okay === 0)) $okay = $post; 1616f940e4a0SAndreas Gohr if ($suho && ($suho < $okay || $okay == 0)) $okay = $suho; 1617f940e4a0SAndreas Gohr if ($upld && ($upld < $okay || $okay == 0)) $okay = $upld; 1618f940e4a0SAndreas Gohr 1619f940e4a0SAndreas Gohr return $okay; 16209f5dde7fSMichael Klier} 16213df72098SAndreas Gohr 16223df72098SAndreas Gohr/** 1623bf1f3ac4Ssarnowski * Print the search field form 1624bf1f3ac4Ssarnowski * 1625bf1f3ac4Ssarnowski * @author Tobias Sarnowski <sarnowski@cosmocode.de> 1626d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1627e0c26282SGerrit Uitslag * 1628e0c26282SGerrit Uitslag * @param string $ns 1629e0c26282SGerrit Uitslag * @param string $query 1630e0c26282SGerrit Uitslag * @param bool $fullscreen 1631bf1f3ac4Ssarnowski */ 1632d868eb89SAndreas Gohrfunction media_searchform($ns, $query = '', $fullscreen = false) 1633d868eb89SAndreas Gohr{ 1634bf1f3ac4Ssarnowski global $lang; 1635bf1f3ac4Ssarnowski 1636bf1f3ac4Ssarnowski // The default HTML search form 1637b960c74fSSatoshi Sahara $form = new Form([ 1638b960c74fSSatoshi Sahara 'id' => 'dw__mediasearch', 1639b960c74fSSatoshi Sahara 'action' => ($fullscreen) 1640b960c74fSSatoshi Sahara ? media_managerURL([], '&') 1641b960c74fSSatoshi Sahara : DOKU_BASE.'lib/exe/mediamanager.php', 1642b960c74fSSatoshi Sahara ]); 1643b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1644b960c74fSSatoshi Sahara $form->setHiddenField('ns', $ns); 1645b960c74fSSatoshi Sahara $form->setHiddenField($fullscreen ? 'mediado' : 'do', 'searchlist'); 1646554a8c9fSAdrian Lang 1647b960c74fSSatoshi Sahara $form->addTagOpen('p'); 1648bde2a644SSatoshi Sahara $form->addTextInput('q', $lang['searchmedia']) 1649b960c74fSSatoshi Sahara ->attr('title', sprintf($lang['searchmedia_in'], hsc($ns) .':*')) 1650b960c74fSSatoshi Sahara ->val($query); 1651bde2a644SSatoshi Sahara $form->addHTML(' '); 1652b960c74fSSatoshi Sahara $form->addButton('', $lang['btn_search'])->attr('type', 'submit'); 1653b960c74fSSatoshi Sahara $form->addTagClose('p'); 1654b960c74fSSatoshi Sahara $form->addTagClose('div'); 1655c6977b3aSSatoshi Sahara print $form->toHTML('SearchMedia'); 1656bf1f3ac4Ssarnowski} 1657bf1f3ac4Ssarnowski 1658bf1f3ac4Ssarnowski/** 16593df72098SAndreas Gohr * Build a tree outline of available media namespaces 16603df72098SAndreas Gohr * 16613df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 1662e0c26282SGerrit Uitslag * 1663e0c26282SGerrit Uitslag * @param string $ns 16643df72098SAndreas Gohr */ 1665d868eb89SAndreas Gohrfunction media_nstree($ns) 1666d868eb89SAndreas Gohr{ 16673df72098SAndreas Gohr global $conf; 1668256ca81eSAndreas Gohr global $lang; 16693df72098SAndreas Gohr 16703df72098SAndreas Gohr // currently selected namespace 16713df72098SAndreas Gohr $ns = cleanID($ns); 16723df72098SAndreas Gohr if (empty($ns)) { 1673de3eb1d7SAdrian Lang global $ID; 1674dd90013aSMichael Hamann $ns = (string)getNS($ID); 16753df72098SAndreas Gohr } 1676dd90013aSMichael Hamann 1677dd90013aSMichael Hamann $ns_dir = utf8_encodeFN(str_replace(':', '/', $ns)); 16783df72098SAndreas Gohr 167924870174SAndreas Gohr $data = []; 168024870174SAndreas Gohr search($data, $conf['mediadir'], 'search_index', ['ns' => $ns_dir, 'nofiles' => true]); 16813df72098SAndreas Gohr 16823df72098SAndreas Gohr // wrap a list with the root level around the other namespaces 168324870174SAndreas Gohr array_unshift($data, ['level' => 0, 'id' => '', 'open' =>'true', 'label' => '['.$lang['mediaroot'].']']); 16843df72098SAndreas Gohr 1685dd90013aSMichael Hamann // insert the current ns into the hierarchy if it isn't already part of it 1686dd90013aSMichael Hamann $ns_parts = explode(':', $ns); 1687dd90013aSMichael Hamann $tmp_ns = ''; 1688dd90013aSMichael Hamann $pos = 0; 1689dd90013aSMichael Hamann foreach ($ns_parts as $level => $part) { 1690dd90013aSMichael Hamann if ($tmp_ns) $tmp_ns .= ':'.$part; 1691dd90013aSMichael Hamann else $tmp_ns = $part; 1692dd90013aSMichael Hamann 1693dd90013aSMichael Hamann // find the namespace parts or insert them 1694dd90013aSMichael Hamann while ($data[$pos]['id'] != $tmp_ns) { 169564159a61SAndreas Gohr if ( 169664159a61SAndreas Gohr $pos >= count($data) || 16972d85e841SAndreas Gohr ($data[$pos]['level'] <= $level+1 && Sort::strcmp($data[$pos]['id'], $tmp_ns) > 0) 169864159a61SAndreas Gohr ) { 169924870174SAndreas Gohr array_splice($data, $pos, 0, [['level' => $level+1, 'id' => $tmp_ns, 'open' => 'true']]); 1700dd90013aSMichael Hamann break; 1701dd90013aSMichael Hamann } 1702dd90013aSMichael Hamann ++$pos; 1703dd90013aSMichael Hamann } 1704dd90013aSMichael Hamann } 1705dd90013aSMichael Hamann 17063df72098SAndreas Gohr echo html_buildlist($data, 'idx', 'media_nstree_item', 'media_nstree_li'); 17073df72098SAndreas Gohr} 17083df72098SAndreas Gohr 17093df72098SAndreas Gohr/** 17103df72098SAndreas Gohr * Userfunction for html_buildlist 17113df72098SAndreas Gohr * 17123df72098SAndreas Gohr * Prints a media namespace tree item 17133df72098SAndreas Gohr * 17143df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 171542ea7f44SGerrit Uitslag * 171642ea7f44SGerrit Uitslag * @param array $item 171742ea7f44SGerrit Uitslag * @return string html 17183df72098SAndreas Gohr */ 1719d868eb89SAndreas Gohrfunction media_nstree_item($item) 1720d868eb89SAndreas Gohr{ 17218108113cSTom N Harris global $INPUT; 17223df72098SAndreas Gohr $pos = strrpos($item['id'], ':'); 17233df72098SAndreas Gohr $label = substr($item['id'], $pos > 0 ? $pos + 1 : 0); 17240e80bb5eSChristopher Smith if (empty($item['label'])) $item['label'] = $label; 17253df72098SAndreas Gohr 17263df72098SAndreas Gohr $ret = ''; 172724870174SAndreas Gohr if ($INPUT->str('do') != 'media') 17283df72098SAndreas Gohr $ret .= '<a href="'.DOKU_BASE.'lib/exe/mediamanager.php?ns='.idfilter($item['id']).'" class="idx_dir">'; 1729b960c74fSSatoshi Sahara else $ret .= '<a href="'.media_managerURL(['ns' => idfilter($item['id'], false), 'tab_files' => 'files']) 173023846a98SKate Arzamastseva .'" class="idx_dir">'; 17313df72098SAndreas Gohr $ret .= $item['label']; 17323df72098SAndreas Gohr $ret .= '</a>'; 17333df72098SAndreas Gohr return $ret; 17343df72098SAndreas Gohr} 17353df72098SAndreas Gohr 17363df72098SAndreas Gohr/** 17373df72098SAndreas Gohr * Userfunction for html_buildlist 17383df72098SAndreas Gohr * 17393df72098SAndreas Gohr * Prints a media namespace tree item opener 17403df72098SAndreas Gohr * 17413df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 174242ea7f44SGerrit Uitslag * 174342ea7f44SGerrit Uitslag * @param array $item 174442ea7f44SGerrit Uitslag * @return string html 17453df72098SAndreas Gohr */ 1746d868eb89SAndreas Gohrfunction media_nstree_li($item) 1747d868eb89SAndreas Gohr{ 17483df72098SAndreas Gohr $class='media level'.$item['level']; 17493df72098SAndreas Gohr if ($item['open']) { 17503df72098SAndreas Gohr $class .= ' open'; 17513df72098SAndreas Gohr $img = DOKU_BASE.'lib/images/minus.gif'; 1752e260f93bSAnika Henke $alt = '−'; 17533df72098SAndreas Gohr } else { 17543df72098SAndreas Gohr $class .= ' closed'; 17553df72098SAndreas Gohr $img = DOKU_BASE.'lib/images/plus.gif'; 17567af1b404SAnika Henke $alt = '+'; 17573df72098SAndreas Gohr } 1758231b8c34SPierre Spring // TODO: only deliver an image if it actually has a subtree... 17593df72098SAndreas Gohr return '<li class="'.$class.'">'. 17607af1b404SAnika Henke '<img src="'.$img.'" alt="'.$alt.'" />'; 17613df72098SAndreas Gohr} 176213c08e2fSMichael Klier 176313c08e2fSMichael Klier/** 1764b021f0b4SAndreas Gohr * Resizes or crop the given image to the given size 1765b021f0b4SAndreas Gohr * 1766b021f0b4SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 1767b021f0b4SAndreas Gohr * 1768b021f0b4SAndreas Gohr * @param string $file filename, path to file 1769b021f0b4SAndreas Gohr * @param string $ext extension 1770b021f0b4SAndreas Gohr * @param int $w desired width 1771b021f0b4SAndreas Gohr * @param int $h desired height 1772b021f0b4SAndreas Gohr * @param bool $crop should a center crop be used? 1773b021f0b4SAndreas Gohr * @return string path to resized or original size if failed 1774b021f0b4SAndreas Gohr */ 1775b021f0b4SAndreas Gohrfunction media_mod_image($file, $ext, $w, $h = 0, $crop = false) 1776b021f0b4SAndreas Gohr{ 1777b021f0b4SAndreas Gohr global $conf; 1778d967ecd8SAndreas Gohr if (!$h) $h = 0; 1779b021f0b4SAndreas Gohr // we wont scale up to infinity 1780b021f0b4SAndreas Gohr if ($w > 2000 || $h > 2000) return $file; 1781b021f0b4SAndreas Gohr 1782b021f0b4SAndreas Gohr $operation = $crop ? 'crop' : 'resize'; 1783b021f0b4SAndreas Gohr 1784b021f0b4SAndreas Gohr $options = [ 1785b021f0b4SAndreas Gohr 'quality' => $conf['jpg_quality'], 1786b021f0b4SAndreas Gohr 'imconvert' => $conf['im_convert'], 1787b021f0b4SAndreas Gohr ]; 1788b021f0b4SAndreas Gohr 178924870174SAndreas Gohr $cache = new CacheImageMod($file, $w, $h, $ext, $crop); 1790b021f0b4SAndreas Gohr if (!$cache->useCache()) { 1791b021f0b4SAndreas Gohr try { 1792b021f0b4SAndreas Gohr Slika::run($file, $options) 1793b021f0b4SAndreas Gohr ->autorotate() 1794b021f0b4SAndreas Gohr ->$operation($w, $h) 1795b021f0b4SAndreas Gohr ->save($cache->cache, $ext); 1796b021f0b4SAndreas Gohr if ($conf['fperm']) @chmod($cache->cache, $conf['fperm']); 179724870174SAndreas Gohr } catch (Exception $e) { 1798b021f0b4SAndreas Gohr Logger::debug($e->getMessage()); 1799b021f0b4SAndreas Gohr return $file; 1800b021f0b4SAndreas Gohr } 1801b021f0b4SAndreas Gohr } 1802b021f0b4SAndreas Gohr 1803b021f0b4SAndreas Gohr return $cache->cache; 1804b021f0b4SAndreas Gohr} 1805b021f0b4SAndreas Gohr 1806b021f0b4SAndreas Gohr/** 180713c08e2fSMichael Klier * Resizes the given image to the given size 180813c08e2fSMichael Klier * 180913c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 181042ea7f44SGerrit Uitslag * 181142ea7f44SGerrit Uitslag * @param string $file filename, path to file 181242ea7f44SGerrit Uitslag * @param string $ext extension 181342ea7f44SGerrit Uitslag * @param int $w desired width 181442ea7f44SGerrit Uitslag * @param int $h desired height 181542ea7f44SGerrit Uitslag * @return string path to resized or original size if failed 181613c08e2fSMichael Klier */ 1817b021f0b4SAndreas Gohrfunction media_resize_image($file, $ext, $w, $h = 0) 1818b021f0b4SAndreas Gohr{ 1819b021f0b4SAndreas Gohr return media_mod_image($file, $ext, $w, $h, false); 1820d2bd34a5SAndreas Gohr} 182113c08e2fSMichael Klier 182213c08e2fSMichael Klier/** 1823d2bd34a5SAndreas Gohr * Center crops the given image to the wanted size 182413c08e2fSMichael Klier * 182513c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 182642ea7f44SGerrit Uitslag * 182742ea7f44SGerrit Uitslag * @param string $file filename, path to file 182842ea7f44SGerrit Uitslag * @param string $ext extension 182942ea7f44SGerrit Uitslag * @param int $w desired width 183042ea7f44SGerrit Uitslag * @param int $h desired height 183142ea7f44SGerrit Uitslag * @return string path to resized or original size if failed 183213c08e2fSMichael Klier */ 1833b021f0b4SAndreas Gohrfunction media_crop_image($file, $ext, $w, $h = 0) 1834b021f0b4SAndreas Gohr{ 1835b021f0b4SAndreas Gohr return media_mod_image($file, $ext, $w, $h, true); 183613c08e2fSMichael Klier} 183713c08e2fSMichael Klier 183813c08e2fSMichael Klier/** 18390f4e0092SChristopher Smith * Calculate a token to be used to verify fetch requests for resized or 18400f4e0092SChristopher Smith * cropped images have been internally generated - and prevent external 18410f4e0092SChristopher Smith * DDOS attacks via fetch 18420f4e0092SChristopher Smith * 18433c124064SAndreas Gohr * @author Christopher Smith <chris@jalakai.co.uk> 18443c124064SAndreas Gohr * 18450f4e0092SChristopher Smith * @param string $id id of the image 18460f4e0092SChristopher Smith * @param int $w resize/crop width 18470f4e0092SChristopher Smith * @param int $h resize/crop height 184842ea7f44SGerrit Uitslag * @return string token or empty string if no token required 18490f4e0092SChristopher Smith */ 1850d868eb89SAndreas Gohrfunction media_get_token($id, $w, $h) 1851d868eb89SAndreas Gohr{ 18520f4e0092SChristopher Smith // token is only required for modified images 1853cc036f74SKlap-in if ($w || $h || media_isexternal($id)) { 18543c124064SAndreas Gohr $token = $id; 18550f4e0092SChristopher Smith if ($w) $token .= '.'.$w; 18560f4e0092SChristopher Smith if ($h) $token .= '.'.$h; 18570f4e0092SChristopher Smith 185824870174SAndreas Gohr return substr(PassHash::hmac('md5', $token, auth_cookiesalt()), 0, 6); 18590f4e0092SChristopher Smith } 18600f4e0092SChristopher Smith 18610f4e0092SChristopher Smith return ''; 18620f4e0092SChristopher Smith} 18630f4e0092SChristopher Smith 18640f4e0092SChristopher Smith/** 186513c08e2fSMichael Klier * Download a remote file and return local filename 186613c08e2fSMichael Klier * 186713c08e2fSMichael Klier * returns false if download fails. Uses cached file if available and 186813c08e2fSMichael Klier * wanted 186913c08e2fSMichael Klier * 187013c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 187113c08e2fSMichael Klier * @author Pavel Vitis <Pavel.Vitis@seznam.cz> 187242ea7f44SGerrit Uitslag * 187342ea7f44SGerrit Uitslag * @param string $url 187442ea7f44SGerrit Uitslag * @param string $ext extension 187542ea7f44SGerrit Uitslag * @param int $cache cachetime in seconds 187642ea7f44SGerrit Uitslag * @return false|string path to cached file 187713c08e2fSMichael Klier */ 1878d868eb89SAndreas Gohrfunction media_get_from_URL($url, $ext, $cache) 1879d868eb89SAndreas Gohr{ 188013c08e2fSMichael Klier global $conf; 188113c08e2fSMichael Klier 188213c08e2fSMichael Klier // if no cache or fetchsize just redirect 188313c08e2fSMichael Klier if ($cache==0) return false; 188413c08e2fSMichael Klier if (!$conf['fetchsize']) return false; 188513c08e2fSMichael Klier 188613c08e2fSMichael Klier $local = getCacheName(strtolower($url), ".media.$ext"); 188713c08e2fSMichael Klier $mtime = @filemtime($local); // 0 if not exists 188813c08e2fSMichael Klier 188913c08e2fSMichael Klier //decide if download needed: 189013c08e2fSMichael Klier if (($mtime == 0) || // cache does not exist 189113c08e2fSMichael Klier ($cache != -1 && $mtime < time() - $cache) // 'recache' and cache has expired 189213c08e2fSMichael Klier ) { 189313c08e2fSMichael Klier if (media_image_download($url, $local)) { 189413c08e2fSMichael Klier return $local; 189513c08e2fSMichael Klier } else { 189613c08e2fSMichael Klier return false; 189713c08e2fSMichael Klier } 189813c08e2fSMichael Klier } 189913c08e2fSMichael Klier 190013c08e2fSMichael Klier //if cache exists use it else 190113c08e2fSMichael Klier if ($mtime) return $local; 190213c08e2fSMichael Klier 190313c08e2fSMichael Klier //else return false 190413c08e2fSMichael Klier return false; 190513c08e2fSMichael Klier} 190613c08e2fSMichael Klier 190713c08e2fSMichael Klier/** 190813c08e2fSMichael Klier * Download image files 190913c08e2fSMichael Klier * 191013c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 191142ea7f44SGerrit Uitslag * 191242ea7f44SGerrit Uitslag * @param string $url 191342ea7f44SGerrit Uitslag * @param string $file path to file in which to put the downloaded content 191442ea7f44SGerrit Uitslag * @return bool 191513c08e2fSMichael Klier */ 1916d868eb89SAndreas Gohrfunction media_image_download($url, $file) 1917d868eb89SAndreas Gohr{ 191813c08e2fSMichael Klier global $conf; 191913c08e2fSMichael Klier $http = new DokuHTTPClient(); 1920a5951419SAndreas Gohr $http->keep_alive = false; // we do single ops here, no need for keep-alive 1921a5951419SAndreas Gohr 192213c08e2fSMichael Klier $http->max_bodysize = $conf['fetchsize']; 192313c08e2fSMichael Klier $http->timeout = 25; //max. 25 sec 192413c08e2fSMichael Klier $http->header_regexp = '!\r\nContent-Type: image/(jpe?g|gif|png)!i'; 192513c08e2fSMichael Klier 192613c08e2fSMichael Klier $data = $http->get($url); 192713c08e2fSMichael Klier if (!$data) return false; 192813c08e2fSMichael Klier 192979e79377SAndreas Gohr $fileexists = file_exists($file); 193013c08e2fSMichael Klier $fp = @fopen($file, "w"); 193113c08e2fSMichael Klier if (!$fp) return false; 193213c08e2fSMichael Klier fwrite($fp, $data); 193313c08e2fSMichael Klier fclose($fp); 193424870174SAndreas Gohr if (!$fileexists && $conf['fperm']) chmod($file, $conf['fperm']); 193513c08e2fSMichael Klier 193613c08e2fSMichael Klier // check if it is really an image 193713c08e2fSMichael Klier $info = @getimagesize($file); 193813c08e2fSMichael Klier if (!$info) { 193913c08e2fSMichael Klier @unlink($file); 194013c08e2fSMichael Klier return false; 194113c08e2fSMichael Klier } 194213c08e2fSMichael Klier 194313c08e2fSMichael Klier return true; 194413c08e2fSMichael Klier} 194513c08e2fSMichael Klier 194613c08e2fSMichael Klier/** 194713c08e2fSMichael Klier * resize images using external ImageMagick convert program 194813c08e2fSMichael Klier * 194913c08e2fSMichael Klier * @author Pavel Vitis <Pavel.Vitis@seznam.cz> 195013c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 195142ea7f44SGerrit Uitslag * 195242ea7f44SGerrit Uitslag * @param string $ext extension 195342ea7f44SGerrit Uitslag * @param string $from filename path to file 195442ea7f44SGerrit Uitslag * @param int $from_w original width 195542ea7f44SGerrit Uitslag * @param int $from_h original height 195642ea7f44SGerrit Uitslag * @param string $to path to resized file 195742ea7f44SGerrit Uitslag * @param int $to_w desired width 195842ea7f44SGerrit Uitslag * @param int $to_h desired height 195942ea7f44SGerrit Uitslag * @return bool 196013c08e2fSMichael Klier */ 1961d868eb89SAndreas Gohrfunction media_resize_imageIM($ext, $from, $from_w, $from_h, $to, $to_w, $to_h) 1962d868eb89SAndreas Gohr{ 196313c08e2fSMichael Klier global $conf; 196413c08e2fSMichael Klier 196513c08e2fSMichael Klier // check if convert is configured 196613c08e2fSMichael Klier if (!$conf['im_convert']) return false; 196713c08e2fSMichael Klier 196813c08e2fSMichael Klier // prepare command 196913c08e2fSMichael Klier $cmd = $conf['im_convert']; 197013c08e2fSMichael Klier $cmd .= ' -resize '.$to_w.'x'.$to_h.'!'; 197113c08e2fSMichael Klier if ($ext == 'jpg' || $ext == 'jpeg') { 197213c08e2fSMichael Klier $cmd .= ' -quality '.$conf['jpg_quality']; 197313c08e2fSMichael Klier } 197413c08e2fSMichael Klier $cmd .= " $from $to"; 197513c08e2fSMichael Klier 197613c08e2fSMichael Klier @exec($cmd, $out, $retval); 197713c08e2fSMichael Klier if ($retval == 0) return true; 197813c08e2fSMichael Klier return false; 197913c08e2fSMichael Klier} 198013c08e2fSMichael Klier 198113c08e2fSMichael Klier/** 198213c08e2fSMichael Klier * crop images using external ImageMagick convert program 198313c08e2fSMichael Klier * 198413c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 198542ea7f44SGerrit Uitslag * 198642ea7f44SGerrit Uitslag * @param string $ext extension 198742ea7f44SGerrit Uitslag * @param string $from filename path to file 198842ea7f44SGerrit Uitslag * @param int $from_w original width 198942ea7f44SGerrit Uitslag * @param int $from_h original height 199042ea7f44SGerrit Uitslag * @param string $to path to resized file 199142ea7f44SGerrit Uitslag * @param int $to_w desired width 199242ea7f44SGerrit Uitslag * @param int $to_h desired height 199342ea7f44SGerrit Uitslag * @param int $ofs_x offset of crop centre 199442ea7f44SGerrit Uitslag * @param int $ofs_y offset of crop centre 199542ea7f44SGerrit Uitslag * @return bool 1996d2bd34a5SAndreas Gohr * @deprecated 2020-09-01 199713c08e2fSMichael Klier */ 1998d868eb89SAndreas Gohrfunction media_crop_imageIM($ext, $from, $from_w, $from_h, $to, $to_w, $to_h, $ofs_x, $ofs_y) 1999d868eb89SAndreas Gohr{ 200013c08e2fSMichael Klier global $conf; 2001d2bd34a5SAndreas Gohr dbg_deprecated('splitbrain\\Slika'); 200213c08e2fSMichael Klier 200313c08e2fSMichael Klier // check if convert is configured 200413c08e2fSMichael Klier if (!$conf['im_convert']) return false; 200513c08e2fSMichael Klier 200613c08e2fSMichael Klier // prepare command 200713c08e2fSMichael Klier $cmd = $conf['im_convert']; 200813c08e2fSMichael Klier $cmd .= ' -crop '.$to_w.'x'.$to_h.'+'.$ofs_x.'+'.$ofs_y; 200913c08e2fSMichael Klier if ($ext == 'jpg' || $ext == 'jpeg') { 201013c08e2fSMichael Klier $cmd .= ' -quality '.$conf['jpg_quality']; 201113c08e2fSMichael Klier } 201213c08e2fSMichael Klier $cmd .= " $from $to"; 201313c08e2fSMichael Klier 201413c08e2fSMichael Klier @exec($cmd, $out, $retval); 201513c08e2fSMichael Klier if ($retval == 0) return true; 201613c08e2fSMichael Klier return false; 201713c08e2fSMichael Klier} 201813c08e2fSMichael Klier 201913c08e2fSMichael Klier/** 202013c08e2fSMichael Klier * resize or crop images using PHP's libGD support 202113c08e2fSMichael Klier * 202213c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 202313c08e2fSMichael Klier * @author Sebastian Wienecke <s_wienecke@web.de> 202442ea7f44SGerrit Uitslag * 202542ea7f44SGerrit Uitslag * @param string $ext extension 202642ea7f44SGerrit Uitslag * @param string $from filename path to file 202742ea7f44SGerrit Uitslag * @param int $from_w original width 202842ea7f44SGerrit Uitslag * @param int $from_h original height 202942ea7f44SGerrit Uitslag * @param string $to path to resized file 203042ea7f44SGerrit Uitslag * @param int $to_w desired width 203142ea7f44SGerrit Uitslag * @param int $to_h desired height 203242ea7f44SGerrit Uitslag * @param int $ofs_x offset of crop centre 203342ea7f44SGerrit Uitslag * @param int $ofs_y offset of crop centre 203442ea7f44SGerrit Uitslag * @return bool 2035d2bd34a5SAndreas Gohr * @deprecated 2020-09-01 203613c08e2fSMichael Klier */ 2037d868eb89SAndreas Gohrfunction media_resize_imageGD($ext, $from, $from_w, $from_h, $to, $to_w, $to_h, $ofs_x = 0, $ofs_y = 0) 2038d868eb89SAndreas Gohr{ 203913c08e2fSMichael Klier global $conf; 2040d2bd34a5SAndreas Gohr dbg_deprecated('splitbrain\\Slika'); 204113c08e2fSMichael Klier 204213c08e2fSMichael Klier if ($conf['gdlib'] < 1) return false; //no GDlib available or wanted 204313c08e2fSMichael Klier 204413c08e2fSMichael Klier // check available memory 204513c08e2fSMichael Klier if (!is_mem_available(($from_w * $from_h * 4) + ($to_w * $to_h * 4))) { 204613c08e2fSMichael Klier return false; 204713c08e2fSMichael Klier } 204813c08e2fSMichael Klier 204913c08e2fSMichael Klier // create an image of the given filetype 205059bc3b48SGerrit Uitslag $image = false; 205113c08e2fSMichael Klier if ($ext == 'jpg' || $ext == 'jpeg') { 205213c08e2fSMichael Klier if (!function_exists("imagecreatefromjpeg")) return false; 205313c08e2fSMichael Klier $image = @imagecreatefromjpeg($from); 205413c08e2fSMichael Klier } elseif ($ext == 'png') { 205513c08e2fSMichael Klier if (!function_exists("imagecreatefrompng")) return false; 205613c08e2fSMichael Klier $image = @imagecreatefrompng($from); 205713c08e2fSMichael Klier } elseif ($ext == 'gif') { 205813c08e2fSMichael Klier if (!function_exists("imagecreatefromgif")) return false; 205913c08e2fSMichael Klier $image = @imagecreatefromgif($from); 206013c08e2fSMichael Klier } 206113c08e2fSMichael Klier if (!$image) return false; 206213c08e2fSMichael Klier 206359bc3b48SGerrit Uitslag $newimg = false; 206413c08e2fSMichael Klier if (($conf['gdlib']>1) && function_exists("imagecreatetruecolor") && $ext != 'gif') { 206513c08e2fSMichael Klier $newimg = @imagecreatetruecolor($to_w, $to_h); 206613c08e2fSMichael Klier } 206713c08e2fSMichael Klier if (!$newimg) $newimg = @imagecreate($to_w, $to_h); 206813c08e2fSMichael Klier if (!$newimg) { 206913c08e2fSMichael Klier imagedestroy($image); 207013c08e2fSMichael Klier return false; 207113c08e2fSMichael Klier } 207213c08e2fSMichael Klier 207313c08e2fSMichael Klier //keep png alpha channel if possible 207413c08e2fSMichael Klier if ($ext == 'png' && $conf['gdlib']>1 && function_exists('imagesavealpha')) { 207513c08e2fSMichael Klier imagealphablending($newimg, false); 207613c08e2fSMichael Klier imagesavealpha($newimg, true); 207713c08e2fSMichael Klier } 207813c08e2fSMichael Klier 207913c08e2fSMichael Klier //keep gif transparent color if possible 208013c08e2fSMichael Klier if ($ext == 'gif' && function_exists('imagefill') && function_exists('imagecolorallocate')) { 208113c08e2fSMichael Klier if (function_exists('imagecolorsforindex') && function_exists('imagecolortransparent')) { 208213c08e2fSMichael Klier $transcolorindex = @imagecolortransparent($image); 208313c08e2fSMichael Klier if ($transcolorindex >= 0 ) { //transparent color exists 208413c08e2fSMichael Klier $transcolor = @imagecolorsforindex($image, $transcolorindex); 208564159a61SAndreas Gohr $transcolorindex = @imagecolorallocate( 208664159a61SAndreas Gohr $newimg, 208764159a61SAndreas Gohr $transcolor['red'], 208864159a61SAndreas Gohr $transcolor['green'], 208964159a61SAndreas Gohr $transcolor['blue'] 209064159a61SAndreas Gohr ); 209113c08e2fSMichael Klier @imagefill($newimg, 0, 0, $transcolorindex); 209213c08e2fSMichael Klier @imagecolortransparent($newimg, $transcolorindex); 209313c08e2fSMichael Klier } else { //filling with white 209413c08e2fSMichael Klier $whitecolorindex = @imagecolorallocate($newimg, 255, 255, 255); 209513c08e2fSMichael Klier @imagefill($newimg, 0, 0, $whitecolorindex); 209613c08e2fSMichael Klier } 209713c08e2fSMichael Klier } else { //filling with white 209813c08e2fSMichael Klier $whitecolorindex = @imagecolorallocate($newimg, 255, 255, 255); 209913c08e2fSMichael Klier @imagefill($newimg, 0, 0, $whitecolorindex); 210013c08e2fSMichael Klier } 210113c08e2fSMichael Klier } 210213c08e2fSMichael Klier 210313c08e2fSMichael Klier //try resampling first 210413c08e2fSMichael Klier if (function_exists("imagecopyresampled")) { 210513c08e2fSMichael Klier if (!@imagecopyresampled($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h)) { 210613c08e2fSMichael Klier imagecopyresized($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h); 210713c08e2fSMichael Klier } 210813c08e2fSMichael Klier } else { 210913c08e2fSMichael Klier imagecopyresized($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h); 211013c08e2fSMichael Klier } 211113c08e2fSMichael Klier 211213c08e2fSMichael Klier $okay = false; 211313c08e2fSMichael Klier if ($ext == 'jpg' || $ext == 'jpeg') { 211413c08e2fSMichael Klier if (!function_exists('imagejpeg')) { 211513c08e2fSMichael Klier $okay = false; 211613c08e2fSMichael Klier } else { 211713c08e2fSMichael Klier $okay = imagejpeg($newimg, $to, $conf['jpg_quality']); 211813c08e2fSMichael Klier } 211913c08e2fSMichael Klier } elseif ($ext == 'png') { 212013c08e2fSMichael Klier if (!function_exists('imagepng')) { 212113c08e2fSMichael Klier $okay = false; 212213c08e2fSMichael Klier } else { 212313c08e2fSMichael Klier $okay = imagepng($newimg, $to); 212413c08e2fSMichael Klier } 212513c08e2fSMichael Klier } elseif ($ext == 'gif') { 212613c08e2fSMichael Klier if (!function_exists('imagegif')) { 212713c08e2fSMichael Klier $okay = false; 212813c08e2fSMichael Klier } else { 212913c08e2fSMichael Klier $okay = imagegif($newimg, $to); 213013c08e2fSMichael Klier } 213113c08e2fSMichael Klier } 213213c08e2fSMichael Klier 213379a2d784SGerrit Uitslag // destroy GD image resources 213479a2d784SGerrit Uitslag imagedestroy($image); 213579a2d784SGerrit Uitslag imagedestroy($newimg); 213613c08e2fSMichael Klier 213713c08e2fSMichael Klier return $okay; 213813c08e2fSMichael Klier} 213913c08e2fSMichael Klier 21403d7a9e0aSAnika Henke/** 21413d7a9e0aSAnika Henke * Return other media files with the same base name 214279e53fe5SAnika Henke * but different extensions. 21433d7a9e0aSAnika Henke * 21443d7a9e0aSAnika Henke * @param string $src - ID of media file 214542ea7f44SGerrit Uitslag * @param string[] $exts - alternative extensions to find other files for 214642ea7f44SGerrit Uitslag * @return array - array(mime type => file ID) 21473d7a9e0aSAnika Henke * 21483d7a9e0aSAnika Henke * @author Anika Henke <anika@selfthinker.org> 21493d7a9e0aSAnika Henke */ 2150d868eb89SAndreas Gohrfunction media_alternativefiles($src, $exts) 2151d868eb89SAndreas Gohr{ 21523d7a9e0aSAnika Henke 215324870174SAndreas Gohr $files = []; 2154a19c9aa0SGerrit Uitslag [$srcExt, /* srcMime */] = mimetype($src); 21553d7a9e0aSAnika Henke $filebase = substr($src, 0, -1 * (strlen($srcExt)+1)); 21563d7a9e0aSAnika Henke 21573d7a9e0aSAnika Henke foreach ($exts as $ext) { 21583d7a9e0aSAnika Henke $fileid = $filebase.'.'.$ext; 21593d7a9e0aSAnika Henke $file = mediaFN($fileid); 21603d7a9e0aSAnika Henke if (file_exists($file)) { 2161a19c9aa0SGerrit Uitslag [/* fileExt */, $fileMime] = mimetype($file); 216279e53fe5SAnika Henke $files[$fileMime] = $fileid; 216399f943f6SAnika Henke } 21643d7a9e0aSAnika Henke } 21653d7a9e0aSAnika Henke return $files; 21663d7a9e0aSAnika Henke} 21673d7a9e0aSAnika Henke 2168f50634f0SAnika Henke/** 2169f50634f0SAnika Henke * Check if video/audio is supported to be embedded. 2170f50634f0SAnika Henke * 2171b83a74f1SAnika Henke * @param string $mime - mimetype of media file 217242ea7f44SGerrit Uitslag * @param string $type - type of media files to check ('video', 'audio', or null for all) 2173f50634f0SAnika Henke * @return boolean 2174f50634f0SAnika Henke * 2175f50634f0SAnika Henke * @author Anika Henke <anika@selfthinker.org> 2176f50634f0SAnika Henke */ 2177ed823bcdSAndreas Gohrfunction media_supportedav($mime, $type = null) 2178d868eb89SAndreas Gohr{ 217924870174SAndreas Gohr $supportedAudio = [ 2180f50634f0SAnika Henke 'ogg' => 'audio/ogg', 2181f50634f0SAnika Henke 'mp3' => 'audio/mpeg', 218224870174SAndreas Gohr 'wav' => 'audio/wav' 218324870174SAndreas Gohr ]; 218424870174SAndreas Gohr $supportedVideo = [ 2185f50634f0SAnika Henke 'webm' => 'video/webm', 2186f50634f0SAnika Henke 'ogv' => 'video/ogg', 218724870174SAndreas Gohr 'mp4' => 'video/mp4' 218824870174SAndreas Gohr ]; 2189f50634f0SAnika Henke if ($type == 'audio') { 2190f50634f0SAnika Henke $supportedAv = $supportedAudio; 2191f50634f0SAnika Henke } elseif ($type == 'video') { 2192f50634f0SAnika Henke $supportedAv = $supportedVideo; 2193f50634f0SAnika Henke } else { 2194f50634f0SAnika Henke $supportedAv = array_merge($supportedAudio, $supportedVideo); 2195f50634f0SAnika Henke } 2196f50634f0SAnika Henke return in_array($mime, $supportedAv); 2197f50634f0SAnika Henke} 2198f50634f0SAnika Henke 21990877a1f1SSchplurtz le Déboulonné/** 22000877a1f1SSchplurtz le Déboulonné * Return track media files with the same base name 22010877a1f1SSchplurtz le Déboulonné * but extensions that indicate kind and lang. 22020877a1f1SSchplurtz le Déboulonné * ie for foo.webm search foo.sub.lang.vtt, foo.cap.lang.vtt... 22030877a1f1SSchplurtz le Déboulonné * 22040877a1f1SSchplurtz le Déboulonné * @param string $src - ID of media file 220501299338SSchplurtz le Déboulonné * @return array - array(mediaID => array( kind, srclang )) 22060877a1f1SSchplurtz le Déboulonné * 22070877a1f1SSchplurtz le Déboulonné * @author Schplurtz le Déboulonné <Schplurtz@laposte.net> 22080877a1f1SSchplurtz le Déboulonné */ 2209d868eb89SAndreas Gohrfunction media_trackfiles($src) 2210d868eb89SAndreas Gohr{ 221124870174SAndreas Gohr $kinds=[ 22120877a1f1SSchplurtz le Déboulonné 'sub' => 'subtitles', 22130877a1f1SSchplurtz le Déboulonné 'cap' => 'captions', 22140877a1f1SSchplurtz le Déboulonné 'des' => 'descriptions', 22150877a1f1SSchplurtz le Déboulonné 'cha' => 'chapters', 22160877a1f1SSchplurtz le Déboulonné 'met' => 'metadata' 221724870174SAndreas Gohr ]; 22180877a1f1SSchplurtz le Déboulonné 221924870174SAndreas Gohr $files = []; 22200877a1f1SSchplurtz le Déboulonné $re='/\\.(sub|cap|des|cha|met)\\.([^.]+)\\.vtt$/'; 22210877a1f1SSchplurtz le Déboulonné $baseid=pathinfo($src, PATHINFO_FILENAME); 22220877a1f1SSchplurtz le Déboulonné $pattern=mediaFN($baseid).'.*.*.vtt'; 22230877a1f1SSchplurtz le Déboulonné $list=glob($pattern); 22240877a1f1SSchplurtz le Déboulonné foreach ($list as $track) { 22250877a1f1SSchplurtz le Déboulonné if (preg_match($re, $track, $matches)) { 222624870174SAndreas Gohr $files[$baseid.'.'.$matches[1].'.'.$matches[2].'.vtt']=[$kinds[$matches[1]], $matches[2]]; 22270877a1f1SSchplurtz le Déboulonné } 22280877a1f1SSchplurtz le Déboulonné } 22290877a1f1SSchplurtz le Déboulonné return $files; 22300877a1f1SSchplurtz le Déboulonné} 22310877a1f1SSchplurtz le Déboulonné 2232365be586SAndreas Gohr/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 2233