Permalink
Browse files

add our own encoder, remove active_support dependency, shorten codes

  • Loading branch information...
1 parent b7bb5b8 commit 183898fa9d26f87c4588a8211253112fd6697116 @grosser committed Jan 19, 2010
Showing with 87 additions and 12 deletions.
  1. +7 −12 lib/url_store.rb
  2. +54 −0 lib/url_store/compact_encoder.rb
  3. +21 −0 spec/url_store/compact_encoder_spec.rb
  4. +5 −0 spec/url_store_spec.rb
View
@@ -1,4 +1,4 @@
-require 'active_support'
+require 'url_store/compact_encoder'
class UrlStore
VERSION = File.read( File.join(File.dirname(__FILE__),'..','VERSION') ).strip
@@ -10,23 +10,18 @@ class UrlStore
IN = '+/='
OUT = '-_|'
- cattr_accessor :secret
- self.secret = SECRET
+ @@secret = SECRET
+ def self.secret=(x); @@secret=x; end
+ def self.secret; @@secret; end
def self.encode(data)
- string = encoder.generate(data)
- string = string.sub('--', ';') # seperator of verifier
+ string = encoder.encode(data)
string.to_s.tr(IN,OUT)
end
def self.decode(string)
string = string.to_s.tr(OUT,IN) # convert to base64url <-> RFC4648
- string = string.sub(';','--') # seperator of verifier
- begin
- encoder.verify(string)
- rescue ActiveSupport::MessageVerifier::InvalidSignature
- nil
- end
+ encoder.decode(string)
end
private
@@ -35,6 +30,6 @@ def self.encoder
if secret == SECRET
warn "WARNING: you should not use the default secret! use UrlStore.secret='something'"
end
- ActiveSupport::MessageVerifier.new(secret, METHOD)
+ UrlStore::CompactEncoder.new(secret, METHOD)
end
end
@@ -0,0 +1,54 @@
+require 'base64'
+require 'zlib'
+
+class UrlStore
+ class CompactEncoder
+ def initialize(secret, algorithm)
+ @secret = secret; @algorithm = algorithm
+ end
+
+ def encode(data)
+ data = compress(serialize(data))
+ data+digest(data)
+ end
+
+ def decode(data)
+ hash = data[-hash_length..-1]
+ data = data[0...-hash_length]
+
+ if digest(data) == hash
+ deserialize extract(data)
+ else
+ nil
+ end
+ end
+
+ private
+
+ def serialize(data)
+ Marshal.dump data
+ end
+
+ def deserialize(data)
+ Marshal.load data
+ end
+
+ def compress(data)
+ Base64.encode64( Zlib::Deflate.deflate data ).gsub("\n",'')
+ end
+
+ def extract(data)
+ Zlib::Inflate.inflate Base64.decode64(data)
+ end
+
+ def hash_length
+ digest('x').size
+ end
+
+ # stolen from ActiveSupport
+ def digest(data)
+ require 'openssl' unless defined?(OpenSSL)
+ OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new(@algorithm), @secret, data)
+ end
+ end
+end
@@ -0,0 +1,21 @@
+require File.dirname(__FILE__) + '/../spec_helper'
+
+describe UrlStore::CompactEncoder do
+ before do
+ @encoder = UrlStore::CompactEncoder.new('asdasdsa','SHA1')
+ @data = {:x => 1, 'asdadadadas' => 'asdasdadawvxcxcxcvjs', 'dasdasdadsadad' => 'asdasdwxczvvcjjkdfjkdf'}
+ end
+
+ it "generates same code for same data" do
+ @encoder.encode(@data).should == @encoder.encode(@data)
+ end
+
+ it "can decode / encode" do
+ @encoder.decode(@encoder.encode(@data)).should == @data
+ end
+
+ it "generates shorter codes than pure base64" do
+ hash_length = 40
+ @encoder.encode(@data).size.should < (Base64.encode64(Marshal.dump(@data)).size + hash_length)
+ end
+end
View
@@ -41,6 +41,11 @@
UrlStore.encode(1)
end
+ it "can compress" do
+ x = 'a'*100
+ UrlStore.encode(x).size.should <= x.size
+ end
+
it "has a VERSION" do
UrlStore::VERSION.should =~ /^\d+\.\d+\.\d+$/
end

0 comments on commit 183898f

Please sign in to comment.