1<?php
2/*
3 * vim:set softtabstop=4 shiftwidth=4 expandtab:
4 *
5 *  LICENSE: GNU Affero General Public License, version 3 (AGPL-3.0-or-later)
6 * Copyright 2001 - 2020 Ampache.org
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20 *
21 */
22
23declare(strict_types=0);
24
25namespace Ampache\Module\Api\Method;
26
27use Ampache\Config\AmpConfig;
28use Ampache\Repository\Model\Catalog;
29use Ampache\Repository\Model\Podcast_Episode;
30use Ampache\Repository\Model\Song;
31use Ampache\Repository\Model\User;
32use Ampache\Repository\Model\Video;
33use Ampache\Module\Api\Api;
34use Ampache\Module\Song\Deletion\SongDeleterInterface;
35use Ampache\Module\System\Session;
36
37/**
38 * Class CatalogFileMethod
39 * @package Lib\ApiMethods
40 */
41final class CatalogFileMethod
42{
43    private const ACTION = 'catalog_file';
44
45    /**
46     * catalog_file
47     * MINIMUM_API_VERSION=420000
48     *
49     * Perform actions on local catalog files.
50     * Single file versions of catalog add, clean and verify.
51     * Make sure you remember to urlencode those file names!
52     *
53     * @param array $input
54     * file    = (string) urlencode(FULL path to local file)
55     * task    = (string) 'add', 'clean', 'verify', 'remove' (can be comma separated)
56     * catalog = (integer) $catalog_id)
57     * @return boolean
58     */
59    public static function catalog_file(array $input)
60    {
61        if (!Api::check_access('interface', 50, User::get_from_username(Session::username($input['auth']))->id, self::ACTION, $input['api_format'])) {
62            return false;
63        }
64        if (!Api::check_parameter($input, array('catalog', 'file', 'task'), self::ACTION)) {
65            return false;
66        }
67        $file = (string) html_entity_decode($input['file']);
68        $task = explode(',', (string)$input['task']);
69        if (!$task) {
70            $task = array();
71        }
72
73        // confirm that a valid task is going to happen
74        if (!AmpConfig::get('delete_from_disk') && in_array('remove', $task)) {
75            Api::error(T_('Enable: delete_from_disk'), '4703', self::ACTION, 'system', $input['api_format']);
76
77            return false;
78        }
79        if (!file_exists($file) && !in_array('clean', $task)) {
80            /* HINT: Requested object string/id/type ("album", "myusername", "some song title", 1298376) */
81            Api::error(sprintf(T_('Not Found: %s'), $file), '4704', self::ACTION, 'file', $input['api_format']);
82
83            return false;
84        }
85        foreach ($task as $item) {
86            if (!in_array($item, array('add', 'clean', 'verify', 'remove'))) {
87                /* HINT: Requested object string/id/type ("album", "myusername", "some song title", 1298376) */
88                Api::error(sprintf(T_('Bad Request: %s'), $item), '4710', self::ACTION, 'task', $input['api_format']);
89
90                return false;
91            }
92        }
93        $catalog_id = (int) $input['catalog'];
94        $catalog    = Catalog::create_from_id($catalog_id);
95        if ($catalog->id < 1) {
96            /* HINT: Requested object string/id/type ("album", "myusername", "some song title", 1298376) */
97            Api::error(sprintf(T_('Not Found: %s'), $catalog_id), '4704', self::ACTION, 'catalog', $input['api_format']);
98
99            return false;
100        }
101        switch ($catalog->gather_types) {
102            case 'podcast':
103                $type  = 'podcast_episode';
104                $media = new Podcast_Episode(Catalog::get_id_from_file($file, $type));
105                break;
106            case 'clip':
107            case 'tvshow':
108            case 'movie':
109            case 'personal_video':
110                $type  = 'video';
111                $media = new Video(Catalog::get_id_from_file($file, $type));
112                break;
113            case 'music':
114            default:
115                $type  = 'song';
116                $media = new Song(Catalog::get_id_from_file($file, $type));
117                break;
118        }
119
120        if ($catalog->catalog_type == 'local') {
121            foreach ($task as $item) {
122                define('API', true);
123                unset($SSE_OUTPUT);
124                switch ($item) {
125                    case 'clean':
126                        if ($media->id) {
127                            $catalog->clean_file($file, $type);
128                        }
129                        break;
130                    case 'verify':
131                        if ($media->id) {
132                            Catalog::update_media_from_tags($media, array($type));
133                        }
134                        break;
135                    case 'add':
136                        if (!$media->id) {
137                            $catalog->add_file($file, array());
138                        }
139                        break;
140                    case 'remove':
141                        if ($media->id) {
142                            $media->remove();
143                        }
144                        break;
145                }
146            }
147            Api::message('successfully started: ' . $task . ' for ' . $file, $input['api_format']);
148        } else {
149            Api::error(T_('Not Found'), '4704', self::ACTION, 'catalog', $input['api_format']);
150        }
151        Session::extend($input['auth']);
152
153        return true;
154    }
155
156    /**
157     * @deprecated
158     */
159    public static function getSongDeleter(): SongDeleterInterface
160    {
161        global $dic;
162
163        return $dic->get(SongDeleterInterface::class);
164    }
165}
166