├── .gitignore ├── config └── website.yml ├── test ├── test_helper.rb └── test_geoip.rb ├── script ├── destroy ├── generate └── txt2html ├── History.rdoc ├── bin └── geoip ├── website ├── template.rhtml ├── stylesheets │ └── screen.css ├── index.txt └── javascripts │ └── rounded_corners_lite.inc.js ├── geoip.gemspec ├── Rakefile ├── data └── geoip │ ├── country_code.yml │ ├── country_continent.yml │ ├── country_code3.yml │ ├── country_name.yml │ └── time_zone.yml ├── README.rdoc └── lib └── geoip.rb /.gitignore: -------------------------------------------------------------------------------- 1 | pkg 2 | rdoc 3 | website/index.html 4 | Geo*.dat 5 | *_test.rb 6 | GeoIP-* 7 | -------------------------------------------------------------------------------- /config/website.yml: -------------------------------------------------------------------------------- 1 | host: cjheath@rubyforge.org 2 | remote_dir: /var/www/gforge-projects/geoip 3 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | require 'stringio' 2 | require 'test/unit' 3 | require File.dirname(__FILE__) + '/../lib/geoip' 4 | -------------------------------------------------------------------------------- /test/test_geoip.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/test_helper.rb' 2 | 3 | class TestGeoip < Test::Unit::TestCase 4 | 5 | def setup 6 | end 7 | 8 | def test_truth 9 | assert true 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /script/destroy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..')) 3 | 4 | begin 5 | require 'rubigen' 6 | rescue LoadError 7 | require 'rubygems' 8 | require 'rubigen' 9 | end 10 | require 'rubigen/scripts/destroy' 11 | 12 | ARGV.shift if ['--help', '-h'].include?(ARGV[0]) 13 | RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit] 14 | RubiGen::Scripts::Destroy.new.run(ARGV) 15 | -------------------------------------------------------------------------------- /script/generate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..')) 3 | 4 | begin 5 | require 'rubigen' 6 | rescue LoadError 7 | require 'rubygems' 8 | require 'rubigen' 9 | end 10 | require 'rubigen/scripts/generate' 11 | 12 | ARGV.shift if ['--help', '-h'].include?(ARGV[0]) 13 | RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit] 14 | RubiGen::Scripts::Generate.new.run(ARGV) 15 | -------------------------------------------------------------------------------- /History.rdoc: -------------------------------------------------------------------------------- 1 | == 1.2.0 2012-10-17 2 | 3 | * Added support for GeoLiteCityv6 IPv6 database type 4 | 5 | == 0.8.1 2009-06-04 6 | 7 | * Added GeoIP#close method to close the file descriptor 8 | 9 | == 0.8.0 2008-08-29 10 | 11 | * Added Mutex protection around file I/O for thread safety 12 | 13 | == 0.7.0 2008-05-03 14 | 15 | * Added Hez Ronningen's patch for using the ISP lookup data file 16 | 17 | == 0.5.0 2007-10-24 18 | 19 | * 1 major enhancement: 20 | * Initial release 21 | -------------------------------------------------------------------------------- /bin/geoip: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | lib_dir = File.expand_path(File.join(File.dirname(__FILE__),'..','lib')) 4 | $LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir) 5 | 6 | require 'geoip' 7 | 8 | data = '/usr/share/GeoIP/GeoIP.dat' 9 | data = ARGV.shift if ARGV[0] =~ /\.dat\Z/ 10 | 11 | geoip = GeoIP.new data 12 | req = ([GeoIP::GEOIP_CITY_EDITION_REV1, GeoIP::GEOIP_CITY_EDITION_REV0].include?(geoip.databaseType)) ? :city : :country 13 | 14 | if ARGV.size > 0 15 | ARGV.each { |a| p geoip.send(req, a) } 16 | else 17 | while (STDIN.isatty && print('geoip> '); ip = gets) 18 | ip.chomp! 19 | result = geoip.send(req, ip) 20 | p result 21 | end 22 | STDIN.isatty && puts 23 | end 24 | -------------------------------------------------------------------------------- /website/template.rhtml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | <%= title %> 9 | 10 | 11 | 14 | 29 | 30 | 31 |
32 | 33 |

<%= title %>

34 |
35 |

Get Version

36 | <%= version %> 37 |
38 | <%= body %> 39 |

40 | Clifford Heath, <%= modified.pretty %>
41 | Theme extended from Paul Battley 42 |

43 |
44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /script/txt2html: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'rubygems' 4 | require 'redcloth' 5 | require 'syntax/convertors/html' 6 | require 'erb' 7 | require File.dirname(__FILE__) + '/../lib/geoip.rb' 8 | 9 | version = GeoIP::VERSION 10 | download = 'http://rubyforge.org/projects/geoip' 11 | 12 | class Fixnum 13 | def ordinal 14 | # teens 15 | return 'th' if (10..19).include?(self % 100) 16 | # others 17 | case self % 10 18 | when 1: return 'st' 19 | when 2: return 'nd' 20 | when 3: return 'rd' 21 | else return 'th' 22 | end 23 | end 24 | end 25 | 26 | class Time 27 | def pretty 28 | return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}" 29 | end 30 | end 31 | 32 | def convert_syntax(syntax, source) 33 | return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^
|
$!,'') 34 | end 35 | 36 | if ARGV.length >= 1 37 | src, template = ARGV 38 | template ||= File.join(File.dirname(__FILE__), '/../website/template.rhtml') 39 | 40 | else 41 | puts("Usage: #{File.split($0).last} source.txt [template.rhtml] > output.html") 42 | exit! 43 | end 44 | 45 | template = ERB.new(File.open(template).read) 46 | 47 | title = nil 48 | body = nil 49 | File.open(src) do |fsrc| 50 | title_text = fsrc.readline 51 | body_text = fsrc.read 52 | syntax_items = [] 53 | body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)!m){ 54 | ident = syntax_items.length 55 | element, syntax, source = $1, $2, $3 56 | syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}" 57 | "syntax-temp-#{ident}" 58 | } 59 | title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip 60 | body = RedCloth.new(body_text).to_html 61 | body.gsub!(%r!(?:
)?syntax-temp-(\d+)(?:
)?!){ syntax_items[$1.to_i] } 62 | end 63 | stat = File.stat(src) 64 | created = stat.ctime 65 | modified = stat.mtime 66 | 67 | $stdout << template.result(binding) 68 | -------------------------------------------------------------------------------- /geoip.gemspec: -------------------------------------------------------------------------------- 1 | # Generated by jeweler 2 | # DO NOT EDIT THIS FILE DIRECTLY 3 | # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec' 4 | # -*- encoding: utf-8 -*- 5 | 6 | Gem::Specification.new do |s| 7 | s.name = "geoip" 8 | s.version = "1.2.1" 9 | 10 | s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= 11 | s.authors = ["Clifford Heath", "Roland Moriz"] 12 | s.date = "2012-12-18" 13 | s.description = "GeoIP searches a GeoIP database for a given host or IP address, and\nreturns information about the country where the IP address is allocated,\nand the city, ISP and other information, if you have that database version." 14 | s.email = ["clifford.heath@gmail.com", "rmoriz@gmail.com"] 15 | s.executables = ["geoip"] 16 | s.extra_rdoc_files = [ 17 | "README.rdoc" 18 | ] 19 | s.files = [ 20 | "History.rdoc", 21 | "README.rdoc", 22 | "Rakefile", 23 | "bin/geoip", 24 | "config/website.yml", 25 | "data/geoip/country_code.yml", 26 | "data/geoip/country_code3.yml", 27 | "data/geoip/country_continent.yml", 28 | "data/geoip/country_name.yml", 29 | "data/geoip/time_zone.yml", 30 | "geoip.gemspec", 31 | "lib/geoip.rb", 32 | "script/destroy", 33 | "script/generate", 34 | "script/txt2html", 35 | "test/test_geoip.rb", 36 | "test/test_helper.rb", 37 | "website/index.txt", 38 | "website/javascripts/rounded_corners_lite.inc.js", 39 | "website/stylesheets/screen.css", 40 | "website/template.rhtml" 41 | ] 42 | s.homepage = "http://github.com/cjheath/geoip" 43 | s.licenses = ["GPL"] 44 | s.require_paths = ["lib"] 45 | s.rubygems_version = "1.8.24" 46 | s.summary = "GeoIP searches a GeoIP database for a given host or IP address, and returns information about the country where the IP address is allocated, and the city, ISP and other information, if you have that database version." 47 | 48 | if s.respond_to? :specification_version then 49 | s.specification_version = 3 50 | 51 | if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then 52 | else 53 | end 54 | else 55 | end 56 | end 57 | 58 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'rake' 3 | 4 | require 'jeweler' 5 | require './lib/geoip' 6 | 7 | Jeweler::Tasks.new do |gem| 8 | # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options 9 | gem.name = "geoip" 10 | gem.version = GeoIP::VERSION 11 | gem.homepage = "http://github.com/cjheath/geoip" 12 | gem.license = "GPL" 13 | gem.summary = %Q{GeoIP searches a GeoIP database for a given host or IP address, and returns information about the country where the IP address is allocated, and the city, ISP and other information, if you have that database version.} 14 | gem.description = %Q{GeoIP searches a GeoIP database for a given host or IP address, and 15 | returns information about the country where the IP address is allocated, 16 | and the city, ISP and other information, if you have that database version.} 17 | gem.email = %w[clifford.heath@gmail.com rmoriz@gmail.com] 18 | gem.authors = ["Clifford Heath", "Roland Moriz"] 19 | # Include your dependencies below. Runtime dependencies are required when using your gem, 20 | # and development dependencies are only needed for development (ie running rake tasks, tests, etc) 21 | # gem.add_runtime_dependency 'jabber4r', '> 0.1' 22 | # gem.add_development_dependency 'rspec', '> 1.2.3' 23 | end 24 | Jeweler::RubygemsDotOrgTasks.new 25 | 26 | require 'rake/testtask' 27 | Rake::TestTask.new(:test) do |test| 28 | test.libs << 'lib' << 'test' 29 | test.pattern = 'test/**/test_*.rb' 30 | test.verbose = true 31 | end 32 | task :default => :test 33 | 34 | require 'rdoc/task' 35 | Rake::RDocTask.new do |rdoc| 36 | rdoc.rdoc_dir = 'rdoc' 37 | rdoc.title = "geoip #{GeoIP::VERSION}" 38 | rdoc.rdoc_files.include('README.rdoc') 39 | rdoc.rdoc_files.include('History.rdoc') 40 | rdoc.rdoc_files.include('lib/**/*.rb') 41 | end 42 | 43 | desc 'Generate website files' 44 | task :website_generate do 45 | sh %q{ruby script/txt2html website/index.txt > website/index.html} 46 | end 47 | 48 | desc 'Upload website files via rsync' 49 | task :website_upload do 50 | local_dir = 'website' 51 | website_config = YAML.load(File.read("config/website.yml")) 52 | host = website_config["host"] 53 | host = host ? "#{host}:" : "" 54 | remote_dir = website_config["remote_dir"] 55 | sh %{rsync -aCv #{local_dir}/ #{host}#{remote_dir}} 56 | end 57 | 58 | -------------------------------------------------------------------------------- /data/geoip/country_code.yml: -------------------------------------------------------------------------------- 1 | # Ordered list of the ISO3166 2-character country codes, ordered by GeoIP ID 2 | --- 3 | - -- 4 | - AP 5 | - EU 6 | - AD 7 | - AE 8 | - AF 9 | - AG 10 | - AI 11 | - AL 12 | - AM 13 | - AN 14 | - AO 15 | - AQ 16 | - AR 17 | - AS 18 | - AT 19 | - AU 20 | - AW 21 | - AZ 22 | - BA 23 | - BB 24 | - BD 25 | - BE 26 | - BF 27 | - BG 28 | - BH 29 | - BI 30 | - BJ 31 | - BM 32 | - BN 33 | - BO 34 | - BR 35 | - BS 36 | - BT 37 | - BV 38 | - BW 39 | - BY 40 | - BZ 41 | - CA 42 | - CC 43 | - CD 44 | - CF 45 | - CG 46 | - CH 47 | - CI 48 | - CK 49 | - CL 50 | - CM 51 | - CN 52 | - CO 53 | - CR 54 | - CU 55 | - CV 56 | - CX 57 | - CY 58 | - CZ 59 | - DE 60 | - DJ 61 | - DK 62 | - DM 63 | - DO 64 | - DZ 65 | - EC 66 | - EE 67 | - EG 68 | - EH 69 | - ER 70 | - ES 71 | - ET 72 | - FI 73 | - FJ 74 | - FK 75 | - FM 76 | - FO 77 | - FR 78 | - FX 79 | - GA 80 | - GB 81 | - GD 82 | - GE 83 | - GF 84 | - GH 85 | - GI 86 | - GL 87 | - GM 88 | - GN 89 | - GP 90 | - GQ 91 | - GR 92 | - GS 93 | - GT 94 | - GU 95 | - GW 96 | - GY 97 | - HK 98 | - HM 99 | - HN 100 | - HR 101 | - HT 102 | - HU 103 | - ID 104 | - IE 105 | - IL 106 | - IN 107 | - IO 108 | - IQ 109 | - IR 110 | - IS 111 | - IT 112 | - JM 113 | - JO 114 | - JP 115 | - KE 116 | - KG 117 | - KH 118 | - KI 119 | - KM 120 | - KN 121 | - KP 122 | - KR 123 | - KW 124 | - KY 125 | - KZ 126 | - LA 127 | - LB 128 | - LC 129 | - LI 130 | - LK 131 | - LR 132 | - LS 133 | - LT 134 | - LU 135 | - LV 136 | - LY 137 | - MA 138 | - MC 139 | - MD 140 | - MG 141 | - MH 142 | - MK 143 | - ML 144 | - MM 145 | - MN 146 | - MO 147 | - MP 148 | - MQ 149 | - MR 150 | - MS 151 | - MT 152 | - MU 153 | - MV 154 | - MW 155 | - MX 156 | - MY 157 | - MZ 158 | - NA 159 | - NC 160 | - NE 161 | - NF 162 | - NG 163 | - NI 164 | - NL 165 | - "NO" 166 | - NP 167 | - NR 168 | - NU 169 | - NZ 170 | - OM 171 | - PA 172 | - PE 173 | - PF 174 | - PG 175 | - PH 176 | - PK 177 | - PL 178 | - PM 179 | - PN 180 | - PR 181 | - PS 182 | - PT 183 | - PW 184 | - PY 185 | - QA 186 | - RE 187 | - RO 188 | - RU 189 | - RW 190 | - SA 191 | - SB 192 | - SC 193 | - SD 194 | - SE 195 | - SG 196 | - SH 197 | - SI 198 | - SJ 199 | - SK 200 | - SL 201 | - SM 202 | - SN 203 | - SO 204 | - SR 205 | - ST 206 | - SV 207 | - SY 208 | - SZ 209 | - TC 210 | - TD 211 | - TF 212 | - TG 213 | - TH 214 | - TJ 215 | - TK 216 | - TM 217 | - TN 218 | - TO 219 | - TL 220 | - TR 221 | - TT 222 | - TV 223 | - TW 224 | - TZ 225 | - UA 226 | - UG 227 | - UM 228 | - US 229 | - UY 230 | - UZ 231 | - VA 232 | - VC 233 | - VE 234 | - VG 235 | - VI 236 | - VN 237 | - VU 238 | - WF 239 | - WS 240 | - YE 241 | - YT 242 | - RS 243 | - ZA 244 | - ZM 245 | - ME 246 | - ZW 247 | - A1 248 | - A2 249 | - O1 250 | - AX 251 | - GG 252 | - IM 253 | - JE 254 | - BL 255 | - MF 256 | -------------------------------------------------------------------------------- /data/geoip/country_continent.yml: -------------------------------------------------------------------------------- 1 | # Ordered list of the ISO3166 2-character continent code of the countries, ordered by GeoIP ID 2 | --- 3 | - -- 4 | - AS 5 | - EU 6 | - EU 7 | - AS 8 | - AS 9 | - SA 10 | - SA 11 | - EU 12 | - AS 13 | - SA 14 | - AF 15 | - AN 16 | - SA 17 | - OC 18 | - EU 19 | - OC 20 | - SA 21 | - AS 22 | - EU 23 | - SA 24 | - AS 25 | - EU 26 | - AF 27 | - EU 28 | - AS 29 | - AF 30 | - AF 31 | - SA 32 | - AS 33 | - SA 34 | - SA 35 | - SA 36 | - AS 37 | - AF 38 | - AF 39 | - EU 40 | - SA 41 | - NA 42 | - AS 43 | - AF 44 | - AF 45 | - AF 46 | - EU 47 | - AF 48 | - OC 49 | - SA 50 | - AF 51 | - AS 52 | - SA 53 | - SA 54 | - SA 55 | - AF 56 | - AS 57 | - AS 58 | - EU 59 | - EU 60 | - AF 61 | - EU 62 | - SA 63 | - SA 64 | - AF 65 | - SA 66 | - EU 67 | - AF 68 | - AF 69 | - AF 70 | - EU 71 | - AF 72 | - EU 73 | - OC 74 | - SA 75 | - OC 76 | - EU 77 | - EU 78 | - EU 79 | - AF 80 | - EU 81 | - SA 82 | - AS 83 | - SA 84 | - AF 85 | - EU 86 | - SA 87 | - AF 88 | - AF 89 | - SA 90 | - AF 91 | - EU 92 | - SA 93 | - SA 94 | - OC 95 | - AF 96 | - SA 97 | - AS 98 | - AF 99 | - SA 100 | - EU 101 | - SA 102 | - EU 103 | - AS 104 | - EU 105 | - AS 106 | - AS 107 | - AS 108 | - AS 109 | - AS 110 | - EU 111 | - EU 112 | - SA 113 | - AS 114 | - AS 115 | - AF 116 | - AS 117 | - AS 118 | - OC 119 | - AF 120 | - SA 121 | - AS 122 | - AS 123 | - AS 124 | - SA 125 | - AS 126 | - AS 127 | - AS 128 | - SA 129 | - EU 130 | - AS 131 | - AF 132 | - AF 133 | - EU 134 | - EU 135 | - EU 136 | - AF 137 | - AF 138 | - EU 139 | - EU 140 | - AF 141 | - OC 142 | - EU 143 | - AF 144 | - AS 145 | - AS 146 | - AS 147 | - OC 148 | - SA 149 | - AF 150 | - SA 151 | - EU 152 | - AF 153 | - AS 154 | - AF 155 | - NA 156 | - AS 157 | - AF 158 | - AF 159 | - OC 160 | - AF 161 | - OC 162 | - AF 163 | - SA 164 | - EU 165 | - EU 166 | - AS 167 | - OC 168 | - OC 169 | - OC 170 | - AS 171 | - SA 172 | - SA 173 | - OC 174 | - OC 175 | - AS 176 | - AS 177 | - EU 178 | - SA 179 | - OC 180 | - SA 181 | - AS 182 | - EU 183 | - OC 184 | - SA 185 | - AS 186 | - AF 187 | - EU 188 | - AS 189 | - AF 190 | - AS 191 | - OC 192 | - AF 193 | - AF 194 | - EU 195 | - AS 196 | - AF 197 | - EU 198 | - EU 199 | - EU 200 | - AF 201 | - EU 202 | - AF 203 | - AF 204 | - SA 205 | - AF 206 | - SA 207 | - AS 208 | - AF 209 | - SA 210 | - AF 211 | - AF 212 | - AF 213 | - AS 214 | - AS 215 | - OC 216 | - AS 217 | - AF 218 | - OC 219 | - AS 220 | - AS 221 | - SA 222 | - OC 223 | - AS 224 | - AF 225 | - EU 226 | - AF 227 | - OC 228 | - NA 229 | - SA 230 | - AS 231 | - EU 232 | - SA 233 | - SA 234 | - SA 235 | - SA 236 | - AS 237 | - OC 238 | - OC 239 | - OC 240 | - AS 241 | - AF 242 | - EU 243 | - AF 244 | - AF 245 | - EU 246 | - AF 247 | - -- 248 | - -- 249 | - -- 250 | - EU 251 | - EU 252 | - EU 253 | - EU 254 | - SA 255 | - SA 256 | -------------------------------------------------------------------------------- /website/stylesheets/screen.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #E1D1F1; 3 | font-family: "Georgia", sans-serif; 4 | font-size: 16px; 5 | line-height: 1.6em; 6 | padding: 1.6em 0 0 0; 7 | color: #333; 8 | } 9 | h1, h2, h3, h4, h5, h6 { 10 | color: #444; 11 | } 12 | h1 { 13 | font-family: sans-serif; 14 | font-weight: normal; 15 | font-size: 4em; 16 | line-height: 0.8em; 17 | letter-spacing: -0.1ex; 18 | margin: 5px; 19 | } 20 | li { 21 | padding: 0; 22 | margin: 0; 23 | list-style-type: square; 24 | } 25 | a { 26 | color: #5E5AFF; 27 | background-color: #DAC; 28 | font-weight: normal; 29 | text-decoration: underline; 30 | } 31 | blockquote { 32 | font-size: 90%; 33 | font-style: italic; 34 | border-left: 1px solid #111; 35 | padding-left: 1em; 36 | } 37 | .caps { 38 | font-size: 80%; 39 | } 40 | 41 | #main { 42 | width: 45em; 43 | padding: 0; 44 | margin: 0 auto; 45 | } 46 | .coda { 47 | text-align: right; 48 | color: #77f; 49 | font-size: smaller; 50 | } 51 | 52 | table { 53 | font-size: 90%; 54 | line-height: 1.4em; 55 | color: #ff8; 56 | background-color: #111; 57 | padding: 2px 10px 2px 10px; 58 | border-style: dashed; 59 | } 60 | 61 | th { 62 | color: #fff; 63 | } 64 | 65 | td { 66 | padding: 2px 10px 2px 10px; 67 | } 68 | 69 | .success { 70 | color: #0CC52B; 71 | } 72 | 73 | .failed { 74 | color: #E90A1B; 75 | } 76 | 77 | .unknown { 78 | color: #995000; 79 | } 80 | pre, code { 81 | font-family: monospace; 82 | font-size: 90%; 83 | line-height: 1.4em; 84 | color: #ff8; 85 | background-color: #111; 86 | padding: 2px 10px 2px 10px; 87 | } 88 | .comment { color: #aaa; font-style: italic; } 89 | .keyword { color: #eff; font-weight: bold; } 90 | .punct { color: #eee; font-weight: bold; } 91 | .symbol { color: #0bb; } 92 | .string { color: #6b4; } 93 | .ident { color: #ff8; } 94 | .constant { color: #66f; } 95 | .regex { color: #ec6; } 96 | .number { color: #F99; } 97 | .expr { color: #227; } 98 | 99 | #version { 100 | float: right; 101 | text-align: right; 102 | font-family: sans-serif; 103 | font-weight: normal; 104 | background-color: #B3ABFF; 105 | color: #141331; 106 | padding: 15px 20px 10px 20px; 107 | margin: 0 auto; 108 | margin-top: 15px; 109 | border: 3px solid #141331; 110 | } 111 | 112 | #version .numbers { 113 | display: block; 114 | font-size: 4em; 115 | line-height: 0.8em; 116 | letter-spacing: -0.1ex; 117 | margin-bottom: 15px; 118 | } 119 | 120 | #version p { 121 | text-decoration: none; 122 | color: #141331; 123 | background-color: #B3ABFF; 124 | margin: 0; 125 | padding: 0; 126 | } 127 | 128 | #version a { 129 | text-decoration: none; 130 | color: #141331; 131 | background-color: #B3ABFF; 132 | } 133 | 134 | .clickable { 135 | cursor: pointer; 136 | cursor: hand; 137 | } 138 | 139 | -------------------------------------------------------------------------------- /data/geoip/country_code3.yml: -------------------------------------------------------------------------------- 1 | # Ordered list of the ISO3166 3-character country codes, ordered by GeoIP ID 2 | --- 3 | - -- 4 | - AP 5 | - EU 6 | - AND 7 | - ARE 8 | - AFG 9 | - ATG 10 | - AIA 11 | - ALB 12 | - ARM 13 | - ANT 14 | - AGO 15 | - AQ 16 | - ARG 17 | - ASM 18 | - AUT 19 | - AUS 20 | - ABW 21 | - AZE 22 | - BIH 23 | - BRB 24 | - BGD 25 | - BEL 26 | - BFA 27 | - BGR 28 | - BHR 29 | - BDI 30 | - BEN 31 | - BMU 32 | - BRN 33 | - BOL 34 | - BRA 35 | - BHS 36 | - BTN 37 | - BV 38 | - BWA 39 | - BLR 40 | - BLZ 41 | - CAN 42 | - CC 43 | - COD 44 | - CAF 45 | - COG 46 | - CHE 47 | - CIV 48 | - COK 49 | - CHL 50 | - CMR 51 | - CHN 52 | - COL 53 | - CRI 54 | - CUB 55 | - CPV 56 | - CX 57 | - CYP 58 | - CZE 59 | - DEU 60 | - DJI 61 | - DNK 62 | - DMA 63 | - DOM 64 | - DZA 65 | - ECU 66 | - EST 67 | - EGY 68 | - ESH 69 | - ERI 70 | - ESP 71 | - ETH 72 | - FIN 73 | - FJI 74 | - FLK 75 | - FSM 76 | - FRO 77 | - FRA 78 | - FX 79 | - GAB 80 | - GBR 81 | - GRD 82 | - GEO 83 | - GUF 84 | - GHA 85 | - GIB 86 | - GRL 87 | - GMB 88 | - GIN 89 | - GLP 90 | - GNQ 91 | - GRC 92 | - GS 93 | - GTM 94 | - GUM 95 | - GNB 96 | - GUY 97 | - HKG 98 | - HM 99 | - HND 100 | - HRV 101 | - HTI 102 | - HUN 103 | - IDN 104 | - IRL 105 | - ISR 106 | - IND 107 | - IO 108 | - IRQ 109 | - IRN 110 | - ISL 111 | - ITA 112 | - JAM 113 | - JOR 114 | - JPN 115 | - KEN 116 | - KGZ 117 | - KHM 118 | - KIR 119 | - COM 120 | - KNA 121 | - PRK 122 | - KOR 123 | - KWT 124 | - CYM 125 | - KAZ 126 | - LAO 127 | - LBN 128 | - LCA 129 | - LIE 130 | - LKA 131 | - LBR 132 | - LSO 133 | - LTU 134 | - LUX 135 | - LVA 136 | - LBY 137 | - MAR 138 | - MCO 139 | - MDA 140 | - MDG 141 | - MHL 142 | - MKD 143 | - MLI 144 | - MMR 145 | - MNG 146 | - MAC 147 | - MNP 148 | - MTQ 149 | - MRT 150 | - MSR 151 | - MLT 152 | - MUS 153 | - MDV 154 | - MWI 155 | - MEX 156 | - MYS 157 | - MOZ 158 | - NAM 159 | - NCL 160 | - NER 161 | - NFK 162 | - NGA 163 | - NIC 164 | - NLD 165 | - NOR 166 | - NPL 167 | - NRU 168 | - NIU 169 | - NZL 170 | - OMN 171 | - PAN 172 | - PER 173 | - PYF 174 | - PNG 175 | - PHL 176 | - PAK 177 | - POL 178 | - SPM 179 | - PCN 180 | - PRI 181 | - PSE 182 | - PRT 183 | - PLW 184 | - PRY 185 | - QAT 186 | - REU 187 | - ROU 188 | - RUS 189 | - RWA 190 | - SAU 191 | - SLB 192 | - SYC 193 | - SDN 194 | - SWE 195 | - SGP 196 | - SHN 197 | - SVN 198 | - SJM 199 | - SVK 200 | - SLE 201 | - SMR 202 | - SEN 203 | - SOM 204 | - SUR 205 | - STP 206 | - SLV 207 | - SYR 208 | - SWZ 209 | - TCA 210 | - TCD 211 | - TF 212 | - TGO 213 | - THA 214 | - TJK 215 | - TKL 216 | - TKM 217 | - TUN 218 | - TON 219 | - TLS 220 | - TUR 221 | - TTO 222 | - TUV 223 | - TWN 224 | - TZA 225 | - UKR 226 | - UGA 227 | - UM 228 | - USA 229 | - URY 230 | - UZB 231 | - VAT 232 | - VCT 233 | - VEN 234 | - VGB 235 | - VIR 236 | - VNM 237 | - VUT 238 | - WLF 239 | - WSM 240 | - YEM 241 | - YT 242 | - SRB 243 | - ZAF 244 | - ZMB 245 | - MNE 246 | - ZWE 247 | - A1 248 | - A2 249 | - O1 250 | - ALA 251 | - GGY 252 | - IMN 253 | - JEY 254 | - BLM 255 | - MAF 256 | -------------------------------------------------------------------------------- /website/index.txt: -------------------------------------------------------------------------------- 1 | h1. geoip 2 | 3 | h2. 'Geographic info for an IP address' 4 | 5 | h2. What 6 | 7 | GeoIP searches a GeoIP database from http://maxmind.com for a given host or IP address, 8 | and returns information about the country, city and/or ISP for that IP address, 9 | depending on the database version. 10 | 11 | h2. Installing 12 | 13 |
sudo gem install geoip
14 | 15 | h2. Locations 16 | 17 | "http://github.com/cjheath/geoip":http://github.com/cjheath/geoip 18 |
19 | "http://geoip.rubyforge.org/":http://geoip.rubyforge.org/ 20 | 21 | h2. Prerequisites 22 | 23 | You need one of the free GeoLite country, city or ASN databases, or a subscription database version. 24 | The last known download locations for the GeoLite database versions are 25 | "http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz":http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz 26 | "http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz":http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz 27 | "http://geolite.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz":http://geolite.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz 28 | 29 | This API requires the database to be decompressed for searching. 30 | 31 | h2. Example 32 | 33 |
34 |     require 'geoip'
35 |     c = GeoIP.new('GeoIP.dat').country('www.nokia.com')
36 |     => ["www.nokia.com", "147.243.3.83", 69, "FI", "FIN", "Finland", "EU"]
37 |     c.country_code3
38 |     => "FIN"
39 |     c.to_hash
40 |     => {:country_code3=>"FIN", :country_name=>"Finland", :continent_code=>"EU",
41 |     :request=>"www.nokia.com", :country_code=>69, :country_code2=>"FI", :ip=>"147.243.3.83"}
42 |     
43 | c = GeoIP.new('GeoLiteCity.dat').city('github.com') 44 | => ["github.com", "207.97.227.239", "US", "USA", "United States", "NA", "CA", 45 | "San Francisco", "94110", 37.7484, -122.4156, 807, 415, "America/Los_Angeles"] 46 | >> c.longitude 47 | => -122.4156 48 | >> c.timezone 49 | => "America/Los_Angeles" 50 |
51 | c = GeoIP.new('GeoIPASNum.dat').asn("www.fsb.ru") 52 | => ["AS8342", "RTComm.RU Autonomous System"] 53 |
54 | 55 | h2. Source Repository 56 | 57 | The trunk repository is http://github.com/cjheath/geoip 58 | 59 | h2. License 60 | 61 | I don't normally use the GPL license, but this one is derived 62 | from Maxmind's code, so I use the license they use. 63 | 64 | This version Copyright (C) 2005 Clifford Heath 65 | Derived from the C version, Copyright (C) 2003 MaxMind LLC 66 | 67 | This library is free software; you can redistribute it and/or 68 | modify it under the terms of the GNU General Public 69 | License as published by the Free Software Foundation; either 70 | version 2.1 of the License, or (at your option) any later version. 71 | 72 | This library is distributed in the hope that it will be useful, 73 | but WITHOUT ANY WARRANTY; without even the implied warranty of 74 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 75 | General Public License for more details. 76 | 77 | You should have received a copy of the GNU General Public 78 | License along with this library; if not, write to the Free Software 79 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 80 | -------------------------------------------------------------------------------- /data/geoip/country_name.yml: -------------------------------------------------------------------------------- 1 | # Ordered list of the English names of the countries, ordered by GeoIP ID 2 | --- 3 | - N/A 4 | - Asia/Pacific Region 5 | - Europe 6 | - Andorra 7 | - United Arab Emirates 8 | - Afghanistan 9 | - Antigua and Barbuda 10 | - Anguilla 11 | - Albania 12 | - Armenia 13 | - Netherlands Antilles 14 | - Angola 15 | - Antarctica 16 | - Argentina 17 | - American Samoa 18 | - Austria 19 | - Australia 20 | - Aruba 21 | - Azerbaijan 22 | - Bosnia and Herzegovina 23 | - Barbados 24 | - Bangladesh 25 | - Belgium 26 | - Burkina Faso 27 | - Bulgaria 28 | - Bahrain 29 | - Burundi 30 | - Benin 31 | - Bermuda 32 | - Brunei Darussalam 33 | - Bolivia 34 | - Brazil 35 | - Bahamas 36 | - Bhutan 37 | - Bouvet Island 38 | - Botswana 39 | - Belarus 40 | - Belize 41 | - Canada 42 | - Cocos (Keeling) Islands 43 | - Congo, the Democratic Republic of the 44 | - Central African Republic 45 | - Congo 46 | - Switzerland 47 | - Cote D'Ivoire 48 | - Cook Islands 49 | - Chile 50 | - Cameroon 51 | - China 52 | - Colombia 53 | - Costa Rica 54 | - Cuba 55 | - Cape Verde 56 | - Christmas Island 57 | - Cyprus 58 | - Czech Republic 59 | - Germany 60 | - Djibouti 61 | - Denmark 62 | - Dominica 63 | - Dominican Republic 64 | - Algeria 65 | - Ecuador 66 | - Estonia 67 | - Egypt 68 | - Western Sahara 69 | - Eritrea 70 | - Spain 71 | - Ethiopia 72 | - Finland 73 | - Fiji 74 | - Falkland Islands (Malvinas) 75 | - Micronesia, Federated States of 76 | - Faroe Islands 77 | - France 78 | - France, Metropolitan 79 | - Gabon 80 | - United Kingdom 81 | - Grenada 82 | - Georgia 83 | - French Guiana 84 | - Ghana 85 | - Gibraltar 86 | - Greenland 87 | - Gambia 88 | - Guinea 89 | - Guadeloupe 90 | - Equatorial Guinea 91 | - Greece 92 | - South Georgia and the South Sandwich Islands 93 | - Guatemala 94 | - Guam 95 | - Guinea-Bissau 96 | - Guyana 97 | - Hong Kong 98 | - Heard Island and McDonald Islands 99 | - Honduras 100 | - Croatia 101 | - Haiti 102 | - Hungary 103 | - Indonesia 104 | - Ireland 105 | - Israel 106 | - India 107 | - British Indian Ocean Territory 108 | - Iraq 109 | - Iran, Islamic Republic of 110 | - Iceland 111 | - Italy 112 | - Jamaica 113 | - Jordan 114 | - Japan 115 | - Kenya 116 | - Kyrgyzstan 117 | - Cambodia 118 | - Kiribati 119 | - Comoros 120 | - Saint Kitts and Nevis 121 | - Korea, Democratic People's Republic of 122 | - Korea, Republic of 123 | - Kuwait 124 | - Cayman Islands 125 | - Kazakhstan 126 | - Lao People's Democratic Republic 127 | - Lebanon 128 | - Saint Lucia 129 | - Liechtenstein 130 | - Sri Lanka 131 | - Liberia 132 | - Lesotho 133 | - Lithuania 134 | - Luxembourg 135 | - Latvia 136 | - Libyan Arab Jamahiriya 137 | - Morocco 138 | - Monaco 139 | - Moldova, Republic of 140 | - Madagascar 141 | - Marshall Islands 142 | - Macedonia, the Former Yugoslav Republic of 143 | - Mali 144 | - Myanmar 145 | - Mongolia 146 | - Macau 147 | - Northern Mariana Islands 148 | - Martinique 149 | - Mauritania 150 | - Montserrat 151 | - Malta 152 | - Mauritius 153 | - Maldives 154 | - Malawi 155 | - Mexico 156 | - Malaysia 157 | - Mozambique 158 | - Namibia 159 | - New Caledonia 160 | - Niger 161 | - Norfolk Island 162 | - Nigeria 163 | - Nicaragua 164 | - Netherlands 165 | - Norway 166 | - Nepal 167 | - Nauru 168 | - Niue 169 | - New Zealand 170 | - Oman 171 | - Panama 172 | - Peru 173 | - French Polynesia 174 | - Papua New Guinea 175 | - Philippines 176 | - Pakistan 177 | - Poland 178 | - Saint Pierre and Miquelon 179 | - Pitcairn 180 | - Puerto Rico 181 | - Palestinian Territory, Occupied 182 | - Portugal 183 | - Palau 184 | - Paraguay 185 | - Qatar 186 | - Reunion 187 | - Romania 188 | - Russian Federation 189 | - Rwanda 190 | - Saudi Arabia 191 | - Solomon Islands 192 | - Seychelles 193 | - Sudan 194 | - Sweden 195 | - Singapore 196 | - Saint Helena 197 | - Slovenia 198 | - Svalbard and Jan Mayen 199 | - Slovakia 200 | - Sierra Leone 201 | - San Marino 202 | - Senegal 203 | - Somalia 204 | - Suriname 205 | - Sao Tome and Principe 206 | - El Salvador 207 | - Syrian Arab Republic 208 | - Swaziland 209 | - Turks and Caicos Islands 210 | - Chad 211 | - French Southern Territories 212 | - Togo 213 | - Thailand 214 | - Tajikistan 215 | - Tokelau 216 | - Turkmenistan 217 | - Tunisia 218 | - Tonga 219 | - Timor-Leste 220 | - Turkey 221 | - Trinidad and Tobago 222 | - Tuvalu 223 | - Taiwan, Province of China 224 | - Tanzania, United Republic of 225 | - Ukraine 226 | - Uganda 227 | - United States Minor Outlying Islands 228 | - United States 229 | - Uruguay 230 | - Uzbekistan 231 | - Holy See (Vatican City State) 232 | - Saint Vincent and the Grenadines 233 | - Venezuela 234 | - Virgin Islands, British 235 | - Virgin Islands, U.S. 236 | - Viet Nam 237 | - Vanuatu 238 | - Wallis and Futuna 239 | - Samoa 240 | - Yemen 241 | - Mayotte 242 | - Serbia 243 | - South Africa 244 | - Zambia 245 | - Montenegro 246 | - Zimbabwe 247 | - Anonymous Proxy 248 | - Satellite Provider 249 | - Other 250 | - Aland Islands 251 | - Guernsey 252 | - Isle of Man 253 | - Jersey 254 | - Saint Barthelemy 255 | - Saint Martin 256 | -------------------------------------------------------------------------------- /README.rdoc: -------------------------------------------------------------------------------- 1 | = geoip 2 | 3 | http://github.com/cjheath/geoip 4 | 5 | == DESCRIPTION: 6 | 7 | GeoIP searches a GeoIP database for a given host or IP address, and 8 | returns information about the country where the IP address is allocated, 9 | and the city, ISP and other information, if you have that database version. 10 | 11 | == FEATURES/PROBLEMS: 12 | 13 | Includes support for ASN data files, thanks to Roland Matiz. 14 | This release adds support for timezone names, thanks to Tonni Aagesen. 15 | 16 | If you have required 'io/extra' and have IO#pread, cross-process file-descriptor sharing is enabled. 17 | Each GeoIP instance keeps the file descriptor open, with a Mutex for thread-safety. 18 | You should consider this if your process will fork without exec, as 19 | {modrails does}[http://www.modrails.com/documentation/Users%20guide%20Nginx.html#_smart_spawning_gotcha_1_unintential_file_descriptor_sharing] 20 | 21 | == SYNOPSIS: 22 | 23 | require 'geoip' 24 | 25 | # Use the country database: 26 | c = GeoIP.new('GeoIP.dat').country('www.nokia.com') 27 | => ["www.nokia.com", "147.243.3.83", 69, "FI", "FIN", "Finland", "EU"] 28 | c.country_code3 29 | => "FIN" 30 | c.to_hash 31 | => {:country_code3=>"FIN", :country_name=>"Finland", :continent_code=>"EU", :request=>"www.nokia.com", :country_code=>69, :country_code2=>"FI", :ip=>"147.243.3.83"} 32 | 33 | Returned values are the requested hostname, the IP address as a dotted quad, 34 | Maxmind's country code, the ISO3166-1 alpha-2 country code, the ISO3166-2 alpha-3 35 | country code, the ISO3166 country name, and the continent code. 36 | 37 | # Use the city database: 38 | c = GeoIP.new('GeoLiteCity.dat').city('github.com') 39 | => ["github.com", "207.97.227.239", "US", "USA", "United States", "NA", "CA", "San Francisco", "94110", 37.7484, -122.4156, 807, 415, "America/Los_Angeles"] 40 | >> c.longitude 41 | => -122.4156 42 | >> c.timezone 43 | => "America/Los_Angeles" 44 | 45 | GeoIP.new('GeoCity.dat').city('github.com') 46 | => ["github.com", "207.97.227.239", "US", "USA", "United States", "NA", "CA", "San Francisco", "94110", 37.7484, -122.4156, 807, 415, "America/Los_Angeles"] 47 | 48 | # Use the city ipv6 database: 49 | GeoIP.new('GeoLiteCityv6.dat').city('::151.38.39.114') 50 | => ["::151.38.39.114", "::151.38.39.114", "IT", "ITA", "Italy", "EU", "05", "Piacenza", "", 45.016699999999986, 9.666699999999992, nil, nil, "Europe/Rome"] 51 | 52 | Returned values are the requested hostname, the IP address as a dotted quad, 53 | the ISO3166-1 alpha-2 country code, the ISO3166-2 alpha-3 country code, the 54 | ISO3166 country name, the continent code, the region (state or territory) name, 55 | city name, postal_code/zipcode, latitude, longitude, USA DMA code, USA area code, 56 | timezone name. 57 | 58 | Result arrays from both city and country have mixed-in accessor methods as appropriate: 59 | request, ip, country_code, country_code2, country_code3, country_name, continent_code, 60 | region_name, city_name, postal_code, latitude, longitude, dma_code, area_code, timezone 61 | 62 | GeoIP.new('GeoIPASNum.dat').asn("www.fsb.ru") 63 | => ["AS8342", "RTComm.RU Autonomous System"] 64 | 65 | == REQUIREMENTS: 66 | 67 | You need one of the free GeoLite country, city or ASN databases, or a subscription database version. 68 | The last known download locations for the GeoLite database versions are 69 | , 70 | , 71 | . 72 | 73 | This API requires the file to be decompressed for searching. Other versions 74 | of this database are available for purchase which contain more detailed 75 | information, but this information is not returned by this implementation. 76 | See www.maxmind.com for more information. 77 | 78 | == INSTALL: 79 | 80 | sudo gem install geoip 81 | 82 | == LICENSE: 83 | 84 | This version Copyright (C) 2005 Clifford Heath 85 | Derived from the C version, Copyright (C) 2003 MaxMind LLC 86 | 87 | This library is free software; you can redistribute it and/or 88 | modify it under the terms of the GNU Lesser General Public License, 89 | as published by the Free Software Foundation; either version 2.1 of 90 | the License, or (at your option) any later version. This follows the 91 | license applied by Maxmind to their C library, for example in the 92 | version here: 93 | . 94 | 95 | This library is distributed in the hope that it will be useful, 96 | but WITHOUT ANY WARRANTY; without even the implied warranty of 97 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 98 | General Public License for more details. 99 | 100 | You should have received a copy of the GNU General Public 101 | License along with this library; if not, write to the Free Software 102 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 103 | -------------------------------------------------------------------------------- /data/geoip/time_zone.yml: -------------------------------------------------------------------------------- 1 | # Hash of the timezone codes mapped to timezone name, per zoneinfo 2 | --- 3 | UA18: Europe/Zaporozhye 4 | NZG1: Pacific/Auckland 5 | KZ12: Asia/Qyzylorda 6 | PS: Asia/Gaza 7 | UA19: Europe/Kiev 8 | NZG2: Pacific/Auckland 9 | KZ13: Asia/Aqtobe 10 | KW: Asia/Kuwait 11 | NZG3: Pacific/Auckland 12 | KZ14: Asia/Qyzylorda 13 | KZ15: Asia/Almaty 14 | KY: America/Cayman 15 | KZ16: Asia/Aqtobe 16 | PW: Pacific/Palau 17 | KZ17: Asia/Almaty 18 | USMA: America/New_York 19 | DE: Europe/Berlin 20 | NA: Africa/Windhoek 21 | PY: America/Asuncion 22 | USTX: America/Chicago 23 | IE: Europe/Dublin 24 | MX10: America/Mazatlan 25 | USMD: America/New_York 26 | NC: Pacific/Noumea 27 | EC01: Pacific/Galapagos 28 | MX11: America/Mexico_City 29 | SA: Asia/Riyadh 30 | USME: America/New_York 31 | UY: America/Montevideo 32 | ZW: Africa/Harare 33 | MX12: America/Mexico_City 34 | SB: Pacific/Guadalcanal 35 | DJ: Africa/Djibouti 36 | NE: Africa/Niamey 37 | USHI: Pacific/Honolulu 38 | EC02: America/Guayaquil 39 | MX13: America/Mexico_City 40 | SC: Indian/Mahe 41 | DK: Europe/Copenhagen 42 | USWA: America/Los_Angeles 43 | NF: Pacific/Norfolk 44 | EC03: America/Guayaquil 45 | CAPE: America/Halifax 46 | RU20: Asia/Irkutsk 47 | MX14: America/Mazatlan 48 | SD: Africa/Khartoum 49 | NG: Africa/Lagos 50 | EC04: America/Guayaquil 51 | RU21: Europe/Moscow 52 | MX15: America/Chihuahua 53 | USMI: America/New_York 54 | DM: America/Dominica 55 | EC05: America/Guayaquil 56 | BR20: America/Fortaleza 57 | SE: Europe/Stockholm 58 | UZ01: Asia/Tashkent 59 | RU70: Europe/Volgograd 60 | RU22: Europe/Volgograd 61 | MX16: America/Mexico_City 62 | CD02: Africa/Kinshasa 63 | NI: America/Managua 64 | EC06: America/Guayaquil 65 | BR21: America/Sao_Paulo 66 | USCO: America/Denver 67 | UZ02: Asia/Samarkand 68 | RU71: Asia/Yekaterinburg 69 | RU23: Europe/Kaliningrad 70 | MX17: America/Mexico_City 71 | DO: America/Santo_Domingo 72 | EC07: America/Guayaquil 73 | BR22: America/Recife 74 | IL: Asia/Jerusalem 75 | SG: Asia/Singapore 76 | UZ03: Asia/Tashkent 77 | RU72: Europe/Moscow 78 | RU24: Europe/Volgograd 79 | MX18: America/Mazatlan 80 | EC08: America/Guayaquil 81 | BR23: America/Sao_Paulo 82 | CN01: Asia/Shanghai 83 | USRI: America/New_York 84 | IM: Europe/Isle_of_Man 85 | SH: Atlantic/St_Helena 86 | RU73: Europe/Samara 87 | RU25: Europe/Moscow 88 | MX19: America/Monterrey 89 | CD05: Africa/Lubumbashi 90 | NL: Europe/Amsterdam 91 | EC09: America/Guayaquil 92 | BR24: America/Porto_Velho 93 | CN02: Asia/Shanghai 94 | IN: Asia/Calcutta 95 | SI: Europe/Ljubljana 96 | RU26: Asia/Kamchatka 97 | USMN: America/Chicago 98 | CD06: Africa/Kinshasa 99 | BR25: America/Boa_Vista 100 | CN03: Asia/Shanghai 101 | IO: Indian/Chagos 102 | SJ: Arctic/Longyearbyen 103 | UZ06: Asia/Tashkent 104 | RU74: Asia/Krasnoyarsk 105 | RU27: Europe/Volgograd 106 | USWI: America/Chicago 107 | BR26: America/Sao_Paulo 108 | CN04: Asia/Shanghai 109 | USCT: America/New_York 110 | SK: Europe/Bratislava 111 | UZ07: Asia/Samarkand 112 | RU75: Asia/Novosibirsk 113 | RU28: Europe/Moscow 114 | USMO: America/Chicago 115 | CD08: Africa/Kinshasa 116 | BR27: America/Sao_Paulo 117 | CN05: Asia/Harbin 118 | IQ: Asia/Baghdad 119 | SL: Africa/Freetown 120 | UZ08: Asia/Samarkand 121 | RU76: Europe/Moscow 122 | RU29: Asia/Novokuznetsk 123 | ES27: Europe/Madrid 124 | "NO": Europe/Oslo 125 | BR28: America/Maceio 126 | CN06: Asia/Chongqing 127 | IR: Asia/Tehran 128 | SM: Europe/San_Marino 129 | UZ09: Asia/Samarkand 130 | RU77: Europe/Moscow 131 | PT02: Europe/Lisbon 132 | NP: Asia/Katmandu 133 | BR29: America/Sao_Paulo 134 | CN07: Asia/Shanghai 135 | IS: Atlantic/Reykjavik 136 | SN: Africa/Dakar 137 | RU78: Asia/Yekaterinburg 138 | PT03: Europe/Lisbon 139 | ES29: Europe/Madrid 140 | CN08: Asia/Harbin 141 | IT: Europe/Rome 142 | SO: Africa/Mogadishu 143 | RU79: Asia/Irkutsk 144 | PT04: Europe/Lisbon 145 | NR: Pacific/Nauru 146 | CN09: Asia/Shanghai 147 | USMS: America/Chicago 148 | PT05: Europe/Lisbon 149 | BA: Europe/Sarajevo 150 | USMT: America/Denver 151 | PT06: Europe/Lisbon 152 | SR: America/Paramaribo 153 | DZ: Africa/Algiers 154 | PT07: Europe/Lisbon 155 | NU: Pacific/Niue 156 | BB: America/Barbados 157 | PT08: Europe/Lisbon 158 | GA: Africa/Libreville 159 | PT09: Europe/Lisbon 160 | GB: Europe/London 161 | BD: Asia/Dhaka 162 | ST: Africa/Sao_Tome 163 | BE: Europe/Brussels 164 | NZE7: Pacific/Auckland 165 | GD: America/Grenada 166 | BF: Africa/Ouagadougou 167 | SV: America/El_Salvador 168 | LA: Asia/Vientiane 169 | NZE8: Pacific/Auckland 170 | USWV: America/New_York 171 | GE: Asia/Tbilisi 172 | BG: Europe/Sofia 173 | LB: Asia/Beirut 174 | USPA: America/New_York 175 | GF: America/Cayenne 176 | CANB: America/Halifax 177 | BH: Asia/Bahrain 178 | LC: America/St_Lucia 179 | NZE9: Pacific/Auckland 180 | QA: Asia/Qatar 181 | BI: Africa/Bujumbura 182 | SY: Asia/Damascus 183 | GG: Europe/Guernsey 184 | USAK: America/Anchorage 185 | BJ: Africa/Porto-Novo 186 | SZ: Africa/Mbabane 187 | USWY: America/Denver 188 | GH: Africa/Accra 189 | USAL: America/Chicago 190 | GI: Europe/Gibraltar 191 | BL: America/St_Barthelemy 192 | VA: Europe/Vatican 193 | RU01: Europe/Volgograd 194 | BM: Atlantic/Bermuda 195 | RU50: Asia/Yekaterinburg 196 | RU02: Asia/Irkutsk 197 | BN: Asia/Brunei 198 | LI: Europe/Vaduz 199 | USFL: America/New_York 200 | VC: America/St_Vincent 201 | BR01: America/Rio_Branco 202 | RU51: Europe/Moscow 203 | RU03: Asia/Novokuznetsk 204 | AR20: America/Argentina/Rio_Gallegos 205 | BO: America/La_Paz 206 | BR02: America/Maceio 207 | RU04: Asia/Novosibirsk 208 | ID20: Asia/Makassar 209 | GM: Africa/Banjul 210 | AR21: America/Argentina/Buenos_Aires 211 | LK: Asia/Colombo 212 | VE: America/Caracas 213 | BR03: America/Sao_Paulo 214 | RU52: Europe/Moscow 215 | RU05: Asia/Vladivostok 216 | ID21: Asia/Makassar 217 | GN: Africa/Conakry 218 | AR22: America/Argentina/Catamarca 219 | USAR: America/Chicago 220 | BR04: America/Manaus 221 | RU53: Asia/Novosibirsk 222 | RU06: Europe/Moscow 223 | ID22: Asia/Makassar 224 | ES51: Africa/Ceuta 225 | AR23: America/Argentina/Ushuaia 226 | CANL: America/St_Johns 227 | CN30: Asia/Chongqing 228 | VG: America/Tortola 229 | BR05: America/Bahia 230 | RU54: Asia/Omsk 231 | RU07: Europe/Volgograd 232 | ID23: Asia/Makassar 233 | ES52: Europe/Madrid 234 | GP: America/Guadeloupe 235 | AR24: America/Argentina/Tucuman 236 | BS: America/Nassau 237 | CN31: Asia/Chongqing 238 | BR06: America/Fortaleza 239 | UA20: Europe/Simferopol 240 | RU55: Europe/Samara 241 | RU08: Europe/Samara 242 | ID24: Asia/Jakarta 243 | ES53: Atlantic/Canary 244 | GQ: Africa/Malabo 245 | BT: Asia/Thimphu 246 | CN32: Asia/Chongqing 247 | CASK: America/Regina 248 | VI: America/St_Thomas 249 | BR07: America/Sao_Paulo 250 | UA21: Europe/Kiev 251 | RU56: Europe/Moscow 252 | RU09: Europe/Moscow 253 | ID25: Asia/Pontianak 254 | ES54: Europe/Madrid 255 | ES07: Europe/Madrid 256 | GR: Europe/Athens 257 | CN33: Asia/Chongqing 258 | BR08: America/Sao_Paulo 259 | UA22: Europe/Uzhgorod 260 | RU57: Europe/Samara 261 | ID26: Asia/Pontianak 262 | ES55: Europe/Madrid 263 | GS: Atlantic/South_Georgia 264 | UA23: Europe/Kiev 265 | RU58: Asia/Yekaterinburg 266 | MY01: Asia/Kuala_Lumpur 267 | ES56: Europe/Madrid 268 | BW: Africa/Gaborone 269 | GT: America/Guatemala 270 | UA24: Europe/Uzhgorod 271 | RU59: Asia/Vladivostok 272 | MY02: Asia/Kuala_Lumpur 273 | ES57: Europe/Madrid 274 | USKS: America/Chicago 275 | LR: Africa/Monrovia 276 | GU: Pacific/Guam 277 | UA25: Europe/Uzhgorod 278 | MY03: Asia/Kuala_Lumpur 279 | ES58: Europe/Madrid 280 | USAZ: America/Phoenix 281 | BY: Europe/Minsk 282 | LS: Africa/Maseru 283 | VN: Asia/Phnom_Penh 284 | UA26: Europe/Zaporozhye 285 | MY04: Asia/Kuala_Lumpur 286 | ES59: Europe/Madrid 287 | CANS: America/Halifax 288 | BZ: America/Belize 289 | LT: Europe/Vilnius 290 | GW: Africa/Bissau 291 | UA27: Europe/Kiev 292 | MY05: Asia/Kuala_Lumpur 293 | CANT: America/Yellowknife 294 | LU: Europe/Luxembourg 295 | MY06: Asia/Kuala_Lumpur 296 | CANU: America/Rankin_Inlet 297 | LV: Europe/Riga 298 | CABC: America/Vancouver 299 | GY: America/Guyana 300 | MY07: Asia/Kuala_Lumpur 301 | USDC: America/New_York 302 | MY08: Asia/Kuala_Lumpur 303 | USKY: America/New_York 304 | USUT: America/Denver 305 | USIA: America/Chicago 306 | MY09: Asia/Kuala_Lumpur 307 | USDE: America/New_York 308 | LY: Africa/Tripoli 309 | VU: Pacific/Efate 310 | EE: Europe/Tallinn 311 | USID: America/Denver 312 | JE: Europe/Jersey 313 | USNC: America/New_York 314 | EG: Africa/Cairo 315 | EC10: America/Guayaquil 316 | MX20: America/Mexico_City 317 | USND: America/Chicago 318 | EH: Africa/El_Aaiun 319 | EC11: America/Guayaquil 320 | MX21: America/Mexico_City 321 | CAQC: America/Montreal 322 | USNE: America/Chicago 323 | EC12: America/Guayaquil 324 | MX22: America/Mexico_City 325 | USSC: America/New_York 326 | MX23: America/Cancun 327 | USSD: America/Chicago 328 | TC: America/Grand_Turk 329 | EC13: America/Guayaquil 330 | RU30: Asia/Vladivostok 331 | MX24: America/Mexico_City 332 | TD: Africa/Ndjamena 333 | USNH: America/New_York 334 | CD10: Africa/Lubumbashi 335 | EC14: America/Guayaquil 336 | UZ10: Asia/Samarkand 337 | RU31: Asia/Krasnoyarsk 338 | MX25: America/Mazatlan 339 | CD11: Africa/Lubumbashi 340 | AR01: America/Argentina/Buenos_Aires 341 | EC15: America/Guayaquil 342 | BR30: America/Recife 343 | RU80: Asia/Yekaterinburg 344 | RU32: Asia/Omsk 345 | MX26: America/Hermosillo 346 | ID01: Asia/Pontianak 347 | TF: Indian/Kerguelen 348 | USNJ: America/New_York 349 | CD12: Africa/Lubumbashi 350 | AR02: America/Argentina/Catamarca 351 | USIL: America/Chicago 352 | BR31: America/Araguaina 353 | UZ12: Asia/Samarkand 354 | RU81: Europe/Samara 355 | RU33: Asia/Yekaterinburg 356 | MX27: America/Merida 357 | ID02: Asia/Makassar 358 | ES31: Europe/Madrid 359 | TG: Africa/Lome 360 | AR03: America/Argentina/Tucuman 361 | EC17: America/Guayaquil 362 | CN10: Asia/Shanghai 363 | UZ13: Asia/Tashkent 364 | RU82: Asia/Irkutsk 365 | RU34: Asia/Yekaterinburg 366 | MX28: America/Monterrey 367 | ID03: Asia/Jakarta 368 | ES32: Europe/Madrid 369 | JM: America/Jamaica 370 | TH: Asia/Bangkok 371 | AR04: America/Argentina/Rio_Gallegos 372 | USIN: America/Indianapolis 373 | EC18: America/Guayaquil 374 | YE: Asia/Aden 375 | CN11: Asia/Chongqing 376 | UZ14: Asia/Tashkent 377 | RU83: Europe/Moscow 378 | RU35: Asia/Yekaterinburg 379 | MX29: America/Mexico_City 380 | ID04: Asia/Jakarta 381 | USNM: America/Denver 382 | AR05: America/Argentina/Cordoba 383 | EC19: America/Guayaquil 384 | CN12: Asia/Shanghai 385 | UA01: Europe/Kiev 386 | RU84: Europe/Volgograd 387 | RU36: Asia/Anadyr 388 | ES34: Europe/Madrid 389 | JO: Asia/Amman 390 | TJ: Asia/Dushanbe 391 | ER: Africa/Asmera 392 | AR06: America/Argentina/Tucuman 393 | OM: Asia/Muscat 394 | CN13: Asia/Urumqi 395 | UA02: Europe/Kiev 396 | RU37: Europe/Moscow 397 | ID05: Asia/Jakarta 398 | TK: Pacific/Fakaofo 399 | AR07: America/Argentina/Buenos_Aires 400 | CN14: Asia/Chongqing 401 | JP: Asia/Tokyo 402 | TL: Asia/Dili 403 | UA03: Europe/Uzhgorod 404 | RU85: Europe/Moscow 405 | RU38: Europe/Volgograd 406 | PT10: Atlantic/Madeira 407 | ID06: Asia/Jakarta 408 | ET: Africa/Addis_Ababa 409 | AR08: America/Argentina/Buenos_Aires 410 | CN15: Asia/Chongqing 411 | UA04: Europe/Zaporozhye 412 | RU86: Europe/Moscow 413 | RU39: Asia/Krasnoyarsk 414 | PT11: Europe/Lisbon 415 | ID07: Asia/Jakarta 416 | TM: Asia/Ashgabat 417 | AR09: America/Argentina/Tucuman 418 | CN16: Asia/Chongqing 419 | UA05: Europe/Zaporozhye 420 | RU87: Asia/Novosibirsk 421 | ID08: Asia/Jakarta 422 | TN: Africa/Tunis 423 | UA06: Europe/Uzhgorod 424 | RU88: Europe/Moscow 425 | PT13: Europe/Lisbon 426 | ID09: Asia/Jayapura 427 | ES39: Europe/Madrid 428 | TO: Pacific/Tongatapu 429 | CN18: Asia/Chongqing 430 | UA07: Europe/Zaporozhye 431 | RU89: Asia/Vladivostok 432 | PT14: Europe/Lisbon 433 | KZ01: Asia/Almaty 434 | CN19: Asia/Harbin 435 | UA08: Europe/Simferopol 436 | NZF1: Pacific/Auckland 437 | KZ02: Asia/Almaty 438 | UA09: Europe/Kiev 439 | PT16: Europe/Lisbon 440 | NZF2: Pacific/Auckland 441 | KZ03: Asia/Qyzylorda 442 | TR: Asia/Istanbul 443 | PT17: Europe/Lisbon 444 | NZF3: Pacific/Auckland 445 | KZ04: Asia/Aqtobe 446 | USNV: America/Los_Angeles 447 | USGA: America/New_York 448 | AU01: Australia/Canberra 449 | PT18: Europe/Lisbon 450 | NZF4: Pacific/Auckland 451 | KZ05: Asia/Qyzylorda 452 | AU02: Australia/NSW 453 | CC: Indian/Cocos 454 | PT19: Europe/Lisbon 455 | NZF5: Pacific/Auckland 456 | KZ06: Asia/Aqtau 457 | TT: America/Port_of_Spain 458 | AU03: Australia/North 459 | KZ07: Asia/Oral 460 | USNY: America/New_York 461 | AU04: Australia/Queensland 462 | USLA: America/Chicago 463 | NZF7: Pacific/Chatham 464 | KZ08: Asia/Qyzylorda 465 | TV: Pacific/Funafuti 466 | MA: Africa/Casablanca 467 | AU05: Australia/South 468 | YT: Indian/Mayotte 469 | CF: Africa/Bangui 470 | NZF8: Pacific/Auckland 471 | KZ09: Asia/Aqtau 472 | TW: Asia/Taipei 473 | AU06: Australia/Tasmania 474 | YU: Europe/Belgrade 475 | CG: Africa/Brazzaville 476 | NZF9: Pacific/Auckland 477 | MC: Europe/Monaco 478 | AU07: Australia/Victoria 479 | CH: Europe/Zurich 480 | MX01: America/Mexico_City 481 | MD: Europe/Chisinau 482 | AU08: Australia/West 483 | CI: Africa/Abidjan 484 | MX02: America/Tijuana 485 | ME: Europe/Podgorica 486 | TZ: Africa/Dar_es_Salaam 487 | MX03: America/Hermosillo 488 | USVA: America/New_York 489 | MF: America/Marigot 490 | CK: Pacific/Rarotonga 491 | RU10: Europe/Moscow 492 | MX04: America/Merida 493 | MG: Indian/Antananarivo 494 | CL: Chile/Continental 495 | RU11: Asia/Irkutsk 496 | MX05: America/Mexico_City 497 | RE: Indian/Reunion 498 | CM: Africa/Lagos 499 | RU60: Europe/Kaliningrad 500 | MX06: America/Chihuahua 501 | BR11: America/Campo_Grande 502 | HK: Asia/Hong_Kong 503 | RU61: Europe/Volgograd 504 | RU13: Asia/Yekaterinburg 505 | MX07: America/Monterrey 506 | CO: America/Bogota 507 | RU62: Europe/Moscow 508 | RU14: Asia/Irkutsk 509 | MX08: America/Mexico_City 510 | ID30: Asia/Jakarta 511 | MK: Europe/Skopje 512 | BR13: America/Belem 513 | RU15: Asia/Anadyr 514 | MX09: America/Mexico_City 515 | ID31: Asia/Makassar 516 | ES60: Europe/Madrid 517 | ML: Africa/Bamako 518 | WF: Pacific/Wallis 519 | BR14: America/Cuiaba 520 | HN: America/Tegucigalpa 521 | RU63: Asia/Yakutsk 522 | RU16: Europe/Samara 523 | BR15: America/Sao_Paulo 524 | CR: America/Costa_Rica 525 | RU64: Asia/Sakhalin 526 | RU17: Europe/Volgograd 527 | ID33: Asia/Jakarta 528 | BR16: America/Belem 529 | MM: Asia/Rangoon 530 | RU65: Europe/Samara 531 | RU18: Asia/Krasnoyarsk 532 | BR17: America/Recife 533 | CAON: America/Rainy_River 534 | MN: Asia/Choibalsan 535 | RU66: Europe/Moscow 536 | BR18: America/Sao_Paulo 537 | HR: Europe/Zagreb 538 | CU: America/Havana 539 | MO: Asia/Macao 540 | RU67: Europe/Samara 541 | CV: Atlantic/Cape_Verde 542 | MP: Pacific/Saipan 543 | RU68: Europe/Volgograd 544 | MY11: Asia/Kuching 545 | HT: America/Port-au-Prince 546 | RO: Europe/Bucharest 547 | MQ: America/Martinique 548 | RU69: Europe/Moscow 549 | MY12: Asia/Kuala_Lumpur 550 | HU: Europe/Budapest 551 | CX: Indian/Christmas 552 | MR: Africa/Nouakchott 553 | MY13: Asia/Kuala_Lumpur 554 | CY: Asia/Nicosia 555 | MS: America/Montserrat 556 | MY14: Asia/Kuala_Lumpur 557 | CZ: Europe/Prague 558 | MT: Europe/Malta 559 | MY15: Asia/Kuching 560 | MU: Indian/Mauritius 561 | MY16: Asia/Kuching 562 | RS: Europe/Belgrade 563 | MV: Indian/Maldives 564 | GL01: America/Thule 565 | AD: Europe/Andorra 566 | MW: Africa/Blantyre 567 | GL02: America/Godthab 568 | WS: Pacific/Samoa 569 | AE: Asia/Dubai 570 | USVT: America/New_York 571 | GL03: America/Godthab 572 | AF: Asia/Kabul 573 | AG: America/Antigua 574 | RW: Africa/Kigali 575 | CAYT: America/Whitehorse 576 | MZ: Africa/Maputo 577 | CAMB: America/Winnipeg 578 | PA: America/Panama 579 | AI: America/Anguilla 580 | EC20: America/Guayaquil 581 | KE: Africa/Nairobi 582 | MX30: America/Mexico_City 583 | MX31: America/Merida 584 | EC22: America/Guayaquil 585 | AL: Europe/Tirane 586 | KG: Asia/Bishkek 587 | FI: Europe/Helsinki 588 | MX32: America/Monterrey 589 | PE: America/Lima 590 | AM: Asia/Yerevan 591 | KH: Asia/Phnom_Penh 592 | FJ: Pacific/Fiji 593 | PF: Pacific/Marquesas 594 | RU40: Asia/Yekaterinburg 595 | AN: America/Curacao 596 | KI: Pacific/Tarawa 597 | FK: Atlantic/Stanley 598 | PG: Pacific/Port_Moresby 599 | AO: Africa/Luanda 600 | ZA: Africa/Johannesburg 601 | USOH: America/New_York 602 | AR10: America/Argentina/Jujuy 603 | RU41: Europe/Moscow 604 | ID10: Asia/Jakarta 605 | PH: Asia/Manila 606 | AR11: America/Argentina/San_Luis 607 | RU42: Europe/Moscow 608 | ID11: Asia/Pontianak 609 | AR12: America/Argentina/La_Rioja 610 | RU43: Europe/Moscow 611 | ID12: Asia/Makassar 612 | CN20: Asia/Harbin 613 | UG: Africa/Kampala 614 | USOK: America/Chicago 615 | FO: Atlantic/Faeroe 616 | AR13: America/Argentina/Mendoza 617 | RU44: Asia/Magadan 618 | ID13: Asia/Makassar 619 | AS: US/Samoa 620 | CN21: Asia/Chongqing 621 | KM: Indian/Comoro 622 | AR14: America/Argentina/Buenos_Aires 623 | PK: Asia/Karachi 624 | UA10: Europe/Zaporozhye 625 | RU45: Europe/Samara 626 | ID14: Asia/Makassar 627 | AT: Europe/Vienna 628 | CN22: Asia/Harbin 629 | KN: America/St_Kitts 630 | AR15: America/Argentina/San_Luis 631 | PL: Europe/Warsaw 632 | UA11: Europe/Simferopol 633 | RU46: Europe/Samara 634 | ID15: Asia/Jakarta 635 | CN23: Asia/Shanghai 636 | FR: Europe/Paris 637 | AR16: America/Argentina/Buenos_Aires 638 | PM: America/Miquelon 639 | RU47: Europe/Moscow 640 | CN24: Asia/Chongqing 641 | KP: Asia/Pyongyang 642 | AR17: America/Argentina/Salta 643 | PN: Pacific/Pitcairn 644 | UA13: Europe/Kiev 645 | RU48: Europe/Moscow 646 | PT20: Europe/Lisbon 647 | ID16: Asia/Makassar 648 | AW: America/Aruba 649 | CN25: Asia/Shanghai 650 | AR18: America/Argentina/San_Juan 651 | UA14: Europe/Zaporozhye 652 | RU49: Europe/Moscow 653 | PT21: Europe/Lisbon 654 | NZ85: Pacific/Auckland 655 | ID17: Asia/Makassar 656 | AX: Europe/Mariehamn 657 | CN26: Asia/Chongqing 658 | USTN: America/Chicago 659 | KR: Asia/Seoul 660 | AR19: America/Argentina/San_Luis 661 | UA15: Europe/Uzhgorod 662 | PT22: Europe/Lisbon 663 | ID18: Asia/Makassar 664 | UA16: Europe/Zaporozhye 665 | KZ10: Asia/Qyzylorda 666 | ID19: Asia/Pontianak 667 | AZ: Asia/Baku 668 | CN28: Asia/Shanghai 669 | USOR: America/Los_Angeles 670 | UA17: Europe/Simferopol 671 | KZ11: Asia/Almaty 672 | ZM: Africa/Lusaka 673 | CN29: Asia/Chongqing 674 | USCA: America/Los_Angeles 675 | CAAB: America/Edmonton 676 | FX: Europe/Paris 677 | PR: America/Puerto_Rico 678 | -------------------------------------------------------------------------------- /lib/geoip.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Native Ruby reader for the GeoIP database 3 | # Lookup the country where IP address is allocated 4 | # 5 | # = COPYRIGHT 6 | # 7 | # This version Copyright (C) 2005 Clifford Heath 8 | # Derived from the C version, Copyright (C) 2003 MaxMind LLC 9 | # 10 | # This library is free software; you can redistribute it and/or 11 | # modify it under the terms of the GNU General Public 12 | # License as published by the Free Software Foundation; either 13 | # version 2.1 of the License, or (at your option) any later version. 14 | # 15 | # This library is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | # General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public 21 | # License along with this library; if not, write to the Free Software 22 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | # 24 | # = SYNOPSIS 25 | # 26 | # require 'geoip' 27 | # p GeoIP.new('/usr/share/GeoIP/GeoIP.dat').country("www.netscape.sk") 28 | # 29 | # = DESCRIPTION 30 | # 31 | # GeoIP searches a GeoIP database for a given host or IP address, and 32 | # returns information about the country where the IP address is allocated. 33 | # 34 | # = PREREQUISITES 35 | # 36 | # You need at least the free GeoIP.dat, for which the last known download 37 | # location is 38 | # This API requires the file to be decompressed for searching. Other versions 39 | # of this database are available for purchase which contain more detailed 40 | # information, but this information is not returned by this implementation. 41 | # See www.maxmind.com for more information. 42 | # 43 | 44 | require 'thread' # Needed for Mutex 45 | require 'socket' 46 | begin 47 | require 'io/extra' # for IO.pread 48 | rescue LoadError 49 | # oh well, hope they're not forking after initializing 50 | end 51 | begin 52 | require 'ipaddr' # Needed for IPv6 support 53 | rescue LoadError 54 | # Won't work for an IPv6 database 55 | end 56 | 57 | require 'yaml' 58 | 59 | class GeoIP 60 | 61 | # The GeoIP GEM version number 62 | VERSION = "1.2.1" 63 | 64 | # The +data/+ directory for geoip 65 | DATA_DIR = File.expand_path(File.join(File.dirname(__FILE__),'..','data','geoip')) 66 | 67 | # Ordered list of the ISO3166 2-character country codes, ordered by 68 | # GeoIP ID 69 | CountryCode = YAML.load_file(File.join(DATA_DIR,'country_code.yml')) 70 | 71 | # Ordered list of the ISO3166 3-character country codes, ordered by 72 | # GeoIP ID 73 | CountryCode3 = YAML.load_file(File.join(DATA_DIR,'country_code3.yml')) 74 | 75 | # Ordered list of the English names of the countries, ordered by GeoIP ID 76 | CountryName = YAML.load_file(File.join(DATA_DIR,'country_name.yml')) 77 | 78 | # Ordered list of the ISO3166 2-character continent code of the countries, 79 | # ordered by GeoIP ID 80 | CountryContinent = YAML.load_file(File.join(DATA_DIR,'country_continent.yml')) 81 | 82 | # Hash of the timezone codes mapped to timezone name, per zoneinfo 83 | TimeZone = YAML.load_file(File.join(DATA_DIR,'time_zone.yml')) 84 | 85 | GEOIP_COUNTRY_EDITION = 1 86 | GEOIP_CITY_EDITION_REV1 = 2 87 | GEOIP_REGION_EDITION_REV1 = 3 88 | GEOIP_ISP_EDITION = 4 89 | GEOIP_ORG_EDITION = 5 90 | GEOIP_CITY_EDITION_REV0 = 6 91 | GEOIP_REGION_EDITION_REV0 = 7 92 | GEOIP_PROXY_EDITION = 8 93 | GEOIP_ASNUM_EDITION = 9 94 | GEOIP_NETSPEED_EDITION = 10 95 | GEOIP_COUNTRY_EDITION_V6 = 12 96 | GEOIP_CITY_EDITION_REV1_V6 = 30 97 | 98 | COUNTRY_BEGIN = 16776960 #:nodoc: 99 | STATE_BEGIN_REV0 = 16700000 #:nodoc: 100 | STATE_BEGIN_REV1 = 16000000 #:nodoc: 101 | STRUCTURE_INFO_MAX_SIZE = 20 #:nodoc: 102 | DATABASE_INFO_MAX_SIZE = 100 #:nodoc: 103 | MAX_ORG_RECORD_LENGTH = 300 #:nodoc: 104 | MAX_ASN_RECORD_LENGTH = 300 #:nodoc: unverified 105 | US_OFFSET = 1 #:nodoc: 106 | CANADA_OFFSET = 677 #:nodoc: 107 | WORLD_OFFSET = 1353 #:nodoc: 108 | FIPS_RANGE = 360 #:nodoc: 109 | FULL_RECORD_LENGTH = 50 #:nodoc: 110 | 111 | STANDARD_RECORD_LENGTH = 3 #:nodoc: 112 | SEGMENT_RECORD_LENGTH = 3 #:nodoc: 113 | 114 | class Country < Struct.new(:request, :ip, :country_code, :country_code2, :country_code3, :country_name, :continent_code) 115 | 116 | def to_hash 117 | Hash[each_pair.to_a] 118 | end 119 | 120 | end 121 | 122 | class City < Struct.new(:request, :ip, :country_code2, :country_code3, :country_name, :continent_code, 123 | :region_name, :city_name, :postal_code, :latitude, :longitude, :dma_code, :area_code, :timezone) 124 | 125 | def to_hash 126 | Hash[each_pair.to_a] 127 | end 128 | 129 | end 130 | 131 | class ASN < Struct.new(:number, :asn) 132 | 133 | alias as_num number 134 | 135 | end 136 | 137 | # The Edition number that identifies which kind of database you've opened 138 | attr_reader :database_type 139 | 140 | alias databaseType database_type 141 | 142 | # Open the GeoIP database and determine the file format version. 143 | # 144 | # +filename+ is a String holding the path to the GeoIP.dat file 145 | # +options+ is an integer holding caching flags (unimplemented) 146 | # 147 | def initialize(filename, flags = 0) 148 | @mutex = unless IO.respond_to?(:pread) 149 | Mutex.new 150 | end 151 | 152 | @flags = flags 153 | @database_type = GEOIP_COUNTRY_EDITION 154 | @record_length = STANDARD_RECORD_LENGTH 155 | @file = File.open(filename, 'rb') 156 | 157 | detect_database_type! 158 | end 159 | 160 | # Search the GeoIP database for the specified host, returning country 161 | # info. 162 | # 163 | # +hostname+ is a String holding the host's DNS name or numeric IP 164 | # address. 165 | # 166 | # If the database is a City database (normal), return the result that 167 | # +city+ would return. 168 | # 169 | # Otherwise, return a Country object with the seven elements: 170 | # * The host or IP address string as requested 171 | # * The IP address string after looking up the host 172 | # * The GeoIP country-ID as an integer (N.B. this is excluded from the 173 | # city results!) 174 | # * The two-character country code (ISO 3166-1 alpha-2) 175 | # * The three-character country code (ISO 3166-2 alpha-3) 176 | # * The ISO 3166 English-language name of the country 177 | # * The two-character continent code 178 | # 179 | def country(hostname) 180 | if (@database_type == GEOIP_CITY_EDITION_REV0 || 181 | @database_type == GEOIP_CITY_EDITION_REV1 || 182 | @database_type == GEOIP_CITY_EDITION_REV1_V6) 183 | return city(hostname) 184 | end 185 | 186 | ip = lookup_ip(hostname) 187 | if (@database_type == GEOIP_COUNTRY_EDITION || 188 | @database_type == GEOIP_PROXY_EDITION || 189 | @database_type == GEOIP_NETSPEED_EDITION) 190 | # Convert numeric IP address to an integer 191 | ipnum = iptonum(ip) 192 | code = (seek_record(ipnum) - COUNTRY_BEGIN) 193 | elsif @database_type == GEOIP_COUNTRY_EDITION_V6 194 | ipaddr = IPAddr.new ip 195 | code = (seek_record_v6(ipaddr.to_i) - COUNTRY_BEGIN) 196 | else 197 | throw "Invalid GeoIP database type, can't look up Country by IP" 198 | end 199 | 200 | Country.new( 201 | hostname, # Requested hostname 202 | ip, # Ip address as dotted quad 203 | code, # GeoIP's country code 204 | CountryCode[code], # ISO3166-1 alpha-2 code 205 | CountryCode3[code], # ISO3166-2 alpha-3 code 206 | CountryName[code], # Country name, per ISO 3166 207 | CountryContinent[code] # Continent code. 208 | ) 209 | end 210 | 211 | # Search the GeoIP database for the specified host, returning city info. 212 | # 213 | # +hostname+ is a String holding the host's DNS name or numeric IP 214 | # address. 215 | # 216 | # Returns a City object with the fourteen elements: 217 | # * The host or IP address string as requested 218 | # * The IP address string after looking up the host 219 | # * The two-character country code (ISO 3166-1 alpha-2) 220 | # * The three-character country code (ISO 3166-2 alpha-3) 221 | # * The ISO 3166 English-language name of the country 222 | # * The two-character continent code 223 | # * The region name (state or territory) 224 | # * The city name 225 | # * The postal code (zipcode) 226 | # * The latitude 227 | # * The longitude 228 | # * The USA dma_code if known (only REV1 City database) 229 | # * The USA area_code if known (only REV1 City database) 230 | # * The timezone name, if known 231 | # 232 | def city(hostname) 233 | ip = lookup_ip(hostname) 234 | 235 | if (@database_type == GEOIP_CITY_EDITION_REV0 || 236 | @database_type == GEOIP_CITY_EDITION_REV1) 237 | # Convert numeric IP address to an integer 238 | ipnum = iptonum(ip) 239 | pos = seek_record(ipnum) 240 | elsif (@database_type == GEOIP_CITY_EDITION_REV1_V6) 241 | ipaddr = IPAddr.new ip 242 | pos = seek_record_v6(ipaddr.to_i) 243 | else 244 | throw "Invalid GeoIP database type, can't look up City by IP" 245 | end 246 | 247 | # This next statement was added to MaxMind's C version after it was 248 | # rewritten in Ruby. It prevents unassigned IP addresses from returning 249 | # bogus data. There was concern over whether the changes to an 250 | # application's behaviour were always correct, but this has been tested 251 | # using an exhaustive search of the top 16 bits of the IP address space. 252 | # The records where the change takes effect contained *no* valid data. 253 | # If you're concerned, email me, and I'll send you the test program so 254 | # you can test whatever IP range you think is causing problems, 255 | # as I don't care to undertake an exhaustive search of the 32-bit space. 256 | unless pos == @database_segments[0] 257 | read_city(pos, hostname, ip) 258 | end 259 | end 260 | 261 | # Search a ISP GeoIP database for the specified host, returning the ISP 262 | # Not all GeoIP databases contain ISP information. 263 | # Check http://maxmind.com 264 | # 265 | # +hostname+ is a String holding the host's DNS name or numeric IP 266 | # address. 267 | # 268 | # Returns the ISP name. 269 | # 270 | def isp(hostname) 271 | ip = lookup_ip(hostname) 272 | 273 | # Convert numeric IP address to an integer 274 | ipnum = iptonum(ip) 275 | 276 | if (@database_type != GEOIP_ISP_EDITION && 277 | @database_type != GEOIP_ORG_EDITION) 278 | throw "Invalid GeoIP database type, can't look up Organization/ISP by IP" 279 | end 280 | 281 | pos = seek_record(ipnum) 282 | off = pos + (2*@record_length - 1) * @database_segments[0] 283 | 284 | record = atomic_read(MAX_ORG_RECORD_LENGTH, off) 285 | record = record.sub(/\000.*/n, '') 286 | record 287 | end 288 | 289 | # Search a ASN GeoIP database for the specified host, returning the AS 290 | # number and description. 291 | # 292 | # +hostname+ is a String holding the host's DNS name or numeric 293 | # IP address. 294 | # 295 | # Returns the AS number and description. 296 | # 297 | # Source: 298 | # http://geolite.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz 299 | # 300 | def asn(hostname) 301 | ip = lookup_ip(hostname) 302 | 303 | # Convert numeric IP address to an integer 304 | ipnum = iptonum(ip) 305 | 306 | if (@database_type != GEOIP_ASNUM_EDITION) 307 | throw "Invalid GeoIP database type, can't look up ASN by IP" 308 | end 309 | 310 | pos = seek_record(ipnum) 311 | off = pos + (2*@record_length - 1) * @database_segments[0] 312 | 313 | record = atomic_read(MAX_ASN_RECORD_LENGTH, off) 314 | record = record.sub(/\000.*/n, '') 315 | 316 | # AS####, Description 317 | ASN.new($1, $2) if record =~ /^(AS\d+)\s(.*)$/ 318 | end 319 | 320 | # Search a ISP GeoIP database for the specified host, returning the 321 | # organization. 322 | # 323 | # +hostname+ is a String holding the host's DNS name or numeric 324 | # IP address. 325 | # 326 | # Returns the organization associated with it. 327 | # 328 | alias_method(:organization, :isp) # Untested, according to Maxmind docs this should work 329 | 330 | # Iterate through a GeoIP city database 331 | def each 332 | return enum_for unless block_given? 333 | 334 | if (@database_type != GEOIP_CITY_EDITION_REV0 && 335 | @database_type != GEOIP_CITY_EDITION_REV1) 336 | throw "Invalid GeoIP database type, can't iterate thru non-City database" 337 | end 338 | 339 | @iter_pos = @database_segments[0] + 1 340 | num = 0 341 | 342 | until ((rec = read_city(@iter_pos)).nil?) 343 | yield rec 344 | print "#{num}: #{@iter_pos}\n" if((num += 1) % 1000 == 0) 345 | end 346 | 347 | @iter_pos = nil 348 | return self 349 | end 350 | 351 | private 352 | 353 | # Detects the type of the database. 354 | def detect_database_type! # :nodoc: 355 | @file.seek(-3, IO::SEEK_END) 356 | 357 | 0.upto(STRUCTURE_INFO_MAX_SIZE - 1) do |i| 358 | if @file.read(3).bytes.all? { |byte| byte == 255 } 359 | @database_type = if @file.respond_to?(:getbyte) 360 | @file.getbyte 361 | else 362 | @file.getc 363 | end 364 | 365 | @database_type -= 105 if @database_type >= 106 366 | 367 | if (@database_type == GEOIP_REGION_EDITION_REV0) 368 | # Region Edition, pre June 2003 369 | @database_segments = [STATE_BEGIN_REV0] 370 | elsif (@database_type == GEOIP_REGION_EDITION_REV1) 371 | # Region Edition, post June 2003 372 | @database_segments = [STATE_BEGIN_REV1] 373 | elsif (@database_type == GEOIP_CITY_EDITION_REV0 || 374 | @database_type == GEOIP_CITY_EDITION_REV1 || 375 | @database_type == GEOIP_CITY_EDITION_REV1_V6 || 376 | @database_type == GEOIP_ORG_EDITION || 377 | @database_type == GEOIP_ISP_EDITION || 378 | @database_type == GEOIP_ASNUM_EDITION) 379 | 380 | # City/Org Editions have two segments, read offset of second segment 381 | @database_segments = [0] 382 | sr = @file.read(3).unpack("C*") 383 | @database_segments[0] += le_to_ui(sr) 384 | 385 | if (@database_type == GEOIP_ORG_EDITION || 386 | @database_type == GEOIP_ISP_EDITION) 387 | @record_length = 4 388 | end 389 | end 390 | 391 | break 392 | else 393 | @file.seek(-4, IO::SEEK_CUR) 394 | end 395 | end 396 | 397 | if (@database_type == GEOIP_COUNTRY_EDITION || 398 | @database_type == GEOIP_PROXY_EDITION || 399 | @database_type == GEOIP_COUNTRY_EDITION_V6 || 400 | @database_type == GEOIP_NETSPEED_EDITION) 401 | @database_segments = [COUNTRY_BEGIN] 402 | end 403 | end 404 | 405 | # Search the GeoIP database for the specified host, returning city info. 406 | # 407 | # +hostname+ is a String holding the host's DNS name or numeric 408 | # IP address. 409 | # 410 | # Returns an array of fourteen elements: 411 | # * All elements from the country query (except GeoIP's country code, 412 | # bah!) 413 | # * The region (state or territory) name 414 | # * The city name 415 | # * The postal code (zipcode) 416 | # * The latitude 417 | # * The longitude 418 | # * The dma_code and area_code, if available (REV1 City database) 419 | # * The timezone name, if known 420 | # 421 | def read_city(pos, hostname = '', ip = '') #:nodoc: 422 | off = pos + (2*@record_length - 1) * @database_segments[0] 423 | record = atomic_read(FULL_RECORD_LENGTH, off) 424 | 425 | return unless (record && record.size == FULL_RECORD_LENGTH) 426 | 427 | # The country code is the first byte: 428 | code = record[0] 429 | code = code.ord if code.respond_to?(:ord) 430 | record = record[1..-1] 431 | @iter_pos += 1 unless @iter_pos.nil? 432 | 433 | spl = record.split("\x00", 4) 434 | # Get the region: 435 | region = spl[0] 436 | @iter_pos += (region.size + 1) unless @iter_pos.nil? 437 | 438 | # Get the city: 439 | city = spl[1] 440 | @iter_pos += (city.size + 1) unless @iter_pos.nil? 441 | # set the correct encoding in ruby 1.9 compatible environments: 442 | city.force_encoding('iso-8859-1') if city.respond_to?(:force_encoding) 443 | 444 | # Get the postal code: 445 | postal_code = spl[2] 446 | @iter_pos += (postal_code.size + 1) unless @iter_pos.nil? || postal_code.nil? 447 | 448 | record = spl[3] 449 | 450 | # Get the latitude/longitude: 451 | if (record && record[0,3]) 452 | latitude = (le_to_ui(record[0,3].unpack('C*')) / 10000.0) - 180 453 | record = record[3..-1] 454 | 455 | @iter_pos += 3 unless @iter_pos.nil? 456 | else 457 | latitude = '' 458 | end 459 | 460 | if (record && record[0,3]) 461 | longitude = le_to_ui(record[0,3].unpack('C*')) / 10000.0 - 180 462 | record = record[3..-1] 463 | 464 | @iter_pos += 3 unless @iter_pos.nil? 465 | else 466 | longitude = '' 467 | end 468 | 469 | # UNTESTED 470 | if (record && 471 | record[0,3] && 472 | @database_type == GEOIP_CITY_EDITION_REV1 && 473 | CountryCode[code] == "US") 474 | 475 | dmaarea_combo = le_to_ui(record[0,3].unpack('C*')) 476 | dma_code = (dmaarea_combo / 1000) 477 | area_code = (dmaarea_combo % 1000) 478 | 479 | @iter_pos += 3 unless @iter_pos.nil? 480 | else 481 | dma_code, area_code = nil, nil 482 | end 483 | 484 | City.new( 485 | hostname, # Requested hostname 486 | ip, # Ip address as dotted quad 487 | CountryCode[code], # ISO3166-1 code 488 | CountryCode3[code], # ISO3166-2 code 489 | CountryName[code], # Country name, per IS03166 490 | CountryContinent[code], # Continent code. 491 | region, # Region name 492 | city, # City name 493 | postal_code, # Postal code 494 | latitude, 495 | longitude, 496 | dma_code, 497 | area_code, 498 | (TimeZone["#{CountryCode[code]}#{region}"] || TimeZone["#{CountryCode[code]}"]) 499 | ) 500 | end 501 | 502 | def lookup_ip(ip_or_hostname) # :nodoc: 503 | if !ip_or_hostname.kind_of?(String) or ip_or_hostname =~ /^[0-9.]+$/ 504 | return ip_or_hostname 505 | end 506 | 507 | # Lookup IP address, we were given a name or IPv6 address 508 | ip = IPSocket.getaddress(ip_or_hostname) 509 | ip = '0.0.0.0' if ip == '::1' 510 | ip 511 | end 512 | 513 | # Convert numeric IP address to Integer. 514 | def iptonum(ip) #:nodoc: 515 | if (ip.kind_of?(String) && 516 | ip =~ /^([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)$/) 517 | ip = be_to_ui(Regexp.last_match().to_a.slice(1..4)) 518 | else 519 | ip = ip.to_i 520 | end 521 | 522 | return ip 523 | end 524 | 525 | def seek_record(ipnum) #:nodoc: 526 | # Binary search in the file. 527 | # Records are pairs of little-endian integers, each of @record_length. 528 | offset = 0 529 | mask = 0x80000000 530 | 531 | 31.downto(0) do |depth| 532 | off = (@record_length * 2 * offset) 533 | buf = atomic_read(@record_length * 2, off) 534 | 535 | buf.slice!(0...@record_length) if ((ipnum & mask) != 0) 536 | offset = le_to_ui(buf[0...@record_length].unpack("C*")) 537 | 538 | if (offset >= @database_segments[0]) 539 | return offset 540 | end 541 | 542 | mask >>= 1 543 | end 544 | end 545 | 546 | def seek_record_v6(ipnum) 547 | 548 | # Binary search in the file. 549 | # Records are pairs of little-endian integers, each of @record_length. 550 | offset = 0 551 | mask = 1 << 127 552 | 553 | 127.downto(0) do |depth| 554 | off = (@record_length * 2 * offset) 555 | buf = atomic_read(@record_length * 2, off) 556 | 557 | buf.slice!(0...@record_length) if ((ipnum & mask) != 0) 558 | offset = le_to_ui(buf[0...@record_length].unpack("C*")) 559 | 560 | if (offset >= @database_segments[0]) 561 | return offset 562 | end 563 | 564 | mask >>= 1 565 | end 566 | 567 | end 568 | 569 | # Convert a big-endian array of numeric bytes to unsigned int. 570 | # 571 | # Returns the unsigned Integer. 572 | # 573 | def be_to_ui(s) #:nodoc: 574 | i = 0 575 | 576 | s.each { |b| i = ((i << 8) | (b.to_i & 0x0ff)) } 577 | return i 578 | end 579 | 580 | # Same for little-endian 581 | def le_to_ui(s) #:nodoc: 582 | be_to_ui(s.reverse) 583 | end 584 | 585 | # reads +length+ bytes from +offset+ as atomically as possible 586 | # if IO.pread is available, it'll use that (making it both multithread 587 | # and multiprocess-safe). Otherwise we'll use a mutex to synchronize 588 | # access (only providing protection against multiple threads, but not 589 | # file descriptors shared across multiple processes). 590 | def atomic_read(length, offset) #:nodoc: 591 | if @mutex 592 | @mutex.synchronize do 593 | @file.seek(offset) 594 | @file.read(length) 595 | end 596 | else 597 | IO.pread(@file.fileno, length, offset) 598 | end 599 | end 600 | 601 | end 602 | -------------------------------------------------------------------------------- /website/javascripts/rounded_corners_lite.inc.js: -------------------------------------------------------------------------------- 1 | 2 | /**************************************************************** 3 | * * 4 | * curvyCorners * 5 | * ------------ * 6 | * * 7 | * This script generates rounded corners for your divs. * 8 | * * 9 | * Version 1.2.9 * 10 | * Copyright (c) 2006 Cameron Cooke * 11 | * By: Cameron Cooke and Tim Hutchison. * 12 | * * 13 | * * 14 | * Website: http://www.curvycorners.net * 15 | * Email: info@totalinfinity.com * 16 | * Forum: http://www.curvycorners.net/forum/ * 17 | * * 18 | * * 19 | * This library is free software; you can redistribute * 20 | * it and/or modify it under the terms of the GNU * 21 | * Lesser General Public License as published by the * 22 | * Free Software Foundation; either version 2.1 of the * 23 | * License, or (at your option) any later version. * 24 | * * 25 | * This library is distributed in the hope that it will * 26 | * be useful, but WITHOUT ANY WARRANTY; without even the * 27 | * implied warranty of MERCHANTABILITY or FITNESS FOR A * 28 | * PARTICULAR PURPOSE. See the GNU Lesser General Public * 29 | * License for more details. * 30 | * * 31 | * You should have received a copy of the GNU Lesser * 32 | * General Public License along with this library; * 33 | * Inc., 59 Temple Place, Suite 330, Boston, * 34 | * MA 02111-1307 USA * 35 | * * 36 | ****************************************************************/ 37 | 38 | var isIE = navigator.userAgent.toLowerCase().indexOf("msie") > -1; var isMoz = document.implementation && document.implementation.createDocument; var isSafari = ((navigator.userAgent.toLowerCase().indexOf('safari')!=-1)&&(navigator.userAgent.toLowerCase().indexOf('mac')!=-1))?true:false; function curvyCorners() 39 | { if(typeof(arguments[0]) != "object") throw newCurvyError("First parameter of curvyCorners() must be an object."); if(typeof(arguments[1]) != "object" && typeof(arguments[1]) != "string") throw newCurvyError("Second parameter of curvyCorners() must be an object or a class name."); if(typeof(arguments[1]) == "string") 40 | { var startIndex = 0; var boxCol = getElementsByClass(arguments[1]);} 41 | else 42 | { var startIndex = 1; var boxCol = arguments;} 43 | var curvyCornersCol = new Array(); if(arguments[0].validTags) 44 | var validElements = arguments[0].validTags; else 45 | var validElements = ["div"]; for(var i = startIndex, j = boxCol.length; i < j; i++) 46 | { var currentTag = boxCol[i].tagName.toLowerCase(); if(inArray(validElements, currentTag) !== false) 47 | { curvyCornersCol[curvyCornersCol.length] = new curvyObject(arguments[0], boxCol[i]);} 48 | } 49 | this.objects = curvyCornersCol; this.applyCornersToAll = function() 50 | { for(var x = 0, k = this.objects.length; x < k; x++) 51 | { this.objects[x].applyCorners();} 52 | } 53 | } 54 | function curvyObject() 55 | { this.box = arguments[1]; this.settings = arguments[0]; this.topContainer = null; this.bottomContainer = null; this.masterCorners = new Array(); this.contentDIV = null; var boxHeight = get_style(this.box, "height", "height"); var boxWidth = get_style(this.box, "width", "width"); var borderWidth = get_style(this.box, "borderTopWidth", "border-top-width"); var borderColour = get_style(this.box, "borderTopColor", "border-top-color"); var boxColour = get_style(this.box, "backgroundColor", "background-color"); var backgroundImage = get_style(this.box, "backgroundImage", "background-image"); var boxPosition = get_style(this.box, "position", "position"); var boxPadding = get_style(this.box, "paddingTop", "padding-top"); this.boxHeight = parseInt(((boxHeight != "" && boxHeight != "auto" && boxHeight.indexOf("%") == -1)? boxHeight.substring(0, boxHeight.indexOf("px")) : this.box.scrollHeight)); this.boxWidth = parseInt(((boxWidth != "" && boxWidth != "auto" && boxWidth.indexOf("%") == -1)? boxWidth.substring(0, boxWidth.indexOf("px")) : this.box.scrollWidth)); this.borderWidth = parseInt(((borderWidth != "" && borderWidth.indexOf("px") !== -1)? borderWidth.slice(0, borderWidth.indexOf("px")) : 0)); this.boxColour = format_colour(boxColour); this.boxPadding = parseInt(((boxPadding != "" && boxPadding.indexOf("px") !== -1)? boxPadding.slice(0, boxPadding.indexOf("px")) : 0)); this.borderColour = format_colour(borderColour); this.borderString = this.borderWidth + "px" + " solid " + this.borderColour; this.backgroundImage = ((backgroundImage != "none")? backgroundImage : ""); this.boxContent = this.box.innerHTML; if(boxPosition != "absolute") this.box.style.position = "relative"; this.box.style.padding = "0px"; if(isIE && boxWidth == "auto" && boxHeight == "auto") this.box.style.width = "100%"; if(this.settings.autoPad == true && this.boxPadding > 0) 56 | this.box.innerHTML = ""; this.applyCorners = function() 57 | { for(var t = 0; t < 2; t++) 58 | { switch(t) 59 | { case 0: 60 | if(this.settings.tl || this.settings.tr) 61 | { var newMainContainer = document.createElement("DIV"); newMainContainer.style.width = "100%"; newMainContainer.style.fontSize = "1px"; newMainContainer.style.overflow = "hidden"; newMainContainer.style.position = "absolute"; newMainContainer.style.paddingLeft = this.borderWidth + "px"; newMainContainer.style.paddingRight = this.borderWidth + "px"; var topMaxRadius = Math.max(this.settings.tl ? this.settings.tl.radius : 0, this.settings.tr ? this.settings.tr.radius : 0); newMainContainer.style.height = topMaxRadius + "px"; newMainContainer.style.top = 0 - topMaxRadius + "px"; newMainContainer.style.left = 0 - this.borderWidth + "px"; this.topContainer = this.box.appendChild(newMainContainer);} 62 | break; case 1: 63 | if(this.settings.bl || this.settings.br) 64 | { var newMainContainer = document.createElement("DIV"); newMainContainer.style.width = "100%"; newMainContainer.style.fontSize = "1px"; newMainContainer.style.overflow = "hidden"; newMainContainer.style.position = "absolute"; newMainContainer.style.paddingLeft = this.borderWidth + "px"; newMainContainer.style.paddingRight = this.borderWidth + "px"; var botMaxRadius = Math.max(this.settings.bl ? this.settings.bl.radius : 0, this.settings.br ? this.settings.br.radius : 0); newMainContainer.style.height = botMaxRadius + "px"; newMainContainer.style.bottom = 0 - botMaxRadius + "px"; newMainContainer.style.left = 0 - this.borderWidth + "px"; this.bottomContainer = this.box.appendChild(newMainContainer);} 65 | break;} 66 | } 67 | if(this.topContainer) this.box.style.borderTopWidth = "0px"; if(this.bottomContainer) this.box.style.borderBottomWidth = "0px"; var corners = ["tr", "tl", "br", "bl"]; for(var i in corners) 68 | { if(i > -1 < 4) 69 | { var cc = corners[i]; if(!this.settings[cc]) 70 | { if(((cc == "tr" || cc == "tl") && this.topContainer != null) || ((cc == "br" || cc == "bl") && this.bottomContainer != null)) 71 | { var newCorner = document.createElement("DIV"); newCorner.style.position = "relative"; newCorner.style.fontSize = "1px"; newCorner.style.overflow = "hidden"; if(this.backgroundImage == "") 72 | newCorner.style.backgroundColor = this.boxColour; else 73 | newCorner.style.backgroundImage = this.backgroundImage; switch(cc) 74 | { case "tl": 75 | newCorner.style.height = topMaxRadius - this.borderWidth + "px"; newCorner.style.marginRight = this.settings.tr.radius - (this.borderWidth*2) + "px"; newCorner.style.borderLeft = this.borderString; newCorner.style.borderTop = this.borderString; newCorner.style.left = -this.borderWidth + "px"; break; case "tr": 76 | newCorner.style.height = topMaxRadius - this.borderWidth + "px"; newCorner.style.marginLeft = this.settings.tl.radius - (this.borderWidth*2) + "px"; newCorner.style.borderRight = this.borderString; newCorner.style.borderTop = this.borderString; newCorner.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px"; newCorner.style.left = this.borderWidth + "px"; break; case "bl": 77 | newCorner.style.height = botMaxRadius - this.borderWidth + "px"; newCorner.style.marginRight = this.settings.br.radius - (this.borderWidth*2) + "px"; newCorner.style.borderLeft = this.borderString; newCorner.style.borderBottom = this.borderString; newCorner.style.left = -this.borderWidth + "px"; newCorner.style.backgroundPosition = "-" + (this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px"; break; case "br": 78 | newCorner.style.height = botMaxRadius - this.borderWidth + "px"; newCorner.style.marginLeft = this.settings.bl.radius - (this.borderWidth*2) + "px"; newCorner.style.borderRight = this.borderString; newCorner.style.borderBottom = this.borderString; newCorner.style.left = this.borderWidth + "px" 79 | newCorner.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px"; break;} 80 | } 81 | } 82 | else 83 | { if(this.masterCorners[this.settings[cc].radius]) 84 | { var newCorner = this.masterCorners[this.settings[cc].radius].cloneNode(true);} 85 | else 86 | { var newCorner = document.createElement("DIV"); newCorner.style.height = this.settings[cc].radius + "px"; newCorner.style.width = this.settings[cc].radius + "px"; newCorner.style.position = "absolute"; newCorner.style.fontSize = "1px"; newCorner.style.overflow = "hidden"; var borderRadius = parseInt(this.settings[cc].radius - this.borderWidth); for(var intx = 0, j = this.settings[cc].radius; intx < j; intx++) 87 | { if((intx +1) >= borderRadius) 88 | var y1 = -1; else 89 | var y1 = (Math.floor(Math.sqrt(Math.pow(borderRadius, 2) - Math.pow((intx+1), 2))) - 1); if(borderRadius != j) 90 | { if((intx) >= borderRadius) 91 | var y2 = -1; else 92 | var y2 = Math.ceil(Math.sqrt(Math.pow(borderRadius,2) - Math.pow(intx, 2))); if((intx+1) >= j) 93 | var y3 = -1; else 94 | var y3 = (Math.floor(Math.sqrt(Math.pow(j ,2) - Math.pow((intx+1), 2))) - 1);} 95 | if((intx) >= j) 96 | var y4 = -1; else 97 | var y4 = Math.ceil(Math.sqrt(Math.pow(j ,2) - Math.pow(intx, 2))); if(y1 > -1) this.drawPixel(intx, 0, this.boxColour, 100, (y1+1), newCorner, -1, this.settings[cc].radius); if(borderRadius != j) 98 | { for(var inty = (y1 + 1); inty < y2; inty++) 99 | { if(this.settings.antiAlias) 100 | { if(this.backgroundImage != "") 101 | { var borderFract = (pixelFraction(intx, inty, borderRadius) * 100); if(borderFract < 30) 102 | { this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, 0, this.settings[cc].radius);} 103 | else 104 | { this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, -1, this.settings[cc].radius);} 105 | } 106 | else 107 | { var pixelcolour = BlendColour(this.boxColour, this.borderColour, pixelFraction(intx, inty, borderRadius)); this.drawPixel(intx, inty, pixelcolour, 100, 1, newCorner, 0, this.settings[cc].radius, cc);} 108 | } 109 | } 110 | if(this.settings.antiAlias) 111 | { if(y3 >= y2) 112 | { if (y2 == -1) y2 = 0; this.drawPixel(intx, y2, this.borderColour, 100, (y3 - y2 + 1), newCorner, 0, 0);} 113 | } 114 | else 115 | { if(y3 >= y1) 116 | { this.drawPixel(intx, (y1 + 1), this.borderColour, 100, (y3 - y1), newCorner, 0, 0);} 117 | } 118 | var outsideColour = this.borderColour;} 119 | else 120 | { var outsideColour = this.boxColour; var y3 = y1;} 121 | if(this.settings.antiAlias) 122 | { for(var inty = (y3 + 1); inty < y4; inty++) 123 | { this.drawPixel(intx, inty, outsideColour, (pixelFraction(intx, inty , j) * 100), 1, newCorner, ((this.borderWidth > 0)? 0 : -1), this.settings[cc].radius);} 124 | } 125 | } 126 | this.masterCorners[this.settings[cc].radius] = newCorner.cloneNode(true);} 127 | if(cc != "br") 128 | { for(var t = 0, k = newCorner.childNodes.length; t < k; t++) 129 | { var pixelBar = newCorner.childNodes[t]; var pixelBarTop = parseInt(pixelBar.style.top.substring(0, pixelBar.style.top.indexOf("px"))); var pixelBarLeft = parseInt(pixelBar.style.left.substring(0, pixelBar.style.left.indexOf("px"))); var pixelBarHeight = parseInt(pixelBar.style.height.substring(0, pixelBar.style.height.indexOf("px"))); if(cc == "tl" || cc == "bl"){ pixelBar.style.left = this.settings[cc].radius -pixelBarLeft -1 + "px";} 130 | if(cc == "tr" || cc == "tl"){ pixelBar.style.top = this.settings[cc].radius -pixelBarHeight -pixelBarTop + "px";} 131 | switch(cc) 132 | { case "tr": 133 | pixelBar.style.backgroundPosition = "-" + Math.abs((this.boxWidth - this.settings[cc].radius + this.borderWidth) + pixelBarLeft) + "px -" + Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth) + "px"; break; case "tl": 134 | pixelBar.style.backgroundPosition = "-" + Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) + "px -" + Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth) + "px"; break; case "bl": 135 | pixelBar.style.backgroundPosition = "-" + Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) + "px -" + Math.abs((this.boxHeight + this.settings[cc].radius + pixelBarTop) -this.borderWidth) + "px"; break;} 136 | } 137 | } 138 | } 139 | if(newCorner) 140 | { switch(cc) 141 | { case "tl": 142 | if(newCorner.style.position == "absolute") newCorner.style.top = "0px"; if(newCorner.style.position == "absolute") newCorner.style.left = "0px"; if(this.topContainer) this.topContainer.appendChild(newCorner); break; case "tr": 143 | if(newCorner.style.position == "absolute") newCorner.style.top = "0px"; if(newCorner.style.position == "absolute") newCorner.style.right = "0px"; if(this.topContainer) this.topContainer.appendChild(newCorner); break; case "bl": 144 | if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px"; if(newCorner.style.position == "absolute") newCorner.style.left = "0px"; if(this.bottomContainer) this.bottomContainer.appendChild(newCorner); break; case "br": 145 | if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px"; if(newCorner.style.position == "absolute") newCorner.style.right = "0px"; if(this.bottomContainer) this.bottomContainer.appendChild(newCorner); break;} 146 | } 147 | } 148 | } 149 | var radiusDiff = new Array(); radiusDiff["t"] = Math.abs(this.settings.tl.radius - this.settings.tr.radius) 150 | radiusDiff["b"] = Math.abs(this.settings.bl.radius - this.settings.br.radius); for(z in radiusDiff) 151 | { if(z == "t" || z == "b") 152 | { if(radiusDiff[z]) 153 | { var smallerCornerType = ((this.settings[z + "l"].radius < this.settings[z + "r"].radius)? z +"l" : z +"r"); var newFiller = document.createElement("DIV"); newFiller.style.height = radiusDiff[z] + "px"; newFiller.style.width = this.settings[smallerCornerType].radius+ "px" 154 | newFiller.style.position = "absolute"; newFiller.style.fontSize = "1px"; newFiller.style.overflow = "hidden"; newFiller.style.backgroundColor = this.boxColour; switch(smallerCornerType) 155 | { case "tl": 156 | newFiller.style.bottom = "0px"; newFiller.style.left = "0px"; newFiller.style.borderLeft = this.borderString; this.topContainer.appendChild(newFiller); break; case "tr": 157 | newFiller.style.bottom = "0px"; newFiller.style.right = "0px"; newFiller.style.borderRight = this.borderString; this.topContainer.appendChild(newFiller); break; case "bl": 158 | newFiller.style.top = "0px"; newFiller.style.left = "0px"; newFiller.style.borderLeft = this.borderString; this.bottomContainer.appendChild(newFiller); break; case "br": 159 | newFiller.style.top = "0px"; newFiller.style.right = "0px"; newFiller.style.borderRight = this.borderString; this.bottomContainer.appendChild(newFiller); break;} 160 | } 161 | var newFillerBar = document.createElement("DIV"); newFillerBar.style.position = "relative"; newFillerBar.style.fontSize = "1px"; newFillerBar.style.overflow = "hidden"; newFillerBar.style.backgroundColor = this.boxColour; newFillerBar.style.backgroundImage = this.backgroundImage; switch(z) 162 | { case "t": 163 | if(this.topContainer) 164 | { if(this.settings.tl.radius && this.settings.tr.radius) 165 | { newFillerBar.style.height = topMaxRadius - this.borderWidth + "px"; newFillerBar.style.marginLeft = this.settings.tl.radius - this.borderWidth + "px"; newFillerBar.style.marginRight = this.settings.tr.radius - this.borderWidth + "px"; newFillerBar.style.borderTop = this.borderString; if(this.backgroundImage != "") 166 | newFillerBar.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px"; this.topContainer.appendChild(newFillerBar);} 167 | this.box.style.backgroundPosition = "0px -" + (topMaxRadius - this.borderWidth) + "px";} 168 | break; case "b": 169 | if(this.bottomContainer) 170 | { if(this.settings.bl.radius && this.settings.br.radius) 171 | { newFillerBar.style.height = botMaxRadius - this.borderWidth + "px"; newFillerBar.style.marginLeft = this.settings.bl.radius - this.borderWidth + "px"; newFillerBar.style.marginRight = this.settings.br.radius - this.borderWidth + "px"; newFillerBar.style.borderBottom = this.borderString; if(this.backgroundImage != "") 172 | newFillerBar.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (topMaxRadius + this.borderWidth)) + "px"; this.bottomContainer.appendChild(newFillerBar);} 173 | } 174 | break;} 175 | } 176 | } 177 | if(this.settings.autoPad == true && this.boxPadding > 0) 178 | { var contentContainer = document.createElement("DIV"); contentContainer.style.position = "relative"; contentContainer.innerHTML = this.boxContent; contentContainer.className = "autoPadDiv"; var topPadding = Math.abs(topMaxRadius - this.boxPadding); var botPadding = Math.abs(botMaxRadius - this.boxPadding); if(topMaxRadius < this.boxPadding) 179 | contentContainer.style.paddingTop = topPadding + "px"; if(botMaxRadius < this.boxPadding) 180 | contentContainer.style.paddingBottom = botMaxRadius + "px"; contentContainer.style.paddingLeft = this.boxPadding + "px"; contentContainer.style.paddingRight = this.boxPadding + "px"; this.contentDIV = this.box.appendChild(contentContainer);} 181 | } 182 | this.drawPixel = function(intx, inty, colour, transAmount, height, newCorner, image, cornerRadius) 183 | { var pixel = document.createElement("DIV"); pixel.style.height = height + "px"; pixel.style.width = "1px"; pixel.style.position = "absolute"; pixel.style.fontSize = "1px"; pixel.style.overflow = "hidden"; var topMaxRadius = Math.max(this.settings["tr"].radius, this.settings["tl"].radius); if(image == -1 && this.backgroundImage != "") 184 | { pixel.style.backgroundImage = this.backgroundImage; pixel.style.backgroundPosition = "-" + (this.boxWidth - (cornerRadius - intx) + this.borderWidth) + "px -" + ((this.boxHeight + topMaxRadius + inty) -this.borderWidth) + "px";} 185 | else 186 | { pixel.style.backgroundColor = colour;} 187 | if (transAmount != 100) 188 | setOpacity(pixel, transAmount); pixel.style.top = inty + "px"; pixel.style.left = intx + "px"; newCorner.appendChild(pixel);} 189 | } 190 | function insertAfter(parent, node, referenceNode) 191 | { parent.insertBefore(node, referenceNode.nextSibling);} 192 | function BlendColour(Col1, Col2, Col1Fraction) 193 | { var red1 = parseInt(Col1.substr(1,2),16); var green1 = parseInt(Col1.substr(3,2),16); var blue1 = parseInt(Col1.substr(5,2),16); var red2 = parseInt(Col2.substr(1,2),16); var green2 = parseInt(Col2.substr(3,2),16); var blue2 = parseInt(Col2.substr(5,2),16); if(Col1Fraction > 1 || Col1Fraction < 0) Col1Fraction = 1; var endRed = Math.round((red1 * Col1Fraction) + (red2 * (1 - Col1Fraction))); if(endRed > 255) endRed = 255; if(endRed < 0) endRed = 0; var endGreen = Math.round((green1 * Col1Fraction) + (green2 * (1 - Col1Fraction))); if(endGreen > 255) endGreen = 255; if(endGreen < 0) endGreen = 0; var endBlue = Math.round((blue1 * Col1Fraction) + (blue2 * (1 - Col1Fraction))); if(endBlue > 255) endBlue = 255; if(endBlue < 0) endBlue = 0; return "#" + IntToHex(endRed)+ IntToHex(endGreen)+ IntToHex(endBlue);} 194 | function IntToHex(strNum) 195 | { base = strNum / 16; rem = strNum % 16; base = base - (rem / 16); baseS = MakeHex(base); remS = MakeHex(rem); return baseS + '' + remS;} 196 | function MakeHex(x) 197 | { if((x >= 0) && (x <= 9)) 198 | { return x;} 199 | else 200 | { switch(x) 201 | { case 10: return "A"; case 11: return "B"; case 12: return "C"; case 13: return "D"; case 14: return "E"; case 15: return "F";} 202 | } 203 | } 204 | function pixelFraction(x, y, r) 205 | { var pixelfraction = 0; var xvalues = new Array(1); var yvalues = new Array(1); var point = 0; var whatsides = ""; var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x,2))); if ((intersect >= y) && (intersect < (y+1))) 206 | { whatsides = "Left"; xvalues[point] = 0; yvalues[point] = intersect - y; point = point + 1;} 207 | var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y+1,2))); if ((intersect >= x) && (intersect < (x+1))) 208 | { whatsides = whatsides + "Top"; xvalues[point] = intersect - x; yvalues[point] = 1; point = point + 1;} 209 | var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x+1,2))); if ((intersect >= y) && (intersect < (y+1))) 210 | { whatsides = whatsides + "Right"; xvalues[point] = 1; yvalues[point] = intersect - y; point = point + 1;} 211 | var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y,2))); if ((intersect >= x) && (intersect < (x+1))) 212 | { whatsides = whatsides + "Bottom"; xvalues[point] = intersect - x; yvalues[point] = 0;} 213 | switch (whatsides) 214 | { case "LeftRight": 215 | pixelfraction = Math.min(yvalues[0],yvalues[1]) + ((Math.max(yvalues[0],yvalues[1]) - Math.min(yvalues[0],yvalues[1]))/2); break; case "TopRight": 216 | pixelfraction = 1-(((1-xvalues[0])*(1-yvalues[1]))/2); break; case "TopBottom": 217 | pixelfraction = Math.min(xvalues[0],xvalues[1]) + ((Math.max(xvalues[0],xvalues[1]) - Math.min(xvalues[0],xvalues[1]))/2); break; case "LeftBottom": 218 | pixelfraction = (yvalues[0]*xvalues[1])/2; break; default: 219 | pixelfraction = 1;} 220 | return pixelfraction;} 221 | function rgb2Hex(rgbColour) 222 | { try{ var rgbArray = rgb2Array(rgbColour); var red = parseInt(rgbArray[0]); var green = parseInt(rgbArray[1]); var blue = parseInt(rgbArray[2]); var hexColour = "#" + IntToHex(red) + IntToHex(green) + IntToHex(blue);} 223 | catch(e){ alert("There was an error converting the RGB value to Hexadecimal in function rgb2Hex");} 224 | return hexColour;} 225 | function rgb2Array(rgbColour) 226 | { var rgbValues = rgbColour.substring(4, rgbColour.indexOf(")")); var rgbArray = rgbValues.split(", "); return rgbArray;} 227 | function setOpacity(obj, opacity) 228 | { opacity = (opacity == 100)?99.999:opacity; if(isSafari && obj.tagName != "IFRAME") 229 | { var rgbArray = rgb2Array(obj.style.backgroundColor); var red = parseInt(rgbArray[0]); var green = parseInt(rgbArray[1]); var blue = parseInt(rgbArray[2]); obj.style.backgroundColor = "rgba(" + red + ", " + green + ", " + blue + ", " + opacity/100 + ")";} 230 | else if(typeof(obj.style.opacity) != "undefined") 231 | { obj.style.opacity = opacity/100;} 232 | else if(typeof(obj.style.MozOpacity) != "undefined") 233 | { obj.style.MozOpacity = opacity/100;} 234 | else if(typeof(obj.style.filter) != "undefined") 235 | { obj.style.filter = "alpha(opacity:" + opacity + ")";} 236 | else if(typeof(obj.style.KHTMLOpacity) != "undefined") 237 | { obj.style.KHTMLOpacity = opacity/100;} 238 | } 239 | function inArray(array, value) 240 | { for(var i = 0; i < array.length; i++){ if (array[i] === value) return i;} 241 | return false;} 242 | function inArrayKey(array, value) 243 | { for(key in array){ if(key === value) return true;} 244 | return false;} 245 | function addEvent(elm, evType, fn, useCapture) { if (elm.addEventListener) { elm.addEventListener(evType, fn, useCapture); return true;} 246 | else if (elm.attachEvent) { var r = elm.attachEvent('on' + evType, fn); return r;} 247 | else { elm['on' + evType] = fn;} 248 | } 249 | function removeEvent(obj, evType, fn, useCapture){ if (obj.removeEventListener){ obj.removeEventListener(evType, fn, useCapture); return true;} else if (obj.detachEvent){ var r = obj.detachEvent("on"+evType, fn); return r;} else { alert("Handler could not be removed");} 250 | } 251 | function format_colour(colour) 252 | { var returnColour = "#ffffff"; if(colour != "" && colour != "transparent") 253 | { if(colour.substr(0, 3) == "rgb") 254 | { returnColour = rgb2Hex(colour);} 255 | else if(colour.length == 4) 256 | { returnColour = "#" + colour.substring(1, 2) + colour.substring(1, 2) + colour.substring(2, 3) + colour.substring(2, 3) + colour.substring(3, 4) + colour.substring(3, 4);} 257 | else 258 | { returnColour = colour;} 259 | } 260 | return returnColour;} 261 | function get_style(obj, property, propertyNS) 262 | { try 263 | { if(obj.currentStyle) 264 | { var returnVal = eval("obj.currentStyle." + property);} 265 | else 266 | { if(isSafari && obj.style.display == "none") 267 | { obj.style.display = ""; var wasHidden = true;} 268 | var returnVal = document.defaultView.getComputedStyle(obj, '').getPropertyValue(propertyNS); if(isSafari && wasHidden) 269 | { obj.style.display = "none";} 270 | } 271 | } 272 | catch(e) 273 | { } 274 | return returnVal;} 275 | function getElementsByClass(searchClass, node, tag) 276 | { var classElements = new Array(); if(node == null) 277 | node = document; if(tag == null) 278 | tag = '*'; var els = node.getElementsByTagName(tag); var elsLen = els.length; var pattern = new RegExp("(^|\s)"+searchClass+"(\s|$)"); for (i = 0, j = 0; i < elsLen; i++) 279 | { if(pattern.test(els[i].className)) 280 | { classElements[j] = els[i]; j++;} 281 | } 282 | return classElements;} 283 | function newCurvyError(errorMessage) 284 | { return new Error("curvyCorners Error:\n" + errorMessage) 285 | } 286 | --------------------------------------------------------------------------------