php_session 0.3.1 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8550806b73142b48e0e82596af2e4f1b8e8ab363
4
- data.tar.gz: 80ad0853de0fea1c9e22c460d65bb60bdae9c3fd
3
+ metadata.gz: b7b87e7c1e025ed1df45430687998b0f60dacc50
4
+ data.tar.gz: 2daeb3db468fe3c91db723e2da73d44ac678571b
5
5
  SHA512:
6
- metadata.gz: 92cfdb1e5126e6d8a7819e3d03467586bd3c0aa39b779586d900d6ae46d01dfb233353dcd909b0d4a6945c8cccecb804c0c70d1ba19b69462dcf63cc54c857b8
7
- data.tar.gz: c0416ce6aee7827f08a5f041f24893ba16bed74f4b29e97f46cb5e41937d335c456be45bf88c5de36169998e7553ec3233b9d8fcecbbc21f815a719d95dc6de4
6
+ metadata.gz: ce3e5b3099257ae86f80dc68b459994d003a95f38ea3e627242237b02947d7769bed8c822dd8dc84b22789a8e93234f3ebb97f7030c569320dcb7474faffa9fe
7
+ data.tar.gz: 684cc95377949741e0d8d9e642caa77288cac2bfc673d8954e123afa237d7437209578479132ea926c9ed17292ae36bb03518725c861bab90f2b0811ac8bd1bc
data/.travis.yml CHANGED
@@ -2,4 +2,5 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
+ - 2.1.2
5
6
  - ruby-head
data/README.md CHANGED
@@ -3,7 +3,9 @@
3
3
  [![Code Climate](https://codeclimate.com/github/Shinpeim/ruby_php_session.png)](https://codeclimate.com/github/Shinpeim/ruby_php_session)
4
4
 
5
5
  ## Description
6
- PHPSession is a php session file reader/writer. Multibyte string and exclusive control are supported.
6
+ PHPSession is a php session reader/writer.
7
+
8
+ ### Mapping between ruby and PHP
7
9
 
8
10
  When decoding php session data to ruby objects,
9
11
 
@@ -17,6 +19,56 @@ When encoding ruby objects to php session data,
17
19
  * Arrays in ruby is mapped to a associative arrays which's keys are integer in PHP.
18
20
  * Hashes in ruby is mapped to a associative arrays which's keys are string in PHP.
19
21
 
22
+ ### Session store engines are pluggable
23
+
24
+ By default, PHPSession use file session store, which is compatible with PHP session file.
25
+
26
+ You can use your own session store like bellow.
27
+
28
+ First, develop your own store_engine.
29
+
30
+ ```ruby
31
+ # lib_path/php_session/store_engine/custom.rb
32
+ class PHPSession
33
+ module StoreEngine
34
+ class File
35
+ def initialize(option)
36
+ # option passed to PHPSession constractor
37
+ @option = option
38
+ end
39
+
40
+ def load(session_id)
41
+ # load php-style serialized session data from your favorite storage
42
+ # and return that
43
+ end
44
+
45
+ def save(session_id, serialized_session)
46
+ # save php-style serialized session data to your favorite storage
47
+ end
48
+
49
+ def destroy(session_id)
50
+ # delete session_data from your favorite storage
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ # register store engine name and store engine class
57
+ PHPSession.register_store_engine(:custom, PHPSession::StoreEngine::Custom)
58
+ ```
59
+
60
+ And then, assingn engine name to option[:store_engine] passed to PHPSession constractor
61
+
62
+ ```ruby
63
+ option = {
64
+ :external_encoding => "EUC-JP",
65
+ :internal_encoding => "UTF-8",
66
+ :encoding_option => {:undef => :replace},
67
+ :session_file_dir => @session_file[:dir_name],
68
+ }
69
+ session = PHPSession.new(option)
70
+ ```
71
+
20
72
  ### Multibyte support
21
73
 
22
74
  Passing option to PHPSession.new, you can handle encodings.
@@ -61,28 +113,35 @@ Or install it yourself as:
61
113
  $ gem install php_session
62
114
 
63
115
  ## Usage
64
- # initialize
65
- option = {
66
- :internal_encoding => "UTF-8", # value will be decoded as UTF-8
67
- :external_encoding => "EUC-JP", # encoding of sesion file is EUC-JP
68
- :encoding_option => {:undef => :replace} # passed to String#encode
69
- }
70
- # option's default values are
71
- # :internal_encoding => Encoding.default_internal_encoding
72
- # :external_encoding => Encoding.default_external_encoding
73
- # :encoding_option => {}
74
- session = PHPSession.new(session_file_dir, option)
75
-
76
- # load session data from file with lock
77
- data = session.load(session_id)
78
-
79
- data.is_a? Hash # => true
80
-
81
- # save session to a file with lock
82
- session.commit(session_id, data)
83
-
84
- # delete session
85
- session.destroy(session_id)
116
+ ```ruby
117
+ # initialize
118
+ option = {
119
+ :internal_encoding => "UTF-8", # value will be decoded as UTF-8
120
+ :external_encoding => "EUC-JP", # encoding of sesion file is EUC-JP
121
+ :encoding_option => {:undef => :replace} # passed to String#encode
122
+
123
+ :store_engine => :file,
124
+ :session_file_dir => "/path/to/session_file_dir" # needed when the store_engine is :file
125
+ }
126
+ # option's default values are
127
+ # :internal_encoding => Encoding.default_internal_encoding
128
+ # :external_encoding => Encoding.default_external_encoding
129
+ # :encoding_option => {}
130
+ # :store_engine => :file,
131
+
132
+ session = PHPSession.new(option)
133
+
134
+ # load session data
135
+ data = session.load(session_id)
136
+
137
+ data.is_a? Hash # => true
138
+
139
+ # save session
140
+ session.commit(session_id, data)
141
+
142
+ # delete session
143
+ session.destroy(session_id)
144
+ ```
86
145
 
87
146
  ## Contributing
88
147
 
data/lib/php_session.rb CHANGED
@@ -3,59 +3,51 @@ require "php_session/version"
3
3
  require "php_session/errors"
4
4
  require "php_session/decoder"
5
5
  require "php_session/encoder"
6
+ require "php_session/store_engine/file"
6
7
 
7
8
  class PHPSession
8
9
  attr_reader :data
9
- def initialize(session_dir, option = {})
10
+
11
+ def self.register_store_engine(engine_name, klass)
12
+ @engines ||= {}
13
+ @engines[engine_name] = klass
14
+ end
15
+
16
+ def self.store_engine_class_of(engine_name)
17
+ store_engine = @engines[engine_name]
18
+ raise PHPSession::Errors, "unknown sotre engine: #{engine_name}" unless store_engine
19
+
20
+ store_engine
21
+ end
22
+
23
+ def initialize(option = {})
10
24
  default_option = {
25
+ :store_engine => :file,
26
+
11
27
  :internal_encoding => Encoding.default_internal,
12
28
  :external_encoding => Encoding.default_external,
13
29
  :encoding_option => {},
14
30
  }
15
31
  @option = default_option.merge(option)
16
- @session_dir = File.expand_path(session_dir)
32
+
33
+ store_engine_class = self.class.store_engine_class_of(@option[:store_engine])
34
+
35
+ @store_engine = store_engine_class.new(@option)
17
36
  end
18
37
 
19
38
  def load(session_id)
20
- with_lock(file_path(session_id)) do |f|
21
- # set internal_encoding to nil to avoid encoding conversion
22
- f.set_encoding(@option[:external_encoding], nil)
23
- Decoder.decode(f.read, @option[:internal_encoding], @option[:encoding_option]) || {}
24
- end
39
+ serialized_session = @store_engine.load(session_id)
40
+ Decoder.decode(serialized_session, @option[:internal_encoding], @option[:encoding_option]) || {}
25
41
  end
26
42
 
27
43
  def destroy(session_id)
28
- File.delete(file_path(session_id))
29
- rescue Errno::ENOENT => e
30
- # file already deleted
44
+ @store_engine.destroy(session_id)
31
45
  end
32
46
 
33
47
  def save(session_id, data)
34
- with_lock(file_path(session_id)) do |f|
35
- f.truncate(0)
36
- f.write(Encoder.encode(data, @option[:external_encoding], @option[:encoding_option]))
37
- end
38
- end
39
-
40
- private
41
-
42
- def with_lock(file_path)
43
- File.open(file_path, File::CREAT|File::RDWR) do |f|
44
- unless f.flock(File::LOCK_EX)
45
- raise PHPSession::Errors, "can't obtain lock of session file"
46
- end
47
- yield(f)
48
- end
49
- end
50
-
51
- def set_session_id(session_id)
52
- @session_id = session_id
53
- raise Errors::SecurityError, "directory traversal detected" unless file_path.index(@session_dir) == 0
54
- end
55
-
56
- def file_path(session_id)
57
- path = File.expand_path(File.join(@session_dir, "sess_#{session_id}"))
58
- raise Errors::SecurityError, "directory traversal detected" unless path.index(@session_dir) == 0
59
- path
48
+ serialized_session = Encoder.encode(data, @option[:external_encoding], @option[:encoding_option])
49
+ @store_engine.save(session_id, serialized_session)
60
50
  end
61
51
  end
52
+
53
+ PHPSession.register_store_engine(:file, PHPSession::StoreEngine::File)
@@ -1,4 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  class PHPSession::Errors < StandardError; end
3
- class PHPSession::Errors::ParseError < StandardError; end
4
- class PHPSession::Errors::EncodeError < StandardError; end
3
+ class PHPSession::Errors::ParameterError < StandardError; end
4
+ class PHPSession::Errors::ParseError < PHPSession::Errors; end
5
+ class PHPSession::Errors::EncodeError < PHPSession::Errors; end
@@ -0,0 +1,55 @@
1
+ # -*- coding: utf-8 -*-
2
+ class PHPSession
3
+ module StoreEngine
4
+ class File
5
+ def initialize(option)
6
+ if ! option[:session_file_dir]
7
+ raise PHPSession::Errors::ParameterError , "option[:session_dir] is required"
8
+ end
9
+
10
+ @option = option
11
+ end
12
+
13
+ def load(session_id)
14
+ serialized_session = with_lock(file_path(session_id)) do |f|
15
+ # set internal_encoding to nil to avoid encoding conversion
16
+ f.set_encoding(@option[:external_encoding], nil)
17
+ f.read
18
+ end
19
+
20
+ serialized_session
21
+ end
22
+
23
+ def save(session_id, serialized_session)
24
+ with_lock(file_path(session_id)) do |f|
25
+ f.truncate(0)
26
+ f.write(serialized_session)
27
+ end
28
+ end
29
+
30
+ def destroy(session_id)
31
+ ::File.delete(file_path(session_id))
32
+ rescue Errno::ENOENT
33
+ # file already deleted
34
+ end
35
+
36
+ private
37
+
38
+ def with_lock(file_path)
39
+ mode = ::File::CREAT|::File::RDWR
40
+ ::File.open(file_path, mode) do |f|
41
+ unless f.flock(::File::LOCK_EX)
42
+ raise PHPSession::Errors, "can't obtain lock of session file"
43
+ end
44
+ yield(f)
45
+ end
46
+ end
47
+
48
+ def file_path(session_id)
49
+ path = ::File.expand_path(::File.join(@option[:session_file_dir], "sess_#{session_id}"))
50
+ raise Errors::SecurityError, "directory traversal detected" unless path.index(@option[:session_file_dir]) == 0
51
+ path
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,4 +1,4 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  class PHPSession
3
- VERSION = "0.3.1"
3
+ VERSION = "0.4.0"
4
4
  end
data/php_session.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Shinpei Maruyama"]
10
10
  spec.email = ["shinpeim@gmail.com"]
11
11
  spec.description = %q{php session reader/writer}
12
- spec.summary = %q{php_session is a php session file reader/writer. Multibyte string and exclusive control is supported}
12
+ spec.summary = %q{php_session is a php session file reader/writer. Multibyte string control is supported}
13
13
  spec.homepage = "https://github.com/Shinpeim/ruby_php_session"
14
14
  spec.license = "MIT"
15
15
 
@@ -12,8 +12,9 @@ describe PHPSession do
12
12
  option = {
13
13
  :internal_encoding => nil,
14
14
  :external_encoding => "UTF-8",
15
+ :session_file_dir => @session_file[:dir_name],
15
16
  }
16
- session = PHPSession.new(@session_file[:dir_name], option)
17
+ session = PHPSession.new(option)
17
18
  data = session.load(@session_file[:session_id])
18
19
  expect(data).to eq({"key" => "テスト🍺"})
19
20
  end
@@ -22,8 +23,9 @@ describe PHPSession do
22
23
  option = {
23
24
  :internal_encoding => "UTF-8",
24
25
  :external_encoding => "UTF-8",
26
+ :session_file_dir => @session_file[:dir_name],
25
27
  }
26
- session = PHPSession.new(@session_file[:dir_name], option)
28
+ session = PHPSession.new(option)
27
29
  data = session.load(@session_file[:session_id])
28
30
  expect(data).to eq({"key" => "テスト🍺"})
29
31
  end
@@ -32,9 +34,10 @@ describe PHPSession do
32
34
  option = {
33
35
  :internal_encoding => "EUC-JP",
34
36
  :external_encoding => "UTF-8",
35
- :encoding_option => {:undef => :replace}
37
+ :encoding_option => {:undef => :replace},
38
+ :session_file_dir => @session_file[:dir_name],
36
39
  }
37
- session = PHPSession.new(@session_file[:dir_name], option)
40
+ session = PHPSession.new(option)
38
41
  data = session.load(@session_file[:session_id])
39
42
  expect(data).to eq({"key" => "テスト🍺".encode("EUC-JP", {:undef => :replace})})
40
43
  end
@@ -50,7 +53,7 @@ describe PHPSession do
50
53
  end
51
54
 
52
55
  it "should return session data" do
53
- session = PHPSession.new(@session_file[:dir_name])
56
+ session = PHPSession.new(:session_file_dir => @session_file[:dir_name])
54
57
  data = session.load(@session_file[:session_id])
55
58
  expect(data).to eq({"key" => "a"})
56
59
  end
@@ -62,7 +65,7 @@ describe PHPSession do
62
65
 
63
66
  context "when session file dosen't exist" do
64
67
  it "should return new session data" do
65
- session = PHPSession.new(Dir.tmpdir)
68
+ session = PHPSession.new(:session_file_dir => Dir.tmpdir)
66
69
  data = session.load("session_id")
67
70
  expect(data).to eq({})
68
71
  end
@@ -78,9 +81,10 @@ describe PHPSession do
78
81
  option = {
79
82
  :external_encoding => "EUC-JP",
80
83
  :internal_encoding => "UTF-8",
81
- :encoding_option => {:undef => :replace}
84
+ :encoding_option => {:undef => :replace},
85
+ :session_file_dir => @session_file[:dir_name],
82
86
  }
83
- session = PHPSession.new(@session_file[:dir_name], option)
87
+ session = PHPSession.new(option)
84
88
  data = session.load(@session_file[:session_id])
85
89
  data["key"] = "テスト🍣"
86
90
  session.save(@session_file[:session_id], data)
@@ -102,7 +106,7 @@ describe PHPSession do
102
106
  end
103
107
 
104
108
  it "should delete session file" do
105
- session = PHPSession.new(@session_file[:dir_name])
109
+ session = PHPSession.new(:session_file_dir => @session_file[:dir_name])
106
110
  session.destroy(@session_file[:session_id])
107
111
  expect(File.exists?(@session_file[:file_path])).to eq(false)
108
112
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: php_session
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shinpei Maruyama
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-23 00:00:00.000000000 Z
11
+ date: 2014-08-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -70,6 +70,7 @@ files:
70
70
  - lib/php_session/decoder.rb
71
71
  - lib/php_session/encoder.rb
72
72
  - lib/php_session/errors.rb
73
+ - lib/php_session/store_engine/file.rb
73
74
  - lib/php_session/version.rb
74
75
  - php_session.gemspec
75
76
  - spec/php_session/decoder_spec.rb
@@ -99,8 +100,8 @@ rubyforge_project:
99
100
  rubygems_version: 2.2.2
100
101
  signing_key:
101
102
  specification_version: 4
102
- summary: php_session is a php session file reader/writer. Multibyte string and exclusive
103
- control is supported
103
+ summary: php_session is a php session file reader/writer. Multibyte string control
104
+ is supported
104
105
  test_files:
105
106
  - spec/php_session/decoder_spec.rb
106
107
  - spec/php_session/encoder_spec.rb