xref: /dokuwiki/inc/media.php (revision 6734bb8cef71e8b4af23e627d4db5430304d55a2)
13df72098SAndreas Gohr<?php
2d4f83172SAndreas Gohr
33df72098SAndreas Gohr/**
43df72098SAndreas Gohr * All output and handler function needed for the media management popup
53df72098SAndreas Gohr *
63df72098SAndreas Gohr * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
73df72098SAndreas Gohr * @author     Andreas Gohr <andi@splitbrain.org>
83df72098SAndreas Gohr */
93df72098SAndreas Gohr
1024870174SAndreas Gohruse dokuwiki\Ui\MediaRevisions;
1124870174SAndreas Gohruse dokuwiki\Cache\CacheImageMod;
1224870174SAndreas Gohruse splitbrain\slika\Exception;
1324870174SAndreas Gohruse dokuwiki\PassHash;
140c3a5702SAndreas Gohruse dokuwiki\ChangeLog\MediaChangeLog;
15e1d9dcc8SAndreas Gohruse dokuwiki\Extension\Event;
16b960c74fSSatoshi Saharause dokuwiki\Form\Form;
173df72098SAndreas Gohruse dokuwiki\HTTP\DokuHTTPClient;
1879a2d784SGerrit Uitslaguse dokuwiki\Logger;
190c3a5702SAndreas Gohruse dokuwiki\Subscriptions\MediaSubscriptionSender;
2079a2d784SGerrit Uitslaguse dokuwiki\Ui\Media\DisplayRow;
2179a2d784SGerrit Uitslaguse dokuwiki\Ui\Media\DisplayTile;
22*6734bb8cSAndreas Gohruse dokuwiki\Search\MetadataSearch;
2379a2d784SGerrit Uitslaguse dokuwiki\Ui\MediaDiff;
2479a2d784SGerrit Uitslaguse dokuwiki\Utf8\PhpString;
252d85e841SAndreas Gohruse dokuwiki\Utf8\Sort;
2679a2d784SGerrit Uitslaguse splitbrain\slika\Slika;
270c3a5702SAndreas Gohr
283df72098SAndreas Gohr/**
293df72098SAndreas Gohr * Lists pages which currently use a media file selected for deletion
303df72098SAndreas Gohr *
313df72098SAndreas Gohr * References uses the same visual as search results and share
323df72098SAndreas Gohr * their CSS tags except pagenames won't be links.
333df72098SAndreas Gohr *
343df72098SAndreas Gohr * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
3542ea7f44SGerrit Uitslag *
3642ea7f44SGerrit Uitslag * @param array $data
3742ea7f44SGerrit Uitslag * @param string $id
383df72098SAndreas Gohr */
39d868eb89SAndreas Gohrfunction media_filesinuse($data, $id)
40d868eb89SAndreas Gohr{
413df72098SAndreas Gohr    global $lang;
423df72098SAndreas Gohr    echo '<h1>' . $lang['reference'] . ' <code>' . hsc(noNS($id)) . '</code></h1>';
433df72098SAndreas Gohr    echo '<p>' . hsc($lang['ref_inuse']) . '</p>';
443df72098SAndreas Gohr
453df72098SAndreas Gohr    $hidden = 0; //count of hits without read permission
463df72098SAndreas Gohr    foreach ($data as $row) {
47a05e297aSAndreas Gohr        if (auth_quickaclcheck($row) >= AUTH_READ && isVisiblePage($row)) {
483df72098SAndreas Gohr            echo '<div class="search_result">';
49a05e297aSAndreas Gohr            echo '<span class="mediaref_ref">' . hsc($row) . '</span>';
503df72098SAndreas Gohr            echo '</div>';
51177d6836SAndreas Gohr        } else $hidden++;
523df72098SAndreas Gohr    }
533df72098SAndreas Gohr    if ($hidden) {
5426dfc232SAndreas Gohr        echo '<div class="mediaref_hidden">' . $lang['ref_hidden'] . '</div>';
553df72098SAndreas Gohr    }
563df72098SAndreas Gohr}
573df72098SAndreas Gohr
583df72098SAndreas Gohr/**
593df72098SAndreas Gohr * Handles the saving of image meta data
603df72098SAndreas Gohr *
613df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
62cf832786SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
63e0c26282SGerrit Uitslag *
64e0c26282SGerrit Uitslag * @param string $id media id
65e0c26282SGerrit Uitslag * @param int $auth permission level
66e0c26282SGerrit Uitslag * @param array $data
6742ea7f44SGerrit Uitslag * @return false|string
683df72098SAndreas Gohr */
69d868eb89SAndreas Gohrfunction media_metasave($id, $auth, $data)
70d868eb89SAndreas Gohr{
713df72098SAndreas Gohr    if ($auth < AUTH_UPLOAD) return false;
72f2ea8432SAndreas Gohr    if (!checkSecurityToken()) return false;
733df72098SAndreas Gohr    global $lang;
740b308644SOtto Vainio    global $conf;
753df72098SAndreas Gohr    $src = mediaFN($id);
763df72098SAndreas Gohr
773df72098SAndreas Gohr    $meta = new JpegMeta($src);
783df72098SAndreas Gohr    $meta->_parseAll();
793df72098SAndreas Gohr
803df72098SAndreas Gohr    foreach ($data as $key => $val) {
813df72098SAndreas Gohr        $val = trim($val);
823df72098SAndreas Gohr        if (empty($val)) {
833df72098SAndreas Gohr            $meta->deleteField($key);
843df72098SAndreas Gohr        } else {
853df72098SAndreas Gohr            $meta->setField($key, $val);
863df72098SAndreas Gohr        }
873df72098SAndreas Gohr    }
883df72098SAndreas Gohr
89cf832786SKate Arzamastseva    $old = @filemtime($src);
9079e79377SAndreas Gohr    if (!file_exists(mediaFN($id, $old)) && file_exists($src)) {
91cf832786SKate Arzamastseva        // add old revision to the attic
92cf832786SKate Arzamastseva        media_saveOldRevision($id);
93cf832786SKate Arzamastseva    }
94ac3ed4afSGerrit Uitslag    $filesize_old = filesize($src);
953df72098SAndreas Gohr    if ($meta->save()) {
960b308644SOtto Vainio        if ($conf['fperm']) chmod($src, $conf['fperm']);
97ac3ed4afSGerrit Uitslag        @clearstatcache(true, $src);
98cf832786SKate Arzamastseva        $new = @filemtime($src);
99ac3ed4afSGerrit Uitslag        $filesize_new = filesize($src);
100ac3ed4afSGerrit Uitslag        $sizechange = $filesize_new - $filesize_old;
101ac3ed4afSGerrit Uitslag
102cf832786SKate Arzamastseva        // add a log entry to the media changelog
103ac3ed4afSGerrit Uitslag        addMediaLogEntry($new, $id, DOKU_CHANGE_TYPE_EDIT, $lang['media_meta_edited'], '', null, $sizechange);
104cf832786SKate Arzamastseva
1053df72098SAndreas Gohr        msg($lang['metasaveok'], 1);
1063df72098SAndreas Gohr        return $id;
1073df72098SAndreas Gohr    } else {
1083df72098SAndreas Gohr        msg($lang['metasaveerr'], -1);
1093df72098SAndreas Gohr        return false;
1103df72098SAndreas Gohr    }
1113df72098SAndreas Gohr}
1123df72098SAndreas Gohr
1133df72098SAndreas Gohr/**
114d54f7963SKlap-in * check if a media is external source
115d54f7963SKlap-in *
116d54f7963SKlap-in * @author Gerrit Uitslag <klapinklapin@gmail.com>
11742ea7f44SGerrit Uitslag *
118d54f7963SKlap-in * @param string $id the media ID or URL
119d54f7963SKlap-in * @return bool
120d54f7963SKlap-in */
121d868eb89SAndreas Gohrfunction media_isexternal($id)
122d868eb89SAndreas Gohr{
123fe578fe9SElan Ruusamäe    if (preg_match('#^(?:https?|ftp)://#i', $id)) return true;
124d54f7963SKlap-in    return false;
125d54f7963SKlap-in}
126d54f7963SKlap-in
127d54f7963SKlap-in/**
128add8678fSAndreas Gohr * Check if a media item is public (eg, external URL or readable by @ALL)
129add8678fSAndreas Gohr *
130add8678fSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
13142ea7f44SGerrit Uitslag *
132add8678fSAndreas Gohr * @param string $id  the media ID or URL
133add8678fSAndreas Gohr * @return bool
134add8678fSAndreas Gohr */
135d868eb89SAndreas Gohrfunction media_ispublic($id)
136d868eb89SAndreas Gohr{
137d54f7963SKlap-in    if (media_isexternal($id)) return true;
138add8678fSAndreas Gohr    $id = cleanID($id);
13924870174SAndreas Gohr    if (auth_aclcheck(getNS($id) . ':*', '', []) >= AUTH_READ) return true;
140add8678fSAndreas Gohr    return false;
141add8678fSAndreas Gohr}
142add8678fSAndreas Gohr
143add8678fSAndreas Gohr/**
1443df72098SAndreas Gohr * Display the form to edit image meta data
1453df72098SAndreas Gohr *
1463df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
147d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
148e0c26282SGerrit Uitslag *
149e0c26282SGerrit Uitslag * @param string $id media id
150e0c26282SGerrit Uitslag * @param int $auth permission level
151e0c26282SGerrit Uitslag * @return bool
1523df72098SAndreas Gohr */
153d868eb89SAndreas Gohrfunction media_metaform($id, $auth)
154d868eb89SAndreas Gohr{
155ebc28e69SAndreas Gohr    global $lang;
1563df72098SAndreas Gohr
15788a71175SKate Arzamastseva    if ($auth < AUTH_UPLOAD) {
158b960c74fSSatoshi Sahara        echo '<div class="nothing">' . $lang['media_perm_upload'] . '</div>' . DOKU_LF;
15988a71175SKate Arzamastseva        return false;
16088a71175SKate Arzamastseva    }
16188a71175SKate Arzamastseva
1623df72098SAndreas Gohr    // load the field descriptions
1633df72098SAndreas Gohr    static $fields = null;
164b960c74fSSatoshi Sahara    if ($fields === null) {
1653e98e685SKate Arzamastseva        $config_files = getConfigFiles('mediameta');
1663e98e685SKate Arzamastseva        foreach ($config_files as $config_file) {
16779e79377SAndreas Gohr            if (file_exists($config_file)) include($config_file);
1683df72098SAndreas Gohr        }
1693df72098SAndreas Gohr    }
1703df72098SAndreas Gohr
1713df72098SAndreas Gohr    $src = mediaFN($id);
1723df72098SAndreas Gohr
1733df72098SAndreas Gohr    // output
174b960c74fSSatoshi Sahara    $form = new Form([
175b960c74fSSatoshi Sahara            'action' => media_managerURL(['tab_details' => 'view'], '&'),
176b960c74fSSatoshi Sahara            'class' => 'meta'
177b960c74fSSatoshi Sahara    ]);
178b960c74fSSatoshi Sahara    $form->addTagOpen('div')->addClass('no');
179b960c74fSSatoshi Sahara    $form->setHiddenField('img', $id);
180b960c74fSSatoshi Sahara    $form->setHiddenField('mediado', 'save');
1813df72098SAndreas Gohr    foreach ($fields as $key => $field) {
1823df72098SAndreas Gohr        // get current value
1833e98e685SKate Arzamastseva        if (empty($field[0])) continue;
18424870174SAndreas Gohr        $tags = [$field[0]];
1855cefb623SEduardo Mozart de Oliveira        if (isset($field[3]) && is_array($field[3])) $tags = array_merge($tags, $field[3]);
1863df72098SAndreas Gohr        $value = tpl_img_getTag($tags, '', $src);
187ca6a0701SAndreas Gohr        $value = cleanText($value);
1883df72098SAndreas Gohr
1893df72098SAndreas Gohr        // prepare attributes
19024870174SAndreas Gohr        $p = [
191b960c74fSSatoshi Sahara            'class' => 'edit',
192b960c74fSSatoshi Sahara            'id'    => 'meta__' . $key,
19324870174SAndreas Gohr            'name'  => 'meta[' . $field[0] . ']'
19424870174SAndreas Gohr        ];
1953df72098SAndreas Gohr
196b960c74fSSatoshi Sahara        $form->addTagOpen('div')->addClass('row');
1973df72098SAndreas Gohr        if ($field[2] == 'text') {
198bde2a644SSatoshi Sahara            $form->addTextInput(
19964159a61SAndreas Gohr                $p['name'],
20079a2d784SGerrit Uitslag                ($lang[$field[1]] ?: $field[1] . ':')
201b960c74fSSatoshi Sahara            )->id($p['id'])->addClass($p['class'])->val($value);
2023df72098SAndreas Gohr        } else {
203b960c74fSSatoshi Sahara            $form->addTextarea($p['name'], $lang[$field[1]])->id($p['id'])
204b960c74fSSatoshi Sahara                ->val(formText($value))
205b960c74fSSatoshi Sahara                ->addClass($p['class'])
206b960c74fSSatoshi Sahara                ->attr('rows', '6')->attr('cols', '50');
2073df72098SAndreas Gohr        }
208b960c74fSSatoshi Sahara        $form->addTagClose('div');
2093df72098SAndreas Gohr    }
210b960c74fSSatoshi Sahara    $form->addTagOpen('div')->addClass('buttons');
211b960c74fSSatoshi Sahara    $form->addButton('mediado[save]', $lang['btn_save'])->attr('type', 'submit')
212b960c74fSSatoshi Sahara        ->attrs(['accesskey' => 's']);
213b960c74fSSatoshi Sahara    $form->addTagClose('div');
214ebc28e69SAndreas Gohr
215b960c74fSSatoshi Sahara    $form->addTagClose('div');
216b960c74fSSatoshi Sahara    echo $form->toHTML();
217ebc28e69SAndreas Gohr    return true;
2183df72098SAndreas Gohr}
2193df72098SAndreas Gohr
220666cdec5SMichael Klier/**
22187229c84SAdrian Lang * Convenience function to check if a media file is still in use
222666cdec5SMichael Klier *
223666cdec5SMichael Klier * @author Michael Klier <chi@chimeric.de>
224e0c26282SGerrit Uitslag *
225e0c26282SGerrit Uitslag * @param string $id media id
226e0c26282SGerrit Uitslag * @return array|bool
227666cdec5SMichael Klier */
228d868eb89SAndreas Gohrfunction media_inuse($id)
229d868eb89SAndreas Gohr{
230666cdec5SMichael Klier    global $conf;
231ebc28e69SAndreas Gohr
232666cdec5SMichael Klier    if ($conf['refcheck']) {
233*6734bb8cSAndreas Gohr        $mediareferences = (new MetadataSearch())->mediause($id, true);
23424870174SAndreas Gohr        if ($mediareferences === []) {
2356dae2464SAndreas Gohr            return false;
236666cdec5SMichael Klier        } else {
237666cdec5SMichael Klier            return $mediareferences;
238666cdec5SMichael Klier        }
239666cdec5SMichael Klier    } else {
240666cdec5SMichael Klier        return false;
241666cdec5SMichael Klier    }
242666cdec5SMichael Klier}
243a05e297aSAndreas Gohr
2443df72098SAndreas Gohr/**
2453df72098SAndreas Gohr * Handles media file deletions
2463df72098SAndreas Gohr *
2473df72098SAndreas Gohr * If configured, checks for media references before deletion
2483df72098SAndreas Gohr *
2493df72098SAndreas Gohr * @author             Andreas Gohr <andi@splitbrain.org>
25042ea7f44SGerrit Uitslag *
251ebc28e69SAndreas Gohr * @param string $id media id
25222db8df7SAndreas Gohr * @param int $auth no longer used
25387229c84SAdrian Lang * @return int One of: 0,
25463703ba5SAndreas Gohr *                     DOKU_MEDIA_DELETED,
25563703ba5SAndreas Gohr *                     DOKU_MEDIA_DELETED | DOKU_MEDIA_EMPTY_NS,
25663703ba5SAndreas Gohr *                     DOKU_MEDIA_NOT_AUTH,
25763703ba5SAndreas Gohr *                     DOKU_MEDIA_INUSE
2583df72098SAndreas Gohr */
259d868eb89SAndreas Gohrfunction media_delete($id, $auth)
260d868eb89SAndreas Gohr{
2616183fb05SKate Arzamastseva    global $lang;
262ff04e8b7SAndreas Gohr    $auth = auth_quickaclcheck(ltrim(getNS($id) . ':*', ':'));
26387229c84SAdrian Lang    if ($auth < AUTH_DELETE) return DOKU_MEDIA_NOT_AUTH;
26487229c84SAdrian Lang    if (media_inuse($id)) return DOKU_MEDIA_INUSE;
2653df72098SAndreas Gohr
2663df72098SAndreas Gohr    $file = mediaFN($id);
2674a961e72SMichal Kolodziejski
2684a961e72SMichal Kolodziejski    // trigger an event - MEDIA_DELETE_FILE
26924870174SAndreas Gohr    $data = [];
270666cdec5SMichael Klier    $data['id']   = $id;
27179a2d784SGerrit Uitslag    $data['name'] = PhpString::basename($file);
2724a961e72SMichal Kolodziejski    $data['path'] = $file;
27379e79377SAndreas Gohr    $data['size'] = (file_exists($file)) ? filesize($file) : 0;
274666cdec5SMichael Klier
275666cdec5SMichael Klier    $data['unl'] = false;
276666cdec5SMichael Klier    $data['del'] = false;
277e1d9dcc8SAndreas Gohr    $evt = new Event('MEDIA_DELETE_FILE', $data);
2784a961e72SMichal Kolodziejski    if ($evt->advise_before()) {
2796183fb05SKate Arzamastseva        $old = @filemtime($file);
28079e79377SAndreas Gohr        if (!file_exists(mediaFN($id, $old)) && file_exists($file)) {
2816183fb05SKate Arzamastseva            // add old revision to the attic
2826183fb05SKate Arzamastseva            media_saveOldRevision($id);
2836183fb05SKate Arzamastseva        }
2846183fb05SKate Arzamastseva
285666cdec5SMichael Klier        $data['unl'] = @unlink($file);
286666cdec5SMichael Klier        if ($data['unl']) {
287ac3ed4afSGerrit Uitslag            $sizechange = 0 - $data['size'];
288ac3ed4afSGerrit Uitslag            addMediaLogEntry(time(), $id, DOKU_CHANGE_TYPE_DELETE, $lang['deleted'], '', null, $sizechange);
289ac3ed4afSGerrit Uitslag
290666cdec5SMichael Klier            $data['del'] = io_sweepNS($id, 'mediadir');
2913df72098SAndreas Gohr        }
2924a961e72SMichal Kolodziejski    }
2934a961e72SMichal Kolodziejski    $evt->advise_after();
2944a961e72SMichal Kolodziejski    unset($evt);
2954a961e72SMichal Kolodziejski
296666cdec5SMichael Klier    if ($data['unl'] && $data['del']) {
29787229c84SAdrian Lang        return DOKU_MEDIA_DELETED | DOKU_MEDIA_EMPTY_NS;
2983df72098SAndreas Gohr    }
2993df72098SAndreas Gohr
30087229c84SAdrian Lang    return $data['unl'] ? DOKU_MEDIA_DELETED : 0;
3013df72098SAndreas Gohr}
3023df72098SAndreas Gohr
3033df72098SAndreas Gohr/**
3042d6cc64fSKate Arzamastseva * Handle file uploads via XMLHttpRequest
3052d6cc64fSKate Arzamastseva *
306ebc28e69SAndreas Gohr * @param string $ns   target namespace
307ebc28e69SAndreas Gohr * @param int    $auth current auth check result
30842ea7f44SGerrit Uitslag * @return false|string false on error, id of the new file on success
3092d6cc64fSKate Arzamastseva */
310d868eb89SAndreas Gohrfunction media_upload_xhr($ns, $auth)
311d868eb89SAndreas Gohr{
312da45d883SKate Arzamastseva    if (!checkSecurityToken()) return false;
3138108113cSTom N Harris    global $INPUT;
314da45d883SKate Arzamastseva
3158108113cSTom N Harris    $id = $INPUT->get->str('qqfile');
31624870174SAndreas Gohr    [$ext, $mime] = mimetype($id);
3172d6cc64fSKate Arzamastseva    $input = fopen("php://input", "r");
3182d6cc64fSKate Arzamastseva    if (!($tmp = io_mktmpdir())) return false;
31962231793SKate Arzamastseva    $path = $tmp . '/' . md5($id);
3202d6cc64fSKate Arzamastseva    $target = fopen($path, "w");
321063fb5b5SAndreas Gohr    $realSize = stream_copy_to_stream($input, $target);
3222d6cc64fSKate Arzamastseva    fclose($target);
323063fb5b5SAndreas Gohr    fclose($input);
3242b9be456SAndreas Gohr    if ($INPUT->server->has('CONTENT_LENGTH') && ($realSize != $INPUT->server->int('CONTENT_LENGTH'))) {
325063fb5b5SAndreas Gohr        unlink($path);
326063fb5b5SAndreas Gohr        return false;
327063fb5b5SAndreas Gohr    }
328063fb5b5SAndreas Gohr
3292d6cc64fSKate Arzamastseva    $res = media_save(
33024870174SAndreas Gohr        ['name' => $path, 'mime' => $mime, 'ext'  => $ext],
3312d6cc64fSKate Arzamastseva        $ns . ':' . $id,
33279a2d784SGerrit Uitslag        ($INPUT->get->str('ow') == 'true'),
3332d6cc64fSKate Arzamastseva        $auth,
3342d6cc64fSKate Arzamastseva        'copy'
3352d6cc64fSKate Arzamastseva    );
3362d6cc64fSKate Arzamastseva    unlink($path);
337900a9e9eSGerrit Uitslag    if ($tmp) io_rmdir($tmp, true);
3382d6cc64fSKate Arzamastseva    if (is_array($res)) {
3392d6cc64fSKate Arzamastseva        msg($res[0], $res[1]);
3402d6cc64fSKate Arzamastseva        return false;
3412d6cc64fSKate Arzamastseva    }
3422d6cc64fSKate Arzamastseva    return $res;
3432d6cc64fSKate Arzamastseva}
3442d6cc64fSKate Arzamastseva
3452d6cc64fSKate Arzamastseva/**
3463df72098SAndreas Gohr * Handles media file uploads
3473df72098SAndreas Gohr *
3483df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
34911d9dfa5SMichael Klier * @author Michael Klier <chi@chimeric.de>
35042ea7f44SGerrit Uitslag *
351ebc28e69SAndreas Gohr * @param string     $ns    target namespace
352ebc28e69SAndreas Gohr * @param int        $auth  current auth check result
353ebc28e69SAndreas Gohr * @param bool|array $file  $_FILES member, $_FILES['upload'] if false
35442ea7f44SGerrit Uitslag * @return false|string false on error, id of the new file on success
3553df72098SAndreas Gohr */
356d868eb89SAndreas Gohrfunction media_upload($ns, $auth, $file = false)
357d868eb89SAndreas Gohr{
358f2ea8432SAndreas Gohr    if (!checkSecurityToken()) return false;
3593df72098SAndreas Gohr    global $lang;
3608108113cSTom N Harris    global $INPUT;
3613df72098SAndreas Gohr
36244409c3dSAndreas Gohr    // get file and id
3638108113cSTom N Harris    $id   = $INPUT->post->str('mediaid');
3642d6cc64fSKate Arzamastseva    if (!$file) $file = $_FILES['upload'];
3653df72098SAndreas Gohr    if (empty($id)) $id = $file['name'];
36644409c3dSAndreas Gohr
36799766eefSAndreas Gohr    // check for errors (messages are done in lib/exe/mediamanager.php)
36899766eefSAndreas Gohr    if ($file['error']) return false;
3699676dc23SAndreas Gohr
37044409c3dSAndreas Gohr    // check extensions
37124870174SAndreas Gohr    [$fext, $fmime] = mimetype($file['name']);
37224870174SAndreas Gohr    [$iext, $imime] = mimetype($id);
37344409c3dSAndreas Gohr    if ($fext && !$iext) {
3748cb1eb01SAndreas Gohr        // no extension specified in id - read original one
37544409c3dSAndreas Gohr        $id   .= '.' . $fext;
3768cb1eb01SAndreas Gohr        $imime = $fmime;
37744409c3dSAndreas Gohr    } elseif ($fext && $fext != $iext) {
37844409c3dSAndreas Gohr        // extension was changed, print warning
37944409c3dSAndreas Gohr        msg(sprintf($lang['mediaextchange'], $fext, $iext));
38044409c3dSAndreas Gohr    }
38144409c3dSAndreas Gohr
38224870174SAndreas Gohr    $res = media_save(
38324870174SAndreas Gohr        [
38424870174SAndreas Gohr            'name' => $file['tmp_name'],
385ffb291f2SAdrian Lang            'mime' => $imime,
38624870174SAndreas Gohr            'ext' => $iext
38724870174SAndreas Gohr        ],
38824870174SAndreas Gohr        $ns . ':' . $id,
38924870174SAndreas Gohr        $INPUT->post->bool('ow'),
39024870174SAndreas Gohr        $auth,
39124870174SAndreas Gohr        'copy_uploaded_file'
39224870174SAndreas Gohr    );
393ffb291f2SAdrian Lang    if (is_array($res)) {
394ffb291f2SAdrian Lang        msg($res[0], $res[1]);
395ffb291f2SAdrian Lang        return false;
396ffb291f2SAdrian Lang    }
397ffb291f2SAdrian Lang    return $res;
398ffb291f2SAdrian Lang}
399ffb291f2SAdrian Lang
400ffb291f2SAdrian Lang/**
40171f17ac4SAndreas Gohr * An alternative to move_uploaded_file that copies
40271f17ac4SAndreas Gohr *
40371f17ac4SAndreas Gohr * Using copy, makes sure any setgid bits on the media directory are honored
40471f17ac4SAndreas Gohr *
40571f17ac4SAndreas Gohr * @see   move_uploaded_file()
40642ea7f44SGerrit Uitslag *
40771f17ac4SAndreas Gohr * @param string $from
40871f17ac4SAndreas Gohr * @param string $to
40971f17ac4SAndreas Gohr * @return bool
41071f17ac4SAndreas Gohr */
411d868eb89SAndreas Gohrfunction copy_uploaded_file($from, $to)
412d868eb89SAndreas Gohr{
41371f17ac4SAndreas Gohr    if (!is_uploaded_file($from)) return false;
41471f17ac4SAndreas Gohr    $ok = copy($from, $to);
41571f17ac4SAndreas Gohr    @unlink($from);
41671f17ac4SAndreas Gohr    return $ok;
41771f17ac4SAndreas Gohr}
41871f17ac4SAndreas Gohr
41971f17ac4SAndreas Gohr/**
420ffb291f2SAdrian Lang * This generates an action event and delegates to _media_upload_action().
421ffb291f2SAdrian Lang * Action plugins are allowed to pre/postprocess the uploaded file.
422ffb291f2SAdrian Lang * (The triggered event is preventable.)
423ffb291f2SAdrian Lang *
424ffb291f2SAdrian Lang * Event data:
425ffb291f2SAdrian Lang * $data[0]     fn_tmp:    the temporary file name (read from $_FILES)
426ffb291f2SAdrian Lang * $data[1]     fn:        the file name of the uploaded file
427ffb291f2SAdrian Lang * $data[2]     id:        the future directory id of the uploaded file
428ffb291f2SAdrian Lang * $data[3]     imime:     the mimetype of the uploaded file
429ffb291f2SAdrian Lang * $data[4]     overwrite: if an existing file is going to be overwritten
43052a281e8SGerrit Uitslag * $data[5]     move:      name of function that performs move/copy/..
431ffb291f2SAdrian Lang *
432ffb291f2SAdrian Lang * @triggers MEDIA_UPLOAD_FINISH
43342ea7f44SGerrit Uitslag *
434e0c26282SGerrit Uitslag * @param array  $file
43552a281e8SGerrit Uitslag * @param string $id   media id
43642ea7f44SGerrit Uitslag * @param bool   $ow   overwrite?
437e0c26282SGerrit Uitslag * @param int    $auth permission level
43852a281e8SGerrit Uitslag * @param string $move name of functions that performs move/copy/..
43942ea7f44SGerrit Uitslag * @return false|array|string
440e0c26282SGerrit Uitslag */
441d868eb89SAndreas Gohrfunction media_save($file, $id, $ow, $auth, $move)
442d868eb89SAndreas Gohr{
443ffb291f2SAdrian Lang    if ($auth < AUTH_UPLOAD) {
44424870174SAndreas Gohr        return ["You don't have permissions to upload files.", -1];
445ffb291f2SAdrian Lang    }
446ffb291f2SAdrian Lang
447ffb291f2SAdrian Lang    if (!isset($file['mime']) || !isset($file['ext'])) {
44824870174SAndreas Gohr        [$ext, $mime] = mimetype($id);
449ffb291f2SAdrian Lang        if (!isset($file['mime'])) {
450ffb291f2SAdrian Lang            $file['mime'] = $mime;
451ffb291f2SAdrian Lang        }
452ffb291f2SAdrian Lang        if (!isset($file['ext'])) {
453ffb291f2SAdrian Lang            $file['ext'] = $ext;
454ffb291f2SAdrian Lang        }
455ffb291f2SAdrian Lang    }
456ffb291f2SAdrian Lang
45792cac9a9SKate Arzamastseva    global $lang, $conf;
458ffb291f2SAdrian Lang
4593df72098SAndreas Gohr    // get filename
4603543c6deSAndreas Gohr    $id   = cleanID($id);
4613df72098SAndreas Gohr    $fn   = mediaFN($id);
4623df72098SAndreas Gohr
4633df72098SAndreas Gohr    // get filetype regexp
4643df72098SAndreas Gohr    $types = array_keys(getMimeTypes());
465bad6fc0dSAndreas Gohr    $types = array_map(
46624870174SAndreas Gohr        static fn($q) => preg_quote($q, "/"),
467bad6fc0dSAndreas Gohr        $types
468bad6fc0dSAndreas Gohr    );
46924870174SAndreas Gohr    $regex = implode('|', $types);
4703df72098SAndreas Gohr
4713df72098SAndreas Gohr    // because a temp file was created already
472ffb291f2SAdrian Lang    if (!preg_match('/\.(' . $regex . ')$/i', $fn)) {
47324870174SAndreas Gohr        return [$lang['uploadwrong'], -1];
474ffb291f2SAdrian Lang    }
475ffb291f2SAdrian Lang
4763df72098SAndreas Gohr    //check for overwrite
47779e79377SAndreas Gohr    $overwrite = file_exists($fn);
478e5d185e1SKate Arzamastseva    $auth_ow = (($conf['mediarevisions']) ? AUTH_UPLOAD : AUTH_DELETE);
479e5d185e1SKate Arzamastseva    if ($overwrite && (!$ow || $auth < $auth_ow)) {
48024870174SAndreas Gohr        return [$lang['uploadexist'], 0];
4813df72098SAndreas Gohr    }
4828cb1eb01SAndreas Gohr    // check for valid content
483ffb291f2SAdrian Lang    $ok = media_contentcheck($file['name'], $file['mime']);
4848cb1eb01SAndreas Gohr    if ($ok == -1) {
48524870174SAndreas Gohr        return [sprintf($lang['uploadbadcontent'], '.' . $file['ext']), -1];
4868cb1eb01SAndreas Gohr    } elseif ($ok == -2) {
48724870174SAndreas Gohr        return [$lang['uploadspam'], -1];
48826ceae18SAndreas Gohr    } elseif ($ok == -3) {
48924870174SAndreas Gohr        return [$lang['uploadxss'], -1];
4908cb1eb01SAndreas Gohr    }
4918cb1eb01SAndreas Gohr
49211d9dfa5SMichael Klier    // prepare event data
49324870174SAndreas Gohr    $data = [];
494ffb291f2SAdrian Lang    $data[0] = $file['name'];
49511d9dfa5SMichael Klier    $data[1] = $fn;
49611d9dfa5SMichael Klier    $data[2] = $id;
497ffb291f2SAdrian Lang    $data[3] = $file['mime'];
49899c8d7f2Smichael    $data[4] = $overwrite;
499ffb291f2SAdrian Lang    $data[5] = $move;
50011d9dfa5SMichael Klier
50111d9dfa5SMichael Klier    // trigger event
502cbb44eabSAndreas Gohr    return Event::createAndTrigger('MEDIA_UPLOAD_FINISH', $data, '_media_upload_action', true);
50311d9dfa5SMichael Klier}
50411d9dfa5SMichael Klier
50511d9dfa5SMichael Klier/**
50642ea7f44SGerrit Uitslag * Callback adapter for media_upload_finish() triggered by MEDIA_UPLOAD_FINISH
50742ea7f44SGerrit Uitslag *
50811d9dfa5SMichael Klier * @author Michael Klier <chi@chimeric.de>
50942ea7f44SGerrit Uitslag *
51042ea7f44SGerrit Uitslag * @param array $data event data
51142ea7f44SGerrit Uitslag * @return false|array|string
51211d9dfa5SMichael Klier */
513d868eb89SAndreas Gohrfunction _media_upload_action($data)
514d868eb89SAndreas Gohr{
51511d9dfa5SMichael Klier    // fixme do further sanity tests of given data?
516ffb291f2SAdrian Lang    if (is_array($data) && count($data) === 6) {
517ffb291f2SAdrian Lang        return media_upload_finish($data[0], $data[1], $data[2], $data[3], $data[4], $data[5]);
51811d9dfa5SMichael Klier    } else {
51911d9dfa5SMichael Klier        return false; //callback error
52011d9dfa5SMichael Klier    }
52111d9dfa5SMichael Klier}
52211d9dfa5SMichael Klier
52311d9dfa5SMichael Klier/**
52411d9dfa5SMichael Klier * Saves an uploaded media file
52511d9dfa5SMichael Klier *
52611d9dfa5SMichael Klier * @author Andreas Gohr <andi@splitbrain.org>
52711d9dfa5SMichael Klier * @author Michael Klier <chi@chimeric.de>
528cbe26ad6SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
52942ea7f44SGerrit Uitslag *
53042ea7f44SGerrit Uitslag * @param string $fn_tmp
53142ea7f44SGerrit Uitslag * @param string $fn
53242ea7f44SGerrit Uitslag * @param string $id        media id
53342ea7f44SGerrit Uitslag * @param string $imime     mime type
53442ea7f44SGerrit Uitslag * @param bool   $overwrite overwrite existing?
53542ea7f44SGerrit Uitslag * @param string $move      function name
53642ea7f44SGerrit Uitslag * @return array|string
53711d9dfa5SMichael Klier */
538d868eb89SAndreas Gohrfunction media_upload_finish($fn_tmp, $fn, $id, $imime, $overwrite, $move = 'move_uploaded_file')
539d868eb89SAndreas Gohr{
54011d9dfa5SMichael Klier    global $conf;
54111d9dfa5SMichael Klier    global $lang;
5429c1bd4bcSKate Arzamastseva    global $REV;
54311d9dfa5SMichael Klier
544e4f389efSKate Arzamastseva    $old = @filemtime($fn);
54579e79377SAndreas Gohr    if (!file_exists(mediaFN($id, $old)) && file_exists($fn)) {
546e4f389efSKate Arzamastseva        // add old revision to the attic if missing
547cbe26ad6SKate Arzamastseva        media_saveOldRevision($id);
548e4f389efSKate Arzamastseva    }
549e4f389efSKate Arzamastseva
5503df72098SAndreas Gohr    // prepare directory
551cc7d0c94SBen Coburn    io_createNamespace($id, 'media');
55211d9dfa5SMichael Klier
553ac3ed4afSGerrit Uitslag    $filesize_old = file_exists($fn) ? filesize($fn) : 0;
554ac3ed4afSGerrit Uitslag
555ffb291f2SAdrian Lang    if ($move($fn_tmp, $fn)) {
55623846a98SKate Arzamastseva        @clearstatcache(true, $fn);
557dad6764eSKate Arzamastseva        $new = @filemtime($fn);
55874400ea5SBen Coburn        // Set the correct permission here.
55974400ea5SBen Coburn        // Always chmod media because they may be saved with different permissions than expected from the php umask.
56074400ea5SBen Coburn        // (Should normally chmod to $conf['fperm'] only if $conf['fperm'] is set.)
56174400ea5SBen Coburn        chmod($fn, $conf['fmode']);
5623df72098SAndreas Gohr        msg($lang['uploadsucc'], 1);
56383734cddSPhy        media_notify($id, $fn, $imime, $old, $new);
56499c8d7f2Smichael        // add a log entry to the media changelog
565ac3ed4afSGerrit Uitslag        $filesize_new = filesize($fn);
566ac3ed4afSGerrit Uitslag        $sizechange = $filesize_new - $filesize_old;
5679c1bd4bcSKate Arzamastseva        if ($REV) {
56864159a61SAndreas Gohr            addMediaLogEntry(
56964159a61SAndreas Gohr                $new,
57064159a61SAndreas Gohr                $id,
57164159a61SAndreas Gohr                DOKU_CHANGE_TYPE_REVERT,
57264159a61SAndreas Gohr                sprintf($lang['restored'], dformat($REV)),
57364159a61SAndreas Gohr                $REV,
57464159a61SAndreas Gohr                null,
57564159a61SAndreas Gohr                $sizechange
57664159a61SAndreas Gohr            );
5779c1bd4bcSKate Arzamastseva        } elseif ($overwrite) {
578ac3ed4afSGerrit Uitslag            addMediaLogEntry($new, $id, DOKU_CHANGE_TYPE_EDIT, '', '', null, $sizechange);
57999c8d7f2Smichael        } else {
580ac3ed4afSGerrit Uitslag            addMediaLogEntry($new, $id, DOKU_CHANGE_TYPE_CREATE, $lang['created'], '', null, $sizechange);
58199c8d7f2Smichael        }
5823df72098SAndreas Gohr        return $id;
5833df72098SAndreas Gohr    } else {
58424870174SAndreas Gohr        return [$lang['uploadfail'], -1];
5853df72098SAndreas Gohr    }
5863df72098SAndreas Gohr}
5873df72098SAndreas Gohr
5888cb1eb01SAndreas Gohr/**
589cbe26ad6SKate Arzamastseva * Moves the current version of media file to the media_attic
590cbe26ad6SKate Arzamastseva * directory
591cbe26ad6SKate Arzamastseva *
592cbe26ad6SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
59342ea7f44SGerrit Uitslag *
594cbe26ad6SKate Arzamastseva * @param string $id
595cbe26ad6SKate Arzamastseva * @return int - revision date
596e4f389efSKate Arzamastseva */
597d868eb89SAndreas Gohrfunction media_saveOldRevision($id)
598d868eb89SAndreas Gohr{
599dbf57c96SKate Arzamastseva    global $conf, $lang;
600dbf57c96SKate Arzamastseva
601e4f389efSKate Arzamastseva    $oldf = mediaFN($id);
60279e79377SAndreas Gohr    if (!file_exists($oldf)) return '';
603e4f389efSKate Arzamastseva    $date = filemtime($oldf);
604e5d185e1SKate Arzamastseva    if (!$conf['mediarevisions']) return $date;
605e5d185e1SKate Arzamastseva
606047bad06SGerrit Uitslag    $medialog = new MediaChangeLog($id);
607047bad06SGerrit Uitslag    if (!$medialog->getRevisionInfo($date)) {
608dbf57c96SKate Arzamastseva        // there was an external edit,
609dbf57c96SKate Arzamastseva        // there is no log entry for current version of file
610ac3ed4afSGerrit Uitslag        $sizechange = filesize($oldf);
61179e79377SAndreas Gohr        if (!file_exists(mediaMetaFN($id, '.changes'))) {
612ac3ed4afSGerrit Uitslag            addMediaLogEntry($date, $id, DOKU_CHANGE_TYPE_CREATE, $lang['created'], '', null, $sizechange);
613dbf57c96SKate Arzamastseva        } else {
614ac3ed4afSGerrit Uitslag            $oldRev = $medialog->getRevisions(-1, 1); // from changelog
615ac3ed4afSGerrit Uitslag            $oldRev = (int) (empty($oldRev) ? 0 : $oldRev[0]);
616ac3ed4afSGerrit Uitslag            $filesize_old = filesize(mediaFN($id, $oldRev));
61724870174SAndreas Gohr            $sizechange -= $filesize_old;
618ac3ed4afSGerrit Uitslag
619ac3ed4afSGerrit Uitslag            addMediaLogEntry($date, $id, DOKU_CHANGE_TYPE_EDIT, '', '', null, $sizechange);
620dbf57c96SKate Arzamastseva        }
621dbf57c96SKate Arzamastseva    }
622dbf57c96SKate Arzamastseva
623e4f389efSKate Arzamastseva    $newf = mediaFN($id, $date);
624e4f389efSKate Arzamastseva    io_makeFileDir($newf);
625cbe26ad6SKate Arzamastseva    if (copy($oldf, $newf)) {
626e4f389efSKate Arzamastseva        // Set the correct permission here.
627e4f389efSKate Arzamastseva        // Always chmod media because they may be saved with different permissions than expected from the php umask.
628e4f389efSKate Arzamastseva        // (Should normally chmod to $conf['fperm'] only if $conf['fperm'] is set.)
629e4f389efSKate Arzamastseva        chmod($newf, $conf['fmode']);
630e4f389efSKate Arzamastseva    }
631e4f389efSKate Arzamastseva    return $date;
632e4f389efSKate Arzamastseva}
633e4f389efSKate Arzamastseva
634e4f389efSKate Arzamastseva/**
6358cb1eb01SAndreas Gohr * This function checks if the uploaded content is really what the
63626ceae18SAndreas Gohr * mimetype says it is. We also do spam checking for text types here.
6378cb1eb01SAndreas Gohr *
6388cb1eb01SAndreas Gohr * We need to do this stuff because we can not rely on the browser
6398cb1eb01SAndreas Gohr * to do this check correctly. Yes, IE is broken as usual.
6408cb1eb01SAndreas Gohr *
6418cb1eb01SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
64226ceae18SAndreas Gohr * @link   http://www.splitbrain.org/blog/2007-02/12-internet_explorer_facilitates_cross_site_scripting
6438cb1eb01SAndreas Gohr * @fixme  check all 26 magic IE filetypes here?
64442ea7f44SGerrit Uitslag *
64542ea7f44SGerrit Uitslag * @param string $file path to file
64642ea7f44SGerrit Uitslag * @param string $mime mimetype
64742ea7f44SGerrit Uitslag * @return int
6488cb1eb01SAndreas Gohr */
649d868eb89SAndreas Gohrfunction media_contentcheck($file, $mime)
650d868eb89SAndreas Gohr{
65126ceae18SAndreas Gohr    global $conf;
65226ceae18SAndreas Gohr    if ($conf['iexssprotect']) {
65326ceae18SAndreas Gohr        $fh = @fopen($file, 'rb');
65426ceae18SAndreas Gohr        if ($fh) {
65526ceae18SAndreas Gohr            $bytes = fread($fh, 256);
65626ceae18SAndreas Gohr            fclose($fh);
65726ceae18SAndreas Gohr            if (preg_match('/<(script|a|img|html|body|iframe)[\s>]/i', $bytes)) {
65842ea7f44SGerrit Uitslag                return -3; //XSS: possibly malicious content
65926ceae18SAndreas Gohr            }
66026ceae18SAndreas Gohr        }
66126ceae18SAndreas Gohr    }
6626c16a3a9Sfiwswe    if (str_starts_with($mime, 'image/')) {
6638cb1eb01SAndreas Gohr        $info = @getimagesize($file);
6648cb1eb01SAndreas Gohr        if ($mime == 'image/gif' && $info[2] != 1) {
66542ea7f44SGerrit Uitslag            return -1; // uploaded content did not match the file extension
6668cb1eb01SAndreas Gohr        } elseif ($mime == 'image/jpeg' && $info[2] != 2) {
6678cb1eb01SAndreas Gohr            return -1;
6688cb1eb01SAndreas Gohr        } elseif ($mime == 'image/png' && $info[2] != 3) {
6698cb1eb01SAndreas Gohr            return -1;
6708cb1eb01SAndreas Gohr        }
6718cb1eb01SAndreas Gohr        # fixme maybe check other images types as well
6726c16a3a9Sfiwswe    } elseif (str_starts_with($mime, 'text/')) {
6738cb1eb01SAndreas Gohr        global $TEXT;
6748cb1eb01SAndreas Gohr        $TEXT = io_readFile($file);
6758cb1eb01SAndreas Gohr        if (checkwordblock()) {
67642ea7f44SGerrit Uitslag            return -2; //blocked by the spam blacklist
6778cb1eb01SAndreas Gohr        }
6788cb1eb01SAndreas Gohr    }
6798cb1eb01SAndreas Gohr    return 0;
6808cb1eb01SAndreas Gohr}
6813df72098SAndreas Gohr
6823df72098SAndreas Gohr/**
68375030359SAndreas Gohr * Send a notify mail on uploads
68475030359SAndreas Gohr *
68575030359SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
68642ea7f44SGerrit Uitslag *
68742ea7f44SGerrit Uitslag * @param string   $id      media id
68842ea7f44SGerrit Uitslag * @param string   $file    path to file
68942ea7f44SGerrit Uitslag * @param string   $mime    mime type
69042ea7f44SGerrit Uitslag * @param bool|int $old_rev revision timestamp or false
69175030359SAndreas Gohr */
692d868eb89SAndreas Gohrfunction media_notify($id, $file, $mime, $old_rev = false, $current_rev = false)
693d868eb89SAndreas Gohr{
69475030359SAndreas Gohr    global $conf;
69579a2d784SGerrit Uitslag    if (empty($conf['notify'])) return; //notify enabled?
69675030359SAndreas Gohr
697704a815fSMichael Große    $subscription = new MediaSubscriptionSender();
69879a2d784SGerrit Uitslag    $subscription->sendMediaDiff($conf['notify'], 'uploadmail', $id, $old_rev, $current_rev);
69975030359SAndreas Gohr}
70075030359SAndreas Gohr
70175030359SAndreas Gohr/**
7023df72098SAndreas Gohr * List all files in a given Media namespace
70342ea7f44SGerrit Uitslag *
70421d806cdSGerrit Uitslag * @param string      $ns             namespace
70542ea7f44SGerrit Uitslag * @param null|int    $auth           permission level
70642ea7f44SGerrit Uitslag * @param string      $jump           id
70742ea7f44SGerrit Uitslag * @param bool        $fullscreenview
7088702de7fSGerrit Uitslag * @param bool|string $sort           sorting order, false skips sorting
7093df72098SAndreas Gohr */
710d868eb89SAndreas Gohrfunction media_filelist($ns, $auth = null, $jump = '', $fullscreenview = false, $sort = false)
711d868eb89SAndreas Gohr{
7123df72098SAndreas Gohr    global $conf;
7133df72098SAndreas Gohr    global $lang;
7143df72098SAndreas Gohr    $ns = cleanID($ns);
7153df72098SAndreas Gohr
7163df72098SAndreas Gohr    // check auth our self if not given (needed for ajax calls)
7173df72098SAndreas Gohr    if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*");
7183df72098SAndreas Gohr
719d9162c6cSKate Arzamastseva    if (!$fullscreenview) echo '<h1 id="media__ns">:' . hsc($ns) . '</h1>' . NL;
7203df72098SAndreas Gohr
7213df72098SAndreas Gohr    if ($auth < AUTH_READ) {
7223df72098SAndreas Gohr        // FIXME: print permission warning here instead?
7233df72098SAndreas Gohr        echo '<div class="nothing">' . $lang['nothingfound'] . '</div>' . NL;
72456fe6664SAndreas Gohr    } else {
72589274c0dSChristopher Smith        if (!$fullscreenview) {
72689274c0dSChristopher Smith            media_uploadform($ns, $auth);
72789274c0dSChristopher Smith            media_searchform($ns);
72889274c0dSChristopher Smith        }
7293df72098SAndreas Gohr
7303df72098SAndreas Gohr        $dir = utf8_encodeFN(str_replace(':', '/', $ns));
73124870174SAndreas Gohr        $data = [];
732dccd6b2bSAndreas Gohr        search(
733dccd6b2bSAndreas Gohr            $data,
734dccd6b2bSAndreas Gohr            $conf['mediadir'],
735dccd6b2bSAndreas Gohr            'search_mediafiles',
736dccd6b2bSAndreas Gohr            ['showmsg' => true, 'depth' => 1],
737dccd6b2bSAndreas Gohr            $dir,
738dccd6b2bSAndreas Gohr            1,
739dccd6b2bSAndreas Gohr            $sort
740dccd6b2bSAndreas Gohr        );
7413df72098SAndreas Gohr
742093fe67eSAndreas Gohr        if ($data === []) {
7433df72098SAndreas Gohr            echo '<div class="nothing">' . $lang['nothingfound'] . '</div>' . NL;
7445b9353faSKate Arzamastseva        } else {
7455b9353faSKate Arzamastseva            if ($fullscreenview) {
746554a8c9fSAdrian Lang                echo '<ul class="' . _media_get_list_type() . '">';
7475b9353faSKate Arzamastseva            }
7485b9353faSKate Arzamastseva            foreach ($data as $item) {
7495b9353faSKate Arzamastseva                if (!$fullscreenview) {
7504f33babfSAndreas Gohr                    //FIXME old call: media_printfile($item,$auth,$jump);
75179a2d784SGerrit Uitslag                    $display = new DisplayRow($item);
7529453716dSAndreas Gohr                    $display->scrollIntoView($jump == $item->getID());
7534f33babfSAndreas Gohr                    $display->show();
7545b9353faSKate Arzamastseva                } else {
7554f33babfSAndreas Gohr                    //FIXME old call: media_printfile_thumbs($item,$auth,$jump);
7564f33babfSAndreas Gohr                    echo '<li>';
75779a2d784SGerrit Uitslag                    $display = new DisplayTile($item);
7589453716dSAndreas Gohr                    $display->scrollIntoView($jump == $item->getID());
7594f33babfSAndreas Gohr                    $display->show();
7604f33babfSAndreas Gohr                    echo '</li>';
7615b9353faSKate Arzamastseva                }
7625b9353faSKate Arzamastseva            }
76394add303SAnika Henke            if ($fullscreenview) echo '</ul>' . NL;
7643df72098SAndreas Gohr        }
76556fe6664SAndreas Gohr    }
766d9162c6cSKate Arzamastseva}
767d9162c6cSKate Arzamastseva
768d9162c6cSKate Arzamastseva/**
769d9162c6cSKate Arzamastseva * Prints tabs for files list actions
770d9162c6cSKate Arzamastseva *
771d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
77295b451bcSAdrian Lang * @author Adrian Lang <mail@adrianlang.de>
77395b451bcSAdrian Lang *
774035e07f1SKate Arzamastseva * @param string $selected_tab - opened tab
775d9162c6cSKate Arzamastseva */
77695b451bcSAdrian Lang
777d868eb89SAndreas Gohrfunction media_tabs_files($selected_tab = '')
778d868eb89SAndreas Gohr{
779d9162c6cSKate Arzamastseva    global $lang;
78024870174SAndreas Gohr    $tabs = [];
7817d34963bSAndreas Gohr    foreach (
7827d34963bSAndreas Gohr        [
78324870174SAndreas Gohr            'files' => 'mediaselect',
78495b451bcSAdrian Lang            'upload' => 'media_uploadtab',
78524870174SAndreas Gohr            'search' => 'media_searchtab'
7867d34963bSAndreas Gohr        ] as $tab => $caption
7877d34963bSAndreas Gohr    ) {
78824870174SAndreas Gohr        $tabs[$tab] = [
78924870174SAndreas Gohr            'href'    => media_managerURL(['tab_files' => $tab], '&'),
79024870174SAndreas Gohr            'caption' => $lang[$caption]
79124870174SAndreas Gohr        ];
79295b451bcSAdrian Lang    }
793d9162c6cSKate Arzamastseva
79495b451bcSAdrian Lang    html_tabs($tabs, $selected_tab);
795d9162c6cSKate Arzamastseva}
796d9162c6cSKate Arzamastseva
797d9162c6cSKate Arzamastseva/**
798d9162c6cSKate Arzamastseva * Prints tabs for files details actions
799d9162c6cSKate Arzamastseva *
800d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
801ebc28e69SAndreas Gohr * @param string $image filename of the current image
802ebc28e69SAndreas Gohr * @param string $selected_tab opened tab
803d9162c6cSKate Arzamastseva */
804d868eb89SAndreas Gohrfunction media_tabs_details($image, $selected_tab = '')
805d868eb89SAndreas Gohr{
806e5d185e1SKate Arzamastseva    global $lang, $conf;
807d9162c6cSKate Arzamastseva
80824870174SAndreas Gohr    $tabs = [];
80924870174SAndreas Gohr    $tabs['view'] = [
81024870174SAndreas Gohr        'href'    => media_managerURL(['tab_details' => 'view'], '&'),
81124870174SAndreas Gohr        'caption' => $lang['media_viewtab']
81224870174SAndreas Gohr    ];
813d9162c6cSKate Arzamastseva
81424870174SAndreas Gohr    [, $mime] = mimetype($image);
81579e79377SAndreas Gohr    if ($mime == 'image/jpeg' && file_exists(mediaFN($image))) {
81624870174SAndreas Gohr        $tabs['edit'] = [
81724870174SAndreas Gohr            'href'    => media_managerURL(['tab_details' => 'edit'], '&'),
81824870174SAndreas Gohr            'caption' => $lang['media_edittab']
81924870174SAndreas Gohr        ];
820dd9ba38eSKate Arzamastseva    }
821e5d185e1SKate Arzamastseva    if ($conf['mediarevisions']) {
82224870174SAndreas Gohr        $tabs['history'] = [
82324870174SAndreas Gohr            'href'    => media_managerURL(['tab_details' => 'history'], '&'),
82424870174SAndreas Gohr            'caption' => $lang['media_historytab']
82524870174SAndreas Gohr        ];
826e5d185e1SKate Arzamastseva    }
827d9162c6cSKate Arzamastseva
82895b451bcSAdrian Lang    html_tabs($tabs, $selected_tab);
829d9162c6cSKate Arzamastseva}
830d9162c6cSKate Arzamastseva
831d9162c6cSKate Arzamastseva/**
832d9162c6cSKate Arzamastseva * Prints options for the tab that displays a list of all files
833d9162c6cSKate Arzamastseva *
834d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
835d9162c6cSKate Arzamastseva */
836d868eb89SAndreas Gohrfunction media_tab_files_options()
837d868eb89SAndreas Gohr{
8388108113cSTom N Harris    global $lang;
8398108113cSTom N Harris    global $INPUT;
840b7e5821dSAndreas Gohr    global $ID;
841b960c74fSSatoshi Sahara
842b960c74fSSatoshi Sahara    $form = new Form([
843b960c74fSSatoshi Sahara            'method' => 'get',
844b960c74fSSatoshi Sahara            'action' => wl($ID),
845b960c74fSSatoshi Sahara            'class' => 'options'
846b960c74fSSatoshi Sahara    ]);
847b960c74fSSatoshi Sahara    $form->addTagOpen('div')->addClass('no');
848b960c74fSSatoshi Sahara    $form->setHiddenField('sectok', null);
849b960c74fSSatoshi Sahara    $media_manager_params = media_managerURL([], '', false, true);
85038b2bf35SAnika Henke    foreach ($media_manager_params as $pKey => $pVal) {
851b960c74fSSatoshi Sahara        $form->setHiddenField($pKey, $pVal);
85238b2bf35SAnika Henke    }
8538108113cSTom N Harris    if ($INPUT->has('q')) {
854b960c74fSSatoshi Sahara        $form->setHiddenField('q', $INPUT->str('q'));
855554a8c9fSAdrian Lang    }
856b960c74fSSatoshi Sahara    $form->addHTML('<ul>' . NL);
8577d34963bSAndreas Gohr    foreach (
8587d34963bSAndreas Gohr        [
85924870174SAndreas Gohr            'list' => ['listType', ['thumbs', 'rows']],
86024870174SAndreas Gohr            'sort' => ['sortBy', ['name', 'date']]
8617d34963bSAndreas Gohr        ] as $group => $content
8627d34963bSAndreas Gohr    ) {
863ec88e837SAndreas Gohr        $checked = "_media_get_{$group}_type";
864554a8c9fSAdrian Lang        $checked = $checked();
865d9162c6cSKate Arzamastseva
866b960c74fSSatoshi Sahara        $form->addHTML('<li class="' . $content[0] . '">');
86795b451bcSAdrian Lang        foreach ($content[1] as $option) {
86824870174SAndreas Gohr            $attrs = [];
869554a8c9fSAdrian Lang            if ($checked == $option) {
87095b451bcSAdrian Lang                $attrs['checked'] = 'checked';
87195b451bcSAdrian Lang            }
872b960c74fSSatoshi Sahara            $radio = $form->addRadioButton(
873b960c74fSSatoshi Sahara                $group . '_dwmedia',
874b960c74fSSatoshi Sahara                $lang['media_' . $group . '_' . $option]
875b960c74fSSatoshi Sahara            )->val($option)->id($content[0] . '__' . $option)->addClass($option);
876b960c74fSSatoshi Sahara            $radio->attrs($attrs);
87795b451bcSAdrian Lang        }
878b960c74fSSatoshi Sahara        $form->addHTML('</li>' . NL);
87995b451bcSAdrian Lang    }
880b960c74fSSatoshi Sahara    $form->addHTML('<li>');
881b960c74fSSatoshi Sahara    $form->addButton('', $lang['btn_apply'])->attr('type', 'submit');
882b960c74fSSatoshi Sahara    $form->addHTML('</li>' . NL);
883b960c74fSSatoshi Sahara    $form->addHTML('</ul>' . NL);
884b960c74fSSatoshi Sahara    $form->addTagClose('div');
88526dfc232SAndreas Gohr    echo $form->toHTML();
886d9162c6cSKate Arzamastseva}
887d9162c6cSKate Arzamastseva
888d9162c6cSKate Arzamastseva/**
88987deddfaSKate Arzamastseva * Returns type of sorting for the list of files in media manager
89087deddfaSKate Arzamastseva *
89187deddfaSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
89242ea7f44SGerrit Uitslag *
89387deddfaSKate Arzamastseva * @return string - sort type
89487deddfaSKate Arzamastseva */
895d868eb89SAndreas Gohrfunction _media_get_sort_type()
896d868eb89SAndreas Gohr{
89724870174SAndreas Gohr    return _media_get_display_param('sort', ['default' => 'name', 'date']);
89887deddfaSKate Arzamastseva}
899554a8c9fSAdrian Lang
9006ffaeda9SGerrit Uitslag/**
9016ffaeda9SGerrit Uitslag * Returns type of listing for the list of files in media manager
9026ffaeda9SGerrit Uitslag *
9036ffaeda9SGerrit Uitslag * @author Kate Arzamastseva <pshns@ukr.net>
90442ea7f44SGerrit Uitslag *
9056ffaeda9SGerrit Uitslag * @return string - list type
9066ffaeda9SGerrit Uitslag */
907d868eb89SAndreas Gohrfunction _media_get_list_type()
908d868eb89SAndreas Gohr{
90924870174SAndreas Gohr    return _media_get_display_param('list', ['default' => 'thumbs', 'rows']);
91087deddfaSKate Arzamastseva}
911554a8c9fSAdrian Lang
9126ffaeda9SGerrit Uitslag/**
9136ffaeda9SGerrit Uitslag * Get display parameters
9146ffaeda9SGerrit Uitslag *
9156ffaeda9SGerrit Uitslag * @param string $param   name of parameter
9166ffaeda9SGerrit Uitslag * @param array  $values  allowed values, where default value has index key 'default'
9176ffaeda9SGerrit Uitslag * @return string the parameter value
9186ffaeda9SGerrit Uitslag */
919d868eb89SAndreas Gohrfunction _media_get_display_param($param, $values)
920d868eb89SAndreas Gohr{
9218108113cSTom N Harris    global $INPUT;
9228108113cSTom N Harris    if (in_array($INPUT->str($param), $values)) {
923554a8c9fSAdrian Lang        // FIXME: Set cookie
9248108113cSTom N Harris        return $INPUT->str($param);
925554a8c9fSAdrian Lang    } else {
9263629bc8cSAdrian Lang        $val = get_doku_pref($param, $values['default']);
9273629bc8cSAdrian Lang        if (!in_array($val, $values)) {
9283629bc8cSAdrian Lang            $val = $values['default'];
9293629bc8cSAdrian Lang        }
9303629bc8cSAdrian Lang        return $val;
931554a8c9fSAdrian Lang    }
93287deddfaSKate Arzamastseva}
93387deddfaSKate Arzamastseva
93487deddfaSKate Arzamastseva/**
935d9162c6cSKate Arzamastseva * Prints tab that displays a list of all files
936d9162c6cSKate Arzamastseva *
937d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
93842ea7f44SGerrit Uitslag *
93942ea7f44SGerrit Uitslag * @param string    $ns
94042ea7f44SGerrit Uitslag * @param null|int  $auth permission level
94142ea7f44SGerrit Uitslag * @param string    $jump item id
942d9162c6cSKate Arzamastseva */
943d868eb89SAndreas Gohrfunction media_tab_files($ns, $auth = null, $jump = '')
944d868eb89SAndreas Gohr{
945d9162c6cSKate Arzamastseva    global $lang;
946d9162c6cSKate Arzamastseva    if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*");
947d9162c6cSKate Arzamastseva
948d9162c6cSKate Arzamastseva    if ($auth < AUTH_READ) {
94988a71175SKate Arzamastseva        echo '<div class="nothing">' . $lang['media_perm_read'] . '</div>' . NL;
950d9162c6cSKate Arzamastseva    } else {
95195b451bcSAdrian Lang        media_filelist($ns, $auth, $jump, true, _media_get_sort_type());
952d9162c6cSKate Arzamastseva    }
953d9162c6cSKate Arzamastseva}
954d9162c6cSKate Arzamastseva
955d9162c6cSKate Arzamastseva/**
956d9162c6cSKate Arzamastseva * Prints tab that displays uploading form
957d9162c6cSKate Arzamastseva *
958d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
95942ea7f44SGerrit Uitslag *
96042ea7f44SGerrit Uitslag * @param string   $ns
96142ea7f44SGerrit Uitslag * @param null|int $auth permission level
96242ea7f44SGerrit Uitslag * @param string   $jump item id
963d9162c6cSKate Arzamastseva */
964d868eb89SAndreas Gohrfunction media_tab_upload($ns, $auth = null, $jump = '')
965d868eb89SAndreas Gohr{
966d9162c6cSKate Arzamastseva    global $lang;
967d9162c6cSKate Arzamastseva    if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*");
968d9162c6cSKate Arzamastseva
96994add303SAnika Henke    echo '<div class="upload">' . NL;
97095b451bcSAdrian Lang    if ($auth >= AUTH_UPLOAD) {
97195b451bcSAdrian Lang        echo '<p>' . $lang['mediaupload'] . '</p>';
97295b451bcSAdrian Lang    }
973d9162c6cSKate Arzamastseva    media_uploadform($ns, $auth, true);
97494add303SAnika Henke    echo '</div>' . NL;
975d9162c6cSKate Arzamastseva}
976d9162c6cSKate Arzamastseva
977d9162c6cSKate Arzamastseva/**
978d9162c6cSKate Arzamastseva * Prints tab that displays search form
979d9162c6cSKate Arzamastseva *
980d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
98142ea7f44SGerrit Uitslag *
98242ea7f44SGerrit Uitslag * @param string $ns
98342ea7f44SGerrit Uitslag * @param null|int $auth permission level
984d9162c6cSKate Arzamastseva */
985d868eb89SAndreas Gohrfunction media_tab_search($ns, $auth = null)
986d868eb89SAndreas Gohr{
9878108113cSTom N Harris    global $INPUT;
988d9162c6cSKate Arzamastseva
9898108113cSTom N Harris    $do = $INPUT->str('mediado');
9908108113cSTom N Harris    $query = $INPUT->str('q');
99194add303SAnika Henke    echo '<div class="search">' . NL;
992d9162c6cSKate Arzamastseva
993d9162c6cSKate Arzamastseva    media_searchform($ns, $query, true);
9942dba8df4SAdrian Lang    if ($do == 'searchlist' || $query) {
99595b451bcSAdrian Lang        media_searchlist($query, $ns, $auth, true, _media_get_sort_type());
99695b451bcSAdrian Lang    }
99794add303SAnika Henke    echo '</div>' . NL;
998d9162c6cSKate Arzamastseva}
999d9162c6cSKate Arzamastseva
1000d9162c6cSKate Arzamastseva/**
1001d9162c6cSKate Arzamastseva * Prints tab that displays mediafile details
1002d9162c6cSKate Arzamastseva *
1003d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
1004e0c26282SGerrit Uitslag *
1005e0c26282SGerrit Uitslag * @param string     $image media id
1006e0c26282SGerrit Uitslag * @param string     $ns
1007e0c26282SGerrit Uitslag * @param null|int   $auth  permission level
100842ea7f44SGerrit Uitslag * @param string|int $rev   revision timestamp or empty string
1009d9162c6cSKate Arzamastseva */
1010d868eb89SAndreas Gohrfunction media_tab_view($image, $ns, $auth = null, $rev = '')
1011d868eb89SAndreas Gohr{
1012ebc28e69SAndreas Gohr    global $lang;
1013d9162c6cSKate Arzamastseva    if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*");
1014d9162c6cSKate Arzamastseva
1015e136d6ccSKate Arzamastseva    if ($image && $auth >= AUTH_READ) {
1016dd9ba38eSKate Arzamastseva        $meta = new JpegMeta(mediaFN($image, $rev));
1017dd9ba38eSKate Arzamastseva        media_preview($image, $auth, $rev, $meta);
1018e136d6ccSKate Arzamastseva        media_preview_buttons($image, $auth, $rev);
1019dd9ba38eSKate Arzamastseva        media_details($image, $auth, $rev, $meta);
1020e136d6ccSKate Arzamastseva    } else {
102194add303SAnika Henke        echo '<div class="nothing">' . $lang['media_perm_read'] . '</div>' . NL;
1022e136d6ccSKate Arzamastseva    }
1023d9162c6cSKate Arzamastseva}
1024d9162c6cSKate Arzamastseva
1025d9162c6cSKate Arzamastseva/**
1026d9162c6cSKate Arzamastseva * Prints tab that displays form for editing mediafile metadata
1027d9162c6cSKate Arzamastseva *
1028d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
1029e0c26282SGerrit Uitslag *
1030e0c26282SGerrit Uitslag * @param string     $image media id
1031e0c26282SGerrit Uitslag * @param string     $ns
1032e0c26282SGerrit Uitslag * @param null|int   $auth permission level
1033d9162c6cSKate Arzamastseva */
1034d868eb89SAndreas Gohrfunction media_tab_edit($image, $ns, $auth = null)
1035d868eb89SAndreas Gohr{
1036d9162c6cSKate Arzamastseva    if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*");
1037d9162c6cSKate Arzamastseva
10381eeeced2SKate Arzamastseva    if ($image) {
103924870174SAndreas Gohr        [, $mime] = mimetype($image);
104030fd72fbSKate Arzamastseva        if ($mime == 'image/jpeg') media_metaform($image, $auth);
10411eeeced2SKate Arzamastseva    }
1042d9162c6cSKate Arzamastseva}
1043d9162c6cSKate Arzamastseva
1044d9162c6cSKate Arzamastseva/**
1045d9162c6cSKate Arzamastseva * Prints tab that displays mediafile revisions
1046d9162c6cSKate Arzamastseva *
1047d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
1048e0c26282SGerrit Uitslag *
1049e0c26282SGerrit Uitslag * @param string     $image media id
1050e0c26282SGerrit Uitslag * @param string     $ns
1051e0c26282SGerrit Uitslag * @param null|int   $auth permission level
1052d9162c6cSKate Arzamastseva */
1053d868eb89SAndreas Gohrfunction media_tab_history($image, $ns, $auth = null)
1054d868eb89SAndreas Gohr{
1055d9162c6cSKate Arzamastseva    global $lang;
10568108113cSTom N Harris    global $INPUT;
10578108113cSTom N Harris
1058d9162c6cSKate Arzamastseva    if (is_null($auth)) $auth = auth_quickaclcheck("$ns:*");
10598108113cSTom N Harris    $do = $INPUT->str('mediado');
1060d9162c6cSKate Arzamastseva
10612e55802cSKate Arzamastseva    if ($auth >= AUTH_READ && $image) {
10622e55802cSKate Arzamastseva        if ($do == 'diff') {
106324870174SAndreas Gohr            (new MediaDiff($image))->show(); //media_diff($image, $ns, $auth);
10642e55802cSKate Arzamastseva        } else {
1065a46cc3dcSAndreas Gohr            $first = $INPUT->int('first', -1);
106624870174SAndreas Gohr            (new MediaRevisions($image))->show($first);
10672e55802cSKate Arzamastseva        }
106888a71175SKate Arzamastseva    } else {
106988a71175SKate Arzamastseva        echo '<div class="nothing">' . $lang['media_perm_read'] . '</div>' . NL;
10702e55802cSKate Arzamastseva    }
10713df72098SAndreas Gohr}
10723df72098SAndreas Gohr
10733df72098SAndreas Gohr/**
10741eeeced2SKate Arzamastseva * Prints mediafile details
10751eeeced2SKate Arzamastseva *
10766ffaeda9SGerrit Uitslag * @param string         $image media id
1077e0c26282SGerrit Uitslag * @param int            $auth permission level
107859bc3b48SGerrit Uitslag * @param int|string     $rev revision timestamp or empty string
10796ffaeda9SGerrit Uitslag * @param JpegMeta|bool  $meta
108042ea7f44SGerrit Uitslag *
10811eeeced2SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
10821eeeced2SKate Arzamastseva */
1083d868eb89SAndreas Gohrfunction media_preview($image, $auth, $rev = '', $meta = false)
1084d868eb89SAndreas Gohr{
1085e136d6ccSKate Arzamastseva
1086e136d6ccSKate Arzamastseva    $size = media_image_preview_size($image, $rev, $meta);
1087e136d6ccSKate Arzamastseva
1088e136d6ccSKate Arzamastseva    if ($size) {
108959f3611bSAnika Henke        global $lang;
109094add303SAnika Henke        echo '<div class="image">';
109194add303SAnika Henke
109224870174SAndreas Gohr        $more = [];
1093e136d6ccSKate Arzamastseva        if ($rev) {
10945b9353faSKate Arzamastseva            $more['rev'] = $rev;
1095e136d6ccSKate Arzamastseva        } else {
1096e136d6ccSKate Arzamastseva            $t = @filemtime(mediaFN($image));
10975b9353faSKate Arzamastseva            $more['t'] = $t;
109888a71175SKate Arzamastseva        }
109923786fd7SKate Arzamastseva
11005b9353faSKate Arzamastseva        $more['w'] = $size[0];
11015b9353faSKate Arzamastseva        $more['h'] = $size[1];
1102e136d6ccSKate Arzamastseva        $src = ml($image, $more);
110359f3611bSAnika Henke
110459f3611bSAnika Henke        echo '<a href="' . $src . '" target="_blank" title="' . $lang['mediaview'] . '">';
110595b451bcSAdrian Lang        echo '<img src="' . $src . '" alt="" style="max-width: ' . $size[0] . 'px;" />';
110659f3611bSAnika Henke        echo '</a>';
1107e136d6ccSKate Arzamastseva
1108871895a7SSatoshi Sahara        echo '</div>';
110994add303SAnika Henke    }
1110e136d6ccSKate Arzamastseva}
1111e136d6ccSKate Arzamastseva
1112e136d6ccSKate Arzamastseva/**
1113e136d6ccSKate Arzamastseva * Prints mediafile action buttons
1114e136d6ccSKate Arzamastseva *
1115e136d6ccSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
1116e0c26282SGerrit Uitslag *
1117e0c26282SGerrit Uitslag * @param string     $image media id
1118e0c26282SGerrit Uitslag * @param int        $auth  permission level
1119871895a7SSatoshi Sahara * @param int|string $rev   revision timestamp, or empty string
1120e136d6ccSKate Arzamastseva */
1121d868eb89SAndreas Gohrfunction media_preview_buttons($image, $auth, $rev = '')
1122d868eb89SAndreas Gohr{
1123e5d185e1SKate Arzamastseva    global $lang, $conf;
1124e136d6ccSKate Arzamastseva
1125871895a7SSatoshi Sahara    echo '<ul class="actions">';
11261eeeced2SKate Arzamastseva
112779e79377SAndreas Gohr    if ($auth >= AUTH_DELETE && !$rev && file_exists(mediaFN($image))) {
1128e136d6ccSKate Arzamastseva        // delete button
1129b960c74fSSatoshi Sahara        $form = new Form([
1130b960c74fSSatoshi Sahara            'id' => 'mediamanager__btn_delete',
1131b960c74fSSatoshi Sahara            'action' => media_managerURL(['delete' => $image], '&'),
1132b960c74fSSatoshi Sahara        ]);
1133b960c74fSSatoshi Sahara        $form->addTagOpen('div')->addClass('no');
1134b960c74fSSatoshi Sahara        $form->addButton('', $lang['btn_delete'])->attr('type', 'submit');
1135b960c74fSSatoshi Sahara        $form->addTagClose('div');
113695b451bcSAdrian Lang        echo '<li>';
1137b960c74fSSatoshi Sahara        echo $form->toHTML();
1138871895a7SSatoshi Sahara        echo '</li>';
1139e5d185e1SKate Arzamastseva    }
1140e5d185e1SKate Arzamastseva
1141e5d185e1SKate Arzamastseva    $auth_ow = (($conf['mediarevisions']) ? AUTH_UPLOAD : AUTH_DELETE);
1142e5d185e1SKate Arzamastseva    if ($auth >= $auth_ow && !$rev) {
1143e136d6ccSKate Arzamastseva        // upload new version button
1144b960c74fSSatoshi Sahara        $form = new Form([
1145b960c74fSSatoshi Sahara            'id' => 'mediamanager__btn_update',
1146b960c74fSSatoshi Sahara            'action' => media_managerURL(['image' => $image, 'mediado' => 'update'], '&'),
1147b960c74fSSatoshi Sahara        ]);
1148b960c74fSSatoshi Sahara        $form->addTagOpen('div')->addClass('no');
1149b960c74fSSatoshi Sahara        $form->addButton('', $lang['media_update'])->attr('type', 'submit');
1150b960c74fSSatoshi Sahara        $form->addTagClose('div');
115195b451bcSAdrian Lang        echo '<li>';
1152b960c74fSSatoshi Sahara        echo $form->toHTML();
1153871895a7SSatoshi Sahara        echo '</li>';
115470c3cc9aSKate Arzamastseva    }
1155e136d6ccSKate Arzamastseva
115679e79377SAndreas Gohr    if ($auth >= AUTH_UPLOAD && $rev && $conf['mediarevisions'] && file_exists(mediaFN($image, $rev))) {
1157e136d6ccSKate Arzamastseva        // restore button
1158b960c74fSSatoshi Sahara        $form = new Form([
1159b960c74fSSatoshi Sahara            'id' => 'mediamanager__btn_restore',
1160b960c74fSSatoshi Sahara            'action' => media_managerURL(['image' => $image], '&'),
1161b960c74fSSatoshi Sahara        ]);
1162b960c74fSSatoshi Sahara        $form->addTagOpen('div')->addClass('no');
1163b960c74fSSatoshi Sahara        $form->setHiddenField('mediado', 'restore');
1164b960c74fSSatoshi Sahara        $form->setHiddenField('rev', $rev);
1165b960c74fSSatoshi Sahara        $form->addButton('', $lang['media_restore'])->attr('type', 'submit');
1166b960c74fSSatoshi Sahara        $form->addTagClose('div');
116795b451bcSAdrian Lang        echo '<li>';
1168b960c74fSSatoshi Sahara        echo $form->toHTML();
1169871895a7SSatoshi Sahara        echo '</li>';
11709c1bd4bcSKate Arzamastseva    }
1171e136d6ccSKate Arzamastseva
1172871895a7SSatoshi Sahara    echo '</ul>';
11732e55802cSKate Arzamastseva}
11742e55802cSKate Arzamastseva
11752e55802cSKate Arzamastseva/**
1176fa8e5c77SKate Arzamastseva * Returns image width and height for mediamanager preview panel
1177fa8e5c77SKate Arzamastseva *
1178fa8e5c77SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
1179fa8e5c77SKate Arzamastseva * @param string         $image
1180e0c26282SGerrit Uitslag * @param int|string     $rev
118159bc3b48SGerrit Uitslag * @param JpegMeta|bool  $meta
1182ebc28e69SAndreas Gohr * @param int            $size
1183871895a7SSatoshi Sahara * @return array
1184fa8e5c77SKate Arzamastseva */
1185d868eb89SAndreas Gohrfunction media_image_preview_size($image, $rev, $meta = false, $size = 500)
1186d868eb89SAndreas Gohr{
11877d34963bSAndreas Gohr    if (
11880296c9b0SMatt Perry        !preg_match("/\.(jpe?g|gif|png|webp)$/", $image)
1189871895a7SSatoshi Sahara        || !file_exists($filename = mediaFN($image, $rev))
119024870174SAndreas Gohr    ) return [];
1191fa8e5c77SKate Arzamastseva
1192871895a7SSatoshi Sahara    $info = getimagesize($filename);
119324870174SAndreas Gohr    $w = $info[0];
119424870174SAndreas Gohr    $h = $info[1];
1195fa8e5c77SKate Arzamastseva
1196fa8e5c77SKate Arzamastseva    if ($meta && ($w > $size || $h > $size)) {
1197fa8e5c77SKate Arzamastseva        $ratio = $meta->getResizeRatio($size, $size);
1198fa8e5c77SKate Arzamastseva        $w = floor($w * $ratio);
1199fa8e5c77SKate Arzamastseva        $h = floor($h * $ratio);
1200fa8e5c77SKate Arzamastseva    }
120124870174SAndreas Gohr    return [$w, $h];
1202fa8e5c77SKate Arzamastseva}
1203fa8e5c77SKate Arzamastseva
1204fa8e5c77SKate Arzamastseva/**
1205fa8e5c77SKate Arzamastseva * Returns the requested EXIF/IPTC tag from the image meta
1206fa8e5c77SKate Arzamastseva *
1207fa8e5c77SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
1208e0c26282SGerrit Uitslag *
120942ea7f44SGerrit Uitslag * @param array    $tags array with tags, first existing is returned
1210fa8e5c77SKate Arzamastseva * @param JpegMeta $meta
121142ea7f44SGerrit Uitslag * @param string   $alt  alternative value
1212fa8e5c77SKate Arzamastseva * @return string
1213fa8e5c77SKate Arzamastseva */
1214d868eb89SAndreas Gohrfunction media_getTag($tags, $meta = false, $alt = '')
1215d868eb89SAndreas Gohr{
1216871895a7SSatoshi Sahara    if (!$meta) return $alt;
1217fa8e5c77SKate Arzamastseva    $info = $meta->getField($tags);
1218871895a7SSatoshi Sahara    if (!$info) return $alt;
1219fa8e5c77SKate Arzamastseva    return $info;
1220fa8e5c77SKate Arzamastseva}
1221fa8e5c77SKate Arzamastseva
1222fa8e5c77SKate Arzamastseva/**
1223e136d6ccSKate Arzamastseva * Returns mediafile tags
12242e55802cSKate Arzamastseva *
12252e55802cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
1226e0c26282SGerrit Uitslag *
1227e136d6ccSKate Arzamastseva * @param JpegMeta $meta
122842ea7f44SGerrit Uitslag * @return array list of tags of the mediafile
12292e55802cSKate Arzamastseva */
1230d868eb89SAndreas Gohrfunction media_file_tags($meta)
1231d868eb89SAndreas Gohr{
1232532850edSKate Arzamastseva    // load the field descriptions
12333e98e685SKate Arzamastseva    static $fields = null;
12343e98e685SKate Arzamastseva    if (is_null($fields)) {
12353e98e685SKate Arzamastseva        $config_files = getConfigFiles('mediameta');
12363e98e685SKate Arzamastseva        foreach ($config_files as $config_file) {
123779e79377SAndreas Gohr            if (file_exists($config_file)) include($config_file);
1238532850edSKate Arzamastseva        }
1239532850edSKate Arzamastseva    }
12401eeeced2SKate Arzamastseva
124124870174SAndreas Gohr    $tags = [];
1242dd9ba38eSKate Arzamastseva
124324870174SAndreas Gohr    foreach ($fields as $tag) {
124424870174SAndreas Gohr        $t = [];
124524870174SAndreas Gohr        if (!empty($tag[0])) $t = [$tag[0]];
12460e80bb5eSChristopher Smith        if (isset($tag[3]) && is_array($tag[3])) $t = array_merge($t, $tag[3]);
1247e136d6ccSKate Arzamastseva        $value = media_getTag($t, $meta);
124824870174SAndreas Gohr        $tags[] = ['tag' => $tag, 'value' => $value];
1249e136d6ccSKate Arzamastseva    }
1250e136d6ccSKate Arzamastseva
1251e136d6ccSKate Arzamastseva    return $tags;
1252e136d6ccSKate Arzamastseva}
1253e136d6ccSKate Arzamastseva
1254e136d6ccSKate Arzamastseva/**
1255e136d6ccSKate Arzamastseva * Prints mediafile tags
1256e136d6ccSKate Arzamastseva *
1257e136d6ccSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
125842ea7f44SGerrit Uitslag *
1259e0c26282SGerrit Uitslag * @param string        $image image id
1260e0c26282SGerrit Uitslag * @param int           $auth  permission level
1261e0c26282SGerrit Uitslag * @param string|int    $rev   revision timestamp, or empty string
1262e0c26282SGerrit Uitslag * @param bool|JpegMeta $meta  image object, or create one if false
1263e0c26282SGerrit Uitslag */
1264d868eb89SAndreas Gohrfunction media_details($image, $auth, $rev = '', $meta = false)
1265d868eb89SAndreas Gohr{
1266e136d6ccSKate Arzamastseva    global $lang;
1267e136d6ccSKate Arzamastseva
1268e136d6ccSKate Arzamastseva    if (!$meta) $meta = new JpegMeta(mediaFN($image, $rev));
1269e136d6ccSKate Arzamastseva    $tags = media_file_tags($meta);
1270e136d6ccSKate Arzamastseva
127194add303SAnika Henke    echo '<dl>' . NL;
1272e136d6ccSKate Arzamastseva    foreach ($tags as $tag) {
1273e136d6ccSKate Arzamastseva        if ($tag['value']) {
1274e136d6ccSKate Arzamastseva            $value = cleanText($tag['value']);
1275fde860beSGerrit Uitslag            echo '<dt>' . $lang[$tag['tag'][1]] . '</dt><dd>';
12764a90f94bSSatoshi Sahara            if ($tag['tag'][2] == 'date') {
12774a90f94bSSatoshi Sahara                echo dformat($value);
12784a90f94bSSatoshi Sahara            } else {
12794a90f94bSSatoshi Sahara                echo hsc($value);
12804a90f94bSSatoshi Sahara            }
128194add303SAnika Henke            echo '</dd>' . NL;
12821eeeced2SKate Arzamastseva        }
1283e136d6ccSKate Arzamastseva    }
128494add303SAnika Henke    echo '</dl>' . NL;
128522e68399Sflammy    echo '<dl>' . NL;
128622e68399Sflammy    echo '<dt>' . $lang['reference'] . ':</dt>';
1287*6734bb8cSAndreas Gohr    $media_usage = (new MetadataSearch())->mediause($image, true);
128824870174SAndreas Gohr    if ($media_usage !== []) {
128922e68399Sflammy        foreach ($media_usage as $path) {
129022e68399Sflammy            echo '<dd>' . html_wikilink($path) . '</dd>';
129122e68399Sflammy        }
129222e68399Sflammy    } else {
129322e68399Sflammy        echo '<dd>' . $lang['nothingfound'] . '</dd>';
129422e68399Sflammy    }
129522e68399Sflammy    echo '</dl>' . NL;
12961eeeced2SKate Arzamastseva}
12972e55802cSKate Arzamastseva
12982e55802cSKate Arzamastseva/**
12992e55802cSKate Arzamastseva * Shows difference between two revisions of file
13002e55802cSKate Arzamastseva *
13012e55802cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
130242ea7f44SGerrit Uitslag *
1303e0c26282SGerrit Uitslag * @param string $image  image id
1304e0c26282SGerrit Uitslag * @param string $ns
1305e0c26282SGerrit Uitslag * @param int $auth permission level
1306e0c26282SGerrit Uitslag * @param bool $fromajax
130779a2d784SGerrit Uitslag *
1308297071beSSatoshi Sahara * @deprecated 2020-12-31
1309e0c26282SGerrit Uitslag */
1310d868eb89SAndreas Gohrfunction media_diff($image, $ns, $auth, $fromajax = false)
1311d868eb89SAndreas Gohr{
131279a2d784SGerrit Uitslag    dbg_deprecated('see ' . MediaDiff::class . '::show()');
131359e81a43SKate Arzamastseva}
131459e81a43SKate Arzamastseva
13156ffaeda9SGerrit Uitslag/**
13166ffaeda9SGerrit Uitslag * Callback for media file diff
13176ffaeda9SGerrit Uitslag *
131842ea7f44SGerrit Uitslag * @param array $data event data
131979a2d784SGerrit Uitslag *
1320297071beSSatoshi Sahara * @deprecated 2020-12-31
13216ffaeda9SGerrit Uitslag */
1322d868eb89SAndreas Gohrfunction _media_file_diff($data)
1323d868eb89SAndreas Gohr{
132479a2d784SGerrit Uitslag    dbg_deprecated('see ' . MediaDiff::class . '::show()');
132559e81a43SKate Arzamastseva}
132659e81a43SKate Arzamastseva
132759e81a43SKate Arzamastseva/**
132859e81a43SKate Arzamastseva * Shows difference between two revisions of image
132959e81a43SKate Arzamastseva *
133059e81a43SKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
1331e0c26282SGerrit Uitslag *
1332e0c26282SGerrit Uitslag * @param string $image
1333e0c26282SGerrit Uitslag * @param string|int $l_rev revision timestamp, or empty string
1334e0c26282SGerrit Uitslag * @param string|int $r_rev revision timestamp, or empty string
1335e0c26282SGerrit Uitslag * @param string $ns
1336e0c26282SGerrit Uitslag * @param int $auth permission level
1337e0c26282SGerrit Uitslag * @param bool $fromajax
1338297071beSSatoshi Sahara * @deprecated 2020-12-31
133959e81a43SKate Arzamastseva */
1340d868eb89SAndreas Gohrfunction media_file_diff($image, $l_rev, $r_rev, $ns, $auth, $fromajax)
1341d868eb89SAndreas Gohr{
134279a2d784SGerrit Uitslag    dbg_deprecated('see ' . MediaDiff::class . '::showFileDiff()');
1343e136d6ccSKate Arzamastseva}
1344e136d6ccSKate Arzamastseva
1345e136d6ccSKate Arzamastseva/**
1346e136d6ccSKate Arzamastseva * Prints two images side by side
1347fa8e5c77SKate Arzamastseva * and slider
1348e136d6ccSKate Arzamastseva *
1349e136d6ccSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
135042ea7f44SGerrit Uitslag *
135142ea7f44SGerrit Uitslag * @param string $image   image id
1352e0c26282SGerrit Uitslag * @param int    $l_rev   revision timestamp, or empty string
1353e0c26282SGerrit Uitslag * @param int    $r_rev   revision timestamp, or empty string
135442ea7f44SGerrit Uitslag * @param array  $l_size  array with width and height
135542ea7f44SGerrit Uitslag * @param array  $r_size  array with width and height
135650fc55feSKate Arzamastseva * @param string $type
1357297071beSSatoshi Sahara * @deprecated 2020-12-31
1358e136d6ccSKate Arzamastseva */
1359d868eb89SAndreas Gohrfunction media_image_diff($image, $l_rev, $r_rev, $l_size, $r_size, $type)
1360d868eb89SAndreas Gohr{
136179a2d784SGerrit Uitslag    dbg_deprecated('see ' . MediaDiff::class . '::showImageDiff()');
13621eeeced2SKate Arzamastseva}
13631eeeced2SKate Arzamastseva
13641eeeced2SKate Arzamastseva/**
13659c1bd4bcSKate Arzamastseva * Restores an old revision of a media file
13669c1bd4bcSKate Arzamastseva *
136742ea7f44SGerrit Uitslag * @param string $image media id
136842ea7f44SGerrit Uitslag * @param int    $rev   revision timestamp or empty string
13699c1bd4bcSKate Arzamastseva * @param int    $auth
13709c1bd4bcSKate Arzamastseva * @return string - file's id
137142ea7f44SGerrit Uitslag *
13729c1bd4bcSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
13739c1bd4bcSKate Arzamastseva */
1374d868eb89SAndreas Gohrfunction media_restore($image, $rev, $auth)
1375d868eb89SAndreas Gohr{
1376e5d185e1SKate Arzamastseva    global $conf;
137780525638SKate Arzamastseva    if ($auth < AUTH_UPLOAD || !$conf['mediarevisions']) return false;
137892cac9a9SKate Arzamastseva    $removed = (!file_exists(mediaFN($image)) && file_exists(mediaMetaFN($image, '.changes')));
137992cac9a9SKate Arzamastseva    if (!$image || (!file_exists(mediaFN($image)) && !$removed)) return false;
13809c1bd4bcSKate Arzamastseva    if (!$rev || !file_exists(mediaFN($image, $rev))) return false;
138124870174SAndreas Gohr    [, $imime, ] = mimetype($image);
1382dccd6b2bSAndreas Gohr    $res = media_upload_finish(
1383dccd6b2bSAndreas Gohr        mediaFN($image, $rev),
13849c1bd4bcSKate Arzamastseva        mediaFN($image),
13859c1bd4bcSKate Arzamastseva        $image,
13869c1bd4bcSKate Arzamastseva        $imime,
13879c1bd4bcSKate Arzamastseva        true,
1388dccd6b2bSAndreas Gohr        'copy'
1389dccd6b2bSAndreas Gohr    );
13909c1bd4bcSKate Arzamastseva    if (is_array($res)) {
13919c1bd4bcSKate Arzamastseva        msg($res[0], $res[1]);
13929c1bd4bcSKate Arzamastseva        return false;
13939c1bd4bcSKate Arzamastseva    }
13949c1bd4bcSKate Arzamastseva    return $res;
13959c1bd4bcSKate Arzamastseva}
13969c1bd4bcSKate Arzamastseva
13979c1bd4bcSKate Arzamastseva/**
1398bf1f3ac4Ssarnowski * List all files found by the search request
1399c9f56829SAndreas Gohr *
1400c9f56829SAndreas Gohr * @author Tobias Sarnowski <sarnowski@cosmocode.de>
1401c9f56829SAndreas Gohr * @author Andreas Gohr <gohr@cosmocode.de>
1402d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
1403c9f56829SAndreas Gohr * @triggers MEDIA_SEARCH
1404e0c26282SGerrit Uitslag *
1405e0c26282SGerrit Uitslag * @param string $query
1406e0c26282SGerrit Uitslag * @param string $ns
1407e0c26282SGerrit Uitslag * @param null|int $auth
1408e0c26282SGerrit Uitslag * @param bool $fullscreen
1409e0c26282SGerrit Uitslag * @param string $sort
1410bf1f3ac4Ssarnowski */
1411d868eb89SAndreas Gohrfunction media_searchlist($query, $ns, $auth = null, $fullscreen = false, $sort = 'natural')
1412d868eb89SAndreas Gohr{
1413bf1f3ac4Ssarnowski    global $conf;
1414bf1f3ac4Ssarnowski    global $lang;
14158e69fd30SKate Arzamastseva
1416bf1f3ac4Ssarnowski    $ns = cleanID($ns);
141724870174SAndreas Gohr    $evdata = [
141856fe6664SAndreas Gohr        'ns'    => $ns,
141924870174SAndreas Gohr        'data'  => [],
142056fe6664SAndreas Gohr        'query' => $query
142124870174SAndreas Gohr    ];
14227ed31746SSzymon Olewniczak    if (!blank($query)) {
1423e1d9dcc8SAndreas Gohr        $evt = new Event('MEDIA_SEARCH', $evdata);
1424bf1f3ac4Ssarnowski        if ($evt->advise_before()) {
142556fe6664SAndreas Gohr            $dir = utf8_encodeFN(str_replace(':', '/', $evdata['ns']));
142676472096SSzymon Olewniczak            $quoted = preg_quote($evdata['query'], '/');
142776472096SSzymon Olewniczak            //apply globbing
142824870174SAndreas Gohr            $quoted = str_replace(['\*', '\?'], ['.*', '.'], $quoted, $count);
142923e31e76SSzymon Olewniczak
143023e31e76SSzymon Olewniczak            //if we use globbing file name must match entirely but may be preceded by arbitrary namespace
143123e31e76SSzymon Olewniczak            if ($count > 0) $quoted = '^([^:]*:)*' . $quoted . '$';
143223e31e76SSzymon Olewniczak
143376472096SSzymon Olewniczak            $pattern = '/' . $quoted . '/i';
1434dccd6b2bSAndreas Gohr            search(
1435dccd6b2bSAndreas Gohr                $evdata['data'],
143656fe6664SAndreas Gohr                $conf['mediadir'],
14374f33babfSAndreas Gohr                'search_mediafiles',
143824870174SAndreas Gohr                ['showmsg' => false, 'pattern' => $pattern],
143900e3e394SChristopher Smith                $dir,
144000e3e394SChristopher Smith                1,
1441dccd6b2bSAndreas Gohr                $sort
1442dccd6b2bSAndreas Gohr            );
1443bf1f3ac4Ssarnowski        }
1444bf1f3ac4Ssarnowski        $evt->advise_after();
1445bf1f3ac4Ssarnowski        unset($evt);
144656fe6664SAndreas Gohr    }
1447bf1f3ac4Ssarnowski
1448d9162c6cSKate Arzamastseva    if (!$fullscreen) {
144956fe6664SAndreas Gohr        echo '<h1 id="media__ns">' . sprintf($lang['searchmedia_in'], hsc($ns) . ':*') . '</h1>' . NL;
145056fe6664SAndreas Gohr        media_searchform($ns, $query);
1451d9162c6cSKate Arzamastseva    }
145256fe6664SAndreas Gohr
145356fe6664SAndreas Gohr    if (!count($evdata['data'])) {
1454bf1f3ac4Ssarnowski        echo '<div class="nothing">' . $lang['nothingfound'] . '</div>' . NL;
14555b9353faSKate Arzamastseva    } else {
14565b9353faSKate Arzamastseva        if ($fullscreen) {
1457554a8c9fSAdrian Lang            echo '<ul class="' . _media_get_list_type() . '">';
14585b9353faSKate Arzamastseva        }
14595b9353faSKate Arzamastseva        foreach ($evdata['data'] as $item) {
14604f33babfSAndreas Gohr            if (!$fullscreen) {
14614f33babfSAndreas Gohr                // FIXME old call: media_printfile($item,$item['perm'],'',true);
146279a2d784SGerrit Uitslag                $display = new DisplayRow($item);
146379b00823SAndreas Gohr                $display->relativeDisplay($ns);
14644f33babfSAndreas Gohr                $display->show();
14654f33babfSAndreas Gohr            } else {
14664f33babfSAndreas Gohr                // FIXME old call: media_printfile_thumbs($item,$item['perm'],false,true);
146779a2d784SGerrit Uitslag                $display = new DisplayTile($item);
146879b00823SAndreas Gohr                $display->relativeDisplay($ns);
14694f33babfSAndreas Gohr                echo '<li>';
14704f33babfSAndreas Gohr                $display->show();
14714f33babfSAndreas Gohr                echo '</li>';
14724f33babfSAndreas Gohr            }
1473bf1f3ac4Ssarnowski        }
147494add303SAnika Henke        if ($fullscreen) echo '</ul>' . NL;
14755b9353faSKate Arzamastseva    }
1476bf1f3ac4Ssarnowski}
1477bf1f3ac4Ssarnowski
1478bf1f3ac4Ssarnowski/**
1479c6571d58SAndreas Gohr * Display a media icon
1480c6571d58SAndreas Gohr *
148142ea7f44SGerrit Uitslag * @param string $filename media id
1482c6571d58SAndreas Gohr * @param string $size     the size subfolder, if not specified 16x16 is used
148342ea7f44SGerrit Uitslag * @return string html
1484c6571d58SAndreas Gohr */
1485d868eb89SAndreas Gohrfunction media_printicon($filename, $size = '')
1486d868eb89SAndreas Gohr{
148724870174SAndreas Gohr    [$ext] = mimetype(mediaFN($filename), false);
148823786fd7SKate Arzamastseva
148979e79377SAndreas Gohr    if (file_exists(DOKU_INC . 'lib/images/fileicons/' . $size . '/' . $ext . '.png')) {
1490c6571d58SAndreas Gohr        $icon = DOKU_BASE . 'lib/images/fileicons/' . $size . '/' . $ext . '.png';
149123786fd7SKate Arzamastseva    } else {
1492c6571d58SAndreas Gohr        $icon = DOKU_BASE . 'lib/images/fileicons/' . $size . '/file.png';
149323786fd7SKate Arzamastseva    }
149423786fd7SKate Arzamastseva
1495421ec38eSKate Arzamastseva    return '<img src="' . $icon . '" alt="' . $filename . '" class="icon" />';
149623786fd7SKate Arzamastseva}
149723786fd7SKate Arzamastseva
14983df72098SAndreas Gohr/**
149942ea7f44SGerrit Uitslag * Build link based on the current, adding/rewriting parameters
1500d9162c6cSKate Arzamastseva *
1501d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
150242ea7f44SGerrit Uitslag *
1503ebc28e69SAndreas Gohr * @param array|bool $params
150442ea7f44SGerrit Uitslag * @param string     $amp           separator
150542ea7f44SGerrit Uitslag * @param bool       $abs           absolute url?
150642ea7f44SGerrit Uitslag * @param bool       $params_array  return the parmeters array?
150742ea7f44SGerrit Uitslag * @return string|array - link or link parameters
1508d9162c6cSKate Arzamastseva */
1509d868eb89SAndreas Gohrfunction media_managerURL($params = false, $amp = '&amp;', $abs = false, $params_array = false)
1510d868eb89SAndreas Gohr{
1511d9162c6cSKate Arzamastseva    global $ID;
15128108113cSTom N Harris    global $INPUT;
1513d9162c6cSKate Arzamastseva
151424870174SAndreas Gohr    $gets = ['do' => 'media'];
151524870174SAndreas Gohr    $media_manager_params = ['tab_files', 'tab_details', 'image', 'ns', 'list', 'sort'];
151623846a98SKate Arzamastseva    foreach ($media_manager_params as $x) {
15178108113cSTom N Harris        if ($INPUT->has($x)) $gets[$x] = $INPUT->str($x);
151823846a98SKate Arzamastseva    }
1519d9162c6cSKate Arzamastseva
1520d9162c6cSKate Arzamastseva    if ($params) {
1521554a8c9fSAdrian Lang        $gets = $params + $gets;
1522d9162c6cSKate Arzamastseva    }
1523d9162c6cSKate Arzamastseva    unset($gets['id']);
1524554a8c9fSAdrian Lang    if (isset($gets['delete'])) {
15251eeeced2SKate Arzamastseva        unset($gets['image']);
15261eeeced2SKate Arzamastseva        unset($gets['tab_details']);
15271eeeced2SKate Arzamastseva    }
1528d9162c6cSKate Arzamastseva
1529035e07f1SKate Arzamastseva    if ($params_array) return $gets;
1530035e07f1SKate Arzamastseva
15316dd095f5SKate Arzamastseva    return wl($ID, $gets, $abs, $amp);
1532d9162c6cSKate Arzamastseva}
1533d9162c6cSKate Arzamastseva
1534d9162c6cSKate Arzamastseva/**
15353df72098SAndreas Gohr * Print the media upload form if permissions are correct
15363df72098SAndreas Gohr *
15373df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
1538d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
1539e0c26282SGerrit Uitslag *
1540e0c26282SGerrit Uitslag * @param string $ns
1541e0c26282SGerrit Uitslag * @param int    $auth permission level
1542e0c26282SGerrit Uitslag * @param bool  $fullscreen
15433df72098SAndreas Gohr */
1544d868eb89SAndreas Gohrfunction media_uploadform($ns, $auth, $fullscreen = false)
1545d868eb89SAndreas Gohr{
15468108113cSTom N Harris    global $lang;
15478108113cSTom N Harris    global $conf;
15488108113cSTom N Harris    global $INPUT;
15493df72098SAndreas Gohr
155088a71175SKate Arzamastseva    if ($auth < AUTH_UPLOAD) {
155188a71175SKate Arzamastseva        echo '<div class="nothing">' . $lang['media_perm_upload'] . '</div>' . NL;
155288a71175SKate Arzamastseva        return;
155388a71175SKate Arzamastseva    }
155492cac9a9SKate Arzamastseva    $auth_ow = (($conf['mediarevisions']) ? AUTH_UPLOAD : AUTH_DELETE);
15553df72098SAndreas Gohr
155670c3cc9aSKate Arzamastseva    $update = false;
155770c3cc9aSKate Arzamastseva    $id = '';
15588108113cSTom N Harris    if ($auth >= $auth_ow && $fullscreen && $INPUT->str('mediado') == 'update') {
155970c3cc9aSKate Arzamastseva        $update = true;
15608108113cSTom N Harris        $id = cleanID($INPUT->str('image'));
156170c3cc9aSKate Arzamastseva    }
156270c3cc9aSKate Arzamastseva
1563d00ec455SAndreas Gohr    // The default HTML upload form
1564b960c74fSSatoshi Sahara    $form = new Form([
1565b960c74fSSatoshi Sahara        'id' => 'dw__upload',
1566b960c74fSSatoshi Sahara        'enctype' => 'multipart/form-data',
1567b960c74fSSatoshi Sahara        'action' => ($fullscreen)
1568b960c74fSSatoshi Sahara                    ? media_managerURL(['tab_files' => 'files', 'tab_details' => 'view'], '&')
1569b960c74fSSatoshi Sahara                    : DOKU_BASE . 'lib/exe/mediamanager.php',
1570b960c74fSSatoshi Sahara    ]);
1571b960c74fSSatoshi Sahara    $form->addTagOpen('div')->addClass('no');
1572b960c74fSSatoshi Sahara    $form->setHiddenField('ns', hsc($ns));  // FIXME hsc required?
1573b960c74fSSatoshi Sahara    $form->addTagOpen('p');
1574b960c74fSSatoshi Sahara    $form->addTextInput('upload', $lang['txt_upload'])->id('upload__file')
1575b960c74fSSatoshi Sahara            ->attrs(['type' => 'file']);
1576b960c74fSSatoshi Sahara    $form->addTagClose('p');
1577b960c74fSSatoshi Sahara    $form->addTagOpen('p');
1578b960c74fSSatoshi Sahara    $form->addTextInput('mediaid', $lang['txt_filename'])->id('upload__name')
1579b960c74fSSatoshi Sahara            ->val(noNS($id));
1580b960c74fSSatoshi Sahara    $form->addButton('', $lang['btn_upload'])->attr('type', 'submit');
1581b960c74fSSatoshi Sahara    $form->addTagClose('p');
158292cac9a9SKate Arzamastseva    if ($auth >= $auth_ow) {
1583b960c74fSSatoshi Sahara        $form->addTagOpen('p');
158424870174SAndreas Gohr        $attrs = [];
158570c3cc9aSKate Arzamastseva        if ($update) $attrs['checked'] = 'checked';
1586b960c74fSSatoshi Sahara        $form->addCheckbox('ow', $lang['txt_overwrt'])->id('dw__ow')->val('1')
1587b960c74fSSatoshi Sahara            ->addClass('check')->attrs($attrs);
1588b960c74fSSatoshi Sahara        $form->addTagClose('p');
1589b960c74fSSatoshi Sahara    }
1590b960c74fSSatoshi Sahara    $form->addTagClose('div');
1591b960c74fSSatoshi Sahara
1592b960c74fSSatoshi Sahara    if (!$fullscreen) {
1593b960c74fSSatoshi Sahara        echo '<div class="upload">' . $lang['mediaupload'] . '</div>' . DOKU_LF;
1594b960c74fSSatoshi Sahara    } else {
1595b960c74fSSatoshi Sahara        echo DOKU_LF;
15963df72098SAndreas Gohr    }
1597c472bad9SKate Arzamastseva
1598b960c74fSSatoshi Sahara    echo '<div id="mediamanager__uploader">' . DOKU_LF;
1599c6977b3aSSatoshi Sahara    echo $form->toHTML('Upload');
1600b960c74fSSatoshi Sahara    echo '</div>' . DOKU_LF;
1601f940e4a0SAndreas Gohr
1602f940e4a0SAndreas Gohr    echo '<p class="maxsize">';
1603f940e4a0SAndreas Gohr    printf($lang['maxuploadsize'], filesize_h(media_getuploadsize()));
160456fc6b15SAnna Dabrowska    echo ' <a class="allowedmime" href="#">' . $lang['allowedmime'] . '</a>';
1605499d9bcdSAndreas Gohr    echo ' <span>' . implode(', ', array_keys(getMimeTypes())) . '</span>';
1606b960c74fSSatoshi Sahara    echo '</p>' . DOKU_LF;
1607f940e4a0SAndreas Gohr}
1608f940e4a0SAndreas Gohr
1609f940e4a0SAndreas Gohr/**
1610f940e4a0SAndreas Gohr * Returns the size uploaded files may have
1611f940e4a0SAndreas Gohr *
1612f940e4a0SAndreas Gohr * This uses a conservative approach using the lowest number found
1613f940e4a0SAndreas Gohr * in any of the limiting ini settings
1614f940e4a0SAndreas Gohr *
1615f940e4a0SAndreas Gohr * @returns int size in bytes
1616f940e4a0SAndreas Gohr */
1617d868eb89SAndreas Gohrfunction media_getuploadsize()
1618d868eb89SAndreas Gohr{
1619f940e4a0SAndreas Gohr    $okay = 0;
1620f940e4a0SAndreas Gohr
162124870174SAndreas Gohr    $post = php_to_byte(@ini_get('post_max_size'));
162224870174SAndreas Gohr    $suho = php_to_byte(@ini_get('suhosin.post.max_value_length'));
162324870174SAndreas Gohr    $upld = php_to_byte(@ini_get('upload_max_filesize'));
1624f940e4a0SAndreas Gohr
162524870174SAndreas Gohr    if ($post && ($post < $okay || $okay === 0)) $okay = $post;
1626f940e4a0SAndreas Gohr    if ($suho && ($suho < $okay || $okay == 0)) $okay = $suho;
1627f940e4a0SAndreas Gohr    if ($upld && ($upld < $okay || $okay == 0)) $okay = $upld;
1628f940e4a0SAndreas Gohr
1629f940e4a0SAndreas Gohr    return $okay;
16309f5dde7fSMichael Klier}
16313df72098SAndreas Gohr
16323df72098SAndreas Gohr/**
1633bf1f3ac4Ssarnowski * Print the search field form
1634bf1f3ac4Ssarnowski *
1635bf1f3ac4Ssarnowski * @author Tobias Sarnowski <sarnowski@cosmocode.de>
1636d9162c6cSKate Arzamastseva * @author Kate Arzamastseva <pshns@ukr.net>
1637e0c26282SGerrit Uitslag *
1638e0c26282SGerrit Uitslag * @param string $ns
1639e0c26282SGerrit Uitslag * @param string $query
1640e0c26282SGerrit Uitslag * @param bool $fullscreen
1641bf1f3ac4Ssarnowski */
1642d868eb89SAndreas Gohrfunction media_searchform($ns, $query = '', $fullscreen = false)
1643d868eb89SAndreas Gohr{
1644bf1f3ac4Ssarnowski    global $lang;
1645bf1f3ac4Ssarnowski
1646bf1f3ac4Ssarnowski    // The default HTML search form
1647b960c74fSSatoshi Sahara    $form = new Form([
1648b960c74fSSatoshi Sahara        'id'     => 'dw__mediasearch',
1649b960c74fSSatoshi Sahara        'action' => ($fullscreen)
1650b960c74fSSatoshi Sahara                    ? media_managerURL([], '&')
1651b960c74fSSatoshi Sahara                    : DOKU_BASE . 'lib/exe/mediamanager.php',
1652b960c74fSSatoshi Sahara    ]);
1653b960c74fSSatoshi Sahara    $form->addTagOpen('div')->addClass('no');
1654b960c74fSSatoshi Sahara    $form->setHiddenField('ns', $ns);
1655b960c74fSSatoshi Sahara    $form->setHiddenField($fullscreen ? 'mediado' : 'do', 'searchlist');
1656554a8c9fSAdrian Lang
1657b960c74fSSatoshi Sahara    $form->addTagOpen('p');
1658bde2a644SSatoshi Sahara    $form->addTextInput('q', $lang['searchmedia'])
1659b960c74fSSatoshi Sahara            ->attr('title', sprintf($lang['searchmedia_in'], hsc($ns) . ':*'))
1660b960c74fSSatoshi Sahara            ->val($query);
1661bde2a644SSatoshi Sahara    $form->addHTML(' ');
1662b960c74fSSatoshi Sahara    $form->addButton('', $lang['btn_search'])->attr('type', 'submit');
1663b960c74fSSatoshi Sahara    $form->addTagClose('p');
1664b960c74fSSatoshi Sahara    $form->addTagClose('div');
166526dfc232SAndreas Gohr    echo $form->toHTML('SearchMedia');
1666bf1f3ac4Ssarnowski}
1667bf1f3ac4Ssarnowski
1668bf1f3ac4Ssarnowski/**
16693df72098SAndreas Gohr * Build a tree outline of available media namespaces
16703df72098SAndreas Gohr *
16713df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
1672e0c26282SGerrit Uitslag *
1673e0c26282SGerrit Uitslag * @param string $ns
16743df72098SAndreas Gohr */
1675d868eb89SAndreas Gohrfunction media_nstree($ns)
1676d868eb89SAndreas Gohr{
16773df72098SAndreas Gohr    global $conf;
1678256ca81eSAndreas Gohr    global $lang;
16793df72098SAndreas Gohr
16803df72098SAndreas Gohr    // currently selected namespace
16813df72098SAndreas Gohr    $ns = cleanID($ns);
16823df72098SAndreas Gohr    if (empty($ns)) {
1683de3eb1d7SAdrian Lang        global $ID;
1684dd90013aSMichael Hamann        $ns = (string)getNS($ID);
16853df72098SAndreas Gohr    }
1686dd90013aSMichael Hamann
1687dd90013aSMichael Hamann    $ns_dir = utf8_encodeFN(str_replace(':', '/', $ns));
16883df72098SAndreas Gohr
168924870174SAndreas Gohr    $data = [];
169024870174SAndreas Gohr    search($data, $conf['mediadir'], 'search_index', ['ns' => $ns_dir, 'nofiles' => true]);
16913df72098SAndreas Gohr
16923df72098SAndreas Gohr    // wrap a list with the root level around the other namespaces
169324870174SAndreas Gohr    array_unshift($data, ['level' => 0, 'id' => '', 'open' => 'true', 'label' => '[' . $lang['mediaroot'] . ']']);
16943df72098SAndreas Gohr
1695dd90013aSMichael Hamann    // insert the current ns into the hierarchy if it isn't already part of it
1696dd90013aSMichael Hamann    $ns_parts = explode(':', $ns);
1697dd90013aSMichael Hamann    $tmp_ns = '';
1698dd90013aSMichael Hamann    $pos = 0;
1699de301a35SDamien Regad    $insert = false;
1700dd90013aSMichael Hamann    foreach ($ns_parts as $level => $part) {
1701186263b2SDamien Regad        if ($tmp_ns) {
1702186263b2SDamien Regad            $tmp_ns .= ':' . $part;
1703186263b2SDamien Regad        } else {
1704186263b2SDamien Regad            $tmp_ns = $part;
1705186263b2SDamien Regad        }
1706dd90013aSMichael Hamann
1707de301a35SDamien Regad        // find the namespace parts
17089988e853SDamien Regad        while (array_key_exists($pos, $data) && $data[$pos]['id'] != $tmp_ns) {
170964159a61SAndreas Gohr            if (
171064159a61SAndreas Gohr                $pos >= count($data) ||
17112d85e841SAndreas Gohr                ($data[$pos]['level'] <= $level + 1 && Sort::strcmp($data[$pos]['id'], $tmp_ns) > 0)
171264159a61SAndreas Gohr            ) {
1713de301a35SDamien Regad                $insert = true;
1714dd90013aSMichael Hamann                break;
1715dd90013aSMichael Hamann            }
1716dd90013aSMichael Hamann            ++$pos;
1717dd90013aSMichael Hamann        }
1718de301a35SDamien Regad        // insert namespace in hierarchy; if not found in above loop, append it to the end
1719b3894732Ssplitbrain        if ($insert || $pos === count($data)) {
1720de301a35SDamien Regad            array_splice($data, $pos, 0, [['level' => $level + 1, 'id' => $tmp_ns, 'open' => 'true']]);
1721de301a35SDamien Regad        }
1722dd90013aSMichael Hamann    }
1723dd90013aSMichael Hamann
17243df72098SAndreas Gohr    echo html_buildlist($data, 'idx', 'media_nstree_item', 'media_nstree_li');
17253df72098SAndreas Gohr}
17263df72098SAndreas Gohr
17273df72098SAndreas Gohr/**
17283df72098SAndreas Gohr * Userfunction for html_buildlist
17293df72098SAndreas Gohr *
17303df72098SAndreas Gohr * Prints a media namespace tree item
17313df72098SAndreas Gohr *
17323df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
173342ea7f44SGerrit Uitslag *
173442ea7f44SGerrit Uitslag * @param array $item
173542ea7f44SGerrit Uitslag * @return string html
17363df72098SAndreas Gohr */
1737d868eb89SAndreas Gohrfunction media_nstree_item($item)
1738d868eb89SAndreas Gohr{
17398108113cSTom N Harris    global $INPUT;
17403df72098SAndreas Gohr    $pos   = strrpos($item['id'], ':');
17413df72098SAndreas Gohr    $label = substr($item['id'], $pos > 0 ? $pos + 1 : 0);
17420e80bb5eSChristopher Smith    if (empty($item['label'])) $item['label'] = $label;
17433df72098SAndreas Gohr
17443df72098SAndreas Gohr    $ret  = '';
174524870174SAndreas Gohr    if ($INPUT->str('do') != 'media')
17463df72098SAndreas Gohr    $ret .= '<a href="' . DOKU_BASE . 'lib/exe/mediamanager.php?ns=' . idfilter($item['id']) . '" class="idx_dir">';
1747b960c74fSSatoshi Sahara    else $ret .= '<a href="' . media_managerURL(['ns' => idfilter($item['id'], false), 'tab_files' => 'files'])
174823846a98SKate Arzamastseva        . '" class="idx_dir">';
17493df72098SAndreas Gohr    $ret .= $item['label'];
17503df72098SAndreas Gohr    $ret .= '</a>';
17513df72098SAndreas Gohr    return $ret;
17523df72098SAndreas Gohr}
17533df72098SAndreas Gohr
17543df72098SAndreas Gohr/**
17553df72098SAndreas Gohr * Userfunction for html_buildlist
17563df72098SAndreas Gohr *
17573df72098SAndreas Gohr * Prints a media namespace tree item opener
17583df72098SAndreas Gohr *
17593df72098SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
176042ea7f44SGerrit Uitslag *
176142ea7f44SGerrit Uitslag * @param array $item
176242ea7f44SGerrit Uitslag * @return string html
17633df72098SAndreas Gohr */
1764d868eb89SAndreas Gohrfunction media_nstree_li($item)
1765d868eb89SAndreas Gohr{
17663df72098SAndreas Gohr    $class = 'media level' . $item['level'];
17673df72098SAndreas Gohr    if ($item['open']) {
17683df72098SAndreas Gohr        $class .= ' open';
17693df72098SAndreas Gohr        $img   = DOKU_BASE . 'lib/images/minus.gif';
1770e260f93bSAnika Henke        $alt   = '−';
17713df72098SAndreas Gohr    } else {
17723df72098SAndreas Gohr        $class .= ' closed';
17733df72098SAndreas Gohr        $img   = DOKU_BASE . 'lib/images/plus.gif';
17747af1b404SAnika Henke        $alt   = '+';
17753df72098SAndreas Gohr    }
1776231b8c34SPierre Spring    // TODO: only deliver an image if it actually has a subtree...
17773df72098SAndreas Gohr    return '<li class="' . $class . '">' .
17787af1b404SAnika Henke        '<img src="' . $img . '" alt="' . $alt . '" />';
17793df72098SAndreas Gohr}
178013c08e2fSMichael Klier
178113c08e2fSMichael Klier/**
1782b021f0b4SAndreas Gohr * Resizes or crop the given image to the given size
1783b021f0b4SAndreas Gohr *
1784b021f0b4SAndreas Gohr * @author  Andreas Gohr <andi@splitbrain.org>
1785b021f0b4SAndreas Gohr *
1786b021f0b4SAndreas Gohr * @param string $file filename, path to file
1787b021f0b4SAndreas Gohr * @param string $ext  extension
1788b021f0b4SAndreas Gohr * @param int    $w    desired width
1789b021f0b4SAndreas Gohr * @param int    $h    desired height
1790b021f0b4SAndreas Gohr * @param bool   $crop should a center crop be used?
1791b021f0b4SAndreas Gohr * @return string path to resized or original size if failed
1792b021f0b4SAndreas Gohr */
1793b021f0b4SAndreas Gohrfunction media_mod_image($file, $ext, $w, $h = 0, $crop = false)
1794b021f0b4SAndreas Gohr{
1795b021f0b4SAndreas Gohr    global $conf;
1796d967ecd8SAndreas Gohr    if (!$h) $h = 0;
1797b021f0b4SAndreas Gohr    // we wont scale up to infinity
1798b021f0b4SAndreas Gohr    if ($w > 2000 || $h > 2000) return $file;
1799b021f0b4SAndreas Gohr
1800b021f0b4SAndreas Gohr    $operation = $crop ? 'crop' : 'resize';
1801b021f0b4SAndreas Gohr
1802b021f0b4SAndreas Gohr    $options = [
1803b021f0b4SAndreas Gohr        'quality' => $conf['jpg_quality'],
1804b021f0b4SAndreas Gohr        'imconvert' => $conf['im_convert'],
1805b021f0b4SAndreas Gohr    ];
1806b021f0b4SAndreas Gohr
180724870174SAndreas Gohr    $cache = new CacheImageMod($file, $w, $h, $ext, $crop);
1808b021f0b4SAndreas Gohr    if (!$cache->useCache()) {
1809b021f0b4SAndreas Gohr        try {
1810b021f0b4SAndreas Gohr            Slika::run($file, $options)
1811b021f0b4SAndreas Gohr                 ->autorotate()
1812b021f0b4SAndreas Gohr                 ->$operation($w, $h)
1813b021f0b4SAndreas Gohr                 ->save($cache->cache, $ext);
1814b021f0b4SAndreas Gohr            if ($conf['fperm']) @chmod($cache->cache, $conf['fperm']);
181524870174SAndreas Gohr        } catch (Exception $e) {
1816b021f0b4SAndreas Gohr            Logger::debug($e->getMessage());
1817b021f0b4SAndreas Gohr            return $file;
1818b021f0b4SAndreas Gohr        }
1819b021f0b4SAndreas Gohr    }
1820b021f0b4SAndreas Gohr
1821b021f0b4SAndreas Gohr    return $cache->cache;
1822b021f0b4SAndreas Gohr}
1823b021f0b4SAndreas Gohr
1824b021f0b4SAndreas Gohr/**
182513c08e2fSMichael Klier * Resizes the given image to the given size
182613c08e2fSMichael Klier *
182713c08e2fSMichael Klier * @author  Andreas Gohr <andi@splitbrain.org>
182842ea7f44SGerrit Uitslag *
182942ea7f44SGerrit Uitslag * @param string $file filename, path to file
183042ea7f44SGerrit Uitslag * @param string $ext  extension
183142ea7f44SGerrit Uitslag * @param int    $w    desired width
183242ea7f44SGerrit Uitslag * @param int    $h    desired height
183342ea7f44SGerrit Uitslag * @return string path to resized or original size if failed
183413c08e2fSMichael Klier */
1835b021f0b4SAndreas Gohrfunction media_resize_image($file, $ext, $w, $h = 0)
1836b021f0b4SAndreas Gohr{
1837b021f0b4SAndreas Gohr    return media_mod_image($file, $ext, $w, $h, false);
1838d2bd34a5SAndreas Gohr}
183913c08e2fSMichael Klier
184013c08e2fSMichael Klier/**
1841d2bd34a5SAndreas Gohr * Center crops the given image to the wanted size
184213c08e2fSMichael Klier *
184313c08e2fSMichael Klier * @author  Andreas Gohr <andi@splitbrain.org>
184442ea7f44SGerrit Uitslag *
184542ea7f44SGerrit Uitslag * @param string $file filename, path to file
184642ea7f44SGerrit Uitslag * @param string $ext  extension
184742ea7f44SGerrit Uitslag * @param int    $w    desired width
184842ea7f44SGerrit Uitslag * @param int    $h    desired height
184942ea7f44SGerrit Uitslag * @return string path to resized or original size if failed
185013c08e2fSMichael Klier */
1851b021f0b4SAndreas Gohrfunction media_crop_image($file, $ext, $w, $h = 0)
1852b021f0b4SAndreas Gohr{
1853b021f0b4SAndreas Gohr    return media_mod_image($file, $ext, $w, $h, true);
185413c08e2fSMichael Klier}
185513c08e2fSMichael Klier
185613c08e2fSMichael Klier/**
18570f4e0092SChristopher Smith * Calculate a token to be used to verify fetch requests for resized or
18580f4e0092SChristopher Smith * cropped images have been internally generated - and prevent external
18590f4e0092SChristopher Smith * DDOS attacks via fetch
18600f4e0092SChristopher Smith *
18613c124064SAndreas Gohr * @author Christopher Smith <chris@jalakai.co.uk>
18623c124064SAndreas Gohr *
18630f4e0092SChristopher Smith * @param string  $id    id of the image
18640f4e0092SChristopher Smith * @param int     $w     resize/crop width
18650f4e0092SChristopher Smith * @param int     $h     resize/crop height
186642ea7f44SGerrit Uitslag * @return string token or empty string if no token required
18670f4e0092SChristopher Smith */
1868d868eb89SAndreas Gohrfunction media_get_token($id, $w, $h)
1869d868eb89SAndreas Gohr{
18700f4e0092SChristopher Smith    // token is only required for modified images
1871cc036f74SKlap-in    if ($w || $h || media_isexternal($id)) {
18723c124064SAndreas Gohr        $token = $id;
18730f4e0092SChristopher Smith        if ($w) $token .= '.' . $w;
18740f4e0092SChristopher Smith        if ($h) $token .= '.' . $h;
18750f4e0092SChristopher Smith
187624870174SAndreas Gohr        return substr(PassHash::hmac('md5', $token, auth_cookiesalt()), 0, 6);
18770f4e0092SChristopher Smith    }
18780f4e0092SChristopher Smith
18790f4e0092SChristopher Smith    return '';
18800f4e0092SChristopher Smith}
18810f4e0092SChristopher Smith
18820f4e0092SChristopher Smith/**
188313c08e2fSMichael Klier * Download a remote file and return local filename
188413c08e2fSMichael Klier *
188513c08e2fSMichael Klier * returns false if download fails. Uses cached file if available and
188613c08e2fSMichael Klier * wanted
188713c08e2fSMichael Klier *
188813c08e2fSMichael Klier * @author  Andreas Gohr <andi@splitbrain.org>
188913c08e2fSMichael Klier * @author  Pavel Vitis <Pavel.Vitis@seznam.cz>
189042ea7f44SGerrit Uitslag *
189142ea7f44SGerrit Uitslag * @param string $url
189242ea7f44SGerrit Uitslag * @param string $ext   extension
189342ea7f44SGerrit Uitslag * @param int    $cache cachetime in seconds
189442ea7f44SGerrit Uitslag * @return false|string path to cached file
189513c08e2fSMichael Klier */
1896d868eb89SAndreas Gohrfunction media_get_from_URL($url, $ext, $cache)
1897d868eb89SAndreas Gohr{
189813c08e2fSMichael Klier    global $conf;
189913c08e2fSMichael Klier
190013c08e2fSMichael Klier    // if no cache or fetchsize just redirect
190113c08e2fSMichael Klier    if ($cache == 0)           return false;
190213c08e2fSMichael Klier    if (!$conf['fetchsize']) return false;
190313c08e2fSMichael Klier
190413c08e2fSMichael Klier    $local = getCacheName(strtolower($url), ".media.$ext");
190513c08e2fSMichael Klier    $mtime = @filemtime($local); // 0 if not exists
190613c08e2fSMichael Klier
190713c08e2fSMichael Klier    //decide if download needed:
19087d34963bSAndreas Gohr    if (
19097d34963bSAndreas Gohr        ($mtime == 0) || // cache does not exist
191013c08e2fSMichael Klier        ($cache != -1 && $mtime < time() - $cache) // 'recache' and cache has expired
191113c08e2fSMichael Klier    ) {
191213c08e2fSMichael Klier        if (media_image_download($url, $local)) {
191313c08e2fSMichael Klier            return $local;
191413c08e2fSMichael Klier        } else {
191513c08e2fSMichael Klier            return false;
191613c08e2fSMichael Klier        }
191713c08e2fSMichael Klier    }
191813c08e2fSMichael Klier
191913c08e2fSMichael Klier    //if cache exists use it else
192013c08e2fSMichael Klier    if ($mtime) return $local;
192113c08e2fSMichael Klier
192213c08e2fSMichael Klier    //else return false
192313c08e2fSMichael Klier    return false;
192413c08e2fSMichael Klier}
192513c08e2fSMichael Klier
192613c08e2fSMichael Klier/**
192713c08e2fSMichael Klier * Download image files
192813c08e2fSMichael Klier *
192913c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org>
193042ea7f44SGerrit Uitslag *
193142ea7f44SGerrit Uitslag * @param string $url
193242ea7f44SGerrit Uitslag * @param string $file path to file in which to put the downloaded content
193342ea7f44SGerrit Uitslag * @return bool
193413c08e2fSMichael Klier */
1935d868eb89SAndreas Gohrfunction media_image_download($url, $file)
1936d868eb89SAndreas Gohr{
193713c08e2fSMichael Klier    global $conf;
193813c08e2fSMichael Klier    $http = new DokuHTTPClient();
1939a5951419SAndreas Gohr    $http->keep_alive = false; // we do single ops here, no need for keep-alive
1940a5951419SAndreas Gohr
194113c08e2fSMichael Klier    $http->max_bodysize = $conf['fetchsize'];
194213c08e2fSMichael Klier    $http->timeout = 25; //max. 25 sec
194313c08e2fSMichael Klier    $http->header_regexp = '!\r\nContent-Type: image/(jpe?g|gif|png)!i';
194413c08e2fSMichael Klier
194513c08e2fSMichael Klier    $data = $http->get($url);
194613c08e2fSMichael Klier    if (!$data) return false;
194713c08e2fSMichael Klier
194879e79377SAndreas Gohr    $fileexists = file_exists($file);
194913c08e2fSMichael Klier    $fp = @fopen($file, "w");
195013c08e2fSMichael Klier    if (!$fp) return false;
195113c08e2fSMichael Klier    fwrite($fp, $data);
195213c08e2fSMichael Klier    fclose($fp);
195324870174SAndreas Gohr    if (!$fileexists && $conf['fperm']) chmod($file, $conf['fperm']);
195413c08e2fSMichael Klier
195513c08e2fSMichael Klier    // check if it is really an image
195613c08e2fSMichael Klier    $info = @getimagesize($file);
195713c08e2fSMichael Klier    if (!$info) {
195813c08e2fSMichael Klier        @unlink($file);
195913c08e2fSMichael Klier        return false;
196013c08e2fSMichael Klier    }
196113c08e2fSMichael Klier
196213c08e2fSMichael Klier    return true;
196313c08e2fSMichael Klier}
196413c08e2fSMichael Klier
196513c08e2fSMichael Klier/**
196613c08e2fSMichael Klier * resize images using external ImageMagick convert program
196713c08e2fSMichael Klier *
196813c08e2fSMichael Klier * @author Pavel Vitis <Pavel.Vitis@seznam.cz>
196913c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org>
197042ea7f44SGerrit Uitslag *
197142ea7f44SGerrit Uitslag * @param string $ext     extension
197242ea7f44SGerrit Uitslag * @param string $from    filename path to file
197342ea7f44SGerrit Uitslag * @param int    $from_w  original width
197442ea7f44SGerrit Uitslag * @param int    $from_h  original height
197542ea7f44SGerrit Uitslag * @param string $to      path to resized file
197642ea7f44SGerrit Uitslag * @param int    $to_w    desired width
197742ea7f44SGerrit Uitslag * @param int    $to_h    desired height
197842ea7f44SGerrit Uitslag * @return bool
197913c08e2fSMichael Klier */
1980d868eb89SAndreas Gohrfunction media_resize_imageIM($ext, $from, $from_w, $from_h, $to, $to_w, $to_h)
1981d868eb89SAndreas Gohr{
198213c08e2fSMichael Klier    global $conf;
198313c08e2fSMichael Klier
198413c08e2fSMichael Klier    // check if convert is configured
198513c08e2fSMichael Klier    if (!$conf['im_convert']) return false;
198613c08e2fSMichael Klier
198713c08e2fSMichael Klier    // prepare command
198813c08e2fSMichael Klier    $cmd  = $conf['im_convert'];
198913c08e2fSMichael Klier    $cmd .= ' -resize ' . $to_w . 'x' . $to_h . '!';
199013c08e2fSMichael Klier    if ($ext == 'jpg' || $ext == 'jpeg') {
199113c08e2fSMichael Klier        $cmd .= ' -quality ' . $conf['jpg_quality'];
199213c08e2fSMichael Klier    }
199313c08e2fSMichael Klier    $cmd .= " $from $to";
199413c08e2fSMichael Klier
199513c08e2fSMichael Klier    @exec($cmd, $out, $retval);
199613c08e2fSMichael Klier    if ($retval == 0) return true;
199713c08e2fSMichael Klier    return false;
199813c08e2fSMichael Klier}
199913c08e2fSMichael Klier
200013c08e2fSMichael Klier/**
200113c08e2fSMichael Klier * crop images using external ImageMagick convert program
200213c08e2fSMichael Klier *
200313c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org>
200442ea7f44SGerrit Uitslag *
200542ea7f44SGerrit Uitslag * @param string $ext     extension
200642ea7f44SGerrit Uitslag * @param string $from    filename path to file
200742ea7f44SGerrit Uitslag * @param int    $from_w  original width
200842ea7f44SGerrit Uitslag * @param int    $from_h  original height
200942ea7f44SGerrit Uitslag * @param string $to      path to resized file
201042ea7f44SGerrit Uitslag * @param int    $to_w    desired width
201142ea7f44SGerrit Uitslag * @param int    $to_h    desired height
201242ea7f44SGerrit Uitslag * @param int    $ofs_x   offset of crop centre
201342ea7f44SGerrit Uitslag * @param int    $ofs_y   offset of crop centre
201442ea7f44SGerrit Uitslag * @return bool
2015d2bd34a5SAndreas Gohr * @deprecated 2020-09-01
201613c08e2fSMichael Klier */
2017d868eb89SAndreas Gohrfunction media_crop_imageIM($ext, $from, $from_w, $from_h, $to, $to_w, $to_h, $ofs_x, $ofs_y)
2018d868eb89SAndreas Gohr{
201913c08e2fSMichael Klier    global $conf;
2020d2bd34a5SAndreas Gohr    dbg_deprecated('splitbrain\\Slika');
202113c08e2fSMichael Klier
202213c08e2fSMichael Klier    // check if convert is configured
202313c08e2fSMichael Klier    if (!$conf['im_convert']) return false;
202413c08e2fSMichael Klier
202513c08e2fSMichael Klier    // prepare command
202613c08e2fSMichael Klier    $cmd  = $conf['im_convert'];
202713c08e2fSMichael Klier    $cmd .= ' -crop ' . $to_w . 'x' . $to_h . '+' . $ofs_x . '+' . $ofs_y;
202813c08e2fSMichael Klier    if ($ext == 'jpg' || $ext == 'jpeg') {
202913c08e2fSMichael Klier        $cmd .= ' -quality ' . $conf['jpg_quality'];
203013c08e2fSMichael Klier    }
203113c08e2fSMichael Klier    $cmd .= " $from $to";
203213c08e2fSMichael Klier
203313c08e2fSMichael Klier    @exec($cmd, $out, $retval);
203413c08e2fSMichael Klier    if ($retval == 0) return true;
203513c08e2fSMichael Klier    return false;
203613c08e2fSMichael Klier}
203713c08e2fSMichael Klier
203813c08e2fSMichael Klier/**
203913c08e2fSMichael Klier * resize or crop images using PHP's libGD support
204013c08e2fSMichael Klier *
204113c08e2fSMichael Klier * @author Andreas Gohr <andi@splitbrain.org>
204213c08e2fSMichael Klier * @author Sebastian Wienecke <s_wienecke@web.de>
204342ea7f44SGerrit Uitslag *
204442ea7f44SGerrit Uitslag * @param string $ext     extension
204542ea7f44SGerrit Uitslag * @param string $from    filename path to file
204642ea7f44SGerrit Uitslag * @param int    $from_w  original width
204742ea7f44SGerrit Uitslag * @param int    $from_h  original height
204842ea7f44SGerrit Uitslag * @param string $to      path to resized file
204942ea7f44SGerrit Uitslag * @param int    $to_w    desired width
205042ea7f44SGerrit Uitslag * @param int    $to_h    desired height
205142ea7f44SGerrit Uitslag * @param int    $ofs_x   offset of crop centre
205242ea7f44SGerrit Uitslag * @param int    $ofs_y   offset of crop centre
205342ea7f44SGerrit Uitslag * @return bool
2054d2bd34a5SAndreas Gohr * @deprecated 2020-09-01
205513c08e2fSMichael Klier */
2056d868eb89SAndreas Gohrfunction media_resize_imageGD($ext, $from, $from_w, $from_h, $to, $to_w, $to_h, $ofs_x = 0, $ofs_y = 0)
2057d868eb89SAndreas Gohr{
205813c08e2fSMichael Klier    global $conf;
2059d2bd34a5SAndreas Gohr    dbg_deprecated('splitbrain\\Slika');
206013c08e2fSMichael Klier
206113c08e2fSMichael Klier    if ($conf['gdlib'] < 1) return false; //no GDlib available or wanted
206213c08e2fSMichael Klier
206313c08e2fSMichael Klier    // check available memory
206413c08e2fSMichael Klier    if (!is_mem_available(($from_w * $from_h * 4) + ($to_w * $to_h * 4))) {
206513c08e2fSMichael Klier        return false;
206613c08e2fSMichael Klier    }
206713c08e2fSMichael Klier
206813c08e2fSMichael Klier    // create an image of the given filetype
206959bc3b48SGerrit Uitslag    $image = false;
207013c08e2fSMichael Klier    if ($ext == 'jpg' || $ext == 'jpeg') {
207113c08e2fSMichael Klier        if (!function_exists("imagecreatefromjpeg")) return false;
207213c08e2fSMichael Klier        $image = @imagecreatefromjpeg($from);
207313c08e2fSMichael Klier    } elseif ($ext == 'png') {
207413c08e2fSMichael Klier        if (!function_exists("imagecreatefrompng")) return false;
207513c08e2fSMichael Klier        $image = @imagecreatefrompng($from);
207613c08e2fSMichael Klier    } elseif ($ext == 'gif') {
207713c08e2fSMichael Klier        if (!function_exists("imagecreatefromgif")) return false;
207813c08e2fSMichael Klier        $image = @imagecreatefromgif($from);
207913c08e2fSMichael Klier    }
208013c08e2fSMichael Klier    if (!$image) return false;
208113c08e2fSMichael Klier
208259bc3b48SGerrit Uitslag    $newimg = false;
208313c08e2fSMichael Klier    if (($conf['gdlib'] > 1) && function_exists("imagecreatetruecolor") && $ext != 'gif') {
208413c08e2fSMichael Klier        $newimg = @imagecreatetruecolor($to_w, $to_h);
208513c08e2fSMichael Klier    }
208613c08e2fSMichael Klier    if (!$newimg) $newimg = @imagecreate($to_w, $to_h);
208713c08e2fSMichael Klier    if (!$newimg) {
208813c08e2fSMichael Klier        imagedestroy($image);
208913c08e2fSMichael Klier        return false;
209013c08e2fSMichael Klier    }
209113c08e2fSMichael Klier
209213c08e2fSMichael Klier    //keep png alpha channel if possible
209313c08e2fSMichael Klier    if ($ext == 'png' && $conf['gdlib'] > 1 && function_exists('imagesavealpha')) {
209413c08e2fSMichael Klier        imagealphablending($newimg, false);
209513c08e2fSMichael Klier        imagesavealpha($newimg, true);
209613c08e2fSMichael Klier    }
209713c08e2fSMichael Klier
209813c08e2fSMichael Klier    //keep gif transparent color if possible
209913c08e2fSMichael Klier    if ($ext == 'gif' && function_exists('imagefill') && function_exists('imagecolorallocate')) {
210013c08e2fSMichael Klier        if (function_exists('imagecolorsforindex') && function_exists('imagecolortransparent')) {
210113c08e2fSMichael Klier            $transcolorindex = @imagecolortransparent($image);
210213c08e2fSMichael Klier            if ($transcolorindex >= 0) { //transparent color exists
210313c08e2fSMichael Klier                $transcolor = @imagecolorsforindex($image, $transcolorindex);
210464159a61SAndreas Gohr                $transcolorindex = @imagecolorallocate(
210564159a61SAndreas Gohr                    $newimg,
210664159a61SAndreas Gohr                    $transcolor['red'],
210764159a61SAndreas Gohr                    $transcolor['green'],
210864159a61SAndreas Gohr                    $transcolor['blue']
210964159a61SAndreas Gohr                );
211013c08e2fSMichael Klier                @imagefill($newimg, 0, 0, $transcolorindex);
211113c08e2fSMichael Klier                @imagecolortransparent($newimg, $transcolorindex);
211213c08e2fSMichael Klier            } else { //filling with white
211313c08e2fSMichael Klier                $whitecolorindex = @imagecolorallocate($newimg, 255, 255, 255);
211413c08e2fSMichael Klier                @imagefill($newimg, 0, 0, $whitecolorindex);
211513c08e2fSMichael Klier            }
211613c08e2fSMichael Klier        } else { //filling with white
211713c08e2fSMichael Klier            $whitecolorindex = @imagecolorallocate($newimg, 255, 255, 255);
211813c08e2fSMichael Klier            @imagefill($newimg, 0, 0, $whitecolorindex);
211913c08e2fSMichael Klier        }
212013c08e2fSMichael Klier    }
212113c08e2fSMichael Klier
212213c08e2fSMichael Klier    //try resampling first
212313c08e2fSMichael Klier    if (function_exists("imagecopyresampled")) {
212413c08e2fSMichael Klier        if (!@imagecopyresampled($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h)) {
212513c08e2fSMichael Klier            imagecopyresized($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h);
212613c08e2fSMichael Klier        }
212713c08e2fSMichael Klier    } else {
212813c08e2fSMichael Klier        imagecopyresized($newimg, $image, 0, 0, $ofs_x, $ofs_y, $to_w, $to_h, $from_w, $from_h);
212913c08e2fSMichael Klier    }
213013c08e2fSMichael Klier
213113c08e2fSMichael Klier    $okay = false;
213213c08e2fSMichael Klier    if ($ext == 'jpg' || $ext == 'jpeg') {
213313c08e2fSMichael Klier        if (!function_exists('imagejpeg')) {
213413c08e2fSMichael Klier            $okay = false;
213513c08e2fSMichael Klier        } else {
213613c08e2fSMichael Klier            $okay = imagejpeg($newimg, $to, $conf['jpg_quality']);
213713c08e2fSMichael Klier        }
213813c08e2fSMichael Klier    } elseif ($ext == 'png') {
213913c08e2fSMichael Klier        if (!function_exists('imagepng')) {
214013c08e2fSMichael Klier            $okay = false;
214113c08e2fSMichael Klier        } else {
214213c08e2fSMichael Klier            $okay =  imagepng($newimg, $to);
214313c08e2fSMichael Klier        }
214413c08e2fSMichael Klier    } elseif ($ext == 'gif') {
214513c08e2fSMichael Klier        if (!function_exists('imagegif')) {
214613c08e2fSMichael Klier            $okay = false;
214713c08e2fSMichael Klier        } else {
214813c08e2fSMichael Klier            $okay = imagegif($newimg, $to);
214913c08e2fSMichael Klier        }
215013c08e2fSMichael Klier    }
215113c08e2fSMichael Klier
215279a2d784SGerrit Uitslag    // destroy GD image resources
215379a2d784SGerrit Uitslag    imagedestroy($image);
215479a2d784SGerrit Uitslag    imagedestroy($newimg);
215513c08e2fSMichael Klier
215613c08e2fSMichael Klier    return $okay;
215713c08e2fSMichael Klier}
215813c08e2fSMichael Klier
21593d7a9e0aSAnika Henke/**
21603d7a9e0aSAnika Henke * Return other media files with the same base name
216179e53fe5SAnika Henke * but different extensions.
21623d7a9e0aSAnika Henke *
21633d7a9e0aSAnika Henke * @param string   $src     - ID of media file
216442ea7f44SGerrit Uitslag * @param string[] $exts    - alternative extensions to find other files for
216542ea7f44SGerrit Uitslag * @return array            - array(mime type => file ID)
21663d7a9e0aSAnika Henke *
21673d7a9e0aSAnika Henke * @author Anika Henke <anika@selfthinker.org>
21683d7a9e0aSAnika Henke */
2169d868eb89SAndreas Gohrfunction media_alternativefiles($src, $exts)
2170d868eb89SAndreas Gohr{
21713d7a9e0aSAnika Henke
217224870174SAndreas Gohr    $files = [];
2173a19c9aa0SGerrit Uitslag    [$srcExt, /* srcMime */] = mimetype($src);
21743d7a9e0aSAnika Henke    $filebase = substr($src, 0, -1 * (strlen($srcExt) + 1));
21753d7a9e0aSAnika Henke
21763d7a9e0aSAnika Henke    foreach ($exts as $ext) {
21773d7a9e0aSAnika Henke        $fileid = $filebase . '.' . $ext;
21783d7a9e0aSAnika Henke        $file = mediaFN($fileid);
21793d7a9e0aSAnika Henke        if (file_exists($file)) {
2180a19c9aa0SGerrit Uitslag            [/* fileExt */, $fileMime] = mimetype($file);
218179e53fe5SAnika Henke            $files[$fileMime] = $fileid;
218299f943f6SAnika Henke        }
21833d7a9e0aSAnika Henke    }
21843d7a9e0aSAnika Henke    return $files;
21853d7a9e0aSAnika Henke}
21863d7a9e0aSAnika Henke
2187f50634f0SAnika Henke/**
2188f50634f0SAnika Henke * Check if video/audio is supported to be embedded.
2189f50634f0SAnika Henke *
2190b83a74f1SAnika Henke * @param string $mime      - mimetype of media file
219142ea7f44SGerrit Uitslag * @param string $type      - type of media files to check ('video', 'audio', or null for all)
2192f50634f0SAnika Henke * @return boolean
2193f50634f0SAnika Henke *
2194f50634f0SAnika Henke * @author Anika Henke <anika@selfthinker.org>
2195f50634f0SAnika Henke */
2196ed823bcdSAndreas Gohrfunction media_supportedav($mime, $type = null)
2197d868eb89SAndreas Gohr{
219824870174SAndreas Gohr    $supportedAudio = [
2199f50634f0SAnika Henke        'ogg' => 'audio/ogg',
2200f50634f0SAnika Henke        'mp3' => 'audio/mpeg',
220124870174SAndreas Gohr        'wav' => 'audio/wav'
220224870174SAndreas Gohr    ];
220324870174SAndreas Gohr    $supportedVideo = [
2204f50634f0SAnika Henke        'webm' => 'video/webm',
2205f50634f0SAnika Henke        'ogv' => 'video/ogg',
220624870174SAndreas Gohr        'mp4' => 'video/mp4'
220724870174SAndreas Gohr    ];
2208f50634f0SAnika Henke    if ($type == 'audio') {
2209f50634f0SAnika Henke        $supportedAv = $supportedAudio;
2210f50634f0SAnika Henke    } elseif ($type == 'video') {
2211f50634f0SAnika Henke        $supportedAv = $supportedVideo;
2212f50634f0SAnika Henke    } else {
2213f50634f0SAnika Henke        $supportedAv = array_merge($supportedAudio, $supportedVideo);
2214f50634f0SAnika Henke    }
2215f50634f0SAnika Henke    return in_array($mime, $supportedAv);
2216f50634f0SAnika Henke}
2217f50634f0SAnika Henke
22180877a1f1SSchplurtz le Déboulonné/**
22190877a1f1SSchplurtz le Déboulonné * Return track media files with the same base name
22200877a1f1SSchplurtz le Déboulonné * but extensions that indicate kind and lang.
22210877a1f1SSchplurtz le Déboulonné * ie for foo.webm search foo.sub.lang.vtt, foo.cap.lang.vtt...
22220877a1f1SSchplurtz le Déboulonné *
22230877a1f1SSchplurtz le Déboulonné * @param string   $src     - ID of media file
222401299338SSchplurtz le Déboulonné * @return array            - array(mediaID => array( kind, srclang ))
22250877a1f1SSchplurtz le Déboulonné *
22260877a1f1SSchplurtz le Déboulonné * @author Schplurtz le Déboulonné <Schplurtz@laposte.net>
22270877a1f1SSchplurtz le Déboulonné */
2228d868eb89SAndreas Gohrfunction media_trackfiles($src)
2229d868eb89SAndreas Gohr{
223024870174SAndreas Gohr    $kinds = [
22310877a1f1SSchplurtz le Déboulonné        'sub' => 'subtitles',
22320877a1f1SSchplurtz le Déboulonné        'cap' => 'captions',
22330877a1f1SSchplurtz le Déboulonné        'des' => 'descriptions',
22340877a1f1SSchplurtz le Déboulonné        'cha' => 'chapters',
22350877a1f1SSchplurtz le Déboulonné        'met' => 'metadata'
223624870174SAndreas Gohr    ];
22370877a1f1SSchplurtz le Déboulonné
223824870174SAndreas Gohr    $files = [];
22390877a1f1SSchplurtz le Déboulonné    $re = '/\\.(sub|cap|des|cha|met)\\.([^.]+)\\.vtt$/';
22400877a1f1SSchplurtz le Déboulonné    $baseid = pathinfo($src, PATHINFO_FILENAME);
22410877a1f1SSchplurtz le Déboulonné    $pattern = mediaFN($baseid) . '.*.*.vtt';
22420877a1f1SSchplurtz le Déboulonné    $list = glob($pattern);
22430877a1f1SSchplurtz le Déboulonné    foreach ($list as $track) {
22440877a1f1SSchplurtz le Déboulonné        if (preg_match($re, $track, $matches)) {
224524870174SAndreas Gohr            $files[$baseid . '.' . $matches[1] . '.' . $matches[2] . '.vtt'] = [$kinds[$matches[1]], $matches[2]];
22460877a1f1SSchplurtz le Déboulonné        }
22470877a1f1SSchplurtz le Déboulonné    }
22480877a1f1SSchplurtz le Déboulonné    return $files;
22490877a1f1SSchplurtz le Déboulonné}
22500877a1f1SSchplurtz le Déboulonné
2251365be586SAndreas Gohr/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
2252