13df72098SAndreas Gohr<?php 2d4f83172SAndreas Gohr 33df72098SAndreas Gohr/** 43df72098SAndreas Gohr * All output and handler function needed for the media management popup 53df72098SAndreas Gohr * 63df72098SAndreas Gohr * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 73df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 83df72098SAndreas Gohr */ 93df72098SAndreas Gohr 1024870174SAndreas Gohruse dokuwiki\Ui\MediaRevisions; 1124870174SAndreas Gohruse dokuwiki\Cache\CacheImageMod; 1224870174SAndreas Gohruse splitbrain\slika\Exception; 1324870174SAndreas Gohruse dokuwiki\PassHash; 140c3a5702SAndreas Gohruse dokuwiki\ChangeLog\MediaChangeLog; 15b021f0b4SAndreas Gohruse dokuwiki\Extension\Event; 16b021f0b4SAndreas Gohruse dokuwiki\Form\Form; 175a8d6e48SMichael Großeuse dokuwiki\HTTP\DokuHTTPClient; 1879a2d784SGerrit Uitslaguse dokuwiki\Logger; 19704a815fSMichael Großeuse dokuwiki\Subscriptions\MediaSubscriptionSender; 2079a2d784SGerrit Uitslaguse dokuwiki\Ui\Media\DisplayRow; 2179a2d784SGerrit Uitslaguse dokuwiki\Ui\Media\DisplayTile; 2279a2d784SGerrit Uitslaguse dokuwiki\Ui\MediaDiff; 2379a2d784SGerrit Uitslaguse dokuwiki\Utf8\PhpString; 242d85e841SAndreas Gohruse dokuwiki\Utf8\Sort; 2579a2d784SGerrit Uitslaguse splitbrain\slika\Slika; 260c3a5702SAndreas Gohr 273df72098SAndreas Gohr/** 283df72098SAndreas Gohr * Lists pages which currently use a media file selected for deletion 293df72098SAndreas Gohr * 303df72098SAndreas Gohr * References uses the same visual as search results and share 313df72098SAndreas Gohr * their CSS tags except pagenames won't be links. 323df72098SAndreas Gohr * 333df72098SAndreas Gohr * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net> 3442ea7f44SGerrit Uitslag * 3542ea7f44SGerrit Uitslag * @param array $data 3642ea7f44SGerrit Uitslag * @param string $id 373df72098SAndreas Gohr */ 38d868eb89SAndreas Gohrfunction media_filesinuse($data, $id) 39d868eb89SAndreas Gohr{ 403df72098SAndreas Gohr global $lang; 413df72098SAndreas Gohr echo '<h1>' . $lang['reference'] . ' <code>' . hsc(noNS($id)) . '</code></h1>'; 423df72098SAndreas Gohr echo '<p>' . hsc($lang['ref_inuse']) . '</p>'; 433df72098SAndreas Gohr 443df72098SAndreas Gohr $hidden = 0; //count of hits without read permission 453df72098SAndreas Gohr foreach ($data as $row) { 46a05e297aSAndreas Gohr if (auth_quickaclcheck($row) >= AUTH_READ && isVisiblePage($row)) { 473df72098SAndreas Gohr echo '<div class="search_result">'; 48a05e297aSAndreas Gohr echo '<span class="mediaref_ref">' . hsc($row) . '</span>'; 493df72098SAndreas Gohr echo '</div>'; 50177d6836SAndreas Gohr } else $hidden++; 513df72098SAndreas Gohr } 523df72098SAndreas Gohr if ($hidden) { 5326dfc232SAndreas Gohr echo '<div class="mediaref_hidden">' . $lang['ref_hidden'] . '</div>'; 543df72098SAndreas Gohr } 553df72098SAndreas Gohr} 563df72098SAndreas Gohr 573df72098SAndreas Gohr/** 583df72098SAndreas Gohr * Handles the saving of image meta data 593df72098SAndreas Gohr * 603df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 61cf832786SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 62e0c26282SGerrit Uitslag * 63e0c26282SGerrit Uitslag * @param string $id media id 64e0c26282SGerrit Uitslag * @param int $auth permission level 65e0c26282SGerrit Uitslag * @param array $data 6642ea7f44SGerrit Uitslag * @return false|string 673df72098SAndreas Gohr */ 68d868eb89SAndreas Gohrfunction media_metasave($id, $auth, $data) 69d868eb89SAndreas Gohr{ 703df72098SAndreas Gohr if ($auth < AUTH_UPLOAD) return false; 71f2ea8432SAndreas Gohr if (!checkSecurityToken()) return false; 723df72098SAndreas Gohr global $lang; 730b308644SOtto Vainio global $conf; 743df72098SAndreas Gohr $src = mediaFN($id); 753df72098SAndreas Gohr 763df72098SAndreas Gohr $meta = new JpegMeta($src); 773df72098SAndreas Gohr $meta->_parseAll(); 783df72098SAndreas Gohr 793df72098SAndreas Gohr foreach ($data as $key => $val) { 803df72098SAndreas Gohr $val = trim($val); 813df72098SAndreas Gohr if (empty($val)) { 823df72098SAndreas Gohr $meta->deleteField($key); 833df72098SAndreas Gohr } else { 843df72098SAndreas Gohr $meta->setField($key, $val); 853df72098SAndreas Gohr } 863df72098SAndreas Gohr } 873df72098SAndreas Gohr 88cf832786SKate Arzamastseva $old = @filemtime($src); 8979e79377SAndreas Gohr if (!file_exists(mediaFN($id, $old)) && file_exists($src)) { 90cf832786SKate Arzamastseva // add old revision to the attic 91cf832786SKate Arzamastseva media_saveOldRevision($id); 92cf832786SKate Arzamastseva } 93ac3ed4afSGerrit Uitslag $filesize_old = filesize($src); 943df72098SAndreas Gohr if ($meta->save()) { 950b308644SOtto Vainio if ($conf['fperm']) chmod($src, $conf['fperm']); 96ac3ed4afSGerrit Uitslag @clearstatcache(true, $src); 97cf832786SKate Arzamastseva $new = @filemtime($src); 98ac3ed4afSGerrit Uitslag $filesize_new = filesize($src); 99ac3ed4afSGerrit Uitslag $sizechange = $filesize_new - $filesize_old; 100ac3ed4afSGerrit Uitslag 101cf832786SKate Arzamastseva // add a log entry to the media changelog 102ac3ed4afSGerrit Uitslag addMediaLogEntry($new, $id, DOKU_CHANGE_TYPE_EDIT, $lang['media_meta_edited'], '', null, $sizechange); 103cf832786SKate Arzamastseva 1043df72098SAndreas Gohr msg($lang['metasaveok'], 1); 1053df72098SAndreas Gohr return $id; 1063df72098SAndreas Gohr } else { 1073df72098SAndreas Gohr msg($lang['metasaveerr'], -1); 1083df72098SAndreas Gohr return false; 1093df72098SAndreas Gohr } 1103df72098SAndreas Gohr} 1113df72098SAndreas Gohr 1123df72098SAndreas Gohr/** 113d54f7963SKlap-in * check if a media is external source 114d54f7963SKlap-in * 115d54f7963SKlap-in * @author Gerrit Uitslag <klapinklapin@gmail.com> 11642ea7f44SGerrit Uitslag * 117d54f7963SKlap-in * @param string $id the media ID or URL 118d54f7963SKlap-in * @return bool 119d54f7963SKlap-in */ 120d868eb89SAndreas Gohrfunction media_isexternal($id) 121d868eb89SAndreas Gohr{ 122fe578fe9SElan Ruusamäe if (preg_match('#^(?:https?|ftp)://#i', $id)) return true; 123d54f7963SKlap-in return false; 124d54f7963SKlap-in} 125d54f7963SKlap-in 126d54f7963SKlap-in/** 127add8678fSAndreas Gohr * Check if a media item is public (eg, external URL or readable by @ALL) 128add8678fSAndreas Gohr * 129add8678fSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 13042ea7f44SGerrit Uitslag * 131add8678fSAndreas Gohr * @param string $id the media ID or URL 132add8678fSAndreas Gohr * @return bool 133add8678fSAndreas Gohr */ 134d868eb89SAndreas Gohrfunction media_ispublic($id) 135d868eb89SAndreas Gohr{ 136d54f7963SKlap-in if (media_isexternal($id)) return true; 137add8678fSAndreas Gohr $id = cleanID($id); 13824870174SAndreas Gohr if (auth_aclcheck(getNS($id) . ':*', '', []) >= AUTH_READ) return true; 139add8678fSAndreas Gohr return false; 140add8678fSAndreas Gohr} 141add8678fSAndreas Gohr 142add8678fSAndreas Gohr/** 1433df72098SAndreas Gohr * Display the form to edit image meta data 1443df72098SAndreas Gohr * 1453df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 146d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 147e0c26282SGerrit Uitslag * 148e0c26282SGerrit Uitslag * @param string $id media id 149e0c26282SGerrit Uitslag * @param int $auth permission level 150e0c26282SGerrit Uitslag * @return bool 1513df72098SAndreas Gohr */ 152d868eb89SAndreas Gohrfunction media_metaform($id, $auth) 153d868eb89SAndreas Gohr{ 154ebc28e69SAndreas Gohr global $lang; 1553df72098SAndreas Gohr 15688a71175SKate Arzamastseva if ($auth < AUTH_UPLOAD) { 157b960c74fSSatoshi Sahara echo '<div class="nothing">' . $lang['media_perm_upload'] . '</div>' . DOKU_LF; 15888a71175SKate Arzamastseva return false; 15988a71175SKate Arzamastseva } 16088a71175SKate Arzamastseva 1613df72098SAndreas Gohr // load the field descriptions 1623df72098SAndreas Gohr static $fields = null; 163b960c74fSSatoshi Sahara if ($fields === null) { 1643e98e685SKate Arzamastseva $config_files = getConfigFiles('mediameta'); 1653e98e685SKate Arzamastseva foreach ($config_files as $config_file) { 16679e79377SAndreas Gohr if (file_exists($config_file)) include($config_file); 1673df72098SAndreas Gohr } 1683df72098SAndreas Gohr } 1693df72098SAndreas Gohr 1703df72098SAndreas Gohr $src = mediaFN($id); 1713df72098SAndreas Gohr 1723df72098SAndreas Gohr // output 173b960c74fSSatoshi Sahara $form = new Form([ 174b960c74fSSatoshi Sahara 'action' => media_managerURL(['tab_details' => 'view'], '&'), 175b960c74fSSatoshi Sahara 'class' => 'meta' 176b960c74fSSatoshi Sahara ]); 177b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 178b960c74fSSatoshi Sahara $form->setHiddenField('img', $id); 179b960c74fSSatoshi Sahara $form->setHiddenField('mediado', 'save'); 1803df72098SAndreas Gohr foreach ($fields as $key => $field) { 1813df72098SAndreas Gohr // get current value 1823e98e685SKate Arzamastseva if (empty($field[0])) continue; 18324870174SAndreas Gohr $tags = [$field[0]]; 1845cefb623SEduardo Mozart de Oliveira if (isset($field[3]) && is_array($field[3])) $tags = array_merge($tags, $field[3]); 1853df72098SAndreas Gohr $value = tpl_img_getTag($tags, '', $src); 186ca6a0701SAndreas Gohr $value = cleanText($value); 1873df72098SAndreas Gohr 1883df72098SAndreas Gohr // prepare attributes 18924870174SAndreas Gohr $p = [ 190b960c74fSSatoshi Sahara 'class' => 'edit', 191b960c74fSSatoshi Sahara 'id' => 'meta__' . $key, 19224870174SAndreas Gohr 'name' => 'meta[' . $field[0] . ']' 19324870174SAndreas Gohr ]; 1943df72098SAndreas Gohr 195b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('row'); 1963df72098SAndreas Gohr if ($field[2] == 'text') { 197bde2a644SSatoshi Sahara $form->addTextInput( 19864159a61SAndreas Gohr $p['name'], 19979a2d784SGerrit Uitslag ($lang[$field[1]] ?: $field[1] . ':') 200b960c74fSSatoshi Sahara )->id($p['id'])->addClass($p['class'])->val($value); 2013df72098SAndreas Gohr } else { 202b960c74fSSatoshi Sahara $form->addTextarea($p['name'], $lang[$field[1]])->id($p['id']) 203b960c74fSSatoshi Sahara ->val(formText($value)) 204b960c74fSSatoshi Sahara ->addClass($p['class']) 205b960c74fSSatoshi Sahara ->attr('rows', '6')->attr('cols', '50'); 2063df72098SAndreas Gohr } 207b960c74fSSatoshi Sahara $form->addTagClose('div'); 2083df72098SAndreas Gohr } 209b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('buttons'); 210b960c74fSSatoshi Sahara $form->addButton('mediado[save]', $lang['btn_save'])->attr('type', 'submit') 211b960c74fSSatoshi Sahara ->attrs(['accesskey' => 's']); 212b960c74fSSatoshi Sahara $form->addTagClose('div'); 213ebc28e69SAndreas Gohr 214b960c74fSSatoshi Sahara $form->addTagClose('div'); 215b960c74fSSatoshi Sahara echo $form->toHTML(); 216ebc28e69SAndreas Gohr return true; 2173df72098SAndreas Gohr} 2183df72098SAndreas Gohr 219666cdec5SMichael Klier/** 22087229c84SAdrian Lang * Convenience function to check if a media file is still in use 221666cdec5SMichael Klier * 222666cdec5SMichael Klier * @author Michael Klier <chi@chimeric.de> 223e0c26282SGerrit Uitslag * 224e0c26282SGerrit Uitslag * @param string $id media id 225e0c26282SGerrit Uitslag * @return array|bool 226666cdec5SMichael Klier */ 227d868eb89SAndreas Gohrfunction media_inuse($id) 228d868eb89SAndreas Gohr{ 229666cdec5SMichael Klier global $conf; 230ebc28e69SAndreas Gohr 231666cdec5SMichael Klier if ($conf['refcheck']) { 232ffec1009SMichael Hamann $mediareferences = ft_mediause($id, true); 23324870174SAndreas Gohr if ($mediareferences === []) { 2346dae2464SAndreas Gohr return false; 235666cdec5SMichael Klier } else { 236666cdec5SMichael Klier return $mediareferences; 237666cdec5SMichael Klier } 238666cdec5SMichael Klier } else { 239666cdec5SMichael Klier return false; 240666cdec5SMichael Klier } 241666cdec5SMichael Klier} 242a05e297aSAndreas Gohr 2433df72098SAndreas Gohr/** 2443df72098SAndreas Gohr * Handles media file deletions 2453df72098SAndreas Gohr * 2463df72098SAndreas Gohr * If configured, checks for media references before deletion 2473df72098SAndreas Gohr * 2483df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 24942ea7f44SGerrit Uitslag * 250ebc28e69SAndreas Gohr * @param string $id media id 25122db8df7SAndreas Gohr * @param int $auth no longer used 25287229c84SAdrian Lang * @return int One of: 0, 25363703ba5SAndreas Gohr * DOKU_MEDIA_DELETED, 25463703ba5SAndreas Gohr * DOKU_MEDIA_DELETED | DOKU_MEDIA_EMPTY_NS, 25563703ba5SAndreas Gohr * DOKU_MEDIA_NOT_AUTH, 25663703ba5SAndreas Gohr * DOKU_MEDIA_INUSE 2573df72098SAndreas Gohr */ 258d868eb89SAndreas Gohrfunction media_delete($id, $auth) 259d868eb89SAndreas Gohr{ 2606183fb05SKate Arzamastseva global $lang; 261ff04e8b7SAndreas Gohr $auth = auth_quickaclcheck(ltrim(getNS($id) . ':*', ':')); 26287229c84SAdrian Lang if ($auth < AUTH_DELETE) return DOKU_MEDIA_NOT_AUTH; 26387229c84SAdrian Lang if (media_inuse($id)) return DOKU_MEDIA_INUSE; 2643df72098SAndreas Gohr 2653df72098SAndreas Gohr $file = mediaFN($id); 2664a961e72SMichal Kolodziejski 2674a961e72SMichal Kolodziejski // trigger an event - MEDIA_DELETE_FILE 26824870174SAndreas Gohr $data = []; 269666cdec5SMichael Klier $data['id'] = $id; 27079a2d784SGerrit Uitslag $data['name'] = PhpString::basename($file); 2714a961e72SMichal Kolodziejski $data['path'] = $file; 27279e79377SAndreas Gohr $data['size'] = (file_exists($file)) ? filesize($file) : 0; 273666cdec5SMichael Klier 274666cdec5SMichael Klier $data['unl'] = false; 275666cdec5SMichael Klier $data['del'] = false; 276e1d9dcc8SAndreas Gohr $evt = new Event('MEDIA_DELETE_FILE', $data); 2774a961e72SMichal Kolodziejski if ($evt->advise_before()) { 2786183fb05SKate Arzamastseva $old = @filemtime($file); 27979e79377SAndreas Gohr if (!file_exists(mediaFN($id, $old)) && file_exists($file)) { 2806183fb05SKate Arzamastseva // add old revision to the attic 2816183fb05SKate Arzamastseva media_saveOldRevision($id); 2826183fb05SKate Arzamastseva } 2836183fb05SKate Arzamastseva 284666cdec5SMichael Klier $data['unl'] = @unlink($file); 285666cdec5SMichael Klier if ($data['unl']) { 286ac3ed4afSGerrit Uitslag $sizechange = 0 - $data['size']; 287ac3ed4afSGerrit Uitslag addMediaLogEntry(time(), $id, DOKU_CHANGE_TYPE_DELETE, $lang['deleted'], '', null, $sizechange); 288ac3ed4afSGerrit Uitslag 289666cdec5SMichael Klier $data['del'] = io_sweepNS($id, 'mediadir'); 2903df72098SAndreas Gohr } 2914a961e72SMichal Kolodziejski } 2924a961e72SMichal Kolodziejski $evt->advise_after(); 2934a961e72SMichal Kolodziejski unset($evt); 2944a961e72SMichal Kolodziejski 295666cdec5SMichael Klier if ($data['unl'] && $data['del']) { 29687229c84SAdrian Lang return DOKU_MEDIA_DELETED | DOKU_MEDIA_EMPTY_NS; 2973df72098SAndreas Gohr } 2983df72098SAndreas Gohr 29987229c84SAdrian Lang return $data['unl'] ? DOKU_MEDIA_DELETED : 0; 3003df72098SAndreas Gohr} 3013df72098SAndreas Gohr 3023df72098SAndreas Gohr/** 3032d6cc64fSKate Arzamastseva * Handle file uploads via XMLHttpRequest 3042d6cc64fSKate Arzamastseva * 305ebc28e69SAndreas Gohr * @param string $ns target namespace 306ebc28e69SAndreas Gohr * @param int $auth current auth check result 30742ea7f44SGerrit Uitslag * @return false|string false on error, id of the new file on success 3082d6cc64fSKate Arzamastseva */ 309d868eb89SAndreas Gohrfunction media_upload_xhr($ns, $auth) 310d868eb89SAndreas Gohr{ 311da45d883SKate Arzamastseva if (!checkSecurityToken()) return false; 3128108113cSTom N Harris global $INPUT; 313da45d883SKate Arzamastseva 3148108113cSTom N Harris $id = $INPUT->get->str('qqfile'); 31524870174SAndreas Gohr [$ext, $mime] = mimetype($id); 3162d6cc64fSKate Arzamastseva $input = fopen("php://input", "r"); 3172d6cc64fSKate Arzamastseva if (!($tmp = io_mktmpdir())) return false; 31862231793SKate Arzamastseva $path = $tmp . '/' . md5($id); 3192d6cc64fSKate Arzamastseva $target = fopen($path, "w"); 320063fb5b5SAndreas Gohr $realSize = stream_copy_to_stream($input, $target); 3212d6cc64fSKate Arzamastseva fclose($target); 322063fb5b5SAndreas Gohr fclose($input); 3232b9be456SAndreas Gohr if ($INPUT->server->has('CONTENT_LENGTH') && ($realSize != $INPUT->server->int('CONTENT_LENGTH'))) { 324063fb5b5SAndreas Gohr unlink($path); 325063fb5b5SAndreas Gohr return false; 326063fb5b5SAndreas Gohr } 327063fb5b5SAndreas Gohr 3282d6cc64fSKate Arzamastseva $res = media_save( 32924870174SAndreas Gohr ['name' => $path, 'mime' => $mime, 'ext' => $ext], 3302d6cc64fSKate Arzamastseva $ns . ':' . $id, 33179a2d784SGerrit Uitslag ($INPUT->get->str('ow') == 'true'), 3322d6cc64fSKate Arzamastseva $auth, 3332d6cc64fSKate Arzamastseva 'copy' 3342d6cc64fSKate Arzamastseva ); 3352d6cc64fSKate Arzamastseva unlink($path); 336900a9e9eSGerrit Uitslag if ($tmp) io_rmdir($tmp, true); 3372d6cc64fSKate Arzamastseva if (is_array($res)) { 3382d6cc64fSKate Arzamastseva msg($res[0], $res[1]); 3392d6cc64fSKate Arzamastseva return false; 3402d6cc64fSKate Arzamastseva } 3412d6cc64fSKate Arzamastseva return $res; 3422d6cc64fSKate Arzamastseva} 3432d6cc64fSKate Arzamastseva 3442d6cc64fSKate Arzamastseva/** 3453df72098SAndreas Gohr * Handles media file uploads 3463df72098SAndreas Gohr * 3473df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 34811d9dfa5SMichael Klier * @author Michael Klier <chi@chimeric.de> 34942ea7f44SGerrit Uitslag * 350ebc28e69SAndreas Gohr * @param string $ns target namespace 351ebc28e69SAndreas Gohr * @param int $auth current auth check result 352ebc28e69SAndreas Gohr * @param bool|array $file $_FILES member, $_FILES['upload'] if false 35342ea7f44SGerrit Uitslag * @return false|string false on error, id of the new file on success 3543df72098SAndreas Gohr */ 355d868eb89SAndreas Gohrfunction media_upload($ns, $auth, $file = false) 356d868eb89SAndreas Gohr{ 357f2ea8432SAndreas Gohr if (!checkSecurityToken()) return false; 3583df72098SAndreas Gohr global $lang; 3598108113cSTom N Harris global $INPUT; 3603df72098SAndreas Gohr 36144409c3dSAndreas Gohr // get file and id 3628108113cSTom N Harris $id = $INPUT->post->str('mediaid'); 3632d6cc64fSKate Arzamastseva if (!$file) $file = $_FILES['upload']; 3643df72098SAndreas Gohr if (empty($id)) $id = $file['name']; 36544409c3dSAndreas Gohr 36699766eefSAndreas Gohr // check for errors (messages are done in lib/exe/mediamanager.php) 36799766eefSAndreas Gohr if ($file['error']) return false; 3689676dc23SAndreas Gohr 36944409c3dSAndreas Gohr // check extensions 37024870174SAndreas Gohr [$fext, $fmime] = mimetype($file['name']); 37124870174SAndreas Gohr [$iext, $imime] = mimetype($id); 37244409c3dSAndreas Gohr if ($fext && !$iext) { 3738cb1eb01SAndreas Gohr // no extension specified in id - read original one 37444409c3dSAndreas Gohr $id .= '.' . $fext; 3758cb1eb01SAndreas Gohr $imime = $fmime; 37644409c3dSAndreas Gohr } elseif ($fext && $fext != $iext) { 37744409c3dSAndreas Gohr // extension was changed, print warning 37844409c3dSAndreas Gohr msg(sprintf($lang['mediaextchange'], $fext, $iext)); 37944409c3dSAndreas Gohr } 38044409c3dSAndreas Gohr 38124870174SAndreas Gohr $res = media_save( 38224870174SAndreas Gohr [ 38324870174SAndreas Gohr 'name' => $file['tmp_name'], 384ffb291f2SAdrian Lang 'mime' => $imime, 38524870174SAndreas Gohr 'ext' => $iext 38624870174SAndreas Gohr ], 38724870174SAndreas Gohr $ns . ':' . $id, 38824870174SAndreas Gohr $INPUT->post->bool('ow'), 38924870174SAndreas Gohr $auth, 39024870174SAndreas Gohr 'copy_uploaded_file' 39124870174SAndreas Gohr ); 392ffb291f2SAdrian Lang if (is_array($res)) { 393ffb291f2SAdrian Lang msg($res[0], $res[1]); 394ffb291f2SAdrian Lang return false; 395ffb291f2SAdrian Lang } 396ffb291f2SAdrian Lang return $res; 397ffb291f2SAdrian Lang} 398ffb291f2SAdrian Lang 399ffb291f2SAdrian Lang/** 40071f17ac4SAndreas Gohr * An alternative to move_uploaded_file that copies 40171f17ac4SAndreas Gohr * 40271f17ac4SAndreas Gohr * Using copy, makes sure any setgid bits on the media directory are honored 40371f17ac4SAndreas Gohr * 40471f17ac4SAndreas Gohr * @see move_uploaded_file() 40542ea7f44SGerrit Uitslag * 40671f17ac4SAndreas Gohr * @param string $from 40771f17ac4SAndreas Gohr * @param string $to 40871f17ac4SAndreas Gohr * @return bool 40971f17ac4SAndreas Gohr */ 410d868eb89SAndreas Gohrfunction copy_uploaded_file($from, $to) 411d868eb89SAndreas Gohr{ 41271f17ac4SAndreas Gohr if (!is_uploaded_file($from)) return false; 41371f17ac4SAndreas Gohr $ok = copy($from, $to); 41471f17ac4SAndreas Gohr @unlink($from); 41571f17ac4SAndreas Gohr return $ok; 41671f17ac4SAndreas Gohr} 41771f17ac4SAndreas Gohr 41871f17ac4SAndreas Gohr/** 419ffb291f2SAdrian Lang * This generates an action event and delegates to _media_upload_action(). 420ffb291f2SAdrian Lang * Action plugins are allowed to pre/postprocess the uploaded file. 421ffb291f2SAdrian Lang * (The triggered event is preventable.) 422ffb291f2SAdrian Lang * 423ffb291f2SAdrian Lang * Event data: 424ffb291f2SAdrian Lang * $data[0] fn_tmp: the temporary file name (read from $_FILES) 425ffb291f2SAdrian Lang * $data[1] fn: the file name of the uploaded file 426ffb291f2SAdrian Lang * $data[2] id: the future directory id of the uploaded file 427ffb291f2SAdrian Lang * $data[3] imime: the mimetype of the uploaded file 428ffb291f2SAdrian Lang * $data[4] overwrite: if an existing file is going to be overwritten 42952a281e8SGerrit Uitslag * $data[5] move: name of function that performs move/copy/.. 430ffb291f2SAdrian Lang * 431ffb291f2SAdrian Lang * @triggers MEDIA_UPLOAD_FINISH 43242ea7f44SGerrit Uitslag * 433e0c26282SGerrit Uitslag * @param array $file 43452a281e8SGerrit Uitslag * @param string $id media id 43542ea7f44SGerrit Uitslag * @param bool $ow overwrite? 436e0c26282SGerrit Uitslag * @param int $auth permission level 43752a281e8SGerrit Uitslag * @param string $move name of functions that performs move/copy/.. 43842ea7f44SGerrit Uitslag * @return false|array|string 439e0c26282SGerrit Uitslag */ 440d868eb89SAndreas Gohrfunction media_save($file, $id, $ow, $auth, $move) 441d868eb89SAndreas Gohr{ 442ffb291f2SAdrian Lang if ($auth < AUTH_UPLOAD) { 44324870174SAndreas Gohr return ["You don't have permissions to upload files.", -1]; 444ffb291f2SAdrian Lang } 445ffb291f2SAdrian Lang 446ffb291f2SAdrian Lang if (!isset($file['mime']) || !isset($file['ext'])) { 44724870174SAndreas Gohr [$ext, $mime] = mimetype($id); 448ffb291f2SAdrian Lang if (!isset($file['mime'])) { 449ffb291f2SAdrian Lang $file['mime'] = $mime; 450ffb291f2SAdrian Lang } 451ffb291f2SAdrian Lang if (!isset($file['ext'])) { 452ffb291f2SAdrian Lang $file['ext'] = $ext; 453ffb291f2SAdrian Lang } 454ffb291f2SAdrian Lang } 455ffb291f2SAdrian Lang 45692cac9a9SKate Arzamastseva global $lang, $conf; 457ffb291f2SAdrian Lang 4583df72098SAndreas Gohr // get filename 4593543c6deSAndreas Gohr $id = cleanID($id); 4603df72098SAndreas Gohr $fn = mediaFN($id); 4613df72098SAndreas Gohr 4623df72098SAndreas Gohr // get filetype regexp 4633df72098SAndreas Gohr $types = array_keys(getMimeTypes()); 464bad6fc0dSAndreas Gohr $types = array_map( 46524870174SAndreas Gohr static fn($q) => preg_quote($q, "/"), 466bad6fc0dSAndreas Gohr $types 467bad6fc0dSAndreas Gohr ); 46824870174SAndreas Gohr $regex = implode('|', $types); 4693df72098SAndreas Gohr 4703df72098SAndreas Gohr // because a temp file was created already 471ffb291f2SAdrian Lang if (!preg_match('/\.(' . $regex . ')$/i', $fn)) { 47224870174SAndreas Gohr return [$lang['uploadwrong'], -1]; 473ffb291f2SAdrian Lang } 474ffb291f2SAdrian Lang 4753df72098SAndreas Gohr //check for overwrite 47679e79377SAndreas Gohr $overwrite = file_exists($fn); 477e5d185e1SKate Arzamastseva $auth_ow = (($conf['mediarevisions']) ? AUTH_UPLOAD : AUTH_DELETE); 478e5d185e1SKate Arzamastseva if ($overwrite && (!$ow || $auth < $auth_ow)) { 47924870174SAndreas Gohr return [$lang['uploadexist'], 0]; 4803df72098SAndreas Gohr } 4818cb1eb01SAndreas Gohr // check for valid content 482ffb291f2SAdrian Lang $ok = media_contentcheck($file['name'], $file['mime']); 4838cb1eb01SAndreas Gohr if ($ok == -1) { 48424870174SAndreas Gohr return [sprintf($lang['uploadbadcontent'], '.' . $file['ext']), -1]; 4858cb1eb01SAndreas Gohr } elseif ($ok == -2) { 48624870174SAndreas Gohr return [$lang['uploadspam'], -1]; 48726ceae18SAndreas Gohr } elseif ($ok == -3) { 48824870174SAndreas Gohr return [$lang['uploadxss'], -1]; 4898cb1eb01SAndreas Gohr } 4908cb1eb01SAndreas Gohr 49111d9dfa5SMichael Klier // prepare event data 49224870174SAndreas Gohr $data = []; 493ffb291f2SAdrian Lang $data[0] = $file['name']; 49411d9dfa5SMichael Klier $data[1] = $fn; 49511d9dfa5SMichael Klier $data[2] = $id; 496ffb291f2SAdrian Lang $data[3] = $file['mime']; 49799c8d7f2Smichael $data[4] = $overwrite; 498ffb291f2SAdrian Lang $data[5] = $move; 49911d9dfa5SMichael Klier 50011d9dfa5SMichael Klier // trigger event 501cbb44eabSAndreas Gohr return Event::createAndTrigger('MEDIA_UPLOAD_FINISH', $data, '_media_upload_action', true); 50211d9dfa5SMichael Klier} 50311d9dfa5SMichael Klier 50411d9dfa5SMichael Klier/** 50542ea7f44SGerrit Uitslag * Callback adapter for media_upload_finish() triggered by MEDIA_UPLOAD_FINISH 50642ea7f44SGerrit Uitslag * 50711d9dfa5SMichael Klier * @author Michael Klier <chi@chimeric.de> 50842ea7f44SGerrit Uitslag * 50942ea7f44SGerrit Uitslag * @param array $data event data 51042ea7f44SGerrit Uitslag * @return false|array|string 51111d9dfa5SMichael Klier */ 512d868eb89SAndreas Gohrfunction _media_upload_action($data) 513d868eb89SAndreas Gohr{ 51411d9dfa5SMichael Klier // fixme do further sanity tests of given data? 515ffb291f2SAdrian Lang if (is_array($data) && count($data) === 6) { 516ffb291f2SAdrian Lang return media_upload_finish($data[0], $data[1], $data[2], $data[3], $data[4], $data[5]); 51711d9dfa5SMichael Klier } else { 51811d9dfa5SMichael Klier return false; //callback error 51911d9dfa5SMichael Klier } 52011d9dfa5SMichael Klier} 52111d9dfa5SMichael Klier 52211d9dfa5SMichael Klier/** 52311d9dfa5SMichael Klier * Saves an uploaded media file 52411d9dfa5SMichael Klier * 52511d9dfa5SMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 52611d9dfa5SMichael Klier * @author Michael Klier <chi@chimeric.de> 527cbe26ad6SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 52842ea7f44SGerrit Uitslag * 52942ea7f44SGerrit Uitslag * @param string $fn_tmp 53042ea7f44SGerrit Uitslag * @param string $fn 53142ea7f44SGerrit Uitslag * @param string $id media id 53242ea7f44SGerrit Uitslag * @param string $imime mime type 53342ea7f44SGerrit Uitslag * @param bool $overwrite overwrite existing? 53442ea7f44SGerrit Uitslag * @param string $move function name 53542ea7f44SGerrit Uitslag * @return array|string 53611d9dfa5SMichael Klier */ 537d868eb89SAndreas Gohrfunction media_upload_finish($fn_tmp, $fn, $id, $imime, $overwrite, $move = 'move_uploaded_file') 538d868eb89SAndreas Gohr{ 53911d9dfa5SMichael Klier global $conf; 54011d9dfa5SMichael Klier global $lang; 5419c1bd4bcSKate Arzamastseva global $REV; 54211d9dfa5SMichael Klier 543e4f389efSKate Arzamastseva $old = @filemtime($fn); 54479e79377SAndreas Gohr if (!file_exists(mediaFN($id, $old)) && file_exists($fn)) { 545e4f389efSKate Arzamastseva // add old revision to the attic if missing 546cbe26ad6SKate Arzamastseva media_saveOldRevision($id); 547e4f389efSKate Arzamastseva } 548e4f389efSKate Arzamastseva 5493df72098SAndreas Gohr // prepare directory 550cc7d0c94SBen Coburn io_createNamespace($id, 'media'); 55111d9dfa5SMichael Klier 552ac3ed4afSGerrit Uitslag $filesize_old = file_exists($fn) ? filesize($fn) : 0; 553ac3ed4afSGerrit Uitslag 554ffb291f2SAdrian Lang if ($move($fn_tmp, $fn)) { 55523846a98SKate Arzamastseva @clearstatcache(true, $fn); 556dad6764eSKate Arzamastseva $new = @filemtime($fn); 55774400ea5SBen Coburn // Set the correct permission here. 55874400ea5SBen Coburn // Always chmod media because they may be saved with different permissions than expected from the php umask. 55974400ea5SBen Coburn // (Should normally chmod to $conf['fperm'] only if $conf['fperm'] is set.) 56074400ea5SBen Coburn chmod($fn, $conf['fmode']); 5613df72098SAndreas Gohr msg($lang['uploadsucc'], 1); 56283734cddSPhy media_notify($id, $fn, $imime, $old, $new); 56399c8d7f2Smichael // add a log entry to the media changelog 564ac3ed4afSGerrit Uitslag $filesize_new = filesize($fn); 565ac3ed4afSGerrit Uitslag $sizechange = $filesize_new - $filesize_old; 5669c1bd4bcSKate Arzamastseva if ($REV) { 56764159a61SAndreas Gohr addMediaLogEntry( 56864159a61SAndreas Gohr $new, 56964159a61SAndreas Gohr $id, 57064159a61SAndreas Gohr DOKU_CHANGE_TYPE_REVERT, 57164159a61SAndreas Gohr sprintf($lang['restored'], dformat($REV)), 57264159a61SAndreas Gohr $REV, 57364159a61SAndreas Gohr null, 57464159a61SAndreas Gohr $sizechange 57564159a61SAndreas Gohr ); 5769c1bd4bcSKate Arzamastseva } elseif ($overwrite) { 577ac3ed4afSGerrit Uitslag addMediaLogEntry($new, $id, DOKU_CHANGE_TYPE_EDIT, '', '', null, $sizechange); 57899c8d7f2Smichael } else { 579ac3ed4afSGerrit Uitslag addMediaLogEntry($new, $id, DOKU_CHANGE_TYPE_CREATE, $lang['created'], '', null, $sizechange); 58099c8d7f2Smichael } 5813df72098SAndreas Gohr return $id; 5823df72098SAndreas Gohr } else { 58324870174SAndreas Gohr return [$lang['uploadfail'], -1]; 5843df72098SAndreas Gohr } 5853df72098SAndreas Gohr} 5863df72098SAndreas Gohr 5878cb1eb01SAndreas Gohr/** 588cbe26ad6SKate Arzamastseva * Moves the current version of media file to the media_attic 589cbe26ad6SKate Arzamastseva * directory 590cbe26ad6SKate Arzamastseva * 591cbe26ad6SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 59242ea7f44SGerrit Uitslag * 593cbe26ad6SKate Arzamastseva * @param string $id 594cbe26ad6SKate Arzamastseva * @return int - revision date 595e4f389efSKate Arzamastseva */ 596d868eb89SAndreas Gohrfunction media_saveOldRevision($id) 597d868eb89SAndreas Gohr{ 598dbf57c96SKate Arzamastseva global $conf, $lang; 599dbf57c96SKate Arzamastseva 600e4f389efSKate Arzamastseva $oldf = mediaFN($id); 60179e79377SAndreas Gohr if (!file_exists($oldf)) return ''; 602e4f389efSKate Arzamastseva $date = filemtime($oldf); 603e5d185e1SKate Arzamastseva if (!$conf['mediarevisions']) return $date; 604e5d185e1SKate Arzamastseva 605047bad06SGerrit Uitslag $medialog = new MediaChangeLog($id); 606047bad06SGerrit Uitslag if (!$medialog->getRevisionInfo($date)) { 607dbf57c96SKate Arzamastseva // there was an external edit, 608dbf57c96SKate Arzamastseva // there is no log entry for current version of file 609ac3ed4afSGerrit Uitslag $sizechange = filesize($oldf); 61079e79377SAndreas Gohr if (!file_exists(mediaMetaFN($id, '.changes'))) { 611ac3ed4afSGerrit Uitslag addMediaLogEntry($date, $id, DOKU_CHANGE_TYPE_CREATE, $lang['created'], '', null, $sizechange); 612dbf57c96SKate Arzamastseva } else { 613ac3ed4afSGerrit Uitslag $oldRev = $medialog->getRevisions(-1, 1); // from changelog 614ac3ed4afSGerrit Uitslag $oldRev = (int) (empty($oldRev) ? 0 : $oldRev[0]); 615ac3ed4afSGerrit Uitslag $filesize_old = filesize(mediaFN($id, $oldRev)); 61624870174SAndreas Gohr $sizechange -= $filesize_old; 617ac3ed4afSGerrit Uitslag 618ac3ed4afSGerrit Uitslag addMediaLogEntry($date, $id, DOKU_CHANGE_TYPE_EDIT, '', '', null, $sizechange); 619dbf57c96SKate Arzamastseva } 620dbf57c96SKate Arzamastseva } 621dbf57c96SKate Arzamastseva 622e4f389efSKate Arzamastseva $newf = mediaFN($id, $date); 623e4f389efSKate Arzamastseva io_makeFileDir($newf); 624cbe26ad6SKate Arzamastseva if (copy($oldf, $newf)) { 625e4f389efSKate Arzamastseva // Set the correct permission here. 626e4f389efSKate Arzamastseva // Always chmod media because they may be saved with different permissions than expected from the php umask. 627e4f389efSKate Arzamastseva // (Should normally chmod to $conf['fperm'] only if $conf['fperm'] is set.) 628e4f389efSKate Arzamastseva chmod($newf, $conf['fmode']); 629e4f389efSKate Arzamastseva } 630e4f389efSKate Arzamastseva return $date; 631e4f389efSKate Arzamastseva} 632e4f389efSKate Arzamastseva 633e4f389efSKate Arzamastseva/** 6348cb1eb01SAndreas Gohr * This function checks if the uploaded content is really what the 63526ceae18SAndreas Gohr * mimetype says it is. We also do spam checking for text types here. 6368cb1eb01SAndreas Gohr * 6378cb1eb01SAndreas Gohr * We need to do this stuff because we can not rely on the browser 6388cb1eb01SAndreas Gohr * to do this check correctly. Yes, IE is broken as usual. 6398cb1eb01SAndreas Gohr * 6408cb1eb01SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 64126ceae18SAndreas Gohr * @link http://www.splitbrain.org/blog/2007-02/12-internet_explorer_facilitates_cross_site_scripting 6428cb1eb01SAndreas Gohr * @fixme check all 26 magic IE filetypes here? 64342ea7f44SGerrit Uitslag * 64442ea7f44SGerrit Uitslag * @param string $file path to file 64542ea7f44SGerrit Uitslag * @param string $mime mimetype 64642ea7f44SGerrit Uitslag * @return int 6478cb1eb01SAndreas Gohr */ 648d868eb89SAndreas Gohrfunction media_contentcheck($file, $mime) 649d868eb89SAndreas Gohr{ 65026ceae18SAndreas Gohr global $conf; 65126ceae18SAndreas Gohr if ($conf['iexssprotect']) { 65226ceae18SAndreas Gohr $fh = @fopen($file, 'rb'); 65326ceae18SAndreas Gohr if ($fh) { 65426ceae18SAndreas Gohr $bytes = fread($fh, 256); 65526ceae18SAndreas Gohr fclose($fh); 65626ceae18SAndreas Gohr if (preg_match('/<(script|a|img|html|body|iframe)[\s>]/i', $bytes)) { 65742ea7f44SGerrit Uitslag return -3; //XSS: possibly malicious content 65826ceae18SAndreas Gohr } 65926ceae18SAndreas Gohr } 66026ceae18SAndreas Gohr } 6616c16a3a9Sfiwswe if (str_starts_with($mime, 'image/')) { 6628cb1eb01SAndreas Gohr $info = @getimagesize($file); 6638cb1eb01SAndreas Gohr if ($mime == 'image/gif' && $info[2] != 1) { 66442ea7f44SGerrit Uitslag return -1; // uploaded content did not match the file extension 6658cb1eb01SAndreas Gohr } elseif ($mime == 'image/jpeg' && $info[2] != 2) { 6668cb1eb01SAndreas Gohr return -1; 6678cb1eb01SAndreas Gohr } elseif ($mime == 'image/png' && $info[2] != 3) { 6688cb1eb01SAndreas Gohr return -1; 6698cb1eb01SAndreas Gohr } 6708cb1eb01SAndreas Gohr # fixme maybe check other images types as well 6716c16a3a9Sfiwswe } elseif (str_starts_with($mime, 'text/')) { 6728cb1eb01SAndreas Gohr global $TEXT; 6738cb1eb01SAndreas Gohr $TEXT = io_readFile($file); 6748cb1eb01SAndreas Gohr if (checkwordblock()) { 67542ea7f44SGerrit Uitslag return -2; //blocked by the spam blacklist 6768cb1eb01SAndreas Gohr } 6778cb1eb01SAndreas Gohr } 6788cb1eb01SAndreas Gohr return 0; 6798cb1eb01SAndreas Gohr} 6803df72098SAndreas Gohr 6813df72098SAndreas Gohr/** 68275030359SAndreas Gohr * Send a notify mail on uploads 68375030359SAndreas Gohr * 68475030359SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 68542ea7f44SGerrit Uitslag * 68642ea7f44SGerrit Uitslag * @param string $id media id 68742ea7f44SGerrit Uitslag * @param string $file path to file 68842ea7f44SGerrit Uitslag * @param string $mime mime type 68942ea7f44SGerrit Uitslag * @param bool|int $old_rev revision timestamp or false 69075030359SAndreas Gohr */ 691d868eb89SAndreas Gohrfunction media_notify($id, $file, $mime, $old_rev = false, $current_rev = false) 692d868eb89SAndreas Gohr{ 69375030359SAndreas Gohr global $conf; 69479a2d784SGerrit Uitslag if (empty($conf['notify'])) return; //notify enabled? 69575030359SAndreas Gohr 696704a815fSMichael Große $subscription = new MediaSubscriptionSender(); 69779a2d784SGerrit Uitslag $subscription->sendMediaDiff($conf['notify'], 'uploadmail', $id, $old_rev, $current_rev); 69875030359SAndreas Gohr} 69975030359SAndreas Gohr 70075030359SAndreas Gohr/** 7013df72098SAndreas Gohr * List all files in a given Media namespace 70242ea7f44SGerrit Uitslag * 70321d806cdSGerrit Uitslag * @param string $ns namespace 70442ea7f44SGerrit Uitslag * @param null|int $auth permission level 70542ea7f44SGerrit Uitslag * @param string $jump id 70642ea7f44SGerrit Uitslag * @param bool $fullscreenview 7078702de7fSGerrit Uitslag * @param bool|string $sort sorting order, false skips sorting 7083df72098SAndreas Gohr */ 709d868eb89SAndreas Gohrfunction media_filelist($ns, $auth = null, $jump = '', $fullscreenview = false, $sort = false) 710d868eb89SAndreas Gohr{ 7113df72098SAndreas Gohr global $conf; 7123df72098SAndreas Gohr global $lang; 7133df72098SAndreas Gohr $ns = cleanID($ns); 7143df72098SAndreas Gohr 7153df72098SAndreas Gohr // check auth our self if not given (needed for ajax calls) 7163df72098SAndreas Gohr if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 7173df72098SAndreas Gohr 718d9162c6cSKate Arzamastseva if (!$fullscreenview) echo '<h1 id="media__ns">:' . hsc($ns) . '</h1>' . NL; 7193df72098SAndreas Gohr 7203df72098SAndreas Gohr if ($auth < AUTH_READ) { 7213df72098SAndreas Gohr // FIXME: print permission warning here instead? 7223df72098SAndreas Gohr echo '<div class="nothing">' . $lang['nothingfound'] . '</div>' . NL; 72356fe6664SAndreas Gohr } else { 72489274c0dSChristopher Smith if (!$fullscreenview) { 72589274c0dSChristopher Smith media_uploadform($ns, $auth); 72689274c0dSChristopher Smith media_searchform($ns); 72789274c0dSChristopher Smith } 7283df72098SAndreas Gohr 7293df72098SAndreas Gohr $dir = utf8_encodeFN(str_replace(':', '/', $ns)); 73024870174SAndreas Gohr $data = []; 731dccd6b2bSAndreas Gohr search( 732dccd6b2bSAndreas Gohr $data, 733dccd6b2bSAndreas Gohr $conf['mediadir'], 734dccd6b2bSAndreas Gohr 'search_mediafiles', 735dccd6b2bSAndreas Gohr ['showmsg' => true, 'depth' => 1], 736dccd6b2bSAndreas Gohr $dir, 737dccd6b2bSAndreas Gohr 1, 738dccd6b2bSAndreas Gohr $sort 739dccd6b2bSAndreas Gohr ); 7403df72098SAndreas Gohr 7413df72098SAndreas Gohr if (!count($data)) { 7423df72098SAndreas Gohr echo '<div class="nothing">' . $lang['nothingfound'] . '</div>' . NL; 7435b9353faSKate Arzamastseva } else { 7445b9353faSKate Arzamastseva if ($fullscreenview) { 745554a8c9fSAdrian Lang echo '<ul class="' . _media_get_list_type() . '">'; 7465b9353faSKate Arzamastseva } 7475b9353faSKate Arzamastseva foreach ($data as $item) { 7485b9353faSKate Arzamastseva if (!$fullscreenview) { 7494f33babfSAndreas Gohr //FIXME old call: media_printfile($item,$auth,$jump); 75079a2d784SGerrit Uitslag $display = new DisplayRow($item); 7519453716dSAndreas Gohr $display->scrollIntoView($jump == $item->getID()); 7524f33babfSAndreas Gohr $display->show(); 7535b9353faSKate Arzamastseva } else { 7544f33babfSAndreas Gohr //FIXME old call: media_printfile_thumbs($item,$auth,$jump); 7554f33babfSAndreas Gohr echo '<li>'; 75679a2d784SGerrit Uitslag $display = new DisplayTile($item); 7579453716dSAndreas Gohr $display->scrollIntoView($jump == $item->getID()); 7584f33babfSAndreas Gohr $display->show(); 7594f33babfSAndreas Gohr echo '</li>'; 7605b9353faSKate Arzamastseva } 7615b9353faSKate Arzamastseva } 76294add303SAnika Henke if ($fullscreenview) echo '</ul>' . NL; 7633df72098SAndreas Gohr } 76456fe6664SAndreas Gohr } 765d9162c6cSKate Arzamastseva} 766d9162c6cSKate Arzamastseva 767d9162c6cSKate Arzamastseva/** 768d9162c6cSKate Arzamastseva * Prints tabs for files list actions 769d9162c6cSKate Arzamastseva * 770d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 77195b451bcSAdrian Lang * @author Adrian Lang <mail@adrianlang.de> 77295b451bcSAdrian Lang * 773035e07f1SKate Arzamastseva * @param string $selected_tab - opened tab 774d9162c6cSKate Arzamastseva */ 77595b451bcSAdrian Lang 776d868eb89SAndreas Gohrfunction media_tabs_files($selected_tab = '') 777d868eb89SAndreas Gohr{ 778d9162c6cSKate Arzamastseva global $lang; 77924870174SAndreas Gohr $tabs = []; 7807d34963bSAndreas Gohr foreach ( 7817d34963bSAndreas Gohr [ 78224870174SAndreas Gohr 'files' => 'mediaselect', 78395b451bcSAdrian Lang 'upload' => 'media_uploadtab', 78424870174SAndreas Gohr 'search' => 'media_searchtab' 7857d34963bSAndreas Gohr ] as $tab => $caption 7867d34963bSAndreas Gohr ) { 78724870174SAndreas Gohr $tabs[$tab] = [ 78824870174SAndreas Gohr 'href' => media_managerURL(['tab_files' => $tab], '&'), 78924870174SAndreas Gohr 'caption' => $lang[$caption] 79024870174SAndreas Gohr ]; 79195b451bcSAdrian Lang } 792d9162c6cSKate Arzamastseva 79395b451bcSAdrian Lang html_tabs($tabs, $selected_tab); 794d9162c6cSKate Arzamastseva} 795d9162c6cSKate Arzamastseva 796d9162c6cSKate Arzamastseva/** 797d9162c6cSKate Arzamastseva * Prints tabs for files details actions 798d9162c6cSKate Arzamastseva * 799d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 800ebc28e69SAndreas Gohr * @param string $image filename of the current image 801ebc28e69SAndreas Gohr * @param string $selected_tab opened tab 802d9162c6cSKate Arzamastseva */ 803d868eb89SAndreas Gohrfunction media_tabs_details($image, $selected_tab = '') 804d868eb89SAndreas Gohr{ 805e5d185e1SKate Arzamastseva global $lang, $conf; 806d9162c6cSKate Arzamastseva 80724870174SAndreas Gohr $tabs = []; 80824870174SAndreas Gohr $tabs['view'] = [ 80924870174SAndreas Gohr 'href' => media_managerURL(['tab_details' => 'view'], '&'), 81024870174SAndreas Gohr 'caption' => $lang['media_viewtab'] 81124870174SAndreas Gohr ]; 812d9162c6cSKate Arzamastseva 81324870174SAndreas Gohr [, $mime] = mimetype($image); 81479e79377SAndreas Gohr if ($mime == 'image/jpeg' && file_exists(mediaFN($image))) { 81524870174SAndreas Gohr $tabs['edit'] = [ 81624870174SAndreas Gohr 'href' => media_managerURL(['tab_details' => 'edit'], '&'), 81724870174SAndreas Gohr 'caption' => $lang['media_edittab'] 81824870174SAndreas Gohr ]; 819dd9ba38eSKate Arzamastseva } 820e5d185e1SKate Arzamastseva if ($conf['mediarevisions']) { 82124870174SAndreas Gohr $tabs['history'] = [ 82224870174SAndreas Gohr 'href' => media_managerURL(['tab_details' => 'history'], '&'), 82324870174SAndreas Gohr 'caption' => $lang['media_historytab'] 82424870174SAndreas Gohr ]; 825e5d185e1SKate Arzamastseva } 826d9162c6cSKate Arzamastseva 82795b451bcSAdrian Lang html_tabs($tabs, $selected_tab); 828d9162c6cSKate Arzamastseva} 829d9162c6cSKate Arzamastseva 830d9162c6cSKate Arzamastseva/** 831d9162c6cSKate Arzamastseva * Prints options for the tab that displays a list of all files 832d9162c6cSKate Arzamastseva * 833d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 834d9162c6cSKate Arzamastseva */ 835d868eb89SAndreas Gohrfunction media_tab_files_options() 836d868eb89SAndreas Gohr{ 8378108113cSTom N Harris global $lang; 8388108113cSTom N Harris global $INPUT; 839b7e5821dSAndreas Gohr global $ID; 840b960c74fSSatoshi Sahara 841b960c74fSSatoshi Sahara $form = new Form([ 842b960c74fSSatoshi Sahara 'method' => 'get', 843b960c74fSSatoshi Sahara 'action' => wl($ID), 844b960c74fSSatoshi Sahara 'class' => 'options' 845b960c74fSSatoshi Sahara ]); 846b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 847b960c74fSSatoshi Sahara $form->setHiddenField('sectok', null); 848b960c74fSSatoshi Sahara $media_manager_params = media_managerURL([], '', false, true); 84938b2bf35SAnika Henke foreach ($media_manager_params as $pKey => $pVal) { 850b960c74fSSatoshi Sahara $form->setHiddenField($pKey, $pVal); 85138b2bf35SAnika Henke } 8528108113cSTom N Harris if ($INPUT->has('q')) { 853b960c74fSSatoshi Sahara $form->setHiddenField('q', $INPUT->str('q')); 854554a8c9fSAdrian Lang } 855b960c74fSSatoshi Sahara $form->addHTML('<ul>' . NL); 8567d34963bSAndreas Gohr foreach ( 8577d34963bSAndreas Gohr [ 85824870174SAndreas Gohr 'list' => ['listType', ['thumbs', 'rows']], 85924870174SAndreas Gohr 'sort' => ['sortBy', ['name', 'date']] 8607d34963bSAndreas Gohr ] as $group => $content 8617d34963bSAndreas Gohr ) { 862ec88e837SAndreas Gohr $checked = "_media_get_{$group}_type"; 863554a8c9fSAdrian Lang $checked = $checked(); 864d9162c6cSKate Arzamastseva 865b960c74fSSatoshi Sahara $form->addHTML('<li class="' . $content[0] . '">'); 86695b451bcSAdrian Lang foreach ($content[1] as $option) { 86724870174SAndreas Gohr $attrs = []; 868554a8c9fSAdrian Lang if ($checked == $option) { 86995b451bcSAdrian Lang $attrs['checked'] = 'checked'; 87095b451bcSAdrian Lang } 871b960c74fSSatoshi Sahara $radio = $form->addRadioButton( 872b960c74fSSatoshi Sahara $group . '_dwmedia', 873b960c74fSSatoshi Sahara $lang['media_' . $group . '_' . $option] 874b960c74fSSatoshi Sahara )->val($option)->id($content[0] . '__' . $option)->addClass($option); 875b960c74fSSatoshi Sahara $radio->attrs($attrs); 87695b451bcSAdrian Lang } 877b960c74fSSatoshi Sahara $form->addHTML('</li>' . NL); 87895b451bcSAdrian Lang } 879b960c74fSSatoshi Sahara $form->addHTML('<li>'); 880b960c74fSSatoshi Sahara $form->addButton('', $lang['btn_apply'])->attr('type', 'submit'); 881b960c74fSSatoshi Sahara $form->addHTML('</li>' . NL); 882b960c74fSSatoshi Sahara $form->addHTML('</ul>' . NL); 883b960c74fSSatoshi Sahara $form->addTagClose('div'); 88426dfc232SAndreas Gohr echo $form->toHTML(); 885d9162c6cSKate Arzamastseva} 886d9162c6cSKate Arzamastseva 887d9162c6cSKate Arzamastseva/** 88887deddfaSKate Arzamastseva * Returns type of sorting for the list of files in media manager 88987deddfaSKate Arzamastseva * 89087deddfaSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 89142ea7f44SGerrit Uitslag * 89287deddfaSKate Arzamastseva * @return string - sort type 89387deddfaSKate Arzamastseva */ 894d868eb89SAndreas Gohrfunction _media_get_sort_type() 895d868eb89SAndreas Gohr{ 89624870174SAndreas Gohr return _media_get_display_param('sort', ['default' => 'name', 'date']); 89787deddfaSKate Arzamastseva} 898554a8c9fSAdrian Lang 8996ffaeda9SGerrit Uitslag/** 9006ffaeda9SGerrit Uitslag * Returns type of listing for the list of files in media manager 9016ffaeda9SGerrit Uitslag * 9026ffaeda9SGerrit Uitslag * @author Kate Arzamastseva <pshns@ukr.net> 90342ea7f44SGerrit Uitslag * 9046ffaeda9SGerrit Uitslag * @return string - list type 9056ffaeda9SGerrit Uitslag */ 906d868eb89SAndreas Gohrfunction _media_get_list_type() 907d868eb89SAndreas Gohr{ 90824870174SAndreas Gohr return _media_get_display_param('list', ['default' => 'thumbs', 'rows']); 90987deddfaSKate Arzamastseva} 910554a8c9fSAdrian Lang 9116ffaeda9SGerrit Uitslag/** 9126ffaeda9SGerrit Uitslag * Get display parameters 9136ffaeda9SGerrit Uitslag * 9146ffaeda9SGerrit Uitslag * @param string $param name of parameter 9156ffaeda9SGerrit Uitslag * @param array $values allowed values, where default value has index key 'default' 9166ffaeda9SGerrit Uitslag * @return string the parameter value 9176ffaeda9SGerrit Uitslag */ 918d868eb89SAndreas Gohrfunction _media_get_display_param($param, $values) 919d868eb89SAndreas Gohr{ 9208108113cSTom N Harris global $INPUT; 9218108113cSTom N Harris if (in_array($INPUT->str($param), $values)) { 922554a8c9fSAdrian Lang // FIXME: Set cookie 9238108113cSTom N Harris return $INPUT->str($param); 924554a8c9fSAdrian Lang } else { 9253629bc8cSAdrian Lang $val = get_doku_pref($param, $values['default']); 9263629bc8cSAdrian Lang if (!in_array($val, $values)) { 9273629bc8cSAdrian Lang $val = $values['default']; 9283629bc8cSAdrian Lang } 9293629bc8cSAdrian Lang return $val; 930554a8c9fSAdrian Lang } 93187deddfaSKate Arzamastseva} 93287deddfaSKate Arzamastseva 93387deddfaSKate Arzamastseva/** 934d9162c6cSKate Arzamastseva * Prints tab that displays a list of all files 935d9162c6cSKate Arzamastseva * 936d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 93742ea7f44SGerrit Uitslag * 93842ea7f44SGerrit Uitslag * @param string $ns 93942ea7f44SGerrit Uitslag * @param null|int $auth permission level 94042ea7f44SGerrit Uitslag * @param string $jump item id 941d9162c6cSKate Arzamastseva */ 942d868eb89SAndreas Gohrfunction media_tab_files($ns, $auth = null, $jump = '') 943d868eb89SAndreas Gohr{ 944d9162c6cSKate Arzamastseva global $lang; 945d9162c6cSKate Arzamastseva if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 946d9162c6cSKate Arzamastseva 947d9162c6cSKate Arzamastseva if ($auth < AUTH_READ) { 94888a71175SKate Arzamastseva echo '<div class="nothing">' . $lang['media_perm_read'] . '</div>' . NL; 949d9162c6cSKate Arzamastseva } else { 95095b451bcSAdrian Lang media_filelist($ns, $auth, $jump, true, _media_get_sort_type()); 951d9162c6cSKate Arzamastseva } 952d9162c6cSKate Arzamastseva} 953d9162c6cSKate Arzamastseva 954d9162c6cSKate Arzamastseva/** 955d9162c6cSKate Arzamastseva * Prints tab that displays uploading form 956d9162c6cSKate Arzamastseva * 957d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 95842ea7f44SGerrit Uitslag * 95942ea7f44SGerrit Uitslag * @param string $ns 96042ea7f44SGerrit Uitslag * @param null|int $auth permission level 96142ea7f44SGerrit Uitslag * @param string $jump item id 962d9162c6cSKate Arzamastseva */ 963d868eb89SAndreas Gohrfunction media_tab_upload($ns, $auth = null, $jump = '') 964d868eb89SAndreas Gohr{ 965d9162c6cSKate Arzamastseva global $lang; 966d9162c6cSKate Arzamastseva if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 967d9162c6cSKate Arzamastseva 96894add303SAnika Henke echo '<div class="upload">' . NL; 96995b451bcSAdrian Lang if ($auth >= AUTH_UPLOAD) { 97095b451bcSAdrian Lang echo '<p>' . $lang['mediaupload'] . '</p>'; 97195b451bcSAdrian Lang } 972d9162c6cSKate Arzamastseva media_uploadform($ns, $auth, true); 97394add303SAnika Henke echo '</div>' . NL; 974d9162c6cSKate Arzamastseva} 975d9162c6cSKate Arzamastseva 976d9162c6cSKate Arzamastseva/** 977d9162c6cSKate Arzamastseva * Prints tab that displays search form 978d9162c6cSKate Arzamastseva * 979d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 98042ea7f44SGerrit Uitslag * 98142ea7f44SGerrit Uitslag * @param string $ns 98242ea7f44SGerrit Uitslag * @param null|int $auth permission level 983d9162c6cSKate Arzamastseva */ 984d868eb89SAndreas Gohrfunction media_tab_search($ns, $auth = null) 985d868eb89SAndreas Gohr{ 9868108113cSTom N Harris global $INPUT; 987d9162c6cSKate Arzamastseva 9888108113cSTom N Harris $do = $INPUT->str('mediado'); 9898108113cSTom N Harris $query = $INPUT->str('q'); 99094add303SAnika Henke echo '<div class="search">' . NL; 991d9162c6cSKate Arzamastseva 992d9162c6cSKate Arzamastseva media_searchform($ns, $query, true); 9932dba8df4SAdrian Lang if ($do == 'searchlist' || $query) { 99495b451bcSAdrian Lang media_searchlist($query, $ns, $auth, true, _media_get_sort_type()); 99595b451bcSAdrian Lang } 99694add303SAnika Henke echo '</div>' . NL; 997d9162c6cSKate Arzamastseva} 998d9162c6cSKate Arzamastseva 999d9162c6cSKate Arzamastseva/** 1000d9162c6cSKate Arzamastseva * Prints tab that displays mediafile details 1001d9162c6cSKate Arzamastseva * 1002d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1003e0c26282SGerrit Uitslag * 1004e0c26282SGerrit Uitslag * @param string $image media id 1005e0c26282SGerrit Uitslag * @param string $ns 1006e0c26282SGerrit Uitslag * @param null|int $auth permission level 100742ea7f44SGerrit Uitslag * @param string|int $rev revision timestamp or empty string 1008d9162c6cSKate Arzamastseva */ 1009d868eb89SAndreas Gohrfunction media_tab_view($image, $ns, $auth = null, $rev = '') 1010d868eb89SAndreas Gohr{ 1011ebc28e69SAndreas Gohr global $lang; 1012d9162c6cSKate Arzamastseva if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 1013d9162c6cSKate Arzamastseva 1014e136d6ccSKate Arzamastseva if ($image && $auth >= AUTH_READ) { 1015dd9ba38eSKate Arzamastseva $meta = new JpegMeta(mediaFN($image, $rev)); 1016dd9ba38eSKate Arzamastseva media_preview($image, $auth, $rev, $meta); 1017e136d6ccSKate Arzamastseva media_preview_buttons($image, $auth, $rev); 1018dd9ba38eSKate Arzamastseva media_details($image, $auth, $rev, $meta); 1019e136d6ccSKate Arzamastseva } else { 102094add303SAnika Henke echo '<div class="nothing">' . $lang['media_perm_read'] . '</div>' . NL; 1021e136d6ccSKate Arzamastseva } 1022d9162c6cSKate Arzamastseva} 1023d9162c6cSKate Arzamastseva 1024d9162c6cSKate Arzamastseva/** 1025d9162c6cSKate Arzamastseva * Prints tab that displays form for editing mediafile metadata 1026d9162c6cSKate Arzamastseva * 1027d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1028e0c26282SGerrit Uitslag * 1029e0c26282SGerrit Uitslag * @param string $image media id 1030e0c26282SGerrit Uitslag * @param string $ns 1031e0c26282SGerrit Uitslag * @param null|int $auth permission level 1032d9162c6cSKate Arzamastseva */ 1033d868eb89SAndreas Gohrfunction media_tab_edit($image, $ns, $auth = null) 1034d868eb89SAndreas Gohr{ 1035d9162c6cSKate Arzamastseva if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 1036d9162c6cSKate Arzamastseva 10371eeeced2SKate Arzamastseva if ($image) { 103824870174SAndreas Gohr [, $mime] = mimetype($image); 103930fd72fbSKate Arzamastseva if ($mime == 'image/jpeg') media_metaform($image, $auth); 10401eeeced2SKate Arzamastseva } 1041d9162c6cSKate Arzamastseva} 1042d9162c6cSKate Arzamastseva 1043d9162c6cSKate Arzamastseva/** 1044d9162c6cSKate Arzamastseva * Prints tab that displays mediafile revisions 1045d9162c6cSKate Arzamastseva * 1046d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1047e0c26282SGerrit Uitslag * 1048e0c26282SGerrit Uitslag * @param string $image media id 1049e0c26282SGerrit Uitslag * @param string $ns 1050e0c26282SGerrit Uitslag * @param null|int $auth permission level 1051d9162c6cSKate Arzamastseva */ 1052d868eb89SAndreas Gohrfunction media_tab_history($image, $ns, $auth = null) 1053d868eb89SAndreas Gohr{ 1054d9162c6cSKate Arzamastseva global $lang; 10558108113cSTom N Harris global $INPUT; 10568108113cSTom N Harris 1057d9162c6cSKate Arzamastseva if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 10588108113cSTom N Harris $do = $INPUT->str('mediado'); 1059d9162c6cSKate Arzamastseva 10602e55802cSKate Arzamastseva if ($auth >= AUTH_READ && $image) { 10612e55802cSKate Arzamastseva if ($do == 'diff') { 106224870174SAndreas Gohr (new MediaDiff($image))->show(); //media_diff($image, $ns, $auth); 10632e55802cSKate Arzamastseva } else { 1064a46cc3dcSAndreas Gohr $first = $INPUT->int('first', -1); 106524870174SAndreas Gohr (new MediaRevisions($image))->show($first); 10662e55802cSKate Arzamastseva } 106788a71175SKate Arzamastseva } else { 106888a71175SKate Arzamastseva echo '<div class="nothing">' . $lang['media_perm_read'] . '</div>' . NL; 10692e55802cSKate Arzamastseva } 10703df72098SAndreas Gohr} 10713df72098SAndreas Gohr 10723df72098SAndreas Gohr/** 10731eeeced2SKate Arzamastseva * Prints mediafile details 10741eeeced2SKate Arzamastseva * 10756ffaeda9SGerrit Uitslag * @param string $image media id 1076e0c26282SGerrit Uitslag * @param int $auth permission level 107759bc3b48SGerrit Uitslag * @param int|string $rev revision timestamp or empty string 10786ffaeda9SGerrit Uitslag * @param JpegMeta|bool $meta 107942ea7f44SGerrit Uitslag * 10801eeeced2SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 10811eeeced2SKate Arzamastseva */ 1082d868eb89SAndreas Gohrfunction media_preview($image, $auth, $rev = '', $meta = false) 1083d868eb89SAndreas Gohr{ 1084e136d6ccSKate Arzamastseva 1085e136d6ccSKate Arzamastseva $size = media_image_preview_size($image, $rev, $meta); 1086e136d6ccSKate Arzamastseva 1087e136d6ccSKate Arzamastseva if ($size) { 108859f3611bSAnika Henke global $lang; 108994add303SAnika Henke echo '<div class="image">'; 109094add303SAnika Henke 109124870174SAndreas Gohr $more = []; 1092e136d6ccSKate Arzamastseva if ($rev) { 10935b9353faSKate Arzamastseva $more['rev'] = $rev; 1094e136d6ccSKate Arzamastseva } else { 1095e136d6ccSKate Arzamastseva $t = @filemtime(mediaFN($image)); 10965b9353faSKate Arzamastseva $more['t'] = $t; 109788a71175SKate Arzamastseva } 109823786fd7SKate Arzamastseva 10995b9353faSKate Arzamastseva $more['w'] = $size[0]; 11005b9353faSKate Arzamastseva $more['h'] = $size[1]; 1101e136d6ccSKate Arzamastseva $src = ml($image, $more); 110259f3611bSAnika Henke 110359f3611bSAnika Henke echo '<a href="' . $src . '" target="_blank" title="' . $lang['mediaview'] . '">'; 110495b451bcSAdrian Lang echo '<img src="' . $src . '" alt="" style="max-width: ' . $size[0] . 'px;" />'; 110559f3611bSAnika Henke echo '</a>'; 1106e136d6ccSKate Arzamastseva 1107871895a7SSatoshi Sahara echo '</div>'; 110894add303SAnika Henke } 1109e136d6ccSKate Arzamastseva} 1110e136d6ccSKate Arzamastseva 1111e136d6ccSKate Arzamastseva/** 1112e136d6ccSKate Arzamastseva * Prints mediafile action buttons 1113e136d6ccSKate Arzamastseva * 1114e136d6ccSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1115e0c26282SGerrit Uitslag * 1116e0c26282SGerrit Uitslag * @param string $image media id 1117e0c26282SGerrit Uitslag * @param int $auth permission level 1118871895a7SSatoshi Sahara * @param int|string $rev revision timestamp, or empty string 1119e136d6ccSKate Arzamastseva */ 1120d868eb89SAndreas Gohrfunction media_preview_buttons($image, $auth, $rev = '') 1121d868eb89SAndreas Gohr{ 1122e5d185e1SKate Arzamastseva global $lang, $conf; 1123e136d6ccSKate Arzamastseva 1124871895a7SSatoshi Sahara echo '<ul class="actions">'; 11251eeeced2SKate Arzamastseva 112679e79377SAndreas Gohr if ($auth >= AUTH_DELETE && !$rev && file_exists(mediaFN($image))) { 1127e136d6ccSKate Arzamastseva // delete button 1128b960c74fSSatoshi Sahara $form = new Form([ 1129b960c74fSSatoshi Sahara 'id' => 'mediamanager__btn_delete', 1130b960c74fSSatoshi Sahara 'action' => media_managerURL(['delete' => $image], '&'), 1131b960c74fSSatoshi Sahara ]); 1132b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1133b960c74fSSatoshi Sahara $form->addButton('', $lang['btn_delete'])->attr('type', 'submit'); 1134b960c74fSSatoshi Sahara $form->addTagClose('div'); 113595b451bcSAdrian Lang echo '<li>'; 1136b960c74fSSatoshi Sahara echo $form->toHTML(); 1137871895a7SSatoshi Sahara echo '</li>'; 1138e5d185e1SKate Arzamastseva } 1139e5d185e1SKate Arzamastseva 1140e5d185e1SKate Arzamastseva $auth_ow = (($conf['mediarevisions']) ? AUTH_UPLOAD : AUTH_DELETE); 1141e5d185e1SKate Arzamastseva if ($auth >= $auth_ow && !$rev) { 1142e136d6ccSKate Arzamastseva // upload new version button 1143b960c74fSSatoshi Sahara $form = new Form([ 1144b960c74fSSatoshi Sahara 'id' => 'mediamanager__btn_update', 1145b960c74fSSatoshi Sahara 'action' => media_managerURL(['image' => $image, 'mediado' => 'update'], '&'), 1146b960c74fSSatoshi Sahara ]); 1147b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1148b960c74fSSatoshi Sahara $form->addButton('', $lang['media_update'])->attr('type', 'submit'); 1149b960c74fSSatoshi Sahara $form->addTagClose('div'); 115095b451bcSAdrian Lang echo '<li>'; 1151b960c74fSSatoshi Sahara echo $form->toHTML(); 1152871895a7SSatoshi Sahara echo '</li>'; 115370c3cc9aSKate Arzamastseva } 1154e136d6ccSKate Arzamastseva 115579e79377SAndreas Gohr if ($auth >= AUTH_UPLOAD && $rev && $conf['mediarevisions'] && file_exists(mediaFN($image, $rev))) { 1156e136d6ccSKate Arzamastseva // restore button 1157b960c74fSSatoshi Sahara $form = new Form([ 1158b960c74fSSatoshi Sahara 'id' => 'mediamanager__btn_restore', 1159b960c74fSSatoshi Sahara 'action' => media_managerURL(['image' => $image], '&'), 1160b960c74fSSatoshi Sahara ]); 1161b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1162b960c74fSSatoshi Sahara $form->setHiddenField('mediado', 'restore'); 1163b960c74fSSatoshi Sahara $form->setHiddenField('rev', $rev); 1164b960c74fSSatoshi Sahara $form->addButton('', $lang['media_restore'])->attr('type', 'submit'); 1165b960c74fSSatoshi Sahara $form->addTagClose('div'); 116695b451bcSAdrian Lang echo '<li>'; 1167b960c74fSSatoshi Sahara echo $form->toHTML(); 1168871895a7SSatoshi Sahara echo '</li>'; 11699c1bd4bcSKate Arzamastseva } 1170e136d6ccSKate Arzamastseva 1171871895a7SSatoshi Sahara echo '</ul>'; 11722e55802cSKate Arzamastseva} 11732e55802cSKate Arzamastseva 11742e55802cSKate Arzamastseva/** 1175fa8e5c77SKate Arzamastseva * Returns image width and height for mediamanager preview panel 1176fa8e5c77SKate Arzamastseva * 1177fa8e5c77SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1178fa8e5c77SKate Arzamastseva * @param string $image 1179e0c26282SGerrit Uitslag * @param int|string $rev 118059bc3b48SGerrit Uitslag * @param JpegMeta|bool $meta 1181ebc28e69SAndreas Gohr * @param int $size 1182871895a7SSatoshi Sahara * @return array 1183fa8e5c77SKate Arzamastseva */ 1184d868eb89SAndreas Gohrfunction media_image_preview_size($image, $rev, $meta = false, $size = 500) 1185d868eb89SAndreas Gohr{ 11867d34963bSAndreas Gohr if ( 11877d34963bSAndreas Gohr !preg_match("/\.(jpe?g|gif|png)$/", $image) 1188871895a7SSatoshi Sahara || !file_exists($filename = mediaFN($image, $rev)) 118924870174SAndreas Gohr ) return []; 1190fa8e5c77SKate Arzamastseva 1191871895a7SSatoshi Sahara $info = getimagesize($filename); 119224870174SAndreas Gohr $w = $info[0]; 119324870174SAndreas Gohr $h = $info[1]; 1194fa8e5c77SKate Arzamastseva 1195fa8e5c77SKate Arzamastseva if ($meta && ($w > $size || $h > $size)) { 1196fa8e5c77SKate Arzamastseva $ratio = $meta->getResizeRatio($size, $size); 1197fa8e5c77SKate Arzamastseva $w = floor($w * $ratio); 1198fa8e5c77SKate Arzamastseva $h = floor($h * $ratio); 1199fa8e5c77SKate Arzamastseva } 120024870174SAndreas Gohr return [$w, $h]; 1201fa8e5c77SKate Arzamastseva} 1202fa8e5c77SKate Arzamastseva 1203fa8e5c77SKate Arzamastseva/** 1204fa8e5c77SKate Arzamastseva * Returns the requested EXIF/IPTC tag from the image meta 1205fa8e5c77SKate Arzamastseva * 1206fa8e5c77SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1207e0c26282SGerrit Uitslag * 120842ea7f44SGerrit Uitslag * @param array $tags array with tags, first existing is returned 1209fa8e5c77SKate Arzamastseva * @param JpegMeta $meta 121042ea7f44SGerrit Uitslag * @param string $alt alternative value 1211fa8e5c77SKate Arzamastseva * @return string 1212fa8e5c77SKate Arzamastseva */ 1213d868eb89SAndreas Gohrfunction media_getTag($tags, $meta = false, $alt = '') 1214d868eb89SAndreas Gohr{ 1215871895a7SSatoshi Sahara if (!$meta) return $alt; 1216fa8e5c77SKate Arzamastseva $info = $meta->getField($tags); 1217871895a7SSatoshi Sahara if (!$info) return $alt; 1218fa8e5c77SKate Arzamastseva return $info; 1219fa8e5c77SKate Arzamastseva} 1220fa8e5c77SKate Arzamastseva 1221fa8e5c77SKate Arzamastseva/** 1222e136d6ccSKate Arzamastseva * Returns mediafile tags 12232e55802cSKate Arzamastseva * 12242e55802cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1225e0c26282SGerrit Uitslag * 1226e136d6ccSKate Arzamastseva * @param JpegMeta $meta 122742ea7f44SGerrit Uitslag * @return array list of tags of the mediafile 12282e55802cSKate Arzamastseva */ 1229d868eb89SAndreas Gohrfunction media_file_tags($meta) 1230d868eb89SAndreas Gohr{ 1231532850edSKate Arzamastseva // load the field descriptions 12323e98e685SKate Arzamastseva static $fields = null; 12333e98e685SKate Arzamastseva if (is_null($fields)) { 12343e98e685SKate Arzamastseva $config_files = getConfigFiles('mediameta'); 12353e98e685SKate Arzamastseva foreach ($config_files as $config_file) { 123679e79377SAndreas Gohr if (file_exists($config_file)) include($config_file); 1237532850edSKate Arzamastseva } 1238532850edSKate Arzamastseva } 12391eeeced2SKate Arzamastseva 124024870174SAndreas Gohr $tags = []; 1241dd9ba38eSKate Arzamastseva 124224870174SAndreas Gohr foreach ($fields as $tag) { 124324870174SAndreas Gohr $t = []; 124424870174SAndreas Gohr if (!empty($tag[0])) $t = [$tag[0]]; 12450e80bb5eSChristopher Smith if (isset($tag[3]) && is_array($tag[3])) $t = array_merge($t, $tag[3]); 1246e136d6ccSKate Arzamastseva $value = media_getTag($t, $meta); 124724870174SAndreas Gohr $tags[] = ['tag' => $tag, 'value' => $value]; 1248e136d6ccSKate Arzamastseva } 1249e136d6ccSKate Arzamastseva 1250e136d6ccSKate Arzamastseva return $tags; 1251e136d6ccSKate Arzamastseva} 1252e136d6ccSKate Arzamastseva 1253e136d6ccSKate Arzamastseva/** 1254e136d6ccSKate Arzamastseva * Prints mediafile tags 1255e136d6ccSKate Arzamastseva * 1256e136d6ccSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 125742ea7f44SGerrit Uitslag * 1258e0c26282SGerrit Uitslag * @param string $image image id 1259e0c26282SGerrit Uitslag * @param int $auth permission level 1260e0c26282SGerrit Uitslag * @param string|int $rev revision timestamp, or empty string 1261e0c26282SGerrit Uitslag * @param bool|JpegMeta $meta image object, or create one if false 1262e0c26282SGerrit Uitslag */ 1263d868eb89SAndreas Gohrfunction media_details($image, $auth, $rev = '', $meta = false) 1264d868eb89SAndreas Gohr{ 1265e136d6ccSKate Arzamastseva global $lang; 1266e136d6ccSKate Arzamastseva 1267e136d6ccSKate Arzamastseva if (!$meta) $meta = new JpegMeta(mediaFN($image, $rev)); 1268e136d6ccSKate Arzamastseva $tags = media_file_tags($meta); 1269e136d6ccSKate Arzamastseva 127094add303SAnika Henke echo '<dl>' . NL; 1271e136d6ccSKate Arzamastseva foreach ($tags as $tag) { 1272e136d6ccSKate Arzamastseva if ($tag['value']) { 1273e136d6ccSKate Arzamastseva $value = cleanText($tag['value']); 1274fde860beSGerrit Uitslag echo '<dt>' . $lang[$tag['tag'][1]] . '</dt><dd>'; 1275e136d6ccSKate Arzamastseva if ($tag['tag'][2] == 'date') echo dformat($value); 12763e98e685SKate Arzamastseva else echo hsc($value); 127794add303SAnika Henke echo '</dd>' . NL; 12781eeeced2SKate Arzamastseva } 1279e136d6ccSKate Arzamastseva } 128094add303SAnika Henke echo '</dl>' . NL; 128122e68399Sflammy echo '<dl>' . NL; 128222e68399Sflammy echo '<dt>' . $lang['reference'] . ':</dt>'; 128322e68399Sflammy $media_usage = ft_mediause($image, true); 128424870174SAndreas Gohr if ($media_usage !== []) { 128522e68399Sflammy foreach ($media_usage as $path) { 128622e68399Sflammy echo '<dd>' . html_wikilink($path) . '</dd>'; 128722e68399Sflammy } 128822e68399Sflammy } else { 128922e68399Sflammy echo '<dd>' . $lang['nothingfound'] . '</dd>'; 129022e68399Sflammy } 129122e68399Sflammy echo '</dl>' . NL; 12921eeeced2SKate Arzamastseva} 12932e55802cSKate Arzamastseva 12942e55802cSKate Arzamastseva/** 12952e55802cSKate Arzamastseva * Shows difference between two revisions of file 12962e55802cSKate Arzamastseva * 12972e55802cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 129842ea7f44SGerrit Uitslag * 1299e0c26282SGerrit Uitslag * @param string $image image id 1300e0c26282SGerrit Uitslag * @param string $ns 1301e0c26282SGerrit Uitslag * @param int $auth permission level 1302e0c26282SGerrit Uitslag * @param bool $fromajax 130379a2d784SGerrit Uitslag * 1304297071beSSatoshi Sahara * @deprecated 2020-12-31 1305e0c26282SGerrit Uitslag */ 1306d868eb89SAndreas Gohrfunction media_diff($image, $ns, $auth, $fromajax = false) 1307d868eb89SAndreas Gohr{ 130879a2d784SGerrit Uitslag dbg_deprecated('see ' . MediaDiff::class . '::show()'); 130959e81a43SKate Arzamastseva} 131059e81a43SKate Arzamastseva 13116ffaeda9SGerrit Uitslag/** 13126ffaeda9SGerrit Uitslag * Callback for media file diff 13136ffaeda9SGerrit Uitslag * 131442ea7f44SGerrit Uitslag * @param array $data event data 131579a2d784SGerrit Uitslag * 1316297071beSSatoshi Sahara * @deprecated 2020-12-31 13176ffaeda9SGerrit Uitslag */ 1318d868eb89SAndreas Gohrfunction _media_file_diff($data) 1319d868eb89SAndreas Gohr{ 132079a2d784SGerrit Uitslag dbg_deprecated('see ' . MediaDiff::class . '::show()'); 132159e81a43SKate Arzamastseva} 132259e81a43SKate Arzamastseva 132359e81a43SKate Arzamastseva/** 132459e81a43SKate Arzamastseva * Shows difference between two revisions of image 132559e81a43SKate Arzamastseva * 132659e81a43SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1327e0c26282SGerrit Uitslag * 1328e0c26282SGerrit Uitslag * @param string $image 1329e0c26282SGerrit Uitslag * @param string|int $l_rev revision timestamp, or empty string 1330e0c26282SGerrit Uitslag * @param string|int $r_rev revision timestamp, or empty string 1331e0c26282SGerrit Uitslag * @param string $ns 1332e0c26282SGerrit Uitslag * @param int $auth permission level 1333e0c26282SGerrit Uitslag * @param bool $fromajax 1334297071beSSatoshi Sahara * @deprecated 2020-12-31 133559e81a43SKate Arzamastseva */ 1336d868eb89SAndreas Gohrfunction media_file_diff($image, $l_rev, $r_rev, $ns, $auth, $fromajax) 1337d868eb89SAndreas Gohr{ 133879a2d784SGerrit Uitslag dbg_deprecated('see ' . MediaDiff::class . '::showFileDiff()'); 1339e136d6ccSKate Arzamastseva} 1340e136d6ccSKate Arzamastseva 1341e136d6ccSKate Arzamastseva/** 1342e136d6ccSKate Arzamastseva * Prints two images side by side 1343fa8e5c77SKate Arzamastseva * and slider 1344e136d6ccSKate Arzamastseva * 1345e136d6ccSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 134642ea7f44SGerrit Uitslag * 134742ea7f44SGerrit Uitslag * @param string $image image id 1348e0c26282SGerrit Uitslag * @param int $l_rev revision timestamp, or empty string 1349e0c26282SGerrit Uitslag * @param int $r_rev revision timestamp, or empty string 135042ea7f44SGerrit Uitslag * @param array $l_size array with width and height 135142ea7f44SGerrit Uitslag * @param array $r_size array with width and height 135250fc55feSKate Arzamastseva * @param string $type 1353297071beSSatoshi Sahara * @deprecated 2020-12-31 1354e136d6ccSKate Arzamastseva */ 1355d868eb89SAndreas Gohrfunction media_image_diff($image, $l_rev, $r_rev, $l_size, $r_size, $type) 1356d868eb89SAndreas Gohr{ 135779a2d784SGerrit Uitslag dbg_deprecated('see ' . MediaDiff::class . '::showImageDiff()'); 13581eeeced2SKate Arzamastseva} 13591eeeced2SKate Arzamastseva 13601eeeced2SKate Arzamastseva/** 13619c1bd4bcSKate Arzamastseva * Restores an old revision of a media file 13629c1bd4bcSKate Arzamastseva * 136342ea7f44SGerrit Uitslag * @param string $image media id 136442ea7f44SGerrit Uitslag * @param int $rev revision timestamp or empty string 13659c1bd4bcSKate Arzamastseva * @param int $auth 13669c1bd4bcSKate Arzamastseva * @return string - file's id 136742ea7f44SGerrit Uitslag * 13689c1bd4bcSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 13699c1bd4bcSKate Arzamastseva */ 1370d868eb89SAndreas Gohrfunction media_restore($image, $rev, $auth) 1371d868eb89SAndreas Gohr{ 1372e5d185e1SKate Arzamastseva global $conf; 137380525638SKate Arzamastseva if ($auth < AUTH_UPLOAD || !$conf['mediarevisions']) return false; 137492cac9a9SKate Arzamastseva $removed = (!file_exists(mediaFN($image)) && file_exists(mediaMetaFN($image, '.changes'))); 137592cac9a9SKate Arzamastseva if (!$image || (!file_exists(mediaFN($image)) && !$removed)) return false; 13769c1bd4bcSKate Arzamastseva if (!$rev || !file_exists(mediaFN($image, $rev))) return false; 137724870174SAndreas Gohr [, $imime, ] = mimetype($image); 1378dccd6b2bSAndreas Gohr $res = media_upload_finish( 1379dccd6b2bSAndreas Gohr mediaFN($image, $rev), 13809c1bd4bcSKate Arzamastseva mediaFN($image), 13819c1bd4bcSKate Arzamastseva $image, 13829c1bd4bcSKate Arzamastseva $imime, 13839c1bd4bcSKate Arzamastseva true, 1384dccd6b2bSAndreas Gohr 'copy' 1385dccd6b2bSAndreas Gohr ); 13869c1bd4bcSKate Arzamastseva if (is_array($res)) { 13879c1bd4bcSKate Arzamastseva msg($res[0], $res[1]); 13889c1bd4bcSKate Arzamastseva return false; 13899c1bd4bcSKate Arzamastseva } 13909c1bd4bcSKate Arzamastseva return $res; 13919c1bd4bcSKate Arzamastseva} 13929c1bd4bcSKate Arzamastseva 13939c1bd4bcSKate Arzamastseva/** 1394bf1f3ac4Ssarnowski * List all files found by the search request 1395c9f56829SAndreas Gohr * 1396c9f56829SAndreas Gohr * @author Tobias Sarnowski <sarnowski@cosmocode.de> 1397c9f56829SAndreas Gohr * @author Andreas Gohr <gohr@cosmocode.de> 1398d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1399c9f56829SAndreas Gohr * @triggers MEDIA_SEARCH 1400e0c26282SGerrit Uitslag * 1401e0c26282SGerrit Uitslag * @param string $query 1402e0c26282SGerrit Uitslag * @param string $ns 1403e0c26282SGerrit Uitslag * @param null|int $auth 1404e0c26282SGerrit Uitslag * @param bool $fullscreen 1405e0c26282SGerrit Uitslag * @param string $sort 1406bf1f3ac4Ssarnowski */ 1407d868eb89SAndreas Gohrfunction media_searchlist($query, $ns, $auth = null, $fullscreen = false, $sort = 'natural') 1408d868eb89SAndreas Gohr{ 1409bf1f3ac4Ssarnowski global $conf; 1410bf1f3ac4Ssarnowski global $lang; 14118e69fd30SKate Arzamastseva 1412bf1f3ac4Ssarnowski $ns = cleanID($ns); 141324870174SAndreas Gohr $evdata = [ 141456fe6664SAndreas Gohr 'ns' => $ns, 141524870174SAndreas Gohr 'data' => [], 141656fe6664SAndreas Gohr 'query' => $query 141724870174SAndreas Gohr ]; 14187ed31746SSzymon Olewniczak if (!blank($query)) { 1419e1d9dcc8SAndreas Gohr $evt = new Event('MEDIA_SEARCH', $evdata); 1420bf1f3ac4Ssarnowski if ($evt->advise_before()) { 142156fe6664SAndreas Gohr $dir = utf8_encodeFN(str_replace(':', '/', $evdata['ns'])); 142276472096SSzymon Olewniczak $quoted = preg_quote($evdata['query'], '/'); 142376472096SSzymon Olewniczak //apply globbing 142424870174SAndreas Gohr $quoted = str_replace(['\*', '\?'], ['.*', '.'], $quoted, $count); 142523e31e76SSzymon Olewniczak 142623e31e76SSzymon Olewniczak //if we use globbing file name must match entirely but may be preceded by arbitrary namespace 142723e31e76SSzymon Olewniczak if ($count > 0) $quoted = '^([^:]*:)*' . $quoted . '$'; 142823e31e76SSzymon Olewniczak 142976472096SSzymon Olewniczak $pattern = '/' . $quoted . '/i'; 1430dccd6b2bSAndreas Gohr search( 1431dccd6b2bSAndreas Gohr $evdata['data'], 143256fe6664SAndreas Gohr $conf['mediadir'], 14334f33babfSAndreas Gohr 'search_mediafiles', 143424870174SAndreas Gohr ['showmsg' => false, 'pattern' => $pattern], 143500e3e394SChristopher Smith $dir, 143600e3e394SChristopher Smith 1, 1437dccd6b2bSAndreas Gohr $sort 1438dccd6b2bSAndreas Gohr ); 1439bf1f3ac4Ssarnowski } 1440bf1f3ac4Ssarnowski $evt->advise_after(); 1441bf1f3ac4Ssarnowski unset($evt); 144256fe6664SAndreas Gohr } 1443bf1f3ac4Ssarnowski 1444d9162c6cSKate Arzamastseva if (!$fullscreen) { 144556fe6664SAndreas Gohr echo '<h1 id="media__ns">' . sprintf($lang['searchmedia_in'], hsc($ns) . ':*') . '</h1>' . NL; 144656fe6664SAndreas Gohr media_searchform($ns, $query); 1447d9162c6cSKate Arzamastseva } 144856fe6664SAndreas Gohr 144956fe6664SAndreas Gohr if (!count($evdata['data'])) { 1450bf1f3ac4Ssarnowski echo '<div class="nothing">' . $lang['nothingfound'] . '</div>' . NL; 14515b9353faSKate Arzamastseva } else { 14525b9353faSKate Arzamastseva if ($fullscreen) { 1453554a8c9fSAdrian Lang echo '<ul class="' . _media_get_list_type() . '">'; 14545b9353faSKate Arzamastseva } 14555b9353faSKate Arzamastseva foreach ($evdata['data'] as $item) { 14564f33babfSAndreas Gohr if (!$fullscreen) { 14574f33babfSAndreas Gohr // FIXME old call: media_printfile($item,$item['perm'],'',true); 145879a2d784SGerrit Uitslag $display = new DisplayRow($item); 145979b00823SAndreas Gohr $display->relativeDisplay($ns); 14604f33babfSAndreas Gohr $display->show(); 14614f33babfSAndreas Gohr } else { 14624f33babfSAndreas Gohr // FIXME old call: media_printfile_thumbs($item,$item['perm'],false,true); 146379a2d784SGerrit Uitslag $display = new DisplayTile($item); 146479b00823SAndreas Gohr $display->relativeDisplay($ns); 14654f33babfSAndreas Gohr echo '<li>'; 14664f33babfSAndreas Gohr $display->show(); 14674f33babfSAndreas Gohr echo '</li>'; 14684f33babfSAndreas Gohr } 1469bf1f3ac4Ssarnowski } 147094add303SAnika Henke if ($fullscreen) echo '</ul>' . NL; 14715b9353faSKate Arzamastseva } 1472bf1f3ac4Ssarnowski} 1473bf1f3ac4Ssarnowski 1474bf1f3ac4Ssarnowski/** 1475c6571d58SAndreas Gohr * Display a media icon 1476c6571d58SAndreas Gohr * 147742ea7f44SGerrit Uitslag * @param string $filename media id 1478c6571d58SAndreas Gohr * @param string $size the size subfolder, if not specified 16x16 is used 147942ea7f44SGerrit Uitslag * @return string html 1480c6571d58SAndreas Gohr */ 1481d868eb89SAndreas Gohrfunction media_printicon($filename, $size = '') 1482d868eb89SAndreas Gohr{ 148324870174SAndreas Gohr [$ext] = mimetype(mediaFN($filename), false); 148423786fd7SKate Arzamastseva 148579e79377SAndreas Gohr if (file_exists(DOKU_INC . 'lib/images/fileicons/' . $size . '/' . $ext . '.png')) { 1486c6571d58SAndreas Gohr $icon = DOKU_BASE . 'lib/images/fileicons/' . $size . '/' . $ext . '.png'; 148723786fd7SKate Arzamastseva } else { 1488c6571d58SAndreas Gohr $icon = DOKU_BASE . 'lib/images/fileicons/' . $size . '/file.png'; 148923786fd7SKate Arzamastseva } 149023786fd7SKate Arzamastseva 1491421ec38eSKate Arzamastseva return '<img src="' . $icon . '" alt="' . $filename . '" class="icon" />'; 149223786fd7SKate Arzamastseva} 149323786fd7SKate Arzamastseva 14943df72098SAndreas Gohr/** 149542ea7f44SGerrit Uitslag * Build link based on the current, adding/rewriting parameters 1496d9162c6cSKate Arzamastseva * 1497d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 149842ea7f44SGerrit Uitslag * 1499ebc28e69SAndreas Gohr * @param array|bool $params 150042ea7f44SGerrit Uitslag * @param string $amp separator 150142ea7f44SGerrit Uitslag * @param bool $abs absolute url? 150242ea7f44SGerrit Uitslag * @param bool $params_array return the parmeters array? 150342ea7f44SGerrit Uitslag * @return string|array - link or link parameters 1504d9162c6cSKate Arzamastseva */ 1505d868eb89SAndreas Gohrfunction media_managerURL($params = false, $amp = '&', $abs = false, $params_array = false) 1506d868eb89SAndreas Gohr{ 1507d9162c6cSKate Arzamastseva global $ID; 15088108113cSTom N Harris global $INPUT; 1509d9162c6cSKate Arzamastseva 151024870174SAndreas Gohr $gets = ['do' => 'media']; 151124870174SAndreas Gohr $media_manager_params = ['tab_files', 'tab_details', 'image', 'ns', 'list', 'sort']; 151223846a98SKate Arzamastseva foreach ($media_manager_params as $x) { 15138108113cSTom N Harris if ($INPUT->has($x)) $gets[$x] = $INPUT->str($x); 151423846a98SKate Arzamastseva } 1515d9162c6cSKate Arzamastseva 1516d9162c6cSKate Arzamastseva if ($params) { 1517554a8c9fSAdrian Lang $gets = $params + $gets; 1518d9162c6cSKate Arzamastseva } 1519d9162c6cSKate Arzamastseva unset($gets['id']); 1520554a8c9fSAdrian Lang if (isset($gets['delete'])) { 15211eeeced2SKate Arzamastseva unset($gets['image']); 15221eeeced2SKate Arzamastseva unset($gets['tab_details']); 15231eeeced2SKate Arzamastseva } 1524d9162c6cSKate Arzamastseva 1525035e07f1SKate Arzamastseva if ($params_array) return $gets; 1526035e07f1SKate Arzamastseva 15276dd095f5SKate Arzamastseva return wl($ID, $gets, $abs, $amp); 1528d9162c6cSKate Arzamastseva} 1529d9162c6cSKate Arzamastseva 1530d9162c6cSKate Arzamastseva/** 15313df72098SAndreas Gohr * Print the media upload form if permissions are correct 15323df72098SAndreas Gohr * 15333df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 1534d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1535e0c26282SGerrit Uitslag * 1536e0c26282SGerrit Uitslag * @param string $ns 1537e0c26282SGerrit Uitslag * @param int $auth permission level 1538e0c26282SGerrit Uitslag * @param bool $fullscreen 15393df72098SAndreas Gohr */ 1540d868eb89SAndreas Gohrfunction media_uploadform($ns, $auth, $fullscreen = false) 1541d868eb89SAndreas Gohr{ 15428108113cSTom N Harris global $lang; 15438108113cSTom N Harris global $conf; 15448108113cSTom N Harris global $INPUT; 15453df72098SAndreas Gohr 154688a71175SKate Arzamastseva if ($auth < AUTH_UPLOAD) { 154788a71175SKate Arzamastseva echo '<div class="nothing">' . $lang['media_perm_upload'] . '</div>' . NL; 154888a71175SKate Arzamastseva return; 154988a71175SKate Arzamastseva } 155092cac9a9SKate Arzamastseva $auth_ow = (($conf['mediarevisions']) ? AUTH_UPLOAD : AUTH_DELETE); 15513df72098SAndreas Gohr 155270c3cc9aSKate Arzamastseva $update = false; 155370c3cc9aSKate Arzamastseva $id = ''; 15548108113cSTom N Harris if ($auth >= $auth_ow && $fullscreen && $INPUT->str('mediado') == 'update') { 155570c3cc9aSKate Arzamastseva $update = true; 15568108113cSTom N Harris $id = cleanID($INPUT->str('image')); 155770c3cc9aSKate Arzamastseva } 155870c3cc9aSKate Arzamastseva 1559d00ec455SAndreas Gohr // The default HTML upload form 1560b960c74fSSatoshi Sahara $form = new Form([ 1561b960c74fSSatoshi Sahara 'id' => 'dw__upload', 1562b960c74fSSatoshi Sahara 'enctype' => 'multipart/form-data', 1563b960c74fSSatoshi Sahara 'action' => ($fullscreen) 1564b960c74fSSatoshi Sahara ? media_managerURL(['tab_files' => 'files', 'tab_details' => 'view'], '&') 1565b960c74fSSatoshi Sahara : DOKU_BASE . 'lib/exe/mediamanager.php', 1566b960c74fSSatoshi Sahara ]); 1567b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1568b960c74fSSatoshi Sahara $form->setHiddenField('ns', hsc($ns)); // FIXME hsc required? 1569b960c74fSSatoshi Sahara $form->addTagOpen('p'); 1570b960c74fSSatoshi Sahara $form->addTextInput('upload', $lang['txt_upload'])->id('upload__file') 1571b960c74fSSatoshi Sahara ->attrs(['type' => 'file']); 1572b960c74fSSatoshi Sahara $form->addTagClose('p'); 1573b960c74fSSatoshi Sahara $form->addTagOpen('p'); 1574b960c74fSSatoshi Sahara $form->addTextInput('mediaid', $lang['txt_filename'])->id('upload__name') 1575b960c74fSSatoshi Sahara ->val(noNS($id)); 1576b960c74fSSatoshi Sahara $form->addButton('', $lang['btn_upload'])->attr('type', 'submit'); 1577b960c74fSSatoshi Sahara $form->addTagClose('p'); 157892cac9a9SKate Arzamastseva if ($auth >= $auth_ow) { 1579b960c74fSSatoshi Sahara $form->addTagOpen('p'); 158024870174SAndreas Gohr $attrs = []; 158170c3cc9aSKate Arzamastseva if ($update) $attrs['checked'] = 'checked'; 1582b960c74fSSatoshi Sahara $form->addCheckbox('ow', $lang['txt_overwrt'])->id('dw__ow')->val('1') 1583b960c74fSSatoshi Sahara ->addClass('check')->attrs($attrs); 1584b960c74fSSatoshi Sahara $form->addTagClose('p'); 1585b960c74fSSatoshi Sahara } 1586b960c74fSSatoshi Sahara $form->addTagClose('div'); 1587b960c74fSSatoshi Sahara 1588b960c74fSSatoshi Sahara if (!$fullscreen) { 1589b960c74fSSatoshi Sahara echo '<div class="upload">' . $lang['mediaupload'] . '</div>' . DOKU_LF; 1590b960c74fSSatoshi Sahara } else { 1591b960c74fSSatoshi Sahara echo DOKU_LF; 15923df72098SAndreas Gohr } 1593c472bad9SKate Arzamastseva 1594b960c74fSSatoshi Sahara echo '<div id="mediamanager__uploader">' . DOKU_LF; 1595c6977b3aSSatoshi Sahara echo $form->toHTML('Upload'); 1596b960c74fSSatoshi Sahara echo '</div>' . DOKU_LF; 1597f940e4a0SAndreas Gohr 1598f940e4a0SAndreas Gohr echo '<p class="maxsize">'; 1599f940e4a0SAndreas Gohr printf($lang['maxuploadsize'], filesize_h(media_getuploadsize())); 160056fc6b15SAnna Dabrowska echo ' <a class="allowedmime" href="#">' . $lang['allowedmime'] . '</a>'; 1601499d9bcdSAndreas Gohr echo ' <span>' . implode(', ', array_keys(getMimeTypes())) . '</span>'; 1602b960c74fSSatoshi Sahara echo '</p>' . DOKU_LF; 1603f940e4a0SAndreas Gohr} 1604f940e4a0SAndreas Gohr 1605f940e4a0SAndreas Gohr/** 1606f940e4a0SAndreas Gohr * Returns the size uploaded files may have 1607f940e4a0SAndreas Gohr * 1608f940e4a0SAndreas Gohr * This uses a conservative approach using the lowest number found 1609f940e4a0SAndreas Gohr * in any of the limiting ini settings 1610f940e4a0SAndreas Gohr * 1611f940e4a0SAndreas Gohr * @returns int size in bytes 1612f940e4a0SAndreas Gohr */ 1613d868eb89SAndreas Gohrfunction media_getuploadsize() 1614d868eb89SAndreas Gohr{ 1615f940e4a0SAndreas Gohr $okay = 0; 1616f940e4a0SAndreas Gohr 161724870174SAndreas Gohr $post = php_to_byte(@ini_get('post_max_size')); 161824870174SAndreas Gohr $suho = php_to_byte(@ini_get('suhosin.post.max_value_length')); 161924870174SAndreas Gohr $upld = php_to_byte(@ini_get('upload_max_filesize')); 1620f940e4a0SAndreas Gohr 162124870174SAndreas Gohr if ($post && ($post < $okay || $okay === 0)) $okay = $post; 1622f940e4a0SAndreas Gohr if ($suho && ($suho < $okay || $okay == 0)) $okay = $suho; 1623f940e4a0SAndreas Gohr if ($upld && ($upld < $okay || $okay == 0)) $okay = $upld; 1624f940e4a0SAndreas Gohr 1625f940e4a0SAndreas Gohr return $okay; 16269f5dde7fSMichael Klier} 16273df72098SAndreas Gohr 16283df72098SAndreas Gohr/** 1629bf1f3ac4Ssarnowski * Print the search field form 1630bf1f3ac4Ssarnowski * 1631bf1f3ac4Ssarnowski * @author Tobias Sarnowski <sarnowski@cosmocode.de> 1632d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1633e0c26282SGerrit Uitslag * 1634e0c26282SGerrit Uitslag * @param string $ns 1635e0c26282SGerrit Uitslag * @param string $query 1636e0c26282SGerrit Uitslag * @param bool $fullscreen 1637bf1f3ac4Ssarnowski */ 1638d868eb89SAndreas Gohrfunction media_searchform($ns, $query = '', $fullscreen = false) 1639d868eb89SAndreas Gohr{ 1640bf1f3ac4Ssarnowski global $lang; 1641bf1f3ac4Ssarnowski 1642bf1f3ac4Ssarnowski // The default HTML search form 1643b960c74fSSatoshi Sahara $form = new Form([ 1644b960c74fSSatoshi Sahara 'id' => 'dw__mediasearch', 1645b960c74fSSatoshi Sahara 'action' => ($fullscreen) 1646b960c74fSSatoshi Sahara ? media_managerURL([], '&') 1647b960c74fSSatoshi Sahara : DOKU_BASE . 'lib/exe/mediamanager.php', 1648b960c74fSSatoshi Sahara ]); 1649b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1650b960c74fSSatoshi Sahara $form->setHiddenField('ns', $ns); 1651b960c74fSSatoshi Sahara $form->setHiddenField($fullscreen ? 'mediado' : 'do', 'searchlist'); 1652554a8c9fSAdrian Lang 1653b960c74fSSatoshi Sahara $form->addTagOpen('p'); 1654bde2a644SSatoshi Sahara $form->addTextInput('q', $lang['searchmedia']) 1655b960c74fSSatoshi Sahara ->attr('title', sprintf($lang['searchmedia_in'], hsc($ns) . ':*')) 1656b960c74fSSatoshi Sahara ->val($query); 1657bde2a644SSatoshi Sahara $form->addHTML(' '); 1658b960c74fSSatoshi Sahara $form->addButton('', $lang['btn_search'])->attr('type', 'submit'); 1659b960c74fSSatoshi Sahara $form->addTagClose('p'); 1660b960c74fSSatoshi Sahara $form->addTagClose('div'); 166126dfc232SAndreas Gohr echo $form->toHTML('SearchMedia'); 1662bf1f3ac4Ssarnowski} 1663bf1f3ac4Ssarnowski 1664bf1f3ac4Ssarnowski/** 16653df72098SAndreas Gohr * Build a tree outline of available media namespaces 16663df72098SAndreas Gohr * 16673df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 1668e0c26282SGerrit Uitslag * 1669e0c26282SGerrit Uitslag * @param string $ns 16703df72098SAndreas Gohr */ 1671d868eb89SAndreas Gohrfunction media_nstree($ns) 1672d868eb89SAndreas Gohr{ 16733df72098SAndreas Gohr global $conf; 1674256ca81eSAndreas Gohr global $lang; 16753df72098SAndreas Gohr 16763df72098SAndreas Gohr // currently selected namespace 16773df72098SAndreas Gohr $ns = cleanID($ns); 16783df72098SAndreas Gohr if (empty($ns)) { 1679de3eb1d7SAdrian Lang global $ID; 1680dd90013aSMichael Hamann $ns = (string)getNS($ID); 16813df72098SAndreas Gohr } 1682dd90013aSMichael Hamann 1683dd90013aSMichael Hamann $ns_dir = utf8_encodeFN(str_replace(':', '/', $ns)); 16843df72098SAndreas Gohr 168524870174SAndreas Gohr $data = []; 168624870174SAndreas Gohr search($data, $conf['mediadir'], 'search_index', ['ns' => $ns_dir, 'nofiles' => true]); 16873df72098SAndreas Gohr 16883df72098SAndreas Gohr // wrap a list with the root level around the other namespaces 168924870174SAndreas Gohr array_unshift($data, ['level' => 0, 'id' => '', 'open' => 'true', 'label' => '[' . $lang['mediaroot'] . ']']); 16903df72098SAndreas Gohr 1691dd90013aSMichael Hamann // insert the current ns into the hierarchy if it isn't already part of it 1692dd90013aSMichael Hamann $ns_parts = explode(':', $ns); 1693dd90013aSMichael Hamann $tmp_ns = ''; 1694dd90013aSMichael Hamann $pos = 0; 1695de301a35SDamien Regad $insert = false; 1696dd90013aSMichael Hamann foreach ($ns_parts as $level => $part) { 1697*186263b2SDamien Regad if ($tmp_ns) { 1698*186263b2SDamien Regad $tmp_ns .= ':' . $part; 1699*186263b2SDamien Regad } else { 1700*186263b2SDamien Regad $tmp_ns = $part; 1701*186263b2SDamien Regad } 1702dd90013aSMichael Hamann 1703de301a35SDamien Regad // find the namespace parts 17049988e853SDamien Regad while (array_key_exists($pos, $data) && $data[$pos]['id'] != $tmp_ns) { 170564159a61SAndreas Gohr if ( 170664159a61SAndreas Gohr $pos >= count($data) || 17072d85e841SAndreas Gohr ($data[$pos]['level'] <= $level + 1 && Sort::strcmp($data[$pos]['id'], $tmp_ns) > 0) 170864159a61SAndreas Gohr ) { 1709de301a35SDamien Regad $insert = true; 1710dd90013aSMichael Hamann break; 1711dd90013aSMichael Hamann } 1712dd90013aSMichael Hamann ++$pos; 1713dd90013aSMichael Hamann } 1714de301a35SDamien Regad // insert namespace in hierarchy; if not found in above loop, append it to the end 1715de301a35SDamien Regad if ($insert || $pos == count($data)) { 1716de301a35SDamien Regad array_splice($data, $pos, 0, [['level' => $level + 1, 'id' => $tmp_ns, 'open' => 'true']]); 1717de301a35SDamien Regad } 1718dd90013aSMichael Hamann } 1719dd90013aSMichael Hamann 17203df72098SAndreas Gohr echo html_buildlist($data, 'idx', 'media_nstree_item', 'media_nstree_li'); 17213df72098SAndreas Gohr} 17223df72098SAndreas Gohr 17233df72098SAndreas Gohr/** 17243df72098SAndreas Gohr * Userfunction for html_buildlist 17253df72098SAndreas Gohr * 17263df72098SAndreas Gohr * Prints a media namespace tree item 17273df72098SAndreas Gohr * 17283df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 172942ea7f44SGerrit Uitslag * 173042ea7f44SGerrit Uitslag * @param array $item 173142ea7f44SGerrit Uitslag * @return string html 17323df72098SAndreas Gohr */ 1733d868eb89SAndreas Gohrfunction media_nstree_item($item) 1734d868eb89SAndreas Gohr{ 17358108113cSTom N Harris global $INPUT; 17363df72098SAndreas Gohr $pos = strrpos($item['id'], ':'); 17373df72098SAndreas Gohr $label = substr($item['id'], $pos > 0 ? $pos + 1 : 0); 17380e80bb5eSChristopher Smith if (empty($item['label'])) $item['label'] = $label; 17393df72098SAndreas Gohr 17403df72098SAndreas Gohr $ret = ''; 174124870174SAndreas Gohr if ($INPUT->str('do') != 'media') 17423df72098SAndreas Gohr $ret .= '<a href="' . DOKU_BASE . 'lib/exe/mediamanager.php?ns=' . idfilter($item['id']) . '" class="idx_dir">'; 1743b960c74fSSatoshi Sahara else $ret .= '<a href="' . media_managerURL(['ns' => idfilter($item['id'], false), 'tab_files' => 'files']) 174423846a98SKate Arzamastseva . '" class="idx_dir">'; 17453df72098SAndreas Gohr $ret .= $item['label']; 17463df72098SAndreas Gohr $ret .= '</a>'; 17473df72098SAndreas Gohr return $ret; 17483df72098SAndreas Gohr} 17493df72098SAndreas Gohr 17503df72098SAndreas Gohr/** 17513df72098SAndreas Gohr * Userfunction for html_buildlist 17523df72098SAndreas Gohr * 17533df72098SAndreas Gohr * Prints a media namespace tree item opener 17543df72098SAndreas Gohr * 17553df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 175642ea7f44SGerrit Uitslag * 175742ea7f44SGerrit Uitslag * @param array $item 175842ea7f44SGerrit Uitslag * @return string html 17593df72098SAndreas Gohr */ 1760d868eb89SAndreas Gohrfunction media_nstree_li($item) 1761d868eb89SAndreas Gohr{ 17623df72098SAndreas Gohr $class = 'media level' . $item['level']; 17633df72098SAndreas Gohr if ($item['open']) { 17643df72098SAndreas Gohr $class .= ' open'; 17653df72098SAndreas Gohr $img = DOKU_BASE . 'lib/images/minus.gif'; 1766e260f93bSAnika Henke $alt = '−'; 17673df72098SAndreas Gohr } else { 17683df72098SAndreas Gohr $class .= ' closed'; 17693df72098SAndreas Gohr $img = DOKU_BASE . 'lib/images/plus.gif'; 17707af1b404SAnika Henke $alt = '+'; 17713df72098SAndreas Gohr } 1772231b8c34SPierre Spring // TODO: only deliver an image if it actually has a subtree... 17733df72098SAndreas Gohr return '<li class="' . $class . '">' . 17747af1b404SAnika Henke '<img src="' . $img . '" alt="' . $alt . '" />'; 17753df72098SAndreas Gohr} 177613c08e2fSMichael Klier 177713c08e2fSMichael Klier/** 1778b021f0b4SAndreas Gohr * Resizes or crop the given image to the given size 1779b021f0b4SAndreas Gohr * 1780b021f0b4SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 1781b021f0b4SAndreas Gohr * 1782b021f0b4SAndreas Gohr * @param string $file filename, path to file 1783b021f0b4SAndreas Gohr * @param string $ext extension 1784b021f0b4SAndreas Gohr * @param int $w desired width 1785b021f0b4SAndreas Gohr * @param int $h desired height 1786b021f0b4SAndreas Gohr * @param bool $crop should a center crop be used? 1787b021f0b4SAndreas Gohr * @return string path to resized or original size if failed 1788b021f0b4SAndreas Gohr */ 1789b021f0b4SAndreas Gohrfunction media_mod_image($file, $ext, $w, $h = 0, $crop = false) 1790b021f0b4SAndreas Gohr{ 1791b021f0b4SAndreas Gohr global $conf; 1792d967ecd8SAndreas Gohr if (!$h) $h = 0; 1793b021f0b4SAndreas Gohr // we wont scale up to infinity 1794b021f0b4SAndreas Gohr if ($w > 2000 || $h > 2000) return $file; 1795b021f0b4SAndreas Gohr 1796b021f0b4SAndreas Gohr $operation = $crop ? 'crop' : 'resize'; 1797b021f0b4SAndreas Gohr 1798b021f0b4SAndreas Gohr $options = [ 1799b021f0b4SAndreas Gohr 'quality' => $conf['jpg_quality'], 1800b021f0b4SAndreas Gohr 'imconvert' => $conf['im_convert'], 1801b021f0b4SAndreas Gohr ]; 1802b021f0b4SAndreas Gohr 180324870174SAndreas Gohr $cache = new CacheImageMod($file, $w, $h, $ext, $crop); 1804b021f0b4SAndreas Gohr if (!$cache->useCache()) { 1805b021f0b4SAndreas Gohr try { 1806b021f0b4SAndreas Gohr Slika::run($file, $options) 1807b021f0b4SAndreas Gohr ->autorotate() 1808b021f0b4SAndreas Gohr ->$operation($w, $h) 1809b021f0b4SAndreas Gohr ->save($cache->cache, $ext); 1810b021f0b4SAndreas Gohr if ($conf['fperm']) @chmod($cache->cache, $conf['fperm']); 181124870174SAndreas Gohr } catch (Exception $e) { 1812b021f0b4SAndreas Gohr Logger::debug($e->getMessage()); 1813b021f0b4SAndreas Gohr return $file; 1814b021f0b4SAndreas Gohr } 1815b021f0b4SAndreas Gohr } 1816b021f0b4SAndreas Gohr 1817b021f0b4SAndreas Gohr return $cache->cache; 1818b021f0b4SAndreas Gohr} 1819b021f0b4SAndreas Gohr 1820b021f0b4SAndreas Gohr/** 182113c08e2fSMichael Klier * Resizes the given image to the given size 182213c08e2fSMichael Klier * 182313c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 182442ea7f44SGerrit Uitslag * 182542ea7f44SGerrit Uitslag * @param string $file filename, path to file 182642ea7f44SGerrit Uitslag * @param string $ext extension 182742ea7f44SGerrit Uitslag * @param int $w desired width 182842ea7f44SGerrit Uitslag * @param int $h desired height 182942ea7f44SGerrit Uitslag * @return string path to resized or original size if failed 183013c08e2fSMichael Klier */ 1831b021f0b4SAndreas Gohrfunction media_resize_image($file, $ext, $w, $h = 0) 1832b021f0b4SAndreas Gohr{ 1833b021f0b4SAndreas Gohr return media_mod_image($file, $ext, $w, $h, false); 1834d2bd34a5SAndreas Gohr} 183513c08e2fSMichael Klier 183613c08e2fSMichael Klier/** 1837d2bd34a5SAndreas Gohr * Center crops the given image to the wanted size 183813c08e2fSMichael Klier * 183913c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 184042ea7f44SGerrit Uitslag * 184142ea7f44SGerrit Uitslag * @param string $file filename, path to file 184242ea7f44SGerrit Uitslag * @param string $ext extension 184342ea7f44SGerrit Uitslag * @param int $w desired width 184442ea7f44SGerrit Uitslag * @param int $h desired height 184542ea7f44SGerrit Uitslag * @return string path to resized or original size if failed 184613c08e2fSMichael Klier */ 1847b021f0b4SAndreas Gohrfunction media_crop_image($file, $ext, $w, $h = 0) 1848b021f0b4SAndreas Gohr{ 1849b021f0b4SAndreas Gohr return media_mod_image($file, $ext, $w, $h, true); 185013c08e2fSMichael Klier} 185113c08e2fSMichael Klier 185213c08e2fSMichael Klier/** 18530f4e0092SChristopher Smith * Calculate a token to be used to verify fetch requests for resized or 18540f4e0092SChristopher Smith * cropped images have been internally generated - and prevent external 18550f4e0092SChristopher Smith * DDOS attacks via fetch 18560f4e0092SChristopher Smith * 18573c124064SAndreas Gohr * @author Christopher Smith <chris@jalakai.co.uk> 18583c124064SAndreas Gohr * 18590f4e0092SChristopher Smith * @param string $id id of the image 18600f4e0092SChristopher Smith * @param int $w resize/crop width 18610f4e0092SChristopher Smith * @param int $h resize/crop height 186242ea7f44SGerrit Uitslag * @return string token or empty string if no token required 18630f4e0092SChristopher Smith */ 1864d868eb89SAndreas Gohrfunction media_get_token($id, $w, $h) 1865d868eb89SAndreas Gohr{ 18660f4e0092SChristopher Smith // token is only required for modified images 1867cc036f74SKlap-in if ($w || $h || media_isexternal($id)) { 18683c124064SAndreas Gohr $token = $id; 18690f4e0092SChristopher Smith if ($w) $token .= '.' . $w; 18700f4e0092SChristopher Smith if ($h) $token .= '.' . $h; 18710f4e0092SChristopher Smith 187224870174SAndreas Gohr return substr(PassHash::hmac('md5', $token, auth_cookiesalt()), 0, 6); 18730f4e0092SChristopher Smith } 18740f4e0092SChristopher Smith 18750f4e0092SChristopher Smith return ''; 18760f4e0092SChristopher Smith} 18770f4e0092SChristopher Smith 18780f4e0092SChristopher Smith/** 187913c08e2fSMichael Klier * Download a remote file and return local filename 188013c08e2fSMichael Klier * 188113c08e2fSMichael Klier * returns false if download fails. Uses cached file if available and 188213c08e2fSMichael Klier * wanted 188313c08e2fSMichael Klier * 188413c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 188513c08e2fSMichael Klier * @author Pavel Vitis <Pavel.Vitis@seznam.cz> 188642ea7f44SGerrit Uitslag * 188742ea7f44SGerrit Uitslag * @param string $url 188842ea7f44SGerrit Uitslag * @param string $ext extension 188942ea7f44SGerrit Uitslag * @param int $cache cachetime in seconds 189042ea7f44SGerrit Uitslag * @return false|string path to cached file 189113c08e2fSMichael Klier */ 1892d868eb89SAndreas Gohrfunction media_get_from_URL($url, $ext, $cache) 1893d868eb89SAndreas Gohr{ 189413c08e2fSMichael Klier global $conf; 189513c08e2fSMichael Klier 189613c08e2fSMichael Klier // if no cache or fetchsize just redirect 189713c08e2fSMichael Klier if ($cache == 0) return false; 189813c08e2fSMichael Klier if (!$conf['fetchsize']) return false; 189913c08e2fSMichael Klier 190013c08e2fSMichael Klier $local = getCacheName(strtolower($url), ".media.$ext"); 190113c08e2fSMichael Klier $mtime = @filemtime($local); // 0 if not exists 190213c08e2fSMichael Klier 190313c08e2fSMichael Klier //decide if download needed: 19047d34963bSAndreas Gohr if ( 19057d34963bSAndreas Gohr ($mtime == 0) || // cache does not exist 190613c08e2fSMichael Klier ($cache != -1 && $mtime < time() - $cache) // 'recache' and cache has expired 190713c08e2fSMichael Klier ) { 190813c08e2fSMichael Klier if (media_image_download($url, $local)) { 190913c08e2fSMichael Klier return $local; 191013c08e2fSMichael Klier } else { 191113c08e2fSMichael Klier return false; 191213c08e2fSMichael Klier } 191313c08e2fSMichael Klier } 191413c08e2fSMichael Klier 191513c08e2fSMichael Klier //if cache exists use it else 191613c08e2fSMichael Klier if ($mtime) return $local; 191713c08e2fSMichael Klier 191813c08e2fSMichael Klier //else return false 191913c08e2fSMichael Klier return false; 192013c08e2fSMichael Klier} 192113c08e2fSMichael Klier 192213c08e2fSMichael Klier/** 192313c08e2fSMichael Klier * Download image files 192413c08e2fSMichael Klier * 192513c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 192642ea7f44SGerrit Uitslag * 192742ea7f44SGerrit Uitslag * @param string $url 192842ea7f44SGerrit Uitslag * @param string $file path to file in which to put the downloaded content 192942ea7f44SGerrit Uitslag * @return bool 193013c08e2fSMichael Klier */ 1931d868eb89SAndreas Gohrfunction media_image_download($url, $file) 1932d868eb89SAndreas Gohr{ 193313c08e2fSMichael Klier global $conf; 193413c08e2fSMichael Klier $http = new DokuHTTPClient(); 1935a5951419SAndreas Gohr $http->keep_alive = false; // we do single ops here, no need for keep-alive 1936a5951419SAndreas Gohr 193713c08e2fSMichael Klier $http->max_bodysize = $conf['fetchsize']; 193813c08e2fSMichael Klier $http->timeout = 25; //max. 25 sec 193913c08e2fSMichael Klier $http->header_regexp = '!\r\nContent-Type: image/(jpe?g|gif|png)!i'; 194013c08e2fSMichael Klier 194113c08e2fSMichael Klier $data = $http->get($url); 194213c08e2fSMichael Klier if (!$data) return false; 194313c08e2fSMichael Klier 194479e79377SAndreas Gohr $fileexists = file_exists($file); 194513c08e2fSMichael Klier $fp = @fopen($file, "w"); 194613c08e2fSMichael Klier if (!$fp) return false; 194713c08e2fSMichael Klier fwrite($fp, $data); 194813c08e2fSMichael Klier fclose($fp); 194924870174SAndreas Gohr if (!$fileexists && $conf['fperm']) chmod($file, $conf['fperm']); 195013c08e2fSMichael Klier 195113c08e2fSMichael Klier // check if it is really an image 195213c08e2fSMichael Klier $info = @getimagesize($file); 195313c08e2fSMichael Klier if (!$info) { 195413c08e2fSMichael Klier @unlink($file); 195513c08e2fSMichael Klier return false; 195613c08e2fSMichael Klier } 195713c08e2fSMichael Klier 195813c08e2fSMichael Klier return true; 195913c08e2fSMichael Klier} 196013c08e2fSMichael Klier 196113c08e2fSMichael Klier/** 196213c08e2fSMichael Klier * resize images using external ImageMagick convert program 196313c08e2fSMichael Klier * 196413c08e2fSMichael Klier * @author Pavel Vitis <Pavel.Vitis@seznam.cz> 196513c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 196642ea7f44SGerrit Uitslag * 196742ea7f44SGerrit Uitslag * @param string $ext extension 196842ea7f44SGerrit Uitslag * @param string $from filename path to file 196942ea7f44SGerrit Uitslag * @param int $from_w original width 197042ea7f44SGerrit Uitslag * @param int $from_h original height 197142ea7f44SGerrit Uitslag * @param string $to path to resized file 197242ea7f44SGerrit Uitslag * @param int $to_w desired width 197342ea7f44SGerrit Uitslag * @param int $to_h desired height 197442ea7f44SGerrit Uitslag * @return bool 197513c08e2fSMichael Klier */ 1976d868eb89SAndreas Gohrfunction media_resize_imageIM($ext, $from, $from_w, $from_h, $to, $to_w, $to_h) 1977d868eb89SAndreas Gohr{ 197813c08e2fSMichael Klier global $conf; 197913c08e2fSMichael Klier 198013c08e2fSMichael Klier // check if convert is configured 198113c08e2fSMichael Klier if (!$conf['im_convert']) return false; 198213c08e2fSMichael Klier 198313c08e2fSMichael Klier // prepare command 198413c08e2fSMichael Klier $cmd = $conf['im_convert']; 198513c08e2fSMichael Klier $cmd .= ' -resize ' . $to_w . 'x' . $to_h . '!'; 198613c08e2fSMichael Klier if ($ext == 'jpg' || $ext == 'jpeg') { 198713c08e2fSMichael Klier $cmd .= ' -quality ' . $conf['jpg_quality']; 198813c08e2fSMichael Klier } 198913c08e2fSMichael Klier $cmd .= " $from $to"; 199013c08e2fSMichael Klier 199113c08e2fSMichael Klier @exec($cmd, $out, $retval); 199213c08e2fSMichael Klier if ($retval == 0) return true; 199313c08e2fSMichael Klier return false; 199413c08e2fSMichael Klier} 199513c08e2fSMichael Klier 199613c08e2fSMichael Klier/** 199713c08e2fSMichael Klier * crop images using external ImageMagick convert program 199813c08e2fSMichael Klier * 199913c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 200042ea7f44SGerrit Uitslag * 200142ea7f44SGerrit Uitslag * @param string $ext extension 200242ea7f44SGerrit Uitslag * @param string $from filename path to file 200342ea7f44SGerrit Uitslag * @param int $from_w original width 200442ea7f44SGerrit Uitslag * @param int $from_h original height 200542ea7f44SGerrit Uitslag * @param string $to path to resized file 200642ea7f44SGerrit Uitslag * @param int $to_w desired width 200742ea7f44SGerrit Uitslag * @param int $to_h desired height 200842ea7f44SGerrit Uitslag * @param int $ofs_x offset of crop centre 200942ea7f44SGerrit Uitslag * @param int $ofs_y offset of crop centre 201042ea7f44SGerrit Uitslag * @return bool 2011d2bd34a5SAndreas Gohr * @deprecated 2020-09-01 201213c08e2fSMichael Klier */ 2013d868eb89SAndreas Gohrfunction media_crop_imageIM($ext, $from, $from_w, $from_h, $to, $to_w, $to_h, $ofs_x, $ofs_y) 2014d868eb89SAndreas Gohr{ 201513c08e2fSMichael Klier global $conf; 2016d2bd34a5SAndreas Gohr dbg_deprecated('splitbrain\\Slika'); 201713c08e2fSMichael Klier 201813c08e2fSMichael Klier // check if convert is configured 201913c08e2fSMichael Klier if (!$conf['im_convert']) return false; 202013c08e2fSMichael Klier 202113c08e2fSMichael Klier // prepare command 202213c08e2fSMichael Klier $cmd = $conf['im_convert']; 202313c08e2fSMichael Klier $cmd .= ' -crop ' . $to_w . 'x' . $to_h . '+' . $ofs_x . '+' . $ofs_y; 202413c08e2fSMichael Klier if ($ext == 'jpg' || $ext == 'jpeg') { 202513c08e2fSMichael Klier $cmd .= ' -quality ' . $conf['jpg_quality']; 202613c08e2fSMichael Klier } 202713c08e2fSMichael Klier $cmd .= " $from $to"; 202813c08e2fSMichael Klier 202913c08e2fSMichael Klier @exec($cmd, $out, $retval); 203013c08e2fSMichael Klier if ($retval == 0) return true; 203113c08e2fSMichael Klier return false; 203213c08e2fSMichael Klier} 203313c08e2fSMichael Klier 203413c08e2fSMichael Klier/** 203513c08e2fSMichael Klier * resize or crop images using PHP's libGD support 203613c08e2fSMichael Klier * 203713c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 203813c08e2fSMichael Klier * @author Sebastian Wienecke <s_wienecke@web.de> 203942ea7f44SGerrit Uitslag * 204042ea7f44SGerrit Uitslag * @param string $ext extension 204142ea7f44SGerrit Uitslag * @param string $from filename path to file 204242ea7f44SGerrit Uitslag * @param int $from_w original width 204342ea7f44SGerrit Uitslag * @param int $from_h original height 204442ea7f44SGerrit Uitslag * @param string $to path to resized file 204542ea7f44SGerrit Uitslag * @param int $to_w desired width 204642ea7f44SGerrit Uitslag * @param int $to_h desired height 204742ea7f44SGerrit Uitslag * @param int $ofs_x offset of crop centre 204842ea7f44SGerrit Uitslag * @param int $ofs_y offset of crop centre 204942ea7f44SGerrit Uitslag * @return bool 2050d2bd34a5SAndreas Gohr * @deprecated 2020-09-01 205113c08e2fSMichael Klier */ 2052d868eb89SAndreas Gohrfunction media_resize_imageGD($ext, $from, $from_w, $from_h, $to, $to_w, $to_h, $ofs_x = 0, $ofs_y = 0) 2053d868eb89SAndreas Gohr{ 205413c08e2fSMichael Klier global $conf; 2055d2bd34a5SAndreas Gohr dbg_deprecated('splitbrain\\Slika'); 205613c08e2fSMichael Klier 205713c08e2fSMichael Klier if ($conf['gdlib'] < 1) return false; //no GDlib available or wanted 205813c08e2fSMichael Klier 205913c08e2fSMichael Klier // check available memory 206013c08e2fSMichael Klier if (!is_mem_available(($from_w * $from_h * 4) + ($to_w * $to_h * 4))) { 206113c08e2fSMichael Klier return false; 206213c08e2fSMichael Klier } 206313c08e2fSMichael Klier 206413c08e2fSMichael Klier // create an image of the given filetype 206559bc3b48SGerrit Uitslag $image = false; 206613c08e2fSMichael Klier if ($ext == 'jpg' || $ext == 'jpeg') { 206713c08e2fSMichael Klier if (!function_exists("imagecreatefromjpeg")) return false; 206813c08e2fSMichael Klier $image = @imagecreatefromjpeg($from); 206913c08e2fSMichael Klier } elseif ($ext == 'png') { 207013c08e2fSMichael Klier if (!function_exists("imagecreatefrompng")) return false; 207113c08e2fSMichael Klier $image = @imagecreatefrompng($from); 207213c08e2fSMichael Klier } elseif ($ext == 'gif') { 207313c08e2fSMichael Klier if (!function_exists("imagecreatefromgif")) return false; 207413c08e2fSMichael Klier $image = @imagecreatefromgif($from); 207513c08e2fSMichael Klier } 207613c08e2fSMichael Klier if (!$image) return false; 207713c08e2fSMichael Klier 207859bc3b48SGerrit Uitslag $newimg = false; 207913c08e2fSMichael Klier if (($conf['gdlib'] > 1) && function_exists("imagecreatetruecolor") && $ext != 'gif') { 208013c08e2fSMichael Klier $newimg = @imagecreatetruecolor($to_w, $to_h); 208113c08e2fSMichael Klier } 208213c08e2fSMichael Klier if (!$newimg) $newimg = @imagecreate($to_w, $to_h); 208313c08e2fSMichael Klier if (!$newimg) { 208413c08e2fSMichael Klier imagedestroy($image); 208513c08e2fSMichael Klier return false; 208613c08e2fSMichael Klier } 208713c08e2fSMichael Klier 208813c08e2fSMichael Klier //keep png alpha channel if possible 208913c08e2fSMichael Klier if ($ext == 'png' && $conf['gdlib'] > 1 && function_exists('imagesavealpha')) { 209013c08e2fSMichael Klier imagealphablending($newimg, false); 209113c08e2fSMichael Klier imagesavealpha($newimg, true); 209213c08e2fSMichael Klier } 209313c08e2fSMichael Klier 209413c08e2fSMichael Klier //keep gif transparent color if possible 209513c08e2fSMichael Klier if ($ext == 'gif' && function_exists('imagefill') && function_exists('imagecolorallocate')) { 209613c08e2fSMichael Klier if (function_exists('imagecolorsforindex') && function_exists('imagecolortransparent')) { 209713c08e2fSMichael Klier $transcolorindex = @imagecolortransparent($image); 209813c08e2fSMichael Klier if ($transcolorindex >= 0) { //transparent color exists 209913c08e2fSMichael Klier $transcolor = @imagecolorsforindex($image, $transcolorindex); 210064159a61SAndreas Gohr $transcolorindex = @imagecolorallocate( 210164159a61SAndreas Gohr $newimg, 210264159a61SAndreas Gohr $transcolor['red'], 210364159a61SAndreas Gohr $transcolor['green'], 210464159a61SAndreas Gohr $transcolor['blue'] 210564159a61SAndreas Gohr ); 210613c08e2fSMichael Klier @imagefill($newimg, 0, 0, $transcolorindex); 210713c08e2fSMichael Klier @imagecolortransparent($newimg, $transcolorindex); 210813c08e2fSMichael Klier } else { //filling with white 210913c08e2fSMichael Klier $whitecolorindex = @imagecolorallocate($newimg, 255, 255, 255); 211013c08e2fSMichael Klier @imagefill($newimg, 0, 0, $whitecolorindex); 211113c08e2fSMichael Klier } 211213c08e2fSMichael Klier } else { //filling with white 211313c08e2fSMichael Klier $whitecolorindex = @imagecolorallocate($newimg, 255, 255, 255); 211413c08e2fSMichael Klier @imagefill($newimg, 0, 0, $whitecolorindex); 211513c08e2fSMichael Klier } 211613c08e2fSMichael Klier } 211713c08e2fSMichael Klier 211813c08e2fSMichael Klier //try resampling first 211913c08e2fSMichael Klier if (function_exists("imagecopyresampled")) { 212013c08e2fSMichael Klier if (!@imagecopyresampled($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h)) { 212113c08e2fSMichael Klier imagecopyresized($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h); 212213c08e2fSMichael Klier } 212313c08e2fSMichael Klier } else { 212413c08e2fSMichael Klier imagecopyresized($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h); 212513c08e2fSMichael Klier } 212613c08e2fSMichael Klier 212713c08e2fSMichael Klier $okay = false; 212813c08e2fSMichael Klier if ($ext == 'jpg' || $ext == 'jpeg') { 212913c08e2fSMichael Klier if (!function_exists('imagejpeg')) { 213013c08e2fSMichael Klier $okay = false; 213113c08e2fSMichael Klier } else { 213213c08e2fSMichael Klier $okay = imagejpeg($newimg, $to, $conf['jpg_quality']); 213313c08e2fSMichael Klier } 213413c08e2fSMichael Klier } elseif ($ext == 'png') { 213513c08e2fSMichael Klier if (!function_exists('imagepng')) { 213613c08e2fSMichael Klier $okay = false; 213713c08e2fSMichael Klier } else { 213813c08e2fSMichael Klier $okay = imagepng($newimg, $to); 213913c08e2fSMichael Klier } 214013c08e2fSMichael Klier } elseif ($ext == 'gif') { 214113c08e2fSMichael Klier if (!function_exists('imagegif')) { 214213c08e2fSMichael Klier $okay = false; 214313c08e2fSMichael Klier } else { 214413c08e2fSMichael Klier $okay = imagegif($newimg, $to); 214513c08e2fSMichael Klier } 214613c08e2fSMichael Klier } 214713c08e2fSMichael Klier 214879a2d784SGerrit Uitslag // destroy GD image resources 214979a2d784SGerrit Uitslag imagedestroy($image); 215079a2d784SGerrit Uitslag imagedestroy($newimg); 215113c08e2fSMichael Klier 215213c08e2fSMichael Klier return $okay; 215313c08e2fSMichael Klier} 215413c08e2fSMichael Klier 21553d7a9e0aSAnika Henke/** 21563d7a9e0aSAnika Henke * Return other media files with the same base name 215779e53fe5SAnika Henke * but different extensions. 21583d7a9e0aSAnika Henke * 21593d7a9e0aSAnika Henke * @param string $src - ID of media file 216042ea7f44SGerrit Uitslag * @param string[] $exts - alternative extensions to find other files for 216142ea7f44SGerrit Uitslag * @return array - array(mime type => file ID) 21623d7a9e0aSAnika Henke * 21633d7a9e0aSAnika Henke * @author Anika Henke <anika@selfthinker.org> 21643d7a9e0aSAnika Henke */ 2165d868eb89SAndreas Gohrfunction media_alternativefiles($src, $exts) 2166d868eb89SAndreas Gohr{ 21673d7a9e0aSAnika Henke 216824870174SAndreas Gohr $files = []; 2169a19c9aa0SGerrit Uitslag [$srcExt, /* srcMime */] = mimetype($src); 21703d7a9e0aSAnika Henke $filebase = substr($src, 0, -1 * (strlen($srcExt) + 1)); 21713d7a9e0aSAnika Henke 21723d7a9e0aSAnika Henke foreach ($exts as $ext) { 21733d7a9e0aSAnika Henke $fileid = $filebase . '.' . $ext; 21743d7a9e0aSAnika Henke $file = mediaFN($fileid); 21753d7a9e0aSAnika Henke if (file_exists($file)) { 2176a19c9aa0SGerrit Uitslag [/* fileExt */, $fileMime] = mimetype($file); 217779e53fe5SAnika Henke $files[$fileMime] = $fileid; 217899f943f6SAnika Henke } 21793d7a9e0aSAnika Henke } 21803d7a9e0aSAnika Henke return $files; 21813d7a9e0aSAnika Henke} 21823d7a9e0aSAnika Henke 2183f50634f0SAnika Henke/** 2184f50634f0SAnika Henke * Check if video/audio is supported to be embedded. 2185f50634f0SAnika Henke * 2186b83a74f1SAnika Henke * @param string $mime - mimetype of media file 218742ea7f44SGerrit Uitslag * @param string $type - type of media files to check ('video', 'audio', or null for all) 2188f50634f0SAnika Henke * @return boolean 2189f50634f0SAnika Henke * 2190f50634f0SAnika Henke * @author Anika Henke <anika@selfthinker.org> 2191f50634f0SAnika Henke */ 2192ed823bcdSAndreas Gohrfunction media_supportedav($mime, $type = null) 2193d868eb89SAndreas Gohr{ 219424870174SAndreas Gohr $supportedAudio = [ 2195f50634f0SAnika Henke 'ogg' => 'audio/ogg', 2196f50634f0SAnika Henke 'mp3' => 'audio/mpeg', 219724870174SAndreas Gohr 'wav' => 'audio/wav' 219824870174SAndreas Gohr ]; 219924870174SAndreas Gohr $supportedVideo = [ 2200f50634f0SAnika Henke 'webm' => 'video/webm', 2201f50634f0SAnika Henke 'ogv' => 'video/ogg', 220224870174SAndreas Gohr 'mp4' => 'video/mp4' 220324870174SAndreas Gohr ]; 2204f50634f0SAnika Henke if ($type == 'audio') { 2205f50634f0SAnika Henke $supportedAv = $supportedAudio; 2206f50634f0SAnika Henke } elseif ($type == 'video') { 2207f50634f0SAnika Henke $supportedAv = $supportedVideo; 2208f50634f0SAnika Henke } else { 2209f50634f0SAnika Henke $supportedAv = array_merge($supportedAudio, $supportedVideo); 2210f50634f0SAnika Henke } 2211f50634f0SAnika Henke return in_array($mime, $supportedAv); 2212f50634f0SAnika Henke} 2213f50634f0SAnika Henke 22140877a1f1SSchplurtz le Déboulonné/** 22150877a1f1SSchplurtz le Déboulonné * Return track media files with the same base name 22160877a1f1SSchplurtz le Déboulonné * but extensions that indicate kind and lang. 22170877a1f1SSchplurtz le Déboulonné * ie for foo.webm search foo.sub.lang.vtt, foo.cap.lang.vtt... 22180877a1f1SSchplurtz le Déboulonné * 22190877a1f1SSchplurtz le Déboulonné * @param string $src - ID of media file 222001299338SSchplurtz le Déboulonné * @return array - array(mediaID => array( kind, srclang )) 22210877a1f1SSchplurtz le Déboulonné * 22220877a1f1SSchplurtz le Déboulonné * @author Schplurtz le Déboulonné <Schplurtz@laposte.net> 22230877a1f1SSchplurtz le Déboulonné */ 2224d868eb89SAndreas Gohrfunction media_trackfiles($src) 2225d868eb89SAndreas Gohr{ 222624870174SAndreas Gohr $kinds = [ 22270877a1f1SSchplurtz le Déboulonné 'sub' => 'subtitles', 22280877a1f1SSchplurtz le Déboulonné 'cap' => 'captions', 22290877a1f1SSchplurtz le Déboulonné 'des' => 'descriptions', 22300877a1f1SSchplurtz le Déboulonné 'cha' => 'chapters', 22310877a1f1SSchplurtz le Déboulonné 'met' => 'metadata' 223224870174SAndreas Gohr ]; 22330877a1f1SSchplurtz le Déboulonné 223424870174SAndreas Gohr $files = []; 22350877a1f1SSchplurtz le Déboulonné $re = '/\\.(sub|cap|des|cha|met)\\.([^.]+)\\.vtt$/'; 22360877a1f1SSchplurtz le Déboulonné $baseid = pathinfo($src, PATHINFO_FILENAME); 22370877a1f1SSchplurtz le Déboulonné $pattern = mediaFN($baseid) . '.*.*.vtt'; 22380877a1f1SSchplurtz le Déboulonné $list = glob($pattern); 22390877a1f1SSchplurtz le Déboulonné foreach ($list as $track) { 22400877a1f1SSchplurtz le Déboulonné if (preg_match($re, $track, $matches)) { 224124870174SAndreas Gohr $files[$baseid . '.' . $matches[1] . '.' . $matches[2] . '.vtt'] = [$kinds[$matches[1]], $matches[2]]; 22420877a1f1SSchplurtz le Déboulonné } 22430877a1f1SSchplurtz le Déboulonné } 22440877a1f1SSchplurtz le Déboulonné return $files; 22450877a1f1SSchplurtz le Déboulonné} 22460877a1f1SSchplurtz le Déboulonné 2247365be586SAndreas Gohr/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 2248