[QUIZ] Code Cleaning (#26)

R

Ruby Quiz

The three rules of Ruby Quiz:

1. Please do not post any solutions or spoiler discussion for this quiz until
48 hours have passed from the time on this message.

2. Support Ruby Quiz by submitting ideas as often as you can:

http://www.rubyquiz.com/

3. Enjoy!

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

I'm always very vocal about how Ruby Quiz isn't interested in golf and
obfuscation. It's my own private fight for clean code.

To be fair though, you can really learn a lot from practices like golf and
obfuscation. It'll teach you a surprising number of details about the inner
workings of your language of choice. Still principals are principals and if I
bend, word will quickly get out that I've given up the fight. Can't allow that!

Here's my compromise.

This week's challenge is to utterly clean some famous examples of compressed
Ruby code. Refactor the code until it's as readable as possible, whatever that
means to you.

For those that faint at the sight of dense code, I offer a an "easier"
challenge. Try this code by Mauricio Fernández:

#!/usr/bin/ruby -rcgi
H,B=%w'HomePage w7.cgi?n=%s';c=CGI.new'html4';n,d=c['n']!=''?c['n']:H,c['d'];t=`
cat #{n}`;d!=''&&`echo #{t=CGI.escapeHTML(d)} >#{n}`;c.instance_eval{out{h1{n}+
a(B%H){H}+pre{t.gsub(/([A-Z]\w+){2}/){a(B%$&){$&}}}+form("get"){textarea('d'){t
}+hidden('n',n)+submit}}}

If you prefer a "trickier" challenge, I offer this famous code from Florian
Gross:

#!/usr/bin/ruby
# Server: ruby p2p.rb password server public-uri private-uri merge-servers
# Sample: ruby p2p.rb foobar server druby://123.123.123.123:1337
# druby://:1337 druby://foo.bar:1337
# Client: ruby p2p.rb password client server-uri download-pattern [list-only]
# Sample: ruby p2p.rb foobar client druby://localhost:1337 *.rb
################################################################################
# You are not allowed to use this application for anything illegal unless you
# live inside a sane place. Insane places currently include California (see
# link) and might soon include the complete USA. People using this software are
# responsible for themselves. I can't prevent them from doing illegal stuff for
# obvious reasons. So have fun and do whatever you can get away with for now.
#
# http://info.sen.ca.gov/pub/bill/sen/sb_0051-0100/sb_96_bill_20050114_introduced.html
################################################################################
require'drb';F=File;def c(u)DRbObject.new((),u)end;def x(u)[P,u].hash;end;def s(
p)F.basename p[/[^|]+/]end;P,M,U,V,*O=$*;M["s"]?(DRb.start_service V,Class.new{
def p(z=O)O.push(*z).uniq;end;new.methods.map{|m|m[/_[_t]/]||private(m)};def y;(
p(U)+p).map{|u|u!=U&&c(u).f(x(u),p(U))};self;end;def f(c,a=O,t=2)x(U)==c&&t<1?
Dir[s(a)]:t<2?[*open(s(a),"rb")]:p(a)end}.new.y;sleep):c(U).f(x(U)).map{|n|c(n).
f(x(n),V,0).map{|f|s f}.map{|f|O[0]?p(f):eek:pen(f,"wb")<<c(n).f(x(n),f,1)}}

This is a little different from the traditional Ruby Quiz, but I encourage all
to play and learn. I promise to go back to normal challenges next week...
 
D

David A. Black

Hi --

I'm always very vocal about how Ruby Quiz isn't interested in golf and
obfuscation. It's my own private fight for clean code.

It's not private -- see the earlier mentions of the idea of a
Deobfuscation (or Code Amelioration) Contest, going back to 2001 and
revived at my suggestion this year. Many of us are more enthralled
with the easy beauty than the hard-won ugliness of Ruby code :)


David
 
J

James Edward Gray II

Many of us are more enthralled with the easy beauty than the hard-won
ugliness of Ruby code :)

To be fair, I did enter the IORCC, as is now known. That was my first
obfuscation attempt and I do have a whole new appreciation for that
craft. I doubt I would do it again, at least anytime in the near
future, but I did learn a lot from the experience. Have to try it once
so you know what you're missing, right? ;)

Then I carefully arranged this quiz for the day after that contest
ended. <laughs>

James Edward Gray II
 
T

Timothy Byrd

Help!

I would find if handy to know how to use Mauricio Fernández's code.
When I run it, I get:

(offline mode: enter name=value pairs on standard input)

What am I supposed to do with it then?

-- Timothy
 
P

Patrick Hurley

Help!

I would find if handy to know how to use Mauricio Fernández's code.
When I run it, I get:

(offline mode: enter name=value pairs on standard input)

What am I supposed to do with it then?

-- Timothy

I have not looked at the code, but it sure sounds like a CGI script
 
B

Bill Guindon

Help!

I would find if handy to know how to use Mauricio Fernández's code.
When I run it, I get:

(offline mode: enter name=value pairs on standard input)

What am I supposed to do with it then?

I'm guessing you're running on Win, if I'm guessing right... type
something in, hit Ctrl-z, then Enter.
You'll also want to change "cat" to "type".
 
J

James Edward Gray II

Help!

I would find if handy to know how to use Mauricio Fernández's code.

There are multiple ways to find this out. That's one of the steps of
Code Reading/Code Archeology, eh? ;)

The "-rcgi" on the first line of that one is a big hint, as others have
pointed out. Get it behind a Web server and play a little. Use Ruby's
included web server, WEBrick, if needed.

That's only one way to find out though. Both programs chosen are
semi-famous... ;)

Good luck!

James Edward Gray II

P.S. "Code Reading: The Open Source Perspective" is a challenging but
sensational read on this very topic, for geeks like me that think this
exercise is fun.
 
T

Timothy Byrd

Perhaps, I should rephrase.

Yes, I'd already gotten as far as the replies so far. But to go into
detail on how for I've gotten would be a spoiler. I guess I'm like a
method actor asking "What's my motivation here?"

-- Timothy
 
J

James Edward Gray II

Here's my solution to the first script. See Thursday's summary for how
it came about...

James Edward Gray II

#!/usr/local/bin/ruby

# wiki.cgi

require 'cgi'

HOME = 'HomePage'
LINK = 'wiki.cgi?name=%s'

query = CGI.new 'html4'

# fetch query data
page_name = if query['name'] == '' then HOME else query['name'] end
page_changes = query['changes']

# fetch file content for this page, unless it's a new page
content = File.read(page_name) rescue content = ''

# save page changes, if needed
unless page_changes == ''
content = CGI.escapeHTML(page_changes)
File.open(page_name, 'w') { |f| f.write content }
end

# output requested page
query.instance_eval do
out do
h1 { page_name } +
a(LINK % HOME) { HOME } +
pre do # content area
content.gsub(/([A-Z]\w+){2}/) do |match|
a(LINK % match) { match }
end
end +
form('get') do # update from
textarea('changes') { content } +
hidden('name', page_name) +
submit
end
end
end
 
J

James Edward Gray II

I guess I'm like a method actor asking "What's my motivation here?"

I doubt I can answer that for you, but mine was:

* To practice my refactoring skills.
* To learn more about Wikis and Peer-to-Peer servers.
* To learn more about tools like WEBrick and DRb.
* To increase my understanding of shortcut language constructs.

Hope that helps.

James Edward Gray II
 
J

James Edward Gray II

Here's my solution to the first script. See Thursday's summary for
how it came about...

And here's my best attempt at the trickier second one.

James Edward Gray II

#!/usr/local/bin/ruby

# p2p.rb

# Server: ruby p2p.rb password server public-uri private-uri
merge-servers
# Sample: ruby p2p.rb foobar server druby://123.123.123.123:1337
# druby://:1337 druby://foo.bar:1337
# Client: ruby p2p.rb password client server-uri download-pattern
[list-only]
# Sample: ruby p2p.rb foobar client druby://localhost:1337 *.rb
########################################################################
########
# You are not allowed to use this application for anything illegal
unless you
# live inside a sane place. Insane places currently include California
(see
# link) and might soon include the complete USA. People using this
software are
# responsible for themselves. I can't prevent them from doing illegal
stuff for
# obvious reasons. So have fun and do whatever you can get away with
for now.
#
#
http://info.sen.ca.gov/pub/bill/sen/sb_0051-0100/
sb_96_bill_20050114_introduced.html
########################################################################
########

require'drb'

# define utility methods
def create_drb_object( uri )
DRbObject.new(nil, uri)
end

def encode( uri )
[PASSWORD, uri].hash
end

def make_safe( path )
File.basename(path[/[^|]+/])
end

# parse command-line options
PASSWORD, MODE, URI, VAR, *OPTIONS = ARGV

# define server operation
class Server
new.methods.map{ |method| private(method) unless method[/_[_t]/] }

def initialize
@servers = OPTIONS.dup
add(URI)
@servers.each do |u|
create_drb_object(u).add(URI) unless u == URI
end
end

attr_reader :servers

def add( z = OPTIONS )
@servers.push(*z).uniq!
@servers
end

def list( code, pattern )
if encode(URI) == code
Dir[make_safe(pattern)]
else
@servers
end
end

def read( file )
open(make_safe(file), "rb").read
end
end

if MODE["s"] # server
DRb.start_service(VAR, Server.new)
sleep
else # client
servers = create_drb_object(URI).servers
servers.each do |server|
files = create_drb_object(server).list(encode(server), VAR).map do |f|
make_safe f
end
files.each do |file|
if OPTIONS[0]
p(file)
else
open(file, "wb") do |f|
f << create_drb_object(server).read(file)
end
end
end
end
end
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top