[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Debian JP master SVN www commits (rev.1082)
=======================================================
Repository: /org/svn.debian.or.jp/repos
Revision: 1082
Commiter: yasu
Date: 2010-09-23 20:25:33 +0900 (木, 23 9月 2010)
=======================================================
Log:
add new geoip lib
=======================================================
Changed:
A cdn/trunk/geoip/
A cdn/trunk/geoip/.git/
A cdn/trunk/geoip/.git/HEAD
A cdn/trunk/geoip/.git/branches/
A cdn/trunk/geoip/.git/config
A cdn/trunk/geoip/.git/description
A cdn/trunk/geoip/.git/hooks/
A cdn/trunk/geoip/.git/hooks/applypatch-msg.sample
A cdn/trunk/geoip/.git/hooks/commit-msg.sample
A cdn/trunk/geoip/.git/hooks/post-commit.sample
A cdn/trunk/geoip/.git/hooks/post-receive.sample
A cdn/trunk/geoip/.git/hooks/post-update.sample
A cdn/trunk/geoip/.git/hooks/pre-applypatch.sample
A cdn/trunk/geoip/.git/hooks/pre-commit.sample
A cdn/trunk/geoip/.git/hooks/pre-rebase.sample
A cdn/trunk/geoip/.git/hooks/prepare-commit-msg.sample
A cdn/trunk/geoip/.git/hooks/update.sample
A cdn/trunk/geoip/.git/index
A cdn/trunk/geoip/.git/info/
A cdn/trunk/geoip/.git/info/exclude
A cdn/trunk/geoip/.git/logs/
A cdn/trunk/geoip/.git/logs/HEAD
A cdn/trunk/geoip/.git/logs/refs/
A cdn/trunk/geoip/.git/logs/refs/heads/
A cdn/trunk/geoip/.git/logs/refs/heads/master
A cdn/trunk/geoip/.git/objects/
A cdn/trunk/geoip/.git/objects/info/
A cdn/trunk/geoip/.git/objects/pack/
A cdn/trunk/geoip/.git/objects/pack/pack-d66c6f783d4495ac3320b4cca8997c8fa3dc8d29.idx
A cdn/trunk/geoip/.git/objects/pack/pack-d66c6f783d4495ac3320b4cca8997c8fa3dc8d29.pack
A cdn/trunk/geoip/.git/packed-refs
A cdn/trunk/geoip/.git/refs/
A cdn/trunk/geoip/.git/refs/heads/
A cdn/trunk/geoip/.git/refs/heads/master
A cdn/trunk/geoip/.git/refs/remotes/
A cdn/trunk/geoip/.git/refs/remotes/origin/
A cdn/trunk/geoip/.git/refs/remotes/origin/HEAD
A cdn/trunk/geoip/.git/refs/tags/
A cdn/trunk/geoip/.gitignore
A cdn/trunk/geoip/History.txt
A cdn/trunk/geoip/Manifest.txt
A cdn/trunk/geoip/README.rdoc
A cdn/trunk/geoip/Rakefile
A cdn/trunk/geoip/config/
A cdn/trunk/geoip/config/website.yml
A cdn/trunk/geoip/geoip.gemspec
A cdn/trunk/geoip/lib/
A cdn/trunk/geoip/lib/geoip.rb
A cdn/trunk/geoip/script/
A cdn/trunk/geoip/script/destroy
A cdn/trunk/geoip/script/generate
A cdn/trunk/geoip/script/txt2html
A cdn/trunk/geoip/tasks/
A cdn/trunk/geoip/tasks/website.rake
A cdn/trunk/geoip/test/
A cdn/trunk/geoip/test/test_geoip.rb
A cdn/trunk/geoip/test/test_helper.rb
A cdn/trunk/geoip/website/
A cdn/trunk/geoip/website/index.txt
A cdn/trunk/geoip/website/javascripts/
A cdn/trunk/geoip/website/javascripts/rounded_corners_lite.inc.js
A cdn/trunk/geoip/website/stylesheets/
A cdn/trunk/geoip/website/stylesheets/screen.css
A cdn/trunk/geoip/website/template.rhtml
Added: cdn/trunk/geoip/.git/HEAD
===================================================================
--- cdn/trunk/geoip/.git/HEAD (rev 0)
+++ cdn/trunk/geoip/.git/HEAD 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1 @@
+ref: refs/heads/master
Added: cdn/trunk/geoip/.git/config
===================================================================
--- cdn/trunk/geoip/.git/config (rev 0)
+++ cdn/trunk/geoip/.git/config 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,11 @@
+[core]
+ repositoryformatversion = 0
+ filemode = true
+ bare = false
+ logallrefupdates = true
+[remote "origin"]
+ fetch = +refs/heads/*:refs/remotes/origin/*
+ url = git://github.com/cjheath/geoip.git
+[branch "master"]
+ remote = origin
+ merge = refs/heads/master
Added: cdn/trunk/geoip/.git/description
===================================================================
--- cdn/trunk/geoip/.git/description (rev 0)
+++ cdn/trunk/geoip/.git/description 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1 @@
+Unnamed repository; edit this file 'description' to name the repository.
Added: cdn/trunk/geoip/.git/hooks/applypatch-msg.sample
===================================================================
--- cdn/trunk/geoip/.git/hooks/applypatch-msg.sample (rev 0)
+++ cdn/trunk/geoip/.git/hooks/applypatch-msg.sample 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message taken by
+# applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit. The hook is
+# allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "applypatch-msg".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/commit-msg" &&
+ exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
+:
Added: cdn/trunk/geoip/.git/hooks/commit-msg.sample
===================================================================
--- cdn/trunk/geoip/.git/hooks/commit-msg.sample (rev 0)
+++ cdn/trunk/geoip/.git/hooks/commit-msg.sample 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message.
+# Called by git-commit with one argument, the name of the file
+# that has the commit message. The hook should exit with non-zero
+# status after issuing an appropriate message if it wants to stop the
+# commit. The hook is allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "commit-msg".
+
+# Uncomment the below to add a Signed-off-by line to the message.
+# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
+# hook is more suited to it.
+#
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
+
+# This example catches duplicate Signed-off-by lines.
+
+test "" = "$(grep '^Signed-off-by: ' "$1" |
+ sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
+ echo >&2 Duplicate Signed-off-by lines.
+ exit 1
+}
Added: cdn/trunk/geoip/.git/hooks/post-commit.sample
===================================================================
--- cdn/trunk/geoip/.git/hooks/post-commit.sample (rev 0)
+++ cdn/trunk/geoip/.git/hooks/post-commit.sample 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# An example hook script that is called after a successful
+# commit is made.
+#
+# To enable this hook, rename this file to "post-commit".
+
+: Nothing
Added: cdn/trunk/geoip/.git/hooks/post-receive.sample
===================================================================
--- cdn/trunk/geoip/.git/hooks/post-receive.sample (rev 0)
+++ cdn/trunk/geoip/.git/hooks/post-receive.sample 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script for the "post-receive" event.
+#
+# The "post-receive" script is run after receive-pack has accepted a pack
+# and the repository has been updated. It is passed arguments in through
+# stdin in the form
+# <oldrev> <newrev> <refname>
+# For example:
+# aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master
+#
+# see contrib/hooks/ for a sample, or uncomment the next line and
+# rename the file to "post-receive".
+
+#. /usr/share/doc/git-core/contrib/hooks/post-receive-email
Added: cdn/trunk/geoip/.git/hooks/post-update.sample
===================================================================
--- cdn/trunk/geoip/.git/hooks/post-update.sample (rev 0)
+++ cdn/trunk/geoip/.git/hooks/post-update.sample 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# An example hook script to prepare a packed repository for use over
+# dumb transports.
+#
+# To enable this hook, rename this file to "post-update".
+
+exec git-update-server-info
Added: cdn/trunk/geoip/.git/hooks/pre-applypatch.sample
===================================================================
--- cdn/trunk/geoip/.git/hooks/pre-applypatch.sample (rev 0)
+++ cdn/trunk/geoip/.git/hooks/pre-applypatch.sample 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed
+# by applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-applypatch".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/pre-commit" &&
+ exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
+:
Added: cdn/trunk/geoip/.git/hooks/pre-commit.sample
===================================================================
--- cdn/trunk/geoip/.git/hooks/pre-commit.sample (rev 0)
+++ cdn/trunk/geoip/.git/hooks/pre-commit.sample 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed.
+# Called by git-commit with no arguments. The hook should
+# exit with non-zero status after issuing an appropriate message if
+# it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-commit".
+
+if git-rev-parse --verify HEAD >/dev/null 2>&1
+then
+ against=HEAD
+else
+ # Initial commit: diff against an empty tree object
+ against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+# If you want to allow non-ascii filenames set this variable to true.
+allownonascii=$(git config hooks.allownonascii)
+
+# Cross platform projects tend to avoid non-ascii filenames; prevent
+# them from being added to the repository. We exploit the fact that the
+# printable range starts at the space character and ends with tilde.
+if [ "$allownonascii" != "true" ] &&
+ # Note that the use of brackets around a tr range is ok here, (it's
+ # even required, for portability to Solaris 10's /usr/bin/tr), since
+ # the square bracket bytes happen to fall in the designated range.
+ test "$(git diff --cached --name-only --diff-filter=A -z $against |
+ LC_ALL=C tr -d '[ -~]\0')"
+then
+ echo "Error: Attempt to add a non-ascii file name."
+ echo
+ echo "This can cause problems if you want to work"
+ echo "with people on other platforms."
+ echo
+ echo "To be portable it is advisable to rename the file ..."
+ echo
+ echo "If you know what you are doing you can disable this"
+ echo "check using:"
+ echo
+ echo " git config hooks.allownonascii true"
+ echo
+ exit 1
+fi
+
+exec git diff-index --check --cached $against --
Added: cdn/trunk/geoip/.git/hooks/pre-rebase.sample
===================================================================
--- cdn/trunk/geoip/.git/hooks/pre-rebase.sample (rev 0)
+++ cdn/trunk/geoip/.git/hooks/pre-rebase.sample 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,169 @@
+#!/bin/sh
+#
+# Copyright (c) 2006, 2008 Junio C Hamano
+#
+# The "pre-rebase" hook is run just before "git-rebase" starts doing
+# its job, and can prevent the command from running by exiting with
+# non-zero status.
+#
+# The hook is called with the following parameters:
+#
+# $1 -- the upstream the series was forked from.
+# $2 -- the branch being rebased (or empty when rebasing the current branch).
+#
+# This sample shows how to prevent topic branches that are already
+# merged to 'next' branch from getting rebased, because allowing it
+# would result in rebasing already published history.
+
+publish=next
+basebranch="$1"
+if test "$#" = 2
+then
+ topic="refs/heads/$2"
+else
+ topic=`git symbolic-ref HEAD` ||
+ exit 0 ;# we do not interrupt rebasing detached HEAD
+fi
+
+case "$topic" in
+refs/heads/??/*)
+ ;;
+*)
+ exit 0 ;# we do not interrupt others.
+ ;;
+esac
+
+# Now we are dealing with a topic branch being rebased
+# on top of master. Is it OK to rebase it?
+
+# Does the topic really exist?
+git show-ref -q "$topic" || {
+ echo >&2 "No such branch $topic"
+ exit 1
+}
+
+# Is topic fully merged to master?
+not_in_master=`git-rev-list --pretty=oneline ^master "$topic"`
+if test -z "$not_in_master"
+then
+ echo >&2 "$topic is fully merged to master; better remove it."
+ exit 1 ;# we could allow it, but there is no point.
+fi
+
+# Is topic ever merged to next? If so you should not be rebasing it.
+only_next_1=`git-rev-list ^master "^$topic" ${publish} | sort`
+only_next_2=`git-rev-list ^master ${publish} | sort`
+if test "$only_next_1" = "$only_next_2"
+then
+ not_in_topic=`git-rev-list "^$topic" master`
+ if test -z "$not_in_topic"
+ then
+ echo >&2 "$topic is already up-to-date with master"
+ exit 1 ;# we could allow it, but there is no point.
+ else
+ exit 0
+ fi
+else
+ not_in_next=`git-rev-list --pretty=oneline ^${publish} "$topic"`
+ perl -e '
+ my $topic = $ARGV[0];
+ my $msg = "* $topic has commits already merged to public branch:\n";
+ my (%not_in_next) = map {
+ /^([0-9a-f]+) /;
+ ($1 => 1);
+ } split(/\n/, $ARGV[1]);
+ for my $elem (map {
+ /^([0-9a-f]+) (.*)$/;
+ [$1 => $2];
+ } split(/\n/, $ARGV[2])) {
+ if (!exists $not_in_next{$elem->[0]}) {
+ if ($msg) {
+ print STDERR $msg;
+ undef $msg;
+ }
+ print STDERR " $elem->[1]\n";
+ }
+ }
+ ' "$topic" "$not_in_next" "$not_in_master"
+ exit 1
+fi
+
+exit 0
+
+################################################################
+
+This sample hook safeguards topic branches that have been
+published from being rewound.
+
+The workflow assumed here is:
+
+ * Once a topic branch forks from "master", "master" is never
+ merged into it again (either directly or indirectly).
+
+ * Once a topic branch is fully cooked and merged into "master",
+ it is deleted. If you need to build on top of it to correct
+ earlier mistakes, a new topic branch is created by forking at
+ the tip of the "master". This is not strictly necessary, but
+ it makes it easier to keep your history simple.
+
+ * Whenever you need to test or publish your changes to topic
+ branches, merge them into "next" branch.
+
+The script, being an example, hardcodes the publish branch name
+to be "next", but it is trivial to make it configurable via
+$GIT_DIR/config mechanism.
+
+With this workflow, you would want to know:
+
+(1) ... if a topic branch has ever been merged to "next". Young
+ topic branches can have stupid mistakes you would rather
+ clean up before publishing, and things that have not been
+ merged into other branches can be easily rebased without
+ affecting other people. But once it is published, you would
+ not want to rewind it.
+
+(2) ... if a topic branch has been fully merged to "master".
+ Then you can delete it. More importantly, you should not
+ build on top of it -- other people may already want to
+ change things related to the topic as patches against your
+ "master", so if you need further changes, it is better to
+ fork the topic (perhaps with the same name) afresh from the
+ tip of "master".
+
+Let's look at this example:
+
+ o---o---o---o---o---o---o---o---o---o "next"
+ / / / /
+ / a---a---b A / /
+ / / / /
+ / / c---c---c---c B /
+ / / / \ /
+ / / / b---b C \ /
+ / / / / \ /
+ ---o---o---o---o---o---o---o---o---o---o---o "master"
+
+
+A, B and C are topic branches.
+
+ * A has one fix since it was merged up to "next".
+
+ * B has finished. It has been fully merged up to "master" and "next",
+ and is ready to be deleted.
+
+ * C has not merged to "next" at all.
+
+We would want to allow C to be rebased, refuse A, and encourage
+B to be deleted.
+
+To compute (1):
+
+ git-rev-list ^master ^topic next
+ git-rev-list ^master next
+
+ if these match, topic has not merged in next at all.
+
+To compute (2):
+
+ git-rev-list master..topic
+
+ if this is empty, it is fully merged to "master".
Added: cdn/trunk/geoip/.git/hooks/prepare-commit-msg.sample
===================================================================
--- cdn/trunk/geoip/.git/hooks/prepare-commit-msg.sample (rev 0)
+++ cdn/trunk/geoip/.git/hooks/prepare-commit-msg.sample 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# An example hook script to prepare the commit log message.
+# Called by git-commit with the name of the file that has the
+# commit message, followed by the description of the commit
+# message's source. The hook's purpose is to edit the commit
+# message file. If the hook fails with a non-zero status,
+# the commit is aborted.
+#
+# To enable this hook, rename this file to "prepare-commit-msg".
+
+# This hook includes three examples. The first comments out the
+# "Conflicts:" part of a merge commit.
+#
+# The second includes the output of "git diff --name-status -r"
+# into the message, just before the "git status" output. It is
+# commented because it doesn't cope with --amend or with squashed
+# commits.
+#
+# The third example adds a Signed-off-by line to the message, that can
+# still be edited. This is rarely a good idea.
+
+case "$2,$3" in
+ merge,)
+ perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
+
+# ,|template,)
+# perl -i.bak -pe '
+# print "\n" . `git diff --cached --name-status -r`
+# if /^#/ && $first++ == 0' "$1" ;;
+
+ *) ;;
+esac
+
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
Added: cdn/trunk/geoip/.git/hooks/update.sample
===================================================================
--- cdn/trunk/geoip/.git/hooks/update.sample (rev 0)
+++ cdn/trunk/geoip/.git/hooks/update.sample 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# An example hook script to blocks unannotated tags from entering.
+# Called by git-receive-pack with arguments: refname sha1-old sha1-new
+#
+# To enable this hook, rename this file to "update".
+#
+# Config
+# ------
+# hooks.allowunannotated
+# This boolean sets whether unannotated tags will be allowed into the
+# repository. By default they won't be.
+# hooks.allowdeletetag
+# This boolean sets whether deleting tags will be allowed in the
+# repository. By default they won't be.
+# hooks.allowmodifytag
+# This boolean sets whether a tag may be modified after creation. By default
+# it won't be.
+# hooks.allowdeletebranch
+# This boolean sets whether deleting branches will be allowed in the
+# repository. By default they won't be.
+# hooks.denycreatebranch
+# This boolean sets whether remotely creating branches will be denied
+# in the repository. By default this is allowed.
+#
+
+# --- Command line
+refname="$1"
+oldrev="$2"
+newrev="$3"
+
+# --- Safety check
+if [ -z "$GIT_DIR" ]; then
+ echo "Don't run this script from the command line." >&2
+ echo " (if you want, you could supply GIT_DIR then run" >&2
+ echo " $0 <ref> <oldrev> <newrev>)" >&2
+ exit 1
+fi
+
+if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
+ echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
+ exit 1
+fi
+
+# --- Config
+allowunannotated=$(git config --bool hooks.allowunannotated)
+allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
+denycreatebranch=$(git config --bool hooks.denycreatebranch)
+allowdeletetag=$(git config --bool hooks.allowdeletetag)
+allowmodifytag=$(git config --bool hooks.allowmodifytag)
+
+# check for no description
+projectdesc=$(sed -e '1q' "$GIT_DIR/description")
+case "$projectdesc" in
+"Unnamed repository"* | "")
+ echo "*** Project description file hasn't been set" >&2
+ exit 1
+ ;;
+esac
+
+# --- Check types
+# if $newrev is 0000...0000, it's a commit to delete a ref.
+zero="0000000000000000000000000000000000000000"
+if [ "$newrev" = "$zero" ]; then
+ newrev_type=delete
+else
+ newrev_type=$(git-cat-file -t $newrev)
+fi
+
+case "$refname","$newrev_type" in
+ refs/tags/*,commit)
+ # un-annotated tag
+ short_refname=${refname##refs/tags/}
+ if [ "$allowunannotated" != "true" ]; then
+ echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
+ echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
+ exit 1
+ fi
+ ;;
+ refs/tags/*,delete)
+ # delete tag
+ if [ "$allowdeletetag" != "true" ]; then
+ echo "*** Deleting a tag is not allowed in this repository" >&2
+ exit 1
+ fi
+ ;;
+ refs/tags/*,tag)
+ # annotated tag
+ if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
+ then
+ echo "*** Tag '$refname' already exists." >&2
+ echo "*** Modifying a tag is not allowed in this repository." >&2
+ exit 1
+ fi
+ ;;
+ refs/heads/*,commit)
+ # branch
+ if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
+ echo "*** Creating a branch is not allowed in this repository" >&2
+ exit 1
+ fi
+ ;;
+ refs/heads/*,delete)
+ # delete branch
+ if [ "$allowdeletebranch" != "true" ]; then
+ echo "*** Deleting a branch is not allowed in this repository" >&2
+ exit 1
+ fi
+ ;;
+ refs/remotes/*,commit)
+ # tracking branch
+ ;;
+ refs/remotes/*,delete)
+ # delete tracking branch
+ if [ "$allowdeletebranch" != "true" ]; then
+ echo "*** Deleting a tracking branch is not allowed in this repository" >&2
+ exit 1
+ fi
+ ;;
+ *)
+ # Anything else (is there anything else?)
+ echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
+ exit 1
+ ;;
+esac
+
+# --- Finished
+exit 0
Added: cdn/trunk/geoip/.git/index
===================================================================
(Binary files differ)
Property changes on: cdn/trunk/geoip/.git/index
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: cdn/trunk/geoip/.git/info/exclude
===================================================================
--- cdn/trunk/geoip/.git/info/exclude (rev 0)
+++ cdn/trunk/geoip/.git/info/exclude 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,6 @@
+# git-ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
Added: cdn/trunk/geoip/.git/logs/HEAD
===================================================================
--- cdn/trunk/geoip/.git/logs/HEAD (rev 0)
+++ cdn/trunk/geoip/.git/logs/HEAD 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 7d8fc2ac99f766efc30150c9dd854d69584cb992 ARAKI Yasuhiro <araki-y@ay-laptop.(none)> 1282977103 +0900 clone: from git://github.com/cjheath/geoip.git
Added: cdn/trunk/geoip/.git/logs/refs/heads/master
===================================================================
--- cdn/trunk/geoip/.git/logs/refs/heads/master (rev 0)
+++ cdn/trunk/geoip/.git/logs/refs/heads/master 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 7d8fc2ac99f766efc30150c9dd854d69584cb992 ARAKI Yasuhiro <araki-y@ay-laptop.(none)> 1282977103 +0900 clone: from git://github.com/cjheath/geoip.git
Added: cdn/trunk/geoip/.git/objects/pack/pack-d66c6f783d4495ac3320b4cca8997c8fa3dc8d29.idx
===================================================================
(Binary files differ)
Property changes on: cdn/trunk/geoip/.git/objects/pack/pack-d66c6f783d4495ac3320b4cca8997c8fa3dc8d29.idx
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: cdn/trunk/geoip/.git/objects/pack/pack-d66c6f783d4495ac3320b4cca8997c8fa3dc8d29.pack
===================================================================
(Binary files differ)
Property changes on: cdn/trunk/geoip/.git/objects/pack/pack-d66c6f783d4495ac3320b4cca8997c8fa3dc8d29.pack
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: cdn/trunk/geoip/.git/packed-refs
===================================================================
--- cdn/trunk/geoip/.git/packed-refs (rev 0)
+++ cdn/trunk/geoip/.git/packed-refs 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,2 @@
+# pack-refs with: peeled
+7d8fc2ac99f766efc30150c9dd854d69584cb992 refs/remotes/origin/master
Added: cdn/trunk/geoip/.git/refs/heads/master
===================================================================
--- cdn/trunk/geoip/.git/refs/heads/master (rev 0)
+++ cdn/trunk/geoip/.git/refs/heads/master 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1 @@
+7d8fc2ac99f766efc30150c9dd854d69584cb992
Added: cdn/trunk/geoip/.git/refs/remotes/origin/HEAD
===================================================================
--- cdn/trunk/geoip/.git/refs/remotes/origin/HEAD (rev 0)
+++ cdn/trunk/geoip/.git/refs/remotes/origin/HEAD 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1 @@
+ref: refs/remotes/origin/master
Added: cdn/trunk/geoip/.gitignore
===================================================================
--- cdn/trunk/geoip/.gitignore (rev 0)
+++ cdn/trunk/geoip/.gitignore 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,3 @@
+pkg
+website/index.html
+GeoLiteCity.dat
Added: cdn/trunk/geoip/History.txt
===================================================================
--- cdn/trunk/geoip/History.txt (rev 0)
+++ cdn/trunk/geoip/History.txt 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,16 @@
+== 0.8.1 2009-06-04
+
+* Added GeoIP#close method to close the file descriptor
+
+== 0.8.0 2008-08-29
+
+* Added Mutex protection around file I/O for thread safety
+
+== 0.7.0 2008-05-03
+
+* Added Hez Ronningen's patch for using the ISP lookup data file
+
+== 0.5.0 2007-10-24
+
+* 1 major enhancement:
+ * Initial release
Added: cdn/trunk/geoip/Manifest.txt
===================================================================
--- cdn/trunk/geoip/Manifest.txt (rev 0)
+++ cdn/trunk/geoip/Manifest.txt 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,7 @@
+History.txt
+Manifest.txt
+README.rdoc
+Rakefile
+lib/geoip.rb
+test/test_geoip.rb
+test/test_helper.rb
Added: cdn/trunk/geoip/README.rdoc
===================================================================
--- cdn/trunk/geoip/README.rdoc (rev 0)
+++ cdn/trunk/geoip/README.rdoc 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,71 @@
+= geoip
+
+http://github.com/cjheath/geoip
+
+== DESCRIPTION:
+
+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.
+
+== FEATURES/PROBLEMS:
+
+Includes support for ASN data files, thanks to Roland Matiz.
+This release adds support for timezone names, thanks to Tonni Aagesen.
+
+== SYNOPSIS:
+
+ require 'geoip'
+ GeoIP.new('GeoLiteCity.dat').country('www.atlantis.sk')
+ => ["www.atlantis.sk", "217.67.18.26", "SK", "SVK", "Slovakia", "EU", "02", "Bratislava", "", 48.15, 17.1167, nil, nil, "Europe/Bratislava"]
+
+ Returned values are the requested hostname, the IP address as a dotted quad,
+ Maxmind's country code, the ISO3166-1 country code, the ISO3166-2 country code,
+ the ISO3166 country name, and the continent code.
+
+ GeoIP.new('GeoCity.dat').city('github.com')
+ => ["github.com", "207.97.227.239", "US", "USA", "United States", "NA", "CA", "San Francisco", "94110", 37.7484, -122.4156, 807, 415, "America/Los_Angeles"]
+
+ Returned values are the country values followed by region or state name,
+ city name, postal_code/zipcode, latitude, longitude, USA DMA code, USA area code,
+ timezone name. Sorry it's not a Hash... historical.
+
+ GeoIP.new('GeoIPASNum.dat').asn("www.fsb.ru")
+ => ["AS8342", "RTComm.RU Autonomous System"]
+
+== REQUIREMENTS:
+
+You need at least the free GeoLiteCity.dat, for which the last known download
+location is <http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz>,
+or the city database from <http://www.maxmind.com/app/geolitecity>.
+
+The ASN database location is
+<http://geolite.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz>.
+
+This API requires the file to be decompressed for searching. Other versions
+of this database are available for purchase which contain more detailed
+information, but this information is not returned by this implementation.
+See www.maxmind.com for more information.
+
+== INSTALL:
+
+sudo gem install geoip
+
+== LICENSE:
+
+This version Copyright (C) 2005 Clifford Heath
+Derived from the C version, Copyright (C) 2003 MaxMind LLC
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Added: cdn/trunk/geoip/Rakefile
===================================================================
--- cdn/trunk/geoip/Rakefile (rev 0)
+++ cdn/trunk/geoip/Rakefile 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,23 @@
+require 'rubygems'
+gem 'hoe', '>= 2.1.0'
+require 'hoe'
+require 'fileutils'
+require './lib/geoip'
+
+Hoe.plugin :newgem
+Hoe.plugin :website
+
+# Generate all the Rake tasks
+# Run 'rake -T' to see list of generated tasks (from gem root directory)
+$hoe = Hoe.spec 'geoip' do
+ self.developer 'Clifford Heath', 'clifford.heath@xxxxxxxxx'
+ self.developer 'Roland Moriz', 'rmoriz@xxxxxxxxx'
+ self.rubyforge_name = self.name # TODO this is default value
+end
+
+require 'newgem/tasks'
+Dir['tasks/**/*.rake'].each { |t| load t }
+
+# TODO - want other tests/tasks run by default? Add them to the list
+# remove_task :default
+# task :default => [:spec, :features]
Added: cdn/trunk/geoip/config/website.yml
===================================================================
--- cdn/trunk/geoip/config/website.yml (rev 0)
+++ cdn/trunk/geoip/config/website.yml 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,2 @@
+host: cjheath@xxxxxxxxxxxxx
+remote_dir: /var/www/gforge-projects/geoip
Added: cdn/trunk/geoip/geoip.gemspec
===================================================================
--- cdn/trunk/geoip/geoip.gemspec (rev 0)
+++ cdn/trunk/geoip/geoip.gemspec 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,37 @@
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
+ s.name = %q{geoip}
+ s.version = "0.8.5"
+
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
+ s.authors = ["Clifford Heath", "Roland Moriz"]
+ s.date = %q{2009-09-03}
+ s.description = %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.}
+ s.email = ["clifford.heath@xxxxxxxxx", "rmoriz@xxxxxxxxx"]
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt"]
+ s.files = ["History.txt", "Manifest.txt", "README.rdoc", "Rakefile", "lib/geoip.rb", "test/test_geoip.rb", "test/test_helper.rb"]
+ s.has_rdoc = true
+ s.homepage = %q{http://github.com/cjheath/geoip}
+ s.rdoc_options = ["--main", "README.rdoc"]
+ s.require_paths = ["lib"]
+ s.rubyforge_project = %q{geoip}
+ s.rubygems_version = %q{1.3.1}
+ s.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.}
+ s.test_files = ["test/test_geoip.rb", "test/test_helper.rb"]
+
+ if s.respond_to? :specification_version then
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+ s.specification_version = 3
+
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
+ s.add_development_dependency(%q<hoe>, [">= 2.3.2"])
+ else
+ s.add_dependency(%q<hoe>, [">= 2.3.2"])
+ end
+ else
+ s.add_dependency(%q<hoe>, [">= 2.3.2"])
+ end
+end
Added: cdn/trunk/geoip/lib/geoip.rb
===================================================================
--- cdn/trunk/geoip/lib/geoip.rb (rev 0)
+++ cdn/trunk/geoip/lib/geoip.rb 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,1028 @@
+$:.unshift File.dirname(__FILE__)
+#
+# Native Ruby reader for the GeoIP database
+# Lookup the country where IP address is allocated
+#
+#= COPYRIGHT
+# This version Copyright (C) 2005 Clifford Heath
+# Derived from the C version, Copyright (C) 2003 MaxMind LLC
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+#= SYNOPSIS
+#
+# require 'geoip'
+# p GeoIP.new('/usr/share/GeoIP/GeoIP.dat').country("www.netscape.sk")
+#
+#= DESCRIPTION
+#
+# GeoIP searches a GeoIP database for a given host or IP address, and
+# returns information about the country where the IP address is allocated.
+#
+#= PREREQUISITES
+#
+# You need at least the free GeoIP.dat, for which the last known download
+# location is <http://www.maxmind.com/download/geoip/database/GeoIP.dat.gz>
+# This API requires the file to be decompressed for searching. Other versions
+# of this database are available for purchase which contain more detailed
+# information, but this information is not returned by this implementation.
+# See www.maxmind.com for more information.
+#
+#=end
+require 'thread' # Needed for Mutex
+require 'socket'
+begin
+ require 'io/extra' # for IO.pread
+rescue LoadError
+ # oh well, hope they're not forking after initializing
+end
+
+class GeoIP
+ VERSION = "0.8.7"
+ private
+ CountryCode = [
+ "--","AP","EU","AD","AE","AF","AG","AI","AL","AM","AN",
+ "AO","AQ","AR","AS","AT","AU","AW","AZ","BA","BB",
+ "BD","BE","BF","BG","BH","BI","BJ","BM","BN","BO",
+ "BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD",
+ "CF","CG","CH","CI","CK","CL","CM","CN","CO","CR",
+ "CU","CV","CX","CY","CZ","DE","DJ","DK","DM","DO",
+ "DZ","EC","EE","EG","EH","ER","ES","ET","FI","FJ",
+ "FK","FM","FO","FR","FX","GA","GB","GD","GE","GF",
+ "GH","GI","GL","GM","GN","GP","GQ","GR","GS","GT",
+ "GU","GW","GY","HK","HM","HN","HR","HT","HU","ID",
+ "IE","IL","IN","IO","IQ","IR","IS","IT","JM","JO",
+ "JP","KE","KG","KH","KI","KM","KN","KP","KR","KW",
+ "KY","KZ","LA","LB","LC","LI","LK","LR","LS","LT",
+ "LU","LV","LY","MA","MC","MD","MG","MH","MK","ML",
+ "MM","MN","MO","MP","MQ","MR","MS","MT","MU","MV",
+ "MW","MX","MY","MZ","NA","NC","NE","NF","NG","NI",
+ "NL","NO","NP","NR","NU","NZ","OM","PA","PE","PF",
+ "PG","PH","PK","PL","PM","PN","PR","PS","PT","PW",
+ "PY","QA","RE","RO","RU","RW","SA","SB","SC","SD",
+ "SE","SG","SH","SI","SJ","SK","SL","SM","SN","SO",
+ "SR","ST","SV","SY","SZ","TC","TD","TF","TG","TH",
+ "TJ","TK","TM","TN","TO","TL","TR","TT","TV","TW",
+ "TZ","UA","UG","UM","US","UY","UZ","VA","VC","VE",
+ "VG","VI","VN","VU","WF","WS","YE","YT","RS","ZA",
+ "ZM","ME","ZW","A1","A2","O1","AX","GG","IM","JE",
+ "BL","MF"
+ ]
+
+ CountryCode3 = [
+ "--","AP","EU","AND","ARE","AFG","ATG","AIA","ALB","ARM","ANT",
+ "AGO","AQ","ARG","ASM","AUT","AUS","ABW","AZE","BIH","BRB",
+ "BGD","BEL","BFA","BGR","BHR","BDI","BEN","BMU","BRN","BOL",
+ "BRA","BHS","BTN","BV","BWA","BLR","BLZ","CAN","CC","COD",
+ "CAF","COG","CHE","CIV","COK","CHL","CMR","CHN","COL","CRI",
+ "CUB","CPV","CX","CYP","CZE","DEU","DJI","DNK","DMA","DOM",
+ "DZA","ECU","EST","EGY","ESH","ERI","ESP","ETH","FIN","FJI",
+ "FLK","FSM","FRO","FRA","FX","GAB","GBR","GRD","GEO","GUF",
+ "GHA","GIB","GRL","GMB","GIN","GLP","GNQ","GRC","GS","GTM",
+ "GUM","GNB","GUY","HKG","HM","HND","HRV","HTI","HUN","IDN",
+ "IRL","ISR","IND","IO","IRQ","IRN","ISL","ITA","JAM","JOR",
+ "JPN","KEN","KGZ","KHM","KIR","COM","KNA","PRK","KOR","KWT",
+ "CYM","KAZ","LAO","LBN","LCA","LIE","LKA","LBR","LSO","LTU",
+ "LUX","LVA","LBY","MAR","MCO","MDA","MDG","MHL","MKD","MLI",
+ "MMR","MNG","MAC","MNP","MTQ","MRT","MSR","MLT","MUS","MDV",
+ "MWI","MEX","MYS","MOZ","NAM","NCL","NER","NFK","NGA","NIC",
+ "NLD","NOR","NPL","NRU","NIU","NZL","OMN","PAN","PER","PYF",
+ "PNG","PHL","PAK","POL","SPM","PCN","PRI","PSE","PRT","PLW",
+ "PRY","QAT","REU","ROU","RUS","RWA","SAU","SLB","SYC","SDN",
+ "SWE","SGP","SHN","SVN","SJM","SVK","SLE","SMR","SEN","SOM",
+ "SUR","STP","SLV","SYR","SWZ","TCA","TCD","TF","TGO","THA",
+ "TJK","TKL","TKM","TUN","TON","TLS","TUR","TTO","TUV","TWN",
+ "TZA","UKR","UGA","UM","USA","URY","UZB","VAT","VCT","VEN",
+ "VGB","VIR","VNM","VUT","WLF","WSM","YEM","YT","SRB","ZAF",
+ "ZMB","MNE","ZWE","A1","A2","O1","ALA","GGY","IMN","JEY",
+ "BLM","MAF"
+ ]
+
+ CountryName = [
+ "N/A",
+ "Asia/Pacific Region",
+ "Europe",
+ "Andorra",
+ "United Arab Emirates",
+ "Afghanistan",
+ "Antigua and Barbuda",
+ "Anguilla",
+ "Albania",
+ "Armenia",
+ "Netherlands Antilles",
+ "Angola",
+ "Antarctica",
+ "Argentina",
+ "American Samoa",
+ "Austria",
+ "Australia",
+ "Aruba",
+ "Azerbaijan",
+ "Bosnia and Herzegovina",
+ "Barbados",
+ "Bangladesh",
+ "Belgium",
+ "Burkina Faso",
+ "Bulgaria",
+ "Bahrain",
+ "Burundi",
+ "Benin",
+ "Bermuda",
+ "Brunei Darussalam",
+ "Bolivia",
+ "Brazil",
+ "Bahamas",
+ "Bhutan",
+ "Bouvet Island",
+ "Botswana",
+ "Belarus",
+ "Belize",
+ "Canada",
+ "Cocos (Keeling) Islands",
+ "Congo, the Democratic Republic of the",
+ "Central African Republic",
+ "Congo",
+ "Switzerland",
+ "Cote D'Ivoire",
+ "Cook Islands",
+ "Chile",
+ "Cameroon",
+ "China",
+ "Colombia",
+ "Costa Rica",
+ "Cuba",
+ "Cape Verde",
+ "Christmas Island",
+ "Cyprus",
+ "Czech Republic",
+ "Germany",
+ "Djibouti",
+ "Denmark",
+ "Dominica",
+ "Dominican Republic",
+ "Algeria",
+ "Ecuador",
+ "Estonia",
+ "Egypt",
+ "Western Sahara",
+ "Eritrea",
+ "Spain",
+ "Ethiopia",
+ "Finland",
+ "Fiji",
+ "Falkland Islands (Malvinas)",
+ "Micronesia, Federated States of",
+ "Faroe Islands",
+ "France",
+ "France, Metropolitan",
+ "Gabon",
+ "United Kingdom",
+ "Grenada",
+ "Georgia",
+ "French Guiana",
+ "Ghana",
+ "Gibraltar",
+ "Greenland",
+ "Gambia",
+ "Guinea",
+ "Guadeloupe",
+ "Equatorial Guinea",
+ "Greece",
+ "South Georgia and the South Sandwich Islands",
+ "Guatemala",
+ "Guam",
+ "Guinea-Bissau",
+ "Guyana",
+ "Hong Kong",
+ "Heard Island and McDonald Islands",
+ "Honduras",
+ "Croatia",
+ "Haiti",
+ "Hungary",
+ "Indonesia",
+ "Ireland",
+ "Israel",
+ "India",
+ "British Indian Ocean Territory",
+ "Iraq",
+ "Iran, Islamic Republic of",
+ "Iceland",
+ "Italy",
+ "Jamaica",
+ "Jordan",
+ "Japan",
+ "Kenya",
+ "Kyrgyzstan",
+ "Cambodia",
+ "Kiribati",
+ "Comoros",
+ "Saint Kitts and Nevis",
+ "Korea, Democratic People's Republic of",
+ "Korea, Republic of",
+ "Kuwait",
+ "Cayman Islands",
+ "Kazakhstan",
+ "Lao People's Democratic Republic",
+ "Lebanon",
+ "Saint Lucia",
+ "Liechtenstein",
+ "Sri Lanka",
+ "Liberia",
+ "Lesotho",
+ "Lithuania",
+ "Luxembourg",
+ "Latvia",
+ "Libyan Arab Jamahiriya",
+ "Morocco",
+ "Monaco",
+ "Moldova, Republic of",
+ "Madagascar",
+ "Marshall Islands",
+ "Macedonia, the Former Yugoslav Republic of",
+ "Mali",
+ "Myanmar",
+ "Mongolia",
+ "Macau",
+ "Northern Mariana Islands",
+ "Martinique",
+ "Mauritania",
+ "Montserrat",
+ "Malta",
+ "Mauritius",
+ "Maldives",
+ "Malawi",
+ "Mexico",
+ "Malaysia",
+ "Mozambique",
+ "Namibia",
+ "New Caledonia",
+ "Niger",
+ "Norfolk Island",
+ "Nigeria",
+ "Nicaragua",
+ "Netherlands",
+ "Norway",
+ "Nepal",
+ "Nauru",
+ "Niue",
+ "New Zealand",
+ "Oman",
+ "Panama",
+ "Peru",
+ "French Polynesia",
+ "Papua New Guinea",
+ "Philippines",
+ "Pakistan",
+ "Poland",
+ "Saint Pierre and Miquelon",
+ "Pitcairn",
+ "Puerto Rico",
+ "Palestinian Territory, Occupied",
+ "Portugal",
+ "Palau",
+ "Paraguay",
+ "Qatar",
+ "Reunion",
+ "Romania",
+ "Russian Federation",
+ "Rwanda",
+ "Saudi Arabia",
+ "Solomon Islands",
+ "Seychelles",
+ "Sudan",
+ "Sweden",
+ "Singapore",
+ "Saint Helena",
+ "Slovenia",
+ "Svalbard and Jan Mayen",
+ "Slovakia",
+ "Sierra Leone",
+ "San Marino",
+ "Senegal",
+ "Somalia",
+ "Suriname",
+ "Sao Tome and Principe",
+ "El Salvador",
+ "Syrian Arab Republic",
+ "Swaziland",
+ "Turks and Caicos Islands",
+ "Chad",
+ "French Southern Territories",
+ "Togo",
+ "Thailand",
+ "Tajikistan",
+ "Tokelau",
+ "Turkmenistan",
+ "Tunisia",
+ "Tonga",
+ "Timor-Leste",
+ "Turkey",
+ "Trinidad and Tobago",
+ "Tuvalu",
+ "Taiwan, Province of China",
+ "Tanzania, United Republic of",
+ "Ukraine",
+ "Uganda",
+ "United States Minor Outlying Islands",
+ "United States",
+ "Uruguay",
+ "Uzbekistan",
+ "Holy See (Vatican City State)",
+ "Saint Vincent and the Grenadines",
+ "Venezuela",
+ "Virgin Islands, British",
+ "Virgin Islands, U.S.",
+ "Viet Nam",
+ "Vanuatu",
+ "Wallis and Futuna",
+ "Samoa",
+ "Yemen",
+ "Mayotte",
+ "Serbia",
+ "South Africa",
+ "Zambia",
+ "Montenegro",
+ "Zimbabwe",
+ "Anonymous Proxy",
+ "Satellite Provider",
+ "Other",
+ "Aland Islands",
+ "Guernsey",
+ "Isle of Man",
+ "Jersey",
+ "Saint Barthelemy",
+ "Saint Martin"
+ ]
+
+ CountryContinent = [
+ "--","AS","EU","EU","AS","AS","SA","SA","EU","AS","SA",
+ "AF","AN","SA","OC","EU","OC","SA","AS","EU","SA",
+ "AS","EU","AF","EU","AS","AF","AF","SA","AS","SA",
+ "SA","SA","AS","AF","AF","EU","SA","NA","AS","AF",
+ "AF","AF","EU","AF","OC","SA","AF","AS","SA","SA",
+ "SA","AF","AS","AS","EU","EU","AF","EU","SA","SA",
+ "AF","SA","EU","AF","AF","AF","EU","AF","EU","OC",
+ "SA","OC","EU","EU","EU","AF","EU","SA","AS","SA",
+ "AF","EU","SA","AF","AF","SA","AF","EU","SA","SA",
+ "OC","AF","SA","AS","AF","SA","EU","SA","EU","AS",
+ "EU","AS","AS","AS","AS","AS","EU","EU","SA","AS",
+ "AS","AF","AS","AS","OC","AF","SA","AS","AS","AS",
+ "SA","AS","AS","AS","SA","EU","AS","AF","AF","EU",
+ "EU","EU","AF","AF","EU","EU","AF","OC","EU","AF",
+ "AS","AS","AS","OC","SA","AF","SA","EU","AF","AS",
+ "AF","NA","AS","AF","AF","OC","AF","OC","AF","SA",
+ "EU","EU","AS","OC","OC","OC","AS","SA","SA","OC",
+ "OC","AS","AS","EU","SA","OC","SA","AS","EU","OC",
+ "SA","AS","AF","EU","AS","AF","AS","OC","AF","AF",
+ "EU","AS","AF","EU","EU","EU","AF","EU","AF","AF",
+ "SA","AF","SA","AS","AF","SA","AF","AF","AF","AS",
+ "AS","OC","AS","AF","OC","AS","AS","SA","OC","AS",
+ "AF","EU","AF","OC","NA","SA","AS","EU","SA","SA",
+ "SA","SA","AS","OC","OC","OC","AS","AF","EU","AF",
+ "AF","EU","AF","--","--","--","EU","EU","EU","EU",
+ "SA","SA"
+ ]
+
+ TimeZone = {
+ "USAL" => "America/Chicago", "USAK" => "America/Anchorage", "USAZ" => "America/Phoenix",
+ "USAR" => "America/Chicago", "USCA" => "America/Los_Angeles", "USCO" => "America/Denver",
+ "USCT" => "America/New_York", "USDE" => "America/New_York", "USDC" => "America/New_York",
+ "USFL" => "America/New_York", "USGA" => "America/New_York", "USHI" => "Pacific/Honolulu",
+ "USID" => "America/Denver", "USIL" => "America/Chicago", "USIN" => "America/Indianapolis",
+ "USIA" => "America/Chicago", "USKS" => "America/Chicago", "USKY" => "America/New_York",
+ "USLA" => "America/Chicago", "USME" => "America/New_York", "USMD" => "America/New_York",
+ "USMA" => "America/New_York", "USMI" => "America/New_York", "USMN" => "America/Chicago",
+ "USMS" => "America/Chicago", "USMO" => "America/Chicago", "USMT" => "America/Denver",
+ "USNE" => "America/Chicago", "USNV" => "America/Los_Angeles", "USNH" => "America/New_York",
+ "USNJ" => "America/New_York", "USNM" => "America/Denver", "USNY" => "America/New_York",
+ "USNC" => "America/New_York", "USND" => "America/Chicago", "USOH" => "America/New_York",
+ "USOK" => "America/Chicago", "USOR" => "America/Los_Angeles", "USPA" => "America/New_York",
+ "USRI" => "America/New_York", "USSC" => "America/New_York", "USSD" => "America/Chicago",
+ "USTN" => "America/Chicago", "USTX" => "America/Chicago", "USUT" => "America/Denver",
+ "USVT" => "America/New_York", "USVA" => "America/New_York", "USWA" => "America/Los_Angeles",
+ "USWV" => "America/New_York", "USWI" => "America/Chicago", "USWY" => "America/Denver",
+ "CAAB" => "America/Edmonton", "CABC" => "America/Vancouver", "CAMB" => "America/Winnipeg",
+ "CANB" => "America/Halifax", "CANL" => "America/St_Johns", "CANT" => "America/Yellowknife",
+ "CANS" => "America/Halifax", "CANU" => "America/Rankin_Inlet", "CAON" => "America/Rainy_River",
+ "CAPE" => "America/Halifax", "CAQC" => "America/Montreal", "CASK" => "America/Regina",
+ "CAYT" => "America/Whitehorse", "AU01" => "Australia/Canberra", "AU02" => "Australia/NSW",
+ "AU03" => "Australia/North", "AU04" => "Australia/Queensland", "AU05" => "Australia/South",
+ "AU06" => "Australia/Tasmania", "AU07" => "Australia/Victoria", "AU08" => "Australia/West",
+ "AS" => "US/Samoa", "CI" => "Africa/Abidjan", "GH" => "Africa/Accra",
+ "DZ" => "Africa/Algiers", "ER" => "Africa/Asmera", "ML" => "Africa/Bamako",
+ "CF" => "Africa/Bangui", "GM" => "Africa/Banjul", "GW" => "Africa/Bissau",
+ "CG" => "Africa/Brazzaville", "BI" => "Africa/Bujumbura", "EG" => "Africa/Cairo",
+ "MA" => "Africa/Casablanca", "GN" => "Africa/Conakry", "SN" => "Africa/Dakar",
+ "DJ" => "Africa/Djibouti", "SL" => "Africa/Freetown", "BW" => "Africa/Gaborone",
+ "ZW" => "Africa/Harare", "ZA" => "Africa/Johannesburg", "UG" => "Africa/Kampala",
+ "SD" => "Africa/Khartoum", "RW" => "Africa/Kigali", "NG" => "Africa/Lagos",
+ "GA" => "Africa/Libreville", "TG" => "Africa/Lome", "AO" => "Africa/Luanda",
+ "ZM" => "Africa/Lusaka", "GQ" => "Africa/Malabo", "MZ" => "Africa/Maputo",
+ "LS" => "Africa/Maseru", "SZ" => "Africa/Mbabane", "SO" => "Africa/Mogadishu",
+ "LR" => "Africa/Monrovia", "KE" => "Africa/Nairobi", "TD" => "Africa/Ndjamena",
+ "NE" => "Africa/Niamey", "MR" => "Africa/Nouakchott", "BF" => "Africa/Ouagadougou",
+ "ST" => "Africa/Sao_Tome", "LY" => "Africa/Tripoli", "TN" => "Africa/Tunis",
+ "AI" => "America/Anguilla", "AG" => "America/Antigua", "AW" => "America/Aruba",
+ "BB" => "America/Barbados", "BZ" => "America/Belize", "CO" => "America/Bogota",
+ "VE" => "America/Caracas", "KY" => "America/Cayman", "CR" => "America/Costa_Rica",
+ "DM" => "America/Dominica", "SV" => "America/El_Salvador", "GD" => "America/Grenada",
+ "FR" => "Europe/Paris", "GP" => "America/Guadeloupe", "GT" => "America/Guatemala",
+ "GY" => "America/Guyana", "CU" => "America/Havana", "JM" => "America/Jamaica",
+ "BO" => "America/La_Paz", "PE" => "America/Lima", "NI" => "America/Managua",
+ "MQ" => "America/Martinique", "UY" => "America/Montevideo", "MS" => "America/Montserrat",
+ "BS" => "America/Nassau", "PA" => "America/Panama", "SR" => "America/Paramaribo",
+ "PR" => "America/Puerto_Rico", "KN" => "America/St_Kitts", "LC" => "America/St_Lucia",
+ "VC" => "America/St_Vincent", "HN" => "America/Tegucigalpa", "YE" => "Asia/Aden",
+ "JO" => "Asia/Amman", "TM" => "Asia/Ashgabat", "IQ" => "Asia/Baghdad",
+ "BH" => "Asia/Bahrain", "AZ" => "Asia/Baku", "TH" => "Asia/Bangkok",
+ "LB" => "Asia/Beirut", "KG" => "Asia/Bishkek", "BN" => "Asia/Brunei",
+ "IN" => "Asia/Calcutta", "MN" => "Asia/Choibalsan", "LK" => "Asia/Colombo",
+ "BD" => "Asia/Dhaka", "AE" => "Asia/Dubai", "TJ" => "Asia/Dushanbe",
+ "HK" => "Asia/Hong_Kong", "TR" => "Asia/Istanbul", "IL" => "Asia/Jerusalem",
+ "AF" => "Asia/Kabul", "PK" => "Asia/Karachi", "NP" => "Asia/Katmandu",
+ "KW" => "Asia/Kuwait", "MO" => "Asia/Macao", "PH" => "Asia/Manila",
+ "OM" => "Asia/Muscat", "CY" => "Asia/Nicosia", "KP" => "Asia/Pyongyang",
+ "QA" => "Asia/Qatar", "MM" => "Asia/Rangoon", "SA" => "Asia/Riyadh",
+ "KR" => "Asia/Seoul", "SG" => "Asia/Singapore", "TW" => "Asia/Taipei",
+ "GE" => "Asia/Tbilisi", "BT" => "Asia/Thimphu", "JP" => "Asia/Tokyo",
+ "LA" => "Asia/Vientiane", "AM" => "Asia/Yerevan", "BM" => "Atlantic/Bermuda",
+ "CV" => "Atlantic/Cape_Verde", "FO" => "Atlantic/Faeroe", "IS" => "Atlantic/Reykjavik",
+ "GS" => "Atlantic/South_Georgia", "SH" => "Atlantic/St_Helena", "CL" => "Chile/Continental",
+ "NL" => "Europe/Amsterdam", "AD" => "Europe/Andorra", "GR" => "Europe/Athens",
+ "YU" => "Europe/Belgrade", "DE" => "Europe/Berlin", "SK" => "Europe/Bratislava",
+ "BE" => "Europe/Brussels", "RO" => "Europe/Bucharest", "HU" => "Europe/Budapest",
+ "DK" => "Europe/Copenhagen", "IE" => "Europe/Dublin", "GI" => "Europe/Gibraltar",
+ "FI" => "Europe/Helsinki", "SI" => "Europe/Ljubljana", "GB" => "Europe/London",
+ "LU" => "Europe/Luxembourg", "MT" => "Europe/Malta", "BY" => "Europe/Minsk",
+ "MC" => "Europe/Monaco", "NO" => "Europe/Oslo", "CZ" => "Europe/Prague",
+ "LV" => "Europe/Riga", "IT" => "Europe/Rome", "SM" => "Europe/San_Marino",
+ "BA" => "Europe/Sarajevo", "MK" => "Europe/Skopje", "BG" => "Europe/Sofia",
+ "SE" => "Europe/Stockholm", "EE" => "Europe/Tallinn", "AL" => "Europe/Tirane",
+ "LI" => "Europe/Vaduz", "VA" => "Europe/Vatican", "AT" => "Europe/Vienna",
+ "LT" => "Europe/Vilnius", "PL" => "Europe/Warsaw", "HR" => "Europe/Zagreb",
+ "IR" => "Asia/Tehran", "MG" => "Indian/Antananarivo", "CX" => "Indian/Christmas",
+ "CC" => "Indian/Cocos", "KM" => "Indian/Comoro", "MV" => "Indian/Maldives",
+ "MU" => "Indian/Mauritius", "YT" => "Indian/Mayotte", "RE" => "Indian/Reunion",
+ "FJ" => "Pacific/Fiji", "TV" => "Pacific/Funafuti", "GU" => "Pacific/Guam",
+ "NR" => "Pacific/Nauru", "NU" => "Pacific/Niue", "NF" => "Pacific/Norfolk",
+ "PW" => "Pacific/Palau", "PN" => "Pacific/Pitcairn", "CK" => "Pacific/Rarotonga",
+ "WS" => "Pacific/Samoa", "KI" => "Pacific/Tarawa", "TO" => "Pacific/Tongatapu",
+ "WF" => "Pacific/Wallis", "TZ" => "Africa/Dar_es_Salaam", "VN" => "Asia/Phnom_Penh",
+ "KH" => "Asia/Phnom_Penh", "CM" => "Africa/Lagos", "DO" => "America/Santo_Domingo",
+ "ET" => "Africa/Addis_Ababa", "FX" => "Europe/Paris", "HT" => "America/Port-au-Prince",
+ "CH" => "Europe/Zurich", "AN" => "America/Curacao", "BJ" => "Africa/Porto-Novo",
+ "EH" => "Africa/El_Aaiun", "FK" => "Atlantic/Stanley", "GF" => "America/Cayenne",
+ "IO" => "Indian/Chagos", "MD" => "Europe/Chisinau", "MP" => "Pacific/Saipan",
+ "MW" => "Africa/Blantyre", "NA" => "Africa/Windhoek", "NC" => "Pacific/Noumea",
+ "PG" => "Pacific/Port_Moresby", "PM" => "America/Miquelon", "PS" => "Asia/Gaza",
+ "PY" => "America/Asuncion", "SB" => "Pacific/Guadalcanal", "SC" => "Indian/Mahe",
+ "SJ" => "Arctic/Longyearbyen", "SY" => "Asia/Damascus", "TC" => "America/Grand_Turk",
+ "TF" => "Indian/Kerguelen", "TK" => "Pacific/Fakaofo", "TT" => "America/Port_of_Spain",
+ "VG" => "America/Tortola", "VI" => "America/St_Thomas", "VU" => "Pacific/Efate",
+ "RS" => "Europe/Belgrade", "ME" => "Europe/Podgorica", "AX" => "Europe/Mariehamn",
+ "GG" => "Europe/Guernsey", "IM" => "Europe/Isle_of_Man", "JE" => "Europe/Jersey",
+ "BL" => "America/St_Barthelemy", "MF" => "America/Marigot", "AR01" => "America/Argentina/Buenos_Aires",
+ "AR02" => "America/Argentina/Catamarca", "AR03" => "America/Argentina/Tucuman", "AR04" => "America/Argentina/Rio_Gallegos",
+ "AR05" => "America/Argentina/Cordoba", "AR06" => "America/Argentina/Tucuman", "AR07" => "America/Argentina/Buenos_Aires",
+ "AR08" => "America/Argentina/Buenos_Aires", "AR09" => "America/Argentina/Tucuman", "AR10" => "America/Argentina/Jujuy",
+ "AR11" => "America/Argentina/San_Luis", "AR12" => "America/Argentina/La_Rioja", "AR13" => "America/Argentina/Mendoza",
+ "AR14" => "America/Argentina/Buenos_Aires", "AR15" => "America/Argentina/San_Luis", "AR16" => "America/Argentina/Buenos_Aires",
+ "AR17" => "America/Argentina/Salta", "AR18" => "America/Argentina/San_Juan", "AR19" => "America/Argentina/San_Luis",
+ "AR20" => "America/Argentina/Rio_Gallegos", "AR21" => "America/Argentina/Buenos_Aires", "AR22" => "America/Argentina/Catamarca",
+ "AR23" => "America/Argentina/Ushuaia", "AR24" => "America/Argentina/Tucuman", "BR01" => "America/Rio_Branco",
+ "BR02" => "America/Maceio", "BR03" => "America/Sao_Paulo", "BR04" => "America/Manaus",
+ "BR05" => "America/Bahia", "BR06" => "America/Fortaleza", "BR07" => "America/Sao_Paulo",
+ "BR08" => "America/Sao_Paulo", "BR11" => "America/Campo_Grande", "BR13" => "America/Belem",
+ "BR14" => "America/Cuiaba", "BR15" => "America/Sao_Paulo", "BR16" => "America/Belem",
+ "BR17" => "America/Recife", "BR18" => "America/Sao_Paulo", "BR20" => "America/Fortaleza",
+ "BR21" => "America/Sao_Paulo", "BR22" => "America/Recife", "BR23" => "America/Sao_Paulo",
+ "BR24" => "America/Porto_Velho", "BR25" => "America/Boa_Vista", "BR26" => "America/Sao_Paulo",
+ "BR27" => "America/Sao_Paulo", "BR28" => "America/Maceio", "BR29" => "America/Sao_Paulo",
+ "BR30" => "America/Recife", "BR31" => "America/Araguaina", "CD02" => "Africa/Kinshasa",
+ "CD05" => "Africa/Lubumbashi", "CD06" => "Africa/Kinshasa", "CD08" => "Africa/Kinshasa",
+ "CD10" => "Africa/Lubumbashi", "CD11" => "Africa/Lubumbashi", "CD12" => "Africa/Lubumbashi",
+ "CN01" => "Asia/Shanghai", "CN02" => "Asia/Shanghai", "CN03" => "Asia/Shanghai",
+ "CN04" => "Asia/Shanghai", "CN05" => "Asia/Harbin", "CN06" => "Asia/Chongqing",
+ "CN07" => "Asia/Shanghai", "CN08" => "Asia/Harbin", "CN09" => "Asia/Shanghai",
+ "CN10" => "Asia/Shanghai", "CN11" => "Asia/Chongqing", "CN12" => "Asia/Shanghai",
+ "CN13" => "Asia/Urumqi", "CN14" => "Asia/Chongqing", "CN15" => "Asia/Chongqing",
+ "CN16" => "Asia/Chongqing", "CN18" => "Asia/Chongqing", "CN19" => "Asia/Harbin",
+ "CN20" => "Asia/Harbin", "CN21" => "Asia/Chongqing", "CN22" => "Asia/Harbin",
+ "CN23" => "Asia/Shanghai", "CN24" => "Asia/Chongqing", "CN25" => "Asia/Shanghai",
+ "CN26" => "Asia/Chongqing", "CN28" => "Asia/Shanghai", "CN29" => "Asia/Chongqing",
+ "CN30" => "Asia/Chongqing", "CN31" => "Asia/Chongqing", "CN32" => "Asia/Chongqing",
+ "CN33" => "Asia/Chongqing", "EC01" => "Pacific/Galapagos", "EC02" => "America/Guayaquil",
+ "EC03" => "America/Guayaquil", "EC04" => "America/Guayaquil", "EC05" => "America/Guayaquil",
+ "EC06" => "America/Guayaquil", "EC07" => "America/Guayaquil", "EC08" => "America/Guayaquil",
+ "EC09" => "America/Guayaquil", "EC10" => "America/Guayaquil", "EC11" => "America/Guayaquil",
+ "EC12" => "America/Guayaquil", "EC13" => "America/Guayaquil", "EC14" => "America/Guayaquil",
+ "EC15" => "America/Guayaquil", "EC17" => "America/Guayaquil", "EC18" => "America/Guayaquil",
+ "EC19" => "America/Guayaquil", "EC20" => "America/Guayaquil", "EC22" => "America/Guayaquil",
+ "ES07" => "Europe/Madrid", "ES27" => "Europe/Madrid", "ES29" => "Europe/Madrid",
+ "ES31" => "Europe/Madrid", "ES32" => "Europe/Madrid", "ES34" => "Europe/Madrid",
+ "ES39" => "Europe/Madrid", "ES51" => "Africa/Ceuta", "ES52" => "Europe/Madrid",
+ "ES53" => "Atlantic/Canary", "ES54" => "Europe/Madrid", "ES55" => "Europe/Madrid",
+ "ES56" => "Europe/Madrid", "ES57" => "Europe/Madrid", "ES58" => "Europe/Madrid",
+ "ES59" => "Europe/Madrid", "ES60" => "Europe/Madrid", "GL01" => "America/Thule",
+ "GL02" => "America/Godthab", "GL03" => "America/Godthab", "ID01" => "Asia/Pontianak",
+ "ID02" => "Asia/Makassar", "ID03" => "Asia/Jakarta", "ID04" => "Asia/Jakarta",
+ "ID05" => "Asia/Jakarta", "ID06" => "Asia/Jakarta", "ID07" => "Asia/Jakarta",
+ "ID08" => "Asia/Jakarta", "ID09" => "Asia/Jayapura", "ID10" => "Asia/Jakarta",
+ "ID11" => "Asia/Pontianak", "ID12" => "Asia/Makassar", "ID13" => "Asia/Makassar",
+ "ID14" => "Asia/Makassar", "ID15" => "Asia/Jakarta", "ID16" => "Asia/Makassar",
+ "ID17" => "Asia/Makassar", "ID18" => "Asia/Makassar", "ID19" => "Asia/Pontianak",
+ "ID20" => "Asia/Makassar", "ID21" => "Asia/Makassar", "ID22" => "Asia/Makassar",
+ "ID23" => "Asia/Makassar", "ID24" => "Asia/Jakarta", "ID25" => "Asia/Pontianak",
+ "ID26" => "Asia/Pontianak", "ID30" => "Asia/Jakarta", "ID31" => "Asia/Makassar",
+ "ID33" => "Asia/Jakarta", "KZ01" => "Asia/Almaty", "KZ02" => "Asia/Almaty",
+ "KZ03" => "Asia/Qyzylorda", "KZ04" => "Asia/Aqtobe", "KZ05" => "Asia/Qyzylorda",
+ "KZ06" => "Asia/Aqtau", "KZ07" => "Asia/Oral", "KZ08" => "Asia/Qyzylorda",
+ "KZ09" => "Asia/Aqtau", "KZ10" => "Asia/Qyzylorda", "KZ11" => "Asia/Almaty",
+ "KZ12" => "Asia/Qyzylorda", "KZ13" => "Asia/Aqtobe", "KZ14" => "Asia/Qyzylorda",
+ "KZ15" => "Asia/Almaty", "KZ16" => "Asia/Aqtobe", "KZ17" => "Asia/Almaty",
+ "MX01" => "America/Mexico_City", "MX02" => "America/Tijuana", "MX03" => "America/Hermosillo",
+ "MX04" => "America/Merida", "MX05" => "America/Mexico_City", "MX06" => "America/Chihuahua",
+ "MX07" => "America/Monterrey", "MX08" => "America/Mexico_City", "MX09" => "America/Mexico_City",
+ "MX10" => "America/Mazatlan", "MX11" => "America/Mexico_City", "MX12" => "America/Mexico_City",
+ "MX13" => "America/Mexico_City", "MX14" => "America/Mazatlan", "MX15" => "America/Chihuahua",
+ "MX16" => "America/Mexico_City", "MX17" => "America/Mexico_City", "MX18" => "America/Mazatlan",
+ "MX19" => "America/Monterrey", "MX20" => "America/Mexico_City", "MX21" => "America/Mexico_City",
+ "MX22" => "America/Mexico_City", "MX23" => "America/Cancun", "MX24" => "America/Mexico_City",
+ "MX25" => "America/Mazatlan", "MX26" => "America/Hermosillo", "MX27" => "America/Merida",
+ "MX28" => "America/Monterrey", "MX29" => "America/Mexico_City", "MX30" => "America/Mexico_City",
+ "MX31" => "America/Merida", "MX32" => "America/Monterrey", "MY01" => "Asia/Kuala_Lumpur",
+ "MY02" => "Asia/Kuala_Lumpur", "MY03" => "Asia/Kuala_Lumpur", "MY04" => "Asia/Kuala_Lumpur",
+ "MY05" => "Asia/Kuala_Lumpur", "MY06" => "Asia/Kuala_Lumpur", "MY07" => "Asia/Kuala_Lumpur",
+ "MY08" => "Asia/Kuala_Lumpur", "MY09" => "Asia/Kuala_Lumpur", "MY11" => "Asia/Kuching",
+ "MY12" => "Asia/Kuala_Lumpur", "MY13" => "Asia/Kuala_Lumpur", "MY14" => "Asia/Kuala_Lumpur",
+ "MY15" => "Asia/Kuching", "MY16" => "Asia/Kuching", "NZ85" => "Pacific/Auckland",
+ "NZE7" => "Pacific/Auckland", "NZE8" => "Pacific/Auckland", "NZE9" => "Pacific/Auckland",
+ "NZF1" => "Pacific/Auckland", "NZF2" => "Pacific/Auckland", "NZF3" => "Pacific/Auckland",
+ "NZF4" => "Pacific/Auckland", "NZF5" => "Pacific/Auckland", "NZF7" => "Pacific/Chatham",
+ "NZF8" => "Pacific/Auckland", "NZF9" => "Pacific/Auckland", "NZG1" => "Pacific/Auckland",
+ "NZG2" => "Pacific/Auckland", "NZG3" => "Pacific/Auckland", "PT02" => "Europe/Lisbon",
+ "PT03" => "Europe/Lisbon", "PT04" => "Europe/Lisbon", "PT05" => "Europe/Lisbon",
+ "PT06" => "Europe/Lisbon", "PT07" => "Europe/Lisbon", "PT08" => "Europe/Lisbon",
+ "PT09" => "Europe/Lisbon", "PT10" => "Atlantic/Madeira", "PT11" => "Europe/Lisbon",
+ "PT13" => "Europe/Lisbon", "PT14" => "Europe/Lisbon", "PT16" => "Europe/Lisbon",
+ "PT17" => "Europe/Lisbon", "PT18" => "Europe/Lisbon", "PT19" => "Europe/Lisbon",
+ "PT20" => "Europe/Lisbon", "PT21" => "Europe/Lisbon", "PT22" => "Europe/Lisbon",
+ "RU01" => "Europe/Volgograd", "RU02" => "Asia/Irkutsk", "RU03" => "Asia/Novokuznetsk",
+ "RU04" => "Asia/Novosibirsk", "RU05" => "Asia/Vladivostok", "RU06" => "Europe/Moscow",
+ "RU07" => "Europe/Volgograd", "RU08" => "Europe/Samara", "RU09" => "Europe/Moscow",
+ "RU10" => "Europe/Moscow", "RU11" => "Asia/Irkutsk", "RU13" => "Asia/Yekaterinburg",
+ "RU14" => "Asia/Irkutsk", "RU15" => "Asia/Anadyr", "RU16" => "Europe/Samara",
+ "RU17" => "Europe/Volgograd", "RU18" => "Asia/Krasnoyarsk", "RU20" => "Asia/Irkutsk",
+ "RU21" => "Europe/Moscow", "RU22" => "Europe/Volgograd", "RU23" => "Europe/Kaliningrad",
+ "RU24" => "Europe/Volgograd", "RU25" => "Europe/Moscow", "RU26" => "Asia/Kamchatka",
+ "RU27" => "Europe/Volgograd", "RU28" => "Europe/Moscow", "RU29" => "Asia/Novokuznetsk",
+ "RU30" => "Asia/Vladivostok", "RU31" => "Asia/Krasnoyarsk", "RU32" => "Asia/Omsk",
+ "RU33" => "Asia/Yekaterinburg", "RU34" => "Asia/Yekaterinburg", "RU35" => "Asia/Yekaterinburg",
+ "RU36" => "Asia/Anadyr", "RU37" => "Europe/Moscow", "RU38" => "Europe/Volgograd",
+ "RU39" => "Asia/Krasnoyarsk", "RU40" => "Asia/Yekaterinburg", "RU41" => "Europe/Moscow",
+ "RU42" => "Europe/Moscow", "RU43" => "Europe/Moscow", "RU44" => "Asia/Magadan",
+ "RU45" => "Europe/Samara", "RU46" => "Europe/Samara", "RU47" => "Europe/Moscow",
+ "RU48" => "Europe/Moscow", "RU49" => "Europe/Moscow", "RU50" => "Asia/Yekaterinburg",
+ "RU51" => "Europe/Moscow", "RU52" => "Europe/Moscow", "RU53" => "Asia/Novosibirsk",
+ "RU54" => "Asia/Omsk", "RU55" => "Europe/Samara", "RU56" => "Europe/Moscow",
+ "RU57" => "Europe/Samara", "RU58" => "Asia/Yekaterinburg", "RU59" => "Asia/Vladivostok",
+ "RU60" => "Europe/Kaliningrad", "RU61" => "Europe/Volgograd", "RU62" => "Europe/Moscow",
+ "RU63" => "Asia/Yakutsk", "RU64" => "Asia/Sakhalin", "RU65" => "Europe/Samara",
+ "RU66" => "Europe/Moscow", "RU67" => "Europe/Samara", "RU68" => "Europe/Volgograd",
+ "RU69" => "Europe/Moscow", "RU70" => "Europe/Volgograd", "RU71" => "Asia/Yekaterinburg",
+ "RU72" => "Europe/Moscow", "RU73" => "Europe/Samara", "RU74" => "Asia/Krasnoyarsk",
+ "RU75" => "Asia/Novosibirsk", "RU76" => "Europe/Moscow", "RU77" => "Europe/Moscow",
+ "RU78" => "Asia/Yekaterinburg", "RU79" => "Asia/Irkutsk", "RU80" => "Asia/Yekaterinburg",
+ "RU81" => "Europe/Samara", "RU82" => "Asia/Irkutsk", "RU83" => "Europe/Moscow",
+ "RU84" => "Europe/Volgograd", "RU85" => "Europe/Moscow", "RU86" => "Europe/Moscow",
+ "RU87" => "Asia/Novosibirsk", "RU88" => "Europe/Moscow", "RU89" => "Asia/Vladivostok",
+ "UA01" => "Europe/Kiev", "UA02" => "Europe/Kiev", "UA03" => "Europe/Uzhgorod",
+ "UA04" => "Europe/Zaporozhye", "UA05" => "Europe/Zaporozhye", "UA06" => "Europe/Uzhgorod",
+ "UA07" => "Europe/Zaporozhye", "UA08" => "Europe/Simferopol", "UA09" => "Europe/Kiev",
+ "UA10" => "Europe/Zaporozhye", "UA11" => "Europe/Simferopol", "UA13" => "Europe/Kiev",
+ "UA14" => "Europe/Zaporozhye", "UA15" => "Europe/Uzhgorod", "UA16" => "Europe/Zaporozhye",
+ "UA17" => "Europe/Simferopol", "UA18" => "Europe/Zaporozhye", "UA19" => "Europe/Kiev",
+ "UA20" => "Europe/Simferopol", "UA21" => "Europe/Kiev", "UA22" => "Europe/Uzhgorod",
+ "UA23" => "Europe/Kiev", "UA24" => "Europe/Uzhgorod", "UA25" => "Europe/Uzhgorod",
+ "UA26" => "Europe/Zaporozhye", "UA27" => "Europe/Kiev", "UZ01" => "Asia/Tashkent",
+ "UZ02" => "Asia/Samarkand", "UZ03" => "Asia/Tashkent", "UZ06" => "Asia/Tashkent",
+ "UZ07" => "Asia/Samarkand", "UZ08" => "Asia/Samarkand", "UZ09" => "Asia/Samarkand",
+ "UZ10" => "Asia/Samarkand", "UZ12" => "Asia/Samarkand", "UZ13" => "Asia/Tashkent",
+ "UZ14" => "Asia/Tashkent", "TL" => "Asia/Dili", "PF" => "Pacific/Marquesas"
+ }
+
+ public
+ # Edition enumeration:
+ (GEOIP_COUNTRY_EDITION,
+ GEOIP_CITY_EDITION_REV1,
+ GEOIP_REGION_EDITION_REV1,
+ GEOIP_ISP_EDITION,
+ GEOIP_ORG_EDITION,
+ GEOIP_CITY_EDITION_REV0,
+ GEOIP_REGION_EDITION_REV0,
+ GEOIP_PROXY_EDITION,
+ GEOIP_ASNUM_EDITION,
+ GEOIP_NETSPEED_EDITION,
+ ) = *1..10
+
+ private
+ COUNTRY_BEGIN = 16776960
+ STATE_BEGIN_REV0 = 16700000
+ STATE_BEGIN_REV1 = 16000000
+ STRUCTURE_INFO_MAX_SIZE = 20
+ DATABASE_INFO_MAX_SIZE = 100
+ MAX_ORG_RECORD_LENGTH = 300
+ MAX_ASN_RECORD_LENGTH = 300 # unverified
+ US_OFFSET = 1
+ CANADA_OFFSET = 677
+ WORLD_OFFSET = 1353
+ FIPS_RANGE = 360
+ FULL_RECORD_LENGTH = 50
+
+ STANDARD_RECORD_LENGTH = 3
+ SEGMENT_RECORD_LENGTH = 3
+
+ public
+ attr_reader :databaseType
+
+ # Open the GeoIP database and determine the file format version
+ #
+ # +filename+ is a String holding the path to the GeoIP.dat file
+ # +options+ is an integer holding caching flags (unimplemented)
+ def initialize(filename, flags = 0)
+ @mutex = IO.respond_to?(:pread) ? false : Mutex.new
+ @flags = flags
+ @databaseType = GEOIP_COUNTRY_EDITION
+ @record_length = STANDARD_RECORD_LENGTH
+ @file = File.open(filename, 'rb')
+ @file.seek(-3, IO::SEEK_END)
+ 0.upto(STRUCTURE_INFO_MAX_SIZE-1) { |i|
+ if @file.read(3) == "\xFF\xFF\xFF"
+ @databaseType = @file.respond_to?(:getbyte) ? @file.getbyte : @file.getc
+ @databaseType -= 105 if @databaseType >= 106
+
+ if (@databaseType == GEOIP_REGION_EDITION_REV0)
+ # Region Edition, pre June 2003
+ @databaseSegments = [ STATE_BEGIN_REV0 ]
+ elsif (@databaseType == GEOIP_REGION_EDITION_REV1)
+ # Region Edition, post June 2003
+ @databaseSegments = [ STATE_BEGIN_REV1 ]
+ elsif (@databaseType == GEOIP_CITY_EDITION_REV0 ||
+ @databaseType == GEOIP_CITY_EDITION_REV1 ||
+ @databaseType == GEOIP_ORG_EDITION ||
+ @databaseType == GEOIP_ISP_EDITION ||
+ @databaseType == GEOIP_ASNUM_EDITION)
+ # City/Org Editions have two segments, read offset of second segment
+ @databaseSegments = [ 0 ]
+ sr = @file.read(3).unpack("C*")
+ @databaseSegments[0] += le_to_ui(sr)
+
+ if (@databaseType == GEOIP_ORG_EDITION ||
+ @databaseType == GEOIP_ISP_EDITION)
+ @record_length = 4
+ end
+ end
+ break
+
+ else
+ @file.seek(-4, IO::SEEK_CUR)
+ end
+ }
+ if (@databaseType == GEOIP_COUNTRY_EDITION ||
+ @databaseType == GEOIP_PROXY_EDITION ||
+ @databaseType == GEOIP_NETSPEED_EDITION)
+ @databaseSegments = [ COUNTRY_BEGIN ]
+ end
+ end
+
+ # Search the GeoIP database for the specified host, returning country info
+ #
+ # +hostname+ is a String holding the host's DNS name or numeric IP address.
+ # Return an array of seven elements:
+ # * The host or IP address string as requested
+ # * The IP address string after looking up the host
+ # * The GeoIP country-ID as an integer
+ # * The ISO3166-1 two-character country code
+ # * The ISO3166-2 three-character country code
+ # * The ISO3166 English-language name of the country
+ # * The two-character continent code
+ #
+ def country(hostname)
+ if (@databaseType == GEOIP_CITY_EDITION_REV0 ||
+ @databaseType == GEOIP_CITY_EDITION_REV1)
+ return city(hostname)
+ end
+
+ ip = hostname
+ if ip.kind_of?(String) && ip !~ /^[0-9.]*$/
+ # Lookup IP address, we were given a name
+ ip = IPSocket.getaddress(hostname)
+ ip = '0.0.0.0' if ip == '::1'
+ end
+
+ # Convert numeric IP address to an integer
+ ipnum = iptonum(ip)
+ if (@databaseType != GEOIP_COUNTRY_EDITION &&
+ @databaseType != GEOIP_PROXY_EDITION &&
+ @databaseType != GEOIP_NETSPEED_EDITION)
+ throw "Invalid GeoIP database type, can't look up Country by IP"
+ end
+ code = seek_record(ipnum) - COUNTRY_BEGIN;
+ [ hostname, # Requested hostname
+ ip, # Ip address as dotted quad
+ code, # GeoIP's country code
+ CountryCode[code], # ISO3166-1 code
+ CountryCode3[code], # ISO3166-2 code
+ CountryName[code], # Country name, per IS03166
+ CountryContinent[code] ] # Continent code.
+ end
+
+ # Search the GeoIP database for the specified host, returning city info
+ #
+ # +hostname+ is a String holding the host's DNS name or numeric IP address
+ # Return an array of twelve or fourteen elements:
+ # * All elements from the country query
+ # * The region (state or territory) name
+ # * The city name
+ # * The postal code (zipcode)
+ # * The latitude
+ # * The longitude
+ # * The dma_code and area_code, if available (REV1 City database)
+ # * The timezone name, if known
+ private
+
+ def read_city(pos, hostname = '', ip = '')
+ off = pos + (2*@record_length-1) * @databaseSegments[0]
+ record = atomic_read(FULL_RECORD_LENGTH, off)
+ return nil unless record && record.size == FULL_RECORD_LENGTH
+
+ # The country code is the first byte:
+ code = record[0]
+ code = code.ord if code.respond_to?(:ord)
+ record = record[1..-1]
+ @iter_pos += 1 unless @iter_pos.nil?
+
+ spl = record.split("\x00", 4)
+ # Get the region:
+ region = spl[0]
+ @iter_pos += (region.size + 1) unless @iter_pos.nil?
+
+ # Get the city:
+ city = spl[1]
+ @iter_pos += (city.size + 1) unless @iter_pos.nil?
+
+ # Get the postal code:
+ postal_code = spl[2]
+ @iter_pos += (postal_code.size + 1) unless @iter_pos.nil?
+
+ record = spl[3]
+ # Get the latitude/longitude:
+ if(record && record[0,3]) then
+ latitude = le_to_ui(record[0,3].unpack('C*')) / 10000.0 - 180
+ record = record[3..-1]
+ @iter_pos += 3 unless @iter_pos.nil?
+ else
+ latitude = ''
+ end
+ if(record && record[0,3]) then
+ longitude = le_to_ui(record[0,3].unpack('C*')) / 10000.0 - 180
+ record = record[3..-1]
+ @iter_pos += 3 unless @iter_pos.nil?
+ else
+ longitude = ''
+ end
+
+ us_area_codes = []
+ if (record &&
+ record[0,3] &&
+ @databaseType == GEOIP_CITY_EDITION_REV1 &&
+ CountryCode[code] == "US") # UNTESTED
+ dmaarea_combo = le_to_ui(record[0,3].unpack('C*'))
+ dma_code = dmaarea_combo / 1000;
+ area_code = dmaarea_combo % 1000;
+ us_area_codes = [ dma_code, area_code ]
+ @iter_pos += 3 unless @iter_pos.nil?
+ else
+ us_area_codes = [ nil, nil ] # Ensure that TimeZone is always at the same offset
+ end
+
+ [ hostname, # Requested hostname
+ ip, # Ip address as dotted quad
+ CountryCode[code], # ISO3166-1 code
+ CountryCode3[code], # ISO3166-2 code
+ CountryName[code], # Country name, per IS03166
+ CountryContinent[code], # Continent code.
+ region, # Region name
+ city, # City name
+ postal_code, # Postal code
+ latitude,
+ longitude,
+ ] +
+ us_area_codes +
+ [ TimeZone["#{CountryCode[code]}#{region}"] || TimeZone["#{CountryCode[code]}"] ]
+ end
+
+ public
+
+ # Search the GeoIP database for the specified host, returning city info.
+ #
+ # +hostname+ is a String holding the host's DNS name or numeric IP address.
+ # Return an array of twelve or fourteen elements:
+ # * The host or IP address string as requested
+ # * The IP address string after looking up the host
+ # * The GeoIP country-ID as an integer
+ # * The ISO3166-1 two-character country code
+ # * The ISO3166-2 three-character country code
+ # * The ISO3166 English-language name of the country
+ # * The two-character continent code
+ # * The region name
+ # * The city name
+ # * The postal code
+ # * The latitude
+ # * The longitude
+ # * The USA dma_code and area_code, if available (REV1 City database)
+ #
+ def city(hostname)
+ ip = hostname
+ if ip.kind_of?(String) && ip !~ /^[0-9.]*$/
+ # Lookup IP address, we were given a name
+ ip = IPSocket.getaddress(hostname)
+ ip = '0.0.0.0' if ip == '::1'
+ end
+
+ # Convert numeric IP address to an integer
+ ipnum = iptonum(ip)
+ if (@databaseType != GEOIP_CITY_EDITION_REV0 &&
+ @databaseType != GEOIP_CITY_EDITION_REV1)
+ throw "Invalid GeoIP database type, can't look up City by IP"
+ end
+ pos = seek_record(ipnum);
+ # This next statement was added to MaxMind's C version after it was rewritten in Ruby.
+ # It prevents unassigned IP addresses from returning bogus data. There was concern over
+ # whether the changes to an application's behaviour were always correct, but this has been
+ # tested using an exhaustive search of the top 16 bits of the IP address space. The records
+ # where the change takes effect contained *no* valid data. If you're concerned, email me,
+ # and I'll send you the test program so you can test whatever IP range you think is causing
+ # problems, as I don't care to undertake an exhaustive search of the 32-bit space.
+ return nil if pos == @databaseSegments[0]
+ read_city(pos, hostname, ip)
+ end
+
+ # Search a ISP GeoIP database for the specified host, returning the ISP
+ #
+ # +hostname+ is a String holding the host's DNS name or numeric IP address.
+ # Return the ISP name
+ #
+ def isp(hostname)
+ ip = hostname
+ if ip.kind_of?(String) && ip !~ /^[0-9.]*$/
+ # Lookup IP address, we were given a name
+ ip = IPSocket.getaddress(hostname)
+ ip = '0.0.0.0' if ip == '::1'
+ end
+
+ # Convert numeric IP address to an integer
+ ipnum = iptonum(ip)
+ if @databaseType != GEOIP_ISP_EDITION
+ throw "Invalid GeoIP database type, can't look up Organization/ISP by IP"
+ end
+ pos = seek_record(ipnum);
+ off = pos + (2*@record_length-1) * @databaseSegments[0]
+ record = atomic_read(MAX_ORG_RECORD_LENGTH, off)
+ record = record.sub(/\000.*/n, '')
+ record
+ end
+
+ # Search a ASN GeoIP database for the specified host, returning the AS number + description
+ #
+ # +hostname+ is a String holding the host's DNS name or numeric IP address.
+ # Return the AS number + description
+ #
+ # Source:
+ # http://geolite.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz
+ #
+ def asn(hostname)
+ ip = hostname
+ if ip.kind_of?(String) && ip !~ /^[0-9.]*$/
+ # Lookup IP address, we were given a name
+ ip = IPSocket.getaddress(hostname)
+ ip = '0.0.0.0' if ip == '::1'
+ end
+
+ # Convert numeric IP address to an integer
+ ipnum = iptonum(ip)
+ if (@databaseType != GEOIP_ASNUM_EDITION)
+ throw "Invalid GeoIP database type, can't look up ASN by IP"
+ end
+ pos = seek_record(ipnum);
+ off = pos + (2*@record_length-1) * @databaseSegments[0]
+ record = atomic_read(MAX_ASN_RECORD_LENGTH, off)
+ record = record.sub(/\000.*/n, '')
+
+ if record =~ /^(AS\d+)\s(.*)$/
+ # AS####, Description
+ return [$1, $2]
+ end
+ end
+
+ # Search a ISP GeoIP database for the specified host, returning the organization
+ #
+ # +hostname+ is a String holding the host's DNS name or numeric IP address.
+ # Return the organization associated with it
+ #
+ alias_method(:organization, :isp) # Untested, according to Maxmind docs this should work
+
+ # Iterate through a GeoIP city database
+ def each
+ if (@databaseType != GEOIP_CITY_EDITION_REV0 &&
+ @databaseType != GEOIP_CITY_EDITION_REV1)
+ throw "Invalid GeoIP database type, can't iterate thru non-City database"
+ end
+
+ @iter_pos = @databaseSegments[0] + 1
+ num = 0
+ until((rec = read_city(@iter_pos)).nil?)
+ yield(rec)
+ print "#{num}: #{@iter_pos}\n" if((num += 1) % 1000 == 0)
+ end
+ @iter_pos = nil
+ self
+ end
+
+ private
+
+ def iptonum(ip) # Convert numeric IP address to integer
+ if ip.kind_of?(String) &&
+ ip =~ /^([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)$/
+ ip = be_to_ui(Regexp.last_match().to_a.slice(1..4))
+ end
+ ip
+ end
+
+ def seek_record(ipnum)
+ # Binary search in the file.
+ # Records are pairs of little-endian integers, each of @record_length.
+ offset = 0
+ mask = 0x80000000
+ 31.downto(0) { |depth|
+ off = @record_length * 2 * offset
+ buf = atomic_read(@record_length * 2, off)
+ buf.slice!(0...@record_length) if ((ipnum & mask) != 0)
+ offset = le_to_ui(buf[0...@record_length].unpack("C*"))
+ return offset if (offset >= @databaseSegments[0])
+ mask >>= 1
+ }
+ end
+
+ # Convert a big-endian array of numeric bytes to unsigned int
+ def be_to_ui(s)
+ s.inject(0) { |m, o|
+ (m << 8) + o.to_i
+ }
+ end
+
+ # Same for little-endian
+ def le_to_ui(s)
+ be_to_ui(s.reverse)
+ end
+
+ # reads +length+ bytes from +offset+ as atomically as possible
+ # if IO.pread is available, it'll use that (making it both multithread
+ # and multiprocess-safe). Otherwise we'll use a mutex to synchronize
+ # access (only providing protection against multiple threads, but not
+ # file descriptors shared across multiple processes).
+ def atomic_read(length, offset)
+ if @mutex
+ @mutex.synchronize {
+ @file.seek(offset)
+ @file.read(length)
+ }
+ else
+ IO.pread(@file.fileno, length, offset)
+ end
+ end
+end
+
+if $0 == __FILE__
+ data = '/usr/share/GeoIP/GeoIP.dat'
+ data = ARGV.shift if ARGV[0] =~ /\.dat\Z/
+ g = GeoIP.new data
+
+ req = ([GeoIP::GEOIP_CITY_EDITION_REV1, GeoIP::GEOIP_CITY_EDITION_REV0].include?(g.databaseType)) ? :city : :country
+ ARGV.each { |a|
+ p g.send(req, a)
+ }
+end
+
Added: cdn/trunk/geoip/script/destroy
===================================================================
--- cdn/trunk/geoip/script/destroy (rev 0)
+++ cdn/trunk/geoip/script/destroy 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,14 @@
+#!/usr/bin/env ruby
+APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+
+begin
+ require 'rubigen'
+rescue LoadError
+ require 'rubygems'
+ require 'rubigen'
+end
+require 'rubigen/scripts/destroy'
+
+ARGV.shift if ['--help', '-h'].include?(ARGV[0])
+RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
+RubiGen::Scripts::Destroy.new.run(ARGV)
Added: cdn/trunk/geoip/script/generate
===================================================================
--- cdn/trunk/geoip/script/generate (rev 0)
+++ cdn/trunk/geoip/script/generate 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,14 @@
+#!/usr/bin/env ruby
+APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+
+begin
+ require 'rubigen'
+rescue LoadError
+ require 'rubygems'
+ require 'rubigen'
+end
+require 'rubigen/scripts/generate'
+
+ARGV.shift if ['--help', '-h'].include?(ARGV[0])
+RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
+RubiGen::Scripts::Generate.new.run(ARGV)
Added: cdn/trunk/geoip/script/txt2html
===================================================================
--- cdn/trunk/geoip/script/txt2html (rev 0)
+++ cdn/trunk/geoip/script/txt2html 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,74 @@
+#!/usr/bin/env ruby
+
+require 'rubygems'
+begin
+ require 'newgem'
+rescue LoadError
+ puts "\n\nGenerating the website requires the newgem RubyGem"
+ puts "Install: gem install newgem\n\n"
+ exit(1)
+end
+require 'redcloth'
+require 'syntax/convertors/html'
+require 'erb'
+require File.dirname(__FILE__) + '/../lib/geoip.rb'
+
+version = GeoIP::VERSION
+download = 'http://rubyforge.org/projects/geoip'
+
+class Fixnum
+ def ordinal
+ # teens
+ return 'th' if (10..19).include?(self % 100)
+ # others
+ case self % 10
+ when 1: return 'st'
+ when 2: return 'nd'
+ when 3: return 'rd'
+ else return 'th'
+ end
+ end
+end
+
+class Time
+ def pretty
+ return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
+ end
+end
+
+def convert_syntax(syntax, source)
+ return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
+end
+
+if ARGV.length >= 1
+ src, template = ARGV
+ template ||= File.join(File.dirname(__FILE__), '/../website/template.rhtml')
+
+else
+ puts("Usage: #{File.split($0).last} source.txt [template.rhtml] > output.html")
+ exit!
+end
+
+template = ERB.new(File.open(template).read)
+
+title = nil
+body = nil
+File.open(src) do |fsrc|
+ title_text = fsrc.readline
+ body_text = fsrc.read
+ syntax_items = []
+ body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</\1>!m){
+ ident = syntax_items.length
+ element, syntax, source = $1, $2, $3
+ syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}</#{element}>"
+ "syntax-temp-#{ident}"
+ }
+ title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
+ body = RedCloth.new(body_text).to_html
+ body.gsub!(%r!(?:<pre><code>)?syntax-temp-(\d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
+end
+stat = File.stat(src)
+created = stat.ctime
+modified = stat.mtime
+
+$stdout << template.result(binding)
Added: cdn/trunk/geoip/tasks/website.rake
===================================================================
--- cdn/trunk/geoip/tasks/website.rake (rev 0)
+++ cdn/trunk/geoip/tasks/website.rake 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,17 @@
+desc 'Generate website files'
+task :website_generate => :ruby_env do
+ (Dir['website/**/*.txt'] - Dir['website/version*.txt']).each do |txt|
+ sh %{ #{ENV['RUBY_APP']||'ruby'} script/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} }
+ end
+end
+
+desc 'Upload website files to rubyforge'
+task :website_upload do
+ host = "#{rubyforge_username}@rubyforge.org"
+ remote_dir = "/var/www/gforge-projects/#{PATH}/"
+ local_dir = 'website'
+ sh %{rsync -aCv #{local_dir}/ #{host}:#{remote_dir}}
+end
+
+desc 'Generate and upload website files'
+task :website => [:website_generate, :website_upload, :publish_docs]
Added: cdn/trunk/geoip/test/test_geoip.rb
===================================================================
--- cdn/trunk/geoip/test/test_geoip.rb (rev 0)
+++ cdn/trunk/geoip/test/test_geoip.rb 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,11 @@
+require File.dirname(__FILE__) + '/test_helper.rb'
+
+class TestGeoip < Test::Unit::TestCase
+
+ def setup
+ end
+
+ def test_truth
+ assert true
+ end
+end
Added: cdn/trunk/geoip/test/test_helper.rb
===================================================================
--- cdn/trunk/geoip/test/test_helper.rb (rev 0)
+++ cdn/trunk/geoip/test/test_helper.rb 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,3 @@
+require 'stringio'
+require 'test/unit'
+require File.dirname(__FILE__) + '/../lib/geoip'
Added: cdn/trunk/geoip/website/index.txt
===================================================================
--- cdn/trunk/geoip/website/index.txt (rev 0)
+++ cdn/trunk/geoip/website/index.txt 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,65 @@
+h1. geoip
+
+h2. 'Geographic info for an IP address'
+
+h2. What
+
+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.
+
+h2. Installing
+
+<pre syntax="ruby">sudo gem install geoip</pre>
+
+h2. Prerequisites
+
+You need at least the free GeoIP.dat, for which the last known download
+location is "http://www.maxmind.com/download/geoip/database/GeoIP.dat.gz":http://www.maxmind.com/download/geoip/database/GeoIP.dat.gz
+or the city database "http://www.maxmind.com/app/geolitecity":http://www.maxmind.com/app/geolitecity
+This API requires the file to be decompressed for searching. Other versions
+of this database are available for purchase which contain more detailed
+information, but this information is not returned by this implementation.
+See www.maxmind.com for more information.
+
+h2. Example
+
+ <pre>
+ require 'geoip'
+ GeoIP.new('GeoIP.dat').country("www.netscape.sk")
+ => ["www.netscape.sk", "217.67.16.35", 196, "SK", "SVK", "Slovakia", "EU"]
+
+
+ GeoIP.new('GeoCity.dat').city('github.com')
+ => ["github.com", "207.97.227.239", "US", "USA", "United States", "NA", "CA", "San Francisco", "94110", 37.7484, -122.4156, "America/Los_Angeles", 807, 415]
+
+
+ GeoIP.new('GeoIPASNum.dat').asn("www.fsb.ru")
+ => ["AS8342", "RTComm.RU Autonomous System"]
+ </pre>
+
+h2. Source Repository
+
+The trunk repository is <code>http://github.com/cjheath/geoip</code>
+
+h2. License
+
+I don't normally use the GPL license, but this one is derived
+from Maxmind's code, so I use the license they use.
+
+This version Copyright (C) 2005 Clifford Heath
+Derived from the C version, Copyright (C) 2003 MaxMind LLC
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Added: cdn/trunk/geoip/website/javascripts/rounded_corners_lite.inc.js
===================================================================
--- cdn/trunk/geoip/website/javascripts/rounded_corners_lite.inc.js (rev 0)
+++ cdn/trunk/geoip/website/javascripts/rounded_corners_lite.inc.js 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,285 @@
+
+ /****************************************************************
+ * *
+ * curvyCorners *
+ * ------------ *
+ * *
+ * This script generates rounded corners for your divs. *
+ * *
+ * Version 1.2.9 *
+ * Copyright (c) 2006 Cameron Cooke *
+ * By: Cameron Cooke and Tim Hutchison. *
+ * *
+ * *
+ * Website: http://www.curvycorners.net *
+ * Email: info@xxxxxxxxxxxxxxxxx *
+ * Forum: http://www.curvycorners.net/forum/ *
+ * *
+ * *
+ * This library is free software; you can redistribute *
+ * it and/or modify it under the terms of the GNU *
+ * Lesser General Public License as published by the *
+ * Free Software Foundation; either version 2.1 of the *
+ * License, or (at your option) any later version. *
+ * *
+ * This library is distributed in the hope that it will *
+ * be useful, but WITHOUT ANY WARRANTY; without even the *
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A *
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public *
+ * License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser *
+ * General Public License along with this library; *
+ * Inc., 59 Temple Place, Suite 330, Boston, *
+ * MA 02111-1307 USA *
+ * *
+ ****************************************************************/
+
+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()
+{ 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")
+{ var startIndex = 0; var boxCol = getElementsByClass(arguments[1]);}
+else
+{ var startIndex = 1; var boxCol = arguments;}
+var curvyCornersCol = new Array(); if(arguments[0].validTags)
+var validElements = arguments[0].validTags; else
+var validElements = ["div"]; for(var i = startIndex, j = boxCol.length; i < j; i++)
+{ var currentTag = boxCol[i].tagName.toLowerCase(); if(inArray(validElements, currentTag) !== false)
+{ curvyCornersCol[curvyCornersCol.length] = new curvyObject(arguments[0], boxCol[i]);}
+}
+this.objects = curvyCornersCol; this.applyCornersToAll = function()
+{ for(var x = 0, k = this.objects.length; x < k; x++)
+{ this.objects[x].applyCorners();}
+}
+}
+function curvyObject()
+{ 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)
+this.box.innerHTML = ""; this.applyCorners = function()
+{ for(var t = 0; t < 2; t++)
+{ switch(t)
+{ case 0:
+if(this.settings.tl || this.settings.tr)
+{ 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);}
+break; case 1:
+if(this.settings.bl || this.settings.br)
+{ 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);}
+break;}
+}
+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)
+{ if(i > -1 < 4)
+{ var cc = corners[i]; if(!this.settings[cc])
+{ if(((cc == "tr" || cc == "tl") && this.topContainer != null) || ((cc == "br" || cc == "bl") && this.bottomContainer != null))
+{ var newCorner = document.createElement("DIV"); newCorner.style.position = "relative"; newCorner.style.fontSize = "1px"; newCorner.style.overflow = "hidden"; if(this.backgroundImage == "")
+newCorner.style.backgroundColor = this.boxColour; else
+newCorner.style.backgroundImage = this.backgroundImage; switch(cc)
+{ case "tl":
+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":
+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":
+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":
+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"
+newCorner.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px"; break;}
+}
+}
+else
+{ if(this.masterCorners[this.settings[cc].radius])
+{ var newCorner = this.masterCorners[this.settings[cc].radius].cloneNode(true);}
+else
+{ 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++)
+{ if((intx +1) >= borderRadius)
+var y1 = -1; else
+var y1 = (Math.floor(Math.sqrt(Math.pow(borderRadius, 2) - Math.pow((intx+1), 2))) - 1); if(borderRadius != j)
+{ if((intx) >= borderRadius)
+var y2 = -1; else
+var y2 = Math.ceil(Math.sqrt(Math.pow(borderRadius,2) - Math.pow(intx, 2))); if((intx+1) >= j)
+var y3 = -1; else
+var y3 = (Math.floor(Math.sqrt(Math.pow(j ,2) - Math.pow((intx+1), 2))) - 1);}
+if((intx) >= j)
+var y4 = -1; else
+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)
+{ for(var inty = (y1 + 1); inty < y2; inty++)
+{ if(this.settings.antiAlias)
+{ if(this.backgroundImage != "")
+{ var borderFract = (pixelFraction(intx, inty, borderRadius) * 100); if(borderFract < 30)
+{ this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, 0, this.settings[cc].radius);}
+else
+{ this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, -1, this.settings[cc].radius);}
+}
+else
+{ 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);}
+}
+}
+if(this.settings.antiAlias)
+{ if(y3 >= y2)
+{ if (y2 == -1) y2 = 0; this.drawPixel(intx, y2, this.borderColour, 100, (y3 - y2 + 1), newCorner, 0, 0);}
+}
+else
+{ if(y3 >= y1)
+{ this.drawPixel(intx, (y1 + 1), this.borderColour, 100, (y3 - y1), newCorner, 0, 0);}
+}
+var outsideColour = this.borderColour;}
+else
+{ var outsideColour = this.boxColour; var y3 = y1;}
+if(this.settings.antiAlias)
+{ for(var inty = (y3 + 1); inty < y4; inty++)
+{ this.drawPixel(intx, inty, outsideColour, (pixelFraction(intx, inty , j) * 100), 1, newCorner, ((this.borderWidth > 0)? 0 : -1), this.settings[cc].radius);}
+}
+}
+this.masterCorners[this.settings[cc].radius] = newCorner.cloneNode(true);}
+if(cc != "br")
+{ for(var t = 0, k = newCorner.childNodes.length; t < k; t++)
+{ 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";}
+if(cc == "tr" || cc == "tl"){ pixelBar.style.top = this.settings[cc].radius -pixelBarHeight -pixelBarTop + "px";}
+switch(cc)
+{ case "tr":
+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":
+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":
+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;}
+}
+}
+}
+if(newCorner)
+{ switch(cc)
+{ case "tl":
+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":
+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":
+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":
+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;}
+}
+}
+}
+var radiusDiff = new Array(); radiusDiff["t"] = Math.abs(this.settings.tl.radius - this.settings.tr.radius)
+radiusDiff["b"] = Math.abs(this.settings.bl.radius - this.settings.br.radius); for(z in radiusDiff)
+{ if(z == "t" || z == "b")
+{ if(radiusDiff[z])
+{ 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"
+newFiller.style.position = "absolute"; newFiller.style.fontSize = "1px"; newFiller.style.overflow = "hidden"; newFiller.style.backgroundColor = this.boxColour; switch(smallerCornerType)
+{ case "tl":
+newFiller.style.bottom = "0px"; newFiller.style.left = "0px"; newFiller.style.borderLeft = this.borderString; this.topContainer.appendChild(newFiller); break; case "tr":
+newFiller.style.bottom = "0px"; newFiller.style.right = "0px"; newFiller.style.borderRight = this.borderString; this.topContainer.appendChild(newFiller); break; case "bl":
+newFiller.style.top = "0px"; newFiller.style.left = "0px"; newFiller.style.borderLeft = this.borderString; this.bottomContainer.appendChild(newFiller); break; case "br":
+newFiller.style.top = "0px"; newFiller.style.right = "0px"; newFiller.style.borderRight = this.borderString; this.bottomContainer.appendChild(newFiller); break;}
+}
+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)
+{ case "t":
+if(this.topContainer)
+{ if(this.settings.tl.radius && this.settings.tr.radius)
+{ 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 != "")
+newFillerBar.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px"; this.topContainer.appendChild(newFillerBar);}
+this.box.style.backgroundPosition = "0px -" + (topMaxRadius - this.borderWidth) + "px";}
+break; case "b":
+if(this.bottomContainer)
+{ if(this.settings.bl.radius && this.settings.br.radius)
+{ 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 != "")
+newFillerBar.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (topMaxRadius + this.borderWidth)) + "px"; this.bottomContainer.appendChild(newFillerBar);}
+}
+break;}
+}
+}
+if(this.settings.autoPad == true && this.boxPadding > 0)
+{ 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)
+contentContainer.style.paddingTop = topPadding + "px"; if(botMaxRadius < this.boxPadding)
+contentContainer.style.paddingBottom = botMaxRadius + "px"; contentContainer.style.paddingLeft = this.boxPadding + "px"; contentContainer.style.paddingRight = this.boxPadding + "px"; this.contentDIV = this.box.appendChild(contentContainer);}
+}
+this.drawPixel = function(intx, inty, colour, transAmount, height, newCorner, image, cornerRadius)
+{ 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 != "")
+{ pixel.style.backgroundImage = this.backgroundImage; pixel.style.backgroundPosition = "-" + (this.boxWidth - (cornerRadius - intx) + this.borderWidth) + "px -" + ((this.boxHeight + topMaxRadius + inty) -this.borderWidth) + "px";}
+else
+{ pixel.style.backgroundColor = colour;}
+if (transAmount != 100)
+setOpacity(pixel, transAmount); pixel.style.top = inty + "px"; pixel.style.left = intx + "px"; newCorner.appendChild(pixel);}
+}
+function insertAfter(parent, node, referenceNode)
+{ parent.insertBefore(node, referenceNode.nextSibling);}
+function BlendColour(Col1, Col2, Col1Fraction)
+{ 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);}
+function IntToHex(strNum)
+{ base = strNum / 16; rem = strNum % 16; base = base - (rem / 16); baseS = MakeHex(base); remS = MakeHex(rem); return baseS + '' + remS;}
+function MakeHex(x)
+{ if((x >= 0) && (x <= 9))
+{ return x;}
+else
+{ switch(x)
+{ case 10: return "A"; case 11: return "B"; case 12: return "C"; case 13: return "D"; case 14: return "E"; case 15: return "F";}
+}
+}
+function pixelFraction(x, y, r)
+{ 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)))
+{ whatsides = "Left"; xvalues[point] = 0; yvalues[point] = intersect - y; point = point + 1;}
+var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y+1,2))); if ((intersect >= x) && (intersect < (x+1)))
+{ whatsides = whatsides + "Top"; xvalues[point] = intersect - x; yvalues[point] = 1; point = point + 1;}
+var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x+1,2))); if ((intersect >= y) && (intersect < (y+1)))
+{ whatsides = whatsides + "Right"; xvalues[point] = 1; yvalues[point] = intersect - y; point = point + 1;}
+var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y,2))); if ((intersect >= x) && (intersect < (x+1)))
+{ whatsides = whatsides + "Bottom"; xvalues[point] = intersect - x; yvalues[point] = 0;}
+switch (whatsides)
+{ case "LeftRight":
+pixelfraction = Math.min(yvalues[0],yvalues[1]) + ((Math.max(yvalues[0],yvalues[1]) - Math.min(yvalues[0],yvalues[1]))/2); break; case "TopRight":
+pixelfraction = 1-(((1-xvalues[0])*(1-yvalues[1]))/2); break; case "TopBottom":
+pixelfraction = Math.min(xvalues[0],xvalues[1]) + ((Math.max(xvalues[0],xvalues[1]) - Math.min(xvalues[0],xvalues[1]))/2); break; case "LeftBottom":
+pixelfraction = (yvalues[0]*xvalues[1])/2; break; default:
+pixelfraction = 1;}
+return pixelfraction;}
+function rgb2Hex(rgbColour)
+{ 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);}
+catch(e){ alert("There was an error converting the RGB value to Hexadecimal in function rgb2Hex");}
+return hexColour;}
+function rgb2Array(rgbColour)
+{ var rgbValues = rgbColour.substring(4, rgbColour.indexOf(")")); var rgbArray = rgbValues.split(", "); return rgbArray;}
+function setOpacity(obj, opacity)
+{ opacity = (opacity == 100)?99.999:opacity; if(isSafari && obj.tagName != "IFRAME")
+{ 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 + ")";}
+else if(typeof(obj.style.opacity) != "undefined")
+{ obj.style.opacity = opacity/100;}
+else if(typeof(obj.style.MozOpacity) != "undefined")
+{ obj.style.MozOpacity = opacity/100;}
+else if(typeof(obj.style.filter) != "undefined")
+{ obj.style.filter = "alpha(opacity:" + opacity + ")";}
+else if(typeof(obj.style.KHTMLOpacity) != "undefined")
+{ obj.style.KHTMLOpacity = opacity/100;}
+}
+function inArray(array, value)
+{ for(var i = 0; i < array.length; i++){ if (array[i] === value) return i;}
+return false;}
+function inArrayKey(array, value)
+{ for(key in array){ if(key === value) return true;}
+return false;}
+function addEvent(elm, evType, fn, useCapture) { if (elm.addEventListener) { elm.addEventListener(evType, fn, useCapture); return true;}
+else if (elm.attachEvent) { var r = elm.attachEvent('on' + evType, fn); return r;}
+else { elm['on' + evType] = fn;}
+}
+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");}
+}
+function format_colour(colour)
+{ var returnColour = "#ffffff"; if(colour != "" && colour != "transparent")
+{ if(colour.substr(0, 3) == "rgb")
+{ returnColour = rgb2Hex(colour);}
+else if(colour.length == 4)
+{ 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);}
+else
+{ returnColour = colour;}
+}
+return returnColour;}
+function get_style(obj, property, propertyNS)
+{ try
+{ if(obj.currentStyle)
+{ var returnVal = eval("obj.currentStyle." + property);}
+else
+{ if(isSafari && obj.style.display == "none")
+{ obj.style.display = ""; var wasHidden = true;}
+var returnVal = document.defaultView.getComputedStyle(obj, '').getPropertyValue(propertyNS); if(isSafari && wasHidden)
+{ obj.style.display = "none";}
+}
+}
+catch(e)
+{ }
+return returnVal;}
+function getElementsByClass(searchClass, node, tag)
+{ var classElements = new Array(); if(node == null)
+node = document; if(tag == null)
+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++)
+{ if(pattern.test(els[i].className))
+{ classElements[j] = els[i]; j++;}
+}
+return classElements;}
+function newCurvyError(errorMessage)
+{ return new Error("curvyCorners Error:\n" + errorMessage)
+}
Added: cdn/trunk/geoip/website/stylesheets/screen.css
===================================================================
--- cdn/trunk/geoip/website/stylesheets/screen.css (rev 0)
+++ cdn/trunk/geoip/website/stylesheets/screen.css 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,138 @@
+body {
+ background-color: #E1D1F1;
+ font-family: "Georgia", sans-serif;
+ font-size: 16px;
+ line-height: 1.6em;
+ padding: 1.6em 0 0 0;
+ color: #333;
+}
+h1, h2, h3, h4, h5, h6 {
+ color: #444;
+}
+h1 {
+ font-family: sans-serif;
+ font-weight: normal;
+ font-size: 4em;
+ line-height: 0.8em;
+ letter-spacing: -0.1ex;
+ margin: 5px;
+}
+li {
+ padding: 0;
+ margin: 0;
+ list-style-type: square;
+}
+a {
+ color: #5E5AFF;
+ background-color: #DAC;
+ font-weight: normal;
+ text-decoration: underline;
+}
+blockquote {
+ font-size: 90%;
+ font-style: italic;
+ border-left: 1px solid #111;
+ padding-left: 1em;
+}
+.caps {
+ font-size: 80%;
+}
+
+#main {
+ width: 45em;
+ padding: 0;
+ margin: 0 auto;
+}
+.coda {
+ text-align: right;
+ color: #77f;
+ font-size: smaller;
+}
+
+table {
+ font-size: 90%;
+ line-height: 1.4em;
+ color: #ff8;
+ background-color: #111;
+ padding: 2px 10px 2px 10px;
+ border-style: dashed;
+}
+
+th {
+ color: #fff;
+}
+
+td {
+ padding: 2px 10px 2px 10px;
+}
+
+.success {
+ color: #0CC52B;
+}
+
+.failed {
+ color: #E90A1B;
+}
+
+.unknown {
+ color: #995000;
+}
+pre, code {
+ font-family: monospace;
+ font-size: 90%;
+ line-height: 1.4em;
+ color: #ff8;
+ background-color: #111;
+ padding: 2px 10px 2px 10px;
+}
+.comment { color: #aaa; font-style: italic; }
+.keyword { color: #eff; font-weight: bold; }
+.punct { color: #eee; font-weight: bold; }
+.symbol { color: #0bb; }
+.string { color: #6b4; }
+.ident { color: #ff8; }
+.constant { color: #66f; }
+.regex { color: #ec6; }
+.number { color: #F99; }
+.expr { color: #227; }
+
+#version {
+ float: right;
+ text-align: right;
+ font-family: sans-serif;
+ font-weight: normal;
+ background-color: #B3ABFF;
+ color: #141331;
+ padding: 15px 20px 10px 20px;
+ margin: 0 auto;
+ margin-top: 15px;
+ border: 3px solid #141331;
+}
+
+#version .numbers {
+ display: block;
+ font-size: 4em;
+ line-height: 0.8em;
+ letter-spacing: -0.1ex;
+ margin-bottom: 15px;
+}
+
+#version p {
+ text-decoration: none;
+ color: #141331;
+ background-color: #B3ABFF;
+ margin: 0;
+ padding: 0;
+}
+
+#version a {
+ text-decoration: none;
+ color: #141331;
+ background-color: #B3ABFF;
+}
+
+.clickable {
+ cursor: pointer;
+ cursor: hand;
+}
+
Added: cdn/trunk/geoip/website/template.rhtml
===================================================================
--- cdn/trunk/geoip/website/template.rhtml (rev 0)
+++ cdn/trunk/geoip/website/template.rhtml 2010-09-23 11:25:33 UTC (rev 1082)
@@ -0,0 +1,48 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <link rel="stylesheet" href="stylesheets/screen.css" type="text/css" media="screen" />
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <title>
+ <%= title %>
+ </title>
+ <script src="javascripts/rounded_corners_lite.inc.js" type="text/javascript"></script>
+<style>
+
+</style>
+ <script type="text/javascript">
+ window.onload = function() {
+ settings = {
+ tl: { radius: 10 },
+ tr: { radius: 10 },
+ bl: { radius: 10 },
+ br: { radius: 10 },
+ antiAlias: true,
+ autoPad: true,
+ validTags: ["div"]
+ }
+ var versionBox = new curvyCorners(settings, document.getElementById("version"));
+ versionBox.applyCornersToAll();
+ }
+ </script>
+</head>
+<body>
+<div id="main">
+
+ <h1><%= title %></h1>
+ <div id="version" class="clickable" onclick='document.location = "<%= download %>"; return false'>
+ <p>Get Version</p>
+ <a href="<%= download %>" class="numbers"><%= version %></a>
+ </div>
+ <%= body %>
+ <p class="coda">
+ <a href="cjheath@xxxxxxxxxxxxx">Clifford Heath</a>, <%= modified.pretty %><br>
+ Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
+ </p>
+</div>
+
+<!-- insert site tracking codes here, like Google Urchin -->
+
+</body>
+</html>