Have Fun
Programming
Programming for
      Fun!
@tenderlove
...
Aaron Patterson
AT&T, AT&T logo and all AT&T related marks are trademarks of AT&T Intellectual Property and/or AT&T affiliated companies.
First
Ujihisa!
Q: How can I
                                                             enjoy
                                                        programming?




http://www.flickr.com/photos/recompile_net/3733132232/
A: Use Vim!




http://www.flickr.com/photos/recompile_net/3732334373/
•
•
•
•
Ruby
class
end
6.times {
            .new
}
Thread.new do
        .    ()
end
Thread.new do
      .    ()
end
(Thread.list -[Thread.main]).each
{ |x|
  x.join
}
• Ruby
•C
• Java
• Lisp
• PHP?
We Speak

•
•
•
•
.count


.count
;_;
";_;".encode(   ) # => ":'("
!
/
Ruby Brigades
Seattle.rb
Hack Night
!!!!
!
!
Hallway Track
•
•
•
•
•
• Rails 3
•
• XML
• YAML
0 bugs in Ruby 1.9
50% used Ruby 1.9
YAML
Psych   Syck
Syck

• Ruby 1.8     1.9

• YAML 1.0 (         ) parser   emitter

•
Psych

• Ruby >= 1.9.2
• libyaml
• YAML 1.1 parser   emitter

•
YAML
Ruby 1.8 / 1.9


require 'yaml'

YAML.load_file('some_file.yml')
YAML.load('--- hello world!')
Ruby 1.9.2 / Psych


require 'psych'

Psych.load_file('some_file.yml')
Psych.load('--- hello world!')
1.9.2 Opt-in


require 'yaml'

YAML::ENGINE.yamler = 'psych'

YAML.load('--- this is psych')
YAML
require 'psych'

Psych.dump { :foo => 'bar' }
{ :hello => 'world' }.to_yaml
JSON
YAML Map


---
foo: bar
YAML Map


---
'foo': 'bar'
YAML Map


---
{ 'foo': 'bar' }
require 'psych'

Psych.to_json { :foo => 'bar' }
Psych
Emitter
class Foo
  def initialize
    @greeting = 'world'
  end

 def encode_with(coder)
   coder['hello'] = @greeting
 end

  def init_with(coder)
    @greeting = coder['hello']
  end
end
Psych.dump


--- !ruby/object:Foo
hello: world
Psych.load



#<Foo:0x000001009f6770 @greeting="world">
Independent
class Foo
  def initialize
    @greeting = 'world'
  end

  def encode_with(coder)
    coder['hello'] = @greeting
  end

  def init_with(coder)
    @greeting = coder['hello']
  end
end
YAML            JSON


Psych.dump    Foo.new
Psych.to_json Foo.new
class XMLDumper < Psych::Handler
  def self.dump(object)
    dumper = new
    viz = Psych::Visitors::YAMLTree.new({}, dumper)
    viz << object
    dumper.doc.to_xml
  end

 attr_reader :doc

 def initialize
   @doc      = Nokogiri::XML::Document.new
   @doc.root = @doc.create_element 'root'
   @tags     = []
   @stack    = [@doc.root]
 end

 def start_mapping(anchor, tag, implicit, style)
   tag = @doc.create_element('table')
   @stack.last << tag
   @stack      << tag
 end

 def end_mapping
   @stack.pop
 end

  def scalar(value, anchor, tag, *args)
    @stack.last << @doc.create_element('tr').tap do |tag|
      tag << @doc.create_element('td', value)
    end
  end
end
YAML, JSON
                  XML

Psych.dump     Foo.new
Psych.to_json Foo.new
XMLDumper.dump Foo.new
class HTMLDumper < XMLDumper
  def initialize
    @doc      = Nokogiri::HTML::Document.new
    @doc.root = @doc.create_element('html')
    @doc.root << @doc.create_element('body')
    @tags     = []
    @stack    = [@doc.root.children.first]
  end
end
YAML, JSON, XML
           HTML

Psych.dump        Foo.new
Psych.to_json     Foo.new
XMLDumper.dump    Foo.new
HTMLDumper.dump   Foo.new
module Marshalable
  module ClassMethods
    def _load data
      x = allocate
      x.init_with Marshal.load data
      x
    end
  end

 def self.included klass
   klass.extend ClassMethods
 end

  def _dump o
    coder = {}
    encode_with coder
    Marshal.dump coder
  end
end

class Foo; include Marshalable; end
YAML, JSON, XML,
     HTML   Marshal
Psych.dump        Foo.new
Psych.to_json     Foo.new
XMLDumper.dump    Foo.new
HTMLDumper.dump   Foo.new
Marshal.dump      Foo.new
SQLite3-Ruby
SQLite3-Ruby

• SQLite3
• Jamis Buck
• SWIG
require 'sqlite3'

connection =
  SQLite3::Database.new('file.sqlite3')
Pro Tip


require 'sqlite3'

connection =
  SQLite3::Database.new(':memory:')
Pro Tip


require 'sqlite3'

connection =
  SQLite3::Database.new(':memory:')
connection.execute('CREATE TABLE foo(id INTEGER)')


connection.execute('INSERT INTO foo (id) VALUES (?)', [10])
stmt = connection.prepare('SELECT * FROM foo WHERE id = ?')

stmt.bind_param(1, 10)

stmt.each do |row|
  p row
end
SQLite3
•   1: API


•   2:


•   3:
: API
struct sqlite3_vfs {
   int iVersion;             /* Structure version number */
   int szOsFile;             /* Size of subclassed sqlite3_file */
   int mxPathname;           /* Maximum file pathname length */
   sqlite3_vfs *pNext;       /* Next registered VFS */
   const char *zName;        /* Name of this virtual file system */
   void *pAppData;           /* Pointer to application-specific data */
   int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
                 int flags, int *pOutFlags);
   int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
   int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut);
   int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut);
   void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename);
   void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg);
   void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void);
   void (*xDlClose)(sqlite3_vfs*, void*);
   int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut);
   int (*xSleep)(sqlite3_vfs*, int microseconds);
   int (*xCurrentTime)(sqlite3_vfs*, double*);
   int (*xGetLastError)(sqlite3_vfs*, int, char *);
   /* New fields may be appended in figure versions. The iVersion
   ** value will increment whenever this happens. */
};
IO Hooks
2:
static int rbFile_close(sqlite3_file * ctx)
{
  rubyFilePtr rfile = (rubyFilePtr)ctx;
  VALUE file = rfile->file;
  rb_funcall(file, rb_intern("close"), 0);
  return SQLITE_OK;
}
class VFS < SQLite3::VFS
  def open(name, flags)
    OurFile.new(name, flags)
  end
end

class OurFile
  def read(...); ... end
  def write(...); ... end
end
SQLite Database
__END__ + DATA
class EvilVFS < SQLite3::VFS
  def open name, flags
    DATABase.new name, flags
  end
end

class DATABase < SQLite3::VFS::File
  def initialize name, flags
    super
    @store = File.open(name, File::RDWR | File::CREAT)
    @offset = 0

   if File.expand_path(__FILE__) == name
     @store.seek DATA.pos
     @offset = DATA.pos
   end
 end

 def close
   @store.close
 end

 def read amt, offset
   @store.seek(offset + @offset)
   @store.read amt
 end

 def write data, offset
   @store.seek(offset + @offset)
   @store.write data
 end

 def sync opts
   @store.fsync
 end

  def file_size
    File.size(@store.path) - @offset
  end
end
SQLite3.vfs_register(EvilVFS.new)
db = SQLite3::Database.new(__FILE__, nil, 'EvilVFS')

db.execute(<<-eosql)
  create table if not exists
  users(id integer primary key, name string)
eosql

100.times {
  db.execute(<<-eosql, 'tenderlove')
    insert into users(name) values (?)
  eosql
}

p db.execute('select count(*) from users')

__END__
3:
http://gist.github.com/319224/
SQLite3-Ruby
• Ruby 1.9
• 1000       (   )
require 'sqlite3'

db = SQLite3::Database.new(':memory:')

db.execute('CREATE TABLE foo(id INTEGER, name VARCHAR)')
db.execute('INSERT INTO foo (id, name) VALUES (?,?)',
[10,'hello world'])

rows = db.execute('SELECT name FROM foo')
p rows.first.first.encoding # => #<Encoding:UTF-8>

Encoding.default_internal = 'EUC-JP'

rows = db.execute('SELECT name FROM foo')
p rows.first.first.encoding # => #<Encoding:EUC-JP>
require 'sqlite3'

db = SQLite3::Database.new(':memory:')

db.execute('CREATE TABLE foo(id INTEGER, name VARCHAR)')
db.execute('INSERT INTO foo (id, name) VALUES (?,?)',
[10,'hello world'])

rows = db.execute('SELECT name FROM foo')
p rows.first.first.encoding # => #<Encoding:UTF-8>

Encoding.default_internal = 'EUC-JP'

rows = db.execute('SELECT name FROM foo')
p rows.first.first.encoding # => #<Encoding:EUC-JP>
require 'sqlite3'

db = SQLite3::Database.new(':memory:')

db.execute('CREATE TABLE foo(id INTEGER, name VARCHAR)')
db.execute('INSERT INTO foo (id, name) VALUES (?,?)',
[10,'hello world'])

rows = db.execute('SELECT name FROM foo')
p rows.first.first.encoding # => #<Encoding:UTF-8>

Encoding.default_internal = 'EUC-JP'

rows = db.execute('SELECT name FROM foo')
p rows.first.first.encoding # => #<Encoding:EUC-JP>
(SELECT                         )
                    1.2.5             1.3.0

1000

 100

  10

   1

 0.1

0.01
       500   1000     1500   2000   2500      3000   3500
PHP + Ruby
Phuby!
Ruby.PHP()


Phuby::Runtime.php do |rt|
  rt.eval('$v = strlen("PHP IS AWESOME");')
  puts rt['v'] # => 14
end
Ruby.PHP()

Phuby::Runtime.php do |rt|
  rt.eval('$foo = array();')
  rt.eval('$foo["hello"] = "world";')

  foo = rt['foo'] # => #<Phuby::Array:
0x101f8f848>
  p foo['hello'] # => ‘world’
end
$PHP->Ruby();
class FUN
  def times
    puts "hello"
  end
end

Phuby::Runtime.php do |rt|
  rt['fun'] = FUN.new
  rt.eval('$fun->times();') # => hello
end
PHP
Variable
 Ruby
PHP
rt['foo'] = Foo.new
Ruby          C        PHP

  Weak
              Proxy
Reference               PHP
            (runtime)
  Table




  Ruby
Ruby          C        PHP

  Weak
              Proxy
Reference               PHP
            (runtime)
  Table




  Ruby
PHP   Ruby
$foo->bar();
Ruby          C        PHP

  Weak
              Proxy
Reference               PHP
            (runtime)
  Table




  Ruby
Ruby          C        PHP

  Weak
              Proxy
Reference               PHP
            (runtime)
  Table




  Ruby
Ruby   PHP
rt['foo'].bar()
Ruby      C        PHP


         Proxy
Ruby               PHP
       (runtime)
Ruby      C        PHP


         Proxy
Ruby               PHP
       (runtime)




        Proxy
       (object)
Phuby
PHP + WEBrick
      =
    Blog
#!/usr/bin/env ruby

require 'rubygems'
require 'phuby'
require 'rack'

##
# Rack::Phrack is a Rack handler that will evaulate and serve PHP files.

class Rack::Phrack < Rack::File
  class Events < Struct.new(:code, :headers, :body)
    def write string; body << string; end
    def send_headers response_code;   end

    def header value, op
      k, v = value.split(': ', 2)
      self.code = 302 if k == 'Location'
      headers[k] = [headers[k], Rack::Utils.unescape(v)].compact.join "n"
    end
  end

  def call   env
    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|
        rt.eval "date_default_timezone_set('America/Los_Angeles');" # *shrug*

        { Rack::Utils.parse_query(env['QUERY_STRING'])     => "_GET",
          Rack::Utils.parse_query(env['rack.input'].read) => "_POST",
          Rack::Utils.parse_query(env['HTTP_COOKIE'], ';') => "_COOKIE",
        }.each do |from, to|
          from.each { |k,v| rt[to][k] = v }
        end

        env.each { |k,v| rt['_SERVER'][k] = v || '' unless k =~ /^rack/ }
        rt["_SERVER"]['REQUEST_URI'] = env['PATH_INFO']

        rt.with_events(events) { open(file) { |f| rt.eval f } } # RUN!
      end
    end
    events.to_a
  end
end

Rack::Handler::WEBrick.run(Rack::Phrack.new(ARGV[0] || Dir.pwd), :Port => 10101)
Client



  Phrack



PHPRuntime
Client



  Phrack



PHPRuntime
Special Thanks!
aka @masuidrive
zenspider
Special Request
One Click Installer




    Luis Lavena
Having Fun Programming!
Having Fun Programming!

Having Fun Programming!

  • 2.
  • 3.
  • 4.
  • 8.
  • 9.
  • 10.
    AT&T, AT&T logoand all AT&T related marks are trademarks of AT&T Intellectual Property and/or AT&T affiliated companies.
  • 11.
  • 13.
  • 14.
    Q: How canI enjoy programming? http://www.flickr.com/photos/recompile_net/3733132232/
  • 15.
  • 16.
  • 22.
  • 27.
  • 29.
    Thread.new do . () end Thread.new do . () end (Thread.list -[Thread.main]).each { |x| x.join }
  • 31.
  • 34.
  • 35.
  • 36.
    ;_; ";_;".encode( ) # => ":'("
  • 42.
  • 49.
  • 54.
  • 55.
  • 56.
  • 61.
  • 62.
  • 63.
  • 65.
  • 69.
  • 70.
    • Rails 3 • •XML • YAML
  • 71.
    0 bugs inRuby 1.9
  • 72.
  • 75.
  • 76.
    Syck • Ruby 1.8 1.9 • YAML 1.0 ( ) parser emitter •
  • 77.
    Psych • Ruby >=1.9.2 • libyaml • YAML 1.1 parser emitter •
  • 78.
  • 79.
    Ruby 1.8 /1.9 require 'yaml' YAML.load_file('some_file.yml') YAML.load('--- hello world!')
  • 80.
    Ruby 1.9.2 /Psych require 'psych' Psych.load_file('some_file.yml') Psych.load('--- hello world!')
  • 81.
    1.9.2 Opt-in require 'yaml' YAML::ENGINE.yamler= 'psych' YAML.load('--- this is psych')
  • 82.
  • 83.
    require 'psych' Psych.dump {:foo => 'bar' } { :hello => 'world' }.to_yaml
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
    class Foo def initialize @greeting = 'world' end def encode_with(coder) coder['hello'] = @greeting end def init_with(coder) @greeting = coder['hello'] end end
  • 92.
  • 93.
  • 94.
    Independent class Foo def initialize @greeting = 'world' end def encode_with(coder) coder['hello'] = @greeting end def init_with(coder) @greeting = coder['hello'] end end
  • 95.
    YAML JSON Psych.dump Foo.new Psych.to_json Foo.new
  • 96.
    class XMLDumper <Psych::Handler def self.dump(object) dumper = new viz = Psych::Visitors::YAMLTree.new({}, dumper) viz << object dumper.doc.to_xml end attr_reader :doc def initialize @doc = Nokogiri::XML::Document.new @doc.root = @doc.create_element 'root' @tags = [] @stack = [@doc.root] end def start_mapping(anchor, tag, implicit, style) tag = @doc.create_element('table') @stack.last << tag @stack << tag end def end_mapping @stack.pop end def scalar(value, anchor, tag, *args) @stack.last << @doc.create_element('tr').tap do |tag| tag << @doc.create_element('td', value) end end end
  • 97.
    YAML, JSON XML Psych.dump Foo.new Psych.to_json Foo.new XMLDumper.dump Foo.new
  • 98.
    class HTMLDumper <XMLDumper def initialize @doc = Nokogiri::HTML::Document.new @doc.root = @doc.create_element('html') @doc.root << @doc.create_element('body') @tags = [] @stack = [@doc.root.children.first] end end
  • 99.
    YAML, JSON, XML HTML Psych.dump Foo.new Psych.to_json Foo.new XMLDumper.dump Foo.new HTMLDumper.dump Foo.new
  • 100.
    module Marshalable module ClassMethods def _load data x = allocate x.init_with Marshal.load data x end end def self.included klass klass.extend ClassMethods end def _dump o coder = {} encode_with coder Marshal.dump coder end end class Foo; include Marshalable; end
  • 101.
    YAML, JSON, XML, HTML Marshal Psych.dump Foo.new Psych.to_json Foo.new XMLDumper.dump Foo.new HTMLDumper.dump Foo.new Marshal.dump Foo.new
  • 105.
  • 106.
  • 108.
    require 'sqlite3' connection = SQLite3::Database.new('file.sqlite3')
  • 109.
    Pro Tip require 'sqlite3' connection= SQLite3::Database.new(':memory:')
  • 110.
    Pro Tip require 'sqlite3' connection= SQLite3::Database.new(':memory:')
  • 111.
    connection.execute('CREATE TABLE foo(idINTEGER)') connection.execute('INSERT INTO foo (id) VALUES (?)', [10])
  • 112.
    stmt = connection.prepare('SELECT* FROM foo WHERE id = ?') stmt.bind_param(1, 10) stmt.each do |row| p row end
  • 116.
  • 117.
    1: API • 2: • 3:
  • 118.
    : API struct sqlite3_vfs{ int iVersion; /* Structure version number */ int szOsFile; /* Size of subclassed sqlite3_file */ int mxPathname; /* Maximum file pathname length */ sqlite3_vfs *pNext; /* Next registered VFS */ const char *zName; /* Name of this virtual file system */ void *pAppData; /* Pointer to application-specific data */ int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, int flags, int *pOutFlags); int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut); int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void); void (*xDlClose)(sqlite3_vfs*, void*); int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); int (*xSleep)(sqlite3_vfs*, int microseconds); int (*xCurrentTime)(sqlite3_vfs*, double*); int (*xGetLastError)(sqlite3_vfs*, int, char *); /* New fields may be appended in figure versions. The iVersion ** value will increment whenever this happens. */ };
  • 119.
  • 120.
  • 121.
    static int rbFile_close(sqlite3_file* ctx) { rubyFilePtr rfile = (rubyFilePtr)ctx; VALUE file = rfile->file; rb_funcall(file, rb_intern("close"), 0); return SQLITE_OK; }
  • 122.
    class VFS <SQLite3::VFS def open(name, flags) OurFile.new(name, flags) end end class OurFile def read(...); ... end def write(...); ... end end
  • 123.
  • 124.
  • 125.
    class EvilVFS <SQLite3::VFS def open name, flags DATABase.new name, flags end end class DATABase < SQLite3::VFS::File def initialize name, flags super @store = File.open(name, File::RDWR | File::CREAT) @offset = 0 if File.expand_path(__FILE__) == name @store.seek DATA.pos @offset = DATA.pos end end def close @store.close end def read amt, offset @store.seek(offset + @offset) @store.read amt end def write data, offset @store.seek(offset + @offset) @store.write data end def sync opts @store.fsync end def file_size File.size(@store.path) - @offset end end
  • 126.
    SQLite3.vfs_register(EvilVFS.new) db = SQLite3::Database.new(__FILE__,nil, 'EvilVFS') db.execute(<<-eosql) create table if not exists users(id integer primary key, name string) eosql 100.times { db.execute(<<-eosql, 'tenderlove') insert into users(name) values (?) eosql } p db.execute('select count(*) from users') __END__
  • 127.
  • 129.
  • 130.
  • 131.
  • 132.
    require 'sqlite3' db =SQLite3::Database.new(':memory:') db.execute('CREATE TABLE foo(id INTEGER, name VARCHAR)') db.execute('INSERT INTO foo (id, name) VALUES (?,?)', [10,'hello world']) rows = db.execute('SELECT name FROM foo') p rows.first.first.encoding # => #<Encoding:UTF-8> Encoding.default_internal = 'EUC-JP' rows = db.execute('SELECT name FROM foo') p rows.first.first.encoding # => #<Encoding:EUC-JP>
  • 133.
    require 'sqlite3' db =SQLite3::Database.new(':memory:') db.execute('CREATE TABLE foo(id INTEGER, name VARCHAR)') db.execute('INSERT INTO foo (id, name) VALUES (?,?)', [10,'hello world']) rows = db.execute('SELECT name FROM foo') p rows.first.first.encoding # => #<Encoding:UTF-8> Encoding.default_internal = 'EUC-JP' rows = db.execute('SELECT name FROM foo') p rows.first.first.encoding # => #<Encoding:EUC-JP>
  • 134.
    require 'sqlite3' db =SQLite3::Database.new(':memory:') db.execute('CREATE TABLE foo(id INTEGER, name VARCHAR)') db.execute('INSERT INTO foo (id, name) VALUES (?,?)', [10,'hello world']) rows = db.execute('SELECT name FROM foo') p rows.first.first.encoding # => #<Encoding:UTF-8> Encoding.default_internal = 'EUC-JP' rows = db.execute('SELECT name FROM foo') p rows.first.first.encoding # => #<Encoding:EUC-JP>
  • 135.
    (SELECT ) 1.2.5 1.3.0 1000 100 10 1 0.1 0.01 500 1000 1500 2000 2500 3000 3500
  • 136.
  • 137.
  • 138.
    Ruby.PHP() Phuby::Runtime.php do |rt| rt.eval('$v = strlen("PHP IS AWESOME");') puts rt['v'] # => 14 end
  • 139.
    Ruby.PHP() Phuby::Runtime.php do |rt| rt.eval('$foo = array();') rt.eval('$foo["hello"] = "world";') foo = rt['foo'] # => #<Phuby::Array: 0x101f8f848> p foo['hello'] # => ‘world’ end
  • 140.
    $PHP->Ruby(); class FUN def times puts "hello" end end Phuby::Runtime.php do |rt| rt['fun'] = FUN.new rt.eval('$fun->times();') # => hello end
  • 141.
  • 145.
  • 146.
  • 147.
    Ruby C PHP Weak Proxy Reference PHP (runtime) Table Ruby
  • 148.
    Ruby C PHP Weak Proxy Reference PHP (runtime) Table Ruby
  • 149.
    PHP Ruby
  • 150.
  • 151.
    Ruby C PHP Weak Proxy Reference PHP (runtime) Table Ruby
  • 152.
    Ruby C PHP Weak Proxy Reference PHP (runtime) Table Ruby
  • 153.
    Ruby PHP
  • 154.
  • 155.
    Ruby C PHP Proxy Ruby PHP (runtime)
  • 156.
    Ruby C PHP Proxy Ruby PHP (runtime) Proxy (object)
  • 157.
  • 158.
  • 160.
    #!/usr/bin/env ruby require 'rubygems' require'phuby' require 'rack' ## # Rack::Phrack is a Rack handler that will evaulate and serve PHP files. class Rack::Phrack < Rack::File class Events < Struct.new(:code, :headers, :body) def write string; body << string; end def send_headers response_code; end def header value, op k, v = value.split(': ', 2) self.code = 302 if k == 'Location' headers[k] = [headers[k], Rack::Utils.unescape(v)].compact.join "n" end end def call env 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| rt.eval "date_default_timezone_set('America/Los_Angeles');" # *shrug* { Rack::Utils.parse_query(env['QUERY_STRING']) => "_GET", Rack::Utils.parse_query(env['rack.input'].read) => "_POST", Rack::Utils.parse_query(env['HTTP_COOKIE'], ';') => "_COOKIE", }.each do |from, to| from.each { |k,v| rt[to][k] = v } end env.each { |k,v| rt['_SERVER'][k] = v || '' unless k =~ /^rack/ } rt["_SERVER"]['REQUEST_URI'] = env['PATH_INFO'] rt.with_events(events) { open(file) { |f| rt.eval f } } # RUN! end end events.to_a end end Rack::Handler::WEBrick.run(Rack::Phrack.new(ARGV[0] || Dir.pwd), :Port => 10101)
  • 161.
  • 162.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.