├── .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 |
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=['"]([^'"]+)[^>]*>(.*?)\1>!m){
54 | ident = syntax_items.length
55 | element, syntax, source = $1, $2, $3
56 | syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}#{element}>"
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 |
--------------------------------------------------------------------------------