about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2015-12-07 09:50:26 +0000
committerEric Wong <e@80x24.org>2015-12-07 09:50:26 +0000
commitb08fe09e296524daf4de7ed16e0bed224f5008a2 (patch)
treec349b14b6e72f168469e3a8a732099d5bd5d681a
parent3e013d3f24f0f935dce985d4c6bd155889e05dbb (diff)
downloaddtas-b08fe09e296524daf4de7ed16e0bed224f5008a2.tar.gz
This defaults to 16384?  This is what mpd uses by default as well.
Of course folks interacting with dtas-player directly can override
this:

	dtas-tl max INTEGER
	dtas-tl max

This is NOT meant to be a hard security measure for local users
talking to dtas-player directly.  It is only to prevent
accidentally stupid things like flooding the playlist with
a broken script and to prevent remote users from DoS-ing
us via the to-be-written mpd proxy/emulation layer.

Remember: dtas-player itself will ALWAYS remain capable of
executing arbitrary code :)
-rw-r--r--lib/dtas/player/client_handler.rb8
-rw-r--r--lib/dtas/tracklist.rb23
-rw-r--r--test/test_tracklist.rb12
3 files changed, 36 insertions, 7 deletions
diff --git a/lib/dtas/player/client_handler.rb b/lib/dtas/player/client_handler.rb
index 500704a..119aa31 100644
--- a/lib/dtas/player/client_handler.rb
+++ b/lib/dtas/player/client_handler.rb
@@ -566,6 +566,7 @@ module DTAS::Player::ClientHandler # :nodoc:
       end
       begin
         track_id = @tl.add_track(path, after_track_id, set_as_current)
+        return io.emit('ERR FULL') unless track_id
       rescue ArgumentError => e
         return io.emit("ERR #{e.message}")
       end
@@ -593,6 +594,13 @@ module DTAS::Player::ClientHandler # :nodoc:
         set_bool(io, 'tl shuffle', v) { |b| @tl.shuffle = b }
         io.emit('OK')
       end
+    when 'max'
+      case v = msg.shift
+      when nil then io.emit("tl max #{@tl.max}")
+      when %r{\A(\d[\d_]*)\z} then io.emit("tl max #{@tl.max = $1.to_i}")
+      else
+        return io.emit('ERR tl max must a non-negative integer')
+      end
     when "remove"
       track_id = msg.shift or return io.emit("ERR track_id not specified")
       track_id = track_id.to_i
diff --git a/lib/dtas/tracklist.rb b/lib/dtas/tracklist.rb
index f3dca31..d3db4e9 100644
--- a/lib/dtas/tracklist.rb
+++ b/lib/dtas/tracklist.rb
@@ -10,20 +10,27 @@ class DTAS::Tracklist # :nodoc:
   include DTAS::Serialize
   attr_accessor :repeat # true, false, 1
   attr_reader :shuffle  # false or shuffled @list
+  attr_accessor :max # integer
 
-  SIVS = %w(list pos repeat)
   TL_DEFAULTS = {
-    "list" => [],
-    "pos" => -1,
-    "repeat" => false,
+    'list' => [],
+    'pos' => -1,
+    'repeat' => false,
+    'max' => 20_000,
   }
+  SIVS = TL_DEFAULTS.keys
 
   def self.load(hash)
     obj = new
     obj.instance_eval do
-      list = hash["list"] and @list.replace(list.map { |s| new_track(s) })
-      @pos = hash["pos"] || -1
-      @repeat = hash["repeat"] || false
+      list = hash['list'] and @list.replace(list.map { |s| new_track(s) })
+      %w(pos repeat max).each do |k|
+        instance_variable_set("@#{k}", hash[k] || TL_DEFAULTS[k])
+      end
+
+      # n.b.: we don't check @list.size against max here in case people
+      # are migrating
+
       if hash['shuffle']
         @shuffle = @list.shuffle
         @pos = _idx_of(@shuffle, @list[@pos].track_id) if @pos >= 0
@@ -121,6 +128,8 @@ class DTAS::Tracklist # :nodoc:
   end
 
   def add_track(track, after_track_id = nil, set_as_current = false)
+    return false if @list.size >= @max
+
     track = new_track(track)
     if after_track_id
       idx = _idx_of(@list, after_track_id) or
diff --git a/test/test_tracklist.rb b/test/test_tracklist.rb
index a3c89f6..4d00227 100644
--- a/test/test_tracklist.rb
+++ b/test/test_tracklist.rb
@@ -106,4 +106,16 @@ class TestTracklist < Testcase
     tl.remove_track(1 << 128)
     assert_equal %w(b c e f), list_to_path(tl), "no change"
   end
+
+  def test_max
+    tl = DTAS::Tracklist.new
+    assert_kind_of Integer, tl.add_track('z')
+    assert_kind_of Integer, tl.max
+    tl.max = 1
+    assert_equal false, tl.add_track('y')
+    assert_equal 1, tl.instance_variable_get(:@list).size
+    tl.max = 2
+    assert_kind_of Integer, tl.add_track('y')
+    assert_equal 2, tl.instance_variable_get(:@list).size
+  end
 end