phuby 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.
- data/.autotest +23 -0
- data/CHANGELOG.rdoc +6 -0
- data/Manifest.txt +35 -0
- data/README.rdoc +96 -0
- data/Rakefile +23 -0
- data/bin/phrack +50 -0
- data/bin/phuby +3 -0
- data/bin/phuby_server +12 -0
- data/ext/phuby/extconf.rb +24 -0
- data/ext/phuby/phuby.c +11 -0
- data/ext/phuby/phuby.h +14 -0
- data/ext/phuby/phuby_array.c +92 -0
- data/ext/phuby/phuby_array.h +9 -0
- data/ext/phuby/phuby_conversions.c +92 -0
- data/ext/phuby/phuby_conversions.h +12 -0
- data/ext/phuby/phuby_runtime.c +243 -0
- data/ext/phuby/phuby_runtime.h +11 -0
- data/lib/phuby.rb +9 -0
- data/lib/phuby/array.rb +24 -0
- data/lib/phuby/events.rb +19 -0
- data/lib/phuby/php_handler.rb +96 -0
- data/lib/phuby/rails.rb +47 -0
- data/lib/phuby/runtime.rb +69 -0
- data/php.patch +145 -0
- data/test/assets/hello_world.php +6 -0
- data/test/assets/htdocs/index.php +22 -0
- data/test/helper.rb +19 -0
- data/test/test_array.rb +101 -0
- data/test/test_handlers.rb +49 -0
- data/test/test_header_sent.rb +25 -0
- data/test/test_nil.rb +10 -0
- data/test/test_object.rb +57 -0
- data/test/test_php_handler.rb +56 -0
- data/test/test_phuby.rb +90 -0
- data/test/test_runtime.rb +77 -0
- metadata +151 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'thread'
|
3
|
+
|
4
|
+
module Phuby
|
5
|
+
class Runtime
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
attr_accessor :events
|
9
|
+
|
10
|
+
def self.php &block
|
11
|
+
instance.php(&block)
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@events = Events.new
|
16
|
+
@mutex = Mutex.new
|
17
|
+
@proxy_map = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def started?
|
21
|
+
@mutex.locked?
|
22
|
+
end
|
23
|
+
|
24
|
+
def with_events event
|
25
|
+
old = @events
|
26
|
+
@events = event
|
27
|
+
yield self
|
28
|
+
@events = old
|
29
|
+
end
|
30
|
+
|
31
|
+
def eval string_or_io, filename = nil
|
32
|
+
raise NotStartedError, "please start the runtime" unless @mutex.locked?
|
33
|
+
|
34
|
+
if string_or_io.respond_to? :read
|
35
|
+
native_eval_io string_or_io, filename || string_or_io.path
|
36
|
+
else
|
37
|
+
native_eval string_or_io, filename || __FILE__
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def php &block
|
42
|
+
start
|
43
|
+
block.call(self)
|
44
|
+
ensure
|
45
|
+
stop
|
46
|
+
end
|
47
|
+
|
48
|
+
def [] key
|
49
|
+
raise NotStartedError, "please start the runtime" unless @mutex.locked?
|
50
|
+
get key
|
51
|
+
end
|
52
|
+
|
53
|
+
def []= key, value
|
54
|
+
raise NotStartedError, "please start the runtime" unless @mutex.locked?
|
55
|
+
set key, value
|
56
|
+
end
|
57
|
+
|
58
|
+
class NotStartedError < RuntimeError; end
|
59
|
+
|
60
|
+
private
|
61
|
+
def call who, what, with
|
62
|
+
list = []
|
63
|
+
with.each do |obj|
|
64
|
+
list << obj
|
65
|
+
end
|
66
|
+
@proxy_map[who].send(what.to_sym, *list)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/php.patch
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
diff --git configure configure
|
2
|
+
index 365e20e..7d116ab 100755
|
3
|
+
--- configure
|
4
|
+
+++ configure
|
5
|
+
@@ -3480,7 +3480,7 @@ if test "$GCC" = "yes"; then
|
6
|
+
;;
|
7
|
+
esac
|
8
|
+
if test $GCC_MAJOR_VERSION -ge 4; then
|
9
|
+
- CFLAGS="$CFLAGS -fvisibility=hidden"
|
10
|
+
+ CFLAGS="$CFLAGS"
|
11
|
+
fi
|
12
|
+
fi
|
13
|
+
|
14
|
+
@@ -4406,12 +4406,12 @@ IFS="- /.
|
15
|
+
build_type=shared
|
16
|
+
;;
|
17
|
+
*darwin*)
|
18
|
+
- MH_BUNDLE_FLAGS="-dynamic -twolevel_namespace -bundle -bundle_loader $APXS_HTTPD"
|
19
|
+
+ MH_BUNDLE_FLAGS="-dylib -twolevel_namespace -bundle -bundle_loader $APXS_HTTPD"
|
20
|
+
|
21
|
+
PHP_VAR_SUBST="$PHP_VAR_SUBST MH_BUNDLE_FLAGS"
|
22
|
+
|
23
|
+
- SAPI_SHARED=libs/libphp5.so
|
24
|
+
- build_type=bundle
|
25
|
+
+ SAPI_SHARED=libs/libphp5.dylib
|
26
|
+
+ build_type=shared
|
27
|
+
;;
|
28
|
+
*)
|
29
|
+
build_type=shared
|
30
|
+
@@ -107680,7 +107680,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
|
31
|
+
if test "$GCC" = yes ; then
|
32
|
+
output_verbose_link_cmd='echo'
|
33
|
+
archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
|
34
|
+
- module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
|
35
|
+
+ module_cmds='$CC $allow_undefined_flag -fPIC -o $lib -dynamiclib $libobjs $deplibs$compiler_flags'
|
36
|
+
# Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds
|
37
|
+
archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
|
38
|
+
module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
|
39
|
+
diff --git configure.in configure.in
|
40
|
+
index dff131d..18c8e72 100644
|
41
|
+
--- configure.in
|
42
|
+
+++ configure.in
|
43
|
+
@@ -427,6 +427,7 @@ alloca.h \
|
44
|
+
arpa/inet.h \
|
45
|
+
arpa/nameser.h \
|
46
|
+
assert.h \
|
47
|
+
+crt_externs.h \
|
48
|
+
crypt.h \
|
49
|
+
fcntl.h \
|
50
|
+
grp.h \
|
51
|
+
diff --git ext/spl/spl_dllist.h ext/spl/spl_dllist.h
|
52
|
+
index 5b0998b..8360282 100644
|
53
|
+
--- ext/spl/spl_dllist.h
|
54
|
+
+++ ext/spl/spl_dllist.h
|
55
|
+
@@ -24,9 +24,9 @@
|
56
|
+
#include "php.h"
|
57
|
+
#include "php_spl.h"
|
58
|
+
|
59
|
+
-PHPAPI zend_class_entry *spl_ce_SplDoublyLinkedList;
|
60
|
+
-PHPAPI zend_class_entry *spl_ce_SplQueue;
|
61
|
+
-PHPAPI zend_class_entry *spl_ce_SplStack;
|
62
|
+
+extern PHPAPI zend_class_entry *spl_ce_SplDoublyLinkedList;
|
63
|
+
+extern PHPAPI zend_class_entry *spl_ce_SplQueue;
|
64
|
+
+extern PHPAPI zend_class_entry *spl_ce_SplStack;
|
65
|
+
|
66
|
+
PHP_MINIT_FUNCTION(spl_dllist);
|
67
|
+
|
68
|
+
diff --git ext/spl/spl_fixedarray.h ext/spl/spl_fixedarray.h
|
69
|
+
index dd556be..f9a2d90 100644
|
70
|
+
--- ext/spl/spl_fixedarray.h
|
71
|
+
+++ ext/spl/spl_fixedarray.h
|
72
|
+
@@ -22,7 +22,7 @@
|
73
|
+
#ifndef SPL_FIXEDARRAY_H
|
74
|
+
#define SPL_FIXEDARRAY_H
|
75
|
+
|
76
|
+
-PHPAPI zend_class_entry *spl_ce_SplFixedArray;
|
77
|
+
+extern PHPAPI zend_class_entry *spl_ce_SplFixedArray;
|
78
|
+
|
79
|
+
PHP_MINIT_FUNCTION(spl_fixedarray);
|
80
|
+
|
81
|
+
diff --git ext/spl/spl_heap.h ext/spl/spl_heap.h
|
82
|
+
index 56c82b5..1d29e57 100644
|
83
|
+
--- ext/spl/spl_heap.h
|
84
|
+
+++ ext/spl/spl_heap.h
|
85
|
+
@@ -24,11 +24,11 @@
|
86
|
+
#include "php.h"
|
87
|
+
#include "php_spl.h"
|
88
|
+
|
89
|
+
-PHPAPI zend_class_entry *spl_ce_SplHeap;
|
90
|
+
-PHPAPI zend_class_entry *spl_ce_SplMinHeap;
|
91
|
+
-PHPAPI zend_class_entry *spl_ce_SplMaxHeap;
|
92
|
+
+extern PHPAPI zend_class_entry *spl_ce_SplHeap;
|
93
|
+
+extern PHPAPI zend_class_entry *spl_ce_SplMinHeap;
|
94
|
+
+extern PHPAPI zend_class_entry *spl_ce_SplMaxHeap;
|
95
|
+
|
96
|
+
-PHPAPI zend_class_entry *spl_ce_SplPriorityQueue;
|
97
|
+
+extern PHPAPI zend_class_entry *spl_ce_SplPriorityQueue;
|
98
|
+
|
99
|
+
PHP_MINIT_FUNCTION(spl_heap);
|
100
|
+
|
101
|
+
diff --git main/php.h main/php.h
|
102
|
+
index 58f4142..035d502 100644
|
103
|
+
--- main/php.h
|
104
|
+
+++ main/php.h
|
105
|
+
@@ -263,7 +263,13 @@ END_EXTERN_C()
|
106
|
+
#if !defined(PHP_WIN32)
|
107
|
+
#define PHP_SLEEP_NON_VOID
|
108
|
+
#define php_sleep sleep
|
109
|
+
+
|
110
|
+
+#if HAVE_CRT_EXTERNS_H
|
111
|
+
+#include <crt_externs.h>
|
112
|
+
+#define environ (*_NSGetEnviron())
|
113
|
+
+#else
|
114
|
+
extern char **environ;
|
115
|
+
+#endif
|
116
|
+
#endif /* !defined(PHP_WIN32) */
|
117
|
+
|
118
|
+
#ifdef PHP_PWRITE_64
|
119
|
+
diff --git main/php_getopt.h main/php_getopt.h
|
120
|
+
index 024ea5c..62f04d6 100644
|
121
|
+
--- main/php_getopt.h
|
122
|
+
+++ main/php_getopt.h
|
123
|
+
@@ -41,7 +41,7 @@ typedef struct _opt_struct {
|
124
|
+
|
125
|
+
BEGIN_EXTERN_C()
|
126
|
+
/* holds the index of the latest fetched element from the opts array */
|
127
|
+
-PHPAPI int php_optidx;
|
128
|
+
+extern PHPAPI int php_optidx;
|
129
|
+
PHPAPI int php_getopt(int argc, char* const *argv, const opt_struct opts[], char **optarg, int *optind, int show_err, int arg_start);
|
130
|
+
END_EXTERN_C()
|
131
|
+
|
132
|
+
diff --git sapi/cli/config.m4 sapi/cli/config.m4
|
133
|
+
index e804357..300b898 100644
|
134
|
+
--- sapi/cli/config.m4
|
135
|
+
+++ sapi/cli/config.m4
|
136
|
+
@@ -20,9 +20,6 @@ if test "$PHP_CLI" != "no"; then
|
137
|
+
BUILD_CLI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_CLI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CLI_PATH)"
|
138
|
+
fi
|
139
|
+
;;
|
140
|
+
- *darwin*)
|
141
|
+
- BUILD_CLI="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_CLI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CLI_PATH)"
|
142
|
+
- ;;
|
143
|
+
*netware*)
|
144
|
+
BUILD_CLI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -Lnetware -lphp5lib -o \$(SAPI_CLI_PATH)"
|
145
|
+
;;
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>
|
4
|
+
Hello
|
5
|
+
</title>
|
6
|
+
</head>
|
7
|
+
<body>
|
8
|
+
<h1>Get Params</h1>
|
9
|
+
<table id="get">
|
10
|
+
<?php
|
11
|
+
foreach($_GET as $key => $val) {
|
12
|
+
?>
|
13
|
+
<tr>
|
14
|
+
<td><?php echo $key; ?></td>
|
15
|
+
<td><?php echo $val; ?></td>
|
16
|
+
</tr>
|
17
|
+
<?php
|
18
|
+
}
|
19
|
+
?>
|
20
|
+
</table>
|
21
|
+
</body>
|
22
|
+
</html>
|
data/test/helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#Process.setrlimit(Process::RLIMIT_CORE, Process::RLIM_INFINITY) unless RUBY_PLATFORM =~ /(java|mswin|mingw)/i
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'phuby'
|
5
|
+
|
6
|
+
module Phuby
|
7
|
+
class TestCase < Test::Unit::TestCase
|
8
|
+
ASSETS_DIR = File.join(File.dirname(__FILE__), 'assets')
|
9
|
+
HTDOCS_DIR = File.join(File.dirname(__FILE__), 'assets', 'htdocs')
|
10
|
+
|
11
|
+
unless RUBY_VERSION >= '1.9'
|
12
|
+
undef :default_test
|
13
|
+
end
|
14
|
+
|
15
|
+
def setup
|
16
|
+
warn "#{name}" if ENV['TESTOPTS'] == '-v'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/test/test_array.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestArray < Phuby::TestCase
|
4
|
+
def test_move_to_runtime
|
5
|
+
Phuby::Runtime.php do |rt|
|
6
|
+
rt['foo'] = [1,2,3]
|
7
|
+
assert_equal 1, rt['foo'][0]
|
8
|
+
assert_equal 2, rt['foo'][1]
|
9
|
+
assert_equal 3, rt['foo'][2]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_array_length
|
14
|
+
Phuby::Runtime.php do |rt|
|
15
|
+
rt.eval('$get_length = count($_GET);')
|
16
|
+
assert_equal rt['get_length'], rt['_GET'].length
|
17
|
+
|
18
|
+
10.times { |i|
|
19
|
+
rt.eval("$_GET['foo#{i}'] = 'bar'; $get_length = count($_GET);")
|
20
|
+
assert_equal rt['get_length'], rt['_GET'].length
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_index_numeric_get
|
26
|
+
Phuby::Runtime.php do |rt|
|
27
|
+
rt.eval('$foo = array(1,2,3,4,5);')
|
28
|
+
list = []
|
29
|
+
assert_equal 1, rt['foo'][0]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_index_numeric_set
|
34
|
+
Phuby::Runtime.php do |rt|
|
35
|
+
rt.eval('$foo = array(1,2,3,4,5);')
|
36
|
+
|
37
|
+
rt['foo'][0] = "hello"
|
38
|
+
|
39
|
+
rt.eval('$bar = $foo[0];')
|
40
|
+
|
41
|
+
assert_equal 'hello', rt['bar']
|
42
|
+
assert_equal 'hello', rt['foo'][0]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_each
|
47
|
+
Phuby::Runtime.php do |rt|
|
48
|
+
rt.eval('$foo = array(1,2,3,4,5);')
|
49
|
+
|
50
|
+
array = rt['foo']
|
51
|
+
|
52
|
+
other = []
|
53
|
+
array.each do |thing|
|
54
|
+
other << thing
|
55
|
+
end
|
56
|
+
assert_equal [1,2,3,4,5], other
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_to_a
|
61
|
+
Phuby::Runtime.php do |rt|
|
62
|
+
rt.eval('$foo = array(1,2,3,4,5);')
|
63
|
+
|
64
|
+
array = rt['foo']
|
65
|
+
|
66
|
+
assert_equal [1,2,3,4,5], array.to_a
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_get
|
71
|
+
Phuby::Runtime.php do |rt|
|
72
|
+
rt.eval('$_GET["foo"] = "bar";')
|
73
|
+
#rt.eval('var_dump($_GET);')
|
74
|
+
|
75
|
+
assert_equal 'bar', rt['_GET']['foo']
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_set
|
80
|
+
Phuby::Runtime.php do |rt|
|
81
|
+
rt['_GET']['foo'] = "bar"
|
82
|
+
rt.eval('$foo = $_GET["foo"];')
|
83
|
+
#rt.eval('var_dump($_GET);')
|
84
|
+
|
85
|
+
assert_equal 'bar', rt['foo']
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_get_non_existent
|
90
|
+
Phuby::Runtime.php do |rt|
|
91
|
+
assert_nil rt['_GET']['foo']
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_key?
|
96
|
+
Phuby::Runtime.php do |rt|
|
97
|
+
rt.eval('$_GET["foo"] = "bar";')
|
98
|
+
assert rt['_GET'].key? 'foo'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestHeaderHandler < Phuby::TestCase
|
4
|
+
def setup
|
5
|
+
super
|
6
|
+
@rt = Phuby::Runtime.instance
|
7
|
+
@rt.start
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
super
|
12
|
+
@rt.stop
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_capture_output
|
16
|
+
quiet = Class.new(Phuby::Events) {
|
17
|
+
attr_accessor :written
|
18
|
+
|
19
|
+
def write string
|
20
|
+
@written ||= []
|
21
|
+
@written << string
|
22
|
+
end
|
23
|
+
}.new
|
24
|
+
|
25
|
+
@rt.with_events(quiet) do |rt|
|
26
|
+
rt.eval 'echo "hello world";'
|
27
|
+
end
|
28
|
+
|
29
|
+
assert_equal ['hello world'], quiet.written
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_header_handler
|
33
|
+
header = Class.new(Phuby::Events) {
|
34
|
+
attr_accessor :headers
|
35
|
+
|
36
|
+
def header header, op
|
37
|
+
@headers ||= []
|
38
|
+
@headers << [header, op]
|
39
|
+
end
|
40
|
+
}.new
|
41
|
+
|
42
|
+
@rt.with_events(header) do |rt|
|
43
|
+
rt.eval 'setcookie("name", "Aaron", time()+3600);'
|
44
|
+
end
|
45
|
+
|
46
|
+
assert_equal 1, header.headers.length
|
47
|
+
assert_equal :store, header.headers.first.last
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestHeaderSent < Phuby::TestCase
|
4
|
+
def test_headers_sent
|
5
|
+
header = Class.new(Phuby::Events) {
|
6
|
+
attr_accessor :response_code
|
7
|
+
|
8
|
+
def send_headers response_code
|
9
|
+
@response_code = response_code
|
10
|
+
end
|
11
|
+
}.new
|
12
|
+
|
13
|
+
@rt = Phuby::Runtime.instance
|
14
|
+
|
15
|
+
@rt.start
|
16
|
+
|
17
|
+
@rt.events = header
|
18
|
+
|
19
|
+
@rt.eval 'header("foo: bar", true, 500);'
|
20
|
+
|
21
|
+
@rt.stop
|
22
|
+
|
23
|
+
assert_equal 500, header.response_code
|
24
|
+
end
|
25
|
+
end
|