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; 15e1d9dcc8SAndreas Gohruse dokuwiki\Extension\Event; 16dd9e8e5eSAndreas Gohruse dokuwiki\File\MediaFile; 17b960c74fSSatoshi Saharause dokuwiki\Form\Form; 183df72098SAndreas Gohruse dokuwiki\HTTP\DokuHTTPClient; 1979a2d784SGerrit Uitslaguse dokuwiki\Logger; 200c3a5702SAndreas Gohruse dokuwiki\Subscriptions\MediaSubscriptionSender; 21dd9e8e5eSAndreas Gohruse dokuwiki\Ui\Media\Display; 2279a2d784SGerrit Uitslaguse dokuwiki\Ui\Media\DisplayRow; 2379a2d784SGerrit Uitslaguse dokuwiki\Ui\Media\DisplayTile; 246734bb8cSAndreas Gohruse dokuwiki\Search\MetadataSearch; 2579a2d784SGerrit Uitslaguse dokuwiki\Ui\MediaDiff; 2679a2d784SGerrit Uitslaguse dokuwiki\Utf8\PhpString; 272d85e841SAndreas Gohruse dokuwiki\Utf8\Sort; 2879a2d784SGerrit Uitslaguse splitbrain\slika\Slika; 290c3a5702SAndreas Gohr 303df72098SAndreas Gohr/** 313df72098SAndreas Gohr * Lists pages which currently use a media file selected for deletion 323df72098SAndreas Gohr * 333df72098SAndreas Gohr * References uses the same visual as search results and share 343df72098SAndreas Gohr * their CSS tags except pagenames won't be links. 353df72098SAndreas Gohr * 363df72098SAndreas Gohr * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net> 3742ea7f44SGerrit Uitslag * 3842ea7f44SGerrit Uitslag * @param array $data 3942ea7f44SGerrit Uitslag * @param string $id 403df72098SAndreas Gohr */ 41d868eb89SAndreas Gohrfunction media_filesinuse($data, $id) 42d868eb89SAndreas Gohr{ 433df72098SAndreas Gohr global $lang; 443df72098SAndreas Gohr echo '<h1>' . $lang['reference'] . ' <code>' . hsc(noNS($id)) . '</code></h1>'; 453df72098SAndreas Gohr echo '<p>' . hsc($lang['ref_inuse']) . '</p>'; 463df72098SAndreas Gohr 473df72098SAndreas Gohr $hidden = 0; //count of hits without read permission 483df72098SAndreas Gohr foreach ($data as $row) { 49a05e297aSAndreas Gohr if (auth_quickaclcheck($row) >= AUTH_READ && isVisiblePage($row)) { 503df72098SAndreas Gohr echo '<div class="search_result">'; 51a05e297aSAndreas Gohr echo '<span class="mediaref_ref">' . hsc($row) . '</span>'; 523df72098SAndreas Gohr echo '</div>'; 53177d6836SAndreas Gohr } else $hidden++; 543df72098SAndreas Gohr } 553df72098SAndreas Gohr if ($hidden) { 5626dfc232SAndreas Gohr echo '<div class="mediaref_hidden">' . $lang['ref_hidden'] . '</div>'; 573df72098SAndreas Gohr } 583df72098SAndreas Gohr} 593df72098SAndreas Gohr 603df72098SAndreas Gohr/** 613df72098SAndreas Gohr * Handles the saving of image meta data 623df72098SAndreas Gohr * 633df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 64cf832786SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 65e0c26282SGerrit Uitslag * 66e0c26282SGerrit Uitslag * @param string $id media id 67e0c26282SGerrit Uitslag * @param int $auth permission level 68e0c26282SGerrit Uitslag * @param array $data 6942ea7f44SGerrit Uitslag * @return false|string 703df72098SAndreas Gohr */ 71d868eb89SAndreas Gohrfunction media_metasave($id, $auth, $data) 72d868eb89SAndreas Gohr{ 733df72098SAndreas Gohr if ($auth < AUTH_UPLOAD) return false; 74f2ea8432SAndreas Gohr if (!checkSecurityToken()) return false; 753df72098SAndreas Gohr global $lang; 760b308644SOtto Vainio global $conf; 773df72098SAndreas Gohr $src = mediaFN($id); 783df72098SAndreas Gohr 793df72098SAndreas Gohr $meta = new JpegMeta($src); 803df72098SAndreas Gohr $meta->_parseAll(); 813df72098SAndreas Gohr 823df72098SAndreas Gohr foreach ($data as $key => $val) { 833df72098SAndreas Gohr $val = trim($val); 843df72098SAndreas Gohr if (empty($val)) { 853df72098SAndreas Gohr $meta->deleteField($key); 863df72098SAndreas Gohr } else { 873df72098SAndreas Gohr $meta->setField($key, $val); 883df72098SAndreas Gohr } 893df72098SAndreas Gohr } 903df72098SAndreas Gohr 91cf832786SKate Arzamastseva $old = @filemtime($src); 9279e79377SAndreas Gohr if (!file_exists(mediaFN($id, $old)) && file_exists($src)) { 93cf832786SKate Arzamastseva // add old revision to the attic 94cf832786SKate Arzamastseva media_saveOldRevision($id); 95cf832786SKate Arzamastseva } 96ac3ed4afSGerrit Uitslag $filesize_old = filesize($src); 973df72098SAndreas Gohr if ($meta->save()) { 980b308644SOtto Vainio if ($conf['fperm']) chmod($src, $conf['fperm']); 99ac3ed4afSGerrit Uitslag @clearstatcache(true, $src); 100cf832786SKate Arzamastseva $new = @filemtime($src); 101ac3ed4afSGerrit Uitslag $filesize_new = filesize($src); 102ac3ed4afSGerrit Uitslag $sizechange = $filesize_new - $filesize_old; 103ac3ed4afSGerrit Uitslag 104cf832786SKate Arzamastseva // add a log entry to the media changelog 105ac3ed4afSGerrit Uitslag addMediaLogEntry($new, $id, DOKU_CHANGE_TYPE_EDIT, $lang['media_meta_edited'], '', null, $sizechange); 106cf832786SKate Arzamastseva 1073df72098SAndreas Gohr msg($lang['metasaveok'], 1); 1083df72098SAndreas Gohr return $id; 1093df72098SAndreas Gohr } else { 1103df72098SAndreas Gohr msg($lang['metasaveerr'], -1); 1113df72098SAndreas Gohr return false; 1123df72098SAndreas Gohr } 1133df72098SAndreas Gohr} 1143df72098SAndreas Gohr 1153df72098SAndreas Gohr/** 116d54f7963SKlap-in * check if a media is external source 117d54f7963SKlap-in * 118d54f7963SKlap-in * @author Gerrit Uitslag <klapinklapin@gmail.com> 11942ea7f44SGerrit Uitslag * 120d54f7963SKlap-in * @param string $id the media ID or URL 121d54f7963SKlap-in * @return bool 122d54f7963SKlap-in */ 123d868eb89SAndreas Gohrfunction media_isexternal($id) 124d868eb89SAndreas Gohr{ 125fe578fe9SElan Ruusamäe if (preg_match('#^(?:https?|ftp)://#i', $id)) return true; 126d54f7963SKlap-in return false; 127d54f7963SKlap-in} 128d54f7963SKlap-in 129d54f7963SKlap-in/** 130add8678fSAndreas Gohr * Check if a media item is public (eg, external URL or readable by @ALL) 131add8678fSAndreas Gohr * 132add8678fSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 13342ea7f44SGerrit Uitslag * 134add8678fSAndreas Gohr * @param string $id the media ID or URL 135add8678fSAndreas Gohr * @return bool 136add8678fSAndreas Gohr */ 137d868eb89SAndreas Gohrfunction media_ispublic($id) 138d868eb89SAndreas Gohr{ 139d54f7963SKlap-in if (media_isexternal($id)) return true; 140add8678fSAndreas Gohr $id = cleanID($id); 141*7e687fd8SAndreas Gohr if (auth_aclcheck(mediaAclPath($id), '', []) >= AUTH_READ) return true; 142add8678fSAndreas Gohr return false; 143add8678fSAndreas Gohr} 144add8678fSAndreas Gohr 145add8678fSAndreas Gohr/** 1463df72098SAndreas Gohr * Display the form to edit image meta data 1473df72098SAndreas Gohr * 1483df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 149d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 150e0c26282SGerrit Uitslag * 151e0c26282SGerrit Uitslag * @param string $id media id 152e0c26282SGerrit Uitslag * @param int $auth permission level 153e0c26282SGerrit Uitslag * @return bool 1543df72098SAndreas Gohr */ 155d868eb89SAndreas Gohrfunction media_metaform($id, $auth) 156d868eb89SAndreas Gohr{ 157ebc28e69SAndreas Gohr global $lang; 1583df72098SAndreas Gohr 15988a71175SKate Arzamastseva if ($auth < AUTH_UPLOAD) { 160b960c74fSSatoshi Sahara echo '<div class="nothing">' . $lang['media_perm_upload'] . '</div>' . DOKU_LF; 16188a71175SKate Arzamastseva return false; 16288a71175SKate Arzamastseva } 16388a71175SKate Arzamastseva 1643df72098SAndreas Gohr // load the field descriptions 1653df72098SAndreas Gohr static $fields = null; 166b960c74fSSatoshi Sahara if ($fields === null) { 1673e98e685SKate Arzamastseva $config_files = getConfigFiles('mediameta'); 1683e98e685SKate Arzamastseva foreach ($config_files as $config_file) { 16979e79377SAndreas Gohr if (file_exists($config_file)) include($config_file); 1703df72098SAndreas Gohr } 1713df72098SAndreas Gohr } 1723df72098SAndreas Gohr 1733df72098SAndreas Gohr $src = mediaFN($id); 1743df72098SAndreas Gohr 1753df72098SAndreas Gohr // output 176b960c74fSSatoshi Sahara $form = new Form([ 177b960c74fSSatoshi Sahara 'action' => media_managerURL(['tab_details' => 'view'], '&'), 178b960c74fSSatoshi Sahara 'class' => 'meta' 179b960c74fSSatoshi Sahara ]); 180b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 181b960c74fSSatoshi Sahara $form->setHiddenField('img', $id); 182b960c74fSSatoshi Sahara $form->setHiddenField('mediado', 'save'); 1833df72098SAndreas Gohr foreach ($fields as $key => $field) { 1843df72098SAndreas Gohr // get current value 1853e98e685SKate Arzamastseva if (empty($field[0])) continue; 18624870174SAndreas Gohr $tags = [$field[0]]; 1875cefb623SEduardo Mozart de Oliveira if (isset($field[3]) && is_array($field[3])) $tags = array_merge($tags, $field[3]); 1883df72098SAndreas Gohr $value = tpl_img_getTag($tags, '', $src); 189ca6a0701SAndreas Gohr $value = cleanText($value); 1903df72098SAndreas Gohr 1913df72098SAndreas Gohr // prepare attributes 19224870174SAndreas Gohr $p = [ 193b960c74fSSatoshi Sahara 'class' => 'edit', 194b960c74fSSatoshi Sahara 'id' => 'meta__' . $key, 19524870174SAndreas Gohr 'name' => 'meta[' . $field[0] . ']' 19624870174SAndreas Gohr ]; 1973df72098SAndreas Gohr 198b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('row'); 1993df72098SAndreas Gohr if ($field[2] == 'text') { 200bde2a644SSatoshi Sahara $form->addTextInput( 20164159a61SAndreas Gohr $p['name'], 20279a2d784SGerrit Uitslag ($lang[$field[1]] ?: $field[1] . ':') 203b960c74fSSatoshi Sahara )->id($p['id'])->addClass($p['class'])->val($value); 2043df72098SAndreas Gohr } else { 205b960c74fSSatoshi Sahara $form->addTextarea($p['name'], $lang[$field[1]])->id($p['id']) 206b960c74fSSatoshi Sahara ->val(formText($value)) 207b960c74fSSatoshi Sahara ->addClass($p['class']) 208b960c74fSSatoshi Sahara ->attr('rows', '6')->attr('cols', '50'); 2093df72098SAndreas Gohr } 210b960c74fSSatoshi Sahara $form->addTagClose('div'); 2113df72098SAndreas Gohr } 212b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('buttons'); 213b960c74fSSatoshi Sahara $form->addButton('mediado[save]', $lang['btn_save'])->attr('type', 'submit') 214b960c74fSSatoshi Sahara ->attrs(['accesskey' => 's']); 215b960c74fSSatoshi Sahara $form->addTagClose('div'); 216ebc28e69SAndreas Gohr 217b960c74fSSatoshi Sahara $form->addTagClose('div'); 218b960c74fSSatoshi Sahara echo $form->toHTML(); 219ebc28e69SAndreas Gohr return true; 2203df72098SAndreas Gohr} 2213df72098SAndreas Gohr 222666cdec5SMichael Klier/** 22387229c84SAdrian Lang * Convenience function to check if a media file is still in use 224666cdec5SMichael Klier * 225666cdec5SMichael Klier * @author Michael Klier <chi@chimeric.de> 226e0c26282SGerrit Uitslag * 227e0c26282SGerrit Uitslag * @param string $id media id 228e0c26282SGerrit Uitslag * @return array|bool 229666cdec5SMichael Klier */ 230d868eb89SAndreas Gohrfunction media_inuse($id) 231d868eb89SAndreas Gohr{ 232666cdec5SMichael Klier global $conf; 233ebc28e69SAndreas Gohr 234666cdec5SMichael Klier if ($conf['refcheck']) { 2356734bb8cSAndreas Gohr $mediareferences = (new MetadataSearch())->mediause($id, true); 23624870174SAndreas Gohr if ($mediareferences === []) { 2376dae2464SAndreas Gohr return false; 238666cdec5SMichael Klier } else { 239666cdec5SMichael Klier return $mediareferences; 240666cdec5SMichael Klier } 241666cdec5SMichael Klier } else { 242666cdec5SMichael Klier return false; 243666cdec5SMichael Klier } 244666cdec5SMichael Klier} 245a05e297aSAndreas Gohr 2463df72098SAndreas Gohr/** 2473df72098SAndreas Gohr * Handles media file deletions 2483df72098SAndreas Gohr * 2493df72098SAndreas Gohr * If configured, checks for media references before deletion 2503df72098SAndreas Gohr * 2513df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 25242ea7f44SGerrit Uitslag * 253ebc28e69SAndreas Gohr * @param string $id media id 25422db8df7SAndreas Gohr * @param int $auth no longer used 25587229c84SAdrian Lang * @return int One of: 0, 25663703ba5SAndreas Gohr * DOKU_MEDIA_DELETED, 25763703ba5SAndreas Gohr * DOKU_MEDIA_DELETED | DOKU_MEDIA_EMPTY_NS, 25863703ba5SAndreas Gohr * DOKU_MEDIA_NOT_AUTH, 25963703ba5SAndreas Gohr * DOKU_MEDIA_INUSE 2603df72098SAndreas Gohr */ 261d868eb89SAndreas Gohrfunction media_delete($id, $auth) 262d868eb89SAndreas Gohr{ 2636183fb05SKate Arzamastseva global $lang; 264*7e687fd8SAndreas Gohr $auth = auth_quickaclcheck(mediaAclPath($id)); 26587229c84SAdrian Lang if ($auth < AUTH_DELETE) return DOKU_MEDIA_NOT_AUTH; 26687229c84SAdrian Lang if (media_inuse($id)) return DOKU_MEDIA_INUSE; 2673df72098SAndreas Gohr 2683df72098SAndreas Gohr $file = mediaFN($id); 2694a961e72SMichal Kolodziejski 2704a961e72SMichal Kolodziejski // trigger an event - MEDIA_DELETE_FILE 27124870174SAndreas Gohr $data = []; 272666cdec5SMichael Klier $data['id'] = $id; 27379a2d784SGerrit Uitslag $data['name'] = PhpString::basename($file); 2744a961e72SMichal Kolodziejski $data['path'] = $file; 27579e79377SAndreas Gohr $data['size'] = (file_exists($file)) ? filesize($file) : 0; 276666cdec5SMichael Klier 277666cdec5SMichael Klier $data['unl'] = false; 278666cdec5SMichael Klier $data['del'] = false; 279e1d9dcc8SAndreas Gohr $evt = new Event('MEDIA_DELETE_FILE', $data); 2804a961e72SMichal Kolodziejski if ($evt->advise_before()) { 2816183fb05SKate Arzamastseva $old = @filemtime($file); 28279e79377SAndreas Gohr if (!file_exists(mediaFN($id, $old)) && file_exists($file)) { 2836183fb05SKate Arzamastseva // add old revision to the attic 2846183fb05SKate Arzamastseva media_saveOldRevision($id); 2856183fb05SKate Arzamastseva } 2866183fb05SKate Arzamastseva 287666cdec5SMichael Klier $data['unl'] = @unlink($file); 288666cdec5SMichael Klier if ($data['unl']) { 289ac3ed4afSGerrit Uitslag $sizechange = 0 - $data['size']; 290ac3ed4afSGerrit Uitslag addMediaLogEntry(time(), $id, DOKU_CHANGE_TYPE_DELETE, $lang['deleted'], '', null, $sizechange); 291ac3ed4afSGerrit Uitslag 292666cdec5SMichael Klier $data['del'] = io_sweepNS($id, 'mediadir'); 2933df72098SAndreas Gohr } 2944a961e72SMichal Kolodziejski } 2954a961e72SMichal Kolodziejski $evt->advise_after(); 2964a961e72SMichal Kolodziejski unset($evt); 2974a961e72SMichal Kolodziejski 298666cdec5SMichael Klier if ($data['unl'] && $data['del']) { 29987229c84SAdrian Lang return DOKU_MEDIA_DELETED | DOKU_MEDIA_EMPTY_NS; 3003df72098SAndreas Gohr } 3013df72098SAndreas Gohr 30287229c84SAdrian Lang return $data['unl'] ? DOKU_MEDIA_DELETED : 0; 3033df72098SAndreas Gohr} 3043df72098SAndreas Gohr 3053df72098SAndreas Gohr/** 3062d6cc64fSKate Arzamastseva * Handle file uploads via XMLHttpRequest 3072d6cc64fSKate Arzamastseva * 308ebc28e69SAndreas Gohr * @param string $ns target namespace 309ebc28e69SAndreas Gohr * @param int $auth current auth check result 31042ea7f44SGerrit Uitslag * @return false|string false on error, id of the new file on success 3112d6cc64fSKate Arzamastseva */ 312d868eb89SAndreas Gohrfunction media_upload_xhr($ns, $auth) 313d868eb89SAndreas Gohr{ 314da45d883SKate Arzamastseva if (!checkSecurityToken()) return false; 3158108113cSTom N Harris global $INPUT; 316da45d883SKate Arzamastseva 3178108113cSTom N Harris $id = $INPUT->get->str('qqfile'); 31824870174SAndreas Gohr [$ext, $mime] = mimetype($id); 3192d6cc64fSKate Arzamastseva $input = fopen("php://input", "r"); 3202d6cc64fSKate Arzamastseva if (!($tmp = io_mktmpdir())) return false; 32162231793SKate Arzamastseva $path = $tmp . '/' . md5($id); 3222d6cc64fSKate Arzamastseva $target = fopen($path, "w"); 323063fb5b5SAndreas Gohr $realSize = stream_copy_to_stream($input, $target); 3242d6cc64fSKate Arzamastseva fclose($target); 325063fb5b5SAndreas Gohr fclose($input); 3262b9be456SAndreas Gohr if ($INPUT->server->has('CONTENT_LENGTH') && ($realSize != $INPUT->server->int('CONTENT_LENGTH'))) { 327063fb5b5SAndreas Gohr unlink($path); 328063fb5b5SAndreas Gohr return false; 329063fb5b5SAndreas Gohr } 330063fb5b5SAndreas Gohr 3312d6cc64fSKate Arzamastseva $res = media_save( 33224870174SAndreas Gohr ['name' => $path, 'mime' => $mime, 'ext' => $ext], 3332d6cc64fSKate Arzamastseva $ns . ':' . $id, 33479a2d784SGerrit Uitslag ($INPUT->get->str('ow') == 'true'), 3352d6cc64fSKate Arzamastseva $auth, 3362d6cc64fSKate Arzamastseva 'copy' 3372d6cc64fSKate Arzamastseva ); 3382d6cc64fSKate Arzamastseva unlink($path); 339900a9e9eSGerrit Uitslag if ($tmp) io_rmdir($tmp, true); 3402d6cc64fSKate Arzamastseva if (is_array($res)) { 3412d6cc64fSKate Arzamastseva msg($res[0], $res[1]); 3422d6cc64fSKate Arzamastseva return false; 3432d6cc64fSKate Arzamastseva } 3442d6cc64fSKate Arzamastseva return $res; 3452d6cc64fSKate Arzamastseva} 3462d6cc64fSKate Arzamastseva 3472d6cc64fSKate Arzamastseva/** 3483df72098SAndreas Gohr * Handles media file uploads 3493df72098SAndreas Gohr * 3503df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 35111d9dfa5SMichael Klier * @author Michael Klier <chi@chimeric.de> 35242ea7f44SGerrit Uitslag * 353ebc28e69SAndreas Gohr * @param string $ns target namespace 354ebc28e69SAndreas Gohr * @param int $auth current auth check result 355ebc28e69SAndreas Gohr * @param bool|array $file $_FILES member, $_FILES['upload'] if false 35642ea7f44SGerrit Uitslag * @return false|string false on error, id of the new file on success 3573df72098SAndreas Gohr */ 358d868eb89SAndreas Gohrfunction media_upload($ns, $auth, $file = false) 359d868eb89SAndreas Gohr{ 360f2ea8432SAndreas Gohr if (!checkSecurityToken()) return false; 3613df72098SAndreas Gohr global $lang; 3628108113cSTom N Harris global $INPUT; 3633df72098SAndreas Gohr 36444409c3dSAndreas Gohr // get file and id 3658108113cSTom N Harris $id = $INPUT->post->str('mediaid'); 3662d6cc64fSKate Arzamastseva if (!$file) $file = $_FILES['upload']; 3673df72098SAndreas Gohr if (empty($id)) $id = $file['name']; 36844409c3dSAndreas Gohr 36999766eefSAndreas Gohr // check for errors (messages are done in lib/exe/mediamanager.php) 37099766eefSAndreas Gohr if ($file['error']) return false; 3719676dc23SAndreas Gohr 37244409c3dSAndreas Gohr // check extensions 37324870174SAndreas Gohr [$fext, $fmime] = mimetype($file['name']); 37424870174SAndreas Gohr [$iext, $imime] = mimetype($id); 37544409c3dSAndreas Gohr if ($fext && !$iext) { 3768cb1eb01SAndreas Gohr // no extension specified in id - read original one 37744409c3dSAndreas Gohr $id .= '.' . $fext; 3788cb1eb01SAndreas Gohr $imime = $fmime; 37944409c3dSAndreas Gohr } elseif ($fext && $fext != $iext) { 38044409c3dSAndreas Gohr // extension was changed, print warning 38144409c3dSAndreas Gohr msg(sprintf($lang['mediaextchange'], $fext, $iext)); 38244409c3dSAndreas Gohr } 38344409c3dSAndreas Gohr 38424870174SAndreas Gohr $res = media_save( 38524870174SAndreas Gohr [ 38624870174SAndreas Gohr 'name' => $file['tmp_name'], 387ffb291f2SAdrian Lang 'mime' => $imime, 38824870174SAndreas Gohr 'ext' => $iext 38924870174SAndreas Gohr ], 39024870174SAndreas Gohr $ns . ':' . $id, 39124870174SAndreas Gohr $INPUT->post->bool('ow'), 39224870174SAndreas Gohr $auth, 39324870174SAndreas Gohr 'copy_uploaded_file' 39424870174SAndreas Gohr ); 395ffb291f2SAdrian Lang if (is_array($res)) { 396ffb291f2SAdrian Lang msg($res[0], $res[1]); 397ffb291f2SAdrian Lang return false; 398ffb291f2SAdrian Lang } 399ffb291f2SAdrian Lang return $res; 400ffb291f2SAdrian Lang} 401ffb291f2SAdrian Lang 402ffb291f2SAdrian Lang/** 40371f17ac4SAndreas Gohr * An alternative to move_uploaded_file that copies 40471f17ac4SAndreas Gohr * 40571f17ac4SAndreas Gohr * Using copy, makes sure any setgid bits on the media directory are honored 40671f17ac4SAndreas Gohr * 40771f17ac4SAndreas Gohr * @see move_uploaded_file() 40842ea7f44SGerrit Uitslag * 40971f17ac4SAndreas Gohr * @param string $from 41071f17ac4SAndreas Gohr * @param string $to 41171f17ac4SAndreas Gohr * @return bool 41271f17ac4SAndreas Gohr */ 413d868eb89SAndreas Gohrfunction copy_uploaded_file($from, $to) 414d868eb89SAndreas Gohr{ 41571f17ac4SAndreas Gohr if (!is_uploaded_file($from)) return false; 41671f17ac4SAndreas Gohr $ok = copy($from, $to); 41771f17ac4SAndreas Gohr @unlink($from); 41871f17ac4SAndreas Gohr return $ok; 41971f17ac4SAndreas Gohr} 42071f17ac4SAndreas Gohr 42171f17ac4SAndreas Gohr/** 422ffb291f2SAdrian Lang * This generates an action event and delegates to _media_upload_action(). 423ffb291f2SAdrian Lang * Action plugins are allowed to pre/postprocess the uploaded file. 424ffb291f2SAdrian Lang * (The triggered event is preventable.) 425ffb291f2SAdrian Lang * 426ffb291f2SAdrian Lang * Event data: 427ffb291f2SAdrian Lang * $data[0] fn_tmp: the temporary file name (read from $_FILES) 428ffb291f2SAdrian Lang * $data[1] fn: the file name of the uploaded file 429ffb291f2SAdrian Lang * $data[2] id: the future directory id of the uploaded file 430ffb291f2SAdrian Lang * $data[3] imime: the mimetype of the uploaded file 431ffb291f2SAdrian Lang * $data[4] overwrite: if an existing file is going to be overwritten 43252a281e8SGerrit Uitslag * $data[5] move: name of function that performs move/copy/.. 433ffb291f2SAdrian Lang * 434ffb291f2SAdrian Lang * @triggers MEDIA_UPLOAD_FINISH 43542ea7f44SGerrit Uitslag * 436e0c26282SGerrit Uitslag * @param array $file 43752a281e8SGerrit Uitslag * @param string $id media id 43842ea7f44SGerrit Uitslag * @param bool $ow overwrite? 439e0c26282SGerrit Uitslag * @param int $auth permission level 44052a281e8SGerrit Uitslag * @param string $move name of functions that performs move/copy/.. 44142ea7f44SGerrit Uitslag * @return false|array|string 442e0c26282SGerrit Uitslag */ 443d868eb89SAndreas Gohrfunction media_save($file, $id, $ow, $auth, $move) 444d868eb89SAndreas Gohr{ 445ffb291f2SAdrian Lang if ($auth < AUTH_UPLOAD) { 44624870174SAndreas Gohr return ["You don't have permissions to upload files.", -1]; 447ffb291f2SAdrian Lang } 448ffb291f2SAdrian Lang 449ffb291f2SAdrian Lang if (!isset($file['mime']) || !isset($file['ext'])) { 45024870174SAndreas Gohr [$ext, $mime] = mimetype($id); 451ffb291f2SAdrian Lang if (!isset($file['mime'])) { 452ffb291f2SAdrian Lang $file['mime'] = $mime; 453ffb291f2SAdrian Lang } 454ffb291f2SAdrian Lang if (!isset($file['ext'])) { 455ffb291f2SAdrian Lang $file['ext'] = $ext; 456ffb291f2SAdrian Lang } 457ffb291f2SAdrian Lang } 458ffb291f2SAdrian Lang 45992cac9a9SKate Arzamastseva global $lang, $conf; 460ffb291f2SAdrian Lang 4613df72098SAndreas Gohr // get filename 4623543c6deSAndreas Gohr $id = cleanID($id); 4633df72098SAndreas Gohr $fn = mediaFN($id); 4643df72098SAndreas Gohr 4653df72098SAndreas Gohr // get filetype regexp 4663df72098SAndreas Gohr $types = array_keys(getMimeTypes()); 467bad6fc0dSAndreas Gohr $types = array_map( 46824870174SAndreas Gohr static fn($q) => preg_quote($q, "/"), 469bad6fc0dSAndreas Gohr $types 470bad6fc0dSAndreas Gohr ); 47124870174SAndreas Gohr $regex = implode('|', $types); 4723df72098SAndreas Gohr 4733df72098SAndreas Gohr // because a temp file was created already 474ffb291f2SAdrian Lang if (!preg_match('/\.(' . $regex . ')$/i', $fn)) { 47524870174SAndreas Gohr return [$lang['uploadwrong'], -1]; 476ffb291f2SAdrian Lang } 477ffb291f2SAdrian Lang 4783df72098SAndreas Gohr //check for overwrite 47979e79377SAndreas Gohr $overwrite = file_exists($fn); 480e5d185e1SKate Arzamastseva $auth_ow = (($conf['mediarevisions']) ? AUTH_UPLOAD : AUTH_DELETE); 481e5d185e1SKate Arzamastseva if ($overwrite && (!$ow || $auth < $auth_ow)) { 48224870174SAndreas Gohr return [$lang['uploadexist'], 0]; 4833df72098SAndreas Gohr } 4848cb1eb01SAndreas Gohr // check for valid content 485ffb291f2SAdrian Lang $ok = media_contentcheck($file['name'], $file['mime']); 4868cb1eb01SAndreas Gohr if ($ok == -1) { 48724870174SAndreas Gohr return [sprintf($lang['uploadbadcontent'], '.' . $file['ext']), -1]; 4888cb1eb01SAndreas Gohr } elseif ($ok == -2) { 48924870174SAndreas Gohr return [$lang['uploadspam'], -1]; 49026ceae18SAndreas Gohr } elseif ($ok == -3) { 49124870174SAndreas Gohr return [$lang['uploadxss'], -1]; 4928cb1eb01SAndreas Gohr } 4938cb1eb01SAndreas Gohr 49411d9dfa5SMichael Klier // prepare event data 49524870174SAndreas Gohr $data = []; 496ffb291f2SAdrian Lang $data[0] = $file['name']; 49711d9dfa5SMichael Klier $data[1] = $fn; 49811d9dfa5SMichael Klier $data[2] = $id; 499ffb291f2SAdrian Lang $data[3] = $file['mime']; 50099c8d7f2Smichael $data[4] = $overwrite; 501ffb291f2SAdrian Lang $data[5] = $move; 50211d9dfa5SMichael Klier 50311d9dfa5SMichael Klier // trigger event 504cbb44eabSAndreas Gohr return Event::createAndTrigger('MEDIA_UPLOAD_FINISH', $data, '_media_upload_action', true); 50511d9dfa5SMichael Klier} 50611d9dfa5SMichael Klier 50711d9dfa5SMichael Klier/** 50842ea7f44SGerrit Uitslag * Callback adapter for media_upload_finish() triggered by MEDIA_UPLOAD_FINISH 50942ea7f44SGerrit Uitslag * 51011d9dfa5SMichael Klier * @author Michael Klier <chi@chimeric.de> 51142ea7f44SGerrit Uitslag * 51242ea7f44SGerrit Uitslag * @param array $data event data 51342ea7f44SGerrit Uitslag * @return false|array|string 51411d9dfa5SMichael Klier */ 515d868eb89SAndreas Gohrfunction _media_upload_action($data) 516d868eb89SAndreas Gohr{ 51711d9dfa5SMichael Klier // fixme do further sanity tests of given data? 518ffb291f2SAdrian Lang if (is_array($data) && count($data) === 6) { 519ffb291f2SAdrian Lang return media_upload_finish($data[0], $data[1], $data[2], $data[3], $data[4], $data[5]); 52011d9dfa5SMichael Klier } else { 52111d9dfa5SMichael Klier return false; //callback error 52211d9dfa5SMichael Klier } 52311d9dfa5SMichael Klier} 52411d9dfa5SMichael Klier 52511d9dfa5SMichael Klier/** 52611d9dfa5SMichael Klier * Saves an uploaded media file 52711d9dfa5SMichael Klier * 52811d9dfa5SMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 52911d9dfa5SMichael Klier * @author Michael Klier <chi@chimeric.de> 530cbe26ad6SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 53142ea7f44SGerrit Uitslag * 53242ea7f44SGerrit Uitslag * @param string $fn_tmp 53342ea7f44SGerrit Uitslag * @param string $fn 53442ea7f44SGerrit Uitslag * @param string $id media id 53542ea7f44SGerrit Uitslag * @param string $imime mime type 53642ea7f44SGerrit Uitslag * @param bool $overwrite overwrite existing? 53742ea7f44SGerrit Uitslag * @param string $move function name 53842ea7f44SGerrit Uitslag * @return array|string 53911d9dfa5SMichael Klier */ 540d868eb89SAndreas Gohrfunction media_upload_finish($fn_tmp, $fn, $id, $imime, $overwrite, $move = 'move_uploaded_file') 541d868eb89SAndreas Gohr{ 54211d9dfa5SMichael Klier global $conf; 54311d9dfa5SMichael Klier global $lang; 5449c1bd4bcSKate Arzamastseva global $REV; 54511d9dfa5SMichael Klier 546e4f389efSKate Arzamastseva $old = @filemtime($fn); 54779e79377SAndreas Gohr if (!file_exists(mediaFN($id, $old)) && file_exists($fn)) { 548e4f389efSKate Arzamastseva // add old revision to the attic if missing 549cbe26ad6SKate Arzamastseva media_saveOldRevision($id); 550e4f389efSKate Arzamastseva } 551e4f389efSKate Arzamastseva 5523df72098SAndreas Gohr // prepare directory 553cc7d0c94SBen Coburn io_createNamespace($id, 'media'); 55411d9dfa5SMichael Klier 555ac3ed4afSGerrit Uitslag $filesize_old = file_exists($fn) ? filesize($fn) : 0; 556ac3ed4afSGerrit Uitslag 557ffb291f2SAdrian Lang if ($move($fn_tmp, $fn)) { 55823846a98SKate Arzamastseva @clearstatcache(true, $fn); 559dad6764eSKate Arzamastseva $new = @filemtime($fn); 56074400ea5SBen Coburn // Set the correct permission here. 56174400ea5SBen Coburn // Always chmod media because they may be saved with different permissions than expected from the php umask. 56274400ea5SBen Coburn // (Should normally chmod to $conf['fperm'] only if $conf['fperm'] is set.) 56374400ea5SBen Coburn chmod($fn, $conf['fmode']); 5643df72098SAndreas Gohr msg($lang['uploadsucc'], 1); 56583734cddSPhy media_notify($id, $fn, $imime, $old, $new); 56699c8d7f2Smichael // add a log entry to the media changelog 567ac3ed4afSGerrit Uitslag $filesize_new = filesize($fn); 568ac3ed4afSGerrit Uitslag $sizechange = $filesize_new - $filesize_old; 5699c1bd4bcSKate Arzamastseva if ($REV) { 57064159a61SAndreas Gohr addMediaLogEntry( 57164159a61SAndreas Gohr $new, 57264159a61SAndreas Gohr $id, 57364159a61SAndreas Gohr DOKU_CHANGE_TYPE_REVERT, 57464159a61SAndreas Gohr sprintf($lang['restored'], dformat($REV)), 57564159a61SAndreas Gohr $REV, 57664159a61SAndreas Gohr null, 57764159a61SAndreas Gohr $sizechange 57864159a61SAndreas Gohr ); 5799c1bd4bcSKate Arzamastseva } elseif ($overwrite) { 580ac3ed4afSGerrit Uitslag addMediaLogEntry($new, $id, DOKU_CHANGE_TYPE_EDIT, '', '', null, $sizechange); 58199c8d7f2Smichael } else { 582ac3ed4afSGerrit Uitslag addMediaLogEntry($new, $id, DOKU_CHANGE_TYPE_CREATE, $lang['created'], '', null, $sizechange); 58399c8d7f2Smichael } 5843df72098SAndreas Gohr return $id; 5853df72098SAndreas Gohr } else { 58624870174SAndreas Gohr return [$lang['uploadfail'], -1]; 5873df72098SAndreas Gohr } 5883df72098SAndreas Gohr} 5893df72098SAndreas Gohr 5908cb1eb01SAndreas Gohr/** 591cbe26ad6SKate Arzamastseva * Moves the current version of media file to the media_attic 592cbe26ad6SKate Arzamastseva * directory 593cbe26ad6SKate Arzamastseva * 594cbe26ad6SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 59542ea7f44SGerrit Uitslag * 596cbe26ad6SKate Arzamastseva * @param string $id 597cbe26ad6SKate Arzamastseva * @return int - revision date 598e4f389efSKate Arzamastseva */ 599d868eb89SAndreas Gohrfunction media_saveOldRevision($id) 600d868eb89SAndreas Gohr{ 601dbf57c96SKate Arzamastseva global $conf, $lang; 602dbf57c96SKate Arzamastseva 603e4f389efSKate Arzamastseva $oldf = mediaFN($id); 60479e79377SAndreas Gohr if (!file_exists($oldf)) return ''; 605e4f389efSKate Arzamastseva $date = filemtime($oldf); 606e5d185e1SKate Arzamastseva if (!$conf['mediarevisions']) return $date; 607e5d185e1SKate Arzamastseva 608047bad06SGerrit Uitslag $medialog = new MediaChangeLog($id); 609047bad06SGerrit Uitslag if (!$medialog->getRevisionInfo($date)) { 610dbf57c96SKate Arzamastseva // there was an external edit, 611dbf57c96SKate Arzamastseva // there is no log entry for current version of file 612ac3ed4afSGerrit Uitslag $sizechange = filesize($oldf); 61379e79377SAndreas Gohr if (!file_exists(mediaMetaFN($id, '.changes'))) { 614ac3ed4afSGerrit Uitslag addMediaLogEntry($date, $id, DOKU_CHANGE_TYPE_CREATE, $lang['created'], '', null, $sizechange); 615dbf57c96SKate Arzamastseva } else { 616ac3ed4afSGerrit Uitslag $oldRev = $medialog->getRevisions(-1, 1); // from changelog 617ac3ed4afSGerrit Uitslag $oldRev = (int) (empty($oldRev) ? 0 : $oldRev[0]); 618ac3ed4afSGerrit Uitslag $filesize_old = filesize(mediaFN($id, $oldRev)); 61924870174SAndreas Gohr $sizechange -= $filesize_old; 620ac3ed4afSGerrit Uitslag 621ac3ed4afSGerrit Uitslag addMediaLogEntry($date, $id, DOKU_CHANGE_TYPE_EDIT, '', '', null, $sizechange); 622dbf57c96SKate Arzamastseva } 623dbf57c96SKate Arzamastseva } 624dbf57c96SKate Arzamastseva 625e4f389efSKate Arzamastseva $newf = mediaFN($id, $date); 626e4f389efSKate Arzamastseva io_makeFileDir($newf); 627cbe26ad6SKate Arzamastseva if (copy($oldf, $newf)) { 628e4f389efSKate Arzamastseva // Set the correct permission here. 629e4f389efSKate Arzamastseva // Always chmod media because they may be saved with different permissions than expected from the php umask. 630e4f389efSKate Arzamastseva // (Should normally chmod to $conf['fperm'] only if $conf['fperm'] is set.) 631e4f389efSKate Arzamastseva chmod($newf, $conf['fmode']); 632e4f389efSKate Arzamastseva } 633e4f389efSKate Arzamastseva return $date; 634e4f389efSKate Arzamastseva} 635e4f389efSKate Arzamastseva 636e4f389efSKate Arzamastseva/** 6378cb1eb01SAndreas Gohr * This function checks if the uploaded content is really what the 63826ceae18SAndreas Gohr * mimetype says it is. We also do spam checking for text types here. 6398cb1eb01SAndreas Gohr * 6408cb1eb01SAndreas Gohr * We need to do this stuff because we can not rely on the browser 6418cb1eb01SAndreas Gohr * to do this check correctly. Yes, IE is broken as usual. 6428cb1eb01SAndreas Gohr * 6438cb1eb01SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 64426ceae18SAndreas Gohr * @link http://www.splitbrain.org/blog/2007-02/12-internet_explorer_facilitates_cross_site_scripting 6458cb1eb01SAndreas Gohr * @fixme check all 26 magic IE filetypes here? 64642ea7f44SGerrit Uitslag * 64742ea7f44SGerrit Uitslag * @param string $file path to file 64842ea7f44SGerrit Uitslag * @param string $mime mimetype 64942ea7f44SGerrit Uitslag * @return int 6508cb1eb01SAndreas Gohr */ 651d868eb89SAndreas Gohrfunction media_contentcheck($file, $mime) 652d868eb89SAndreas Gohr{ 65326ceae18SAndreas Gohr global $conf; 65426ceae18SAndreas Gohr if ($conf['iexssprotect']) { 65526ceae18SAndreas Gohr $fh = @fopen($file, 'rb'); 65626ceae18SAndreas Gohr if ($fh) { 65726ceae18SAndreas Gohr $bytes = fread($fh, 256); 65826ceae18SAndreas Gohr fclose($fh); 65926ceae18SAndreas Gohr if (preg_match('/<(script|a|img|html|body|iframe)[\s>]/i', $bytes)) { 66042ea7f44SGerrit Uitslag return -3; //XSS: possibly malicious content 66126ceae18SAndreas Gohr } 66226ceae18SAndreas Gohr } 66326ceae18SAndreas Gohr } 6646c16a3a9Sfiwswe if (str_starts_with($mime, 'image/')) { 6658cb1eb01SAndreas Gohr $info = @getimagesize($file); 6668cb1eb01SAndreas Gohr if ($mime == 'image/gif' && $info[2] != 1) { 66742ea7f44SGerrit Uitslag return -1; // uploaded content did not match the file extension 6688cb1eb01SAndreas Gohr } elseif ($mime == 'image/jpeg' && $info[2] != 2) { 6698cb1eb01SAndreas Gohr return -1; 6708cb1eb01SAndreas Gohr } elseif ($mime == 'image/png' && $info[2] != 3) { 6718cb1eb01SAndreas Gohr return -1; 6728cb1eb01SAndreas Gohr } 6738cb1eb01SAndreas Gohr # fixme maybe check other images types as well 6746c16a3a9Sfiwswe } elseif (str_starts_with($mime, 'text/')) { 6758cb1eb01SAndreas Gohr global $TEXT; 6768cb1eb01SAndreas Gohr $TEXT = io_readFile($file); 6778cb1eb01SAndreas Gohr if (checkwordblock()) { 67842ea7f44SGerrit Uitslag return -2; //blocked by the spam blacklist 6798cb1eb01SAndreas Gohr } 6808cb1eb01SAndreas Gohr } 6818cb1eb01SAndreas Gohr return 0; 6828cb1eb01SAndreas Gohr} 6833df72098SAndreas Gohr 6843df72098SAndreas Gohr/** 68575030359SAndreas Gohr * Send a notify mail on uploads 68675030359SAndreas Gohr * 68775030359SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 68842ea7f44SGerrit Uitslag * 68942ea7f44SGerrit Uitslag * @param string $id media id 69042ea7f44SGerrit Uitslag * @param string $file path to file 69142ea7f44SGerrit Uitslag * @param string $mime mime type 69242ea7f44SGerrit Uitslag * @param bool|int $old_rev revision timestamp or false 69375030359SAndreas Gohr */ 694d868eb89SAndreas Gohrfunction media_notify($id, $file, $mime, $old_rev = false, $current_rev = false) 695d868eb89SAndreas Gohr{ 69675030359SAndreas Gohr global $conf; 69779a2d784SGerrit Uitslag if (empty($conf['notify'])) return; //notify enabled? 69875030359SAndreas Gohr 699704a815fSMichael Große $subscription = new MediaSubscriptionSender(); 70079a2d784SGerrit Uitslag $subscription->sendMediaDiff($conf['notify'], 'uploadmail', $id, $old_rev, $current_rev); 70175030359SAndreas Gohr} 70275030359SAndreas Gohr 70375030359SAndreas Gohr/** 7043df72098SAndreas Gohr * List all files in a given Media namespace 70542ea7f44SGerrit Uitslag * 70621d806cdSGerrit Uitslag * @param string $ns namespace 70742ea7f44SGerrit Uitslag * @param null|int $auth permission level 70842ea7f44SGerrit Uitslag * @param string $jump id 70942ea7f44SGerrit Uitslag * @param bool $fullscreenview 7108702de7fSGerrit Uitslag * @param bool|string $sort sorting order, false skips sorting 7113df72098SAndreas Gohr */ 712d868eb89SAndreas Gohrfunction media_filelist($ns, $auth = null, $jump = '', $fullscreenview = false, $sort = false) 713d868eb89SAndreas Gohr{ 7143df72098SAndreas Gohr global $conf; 7153df72098SAndreas Gohr global $lang; 7163df72098SAndreas Gohr $ns = cleanID($ns); 7173df72098SAndreas Gohr 7183df72098SAndreas Gohr // check auth our self if not given (needed for ajax calls) 7193df72098SAndreas Gohr if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 7203df72098SAndreas Gohr 721d9162c6cSKate Arzamastseva if (!$fullscreenview) echo '<h1 id="media__ns">:' . hsc($ns) . '</h1>' . NL; 7223df72098SAndreas Gohr 7233df72098SAndreas Gohr if ($auth < AUTH_READ) { 7243df72098SAndreas Gohr // FIXME: print permission warning here instead? 7253df72098SAndreas Gohr echo '<div class="nothing">' . $lang['nothingfound'] . '</div>' . NL; 72656fe6664SAndreas Gohr } else { 72789274c0dSChristopher Smith if (!$fullscreenview) { 72889274c0dSChristopher Smith media_uploadform($ns, $auth); 72989274c0dSChristopher Smith media_searchform($ns); 73089274c0dSChristopher Smith } 7313df72098SAndreas Gohr 7323df72098SAndreas Gohr $dir = utf8_encodeFN(str_replace(':', '/', $ns)); 73324870174SAndreas Gohr $data = []; 734dccd6b2bSAndreas Gohr search( 735dccd6b2bSAndreas Gohr $data, 736dccd6b2bSAndreas Gohr $conf['mediadir'], 737dccd6b2bSAndreas Gohr 'search_mediafiles', 738dccd6b2bSAndreas Gohr ['showmsg' => true, 'depth' => 1], 739dccd6b2bSAndreas Gohr $dir, 740dccd6b2bSAndreas Gohr 1, 741dccd6b2bSAndreas Gohr $sort 742dccd6b2bSAndreas Gohr ); 7433df72098SAndreas Gohr 744093fe67eSAndreas Gohr if ($data === []) { 7453df72098SAndreas Gohr echo '<div class="nothing">' . $lang['nothingfound'] . '</div>' . NL; 7465b9353faSKate Arzamastseva } else { 7475b9353faSKate Arzamastseva if ($fullscreenview) { 748554a8c9fSAdrian Lang echo '<ul class="' . _media_get_list_type() . '">'; 7495b9353faSKate Arzamastseva } 7505b9353faSKate Arzamastseva foreach ($data as $item) { 7515b9353faSKate Arzamastseva if (!$fullscreenview) { 7524f33babfSAndreas Gohr //FIXME old call: media_printfile($item,$auth,$jump); 75379a2d784SGerrit Uitslag $display = new DisplayRow($item); 7549453716dSAndreas Gohr $display->scrollIntoView($jump == $item->getID()); 7554f33babfSAndreas Gohr $display->show(); 7565b9353faSKate Arzamastseva } else { 7574f33babfSAndreas Gohr //FIXME old call: media_printfile_thumbs($item,$auth,$jump); 7584f33babfSAndreas Gohr echo '<li>'; 75979a2d784SGerrit Uitslag $display = new DisplayTile($item); 7609453716dSAndreas Gohr $display->scrollIntoView($jump == $item->getID()); 7614f33babfSAndreas Gohr $display->show(); 7624f33babfSAndreas Gohr echo '</li>'; 7635b9353faSKate Arzamastseva } 7645b9353faSKate Arzamastseva } 76594add303SAnika Henke if ($fullscreenview) echo '</ul>' . NL; 7663df72098SAndreas Gohr } 76756fe6664SAndreas Gohr } 768d9162c6cSKate Arzamastseva} 769d9162c6cSKate Arzamastseva 770d9162c6cSKate Arzamastseva/** 771d9162c6cSKate Arzamastseva * Prints tabs for files list actions 772d9162c6cSKate Arzamastseva * 773d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 77495b451bcSAdrian Lang * @author Adrian Lang <mail@adrianlang.de> 77595b451bcSAdrian Lang * 776035e07f1SKate Arzamastseva * @param string $selected_tab - opened tab 777d9162c6cSKate Arzamastseva */ 77895b451bcSAdrian Lang 779d868eb89SAndreas Gohrfunction media_tabs_files($selected_tab = '') 780d868eb89SAndreas Gohr{ 781d9162c6cSKate Arzamastseva global $lang; 78224870174SAndreas Gohr $tabs = []; 7837d34963bSAndreas Gohr foreach ( 7847d34963bSAndreas Gohr [ 78524870174SAndreas Gohr 'files' => 'mediaselect', 78695b451bcSAdrian Lang 'upload' => 'media_uploadtab', 78724870174SAndreas Gohr 'search' => 'media_searchtab' 7887d34963bSAndreas Gohr ] as $tab => $caption 7897d34963bSAndreas Gohr ) { 79024870174SAndreas Gohr $tabs[$tab] = [ 79124870174SAndreas Gohr 'href' => media_managerURL(['tab_files' => $tab], '&'), 79224870174SAndreas Gohr 'caption' => $lang[$caption] 79324870174SAndreas Gohr ]; 79495b451bcSAdrian Lang } 795d9162c6cSKate Arzamastseva 79695b451bcSAdrian Lang html_tabs($tabs, $selected_tab); 797d9162c6cSKate Arzamastseva} 798d9162c6cSKate Arzamastseva 799d9162c6cSKate Arzamastseva/** 800d9162c6cSKate Arzamastseva * Prints tabs for files details actions 801d9162c6cSKate Arzamastseva * 802d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 803ebc28e69SAndreas Gohr * @param string $image filename of the current image 804ebc28e69SAndreas Gohr * @param string $selected_tab opened tab 805d9162c6cSKate Arzamastseva */ 806d868eb89SAndreas Gohrfunction media_tabs_details($image, $selected_tab = '') 807d868eb89SAndreas Gohr{ 808e5d185e1SKate Arzamastseva global $lang, $conf; 809d9162c6cSKate Arzamastseva 81024870174SAndreas Gohr $tabs = []; 81124870174SAndreas Gohr $tabs['view'] = [ 81224870174SAndreas Gohr 'href' => media_managerURL(['tab_details' => 'view'], '&'), 81324870174SAndreas Gohr 'caption' => $lang['media_viewtab'] 81424870174SAndreas Gohr ]; 815d9162c6cSKate Arzamastseva 81624870174SAndreas Gohr [, $mime] = mimetype($image); 81779e79377SAndreas Gohr if ($mime == 'image/jpeg' && file_exists(mediaFN($image))) { 81824870174SAndreas Gohr $tabs['edit'] = [ 81924870174SAndreas Gohr 'href' => media_managerURL(['tab_details' => 'edit'], '&'), 82024870174SAndreas Gohr 'caption' => $lang['media_edittab'] 82124870174SAndreas Gohr ]; 822dd9ba38eSKate Arzamastseva } 823e5d185e1SKate Arzamastseva if ($conf['mediarevisions']) { 82424870174SAndreas Gohr $tabs['history'] = [ 82524870174SAndreas Gohr 'href' => media_managerURL(['tab_details' => 'history'], '&'), 82624870174SAndreas Gohr 'caption' => $lang['media_historytab'] 82724870174SAndreas Gohr ]; 828e5d185e1SKate Arzamastseva } 829d9162c6cSKate Arzamastseva 83095b451bcSAdrian Lang html_tabs($tabs, $selected_tab); 831d9162c6cSKate Arzamastseva} 832d9162c6cSKate Arzamastseva 833d9162c6cSKate Arzamastseva/** 834d9162c6cSKate Arzamastseva * Prints options for the tab that displays a list of all files 835d9162c6cSKate Arzamastseva * 836d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 837d9162c6cSKate Arzamastseva */ 838d868eb89SAndreas Gohrfunction media_tab_files_options() 839d868eb89SAndreas Gohr{ 8408108113cSTom N Harris global $lang; 8418108113cSTom N Harris global $INPUT; 842b7e5821dSAndreas Gohr global $ID; 843b960c74fSSatoshi Sahara 844b960c74fSSatoshi Sahara $form = new Form([ 845b960c74fSSatoshi Sahara 'method' => 'get', 846b960c74fSSatoshi Sahara 'action' => wl($ID), 847b960c74fSSatoshi Sahara 'class' => 'options' 848b960c74fSSatoshi Sahara ]); 849b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 850b960c74fSSatoshi Sahara $form->setHiddenField('sectok', null); 851b960c74fSSatoshi Sahara $media_manager_params = media_managerURL([], '', false, true); 85238b2bf35SAnika Henke foreach ($media_manager_params as $pKey => $pVal) { 853b960c74fSSatoshi Sahara $form->setHiddenField($pKey, $pVal); 85438b2bf35SAnika Henke } 8558108113cSTom N Harris if ($INPUT->has('q')) { 856b960c74fSSatoshi Sahara $form->setHiddenField('q', $INPUT->str('q')); 857554a8c9fSAdrian Lang } 858b960c74fSSatoshi Sahara $form->addHTML('<ul>' . NL); 8597d34963bSAndreas Gohr foreach ( 8607d34963bSAndreas Gohr [ 86124870174SAndreas Gohr 'list' => ['listType', ['thumbs', 'rows']], 86224870174SAndreas Gohr 'sort' => ['sortBy', ['name', 'date']] 8637d34963bSAndreas Gohr ] as $group => $content 8647d34963bSAndreas Gohr ) { 865ec88e837SAndreas Gohr $checked = "_media_get_{$group}_type"; 866554a8c9fSAdrian Lang $checked = $checked(); 867d9162c6cSKate Arzamastseva 868b960c74fSSatoshi Sahara $form->addHTML('<li class="' . $content[0] . '">'); 86995b451bcSAdrian Lang foreach ($content[1] as $option) { 87024870174SAndreas Gohr $attrs = []; 871554a8c9fSAdrian Lang if ($checked == $option) { 87295b451bcSAdrian Lang $attrs['checked'] = 'checked'; 87395b451bcSAdrian Lang } 874b960c74fSSatoshi Sahara $radio = $form->addRadioButton( 875b960c74fSSatoshi Sahara $group . '_dwmedia', 876b960c74fSSatoshi Sahara $lang['media_' . $group . '_' . $option] 877b960c74fSSatoshi Sahara )->val($option)->id($content[0] . '__' . $option)->addClass($option); 878b960c74fSSatoshi Sahara $radio->attrs($attrs); 87995b451bcSAdrian Lang } 880b960c74fSSatoshi Sahara $form->addHTML('</li>' . NL); 88195b451bcSAdrian Lang } 882b960c74fSSatoshi Sahara $form->addHTML('<li>'); 883b960c74fSSatoshi Sahara $form->addButton('', $lang['btn_apply'])->attr('type', 'submit'); 884b960c74fSSatoshi Sahara $form->addHTML('</li>' . NL); 885b960c74fSSatoshi Sahara $form->addHTML('</ul>' . NL); 886b960c74fSSatoshi Sahara $form->addTagClose('div'); 88726dfc232SAndreas Gohr echo $form->toHTML(); 888d9162c6cSKate Arzamastseva} 889d9162c6cSKate Arzamastseva 890d9162c6cSKate Arzamastseva/** 89187deddfaSKate Arzamastseva * Returns type of sorting for the list of files in media manager 89287deddfaSKate Arzamastseva * 89387deddfaSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 89442ea7f44SGerrit Uitslag * 89587deddfaSKate Arzamastseva * @return string - sort type 89687deddfaSKate Arzamastseva */ 897d868eb89SAndreas Gohrfunction _media_get_sort_type() 898d868eb89SAndreas Gohr{ 89924870174SAndreas Gohr return _media_get_display_param('sort', ['default' => 'name', 'date']); 90087deddfaSKate Arzamastseva} 901554a8c9fSAdrian Lang 9026ffaeda9SGerrit Uitslag/** 9036ffaeda9SGerrit Uitslag * Returns type of listing for the list of files in media manager 9046ffaeda9SGerrit Uitslag * 9056ffaeda9SGerrit Uitslag * @author Kate Arzamastseva <pshns@ukr.net> 90642ea7f44SGerrit Uitslag * 9076ffaeda9SGerrit Uitslag * @return string - list type 9086ffaeda9SGerrit Uitslag */ 909d868eb89SAndreas Gohrfunction _media_get_list_type() 910d868eb89SAndreas Gohr{ 91124870174SAndreas Gohr return _media_get_display_param('list', ['default' => 'thumbs', 'rows']); 91287deddfaSKate Arzamastseva} 913554a8c9fSAdrian Lang 9146ffaeda9SGerrit Uitslag/** 9156ffaeda9SGerrit Uitslag * Get display parameters 9166ffaeda9SGerrit Uitslag * 9176ffaeda9SGerrit Uitslag * @param string $param name of parameter 9186ffaeda9SGerrit Uitslag * @param array $values allowed values, where default value has index key 'default' 9196ffaeda9SGerrit Uitslag * @return string the parameter value 9206ffaeda9SGerrit Uitslag */ 921d868eb89SAndreas Gohrfunction _media_get_display_param($param, $values) 922d868eb89SAndreas Gohr{ 9238108113cSTom N Harris global $INPUT; 9248108113cSTom N Harris if (in_array($INPUT->str($param), $values)) { 925554a8c9fSAdrian Lang // FIXME: Set cookie 9268108113cSTom N Harris return $INPUT->str($param); 927554a8c9fSAdrian Lang } else { 9283629bc8cSAdrian Lang $val = get_doku_pref($param, $values['default']); 9293629bc8cSAdrian Lang if (!in_array($val, $values)) { 9303629bc8cSAdrian Lang $val = $values['default']; 9313629bc8cSAdrian Lang } 9323629bc8cSAdrian Lang return $val; 933554a8c9fSAdrian Lang } 93487deddfaSKate Arzamastseva} 93587deddfaSKate Arzamastseva 93687deddfaSKate Arzamastseva/** 937d9162c6cSKate Arzamastseva * Prints tab that displays a list of all files 938d9162c6cSKate Arzamastseva * 939d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 94042ea7f44SGerrit Uitslag * 94142ea7f44SGerrit Uitslag * @param string $ns 94242ea7f44SGerrit Uitslag * @param null|int $auth permission level 94342ea7f44SGerrit Uitslag * @param string $jump item id 944d9162c6cSKate Arzamastseva */ 945d868eb89SAndreas Gohrfunction media_tab_files($ns, $auth = null, $jump = '') 946d868eb89SAndreas Gohr{ 947d9162c6cSKate Arzamastseva global $lang; 948d9162c6cSKate Arzamastseva if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 949d9162c6cSKate Arzamastseva 950d9162c6cSKate Arzamastseva if ($auth < AUTH_READ) { 95188a71175SKate Arzamastseva echo '<div class="nothing">' . $lang['media_perm_read'] . '</div>' . NL; 952d9162c6cSKate Arzamastseva } else { 95395b451bcSAdrian Lang media_filelist($ns, $auth, $jump, true, _media_get_sort_type()); 954d9162c6cSKate Arzamastseva } 955d9162c6cSKate Arzamastseva} 956d9162c6cSKate Arzamastseva 957d9162c6cSKate Arzamastseva/** 958d9162c6cSKate Arzamastseva * Prints tab that displays uploading form 959d9162c6cSKate Arzamastseva * 960d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 96142ea7f44SGerrit Uitslag * 96242ea7f44SGerrit Uitslag * @param string $ns 96342ea7f44SGerrit Uitslag * @param null|int $auth permission level 96442ea7f44SGerrit Uitslag * @param string $jump item id 965d9162c6cSKate Arzamastseva */ 966d868eb89SAndreas Gohrfunction media_tab_upload($ns, $auth = null, $jump = '') 967d868eb89SAndreas Gohr{ 968d9162c6cSKate Arzamastseva global $lang; 969d9162c6cSKate Arzamastseva if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 970d9162c6cSKate Arzamastseva 97194add303SAnika Henke echo '<div class="upload">' . NL; 97295b451bcSAdrian Lang if ($auth >= AUTH_UPLOAD) { 97395b451bcSAdrian Lang echo '<p>' . $lang['mediaupload'] . '</p>'; 97495b451bcSAdrian Lang } 975d9162c6cSKate Arzamastseva media_uploadform($ns, $auth, true); 97694add303SAnika Henke echo '</div>' . NL; 977d9162c6cSKate Arzamastseva} 978d9162c6cSKate Arzamastseva 979d9162c6cSKate Arzamastseva/** 980d9162c6cSKate Arzamastseva * Prints tab that displays search form 981d9162c6cSKate Arzamastseva * 982d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 98342ea7f44SGerrit Uitslag * 98442ea7f44SGerrit Uitslag * @param string $ns 98542ea7f44SGerrit Uitslag * @param null|int $auth permission level 986d9162c6cSKate Arzamastseva */ 987d868eb89SAndreas Gohrfunction media_tab_search($ns, $auth = null) 988d868eb89SAndreas Gohr{ 9898108113cSTom N Harris global $INPUT; 990d9162c6cSKate Arzamastseva 9918108113cSTom N Harris $do = $INPUT->str('mediado'); 9928108113cSTom N Harris $query = $INPUT->str('q'); 99394add303SAnika Henke echo '<div class="search">' . NL; 994d9162c6cSKate Arzamastseva 995d9162c6cSKate Arzamastseva media_searchform($ns, $query, true); 9962dba8df4SAdrian Lang if ($do == 'searchlist' || $query) { 99795b451bcSAdrian Lang media_searchlist($query, $ns, $auth, true, _media_get_sort_type()); 99895b451bcSAdrian Lang } 99994add303SAnika Henke echo '</div>' . NL; 1000d9162c6cSKate Arzamastseva} 1001d9162c6cSKate Arzamastseva 1002d9162c6cSKate Arzamastseva/** 1003d9162c6cSKate Arzamastseva * Prints tab that displays mediafile details 1004d9162c6cSKate Arzamastseva * 1005d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1006e0c26282SGerrit Uitslag * 1007e0c26282SGerrit Uitslag * @param string $image media id 1008e0c26282SGerrit Uitslag * @param string $ns 1009e0c26282SGerrit Uitslag * @param null|int $auth permission level 101042ea7f44SGerrit Uitslag * @param string|int $rev revision timestamp or empty string 1011d9162c6cSKate Arzamastseva */ 1012d868eb89SAndreas Gohrfunction media_tab_view($image, $ns, $auth = null, $rev = '') 1013d868eb89SAndreas Gohr{ 1014ebc28e69SAndreas Gohr global $lang; 1015d9162c6cSKate Arzamastseva if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 1016d9162c6cSKate Arzamastseva 1017e136d6ccSKate Arzamastseva if ($image && $auth >= AUTH_READ) { 1018dd9e8e5eSAndreas Gohr $mf = new MediaFile($image, $rev); 1019dd9e8e5eSAndreas Gohr echo (new Display($mf))->getDetailHtml(); 1020e136d6ccSKate Arzamastseva media_preview_buttons($image, $auth, $rev); 1021dd9e8e5eSAndreas Gohr media_details($image, $auth, $rev, $mf->getMeta()); 1022e136d6ccSKate Arzamastseva } else { 102394add303SAnika Henke echo '<div class="nothing">' . $lang['media_perm_read'] . '</div>' . NL; 1024e136d6ccSKate Arzamastseva } 1025d9162c6cSKate Arzamastseva} 1026d9162c6cSKate Arzamastseva 1027d9162c6cSKate Arzamastseva/** 1028d9162c6cSKate Arzamastseva * Prints tab that displays form for editing mediafile metadata 1029d9162c6cSKate Arzamastseva * 1030d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1031e0c26282SGerrit Uitslag * 1032e0c26282SGerrit Uitslag * @param string $image media id 1033e0c26282SGerrit Uitslag * @param string $ns 1034e0c26282SGerrit Uitslag * @param null|int $auth permission level 1035d9162c6cSKate Arzamastseva */ 1036d868eb89SAndreas Gohrfunction media_tab_edit($image, $ns, $auth = null) 1037d868eb89SAndreas Gohr{ 1038d9162c6cSKate Arzamastseva if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 1039d9162c6cSKate Arzamastseva 10401eeeced2SKate Arzamastseva if ($image) { 104124870174SAndreas Gohr [, $mime] = mimetype($image); 104230fd72fbSKate Arzamastseva if ($mime == 'image/jpeg') media_metaform($image, $auth); 10431eeeced2SKate Arzamastseva } 1044d9162c6cSKate Arzamastseva} 1045d9162c6cSKate Arzamastseva 1046d9162c6cSKate Arzamastseva/** 1047d9162c6cSKate Arzamastseva * Prints tab that displays mediafile revisions 1048d9162c6cSKate Arzamastseva * 1049d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1050e0c26282SGerrit Uitslag * 1051e0c26282SGerrit Uitslag * @param string $image media id 1052e0c26282SGerrit Uitslag * @param string $ns 1053e0c26282SGerrit Uitslag * @param null|int $auth permission level 1054d9162c6cSKate Arzamastseva */ 1055d868eb89SAndreas Gohrfunction media_tab_history($image, $ns, $auth = null) 1056d868eb89SAndreas Gohr{ 1057d9162c6cSKate Arzamastseva global $lang; 10588108113cSTom N Harris global $INPUT; 10598108113cSTom N Harris 1060d9162c6cSKate Arzamastseva if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*"); 10618108113cSTom N Harris $do = $INPUT->str('mediado'); 1062d9162c6cSKate Arzamastseva 10632e55802cSKate Arzamastseva if ($auth >= AUTH_READ && $image) { 10642e55802cSKate Arzamastseva if ($do == 'diff') { 106524870174SAndreas Gohr (new MediaDiff($image))->show(); //media_diff($image, $ns, $auth); 10662e55802cSKate Arzamastseva } else { 1067a46cc3dcSAndreas Gohr $first = $INPUT->int('first', -1); 106824870174SAndreas Gohr (new MediaRevisions($image))->show($first); 10692e55802cSKate Arzamastseva } 107088a71175SKate Arzamastseva } else { 107188a71175SKate Arzamastseva echo '<div class="nothing">' . $lang['media_perm_read'] . '</div>' . NL; 10722e55802cSKate Arzamastseva } 10733df72098SAndreas Gohr} 10743df72098SAndreas Gohr 10753df72098SAndreas Gohr/** 1076e136d6ccSKate Arzamastseva * Prints mediafile action buttons 1077e136d6ccSKate Arzamastseva * 1078e136d6ccSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1079e0c26282SGerrit Uitslag * 1080e0c26282SGerrit Uitslag * @param string $image media id 1081e0c26282SGerrit Uitslag * @param int $auth permission level 1082871895a7SSatoshi Sahara * @param int|string $rev revision timestamp, or empty string 1083e136d6ccSKate Arzamastseva */ 1084d868eb89SAndreas Gohrfunction media_preview_buttons($image, $auth, $rev = '') 1085d868eb89SAndreas Gohr{ 1086e5d185e1SKate Arzamastseva global $lang, $conf; 1087e136d6ccSKate Arzamastseva 1088871895a7SSatoshi Sahara echo '<ul class="actions">'; 10891eeeced2SKate Arzamastseva 109079e79377SAndreas Gohr if ($auth >= AUTH_DELETE && !$rev && file_exists(mediaFN($image))) { 1091e136d6ccSKate Arzamastseva // delete button 1092b960c74fSSatoshi Sahara $form = new Form([ 1093b960c74fSSatoshi Sahara 'id' => 'mediamanager__btn_delete', 1094b960c74fSSatoshi Sahara 'action' => media_managerURL(['delete' => $image], '&'), 1095b960c74fSSatoshi Sahara ]); 1096b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1097b960c74fSSatoshi Sahara $form->addButton('', $lang['btn_delete'])->attr('type', 'submit'); 1098b960c74fSSatoshi Sahara $form->addTagClose('div'); 109995b451bcSAdrian Lang echo '<li>'; 1100b960c74fSSatoshi Sahara echo $form->toHTML(); 1101871895a7SSatoshi Sahara echo '</li>'; 1102e5d185e1SKate Arzamastseva } 1103e5d185e1SKate Arzamastseva 1104e5d185e1SKate Arzamastseva $auth_ow = (($conf['mediarevisions']) ? AUTH_UPLOAD : AUTH_DELETE); 1105e5d185e1SKate Arzamastseva if ($auth >= $auth_ow && !$rev) { 1106e136d6ccSKate Arzamastseva // upload new version button 1107b960c74fSSatoshi Sahara $form = new Form([ 1108b960c74fSSatoshi Sahara 'id' => 'mediamanager__btn_update', 1109b960c74fSSatoshi Sahara 'action' => media_managerURL(['image' => $image, 'mediado' => 'update'], '&'), 1110b960c74fSSatoshi Sahara ]); 1111b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1112b960c74fSSatoshi Sahara $form->addButton('', $lang['media_update'])->attr('type', 'submit'); 1113b960c74fSSatoshi Sahara $form->addTagClose('div'); 111495b451bcSAdrian Lang echo '<li>'; 1115b960c74fSSatoshi Sahara echo $form->toHTML(); 1116871895a7SSatoshi Sahara echo '</li>'; 111770c3cc9aSKate Arzamastseva } 1118e136d6ccSKate Arzamastseva 111979e79377SAndreas Gohr if ($auth >= AUTH_UPLOAD && $rev && $conf['mediarevisions'] && file_exists(mediaFN($image, $rev))) { 1120e136d6ccSKate Arzamastseva // restore button 1121b960c74fSSatoshi Sahara $form = new Form([ 1122b960c74fSSatoshi Sahara 'id' => 'mediamanager__btn_restore', 1123b960c74fSSatoshi Sahara 'action' => media_managerURL(['image' => $image], '&'), 1124b960c74fSSatoshi Sahara ]); 1125b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1126b960c74fSSatoshi Sahara $form->setHiddenField('mediado', 'restore'); 1127b960c74fSSatoshi Sahara $form->setHiddenField('rev', $rev); 1128b960c74fSSatoshi Sahara $form->addButton('', $lang['media_restore'])->attr('type', 'submit'); 1129b960c74fSSatoshi Sahara $form->addTagClose('div'); 113095b451bcSAdrian Lang echo '<li>'; 1131b960c74fSSatoshi Sahara echo $form->toHTML(); 1132871895a7SSatoshi Sahara echo '</li>'; 11339c1bd4bcSKate Arzamastseva } 1134e136d6ccSKate Arzamastseva 1135871895a7SSatoshi Sahara echo '</ul>'; 11362e55802cSKate Arzamastseva} 11372e55802cSKate Arzamastseva 11382e55802cSKate Arzamastseva/** 1139fa8e5c77SKate Arzamastseva * Returns the requested EXIF/IPTC tag from the image meta 1140fa8e5c77SKate Arzamastseva * 1141fa8e5c77SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1142e0c26282SGerrit Uitslag * 114342ea7f44SGerrit Uitslag * @param array $tags array with tags, first existing is returned 1144fa8e5c77SKate Arzamastseva * @param JpegMeta $meta 114542ea7f44SGerrit Uitslag * @param string $alt alternative value 1146fa8e5c77SKate Arzamastseva * @return string 1147fa8e5c77SKate Arzamastseva */ 1148d868eb89SAndreas Gohrfunction media_getTag($tags, $meta = false, $alt = '') 1149d868eb89SAndreas Gohr{ 1150871895a7SSatoshi Sahara if (!$meta) return $alt; 1151fa8e5c77SKate Arzamastseva $info = $meta->getField($tags); 1152871895a7SSatoshi Sahara if (!$info) return $alt; 1153fa8e5c77SKate Arzamastseva return $info; 1154fa8e5c77SKate Arzamastseva} 1155fa8e5c77SKate Arzamastseva 1156fa8e5c77SKate Arzamastseva/** 1157e136d6ccSKate Arzamastseva * Returns mediafile tags 11582e55802cSKate Arzamastseva * 11592e55802cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1160e0c26282SGerrit Uitslag * 1161e136d6ccSKate Arzamastseva * @param JpegMeta $meta 116242ea7f44SGerrit Uitslag * @return array list of tags of the mediafile 11632e55802cSKate Arzamastseva */ 1164d868eb89SAndreas Gohrfunction media_file_tags($meta) 1165d868eb89SAndreas Gohr{ 1166532850edSKate Arzamastseva // load the field descriptions 11673e98e685SKate Arzamastseva static $fields = null; 11683e98e685SKate Arzamastseva if (is_null($fields)) { 11693e98e685SKate Arzamastseva $config_files = getConfigFiles('mediameta'); 11703e98e685SKate Arzamastseva foreach ($config_files as $config_file) { 117179e79377SAndreas Gohr if (file_exists($config_file)) include($config_file); 1172532850edSKate Arzamastseva } 1173532850edSKate Arzamastseva } 11741eeeced2SKate Arzamastseva 117524870174SAndreas Gohr $tags = []; 1176dd9ba38eSKate Arzamastseva 117724870174SAndreas Gohr foreach ($fields as $tag) { 117824870174SAndreas Gohr $t = []; 117924870174SAndreas Gohr if (!empty($tag[0])) $t = [$tag[0]]; 11800e80bb5eSChristopher Smith if (isset($tag[3]) && is_array($tag[3])) $t = array_merge($t, $tag[3]); 1181e136d6ccSKate Arzamastseva $value = media_getTag($t, $meta); 118224870174SAndreas Gohr $tags[] = ['tag' => $tag, 'value' => $value]; 1183e136d6ccSKate Arzamastseva } 1184e136d6ccSKate Arzamastseva 1185e136d6ccSKate Arzamastseva return $tags; 1186e136d6ccSKate Arzamastseva} 1187e136d6ccSKate Arzamastseva 1188e136d6ccSKate Arzamastseva/** 1189e136d6ccSKate Arzamastseva * Prints mediafile tags 1190e136d6ccSKate Arzamastseva * 1191e136d6ccSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 119242ea7f44SGerrit Uitslag * 1193e0c26282SGerrit Uitslag * @param string $image image id 1194e0c26282SGerrit Uitslag * @param int $auth permission level 1195e0c26282SGerrit Uitslag * @param string|int $rev revision timestamp, or empty string 1196e0c26282SGerrit Uitslag * @param bool|JpegMeta $meta image object, or create one if false 1197e0c26282SGerrit Uitslag */ 1198d868eb89SAndreas Gohrfunction media_details($image, $auth, $rev = '', $meta = false) 1199d868eb89SAndreas Gohr{ 1200e136d6ccSKate Arzamastseva global $lang; 1201e136d6ccSKate Arzamastseva 1202e136d6ccSKate Arzamastseva if (!$meta) $meta = new JpegMeta(mediaFN($image, $rev)); 1203e136d6ccSKate Arzamastseva $tags = media_file_tags($meta); 1204e136d6ccSKate Arzamastseva 120594add303SAnika Henke echo '<dl>' . NL; 1206e136d6ccSKate Arzamastseva foreach ($tags as $tag) { 1207e136d6ccSKate Arzamastseva if ($tag['value']) { 1208e136d6ccSKate Arzamastseva $value = cleanText($tag['value']); 1209fde860beSGerrit Uitslag echo '<dt>' . $lang[$tag['tag'][1]] . '</dt><dd>'; 12104a90f94bSSatoshi Sahara if ($tag['tag'][2] == 'date') { 12114a90f94bSSatoshi Sahara echo dformat($value); 12124a90f94bSSatoshi Sahara } else { 12134a90f94bSSatoshi Sahara echo hsc($value); 12144a90f94bSSatoshi Sahara } 121594add303SAnika Henke echo '</dd>' . NL; 12161eeeced2SKate Arzamastseva } 1217e136d6ccSKate Arzamastseva } 121894add303SAnika Henke echo '</dl>' . NL; 121922e68399Sflammy echo '<dl>' . NL; 122022e68399Sflammy echo '<dt>' . $lang['reference'] . ':</dt>'; 12216734bb8cSAndreas Gohr $media_usage = (new MetadataSearch())->mediause($image, true); 122224870174SAndreas Gohr if ($media_usage !== []) { 122322e68399Sflammy foreach ($media_usage as $path) { 122422e68399Sflammy echo '<dd>' . html_wikilink($path) . '</dd>'; 122522e68399Sflammy } 122622e68399Sflammy } else { 122722e68399Sflammy echo '<dd>' . $lang['nothingfound'] . '</dd>'; 122822e68399Sflammy } 122922e68399Sflammy echo '</dl>' . NL; 12301eeeced2SKate Arzamastseva} 12312e55802cSKate Arzamastseva 12322e55802cSKate Arzamastseva/** 12332e55802cSKate Arzamastseva * Shows difference between two revisions of file 12342e55802cSKate Arzamastseva * 12352e55802cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 123642ea7f44SGerrit Uitslag * 1237e0c26282SGerrit Uitslag * @param string $image image id 1238e0c26282SGerrit Uitslag * @param string $ns 1239e0c26282SGerrit Uitslag * @param int $auth permission level 1240e0c26282SGerrit Uitslag * @param bool $fromajax 124179a2d784SGerrit Uitslag * 1242297071beSSatoshi Sahara * @deprecated 2020-12-31 1243e0c26282SGerrit Uitslag */ 1244d868eb89SAndreas Gohrfunction media_diff($image, $ns, $auth, $fromajax = false) 1245d868eb89SAndreas Gohr{ 124679a2d784SGerrit Uitslag dbg_deprecated('see ' . MediaDiff::class . '::show()'); 124759e81a43SKate Arzamastseva} 124859e81a43SKate Arzamastseva 12496ffaeda9SGerrit Uitslag/** 12506ffaeda9SGerrit Uitslag * Callback for media file diff 12516ffaeda9SGerrit Uitslag * 125242ea7f44SGerrit Uitslag * @param array $data event data 125379a2d784SGerrit Uitslag * 1254297071beSSatoshi Sahara * @deprecated 2020-12-31 12556ffaeda9SGerrit Uitslag */ 1256d868eb89SAndreas Gohrfunction _media_file_diff($data) 1257d868eb89SAndreas Gohr{ 125879a2d784SGerrit Uitslag dbg_deprecated('see ' . MediaDiff::class . '::show()'); 125959e81a43SKate Arzamastseva} 126059e81a43SKate Arzamastseva 126159e81a43SKate Arzamastseva/** 126259e81a43SKate Arzamastseva * Shows difference between two revisions of image 126359e81a43SKate Arzamastseva * 126459e81a43SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1265e0c26282SGerrit Uitslag * 1266e0c26282SGerrit Uitslag * @param string $image 1267e0c26282SGerrit Uitslag * @param string|int $l_rev revision timestamp, or empty string 1268e0c26282SGerrit Uitslag * @param string|int $r_rev revision timestamp, or empty string 1269e0c26282SGerrit Uitslag * @param string $ns 1270e0c26282SGerrit Uitslag * @param int $auth permission level 1271e0c26282SGerrit Uitslag * @param bool $fromajax 1272297071beSSatoshi Sahara * @deprecated 2020-12-31 127359e81a43SKate Arzamastseva */ 1274d868eb89SAndreas Gohrfunction media_file_diff($image, $l_rev, $r_rev, $ns, $auth, $fromajax) 1275d868eb89SAndreas Gohr{ 127679a2d784SGerrit Uitslag dbg_deprecated('see ' . MediaDiff::class . '::showFileDiff()'); 1277e136d6ccSKate Arzamastseva} 1278e136d6ccSKate Arzamastseva 1279e136d6ccSKate Arzamastseva/** 1280e136d6ccSKate Arzamastseva * Prints two images side by side 1281fa8e5c77SKate Arzamastseva * and slider 1282e136d6ccSKate Arzamastseva * 1283e136d6ccSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 128442ea7f44SGerrit Uitslag * 128542ea7f44SGerrit Uitslag * @param string $image image id 1286e0c26282SGerrit Uitslag * @param int $l_rev revision timestamp, or empty string 1287e0c26282SGerrit Uitslag * @param int $r_rev revision timestamp, or empty string 128842ea7f44SGerrit Uitslag * @param array $l_size array with width and height 128942ea7f44SGerrit Uitslag * @param array $r_size array with width and height 129050fc55feSKate Arzamastseva * @param string $type 1291297071beSSatoshi Sahara * @deprecated 2020-12-31 1292e136d6ccSKate Arzamastseva */ 1293d868eb89SAndreas Gohrfunction media_image_diff($image, $l_rev, $r_rev, $l_size, $r_size, $type) 1294d868eb89SAndreas Gohr{ 129579a2d784SGerrit Uitslag dbg_deprecated('see ' . MediaDiff::class . '::showImageDiff()'); 12961eeeced2SKate Arzamastseva} 12971eeeced2SKate Arzamastseva 12981eeeced2SKate Arzamastseva/** 12999c1bd4bcSKate Arzamastseva * Restores an old revision of a media file 13009c1bd4bcSKate Arzamastseva * 130142ea7f44SGerrit Uitslag * @param string $image media id 130242ea7f44SGerrit Uitslag * @param int $rev revision timestamp or empty string 13039c1bd4bcSKate Arzamastseva * @param int $auth 13049c1bd4bcSKate Arzamastseva * @return string - file's id 130542ea7f44SGerrit Uitslag * 13069c1bd4bcSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 13079c1bd4bcSKate Arzamastseva */ 1308d868eb89SAndreas Gohrfunction media_restore($image, $rev, $auth) 1309d868eb89SAndreas Gohr{ 1310e5d185e1SKate Arzamastseva global $conf; 131180525638SKate Arzamastseva if ($auth < AUTH_UPLOAD || !$conf['mediarevisions']) return false; 131292cac9a9SKate Arzamastseva $removed = (!file_exists(mediaFN($image)) && file_exists(mediaMetaFN($image, '.changes'))); 131392cac9a9SKate Arzamastseva if (!$image || (!file_exists(mediaFN($image)) && !$removed)) return false; 13149c1bd4bcSKate Arzamastseva if (!$rev || !file_exists(mediaFN($image, $rev))) return false; 131524870174SAndreas Gohr [, $imime, ] = mimetype($image); 1316dccd6b2bSAndreas Gohr $res = media_upload_finish( 1317dccd6b2bSAndreas Gohr mediaFN($image, $rev), 13189c1bd4bcSKate Arzamastseva mediaFN($image), 13199c1bd4bcSKate Arzamastseva $image, 13209c1bd4bcSKate Arzamastseva $imime, 13219c1bd4bcSKate Arzamastseva true, 1322dccd6b2bSAndreas Gohr 'copy' 1323dccd6b2bSAndreas Gohr ); 13249c1bd4bcSKate Arzamastseva if (is_array($res)) { 13259c1bd4bcSKate Arzamastseva msg($res[0], $res[1]); 13269c1bd4bcSKate Arzamastseva return false; 13279c1bd4bcSKate Arzamastseva } 13289c1bd4bcSKate Arzamastseva return $res; 13299c1bd4bcSKate Arzamastseva} 13309c1bd4bcSKate Arzamastseva 13319c1bd4bcSKate Arzamastseva/** 1332bf1f3ac4Ssarnowski * List all files found by the search request 1333c9f56829SAndreas Gohr * 1334c9f56829SAndreas Gohr * @author Tobias Sarnowski <sarnowski@cosmocode.de> 1335c9f56829SAndreas Gohr * @author Andreas Gohr <gohr@cosmocode.de> 1336d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1337c9f56829SAndreas Gohr * @triggers MEDIA_SEARCH 1338e0c26282SGerrit Uitslag * 1339e0c26282SGerrit Uitslag * @param string $query 1340e0c26282SGerrit Uitslag * @param string $ns 1341e0c26282SGerrit Uitslag * @param null|int $auth 1342e0c26282SGerrit Uitslag * @param bool $fullscreen 1343e0c26282SGerrit Uitslag * @param string $sort 1344bf1f3ac4Ssarnowski */ 1345d868eb89SAndreas Gohrfunction media_searchlist($query, $ns, $auth = null, $fullscreen = false, $sort = 'natural') 1346d868eb89SAndreas Gohr{ 1347bf1f3ac4Ssarnowski global $conf; 1348bf1f3ac4Ssarnowski global $lang; 13498e69fd30SKate Arzamastseva 1350bf1f3ac4Ssarnowski $ns = cleanID($ns); 135124870174SAndreas Gohr $evdata = [ 135256fe6664SAndreas Gohr 'ns' => $ns, 135324870174SAndreas Gohr 'data' => [], 135456fe6664SAndreas Gohr 'query' => $query 135524870174SAndreas Gohr ]; 13567ed31746SSzymon Olewniczak if (!blank($query)) { 1357e1d9dcc8SAndreas Gohr $evt = new Event('MEDIA_SEARCH', $evdata); 1358bf1f3ac4Ssarnowski if ($evt->advise_before()) { 135956fe6664SAndreas Gohr $dir = utf8_encodeFN(str_replace(':', '/', $evdata['ns'])); 136076472096SSzymon Olewniczak $quoted = preg_quote($evdata['query'], '/'); 136176472096SSzymon Olewniczak //apply globbing 136224870174SAndreas Gohr $quoted = str_replace(['\*', '\?'], ['.*', '.'], $quoted, $count); 136323e31e76SSzymon Olewniczak 136423e31e76SSzymon Olewniczak //if we use globbing file name must match entirely but may be preceded by arbitrary namespace 136523e31e76SSzymon Olewniczak if ($count > 0) $quoted = '^([^:]*:)*' . $quoted . '$'; 136623e31e76SSzymon Olewniczak 136776472096SSzymon Olewniczak $pattern = '/' . $quoted . '/i'; 1368dccd6b2bSAndreas Gohr search( 1369dccd6b2bSAndreas Gohr $evdata['data'], 137056fe6664SAndreas Gohr $conf['mediadir'], 13714f33babfSAndreas Gohr 'search_mediafiles', 137224870174SAndreas Gohr ['showmsg' => false, 'pattern' => $pattern], 137300e3e394SChristopher Smith $dir, 137400e3e394SChristopher Smith 1, 1375dccd6b2bSAndreas Gohr $sort 1376dccd6b2bSAndreas Gohr ); 1377bf1f3ac4Ssarnowski } 1378bf1f3ac4Ssarnowski $evt->advise_after(); 1379bf1f3ac4Ssarnowski unset($evt); 138056fe6664SAndreas Gohr } 1381bf1f3ac4Ssarnowski 1382d9162c6cSKate Arzamastseva if (!$fullscreen) { 138356fe6664SAndreas Gohr echo '<h1 id="media__ns">' . sprintf($lang['searchmedia_in'], hsc($ns) . ':*') . '</h1>' . NL; 138456fe6664SAndreas Gohr media_searchform($ns, $query); 1385d9162c6cSKate Arzamastseva } 138656fe6664SAndreas Gohr 138756fe6664SAndreas Gohr if (!count($evdata['data'])) { 1388bf1f3ac4Ssarnowski echo '<div class="nothing">' . $lang['nothingfound'] . '</div>' . NL; 13895b9353faSKate Arzamastseva } else { 13905b9353faSKate Arzamastseva if ($fullscreen) { 1391554a8c9fSAdrian Lang echo '<ul class="' . _media_get_list_type() . '">'; 13925b9353faSKate Arzamastseva } 13935b9353faSKate Arzamastseva foreach ($evdata['data'] as $item) { 13944f33babfSAndreas Gohr if (!$fullscreen) { 13954f33babfSAndreas Gohr // FIXME old call: media_printfile($item,$item['perm'],'',true); 139679a2d784SGerrit Uitslag $display = new DisplayRow($item); 139779b00823SAndreas Gohr $display->relativeDisplay($ns); 13984f33babfSAndreas Gohr $display->show(); 13994f33babfSAndreas Gohr } else { 14004f33babfSAndreas Gohr // FIXME old call: media_printfile_thumbs($item,$item['perm'],false,true); 140179a2d784SGerrit Uitslag $display = new DisplayTile($item); 140279b00823SAndreas Gohr $display->relativeDisplay($ns); 14034f33babfSAndreas Gohr echo '<li>'; 14044f33babfSAndreas Gohr $display->show(); 14054f33babfSAndreas Gohr echo '</li>'; 14064f33babfSAndreas Gohr } 1407bf1f3ac4Ssarnowski } 140894add303SAnika Henke if ($fullscreen) echo '</ul>' . NL; 14095b9353faSKate Arzamastseva } 1410bf1f3ac4Ssarnowski} 1411bf1f3ac4Ssarnowski 1412bf1f3ac4Ssarnowski/** 1413c6571d58SAndreas Gohr * Display a media icon 1414c6571d58SAndreas Gohr * 141542ea7f44SGerrit Uitslag * @param string $filename media id 1416c6571d58SAndreas Gohr * @param string $size the size subfolder, if not specified 16x16 is used 141742ea7f44SGerrit Uitslag * @return string html 1418c6571d58SAndreas Gohr */ 1419d868eb89SAndreas Gohrfunction media_printicon($filename, $size = '') 1420d868eb89SAndreas Gohr{ 142124870174SAndreas Gohr [$ext] = mimetype(mediaFN($filename), false); 142223786fd7SKate Arzamastseva 142379e79377SAndreas Gohr if (file_exists(DOKU_INC . 'lib/images/fileicons/' . $size . '/' . $ext . '.png')) { 1424c6571d58SAndreas Gohr $icon = DOKU_BASE . 'lib/images/fileicons/' . $size . '/' . $ext . '.png'; 142523786fd7SKate Arzamastseva } else { 1426c6571d58SAndreas Gohr $icon = DOKU_BASE . 'lib/images/fileicons/' . $size . '/file.png'; 142723786fd7SKate Arzamastseva } 142823786fd7SKate Arzamastseva 1429421ec38eSKate Arzamastseva return '<img src="' . $icon . '" alt="' . $filename . '" class="icon" />'; 143023786fd7SKate Arzamastseva} 143123786fd7SKate Arzamastseva 14323df72098SAndreas Gohr/** 143342ea7f44SGerrit Uitslag * Build link based on the current, adding/rewriting parameters 1434d9162c6cSKate Arzamastseva * 1435d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 143642ea7f44SGerrit Uitslag * 1437ebc28e69SAndreas Gohr * @param array|bool $params 143842ea7f44SGerrit Uitslag * @param string $amp separator 143942ea7f44SGerrit Uitslag * @param bool $abs absolute url? 144042ea7f44SGerrit Uitslag * @param bool $params_array return the parmeters array? 144142ea7f44SGerrit Uitslag * @return string|array - link or link parameters 1442d9162c6cSKate Arzamastseva */ 1443d868eb89SAndreas Gohrfunction media_managerURL($params = false, $amp = '&', $abs = false, $params_array = false) 1444d868eb89SAndreas Gohr{ 1445d9162c6cSKate Arzamastseva global $ID; 14468108113cSTom N Harris global $INPUT; 1447d9162c6cSKate Arzamastseva 144824870174SAndreas Gohr $gets = ['do' => 'media']; 144924870174SAndreas Gohr $media_manager_params = ['tab_files', 'tab_details', 'image', 'ns', 'list', 'sort']; 145023846a98SKate Arzamastseva foreach ($media_manager_params as $x) { 14518108113cSTom N Harris if ($INPUT->has($x)) $gets[$x] = $INPUT->str($x); 145223846a98SKate Arzamastseva } 1453d9162c6cSKate Arzamastseva 1454d9162c6cSKate Arzamastseva if ($params) { 1455554a8c9fSAdrian Lang $gets = $params + $gets; 1456d9162c6cSKate Arzamastseva } 1457d9162c6cSKate Arzamastseva unset($gets['id']); 1458554a8c9fSAdrian Lang if (isset($gets['delete'])) { 14591eeeced2SKate Arzamastseva unset($gets['image']); 14601eeeced2SKate Arzamastseva unset($gets['tab_details']); 14611eeeced2SKate Arzamastseva } 1462d9162c6cSKate Arzamastseva 1463035e07f1SKate Arzamastseva if ($params_array) return $gets; 1464035e07f1SKate Arzamastseva 14656dd095f5SKate Arzamastseva return wl($ID, $gets, $abs, $amp); 1466d9162c6cSKate Arzamastseva} 1467d9162c6cSKate Arzamastseva 1468d9162c6cSKate Arzamastseva/** 14693df72098SAndreas Gohr * Print the media upload form if permissions are correct 14703df72098SAndreas Gohr * 14713df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 1472d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1473e0c26282SGerrit Uitslag * 1474e0c26282SGerrit Uitslag * @param string $ns 1475e0c26282SGerrit Uitslag * @param int $auth permission level 1476e0c26282SGerrit Uitslag * @param bool $fullscreen 14773df72098SAndreas Gohr */ 1478d868eb89SAndreas Gohrfunction media_uploadform($ns, $auth, $fullscreen = false) 1479d868eb89SAndreas Gohr{ 14808108113cSTom N Harris global $lang; 14818108113cSTom N Harris global $conf; 14828108113cSTom N Harris global $INPUT; 14833df72098SAndreas Gohr 148488a71175SKate Arzamastseva if ($auth < AUTH_UPLOAD) { 148588a71175SKate Arzamastseva echo '<div class="nothing">' . $lang['media_perm_upload'] . '</div>' . NL; 148688a71175SKate Arzamastseva return; 148788a71175SKate Arzamastseva } 148892cac9a9SKate Arzamastseva $auth_ow = (($conf['mediarevisions']) ? AUTH_UPLOAD : AUTH_DELETE); 14893df72098SAndreas Gohr 149070c3cc9aSKate Arzamastseva $update = false; 149170c3cc9aSKate Arzamastseva $id = ''; 14928108113cSTom N Harris if ($auth >= $auth_ow && $fullscreen && $INPUT->str('mediado') == 'update') { 149370c3cc9aSKate Arzamastseva $update = true; 14948108113cSTom N Harris $id = cleanID($INPUT->str('image')); 149570c3cc9aSKate Arzamastseva } 149670c3cc9aSKate Arzamastseva 1497d00ec455SAndreas Gohr // The default HTML upload form 1498b960c74fSSatoshi Sahara $form = new Form([ 1499b960c74fSSatoshi Sahara 'id' => 'dw__upload', 1500b960c74fSSatoshi Sahara 'enctype' => 'multipart/form-data', 1501b960c74fSSatoshi Sahara 'action' => ($fullscreen) 1502b960c74fSSatoshi Sahara ? media_managerURL(['tab_files' => 'files', 'tab_details' => 'view'], '&') 1503b960c74fSSatoshi Sahara : DOKU_BASE . 'lib/exe/mediamanager.php', 1504b960c74fSSatoshi Sahara ]); 1505b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1506b960c74fSSatoshi Sahara $form->setHiddenField('ns', hsc($ns)); // FIXME hsc required? 1507b960c74fSSatoshi Sahara $form->addTagOpen('p'); 1508b960c74fSSatoshi Sahara $form->addTextInput('upload', $lang['txt_upload'])->id('upload__file') 1509b960c74fSSatoshi Sahara ->attrs(['type' => 'file']); 1510b960c74fSSatoshi Sahara $form->addTagClose('p'); 1511b960c74fSSatoshi Sahara $form->addTagOpen('p'); 1512b960c74fSSatoshi Sahara $form->addTextInput('mediaid', $lang['txt_filename'])->id('upload__name') 1513b960c74fSSatoshi Sahara ->val(noNS($id)); 1514b960c74fSSatoshi Sahara $form->addButton('', $lang['btn_upload'])->attr('type', 'submit'); 1515b960c74fSSatoshi Sahara $form->addTagClose('p'); 151692cac9a9SKate Arzamastseva if ($auth >= $auth_ow) { 1517b960c74fSSatoshi Sahara $form->addTagOpen('p'); 151824870174SAndreas Gohr $attrs = []; 151970c3cc9aSKate Arzamastseva if ($update) $attrs['checked'] = 'checked'; 1520b960c74fSSatoshi Sahara $form->addCheckbox('ow', $lang['txt_overwrt'])->id('dw__ow')->val('1') 1521b960c74fSSatoshi Sahara ->addClass('check')->attrs($attrs); 1522b960c74fSSatoshi Sahara $form->addTagClose('p'); 1523b960c74fSSatoshi Sahara } 1524b960c74fSSatoshi Sahara $form->addTagClose('div'); 1525b960c74fSSatoshi Sahara 1526b960c74fSSatoshi Sahara if (!$fullscreen) { 1527b960c74fSSatoshi Sahara echo '<div class="upload">' . $lang['mediaupload'] . '</div>' . DOKU_LF; 1528b960c74fSSatoshi Sahara } else { 1529b960c74fSSatoshi Sahara echo DOKU_LF; 15303df72098SAndreas Gohr } 1531c472bad9SKate Arzamastseva 1532b960c74fSSatoshi Sahara echo '<div id="mediamanager__uploader">' . DOKU_LF; 1533c6977b3aSSatoshi Sahara echo $form->toHTML('Upload'); 1534b960c74fSSatoshi Sahara echo '</div>' . DOKU_LF; 1535f940e4a0SAndreas Gohr 1536f940e4a0SAndreas Gohr echo '<p class="maxsize">'; 1537f940e4a0SAndreas Gohr printf($lang['maxuploadsize'], filesize_h(media_getuploadsize())); 153856fc6b15SAnna Dabrowska echo ' <a class="allowedmime" href="#">' . $lang['allowedmime'] . '</a>'; 1539499d9bcdSAndreas Gohr echo ' <span>' . implode(', ', array_keys(getMimeTypes())) . '</span>'; 1540b960c74fSSatoshi Sahara echo '</p>' . DOKU_LF; 1541f940e4a0SAndreas Gohr} 1542f940e4a0SAndreas Gohr 1543f940e4a0SAndreas Gohr/** 1544f940e4a0SAndreas Gohr * Returns the size uploaded files may have 1545f940e4a0SAndreas Gohr * 1546f940e4a0SAndreas Gohr * This uses a conservative approach using the lowest number found 1547f940e4a0SAndreas Gohr * in any of the limiting ini settings 1548f940e4a0SAndreas Gohr * 1549f940e4a0SAndreas Gohr * @returns int size in bytes 1550f940e4a0SAndreas Gohr */ 1551d868eb89SAndreas Gohrfunction media_getuploadsize() 1552d868eb89SAndreas Gohr{ 1553f940e4a0SAndreas Gohr $okay = 0; 1554f940e4a0SAndreas Gohr 155524870174SAndreas Gohr $post = php_to_byte(@ini_get('post_max_size')); 155624870174SAndreas Gohr $suho = php_to_byte(@ini_get('suhosin.post.max_value_length')); 155724870174SAndreas Gohr $upld = php_to_byte(@ini_get('upload_max_filesize')); 1558f940e4a0SAndreas Gohr 155924870174SAndreas Gohr if ($post && ($post < $okay || $okay === 0)) $okay = $post; 1560f940e4a0SAndreas Gohr if ($suho && ($suho < $okay || $okay == 0)) $okay = $suho; 1561f940e4a0SAndreas Gohr if ($upld && ($upld < $okay || $okay == 0)) $okay = $upld; 1562f940e4a0SAndreas Gohr 1563f940e4a0SAndreas Gohr return $okay; 15649f5dde7fSMichael Klier} 15653df72098SAndreas Gohr 15663df72098SAndreas Gohr/** 1567bf1f3ac4Ssarnowski * Print the search field form 1568bf1f3ac4Ssarnowski * 1569bf1f3ac4Ssarnowski * @author Tobias Sarnowski <sarnowski@cosmocode.de> 1570d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net> 1571e0c26282SGerrit Uitslag * 1572e0c26282SGerrit Uitslag * @param string $ns 1573e0c26282SGerrit Uitslag * @param string $query 1574e0c26282SGerrit Uitslag * @param bool $fullscreen 1575bf1f3ac4Ssarnowski */ 1576d868eb89SAndreas Gohrfunction media_searchform($ns, $query = '', $fullscreen = false) 1577d868eb89SAndreas Gohr{ 1578bf1f3ac4Ssarnowski global $lang; 1579bf1f3ac4Ssarnowski 1580bf1f3ac4Ssarnowski // The default HTML search form 1581b960c74fSSatoshi Sahara $form = new Form([ 1582b960c74fSSatoshi Sahara 'id' => 'dw__mediasearch', 1583b960c74fSSatoshi Sahara 'action' => ($fullscreen) 1584b960c74fSSatoshi Sahara ? media_managerURL([], '&') 1585b960c74fSSatoshi Sahara : DOKU_BASE . 'lib/exe/mediamanager.php', 1586b960c74fSSatoshi Sahara ]); 1587b960c74fSSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1588b960c74fSSatoshi Sahara $form->setHiddenField('ns', $ns); 1589b960c74fSSatoshi Sahara $form->setHiddenField($fullscreen ? 'mediado' : 'do', 'searchlist'); 1590554a8c9fSAdrian Lang 1591b960c74fSSatoshi Sahara $form->addTagOpen('p'); 1592bde2a644SSatoshi Sahara $form->addTextInput('q', $lang['searchmedia']) 1593b960c74fSSatoshi Sahara ->attr('title', sprintf($lang['searchmedia_in'], hsc($ns) . ':*')) 1594b960c74fSSatoshi Sahara ->val($query); 1595bde2a644SSatoshi Sahara $form->addHTML(' '); 1596b960c74fSSatoshi Sahara $form->addButton('', $lang['btn_search'])->attr('type', 'submit'); 1597b960c74fSSatoshi Sahara $form->addTagClose('p'); 1598b960c74fSSatoshi Sahara $form->addTagClose('div'); 159926dfc232SAndreas Gohr echo $form->toHTML('SearchMedia'); 1600bf1f3ac4Ssarnowski} 1601bf1f3ac4Ssarnowski 1602bf1f3ac4Ssarnowski/** 16033df72098SAndreas Gohr * Build a tree outline of available media namespaces 16043df72098SAndreas Gohr * 16053df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 1606e0c26282SGerrit Uitslag * 1607e0c26282SGerrit Uitslag * @param string $ns 16083df72098SAndreas Gohr */ 1609d868eb89SAndreas Gohrfunction media_nstree($ns) 1610d868eb89SAndreas Gohr{ 16113df72098SAndreas Gohr global $conf; 1612256ca81eSAndreas Gohr global $lang; 16133df72098SAndreas Gohr 16143df72098SAndreas Gohr // currently selected namespace 16153df72098SAndreas Gohr $ns = cleanID($ns); 16163df72098SAndreas Gohr if (empty($ns)) { 1617de3eb1d7SAdrian Lang global $ID; 1618dd90013aSMichael Hamann $ns = (string)getNS($ID); 16193df72098SAndreas Gohr } 1620dd90013aSMichael Hamann 1621dd90013aSMichael Hamann $ns_dir = utf8_encodeFN(str_replace(':', '/', $ns)); 16223df72098SAndreas Gohr 162324870174SAndreas Gohr $data = []; 162424870174SAndreas Gohr search($data, $conf['mediadir'], 'search_index', ['ns' => $ns_dir, 'nofiles' => true]); 16253df72098SAndreas Gohr 16263df72098SAndreas Gohr // wrap a list with the root level around the other namespaces 162724870174SAndreas Gohr array_unshift($data, ['level' => 0, 'id' => '', 'open' => 'true', 'label' => '[' . $lang['mediaroot'] . ']']); 16283df72098SAndreas Gohr 1629dd90013aSMichael Hamann // insert the current ns into the hierarchy if it isn't already part of it 1630dd90013aSMichael Hamann $ns_parts = explode(':', $ns); 1631dd90013aSMichael Hamann $tmp_ns = ''; 1632dd90013aSMichael Hamann $pos = 0; 1633de301a35SDamien Regad $insert = false; 1634dd90013aSMichael Hamann foreach ($ns_parts as $level => $part) { 1635186263b2SDamien Regad if ($tmp_ns) { 1636186263b2SDamien Regad $tmp_ns .= ':' . $part; 1637186263b2SDamien Regad } else { 1638186263b2SDamien Regad $tmp_ns = $part; 1639186263b2SDamien Regad } 1640dd90013aSMichael Hamann 1641de301a35SDamien Regad // find the namespace parts 16429988e853SDamien Regad while (array_key_exists($pos, $data) && $data[$pos]['id'] != $tmp_ns) { 164364159a61SAndreas Gohr if ( 164464159a61SAndreas Gohr $pos >= count($data) || 16452d85e841SAndreas Gohr ($data[$pos]['level'] <= $level + 1 && Sort::strcmp($data[$pos]['id'], $tmp_ns) > 0) 164664159a61SAndreas Gohr ) { 1647de301a35SDamien Regad $insert = true; 1648dd90013aSMichael Hamann break; 1649dd90013aSMichael Hamann } 1650dd90013aSMichael Hamann ++$pos; 1651dd90013aSMichael Hamann } 1652de301a35SDamien Regad // insert namespace in hierarchy; if not found in above loop, append it to the end 1653b3894732Ssplitbrain if ($insert || $pos === count($data)) { 1654de301a35SDamien Regad array_splice($data, $pos, 0, [['level' => $level + 1, 'id' => $tmp_ns, 'open' => 'true']]); 1655de301a35SDamien Regad } 1656dd90013aSMichael Hamann } 1657dd90013aSMichael Hamann 16583df72098SAndreas Gohr echo html_buildlist($data, 'idx', 'media_nstree_item', 'media_nstree_li'); 16593df72098SAndreas Gohr} 16603df72098SAndreas Gohr 16613df72098SAndreas Gohr/** 16623df72098SAndreas Gohr * Userfunction for html_buildlist 16633df72098SAndreas Gohr * 16643df72098SAndreas Gohr * Prints a media namespace tree item 16653df72098SAndreas Gohr * 16663df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 166742ea7f44SGerrit Uitslag * 166842ea7f44SGerrit Uitslag * @param array $item 166942ea7f44SGerrit Uitslag * @return string html 16703df72098SAndreas Gohr */ 1671d868eb89SAndreas Gohrfunction media_nstree_item($item) 1672d868eb89SAndreas Gohr{ 16738108113cSTom N Harris global $INPUT; 16743df72098SAndreas Gohr $pos = strrpos($item['id'], ':'); 16753df72098SAndreas Gohr $label = substr($item['id'], $pos > 0 ? $pos + 1 : 0); 16760e80bb5eSChristopher Smith if (empty($item['label'])) $item['label'] = $label; 16773df72098SAndreas Gohr 16783df72098SAndreas Gohr $ret = ''; 167924870174SAndreas Gohr if ($INPUT->str('do') != 'media') 16803df72098SAndreas Gohr $ret .= '<a href="' . DOKU_BASE . 'lib/exe/mediamanager.php?ns=' . idfilter($item['id']) . '" class="idx_dir">'; 1681b960c74fSSatoshi Sahara else $ret .= '<a href="' . media_managerURL(['ns' => idfilter($item['id'], false), 'tab_files' => 'files']) 168223846a98SKate Arzamastseva . '" class="idx_dir">'; 16833df72098SAndreas Gohr $ret .= $item['label']; 16843df72098SAndreas Gohr $ret .= '</a>'; 16853df72098SAndreas Gohr return $ret; 16863df72098SAndreas Gohr} 16873df72098SAndreas Gohr 16883df72098SAndreas Gohr/** 16893df72098SAndreas Gohr * Userfunction for html_buildlist 16903df72098SAndreas Gohr * 16913df72098SAndreas Gohr * Prints a media namespace tree item opener 16923df72098SAndreas Gohr * 16933df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 169442ea7f44SGerrit Uitslag * 169542ea7f44SGerrit Uitslag * @param array $item 169642ea7f44SGerrit Uitslag * @return string html 16973df72098SAndreas Gohr */ 1698d868eb89SAndreas Gohrfunction media_nstree_li($item) 1699d868eb89SAndreas Gohr{ 17003df72098SAndreas Gohr $class = 'media level' . $item['level']; 17013df72098SAndreas Gohr if ($item['open']) { 17023df72098SAndreas Gohr $class .= ' open'; 17033df72098SAndreas Gohr $img = DOKU_BASE . 'lib/images/minus.gif'; 1704e260f93bSAnika Henke $alt = '−'; 17053df72098SAndreas Gohr } else { 17063df72098SAndreas Gohr $class .= ' closed'; 17073df72098SAndreas Gohr $img = DOKU_BASE . 'lib/images/plus.gif'; 17087af1b404SAnika Henke $alt = '+'; 17093df72098SAndreas Gohr } 1710231b8c34SPierre Spring // TODO: only deliver an image if it actually has a subtree... 17113df72098SAndreas Gohr return '<li class="' . $class . '">' . 17127af1b404SAnika Henke '<img src="' . $img . '" alt="' . $alt . '" />'; 17133df72098SAndreas Gohr} 171413c08e2fSMichael Klier 171513c08e2fSMichael Klier/** 1716b021f0b4SAndreas Gohr * Resizes or crop the given image to the given size 1717b021f0b4SAndreas Gohr * 1718b021f0b4SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 1719b021f0b4SAndreas Gohr * 1720b021f0b4SAndreas Gohr * @param string $file filename, path to file 1721b021f0b4SAndreas Gohr * @param string $ext extension 1722b021f0b4SAndreas Gohr * @param int $w desired width 1723b021f0b4SAndreas Gohr * @param int $h desired height 1724b021f0b4SAndreas Gohr * @param bool $crop should a center crop be used? 1725b021f0b4SAndreas Gohr * @return string path to resized or original size if failed 1726b021f0b4SAndreas Gohr */ 1727b021f0b4SAndreas Gohrfunction media_mod_image($file, $ext, $w, $h = 0, $crop = false) 1728b021f0b4SAndreas Gohr{ 1729b021f0b4SAndreas Gohr global $conf; 1730d967ecd8SAndreas Gohr if (!$h) $h = 0; 1731b021f0b4SAndreas Gohr // we wont scale up to infinity 1732b021f0b4SAndreas Gohr if ($w > 2000 || $h > 2000) return $file; 1733b021f0b4SAndreas Gohr 1734b021f0b4SAndreas Gohr $operation = $crop ? 'crop' : 'resize'; 1735b021f0b4SAndreas Gohr 1736b021f0b4SAndreas Gohr $options = [ 1737b021f0b4SAndreas Gohr 'quality' => $conf['jpg_quality'], 1738b021f0b4SAndreas Gohr 'imconvert' => $conf['im_convert'], 1739b021f0b4SAndreas Gohr ]; 1740b021f0b4SAndreas Gohr 174124870174SAndreas Gohr $cache = new CacheImageMod($file, $w, $h, $ext, $crop); 1742b021f0b4SAndreas Gohr if (!$cache->useCache()) { 1743b021f0b4SAndreas Gohr try { 1744b021f0b4SAndreas Gohr Slika::run($file, $options) 1745b021f0b4SAndreas Gohr ->autorotate() 1746b021f0b4SAndreas Gohr ->$operation($w, $h) 1747b021f0b4SAndreas Gohr ->save($cache->cache, $ext); 1748b021f0b4SAndreas Gohr if ($conf['fperm']) @chmod($cache->cache, $conf['fperm']); 174924870174SAndreas Gohr } catch (Exception $e) { 1750b021f0b4SAndreas Gohr Logger::debug($e->getMessage()); 1751b021f0b4SAndreas Gohr return $file; 1752b021f0b4SAndreas Gohr } 1753b021f0b4SAndreas Gohr } 1754b021f0b4SAndreas Gohr 1755b021f0b4SAndreas Gohr return $cache->cache; 1756b021f0b4SAndreas Gohr} 1757b021f0b4SAndreas Gohr 1758b021f0b4SAndreas Gohr/** 175913c08e2fSMichael Klier * Resizes the given image to the given size 176013c08e2fSMichael Klier * 176113c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 176242ea7f44SGerrit Uitslag * 176342ea7f44SGerrit Uitslag * @param string $file filename, path to file 176442ea7f44SGerrit Uitslag * @param string $ext extension 176542ea7f44SGerrit Uitslag * @param int $w desired width 176642ea7f44SGerrit Uitslag * @param int $h desired height 176742ea7f44SGerrit Uitslag * @return string path to resized or original size if failed 176813c08e2fSMichael Klier */ 1769b021f0b4SAndreas Gohrfunction media_resize_image($file, $ext, $w, $h = 0) 1770b021f0b4SAndreas Gohr{ 1771b021f0b4SAndreas Gohr return media_mod_image($file, $ext, $w, $h, false); 1772d2bd34a5SAndreas Gohr} 177313c08e2fSMichael Klier 177413c08e2fSMichael Klier/** 1775d2bd34a5SAndreas Gohr * Center crops the given image to the wanted size 177613c08e2fSMichael Klier * 177713c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 177842ea7f44SGerrit Uitslag * 177942ea7f44SGerrit Uitslag * @param string $file filename, path to file 178042ea7f44SGerrit Uitslag * @param string $ext extension 178142ea7f44SGerrit Uitslag * @param int $w desired width 178242ea7f44SGerrit Uitslag * @param int $h desired height 178342ea7f44SGerrit Uitslag * @return string path to resized or original size if failed 178413c08e2fSMichael Klier */ 1785b021f0b4SAndreas Gohrfunction media_crop_image($file, $ext, $w, $h = 0) 1786b021f0b4SAndreas Gohr{ 1787b021f0b4SAndreas Gohr return media_mod_image($file, $ext, $w, $h, true); 178813c08e2fSMichael Klier} 178913c08e2fSMichael Klier 179013c08e2fSMichael Klier/** 17910f4e0092SChristopher Smith * Calculate a token to be used to verify fetch requests for resized or 17920f4e0092SChristopher Smith * cropped images have been internally generated - and prevent external 17930f4e0092SChristopher Smith * DDOS attacks via fetch 17940f4e0092SChristopher Smith * 17953c124064SAndreas Gohr * @author Christopher Smith <chris@jalakai.co.uk> 17963c124064SAndreas Gohr * 17970f4e0092SChristopher Smith * @param string $id id of the image 17980f4e0092SChristopher Smith * @param int $w resize/crop width 17990f4e0092SChristopher Smith * @param int $h resize/crop height 180042ea7f44SGerrit Uitslag * @return string token or empty string if no token required 18010f4e0092SChristopher Smith */ 1802d868eb89SAndreas Gohrfunction media_get_token($id, $w, $h) 1803d868eb89SAndreas Gohr{ 18040f4e0092SChristopher Smith // token is only required for modified images 1805cc036f74SKlap-in if ($w || $h || media_isexternal($id)) { 18063c124064SAndreas Gohr $token = $id; 18070f4e0092SChristopher Smith if ($w) $token .= '.' . $w; 18080f4e0092SChristopher Smith if ($h) $token .= '.' . $h; 18090f4e0092SChristopher Smith 181024870174SAndreas Gohr return substr(PassHash::hmac('md5', $token, auth_cookiesalt()), 0, 6); 18110f4e0092SChristopher Smith } 18120f4e0092SChristopher Smith 18130f4e0092SChristopher Smith return ''; 18140f4e0092SChristopher Smith} 18150f4e0092SChristopher Smith 18160f4e0092SChristopher Smith/** 181713c08e2fSMichael Klier * Download a remote file and return local filename 181813c08e2fSMichael Klier * 181913c08e2fSMichael Klier * returns false if download fails. Uses cached file if available and 182013c08e2fSMichael Klier * wanted 182113c08e2fSMichael Klier * 182213c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 182313c08e2fSMichael Klier * @author Pavel Vitis <Pavel.Vitis@seznam.cz> 182442ea7f44SGerrit Uitslag * 182542ea7f44SGerrit Uitslag * @param string $url 182642ea7f44SGerrit Uitslag * @param string $ext extension 182742ea7f44SGerrit Uitslag * @param int $cache cachetime in seconds 182842ea7f44SGerrit Uitslag * @return false|string path to cached file 182913c08e2fSMichael Klier */ 1830d868eb89SAndreas Gohrfunction media_get_from_URL($url, $ext, $cache) 1831d868eb89SAndreas Gohr{ 183213c08e2fSMichael Klier global $conf; 183313c08e2fSMichael Klier 183413c08e2fSMichael Klier // if no cache or fetchsize just redirect 183513c08e2fSMichael Klier if ($cache == 0) return false; 183613c08e2fSMichael Klier if (!$conf['fetchsize']) return false; 183713c08e2fSMichael Klier 183813c08e2fSMichael Klier $local = getCacheName(strtolower($url), ".media.$ext"); 183913c08e2fSMichael Klier $mtime = @filemtime($local); // 0 if not exists 184013c08e2fSMichael Klier 184113c08e2fSMichael Klier //decide if download needed: 18427d34963bSAndreas Gohr if ( 18437d34963bSAndreas Gohr ($mtime == 0) || // cache does not exist 184413c08e2fSMichael Klier ($cache != -1 && $mtime < time() - $cache) // 'recache' and cache has expired 184513c08e2fSMichael Klier ) { 184613c08e2fSMichael Klier if (media_image_download($url, $local)) { 184713c08e2fSMichael Klier return $local; 184813c08e2fSMichael Klier } else { 184913c08e2fSMichael Klier return false; 185013c08e2fSMichael Klier } 185113c08e2fSMichael Klier } 185213c08e2fSMichael Klier 185313c08e2fSMichael Klier //if cache exists use it else 185413c08e2fSMichael Klier if ($mtime) return $local; 185513c08e2fSMichael Klier 185613c08e2fSMichael Klier //else return false 185713c08e2fSMichael Klier return false; 185813c08e2fSMichael Klier} 185913c08e2fSMichael Klier 186013c08e2fSMichael Klier/** 186113c08e2fSMichael Klier * Download image files 186213c08e2fSMichael Klier * 186313c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 186442ea7f44SGerrit Uitslag * 186542ea7f44SGerrit Uitslag * @param string $url 186642ea7f44SGerrit Uitslag * @param string $file path to file in which to put the downloaded content 186742ea7f44SGerrit Uitslag * @return bool 186813c08e2fSMichael Klier */ 1869d868eb89SAndreas Gohrfunction media_image_download($url, $file) 1870d868eb89SAndreas Gohr{ 187113c08e2fSMichael Klier global $conf; 187213c08e2fSMichael Klier $http = new DokuHTTPClient(); 1873a5951419SAndreas Gohr $http->keep_alive = false; // we do single ops here, no need for keep-alive 1874a5951419SAndreas Gohr 187513c08e2fSMichael Klier $http->max_bodysize = $conf['fetchsize']; 187613c08e2fSMichael Klier $http->timeout = 25; //max. 25 sec 187713c08e2fSMichael Klier $http->header_regexp = '!\r\nContent-Type: image/(jpe?g|gif|png)!i'; 187813c08e2fSMichael Klier 187913c08e2fSMichael Klier $data = $http->get($url); 188013c08e2fSMichael Klier if (!$data) return false; 188113c08e2fSMichael Klier 188279e79377SAndreas Gohr $fileexists = file_exists($file); 188313c08e2fSMichael Klier $fp = @fopen($file, "w"); 188413c08e2fSMichael Klier if (!$fp) return false; 188513c08e2fSMichael Klier fwrite($fp, $data); 188613c08e2fSMichael Klier fclose($fp); 188724870174SAndreas Gohr if (!$fileexists && $conf['fperm']) chmod($file, $conf['fperm']); 188813c08e2fSMichael Klier 188913c08e2fSMichael Klier // check if it is really an image 189013c08e2fSMichael Klier $info = @getimagesize($file); 189113c08e2fSMichael Klier if (!$info) { 189213c08e2fSMichael Klier @unlink($file); 189313c08e2fSMichael Klier return false; 189413c08e2fSMichael Klier } 189513c08e2fSMichael Klier 189613c08e2fSMichael Klier return true; 189713c08e2fSMichael Klier} 189813c08e2fSMichael Klier 189913c08e2fSMichael Klier/** 190013c08e2fSMichael Klier * resize images using external ImageMagick convert program 190113c08e2fSMichael Klier * 190213c08e2fSMichael Klier * @author Pavel Vitis <Pavel.Vitis@seznam.cz> 190313c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 190442ea7f44SGerrit Uitslag * 190542ea7f44SGerrit Uitslag * @param string $ext extension 190642ea7f44SGerrit Uitslag * @param string $from filename path to file 190742ea7f44SGerrit Uitslag * @param int $from_w original width 190842ea7f44SGerrit Uitslag * @param int $from_h original height 190942ea7f44SGerrit Uitslag * @param string $to path to resized file 191042ea7f44SGerrit Uitslag * @param int $to_w desired width 191142ea7f44SGerrit Uitslag * @param int $to_h desired height 191242ea7f44SGerrit Uitslag * @return bool 191313c08e2fSMichael Klier */ 1914d868eb89SAndreas Gohrfunction media_resize_imageIM($ext, $from, $from_w, $from_h, $to, $to_w, $to_h) 1915d868eb89SAndreas Gohr{ 191613c08e2fSMichael Klier global $conf; 191713c08e2fSMichael Klier 191813c08e2fSMichael Klier // check if convert is configured 191913c08e2fSMichael Klier if (!$conf['im_convert']) return false; 192013c08e2fSMichael Klier 192113c08e2fSMichael Klier // prepare command 192213c08e2fSMichael Klier $cmd = $conf['im_convert']; 192313c08e2fSMichael Klier $cmd .= ' -resize ' . $to_w . 'x' . $to_h . '!'; 192413c08e2fSMichael Klier if ($ext == 'jpg' || $ext == 'jpeg') { 192513c08e2fSMichael Klier $cmd .= ' -quality ' . $conf['jpg_quality']; 192613c08e2fSMichael Klier } 192713c08e2fSMichael Klier $cmd .= " $from $to"; 192813c08e2fSMichael Klier 192913c08e2fSMichael Klier @exec($cmd, $out, $retval); 193013c08e2fSMichael Klier if ($retval == 0) return true; 193113c08e2fSMichael Klier return false; 193213c08e2fSMichael Klier} 193313c08e2fSMichael Klier 193413c08e2fSMichael Klier/** 193513c08e2fSMichael Klier * crop images using external ImageMagick convert program 193613c08e2fSMichael Klier * 193713c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 193842ea7f44SGerrit Uitslag * 193942ea7f44SGerrit Uitslag * @param string $ext extension 194042ea7f44SGerrit Uitslag * @param string $from filename path to file 194142ea7f44SGerrit Uitslag * @param int $from_w original width 194242ea7f44SGerrit Uitslag * @param int $from_h original height 194342ea7f44SGerrit Uitslag * @param string $to path to resized file 194442ea7f44SGerrit Uitslag * @param int $to_w desired width 194542ea7f44SGerrit Uitslag * @param int $to_h desired height 194642ea7f44SGerrit Uitslag * @param int $ofs_x offset of crop centre 194742ea7f44SGerrit Uitslag * @param int $ofs_y offset of crop centre 194842ea7f44SGerrit Uitslag * @return bool 1949d2bd34a5SAndreas Gohr * @deprecated 2020-09-01 195013c08e2fSMichael Klier */ 1951d868eb89SAndreas Gohrfunction media_crop_imageIM($ext, $from, $from_w, $from_h, $to, $to_w, $to_h, $ofs_x, $ofs_y) 1952d868eb89SAndreas Gohr{ 195313c08e2fSMichael Klier global $conf; 1954d2bd34a5SAndreas Gohr dbg_deprecated('splitbrain\\Slika'); 195513c08e2fSMichael Klier 195613c08e2fSMichael Klier // check if convert is configured 195713c08e2fSMichael Klier if (!$conf['im_convert']) return false; 195813c08e2fSMichael Klier 195913c08e2fSMichael Klier // prepare command 196013c08e2fSMichael Klier $cmd = $conf['im_convert']; 196113c08e2fSMichael Klier $cmd .= ' -crop ' . $to_w . 'x' . $to_h . '+' . $ofs_x . '+' . $ofs_y; 196213c08e2fSMichael Klier if ($ext == 'jpg' || $ext == 'jpeg') { 196313c08e2fSMichael Klier $cmd .= ' -quality ' . $conf['jpg_quality']; 196413c08e2fSMichael Klier } 196513c08e2fSMichael Klier $cmd .= " $from $to"; 196613c08e2fSMichael Klier 196713c08e2fSMichael Klier @exec($cmd, $out, $retval); 196813c08e2fSMichael Klier if ($retval == 0) return true; 196913c08e2fSMichael Klier return false; 197013c08e2fSMichael Klier} 197113c08e2fSMichael Klier 197213c08e2fSMichael Klier/** 197313c08e2fSMichael Klier * resize or crop images using PHP's libGD support 197413c08e2fSMichael Klier * 197513c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org> 197613c08e2fSMichael Klier * @author Sebastian Wienecke <s_wienecke@web.de> 197742ea7f44SGerrit Uitslag * 197842ea7f44SGerrit Uitslag * @param string $ext extension 197942ea7f44SGerrit Uitslag * @param string $from filename path to file 198042ea7f44SGerrit Uitslag * @param int $from_w original width 198142ea7f44SGerrit Uitslag * @param int $from_h original height 198242ea7f44SGerrit Uitslag * @param string $to path to resized file 198342ea7f44SGerrit Uitslag * @param int $to_w desired width 198442ea7f44SGerrit Uitslag * @param int $to_h desired height 198542ea7f44SGerrit Uitslag * @param int $ofs_x offset of crop centre 198642ea7f44SGerrit Uitslag * @param int $ofs_y offset of crop centre 198742ea7f44SGerrit Uitslag * @return bool 1988d2bd34a5SAndreas Gohr * @deprecated 2020-09-01 198913c08e2fSMichael Klier */ 1990d868eb89SAndreas Gohrfunction media_resize_imageGD($ext, $from, $from_w, $from_h, $to, $to_w, $to_h, $ofs_x = 0, $ofs_y = 0) 1991d868eb89SAndreas Gohr{ 199213c08e2fSMichael Klier global $conf; 1993d2bd34a5SAndreas Gohr dbg_deprecated('splitbrain\\Slika'); 199413c08e2fSMichael Klier 199513c08e2fSMichael Klier if ($conf['gdlib'] < 1) return false; //no GDlib available or wanted 199613c08e2fSMichael Klier 199713c08e2fSMichael Klier // check available memory 199813c08e2fSMichael Klier if (!is_mem_available(($from_w * $from_h * 4) + ($to_w * $to_h * 4))) { 199913c08e2fSMichael Klier return false; 200013c08e2fSMichael Klier } 200113c08e2fSMichael Klier 200213c08e2fSMichael Klier // create an image of the given filetype 200359bc3b48SGerrit Uitslag $image = false; 200413c08e2fSMichael Klier if ($ext == 'jpg' || $ext == 'jpeg') { 200513c08e2fSMichael Klier if (!function_exists("imagecreatefromjpeg")) return false; 200613c08e2fSMichael Klier $image = @imagecreatefromjpeg($from); 200713c08e2fSMichael Klier } elseif ($ext == 'png') { 200813c08e2fSMichael Klier if (!function_exists("imagecreatefrompng")) return false; 200913c08e2fSMichael Klier $image = @imagecreatefrompng($from); 201013c08e2fSMichael Klier } elseif ($ext == 'gif') { 201113c08e2fSMichael Klier if (!function_exists("imagecreatefromgif")) return false; 201213c08e2fSMichael Klier $image = @imagecreatefromgif($from); 201313c08e2fSMichael Klier } 201413c08e2fSMichael Klier if (!$image) return false; 201513c08e2fSMichael Klier 201659bc3b48SGerrit Uitslag $newimg = false; 201713c08e2fSMichael Klier if (($conf['gdlib'] > 1) && function_exists("imagecreatetruecolor") && $ext != 'gif') { 201813c08e2fSMichael Klier $newimg = @imagecreatetruecolor($to_w, $to_h); 201913c08e2fSMichael Klier } 202013c08e2fSMichael Klier if (!$newimg) $newimg = @imagecreate($to_w, $to_h); 202113c08e2fSMichael Klier if (!$newimg) { 202213c08e2fSMichael Klier imagedestroy($image); 202313c08e2fSMichael Klier return false; 202413c08e2fSMichael Klier } 202513c08e2fSMichael Klier 202613c08e2fSMichael Klier //keep png alpha channel if possible 202713c08e2fSMichael Klier if ($ext == 'png' && $conf['gdlib'] > 1 && function_exists('imagesavealpha')) { 202813c08e2fSMichael Klier imagealphablending($newimg, false); 202913c08e2fSMichael Klier imagesavealpha($newimg, true); 203013c08e2fSMichael Klier } 203113c08e2fSMichael Klier 203213c08e2fSMichael Klier //keep gif transparent color if possible 203313c08e2fSMichael Klier if ($ext == 'gif' && function_exists('imagefill') && function_exists('imagecolorallocate')) { 203413c08e2fSMichael Klier if (function_exists('imagecolorsforindex') && function_exists('imagecolortransparent')) { 203513c08e2fSMichael Klier $transcolorindex = @imagecolortransparent($image); 203613c08e2fSMichael Klier if ($transcolorindex >= 0) { //transparent color exists 203713c08e2fSMichael Klier $transcolor = @imagecolorsforindex($image, $transcolorindex); 203864159a61SAndreas Gohr $transcolorindex = @imagecolorallocate( 203964159a61SAndreas Gohr $newimg, 204064159a61SAndreas Gohr $transcolor['red'], 204164159a61SAndreas Gohr $transcolor['green'], 204264159a61SAndreas Gohr $transcolor['blue'] 204364159a61SAndreas Gohr ); 204413c08e2fSMichael Klier @imagefill($newimg, 0, 0, $transcolorindex); 204513c08e2fSMichael Klier @imagecolortransparent($newimg, $transcolorindex); 204613c08e2fSMichael Klier } else { //filling with white 204713c08e2fSMichael Klier $whitecolorindex = @imagecolorallocate($newimg, 255, 255, 255); 204813c08e2fSMichael Klier @imagefill($newimg, 0, 0, $whitecolorindex); 204913c08e2fSMichael Klier } 205013c08e2fSMichael Klier } else { //filling with white 205113c08e2fSMichael Klier $whitecolorindex = @imagecolorallocate($newimg, 255, 255, 255); 205213c08e2fSMichael Klier @imagefill($newimg, 0, 0, $whitecolorindex); 205313c08e2fSMichael Klier } 205413c08e2fSMichael Klier } 205513c08e2fSMichael Klier 205613c08e2fSMichael Klier //try resampling first 205713c08e2fSMichael Klier if (function_exists("imagecopyresampled")) { 205813c08e2fSMichael Klier if (!@imagecopyresampled($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h)) { 205913c08e2fSMichael Klier imagecopyresized($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h); 206013c08e2fSMichael Klier } 206113c08e2fSMichael Klier } else { 206213c08e2fSMichael Klier imagecopyresized($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h); 206313c08e2fSMichael Klier } 206413c08e2fSMichael Klier 206513c08e2fSMichael Klier $okay = false; 206613c08e2fSMichael Klier if ($ext == 'jpg' || $ext == 'jpeg') { 206713c08e2fSMichael Klier if (!function_exists('imagejpeg')) { 206813c08e2fSMichael Klier $okay = false; 206913c08e2fSMichael Klier } else { 207013c08e2fSMichael Klier $okay = imagejpeg($newimg, $to, $conf['jpg_quality']); 207113c08e2fSMichael Klier } 207213c08e2fSMichael Klier } elseif ($ext == 'png') { 207313c08e2fSMichael Klier if (!function_exists('imagepng')) { 207413c08e2fSMichael Klier $okay = false; 207513c08e2fSMichael Klier } else { 207613c08e2fSMichael Klier $okay = imagepng($newimg, $to); 207713c08e2fSMichael Klier } 207813c08e2fSMichael Klier } elseif ($ext == 'gif') { 207913c08e2fSMichael Klier if (!function_exists('imagegif')) { 208013c08e2fSMichael Klier $okay = false; 208113c08e2fSMichael Klier } else { 208213c08e2fSMichael Klier $okay = imagegif($newimg, $to); 208313c08e2fSMichael Klier } 208413c08e2fSMichael Klier } 208513c08e2fSMichael Klier 208679a2d784SGerrit Uitslag // destroy GD image resources 208779a2d784SGerrit Uitslag imagedestroy($image); 208879a2d784SGerrit Uitslag imagedestroy($newimg); 208913c08e2fSMichael Klier 209013c08e2fSMichael Klier return $okay; 209113c08e2fSMichael Klier} 209213c08e2fSMichael Klier 20933d7a9e0aSAnika Henke/** 20943d7a9e0aSAnika Henke * Return other media files with the same base name 209579e53fe5SAnika Henke * but different extensions. 20963d7a9e0aSAnika Henke * 20973d7a9e0aSAnika Henke * @param string $src - ID of media file 209842ea7f44SGerrit Uitslag * @param string[] $exts - alternative extensions to find other files for 209942ea7f44SGerrit Uitslag * @return array - array(mime type => file ID) 21003d7a9e0aSAnika Henke * 21013d7a9e0aSAnika Henke * @author Anika Henke <anika@selfthinker.org> 21023d7a9e0aSAnika Henke */ 2103d868eb89SAndreas Gohrfunction media_alternativefiles($src, $exts) 2104d868eb89SAndreas Gohr{ 21053d7a9e0aSAnika Henke 210624870174SAndreas Gohr $files = []; 2107a19c9aa0SGerrit Uitslag [$srcExt, /* srcMime */] = mimetype($src); 21083d7a9e0aSAnika Henke $filebase = substr($src, 0, -1 * (strlen($srcExt) + 1)); 21093d7a9e0aSAnika Henke 21103d7a9e0aSAnika Henke foreach ($exts as $ext) { 21113d7a9e0aSAnika Henke $fileid = $filebase . '.' . $ext; 21123d7a9e0aSAnika Henke $file = mediaFN($fileid); 21133d7a9e0aSAnika Henke if (file_exists($file)) { 2114a19c9aa0SGerrit Uitslag [/* fileExt */, $fileMime] = mimetype($file); 211579e53fe5SAnika Henke $files[$fileMime] = $fileid; 211699f943f6SAnika Henke } 21173d7a9e0aSAnika Henke } 21183d7a9e0aSAnika Henke return $files; 21193d7a9e0aSAnika Henke} 21203d7a9e0aSAnika Henke 2121f50634f0SAnika Henke/** 2122f50634f0SAnika Henke * Check if video/audio is supported to be embedded. 2123f50634f0SAnika Henke * 2124b83a74f1SAnika Henke * @param string $mime - mimetype of media file 212542ea7f44SGerrit Uitslag * @param string $type - type of media files to check ('video', 'audio', or null for all) 2126f50634f0SAnika Henke * @return boolean 2127f50634f0SAnika Henke * 2128f50634f0SAnika Henke * @author Anika Henke <anika@selfthinker.org> 2129f50634f0SAnika Henke */ 2130ed823bcdSAndreas Gohrfunction media_supportedav($mime, $type = null) 2131d868eb89SAndreas Gohr{ 213224870174SAndreas Gohr $supportedAudio = [ 2133f50634f0SAnika Henke 'ogg' => 'audio/ogg', 2134f50634f0SAnika Henke 'mp3' => 'audio/mpeg', 213524870174SAndreas Gohr 'wav' => 'audio/wav' 213624870174SAndreas Gohr ]; 213724870174SAndreas Gohr $supportedVideo = [ 2138f50634f0SAnika Henke 'webm' => 'video/webm', 2139f50634f0SAnika Henke 'ogv' => 'video/ogg', 214024870174SAndreas Gohr 'mp4' => 'video/mp4' 214124870174SAndreas Gohr ]; 2142f50634f0SAnika Henke if ($type == 'audio') { 2143f50634f0SAnika Henke $supportedAv = $supportedAudio; 2144f50634f0SAnika Henke } elseif ($type == 'video') { 2145f50634f0SAnika Henke $supportedAv = $supportedVideo; 2146f50634f0SAnika Henke } else { 2147f50634f0SAnika Henke $supportedAv = array_merge($supportedAudio, $supportedVideo); 2148f50634f0SAnika Henke } 2149f50634f0SAnika Henke return in_array($mime, $supportedAv); 2150f50634f0SAnika Henke} 2151f50634f0SAnika Henke 21520877a1f1SSchplurtz le Déboulonné/** 21530877a1f1SSchplurtz le Déboulonné * Return track media files with the same base name 21540877a1f1SSchplurtz le Déboulonné * but extensions that indicate kind and lang. 21550877a1f1SSchplurtz le Déboulonné * ie for foo.webm search foo.sub.lang.vtt, foo.cap.lang.vtt... 21560877a1f1SSchplurtz le Déboulonné * 21570877a1f1SSchplurtz le Déboulonné * @param string $src - ID of media file 215801299338SSchplurtz le Déboulonné * @return array - array(mediaID => array( kind, srclang )) 21590877a1f1SSchplurtz le Déboulonné * 21600877a1f1SSchplurtz le Déboulonné * @author Schplurtz le Déboulonné <Schplurtz@laposte.net> 21610877a1f1SSchplurtz le Déboulonné */ 2162d868eb89SAndreas Gohrfunction media_trackfiles($src) 2163d868eb89SAndreas Gohr{ 216424870174SAndreas Gohr $kinds = [ 21650877a1f1SSchplurtz le Déboulonné 'sub' => 'subtitles', 21660877a1f1SSchplurtz le Déboulonné 'cap' => 'captions', 21670877a1f1SSchplurtz le Déboulonné 'des' => 'descriptions', 21680877a1f1SSchplurtz le Déboulonné 'cha' => 'chapters', 21690877a1f1SSchplurtz le Déboulonné 'met' => 'metadata' 217024870174SAndreas Gohr ]; 21710877a1f1SSchplurtz le Déboulonné 217224870174SAndreas Gohr $files = []; 21730877a1f1SSchplurtz le Déboulonné $re = '/\\.(sub|cap|des|cha|met)\\.([^.]+)\\.vtt$/'; 21740877a1f1SSchplurtz le Déboulonné $baseid = pathinfo($src, PATHINFO_FILENAME); 21750877a1f1SSchplurtz le Déboulonné $pattern = mediaFN($baseid) . '.*.*.vtt'; 21760877a1f1SSchplurtz le Déboulonné $list = glob($pattern); 21770877a1f1SSchplurtz le Déboulonné foreach ($list as $track) { 21780877a1f1SSchplurtz le Déboulonné if (preg_match($re, $track, $matches)) { 217924870174SAndreas Gohr $files[$baseid . '.' . $matches[1] . '.' . $matches[2] . '.vtt'] = [$kinds[$matches[1]], $matches[2]]; 21800877a1f1SSchplurtz le Déboulonné } 21810877a1f1SSchplurtz le Déboulonné } 21820877a1f1SSchplurtz le Déboulonné return $files; 21830877a1f1SSchplurtz le Déboulonné} 21840877a1f1SSchplurtz le Déboulonné 2185365be586SAndreas Gohr/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 2186