diff --git a/src/Module/Api/Method/BookmarkCreateMethod.php b/src/Module/Api/Method/BookmarkCreateMethod.php index a30f495335..e833a57ec4 100644 --- a/src/Module/Api/Method/BookmarkCreateMethod.php +++ b/src/Module/Api/Method/BookmarkCreateMethod.php @@ -66,7 +66,7 @@ public static function bookmark_create(array $input) $object_id = $input['filter']; $type = $input['type']; $position = $input['position']; - $comment = (isset($input['client'])) ? $input['client'] : 'AmpacheAPI'; + $comment = (isset($input['client'])) ? filter_var($input['client'], FILTER_SANITIZE_STRING) : 'AmpacheAPI'; $time = (isset($input['date'])) ? (int) $input['date'] : time(); if (!AmpConfig::get('allow_video') && $type == 'video') { Api::error(T_('Enable: video'), '4703', self::ACTION, 'system', $input['api_format']); diff --git a/src/Module/Api/Method/BookmarkDeleteMethod.php b/src/Module/Api/Method/BookmarkDeleteMethod.php index fa5b3f92c3..5d820cb67f 100644 --- a/src/Module/Api/Method/BookmarkDeleteMethod.php +++ b/src/Module/Api/Method/BookmarkDeleteMethod.php @@ -61,7 +61,7 @@ public static function bookmark_delete(array $input) $user = User::get_from_username(Session::username($input['auth'])); $object_id = $input['filter']; $type = $input['type']; - $comment = (isset($input['client'])) ? (string) $input['client'] : 'AmpacheAPI'; + $comment = (isset($input['client'])) ? filter_var($input['client'], FILTER_SANITIZE_STRING) : 'AmpacheAPI'; if (!AmpConfig::get('allow_video') && $type == 'video') { Api::error(T_('Enable: video'), '4703', self::ACTION, 'system', $input['api_format']); diff --git a/src/Module/Api/Method/BookmarkEditMethod.php b/src/Module/Api/Method/BookmarkEditMethod.php index c348df8f16..7a20bd15d3 100644 --- a/src/Module/Api/Method/BookmarkEditMethod.php +++ b/src/Module/Api/Method/BookmarkEditMethod.php @@ -64,8 +64,8 @@ public static function bookmark_edit(array $input) $user = User::get_from_username(Session::username($input['auth'])); $object_id = $input['filter']; $type = $input['type']; - $position = $input['position']; - $comment = (isset($input['client'])) ? $input['client'] : 'AmpacheAPI'; + $position = filter_var($input['position'], FILTER_SANITIZE_NUMBER_INT) ?? 0; + $comment = (isset($input['client'])) ? filter_var($input['client'], FILTER_SANITIZE_STRING) : 'AmpacheAPI'; $time = (isset($input['date'])) ? (int) $input['date'] : time(); if (!AmpConfig::get('allow_video') && $type == 'video') { Api::error(T_('Enable: video'), '4703', self::ACTION, 'system', $input['api_format']); diff --git a/src/Module/Api/Method/HandshakeMethod.php b/src/Module/Api/Method/HandshakeMethod.php index ed65331221..9ef46a8312 100644 --- a/src/Module/Api/Method/HandshakeMethod.php +++ b/src/Module/Api/Method/HandshakeMethod.php @@ -145,7 +145,7 @@ public static function handshake(array $input) $data['apikey'] = $client->apikey; $data['value'] = $timestamp; if (isset($input['client'])) { - $data['agent'] = $input['client']; + $data['agent'] = filter_var($input['client'], FILTER_SANITIZE_STRING); } if (isset($input['geo_latitude'])) { $data['geo_latitude'] = $input['geo_latitude']; diff --git a/src/Module/Api/Method/PodcastEditMethod.php b/src/Module/Api/Method/PodcastEditMethod.php index e6e23ff3e8..e28f52cd64 100644 --- a/src/Module/Api/Method/PodcastEditMethod.php +++ b/src/Module/Api/Method/PodcastEditMethod.php @@ -83,9 +83,9 @@ public static function podcast_edit(array $input) $feed = filter_var($input['feed'], FILTER_VALIDATE_URL) ? $input['feed'] : $podcast->feed; $title = isset($input['title']) ? scrub_in($input['title']) : $podcast->title; $website = filter_var($input['website'], FILTER_VALIDATE_URL) ? scrub_in($input['website']) : $podcast->website; - $description = isset($input['description']) ? scrub_in($input['description']) : $podcast->description; - $generator = isset($input['generator']) ? scrub_in($input['generator']) : $podcast->generator; - $copyright = isset($input['copyright']) ? scrub_in($input['copyright']) : $podcast->copyright; + $description = filter_var($input['description'], FILTER_SANITIZE_STRING) ?? $podcast->description; + $generator = filter_var($input['generator'], FILTER_SANITIZE_STRING) ?? $podcast->generator; + $copyright = filter_var($input['copyright'], FILTER_SANITIZE_STRING) ?? $podcast->copyright; $data = array( 'feed' => $feed, 'title' => $title, diff --git a/src/Module/Api/Method/RecordPlayMethod.php b/src/Module/Api/Method/RecordPlayMethod.php index 5926c9b24f..1c3aaecd89 100644 --- a/src/Module/Api/Method/RecordPlayMethod.php +++ b/src/Module/Api/Method/RecordPlayMethod.php @@ -81,7 +81,7 @@ public static function record_play(array $input) // validate client string or fall back to 'api' $agent = (array_key_exists('client', $input)) - ? $input['client'] + ? filter_var($input['client'], FILTER_SANITIZE_STRING) : 'api'; $media = new Song($object_id); diff --git a/src/Module/Api/Method/ScrobbleMethod.php b/src/Module/Api/Method/ScrobbleMethod.php index e68c6cc576..f04058fe06 100644 --- a/src/Module/Api/Method/ScrobbleMethod.php +++ b/src/Module/Api/Method/ScrobbleMethod.php @@ -92,7 +92,7 @@ public static function scrobble(array $input) } // validate client string or fall back to 'api' - $agent = $input['client'] ?? 'api'; + $agent = filter_var($input['client'], FILTER_SANITIZE_STRING) ?? 'api'; $scrobble_id = Song::can_scrobble($song_name, $artist_name, $album_name, $song_mbid, $artist_mbid, $album_mbid); if ($scrobble_id === '') { diff --git a/src/Module/Api/Method/ShareEditMethod.php b/src/Module/Api/Method/ShareEditMethod.php index dbc664cee0..2e7bb17164 100644 --- a/src/Module/Api/Method/ShareEditMethod.php +++ b/src/Module/Api/Method/ShareEditMethod.php @@ -67,10 +67,10 @@ public static function share_edit(array $input) $share_id = $input['filter']; if (in_array($share_id, Share::get_share_list($user))) { $share = new Share($share_id); - $description = isset($input['description']) ? $input['description'] : $share->description; - $stream = isset($input['stream']) ? $input['stream'] : $share->allow_stream; - $download = isset($input['download']) ? $input['download'] : $share->allow_download; - $expires = isset($input['expires']) ? Share::get_expiry($input['expires']) : $share->expire_days; + $description = filter_var($input['description'], FILTER_SANITIZE_STRING) ?? $share->description; + $stream = filter_var($input['stream'], FILTER_SANITIZE_NUMBER_INT) ?? $share->allow_stream; + $download = filter_var($input['download'], FILTER_SANITIZE_NUMBER_INT) ?? $share->allow_download; + $expires = isset($input['expires']) ? Share::get_expiry(filter_var($input['expires'], FILTER_SANITIZE_NUMBER_INT)) : $share->expire_days; $user = User::get_from_username(Session::username($input['auth'])); $data = array( diff --git a/src/Module/Api/Subsonic_Api.php b/src/Module/Api/Subsonic_Api.php index 074bb24c0c..7cb3386b69 100644 --- a/src/Module/Api/Subsonic_Api.php +++ b/src/Module/Api/Subsonic_Api.php @@ -449,10 +449,11 @@ public static function getlicense($input) */ public static function getmusicfolders($input) { - $username = $input['u']; - $user = User::get_from_username((string)$username); + $username = (string)filter_var($input['u'], FILTER_SANITIZE_STRING); + $user = User::get_from_username($username); $catalogs = Catalog::get_catalogs('music', $user->id); $response = Subsonic_Xml_Data::createSuccessResponse('getmusicfolders'); + Subsonic_Xml_Data::addMusicFolders($response, $catalogs); self::apiOutput($input, $response); } @@ -982,9 +983,9 @@ public static function search3($input) */ public static function getplaylists($input) { - $response = Subsonic_Xml_Data::createSuccessResponse('getplaylists'); - $username = $input['username'] ?? $input['u']; + $username = (string)filter_var($input['username'], FILTER_SANITIZE_STRING) ?? (string)filter_var($input['u'], FILTER_SANITIZE_STRING); $user = User::get_from_username((string)$username); + $response = Subsonic_Xml_Data::createSuccessResponse('getplaylists'); // Don't allow playlist listing for another user Subsonic_Xml_Data::addPlaylists($response, Playlist::get_playlists($user->id), Playlist::get_smartlists($user->id)); @@ -1152,13 +1153,16 @@ public static function stream($input) { $fileid = self::check_parameter($input, 'id', true); - $maxBitRate = $input['maxBitRate'] ?? 0; + $maxBitRate = (int)($input['maxBitRate'] ?? 0); $format = $input['format'] ?? ''; // mp3, flv or raw $timeOffset = $input['timeOffset'] ?? false; - $contentLength = $input['estimateContentLength'] ?? false; // Force content-length guessing if transcode - $user_id = User::get_from_username($input['u'])->id; + $contentLength = $input['estimateContentLength'] ?? false; // Force content-length guessing if transcode$username = (string)filter_var($input['u'], FILTER_SANITIZE_STRING); + $username = (string)filter_var($input['u'], FILTER_SANITIZE_STRING); + $user = User::get_from_username($username); + $user_id = $user->id; + $client = (string)filter_var($input['c'], FILTER_SANITIZE_STRING) ?? 'Subsonic'; - $params = '&client=' . rawurlencode($input['c']); + $params = '&client=' . rawurlencode($client); if ($contentLength == 'true') { $params .= '&content_length=required'; } @@ -1204,7 +1208,8 @@ public static function download($input) { $fileid = self::check_parameter($input, 'id', true); $user_id = User::get_from_username($input['u'])->id; - $params = '&client=' . rawurlencode($input['c']) . '&action=download&cache=1'; + $client = (string)filter_var($input['c'], FILTER_SANITIZE_STRING) ?? 'Subsonic'; + $params = '&client=' . rawurlencode($client) . '&action=download&cache=1'; $url = ''; if (Subsonic_Xml_Data::isSong($fileid)) { $object = new Song(Subsonic_Xml_Data::getAmpacheId($fileid)); @@ -2049,7 +2054,7 @@ public static function scrobble($input) $object_ids = self::check_parameter($input, 'id'); $submission = ($input['submission'] === 'true' || $input['submission'] === '1'); $username = (string) $input['u']; - $client = (string) $input['c']; + $client = (string)filter_var($input['c'], FILTER_SANITIZE_STRING) ?? 'Subsonic'; $user = User::get_from_username($username); if (!is_array($object_ids)) { @@ -2415,12 +2420,10 @@ public static function downloadpodcastepisode($input) $episode->gather(); $response = Subsonic_Xml_Data::createSuccessResponse('downloadpodcastepisode'); } else { - $response = Subsonic_Xml_Data::createError(Subsonic_Xml_Data::SSERROR_DATA_NOTFOUND, '', - 'downloadpodcastepisode'); + $response = Subsonic_Xml_Data::createError(Subsonic_Xml_Data::SSERROR_DATA_NOTFOUND, '', 'downloadpodcastepisode'); } } else { - $response = Subsonic_Xml_Data::createError(Subsonic_Xml_Data::SSERROR_UNAUTHORIZED, '', - 'downloadpodcastepisode'); + $response = Subsonic_Xml_Data::createError(Subsonic_Xml_Data::SSERROR_UNAUTHORIZED, '', 'downloadpodcastepisode'); } self::apiOutput($input, $response); } @@ -2569,9 +2572,10 @@ public static function saveplayqueue($input) if ($media->id) { $response = Subsonic_Xml_Data::createSuccessResponse('saveplayqueue'); $position = (int)((int)$input['position'] / 1000); - $username = (string) $input['u']; - $client = (string) $input['c']; - $user_id = User::get_from_username($username)->id; + $client = (string)filter_var($input['c'], FILTER_SANITIZE_STRING) ?? 'Subsonic'; + $username = (string)filter_var($input['u'], FILTER_SANITIZE_STRING); + $user = User::get_from_username($username); + $user_id = $user->id; $user_data = User::get_user_data($user_id, 'playqueue_time'); $time = time(); // wait a few seconds before smashing out play times @@ -2616,9 +2620,10 @@ public static function saveplayqueue($input) */ public static function getplayqueue($input) { - $username = (string) $input['u']; - $client = (string) $input['c']; - $user_id = User::get_from_username($username)->id; + $username = (string)filter_var($input['u'], FILTER_SANITIZE_STRING); + $user = User::get_from_username($username); + $client = (string)filter_var($input['c'], FILTER_SANITIZE_STRING) ?? 'Subsonic'; + $user_id = $user->id; $response = Subsonic_Xml_Data::createSuccessResponse('getplayqueue'); User::set_user_data($user_id, 'playqueue_time', time()); User::set_user_data($user_id, 'playqueue_client', $client); diff --git a/src/Module/Application/Admin/Access/AddHostAction.php b/src/Module/Application/Admin/Access/AddHostAction.php index 0093283e6f..7e43fba9c7 100644 --- a/src/Module/Application/Admin/Access/AddHostAction.php +++ b/src/Module/Application/Admin/Access/AddHostAction.php @@ -78,8 +78,7 @@ public function run(ServerRequestInterface $request, GuiGatekeeperInterface $gat $this->ui->showHeader(); - $data = $request->getParsedBody(); - + $data = $request->getParsedBody(); $startIp = $data['start'] ?? ''; $endIp = $data['end'] ?? ''; diff --git a/src/Module/Application/Admin/Access/UpdateRecordAction.php b/src/Module/Application/Admin/Access/UpdateRecordAction.php index 89f060e971..1920695af5 100644 --- a/src/Module/Application/Admin/Access/UpdateRecordAction.php +++ b/src/Module/Application/Admin/Access/UpdateRecordAction.php @@ -73,12 +73,11 @@ public function run(ServerRequestInterface $request, GuiGatekeeperInterface $gat throw new AccessDeniedException(); } - $accessId = (int) $request->getQueryParams()['access_id'] ?? 0; $this->ui->showHeader(); - $data = $request->getParsedBody(); - + $data = $request->getParsedBody(); + $accessId = (int) $request->getQueryParams()['access_id'] ?? 0; try { $this->accessListManager->update( $accessId, diff --git a/src/Module/Application/Admin/License/EditAction.php b/src/Module/Application/Admin/License/EditAction.php index 49074525a3..8f167167ee 100644 --- a/src/Module/Application/Admin/License/EditAction.php +++ b/src/Module/Application/Admin/License/EditAction.php @@ -67,26 +67,27 @@ public function run(ServerRequestInterface $request, GuiGatekeeperInterface $gat $this->ui->showHeader(); - $data = $request->getParsedBody(); - - $licenseId = (int) ($data['license_id'] ?? 0); + $data = $request->getParsedBody(); + $licenseId = (array_key_exists('license_id', $data)) + ? filter_var($data['license_id'], FILTER_SANITIZE_NUMBER_INT) + : 0; if ($licenseId > 0) { $license = $this->modelFactory->createLicense($licenseId); if ($license->id) { $this->licenseRepository->update( $licenseId, - $data['name'] ?? '', - $data['description'] ?? '', - $data['external_link'] ?? '' + (array_key_exists('name', $data)) ? filter_var($data['name'], FILTER_SANITIZE_STRING) : '', + (array_key_exists('description', $data)) ? filter_var($data['description'], FILTER_SANITIZE_STRING) : '', + (array_key_exists('external_link', $data)) ? filter_var($data['external_link'], FILTER_SANITIZE_URL) : '' ); } $text = T_('The License has been updated'); } else { $this->licenseRepository->create( - $data['name'] ?? '', - $data['description'] ?? '', - $data['external_link'] ?? '' + (array_key_exists('name', $data)) ? filter_var($data['name'], FILTER_SANITIZE_STRING) : '', + (array_key_exists('description', $data)) ? filter_var($data['description'], FILTER_SANITIZE_STRING) : '', + (array_key_exists('external_link', $data)) ? filter_var($data['external_link'], FILTER_SANITIZE_URL) : '' ); $text = T_('A new License has been created'); } diff --git a/src/Module/Application/Admin/Shout/EditShoutAction.php b/src/Module/Application/Admin/Shout/EditShoutAction.php index 0a92c92f3e..25de048d2f 100644 --- a/src/Module/Application/Admin/Shout/EditShoutAction.php +++ b/src/Module/Application/Admin/Shout/EditShoutAction.php @@ -62,13 +62,19 @@ public function run(ServerRequestInterface $request, GuiGatekeeperInterface $gat $this->ui->showHeader(); - $body = $request->getParsedBody(); - + $data = $request->getParsedBody(); $shout = $this->modelFactory->createShoutbox( - (int) $body['shout_id'] ?? 0 + (int)(filter_var($data['shout_id'], FILTER_SANITIZE_NUMBER_INT) ?? 0) ); + if ($shout->id) { - $shout->update($body); + $data['comment'] = (array_key_exists('license_id', $data)) + ? filter_var($data['comment'], FILTER_SANITIZE_STRING) + : ''; + $data['sticky'] = (array_key_exists('license_id', $data)) + ? filter_var($data['sticky'], FILTER_SANITIZE_STRING) + : ''; + $shout->update($data); } $this->ui->showConfirmation( T_('No Problem'), diff --git a/tests/Module/Application/Admin/Shout/EditShoutActionTest.php b/tests/Module/Application/Admin/Shout/EditShoutActionTest.php index 3131a23100..134636eab0 100644 --- a/tests/Module/Application/Admin/Shout/EditShoutActionTest.php +++ b/tests/Module/Application/Admin/Shout/EditShoutActionTest.php @@ -82,7 +82,7 @@ public function testRunUpdatesEntry(): void $shoutbox = $this->mock(Shoutbox::class); $shout_id = 666; - $data = ['shout_id' => (string) $shout_id]; + $data = ['shout_id' => $shout_id, 'comment' => '', 'sticky' => '']; $webPath = 'some-path'; $shoutbox->id = $shout_id;