php-serialization 0.5.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  #
2
2
  # DO NOT MODIFY!!!!
3
- # This file is automatically generated by Racc 1.4.6
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', 69)
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
- 5, 6, 19, 20, 9, 11, 13, 21, 1, 5,
35
- 6, 4, 22, 9, 11, 13, 23, 1, 5, 6,
36
- 4, 24, 9, 11, 13, 25, 1, 26, 46, 4,
37
- 5, 6, 27, 28, 9, 11, 13, 29, 1, 30,
38
- 52, 4, 18, 32, 33, 34, 35, 36, 37, 38,
39
- 39, 40, 41, 43, 45, 17, 49, 16, 31 ]
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, 7, 8, 0, 0, 0, 9, 0, 48,
43
- 48, 0, 10, 48, 48, 48, 11, 48, 44, 44,
44
- 48, 12, 44, 44, 44, 13, 44, 14, 44, 44,
45
- 51, 51, 15, 16, 51, 51, 51, 17, 51, 18,
46
- 51, 51, 6, 21, 23, 25, 28, 29, 34, 35,
47
- 36, 37, 38, 41, 43, 4, 45, 1, 19 ]
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, 52, nil, nil, 50, nil, 37, 2, 1, 2,
51
- 10, 11, 19, 20, 25, 30, 27, 31, 33, 58,
52
- nil, 37, nil, 38, nil, 39, nil, nil, 41, 42,
53
- nil, nil, nil, nil, 43, 39, 38, 41, 47, nil,
54
- nil, 47, nil, 49, 15, 44, nil, nil, 6, nil,
55
- nil, 27, nil ]
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
- -19, -19, -6, -7, -19, -8, -19, -19, -19, -19,
59
- -19, -19, -19, -19, -19, -19, -19, -19, -19, -19,
60
- -1, -19, -2, -19, -3, -19, -4, -5, -19, -19,
61
- -9, 53, -10, -11, -19, -19, -19, -19, -19, -17,
62
- -12, -19, -15, -19, -19, -19, -18, -14, -19, -15,
63
- -16, -19, -13 ]
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
- 7, 44, 42, nil, nil, nil, nil, nil, 51, nil,
67
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
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, nil, nil, nil, 50 ]
70
+ nil, nil, nil, nil, nil, 48 ]
71
71
 
72
72
  racc_goto_check = [
73
- 1, 9, 11, nil, nil, nil, nil, nil, 9, nil,
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, 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, -41,
81
- nil, -37 ]
80
+ nil, 0, nil, nil, nil, nil, nil, nil, nil, -39,
81
+ nil ]
82
82
 
83
83
  racc_goto_default = [
84
- nil, 48, 8, 10, 12, 14, 15, 2, 3, nil,
85
- 47, nil ]
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
- 0, 26, :_reduce_17,
106
- 8, 22, :_reduce_18 ]
105
+ 7, 22, :_reduce_17 ]
107
106
 
108
- racc_reduce_n = 19
107
+ racc_reduce_n = 18
109
108
 
110
- racc_shift_n = 53
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
- "array",
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
- result.instance_variable_set("@#{attr_name.gsub(/(^\*)|\0/, '')}", value)
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
- result = Struct.new(klass_name, *val[9].map { |(k,v)| k.gsub(/(^\*)|\0/, '').to_sym }).new(*val[9].map { |(k,v)| v })
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', 43)
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', 44)
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', 47)
308
+ module_eval(<<'.,.,', 'unserializer.y', 57)
301
309
  def _reduce_16(val, _values, result)
302
- @numeric_array = false unless val[0].is_a?(Integer); result = [val[0], val[1]]
310
+ result = val
303
311
  result
304
312
  end
305
313
  .,.,
306
314
 
307
- module_eval(<<'.,.,', 'unserializer.y', 50)
315
+ module_eval(<<'.,.,', 'unserializer.y', 62)
308
316
  def _reduce_17(val, _values, result)
309
- @numeric_array = true
310
- result
311
- end
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
- module_eval(<<'.,.,', 'unserializer.y', 52)
315
- def _reduce_18(val, _values, result)
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
- | array { @object = val[0] }
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
- result.instance_variable_set("@#{attr_name.gsub(/(^\*)|\0/, '')}", value)
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
- result = Struct.new(klass_name, *val[9].map { |(k,v)| k.gsub(/(^\*)|\0/, '').to_sym }).new(*val[9].map { |(k,v)| v })
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
- | { result = [] }
55
+ | { result = [] }
46
56
  ;
47
57
 
48
- attribute : data data { @numeric_array = false unless val[0].is_a?(Integer); result = [val[0], val[1]] }
58
+ attribute : data data { result = val }
49
59
  ;
50
-
51
- array : 'a' ':' NUMBER ':' '{' { @numeric_array = true } attribute_list '}'
52
- {
53
- if @numeric_array
54
- result = []
55
- val[6].each { |(i,v)| result[i] = v }
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,3 @@
1
+ module PhpSerialization
2
+ VERSION = "1.0.0"
3
+ 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