php-serialize4ruby 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +14 -0
- data/LICENSE.txt +20 -0
- data/README +34 -0
- data/README.rdoc +19 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/lib/php-serialize4ruby.rb +314 -0
- data/lib/php_serialize.rb +314 -0
- data/php-serialize.gemspec +19 -0
- data/php-serialize4ruby.gemspec +67 -0
- data/spec/php-serialize4ruby_spec.rb +9 -0
- data/spec/spec_helper.rb +12 -0
- data/test.rb +119 -0
- metadata +129 -0
data/.document
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
# Add dependencies to develop your gem here.
|
7
|
+
# Include everything needed to run rake, tests, features, etc.
|
8
|
+
group :development do
|
9
|
+
gem "rspec", "~> 2.8.0"
|
10
|
+
gem "rdoc", "~> 3.12"
|
11
|
+
gem "bundler", ">= 1.0.0"
|
12
|
+
gem "jeweler", "~> 1.8.3"
|
13
|
+
gem "simplecov"
|
14
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Kasper Johansen
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
Ruby PHP Serializer
|
2
|
+
===================
|
3
|
+
|
4
|
+
This module provides two methods: PHP.serialize() and PHP.unserialize(), both
|
5
|
+
of which should be compatible with the similarly named functions in PHP.
|
6
|
+
|
7
|
+
Basic usage:
|
8
|
+
|
9
|
+
require 'php_serialize'
|
10
|
+
in = {'foo' => 'bar'}
|
11
|
+
php = PHP.serialize(in)
|
12
|
+
# pass string to PHP unserialize() to get array('foo' => 'bar')
|
13
|
+
out = PHP.unserialize(php) # => {'foo' => 'bar'}
|
14
|
+
|
15
|
+
|
16
|
+
PHP.unserialize can also read PHP sessions, which are collections of named
|
17
|
+
serialized objects. These can be reserialized using PHP.serialize_session(),
|
18
|
+
which has the same semantics as PHP.serialize(), but which only supports
|
19
|
+
Hash and associative Arrays for the root object.
|
20
|
+
|
21
|
+
|
22
|
+
Acknowledgements
|
23
|
+
================
|
24
|
+
|
25
|
+
TJ Vanderpoel, initial PHP serialized session support.
|
26
|
+
|
27
|
+
Philip Hallstrom, fix for self-generated Structs on unserialization.
|
28
|
+
|
29
|
+
Edward Speyer, fix for assoc serialization in nested structures.
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
Author: Thomas Hurst <tom@hur.st>, http://hur.st/
|
34
|
+
WWW: http://www.aagh.net/projects/ruby-php-serialize
|
data/README.rdoc
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
= php-serialize4ruby
|
2
|
+
|
3
|
+
Description goes here.
|
4
|
+
|
5
|
+
== Contributing to php-serialize4ruby
|
6
|
+
|
7
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
8
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
9
|
+
* Fork the project.
|
10
|
+
* Start a feature/bugfix branch.
|
11
|
+
* Commit and push until you are happy with your contribution.
|
12
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
13
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
14
|
+
|
15
|
+
== Copyright
|
16
|
+
|
17
|
+
Copyright (c) 2012 Kasper Johansen. See LICENSE.txt for
|
18
|
+
further details.
|
19
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "php-serialize4ruby"
|
18
|
+
gem.homepage = "http://github.com/kaspernj/php-serialize4ruby"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{A fork of the original gem "php-serialize" because I have no hope of the original guy to update the gem}
|
21
|
+
gem.description = %Q{Read the original gems description.}
|
22
|
+
gem.email = "k@spernj.org"
|
23
|
+
gem.authors = ["Kasper Johansen"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rspec/core'
|
29
|
+
require 'rspec/core/rake_task'
|
30
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
31
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
32
|
+
end
|
33
|
+
|
34
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
35
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
36
|
+
spec.rcov = true
|
37
|
+
end
|
38
|
+
|
39
|
+
task :default => :spec
|
40
|
+
|
41
|
+
require 'rdoc/task'
|
42
|
+
Rake::RDocTask.new do |rdoc|
|
43
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
44
|
+
|
45
|
+
rdoc.rdoc_dir = 'rdoc'
|
46
|
+
rdoc.title = "php-serialize4ruby #{version}"
|
47
|
+
rdoc.rdoc_files.include('README*')
|
48
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
49
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
@@ -0,0 +1,314 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Copyright (c) 2003-2009 Thomas Hurst <tom@hur.st>
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
20
|
+
# SOFTWARE.
|
21
|
+
|
22
|
+
# PHP serialize() and unserialize() workalikes
|
23
|
+
#
|
24
|
+
# Release History:
|
25
|
+
# 1.0.0 - 2003-06-02 - First release.
|
26
|
+
# 1.0.1 - 2003-06-16 - Minor bugfixes.
|
27
|
+
# 1.0.2 - 2004-09-17 - Switch all {}'s to explicit Hash.new's.
|
28
|
+
# 1.1.0 - 2009-04-01 - Pass assoc to recursive calls (thanks to Edward Speyer).
|
29
|
+
# - Serialize Symbol like String.
|
30
|
+
# - Add testsuite.
|
31
|
+
# - Instantiate auto-generated Structs properly (thanks
|
32
|
+
# to Philip Hallstrom).
|
33
|
+
# - Unserialize arrays properly in assoc mode.
|
34
|
+
# - Add PHP session support (thanks to TJ Vanderpoel).
|
35
|
+
# - Release as tarball and gem.
|
36
|
+
#
|
37
|
+
# See http://www.php.net/serialize and http://www.php.net/unserialize for
|
38
|
+
# details on the PHP side of all this.
|
39
|
+
module PHP
|
40
|
+
# string = PHP.serialize(mixed var[, bool assoc])
|
41
|
+
#
|
42
|
+
# Returns a string representing the argument in a form PHP.unserialize
|
43
|
+
# and PHP's unserialize() should both be able to load.
|
44
|
+
#
|
45
|
+
# Array, Hash, Fixnum, Float, True/FalseClass, NilClass, String and Struct
|
46
|
+
# are supported; as are objects which support the to_assoc method, which
|
47
|
+
# returns an array of the form [['attr_name', 'value']..]. Anything else
|
48
|
+
# will raise a TypeError.
|
49
|
+
#
|
50
|
+
# If 'assoc' is specified, Array's who's first element is a two value
|
51
|
+
# array will be assumed to be an associative array, and will be serialized
|
52
|
+
# as a PHP associative array rather than a multidimensional array.
|
53
|
+
def PHP.serialize(var, assoc = false) # {{{
|
54
|
+
s = ''
|
55
|
+
case var
|
56
|
+
when Array
|
57
|
+
s << "a:#{var.size}:{"
|
58
|
+
if assoc and var.first.is_a?(Array) and var.first.size == 2
|
59
|
+
var.each { |k,v|
|
60
|
+
s << PHP.serialize(k, assoc) << PHP.serialize(v, assoc)
|
61
|
+
}
|
62
|
+
else
|
63
|
+
var.each_with_index { |v,i|
|
64
|
+
s << "i:#{i};#{PHP.serialize(v, assoc)}"
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
s << '}'
|
69
|
+
|
70
|
+
when Hash
|
71
|
+
s << "a:#{var.size}:{"
|
72
|
+
var.each do |k,v|
|
73
|
+
s << "#{PHP.serialize(k, assoc)}#{PHP.serialize(v, assoc)}"
|
74
|
+
end
|
75
|
+
s << '}'
|
76
|
+
|
77
|
+
when Struct
|
78
|
+
# encode as Object with same name
|
79
|
+
s << "O:#{var.class.to_s.length}:\"#{var.class.to_s.downcase}\":#{var.members.length}:{"
|
80
|
+
var.members.each do |member|
|
81
|
+
s << "#{PHP.serialize(member, assoc)}#{PHP.serialize(var[member], assoc)}"
|
82
|
+
end
|
83
|
+
s << '}'
|
84
|
+
|
85
|
+
when String, Symbol
|
86
|
+
s << "s:#{var.to_s.bytesize}:\"#{var.to_s}\";"
|
87
|
+
|
88
|
+
when Fixnum # PHP doesn't have bignums
|
89
|
+
s << "i:#{var};"
|
90
|
+
|
91
|
+
when Float
|
92
|
+
s << "d:#{var};"
|
93
|
+
|
94
|
+
when NilClass
|
95
|
+
s << 'N;'
|
96
|
+
|
97
|
+
when FalseClass, TrueClass
|
98
|
+
s << "b:#{var ? 1 :0};"
|
99
|
+
|
100
|
+
else
|
101
|
+
if var.respond_to?(:to_assoc)
|
102
|
+
v = var.to_assoc
|
103
|
+
# encode as Object with same name
|
104
|
+
s << "O:#{var.class.to_s.length}:\"#{var.class.to_s.downcase}\":#{v.length}:{"
|
105
|
+
v.each do |k,v|
|
106
|
+
s << "#{PHP.serialize(k.to_s, assoc)}#{PHP.serialize(v, assoc)}"
|
107
|
+
end
|
108
|
+
s << '}'
|
109
|
+
else
|
110
|
+
raise TypeError, "Unable to serialize type #{var.class}"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
s
|
115
|
+
end # }}}
|
116
|
+
|
117
|
+
# string = PHP.serialize_session(mixed var[, bool assoc])
|
118
|
+
#
|
119
|
+
# Like PHP.serialize, but only accepts a Hash or associative Array as the root
|
120
|
+
# type. The results are returned in PHP session format.
|
121
|
+
def PHP.serialize_session(var, assoc = false) # {{{
|
122
|
+
s = ''
|
123
|
+
case var
|
124
|
+
when Hash
|
125
|
+
var.each do |key,value|
|
126
|
+
if key.to_s =~ /\|/
|
127
|
+
raise IndexError, "Top level names may not contain pipes"
|
128
|
+
end
|
129
|
+
s << "#{key}|#{PHP.serialize(value, assoc)}"
|
130
|
+
end
|
131
|
+
when Array
|
132
|
+
var.each do |x|
|
133
|
+
case x
|
134
|
+
when Array
|
135
|
+
if x.size == 2
|
136
|
+
s << "#{x[0]}|#{PHP.serialize(x[1])}"
|
137
|
+
else
|
138
|
+
raise TypeError, "Array is not associative"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
else
|
143
|
+
raise TypeError, "Unable to serialize sessions with top level types other than Hash and associative Array"
|
144
|
+
end
|
145
|
+
s
|
146
|
+
end # }}}
|
147
|
+
|
148
|
+
# mixed = PHP.unserialize(string serialized, [hash classmap, [bool assoc]])
|
149
|
+
#
|
150
|
+
# Returns an object containing the reconstituted data from serialized.
|
151
|
+
#
|
152
|
+
# If a PHP array (associative; like an ordered hash) is encountered, it
|
153
|
+
# scans the keys; if they're all incrementing integers counting from 0,
|
154
|
+
# it's unserialized as an Array, otherwise it's unserialized as a Hash.
|
155
|
+
# Note: this will lose ordering. To avoid this, specify assoc=true,
|
156
|
+
# and it will be unserialized as an associative array: [[key,value],...]
|
157
|
+
#
|
158
|
+
# If a serialized object is encountered, the hash 'classmap' is searched for
|
159
|
+
# the class name (as a symbol). Since PHP classnames are not case-preserving,
|
160
|
+
# this *must* be a .capitalize()d representation. The value is expected
|
161
|
+
# to be the class itself; i.e. something you could call .new on.
|
162
|
+
#
|
163
|
+
# If it's not found in 'classmap', the current constant namespace is searched,
|
164
|
+
# and failing that, a new Struct(classname) is generated, with the arguments
|
165
|
+
# for .new specified in the same order PHP provided; since PHP uses hashes
|
166
|
+
# to represent attributes, this should be the same order they're specified
|
167
|
+
# in PHP, but this is untested.
|
168
|
+
#
|
169
|
+
# each serialized attribute is sent to the new object using the respective
|
170
|
+
# {attribute}=() method; you'll get a NameError if the method doesn't exist.
|
171
|
+
#
|
172
|
+
# Array, Hash, Fixnum, Float, True/FalseClass, NilClass and String should
|
173
|
+
# be returned identically (i.e. foo == PHP.unserialize(PHP.serialize(foo))
|
174
|
+
# for these types); Struct should be too, provided it's in the namespace
|
175
|
+
# Module.const_get within unserialize() can see, or you gave it the same
|
176
|
+
# name in the Struct.new(<structname>), otherwise you should provide it in
|
177
|
+
# classmap.
|
178
|
+
#
|
179
|
+
# Note: StringIO is required for unserialize(); it's loaded as needed
|
180
|
+
def PHP.unserialize(string, classmap = nil, assoc = false) # {{{
|
181
|
+
if classmap == true or classmap == false
|
182
|
+
assoc = classmap
|
183
|
+
classmap = {}
|
184
|
+
end
|
185
|
+
classmap ||= {}
|
186
|
+
|
187
|
+
require 'stringio'
|
188
|
+
string = StringIO.new(string)
|
189
|
+
def string.read_until(char)
|
190
|
+
val = ''
|
191
|
+
while (c = self.read(1)) != char
|
192
|
+
val << c
|
193
|
+
end
|
194
|
+
val
|
195
|
+
end
|
196
|
+
|
197
|
+
if string.string =~ /^(\w+)\|/ # session_name|serialized_data
|
198
|
+
ret = Hash.new
|
199
|
+
loop do
|
200
|
+
if string.string[string.pos, 32] =~ /^(\w+)\|/
|
201
|
+
string.pos += $&.size
|
202
|
+
ret[$1] = PHP.do_unserialize(string, classmap, assoc)
|
203
|
+
else
|
204
|
+
break
|
205
|
+
end
|
206
|
+
end
|
207
|
+
ret
|
208
|
+
else
|
209
|
+
PHP.do_unserialize(string, classmap, assoc)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
private
|
214
|
+
def PHP.do_unserialize(string, classmap, assoc)
|
215
|
+
val = nil
|
216
|
+
# determine a type
|
217
|
+
type = string.read(2)[0,1]
|
218
|
+
case type
|
219
|
+
when 'a' # associative array, a:length:{[index][value]...}
|
220
|
+
count = string.read_until('{').to_i
|
221
|
+
val = vals = Array.new
|
222
|
+
count.times do |i|
|
223
|
+
vals << [do_unserialize(string, classmap, assoc), do_unserialize(string, classmap, assoc)]
|
224
|
+
end
|
225
|
+
string.read(1) # skip the ending }
|
226
|
+
|
227
|
+
# now, we have an associative array, let's clean it up a bit...
|
228
|
+
# arrays have all numeric indexes, in order; otherwise we assume a hash
|
229
|
+
array = true
|
230
|
+
i = 0
|
231
|
+
vals.each do |key,value|
|
232
|
+
if key != i # wrong index -> assume hash
|
233
|
+
array = false
|
234
|
+
break
|
235
|
+
end
|
236
|
+
i += 1
|
237
|
+
end
|
238
|
+
|
239
|
+
if array
|
240
|
+
vals.collect! do |key,value|
|
241
|
+
value
|
242
|
+
end
|
243
|
+
else
|
244
|
+
if assoc
|
245
|
+
val = vals.map {|v| v }
|
246
|
+
else
|
247
|
+
val = Hash.new
|
248
|
+
vals.each do |key,value|
|
249
|
+
val[key] = value
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
when 'O' # object, O:length:"class":length:{[attribute][value]...}
|
255
|
+
# class name (lowercase in PHP, grr)
|
256
|
+
len = string.read_until(':').to_i + 3 # quotes, seperator
|
257
|
+
klass = string.read(len)[1...-2].capitalize.intern # read it, kill useless quotes
|
258
|
+
|
259
|
+
# read the attributes
|
260
|
+
attrs = []
|
261
|
+
len = string.read_until('{').to_i
|
262
|
+
|
263
|
+
len.times do
|
264
|
+
attr = (do_unserialize(string, classmap, assoc))
|
265
|
+
attrs << [attr.intern, (attr << '=').intern, do_unserialize(string, classmap, assoc)]
|
266
|
+
end
|
267
|
+
string.read(1)
|
268
|
+
|
269
|
+
val = nil
|
270
|
+
# See if we need to map to a particular object
|
271
|
+
if classmap.has_key?(klass)
|
272
|
+
val = classmap[klass].new
|
273
|
+
elsif Struct.const_defined?(klass) # Nope; see if there's a Struct
|
274
|
+
classmap[klass] = val = Struct.const_get(klass)
|
275
|
+
val = val.new
|
276
|
+
else # Nope; see if there's a Constant
|
277
|
+
begin
|
278
|
+
classmap[klass] = val = Module.const_get(klass)
|
279
|
+
|
280
|
+
val = val.new
|
281
|
+
rescue NameError # Nope; make a new Struct
|
282
|
+
classmap[klass] = Struct.new(klass.to_s, *attrs.collect { |v| v[0].to_s })
|
283
|
+
val = val.new
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
attrs.each do |attr,attrassign,v|
|
288
|
+
val.__send__(attrassign, v)
|
289
|
+
end
|
290
|
+
|
291
|
+
when 's' # string, s:length:"data";
|
292
|
+
len = string.read_until(':').to_i + 3 # quotes, separator
|
293
|
+
val = string.read(len)[1...-2] # read it, kill useless quotes
|
294
|
+
|
295
|
+
when 'i' # integer, i:123
|
296
|
+
val = string.read_until(';').to_i
|
297
|
+
|
298
|
+
when 'd' # double (float), d:1.23
|
299
|
+
val = string.read_until(';').to_f
|
300
|
+
|
301
|
+
when 'N' # NULL, N;
|
302
|
+
val = nil
|
303
|
+
|
304
|
+
when 'b' # bool, b:0 or 1
|
305
|
+
val = (string.read(2)[0] == ?1 ? true : false)
|
306
|
+
|
307
|
+
else
|
308
|
+
raise TypeError, "Unable to unserialize type '#{type}'"
|
309
|
+
end
|
310
|
+
|
311
|
+
val
|
312
|
+
end # }}}
|
313
|
+
end
|
314
|
+
|
@@ -0,0 +1,314 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Copyright (c) 2003-2009 Thomas Hurst <tom@hur.st>
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
20
|
+
# SOFTWARE.
|
21
|
+
|
22
|
+
# PHP serialize() and unserialize() workalikes
|
23
|
+
#
|
24
|
+
# Release History:
|
25
|
+
# 1.0.0 - 2003-06-02 - First release.
|
26
|
+
# 1.0.1 - 2003-06-16 - Minor bugfixes.
|
27
|
+
# 1.0.2 - 2004-09-17 - Switch all {}'s to explicit Hash.new's.
|
28
|
+
# 1.1.0 - 2009-04-01 - Pass assoc to recursive calls (thanks to Edward Speyer).
|
29
|
+
# - Serialize Symbol like String.
|
30
|
+
# - Add testsuite.
|
31
|
+
# - Instantiate auto-generated Structs properly (thanks
|
32
|
+
# to Philip Hallstrom).
|
33
|
+
# - Unserialize arrays properly in assoc mode.
|
34
|
+
# - Add PHP session support (thanks to TJ Vanderpoel).
|
35
|
+
# - Release as tarball and gem.
|
36
|
+
#
|
37
|
+
# See http://www.php.net/serialize and http://www.php.net/unserialize for
|
38
|
+
# details on the PHP side of all this.
|
39
|
+
module PHP
|
40
|
+
# string = PHP.serialize(mixed var[, bool assoc])
|
41
|
+
#
|
42
|
+
# Returns a string representing the argument in a form PHP.unserialize
|
43
|
+
# and PHP's unserialize() should both be able to load.
|
44
|
+
#
|
45
|
+
# Array, Hash, Fixnum, Float, True/FalseClass, NilClass, String and Struct
|
46
|
+
# are supported; as are objects which support the to_assoc method, which
|
47
|
+
# returns an array of the form [['attr_name', 'value']..]. Anything else
|
48
|
+
# will raise a TypeError.
|
49
|
+
#
|
50
|
+
# If 'assoc' is specified, Array's who's first element is a two value
|
51
|
+
# array will be assumed to be an associative array, and will be serialized
|
52
|
+
# as a PHP associative array rather than a multidimensional array.
|
53
|
+
def PHP.serialize(var, assoc = false) # {{{
|
54
|
+
s = ''
|
55
|
+
case var
|
56
|
+
when Array
|
57
|
+
s << "a:#{var.size}:{"
|
58
|
+
if assoc and var.first.is_a?(Array) and var.first.size == 2
|
59
|
+
var.each { |k,v|
|
60
|
+
s << PHP.serialize(k, assoc) << PHP.serialize(v, assoc)
|
61
|
+
}
|
62
|
+
else
|
63
|
+
var.each_with_index { |v,i|
|
64
|
+
s << "i:#{i};#{PHP.serialize(v, assoc)}"
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
s << '}'
|
69
|
+
|
70
|
+
when Hash
|
71
|
+
s << "a:#{var.size}:{"
|
72
|
+
var.each do |k,v|
|
73
|
+
s << "#{PHP.serialize(k, assoc)}#{PHP.serialize(v, assoc)}"
|
74
|
+
end
|
75
|
+
s << '}'
|
76
|
+
|
77
|
+
when Struct
|
78
|
+
# encode as Object with same name
|
79
|
+
s << "O:#{var.class.to_s.length}:\"#{var.class.to_s.downcase}\":#{var.members.length}:{"
|
80
|
+
var.members.each do |member|
|
81
|
+
s << "#{PHP.serialize(member, assoc)}#{PHP.serialize(var[member], assoc)}"
|
82
|
+
end
|
83
|
+
s << '}'
|
84
|
+
|
85
|
+
when String, Symbol
|
86
|
+
s << "s:#{var.to_s.bytesize}:\"#{var.to_s}\";"
|
87
|
+
|
88
|
+
when Fixnum # PHP doesn't have bignums
|
89
|
+
s << "i:#{var};"
|
90
|
+
|
91
|
+
when Float
|
92
|
+
s << "d:#{var};"
|
93
|
+
|
94
|
+
when NilClass
|
95
|
+
s << 'N;'
|
96
|
+
|
97
|
+
when FalseClass, TrueClass
|
98
|
+
s << "b:#{var ? 1 :0};"
|
99
|
+
|
100
|
+
else
|
101
|
+
if var.respond_to?(:to_assoc)
|
102
|
+
v = var.to_assoc
|
103
|
+
# encode as Object with same name
|
104
|
+
s << "O:#{var.class.to_s.length}:\"#{var.class.to_s.downcase}\":#{v.length}:{"
|
105
|
+
v.each do |k,v|
|
106
|
+
s << "#{PHP.serialize(k.to_s, assoc)}#{PHP.serialize(v, assoc)}"
|
107
|
+
end
|
108
|
+
s << '}'
|
109
|
+
else
|
110
|
+
raise TypeError, "Unable to serialize type #{var.class}"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
s
|
115
|
+
end # }}}
|
116
|
+
|
117
|
+
# string = PHP.serialize_session(mixed var[, bool assoc])
|
118
|
+
#
|
119
|
+
# Like PHP.serialize, but only accepts a Hash or associative Array as the root
|
120
|
+
# type. The results are returned in PHP session format.
|
121
|
+
def PHP.serialize_session(var, assoc = false) # {{{
|
122
|
+
s = ''
|
123
|
+
case var
|
124
|
+
when Hash
|
125
|
+
var.each do |key,value|
|
126
|
+
if key.to_s =~ /\|/
|
127
|
+
raise IndexError, "Top level names may not contain pipes"
|
128
|
+
end
|
129
|
+
s << "#{key}|#{PHP.serialize(value, assoc)}"
|
130
|
+
end
|
131
|
+
when Array
|
132
|
+
var.each do |x|
|
133
|
+
case x
|
134
|
+
when Array
|
135
|
+
if x.size == 2
|
136
|
+
s << "#{x[0]}|#{PHP.serialize(x[1])}"
|
137
|
+
else
|
138
|
+
raise TypeError, "Array is not associative"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
else
|
143
|
+
raise TypeError, "Unable to serialize sessions with top level types other than Hash and associative Array"
|
144
|
+
end
|
145
|
+
s
|
146
|
+
end # }}}
|
147
|
+
|
148
|
+
# mixed = PHP.unserialize(string serialized, [hash classmap, [bool assoc]])
|
149
|
+
#
|
150
|
+
# Returns an object containing the reconstituted data from serialized.
|
151
|
+
#
|
152
|
+
# If a PHP array (associative; like an ordered hash) is encountered, it
|
153
|
+
# scans the keys; if they're all incrementing integers counting from 0,
|
154
|
+
# it's unserialized as an Array, otherwise it's unserialized as a Hash.
|
155
|
+
# Note: this will lose ordering. To avoid this, specify assoc=true,
|
156
|
+
# and it will be unserialized as an associative array: [[key,value],...]
|
157
|
+
#
|
158
|
+
# If a serialized object is encountered, the hash 'classmap' is searched for
|
159
|
+
# the class name (as a symbol). Since PHP classnames are not case-preserving,
|
160
|
+
# this *must* be a .capitalize()d representation. The value is expected
|
161
|
+
# to be the class itself; i.e. something you could call .new on.
|
162
|
+
#
|
163
|
+
# If it's not found in 'classmap', the current constant namespace is searched,
|
164
|
+
# and failing that, a new Struct(classname) is generated, with the arguments
|
165
|
+
# for .new specified in the same order PHP provided; since PHP uses hashes
|
166
|
+
# to represent attributes, this should be the same order they're specified
|
167
|
+
# in PHP, but this is untested.
|
168
|
+
#
|
169
|
+
# each serialized attribute is sent to the new object using the respective
|
170
|
+
# {attribute}=() method; you'll get a NameError if the method doesn't exist.
|
171
|
+
#
|
172
|
+
# Array, Hash, Fixnum, Float, True/FalseClass, NilClass and String should
|
173
|
+
# be returned identically (i.e. foo == PHP.unserialize(PHP.serialize(foo))
|
174
|
+
# for these types); Struct should be too, provided it's in the namespace
|
175
|
+
# Module.const_get within unserialize() can see, or you gave it the same
|
176
|
+
# name in the Struct.new(<structname>), otherwise you should provide it in
|
177
|
+
# classmap.
|
178
|
+
#
|
179
|
+
# Note: StringIO is required for unserialize(); it's loaded as needed
|
180
|
+
def PHP.unserialize(string, classmap = nil, assoc = false) # {{{
|
181
|
+
if classmap == true or classmap == false
|
182
|
+
assoc = classmap
|
183
|
+
classmap = {}
|
184
|
+
end
|
185
|
+
classmap ||= {}
|
186
|
+
|
187
|
+
require 'stringio'
|
188
|
+
string = StringIO.new(string)
|
189
|
+
def string.read_until(char)
|
190
|
+
val = ''
|
191
|
+
while (c = self.read(1)) != char
|
192
|
+
val << c
|
193
|
+
end
|
194
|
+
val
|
195
|
+
end
|
196
|
+
|
197
|
+
if string.string =~ /^(\w+)\|/ # session_name|serialized_data
|
198
|
+
ret = Hash.new
|
199
|
+
loop do
|
200
|
+
if string.string[string.pos, 32] =~ /^(\w+)\|/
|
201
|
+
string.pos += $&.size
|
202
|
+
ret[$1] = PHP.do_unserialize(string, classmap, assoc)
|
203
|
+
else
|
204
|
+
break
|
205
|
+
end
|
206
|
+
end
|
207
|
+
ret
|
208
|
+
else
|
209
|
+
PHP.do_unserialize(string, classmap, assoc)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
private
|
214
|
+
def PHP.do_unserialize(string, classmap, assoc)
|
215
|
+
val = nil
|
216
|
+
# determine a type
|
217
|
+
type = string.read(2)[0,1]
|
218
|
+
case type
|
219
|
+
when 'a' # associative array, a:length:{[index][value]...}
|
220
|
+
count = string.read_until('{').to_i
|
221
|
+
val = vals = Array.new
|
222
|
+
count.times do |i|
|
223
|
+
vals << [do_unserialize(string, classmap, assoc), do_unserialize(string, classmap, assoc)]
|
224
|
+
end
|
225
|
+
string.read(1) # skip the ending }
|
226
|
+
|
227
|
+
# now, we have an associative array, let's clean it up a bit...
|
228
|
+
# arrays have all numeric indexes, in order; otherwise we assume a hash
|
229
|
+
array = true
|
230
|
+
i = 0
|
231
|
+
vals.each do |key,value|
|
232
|
+
if key != i # wrong index -> assume hash
|
233
|
+
array = false
|
234
|
+
break
|
235
|
+
end
|
236
|
+
i += 1
|
237
|
+
end
|
238
|
+
|
239
|
+
if array
|
240
|
+
vals.collect! do |key,value|
|
241
|
+
value
|
242
|
+
end
|
243
|
+
else
|
244
|
+
if assoc
|
245
|
+
val = vals.map {|v| v }
|
246
|
+
else
|
247
|
+
val = Hash.new
|
248
|
+
vals.each do |key,value|
|
249
|
+
val[key] = value
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
when 'O' # object, O:length:"class":length:{[attribute][value]...}
|
255
|
+
# class name (lowercase in PHP, grr)
|
256
|
+
len = string.read_until(':').to_i + 3 # quotes, seperator
|
257
|
+
klass = string.read(len)[1...-2].capitalize.intern # read it, kill useless quotes
|
258
|
+
|
259
|
+
# read the attributes
|
260
|
+
attrs = []
|
261
|
+
len = string.read_until('{').to_i
|
262
|
+
|
263
|
+
len.times do
|
264
|
+
attr = (do_unserialize(string, classmap, assoc))
|
265
|
+
attrs << [attr.intern, (attr << '=').intern, do_unserialize(string, classmap, assoc)]
|
266
|
+
end
|
267
|
+
string.read(1)
|
268
|
+
|
269
|
+
val = nil
|
270
|
+
# See if we need to map to a particular object
|
271
|
+
if classmap.has_key?(klass)
|
272
|
+
val = classmap[klass].new
|
273
|
+
elsif Struct.const_defined?(klass) # Nope; see if there's a Struct
|
274
|
+
classmap[klass] = val = Struct.const_get(klass)
|
275
|
+
val = val.new
|
276
|
+
else # Nope; see if there's a Constant
|
277
|
+
begin
|
278
|
+
classmap[klass] = val = Module.const_get(klass)
|
279
|
+
|
280
|
+
val = val.new
|
281
|
+
rescue NameError # Nope; make a new Struct
|
282
|
+
classmap[klass] = Struct.new(klass.to_s, *attrs.collect { |v| v[0].to_s })
|
283
|
+
val = val.new
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
attrs.each do |attr,attrassign,v|
|
288
|
+
val.__send__(attrassign, v)
|
289
|
+
end
|
290
|
+
|
291
|
+
when 's' # string, s:length:"data";
|
292
|
+
len = string.read_until(':').to_i + 3 # quotes, separator
|
293
|
+
val = string.read(len)[1...-2] # read it, kill useless quotes
|
294
|
+
|
295
|
+
when 'i' # integer, i:123
|
296
|
+
val = string.read_until(';').to_i
|
297
|
+
|
298
|
+
when 'd' # double (float), d:1.23
|
299
|
+
val = string.read_until(';').to_f
|
300
|
+
|
301
|
+
when 'N' # NULL, N;
|
302
|
+
val = nil
|
303
|
+
|
304
|
+
when 'b' # bool, b:0 or 1
|
305
|
+
val = (string.read(2)[0] == ?1 ? true : false)
|
306
|
+
|
307
|
+
else
|
308
|
+
raise TypeError, "Unable to unserialize type '#{type}'"
|
309
|
+
end
|
310
|
+
|
311
|
+
val
|
312
|
+
end # }}}
|
313
|
+
end
|
314
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
Gem::Specification.new do |spec|
|
3
|
+
spec.name = "php-serialize"
|
4
|
+
spec.version = "1.1.0"
|
5
|
+
spec.summary = "Ruby analogs to PHP's serialize() and unserialize() functions"
|
6
|
+
spec.require_path = 'lib/'
|
7
|
+
spec.files = Dir['lib/*.rb']
|
8
|
+
spec.author = "Thomas Hurst"
|
9
|
+
spec.email = "tom@hur.st"
|
10
|
+
spec.homepage = "http://www.aagh.net/projects/ruby-php-serialize"
|
11
|
+
spec.description = <<-EOF
|
12
|
+
This module provides two methods: PHP.serialize() and PHP.unserialize(), both
|
13
|
+
of which should be compatible with the similarly named functions in PHP.
|
14
|
+
|
15
|
+
It can also serialize and unserialize PHP sessions.
|
16
|
+
EOF
|
17
|
+
spec.test_file = 'test.rb'
|
18
|
+
spec.has_rdoc = true
|
19
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{php-serialize4ruby}
|
8
|
+
s.version = "0.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Kasper Johansen"]
|
12
|
+
s.date = %q{2012-05-06}
|
13
|
+
s.description = %q{Read the original gems description.}
|
14
|
+
s.email = %q{k@spernj.org}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README",
|
18
|
+
"README.rdoc"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
".document",
|
22
|
+
".rspec",
|
23
|
+
"Gemfile",
|
24
|
+
"LICENSE.txt",
|
25
|
+
"README",
|
26
|
+
"README.rdoc",
|
27
|
+
"Rakefile",
|
28
|
+
"VERSION",
|
29
|
+
"lib/php-serialize4ruby.rb",
|
30
|
+
"lib/php_serialize.rb",
|
31
|
+
"php-serialize.gemspec",
|
32
|
+
"php-serialize4ruby.gemspec",
|
33
|
+
"spec/php-serialize4ruby_spec.rb",
|
34
|
+
"spec/spec_helper.rb",
|
35
|
+
"test.rb"
|
36
|
+
]
|
37
|
+
s.homepage = %q{http://github.com/kaspernj/php-serialize4ruby}
|
38
|
+
s.licenses = ["MIT"]
|
39
|
+
s.require_paths = ["lib"]
|
40
|
+
s.rubygems_version = %q{1.6.2}
|
41
|
+
s.summary = %q{A fork of the original gem "php-serialize" because I have no hope of the original guy to update the gem}
|
42
|
+
|
43
|
+
if s.respond_to? :specification_version then
|
44
|
+
s.specification_version = 3
|
45
|
+
|
46
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
47
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
|
48
|
+
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
49
|
+
s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
|
50
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
|
51
|
+
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
52
|
+
else
|
53
|
+
s.add_dependency(%q<rspec>, ["~> 2.8.0"])
|
54
|
+
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
55
|
+
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
56
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
|
57
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
58
|
+
end
|
59
|
+
else
|
60
|
+
s.add_dependency(%q<rspec>, ["~> 2.8.0"])
|
61
|
+
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
62
|
+
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
63
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
|
64
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'php-serialize4ruby'
|
5
|
+
|
6
|
+
# Requires supporting files with custom matchers and macros, etc,
|
7
|
+
# in ./support/ and its subdirectories.
|
8
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
|
12
|
+
end
|
data/test.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
if RUBY_VERSION == "1.9.2"
|
5
|
+
# needed, when running in Ruby 1.9.2 -> no stdlib test/unit
|
6
|
+
gem 'test-unit'
|
7
|
+
end
|
8
|
+
require 'test/unit'
|
9
|
+
require 'test/unit/ui/console/testrunner'
|
10
|
+
|
11
|
+
$:.unshift "lib"
|
12
|
+
require 'php_serialize'
|
13
|
+
|
14
|
+
TestStruct = Struct.new(:name, :value)
|
15
|
+
class TestClass
|
16
|
+
attr_accessor :name
|
17
|
+
attr_accessor :value
|
18
|
+
|
19
|
+
def initialize(name = nil, value = nil)
|
20
|
+
@name = name
|
21
|
+
@value = value
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_assoc
|
25
|
+
[['name', @name], ['value', @value]]
|
26
|
+
end
|
27
|
+
|
28
|
+
def ==(other)
|
29
|
+
other.class == self.class and other.name == @name and other.value == @value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
ClassMap = {
|
34
|
+
TestStruct.name.capitalize.intern => TestStruct,
|
35
|
+
TestClass.name.capitalize.intern => TestClass
|
36
|
+
}
|
37
|
+
|
38
|
+
class TestPhpSerialize < Test::Unit::TestCase
|
39
|
+
def self.test(ruby, php, opts = {})
|
40
|
+
if opts[:name]
|
41
|
+
name = opts[:name]
|
42
|
+
else
|
43
|
+
name = ruby.to_s
|
44
|
+
end
|
45
|
+
|
46
|
+
define_method("test_#{name}".intern) do
|
47
|
+
assert_nothing_thrown do
|
48
|
+
serialized = PHP.serialize(ruby)
|
49
|
+
assert_equal php, serialized
|
50
|
+
|
51
|
+
unserialized = PHP.unserialize(serialized, ClassMap)
|
52
|
+
case ruby
|
53
|
+
when Symbol
|
54
|
+
assert_equal ruby.to_s, unserialized
|
55
|
+
else
|
56
|
+
assert_equal ruby, unserialized
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
test nil, 'N;'
|
63
|
+
test false, 'b:0;'
|
64
|
+
test true, 'b:1;'
|
65
|
+
test 42, 'i:42;'
|
66
|
+
test -42, 'i:-42;'
|
67
|
+
test 2147483647, "i:2147483647;", :name => 'Max Fixnum'
|
68
|
+
test -2147483648, "i:-2147483648;", :name => 'Min Fixnum'
|
69
|
+
test 4.2, 'd:4.2;'
|
70
|
+
test 'test', 's:4:"test";'
|
71
|
+
test :test, 's:4:"test";', :name => 'Symbol'
|
72
|
+
test "\"\n\t\"", "s:4:\"\"\n\t\"\";", :name => 'Complex string'
|
73
|
+
test [nil, true, false, 42, 4.2, 'test'], 'a:6:{i:0;N;i:1;b:1;i:2;b:0;i:3;i:42;i:4;d:4.2;i:5;s:4:"test";}',
|
74
|
+
:name => 'Array'
|
75
|
+
test({'foo' => 'bar', 4 => [5,4,3,2]}, 'a:2:{s:3:"foo";s:3:"bar";i:4;a:4:{i:0;i:5;i:1;i:4;i:2;i:3;i:3;i:2;}}', :name => 'Hash')
|
76
|
+
test TestStruct.new("Foo", 65), 'O:10:"teststruct":2:{s:4:"name";s:3:"Foo";s:5:"value";i:65;}',
|
77
|
+
:name => 'Struct'
|
78
|
+
test TestClass.new("Foo", 65), 'O:9:"testclass":2:{s:4:"name";s:3:"Foo";s:5:"value";i:65;}',
|
79
|
+
:name => 'Class'
|
80
|
+
|
81
|
+
# PHP counts multibyte string, not string length
|
82
|
+
def test_multibyte_string
|
83
|
+
assert_equal "s:6:\"öäü\";", PHP.serialize("öäü")
|
84
|
+
end
|
85
|
+
# Verify assoc is passed down calls.
|
86
|
+
# Slightly awkward because hashes don't guarantee order.
|
87
|
+
def test_assoc
|
88
|
+
assert_nothing_raised do
|
89
|
+
ruby = {'foo' => ['bar','baz'], 'hash' => {'hash' => 'smoke'}}
|
90
|
+
ruby_assoc = [['foo', ['bar','baz']], ['hash', [['hash','smoke']]]]
|
91
|
+
phps = [
|
92
|
+
'a:2:{s:4:"hash";a:1:{s:4:"hash";s:5:"smoke";}s:3:"foo";a:2:{i:0;s:3:"bar";i:1;s:3:"baz";}}',
|
93
|
+
'a:2:{s:3:"foo";a:2:{i:0;s:3:"bar";i:1;s:3:"baz";}s:4:"hash";a:1:{s:4:"hash";s:5:"smoke";}}'
|
94
|
+
]
|
95
|
+
serialized = PHP.serialize(ruby, true)
|
96
|
+
assert phps.include?(serialized)
|
97
|
+
unserialized = PHP.unserialize(serialized, true)
|
98
|
+
assert_equal ruby_assoc.sort, unserialized.sort
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_sessions
|
103
|
+
assert_nothing_raised do
|
104
|
+
ruby = {'session_id' => 42, 'user_data' => {'uid' => 666}}
|
105
|
+
phps = [
|
106
|
+
'session_id|i:42;user_data|a:1:{s:3:"uid";i:666;}',
|
107
|
+
'user_data|a:1:{s:3:"uid";i:666;}session_id|i:42;'
|
108
|
+
]
|
109
|
+
unserialized = PHP.unserialize(phps.first)
|
110
|
+
assert_equal ruby, unserialized
|
111
|
+
serialized = PHP.serialize_session(ruby)
|
112
|
+
assert phps.include?(serialized)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
require 'test/unit/ui/console/testrunner'
|
118
|
+
Test::Unit::UI::Console::TestRunner.run(TestPhpSerialize)
|
119
|
+
|
metadata
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: php-serialize4ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kasper Johansen
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2012-05-06 00:00:00 +02:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: rspec
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.8.0
|
24
|
+
type: :development
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rdoc
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ~>
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: "3.12"
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: bundler
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.0.0
|
46
|
+
type: :development
|
47
|
+
prerelease: false
|
48
|
+
version_requirements: *id003
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: jeweler
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ~>
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 1.8.3
|
57
|
+
type: :development
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: *id004
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: simplecov
|
62
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: "0"
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: *id005
|
71
|
+
description: Read the original gems description.
|
72
|
+
email: k@spernj.org
|
73
|
+
executables: []
|
74
|
+
|
75
|
+
extensions: []
|
76
|
+
|
77
|
+
extra_rdoc_files:
|
78
|
+
- LICENSE.txt
|
79
|
+
- README
|
80
|
+
- README.rdoc
|
81
|
+
files:
|
82
|
+
- .document
|
83
|
+
- .rspec
|
84
|
+
- Gemfile
|
85
|
+
- LICENSE.txt
|
86
|
+
- README
|
87
|
+
- README.rdoc
|
88
|
+
- Rakefile
|
89
|
+
- VERSION
|
90
|
+
- lib/php-serialize4ruby.rb
|
91
|
+
- lib/php_serialize.rb
|
92
|
+
- php-serialize.gemspec
|
93
|
+
- php-serialize4ruby.gemspec
|
94
|
+
- spec/php-serialize4ruby_spec.rb
|
95
|
+
- spec/spec_helper.rb
|
96
|
+
- test.rb
|
97
|
+
has_rdoc: true
|
98
|
+
homepage: http://github.com/kaspernj/php-serialize4ruby
|
99
|
+
licenses:
|
100
|
+
- MIT
|
101
|
+
post_install_message:
|
102
|
+
rdoc_options: []
|
103
|
+
|
104
|
+
require_paths:
|
105
|
+
- lib
|
106
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
hash: -4127720001001404955
|
112
|
+
segments:
|
113
|
+
- 0
|
114
|
+
version: "0"
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
|
+
none: false
|
117
|
+
requirements:
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: "0"
|
121
|
+
requirements: []
|
122
|
+
|
123
|
+
rubyforge_project:
|
124
|
+
rubygems_version: 1.6.2
|
125
|
+
signing_key:
|
126
|
+
specification_version: 3
|
127
|
+
summary: A fork of the original gem "php-serialize" because I have no hope of the original guy to update the gem
|
128
|
+
test_files: []
|
129
|
+
|