php-serialization 0.5.3 → 1.0.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 +7 -0
- data/.gitignore +14 -5
- data/.travis.yml +12 -0
- data/Gemfile +4 -0
- data/{LICENSE → LICENSE.txt} +3 -1
- data/README.md +31 -0
- data/Rakefile +5 -67
- data/bin/racc +16 -0
- data/bin/racc2y +16 -0
- data/bin/rake +16 -0
- data/bin/rspec +16 -0
- data/bin/y2racc +16 -0
- data/lib/php_serialization/serializer.rb +7 -7
- data/lib/php_serialization/tokenizer.rb +5 -5
- data/lib/php_serialization/unserializer.output +503 -0
- data/lib/php_serialization/unserializer.rb +67 -64
- data/lib/php_serialization/unserializer.y +39 -27
- data/lib/php_serialization/version.rb +3 -0
- data/ruby-php-serialization.gemspec +26 -0
- data/spec/functional/session_serialization_spec.rb +23 -0
- data/spec/unit/serializer_spec.rb +49 -0
- data/spec/unit/unserializer_spec.rb +67 -0
- metadata +100 -81
- data/.document +0 -5
- data/README.rdoc +0 -72
- data/VERSION +0 -1
- data/features/ruby_php_serialization.feature +0 -9
- data/features/step_definitions/ruby_php_serialization_steps.rb +0 -0
- data/features/support/env.rb +0 -4
- data/php-serialization.gemspec +0 -72
- data/spec/serialization_spec.rb +0 -49
- data/spec/session_serialization_spec.rb +0 -21
- data/spec/spec.opts +0 -3
- data/spec/spec_helper.rb +0 -9
- data/spec/unserialization_spec.rb +0 -51
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# DO NOT MODIFY!!!!
|
3
|
-
# This file is automatically generated by Racc 1.4.
|
3
|
+
# This file is automatically generated by Racc 1.4.12
|
4
4
|
# from Racc grammer file "".
|
5
5
|
#
|
6
6
|
|
@@ -11,11 +11,11 @@ require 'php_serialization/tokenizer'
|
|
11
11
|
module PhpSerialization
|
12
12
|
class Unserializer < Racc::Parser
|
13
13
|
|
14
|
-
module_eval(<<'...end unserializer.y/module_eval...', 'unserializer.y',
|
14
|
+
module_eval(<<'...end unserializer.y/module_eval...', 'unserializer.y', 81)
|
15
15
|
def initialize(tokenizer_klass = Tokenizer)
|
16
16
|
@tokenizer_klass = tokenizer_klass
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def run(string)
|
20
20
|
@tokenizer = @tokenizer_klass.new(string)
|
21
21
|
yyparse(@tokenizer, :each)
|
@@ -23,7 +23,7 @@ module_eval(<<'...end unserializer.y/module_eval...', 'unserializer.y', 69)
|
|
23
23
|
ensure
|
24
24
|
@tokenizer = nil
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
def next_token
|
28
28
|
@tokenizer.next_token
|
29
29
|
end
|
@@ -31,58 +31,58 @@ module_eval(<<'...end unserializer.y/module_eval...', 'unserializer.y', 69)
|
|
31
31
|
##### State transition tables begin ###
|
32
32
|
|
33
33
|
racc_action_table = [
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
39, 40, 41, 43,
|
34
|
+
9, 10, 19, 20, 11, 12, 13, 21, 14, 9,
|
35
|
+
10, 15, 22, 11, 12, 13, 23, 14, 9, 10,
|
36
|
+
15, 24, 11, 12, 13, 25, 14, 26, 46, 15,
|
37
|
+
9, 10, 27, 28, 11, 12, 13, 29, 14, 30,
|
38
|
+
51, 15, 18, 32, 33, 34, 35, 36, 37, 38,
|
39
|
+
39, 40, 41, 43, 17, 47, 16, 49, 31 ]
|
40
40
|
|
41
41
|
racc_action_check = [
|
42
|
-
0, 0,
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
36, 37,
|
42
|
+
0, 0, 4, 5, 0, 0, 0, 6, 0, 45,
|
43
|
+
45, 0, 10, 45, 45, 45, 11, 45, 42, 42,
|
44
|
+
45, 12, 42, 42, 42, 13, 42, 14, 42, 42,
|
45
|
+
50, 50, 15, 16, 50, 50, 50, 22, 50, 23,
|
46
|
+
50, 50, 3, 25, 26, 27, 32, 33, 34, 35,
|
47
|
+
36, 37, 39, 41, 2, 43, 1, 47, 24 ]
|
48
48
|
|
49
49
|
racc_action_pointer = [
|
50
|
-
-3,
|
51
|
-
|
52
|
-
nil,
|
53
|
-
nil, nil,
|
54
|
-
nil, 47,
|
55
|
-
|
50
|
+
-3, 56, 52, 40, 0, 1, 5, nil, nil, nil,
|
51
|
+
7, 11, 16, 20, 22, 27, 33, nil, nil, nil,
|
52
|
+
nil, nil, 31, 33, 52, 37, 38, 39, nil, nil,
|
53
|
+
nil, nil, 41, 42, 43, 39, 40, 39, nil, 47,
|
54
|
+
nil, 47, 15, 50, nil, 6, nil, 45, nil, nil,
|
55
|
+
27, nil ]
|
56
56
|
|
57
57
|
racc_action_default = [
|
58
|
-
-
|
59
|
-
-
|
60
|
-
-
|
61
|
-
|
62
|
-
-
|
63
|
-
-
|
58
|
+
-18, -18, -18, -18, -18, -18, -18, -6, -7, -8,
|
59
|
+
-18, -18, -18, -18, -18, -18, -18, -1, -2, -3,
|
60
|
+
-4, -5, -18, -18, -18, -18, -18, -18, 52, -9,
|
61
|
+
-10, -11, -18, -18, -18, -18, -18, -18, -12, -18,
|
62
|
+
-15, -18, -18, -18, -14, -18, -17, -18, -16, -15,
|
63
|
+
-18, -13 ]
|
64
64
|
|
65
65
|
racc_goto_table = [
|
66
|
-
|
67
|
-
|
66
|
+
1, 42, nil, nil, nil, nil, nil, nil, nil, nil,
|
67
|
+
50, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
68
68
|
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
69
69
|
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
70
|
-
nil, nil, nil, nil, nil,
|
70
|
+
nil, nil, nil, nil, nil, 48 ]
|
71
71
|
|
72
72
|
racc_goto_check = [
|
73
|
-
1, 9,
|
73
|
+
1, 9, nil, nil, nil, nil, nil, nil, nil, nil,
|
74
|
+
9, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
74
75
|
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
75
76
|
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
|
76
|
-
nil, nil, nil, nil, nil,
|
77
|
-
nil, nil, nil, nil, nil, nil, nil, nil, 1 ]
|
77
|
+
nil, nil, nil, nil, nil, 1 ]
|
78
78
|
|
79
79
|
racc_goto_pointer = [
|
80
|
-
nil, 0, nil, nil, nil, nil, nil, nil, nil, -
|
81
|
-
nil
|
80
|
+
nil, 0, nil, nil, nil, nil, nil, nil, nil, -39,
|
81
|
+
nil ]
|
82
82
|
|
83
83
|
racc_goto_default = [
|
84
|
-
nil,
|
85
|
-
|
84
|
+
nil, 45, 2, 3, 4, 5, 6, 7, 8, nil,
|
85
|
+
44 ]
|
86
86
|
|
87
87
|
racc_reduce_table = [
|
88
88
|
0, 0, :racc_error,
|
@@ -102,12 +102,11 @@ racc_reduce_table = [
|
|
102
102
|
2, 24, :_reduce_14,
|
103
103
|
0, 24, :_reduce_15,
|
104
104
|
2, 25, :_reduce_16,
|
105
|
-
|
106
|
-
8, 22, :_reduce_18 ]
|
105
|
+
7, 22, :_reduce_17 ]
|
107
106
|
|
108
|
-
racc_reduce_n =
|
107
|
+
racc_reduce_n = 18
|
109
108
|
|
110
|
-
racc_shift_n =
|
109
|
+
racc_shift_n = 52
|
111
110
|
|
112
111
|
racc_token_table = {
|
113
112
|
false => 0,
|
@@ -169,11 +168,10 @@ Racc_token_to_s_table = [
|
|
169
168
|
"integer",
|
170
169
|
"double",
|
171
170
|
"string",
|
172
|
-
"
|
171
|
+
"assoc_array",
|
173
172
|
"object",
|
174
173
|
"attribute_list",
|
175
|
-
"attribute"
|
176
|
-
"@1" ]
|
174
|
+
"attribute" ]
|
177
175
|
|
178
176
|
Racc_debug_parser = false
|
179
177
|
|
@@ -269,13 +267,23 @@ module_eval(<<'.,.,', 'unserializer.y', 29)
|
|
269
267
|
def _reduce_13(val, _values, result)
|
270
268
|
if eval("defined?(#{val[4]})")
|
271
269
|
result = Object.const_get(val[4]).new
|
272
|
-
|
270
|
+
|
273
271
|
val[9].each do |(attr_name, value)|
|
274
|
-
|
272
|
+
# Protected and private attributes will have a \0..\0 prefix
|
273
|
+
attr_name = attr_name.gsub(/\A\\0[^\\]+\\0/, '')
|
274
|
+
result.instance_variable_set("@#{attr_name}", value)
|
275
275
|
end
|
276
276
|
else
|
277
277
|
klass_name = val[4].gsub(/^Struct::/, '')
|
278
|
-
|
278
|
+
attr_names, values = [], []
|
279
|
+
|
280
|
+
val[9].each do |(attr_name, value)|
|
281
|
+
# Protected and private attributes will have a \0..\0 prefix
|
282
|
+
attr_names << attr_name.gsub(/\A\\0[^\\]+\\0/, '')
|
283
|
+
values << value
|
284
|
+
end
|
285
|
+
|
286
|
+
result = Struct.new(klass_name, *attr_names).new(*values)
|
279
287
|
result.instance_variable_set("@_php_class", klass_name)
|
280
288
|
end
|
281
289
|
|
@@ -283,42 +291,37 @@ module_eval(<<'.,.,', 'unserializer.y', 29)
|
|
283
291
|
end
|
284
292
|
.,.,
|
285
293
|
|
286
|
-
module_eval(<<'.,.,', 'unserializer.y',
|
294
|
+
module_eval(<<'.,.,', 'unserializer.y', 53)
|
287
295
|
def _reduce_14(val, _values, result)
|
288
296
|
result = val[0] << val[1]
|
289
297
|
result
|
290
298
|
end
|
291
299
|
.,.,
|
292
300
|
|
293
|
-
module_eval(<<'.,.,', 'unserializer.y',
|
301
|
+
module_eval(<<'.,.,', 'unserializer.y', 54)
|
294
302
|
def _reduce_15(val, _values, result)
|
295
303
|
result = []
|
296
304
|
result
|
297
305
|
end
|
298
306
|
.,.,
|
299
307
|
|
300
|
-
module_eval(<<'.,.,', 'unserializer.y',
|
308
|
+
module_eval(<<'.,.,', 'unserializer.y', 57)
|
301
309
|
def _reduce_16(val, _values, result)
|
302
|
-
|
310
|
+
result = val
|
303
311
|
result
|
304
312
|
end
|
305
313
|
.,.,
|
306
314
|
|
307
|
-
module_eval(<<'.,.,', 'unserializer.y',
|
315
|
+
module_eval(<<'.,.,', 'unserializer.y', 62)
|
308
316
|
def _reduce_17(val, _values, result)
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
.,.,
|
317
|
+
# Checks if the keys are a sequence of integers
|
318
|
+
idx = -1
|
319
|
+
arr = val[5].all? { |(k,v)| k == (idx += 1) }
|
313
320
|
|
314
|
-
|
315
|
-
|
316
|
-
if @numeric_array
|
317
|
-
result = []
|
318
|
-
val[6].each { |(i,v)| result[i] = v }
|
321
|
+
if arr
|
322
|
+
result = val[5].map { |(k,v)| v }
|
319
323
|
else
|
320
|
-
result =
|
321
|
-
val[6].each { |(k, v)| result[k] = v}
|
324
|
+
result = Hash[val[5]]
|
322
325
|
end
|
323
326
|
|
324
327
|
result
|
@@ -6,70 +6,82 @@ rule
|
|
6
6
|
| integer ';' { @object = val[0] }
|
7
7
|
| double ';' { @object = val[0] }
|
8
8
|
| string ';' { @object = val[0] }
|
9
|
-
|
|
9
|
+
| assoc_array { @object = val[0] }
|
10
10
|
| object { @object = val[0] }
|
11
|
-
;
|
12
|
-
|
11
|
+
;
|
12
|
+
|
13
13
|
null : 'N' { result = nil }
|
14
14
|
;
|
15
|
-
|
15
|
+
|
16
16
|
bool : 'b' ':' NUMBER { result = Integer(val[2]) > 0 }
|
17
17
|
;
|
18
|
-
|
18
|
+
|
19
19
|
integer : 'i' ':' NUMBER { result = Integer(val[2]) }
|
20
20
|
;
|
21
|
-
|
21
|
+
|
22
22
|
double : 'd' ':' NUMBER { result = Float(val[2]) }
|
23
23
|
;
|
24
|
-
|
24
|
+
|
25
25
|
string : 's' ':' NUMBER ':' STRING { result = val[4] }
|
26
26
|
;
|
27
|
-
|
28
|
-
object : 'O' ':' NUMBER ':' STRING ':' NUMBER ':' '{' attribute_list '}'
|
29
|
-
{
|
27
|
+
|
28
|
+
object : 'O' ':' NUMBER ':' STRING ':' NUMBER ':' '{' attribute_list '}'
|
29
|
+
{
|
30
30
|
if eval("defined?(#{val[4]})")
|
31
31
|
result = Object.const_get(val[4]).new
|
32
|
-
|
32
|
+
|
33
33
|
val[9].each do |(attr_name, value)|
|
34
|
-
|
34
|
+
# Protected and private attributes will have a \0..\0 prefix
|
35
|
+
attr_name = attr_name.gsub(/\A\\0[^\\]+\\0/, '')
|
36
|
+
result.instance_variable_set("@#{attr_name}", value)
|
35
37
|
end
|
36
38
|
else
|
37
39
|
klass_name = val[4].gsub(/^Struct::/, '')
|
38
|
-
|
40
|
+
attr_names, values = [], []
|
41
|
+
|
42
|
+
val[9].each do |(attr_name, value)|
|
43
|
+
# Protected and private attributes will have a \0..\0 prefix
|
44
|
+
attr_names << attr_name.gsub(/\A\\0[^\\]+\\0/, '')
|
45
|
+
values << value
|
46
|
+
end
|
47
|
+
|
48
|
+
result = Struct.new(klass_name, *attr_names).new(*values)
|
39
49
|
result.instance_variable_set("@_php_class", klass_name)
|
40
50
|
end
|
41
51
|
}
|
42
52
|
;
|
43
53
|
|
44
54
|
attribute_list : attribute_list attribute { result = val[0] << val[1] }
|
45
|
-
|
|
55
|
+
| { result = [] }
|
46
56
|
;
|
47
57
|
|
48
|
-
attribute : data data {
|
58
|
+
attribute : data data { result = val }
|
49
59
|
;
|
50
|
-
|
51
|
-
|
52
|
-
{
|
53
|
-
if
|
54
|
-
|
55
|
-
|
60
|
+
|
61
|
+
assoc_array : 'a' ':' NUMBER ':' '{' attribute_list '}'
|
62
|
+
{
|
63
|
+
# Checks if the keys are a sequence of integers
|
64
|
+
idx = -1
|
65
|
+
arr = val[5].all? { |(k,v)| k == (idx += 1) }
|
66
|
+
|
67
|
+
if arr
|
68
|
+
result = val[5].map { |(k,v)| v }
|
56
69
|
else
|
57
|
-
result =
|
58
|
-
val[6].each { |(k, v)| result[k] = v}
|
70
|
+
result = Hash[val[5]]
|
59
71
|
end
|
60
72
|
}
|
61
73
|
;
|
62
|
-
|
74
|
+
|
63
75
|
end
|
64
76
|
|
65
77
|
---- header ----
|
66
78
|
require 'php_serialization/tokenizer'
|
67
79
|
|
68
|
-
---- inner ----
|
80
|
+
---- inner ----
|
69
81
|
def initialize(tokenizer_klass = Tokenizer)
|
70
82
|
@tokenizer_klass = tokenizer_klass
|
71
83
|
end
|
72
|
-
|
84
|
+
|
73
85
|
def run(string)
|
74
86
|
@tokenizer = @tokenizer_klass.new(string)
|
75
87
|
yyparse(@tokenizer, :each)
|
@@ -77,7 +89,7 @@ require 'php_serialization/tokenizer'
|
|
77
89
|
ensure
|
78
90
|
@tokenizer = nil
|
79
91
|
end
|
80
|
-
|
92
|
+
|
81
93
|
def next_token
|
82
94
|
@tokenizer.next_token
|
83
95
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'php_serialization/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "php-serialization"
|
8
|
+
spec.version = PhpSerialization::VERSION
|
9
|
+
spec.authors = ["Rodrigo Kochenburger"]
|
10
|
+
spec.email = ["divoxx@gmail.com"]
|
11
|
+
spec.summary = %q{Pure Ruby implementation of php's methods: serialize() and unserializer()}
|
12
|
+
spec.description = %q{Pure Ruby implementation of php's methods: serialize() and unserializer()}
|
13
|
+
spec.homepage = "https://github.com/divoxx/ruby-php-serialization"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_development_dependency "rspec", "~> 3.0.0"
|
24
|
+
|
25
|
+
spec.add_dependency "racc"
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "php_serialization"
|
2
|
+
|
3
|
+
RSpec.describe "Session serialization" do
|
4
|
+
it "should store session correctly" do
|
5
|
+
data = PhpSessionSerialization.load("userId|i:123;store|s:3:\"foo\";someArr|a:2:{i:0;b:1;i:1;s:3:\"foo\";}")
|
6
|
+
expect(data).to eq(
|
7
|
+
"userId" => 123,
|
8
|
+
"store" => "foo",
|
9
|
+
"someArr" => [true, "foo"]
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should dump a hash as session" do
|
14
|
+
session_hash = {
|
15
|
+
"userId" => 123,
|
16
|
+
"store" => "foo",
|
17
|
+
"someArr" => [true, "foo"]
|
18
|
+
}
|
19
|
+
|
20
|
+
data = PhpSessionSerialization.load(PhpSessionSerialization.dump(session_hash))
|
21
|
+
expect(data).to eq(session_hash)
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "php_serialization/serializer"
|
2
|
+
|
3
|
+
RSpec.describe PhpSerialization::Serializer do
|
4
|
+
it "should serialize a integer" do
|
5
|
+
expect(subject.run(10)).to eq("i:10;")
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should serialize a string" do
|
9
|
+
expect(subject.run("Name")).to eq('s:4:"Name";')
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should serialize a symbol string" do
|
13
|
+
expect(subject.run(:name)).to eq('s:4:"name";')
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should serialize true" do
|
17
|
+
expect(subject.run(true)).to eq('b:1;')
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should serialize false" do
|
21
|
+
expect(subject.run(false)).to eq('b:0;')
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should serialize nil" do
|
25
|
+
expect(subject.run(nil)).to eq('N;')
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should unzerialize an array" do
|
29
|
+
expect(subject.run([true, "foo"])).to eq('a:2:{i:0;b:1;i:1;s:3:"foo";}')
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should serialize a hash" do
|
33
|
+
expect(subject.run("name" => "Rodrigo", "age" => 23)).to eq('a:2:{s:4:"name";s:7:"Rodrigo";s:3:"age";i:23;}')
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should serialize object with class existant" do
|
37
|
+
class Person
|
38
|
+
attr_accessor :name, :age
|
39
|
+
end
|
40
|
+
|
41
|
+
person = Person.new
|
42
|
+
person.name = "Rodrigo"
|
43
|
+
person.age = 23
|
44
|
+
|
45
|
+
expect(subject.run(person)).to eq("O:6:\"Person\":2:{s:3:\"age\";i:23;s:4:\"name\";s:7:\"Rodrigo\";}")
|
46
|
+
|
47
|
+
Object.send(:remove_const, :Person)
|
48
|
+
end
|
49
|
+
end
|