url_store 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.markdown CHANGED
@@ -1,15 +1,23 @@
1
1
  Data securely stored in urls.
2
2
 
3
+ - url-save output
4
+ - short codes through GZip
5
+ - serializing through __:marshal__ :yaml
6
+ - hashing through DSS DSS1 MD2 MD4 MD5 MDC2 RIPEMD160 SHA __SHA1__ SHA224 SHA256 SHA384 SHA512
7
+
8
+
3
9
  Install
4
10
  =======
5
11
  - As gem: ` sudo gem install url_store `
6
12
  - As Rails plugin: ` script/plugin install git://github.com/grosser/url_store.git `
7
13
 
8
-
9
14
  Usage
10
15
  =====
16
+ # config (e.g environment.rb)
17
+ UrlStore.secret = 'adadasd2adsdasd4ads4eas4dea4dsea4sd'
18
+
11
19
  # View:
12
- <%= link_to 'paid', :controller=>:payments, :action=>:paid, :data=>UrlStore.encode(:id=>1, :status=>'paid')%>
20
+ <%= link_to 'paid', :controller=>:payments, :action=>:paid, :data=>UrlStore.encode(:id=>1, :status=>'paid') %>
13
21
 
14
22
  # Controller:
15
23
  if data = UrlStore.decode(params[:data])
@@ -18,6 +26,11 @@ Usage
18
26
  raise 'FRAUD!'
19
27
  end
20
28
 
29
+ ### Options
30
+ UrlStore.secret = 'something random'
31
+ UrlStore.hasher = 'MD5' # default: 'SHA1'
32
+ UrlStore.serializer = :yaml # default: :marshal
33
+
21
34
  Author
22
35
  =======
23
36
  [Michael Grosser](http://pragmatig.wordpress.com)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
@@ -0,0 +1,62 @@
1
+ require 'base64'
2
+ require 'zlib'
3
+
4
+ class UrlStore
5
+ class CompactEncoder
6
+ def initialize(secret, options={})
7
+ @secret = secret
8
+ @hasher = options[:hasher] || 'SHA1'
9
+ @serializer = options[:serializer] || :marshal
10
+ end
11
+
12
+ def encode(data)
13
+ data = compress(serialize(data))
14
+ data+digest(data)
15
+ end
16
+
17
+ def decode(data)
18
+ hash = data[-hash_length..-1]
19
+ data = data[0...-hash_length]
20
+
21
+ if digest(data) == hash
22
+ deserialize extract(data)
23
+ else
24
+ nil
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def serialize(data)
31
+ case @serializer.to_sym
32
+ when :yaml then data.to_yaml
33
+ when :marshal then Marshal.dump(data)
34
+ end
35
+ end
36
+
37
+ def deserialize(data)
38
+ case @serializer.to_sym
39
+ when :yaml then YAML.load(data)
40
+ when :marshal then Marshal.load(data)
41
+ end
42
+ end
43
+
44
+ def compress(data)
45
+ Base64.encode64( Zlib::Deflate.deflate(data)).gsub("\n",'')
46
+ end
47
+
48
+ def extract(data)
49
+ Zlib::Inflate.inflate Base64.decode64(data)
50
+ end
51
+
52
+ def hash_length
53
+ digest('x').size
54
+ end
55
+
56
+ # stolen from ActiveSupport
57
+ def digest(data)
58
+ require 'openssl' unless defined?(OpenSSL)
59
+ OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new(@hasher.to_s), @secret, data)
60
+ end
61
+ end
62
+ end
data/lib/url_store.rb CHANGED
@@ -1,37 +1,44 @@
1
- require 'active_support'
1
+ require 'url_store/compact_encoder'
2
2
 
3
3
  class UrlStore
4
4
  VERSION = File.read( File.join(File.dirname(__FILE__),'..','VERSION') ).strip
5
5
  SECRET = 'asdkasjlwqjdqaccxnjkasdfh2313'
6
- METHOD = 'SHA1'
6
+ HASHER = 'SHA1'
7
+ SERIALIZER = :marshal
7
8
 
8
9
  # (convert to base64url <-> RFC4648) and '|'
9
10
  # which is not url-safe if you ask ERB/CGI, but browsers accept it
10
11
  IN = '+/='
11
12
  OUT = '-_|'
12
13
 
13
- cattr_accessor :secret
14
- self.secret = SECRET
14
+ @@secret = SECRET
15
+ def self.secret=(x); @@secret=x; end
16
+ def self.secret; @@secret; end
17
+
18
+ @@hasher = HASHER
19
+ def self.hasher=(x); @@hasher=x; end
20
+ def self.hasher; @@hasher; end
21
+
22
+ @@serializer = SERIALIZER
23
+ def self.serializer=(x); @@serializer=x; end
24
+ def self.serializer; @@serializer; end
15
25
 
16
26
  def self.encode(data)
17
- string = encoder.generate(data)
18
- string = string.sub('--', ';') # seperator of verifier
27
+ string = encoder.encode(data)
19
28
  string.to_s.tr(IN,OUT)
20
29
  end
21
30
 
22
31
  def self.decode(string)
23
32
  string = string.to_s.tr(OUT,IN) # convert to base64url <-> RFC4648
24
- string = string.sub(';','--') # seperator of verifier
25
- begin
26
- encoder.verify(string)
27
- rescue ActiveSupport::MessageVerifier::InvalidSignature
28
- nil
29
- end
33
+ encoder.decode(string)
30
34
  end
31
35
 
32
36
  private
33
37
 
34
38
  def self.encoder
35
- ActiveSupport::MessageVerifier.new(secret, METHOD)
39
+ if secret == SECRET
40
+ warn "WARNING: you should not use the default secret! use UrlStore.secret='something'"
41
+ end
42
+ UrlStore::CompactEncoder.new(secret, :hasher => hasher, :serializer => serializer)
36
43
  end
37
44
  end
@@ -0,0 +1,31 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe UrlStore::CompactEncoder do
4
+ before do
5
+ @encoder = UrlStore::CompactEncoder.new('asdasdsa')
6
+ @data = {:x => 1, 'asdadadadas' => 'asdasdadawvxcxcxcvjs', 'dasdasdadsadad' => 'asdasdwxczvvcjjkdfjkdf'}
7
+ end
8
+
9
+ it "generates same code for same data" do
10
+ @encoder.encode(@data).should == @encoder.encode(@data)
11
+ end
12
+
13
+ it "can decode / encode" do
14
+ @encoder.decode(@encoder.encode(@data)).should == @data
15
+ end
16
+
17
+ it "generates shorter codes than pure base64" do
18
+ hash_length = 40
19
+ @encoder.encode(@data).size.should < (Base64.encode64(Marshal.dump(@data)).size + hash_length)
20
+ end
21
+
22
+ it "can encode/decode with yaml" do
23
+ @encoder = UrlStore::CompactEncoder.new('asdasdsa', :serializer => :yaml)
24
+ @encoder.decode(@encoder.encode(@data)).should == @data
25
+ end
26
+
27
+ it "can hash with other hasher" do
28
+ @encoder = UrlStore::CompactEncoder.new('asdasdsa', :hasher => 'MD5')
29
+ @encoder.decode(@encoder.encode(@data)).should == @data
30
+ end
31
+ end
@@ -3,6 +3,7 @@ require 'cgi'
3
3
 
4
4
  describe UrlStore do
5
5
  before do
6
+ UrlStore.secret = 'not the standart sssecrettt1231231áßðáïíœï©óáßïáöððííïö'
6
7
  @data = {:x => 11212, :y => 'asdasda sdasdasdASDJKSAJDLSKDLKDS', 'asdasd' => 12312312, 12.12 => 123123212312123, :asdasdasd => '2134 adasdasóáößðóöáåöäóðᜩöóöfóöåäfóöéåfó'}
7
8
  end
8
9
 
@@ -20,7 +21,7 @@ describe UrlStore do
20
21
  end
21
22
 
22
23
  it "uses a lot of different chars" do
23
- UrlStore.encode(@data).split('').uniq.size.should >= 63
24
+ UrlStore.encode(@data).split('').uniq.size.should >= 62
24
25
  end
25
26
 
26
27
  it "uses url-save characters" do
@@ -34,6 +35,29 @@ describe UrlStore do
34
35
  UrlStore.decode(encoded).should == nil
35
36
  end
36
37
 
38
+ it "warns when default secret is used" do
39
+ UrlStore.secret = UrlStore::SECRET
40
+ UrlStore.should_receive(:warn)
41
+ UrlStore.encode(1)
42
+ end
43
+
44
+ it "can compress" do
45
+ x = 'a'*100
46
+ UrlStore.encode(x).size.should <= x.size
47
+ end
48
+
49
+ it "can serialize using a different method" do
50
+ old = UrlStore.encode(@data)
51
+ UrlStore.serializer = :yaml
52
+ UrlStore.encode(@data).size.should_not == old.size
53
+ end
54
+
55
+ it "can serialize using different hasher" do
56
+ old = UrlStore.encode(@data)
57
+ UrlStore.hasher = 'MD5'
58
+ UrlStore.encode(@data).size.should_not == old.size
59
+ end
60
+
37
61
  it "has a VERSION" do
38
62
  UrlStore::VERSION.should =~ /^\d+\.\d+\.\d+$/
39
63
  end
data/url_store.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{url_store}
8
- s.version = "0.1.0"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Michael Grosser"]
@@ -20,7 +20,9 @@ Gem::Specification.new do |s|
20
20
  "Rakefile",
21
21
  "VERSION",
22
22
  "lib/url_store.rb",
23
+ "lib/url_store/compact_encoder.rb",
23
24
  "spec/spec_helper.rb",
25
+ "spec/url_store/compact_encoder_spec.rb",
24
26
  "spec/url_store_spec.rb",
25
27
  "url_store.gemspec"
26
28
  ]
@@ -31,7 +33,8 @@ Gem::Specification.new do |s|
31
33
  s.summary = %q{Data securely stored in urls.}
32
34
  s.test_files = [
33
35
  "spec/spec_helper.rb",
34
- "spec/url_store_spec.rb"
36
+ "spec/url_store_spec.rb",
37
+ "spec/url_store/compact_encoder_spec.rb"
35
38
  ]
36
39
 
37
40
  if s.respond_to? :specification_version then
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: url_store
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Grosser
@@ -26,7 +26,9 @@ files:
26
26
  - Rakefile
27
27
  - VERSION
28
28
  - lib/url_store.rb
29
+ - lib/url_store/compact_encoder.rb
29
30
  - spec/spec_helper.rb
31
+ - spec/url_store/compact_encoder_spec.rb
30
32
  - spec/url_store_spec.rb
31
33
  - url_store.gemspec
32
34
  has_rdoc: true
@@ -60,3 +62,4 @@ summary: Data securely stored in urls.
60
62
  test_files:
61
63
  - spec/spec_helper.rb
62
64
  - spec/url_store_spec.rb
65
+ - spec/url_store/compact_encoder_spec.rb