initial commit

This commit is contained in:
Andrew Davidson 2010-09-13 16:58:49 +08:00
commit 064003fa20
19 changed files with 573 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
.DS_Store

30
config.ru Executable file
View file

@ -0,0 +1,30 @@
#$LOAD_PATH.unshift ('/home/eschaton/.gem/ruby/1.8/gems/rack-0.9.1/lib')
#require ('/home/eschaton/.gem/ruby/1.8/gems/rack-0.9.1/lib/rack.rb')
#require ('/home/eschaton/.gem/ruby/1.8/gems/sinatra-0.9.1.1/lib/sinatra.rb')
#$LOAD_PATH.unshift '/Library/Ruby/Gems/1.8/gems/sqlite3-ruby-1.2.4/lib'
#require ('/Library/Ruby/Gems/1.8/gems/sqlite3-ruby-1.2.4/sqlite3.rb')
#$LOAD_PATH.unshift '/Library/Ruby/Gems/1.8/gems/sequel-3.0.0/lib'
#require ('/home/eschaton/.gems/gems/sequel-2.12.0/lib/sequel.rb')
require 'rubygems'
require 'sequel'
require 'rack'
require 'sinatra'
#require File.expand_path('~/.gem/ruby/1.8/gems/rack*')
#require File.expand_path('~/.gem/ruby/1.8/gems/sinatra*')
Sinatra::Application.default_options.merge!(
:views => File.join(File.dirname(__FILE__), 'views'),
:run => false,
:env => ENV['RACK_ENV'],
:raise_errors => true
)
log = File.new("sinatra.log", "a")
$stdout.reopen(log)
$stderr.reopen(log)
require 'main'
run Sinatra::Application

12
lib/log.rb Normal file
View file

@ -0,0 +1,12 @@
class Log < Sequel::Model
unless table_exists?
set_schema do
primary_key :id
Integer :shorten_url_id
String :ip
String :coordinates
Time :time
end
create_table
end
end

74
lib/shorteners/base62.rb Executable file
View file

@ -0,0 +1,74 @@
class Base62
@@ranges = [
('0'..'9'),
('a'..'z'),
('A'..'Z')
]
@@base = nil
@@offsets = nil
def self.to_s(number)
if @@base.nil?
@@base = self.calculate_base
end
string = ""
while number > (@@base - 1)
place = number % @@base
string = self.lookup(place) + string
number = number / @@base
end
self.lookup(number) + string
end
def self.to_i(string)
if @@base.nil?
@@base = self.calculate_base
end
number = 0
i = string.length - 1
string.each_byte do |c|
c = c.chr
@@ranges.each_index do |j|
range = @@ranges[j]
if range.member? c
number += (c[0] - range.to_a.first[0] + @@offsets[j]) * (@@base ** i)
break
end
end
i -= 1
end
number
end
def self.lookup(place)
string = ""
if @@base.nil?
@@base = self.calculate_base
end
(0..(@@ranges.length-1)).each do |i|
range_array = @@ranges[i].to_a
start = 0 + @@offsets[i]
stop = range_array.length - 1 + @@offsets[i]
if (start..stop).member? place
string = range_array[place - @@offsets[i]]
break
end
end
string
end
def self.next_integer(integer)
integer + 1
end
def self.calculate_base
i = 0
@@offsets = []
@@ranges.each do |range|
@@offsets << i
i += range.to_a.length
end
i
end
end

97
lib/shorteners/base71.rb Normal file
View file

@ -0,0 +1,97 @@
class Base71
@@ranges = [
('0'..'9'),
('a'..'z'),
('A'..'Z'),
('$'..'$'),
('-'..'.'),
('_'..'_'),
('('..')'),
('*'..'+'),
('!'..'!')
]
@@base = nil
@@offsets = nil
def self.to_s(number)
if @@base.nil?
@@base = self.calculate_base
end
string = ""
while number > (@@base - 1)
place = number % @@base
string = self.lookup(place) + string
number = number / @@base
end
self.lookup(number) + string
end
def self.to_i(string)
if @@base.nil?
@@base = self.calculate_base
end
number = 0
i = string.length - 1
string.each_byte do |c|
c = c.chr
@@ranges.each_index do |j|
range = @@ranges[j]
if range.member? c
number += (c[0] - range.to_a.first[0] + @@offsets[j]) * (@@base ** i)
break
end
end
#if ("0".."9").member? c
# number += c.to_i * (@@base ** i)
#elsif ("a".."z").member? c
# first = "a"
# number += (c[0] - first[0] + 10) * (@@base ** i)
#else
# first = "A"
# number += (c[0] - first[0] + 36) * (@@base ** i)
#end
i -= 1
end
number
end
def self.lookup(place)
string = ""
if @@base.nil?
@@base = self.calculate_base
end
(0..(@@ranges.length-1)).each do |i|
range_array = @@ranges[i].to_a
start = 0 + @@offsets[i]
stop = range_array.length - 1 + @@offsets[i]
if (start..stop).member? place
string = range_array[place - @@offsets[i]]
break
end
end
#if (0..9).member? place
# string = "#{place}"
#elsif (10..35).member? place
# string = ("a".."z").to_a[place - 10]
#else
# string = ("A".."Z").to_a[place - 36]
#end
string
end
def self.next_integer(integer)
integer + 1
end
def self.calculate_base
i = 0
@@offsets = []
@@ranges.each do |range|
@@offsets << i
i += range.to_a.length
end
i
end
end

34
lib/shortenurl.rb Executable file
View file

@ -0,0 +1,34 @@
class ShortenUrl < Sequel::Model
unless table_exists?
set_schema do
primary_key :id
String :key
String :url
Time :time
end
create_table
end
def short_url
"#{Shorten.base_url}#{Shorten.shortener.to_s(id)}"
end
def self.create_url(link)
uri = URI::parse(link)
raise "Invalid URL" unless uri.kind_of? URI::HTTP or uri.kind_of? URI::HTTPS
url = self.filter(:url => link).first
if !url
max_id = self.order(:id.desc).first
if !max_id
max_id = 0
else
max_id = max_id.id
end
url = self.new(:url => link)
url.save
end
url
end
end

117
main.rb Executable file
View file

@ -0,0 +1,117 @@
require 'rubygems'
require 'sinatra'
require 'sequel'
require 'uri'
configure do
Sequel::Model.plugin(:schema)
Sequel.connect(ENV['DATABASE_URL'] || 'sqlite://shorten.db')
require 'ostruct'
Shorten = OpenStruct.new(
:base_url => "http://localhost:4567/",
:service_name => "Lavish URL Shortener",
:button_text => "Short ♥!"
)
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/lib')
# Change these two references from "62" to "71" if you want to include
# URL-legal, non-alphanumeric characters in your URLs.
require "shorteners/base62"
Shorten.shortener = Base62
end
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/lib')
require 'shortenurl'
helpers do
def show_information
erb :information, :layout => false
end
def validate_link(link)
halt 401, 'We do not accept local URLs to be shortened' unless valid_url? link
end
# Determine if a URL is valid. We run it through
def valid_url?(url)
if url.include? "%3A"
url = URI.unescape(url)
end
retval = true
begin
uri = URI.parse(URI.escape(url))
if uri.class != URI::HTTP
retval = false
end
host = (URI.split(url))[2]
if host =~ /^(localhost|192\.168\.\d{1,3}\.\d{1,3}|127\.0\.0\.1|172\.((1[6-9])|(2[0-9])|(3[0-1])).\d{1,3}\.\d{1,3}|10.\d{1,3}\.\d{1,3}.\d{1,3})/
retval = false
end
rescue URI::InvalidURIError
retval = false
end
retval
end
end
get '/' do
@information = show_information
erb :index, :locals => { :type => "main" }
end
get %r(/(api-){0,1}create/(.*)) do |api, link|
#link = params[:link]
validate_link link
url = ShortenUrl.create_url(link)
if api == "api-"
"#{url.short_url}"
else
erb :finished, :locals => { :url => url, :type => "finished" }
end
end
get %r(/(api-){0,1}create) do |api|
if request['url']
validate_link request['url']
url = ShortenUrl.create_url(request['url'])
if api == "api-"
"#{url.short_url}"
else
erb :finished, :locals => { :url => url, :type => "finished" }
end
end
end
post '/' do
validate_link params[:url]
url = ShortenUrl.create_url(params[:url])
#"#{url.short_url}"
erb :finished, :locals => { :url => url, :type => "finished" }
end
get '/:short' do
url = ShortenUrl.filter(:id => Shorten.shortener.to_i(params[:short])).first
require 'log'
log = Log.new
log.ip = request.ip
log.time = Time.now
log.shorten_url_id = url.id
log.save
halt 404, "Page not found" unless url
redirect url.url
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
public/images/main_background.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

67
public/main.css Executable file
View file

@ -0,0 +1,67 @@
a {
text-decoration: none;
color: #5671a7;
}
a:hover {
text-decoration: underline;
}
a:active {
color: #ff9400;
}
#content {
width: 689px;
height: 295px;
margin: 1.5em auto;
padding: 83px 0px 0px 22px;
}
#content p {
margin-top: 0px;
}
#url {
font-size: 1.8em;
font-weight: bold;
font-family: "Verdana", sans-serif;
border: 7px solid black;
padding: 7px;
}
#content input[type="submit"] {
font-size: 1.8em;
font-family: "Verdana", sans-serif;
font-weight: bold;
border: 7px solid black;
padding: 7px;
}
#information {
width: 490px;
padding-top: 0.5em;
padding-right: 199px;
margin: 0 auto;
margin-top: -197px;
font-family: "Verdana", sans-serif;
}
#information h2 {
font-size: 1.2em;
}
#information p {
font-size: 0.90em;
}
.main {
background: url('images/main_background.png') no-repeat;
}
.finished {
background: url('images/finished_background.png') no-repeat;
font-size: 1.8em;
font-family: "Verdana", sans-serif;
font-weight: bold;
}

BIN
public/shorten.zip Normal file

Binary file not shown.

View file

@ -0,0 +1,18 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Andrew's URL Shortener</title>
<link rel="stylesheet" type="text/css" href="/main.css" />
<link rel="commands" href="shorten.js" name="Shorten w/ u.pilsch.com" />
</head>
<body>
<div id="content" class="finished">
<p>Install Ubiquity Command!</p>
</div>
<div id="information">
<p><a href="/">Back to Main Page</a></p>
</div>
</body>
</html>

View file

@ -0,0 +1,82 @@
/*var isParser2 = function(){
var prefs = Components.classes["@mozilla.org/preferences-service;1
"].getService(Components.interfaces.nsIPrefService);
var branch = prefs.getBranch("extensions.ubiquity.");
return (branch.getPrefType("parserVersion") != 0) ?
branch.getIntPref("parserVersion") == 2 : false;
}
if (isParser2()) {*/
/* Parser 2 version of the CmdUtils.CreateCommand calls here */
CmdUtils.CreateCommand({
names: ['shorten'],
icon: "http://u.pilsch.com/favicon.png",
homepage: "http://u.pilsch.com",
author: { name: "Andrew Pilsch (based on code by Arun Shivaram)", email: "andrew@pilsch.com"},
license: "GPL",
description: "Shortens the selected URL using u.pilsch.com",
help: "shorten <long url>",
arguments: [ {role: 'object', nountype: noun_arb_text, label: 'longurl'} ],
preview: function( pblock, args ) {
pblock.innerHTML = _("Replaces the selected URL with a u.pilsch.com URL");
this._shorturl(pblock,args.object,"preview");
},
execute: function(object, args) {
this._shorturl("",args.object,"execute");
},
_shorturl: function( pblock,lurl,call ) {
var baseUrl = "http://u.pilsch.com/api-create?url=" + lurl.text;
//var params = {longurl: lurl.text};
var params = {}
jQuery.get( baseUrl, params,function(sUrl){
if (call=="preview"){
pblock.innerHTML = _("Replaces the selected URL with "+sUrl);
}
if (call=="execute"){
CmdUtils.setSelection(sUrl);
CmdUtils.copyToClipboard(sUrl);
}
})
}
});
/* ... */
/*} else {
CmdUtils.CreateCommand({
name: "shorten",
icon: "http://is.gd/favicon.ico",
homepage: "http://u.pilsch.com",
author: { name: "Andrew Pilsch (based on code by Arun Shivaram)", email: "andrew@pilsch.com"},
license: "GPL",
description: "Shortens the selected URL using u.pilsch.com",
help: "shorten <long url>",
takes: {"longurl": noun_arb_text},
preview: function( pblock, lurl ) {
pblock.innerHTML = "Replaces the selected URL with a u.pilsch.com URL";
this._shorturl(pblock,lurl,"preview");
},
execute: function(lurl) {
this._shorturl("",lurl,"execute");
},
_shorturl: function( pblock,lurl,call){
var baseUrl = "http://u.pilsch.com/api-create/" + lurl.text;
//var params = {longurl: lurl.text};
var params = {}
jQuery.get( baseUrl, params,function(sUrl){
if (call=="preview"){
pblock.innerHTML = "Replaces the selected URL with "+sUrl;
}
if (call=="execute"){
CmdUtils.setSelection(sUrl);
CmdUtils.copyToClipboard(sUrl);
}
})
}
});
}*/

BIN
shorten.db Normal file

Binary file not shown.

11
sinatra.log Normal file
View file

@ -0,0 +1,11 @@
./main.rb:112: warning: Object#id will be deprecated; use Object#object_id
::1 - - [12/Jul/2009 13:10:27] "GET /favicon.ico " 404 14 0.0112
./main.rb:112: warning: Object#id will be deprecated; use Object#object_id
::1 - - [12/Jul/2009 13:10:31] "GET /favicon.ico " 404 14 0.0055
./main.rb:112: warning: Object#id will be deprecated; use Object#object_id
::1 - - [12/Jul/2009 13:10:31] "GET /favicon.ico " 404 14 0.0073
::1 - - [12/Jul/2009 13:10:32] "GET /~test/mysql " 404 420 0.0014
::1 - - [12/Jul/2009 13:10:32] "GET /__sinatra__/404.png " 200 23305 0.0029
::1 - - [12/Jul/2009 13:10:46] "GET /~test/mysql " 404 420 0.0023
::1 - - [12/Jul/2009 13:10:46] "GET /__sinatra__/404.png " 304 - 0.0020
::1 - - [12/Jul/2009 13:10:48] "GET /~test/mysql " 404 420 0.0020

1
views/finished.erb Executable file
View file

@ -0,0 +1 @@
<p><a href="<%= url.short_url %>"><%= url.short_url %></a></p>

4
views/index.erb Executable file
View file

@ -0,0 +1,4 @@
<form method="POST" action="/">
<input type="text" name="url" id="url" />
<input type="submit" value="<%= Shorten.button_text %>" id="create_url" />
</form>

10
views/information.erb Executable file
View file

@ -0,0 +1,10 @@
<div id="information">
<h2>use this site from your browser:</h2>
<p>
<a href="javascript:void(location.href='<%= Shorten.base_url %>create/' + encodeURIComponent(location.href));"><%= Shorten.button_text %></a> - Drag this link to your bookmark bar or right click and select "Bookmark This Location." When you want to shorten a URL, just click on the bookmark! Hooray!
</p>
<h2>try our ubiquity command:</h2>
<p>
<a href="/ubiquity">Click here to go to the install page.</a> For more information about Ubiquity, <a href="http://labs.mozilla.com/projects/ubiquity/">click here</a>.
</p>
</div>

15
views/layout.erb Executable file
View file

@ -0,0 +1,15 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title><%= Shorten.service_name %></title>
<link rel="stylesheet" type="text/css" href="/main.css" />
</head>
<body>
<div id="content" class="<%= type %>">
<%= yield %>
</div>
<%= @information %>
</body>
</html>