Accomodate otherwise valid user-supplied portable data hashes with no size
[arvados.git] / services / api / app / models / locator.rb
index 39d7da94dc234ab4797d5cfe91a0d75a6378327e..22dfc2c4a06a3306abcde72b801306354f0aa786 100644 (file)
@@ -11,7 +11,7 @@
 #   hint-content ::= [A-Za-z0-9@_-]+
 #
 # Individual hints may have their own required format:
-# 
+#
 #   sign-hint      ::= "+A" <40 lowercase hex digits> "@" sign-timestamp
 #   sign-timestamp ::= <8 lowercase hex digits>
 
@@ -35,9 +35,16 @@ class Locator
   # Locator.parse! returns a Locator object parsed from the string tok,
   # raising an ArgumentError if tok cannot be parsed.
   def self.parse!(tok)
+    if tok.nil? or tok.empty?
+      raise ArgumentError.new "locator is nil or empty"
+    end
+
     m = /^([[:xdigit:]]{32})(\+([[:digit:]]+))?(\+([[:upper:]][[:alnum:]+@_-]*))?$/.match(tok.strip)
     unless m
-      raise ArgumentError.new "could not parse #{tok}"
+      raise ArgumentError.new "not a valid locator #{tok}"
+    end
+    unless m[2]
+      Rails.logger.debug ArgumentError.new "missing size hint on #{tok}"
     end
 
     tokhash, _, toksize, _, trailer = m[1..5]
@@ -66,6 +73,15 @@ class Locator
     Locator.new(@hash, @size, @hints.reject { |o| o.start_with?("A") })
   end
 
+  def strip_hints
+    Locator.new(@hash, @size, [])
+  end
+
+  def strip_hints!
+    @hints = []
+    self
+  end
+
   def hash
     @hash
   end
@@ -79,6 +95,10 @@ class Locator
   end
 
   def to_s
-    [ @hash, @size, *@hints ].join('+')
+    if @size
+      [ @hash, @size, *@hints ].join('+')
+    else
+      [ @hash, *@hints ].join('+')
+    end
   end
 end