@@ -0,0 +1,217 @@
require "uri"
require "net/https"
require "resolv"
require "ipaddr"
class Sponge
MAX_TIME = 60
MAX_DNS_TIME = 5
attr_accessor :debug, :last_res, :timeout
# rfc3330
BAD_NETS = [
"0.0.0.0/8",
"10.0.0.0/8",
"127.0.0.0/8",
"169.254.0.0/16",
"172.16.0.0/12",
"192.0.2.0/24",
"192.88.99.0/24",
"192.168.0.0/16",
"198.18.0.0/15",
"224.0.0.0/4",
"240.0.0.0/4"
]
# old api
def self.fetch(url, headers = {}, limit = 10)
s = Sponge.new
s.fetch(url, "get", nil, nil, headers, limit)
end
def initialize
@cookies = {}
@timeout = MAX_TIME
end
def set_cookie(host, name, val)
dputs "setting cookie #{name} on domain #{host} to #{val}"
if !@cookies[host]
@cookies[host] = {}
end
if val.to_s == ""
@cookies[host][name] ? @cookies[host][name].delete : nil
else
@cookies[host][name] = val
end
end
def cookies(host)
cooks = @cookies[host] || {}
# check for domain cookies
@cookies.keys.each do |dom|
if dom.length < host.length &&
dom == host[host.length - dom.length .. host.length - 1]
dputs "adding domain keys from #{dom}"
cooks = cooks.merge @cookies[dom]
end
end
if cooks
return cooks.map{|k,v| "#{k}=#{v};" }.join(" ")
else
return ""
end
end
def fetch(url, method = :get, fields = nil, raw_post_data = nil,
headers = {}, limit = 10)
raise ArgumentError, "http redirection too deep" if limit <= 0
uri = URI.parse(url)
# we'll manually resolve the ip so we can verify it's not local
ip = nil
tip = nil
ips = []
retried = false
begin
Timeout.timeout(MAX_DNS_TIME) do
ips = Resolv.getaddresses(uri.host)
if !ips.any?
raise
end
# pick a random one
tip = ips[rand(ips.length)]
ip = IPAddr.new(tip)
end
rescue Timeout::Error => e
if retried
raise "couldn't resolve #{uri.host} (DNS timeout)"
else
retried = true
retry
end
rescue StandardError => e
raise "couldn't resolve #{uri.host} (#{e.inspect})"
end
if !ip
raise "couldn't resolve #{uri.host}"
end
if BAD_NETS.select{|n| IPAddr.new(n).include?(ip) }.any?
raise "refusing to talk to IP #{ip.to_s}"
end
host = Net::HTTP.new(ip.to_s, uri.port)
if self.debug
host.set_debug_output $stdout
end
if uri.scheme == "https"
host.use_ssl = true
host.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
path = (uri.path == "" ? "/" : uri.path)
if uri.query
path += "?" + uri.query
elsif method == :get && raw_post_data
path += "?" + URI.encode(raw_post_data)
headers["Content-type"] = "application/x-www-form-urlencoded"
end
if method == :post
if raw_post_data
post_data = raw_post_data
headers["Content-type"] = "application/x-www-form-urlencoded"
else
post_data = fields.map{|k,v| "#{k}=#{v}" }.join("&")
end
headers["Content-Length"] = post_data.length.to_s
end
path.gsub!(/^\/\//, "/")
dputs "fetching #{url} (#{ip.to_s}) " + (uri.user ? "with http auth " +
uri.user + "/" + ("*" * uri.password.length) + " " : "") +
"by #{method} with cookies #{cookies(uri.host)}"
headers = {
"Host" => uri.host,
"Cookie" => cookies(uri.host),
"Referer" => url.to_s,
"User-Agent" => "Mozilla/5.0 (compatible)",
}.merge(headers || {})
if uri.user
headers["Authorization"] = "Basic " +
["#{uri.user}:#{uri.password}"].pack('m').delete("\r\n")
end
res = nil
Timeout.timeout(self.timeout) do
if method == :post
res = host.post(path, post_data, headers)
else
res = host.get(path, headers)
end
end
if res.get_fields("Set-Cookie")
res.get_fields("Set-Cookie").each do |cook|
if p = Regexp.new(/^([^=]+)=([^;]*)/).match(cook)
set_cookie(uri.host, p[1], p[2])
else
dputs "unable to match cookie line #{cook}"
end
end
end
last_res = res
case res
when Net::HTTPSuccess
return res.body
when Net::HTTPRedirection
# follow
newuri = URI.parse(res["location"])
if newuri.host
dputs "following redirection to " + res["location"]
else
# relative path
newuri.host = uri.host
newuri.scheme = uri.scheme
newuri.port = uri.port
newuri.path = "/#{newuri.path}"
dputs "following relative redirection to " + newuri.to_s
end
fetch(newuri.to_s, "get", nil, nil, headers, limit - 1)
end
end
def get(url)
fetch(url, "get")
end
def post(url, fields)
fetch(url, "post", fields)
end
private
def dputs(string)
if self.debug
puts string
end
end
end
@@ -0,0 +1,16 @@
class Utils
def self.random_str(len)
str = ""
while str.length < len
chr = OpenSSL::Random.random_bytes(1)
ord = chr.unpack('C')[0]
# 0 9 A Z a z
if (ord >= 48 && ord <= 57) || (ord >= 65 && ord <= 90) || (ord >= 97 && ord <= 122)
str += chr
end
end
return str
end
end
No changes.
@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<title>The page you were looking for doesn't exist (404)</title>
<style type="text/css">
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
div.dialog {
width: 25em;
padding: 0 4em;
margin: 4em auto 0 auto;
border: 1px solid #ccc;
border-right-color: #999;
border-bottom-color: #999;
}
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
</style>
</head>
<body>
<!-- This file lives in public/404.html -->
<div class="dialog">
<h1>The page you were looking for doesn't exist.</h1>
<p>You may have mistyped the address or the page may have moved.</p>
</div>
</body>
</html>
@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<title>The change you wanted was rejected (422)</title>
<style type="text/css">
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
div.dialog {
width: 25em;
padding: 0 4em;
margin: 4em auto 0 auto;
border: 1px solid #ccc;
border-right-color: #999;
border-bottom-color: #999;
}
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
</style>
</head>
<body>
<!-- This file lives in public/422.html -->
<div class="dialog">
<h1>The change you wanted was rejected.</h1>
<p>Maybe you tried to change something you didn't have access to.</p>
</div>
</body>
</html>
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<title>We're sorry, but something went wrong (500)</title>
<style type="text/css">
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
div.dialog {
width: 25em;
padding: 0 4em;
margin: 4em auto 0 auto;
border: 1px solid #ccc;
border-right-color: #999;
border-bottom-color: #999;
}
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
</style>
</head>
<body>
<!-- This file lives in public/500.html -->
<div class="dialog">
<h1>We're sorry, but something went wrong.</h1>
</div>
</body>
</html>
Binary file not shown.
@@ -0,0 +1,5 @@
# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
#
# To ban all spiders from the entire site uncomment the next two lines:
# User-Agent: *
# Disallow: /
@@ -0,0 +1,6 @@
#!/usr/bin/env ruby
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
APP_PATH = File.expand_path('../../config/application', __FILE__)
require File.expand_path('../../config/boot', __FILE__)
require 'rails/commands'
@@ -0,0 +1,104 @@
require "spec_helper"
def m(inp, out)
Markdowner::markdown(inp).should == out
end
describe Markdowner do
it "converts indented text into <pre>" do
m " This is some\n text.\n",
"<p><pre> This is some\n text.\n</pre></p>"
m " blah <script>alert('hi');</script>",
"<p><pre> blah &lt;script&gt;alert('hi');&lt;/script&gt;\n</pre></p>"
end
it "converts text surrounded by * to <em>" do
m "oh hullo *there*",
"<p>oh hullo <em>there</em></p>"
m "*hi*",
"<p><em>hi</em></p>"
m "* hi hello*zap zap*",
"<p>* hi hello*zap zap*</p>"
m "oh hullo * there*",
"<p>oh hullo * there*</p>"
m " oh hullo *there*",
"<p><pre> oh hullo *there*\n</pre></p>"
m "oh hullo*there*",
"<p>oh hullo*there*</p>"
end
it "converts text surrounded by _ to <u>" do
m "oh hullo _there_",
"<p>oh hullo <u>there</u></p>"
m "oh hullo _ there_",
"<p>oh hullo _ there_</p>"
m "oh hullo _there_ and *yes* i see",
"<p>oh hullo <u>there</u> and <em>yes</em> i see</p>"
end
it "combines conversions" do
m "oh _*hullo*_ there_",
"<p>oh <u><em>hullo</em></u> there_</p>"
m "oh *_hullo_* there_",
"<p>oh <em><u>hullo</u></em> there_</p>"
m "oh *[hello](http://jcs.org/)* there_",
"<p>oh <em><a href=\"http://jcs.org/\" rel=\"nofollow\">hello</a>" <<
"</em> there_</p>"
end
it "converts domain names to links" do
m "oh hullo www.google.com",
"<p>oh hullo <a href=\"http://www.google.com\" rel=\"nofollow\">" <<
"www.google.com</a></p>"
end
it "converts urls to links" do
# no trailing question mark
m "do you mean http://jcs.org? or",
"<p>do you mean <a href=\"http://jcs.org\" rel=\"nofollow\">" <<
"jcs.org</a>? or</p>"
m "do you mean http://jcs.org?a",
"<p>do you mean <a href=\"http://jcs.org?a\" rel=\"nofollow\">" <<
"jcs.org?a</a></p>"
# no trailing dot in url
m "i like http://jcs.org.",
"<p>i like <a href=\"http://jcs.org\" rel=\"nofollow\">" <<
"jcs.org</a>.</p>"
m "i like http://jcs.org/goose_blah_here",
"<p>i like <a href=\"http://jcs.org/goose_blah_here\" " <<
"rel=\"nofollow\">jcs.org/goose_blah_here</a></p>"
end
it "truncates long url titles" do
m "a long http://www.example.com/goes/here/and/this/is/a/long/" <<
"url/which/should.get.shortened.html?because=this+will+cause+" <<
"the+page+to+wrap&such+ok",
"<p>a long <a href=\"http://www.example.com/goes/here/and/this/" <<
"is/a/long/url/which/should.get.shortened.html?because=this+" <<
"will+cause+the+page+to+wrap&amp;such+ok\" rel=\"nofollow\">" <<
"www.example.com/goes/here/and/this/is/a/long/url/w...</a></p>"
end
it "converts markdown url format to links" do
m "this is a *[link](http://example.com/)*",
"<p>this is a <em><a href=\"http://example.com/\" rel=\"nofollow\">" <<
"link</a></em></p>"
m "this is a [link](http://example.com/)",
"<p>this is a <a href=\"http://example.com/\" rel=\"nofollow\">" <<
"link</a></p>"
end
end
@@ -0,0 +1,32 @@
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
# ## Mock Framework
#
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
#
# config.mock_with :mocha
# config.mock_with :flexmock
# config.mock_with :rr
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
#config.fixture_path = "#{::Rails.root}/spec/fixtures"
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
# If true, the base class of anonymous controllers will be inferred
# automatically. This will be the default behavior in future versions of
# rspec-rails.
config.infer_base_class_for_anonymous_controllers = false
end
@@ -0,0 +1,7 @@
require 'machinist/active_record'
User.blueprint do
email { "user-#{sn}@example.com" }
password { "blah blah" }
password_confirmation { object.password }
end
No changes.
No changes.
No changes.