phuby 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,23 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'autotest/restart'
4
+
5
+ # Autotest.add_hook :initialize do |at|
6
+ # at.extra_files << "../some/external/dependency.rb"
7
+ #
8
+ # at.libs << ":../some/external"
9
+ #
10
+ # at.add_exception 'vendor'
11
+ #
12
+ # at.add_mapping(/dependency.rb/) do |f, _|
13
+ # at.files_matching(/test_.*rb$/)
14
+ # end
15
+ #
16
+ # %w(TestA TestB).each do |klass|
17
+ # at.extra_class_map[klass] = "test/test_misc.rb"
18
+ # end
19
+ # end
20
+
21
+ # Autotest.add_hook :run_command do |at|
22
+ # system "rake build"
23
+ # end
@@ -0,0 +1,6 @@
1
+ === 1.0.0 / 2009-07-31
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
@@ -0,0 +1,35 @@
1
+ .autotest
2
+ CHANGELOG.rdoc
3
+ Manifest.txt
4
+ README.rdoc
5
+ Rakefile
6
+ bin/phrack
7
+ bin/phuby
8
+ bin/phuby_server
9
+ ext/phuby/extconf.rb
10
+ ext/phuby/phuby.c
11
+ ext/phuby/phuby.h
12
+ ext/phuby/phuby_array.c
13
+ ext/phuby/phuby_array.h
14
+ ext/phuby/phuby_conversions.c
15
+ ext/phuby/phuby_conversions.h
16
+ ext/phuby/phuby_runtime.c
17
+ ext/phuby/phuby_runtime.h
18
+ lib/phuby.rb
19
+ lib/phuby/array.rb
20
+ lib/phuby/events.rb
21
+ lib/phuby/php_handler.rb
22
+ lib/phuby/rails.rb
23
+ lib/phuby/runtime.rb
24
+ php.patch
25
+ test/assets/hello_world.php
26
+ test/assets/htdocs/index.php
27
+ test/helper.rb
28
+ test/test_array.rb
29
+ test/test_handlers.rb
30
+ test/test_header_sent.rb
31
+ test/test_nil.rb
32
+ test/test_object.rb
33
+ test/test_php_handler.rb
34
+ test/test_phuby.rb
35
+ test/test_runtime.rb
@@ -0,0 +1,96 @@
1
+ = phuby
2
+
3
+ * http://github.com/tenderlove/phuby
4
+
5
+ == DESCRIPTION:
6
+
7
+ Phuby wraps PHP in a loving embrace. Exposes a PHP runtime in ruby
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * many
12
+
13
+ == SYNOPSIS:
14
+
15
+ rt = Phuby::Runtime.new
16
+ rt.start
17
+
18
+ rt.eval('$hello = "world"')
19
+ assert_equal "world", rt['hello']
20
+
21
+ rt.stop
22
+
23
+ == REQUIREMENTS:
24
+
25
+ * php
26
+
27
+ == BUILD INSTRUCTIONS:
28
+
29
+ * Download php-5.3.0
30
+
31
+ The following instructions apply to OS X (probably not needed on linux):
32
+
33
+ DO NOT change the prefix... No, I don't know why yet.
34
+
35
+ === Install iconv with macports
36
+
37
+ $ sudo port install iconv
38
+
39
+ === Install MySQL with macports
40
+
41
+ $ sudo port install mysql5 mysql5-server
42
+
43
+ Set some symbolic links:
44
+
45
+ $ cd /opt/local
46
+ $ sudo ln -s mysql5/mysql include/mysql
47
+ $ sudo ln -s mysql5/mysql/libmysqlclient.15.dylib lib/libmysqlclient.dylib
48
+
49
+ === Patch and configure php
50
+
51
+ If you're on OS X, apply php.patch to the downloaded php. Then configure
52
+ php with the proper flags. These paths are for OS X, but you should be able
53
+ to adjust them for linux:
54
+
55
+ $ patch -p0 < ../path/to/php.patch
56
+
57
+ $ ./configure --enable-debug \
58
+ --enable-embed \
59
+ --disable-cli \
60
+ --with-mysql=/opt/local \
61
+ --with-mysqli=/opt/local/lib/mysql5/bin/mysql_config \
62
+ --with-mysql-sock=/opt/local/var/run/mysql5/mysqld.sock \
63
+ --prefix=/usr/local
64
+
65
+ $ make && sudo make install
66
+
67
+ Then, either install the gem, or rake test
68
+
69
+ == INSTALL:
70
+
71
+ * No.
72
+
73
+ == LICENSE:
74
+
75
+ (The MIT License)
76
+
77
+ Copyright (c) Aaron Patterson and Ryan Davis of Seattle.rb
78
+
79
+ Permission is hereby granted, free of charge, to any person obtaining
80
+ a copy of this software and associated documentation files (the
81
+ 'Software'), to deal in the Software without restriction, including
82
+ without limitation the rights to use, copy, modify, merge, publish,
83
+ distribute, sublicense, and/or sell copies of the Software, and to
84
+ permit persons to whom the Software is furnished to do so, subject to
85
+ the following conditions:
86
+
87
+ The above copyright notice and this permission notice shall be
88
+ included in all copies or substantial portions of the Software.
89
+
90
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
91
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
92
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
93
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
94
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
95
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
96
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,23 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ gem 'rake-compiler', '>= 0.4.1'
6
+ require "rake/extensiontask"
7
+
8
+ HOE = Hoe.spec 'phuby' do
9
+ developer('Aaron Patterson', 'aaronp@rubyforge.org')
10
+ self.readme_file = 'README.rdoc'
11
+ self.history_file = 'CHANGELOG.rdoc'
12
+ self.extra_rdoc_files = FileList['*.rdoc']
13
+
14
+ self.spec_extras = { :extensions => ["ext/phuby/extconf.rb"] }
15
+ end
16
+
17
+ RET = Rake::ExtensionTask.new("phuby", HOE.spec) do |ext|
18
+ ext.lib_dir = File.join('lib', 'phuby')
19
+ end
20
+
21
+ Rake::Task[:test].prerequisites << :compile
22
+
23
+ # vim: syntax=ruby
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'phuby'
5
+ require 'rack'
6
+
7
+ ##
8
+ # Rack::Phrack is a Rack handler that will evaulate and serve PHP files.
9
+
10
+ class Rack::Phrack < Rack::File
11
+ class Events < Struct.new(:code, :headers, :body)
12
+ def write string; body << string; end
13
+ def send_headers response_code; end
14
+
15
+ def header value, op
16
+ k, v = value.split(': ', 2)
17
+ self.code = 302 if k == 'Location'
18
+ headers[k] = [headers[k], Rack::Utils.unescape(v)].compact.join "\n"
19
+ end
20
+ end
21
+
22
+ def call env
23
+ events = Events.new 200, {}, ''
24
+ file = File.join @root, env['PATH_INFO']
25
+ file = File.join file, "index.php" if File.directory?(file)
26
+
27
+ return super unless file =~ /php$/
28
+
29
+ Dir.chdir(File.dirname(file)) do
30
+ Phuby::Runtime.php do |rt|
31
+ rt.eval "date_default_timezone_set('America/Los_Angeles');" # *shrug*
32
+
33
+ { Rack::Utils.parse_query(env['QUERY_STRING']) => "_GET",
34
+ Rack::Utils.parse_query(env['rack.input'].read) => "_POST",
35
+ Rack::Utils.parse_query(env['HTTP_COOKIE'], ';') => "_COOKIE",
36
+ }.each do |from, to|
37
+ from.each { |k,v| rt[to][k] = v }
38
+ end
39
+
40
+ env.each { |k,v| rt['_SERVER'][k] = v || '' unless k =~ /^rack/ }
41
+ rt["_SERVER"]['REQUEST_URI'] = env['PATH_INFO']
42
+
43
+ rt.with_events(events) { open(file) { |f| rt.eval f } } # RUN!
44
+ end
45
+ end
46
+ events.to_a
47
+ end
48
+ end
49
+
50
+ Rack::Handler::WEBrick.run(Rack::Phrack.new(ARGV[0] || Dir.pwd), :Port => 10101)
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ abort "you need to write me"
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'phuby'
5
+ require 'webrick'
6
+
7
+ s = WEBrick::HTTPServer.new(:Port => 10101, :DocumentRoot => ARGV[0])
8
+
9
+ s.mount('/', Phuby::PHPHandler)
10
+
11
+ trap('INT') { s.shutdown }
12
+ s.start
@@ -0,0 +1,24 @@
1
+ ENV['RC_ARCHS'] = '' if RUBY_PLATFORM =~ /darwin/
2
+
3
+ # :stopdoc:
4
+
5
+ require 'mkmf'
6
+
7
+ config = Dir["/{usr,opt}/local/bin/php-config"]
8
+ prefix = `#{config} --prefix`.chomp
9
+
10
+ php_inc, php_lib = dir_config("php5", "#{prefix}/include", "#{prefix}/lib")
11
+
12
+ $INCFLAGS = "-I#{File.join(php_inc, "php").quote} #{$INCFLAGS}"
13
+
14
+ %w{ Zend TSRM main }.each do |dir|
15
+ $INCFLAGS = "-I#{File.join(php_inc, "php", dir).quote} #{$INCFLAGS}"
16
+ end
17
+
18
+ unless find_library("php5", "php_embed_init", php_lib)
19
+ abort "php is missing!"
20
+ end
21
+
22
+ create_makefile("phuby/phuby")
23
+
24
+ # :startdoc:
@@ -0,0 +1,11 @@
1
+ #include <phuby.h>
2
+
3
+ VALUE mPhuby;
4
+
5
+ void Init_phuby()
6
+ {
7
+ mPhuby = rb_define_module("Phuby");
8
+
9
+ init_phuby_runtime();
10
+ init_phuby_array();
11
+ }
@@ -0,0 +1,14 @@
1
+ #ifndef PHUBY
2
+ #define PHUBY
3
+
4
+ #include <stdlib.h>
5
+ #include <ruby.h>
6
+ #include <sapi/embed/php_embed.h>
7
+
8
+ #include <phuby_conversions.h>
9
+ #include <phuby_runtime.h>
10
+ #include <phuby_array.h>
11
+
12
+ extern VALUE mPhuby;
13
+
14
+ #endif
@@ -0,0 +1,92 @@
1
+ #include <phuby.h>
2
+
3
+ VALUE cPhubyArray;
4
+
5
+ VALUE Data_Wrap_PhubyArray(VALUE rt, zval * value)
6
+ {
7
+ VALUE arry = Data_Wrap_Struct(cPhubyArray, 0, 0, value);
8
+ rb_iv_set(arry, "@runtime", rt);
9
+ return arry;
10
+ }
11
+
12
+ static VALUE length(VALUE self)
13
+ {
14
+ zval * array;
15
+
16
+ Data_Get_Struct(self, zval, array);
17
+
18
+ return INT2NUM(zend_hash_num_elements(Z_ARRVAL_P(array)));
19
+ }
20
+
21
+ static VALUE get(VALUE self, VALUE key)
22
+ {
23
+ zval * array;
24
+ zval **value;
25
+
26
+ Data_Get_Struct(self, zval, array);
27
+
28
+ switch(TYPE(key))
29
+ {
30
+ case T_FIXNUM:
31
+ if(SUCCESS == zend_hash_index_find(
32
+ Z_ARRVAL_P(array),
33
+ NUM2INT(key),
34
+ (void **)&value
35
+ )) {
36
+ return ZVAL2VALUE(rb_iv_get(self, "@runtime"), *value);
37
+ }
38
+ break;
39
+ default:
40
+ if(SUCCESS == zend_hash_find(
41
+ Z_ARRVAL_P(array),
42
+ StringValuePtr(key),
43
+ RSTRING_LEN(key) + 1, // Add one for the NULL byte
44
+ (void **)&value
45
+ )) {
46
+ return ZVAL2VALUE(rb_iv_get(self, "@runtime"), *value);
47
+ }
48
+ }
49
+
50
+ return Qnil;
51
+ }
52
+
53
+ static VALUE set(VALUE self, VALUE key, VALUE value)
54
+ {
55
+ zval * array;
56
+
57
+ Data_Get_Struct(self, zval, array);
58
+
59
+ VALUE s_key = rb_funcall(key, rb_intern("to_s"), 0);
60
+
61
+ add_assoc_zval(array,
62
+ StringValuePtr(s_key),
63
+ VALUE2ZVAL(rb_iv_get(self, "@runtime"), value)
64
+ );
65
+
66
+ return self;
67
+ }
68
+
69
+ static VALUE key_eh(VALUE self, VALUE key)
70
+ {
71
+ zval * array;
72
+ zval **value;
73
+
74
+ Data_Get_Struct(self, zval, array);
75
+
76
+ if(zend_hash_exists(Z_ARRVAL_P(array),
77
+ StringValuePtr(key), RSTRING_LEN(key) + 1)) {
78
+ return Qtrue;
79
+ }
80
+
81
+ return Qfalse;
82
+ }
83
+
84
+ void init_phuby_array()
85
+ {
86
+ cPhubyArray = rb_define_class_under(mPhuby, "Array", rb_cObject);
87
+
88
+ rb_define_method(cPhubyArray, "length", length, 0);
89
+ rb_define_method(cPhubyArray, "get", get, 1);
90
+ rb_define_method(cPhubyArray, "set", set, 2);
91
+ rb_define_method(cPhubyArray, "key?", key_eh, 1);
92
+ }
@@ -0,0 +1,9 @@
1
+ #ifndef PHUBY_ARRAY
2
+ #define PHUBY_ARRAY
3
+
4
+ extern VALUE cPhubyArray;
5
+
6
+ void init_phuby_array();
7
+ VALUE Data_Wrap_PhubyArray(VALUE rt, zval * value);
8
+
9
+ #endif
@@ -0,0 +1,92 @@
1
+ #include <phuby.h>
2
+
3
+ zval * Phuby_value_to_zval(VALUE rt, VALUE value)
4
+ {
5
+ zval *php_value;
6
+
7
+ MAKE_STD_ZVAL(php_value);
8
+
9
+ switch(TYPE(value))
10
+ {
11
+ case T_FIXNUM:
12
+ ZVAL_LONG(php_value, NUM2INT(value));
13
+ break;
14
+
15
+ case T_TRUE:
16
+ case T_FALSE:
17
+ ZVAL_BOOL(php_value, value == Qtrue ? 1 : 0);
18
+ break;
19
+
20
+ case T_FLOAT:
21
+ case T_BIGNUM:
22
+ ZVAL_DOUBLE(php_value, NUM2DBL(value));
23
+ break;
24
+
25
+ case T_STRING:
26
+ ZVAL_STRINGL(php_value, StringValuePtr(value), RSTRING_LEN(value), 1);
27
+ break;
28
+ case T_OBJECT:
29
+ case T_DATA:
30
+ {
31
+ object_init_ex(php_value, php_ruby_proxy);
32
+ VALUE map = rb_iv_get(rt, "@proxy_map");
33
+ rb_hash_aset(map, INT2NUM((int)php_value), value);
34
+ }
35
+ break;
36
+ case T_ARRAY:
37
+ {
38
+ array_init(php_value);
39
+ int i;
40
+ for(i = 0; i < RARRAY_LEN(value); i++) {
41
+ VALUE key = rb_funcall(INT2NUM(i), rb_intern("to_s"), 0);
42
+ VALUE thing = RARRAY_PTR(value)[i];
43
+ add_assoc_zval(php_value, StringValuePtr(key), Phuby_value_to_zval(rt, thing));
44
+ }
45
+ VALUE map = rb_iv_get(rt, "@proxy_map");
46
+ rb_hash_aset(map, INT2NUM((int)php_value), value);
47
+ }
48
+ break;
49
+ case T_NIL:
50
+ ZVAL_NULL(php_value);
51
+ break;
52
+ default:
53
+ rb_raise(rb_eRuntimeError, "Can't convert ruby object: %s %d", rb_class2name(CLASS_OF(value)), TYPE(value));
54
+ }
55
+
56
+ return php_value;
57
+ }
58
+
59
+ VALUE Phuby_zval_to_value(VALUE rt, zval * value)
60
+ {
61
+ switch(Z_TYPE_P(value)) {
62
+ case IS_NULL:
63
+ return Qnil;
64
+ break;
65
+ case IS_BOOL:
66
+ if(Z_BVAL_P(value))
67
+ return Qtrue;
68
+ else
69
+ return Qfalse;
70
+ break;
71
+ case IS_LONG:
72
+ return INT2NUM(Z_LVAL_P(value));
73
+ break;
74
+ case IS_DOUBLE:
75
+ return rb_float_new(Z_DVAL_P(value));
76
+ break;
77
+ case IS_STRING:
78
+ return rb_str_new(Z_STRVAL_P(value), Z_STRLEN_P(value));
79
+ break;
80
+ case IS_ARRAY:
81
+ return Data_Wrap_PhubyArray(rt, value);
82
+ break;
83
+ case IS_OBJECT:
84
+ {
85
+ VALUE map = rb_iv_get(rt, "@proxy_map");
86
+ return rb_hash_aref(map, INT2NUM((int)value));
87
+ }
88
+ default:
89
+ rb_raise(rb_eRuntimeError, "Whoa, I don't know how to convert that");
90
+ }
91
+ }
92
+