From b42a853d10cfe374f8909d9035931159ee350d37 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 22 Oct 2009 13:16:20 -0700 Subject: [PATCH 1/4] arrays move across --- ext/phuby/phuby_conversions.c | 15 ++++++++++++++- test/test_array.rb | 9 +++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/ext/phuby/phuby_conversions.c b/ext/phuby/phuby_conversions.c index 9a0c50f..72ef5fd 100644 --- a/ext/phuby/phuby_conversions.c +++ b/ext/phuby/phuby_conversions.c @@ -1,4 +1,4 @@ -#include +#include zval * Phuby_value_to_zval(VALUE rt, VALUE value) { @@ -32,6 +32,19 @@ zval * Phuby_value_to_zval(VALUE rt, VALUE value) rb_hash_aset(map, INT2NUM((int)php_value), value); } break; + case T_ARRAY: + { + array_init(php_value); + int i; + for(i = 0; i < RARRAY_LEN(value); i++) { + VALUE key = rb_funcall(INT2NUM(i), rb_intern("to_s"), 0); + VALUE thing = RARRAY_PTR(value)[i]; + add_assoc_zval(php_value, StringValuePtr(key), Phuby_value_to_zval(rt, thing)); + } + VALUE map = rb_iv_get(rt, "@proxy_map"); + rb_hash_aset(map, INT2NUM((int)php_value), value); + } + break; case T_NIL: ZVAL_NULL(php_value); break; diff --git a/test/test_array.rb b/test/test_array.rb index 0c33be7..db05ae3 100644 --- a/test/test_array.rb +++ b/test/test_array.rb @@ -1,6 +1,15 @@ require 'helper' class TestArray < Phuby::TestCase + def test_move_to_runtime + Phuby::Runtime.php do |rt| + rt['foo'] = [1,2,3] + assert_equal 1, rt['foo'][0] + assert_equal 2, rt['foo'][1] + assert_equal 3, rt['foo'][2] + end + end + def test_array_length Phuby::Runtime.php do |rt| rt.eval('$get_length = count($_GET);') From afd1a97abe5c9117c16d508dca282c3066ba1639 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 22 Oct 2009 15:55:16 -0700 Subject: [PATCH 2/4] a rack adapter for phuby --- bin/phrack | 83 +++++++++++++++++++++++++++++++++++ ext/phuby/phuby_conversions.c | 3 +- test/test_object.rb | 6 +++ 3 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 bin/phrack diff --git a/bin/phrack b/bin/phrack new file mode 100644 index 0000000..b0fd66d --- /dev/null +++ b/bin/phrack @@ -0,0 +1,83 @@ +#!/usr/bin/env ruby + +require 'phuby' +require 'rack' + +class Rack::Phrack < Rack::File + class Events < Struct.new(:code, :headers, :body) + def write string + body << string + end + + def header value, op + k, v = value.split(': ', 2) + case k + when 'Location' + self.code = 302 + v = CGI.unescape v + when 'Set-Cookie' + v = [headers[k], v].compact.join "\n" + end + headers[k] = v + end + + def send_headers response_code + end + end + + def call env + code, headers, body = 200, {}, '' + events = Events.new code, headers, body + file = File.join(@root, env['PATH_INFO']) + file = File.join(file, "index.php") if File.directory?(file) + + return super unless file =~ /php$/ + + Dir.chdir(File.dirname(file)) do + Phuby::Runtime.php do |rt| + rt.eval("date_default_timezone_set('America/Los_Angeles');") + + params(env['QUERY_STRING']) do |k,v| + rt["_GET"][k] = v + end + + params(env['rack.input'].read) do |k,v| + rt["_POST"][k] = v + end + + env['HTTP_COOKIE'].split('; ').each do |pair| + k, v = pair.split '=' + rt["_COOKIE"][k] = CGI.unescape(v) + end + + env.each { |k,v| + next if k =~ /^rack/ + rt['_SERVER'][k] = v || '' + } + rt["_SERVER"]['REQUEST_URI'] = env['PATH_INFO'] + + rt.with_events(events) do + File.open(file, 'rb') { |f| + rt.eval f + } + end + end + end + events.to_a + end + + private + def params string + string.split('&').each do |pair| + yield pair.split('=').map { |x| CGI.unescape(x) } + end + end +end + +if $0 == __FILE__ + require 'rack' + require 'rack/showexceptions' + + Rack::Handler::WEBrick.run( + Rack::ShowExceptions.new(Rack::Phrack.new(Dir.pwd)), :Port => 10101) +end diff --git a/ext/phuby/phuby_conversions.c b/ext/phuby/phuby_conversions.c index 72ef5fd..428813a 100644 --- a/ext/phuby/phuby_conversions.c +++ b/ext/phuby/phuby_conversions.c @@ -26,6 +26,7 @@ zval * Phuby_value_to_zval(VALUE rt, VALUE value) ZVAL_STRINGL(php_value, StringValuePtr(value), RSTRING_LEN(value), 1); break; case T_OBJECT: + case T_DATA: { object_init_ex(php_value, php_ruby_proxy); VALUE map = rb_iv_get(rt, "@proxy_map"); @@ -49,7 +50,7 @@ zval * Phuby_value_to_zval(VALUE rt, VALUE value) ZVAL_NULL(php_value); break; default: - rb_raise(rb_eRuntimeError, "Can't convert ruby object: %d", TYPE(value)); + rb_raise(rb_eRuntimeError, "Can't convert ruby object: %s %d", rb_class2name(CLASS_OF(value)), TYPE(value)); } return php_value; diff --git a/test/test_object.rb b/test/test_object.rb index 86d357e..c0caa0b 100644 --- a/test/test_object.rb +++ b/test/test_object.rb @@ -17,6 +17,12 @@ def value x end end + def test_stringio + Phuby::Runtime.php do |rt| + rt['x'] = StringIO.new('') + end + end + def test_method_call x = FunObject.new Phuby::Runtime.php do |rt| From 640cecdcd4e9ed74560f1bb56a6ababa0642d12e Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 22 Oct 2009 16:07:45 -0700 Subject: [PATCH 3/4] cleaning up the php handler --- bin/phrack | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/bin/phrack b/bin/phrack index b0fd66d..02c3453 100644 --- a/bin/phrack +++ b/bin/phrack @@ -2,6 +2,7 @@ require 'phuby' require 'rack' +require 'rack/showexceptions' class Rack::Phrack < Rack::File class Events < Struct.new(:code, :headers, :body) @@ -14,7 +15,7 @@ class Rack::Phrack < Rack::File case k when 'Location' self.code = 302 - v = CGI.unescape v + v = Rack::Utils.unescape v when 'Set-Cookie' v = [headers[k], v].compact.join "\n" end @@ -26,40 +27,40 @@ class Rack::Phrack < Rack::File end def call env - code, headers, body = 200, {}, '' - events = Events.new code, headers, body - file = File.join(@root, env['PATH_INFO']) - file = File.join(file, "index.php") if File.directory?(file) + events = Events.new 200, {}, '' + file = File.join(@root, env['PATH_INFO']) + file = File.join(file, "index.php") if File.directory?(file) return super unless file =~ /php$/ Dir.chdir(File.dirname(file)) do Phuby::Runtime.php do |rt| + + # Set the timezone. *shrug* rt.eval("date_default_timezone_set('America/Los_Angeles');") - params(env['QUERY_STRING']) do |k,v| - rt["_GET"][k] = v - end + # Set the GET parameters in the PHP runtime + params(env['QUERY_STRING']) { |k,v| rt["_GET"][k] = v } - params(env['rack.input'].read) do |k,v| - rt["_POST"][k] = v - end + # Set the POST parameters in the PHP runtime + params(env['rack.input'].read) { |k,v| rt["_POST"][k] = v } + # Set the cookies in the PHP runtime env['HTTP_COOKIE'].split('; ').each do |pair| k, v = pair.split '=' - rt["_COOKIE"][k] = CGI.unescape(v) + rt["_COOKIE"][k] = Rack::Utils.unescape v end + # Set other misc info. env.each { |k,v| next if k =~ /^rack/ rt['_SERVER'][k] = v || '' } rt["_SERVER"]['REQUEST_URI'] = env['PATH_INFO'] + # Evaluate the PHP file rt.with_events(events) do - File.open(file, 'rb') { |f| - rt.eval f - } + File.open(file, 'rb') { |f| rt.eval f } end end end @@ -75,9 +76,6 @@ class Rack::Phrack < Rack::File end if $0 == __FILE__ - require 'rack' - require 'rack/showexceptions' - Rack::Handler::WEBrick.run( Rack::ShowExceptions.new(Rack::Phrack.new(Dir.pwd)), :Port => 10101) end From 6c8d3502cdb71811dfefb4c8f817708abe34f486 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 26 Oct 2009 12:12:46 -0700 Subject: [PATCH 4/4] switching to rack::utils --- bin/phrack | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/bin/phrack b/bin/phrack index 02c3453..3f120cb 100644 --- a/bin/phrack +++ b/bin/phrack @@ -3,7 +3,13 @@ require 'phuby' require 'rack' require 'rack/showexceptions' +require 'logger' +### +# Rack::Phrack is a Rack handler that will evaulate and serve PHP files. +# +# The handler creates a new PHP runtime if it detects that a PHP file has +# been requested. class Rack::Phrack < Rack::File class Events < Struct.new(:code, :headers, :body) def write string @@ -36,6 +42,8 @@ class Rack::Phrack < Rack::File Dir.chdir(File.dirname(file)) do Phuby::Runtime.php do |rt| + rt['_LOGGER'] = Logger.new($stderr) + # Set the timezone. *shrug* rt.eval("date_default_timezone_set('America/Los_Angeles');") @@ -70,12 +78,13 @@ class Rack::Phrack < Rack::File private def params string string.split('&').each do |pair| - yield pair.split('=').map { |x| CGI.unescape(x) } + yield pair.split('=').map { |x| Rack::Utils.unescape(x) } end end end if $0 == __FILE__ Rack::Handler::WEBrick.run( - Rack::ShowExceptions.new(Rack::Phrack.new(Dir.pwd)), :Port => 10101) + Rack::ShowExceptions.new(Rack::Phrack.new(ARGV[0] || Dir.pwd)), + :Port => 10101) end