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