mpd: Sanity check stored playlist names

This commit is contained in:
Thomas Adamcik 2015-12-05 13:51:36 +01:00
parent c3393d3d85
commit b21debf6ee
3 changed files with 54 additions and 0 deletions

View File

@ -84,6 +84,15 @@ class MpdSystemError(MpdAckError):
error_code = MpdAckError.ACK_ERROR_SYSTEM
class MpdInvalidPlaylistName(MpdAckError):
error_code = MpdAckError.ACK_ERROR_ARG
def __init__(self, *args, **kwargs):
super(MpdInvalidPlaylistName, self).__init__(*args, **kwargs)
self.message = ('playlist name is invalid: playlist names may not '
'contain slashes, newlines or carriage returns')
class MpdNotImplemented(MpdAckError):
error_code = 0

View File

@ -2,6 +2,7 @@ from __future__ import absolute_import, division, unicode_literals
import datetime
import logging
import re
import warnings
from mopidy.compat import urllib
@ -10,6 +11,11 @@ from mopidy.mpd import exceptions, protocol, translator
logger = logging.getLogger(__name__)
def _check_playlist_name(name):
if re.search('[/\n\r]', name):
raise exceptions.MpdInvalidPlaylistName()
@protocol.commands.add('listplaylist')
def listplaylist(context, name):
"""
@ -149,6 +155,7 @@ def playlistadd(context, name, track_uri):
``NAME.m3u`` will be created if it does not exist.
"""
_check_playlist_name(name)
uri = context.lookup_playlist_uri_from_name(name)
old_playlist = uri is not None and context.core.playlists.lookup(uri).get()
if not old_playlist:
@ -219,6 +226,7 @@ def playlistclear(context, name):
The playlist will be created if it does not exist.
"""
_check_playlist_name(name)
uri = context.lookup_playlist_uri_from_name(name)
playlist = uri is not None and context.core.playlists.lookup(uri).get()
if not playlist:
@ -240,6 +248,7 @@ def playlistdelete(context, name, songpos):
Deletes ``SONGPOS`` from the playlist ``NAME.m3u``.
"""
_check_playlist_name(name)
uri = context.lookup_playlist_uri_from_name(name)
playlist = uri is not None and context.core.playlists.lookup(uri).get()
if not playlist:
@ -327,6 +336,7 @@ def rm(context, name):
Removes the playlist ``NAME.m3u`` from the playlist directory.
"""
_check_playlist_name(name)
uri = context.lookup_playlist_uri_from_name(name)
if not uri:
raise exceptions.MpdNoExistError('No such playlist')
@ -343,6 +353,7 @@ def save(context, name):
Saves the current playlist to ``NAME.m3u`` in the playlist
directory.
"""
_check_playlist_name(name)
tracks = context.core.tracklist.get_tracks().get()
uri = context.lookup_playlist_uri_from_name(name)
playlist = uri is not None and context.core.playlists.lookup(uri).get()

View File

@ -232,6 +232,10 @@ class PlaylistsHandlerTest(protocol.BaseTestCase):
self.assertEqual(0, len(self.core.tracklist.tracks.get()))
self.assertEqualResponse('ACK [50@0] {load} No such playlist')
# No invalid name check for load.
self.send_request('load "unknown/playlist"')
self.assertEqualResponse('ACK [50@0] {load} No such playlist')
def test_playlistadd(self):
tracks = [
Track(uri='dummy:a'),
@ -259,6 +263,12 @@ class PlaylistsHandlerTest(protocol.BaseTestCase):
self.assertInResponse('OK')
self.assertIsNotNone(self.backend.playlists.lookup('dummy:name').get())
def test_playlistadd_invalid_name_acks(self):
self.send_request('playlistadd "foo/bar" "dummy:a"')
self.assertInResponse('ACK [2@0] {playlistadd} playlist name is '
'invalid: playlist names may not contain '
'slashes, newlines or carriage returns')
def test_playlistclear(self):
self.backend.playlists.set_dummy_playlists([
Playlist(
@ -276,6 +286,12 @@ class PlaylistsHandlerTest(protocol.BaseTestCase):
self.assertInResponse('OK')
self.assertIsNotNone(self.backend.playlists.lookup('dummy:name').get())
def test_playlistclear_invalid_name_acks(self):
self.send_request('playlistclear "foo/bar"')
self.assertInResponse('ACK [2@0] {playlistclear} playlist name is '
'invalid: playlist names may not contain '
'slashes, newlines or carriage returns')
def test_playlistdelete(self):
tracks = [
Track(uri='dummy:a'),
@ -292,6 +308,12 @@ class PlaylistsHandlerTest(protocol.BaseTestCase):
self.assertEqual(
2, len(self.backend.playlists.get_items('dummy:a1').get()))
def test_playlistdelete_invalid_name_acks(self):
self.send_request('playlistdelete "foo/bar" "0"')
self.assertInResponse('ACK [2@0] {playlistdelete} playlist name is '
'invalid: playlist names may not contain '
'slashes, newlines or carriage returns')
def test_playlistmove(self):
tracks = [
Track(uri='dummy:a'),
@ -334,8 +356,20 @@ class PlaylistsHandlerTest(protocol.BaseTestCase):
self.send_request('rm "name"')
self.assertInResponse('ACK [50@0] {rm} No such playlist')
def test_rm_invalid_name_acks(self):
self.send_request('rm "foo/bar"')
self.assertInResponse('ACK [2@0] {rm} playlist name is invalid: '
'playlist names may not contain slashes, '
'newlines or carriage returns')
def test_save(self):
self.send_request('save "name"')
self.assertInResponse('OK')
self.assertIsNotNone(self.backend.playlists.lookup('dummy:name').get())
def test_save_invalid_name_acks(self):
self.send_request('save "foo/bar"')
self.assertInResponse('ACK [2@0] {save} playlist name is invalid: '
'playlist names may not contain slashes, '
'newlines or carriage returns')