diff --git a/lib/hyde/util/cookie.rb b/lib/hyde/util/cookie.rb new file mode 100644 index 0000000..b7ece50 --- /dev/null +++ b/lib/hyde/util/cookie.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require_relative 'header' + +module Hyde + # Utility class for handling cookies + class Cookie + # @param data [String] raw cookie data + def initialize(key, value, params = {}) + @key = key + @value = value + @params = params + end + + # Convert cookie to "Set-Cookie: " string representation. + # @return [String] + def to_s + Hyde::Util.make_value(to_short, @params) + end + + # Convert cookie to "Cookie: " string representation (no params) + def to_short + "#{key.to_s.strip}=#{value.to_s.strip}" + end + + attr_accessor :key, :value + attr_reader :params + + # Create cookie from a "Set-Cookie: " format + # @param data [String] value part of "Set-Cookie: " header + # @return [Cookie] + def self.from_setcookie_string(data) + kvpair, params = Hyde::Util.parse_value(data) + key, value = kvpair.split("=").map(&:strip) + Cookie.new(key, value, params) + end + + # Create cookie(s) from a "Cookie: " format + # @param data [String] value part of "Cookie: " header + # @return [Array(Cookie)] + def self.from_cookie_string(data) + data.split(";").map do |cookiestr| + Cookie.new(*cookiestr.split("=").map(&:strip)) + end + end + end +end diff --git a/lib/hyde/util/header.rb b/lib/hyde/util/header.rb index 54671c1..1e1a56c 100644 --- a/lib/hyde/util/header.rb +++ b/lib/hyde/util/header.rb @@ -12,7 +12,12 @@ module Hyde parts = input.split(sep).map { |x| URI.decode_uri_component(x).strip } base = parts.shift opts = parts.map do |raw| - key, value = raw.match(/^([^=]*)(?:=(.*)|)\Z/).to_a[1..] + key, value = raw.match(/ + \A # beginning of string + ([!-~&&[^=;,]]+) # key + (?:=([\s!-~&&[^;,]]*)|) # optional value + \Z # end of sting + /x).to_a[1..] [key, ((value&.match?(/^".*"$/) ? value[1..-2] : value) or true)] end.to_h [base, opts] @@ -24,7 +29,7 @@ module Hyde # @return [String] def self.make_value(input, opts, sep = ";") unless input.match?(/^[\w!#$%&'*+-.^_`|~]*=?[^[:cntrl:]\\",;]+$/) - raise StandardError, "input contains invalid characters" + raise StandardError, "input format is invalid" end output = input