Merge branch 'wip-MDL-29332-master-3' of git://github.com/marinaglancy/moodle
authorEloy Lafuente (stronk7) <stronk7@moodle.org>
Mon, 19 Sep 2016 09:51:08 +0000 (11:51 +0200)
committerEloy Lafuente (stronk7) <stronk7@moodle.org>
Mon, 19 Sep 2016 09:51:08 +0000 (11:51 +0200)
147 files changed:
.eslintignore
.stylelintignore
admin/cli/svgtool.php [moved from theme/base/cli/svgtool.php with 91% similarity]
admin/settings/location.php
blocks/rss_client/classes/output/item.php
course/tests/externallib_test.php
iplookup/index.php
iplookup/lib.php
iplookup/tests/geoip_test.php
iplookup/tests/geoplugin_test.php
lang/en/admin.php
lib/classes/component.php
lib/classes/plugin_manager.php
lib/db/upgrade.php
lib/maxmind/GeoIp2/Compat/JsonSerializable.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Database/Reader.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Exception/AddressNotFoundException.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Exception/AuthenticationException.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Exception/GeoIp2Exception.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Exception/HttpException.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Exception/InvalidRequestException.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Exception/OutOfQueriesException.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Model/AbstractModel.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Model/AnonymousIp.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Model/City.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Model/ConnectionType.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Model/Country.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Model/Domain.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Model/Enterprise.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Model/Insights.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Model/Isp.php [new file with mode: 0644]
lib/maxmind/GeoIp2/ProviderInterface.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Record/AbstractPlaceRecord.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Record/AbstractRecord.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Record/City.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Record/Continent.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Record/Country.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Record/Location.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Record/MaxMind.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Record/Postal.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Record/RepresentedCountry.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Record/Subdivision.php [new file with mode: 0644]
lib/maxmind/GeoIp2/Record/Traits.php [new file with mode: 0644]
lib/maxmind/GeoIp2/WebService/Client.php [new file with mode: 0644]
lib/maxmind/MaxMind/Db/Reader.php [new file with mode: 0644]
lib/maxmind/MaxMind/Db/Reader/Decoder.php [new file with mode: 0644]
lib/maxmind/MaxMind/Db/Reader/InvalidDatabaseException.php [new file with mode: 0644]
lib/maxmind/MaxMind/Db/Reader/Metadata.php [new file with mode: 0644]
lib/maxmind/MaxMind/Db/Reader/Util.php [new file with mode: 0644]
lib/maxmind/README_moodle.txt [new file with mode: 0644]
lib/moodlelib.php
lib/outputlib.php
lib/pear/Net/GeoIP.php [deleted file]
lib/pear/Net/GeoIP/DMA.php [deleted file]
lib/pear/Net/GeoIP/Location.php [deleted file]
lib/tests/moodlelib_test.php
lib/tests/user_test.php
lib/thirdpartylibs.xml
lib/upgrade.txt
mod/book/lib.php
theme/base/config.php [deleted file]
theme/base/lang/en/theme_base.php [deleted file]
theme/base/layout/embedded.php [deleted file]
theme/base/layout/frontpage.php [deleted file]
theme/base/layout/general.php [deleted file]
theme/base/layout/report.php [deleted file]
theme/base/pix/favicon.ico [deleted file]
theme/base/pix/fp/add_file.png [deleted file]
theme/base/pix/fp/add_file.svg [deleted file]
theme/base/pix/fp/alias.png [deleted file]
theme/base/pix/fp/alias_sm.png [deleted file]
theme/base/pix/fp/check.png [deleted file]
theme/base/pix/fp/create_folder.png [deleted file]
theme/base/pix/fp/create_folder.svg [deleted file]
theme/base/pix/fp/cross.png [deleted file]
theme/base/pix/fp/dnd_arrow.gif [deleted file]
theme/base/pix/fp/download_all.png [deleted file]
theme/base/pix/fp/download_all.svg [deleted file]
theme/base/pix/fp/help.png [deleted file]
theme/base/pix/fp/help.svg [deleted file]
theme/base/pix/fp/link.png [deleted file]
theme/base/pix/fp/link_sm.png [deleted file]
theme/base/pix/fp/logout.png [deleted file]
theme/base/pix/fp/logout.svg [deleted file]
theme/base/pix/fp/path_folder.png [deleted file]
theme/base/pix/fp/path_folder_rtl.png [deleted file]
theme/base/pix/fp/refresh.png [deleted file]
theme/base/pix/fp/refresh.svg [deleted file]
theme/base/pix/fp/search.png [deleted file]
theme/base/pix/fp/search.svg [deleted file]
theme/base/pix/fp/setting.png [deleted file]
theme/base/pix/fp/setting.svg [deleted file]
theme/base/pix/fp/view_icon_active.png [deleted file]
theme/base/pix/fp/view_icon_active.svg [deleted file]
theme/base/pix/fp/view_list_active.png [deleted file]
theme/base/pix/fp/view_list_active.svg [deleted file]
theme/base/pix/fp/view_tree_active.png [deleted file]
theme/base/pix/fp/view_tree_active.svg [deleted file]
theme/base/pix/horizontal-menu-submenu-indicator.png [deleted file]
theme/base/pix/progress.gif [deleted file]
theme/base/pix/screenshot.png [deleted file]
theme/base/pix/sprite.png [deleted file]
theme/base/pix/vertical-menu-submenu-indicator.png [deleted file]
theme/base/pix/yui2-treeview-sprite-rtl.gif [deleted file]
theme/base/style/admin.css [deleted file]
theme/base/style/autocomplete.css [deleted file]
theme/base/style/blocks.css [deleted file]
theme/base/style/calendar.css [deleted file]
theme/base/style/core.css [deleted file]
theme/base/style/course.css [deleted file]
theme/base/style/dock.css [deleted file]
theme/base/style/editor.css [deleted file]
theme/base/style/filemanager.css [deleted file]
theme/base/style/grade.css [deleted file]
theme/base/style/message.css [deleted file]
theme/base/style/modal.css [deleted file]
theme/base/style/pagelayout.css [deleted file]
theme/base/style/question.css [deleted file]
theme/base/style/search.css [deleted file]
theme/base/style/tabs.css [deleted file]
theme/base/style/templates.css [deleted file]
theme/base/style/user.css [deleted file]
theme/base/templates/core/notification_error.mustache [deleted file]
theme/base/templates/core/notification_info.mustache [deleted file]
theme/base/templates/core/notification_success.mustache [deleted file]
theme/base/templates/core/notification_warning.mustache [deleted file]
theme/base/version.php [deleted file]
theme/canvas/config.php [deleted file]
theme/canvas/lang/en/theme_canvas.php [deleted file]
theme/canvas/layout/embedded.php [deleted file]
theme/canvas/layout/frontpage.php [deleted file]
theme/canvas/layout/general.php [deleted file]
theme/canvas/layout/report.php [deleted file]
theme/canvas/style/admin.css [deleted file]
theme/canvas/style/blocks.css [deleted file]
theme/canvas/style/core.css [deleted file]
theme/canvas/style/course.css [deleted file]
theme/canvas/style/editor.css [deleted file]
theme/canvas/style/mods.css [deleted file]
theme/canvas/style/pagelayout.css [deleted file]
theme/canvas/style/popups.css [deleted file]
theme/canvas/style/tables.css [deleted file]
theme/canvas/style/tabs.css [deleted file]
theme/canvas/style/text.css [deleted file]
theme/canvas/version.php [deleted file]
theme/upgrade.txt
version.php

index 576c8c4..e11f4c5 100644 (file)
@@ -17,7 +17,6 @@ lib/bennu/
 lib/evalmath/
 lib/lessphp/
 lib/phpexcel/
-lib/pear/Net/
 lib/google/
 lib/htmlpurifier/
 lib/jabber/
@@ -49,6 +48,8 @@ lib/amd/src/mustache.js
 lib/graphlib.php
 lib/spout/
 lib/amd/src/chartjs-lazy.js
+lib/maxmind/GeoIp2/
+lib/maxmind/MaxMind/
 mod/assign/feedback/editpdf/fpdi/
 repository/s3/S3.php
 theme/bootstrapbase/less/bootstrap/
index c73d41a..ceeb1a0 100644 (file)
@@ -16,7 +16,6 @@ lib/bennu/
 lib/evalmath/
 lib/lessphp/
 lib/phpexcel/
-lib/pear/Net/
 lib/google/
 lib/htmlpurifier/
 lib/jabber/
@@ -48,6 +47,8 @@ lib/amd/src/mustache.js
 lib/graphlib.php
 lib/spout/
 lib/amd/src/chartjs-lazy.js
+lib/maxmind/GeoIp2/
+lib/maxmind/MaxMind/
 mod/assign/feedback/editpdf/fpdi/
 repository/s3/S3.php
 theme/bootstrapbase/less/bootstrap/
similarity index 91%
rename from theme/base/cli/svgtool.php
rename to admin/cli/svgtool.php
index 47d294e..929a7c9 100644 (file)
@@ -17,7 +17,7 @@
 /**
  * This script implements some useful svg manipulation tricks.
  *
- * @package    theme_base
+ * @package    core_admin
  * @subpackage cli
  * @copyright  2012 Petr Skoda {@link http://skodak.org}
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@@ -25,7 +25,7 @@
 
 define('CLI_SCRIPT', true);
 
-require(__DIR__.'/../../../config.php');
+require(__DIR__.'/../../config.php');
 require_once($CFG->libdir.'/clilib.php');
 
 // Now get cli options.
@@ -45,10 +45,10 @@ if (!file_exists($path)) {
 }
 
 if ($options['ie9fix']) {
-    theme_base_recurse_svgs($path, '', 'theme_base_svgtool_ie9fix', $blacklist);
+    core_admin_recurse_svgs($path, '', 'core_admin_svgtool_ie9fix', $blacklist);
 
 } else if ($options['noaspectratio']) {
-    theme_base_recurse_svgs($path, '', 'theme_base_svgtool_noaspectratio', $blacklist);
+    core_admin_recurse_svgs($path, '', 'core_admin_svgtool_noaspectratio', $blacklist);
 
 } else {
     $help =
@@ -78,7 +78,7 @@ exit(0);
  *
  * @param string $file
  */
-function theme_base_svgtool_ie9fix($file) {
+function core_admin_svgtool_ie9fix($file) {
     global $CFG;
 
     if (strpos($file, $CFG->dirroot.DIRECTORY_SEPARATOR) === 0) {
@@ -115,7 +115,7 @@ function theme_base_svgtool_ie9fix($file) {
  *
  * @param string $file
  */
-function theme_base_svgtool_noaspectratio($file) {
+function core_admin_svgtool_noaspectratio($file) {
     global $CFG;
 
     if (strpos($file, $CFG->dirroot.DIRECTORY_SEPARATOR) === 0) {
@@ -155,7 +155,7 @@ function theme_base_svgtool_noaspectratio($file) {
  * @param string $filecallback
  * @param array $blacklist
  */
-function theme_base_recurse_svgs($base, $sub, $filecallback, $blacklist) {
+function core_admin_recurse_svgs($base, $sub, $filecallback, $blacklist) {
     if (is_dir("$base/$sub")) {
         $items = new DirectoryIterator("$base/$sub");
         foreach ($items as $item) {
@@ -163,7 +163,7 @@ function theme_base_recurse_svgs($base, $sub, $filecallback, $blacklist) {
                 continue;
             }
             $file = $item->getFilename();
-            theme_base_recurse_svgs("$base/$sub", $file, $filecallback, $blacklist);
+            core_admin_recurse_svgs("$base/$sub", $file, $filecallback, $blacklist);
         }
         unset($item);
         unset($items);
index 1868f33..504cbb9 100644 (file)
@@ -10,7 +10,8 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
     $temp->add(new admin_setting_configtext('defaultcity', new lang_string('defaultcity', 'admin'), new lang_string('defaultcity_help', 'admin'), ''));
 
     $temp->add(new admin_setting_heading('iplookup', new lang_string('iplookup', 'admin'), new lang_string('iplookupinfo', 'admin')));
-    $temp->add(new admin_setting_configfile('geoipfile', new lang_string('geoipfile', 'admin'), new lang_string('configgeoipfile', 'admin', $CFG->dataroot.'/geoip/'), $CFG->dataroot.'/geoip/GeoLiteCity.dat'));
+    $temp->add(new admin_setting_configfile('geoip2file', new lang_string('geoipfile', 'admin'),
+        new lang_string('configgeoipfile', 'admin', $CFG->dataroot.'/geoip/'), $CFG->dataroot.'/geoip/GeoLite2-City.mmdb'));
     $temp->add(new admin_setting_configtext('googlemapkey3', new lang_string('googlemapkey3', 'admin'), new lang_string('googlemapkey3_help', 'admin'), '', PARAM_RAW, 60));
 
     $temp->add(new admin_setting_configtext('allcountrycodes', new lang_string('allcountrycodes', 'admin'), new lang_string('configallcountrycodes', 'admin'), '', '/^(?:\w+(?:,\w+)*)?$/'));
index 71a71dc..e988304 100644 (file)
@@ -127,7 +127,7 @@ class item implements \renderable, \templatable {
         $title = $this->title;
         if (!$title) {
             $title = strip_tags($this->description);
-            $title = core_text::substr($title, 0, 20) . '...';
+            $title = \core_text::substr($title, 0, 20) . '...';
         }
 
         // Allow the renderer to format the title and description.
index b7fbe2f..2a49a47 100644 (file)
@@ -67,7 +67,7 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
         $category2->name = 'Root Test Category 2';
         $category2->idnumber = 'rootcattest2';
         $category2->desc = 'Description for root test category 1';
-        $category2->theme = 'base';
+        $category2->theme = 'bootstrapbase';
         $categories = array(
             array('name' => $category1->name, 'parent' => 0),
             array('name' => $category2->name, 'parent' => 0, 'idnumber' => $category2->idnumber,
@@ -395,7 +395,7 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
         $course2['enablecompletion'] = 1;
         $course2['completionnotify'] = 1;
         $course2['lang'] = 'en';
-        $course2['forcetheme'] = 'base';
+        $course2['forcetheme'] = 'bootstrapbase';
         $course3['fullname'] = 'Test course 3';
         $course3['shortname'] = 'Testcourse3';
         $course3['categoryid'] = $category->id;
@@ -1061,7 +1061,7 @@ class core_course_externallib_testcase extends externallib_advanced_testcase {
         $course2['defaultgroupingid'] = 0;
         $course2['enablecompletion'] = 1;
         $course2['lang'] = 'en';
-        $course2['forcetheme'] = 'base';
+        $course2['forcetheme'] = 'bootstrapbase';
         $courses = array($course1, $course2);
 
         $updatedcoursewarnings = core_course_external::update_courses($courses);
index 07981ed..c285ee7 100644 (file)
@@ -33,7 +33,7 @@ if (isguestuser()) {
     throw new require_login_exception('Guests are not allowed here.');
 }
 
-$ip   = optional_param('ip', getremoteaddr(), PARAM_HOST);
+$ip   = optional_param('ip', getremoteaddr(), PARAM_RAW);
 $user = optional_param('user', 0, PARAM_INT);
 
 if (isset($CFG->iplookup)) {
@@ -48,15 +48,11 @@ $PAGE->set_context(context_system::instance());
 $info = array($ip);
 $note = array();
 
-if (!preg_match('/(^\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/', $ip, $match)) {
+if (cleanremoteaddr($ip) === false) {
     print_error('invalidipformat', 'error');
 }
 
-if ($match[1] > 255 or $match[2] > 255 or $match[3] > 255 or $match[4] > 255) {
-    print_error('invalidipformat', 'error');
-}
-
-if ($match[1] == '127' or $match[1] == '10' or ($match[1] == '172' and $match[2] >= '16' and $match[2] <= '31') or ($match[1] == '192' and $match[2] == '168')) {
+if (!ip_is_public($ip)) {
     print_error('iplookupprivate', 'error');
 }
 
index da07be6..4afeb3f 100644 (file)
@@ -36,39 +36,30 @@ function iplookup_find_location($ip) {
 
     $info = array('city'=>null, 'country'=>null, 'longitude'=>null, 'latitude'=>null, 'error'=>null, 'note'=>'',  'title'=>array());
 
-    if (!empty($CFG->geoipfile) and file_exists($CFG->geoipfile)) {
-        require_once('Net/GeoIP.php');
+    if (!empty($CFG->geoip2file) and file_exists($CFG->geoip2file)) {
+        $reader = new GeoIp2\Database\Reader($CFG->geoip2file);
+        $record = $reader->city($ip);
 
-        $geoip = Net_GeoIP::getInstance($CFG->geoipfile, Net_GeoIP::STANDARD);
-        $location = $geoip->lookupLocation($ip);
-        $geoip->close();
-
-        if (empty($location)) {
+        if (empty($record)) {
             $info['error'] = get_string('iplookupfailed', 'error', $ip);
             return $info;
         }
-        if (!empty($location->city)) {
-            $info['city'] = core_text::convert($location->city, 'iso-8859-1', 'utf-8');
-            $info['title'][] = $info['city'];
-        }
 
-        if (!empty($location->countryCode)) {
-            $countries = get_string_manager()->get_list_of_countries(true);
-            if (isset($countries[$location->countryCode])) {
-                // prefer our localized country names
-                $info['country'] = $countries[$location->countryCode];
-            } else {
-                $info['country'] = $location->countryName;
-            }
-            $info['title'][] = $info['country'];
-
-        } else if (!empty($location->countryName)) {
-            $info['country'] = $location->countryName;
-            $info['title'][] = $info['country'];
+        $info['city'] = core_text::convert($record->city->name, 'iso-8859-1', 'utf-8');
+        $info['title'][] = $info['city'];
+
+        $countrycode = $record->country->isoCode;
+        $countries = get_string_manager()->get_list_of_countries(true);
+        if (isset($countries[$countrycode])) {
+            // Prefer our localized country names.
+            $info['country'] = $countries[$countrycode];
+        } else {
+            $info['country'] = $record->country->names['en'];
         }
+        $info['title'][] = $info['country'];
 
-        $info['longitude'] = $location->longitude;
-        $info['latitude']  = $location->latitude;
+        $info['longitude'] = $record->location->longitude;
+        $info['latitude']  = $record->location->latitude;
         $info['note'] = get_string('iplookupmaxmindnote', 'admin');
 
         return $info;
@@ -76,6 +67,12 @@ function iplookup_find_location($ip) {
     } else {
         require_once($CFG->libdir.'/filelib.php');
 
+        if (strpos($ip, ':') !== false) {
+            // IPv6 is not supported by geoplugin.net.
+            $info['error'] = get_string('invalidipformat', 'error');
+            return $info;
+        }
+
         $ipdata = download_file_content('http://www.geoplugin.net/json.gp?ip='.$ip);
         if ($ipdata) {
             $ipdata = preg_replace('/^geoPlugin\((.*)\)\s*$/s', '$1', $ipdata);
index 3c21394..2143bc0 100644 (file)
@@ -31,20 +31,20 @@ defined('MOODLE_INTERNAL') || die();
  */
 class core_iplookup_geoip_testcase extends advanced_testcase {
 
-    public function test_geoip() {
+    public function setUp() {
         global $CFG;
         require_once("$CFG->libdir/filelib.php");
         require_once("$CFG->dirroot/iplookup/lib.php");
 
         if (!PHPUNIT_LONGTEST) {
             // this may take a long time
-            return;
+            $this->markTestSkipped('PHPUNIT_LONGTEST is not defined');
         }
 
         $this->resetAfterTest();
 
         // let's store the file somewhere
-        $gzfile = "$CFG->dataroot/phpunit/geoip/GeoLiteCity.dat.gz";
+        $gzfile = "$CFG->dataroot/phpunit/geoip/GeoLite2-City.mmdb.gz";
         check_dir_exists(dirname($gzfile));
         if (file_exists($gzfile) and (filemtime($gzfile) < time() - 60*60*24*30)) {
             // delete file if older than 1 month
@@ -52,35 +52,60 @@ class core_iplookup_geoip_testcase extends advanced_testcase {
         }
 
         if (!file_exists($gzfile)) {
-            download_file_content('http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz', null, null, false, 300, 20, false, $gzfile);
+            download_file_content('http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz',
+                null, null, false, 300, 20, false, $gzfile);
         }
 
         $this->assertTrue(file_exists($gzfile));
 
-        $zd = gzopen($gzfile, "r");
-        $contents = gzread($zd, 50000000);
-        gzclose($zd);
+        $geoipfile = str_replace('.gz', '', $gzfile);
 
-        $geoipfile = "$CFG->dataroot/geoip/GeoLiteCity.dat";
-        check_dir_exists(dirname($geoipfile));
-        $fp = fopen($geoipfile, 'w');
-        fwrite($fp, $contents);
-        fclose($fp);
+        // Open our files (in binary mode).
+        $file = gzopen($gzfile, 'rb');
+        $geoipfilebuf = fopen($geoipfile, 'wb');
+
+        // Keep repeating until the end of the input file.
+        while (!gzeof($file)) {
+            // Read buffer-size bytes.
+            // Both fwrite and gzread and binary-safe.
+            fwrite($geoipfilebuf, gzread($file, 4096));
+        }
+
+        // Files are done, close files.
+        fclose($geoipfilebuf);
+        gzclose($file);
 
         $this->assertTrue(file_exists($geoipfile));
 
-        $CFG->geoipfile = $geoipfile;
+        $CFG->geoip2file = $geoipfile;
+    }
+
+    public function test_ipv4() {
+
+        $result = iplookup_find_location('131.111.150.25');
+
+        $this->assertEquals('array', gettype($result));
+        $this->assertEquals('Cambridge', $result['city']);
+        $this->assertEquals(0.1249, $result['longitude'], '', 0.001);
+        $this->assertEquals(52.191000000000003, $result['latitude'], '', 0.001);
+        $this->assertNull($result['error']);
+        $this->assertEquals('array', gettype($result['title']));
+        $this->assertEquals('Cambridge', $result['title'][0]);
+        $this->assertEquals('United Kingdom', $result['title'][1]);
+    }
+
+    public function test_ipv6() {
 
-        $result = iplookup_find_location('147.230.16.1');
+        $result = iplookup_find_location('2a01:8900:2:3:8c6c:c0db:3d33:9ce6');
 
         $this->assertEquals('array', gettype($result));
-        $this->assertEquals('Liberec', $result['city']);
-        $this->assertEquals(15.0653, $result['longitude'], '', 0.001);
-        $this->assertEquals(50.7639, $result['latitude'], '', 0.001);
+        $this->assertEquals('Lancaster', $result['city']);
+        $this->assertEquals(-2.79970, $result['longitude'], '', 0.001);
+        $this->assertEquals(54.04650, $result['latitude'], '', 0.001);
         $this->assertNull($result['error']);
         $this->assertEquals('array', gettype($result['title']));
-        $this->assertEquals('Liberec', $result['title'][0]);
-        $this->assertEquals('Czech Republic', $result['title'][1]);
+        $this->assertEquals('Lancaster', $result['title'][0]);
+        $this->assertEquals('United Kingdom', $result['title'][1]);
     }
 }
 
index bf54697..8c94273 100644 (file)
@@ -31,30 +31,39 @@ defined('MOODLE_INTERNAL') || die();
  */
 class core_iplookup_geoplugin_testcase extends advanced_testcase {
 
-    public function test_geoip() {
+    public function setUp() {
         global $CFG;
         require_once("$CFG->libdir/filelib.php");
         require_once("$CFG->dirroot/iplookup/lib.php");
 
         if (!PHPUNIT_LONGTEST) {
             // we do not want to DDOS their server, right?
-            return;
+            $this->markTestSkipped('PHPUNIT_LONGTEST is not defined');
         }
 
         $this->resetAfterTest();
 
         $CFG->geoipfile = '';
+    }
 
-        $result = iplookup_find_location('147.230.16.1');
+    public function test_geoip_ipv4() {
+        $result = iplookup_find_location('131.111.150.25');
 
         $this->assertEquals('array', gettype($result));
-        $this->assertEquals('Liberec', $result['city']);
-        $this->assertEquals(15.0653, $result['longitude'], '', 0.001);
-        $this->assertEquals(50.7639, $result['latitude'], '', 0.001);
+        $this->assertEquals('Cambridge', $result['city']);
+        $this->assertEquals(0.1167, $result['longitude'], '', 0.001);
+        $this->assertEquals(52.200000000000003, $result['latitude'], '', 0.001);
         $this->assertNull($result['error']);
         $this->assertEquals('array', gettype($result['title']));
-        $this->assertEquals('Liberec', $result['title'][0]);
-        $this->assertEquals('Czech Republic', $result['title'][1]);
+        $this->assertEquals('Cambridge', $result['title'][0]);
+        $this->assertEquals('United Kingdom', $result['title'][1]);
+    }
+
+    public function test_geoip_ipv6() {
+        $result = iplookup_find_location('2a01:8900:2:3:8c6c:c0db:3d33:9ce6');
+
+        $this->assertNotNull($result['error']);
+        $this->assertEquals($result['error'], get_string('invalidipformat', 'error'));
     }
 }
 
index 52f555b..e3fd072 100644 (file)
@@ -230,7 +230,7 @@ $string['configfrontpageloggedin'] = 'The items selected above will be displayed
 $string['configfullnamedisplay'] = 'This defines how names are shown when they are displayed in full. The default value, "language", leaves it to the string "fullnamedisplay" in the current language pack to decide. Some languages have different name display conventions.
 
 For most mono-lingual sites the most efficient setting is "firstname lastname", but you may choose to hide surnames altogether. Placeholders that can be used are: firstname, lastname, firstnamephonetic, lastnamephonetic, middlename, and alternatename.';
-$string['configgeoipfile'] = 'Location of GeoIP City binary data file. This file is not part of Moodle distribution and must be obtained separately from <a href="http://www.maxmind.com/">MaxMind</a>. You can either buy a commercial version or use the free version. Simply download <a href="http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz" >http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz</a> and extract it into "{$a}" directory on your server.';
+$string['configgeoipfile'] = 'Location of GeoLite2 City binary data file. This file is not part of Moodle distribution and must be obtained separately from <a href="http://www.maxmind.com/">MaxMind</a>. You can either buy a commercial version or use the free version. Simply download <a href="http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz" >http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz</a> and extract it into "{$a}" directory on your server.';
 $string['configgetremoteaddrconf'] = 'If your server is behind a reverse proxy, you can use this setting to specify which HTTP headers can be trusted to contain the remote IP address. The headers are read in order, using the first one that is available.';
 $string['configgradebookroles'] = 'This setting allows you to control who appears on the gradebook.  Users need to have at least one of these roles in a course to be shown in the gradebook for that course.';
 $string['configgradeexport'] = 'Choose which gradebook export formats are your primary methods for exporting grades.  Chosen plugins will then set and use a "last exported" field for every grade.  For example, this might result in exported records being identified as being "new" or "updated".  If you are not sure about this then leave everything unchecked.';
@@ -540,7 +540,7 @@ $string['fullnamedisplay'] = 'Full name format';
 $string['fullnamedisplayprivate'] = 'Full name format - private';
 $string['gdrequired'] = 'The GD extension is now required by Moodle for image conversion.';
 $string['generalsettings'] = 'General settings';
-$string['geoipfile'] = 'GeoIP city data file';
+$string['geoipfile'] = 'GeoLite2 City MaxMind DB';
 $string['getremoteaddrconf'] = 'Logged IP address source';
 $string['globalsearch'] = 'Global search';
 $string['globalsearchmanage'] = 'Manage global search';
@@ -598,9 +598,9 @@ $string['ipblockersyntax'] = 'Put every entry on one line. Valid entries are eit
 $string['iplookup'] = 'IP address lookup';
 $string['iplookupgeoplugin'] = '<a href="http://www.geoplugin.com">geoPlugin</a> service is currently being used to look up geographical information. For more accurate results we recommend installing a local copy of the MaxMind GeoLite database.';
 $string['iplookupinfo'] = 'By default Moodle uses the free online NetGeo (The Internet Geographic Database) server to lookup location of IP addresses, unfortunately this database is not maintained anymore and may return <em>wildly incorrect</em> data.
-It is recommended to install local copy of free GeoLite City database from MaxMind.<br />
+It is recommended to install local copy of free GeoLite2 City database from MaxMind.<br />
 IP address location is displayed on simple map or using Google Maps. Please note that you need to have a Google account and apply for free Google Maps API key to enable interactive maps.';
-$string['iplookupmaxmindnote'] = 'This product includes GeoLite data created by MaxMind, available from <a href="http://www.maxmind.com/">http://www.maxmind.com/</a>.';
+$string['iplookupmaxmindnote'] = 'This product includes GeoLite2 data created by MaxMind, available from <a href="http://www.maxmind.com">http://www.maxmind.com</a>.';
 $string['keeptagnamecase'] = 'Keep tag name casing';
 $string['lang'] = 'Default language';
 $string['langcache'] = 'Cache language menu';
index c49ed69..6544ab4 100644 (file)
@@ -73,6 +73,8 @@ class core_component {
     );
     /** @var array associative array of PRS-4 namespaces and corresponding paths. */
     protected static $psr4namespaces = array(
+        'MaxMind' => 'lib/maxmind/MaxMind',
+        'GeoIp2' => 'lib/maxmind/GeoIP2',
     );
 
     /**
index 559a99a..53e8ec1 100644 (file)
@@ -1664,9 +1664,9 @@ class core_plugin_manager {
             'repository' => array('alfresco'),
             'tinymce' => array('dragmath'),
             'tool' => array('bloglevelupgrade', 'qeupgradehelper', 'timezoneimport'),
-            'theme' => array('mymobile', 'afterburner', 'anomaly', 'arialist', 'binarius', 'boxxie', 'brick', 'formal_white',
-                'formfactor', 'fusion', 'leatherbound', 'magazine', 'nimble', 'nonzero', 'overlay', 'serenity', 'sky_high',
-                'splash', 'standard', 'standardold'),
+            'theme' => array('afterburner', 'anomaly', 'arialist', 'base', 'binarius', 'boxxie', 'brick', 'canvas',
+                'formal_white', 'formfactor', 'fusion', 'leatherbound', 'magazine', 'mymobile', 'nimble', 'nonzero',
+                'overlay', 'serenity', 'sky_high', 'splash', 'standard', 'standardold'),
             'webservice' => array('amf'),
         );
 
@@ -1900,7 +1900,7 @@ class core_plugin_manager {
             ),
 
             'theme' => array(
-                'base', 'bootstrapbase', 'canvas', 'clean', 'more'
+                'bootstrapbase', 'clean', 'more'
             ),
 
             'tool' => array(
index 557f93c..469b6ab 100644 (file)
@@ -2177,7 +2177,53 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2016082200.00);
     }
 
-    if ($oldversion < 2016091501.00) {
+    if ($oldversion < 2016091900.00) {
+
+        // Removing the themes from core.
+        $themes = array('base', 'canvas');
+
+        foreach ($themes as $key => $theme) {
+            if (check_dir_exists($CFG->dirroot . '/theme/' . $theme, false)) {
+                // Ignore the themes that have been re-downloaded.
+                unset($themes[$key]);
+            }
+        }
+
+        if (!empty($themes)) {
+
+            list($insql, $inparams) = $DB->get_in_or_equal($themes, SQL_PARAMS_NAMED);
+
+            // Replace the theme usage.
+            $DB->set_field_select('course', 'theme', 'clean', "theme $insql", $inparams);
+            $DB->set_field_select('course_categories', 'theme', 'clean', "theme $insql", $inparams);
+            $DB->set_field_select('user', 'theme', 'clean', "theme $insql", $inparams);
+            $DB->set_field_select('mnet_host', 'theme', 'clean', "theme $insql", $inparams);
+
+            // Replace the theme configs.
+            if (in_array(get_config('core', 'theme'), $themes)) {
+                set_config('theme', 'clean');
+            }
+            if (in_array(get_config('core', 'thememobile'), $themes)) {
+                set_config('thememobile', 'clean');
+            }
+            if (in_array(get_config('core', 'themelegacy'), $themes)) {
+                set_config('themelegacy', 'clean');
+            }
+            if (in_array(get_config('core', 'themetablet'), $themes)) {
+                set_config('themetablet', 'clean');
+            }
+
+            // Hacky emulation of plugin uninstallation.
+            foreach ($themes as $theme) {
+                unset_all_config_for_plugin('theme_' . $theme);
+            }
+        }
+
+        // Main savepoint reached.
+        upgrade_main_savepoint(true, 2016091900.00);
+    }
+
+    if ($oldversion < 2016091900.02) {
 
         // Define index attemptstepid-name (unique) to be dropped from question_attempt_step_data.
         $table = new xmldb_table('question_attempt_step_data');
@@ -2189,7 +2235,7 @@ function xmldb_main_upgrade($oldversion) {
         }
 
         // Main savepoint reached.
-        upgrade_main_savepoint(true, 2016091501.00);
+        upgrade_main_savepoint(true, 2016091900.02);
     }
 
     return true;
diff --git a/lib/maxmind/GeoIp2/Compat/JsonSerializable.php b/lib/maxmind/GeoIp2/Compat/JsonSerializable.php
new file mode 100644 (file)
index 0000000..4846ce7
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+
+namespace GeoIp2\Compat;
+
+// @codingStandardsIgnoreFile
+
+/**
+  * This interface exists to provide backwards compatibility with PHP 5.3
+  *
+  * This should _not_ be used by any third-party code.
+  *
+  * @ignore
+  */
+if (interface_exists('JsonSerializable')) {
+    interface JsonSerializable extends \JsonSerializable
+    {
+    }
+} else {
+    interface JsonSerializable
+    {
+        /**
+         * Returns data that can be serialized by json_encode
+         * @ignore
+         */
+        public function jsonSerialize();
+    }
+}
diff --git a/lib/maxmind/GeoIp2/Database/Reader.php b/lib/maxmind/GeoIp2/Database/Reader.php
new file mode 100644 (file)
index 0000000..b19b5f1
--- /dev/null
@@ -0,0 +1,246 @@
+<?php
+
+namespace GeoIp2\Database;
+
+use GeoIp2\Exception\AddressNotFoundException;
+use GeoIp2\ProviderInterface;
+use MaxMind\Db\Reader as DbReader;
+
+/**
+ * Instances of this class provide a reader for the GeoIP2 database format.
+ * IP addresses can be looked up using the database specific methods.
+ *
+ * ## Usage ##
+ *
+ * The basic API for this class is the same for every database. First, you
+ * create a reader object, specifying a file name. You then call the method
+ * corresponding to the specific database, passing it the IP address you want
+ * to look up.
+ *
+ * If the request succeeds, the method call will return a model class for
+ * the method you called. This model in turn contains multiple record classes,
+ * each of which represents part of the data returned by the database. If
+ * the database does not contain the requested information, the attributes
+ * on the record class will have a `null` value.
+ *
+ * If the address is not in the database, an
+ * {@link \GeoIp2\Exception\AddressNotFoundException} exception will be
+ * thrown. If an invalid IP address is passed to one of the methods, a
+ * SPL {@link \InvalidArgumentException} will be thrown. If the database is
+ * corrupt or invalid, a {@link \MaxMind\Db\Reader\InvalidDatabaseException}
+ * will be thrown.
+ *
+ */
+class Reader implements ProviderInterface
+{
+    private $dbReader;
+    private $locales;
+
+    /**
+     * Constructor.
+     *
+     * @param string $filename The path to the GeoIP2 database file.
+     * @param array $locales  List of locale codes to use in name property
+     * from most preferred to least preferred.
+     * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
+     *          is corrupt or invalid
+     */
+    public function __construct(
+        $filename,
+        $locales = array('en')
+    ) {
+        $this->dbReader = new DbReader($filename);
+        $this->locales = $locales;
+    }
+
+    /**
+     * This method returns a GeoIP2 City model.
+     *
+     * @param string $ipAddress IPv4 or IPv6 address as a string.
+     *
+     * @return \GeoIp2\Model\City
+     *
+     * @throws \GeoIp2\Exception\AddressNotFoundException if the address is
+     *         not in the database.
+     * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
+     *         is corrupt or invalid
+     */
+    public function city($ipAddress)
+    {
+        return $this->modelFor('City', 'City', $ipAddress);
+    }
+
+    /**
+     * This method returns a GeoIP2 Country model.
+     *
+     * @param string $ipAddress IPv4 or IPv6 address as a string.
+     *
+     * @return \GeoIp2\Model\Country
+     *
+     * @throws \GeoIp2\Exception\AddressNotFoundException if the address is
+     *         not in the database.
+     * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
+     *         is corrupt or invalid
+     */
+    public function country($ipAddress)
+    {
+        return $this->modelFor('Country', 'Country', $ipAddress);
+    }
+
+    /**
+     * This method returns a GeoIP2 Anonymous IP model.
+     *
+     * @param string $ipAddress IPv4 or IPv6 address as a string.
+     *
+     * @return \GeoIp2\Model\AnonymousIp
+     *
+     * @throws \GeoIp2\Exception\AddressNotFoundException if the address is
+     *         not in the database.
+     * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
+     *         is corrupt or invalid
+     */
+    public function anonymousIp($ipAddress)
+    {
+        return $this->flatModelFor(
+            'AnonymousIp',
+            'GeoIP2-Anonymous-IP',
+            $ipAddress
+        );
+    }
+
+    /**
+     * This method returns a GeoIP2 Connection Type model.
+     *
+     * @param string $ipAddress IPv4 or IPv6 address as a string.
+     *
+     * @return \GeoIp2\Model\ConnectionType
+     *
+     * @throws \GeoIp2\Exception\AddressNotFoundException if the address is
+     *         not in the database.
+     * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
+     *         is corrupt or invalid
+     */
+    public function connectionType($ipAddress)
+    {
+        return $this->flatModelFor(
+            'ConnectionType',
+            'GeoIP2-Connection-Type',
+            $ipAddress
+        );
+    }
+
+    /**
+     * This method returns a GeoIP2 Domain model.
+     *
+     * @param string $ipAddress IPv4 or IPv6 address as a string.
+     *
+     * @return \GeoIp2\Model\Domain
+     *
+     * @throws \GeoIp2\Exception\AddressNotFoundException if the address is
+     *         not in the database.
+     * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
+     *         is corrupt or invalid
+     */
+    public function domain($ipAddress)
+    {
+        return $this->flatModelFor(
+            'Domain',
+            'GeoIP2-Domain',
+            $ipAddress
+        );
+    }
+
+    /**
+     * This method returns a GeoIP2 Enterprise model.
+     *
+     * @param string $ipAddress IPv4 or IPv6 address as a string.
+     *
+     * @return \GeoIp2\Model\Enterprise
+     *
+     * @throws \GeoIp2\Exception\AddressNotFoundException if the address is
+     *         not in the database.
+     * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
+     *         is corrupt or invalid
+     */
+    public function enterprise($ipAddress)
+    {
+        return $this->modelFor('Enterprise', 'Enterprise', $ipAddress);
+    }
+
+    /**
+     * This method returns a GeoIP2 ISP model.
+     *
+     * @param string $ipAddress IPv4 or IPv6 address as a string.
+     *
+     * @return \GeoIp2\Model\Isp
+     *
+     * @throws \GeoIp2\Exception\AddressNotFoundException if the address is
+     *         not in the database.
+     * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
+     *         is corrupt or invalid
+     */
+    public function isp($ipAddress)
+    {
+        return $this->flatModelFor(
+            'Isp',
+            'GeoIP2-ISP',
+            $ipAddress
+        );
+    }
+
+    private function modelFor($class, $type, $ipAddress)
+    {
+        $record = $this->getRecord($class, $type, $ipAddress);
+
+        $record['traits']['ip_address'] = $ipAddress;
+        $class = "GeoIp2\\Model\\" . $class;
+
+        return new $class($record, $this->locales);
+    }
+
+    private function flatModelFor($class, $type, $ipAddress)
+    {
+        $record = $this->getRecord($class, $type, $ipAddress);
+
+        $record['ip_address'] = $ipAddress;
+        $class = "GeoIp2\\Model\\" . $class;
+
+        return new $class($record);
+    }
+
+    private function getRecord($class, $type, $ipAddress)
+    {
+        if (strpos($this->metadata()->databaseType, $type) === false) {
+            $method = lcfirst($class);
+            throw new \BadMethodCallException(
+                "The $method method cannot be used to open a "
+                . $this->metadata()->databaseType . " database"
+            );
+        }
+        $record = $this->dbReader->get($ipAddress);
+        if ($record === null) {
+            throw new AddressNotFoundException(
+                "The address $ipAddress is not in the database."
+            );
+        }
+        return $record;
+    }
+
+    /**
+     * @throws \InvalidArgumentException if arguments are passed to the method.
+     * @throws \BadMethodCallException if the database has been closed.
+     * @return \MaxMind\Db\Reader\Metadata object for the database.
+     */
+    public function metadata()
+    {
+        return $this->dbReader->metadata();
+    }
+
+    /**
+     * Closes the GeoIP2 database and returns the resources to the system.
+     */
+    public function close()
+    {
+        $this->dbReader->close();
+    }
+}
diff --git a/lib/maxmind/GeoIp2/Exception/AddressNotFoundException.php b/lib/maxmind/GeoIp2/Exception/AddressNotFoundException.php
new file mode 100644 (file)
index 0000000..d548338
--- /dev/null
@@ -0,0 +1,10 @@
+<?php
+
+namespace GeoIp2\Exception;
+
+/**
+ * This class represents a generic error.
+ */
+class AddressNotFoundException extends GeoIp2Exception
+{
+}
diff --git a/lib/maxmind/GeoIp2/Exception/AuthenticationException.php b/lib/maxmind/GeoIp2/Exception/AuthenticationException.php
new file mode 100644 (file)
index 0000000..2a8b592
--- /dev/null
@@ -0,0 +1,10 @@
+<?php
+
+namespace GeoIp2\Exception;
+
+/**
+ * This class represents a generic error.
+ */
+class AuthenticationException extends GeoIp2Exception
+{
+}
diff --git a/lib/maxmind/GeoIp2/Exception/GeoIp2Exception.php b/lib/maxmind/GeoIp2/Exception/GeoIp2Exception.php
new file mode 100644 (file)
index 0000000..7c4d745
--- /dev/null
@@ -0,0 +1,10 @@
+<?php
+
+namespace GeoIp2\Exception;
+
+/**
+ * This class represents a generic error.
+ */
+class GeoIp2Exception extends \Exception
+{
+}
diff --git a/lib/maxmind/GeoIp2/Exception/HttpException.php b/lib/maxmind/GeoIp2/Exception/HttpException.php
new file mode 100644 (file)
index 0000000..931fd46
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+
+namespace GeoIp2\Exception;
+
+/**
+ *  This class represents an HTTP transport error.
+ */
+
+class HttpException extends GeoIp2Exception
+{
+    /**
+     * The URI queried
+     */
+    public $uri;
+
+    public function __construct(
+        $message,
+        $httpStatus,
+        $uri,
+        \Exception $previous = null
+    ) {
+        $this->uri = $uri;
+        parent::__construct($message, $httpStatus, $previous);
+    }
+}
diff --git a/lib/maxmind/GeoIp2/Exception/InvalidRequestException.php b/lib/maxmind/GeoIp2/Exception/InvalidRequestException.php
new file mode 100644 (file)
index 0000000..6712d73
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+
+namespace GeoIp2\Exception;
+
+/**
+ * This class represents an error returned by MaxMind's GeoIP2
+ * web service.
+ */
+class InvalidRequestException extends HttpException
+{
+    /**
+     * The code returned by the MaxMind web service
+     */
+    public $error;
+
+    public function __construct(
+        $message,
+        $error,
+        $httpStatus,
+        $uri,
+        \Exception $previous = null
+    ) {
+        $this->error = $error;
+        parent::__construct($message, $httpStatus, $uri, $previous);
+    }
+}
diff --git a/lib/maxmind/GeoIp2/Exception/OutOfQueriesException.php b/lib/maxmind/GeoIp2/Exception/OutOfQueriesException.php
new file mode 100644 (file)
index 0000000..87a6ade
--- /dev/null
@@ -0,0 +1,10 @@
+<?php
+
+namespace GeoIp2\Exception;
+
+/**
+ * This class represents a generic error.
+ */
+class OutOfQueriesException extends GeoIp2Exception
+{
+}
diff --git a/lib/maxmind/GeoIp2/Model/AbstractModel.php b/lib/maxmind/GeoIp2/Model/AbstractModel.php
new file mode 100644 (file)
index 0000000..c242666
--- /dev/null
@@ -0,0 +1,62 @@
+<?php
+
+namespace GeoIp2\Model;
+
+use GeoIp2\Compat\JsonSerializable;
+
+/**
+ * @ignore
+ */
+abstract class AbstractModel implements JsonSerializable
+{
+    protected $raw;
+
+    /**
+     * @ignore
+     */
+    public function __construct($raw)
+    {
+        $this->raw = $raw;
+    }
+
+    /**
+     * @ignore
+     */
+    protected function get($field)
+    {
+        if (isset($this->raw[$field])) {
+            return $this->raw[$field];
+        } else {
+            if (preg_match('/^is_/', $field)) {
+                return false;
+            } else {
+                return null;
+            }
+        }
+    }
+
+    /**
+     * @ignore
+     */
+    public function __get($attr)
+    {
+        if ($attr != "instance" && property_exists($this, $attr)) {
+            return $this->$attr;
+        }
+
+        throw new \RuntimeException("Unknown attribute: $attr");
+    }
+
+    /**
+     * @ignore
+     */
+    public function __isset($attr)
+    {
+        return $attr != "instance" && isset($this->$attr);
+    }
+
+    public function jsonSerialize()
+    {
+        return $this->raw;
+    }
+}
diff --git a/lib/maxmind/GeoIp2/Model/AnonymousIp.php b/lib/maxmind/GeoIp2/Model/AnonymousIp.php
new file mode 100644 (file)
index 0000000..90e7706
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+
+namespace GeoIp2\Model;
+
+/**
+ * This class provides the GeoIP2 Anonymous IP model.
+ *
+ * @property-read boolean $isAnonymous This is true if the IP address belongs to
+ *     any sort of anonymous network.
+ *
+ * @property-read boolean $isAnonymousVpn This is true if the IP address belongs to
+ *     an anonymous VPN system.
+ *
+ * @property-read boolean $isHostingProvider This is true if the IP address belongs
+ *     to a hosting provider.
+ *
+ * @property-read boolean $isPublicProxy This is true if the IP address belongs to
+ *     a public proxy.
+ *
+ * @property-read boolean $isTorExitNode This is true if the IP address is a Tor
+ *     exit node.
+ *
+ * @property-read string $ipAddress The IP address that the data in the model is
+ *     for.
+ *
+ */
+class AnonymousIp extends AbstractModel
+{
+    protected $isAnonymous;
+    protected $isAnonymousVpn;
+    protected $isHostingProvider;
+    protected $isPublicProxy;
+    protected $isTorExitNode;
+    protected $ipAddress;
+
+    /**
+     * @ignore
+     */
+    public function __construct($raw)
+    {
+        parent::__construct($raw);
+
+        $this->isAnonymous = $this->get('is_anonymous');
+        $this->isAnonymousVpn = $this->get('is_anonymous_vpn');
+        $this->isHostingProvider = $this->get('is_hosting_provider');
+        $this->isPublicProxy = $this->get('is_public_proxy');
+        $this->isTorExitNode = $this->get('is_tor_exit_node');
+        $this->ipAddress = $this->get('ip_address');
+    }
+}
diff --git a/lib/maxmind/GeoIp2/Model/City.php b/lib/maxmind/GeoIp2/Model/City.php
new file mode 100644 (file)
index 0000000..fb7ddda
--- /dev/null
@@ -0,0 +1,122 @@
+<?php
+
+namespace GeoIp2\Model;
+
+/**
+ * Model class for the data returned by GeoIP2 City web service and database.
+ *
+ * The only difference between the City and Insights model classes is which
+ * fields in each record may be populated. See
+ * http://dev.maxmind.com/geoip/geoip2/web-services more details.
+ *
+ * @property-read \GeoIp2\Record\City $city City data for the requested IP
+ * address.
+ *
+ * @property-read \GeoIp2\Record\Continent $continent Continent data for the
+ * requested IP address.
+ *
+ * @property-read \GeoIp2\Record\Country $country Country data for the requested
+ * IP address. This object represents the country where MaxMind believes the
+ * end user is located.
+ *
+ * @property-read \GeoIp2\Record\Location $location Location data for the
+ * requested IP address.
+ *
+ * @property-read \GeoIp2\Record\Postal $postal Postal data for the
+ * requested IP address.
+ *
+ * @property-read \GeoIp2\Record\MaxMind $maxmind Data related to your MaxMind
+ * account.
+ *
+ * @property-read \GeoIp2\Record\Country $registeredCountry Registered country
+ * data for the requested IP address. This record represents the country
+ * where the ISP has registered a given IP block and may differ from the
+ * user's country.
+ *
+ * @property-read \GeoIp2\Record\RepresentedCountry $representedCountry
+ * Represented country data for the requested IP address. The represented
+ * country is used for things like military bases. It is only present when
+ * the represented country differs from the country.
+ *
+ * @property-read array $subdivisions An array of {@link \GeoIp2\Record\Subdivision}
+ * objects representing the country subdivisions for the requested IP
+ * address. The number and type of subdivisions varies by country, but a
+ * subdivision is typically a state, province, county, etc. Subdivisions
+ * are ordered from most general (largest) to most specific (smallest).
+ * If the response did not contain any subdivisions, this method returns
+ * an empty array.
+ *
+ * @property-read \GeoIp2\Record\Subdivision $mostSpecificSubdivision An  object
+ * representing the most specific subdivision returned. If the response
+ * did not contain any subdivisions, this method returns an empty
+ * {@link \GeoIp2\Record\Subdivision} object.
+ *
+ * @property-read \GeoIp2\Record\Traits $traits Data for the traits of the
+ * requested IP address.
+ */
+class City extends Country
+{
+    /**
+     * @ignore
+     */
+    protected $city;
+    /**
+     * @ignore
+     */
+    protected $location;
+    /**
+     * @ignore
+     */
+    protected $postal;
+    /**
+     * @ignore
+     */
+    protected $subdivisions = array();
+
+    /**
+     * @ignore
+     */
+    public function __construct($raw, $locales = array('en'))
+    {
+        parent::__construct($raw, $locales);
+
+        $this->city = new \GeoIp2\Record\City($this->get('city'), $locales);
+        $this->location = new \GeoIp2\Record\Location($this->get('location'));
+        $this->postal = new \GeoIp2\Record\Postal($this->get('postal'));
+
+        $this->createSubdivisions($raw, $locales);
+    }
+
+    private function createSubdivisions($raw, $locales)
+    {
+        if (!isset($raw['subdivisions'])) {
+            return;
+        }
+
+        foreach ($raw['subdivisions'] as $sub) {
+            array_push(
+                $this->subdivisions,
+                new \GeoIp2\Record\Subdivision($sub, $locales)
+            );
+        }
+    }
+
+    /**
+     * @ignore
+     */
+    public function __get($attr)
+    {
+        if ($attr == 'mostSpecificSubdivision') {
+            return $this->$attr();
+        } else {
+            return parent::__get($attr);
+        }
+    }
+
+    private function mostSpecificSubdivision()
+    {
+        return empty($this->subdivisions) ?
+            new \GeoIp2\Record\Subdivision(array(), $this->locales) :
+            end($this->subdivisions);
+    }
+}
diff --git a/lib/maxmind/GeoIp2/Model/ConnectionType.php b/lib/maxmind/GeoIp2/Model/ConnectionType.php
new file mode 100644 (file)
index 0000000..dccd500
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+
+namespace GeoIp2\Model;
+
+/**
+ * This class provides the GeoIP2 Connection-Type model.
+ *
+ * @property-read string|null $connectionType The connection type may take the
+ *     following values: "Dialup", "Cable/DSL", "Corporate", "Cellular".
+ *     Additional values may be added in the future.
+ *
+ * @property-read string $ipAddress The IP address that the data in the model is
+ *     for.
+ *
+ */
+class ConnectionType extends AbstractModel
+{
+    protected $connectionType;
+    protected $ipAddress;
+
+    /**
+     * @ignore
+     */
+    public function __construct($raw)
+    {
+        parent::__construct($raw);
+
+        $this->connectionType = $this->get('connection_type');
+        $this->ipAddress = $this->get('ip_address');
+    }
+}
diff --git a/lib/maxmind/GeoIp2/Model/Country.php b/lib/maxmind/GeoIp2/Model/Country.php
new file mode 100644 (file)
index 0000000..05cdea7
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+
+namespace GeoIp2\Model;
+
+/**
+ * Model class for the data returned by GeoIP2 Country web service and database.
+ *
+ * The only difference between the City and Insights model classes is which
+ * fields in each record may be populated. See
+ * http://dev.maxmind.com/geoip/geoip2/web-services more details.
+ *
+ * @property-read \GeoIp2\Record\Continent $continent Continent data for the
+ * requested IP address.
+ *
+ * @property-read \GeoIp2\Record\Country $country Country data for the requested
+ * IP address. This object represents the country where MaxMind believes the
+ * end user is located.
+ *
+ * @property-read \GeoIp2\Record\MaxMind $maxmind Data related to your MaxMind
+ * account.
+ *
+ * @property-read \GeoIp2\Record\Country $registeredCountry Registered country
+ * data for the requested IP address. This record represents the country
+ * where the ISP has registered a given IP block and may differ from the
+ * user's country.
+ *
+ * @property-read \GeoIp2\Record\RepresentedCountry $representedCountry
+ * Represented country data for the requested IP address. The represented
+ * country is used for things like military bases. It is only present when
+ * the represented country differs from the country.
+ *
+ * @property-read \GeoIp2\Record\Traits $traits Data for the traits of the
+ * requested IP address.
+ */
+class Country extends AbstractModel
+{
+    protected $continent;
+    protected $country;
+    protected $locales;
+    protected $maxmind;
+    protected $registeredCountry;
+    protected $representedCountry;
+    protected $traits;
+
+    /**
+     * @ignore
+     */
+    public function __construct($raw, $locales = array('en'))
+    {
+        parent::__construct($raw);
+
+        $this->continent = new \GeoIp2\Record\Continent(
+            $this->get('continent'),
+            $locales
+        );
+        $this->country = new \GeoIp2\Record\Country(
+            $this->get('country'),
+            $locales
+        );
+        $this->maxmind = new \GeoIp2\Record\MaxMind($this->get('maxmind'));
+        $this->registeredCountry = new \GeoIp2\Record\Country(
+            $this->get('registered_country'),
+            $locales
+        );
+        $this->representedCountry = new \GeoIp2\Record\RepresentedCountry(
+            $this->get('represented_country'),
+            $locales
+        );
+        $this->traits = new \GeoIp2\Record\Traits($this->get('traits'));
+
+        $this->locales = $locales;
+    }
+}
diff --git a/lib/maxmind/GeoIp2/Model/Domain.php b/lib/maxmind/GeoIp2/Model/Domain.php
new file mode 100644 (file)
index 0000000..c540644
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+
+namespace GeoIp2\Model;
+
+/**
+ * This class provides the GeoIP2 Domain model.
+ *
+ * @property-read string|null $domain The second level domain associated with the
+ *     IP address. This will be something like "example.com" or
+ *     "example.co.uk", not "foo.example.com".
+ *
+ * @property-read string $ipAddress The IP address that the data in the model is
+ *     for.
+ *
+ */
+class Domain extends AbstractModel
+{
+    protected $domain;
+    protected $ipAddress;
+
+    /**
+     * @ignore
+     */
+    public function __construct($raw)
+    {
+        parent::__construct($raw);
+
+        $this->domain = $this->get('domain');
+        $this->ipAddress = $this->get('ip_address');
+    }
+}
diff --git a/lib/maxmind/GeoIp2/Model/Enterprise.php b/lib/maxmind/GeoIp2/Model/Enterprise.php
new file mode 100644 (file)
index 0000000..12d45bd
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+
+namespace GeoIp2\Model;
+
+/**
+ * Model class for the data returned by GeoIP2 Enterprise database lookups.
+ *
+ * The only difference between the City and Enterprise model classes is which
+ * fields in each record may be populated. See
+ * http://dev.maxmind.com/geoip/geoip2/web-services more details.
+ *
+ * @property-read \GeoIp2\Record\City $city City data for the requested IP
+ * address.
+ *
+ * @property-read \GeoIp2\Record\Continent $continent Continent data for the
+ * requested IP address.
+ *
+ * @property-read \GeoIp2\Record\Country $country Country data for the requested
+ * IP address. This object represents the country where MaxMind believes the
+ * end user is located.
+ *
+ * @property-read \GeoIp2\Record\Location $location Location data for the
+ * requested IP address.
+ *
+ * @property-read \GeoIp2\Record\MaxMind $maxmind Data related to your MaxMind
+ * account.
+ *
+ * @property-read \GeoIp2\Record\Country $registeredCountry Registered country
+ * data for the requested IP address. This record represents the country
+ * where the ISP has registered a given IP block and may differ from the
+ * user's country.
+ *
+ * @property-read \GeoIp2\Record\RepresentedCountry $representedCountry
+ * Represented country data for the requested IP address. The represented
+ * country is used for things like military bases. It is only present when
+ * the represented country differs from the country.
+ *
+ * @property-read array $subdivisions An array of {@link \GeoIp2\Record\Subdivision}
+ * objects representing the country subdivisions for the requested IP
+ * address. The number and type of subdivisions varies by country, but a
+ * subdivision is typically a state, province, county, etc. Subdivisions
+ * are ordered from most general (largest) to most specific (smallest).
+ * If the response did not contain any subdivisions, this method returns
+ * an empty array.
+ *
+ * @property-read \GeoIp2\Record\Subdivision $mostSpecificSubdivision An  object
+ * representing the most specific subdivision returned. If the response
+ * did not contain any subdivisions, this method returns an empty
+ * {@link \GeoIp2\Record\Subdivision} object.
+ *
+ * @property-read \GeoIp2\Record\Traits $traits Data for the traits of the
+ * requested IP address.
+ */
+class Enterprise extends City
+{
+}
diff --git a/lib/maxmind/GeoIp2/Model/Insights.php b/lib/maxmind/GeoIp2/Model/Insights.php
new file mode 100644 (file)
index 0000000..7c0c9e1
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+
+namespace GeoIp2\Model;
+
+/**
+ * Model class for the data returned by GeoIP2 Precision: Insights web service.
+ *
+ * The only difference between the City and Insights model classes is which
+ * fields in each record may be populated. See
+ * http://dev.maxmind.com/geoip/geoip2/web-services more details.
+ *
+ * @property-read \GeoIp2\Record\City $city City data for the requested IP
+ * address.
+ *
+ * @property-read \GeoIp2\Record\Continent $continent Continent data for the
+ * requested IP address.
+ *
+ * @property-read \GeoIp2\Record\Country $country Country data for the requested
+ * IP address. This object represents the country where MaxMind believes the
+ * end user is located.
+ *
+ * @property-read \GeoIp2\Record\Location $location Location data for the
+ * requested IP address.
+ *
+ * @property-read \GeoIp2\Record\MaxMind $maxmind Data related to your MaxMind
+ * account.
+ *
+ * @property-read \GeoIp2\Record\Country $registeredCountry Registered country
+ * data for the requested IP address. This record represents the country
+ * where the ISP has registered a given IP block and may differ from the
+ * user's country.
+ *
+ * @property-read \GeoIp2\Record\RepresentedCountry $representedCountry
+ * Represented country data for the requested IP address. The represented
+ * country is used for things like military bases. It is only present when
+ * the represented country differs from the country.
+ *
+ * @property-read array $subdivisions An array of {@link \GeoIp2\Record\Subdivision}
+ * objects representing the country subdivisions for the requested IP
+ * address. The number and type of subdivisions varies by country, but a
+ * subdivision is typically a state, province, county, etc. Subdivisions
+ * are ordered from most general (largest) to most specific (smallest).
+ * If the response did not contain any subdivisions, this method returns
+ * an empty array.
+ *
+ * @property-read \GeoIp2\Record\Subdivision $mostSpecificSubdivision An  object
+ * representing the most specific subdivision returned. If the response
+ * did not contain any subdivisions, this method returns an empty
+ * {@link \GeoIp2\Record\Subdivision} object.
+ *
+ * @property-read \GeoIp2\Record\Traits $traits Data for the traits of the
+ * requested IP address.
+ */
+class Insights extends City
+{
+}
diff --git a/lib/maxmind/GeoIp2/Model/Isp.php b/lib/maxmind/GeoIp2/Model/Isp.php
new file mode 100644 (file)
index 0000000..c2dd357
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+
+namespace GeoIp2\Model;
+
+/**
+ * This class provides the GeoIP2 Connection-Type model.
+ *
+ * @property-read integer|null $autonomousSystemNumber The autonomous system number
+ *     associated with the IP address.
+ *
+ * @property-read string|null $autonomousSystemOrganization The organization
+ *     associated with the registered autonomous system number for the IP
+ *     address.
+ *
+ * @property-read string|null $isp The name of the ISP associated with the IP
+ *     address.
+ *
+ * @property-read string|null $organization The name of the organization associated
+ *     with the IP address.
+ *
+ * @property-read string $ipAddress The IP address that the data in the model is
+ *     for.
+ *
+ */
+class Isp extends AbstractModel
+{
+    protected $autonomousSystemNumber;
+    protected $autonomousSystemOrganization;
+    protected $isp;
+    protected $organization;
+    protected $ipAddress;
+
+    /**
+     * @ignore
+     */
+    public function __construct($raw)
+    {
+        parent::__construct($raw);
+        $this->autonomousSystemNumber = $this->get('autonomous_system_number');
+        $this->autonomousSystemOrganization =
+            $this->get('autonomous_system_organization');
+        $this->isp = $this->get('isp');
+        $this->organization = $this->get('organization');
+
+        $this->ipAddress = $this->get('ip_address');
+    }
+}
diff --git a/lib/maxmind/GeoIp2/ProviderInterface.php b/lib/maxmind/GeoIp2/ProviderInterface.php
new file mode 100644 (file)
index 0000000..6c3992f
--- /dev/null
@@ -0,0 +1,20 @@
+<?php
+
+namespace GeoIp2;
+
+interface ProviderInterface
+{
+    /**
+     * @param ipAddress
+     *            IPv4 or IPv6 address to lookup.
+     * @return \GeoIp2\Model\Country A Country model for the requested IP address.
+     */
+    public function country($ipAddress);
+
+    /**
+     * @param ipAddress
+     *            IPv4 or IPv6 address to lookup.
+     * @return \GeoIp2\Model\City A City model for the requested IP address.
+     */
+    public function city($ipAddress);
+}
diff --git a/lib/maxmind/GeoIp2/Record/AbstractPlaceRecord.php b/lib/maxmind/GeoIp2/Record/AbstractPlaceRecord.php
new file mode 100644 (file)
index 0000000..0b7e7d6
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+
+namespace GeoIp2\Record;
+
+abstract class AbstractPlaceRecord extends AbstractRecord
+{
+    private $locales;
+
+    /**
+     * @ignore
+     */
+    public function __construct($record, $locales = array('en'))
+    {
+        $this->locales = $locales;
+        parent::__construct($record);
+    }
+
+    /**
+     * @ignore
+     */
+    public function __get($attr)
+    {
+        if ($attr == 'name') {
+            return $this->name();
+        } else {
+            return parent::__get($attr);
+        }
+    }
+
+    private function name()
+    {
+        foreach ($this->locales as $locale) {
+            if (isset($this->names[$locale])) {
+                return $this->names[$locale];
+            }
+        }
+    }
+}
diff --git a/lib/maxmind/GeoIp2/Record/AbstractRecord.php b/lib/maxmind/GeoIp2/Record/AbstractRecord.php
new file mode 100644 (file)
index 0000000..7bb1c5b
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+
+namespace GeoIp2\Record;
+
+use GeoIp2\Compat\JsonSerializable;
+
+abstract class AbstractRecord implements JsonSerializable
+{
+    private $record;
+
+    /**
+     * @ignore
+     */
+    public function __construct($record)
+    {
+        $this->record = isset($record) ? $record : array();
+    }
+
+    /**
+     * @ignore
+     */
+    public function __get($attr)
+    {
+        // XXX - kind of ugly but greatly reduces boilerplate code
+        $key = $this->attributeToKey($attr);
+
+        if ($this->__isset($attr)) {
+            return $this->record[$key];
+        } elseif ($this->validAttribute($attr)) {
+            if (preg_match('/^is_/', $key)) {
+                return false;
+            } else {
+                return null;
+            }
+        } else {
+            throw new \RuntimeException("Unknown attribute: $attr");
+        }
+    }
+
+    public function __isset($attr)
+    {
+        return $this->validAttribute($attr) &&
+             isset($this->record[$this->attributeToKey($attr)]);
+    }
+
+    private function attributeToKey($attr)
+    {
+        return strtolower(preg_replace('/([A-Z])/', '_\1', $attr));
+    }
+
+    private function validAttribute($attr)
+    {
+        return in_array($attr, $this->validAttributes);
+    }
+
+    public function jsonSerialize()
+    {
+        return $this->record;
+    }
+}
diff --git a/lib/maxmind/GeoIp2/Record/City.php b/lib/maxmind/GeoIp2/Record/City.php
new file mode 100644 (file)
index 0000000..9f1560f
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+
+namespace GeoIp2\Record;
+
+/**
+ * City-level data associated with an IP address.
+ *
+ * This record is returned by all location services and databases besides
+ * Country.
+ *
+ * @property-read int|null $confidence A value from 0-100 indicating MaxMind's
+ * confidence that the city is correct. This attribute is only available
+ * from the Insights service and the GeoIP2 Enterprise database.
+ *
+ * @property-read int|null $geonameId The GeoName ID for the city. This attribute
+ * is returned by all location services and databases.
+ *
+ * @property-read string|null $name The name of the city based on the locales list
+ * passed to the constructor. This attribute is returned by all location
+ * services and databases.
+ *
+ * @property-read array|null $names A array map where the keys are locale codes
+ * and the values are names. This attribute is returned by all location
+ * services and databases.
+ */
+class City extends AbstractPlaceRecord
+{
+    /**
+     * @ignore
+     */
+    protected $validAttributes = array('confidence', 'geonameId', 'names');
+}
diff --git a/lib/maxmind/GeoIp2/Record/Continent.php b/lib/maxmind/GeoIp2/Record/Continent.php
new file mode 100644 (file)
index 0000000..4893e9e
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+
+namespace GeoIp2\Record;
+
+/**
+ * Contains data for the continent record associated with an IP address
+ *
+ * This record is returned by all location services and databases.
+ *
+ * @property-read string|null $code A two character continent code like "NA" (North
+ * America) or "OC" (Oceania). This attribute is returned by all location
+ * services and databases.
+ *
+ * @property-read int|null $geonameId The GeoName ID for the continent. This
+ * attribute is returned by all location services and databases.
+ *
+ * @property-read string|null $name Returns the name of the continent based on the
+ * locales list passed to the constructor. This attribute is returned by all location
+ * services and databases.
+ *
+ * @property-read array|null $names An array map where the keys are locale codes
+ * and the values are names. This attribute is returned by all location
+ * services and databases.
+ */
+class Continent extends AbstractPlaceRecord
+{
+    /**
+     * @ignore
+     */
+    protected $validAttributes = array(
+        'code',
+        'geonameId',
+        'names'
+    );
+}
diff --git a/lib/maxmind/GeoIp2/Record/Country.php b/lib/maxmind/GeoIp2/Record/Country.php
new file mode 100644 (file)
index 0000000..922195b
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+
+namespace GeoIp2\Record;
+
+/**
+ * Contains data for the country record associated with an IP address
+ *
+ * This record is returned by all location services and databases.
+ *
+ * @property-read int|null $confidence A value from 0-100 indicating MaxMind's
+ * confidence that the country is correct. This attribute is only available
+ * from the Insights service and the GeoIP2 Enterprise database.
+ *
+ * @property-read int|null $geonameId The GeoName ID for the country. This
+ * attribute is returned by location services and databases.
+ *
+ * @property-read string|null $isoCode The {@link
+ * http://en.wikipedia.org/wiki/ISO_3166-1 two-character ISO 3166-1 alpha
+ * code} for the country. This attribute is returned by all location services
+ * and databases.
+ *
+ * @property-read string|null $name The name of the country based on the locales
+ * list passed to the constructor. This attribute is returned by all location
+ * services and databases.
+ *
+ * @property-read array|null $names An array map where the keys are locale codes
+ * and the values are names. This attribute is returned by all location
+ * services and databases.
+ */
+class Country extends AbstractPlaceRecord
+{
+    /**
+     * @ignore
+     */
+    protected $validAttributes = array(
+        'confidence',
+        'geonameId',
+        'isoCode',
+        'names'
+    );
+}
diff --git a/lib/maxmind/GeoIp2/Record/Location.php b/lib/maxmind/GeoIp2/Record/Location.php
new file mode 100644 (file)
index 0000000..5d0742d
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+
+namespace GeoIp2\Record;
+
+/**
+ * Contains data for the location record associated with an IP address
+ *
+ * This record is returned by all location services and databases besides
+ * Country.
+ *
+ * @property-read int|null $averageIncome The average income in US dollars
+ * associated with the requested IP address. This attribute is only available
+ * from the Insights service.
+ *
+ * @property-read int|null $accuracyRadius The approximate accuracy radius in
+ * kilometers around the latitude and longitude for the IP address. This is
+ * the radius where we have a 67% confidence that the device using the IP
+ * address resides within the circle centered at the latitude and longitude
+ * with the provided radius.
+ *
+ * @property-read float|null $latitude The approximate latitude of the location
+ * associated with the IP address. This value is not precise and should not be
+ * used to identify a particular address or household.
+ *
+ * @property-read float|null $longitude The approximate longitude of the location
+ * associated with the IP address. This value is not precise and should not be
+ * used to identify a particular address or household.
+ *
+ * @property-read int|null $populationDensity The estimated population per square
+ * kilometer associated with the IP address. This attribute is only available
+ * from the Insights service.
+ *
+ * @property-read int|null $metroCode The metro code of the location if the location
+ * is in the US. MaxMind returns the same metro codes as the
+ * {@link
+ * https://developers.google.com/adwords/api/docs/appendix/cities-DMAregions
+ * Google AdWords API}.
+ *
+ * @property-read string|null $timeZone The time zone associated with location, as
+ * specified by the {@link http://www.iana.org/time-zones IANA Time Zone
+ * Database}, e.g., "America/New_York".
+ */
+class Location extends AbstractRecord
+{
+    /**
+     * @ignore
+     */
+    protected $validAttributes = array(
+        'averageIncome',
+        'accuracyRadius',
+        'latitude',
+        'longitude',
+        'metroCode',
+        'populationDensity',
+        'postalCode',
+        'postalConfidence',
+        'timeZone'
+    );
+}
diff --git a/lib/maxmind/GeoIp2/Record/MaxMind.php b/lib/maxmind/GeoIp2/Record/MaxMind.php
new file mode 100644 (file)
index 0000000..8971e96
--- /dev/null
@@ -0,0 +1,19 @@
+<?php
+
+namespace GeoIp2\Record;
+
+/**
+ * Contains data about your account.
+ *
+ * This record is returned by all location services and databases.
+ *
+ * @property-read int|null $queriesRemaining The number of remaining queries you
+ * have for the service you are calling.
+ */
+class MaxMind extends AbstractRecord
+{
+    /**
+     * @ignore
+     */
+    protected $validAttributes = array('queriesRemaining');
+}
diff --git a/lib/maxmind/GeoIp2/Record/Postal.php b/lib/maxmind/GeoIp2/Record/Postal.php
new file mode 100644 (file)
index 0000000..81d3011
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+
+namespace GeoIp2\Record;
+
+/**
+ * Contains data for the postal record associated with an IP address
+ *
+ * This record is returned by all location databases and services besides
+ * Country.
+ *
+ * @property-read string|null $code The postal code of the location. Postal codes
+ * are not available for all countries. In some countries, this will only
+ * contain part of the postal code. This attribute is returned by all location
+ * databases and services besides Country.
+ *
+ * @property-read int|null $confidence A value from 0-100 indicating MaxMind's
+ * confidence that the postal code is correct. This attribute is only
+ * available from the Insights service and the GeoIP2 Enterprise
+ * database.
+ */
+class Postal extends AbstractRecord
+{
+    /**
+     * @ignore
+     */
+    protected $validAttributes = array('code', 'confidence');
+}
diff --git a/lib/maxmind/GeoIp2/Record/RepresentedCountry.php b/lib/maxmind/GeoIp2/Record/RepresentedCountry.php
new file mode 100644 (file)
index 0000000..dd49114
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+
+namespace GeoIp2\Record;
+
+/**
+ * Contains data for the represented country associated with an IP address
+ *
+ * This class contains the country-level data associated with an IP address
+ * for the IP's represented country. The represented country is the country
+ * represented by something like a military base.
+ *
+ * @property-read int|null $confidence A value from 0-100 indicating MaxMind's
+ * confidence that the country is correct. This attribute is only available
+ * from the Insights service and the GeoIP2 Enterprise database.
+ *
+ * @property-read int|null $geonameId The GeoName ID for the country.
+ *
+ * @property-read string|null $isoCode The {@link http://en.wikipedia.org/wiki/ISO_3166-1
+ * two-character ISO 3166-1 alpha code} for the country.
+ *
+ * @property-read string|null $name The name of the country based on the locales list
+ * passed to the constructor.
+ *
+ * @property-read array|null $names An array map where the keys are locale codes and
+ * the values are names.
+ *
+ * @property-read string|null $type A string indicating the type of entity that is
+ * representing the country. Currently we only return <code>military</code>
+ * but this could expand to include other types in the future.
+ */
+class RepresentedCountry extends Country
+{
+    protected $validAttributes = array(
+        'confidence',
+        'geonameId',
+        'isoCode',
+        'names',
+        'type'
+    );
+}
diff --git a/lib/maxmind/GeoIp2/Record/Subdivision.php b/lib/maxmind/GeoIp2/Record/Subdivision.php
new file mode 100644 (file)
index 0000000..cb5256a
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+
+namespace GeoIp2\Record;
+
+/**
+ *
+ * Contains data for the subdivisions associated with an IP address
+ *
+ * This record is returned by all location databases and services besides
+ * Country.
+ *
+ * @property-read int|null $confidence This is a value from 0-100 indicating
+ * MaxMind's confidence that the subdivision is correct. This attribute is
+ * only available from the Insights service and the GeoIP2 Enterprise
+ * database.
+ *
+ * @property-read int|null $geonameId This is a GeoName ID for the subdivision.
+ * This attribute is returned by all location databases and services besides
+ * Country.
+ *
+ * @property-read string|null $isoCode This is a string up to three characters long
+ * contain the subdivision portion of the {@link
+ * http://en.wikipedia.org/wiki/ISO_3166-2 ISO 3166-2 code}. This attribute
+ * is returned by all location databases and services except Country.
+ *
+ * @property-read string|null $name The name of the subdivision based on the
+ * locales list passed to the constructor. This attribute is returned by all
+ * location databases and services besides Country.
+ *
+ * @property-read array|null $names An array map where the keys are locale codes
+ * and the values are names. This attribute is returned by all location
+ * databases and services besides Country.
+ */
+class Subdivision extends AbstractPlaceRecord
+{
+    /**
+     * @ignore
+     */
+    protected $validAttributes = array(
+        'confidence',
+        'geonameId',
+        'isoCode',
+        'names'
+    );
+}
diff --git a/lib/maxmind/GeoIp2/Record/Traits.php b/lib/maxmind/GeoIp2/Record/Traits.php
new file mode 100644 (file)
index 0000000..7d8710f
--- /dev/null
@@ -0,0 +1,107 @@
+<?php
+
+namespace GeoIp2\Record;
+
+/**
+ *
+ * Contains data for the traits record associated with an IP address
+ *
+ * This record is returned by all location services and databases.
+ *
+ * @property-read int|null $autonomousSystemNumber The {@link
+ * http://en.wikipedia.org/wiki/Autonomous_system_(Internet) autonomous
+ * system number} associated with the IP address. This attribute is only
+ * available from the City and Insights web service and the GeoIP2
+ * Enterprise database.
+ *
+ * @property-read string|null $autonomousSystemOrganization The organization
+ * associated with the registered {@link
+ * http://en.wikipedia.org/wiki/Autonomous_system_(Internet) autonomous
+ * system number} for the IP address. This attribute is only available from
+ * the City and Insights web service and the GeoIP2 Enterprise
+ * database.
+ *
+ * @property-read string|null $connectionType The connection type may take the
+ * following  values: "Dialup", "Cable/DSL", "Corporate", "Cellular".
+ * Additional values may be added in the future. This attribute is only
+ * available in the GeoIP2 Enterprise database.
+ *
+ * @property-read string|null $domain The second level domain associated with the
+ * IP address. This will be something like "example.com" or "example.co.uk",
+ * not "foo.example.com". This attribute is only available from the
+ * City and Insights web service and the GeoIP2 Enterprise
+ * database.
+ *
+ * @property-read string $ipAddress The IP address that the data in the model
+ * is for. If you performed a "me" lookup against the web service, this
+ * will be the externally routable IP address for the system the code is
+ * running on. If the system is behind a NAT, this may differ from the IP
+ * address locally assigned to it. This attribute is returned by all end
+ * points.
+ *
+ * @property-read boolean $isAnonymousProxy *Deprecated.* Please see our {@link
+ * https://www.maxmind.com/en/geoip2-anonymous-ip-database GeoIP2
+ * Anonymous IP database} to determine whether the IP address is used by an
+ * anonymizing service.
+ *
+ * @property-read boolean $isLegitimateProxy This attribute is true if MaxMind
+ * believes this IP address to be a legitimate proxy, such as an internal
+ * VPN used by a corporation. This attribute is only available in the GeoIP2
+ * Enterprise database.
+ *
+ * @property-read boolean $isSatelliteProvider *Deprecated.* Due to the
+ * increased coverage by mobile carriers, very few satellite providers now
+ * serve multiple countries. As a result, the output does not provide
+ * sufficiently relevant data for us to maintain it.
+ *
+ * @property-read string|null $isp The name of the ISP associated with the IP
+ * address. This attribute is only available from the City and Insights web
+ * services and the GeoIP2 Enterprise database.
+ *
+ * @property-read string|null $organization The name of the organization associated
+ * with the IP address. This attribute is only available from the City and
+ * Insights web services and the GeoIP2 Enterprise database.
+ *
+ * @property-read string|null $userType <p>The user type associated with the IP
+ *  address. This can be one of the following values:</p>
+ *  <ul>
+ *    <li>business
+ *    <li>cafe
+ *    <li>cellular
+ *    <li>college
+ *    <li>content_delivery_network
+ *    <li>dialup
+ *    <li>government
+ *    <li>hosting
+ *    <li>library
+ *    <li>military
+ *    <li>residential
+ *    <li>router
+ *    <li>school
+ *    <li>search_engine_spider
+ *    <li>traveler
+ * </ul>
+ * <p>
+ *   This attribute is only available from the Insights web service and the
+ *   GeoIP2 Enterprise database.
+ * </p>
+ */
+class Traits extends AbstractRecord
+{
+    /**
+     * @ignore
+     */
+    protected $validAttributes = array(
+        'autonomousSystemNumber',
+        'autonomousSystemOrganization',
+        'connectionType',
+        'domain',
+        'isAnonymousProxy',
+        'isLegitimateProxy',
+        'isSatelliteProvider',
+        'isp',
+        'ipAddress',
+        'organization',
+        'userType'
+    );
+}
diff --git a/lib/maxmind/GeoIp2/WebService/Client.php b/lib/maxmind/GeoIp2/WebService/Client.php
new file mode 100644 (file)
index 0000000..f42ec81
--- /dev/null
@@ -0,0 +1,242 @@
+<?php
+
+namespace GeoIp2\WebService;
+
+use GeoIp2\Exception\AddressNotFoundException;
+use GeoIp2\Exception\AuthenticationException;
+use GeoIp2\Exception\GeoIp2Exception;
+use GeoIp2\Exception\HttpException;
+use GeoIp2\Exception\InvalidRequestException;
+use GeoIp2\Exception\OutOfQueriesException;
+use GeoIp2\ProviderInterface;
+use MaxMind\Exception\InvalidInputException;
+use MaxMind\WebService\Client as WsClient;
+
+/**
+ * This class provides a client API for all the GeoIP2 Precision web services.
+ * The services are Country, City, and Insights. Each service returns a
+ * different set of data about an IP address, with Country returning the
+ * least data and Insights the most.
+ *
+ * Each web service is represented by a different model class, and these model
+ * classes in turn contain multiple record classes. The record classes have
+ * attributes which contain data about the IP address.
+ *
+ * If the web service does not return a particular piece of data for an IP
+ * address, the associated attribute is not populated.
+ *
+ * The web service may not return any information for an entire record, in
+ * which case all of the attributes for that record class will be empty.
+ *
+ * ## Usage ##
+ *
+ * The basic API for this class is the same for all of the web service end
+ * points. First you create a web service object with your MaxMind `$userId`
+ * and `$licenseKey`, then you call the method corresponding to a specific end
+ * point, passing it the IP address you want to look up.
+ *
+ * If the request succeeds, the method call will return a model class for
+ * the service you called. This model in turn contains multiple record
+ * classes, each of which represents part of the data returned by the web
+ * service.
+ *
+ * If the request fails, the client class throws an exception.
+ */
+class Client implements ProviderInterface
+{
+    private $locales;
+    private $client;
+    private static $basePath = '/geoip/v2.1';
+
+    const VERSION = 'v2.4.2';
+
+    /**
+     * Constructor.
+     *
+     * @param int $userId     Your MaxMind user ID
+     * @param string $licenseKey Your MaxMind license key
+     * @param array $locales  List of locale codes to use in name property
+     * from most preferred to least preferred.
+     * @param array $options Array of options. Valid options include:
+     *      * `host` - The host to use when querying the web service.
+     *      * `timeout` - Timeout in seconds.
+     *      * `connectTimeout` - Initial connection timeout in seconds.
+     *      * `proxy` - The HTTP proxy to use. May include a schema, port,
+     *        username, and password, e.g.,
+     *        `http://username:password@127.0.0.1:10`.
+     */
+    public function __construct(
+        $userId,
+        $licenseKey,
+        $locales = array('en'),
+        $options = array()
+    ) {
+        $this->locales = $locales;
+
+        // This is for backwards compatibility. Do not remove except for a
+        // major version bump.
+        if (is_string($options)) {
+            $options = array( 'host' => $options );
+        }
+
+        if (!isset($options['host'])) {
+            $options['host'] = 'geoip.maxmind.com';
+        }
+
+        $options['userAgent'] = $this->userAgent();
+
+        $this->client = new WsClient($userId, $licenseKey, $options);
+    }
+
+    private function userAgent()
+    {
+        return 'GeoIP2-API/' . Client::VERSION;
+    }
+
+    /**
+     * This method calls the GeoIP2 Precision: City service.
+     *
+     * @param string $ipAddress IPv4 or IPv6 address as a string. If no
+     * address is provided, the address that the web service is called
+     * from will be used.
+     *
+     * @return \GeoIp2\Model\City
+     *
+     * @throws \GeoIp2\Exception\AddressNotFoundException if the address you
+     *   provided is not in our database (e.g., a private address).
+     * @throws \GeoIp2\Exception\AuthenticationException if there is a problem
+     *   with the user ID or license key that you provided.
+     * @throws \GeoIp2\Exception\OutOfQueriesException if your account is out
+     *   of queries.
+     * @throws \GeoIp2\Exception\InvalidRequestException} if your request was
+     *   received by the web service but is invalid for some other reason.
+     *   This may indicate an issue with this API. Please report the error to
+     *   MaxMind.
+     * @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error
+     *   code or message was returned. This could indicate a problem with the
+     *   connection between your server and the web service or that the web
+     *   service returned an invalid document or 500 error code.
+     * @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent
+     *   class to the above exceptions. It will be thrown directly if a 200
+     *   status code is returned but the body is invalid.
+     */
+    public function city($ipAddress = 'me')
+    {
+        return $this->responseFor('city', 'City', $ipAddress);
+    }
+
+    /**
+     * This method calls the GeoIP2 Precision: Country service.
+     *
+     * @param string $ipAddress IPv4 or IPv6 address as a string. If no
+     * address is provided, the address that the web service is called
+     * from will be used.
+     *
+     * @return \GeoIp2\Model\Country
+     *
+     * @throws \GeoIp2\Exception\AddressNotFoundException if the address you
+     *   provided is not in our database (e.g., a private address).
+     * @throws \GeoIp2\Exception\AuthenticationException if there is a problem
+     *   with the user ID or license key that you provided.
+     * @throws \GeoIp2\Exception\OutOfQueriesException if your account is out
+     *   of queries.
+     * @throws \GeoIp2\Exception\InvalidRequestException} if your request was
+     *   received by the web service but is invalid for some other reason.
+     *   This may indicate an issue with this API. Please report the error to
+     *   MaxMind.
+     * @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error
+     *   code or message was returned. This could indicate a problem with the
+     *   connection between your server and the web service or that the web
+     *   service returned an invalid document or 500 error code.
+     * @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent
+     *   class to the above exceptions. It will be thrown directly if a 200
+     *   status code is returned but the body is invalid.
+     */
+    public function country($ipAddress = 'me')
+    {
+        return $this->responseFor('country', 'Country', $ipAddress);
+    }
+
+    /**
+     * This method calls the GeoIP2 Precision: Insights service.
+     *
+     * @param string $ipAddress IPv4 or IPv6 address as a string. If no
+     * address is provided, the address that the web service is called
+     * from will be used.
+     *
+     * @return \GeoIp2\Model\Insights
+     *
+     * @throws \GeoIp2\Exception\AddressNotFoundException if the address you
+     *   provided is not in our database (e.g., a private address).
+     * @throws \GeoIp2\Exception\AuthenticationException if there is a problem
+     *   with the user ID or license key that you provided.
+     * @throws \GeoIp2\Exception\OutOfQueriesException if your account is out
+     *   of queries.
+     * @throws \GeoIp2\Exception\InvalidRequestException} if your request was
+     *   received by the web service but is invalid for some other reason.
+     *   This may indicate an issue with this API. Please report the error to
+     *   MaxMind.
+     * @throws \GeoIp2\Exception\HttpException if an unexpected HTTP error
+     *   code or message was returned. This could indicate a problem with the
+     *   connection between your server and the web service or that the web
+     *   service returned an invalid document or 500 error code.
+     * @throws \GeoIp2\Exception\GeoIp2Exception This serves as the parent
+     *   class to the above exceptions. It will be thrown directly if a 200
+     *   status code is returned but the body is invalid.
+     */
+    public function insights($ipAddress = 'me')
+    {
+        return $this->responseFor('insights', 'Insights', $ipAddress);
+    }
+
+    private function responseFor($endpoint, $class, $ipAddress)
+    {
+        $path = implode('/', array(self::$basePath, $endpoint, $ipAddress));
+
+        try {
+            $body = $this->client->get('GeoIP2 ' . $class, $path);
+        } catch (\MaxMind\Exception\IpAddressNotFoundException $ex) {
+            throw new AddressNotFoundException(
+                $ex->getMessage(),
+                $ex->getStatusCode(),
+                $ex
+            );
+        } catch (\MaxMind\Exception\AuthenticationException $ex) {
+            throw new AuthenticationException(
+                $ex->getMessage(),
+                $ex->getStatusCode(),
+                $ex
+            );
+        } catch (\MaxMind\Exception\InsufficientFundsException $ex) {
+            throw new OutOfQueriesException(
+                $ex->getMessage(),
+                $ex->getStatusCode(),
+                $ex
+            );
+        } catch (\MaxMind\Exception\InvalidRequestException $ex) {
+            throw new InvalidRequestException(
+                $ex->getMessage(),
+                $ex->getErrorCode(),
+                $ex->getStatusCode(),
+                $ex->getUri(),
+                $ex
+            );
+        } catch (\MaxMind\Exception\HttpException $ex) {
+            throw new HttpException(
+                $ex->getMessage(),
+                $ex->getStatusCode(),
+                $ex->getUri(),
+                $ex
+            );
+        } catch (\MaxMind\Exception\WebServiceException $ex) {
+            throw new GeoIp2Exception(
+                $ex->getMessage(),
+                $ex->getCode(),
+                $ex
+            );
+        }
+
+        $class = "GeoIp2\\Model\\" . $class;
+        return new $class($body, $this->locales);
+    }
+}
diff --git a/lib/maxmind/MaxMind/Db/Reader.php b/lib/maxmind/MaxMind/Db/Reader.php
new file mode 100644 (file)
index 0000000..f524e70
--- /dev/null
@@ -0,0 +1,296 @@
+<?php
+
+namespace MaxMind\Db;
+
+use MaxMind\Db\Reader\Decoder;
+use MaxMind\Db\Reader\InvalidDatabaseException;
+use MaxMind\Db\Reader\Metadata;
+use MaxMind\Db\Reader\Util;
+
+/**
+ * Instances of this class provide a reader for the MaxMind DB format. IP
+ * addresses can be looked up using the <code>get</code> method.
+ */
+class Reader
+{
+    private static $DATA_SECTION_SEPARATOR_SIZE = 16;
+    private static $METADATA_START_MARKER = "\xAB\xCD\xEFMaxMind.com";
+    private static $METADATA_START_MARKER_LENGTH = 14;
+
+    private $decoder;
+    private $fileHandle;
+    private $fileSize;
+    private $ipV4Start;
+    private $metadata;
+
+    /**
+     * Constructs a Reader for the MaxMind DB format. The file passed to it must
+     * be a valid MaxMind DB file such as a GeoIp2 database file.
+     *
+     * @param string $database
+     *            the MaxMind DB file to use.
+     * @throws \InvalidArgumentException for invalid database path or unknown arguments
+     * @throws \MaxMind\Db\Reader\InvalidDatabaseException
+     *             if the database is invalid or there is an error reading
+     *             from it.
+     */
+    public function __construct($database)
+    {
+        if (func_num_args() != 1) {
+            throw new \InvalidArgumentException(
+                'The constructor takes exactly one argument.'
+            );
+        }
+
+        if (!is_readable($database)) {
+            throw new \InvalidArgumentException(
+                "The file \"$database\" does not exist or is not readable."
+            );
+        }
+        $this->fileHandle = @fopen($database, 'rb');
+        if ($this->fileHandle === false) {
+            throw new \InvalidArgumentException(
+                "Error opening \"$database\"."
+            );
+        }
+        $this->fileSize = @filesize($database);
+        if ($this->fileSize === false) {
+            throw new \UnexpectedValueException(
+                "Error determining the size of \"$database\"."
+            );
+        }
+
+        $start = $this->findMetadataStart($database);
+        $metadataDecoder = new Decoder($this->fileHandle, $start);
+        list($metadataArray) = $metadataDecoder->decode($start);
+        $this->metadata = new Metadata($metadataArray);
+        $this->decoder = new Decoder(
+            $this->fileHandle,
+            $this->metadata->searchTreeSize + self::$DATA_SECTION_SEPARATOR_SIZE
+        );
+    }
+
+    /**
+     * Looks up the <code>address</code> in the MaxMind DB.
+     *
+     * @param string $ipAddress
+     *            the IP address to look up.
+     * @return array the record for the IP address.
+     * @throws \BadMethodCallException if this method is called on a closed database.
+     * @throws \InvalidArgumentException if something other than a single IP address is passed to the method.
+     * @throws InvalidDatabaseException
+     *             if the database is invalid or there is an error reading
+     *             from it.
+     */
+    public function get($ipAddress)
+    {
+        if (func_num_args() != 1) {
+            throw new \InvalidArgumentException(
+                'Method takes exactly one argument.'
+            );
+        }
+
+        if (!is_resource($this->fileHandle)) {
+            throw new \BadMethodCallException(
+                'Attempt to read from a closed MaxMind DB.'
+            );
+        }
+
+        if (!filter_var($ipAddress, FILTER_VALIDATE_IP)) {
+            throw new \InvalidArgumentException(
+                "The value \"$ipAddress\" is not a valid IP address."
+            );
+        }
+
+        if ($this->metadata->ipVersion == 4 && strrpos($ipAddress, ':')) {
+            throw new \InvalidArgumentException(
+                "Error looking up $ipAddress. You attempted to look up an"
+                . " IPv6 address in an IPv4-only database."
+            );
+        }
+        $pointer = $this->findAddressInTree($ipAddress);
+        if ($pointer == 0) {
+            return null;
+        }
+        return $this->resolveDataPointer($pointer);
+    }
+
+    private function findAddressInTree($ipAddress)
+    {
+        // XXX - could simplify. Done as a byte array to ease porting
+        $rawAddress = array_merge(unpack('C*', inet_pton($ipAddress)));
+
+        $bitCount = count($rawAddress) * 8;
+
+        // The first node of the tree is always node 0, at the beginning of the
+        // value
+        $node = $this->startNode($bitCount);
+
+        for ($i = 0; $i < $bitCount; $i++) {
+            if ($node >= $this->metadata->nodeCount) {
+                break;
+            }
+            $tempBit = 0xFF & $rawAddress[$i >> 3];
+            $bit = 1 & ($tempBit >> 7 - ($i % 8));
+
+            $node = $this->readNode($node, $bit);
+        }
+        if ($node == $this->metadata->nodeCount) {
+            // Record is empty
+            return 0;
+        } elseif ($node > $this->metadata->nodeCount) {
+            // Record is a data pointer
+            return $node;
+        }
+        throw new InvalidDatabaseException("Something bad happened");
+    }
+
+
+    private function startNode($length)
+    {
+        // Check if we are looking up an IPv4 address in an IPv6 tree. If this
+        // is the case, we can skip over the first 96 nodes.
+        if ($this->metadata->ipVersion == 6 && $length == 32) {
+            return $this->ipV4StartNode();
+        }
+        // The first node of the tree is always node 0, at the beginning of the
+        // value
+        return 0;
+    }
+
+    private function ipV4StartNode()
+    {
+        // This is a defensive check. There is no reason to call this when you
+        // have an IPv4 tree.
+        if ($this->metadata->ipVersion == 4) {
+            return 0;
+        }
+
+        if ($this->ipV4Start != 0) {
+            return $this->ipV4Start;
+        }
+        $node = 0;
+
+        for ($i = 0; $i < 96 && $node < $this->metadata->nodeCount; $i++) {
+            $node = $this->readNode($node, 0);
+        }
+        $this->ipV4Start = $node;
+        return $node;
+    }
+
+    private function readNode($nodeNumber, $index)
+    {
+        $baseOffset = $nodeNumber * $this->metadata->nodeByteSize;
+
+        // XXX - probably could condense this.
+        switch ($this->metadata->recordSize) {
+            case 24:
+                $bytes = Util::read($this->fileHandle, $baseOffset + $index * 3, 3);
+                list(, $node) = unpack('N', "\x00" . $bytes);
+                return $node;
+            case 28:
+                $middleByte = Util::read($this->fileHandle, $baseOffset + 3, 1);
+                list(, $middle) = unpack('C', $middleByte);
+                if ($index == 0) {
+                    $middle = (0xF0 & $middle) >> 4;
+                } else {
+                    $middle = 0x0F & $middle;
+                }
+                $bytes = Util::read($this->fileHandle, $baseOffset + $index * 4, 3);
+                list(, $node) = unpack('N', chr($middle) . $bytes);
+                return $node;
+            case 32:
+                $bytes = Util::read($this->fileHandle, $baseOffset + $index * 4, 4);
+                list(, $node) = unpack('N', $bytes);
+                return $node;
+            default:
+                throw new InvalidDatabaseException(
+                    'Unknown record size: '
+                    . $this->metadata->recordSize
+                );
+        }
+    }
+
+    private function resolveDataPointer($pointer)
+    {
+        $resolved = $pointer - $this->metadata->nodeCount
+            + $this->metadata->searchTreeSize;
+        if ($resolved > $this->fileSize) {
+            throw new InvalidDatabaseException(
+                "The MaxMind DB file's search tree is corrupt"
+            );
+        }
+
+        list($data) = $this->decoder->decode($resolved);
+        return $data;
+    }
+
+    /*
+     * This is an extremely naive but reasonably readable implementation. There
+     * are much faster algorithms (e.g., Boyer-Moore) for this if speed is ever
+     * an issue, but I suspect it won't be.
+     */
+    private function findMetadataStart($filename)
+    {
+        $handle = $this->fileHandle;
+        $fstat = fstat($handle);
+        $fileSize = $fstat['size'];
+        $marker = self::$METADATA_START_MARKER;
+        $markerLength = self::$METADATA_START_MARKER_LENGTH;
+
+        for ($i = 0; $i < $fileSize - $markerLength + 1; $i++) {
+            for ($j = 0; $j < $markerLength; $j++) {
+                fseek($handle, $fileSize - $i - $j - 1);
+                $matchBit = fgetc($handle);
+                if ($matchBit != $marker[$markerLength - $j - 1]) {
+                    continue 2;
+                }
+            }
+            return $fileSize - $i;
+        }
+        throw new InvalidDatabaseException(
+            "Error opening database file ($filename). " .
+            'Is this a valid MaxMind DB file?'
+        );
+    }
+
+    /**
+     * @throws \InvalidArgumentException if arguments are passed to the method.
+     * @throws \BadMethodCallException if the database has been closed.
+     * @return Metadata object for the database.
+     */
+    public function metadata()
+    {
+        if (func_num_args()) {
+            throw new \InvalidArgumentException(
+                'Method takes no arguments.'
+            );
+        }
+
+        // Not technically required, but this makes it consistent with
+        // C extension and it allows us to change our implementation later.
+        if (!is_resource($this->fileHandle)) {
+            throw new \BadMethodCallException(
+                'Attempt to read from a closed MaxMind DB.'
+            );
+        }
+
+        return $this->metadata;
+    }
+
+    /**
+     * Closes the MaxMind DB and returns resources to the system.
+     *
+     * @throws \Exception
+     *             if an I/O error occurs.
+     */
+    public function close()
+    {
+        if (!is_resource($this->fileHandle)) {
+            throw new \BadMethodCallException(
+                'Attempt to close a closed MaxMind DB.'
+            );
+        }
+        fclose($this->fileHandle);
+    }
+}
diff --git a/lib/maxmind/MaxMind/Db/Reader/Decoder.php b/lib/maxmind/MaxMind/Db/Reader/Decoder.php
new file mode 100644 (file)
index 0000000..4575b27
--- /dev/null
@@ -0,0 +1,309 @@
+<?php
+
+namespace MaxMind\Db\Reader;
+
+use MaxMind\Db\Reader\InvalidDatabaseException;
+use MaxMind\Db\Reader\Util;
+
+class Decoder
+{
+
+    private $fileStream;
+    private $pointerBase;
+    // This is only used for unit testing
+    private $pointerTestHack;
+    private $switchByteOrder;
+
+    private $types = array(
+        0 => 'extended',
+        1 => 'pointer',
+        2 => 'utf8_string',
+        3 => 'double',
+        4 => 'bytes',
+        5 => 'uint16',
+        6 => 'uint32',
+        7 => 'map',
+        8 => 'int32',
+        9 => 'uint64',
+        10 => 'uint128',
+        11 => 'array',
+        12 => 'container',
+        13 => 'end_marker',
+        14 => 'boolean',
+        15 => 'float',
+    );
+
+    public function __construct(
+        $fileStream,
+        $pointerBase = 0,
+        $pointerTestHack = false
+    ) {
+        $this->fileStream = $fileStream;
+        $this->pointerBase = $pointerBase;
+        $this->pointerTestHack = $pointerTestHack;
+
+        $this->switchByteOrder = $this->isPlatformLittleEndian();
+    }
+
+
+    public function decode($offset)
+    {
+        list(, $ctrlByte) = unpack(
+            'C',
+            Util::read($this->fileStream, $offset, 1)
+        );
+        $offset++;
+
+        $type = $this->types[$ctrlByte >> 5];
+
+        // Pointers are a special case, we don't read the next $size bytes, we
+        // use the size to determine the length of the pointer and then follow
+        // it.
+        if ($type == 'pointer') {
+            list($pointer, $offset) = $this->decodePointer($ctrlByte, $offset);
+
+            // for unit testing
+            if ($this->pointerTestHack) {
+                return array($pointer);
+            }
+
+            list($result) = $this->decode($pointer);
+
+            return array($result, $offset);
+        }
+
+        if ($type == 'extended') {
+            list(, $nextByte) = unpack(
+                'C',
+                Util::read($this->fileStream, $offset, 1)
+            );
+
+            $typeNum = $nextByte + 7;
+
+            if ($typeNum < 8) {
+                throw new InvalidDatabaseException(
+                    "Something went horribly wrong in the decoder. An extended type "
+                    . "resolved to a type number < 8 ("
+                    . $this->types[$typeNum]
+                    . ")"
+                );
+            }
+
+            $type = $this->types[$typeNum];
+            $offset++;
+        }
+
+        list($size, $offset) = $this->sizeFromCtrlByte($ctrlByte, $offset);
+
+        return $this->decodeByType($type, $offset, $size);
+    }
+
+    private function decodeByType($type, $offset, $size)
+    {
+        switch ($type) {
+            case 'map':
+                return $this->decodeMap($size, $offset);
+            case 'array':
+                return $this->decodeArray($size, $offset);
+            case 'boolean':
+                return array($this->decodeBoolean($size), $offset);
+        }
+
+        $newOffset = $offset + $size;
+        $bytes = Util::read($this->fileStream, $offset, $size);
+        switch ($type) {
+            case 'utf8_string':
+                return array($this->decodeString($bytes), $newOffset);
+            case 'double':
+                $this->verifySize(8, $size);
+                return array($this->decodeDouble($bytes), $newOffset);
+            case 'float':
+                $this->verifySize(4, $size);
+                return array($this->decodeFloat($bytes), $newOffset);
+            case 'bytes':
+                return array($bytes, $newOffset);
+            case 'uint16':
+            case 'uint32':
+                return array($this->decodeUint($bytes), $newOffset);
+            case 'int32':
+                return array($this->decodeInt32($bytes), $newOffset);
+            case 'uint64':
+            case 'uint128':
+                return array($this->decodeBigUint($bytes, $size), $newOffset);
+            default:
+                throw new InvalidDatabaseException(
+                    "Unknown or unexpected type: " . $type
+                );
+        }
+    }
+
+    private function verifySize($expected, $actual)
+    {
+        if ($expected != $actual) {
+            throw new InvalidDatabaseException(
+                "The MaxMind DB file's data section contains bad data (unknown data type or corrupt data)"
+            );
+        }
+    }
+
+    private function decodeArray($size, $offset)
+    {
+        $array = array();
+
+        for ($i = 0; $i < $size; $i++) {
+            list($value, $offset) = $this->decode($offset);
+            array_push($array, $value);
+        }
+
+        return array($array, $offset);
+    }
+
+    private function decodeBoolean($size)
+    {
+        return $size == 0 ? false : true;
+    }
+
+    private function decodeDouble($bits)
+    {
+        // XXX - Assumes IEEE 754 double on platform
+        list(, $double) = unpack('d', $this->maybeSwitchByteOrder($bits));
+        return $double;
+    }
+
+    private function decodeFloat($bits)
+    {
+        // XXX - Assumes IEEE 754 floats on platform
+        list(, $float) = unpack('f', $this->maybeSwitchByteOrder($bits));
+        return $float;
+    }
+
+    private function decodeInt32($bytes)
+    {
+        $bytes = $this->zeroPadLeft($bytes, 4);
+        list(, $int) = unpack('l', $this->maybeSwitchByteOrder($bytes));
+        return $int;
+    }
+
+    private function decodeMap($size, $offset)
+    {
+
+        $map = array();
+
+        for ($i = 0; $i < $size; $i++) {
+            list($key, $offset) = $this->decode($offset);
+            list($value, $offset) = $this->decode($offset);
+            $map[$key] = $value;
+        }
+
+        return array($map, $offset);
+    }
+
+    private $pointerValueOffset = array(
+        1 => 0,
+        2 => 2048,
+        3 => 526336,
+        4 => 0,
+    );
+
+    private function decodePointer($ctrlByte, $offset)
+    {
+        $pointerSize = (($ctrlByte >> 3) & 0x3) + 1;
+
+        $buffer = Util::read($this->fileStream, $offset, $pointerSize);
+        $offset = $offset + $pointerSize;
+
+        $packed = $pointerSize == 4
+            ? $buffer
+            : (pack('C', $ctrlByte & 0x7)) . $buffer;
+
+        $unpacked = $this->decodeUint($packed);
+        $pointer = $unpacked + $this->pointerBase
+            + $this->pointerValueOffset[$pointerSize];
+
+        return array($pointer, $offset);
+    }
+
+    private function decodeUint($bytes)
+    {
+        list(, $int) = unpack('N', $this->zeroPadLeft($bytes, 4));
+        return $int;
+    }
+
+    private function decodeBigUint($bytes, $byteLength)
+    {
+        $maxUintBytes = log(PHP_INT_MAX, 2) / 8;
+
+        if ($byteLength == 0) {
+            return 0;
+        }
+
+        $numberOfLongs = ceil($byteLength / 4);
+        $paddedLength = $numberOfLongs * 4;
+        $paddedBytes = $this->zeroPadLeft($bytes, $paddedLength);
+        $unpacked = array_merge(unpack("N$numberOfLongs", $paddedBytes));
+
+        $integer = 0;
+
+        // 2^32
+        $twoTo32 = '4294967296';
+
+        foreach ($unpacked as $part) {
+            // We only use gmp or bcmath if the final value is too big
+            if ($byteLength <= $maxUintBytes) {
+                $integer = ($integer << 32) + $part;
+            } elseif (extension_loaded('gmp')) {
+                $integer = gmp_strval(gmp_add(gmp_mul($integer, $twoTo32), $part));
+            } elseif (extension_loaded('bcmath')) {
+                $integer = bcadd(bcmul($integer, $twoTo32), $part);
+            } else {
+                throw new \RuntimeException(
+                    'The gmp or bcmath extension must be installed to read this database.'
+                );
+            }
+        }
+        return $integer;
+    }
+
+    private function decodeString($bytes)
+    {
+        // XXX - NOOP. As far as I know, the end user has to explicitly set the
+        // encoding in PHP. Strings are just bytes.
+        return $bytes;
+    }
+
+    private function sizeFromCtrlByte($ctrlByte, $offset)
+    {
+        $size = $ctrlByte & 0x1f;
+        $bytesToRead = $size < 29 ? 0 : $size - 28;
+        $bytes = Util::read($this->fileStream, $offset, $bytesToRead);
+        $decoded = $this->decodeUint($bytes);
+
+        if ($size == 29) {
+            $size = 29 + $decoded;
+        } elseif ($size == 30) {
+            $size = 285 + $decoded;
+        } elseif ($size > 30) {
+            $size = ($decoded & (0x0FFFFFFF >> (32 - (8 * $bytesToRead))))
+                + 65821;
+        }
+
+        return array($size, $offset + $bytesToRead);
+    }
+
+    private function zeroPadLeft($content, $desiredLength)
+    {
+        return str_pad($content, $desiredLength, "\x00", STR_PAD_LEFT);
+    }
+
+    private function maybeSwitchByteOrder($bytes)
+    {
+        return $this->switchByteOrder ? strrev($bytes) : $bytes;
+    }
+
+    private function isPlatformLittleEndian()
+    {
+        $testint = 0x00FF;
+        $packed = pack('S', $testint);
+        return $testint === current(unpack('v', $packed));
+    }
+}
diff --git a/lib/maxmind/MaxMind/Db/Reader/InvalidDatabaseException.php b/lib/maxmind/MaxMind/Db/Reader/InvalidDatabaseException.php
new file mode 100644 (file)
index 0000000..d2a9a77
--- /dev/null
@@ -0,0 +1,10 @@
+<?php
+
+namespace MaxMind\Db\Reader;
+
+/**
+ * This class should be thrown when unexpected data is found in the database.
+ */
+class InvalidDatabaseException extends \Exception
+{
+}
diff --git a/lib/maxmind/MaxMind/Db/Reader/Metadata.php b/lib/maxmind/MaxMind/Db/Reader/Metadata.php
new file mode 100644 (file)
index 0000000..3ac908b
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+
+namespace MaxMind\Db\Reader;
+
+/**
+ * This class provides the metadata for the MaxMind DB file.
+ *
+ * @property integer nodeCount This is an unsigned 32-bit integer indicating
+ * the number of nodes in the search tree.
+ *
+ * @property integer recordSize This is an unsigned 16-bit integer. It
+ * indicates the number of bits in a record in the search tree. Note that each
+ * node consists of two records.
+ *
+ * @property integer ipVersion This is an unsigned 16-bit integer which is
+ * always 4 or 6. It indicates whether the database contains IPv4 or IPv6
+ * address data.
+ *
+ * @property string databaseType This is a string that indicates the structure
+ * of each data record associated with an IP address. The actual definition of
+ * these structures is left up to the database creator.
+ *
+ * @property array languages An array of strings, each of which is a language
+ * code. A given record may contain data items that have been localized to
+ * some or all of these languages. This may be undefined.
+ *
+ * @property integer binaryFormatMajorVersion This is an unsigned 16-bit
+ * integer indicating the major version number for the database's binary
+ * format.
+ *
+ * @property integer binaryFormatMinorVersion This is an unsigned 16-bit
+ * integer indicating the minor version number for the database's binary format.
+ *
+ * @property integer buildEpoch This is an unsigned 64-bit integer that
+ * contains the database build timestamp as a Unix epoch value.
+ *
+ * @property array description This key will always point to a map
+ * (associative array). The keys of that map will be language codes, and the
+ * values will be a description in that language as a UTF-8 string. May be
+ * undefined for some databases.
+ */
+class Metadata
+{
+    private $binaryFormatMajorVersion;
+    private $binaryFormatMinorVersion;
+    private $buildEpoch;
+    private $databaseType;
+    private $description;
+    private $ipVersion;
+    private $languages;
+    private $nodeByteSize;
+    private $nodeCount;
+    private $recordSize;
+    private $searchTreeSize;
+
+    public function __construct($metadata)
+    {
+        $this->binaryFormatMajorVersion =
+            $metadata['binary_format_major_version'];
+        $this->binaryFormatMinorVersion =
+            $metadata['binary_format_minor_version'];
+        $this->buildEpoch = $metadata['build_epoch'];
+        $this->databaseType = $metadata['database_type'];
+        $this->languages = $metadata['languages'];
+        $this->description = $metadata['description'];
+        $this->ipVersion = $metadata['ip_version'];
+        $this->nodeCount = $metadata['node_count'];
+        $this->recordSize = $metadata['record_size'];
+        $this->nodeByteSize = $this->recordSize / 4;
+        $this->searchTreeSize = $this->nodeCount * $this->nodeByteSize;
+    }
+
+    public function __get($var)
+    {
+        return $this->$var;
+    }
+}
diff --git a/lib/maxmind/MaxMind/Db/Reader/Util.php b/lib/maxmind/MaxMind/Db/Reader/Util.php
new file mode 100644 (file)
index 0000000..dc8ec80
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+
+namespace MaxMind\Db\Reader;
+
+use MaxMind\Db\Reader\InvalidDatabaseException;
+
+class Util
+{
+    public static function read($stream, $offset, $numberOfBytes)
+    {
+        if ($numberOfBytes == 0) {
+            return '';
+        }
+        if (fseek($stream, $offset) == 0) {
+            $value = fread($stream, $numberOfBytes);
+
+            // We check that the number of bytes read is equal to the number
+            // asked for. We use ftell as getting the length of $value is
+            // much slower.
+            if (ftell($stream) - $offset === $numberOfBytes) {
+                return $value;
+            }
+        }
+        throw new InvalidDatabaseException(
+            "The MaxMind DB file contains bad data"
+        );
+    }
+}
diff --git a/lib/maxmind/README_moodle.txt b/lib/maxmind/README_moodle.txt
new file mode 100644 (file)
index 0000000..e9a5bf3
--- /dev/null
@@ -0,0 +1,30 @@
+GeoIP2 PHP API
+==============
+
+No changes from the upstream version have been made, it is recommended by upstream
+to install these depdencies via composer - but the composer installation is bundled
+with a load of test files, shell scripts etc (and we don't use composer to manage
+'production depdendencies') so we have to do it manually.
+
+Information
+-----------
+
+URL: http://maxmind.github.io/GeoIP2-php/
+License: Apache License, Version 2.0.
+
+Installation
+------------
+
+1) Download the latest versions of GeoIP2-php and MaxMind-DB-Reader-php
+wget https://github.com/maxmind/GeoIP2-php/archive/v2.4.2.zip
+wget https://github.com/maxmind/MaxMind-DB-Reader-php/archive/v1.1.0.zip
+
+2) Unzip the archives
+unzip v2.4.2.zip
+unzip v1.1.0.zip
+
+3) Move the source code directories into place
+mv GeoIP2-php-2.4.2/src/ /path/to/moodle/lib/maxmind/GeoIp2/
+mv MaxMind-DB-Reader-php-1.1.0/src/MaxMind/ /path/to/moodle/lib/maxmind/MaxMind/
+
+4) Run unit tests on iplookup/tests/geoip_test.php with PHPUNIT_LONGTEST defined.
index fc0fc31..0977ec1 100644 (file)
@@ -8641,8 +8641,6 @@ function getremoteaddr($default='0.0.0.0') {
 function cleanremoteaddr($addr, $compress=false) {
     $addr = trim($addr);
 
-    // TODO: maybe add a separate function is_addr_public() or something like this.
-
     if (strpos($addr, ':') !== false) {
         // Can be only IPv6.
         $parts = explode(':', $addr);
@@ -8735,6 +8733,17 @@ function cleanremoteaddr($addr, $compress=false) {
     return implode('.', $parts);
 }
 
+
+/**
+ * Is IP address a public address?
+ *
+ * @param string $ip The ip to check
+ * @return bool true if the ip is public
+ */
+function ip_is_public($ip) {
+    return (bool) filter_var($ip, FILTER_VALIDATE_IP, (FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE));
+}
+
 /**
  * This function will make a complete copy of anything it's given,
  * regardless of whether it's an object or not.
index 11e42fa..1bcc92d 100644 (file)
@@ -488,8 +488,8 @@ class theme_config {
         $this->name     = $config->name;
         $this->dir      = $config->dir;
 
-        if ($this->name != 'base') {
-            $baseconfig = theme_config::find_theme_config('base', $this->settings);
+        if ($this->name != 'bootstrapbase') {
+            $baseconfig = theme_config::find_theme_config('bootstrapbase', $this->settings);
         } else {
             $baseconfig = $config;
         }
@@ -510,9 +510,7 @@ class theme_config {
 
         // verify all parents and load configs and renderers
         foreach ($this->parents as $parent) {
-            if ($parent == 'base') {
-                $parent_config = $baseconfig;
-            } else if (!$parent_config = theme_config::find_theme_config($parent, $this->settings)) {
+            if (!$parent_config = theme_config::find_theme_config($parent, $this->settings)) {
                 // this is not good - better exclude faulty parents
                 continue;
             }
@@ -1947,8 +1945,8 @@ class theme_config {
             }
         }
 
-        // Last resort, try the base theme for names
-        return get_string('region-' . $region, 'theme_base');
+        // Last resort, try the bootstrapbase theme for names
+        return get_string('region-' . $region, 'theme_bootstrapbase');
     }
 
     /**
diff --git a/lib/pear/Net/GeoIP.php b/lib/pear/Net/GeoIP.php
deleted file mode 100644 (file)
index f3c48c6..0000000
+++ /dev/null
@@ -1,904 +0,0 @@
-<?php
-/**
- * +----------------------------------------------------------------------+
- * | PHP version 5                                                        |
- * +----------------------------------------------------------------------+
- * | Copyright (C) 2004 MaxMind LLC                                       |
- * +----------------------------------------------------------------------+
- * | 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; if not, write to the Free Software  |
- * | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 |
- * | USA, or view it online at http://www.gnu.org/licenses/lgpl.txt.      |
- * +----------------------------------------------------------------------+
- * | Authors: Jim Winstead <jimw@apache.org> (original Maxmind version)   |
- * |          Hans Lellelid <hans@xmpl.org>                               |
- * +----------------------------------------------------------------------+
- *
- * @category Net
- * @package  Net_GeoIP
- * @author   Jim Winstead <jimw@apache.org> (original Maxmind PHP API)
- * @author   Hans Lellelid <hans@xmpl.org>
- * @license  LGPL http://www.gnu.org/licenses/lgpl.txt
- * @link     http://pear.php.net/package/Net_GeoIp
- * $Id$
- */
-
-require_once 'PEAR/Exception.php';
-
-/**
- * GeoIP class provides an API for performing geo-location lookups based on IP
- * address.
- *
- * To use this class you must have a [binary version] GeoIP database. There is
- * a free GeoIP country database which can be obtained from Maxmind:
- * {@link http://www.maxmind.com/app/geoip_country}
- *
- *
- * <b>SIMPLE USE</b>
- *
- *
- * Create an instance:
- *
- * <code>
- * $geoip = Net_GeoIP::getInstance('/path/to/geoipdb.dat', Net_GeoIP::SHARED_MEMORY);
- * </code>
- *
- * Depending on which database you are using (free, or one of paid versions)
- * you must use appropriate lookup method:
- *
- * <code>
- * // for free country db:
- * $country_name = $geoip->lookupCountryName($_SERVER['REMOTE_ADDR']);
- * $country_code = $geoip->lookupCountryCode($_SERVER['REMOTE_ADDR']);
- *
- * // for [non-free] region db:
- * list($ctry_code, $region) = $geoip->lookupRegion($_SERVER['REMOTE_ADDR']);
- *
- * // for [non-free] city db:
- * $location = $geoip->lookupLocation($_SERVER['REMOTE_ADDR']);
- * print "city: " . $location->city . ", " . $location->region;
- * print "lat: " . $location->latitude . ", long: " . $location->longitude;
- *
- * // for organization or ISP db:
- * $org_or_isp_name = $geoip->lookupOrg($_SERVER['REMOTE_ADDR']);
- * </code>
- *
- *
- * <b>MULTIPLE INSTANCES</b>
- *
- *
- * You can have several instances of this class, one for each database file
- * you are using.  You should use the static getInstance() singleton method
- * to save on overhead of setting up database segments.  Note that only one
- * instance is stored per filename, and any flags will be ignored if an
- * instance already exists for the specifiedfilename.
- *
- * <b>Special note on using SHARED_MEMORY flag</b>
- *
- * If you are using SHARED_MEMORY (shmop) you can only use SHARED_MEMORY for
- * one (1) instance  (i.e. for one database). Any subsequent attempts to
- * instantiate using SHARED_MEMORY will read the same shared memory block
- * already initialized, and therefore will cause problems since the expected
- * database format won't match the database in the shared memory block.
- *
- * Note that there is no easy way to flag "nice errors" to prevent attempts
- * to create new instances using SHARED_MEMORY flag and it is also not posible
- * (in a safe way) to allow new instances to overwrite the shared memory block.
- *
- * In short, is you are using multiple databses, use the SHARED_MEMORY flag
- * with care.
- *
- *
- * <b>LOOKUPS ON HOSTNAMES</b>
- *
- *
- * Note that this PHP API does NOT support lookups on hostnames.  This is so
- * that the public API can be kept simple and so that the lookup functions
- * don't need to try name lookups if IP lookup fails (which would be the only
- * way to keep the API simple and support name-based lookups).
- *
- * If you do not know the IP address, you can convert an name to IP very
- * simply using PHP native functions or other libraries:
- *
- * <code>
- *     $geoip->lookupCountryName(gethostbyname('www.sunset.se'));
- * </code>
- *
- * Or, if you don't know whether an address is a name or ip address, use
- * application-level logic:
- *
- * <code>
- * if (ip2long($ip_or_name) === false) {
- *   $ip = gethostbyname($ip_or_name);
- * } else {
- *   $ip = $ip_or_name;
- * }
- * $ctry = $geoip->lookupCountryName($ip);
- * </code>
- *
- * @category Net
- * @package  Net_GeoIP
- * @author   Jim Winstead <jimw@apache.org> (original Maxmind PHP API)
- * @author   Hans Lellelid <hans@xmpl.org>
- * @license  LGPL http://www.gnu.org/licenses/lgpl.txt
- * @link     http://pear.php.net/package/Net_GeoIp
- */
-class Net_GeoIP
-{
-    /**
-     * Exception error code used for invalid IP address.
-     */
-    const ERR_INVALID_IP =  218624992; // crc32('Net_GeoIP::ERR_INVALID_IP')
-
-    /**
-     * Exception error code when there is a DB-format-related error.
-     */
-    const ERR_DB_FORMAT = 866184008; // crc32('Net_GeoIP::ERR_DB_FORMAT')
-
-    public static $COUNTRY_CODES = array(
-      "", "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"
-        );
-
-    public static $COUNTRY_CODES3 = array(
-    "","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","TLS","TKM","TUN","TON","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"
-        );
-
-    public static $COUNTRY_NAMES = array(
-        "", "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",
-        "Kazakstan", "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",
-        "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 Islands", "Puerto Rico", "Palestinian Territory",
-        "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", "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.",
-        "Vietnam", "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"
-        );
-
-    // storage / caching flags
-    const STANDARD = 0;
-    const MEMORY_CACHE = 1;
-    const SHARED_MEMORY = 2;
-
-    // Database structure constants
-    const COUNTRY_BEGIN = 16776960;
-    const STATE_BEGIN_REV0 = 16700000;
-    const STATE_BEGIN_REV1 = 16000000;
-
-    const STRUCTURE_INFO_MAX_SIZE = 20;
-    const DATABASE_INFO_MAX_SIZE = 100;
-    const COUNTRY_EDITION = 106;
-    const REGION_EDITION_REV0 = 112;
-    const REGION_EDITION_REV1 = 3;
-    const CITY_EDITION_REV0 = 111;
-    const CITY_EDITION_REV1 = 2;
-    const ORG_EDITION = 110;
-    const SEGMENT_RECORD_LENGTH = 3;
-    const STANDARD_RECORD_LENGTH = 3;
-    const ORG_RECORD_LENGTH = 4;
-    const MAX_RECORD_LENGTH = 4;
-    const MAX_ORG_RECORD_LENGTH = 300;
-    const FULL_RECORD_LENGTH = 50;
-
-    const US_OFFSET = 1;
-    const CANADA_OFFSET = 677;
-    const WORLD_OFFSET = 1353;
-    const FIPS_RANGE = 360;
-
-    // SHMOP memory address
-    const SHM_KEY = 0x4f415401;
-
-    /**
-     * @var int
-     */
-    private $flags = 0;
-
-    /**
-     * @var resource
-     */
-    private $filehandle;
-
-    /**
-     * @var string
-     */
-    private $memoryBuffer;
-
-    /**
-     * @var int
-     */
-    private $databaseType;
-
-    /**
-     * @var int
-     */
-    private $databaseSegments;
-
-    /**
-     * @var int
-     */
-    private $recordLength;
-
-    /**
-     * The memory addr "id" for use with SHMOP.
-     * @var int
-     */
-    private $shmid;
-
-    /**
-     * Support for singleton pattern.
-     * @var array
-     */
-    private static $instances = array();
-
-    /**
-     * Construct a Net_GeoIP instance.
-     * You should use the getInstance() method if you plan to use multiple databases or
-     * the same database from several different places in your script.
-     *
-     * @param string $filename Path to binary geoip database.
-     * @param int    $flags    Flags
-     *
-     * @see getInstance()
-     */
-    public function __construct($filename = null, $flags = null)
-    {
-        if ($filename !== null) {
-            $this->open($filename, $flags);
-        }
-        // store the instance, so that it will be returned by a call to
-        // getInstance() (with the same db filename).
-        self::$instances[$filename] = $this;
-    }
-
-    /**
-     * Calls the close() function to free any resources.
-     * @see close()
-     *
-     * COMMENTED OUT TO ADDRESS BUG IN PHP 5.0.4, 5.0.5dev.  THIS RESOURCE
-     * SHOULD AUTOMATICALLY BE FREED AT SCRIPT CLOSE, SO A DESTRUCTOR
-     * IS A GOOD IDEA BUT NOT NECESSARILY A NECESSITY.
-    public function __destruct()
-    {
-        $this->close();
-    }
-    */
-
-    /**
-     * Singleton method, use this to get an instance and avoid re-parsing the db.
-     *
-     * Unique instances are instantiated based on the filename of the db. The flags
-     * are ignored -- in that requests to for instance with same filename but different
-     * flags will return the already-instantiated instance.  For example:
-     * <code>
-     * // create new instance with memory_cache enabled
-     * $geoip = Net_GeoIP::getInstance('C:\mydb.dat', Net_GeoIP::MEMORY_CACHE);
-     * ....
-     *
-     * // later in code, request instance with no flags specified.
-     * $geoip = Net_GeoIP::getInstance('C:\mydb.dat');
-     *
-     * // Normally this means no MEMORY_CACHE but since an instance
-     * // with memory cache enabled has already been created for 'C:\mydb.dat', the
-     * // existing instance (with memory cache) will be returned.
-     * </code>
-     *
-     * NOTE: You can only use SHARED_MEMORY flag for one instance!  Any subsquent instances
-     * that attempt to use the SHARED_MEMORY will use the *same* shared memory, which will break
-     * your script.
-     *
-     * @param string $filename Filename
-     * @param int    $flags    Flags that control class behavior.
-     *          + Net_GeoIp::SHARED_MEMORY
-     *             Use SHMOP to share a db among multiple PHP instances.
-     *             NOTE: ONLY ONE GEOIP INSTANCE CAN USE SHARED MEMORY!!!
-     *          + Net_GeoIp::MEMORY_CACHE
-     *             Store the full contents of the database in memory for current script.
-     *             This is useful if you access the database several times in a script.
-     *          + Net_GeoIp::STANDARD
-     *             [default] standard no-cache version.
-     *
-     * @return Net_GeoIP
-     */
-    public static function getInstance($filename = null, $flags = null)
-    {
-        if (!isset(self::$instances[$filename])) {
-            self::$instances[$filename] = new Net_GeoIP($filename, $flags);
-        }
-        return self::$instances[$filename];
-    }
-
-    /**
-     * Opens geoip database at filename and with specified flags.
-     *
-     * @param string $filename File to open
-     * @param int    $flags    Flags
-     *
-     * @return void
-     *
-     * @throws PEAR_Exception if unable to open specified file or shared memory.
-     */
-    public function open($filename, $flags = null)
-    {
-        if ($flags !== null) {
-            $this->flags = $flags;
-        }
-        if ($this->flags & self::SHARED_MEMORY) {
-            $this->shmid = @shmop_open(self::SHM_KEY, "a", 0, 0);
-            if ($this->shmid === false) {
-                $this->loadSharedMemory($filename);
-                $this->shmid = @shmop_open(self::SHM_KEY, "a", 0, 0);
-                if ($this->shmid === false) { // should never be false as loadSharedMemory() will throw Exc if cannot create
-                    throw new PEAR_Exception("Unable to open shared memory at key: " . dechex(self::SHM_KEY));
-                }
-            }
-        } else {
-            $this->filehandle = fopen($filename, "rb");
-            if (!$this->filehandle) {
-                throw new PEAR_Exception("Unable to open file: $filename");
-            }
-            if ($this->flags & self::MEMORY_CACHE) {
-                $s_array = fstat($this->filehandle);
-                $this->memoryBuffer = fread($this->filehandle, $s_array['size']);
-            }
-        }
-        $this->setupSegments();
-    }
-
-    /**
-     * Loads the database file into shared memory.
-     *
-     * @param string $filename Path to database file to read into shared memory.
-     *
-     * @return void
-     *
-     * @throws PEAR_Exception     - if unable to read the db file.
-     */
-    protected function loadSharedMemory($filename)
-    {
-        $fp = fopen($filename, "rb");
-        if (!$fp) {
-            throw new PEAR_Exception("Unable to open file: $filename");
-        }
-        $s_array = fstat($fp);
-        $size = $s_array['size'];
-
-        if ($shmid = @shmop_open(self::SHM_KEY, "w", 0, 0)) {
-            shmop_delete($shmid);
-            shmop_close($shmid);
-        }
-
-        if ($shmid = @shmop_open(self::SHM_KEY, "c", 0644, $size)) {
-            $offset = 0;
-            while ($offset < $size) {
-                $buf = fread($fp, 524288);
-                shmop_write($shmid, $buf, $offset);
-                $offset += 524288;
-            }
-            shmop_close($shmid);
-        }
-
-        fclose($fp);
-    }
-
-    /**
-     * Parses the database file to determine what kind of database is being used and setup
-     * segment sizes and start points that will be used by the seek*() methods later.
-     *
-     * @return void
-     */
-    protected function setupSegments()
-    {
-
-        $this->databaseType = self::COUNTRY_EDITION;
-        $this->recordLength = self::STANDARD_RECORD_LENGTH;
-
-        if ($this->flags & self::SHARED_MEMORY) {
-
-            $offset = shmop_size($this->shmid) - 3;
-            for ($i = 0; $i < self::STRUCTURE_INFO_MAX_SIZE; $i++) {
-                $delim = shmop_read($this->shmid, $offset, 3);
-                $offset += 3;
-                if ($delim == (chr(255).chr(255).chr(255))) {
-                    $this->databaseType = ord(shmop_read($this->shmid, $offset, 1));
-                    $offset++;
-                    if ($this->databaseType === self::REGION_EDITION_REV0) {
-                        $this->databaseSegments = self::STATE_BEGIN_REV0;
-                    } elseif ($this->databaseType === self::REGION_EDITION_REV1) {
-                        $this->databaseSegments = self::STATE_BEGIN_REV1;
-                    } elseif (($this->databaseType === self::CITY_EDITION_REV0)
-                                || ($this->databaseType === self::CITY_EDITION_REV1)
-                                || ($this->databaseType === self::ORG_EDITION)) {
-                        $this->databaseSegments = 0;
-                        $buf = shmop_read($this->shmid, $offset, self::SEGMENT_RECORD_LENGTH);
-                        for ($j = 0; $j < self::SEGMENT_RECORD_LENGTH; $j++) {
-                            $this->databaseSegments += (ord($buf[$j]) << ($j * 8));
-                        }
-                        if ($this->databaseType === self::ORG_EDITION) {
-                            $this->recordLength = self::ORG_RECORD_LENGTH;
-                        }
-                    }
-                    break;
-                } else {
-                    $offset -= 4;
-                }
-            }
-            if ($this->databaseType == self::COUNTRY_EDITION) {
-                $this->databaseSegments = self::COUNTRY_BEGIN;
-            }
-
-        } else {
-
-            $filepos = ftell($this->filehandle);
-            fseek($this->filehandle, -3, SEEK_END);
-            for ($i = 0; $i < self::STRUCTURE_INFO_MAX_SIZE; $i++) {
-                $delim = fread($this->filehandle, 3);
-                if ($delim == (chr(255).chr(255).chr(255))) {
-                    $this->databaseType = ord(fread($this->filehandle, 1));
-                    if ($this->databaseType === self::REGION_EDITION_REV0) {
-                        $this->databaseSegments = self::STATE_BEGIN_REV0;
-                    } elseif ($this->databaseType === self::REGION_EDITION_REV1) {
-                        $this->databaseSegments = self::STATE_BEGIN_REV1;
-                    } elseif ($this->databaseType === self::CITY_EDITION_REV0
-                                || $this->databaseType === self::CITY_EDITION_REV1
-                                || $this->databaseType === self::ORG_EDITION) {
-                        $this->databaseSegments = 0;
-                        $buf = fread($this->filehandle, self::SEGMENT_RECORD_LENGTH);
-                        for ($j = 0; $j < self::SEGMENT_RECORD_LENGTH; $j++) {
-                            $this->databaseSegments += (ord($buf[$j]) << ($j * 8));
-                        }
-                        if ($this->databaseType === self::ORG_EDITION) {
-                            $this->recordLength = self::ORG_RECORD_LENGTH;
-                        }
-                    }
-                    break;
-                } else {
-                    fseek($this->filehandle, -4, SEEK_CUR);
-                }
-            }
-            if ($this->databaseType === self::COUNTRY_EDITION) {
-                $this->databaseSegments = self::COUNTRY_BEGIN;
-            }
-            fseek($this->filehandle, $filepos, SEEK_SET);
-
-        }
-    }
-
-    /**
-     * Closes the geoip database.
-     *
-     * @return int Status of close command.
-     */
-    public function close()
-    {
-        if ($this->flags & self::SHARED_MEMORY) {
-            return shmop_close($this->shmid);
-        } else {
-            // right now even if file was cached in RAM the file was not closed
-            // so it's safe to expect no error w/ fclose()
-            return fclose($this->filehandle);
-        }
-    }
-
-    /**
-     * Get the country index.
-     *
-     * This method is called by the lookupCountryCode() and lookupCountryName()
-     * methods.  It lookups up the index ('id') for the country which is the key
-     * for the code and name.
-     *
-     * @param string $addr IP address (hostname not allowed)
-     *
-     * @throws PEAR_Exception  - if IP address is invalid.
-     *                         - if database type is incorrect
-     *
-     * @return string ID for the country
-     */
-    protected function lookupCountryId($addr)
-    {
-        $ipnum = ip2long($addr);
-        if ($ipnum === false) {
-            throw new PEAR_Exception("Invalid IP address: " . var_export($addr, true), self::ERR_INVALID_IP);
-        }
-        if ($this->databaseType !== self::COUNTRY_EDITION) {
-            throw new PEAR_Exception("Invalid database type; lookupCountry*() methods expect Country database.");
-        }
-        return $this->seekCountry($ipnum) - self::COUNTRY_BEGIN;
-    }
-
-    /**
-     * Returns 2-letter country code (e.g. 'CA') for specified IP address.
-     * Use this method if you have a Country database.
-     *
-     * @param string $addr IP address (hostname not allowed).
-     *
-     * @return string 2-letter country code
-     *
-     * @throws PEAR_Exception (see lookupCountryId())
-     * @see lookupCountryId()
-     */
-    public function lookupCountryCode($addr)
-    {
-        return self::$COUNTRY_CODES[$this->lookupCountryId($addr)];
-    }
-
-    /**
-     * Returns full country name for specified IP address.
-     * Use this method if you have a Country database.
-     *
-     * @param string $addr IP address (hostname not allowed).
-     *
-     * @return string Country name
-     * @throws PEAR_Exception (see lookupCountryId())
-     * @see lookupCountryId()
-     */
-    public function lookupCountryName($addr)
-    {
-        return self::$COUNTRY_NAMES[$this->lookupCountryId($addr)];
-    }
-
-    /**
-     * Using the record length and appropriate start points, seek to the country that corresponds
-     * to the converted IP address integer.
-     *
-     * @param int $ipnum Result of ip2long() conversion.
-     *
-     * @return int Offset of start of record.
-     * @throws PEAR_Exception - if fseek() fails on the file or no results after traversing the database (indicating corrupt db).
-     */
-    protected function seekCountry($ipnum)
-    {
-        $offset = 0;
-        for ($depth = 31; $depth >= 0; --$depth) {
-            if ($this->flags & self::MEMORY_CACHE) {
-                  $buf = substr($this->memoryBuffer, 2 * $this->recordLength * $offset, 2 * $this->recordLength);
-            } elseif ($this->flags & self::SHARED_MEMORY) {
-                $buf = shmop_read($this->shmid, 2 * $this->recordLength * $offset, 2 * $this->recordLength);
-            } else {
-                if (fseek($this->filehandle, 2 * $this->recordLength * $offset, SEEK_SET) !== 0) {
-                    throw new PEAR_Exception("fseek failed");
-                }
-                $buf = fread($this->filehandle, 2 * $this->recordLength);
-            }
-            $x = array(0,0);
-            for ($i = 0; $i < 2; ++$i) {
-                for ($j = 0; $j < $this->recordLength; ++$j) {
-                    $x[$i] += ord($buf[$this->recordLength * $i + $j]) << ($j * 8);
-                }
-            }
-            if ($ipnum & (1 << $depth)) {
-                if ($x[1] >= $this->databaseSegments) {
-                    return $x[1];
-                }
-                $offset = $x[1];
-            } else {
-                if ($x[0] >= $this->databaseSegments) {
-                    return $x[0];
-                }
-                $offset = $x[0];
-            }
-        }
-        throw new PEAR_Exception("Error traversing database - perhaps it is corrupt?");
-    }
-
-    /**
-     * Lookup the organization (or ISP) for given IP address.
-     * Use this method if you have an Organization/ISP database.
-     *
-     * @param string $addr IP address (hostname not allowed).
-     *
-     * @throws PEAR_Exception  - if IP address is invalid.
-     *                         - if database is of wrong type
-     *
-     * @return string The organization
-     */
-    public function lookupOrg($addr)
-    {
-        $ipnum = ip2long($addr);
-        if ($ipnum === false) {
-            throw new PEAR_Exception("Invalid IP address: " . var_export($addr, true), self::ERR_INVALID_IP);
-        }
-        if ($this->databaseType !== self::ORG_EDITION) {
-            throw new PEAR_Exception("Invalid database type; lookupOrg() method expects Org/ISP database.", self::ERR_DB_FORMAT);
-        }
-        return $this->getOrg($ipnum);
-    }
-
-    /**
-     * Lookup the region for given IP address.
-     * Use this method if you have a Region database.
-     *
-     * @param string $addr IP address (hostname not allowed).
-     *
-     * @return array Array containing country code and region: array($country_code, $region)
-     *
-     * @throws PEAR_Exception - if IP address is invalid.
-     */
-    public function lookupRegion($addr)
-    {
-        $ipnum = ip2long($addr);
-        if ($ipnum === false) {
-            throw new PEAR_Exception("Invalid IP address: " . var_export($addr, true), self::ERR_INVALID_IP);
-        }
-        if ($this->databaseType !== self::REGION_EDITION_REV0 && $this->databaseType !== self::REGION_EDITION_REV1) {
-            throw new PEAR_Exception("Invalid database type; lookupRegion() method expects Region database.", self::ERR_DB_FORMAT);
-        }
-        return $this->getRegion($ipnum);
-    }
-
-    /**
-     * Lookup the location record for given IP address.
-     * Use this method if you have a City database.
-     *
-     * @param string $addr IP address (hostname not allowed).
-     *
-     * @return Net_GeoIP_Location The full location record.
-     *
-     * @throws PEAR_Exception - if IP address is invalid.
-     */
-    public function lookupLocation($addr)
-    {
-        include_once 'Net/GeoIP/Location.php';
-        $ipnum = ip2long($addr);
-        if ($ipnum === false) {
-            throw new PEAR_Exception("Invalid IP address: " . var_export($addr, true), self::ERR_INVALID_IP);
-        }
-        if ($this->databaseType !== self::CITY_EDITION_REV0 && $this->databaseType !== self::CITY_EDITION_REV1) {
-            throw new PEAR_Exception("Invalid database type; lookupLocation() method expects City database.");
-        }
-        return $this->getRecord($ipnum);
-    }
-
-    /**
-     * Seek and return organization (or ISP) name for converted IP addr.
-     *
-     * @param int $ipnum Converted IP address.
-     *
-     * @return string The organization
-     */
-    protected function getOrg($ipnum)
-    {
-        $seek_org = $this->seekCountry($ipnum);
-        if ($seek_org == $this->databaseSegments) {
-            return null;
-        }
-        $record_pointer = $seek_org + (2 * $this->recordLength - 1) * $this->databaseSegments;
-        if ($this->flags & self::SHARED_MEMORY) {
-            $org_buf = shmop_read($this->shmid, $record_pointer, self::MAX_ORG_RECORD_LENGTH);
-        } else {
-            fseek($this->filehandle, $record_pointer, SEEK_SET);
-            $org_buf = fread($this->filehandle, self::MAX_ORG_RECORD_LENGTH);
-        }
-        $org_buf = substr($org_buf, 0, strpos($org_buf, 0));
-        return $org_buf;
-    }
-
-    /**
-     * Seek and return the region info (array containing country code and region name) for converted IP addr.
-     *
-     * @param int $ipnum Converted IP address.
-     *
-     * @return array Array containing country code and region: array($country_code, $region)
-     */
-    protected function getRegion($ipnum)
-    {
-        if ($this->databaseType == self::REGION_EDITION_REV0) {
-            $seek_region = $this->seekCountry($ipnum) - self::STATE_BEGIN_REV0;
-            if ($seek_region >= 1000) {
-                $country_code = "US";
-                $region = chr(($seek_region - 1000)/26 + 65) . chr(($seek_region - 1000)%26 + 65);
-            } else {
-                $country_code = self::$COUNTRY_CODES[$seek_region];
-                $region = "";
-            }
-            return array($country_code, $region);
-        } elseif ($this->databaseType == self::REGION_EDITION_REV1) {
-            $seek_region = $this->seekCountry($ipnum) - self::STATE_BEGIN_REV1;
-            //print $seek_region;
-            if ($seek_region < self::US_OFFSET) {
-                $country_code = "";
-                $region = "";
-            } elseif ($seek_region < self::CANADA_OFFSET) {
-                $country_code = "US";
-                $region = chr(($seek_region - self::US_OFFSET)/26 + 65) . chr(($seek_region - self::US_OFFSET)%26 + 65);
-            } elseif ($seek_region < self::WORLD_OFFSET) {
-                $country_code = "CA";
-                $region = chr(($seek_region - self::CANADA_OFFSET)/26 + 65) . chr(($seek_region - self::CANADA_OFFSET)%26 + 65);
-            } else {
-                $country_code = self::$COUNTRY_CODES[($seek_region - self::WORLD_OFFSET) / self::FIPS_RANGE];
-                $region = "";
-            }
-            return array ($country_code,$region);
-        }
-    }
-
-    /**
-     * Seek and populate Net_GeoIP_Location object for converted IP addr.
-     * Note: this
-     *
-     * @param int $ipnum Converted IP address.
-     *
-     * @return Net_GeoIP_Location
-     */
-    protected function getRecord($ipnum)
-    {
-        $seek_country = $this->seekCountry($ipnum);
-        if ($seek_country == $this->databaseSegments) {
-            return null;
-        }
-
-        $record_pointer = $seek_country + (2 * $this->recordLength - 1) * $this->databaseSegments;
-
-        if ($this->flags & self::SHARED_MEMORY) {
-            $record_buf = shmop_read($this->shmid, $record_pointer, self::FULL_RECORD_LENGTH);
-        } else {
-            fseek($this->filehandle, $record_pointer, SEEK_SET);
-            $record_buf = fread($this->filehandle, self::FULL_RECORD_LENGTH);
-        }
-
-        $record = new Net_GeoIP_Location();
-
-        $record_buf_pos = 0;
-        $char = ord(substr($record_buf, $record_buf_pos, 1));
-
-        $record->countryCode  = self::$COUNTRY_CODES[$char];
-        $record->countryCode3 = self::$COUNTRY_CODES3[$char];
-        $record->countryName  = self::$COUNTRY_NAMES[$char];
-        $record_buf_pos++;
-        $str_length = 0;
-
-        //get region
-        $char = ord(substr($record_buf, $record_buf_pos+$str_length, 1));
-        while ($char != 0) {
-            $str_length++;
-            $char = ord(substr($record_buf, $record_buf_pos+$str_length, 1));
-        }
-        if ($str_length > 0) {
-            $record->region = substr($record_buf, $record_buf_pos, $str_length);
-        }
-        $record_buf_pos += $str_length + 1;
-        $str_length = 0;
-
-        //get city
-        $char = ord(substr($record_buf, $record_buf_pos+$str_length, 1));
-        while ($char != 0) {
-            $str_length++;
-            $char = ord(substr($record_buf, $record_buf_pos+$str_length, 1));
-        }
-        if ($str_length > 0) {
-            $record->city = substr($record_buf, $record_buf_pos, $str_length);
-        }
-        $record_buf_pos += $str_length + 1;
-        $str_length = 0;
-
-        //get postal code
-        $char = ord(substr($record_buf, $record_buf_pos+$str_length, 1));
-        while ($char != 0) {
-            $str_length++;
-            $char = ord(substr($record_buf, $record_buf_pos+$str_length, 1));
-        }
-        if ($str_length > 0) {
-            $record->postalCode = substr($record_buf, $record_buf_pos, $str_length);
-        }
-        $record_buf_pos += $str_length + 1;
-        $str_length = 0;
-        $latitude   = 0;
-        $longitude  = 0;
-        for ($j = 0;$j < 3; ++$j) {
-            $char = ord(substr($record_buf, $record_buf_pos++, 1));
-            $latitude += ($char << ($j * 8));
-        }
-        $record->latitude = ($latitude/10000) - 180;
-
-        for ($j = 0;$j < 3; ++$j) {
-            $char = ord(substr($record_buf, $record_buf_pos++, 1));
-            $longitude += ($char << ($j * 8));
-        }
-        $record->longitude = ($longitude/10000) - 180;
-
-        if ($this->databaseType === self::CITY_EDITION_REV1) {
-            $dmaarea_combo = 0;
-            if ($record->countryCode == "US") {
-                for ($j = 0;$j < 3;++$j) {
-                    $char = ord(substr($record_buf, $record_buf_pos++, 1));
-                    $dmaarea_combo += ($char << ($j * 8));
-                }
-                $record->dmaCode = floor($dmaarea_combo/1000);
-                $record->areaCode = $dmaarea_combo%1000;
-            }
-        }
-
-        return $record;
-    }
-
-}
-
diff --git a/lib/pear/Net/GeoIP/DMA.php b/lib/pear/Net/GeoIP/DMA.php
deleted file mode 100644 (file)
index 253f7b5..0000000
+++ /dev/null
@@ -1,315 +0,0 @@
-<?php
-/**
- * +----------------------------------------------------------------------+
- * | PHP version 5                                                        |
- * +----------------------------------------------------------------------+
- * | Copyright (C) 2004 MaxMind LLC                                       |
- * +----------------------------------------------------------------------+
- * | 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; if not, write to the Free Software  |
- * | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 |
- * | USA, or view it online at http://www.gnu.org/licenses/lgpl.txt.      |
- * +----------------------------------------------------------------------+
- * | Authors: Jim Winstead <jimw@apache.org> (original Maxmind version)   |
- * |          Hans Lellelid <hans@xmpl.org>                               |
- * +----------------------------------------------------------------------+
- *
- * @category Net
- * @package  Net_GeoIP
- * @author   Hans Lellelid <hans@xmpl.org>
- * @license  LGPL http://www.gnu.org/licenses/lgpl.txt
- * @link     http://pear.php.net/package/Net_GeoIp
- * $Id$
- */
-
-/**
- * Static class to handle mapping of DMA codes to metro regions.
- * 
- * Use this class with the dmaCode property of the Net_GeoIpLocation object.
- * 
- * <code>
- * $region = Net_GeoIPDMA::getMetroRegion($record->dmaCode);
- * </code>
- * 
- * @category Net
- * @package  Net_GeoIP
- * @author   Hans Lellelid <hans@xmpl.org>
- * @author   Dmitri Snytkine <d.snytkine@gmail.com>
- * @license  LGPL http://www.gnu.org/licenses/lgpl.txt
- * @version  $Revision$
- * @link     http://pear.php.net/package/Net_GeoIp
- */
-class Net_GeoIP_DMA
-{
-    /**
-     * Holds DMA -> Metro mapping.
-     * @var array
-     */
-    private static $dmaMap;
-    
-    /**
-     * Initialize
-     * 
-     * @return void
-     */
-    public static function initialize()
-    {
-        self::$dmaMap = array(
-            500 => 'Portland-Auburn, ME',
-            501 => 'New York, NY',
-            502 => 'Binghamton, NY',
-            503 => 'Macon, GA',
-            504 => 'Philadelphia, PA',
-            505 => 'Detroit, MI',
-            506 => 'Boston, MA',
-            507 => 'Savannah, GA',
-            508 => 'Pittsburgh, PA',
-            509 => 'Ft Wayne, IN',
-            510 => 'Cleveland, OH',
-            511 => 'Washington, DC',
-            512 => 'Baltimore, MD',
-            513 => 'Flint, MI',
-            514 => 'Buffalo, NY',
-            515 => 'Cincinnati, OH',
-            516 => 'Erie, PA',
-            517 => 'Charlotte, NC',
-            518 => 'Greensboro, NC',
-            519 => 'Charleston, SC',
-            520 => 'Augusta, GA',
-            521 => 'Providence, RI',
-            522 => 'Columbus, GA',
-            523 => 'Burlington, VT',
-            524 => 'Atlanta, GA',
-            525 => 'Albany, GA',
-            526 => 'Utica-Rome, NY',
-            527 => 'Indianapolis, IN',
-            528 => 'Miami, FL',
-            529 => 'Louisville, KY',
-            530 => 'Tallahassee, FL',
-            531 => 'Tri-Cities, TN',
-            532 => 'Albany-Schenectady-Troy, NY',
-            533 => 'Hartford, CT',
-            534 => 'Orlando, FL',
-            535 => 'Columbus, OH',
-            536 => 'Youngstown-Warren, OH',
-            537 => 'Bangor, ME',
-            538 => 'Rochester, NY',
-            539 => 'Tampa, FL',
-            540 => 'Traverse City-Cadillac, MI',
-            541 => 'Lexington, KY',
-            542 => 'Dayton, OH',
-            543 => 'Springfield-Holyoke, MA',
-            544 => 'Norfolk-Portsmouth, VA',
-            545 => 'Greenville-New Bern-Washington, NC',
-            546 => 'Columbia, SC',
-            547 => 'Toledo, OH',
-            548 => 'West Palm Beach, FL',
-            549 => 'Watertown, NY',
-            550 => 'Wilmington, NC',
-            551 => 'Lansing, MI',
-            552 => 'Presque Isle, ME',
-            553 => 'Marquette, MI',
-            554 => 'Wheeling, WV',
-            555 => 'Syracuse, NY',
-            556 => 'Richmond-Petersburg, VA',
-            557 => 'Knoxville, TN',
-            558 => 'Lima, OH',
-            559 => 'Bluefield-Beckley-Oak Hill, WV',
-            560 => 'Raleigh-Durham, NC',
-            561 => 'Jacksonville, FL',
-            563 => 'Grand Rapids, MI',
-            564 => 'Charleston-Huntington, WV',
-            565 => 'Elmira, NY',
-            566 => 'Harrisburg-Lancaster-Lebanon-York, PA',
-            567 => 'Greenville-Spartenburg, SC',
-            569 => 'Harrisonburg, VA',
-            570 => 'Florence-Myrtle Beach, SC',
-            571 => 'Ft Myers, FL',
-            573 => 'Roanoke-Lynchburg, VA',
-            574 => 'Johnstown-Altoona, PA',
-            575 => 'Chattanooga, TN',
-            576 => 'Salisbury, MD',
-            577 => 'Wilkes Barre-Scranton, PA',
-            581 => 'Terre Haute, IN',
-            582 => 'Lafayette, IN',
-            583 => 'Alpena, MI',
-            584 => 'Charlottesville, VA',
-            588 => 'South Bend, IN',
-            592 => 'Gainesville, FL',
-            596 => 'Zanesville, OH',
-            597 => 'Parkersburg, WV',
-            598 => 'Clarksburg-Weston, WV',
-            600 => 'Corpus Christi, TX',
-            602 => 'Chicago, IL',
-            603 => 'Joplin-Pittsburg, MO',
-            604 => 'Columbia-Jefferson City, MO',
-            605 => 'Topeka, KS',
-            606 => 'Dothan, AL',
-            609 => 'St Louis, MO',
-            610 => 'Rockford, IL',
-            611 => 'Rochester-Mason City-Austin, MN',
-            612 => 'Shreveport, LA',
-            613 => 'Minneapolis-St Paul, MN',
-            616 => 'Kansas City, MO',
-            617 => 'Milwaukee, WI',
-            618 => 'Houston, TX',
-            619 => 'Springfield, MO',
-            620 => 'Tuscaloosa, AL',
-            622 => 'New Orleans, LA',
-            623 => 'Dallas-Fort Worth, TX',
-            624 => 'Sioux City, IA',
-            625 => 'Waco-Temple-Bryan, TX',
-            626 => 'Victoria, TX',
-            627 => 'Wichita Falls, TX',
-            628 => 'Monroe, LA',
-            630 => 'Birmingham, AL',
-            631 => 'Ottumwa-Kirksville, IA',
-            632 => 'Paducah, KY',
-            633 => 'Odessa-Midland, TX',
-            634 => 'Amarillo, TX',
-            635 => 'Austin, TX',
-            636 => 'Harlingen, TX',
-            637 => 'Cedar Rapids-Waterloo, IA',
-            638 => 'St Joseph, MO',
-            639 => 'Jackson, TN',
-            640 => 'Memphis, TN',
-            641 => 'San Antonio, TX',
-            642 => 'Lafayette, LA',
-            643 => 'Lake Charles, LA',
-            644 => 'Alexandria, LA',
-            646 => 'Anniston, AL',
-            647 => 'Greenwood-Greenville, MS',
-            648 => 'Champaign-Springfield-Decatur, IL',
-            649 => 'Evansville, IN',
-            650 => 'Oklahoma City, OK',
-            651 => 'Lubbock, TX',
-            652 => 'Omaha, NE',
-            656 => 'Panama City, FL',
-            657 => 'Sherman, TX',
-            658 => 'Green Bay-Appleton, WI',
-            659 => 'Nashville, TN',
-            661 => 'San Angelo, TX',
-            662 => 'Abilene-Sweetwater, TX',
-            669 => 'Madison, WI',
-            670 => 'Ft Smith-Fay-Springfield, AR',
-            671 => 'Tulsa, OK',
-            673 => 'Columbus-Tupelo-West Point, MS',
-            675 => 'Peoria-Bloomington, IL',
-            676 => 'Duluth, MN',
-            678 => 'Wichita, KS',
-            679 => 'Des Moines, IA',
-            682 => 'Davenport-Rock Island-Moline, IL',
-            686 => 'Mobile, AL',
-            687 => 'Minot-Bismarck-Dickinson, ND',
-            691 => 'Huntsville, AL',
-            692 => 'Beaumont-Port Author, TX',
-            693 => 'Little Rock-Pine Bluff, AR',
-            698 => 'Montgomery, AL',
-            702 => 'La Crosse-Eau Claire, WI',
-            705 => 'Wausau-Rhinelander, WI',
-            709 => 'Tyler-Longview, TX',
-            710 => 'Hattiesburg-Laurel, MS',
-            711 => 'Meridian, MS',
-            716 => 'Baton Rouge, LA',
-            717 => 'Quincy, IL',
-            718 => 'Jackson, MS',
-            722 => 'Lincoln-Hastings, NE',
-            724 => 'Fargo-Valley City, ND',
-            725 => 'Sioux Falls, SD',
-            734 => 'Jonesboro, AR',
-            736 => 'Bowling Green, KY',
-            737 => 'Mankato, MN',
-            740 => 'North Platte, NE',
-            743 => 'Anchorage, AK',
-            744 => 'Honolulu, HI',
-            745 => 'Fairbanks, AK',
-            746 => 'Biloxi-Gulfport, MS',
-            747 => 'Juneau, AK',
-            749 => 'Laredo, TX',
-            751 => 'Denver, CO',
-            752 => 'Colorado Springs, CO',
-            753 => 'Phoenix, AZ',
-            754 => 'Butte-Bozeman, MT',
-            755 => 'Great Falls, MT',
-            756 => 'Billings, MT',
-            757 => 'Boise, ID',
-            758 => 'Idaho Falls-Pocatello, ID',
-            759 => 'Cheyenne, WY',
-            760 => 'Twin Falls, ID',
-            762 => 'Missoula, MT',
-            764 => 'Rapid City, SD',
-            765 => 'El Paso, TX',
-            766 => 'Helena, MT',
-            767 => 'Casper-Riverton, WY',
-            770 => 'Salt Lake City, UT',
-            771 => 'Yuma, AZ',
-            773 => 'Grand Junction, CO',
-            789 => 'Tucson, AZ',
-            790 => 'Albuquerque, NM',
-            798 => 'Glendive, MT',
-            800 => 'Bakersfield, CA',
-            801 => 'Eugene, OR',
-            802 => 'Eureka, CA',
-            803 => 'Los Angeles, CA',
-            804 => 'Palm Springs, CA',
-            807 => 'San Francisco, CA',
-            810 => 'Yakima-Pasco, WA',
-            811 => 'Reno, NV',
-            813 => 'Medford-Klamath Falls, OR',
-            819 => 'Seattle-Tacoma, WA',
-            820 => 'Portland, OR',
-            821 => 'Bend, OR',
-            825 => 'San Diego, CA',
-            828 => 'Monterey-Salinas, CA',
-            839 => 'Las Vegas, NV',
-            855 => 'Santa Barbara, CA',
-            862 => 'Sacramento, CA',
-            866 => 'Fresno, CA',
-            868 => 'Chico-Redding, CA',
-            881 => 'Spokane, WA');
-    }
-    
-    /**
-     * Lookup the metro region based on the provided DMA code.
-     * 
-     * @param int $dmaCode The DMA code
-     * 
-     * @return string Metro region name.
-     */
-    public static function getMetroRegion($dmaCode)
-    {
-        if ($dmaCode === null) {
-            return null;
-        }
-        if (self::$dmaMap === null) {
-            self::initialize();
-        }
-        return self::$dmaMap[$dmaCode];
-    }
-
-    /**
-     * Reverse lookup of DMA code if [exact] metro region name is known.
-     * 
-     * @param string $metro Metro region name.
-     * 
-     * @return int DMA code, or false if not found.
-     */
-    public static function getDMACode($metro)    
-    {
-        if (self::$dmaMap === null) {
-            self::initialize();
-        }
-        return array_search($metro, self::$dmaMap);
-    }
-
-}
\ No newline at end of file
diff --git a/lib/pear/Net/GeoIP/Location.php b/lib/pear/Net/GeoIP/Location.php
deleted file mode 100644 (file)
index c02598b..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-<?php
-/**
- * +----------------------------------------------------------------------+
- * | PHP version 5                                                        |
- * +----------------------------------------------------------------------+
- * | Copyright (C) 2004 MaxMind LLC                                       |
- * +----------------------------------------------------------------------+
- * | 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; if not, write to the Free Software  |
- * | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 |
- * | USA, or view it online at http://www.gnu.org/licenses/lgpl.txt.      |
- * +----------------------------------------------------------------------+
- * | Authors: Jim Winstead <jimw@apache.org> (original Maxmind version)   |
- * |          Hans Lellelid <hans@xmpl.org>                               |
- * +----------------------------------------------------------------------+
- *
- * @category Net
- * @package  Net_GeoIP
- * @author   Hans Lellelid <hans@xmpl.org>
- * @license  LGPL http://www.gnu.org/licenses/lgpl.txt
- * @link     http://pear.php.net/package/Net_GeoIp
- * $Id$
- */
-
-/**
- * This class represents a location record as returned by Net_GeoIP::lookupLocation().
- *
- * This class is primarily a collection of values (the public properties of the class), but
- * there is also a distance() method to calculate the km distance between two points.
- *
- * @category Net
- * @package  Net_GeoIP
- * @author   Hans Lellelid <hans@xmpl.org>
- * @author   Dmitri Snytkine <d.snytkine@gmail.com>
- * @license  LGPL http://www.gnu.org/licenses/lgpl.txt
- * @version  $Revision$
- * @link     http://pear.php.net/package/Net_GeoIp
- * @see      Net_GeoIP::lookupLocation()
- */
-class Net_GeoIP_Location implements Serializable
-{
-    protected $aData = array(
-        'countryCode'  => null,
-        'countryCode3' => null,
-        'countryName'  => null,
-        'region'       => null,
-        'city'         => null,
-        'postalCode'   => null,
-        'latitude'     => null,
-        'longitude'    => null,
-        'areaCode'     => null,
-        'dmaCode'      => null
-    );
-
-
-    /**
-     * Calculate the distance in km between two points.
-     *
-     * @param Net_GeoIP_Location $loc The other point to which distance will be calculated.
-     *
-     * @return float The number of km between two points on the globe.
-     */
-    public function distance(Net_GeoIP_Location $loc)
-    {
-        // ideally these should be class constants, but class constants
-        // can't be operations.
-        $RAD_CONVERT = M_PI / 180;
-        $EARTH_DIAMETER = 2 * 6378.2;
-
-        $lat1 = $this->latitude;
-        $lon1 = $this->longitude;
-        $lat2 = $loc->latitude;
-        $lon2 = $loc->longitude;
-
-        // convert degrees to radians
-        $lat1 *= $RAD_CONVERT;
-        $lat2 *= $RAD_CONVERT;
-
-        // find the deltas
-        $delta_lat = $lat2 - $lat1;
-        $delta_lon = ($lon2 - $lon1) * $RAD_CONVERT;
-
-        // Find the great circle distance
-        $temp = pow(sin($delta_lat/2), 2) + cos($lat1) * cos($lat2) * pow(sin($delta_lon/2), 2);
-        return $EARTH_DIAMETER * atan2(sqrt($temp), sqrt(1-$temp));
-    }
-
-    /**
-     * magic method to make it possible
-     * to store this object in cache when
-     * automatic serialization is on
-     * Specifically it makes it possible to store
-     * this object in memcache
-     *
-     * @return array
-     */
-    public function serialize()
-    {
-        return serialize($this->aData);
-    }
-
-    /**
-     * unserialize a representation of the object
-     *
-     * @param array $serialized The serialized representation of the location
-     *
-     * @return void
-     */
-    public function unserialize($serialized)
-    {
-        $this->aData = unserialize($serialized);
-    }
-
-
-    /**
-     * Setter for elements of $this->aData array
-     *
-     * @param string $name The variable to set
-     * @param string $val  The value
-     *
-     * @return object $this object
-     */
-    public function set($name, $val)
-    {
-        if (array_key_exists($name, $this->aData)) {
-            $this->aData[$name] = $val;
-        }
-
-        return $this;
-    }
-
-    public function __set($name, $val)
-    {
-        return $this->set($name, $val);
-    }
-
-    /**
-     * Getter for $this->aData array
-     *
-     * @return array
-     */
-    public function getData()
-    {
-         return $this->aData;
-    }
-
-
-    /**
-     * Magic method to get value from $this->aData array
-     *
-     * @param string $name The var to get
-     *
-     * @return mixed string if value exists or null if it is empty of
-     * just does not exist
-     */
-    public function __get($name)
-    {
-        if (array_key_exists($name, $this->aData)) {
-            return $this->aData[$name];
-        }
-
-        return null;
-    }
-
-
-    /**
-     * String representation of the object
-     *
-     * @return string text and result of print_r of $this->aData array
-     */
-    public function __toString()
-    {
-        return 'object of type '.__CLASS__.'. data: '.implode(',', $this->aData);
-    }
-
-
-    /**
-     * Magic method
-     * makes it possible to check if specific record exists
-     * and also makes it possible to use empty() on any property
-     *
-     * @param strign $name The name of the var to check
-     *
-     * @return bool
-     */
-    public function __isset($name)
-    {
-        return (null !== $this->__get($name));
-    }
-
-}
index 353187e..d9c53fc 100644 (file)
@@ -3130,4 +3130,52 @@ class core_moodlelib_testcase extends advanced_testcase {
         $this->assertSame('', $result);
         $this->assertDebuggingCalled();
     }
+
+    /**
+     * Data provider for private ips.
+     */
+    public function data_private_ips() {
+        return array(
+            array('10.0.0.0'),
+            array('172.16.0.0'),
+            array('192.168.1.0'),
+            array('fdfe:dcba:9876:ffff:fdc6:c46b:bb8f:7d4c'),
+            array('fdc6:c46b:bb8f:7d4c:fdc6:c46b:bb8f:7d4c'),
+            array('fdc6:c46b:bb8f:7d4c:0000:8a2e:0370:7334'),
+            array('127.0.0.1'), // This has been buggy in past: https://bugs.php.net/bug.php?id=53150.
+        );
+    }
+
+    /**
+     * Checks ip_is_public returns false for private ips.
+     *
+     * @param string $ip the ipaddress to test
+     * @dataProvider data_private_ips
+     */
+    public function test_ip_is_public_private_ips($ip) {
+        $this->assertFalse(ip_is_public($ip));
+    }
+
+    /**
+     * Data provider for public ips.
+     */
+    public function data_public_ips() {
+        return array(
+            array('2400:cb00:2048:1::8d65:71b3'),
+            array('2400:6180:0:d0::1b:2001'),
+            array('141.101.113.179'),
+            array('123.45.67.178'),
+        );
+    }
+
+    /**
+     * Checks ip_is_public returns true for public ips.
+     *
+     * @param string $ip the ipaddress to test
+     * @dataProvider data_public_ips
+     */
+    public function test_ip_is_public_public_ips($ip) {
+        $this->assertTrue(ip_is_public($ip));
+    }
+
 }
index 626f270..8a443ef 100644 (file)
@@ -360,7 +360,7 @@ class core_user_testcase extends advanced_testcase {
 
         // Test against theme property choices.
         $choices = core_user::get_property_choices('theme');
-        $this->assertArrayHasKey('base', $choices);
+        $this->assertArrayHasKey('bootstrapbase', $choices);
         $this->assertArrayHasKey('clean', $choices);
         $this->assertArrayNotHasKey('unknowntheme', $choices);
         $this->assertArrayNotHasKey('wrongtheme', $choices);
index d0a78f5..bb93959 100644 (file)
     <version>1.8.1</version>
     <licenseversion>2.1+</licenseversion>
   </library>
-  <library>
-    <location>pear/Net</location>
-    <name>GeoIP</name>
-    <license>LGPL</license>
-    <version>1.0.0</version>
-    <licenseversion>2.1+</licenseversion>
-  </library>
   <library>
     <location>google</location>
     <name>Google APIs Client Library</name>
     <license>MIT</license>
     <version>2.1.6</version>
   </library>
+  <library>
+    <location>maxmind/GeoIp2</location>
+    <name>GeoIP2 PHP API</name>
+    <license>Apache 2.0</license>
+    <version>2.4.2</version>
+  </library>
+  <library>
+    <location>maxmind/MaxMind</location>
+    <name>MaxMind DB Reader API</name>
+    <license>Apache 2.0</license>
+    <version>1.1.0</version>
+  </library>
 </libraries>
index f453fc8..83f2b2e 100644 (file)
@@ -210,6 +210,7 @@ information provided here is intended especially for developers.
   These hooks allow developers to use the item in question before it is deleted by core. For example, if your plugin is
   a module (plugins located in the mod folder) called 'xxx' and you wish to interact with the user object before it is
   deleted then the function to create would be mod_xxx_pre_user_delete($user) in mod/xxx/lib.php.
+* pear::Net::GeoIP has been removed.
 
 === 3.0 ===
 
index cbb471c..d07a279 100644 (file)
@@ -291,7 +291,7 @@ function book_supports($feature) {
  * @return void
  */
 function book_extend_settings_navigation(settings_navigation $settingsnav, navigation_node $booknode) {
-    global $USER, $PAGE;
+    global $USER, $PAGE, $OUTPUT;
 
     $plugins = core_component::get_plugin_list('booktool');
     foreach ($plugins as $plugin => $dir) {
@@ -306,7 +306,8 @@ function book_extend_settings_navigation(settings_navigation $settingsnav, navig
 
     $params = $PAGE->url->params();
 
-    if (!empty($params['id']) and !empty($params['chapterid']) and has_capability('mod/book:edit', $PAGE->cm->context)) {
+    if ($PAGE->cm->modname === 'book' and !empty($params['id']) and !empty($params['chapterid'])
+            and has_capability('mod/book:edit', $PAGE->cm->context)) {
         if (!empty($USER->editing)) {
             $string = get_string("turneditingoff");
             $edit = '0';
@@ -316,6 +317,7 @@ function book_extend_settings_navigation(settings_navigation $settingsnav, navig
         }
         $url = new moodle_url('/mod/book/view.php', array('id'=>$params['id'], 'chapterid'=>$params['chapterid'], 'edit'=>$edit, 'sesskey'=>sesskey()));
         $booknode->add($string, $url, navigation_node::TYPE_SETTING);
+        $PAGE->set_button($OUTPUT->single_button($url, $string));
     }
 }
 
diff --git a/theme/base/config.php b/theme/base/config.php
deleted file mode 100644 (file)
index a2dca72..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-<?php
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle 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 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
-
-/**
- * Configuration for Moodle's base theme.
- *
- * This theme is special, and implements a minimalist theme with only
- * basic layout. It is intended as a base for other themes to build upon.
- * It is not recommend to actually choose this theme for production sites!
- *
- * DO NOT COPY THIS TO START NEW THEMES!
- * Start with another theme, like "standard".
- *
- * For full information about creating Moodle themes, see:
- *  http://docs.moodle.org/dev/Themes_2.0
- *
- * @package   theme_base
- * @copyright 2009 Tim Hunt
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-$THEME->name = 'base';
-
-$THEME->parents = array();
-
-$THEME->sheets = array(
-    'pagelayout',   // Must come first: Page layout.
-    'core',         // Must come second: General styles.
-    'admin',
-    'blocks',
-    'calendar',
-    'course',
-    'dock',
-    'grade',
-    'message',
-    'question',
-    'user',
-    'tabs',
-    'filemanager',
-    'templates',
-    'autocomplete',
-    'search',
-    'modal'
-);
-
-$THEME->editor_sheets = array('editor');
-
-$THEME->layouts = array(
-    // Most backwards compatible layout without the blocks - this is the layout used by default.
-    'base' => array(
-        'file' => 'general.php',
-        'regions' => array(),
-    ),
-    // Standard layout with blocks, this is recommended for most pages with general information.
-    'standard' => array(
-        'file' => 'general.php',
-        'regions' => array('side-pre', 'side-post'),
-        'defaultregion' => 'side-pre',
-    ),
-    // Main course page.
-    'course' => array(
-        'file' => 'general.php',
-        'regions' => array('side-pre', 'side-post'),
-        'defaultregion' => 'side-pre',
-        'options' => array('langmenu'=>true),
-    ),
-    'coursecategory' => array(
-        'file' => 'general.php',
-        'regions' => array('side-pre', 'side-post'),
-        'defaultregion' => 'side-pre',
-    ),
-    // Part of course, typical for modules - default page layout if $cm specified in require_login().
-    'incourse' => array(
-        'file' => 'general.php',
-        'regions' => array('side-pre', 'side-post'),
-        'defaultregion' => 'side-pre',
-    ),
-    // The site home page.
-    'frontpage' => array(
-        'file' => 'frontpage.php',
-        'regions' => array('side-pre', 'side-post'),
-        'defaultregion' => 'side-pre',
-    ),
-    // Server administration scripts.
-    'admin' => array(
-        'file' => 'general.php',
-        'regions' => array('side-pre'),
-        'defaultregion' => 'side-pre',
-    ),
-    // My dashboard page.
-    'mydashboard' => array(
-        'file' => 'general.php',
-        'regions' => array('side-pre', 'side-post'),
-        'defaultregion' => 'side-pre',
-        'options' => array('langmenu'=>true),
-    ),
-    // My public page.
-    'mypublic' => array(
-        'file' => 'general.php',
-        'regions' => array('side-pre', 'side-post'),
-        'defaultregion' => 'side-pre',
-    ),
-    'login' => array(
-        'file' => 'general.php',
-        'regions' => array(),
-        'options' => array('langmenu'=>true),
-    ),
-
-    // Pages that appear in pop-up windows - no navigation, no blocks, no header.
-    'popup' => array(
-        'file' => 'general.php',
-        'regions' => array(),
-        'options' => array('nofooter'=>true, 'nonavbar'=>true, 'nocustommenu'=>true, 'nologininfo'=>true, 'nocourseheaderfooter'=>true),
-    ),
-    // No blocks and minimal footer - used for legacy frame layouts only!
-    'frametop' => array(
-        'file' => 'general.php',
-        'regions' => array(),
-        'options' => array('nofooter'=>true, 'nocoursefooter'=>true),
-    ),
-    // Embeded pages, like iframe/object embeded in moodleform - it needs as much space as possible.
-    'embedded' => array(
-        'file' => 'embedded.php',
-        'regions' => array(),
-        'options' => array('nofooter'=>true, 'nonavbar'=>true, 'nocustommenu'=>true, 'nocourseheaderfooter'=>true),
-    ),
-    // Used during upgrade and install, and for the 'This site is undergoing maintenance' message.
-    // This must not have any blocks, and it is good idea if it does not have links to
-    // other places - for example there should not be a home link in the footer...
-    'maintenance' => array(
-        'file' => 'general.php',
-        'regions' => array(),
-        'options' => array('noblocks'=>true, 'nofooter'=>true, 'nonavbar'=>true, 'nocustommenu'=>true, 'nocourseheaderfooter'=>true),
-    ),
-    // Should display the content and basic headers only.
-    'print' => array(
-        'file' => 'general.php',
-        'regions' => array(),
-        'options' => array('noblocks'=>true, 'nofooter'=>true, 'nonavbar'=>false, 'nocustommenu'=>true, 'nocourseheaderfooter'=>true),
-    ),
-    // The pagelayout used when a redirection is occuring.
-    'redirect' => array(
-        'file' => 'embedded.php',
-        'regions' => array(),
-        'options' => array('nofooter'=>true, 'nonavbar'=>true, 'nocustommenu'=>true, 'nocourseheaderfooter'=>true),
-    ),
-    // The pagelayout used for reports.
-    'report' => array(
-        'file' => 'report.php',
-        'regions' => array('side-pre'),
-        'defaultregion' => 'side-pre',
-    ),
-    // The pagelayout used for safebrowser and securewindow.
-    'secure' => array(
-        'file' => 'general.php',
-        'regions' => array('side-pre', 'side-post'),
-        'defaultregion' => 'side-pre',
-        'options' => array('nofooter'=>true, 'nonavbar'=>true, 'nocustommenu'=>true, 'nologinlinks'=>true, 'nocourseheaderfooter'=>true),
-    ),
-);
-
-// We don't want the base theme to be shown on the theme selection screen, by setting
-// this to true it will only be shown if theme designer mode is switched on.
-$THEME->hidefromselector = true;
-
-/** List of javascript files that need to included on each page */
-$THEME->javascripts = array();
-$THEME->javascripts_footer = array();
-
-// Set this to the method you will use in your layout files for rendering blocks.
-// It should be either blocks (default) or blocks_for_region.
-$THEME->blockrendermethod = 'blocks_for_region';
diff --git a/theme/base/lang/en/theme_base.php b/theme/base/lang/en/theme_base.php
deleted file mode 100644 (file)
index d71971e..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-<?php
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle 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 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
-
-/**
- * Strings for component 'theme_base', language 'en', branch 'MOODLE_20_STABLE'
- *
- * @package   theme_base
- * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-$string['pluginname'] = 'Base';
-$string['region-side-post'] = 'Right';
-$string['region-side-pre'] = 'Left';
-$string['choosereadme'] = 'Base is a special minimalist theme with only basic layout. It is intended as a starting point for other themes to build upon.  It is not recommend to actually choose this theme for production sites!';
diff --git a/theme/base/layout/embedded.php b/theme/base/layout/embedded.php
deleted file mode 100644 (file)
index 45bc0a4..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle 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 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
-
-/**
- * The embedded layout for the base theme.
- *
- * @package   theme_base
- * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-echo $OUTPUT->doctype(); ?>
-<html <?php echo $OUTPUT->htmlattributes() ?>>
-<head>
-    <title><?php echo $PAGE->title ?></title>
-    <link rel="shortcut icon" href="<?php echo $OUTPUT->pix_url('favicon', 'theme')?>" />
-    <?php echo $OUTPUT->standard_head_html() ?>
-</head>
-<body id="<?php p($PAGE->bodyid) ?>" class="<?php p($PAGE->bodyclasses) ?>">
-<?php echo $OUTPUT->standard_top_of_body_html() ?>
-
-<div id="page">
-
-<!-- END OF HEADER -->
-
-    <div id="page-content" class="clearfix">
-        <?php echo $OUTPUT->main_content() ?>
-    </div>
-
-<!-- START OF FOOTER -->
-</div>
-<?php echo $OUTPUT->standard_end_of_body_html() ?>
-</body>
-</html>
\ No newline at end of file
diff --git a/theme/base/layout/frontpage.php b/theme/base/layout/frontpage.php
deleted file mode 100644 (file)
index 3c27f4c..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-<?php
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle 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 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
-
-/**
- * The frontpage layout for the base theme.
- *
- * @package   theme_base
- * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-$hassidepre = $PAGE->blocks->region_has_content('side-pre', $OUTPUT);
-$hassidepost = $PAGE->blocks->region_has_content('side-post', $OUTPUT);
-$showsidepre = $hassidepre && !$PAGE->blocks->region_completely_docked('side-pre', $OUTPUT);
-$showsidepost = $hassidepost && !$PAGE->blocks->region_completely_docked('side-post', $OUTPUT);
-
-$custommenu = $OUTPUT->custom_menu();
-$hascustommenu = (empty($PAGE->layout_options['nocustommenu']) && !empty($custommenu));
-
-$bodyclasses = array();
-if ($showsidepre && !$showsidepost) {
-    if (!right_to_left()) {
-        $bodyclasses[] = 'side-pre-only';
-    }else{
-        $bodyclasses[] = 'side-post-only';
-    }
-} else if ($showsidepost && !$showsidepre) {
-    if (!right_to_left()) {
-        $bodyclasses[] = 'side-post-only';
-    }else{
-        $bodyclasses[] = 'side-pre-only';
-    }
-} else if (!$showsidepost && !$showsidepre) {
-    $bodyclasses[] = 'content-only';
-}
-if ($hascustommenu) {
-    $bodyclasses[] = 'has_custom_menu';
-}
-
-echo $OUTPUT->doctype() ?>
-<html <?php echo $OUTPUT->htmlattributes() ?>>
-<head>
-    <title><?php echo $PAGE->title ?></title>
-    <link rel="shortcut icon" href="<?php echo $OUTPUT->pix_url('favicon', 'theme')?>" />
-    <meta name="description" content="<?php p(strip_tags(format_text($SITE->summary, FORMAT_HTML))) ?>" />
-    <?php echo $OUTPUT->standard_head_html() ?>
-</head>
-<body id="<?php p($PAGE->bodyid) ?>" class="<?php p($PAGE->bodyclasses.' '.join(' ', $bodyclasses)) ?>">
-<?php echo $OUTPUT->standard_top_of_body_html() ?>
-
-<div id="page">
-
-    <div id="page-header" class="clearfix">
-        <h1 class="headermain"><?php echo $PAGE->heading ?></h1>
-        <div class="headermenu"><?php
-            echo $OUTPUT->user_menu();
-            echo $OUTPUT->lang_menu();
-            echo $PAGE->headingmenu;
-        ?></div>
-        <?php if ($hascustommenu) { ?>
-        <div id="custommenu"><?php echo $custommenu; ?></div>
-         <?php } ?>
-    </div>
-<!-- END OF HEADER -->
-
-    <div id="page-content">
-        <div id="region-main-box">
-            <div id="region-post-box">
-
-                <div id="region-main-wrap">
-                    <div id="region-main">
-                        <div class="region-content">
-                            <?php echo $OUTPUT->main_content() ?>
-                        </div>
-                    </div>
-                </div>
-
-                <?php if ($hassidepre OR (right_to_left() AND $hassidepost)) { ?>
-                <div id="region-pre" class="block-region">
-                    <div class="region-content">
-                            <?php
-                        if (!right_to_left()) {
-                            echo $OUTPUT->blocks_for_region('side-pre');
-                        } elseif ($hassidepost) {
-                            echo $OUTPUT->blocks_for_region('side-post');
-                    } ?>
-
-                    </div>
-                </div>
-                <?php } ?>
-
-                <?php if ($hassidepost OR (right_to_left() AND $hassidepre)) { ?>
-                <div id="region-post" class="block-region">
-                    <div class="region-content">
-                           <?php
-                       if (!right_to_left()) {
-                           echo $OUTPUT->blocks_for_region('side-post');
-                       } elseif ($hassidepre) {
-                           echo $OUTPUT->blocks_for_region('side-pre');
-                    } ?>
-                    </div>
-                </div>
-                <?php } ?>
-
-            </div>
-        </div>
-    </div>
-
-<!-- START OF FOOTER -->
-    <div id="page-footer">
-        <p class="helplink">
-        <?php echo page_doc_link(get_string('moodledocslink')) ?>
-        </p>
-
-        <?php
-        echo $OUTPUT->login_info();
-        echo $OUTPUT->home_link();
-        echo $OUTPUT->standard_footer_html();
-        ?>
-    </div>
-    <div class="clearfix"></div>
-</div>
-<?php echo $OUTPUT->standard_end_of_body_html() ?>
-</body>
-</html>
\ No newline at end of file
diff --git a/theme/base/layout/general.php b/theme/base/layout/general.php
deleted file mode 100644 (file)
index ad1c590..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-<?php
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle 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 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
-
-/**
- * The default layout for the base theme.
- *
- * @package   theme_base
- * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-$hasheading = ($PAGE->heading);
-$hasnavbar = (empty($PAGE->layout_options['nonavbar']) && $PAGE->has_navbar());
-$hasfooter = (empty($PAGE->layout_options['nofooter']));
-$hassidepre = (empty($PAGE->layout_options['noblocks']) && $PAGE->blocks->region_has_content('side-pre', $OUTPUT));
-$hassidepost = (empty($PAGE->layout_options['noblocks']) && $PAGE->blocks->region_has_content('side-post', $OUTPUT));
-$haslogininfo = (empty($PAGE->layout_options['nologininfo']));
-
-$showsidepre = ($hassidepre && !$PAGE->blocks->region_completely_docked('side-pre', $OUTPUT));
-$showsidepost = ($hassidepost && !$PAGE->blocks->region_completely_docked('side-post', $OUTPUT));
-
-$custommenu = $OUTPUT->custom_menu();
-$hascustommenu = (empty($PAGE->layout_options['nocustommenu']) && !empty($custommenu));
-
-$courseheader = $coursecontentheader = $coursecontentfooter = $coursefooter = '';
-if (empty($PAGE->layout_options['nocourseheaderfooter'])) {
-    $courseheader = $OUTPUT->course_header();
-    $coursecontentheader = $OUTPUT->course_content_header();
-    if (empty($PAGE->layout_options['nocoursefooter'])) {
-        $coursecontentfooter = $OUTPUT->course_content_footer();
-        $coursefooter = $OUTPUT->course_footer();
-    }
-}
-
-$bodyclasses = array();
-if ($showsidepre && !$showsidepost) {
-    if (!right_to_left()) {
-        $bodyclasses[] = 'side-pre-only';
-    }else{
-        $bodyclasses[] = 'side-post-only';
-    }
-} else if ($showsidepost && !$showsidepre) {
-    if (!right_to_left()) {
-        $bodyclasses[] = 'side-post-only';
-    }else{
-        $bodyclasses[] = 'side-pre-only';
-    }
-} else if (!$showsidepost && !$showsidepre) {
-    $bodyclasses[] = 'content-only';
-}
-if ($hascustommenu) {
-    $bodyclasses[] = 'has_custom_menu';
-}
-
-echo $OUTPUT->doctype() ?>
-<html <?php echo $OUTPUT->htmlattributes() ?>>
-<head>
-    <title><?php echo $PAGE->title ?></title>
-    <link rel="shortcut icon" href="<?php echo $OUTPUT->pix_url('favicon', 'theme')?>" />
-    <?php echo $OUTPUT->standard_head_html() ?>
-</head>
-<body id="<?php p($PAGE->bodyid) ?>" class="<?php p($PAGE->bodyclasses.' '.join(' ', $bodyclasses)) ?>">
-<?php echo $OUTPUT->standard_top_of_body_html() ?>
-<div id="page">
-<?php if ($hasheading || $hasnavbar || !empty($courseheader)) { ?>
-    <div id="page-header">
-        <?php if ($hasheading) { ?>
-        <h1 class="headermain"><?php echo $PAGE->heading ?></h1>
-        <div class="headermenu"><?php
-            echo $OUTPUT->user_menu();
-            if (!empty($PAGE->layout_options['langmenu'])) {
-                echo $OUTPUT->lang_menu();
-            }
-            echo $PAGE->headingmenu
-        ?></div><?php } ?>
-        <?php if (!empty($courseheader)) { ?>
-            <div id="course-header"><?php echo $courseheader; ?></div>
-        <?php } ?>
-        <?php if ($hascustommenu) { ?>
-        <div id="custommenu"><?php echo $custommenu; ?></div>
-        <?php } ?>
-        <?php if ($hasnavbar) { ?>
-            <div class="navbar clearfix">
-                <div class="breadcrumb"><?php echo $OUTPUT->navbar(); ?></div>
-                <div class="navbutton"> <?php echo $PAGE->button; ?></div>
-            </div>
-        <?php } ?>
-    </div>
-<?php } ?>
-<!-- END OF HEADER -->
-
-    <div id="page-content">
-        <div id="region-main-box">
-            <div id="region-post-box">
-
-                <div id="region-main-wrap">
-                    <div id="region-main">
-                        <div class="region-content">
-                            <?php echo $coursecontentheader; ?>
-                            <?php echo $OUTPUT->main_content() ?>
-                            <?php echo $coursecontentfooter; ?>
-                        </div>
-                    </div>
-                </div>
-
-                <?php if ($hassidepre OR (right_to_left() AND $hassidepost)) { ?>
-                <div id="region-pre" class="block-region">
-                    <div class="region-content">
-                            <?php
-                        if (!right_to_left()) {
-                            echo $OUTPUT->blocks_for_region('side-pre');
-                        } elseif ($hassidepost) {
-                            echo $OUTPUT->blocks_for_region('side-post');
-                    } ?>
-
-                    </div>
-                </div>
-                <?php } ?>
-
-                <?php if ($hassidepost OR (right_to_left() AND $hassidepre)) { ?>
-                <div id="region-post" class="block-region">
-                    <div class="region-content">
-                           <?php
-                       if (!right_to_left()) {
-                           echo $OUTPUT->blocks_for_region('side-post');
-                       } elseif ($hassidepre) {
-                           echo $OUTPUT->blocks_for_region('side-pre');
-                    } ?>
-                    </div>
-                </div>
-                <?php } ?>
-
-            </div>
-        </div>
-    </div>
-
-<!-- START OF FOOTER -->
-    <?php if (!empty($coursefooter)) { ?>
-        <div id="course-footer"><?php echo $coursefooter; ?></div>
-    <?php } ?>
-    <?php if ($hasfooter) { ?>
-    <div id="page-footer" class="clearfix">
-        <p class="helplink"><?php echo page_doc_link(get_string('moodledocslink')) ?></p>
-        <?php
-        echo $OUTPUT->login_info();
-        echo $OUTPUT->home_link();
-        echo $OUTPUT->standard_footer_html();
-        ?>
-    </div>
-    <?php } ?>
-    <div class="clearfix"></div>
-</div>
-<?php echo $OUTPUT->standard_end_of_body_html() ?>
-</body>
-</html>
\ No newline at end of file
diff --git a/theme/base/layout/report.php b/theme/base/layout/report.php
deleted file mode 100644 (file)
index b5d909c..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-<?php
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle 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 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
-
-/**
- * The report layout for the base theme.
- *
- * @package   theme_base
- * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
- * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-$hasheading = ($PAGE->heading);
-$hasnavbar = (empty($PAGE->layout_options['nonavbar']) && $PAGE->has_navbar());
-$hasfooter = (empty($PAGE->layout_options['nofooter']));
-$hassidepre = (empty($PAGE->layout_options['noblocks']) && $PAGE->blocks->region_has_content('side-pre', $OUTPUT));
-$haslogininfo = (empty($PAGE->layout_options['nologininfo']));
-
-$showsidepre = ($hassidepre && !$PAGE->blocks->region_completely_docked('side-pre', $OUTPUT));
-
-$custommenu = $OUTPUT->custom_menu();
-$hascustommenu = (empty($PAGE->layout_options['nocustommenu']) && !empty($custommenu));
-
-$bodyclasses = array();
-if (!$showsidepre) {
-    $bodyclasses[] = 'content-only';
-}
-if ($hascustommenu) {
-    $bodyclasses[] = 'has_custom_menu';
-}
-$courseheader = $coursecontentheader = $coursecontentfooter = $coursefooter = '';
-if (empty($PAGE->layout_options['nocourseheaderfooter'])) {
-    $courseheader = $OUTPUT->course_header();
-    $coursecontentheader = $OUTPUT->course_content_header();
-    if (empty($PAGE->layout_options['nocoursefooter'])) {
-        $coursecontentfooter = $OUTPUT->course_content_footer();
-        $coursefooter = $OUTPUT->course_footer();
-    }
-}
-
-echo $OUTPUT->doctype() ?>
-<html <?php echo $OUTPUT->htmlattributes() ?>>
-<head>
-    <title><?php echo $PAGE->title ?></title>
-    <link rel="shortcut icon" href="<?php echo $OUTPUT->pix_url('favicon', 'theme')?>" />
-    <?php echo $OUTPUT->standard_head_html() ?>
-</head>
-<body id="<?php p($PAGE->bodyid) ?>" class="<?php p($PAGE->bodyclasses.' '.join(' ', $bodyclasses)) ?>">
-<?php echo $OUTPUT->standard_top_of_body_html() ?>
-<div id="page">
-<?php if ($hasheading || $hasnavbar || !empty($courseheader)) { ?>
-    <div id="page-header">
-        <?php if ($hasheading) { ?>
-        <h1 class="headermain"><?php echo $PAGE->heading ?></h1>
-        <div class="headermenu"><?php
-            if ($haslogininfo) {
-                echo $OUTPUT->login_info();
-            }
-            if (!empty($PAGE->layout_options['langmenu'])) {
-                echo $OUTPUT->lang_menu();
-            }
-            echo $PAGE->headingmenu
-        ?></div><?php } ?>
-        <?php if (!empty($courseheader)) { ?>
-            <div id="course-header"><?php echo $courseheader; ?></div>
-        <?php } ?>
-        <?php if ($hascustommenu) { ?>
-        <div id="custommenu"><?php echo $custommenu; ?></div>
-        <?php } ?>
-        <?php if ($hasnavbar) { ?>
-            <div class="navbar clearfix">
-                <div class="breadcrumb"><?php echo $OUTPUT->navbar(); ?></div>
-                <div class="navbutton"> <?php echo $PAGE->button; ?></div>
-            </div>
-        <?php } ?>
-    </div>
-<?php } ?>
-<!-- END OF HEADER -->
-
-    <div id="page-content" class="clearfix">
-        <div id="report-main-content">
-            <div class="region-content">
-                <?php echo $coursecontentheader; ?>
-                <?php echo $OUTPUT->main_content() ?>
-                <?php echo $coursecontentfooter; ?>
-            </div>
-        </div>
-        <?php if ($hassidepre) { ?>
-        <div id="report-region-wrap">
-            <div id="report-region-pre" class="block-region">
-                <div class="region-content">
-                    <?php echo $OUTPUT->blocks_for_region('side-pre') ?>
-                </div>
-            </div>
-        </div>
-        <?php } ?>
-    </div>
-
-<!-- START OF FOOTER -->
-    <?php if (!empty($coursefooter)) { ?>
-        <div id="course-footer"><?php echo $coursefooter; ?></div>
-    <?php } ?>
-    <?php if ($hasfooter) { ?>
-    <div id="page-footer" class="clearfix">
-        <p class="helplink"><?php echo page_doc_link(get_string('moodledocslink')) ?></p>
-        <?php
-        echo $OUTPUT->login_info();
-        echo $OUTPUT->home_link();
-        echo $OUTPUT->standard_footer_html();
-        ?>
-    </div>
-    <?php } ?>
-    <div class="clearfix"></div>
-</div>
-<?php echo $OUTPUT->standard_end_of_body_html() ?>
-</body>
-</html>
diff --git a/theme/base/pix/favicon.ico b/theme/base/pix/favicon.ico
deleted file mode 100644 (file)
index eea0248..0000000
Binary files a/theme/base/pix/favicon.ico and /dev/null differ
diff --git a/theme/base/pix/fp/add_file.png b/theme/base/pix/fp/add_file.png
deleted file mode 100644 (file)
index 7e868fe..0000000
Binary files a/theme/base/pix/fp/add_file.png and /dev/null differ
diff --git a/theme/base/pix/fp/add_file.svg b/theme/base/pix/fp/add_file.svg
deleted file mode 100644 (file)
index 7efdd9b..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [\r
-       <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">\r
-]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="-1 0 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M10 15H1.2c-.1 0-.2-.1-.2-.3V1.2c0-.1.1-.2.2-.2H9v4h4v4h1V5.2c0-.7-.4-1.6-.9-2.1L10.9.9C10.4.4 9.4 0 8.8 0H1.2C.6 0 0 .6 0 1.2v13.5c0 .7.6 1.3 1.2 1.3H10v-1zm0-13.6c.1 0 2.5 2.5 2.6 2.6H10V1.4zM15 14h-2v2h-2v-2H9v-2h2v-2h2v2h2v2z" fill="#999"/></svg>
\ No newline at end of file
diff --git a/theme/base/pix/fp/alias.png b/theme/base/pix/fp/alias.png
deleted file mode 100644 (file)
index c7747f9..0000000
Binary files a/theme/base/pix/fp/alias.png and /dev/null differ
diff --git a/theme/base/pix/fp/alias_sm.png b/theme/base/pix/fp/alias_sm.png
deleted file mode 100644 (file)
index 3fcc54b..0000000
Binary files a/theme/base/pix/fp/alias_sm.png and /dev/null differ
diff --git a/theme/base/pix/fp/check.png b/theme/base/pix/fp/check.png
deleted file mode 100644 (file)
index 0cbaca0..0000000
Binary files a/theme/base/pix/fp/check.png and /dev/null differ
diff --git a/theme/base/pix/fp/create_folder.png b/theme/base/pix/fp/create_folder.png
deleted file mode 100644 (file)
index 6725d42..0000000
Binary files a/theme/base/pix/fp/create_folder.png and /dev/null differ
diff --git a/theme/base/pix/fp/create_folder.svg b/theme/base/pix/fp/create_folder.svg
deleted file mode 100644 (file)
index e9b3d33..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [\r
-       <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">\r
-]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 -1.5 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M9 9.5v4H1c-.5 0-1-.5-1-1V1c0-.5.5-1 1-1h6c.5 0 1 .5 1 1v1.5h7c.5 0 1 .5 1 1v6h-1v-2h-4v2H9zm7 1h-2v-2h-2v2h-2v2h2v2h2v-2h2v-2z" fill="#989898"/></svg>
\ No newline at end of file
diff --git a/theme/base/pix/fp/cross.png b/theme/base/pix/fp/cross.png
deleted file mode 100644 (file)
index e595ade..0000000
Binary files a/theme/base/pix/fp/cross.png and /dev/null differ
diff --git a/theme/base/pix/fp/dnd_arrow.gif b/theme/base/pix/fp/dnd_arrow.gif
deleted file mode 100644 (file)
index 62d1a5b..0000000
Binary files a/theme/base/pix/fp/dnd_arrow.gif and /dev/null differ
diff --git a/theme/base/pix/fp/download_all.png b/theme/base/pix/fp/download_all.png
deleted file mode 100644 (file)
index 0f08f97..0000000
Binary files a/theme/base/pix/fp/download_all.png and /dev/null differ
diff --git a/theme/base/pix/fp/download_all.svg b/theme/base/pix/fp/download_all.svg
deleted file mode 100644 (file)
index 007cc99..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [\r
-       <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">\r
-]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M16 9v6c0 .5-.5 1-1 1H1c-.5 0-1-.5-1-1V9c0-.5.5-1 1-1h1c.5 0 1 .5 1 1v4h10V9c0-.5.5-1 1-1h1c.5 0 1 .5 1 1zm-3.6-3.9l-.7-.7c-.4-.4-1-.4-1.4 0l-.8.8V1c0-.5-.4-1-1-1h-1c-.5 0-1 .5-1 1v4.2l-.8-.8c-.4-.4-1-.4-1.4 0l-.7.7c-.4.4-.4 1 0 1.4l3.7 3.7c.2.2.5.3.7.3.3 0 .5-.1.7-.3l3.7-3.7c.4-.3.4-1 0-1.4z" fill="#999"/></svg>
\ No newline at end of file
diff --git a/theme/base/pix/fp/help.png b/theme/base/pix/fp/help.png
deleted file mode 100644 (file)
index c955f9c..0000000
Binary files a/theme/base/pix/fp/help.png and /dev/null differ
diff --git a/theme/base/pix/fp/help.svg b/theme/base/pix/fp/help.svg
deleted file mode 100644 (file)
index f6b5306..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [\r
-       <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">\r
-]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm0 14c-3.3 0-6-2.7-6-6s2.7-6 6-6 6 2.7 6 6-2.7 6-6 6zM5.8 6.6c-.6 0-1-.4-1-1C4.7 4.5 5.9 3 8.1 3c1.4 0 3.4 1 3.4 2.6 0 .8-.5 1.5-1.5 1.9-1.5.5-.7 1.6-2 1.6-.6 0-1-.3-1-.9 0-1.2 1.2-1.8 1.2-3 0-.3-.1-.7-.5-.7s-.4.4-.4.7c-.1.9-.6 1.4-1.5 1.4zm2.1 6.5c-.8 0-1.5-.7-1.5-1.5S7 10 7.9 10c.8 0 1.5.7 1.5 1.5s-.7 1.6-1.5 1.6z" fill="#999"/></svg>
\ No newline at end of file
diff --git a/theme/base/pix/fp/link.png b/theme/base/pix/fp/link.png
deleted file mode 100644 (file)
index bdd370c..0000000
Binary files a/theme/base/pix/fp/link.png and /dev/null differ
diff --git a/theme/base/pix/fp/link_sm.png b/theme/base/pix/fp/link_sm.png
deleted file mode 100644 (file)
index 90584ac..0000000
Binary files a/theme/base/pix/fp/link_sm.png and /dev/null differ
diff --git a/theme/base/pix/fp/logout.png b/theme/base/pix/fp/logout.png
deleted file mode 100644 (file)
index dab5716..0000000
Binary files a/theme/base/pix/fp/logout.png and /dev/null differ
diff --git a/theme/base/pix/fp/logout.svg b/theme/base/pix/fp/logout.svg
deleted file mode 100644 (file)
index 409824a..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [\r
-       <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">\r
-]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M9 16H1c-.5 0-1-.5-1-1V1c0-.5.5-1 1-1h8v2H3c-.6 0-1 .4-1 1v10c0 .6.4 1 1 1h6v2zM5 7.5v1c0 .5.5 1 1 1h4.7l-1.1 1.1c-.4.4-.4 1 0 1.4l.7.7c.4.4 1 .4 1.4 0l4-4c.4-.4.4-1 0-1.4l-4-4c-.4-.4-1-.4-1.4 0l-.7.7c-.4.4-.4 1 0 1.4l1 1H6c-.5.1-1 .6-1 1.1z" fill="#989898"/></svg>
\ No newline at end of file
diff --git a/theme/base/pix/fp/path_folder.png b/theme/base/pix/fp/path_folder.png
deleted file mode 100644 (file)
index 8cd1788..0000000
Binary files a/theme/base/pix/fp/path_folder.png and /dev/null differ
diff --git a/theme/base/pix/fp/path_folder_rtl.png b/theme/base/pix/fp/path_folder_rtl.png
deleted file mode 100644 (file)
index a9496d7..0000000
Binary files a/theme/base/pix/fp/path_folder_rtl.png and /dev/null differ
diff --git a/theme/base/pix/fp/refresh.png b/theme/base/pix/fp/refresh.png
deleted file mode 100644 (file)
index beb8d71..0000000
Binary files a/theme/base/pix/fp/refresh.png and /dev/null differ
diff --git a/theme/base/pix/fp/refresh.svg b/theme/base/pix/fp/refresh.svg
deleted file mode 100644 (file)
index 2a3c4bb..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [\r
-       <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">\r
-]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M7.9 16c4 0 7.4-3 7.8-7h-3c-.5 2-2.5 4-4.9 4-2.8 0-5-2.2-5-5s2.2-5 5-5c1.1 0 2.1 0 3 1h-1c-.5 0-.8.5-.8 1.1v1c0 .5.3.9.8.9h5c.6 0 1.2-.4 1.2-.9v-5c0-.6-.6-1.1-1.2-1.1h-1c-.5 0-.8.5-.8 1.1V2C12 .9 9.9.2 8 .2 3.6.2 0 3.7 0 8.1 0 12.4 3.5 16 7.9 16z" fill="#999"/></svg>
\ No newline at end of file
diff --git a/theme/base/pix/fp/search.png b/theme/base/pix/fp/search.png
deleted file mode 100644 (file)
index 8fc4ca9..0000000
Binary files a/theme/base/pix/fp/search.png and /dev/null differ
diff --git a/theme/base/pix/fp/search.svg b/theme/base/pix/fp/search.svg
deleted file mode 100644 (file)
index 2b78535..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [\r
-       <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">\r
-]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="-0.1 -0.1 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M15.5 13.4l-2.1-2.1c-.2-.2-.4-.3-.6-.3.8-1.2 1.2-2.6 1.2-4 0-3.9-3.1-7-7-7S0 3.1 0 7c0 1.9.7 3.6 2 5 1.3 1.3 3.1 2 5 2 1.4 0 2.8-.4 3.9-1.2l.3.6 2.1 2.1c.6.6 1.5.6 2.1 0s.7-1.6.1-2.1zM7 11v1.5V11c-1.1 0-2.1-.4-2.8-1.2C3.4 9.1 3 8.1 3 7c0-2.2 1.8-4 4-4s4 1.8 4 4c0 1.1-.4 2.1-1.2 2.8-.7.8-1.7 1.2-2.8 1.2z" fill="#999"/></svg>
\ No newline at end of file
diff --git a/theme/base/pix/fp/setting.png b/theme/base/pix/fp/setting.png
deleted file mode 100644 (file)
index 6cb4579..0000000
Binary files a/theme/base/pix/fp/setting.png and /dev/null differ
diff --git a/theme/base/pix/fp/setting.svg b/theme/base/pix/fp/setting.svg
deleted file mode 100644 (file)
index ba1abfb..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [\r
-       <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">\r
-]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M15.9 9.3c.1-.4.1-.9.1-1.3s0-.9-.1-1.3l-2.1-.4c-.1-.4-.3-.8-.5-1.2l1.2-1.8c-.5-.7-1.1-1.3-1.9-1.8l-1.8 1.2c-.4-.2-.8-.4-1.2-.5L9.3.1C8.9 0 8.4 0 8 0s-.9 0-1.3.1l-.4 2.1c-.4.2-.8.3-1.2.5L3.4 1.5C2.6 2 2 2.6 1.5 3.4l1.2 1.8c-.2.3-.3.7-.5 1.1l-2.1.4C0 7.1 0 7.6 0 8s0 .9.1 1.3l2.1.4c.1.4.3.8.5 1.2l-1.2 1.8c.5.7 1.1 1.3 1.9 1.8l1.8-1.2c.4.2.8.4 1.2.5l.4 2.1c.3.1.8.1 1.2.1s.9 0 1.3-.1l.4-2.1c.4-.1.8-.3 1.2-.5l1.8 1.2c.7-.5 1.3-1.1 1.9-1.9l-1.2-1.8c.2-.4.4-.8.5-1.2l2-.3zM8 10c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z" fill="#999"/></svg>
\ No newline at end of file
diff --git a/theme/base/pix/fp/view_icon_active.png b/theme/base/pix/fp/view_icon_active.png
deleted file mode 100644 (file)
index d6d8d3b..0000000
Binary files a/theme/base/pix/fp/view_icon_active.png and /dev/null differ
diff --git a/theme/base/pix/fp/view_icon_active.svg b/theme/base/pix/fp/view_icon_active.svg
deleted file mode 100644 (file)
index 04c1f45..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [\r
-       <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">\r
-]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 -1 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M9 14h7V8H9v6zm5-4v2h-3v-2h3zM7 8H0v6h7V8zm-5 4v-2h3v2H2zM9 0v6h7V0H9zm5 4h-3V2h3v2zM7 0H0v6h7V0zM2 4V2h3v2H2z" fill="#999"/></svg>
\ No newline at end of file
diff --git a/theme/base/pix/fp/view_list_active.png b/theme/base/pix/fp/view_list_active.png
deleted file mode 100644 (file)
index be1a89b..0000000
Binary files a/theme/base/pix/fp/view_list_active.png and /dev/null differ
diff --git a/theme/base/pix/fp/view_list_active.svg b/theme/base/pix/fp/view_list_active.svg
deleted file mode 100644 (file)
index b52cccb..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [\r
-       <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">\r
-]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 -1 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M16 14H0v-2h16v2zM0 10h16V8H0v2zm16-6H0v2h16V4zm0-2V0H0v2h16z" fill="#999"/></svg>
\ No newline at end of file
diff --git a/theme/base/pix/fp/view_tree_active.png b/theme/base/pix/fp/view_tree_active.png
deleted file mode 100644 (file)
index ee00bd1..0000000
Binary files a/theme/base/pix/fp/view_tree_active.png and /dev/null differ
diff --git a/theme/base/pix/fp/view_tree_active.svg b/theme/base/pix/fp/view_tree_active.svg
deleted file mode 100644 (file)
index 34755ad..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [\r
-       <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">\r
-]><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 -1 16 16" preserveAspectRatio="xMinYMid meet" overflow="visible"><path d="M10 12h6v2h-6v-2zm-2 2v-2H6v2h2zm0-4h8V8H8v2zM4 8v2h2V8H4zm2-2h10V4H6v2zM2 4v2h2V4H2zm2-4v2h12V0H4zM2 0H0v2h2V0z" fill="#999"/></svg>
\ No newline at end of file
diff --git a/theme/base/pix/horizontal-menu-submenu-indicator.png b/theme/base/pix/horizontal-menu-submenu-indicator.png
deleted file mode 100644 (file)
index f465263..0000000
Binary files a/theme/base/pix/horizontal-menu-submenu-indicator.png and /dev/null differ
diff --git a/theme/base/pix/progress.gif b/theme/base/pix/progress.gif
deleted file mode 100644 (file)
index 0bc00df..0000000
Binary files a/theme/base/pix/progress.gif and /dev/null differ
diff --git a/theme/base/pix/screenshot.png b/theme/base/pix/screenshot.png
deleted file mode 100644 (file)
index 82e1abc..0000000
Binary files a/theme/base/pix/screenshot.png and /dev/null differ
diff --git a/theme/base/pix/sprite.png b/theme/base/pix/sprite.png
deleted file mode 100644 (file)
index b2a31cd..0000000
Binary files a/theme/base/pix/sprite.png and /dev/null differ
diff --git a/theme/base/pix/vertical-menu-submenu-indicator.png b/theme/base/pix/vertical-menu-submenu-indicator.png
deleted file mode 100644 (file)
index bbd8044..0000000
Binary files a/theme/base/pix/vertical-menu-submenu-indicator.png and /dev/null differ
diff --git a/theme/base/pix/yui2-treeview-sprite-rtl.gif b/theme/base/pix/yui2-treeview-sprite-rtl.gif
deleted file mode 100644 (file)
index 5198c1b..0000000
Binary files a/theme/base/pix/yui2-treeview-sprite-rtl.gif and /dev/null differ
diff --git a/theme/base/style/admin.css b/theme/base/style/admin.css
deleted file mode 100644 (file)
index 17edc0e..0000000
+++ /dev/null
@@ -1,1110 +0,0 @@
-/**
- * Admin
- **/
-.formtable tbody th {
-    font-weight: normal;
-    text-align: right;
-}
-
-.path-admin #manageauthtable,
-.path-admin .admintable {
-    width: 100%;
-}
-
-.path-admin #assignrole {
-    width: 60%;
-    margin-left: auto;
-    margin-right: auto;
-}
-
-.path-admin .admintable .leftalign {
-    text-align: left;
-}
-
-.dir-rtl.path-admin .admintable .leftalign {
-    text-align: right;
-}
-
-.path-admin .admintable .centeralign {
-    text-align: center;
-}
-
-.path-admin .admintable.environmenttable .name,
-.path-admin .admintable.environmenttable .status,
-.path-admin .admintable.environmenttable .info {
-    width: 10%;
-    white-space: nowrap;
-}
-
-.path-admin #cohorts .admintable .name {
-    width: 20%;
-}
-
-.path-admin #cohorts .admintable .id,
-.path-admin #cohorts .admintable .size,
-.path-admin #cohorts .admintable .action,
-.path-admin #cohorts .admintable .source {
-    width: 10%;
-}
-
-.path-admin #cohorts .admintable .description {
-    width: 40%;
-}
-
-.path-admin .admintable.externalservices .service {
-    width: 30%;
-}
-
-.path-admin .admintable.externalservices .plugin,
-.path-admin .admintable.externalservices .delete {
-    width: 20%;
-}
-
-.path-admin .admintable.externalservices .functions {
-    width: 20%;
-}
-
-.path-admin .admintable.externalservices .users {
-    width: 20%;
-}
-
-.path-admin .admintable.externalservices .action {
-    width: 10%;
-}
-
-.path-admin .wsoverview.admintable .step {
-    width: 30%;
-}
-
-.path-admin .wsoverview.admintable .status {
-    width: 10%;
-}
-
-.path-admin .wsoverview.admintable .description {
-    width: 60%;
-}
-
-.path-admin #assignrole .admintable .role,
-.path-admin #assignrole .admintable .userrole,
-.path-admin #assignrole .admintable .roleholder {
-    white-space: nowrap;
-}
-
-.path-admin .admintable.environmenttable .report {
-    width: 100%;
-}
-
-.path-admin #configchanges .admintable .date {
-    width: 30%;
-}
-
-.path-admin #configchanges .admintable .name,
-.path-admin #configchanges .admintable .plugin,
-.path-admin #configchanges .admintable .setting {
-    width: 10%;
-}
-
-.path-admin #configchanges .admintable .newvalue,
-.path-admin #configchanges .admintable .originalvalue {
-    width: 20%;
-}
-
-.path-admin .securityreport.admintable .issue {
-    width: 30%;
-}
-
-.path-admin .securityreport.admintable .status {
-    width: 10%;
-}
-
-.path-admin .securityreport.admintable .desc {
-    width: 50%;
-}
-
-.path-admin .securityreport.admintable .config {
-    width: 10%;
-}
-
-.path-admin #securityreporttable .admintable  .desc {
-    width: 60%;
-}
-
-#page-admin-index .c0 {
-    vertical-align: top;
-}
-
-#page-admin-index .c1 {
-    vertical-align: middle;
-}
-
-#page-admin-blocks .generaltable th,
-#page-admin-filters .generaltable th,
-#page-admin-auth .generaltable th,
-#page-admin-modules .generaltable th,
-#page-admin-modules .generaltable td.c0 {
-    white-space: nowrap;
-    padding: 4px;
-}
-
-#page-admin-blocks .generaltable td.cell,
-#page-admin-filters .generaltable td.cell,
-#page-admin-modules .generaltable td.cell,
-#page-admin-auth .generaltable td.cell {
-    padding: 4px;
-}
-
-.path-admin .incompatibleblockstable td.c0 {
-    font-weight: bold;
-}
-
-#page-admin-course-manage .addcategory {
-    padding: 10px;
-}
-
-#page-admin-course-manage .buttons {
-    margin-bottom: 15px;
-}
-
-#page-admin-course-manage .editcourse {
-    margin: 20px auto;
-}
-
-#page-admin-course-manage .editcourse th,
-#page-admin-course-manage .editcourse td {
-    padding-left: 10px;
-    padding-right: 10px;
-}
-
-#page-admin-course-manage .editcourse .count {
-    text-align: right;
-}
-
-#page-admin-course-manage.dir-rtl .editcourse td[align="left"] {
-    text-align: right;
-}
-
-#page-admin-course-manage.dir-rtl .editcourse td[align="right"] {
-    text-align: left;
-}
-
-#page-admin-report-security-index .timewarninghidden {
-    display: none;
-}
-
-#page-admin-report-security-index .statuswarning,
-#page-admin-report-performance-index .statuswarning {
-    background-color: #f0e000;
-}
-
-#page-admin-report-security-index .statusserious,
-#page-admin-report-performance-index .statusserious {
-    background-color: #f07000;
-}
-
-#page-admin-report-security-index .statuscritical,
-#page-admin-report-performance-index .statuscritical {
-    background-color: #f00000;
-}
-
-#page-admin-report-capability-index .rolecaps th {
-    text-align: left;
-}
-
-#page-admin-report-capability-index #settingsform #capabilitysearch {
-    width: 30em;
-}
-
-#page-admin-report-backups-index .backup-report {
-    width: 100%;
-}
-
-#page-admin-report-backups-index .backup-error,
-#page-admin-report-backups-index .backup-unfinished {
-    color: #f00000;
-}
-
-#page-admin-report-backups-index .backup-skipped,
-#page-admin-report-backups-index .backup-ok {
-    color: #006400;
-}
-
-#page-admin-report-backups-index .backup-warning {
-    color: #ff9900;
-}
-
-#page-admin-report-backups-index .backup-notyetrun {
-    color: #006400;
-}
-
-#page-admin-qbehaviours .disabled {
-    color: gray;
-}
-
-#page-admin-qbehaviours th {
-    white-space: normal;
-}
-
-#page-admin-qbehaviours .cell.c1,
-#page-admin-qbehaviours .cell.c2 {
-    text-align: right;
-}
-
-#page-admin-qbehaviours .cell.c3 {
-    font-size: 0.7em;
-}
-
-#page-admin-qbehaviours #qbehaviours div,
-#page-admin-qbehaviours #qbehaviours form {
-    display: inline;
-}
-
-#page-admin-qbehaviours #qbehaviours img.spacer {
-    width: 16px;
-}
-
-#page-admin-qbehaviours #qbehaviours img {
-    padding-right: .45em;
-}
-
-#page-admin-qtypes .disabled {
-    color: gray;
-}
-
-#page-admin-qtypes th {
-    white-space: normal;
-}
-
-#page-admin-qtypes .cell.c1,
-#page-admin-qtypes .cell.c2 {
-    text-align: right;
-}
-
-#page-admin-qtypes .cell.c3 {
-    font-size: 0.7em;
-}
-
-#page-admin-qtypes #qtypes div,
-#page-admin-qtypes #qtypes form {
-    display: inline;
-}
-
-#page-admin-qtypes #qtypes img.spacer {
-    width: 16px;
-}
-
-#page-admin-qtypes #qtypes img {
-    padding-right: .45em;
-    vertical-align: text-bottom;
-}
-
-.path-admin-roles .buttons .singlebutton,
-#page-admin-course-manage .buttons {
-    display: inline;
-    padding: 5px;
-}
-
-.path-admin-roles .capabilitysearchui {
-    text-align: left;
-    margin-left: auto;
-    margin-right: auto;
-}
-
-#page-admin-roles-define .topfields {
-    margin: 1em 0 2em;
-}
-
-#page-admin-roles-define .mform {
-    width: 100%;
-}
-
-#page-admin-roles-define .capdefault {
-    background-color: #eee;
-    border: 1px solid #cecece;
-}
-
-#page-filter-manage .backlink,
-.path-admin-roles .backlink {
-    margin-top: 1em;
-}
-
-#page-admin-roles-explain #chooseuser h3,
-#page-admin-roles-usersroles .contextname {
-    margin-top: 0;
-}
-
-#page-admin-roles-explain #chooseusersubmit {
-    margin-top: 0;
-    text-align: center;
-}
-
-#page-admin-roles-usersroles p {
-    margin: 0;
-}
-
-#page-admin-roles-override .cell.c1,
-#page-admin-roles-assign .cell.c3,
-#page-admin-roles-assign .cell.c1 {
-    padding-top: 0.75em;
-}
-
-#page-admin-roles-override .overridenotice,
-#page-admin-roles-define .definenotice {
-    margin: 1em 10% 2em 10%;
-    text-align: left;
-}
-
-#page-admin-index .adminerror {
-    background-color: #ffd3d9;
-}
-
-#page-admin-index .adminerror .singlebutton,
-#page-admin-index .adminwarning .singlebutton,
-#page-admin-index #layout-table .singlebutton {
-    margin: 20px;
-}
-
-#page-admin-index .adminwarning.availableupdatesinfo .moodleupdateinfo {
-    line-height: 1.8;
-    margin: 20px auto;
-    width: 60%;
-    text-align: left;
-}
-
-#page-admin-index .adminwarning.availableupdatesinfo .moodleupdateinfo .info.release {
-    margin-right: 10px;
-    padding: 5px 10px;
-    -moz-border-radius: 10px;
-    -webkit-border-radius: 10px;
-    border-radius: 10px;
-}
-
-#page-admin-index .adminwarning.availableupdatesinfo .moodleupdateinfo.maturity50 .info.release {
-    background-color: #ffd3d9;
-}
-
-#page-admin-index .adminwarning.availableupdatesinfo .moodleupdateinfo.maturity100 .info.release,
-#page-admin-index .adminwarning.availableupdatesinfo .moodleupdateinfo.maturity150 .info.release {
-    background-color: #f3f2aa;
-}
-
-#page-admin-index .adminwarning.availableupdatesinfo .moodleupdateinfo.maturity200 .info.release {
-    background-color: #d2ebff;
-}
-
-#page-admin-index .adminwarning.availableupdatesinfo .moodleupdateinfo span,
-#page-admin-index .adminwarning.availableupdatesinfo .moodleupdateinfo a {
-    padding-right: 1em;
-}
-
-#page-admin-index .adminwarning.availableupdatesinfo .moodleupdateinfo .separator {
-    border-left: 1px dotted #333;
-}
-
-#page-admin-index .updateplugin div,
-#page-admin-plugins .updateplugin div {
-    margin-bottom: 0.5em;
-}
-
-#page-admin-index .updateplugin .updatepluginconfirmexternal,
-#page-admin-plugins .updateplugin .updatepluginconfirmexternal {
-    padding: 1em;
-    background-color: #ffd3d9;
-    border: 1px solid #EEAAAA;
-}
-
-#page-admin-plugins .uninstalldeleteconfirmexternal {
-    margin: 1em auto;
-    padding: 1em;
-    background-color: #ffd3d9;
-    border: 1px solid #EEAAAA;
-}
-
-#page-admin-user-user_bulk #users .fgroup {
-    white-space: nowrap;
-}
-
-#page-admin-report-stats-index .graph {
-    text-align: center;
-    margin-bottom: 1em;
-}
-
-#page-admin-report-courseoverview-index .graph {
-    text-align: center;
-    margin-bottom: 1em;
-}
-
-#page-admin-lang .translator {
-    border-width: 1px;
-    border-style: solid;
-}
-
-#page-admin-uploaduser table#uuresults {
-    margin-bottom: 2em;
-}
-
-#page-admin-uploaduser table#uupreview,
-#page-admin-uploaduser table#uuresults td.cell {
-    padding: 3px;
-}
-
-/** This is the CSS for the role assignment control **/
-.path-admin .roleassigntable {
-    width: 100%;
-}
-
-.path-admin .roleassigntable td {
-    vertical-align: top;
-    padding: 0.2em 0.3em;
-}
-
-.path-admin .roleassigntable p {
-    text-align: left;
-    margin: 0.2em 0;
-}
-
-.path-admin .roleassigntable #existingcell,
-.path-admin .roleassigntable #potentialcell {
-    width: 42%;
-}
-
-.path-admin .roleassigntable #existingcell label,
-.path-admin .roleassigntable #potentialcell label {
-    font-weight: bold;
-}
-
-.path-admin .roleassigntable #buttonscell {
-    width: 16%;
-}
-
-.path-admin .roleassigntable #buttonscell #add,
-.path-admin .roleassigntable #buttonscell #remove {
-    width: 100%;
-    margin: 0.3em 0;
-    padding: 0.5em 0;
-}
-
-.path-admin .roleassigntable #buttonscell p {
-    margin: 0.3em 0;
-}
-
-.path-admin .roleassigntable #buttonscell #assignoptions {
-    font-size: 0.75em;
-}
-
-.path-admin .roleassigntable #buttonscell #assignoptions .collapsibleregioncaption {
-    font-weight: bold;
-}
-
-.path-admin .roleassigntable #buttonscell #addcontrols {
-    margin-top: 3em;
-    height: 13em;
-}
-
-.path-admin .roleassigntable #removeselect_wrapper,
-.path-admin .roleassigntable #addselect_wrapper {
-    width: 100%;
-}
-
-.path-admin .roleassigntable #removeselect_wrapper label,
-.path-admin .roleassigntable #addselect_wrapper label {
-    font-weight: normal;
-}
-
-.path-admin table.rolecap {
-    margin-left: auto;
-    margin-right: auto;
-}
-
-.path-admin table.rolecap tr.rolecap th {
-    text-align: left;
-    font-weight: normal;
-}
-
-.path-admin.dir-rtl table.rolecap tr.rolecap th {
-    text-align: right;
-}
-
-.path-admin .rolecap .hiddenrow {
-    display: none;
-}
-
-.path-admin .rolecap .inherit,
-.path-admin .rolecap .allow,
-.path-admin .rolecap .prevent,
-.path-admin .rolecap .prohibit {
-    text-align: center;
-}
-
-.path-admin .rolecap .cap-name,
-.path-admin .rolecap .note {
-    display: block;
-    padding: 0 0.5em;
-}
-
-.path-admin .rolecap label {
-    display: block;
-    width: 100%;
-    min-height: 2.5em;
-}
-
-#page-admin-enrol .enrolplugintable {
-    width: 100%;
-}
-
-.plugincheckwrapper {
-    width: 100%;
-}
-
-.adminsearchform {
-    padding-top: 10px;
-}
-
-.environmentbox {
-    margin-top: 1em;
-}
-
-#mnetconfig table,
-.environmenttable {
-    margin-left: auto;
-    margin-right: auto;
-}
-
-.environmenttable .cell {
-    padding: 0.15em 0.5em;
-}
-
-.environmenttable img.iconhelp {
-    padding-right: 0.3em;
-}
-
-.dir-rtl .environmenttable img.iconhelp {
-    padding-left: 0.3em;
-    padding-right: 0;
-}
-
-#trustedhosts .generaltable {
-    margin-left: auto;
-    margin-right: auto;
-    width: 500px;
-}
-
-#trustedhosts .standard {
-    width: auto;
-}
-
-.form-buttons {
-    margin: 10px 0 0 13em;
-}
-
-#adminsettings fieldset {
-    margin-top: 1em;
-    padding: 1em 0.5em;
-}
-
-#adminsettings legend {
-    display: none;
-}
-
-#adminsettings fieldset.error {
-    margin: 0.2em 0 0.5em 0;
-    padding: 0.5em 0 0 0;
-}
-
-#adminsettings fieldset.error legend {
-    display: block;
-}
-
-#adminsettings .form-item {
-    clear: both;
-    margin: 1em 0 2em 0;
-}
-
-#adminsettings .form-item .form-label {
-    display: block;
-    float: left;
-    width: 12.5em;
-    text-align: right;
-}
-
-.dir-rtl #adminsettings .form-item .form-label {
-    float: right;
-}
-
-#adminsettings .form-item .form-label .form-shortname {
-    display: block;
-}
-
-.dir-rtl #adminsettings .form-item .form-label .form-shortname {
-    text-align: left;
-}
-
-#adminsettings .form-item .form-setting {
-    display: block;
-    margin-left: 13.5em;
-    text-align: left;
-}
-
-.dir-rtl #adminsettings .form-item .form-setting {
-    margin-right: 13.5em;
-    margin-left: auto;
-    text-align: right;
-}
-
-.dir-rtl #admin-spelllanguagelist textarea,
-#page-admin-setting-editorsettingstinymce.dir-rtl .form-textarea textarea {
-    text-align: left;
-    direction: ltr;
-}
-
-#adminsettings .form-item .form-setting .form-htmlarea {
-    display: inline;
-}
-
-#adminsettings .form-item .form-setting .form-htmlarea .htmlarea {
-    width: 640px;
-    display: block;
-}
-
-#adminsettings .form-item .form-setting .form-multicheckbox li {
-    list-style: none;
-}
-
-#adminsettings .form-item .form-setting .form-multicheckbox ul {
-    padding: 0;
-    margin: 0;
-}
-
-#adminsettings .form-item .form-setting .defaultsnext {
-    margin-right: 0.5em;
-    display: inline;
-}
-
-#adminsettings .form-item .form-setting .locked-checkbox {
-    margin-right: 0.2em;
-    margin-left: 0.5em;
-    display: inline;
-}
-
-.dir-rtl #adminsettings .form-item .form-setting .locked-checkbox {
-    margin-right: 0.5em;
-    margin-left: 0.2em;
-    display: inline;
-}
-
-#adminsettings .form-item .form-setting .form-password .unmask,
-#adminsettings .form-item .form-setting .form-defaultinfo {
-    display: inline;
-}
-
-#adminsettings .form-item .form-description {
-    display: block;
-    margin: 0.5em 0 0em 14.25em;
-    text-align: left;
-}
-
-.dir-rtl #adminsettings .form-item .form-description {
-    margin: 0.5em 14.25em 0em 0em;
-}
-
-#adminsettings .form-item .pathok,
-#adminsettings .form-item .patherror {
-    margin-left: 0.5em;
-}
-
-#adminsettings #admin-emoticons table td input {
-    width: 8em;
-}
-
-#adminsettings #admin-emoticons table td.c0 input {
-    width: 4em;
-}
-
-#adminsettings .form-overridden {
-    background-color: yellow;
-}
-
-#adminthemeselector .selectedtheme td.c0 {
-    border: 1px solid;
-    border-right-width: 0;
-}
-
-#adminthemeselector .selectedtheme td.c1 {
-    border: 1px solid;
-    border-left-width: 0;
-}
-
-.admin_colourpicker,
-.admin_colourpicker_preview {
-    display: none;
-}
-
-.jsenabled .admin_colourpicker_preview {
-    display: inline;
-}
-
-.jsenabled .admin_colourpicker {
-    display: block;
-    height: 102px;
-    width: 410px;
-    margin-bottom: 10px;
-}
-
-.admin_colourpicker .loadingicon {
-    vertical-align: middle;
-    margin-left: auto;
-}
-
-.admin_colourpicker .colourdialogue {
-    float: left;
-    border: 1px solid #000;
-}
-
-.admin_colourpicker .previewcolour {
-    border: 1px solid #000;
-    margin-left: 301px;
-}
-
-.admin_colourpicker .currentcolour {
-    border: 1px solid #000;
-    margin-left: 301px;
-    border-top-width: 0;
-}
-
-/* Styles for flags on admin settings */
-.adminsettingsflags {
-    float: right;
-}
-
-.dir-rtl .adminsettingsflags {
-    float: left;
-}
-
-.adminsettingsflags label {
-    margin-right: 7px;
-}
-
-.dir-rtl .adminsettingsflags label {
-    margin-left: 7px;
-}
-
-/** Overide for RTL layout **/
-.dir-rtl #adminsettings .form-item  .form-setting,
-.dir-rtl #adminsettings .form-item  .form-label,
-.dir-rtl #adminsettings .form-item .form-description {
-    text-align: right;
-}
-
-.dir-rtl.path-admin .roleassigntable p {
-    text-align: right;
-}
-
-/** Plugins check */
-#page-admin-index .checkforupdates {
-    text-align: center;
-}
-
-#page-admin-index #plugins-check-info {
-    text-align: center;
-    margin: 1em;
-}
-
-#page-admin-index #plugins-check td {
-    vertical-align: top;
-}
-
-#page-admin-index #plugins-check {
-    margin-left: auto;
-    margin-right: auto;
-}
-
-#page-admin-index #plugins-check .displayname .pluginicon {
-    width: 16px;
-    margin-right: 5px;
-}
-
-#page-admin-index #plugins-check .displayname .plugindir {
-    font-size: 0.7em;
-    color: #999;
-}
-
-#page-admin-index #plugins-check .msg td {
-    text-align: center;
-}
-
-#page-admin-index #plugins-check .status-downgrade .status {
-    background-color: #ffd3d9;
-}
-
-#page-admin-index #plugins-check .status-missing .status {
-    background-color: #ffd3d9;
-}
-
-#page-admin-index #plugins-check .status-new .status {
-    background-color: #e7f1c3;
-}
-
-#page-admin-index #plugins-check .status-nodb .status .statustext {
-    color: #999;
-}
-
-#page-admin-index #plugins-check .status-delete .status {
-    background-color: #d2ebff;
-}
-
-#page-admin-index #plugins-check .status-upgrade .status {
-    background-color: #d2ebff;
-}
-
-#page-admin-index #plugins-check .status-uptodate .status .statustext {
-    color: #999;
-}
-
-#page-admin-index #plugins-check .status .sourcetext:after {
-    content: " / ";
-}
-
-#page-admin-index #plugins-check .standard .status .sourcetext {
-    color: #999;
-}
-
-#page-admin-index #plugins-check .requires ul {
-    font-size: 0.7em;
-    margin: 0;
-}
-
-#page-admin-index #plugins-check .requires li {
-    display: block;
-}
-
-#page-admin-index #plugins-check .requires-ok {
-    color: #999;
-}
-
-#page-admin-index #plugins-check .requires-failed {
-    background-color: #ffd3d9;
-}
-
-#page-admin-index #plugins-check .requires-failed .label-important {
-    color: red;
-}
-
-#page-admin-index #plugins-check .pluginupdateinfo {
-    padding: 5px;
-    margin: 10px 0;
-    background-color: #d2ebff;
-    -moz-border-radius: 5px;
-    -webkit-border-radius: 5px;
-    border-radius: 5px;
-}
-
-#page-admin-index #plugins-check .pluginupdateinfo.maturity50 {
-    background-color: #ffd3d9;
-}
-
-#page-admin-index #plugins-check .pluginupdateinfo.maturity100,
-#page-admin-index #plugins-check .pluginupdateinfo.maturity150 {
-    background-color: #f3f2aa;
-}
-
-#page-admin-index #plugins-check .pluginupdateinfo .info {
-    display: inline-block;
-}
-
-#page-admin-index #plugins-check .pluginupdateinfo .separator:after {
-    content: " | ";
-}
-
-#page-admin-index .upgradepluginsinfo {
-    text-align: center;
-}
-
-#page-admin-index .plugins-check-dependencies {
-    text-align: center;
-}
-
-#page-admin-index #plugins-check-available-dependencies {
-    margin-left: auto;
-    margin-right: auto;
-}
-
-/** Plugins management */
-#page-admin-plugins .checkforupdates {
-    margin: 0 auto 1em;
-    text-align: center;
-}
-
-#page-admin-plugins #plugins-control-panel {
-    margin-left: auto;
-    margin-right: auto;
-}
-
-#page-admin-plugins #plugins-control-panel .pluginname .pluginicon {
-    width: 16px;
-}
-
-#page-admin-plugins #plugins-control-panel .pluginname .componentname {
-    font-size: 0.8em;
-    color: #999;
-    margin-left: 26px;
-}
-
-#page-admin-plugins #plugins-control-panel .statusmsg {
-    background-color: #eee;
-    padding: 3px;
-    -webkit-border-radius: 5px;
-    -moz-border-radius: 5px;
-    border-radius: 5px;
-}
-
-#page-admin-plugins #plugins-control-panel .status-missing td {
-    background-color: #ffd3d9;
-}
-
-#page-admin-plugins #plugins-control-panel .status-missing .statusmsg {
-    color: #600;
-}
-
-#page-admin-plugins #plugins-control-panel .status-new td {
-    background-color: #e7f1c3;
-}
-
-#page-admin-plugins #plugins-control-panel .status-new .statusmsg {
-    color: #060;
-}
-
-#page-admin-plugins #plugins-control-panel .disabled .availability {
-    background-color: #eee;
-}
-
-#page-admin-plugins #plugins-control-panel .msg td {
-    text-align: center;
-}
-
-#page-admin-plugins #plugins-control-panel .requiredby {
-    font-size: 0.8em;
-    color: #999;
-}
-
-#page-admin-plugins #plugins-overview-panel {
-    margin: 1em auto;
-    text-align: center;
-}
-
-#page-admin-plugins #plugins-overview-panel .info {
-    padding: 5px 10px;
-}
-
-#page-admin-plugins #plugins-control-panel .displayname img.icon {
-    padding-top: 0;
-    padding-bottom: 0;
-}
-
-#page-admin-plugins #plugins-control-panel .uninstall a {
-    color: #900;
-}
-
-#page-admin-plugins #plugins-control-panel .pluginupdateinfo {
-    padding: 5px;
-    margin: 10px 0;
-    background-color: #d2ebff;
-    -moz-border-radius: 5px;
-    -webkit-border-radius: 5px;
-    border-radius: 5px;
-}
-
-#page-admin-plugins #plugins-control-panel .pluginupdateinfo.maturity50 {
-    background-color: #ffd3d9;
-}
-
-#page-admin-plugins #plugins-control-panel .pluginupdateinfo.maturity100,
-#page-admin-plugins #plugins-control-panel .pluginupdateinfo.maturity150 {
-    background-color: #f3f2aa;
-}
-
-#page-admin-plugins #plugins-control-panel .pluginupdateinfo .info {
-    display: inline-block;
-}
-
-#page-admin-plugins #plugins-control-panel .pluginupdateinfo .separator:after {
-    content: " | ";
-}
-
-.dir-rtl #plugins-check .pluginupdateinfo {
-    text-align: center;
-    direction: ltr;
-}
-
-.dir-rtl #plugins-check .requires-ok {
-    text-align: left;
-    direction: ltr;
-}
-
-/** MNet networking */
-#page-admin-mnet-peers .box.deletedhosts {
-    margin-bottom: 1em;
-    font-size: 80%;
-}
-
-#page-admin-mnet-peers .mform .certdetails {
-    background-color: white;
-}
-
-#page-admin-mnet-peers .mform .deletedhostinfo {
-    background-color: #ffd3d9;
-    border: 2px solid #eeaaaa;
-    padding: 4px;
-    margin-bottom: 5px;
-}
-
-#core-cache-plugin-summaries table,
-#core-cache-store-summaries table {
-    width: 100%;
-}
-
-#core-cache-lock-summary table,
-#core-cache-definition-summaries table,
-#core-cache-mode-mappings table {
-    margin: 0 auto;
-}
-
-#core-cache-store-summaries .default-store td {
-    color: #333;
-    font-style: italic;
-}
-
-#core-cache-rescan-definitions,
-#core-cache-mode-mappings .edit-link,
-#core-cache-lock-summary .new-instance {
-    margin-top: 0.5em;
-    text-align: center;
-}
-
-#core-cache-store-summaries .store-requires-attention {
-    background-color: #ffd3d9;
-}
-
-.tinymcesubplugins img.icon {
-    padding-top: 0;
-    padding-bottom: 0;
-}
-
-.maintenancewarning {
-    padding: 3px 1em;
-    text-align: center;
-    position: fixed;
-    bottom: 0;
-    right: 0;
-    overflow: hidden;
-    z-index: 1;
-}
-
-.maintenancewarning.error {
-    background-color: #F2DEDE;
-    border: 2px solid #EED3D7;
-    font-weight: bold;
-}
-
-.maintenancewarning.warning {
-    background-color: #ffd3d9;
-    border: 2px solid #EED3D7;
-}
diff --git a/theme/base/style/autocomplete.css b/theme/base/style/autocomplete.css
deleted file mode 100644 (file)
index 6c60507..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Custom styles for autocomplete form element */
-.form-autocomplete-selection {
-    margin: 0.2em;
-    min-height: 21px;
-}
-
-.form-autocomplete-multiple [role=listitem].label {
-    cursor: pointer;
-}
-
-.form-autocomplete-selection [role=listitem].label {
-    background-color: #00E;
-    border: 4px solid #00E;
-    color: #FFF;
-    font-weight: bold;
-    border-radius: 3px;
-    display: inline-block;
-    margin-bottom: 3px;
-}
-
-.form-autocomplete-suggestions {
-    position: absolute;
-    background-color: white;
-    border: 2px solid #EEE;
-    border-radius: 3px;
-    min-width: 206px;
-    max-height: 20em;
-    overflow: auto;
-    margin: 0px;
-    padding: 0px;
-    margin-top: -0.2em;
-    z-index: 1;
-}
-
-.form-autocomplete-suggestions li {
-    list-style-type: none;
-    padding: 0.2em;
-    margin: 0;
-    cursor: pointer;
-    color: #333;
-}
-
-.form-autocomplete-suggestions li:hover {
-    background-color: #00E;
-    color: #FFF;
-}
-
-.form-autocomplete-suggestions li[aria-selected=true] {
-    background-color: #555;
-    color: #FFF;
-}
-
-.form-autocomplete-downarrow {
-    position: relative;
-    top: -0.1em;
-    left: -1.5em;
-    cursor: pointer;
-    color: #000;
-}
-
-.dir-rtl .form-autocomplete-downarrow {
-    right: -1.5em;
-    left: inherit;
-}
-
-.form-autocomplete-selection:focus {
-    outline: none;
-}
-
-.form-autocomplete-selection [data-active-selection=true] {
-    padding: 0.5em;
-    font-size: large;
-}
diff --git a/theme/base/style/blocks.css b/theme/base/style/blocks.css
deleted file mode 100644 (file)
index 99b2fe4..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-.block {
-    border: 1px solid;
-    margin-bottom: 1em;
-}
-
-.block .header h2 {
-    padding: .2em 0 0 .2em;
-    margin: 0;
-    word-wrap: break-word;
-}
-
-.block .header .block_action {
-    float: right;
-    margin: 4px 0 3px 0;
-    vertical-align: top;
-}
-
-.block .header .block_action img,
-.block .header .block_action input {
-    margin: 0 3px;
-    width: 12px;
-    height: 12px;
-}
-
-.block .content {
-    padding: 4px;
-}
-
-.jsenabled .block.hidden .content {
-    display: none;
-}
-
-.block .content .userpicture {
-    width: 16px;
-    height: 16px;
-    margin-right: 6px;
-}
-
-.block .content .list li.listentry {
-    clear: both;
-}
-
-.block .content .list .c0 {
-    display: inline;
-}
-
-.block .content .list .c1 {
-    margin-left: 5px;
-    display: inline;
-}
-
-.block .footer {
-    margin-bottom: 4px;
-}
-
-.block_navigation .block_tree li {
-    overflow: hidden;
-}
-
-.block_calendar_upcoming .footer {
-    margin-top: .5em;
-}
-
-/** block_list blocks need column stuffs **/
-.block.list_block .unlist > li > .column {
-    display: inline-block;
-}
-
-.ie6 .block.list_block .unlist .column {
-    display: inline;
-}
-
-.block.beingmoved {
-    border-width: 2px;
-    border-style: dashed;
-}
-
-.blockmovetarget {
-    display: block;
-    height: 1em;
-    margin-bottom: 1em;
-    border-width: 2px;
-    border-style: dashed;
-}
-
-.block-region block.invisible .header h2 {
-    opacity: 0.5;
-    filter: alpha(opacity=50);
-}
-
-.block .block-hider-show,
-.block .block-hider-hide {
-    cursor: pointer;
-}
-
-.block .block-hider-show,
-.block.hidden .block-hider-hide {
-    display: none;
-}
-
-.block.hidden .block-hider-show {
-    display: inline;
-}
-
-.block_completionstatus .generaltable {
-    border: 0px;
-}
-
-.block_completionstatus .generaltable .cell {
-    border: 0px;
-}
-
-.block-region {
-    min-height: 400px;
-    overflow: hidden;
-}
-/** Block commands when editing  **/
-
-.editing .block .header .commands {
-    text-align: right;
-    clear: both;
-}
-
-.editing .block .header .commands > a {
-    margin: 0 3px;
-}
-
-.editing .block .header .commands .icon img {
-    width: 12px;
-    height: 12px;
-}
-
-.editing .block .header .commands img.actionmenu {
-    width: auto;
-}
-
-/** Overide for RTL layout **/
-.dir-rtl .block .header h2 {
-    padding: .2em .2em 0 0;
-}
-
-.dir-rtl .block .header .block_action {
-    float: left;
-}
-
-.dir-rtl.editing .block .header .commands {
-    text-align: left;
-}
diff --git a/theme/base/style/calendar.css b/theme/base/style/calendar.css
deleted file mode 100644 (file)
index 303c5ae..0000000
+++ /dev/null
@@ -1,297 +0,0 @@
-/** Calendar **/
-.calendartable {
-    width: 100%;
-}
-
-.calendartable th,
-.calendartable td {
-    width: 14%;
-    vertical-align: top;
-    text-align: center;
-    border-width: 1px;
-}
-
-.calendar_event_course {
-    background-color: #FFD3BD;
-}
-
-.calendar_event_global {
-    background-color: #D6F8CD;
-}
-
-.calendar_event_group {
-    background-color: #FEE7AE;
-}
-
-.calendar_event_user {
-    background-color: #DCE7EC;
-}
-
-.path-calendar .calendar-controls .previous,
-.path-calendar .calendar-controls .next,
-.path-calendar .calendar-controls .current {
-    display: block;
-    float: left;
-    width: 12%;
-}
-
-.path-calendar .calendar-controls .previous {
-    text-align: left;
-}
-
-.path-calendar .calendar-controls .current {
-    text-align: center;
-    width: 76%;
-}
-
-.path-calendar .calendar-controls .next {
-    text-align: right;
-}
-
-.path-calendar .maincalendar {
-    vertical-align: top;
-    padding: 0;
-}
-
-.path-calendar .maincalendar .bottom {
-    text-align: center;
-    padding: 5px 0 0 0;
-}
-
-.path-calendar .maincalendar .heightcontainer {
-    height: 100%;
-    position: relative;
-}
-
-.path-calendar .maincalendar .calendarmonth {
-    width: 98%;
-    margin: 10px auto;
-}
-
-.path-calendar .maincalendar .calendarmonth ul {
-    margin: 0;
-}
-
-.path-calendar .maincalendar .calendarmonth ul li {
-    list-style-type: none;
-    margin-top: 4px;
-}
-
-.path-calendar .maincalendar .calendarmonth td {
-    height: 5em;
-}
-
-.path-calendar .maincalendar .calendar-controls .previous,
-.path-calendar .maincalendar .calendar-controls .next {
-    width: 30%;
-}
-
-.path-calendar .maincalendar .calendar-controls .current {
-    width: 39.95%;
-}
-
-.path-calendar .maincalendar .controls {
-    width: 98%;
-    margin: 10px auto;
-}
-
-.path-calendar .maincalendar .eventlist {
-    margin: 0;
-}
-
-.path-calendar .maincalendar .eventlist .event {
-    width: 100%;
-    margin-bottom: 10px;
-    border-spacing: 0px;
-    border-collapse: separate;
-    border-width: 1px;
-    border-style: solid;
-    list-style-type: none;
-}
-
-.path-calendar .maincalendar .eventlist .event > img {
-    float: left;
-}
-
-.path-calendar .maincalendar .eventlist .event > img {
-    float: right;
-}
-
-.path-calendar .maincalendar .eventlist .event .name {
-    float: left;
-    margin: 0;
-}
-
-.dir-rtl.path-calendar .maincalendar .eventlist .event .name {
-    float: right;
-}
-
-.path-calendar .maincalendar .eventlist .event .date {
-    float: right;
-}
-
-.dir-rtl.path-calendar .maincalendar .eventlist .event .date {
-    float: left;
-}
-
-.path-calendar .maincalendar .eventlist .event .subscription {
-    float: left;
-    clear: left;
-}
-
-.dir-rtl.path-calendar .maincalendar .eventlist .event .subscription {
-    float: right;
-    clear: right;
-}
-
-.path-calendar .maincalendar .eventlist .event .course {
-    float: left;
-    clear: left;
-}
-
-.dir-rtl.path-calendar .maincalendar .eventlist .event .course {
-    float: right;
-    clear: right;
-}
-
-.path-calendar .maincalendar .eventlist .event .side {
-    width: 32px;
-}
-
-.path-calendar .maincalendar .eventlist .event .commands a {
-    margin: 0 3px;
-}
-
-.path-calendar .maincalendar .eventlist .description {
-    clear: both;
-}
-
-.path-calendar .maincalendar .header {
-    overflow: hidden;
-}
-
-.path-calendar .maincalendar .header .buttons {
-    float: right;
-}
-
-.dir-rtl.path-calendar .maincalendar .header .buttons {
-    float: left;
-}
-
-.path-calendar .filters table {
-    border-collapse: separate;
-    border-spacing: 2px;
-    width: 100%;
-}
-
-#page-calendar-export .indent {
-    padding-left: 20px;
-}
-
-.path-calendar div.cal_courses_flt {
-    float: left;
-}
-
-.dir-rtl.path-calendar div.cal_courses_flt {
-    float: right;
-}
-
-.path-calendar .cal_courses_flt label {
-    margin-right: .45em;
-}
-
-.dir-rtl.path-calendar .cal_courses_flt label {
-    margin-left: .45em;
-    margin-right: 0;
-}
-
-.block .minicalendar {
-    width: 100%;
-    margin: 10px auto;
-}
-
-.block .minicalendar th,
-.block .minicalendar td {
-    padding: 2px;
-    font-size: 0.8em;
-}
-
-.block .minicalendar caption {
-    font-size: inherit;
-    font-weight: inherit;
-    line-height: inherit;
-    text-align: center;
-}
-
-.block .minicalendar td.weekend {
-    color: #A00;
-}
-
-.block .calendar-controls .previous {
-    text-align: left;
-    display: block;
-    float: left;
-    width: 12%;
-}
-
-.block .calendar-controls .current {
-    float: left;
-    text-align: center;
-    display: block;
-    width: 76%;
-}
-
-.block .calendar-controls .next {
-    text-align: right;
-    display: block;
-    float: left;
-    width: 12%;
-}
-
-.block .calendar_filters ul {
-    list-style: none;
-    margin: 0;
-}
-
-.block .calendar_filters li {
-    margin-bottom: .2em;
-}
-
-.block .calendar_filters li span img {
-    padding: 0 .2em;
-}
-
-.block .calendar_filters .eventname {
-    padding-left: .2em;
-}
-
-.dir-rtl .block .calendar_filters .eventname {
-    padding-right: .2em;
-    padding-left: 0;
-}
-
-.block .content h3.eventskey {
-    margin-top: 0.5em;
-}
-
-.ical-link {
-    font-size: 10px;
-    font-weight: bold;
-    background-color: #f60;
-    padding: 0px 5px;
-    color: #fff;
-    border-top: 1px solid #f93;
-    border-left: 1px solid #f93;
-    border-bottom: 1px solid #013;
-    border-right: 1px solid #013;
-    margin: 3px;
-    text-decoration: none;
-}
-
-.ical-link:hover,
-.ical-link:active,
-.ical-link:focus,
-.ical-link:visited {
-    color: #fff;
-    text-decoration: none;
-}
diff --git a/theme/base/style/core.css b/theme/base/style/core.css
deleted file mode 100644 (file)
index 045cdac..0000000
+++ /dev/null
@@ -1,4919 +0,0 @@
-/**
- * Required to undo YUI resets that override input size, margin, etc.
- */
-input[type=text],
-input[type=password],
-textarea {
-    width: auto;
-}
-
-input[type=checkbox],
-input[type=radio] {
-    margin-right: 7px;
-}
-
-/* Fix for YUI overriding styles */
-strong {
-    font-style: inherit;
-}
-
-em {
-    font-weight: inherit;
-}
-
-/**
- * General
- */
-th,
-td,
-a img {
-    border-width: 0;
-}
-
-acronym,
-abbr {
-    cursor: help;
-}
-
-.dir-ltr,
-.mdl-left,
-.dir-rtl .mdl-right {
-    text-align: left;
-}
-
-.dir-rtl,
-.mdl-right,
-.dir-rtl .mdl-left {
-    text-align: right;
-}
-
-#add,
-#remove,
-.centerpara,
-.mdl-align {
-    text-align: center;
-}
-
-a.dimmed,
-a.dimmed:link,
-a.dimmed:visited,
-a.dimmed_text,
-a.dimmed_text:link,
-a.dimmed_text:visited,
-.dimmed_text,
-.dimmed_text a,
-.dimmed_text a:link,
-.dimmed_text a:visited,
-.usersuspended,
-.usersuspended a,
-.usersuspended a:link,
-.usersuspended a:visited,
-.dimmed_category,
-.dimmed_category a,
-.dimmed_category a:link,
-.dimmed_category a:visited {
-    color: #AAA;
-}
-
-.activity.label .dimmed_text {
-    opacity: 0.5;
-    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
-    filter: alpha(opacity=50);
-}
-
-.unlist,
-.unlist li,
-.inline-list,
-.inline-list li,
-.block .list,
-.block .list li,
-.sitetopic .section li.activity,
-.course-content .section li.activity,
-.sitetopic .section li.movehere,
-.course-content .section li.movehere {
-    list-style: none;
-    margin: 0;
-    padding: 0;
-}
-
-.course-content .current {
-    background: #E3E3E3;
-}
-
-.inline,
-.inline-list li {
-    display: inline;
-}
-
-.notifytiny {
-    font-size: 0.7em;
-}
-
-.notifytiny li,
-.notifytiny td {
-    font-size: 100%;
-}
-
-.red,
-.notifyproblem {
-    color: #660000;
-}
-
-.green,
-.notifysuccess {
-    color: #006600;
-}
-
-.reportlink {
-    text-align: right;
-}
-
-a.autolink.glossary:hover {
-    cursor: help;
-}
-/* Block which is hidden if javascript enabled, prevents flickering, visible when JS from footer used! */
-.collapsibleregioncaption {
-    white-space: nowrap;
-}
-
-.pagelayout-mydashboard.jsenabled .collapsibleregioncaption {
-    cursor: pointer;
-}
-
-.collapsibleregioncaption img {
-    vertical-align: middle;
-}
-
-.jsenabled .hiddenifjs {
-    display: none;
-}
-
-.visibleifjs {
-    display: none;
-}
-
-.jsenabled .visibleifjs {
-    display: inline;
-}
-
-.jsenabled .collapsibleregion {
-    overflow: hidden;
-}
-
-.jsenabled .collapsed .collapsibleregioninner {
-    visibility: hidden;
-}
-
-.yui-overlay .yui-widget-bd {
-    background-color: #FFEE69;
-    border: 1px solid #A6982B;
-    border-top-color: #D4C237;
-    color: #000000;
-    left: 0;
-    padding: 2px 5px;
-    position: relative;
-    top: 0;
-    z-index: 1;
-}
-
-.clearer {
-    background: transparent;
-    border-width: 0;
-    clear: both;
-    display: block;
-    height: 1px;
-    margin: 0;
-    padding: 0;
-}
-
-.clearfix:after {
-    clear: both;
-    content: ".";
-    display: block;
-    height: 0;
-    min-width: 0;
-    visibility: hidden;
-}
-
-.bold,
-.warning,
-.errorbox .title,
-.pagingbar .title,
-.pagingbar .thispage,
-#site-news-forum h2,
-#frontpage-course-list h2,
-#frontpage-category-names h2,
-#frontpage-category-combo h2 {
-    font-weight: bold;
-}
-
-img.resize {
-    height: 1em;
-    width: 1em;
-}
-
-.block img.resize,
-.breadcrumb img.resize {
-    height: 0.9em;
-    width: 0.8em;
-}
-
-/* Icon styles */
-img.icon {
-    height: 16px;
-    vertical-align: text-bottom;
-    width: 16px;
-    padding-right: 6px;
-}
-
-.dir-rtl img.icon {
-    padding-left: 6px;
-    padding-right: 0;
-}
-
-img.iconsmall {
-    height: 12px;
-    margin-right: 3px;
-    margin-left: 3px;
-    vertical-align: middle;
-    width: 12px;
-}
-
-img.iconhelp,
-.helplink img {
-    height: 16px;
-    padding-left: 3px;
-    vertical-align: text-bottom;
-    width: 16px;
-}
-
-.dir-rtl img.iconhelp,
-.dir-rtl .helplink img {
-    padding-right: 3px;
-    padding-left: 0;
-}
-
-img.iconlarge {
-    height: 24px;
-    width: 24px;
-    vertical-align: middle;
-}
-
-img.iconsort {
-    vertical-align: text-bottom;
-    padding-left: .3em;
-    margin-bottom: .15em;
-}
-
-.dir-rtl img.iconsort {
-    padding-right: .3em;
-    padding-left: 0;
-}
-
-img.icontoggle {
-    height: 17px;
-    vertical-align: middle;
-    width: 50px;
-}
-
-img.iconkbhelp {
-    height: 17px;
-    width: 49px;
-}
-
-img.icon-pre,
-.dir-rtl img.icon-post {
-    padding-right: 3px;
-    padding-left: 0;
-}
-
-img.icon-post,
-.dir-rtl img.icon-pre {
-    padding-left: 3px;
-    padding-right: 0;
-}
-
-.generalbox {
-    border: 1px solid;
-}
-
-.boxaligncenter {
-    margin-left: auto;
-    margin-right: auto;
-}
-
-.boxalignright {
-    margin-left: auto;
-    margin-right: 0;
-}
-
-.boxalignleft {
-    margin-left: 0;
-    margin-right: auto;
-}
-
-.boxwidthnarrow {
-    width: 30%;
-}
-
-.boxwidthnormal {
-    width: 50%;
-}
-
-.boxwidthwide {
-    width: 80%;
-}
-
-.buttons .singlebutton,
-.buttons .singlebutton form,
-.buttons .singlebutton div {
-    display: inline;
-}
-
-.buttons .singlebutton input {
-    margin: 20px 5px;
-}
-
-.headermain {
-    font-weight: bold;
-}
-
-#maincontent {
-    display: block;
-    height: 1px;
-    overflow: hidden;
-}
-
-img.uihint {
-    cursor: help;
-}
-
-#addmembersform table {
-    margin-left: auto;
-    margin-right: auto;
-}
-
-.formtable tbody th,
-.generaltable th.header {
-    vertical-align: top;
-}
-
-.cell {
-    vertical-align: top;
-}
-
-img.emoticon {
-    vertical-align: middle;
-    width: 15px;
-    height: 15px;
-}
-
-form.popupform,
-form.popupform div {
-    display: inline;
-}
-
-.arrow_button input {
-    overflow: hidden;
-}
-
-.action-icon img.smallicon {
-    vertical-align: text-bottom;
-    margin-left: .45em;
-}
-
-.dir-rtl .action-icon img.smallicon {
-    margin-right: .45em;
-    margin-left: 0;
-}
-
-h1 img.icon,
-h1 img.iconhelp,
-h2 img.icon,
-h2 img.iconhelp,
-h3 img.icon,
-h3 img.iconhelp,
-h4 img.icon,
-h4 img.iconhelp,
-h5 img.icon,
-h5 img.iconhelp,
-h6 img.icon,
-h6 img.iconhelp {
-    vertical-align: middle;
-    padding: 4px;
-}
-
-/** Table caption support */
-table caption {
-    font-size: 24px;
-    font-weight: bold;
-    line-height: 42px;
-    text-align: left;
-}
-
-.dir-rtl table caption {
-    text-align: right;
-}
-
-/** The 1-pixel padding is there to avoid phantom scroll bars on OS X (FF, Safari and Chrome)**/
-.no-overflow {
-    overflow: auto;
-    padding-bottom: 1px;
-}
-
-.pagelayout-report .no-overflow {
-    overflow: visible;
-}
-
-.no-overflow > .generaltable {
-    margin-bottom: 0;
-}
-
-.ie6 .no-overflow {
-    width: 100%;
-}
-
-/** IE6 float + background bug solution **/
-.ie6 li.section {
-    line-height: 1.2em;
-    width: 100%;
-}
-
-/**
- * Accessibility features
- */
-/*Accessibility: text 'seen' by screen readers but not visual users. */
-.accesshide {
-    position: absolute;
-    left: -10000px;
-    font-weight: normal;
-    font-size: 1em;
-}
-
-.dir-rtl .accesshide {
-    top: -30000px;
-    left: auto;
-}
-
-span.hide,
-div.hide {
-    display: none;
-}
-
-.invisiblefieldset {
-    display: inline;
-    border-width: 0;
-    padding: 0;
-}
-/*Accessibility: Skip block link, for keyboard-only users. */
-a.skip-block,
-a.skip {
-    position: absolute;
-    top: -1000em;
-    font-size: 0.85em;
-    text-decoration: none;
-}
-
-a.skip-block:focus,
-a.skip-block:active,
-a.skip:focus,
-a.skip:active {
-    position: static;
-    display: block;
-}
-
-.skip-block-to {
-    display: block;
-    height: 1px;
-    overflow: hidden;
-}
-/* Accessibility: only certain fonts support Unicode chars like &#x25BA; in IE6 */
-.arrow,
-.arrow_button input {
-    font-family: Arial,Helvetica,Courier,sans-serif;
-}
-
-/**
- * Header
- */
-.headermain {
-    float: left;
-    margin: 15px;
-    font-size: 2.3em;
-}
-
-.headermenu {
-    float: right;
-    margin: 10px;
-    font-size: 0.8em;
-    text-align: right;
-}
-
-#course-header {
-    clear: both;
-}
-
-/**
- * User menu
- */
-.usermenu .moodle-actionmenu .toggle-display {
-    display: block;
-    opacity: 1;
-    height: 40px;
-    line-height: 40px;
-    padding: 6px;
-    color: inherit;
-}
-
-.usermenu .moodle-actionmenu .toggle-display .userbutton {
-    height: 40px;
-    line-height: 40px;
-}
-
-.usermenu .moodle-actionmenu .toggle-display .userbutton .avatars {
-    display: inline-block;
-    height: 36px;
-    width: 36px;
-    vertical-align: middle;
-    margin-right: 6px;
-    margin-left: 6px;
-}
-
-.usermenu .moodle-actionmenu .toggle-display .userbutton .avatars .avatar,
-.usermenu .moodle-actionmenu .toggle-display .userbutton .avatars img {
-    display: block;
-}
-
-.usermenu .moodle-actionmenu .toggle-display .userbutton .usertext {
-    display: inline-block;
-    vertical-align: middle;
-    font-size: 14px;
-    line-height: 1em;
-    color: #777;
-}
-
-.usermenu .moodle-actionmenu:hover .toggle-display .userbutton .usertext {
-    color: #000;
-}
-
-.usermenu .moodle-actionmenu .toggle-display .userbutton .usertext .meta,
-.usermenu .moodle-actionmenu .toggle-display .userbutton .usertext .role {
-    display: block;
-    font-size: 12px;
-}
-
-.usermenu .moodle-actionmenu .toggle-display .userbutton .usertext .meta .value,
-.usermenu .moodle-actionmenu .toggle-display .userbutton .usertext .role .value {
-    font-weight: bold;
-}
-
-.usermenu .moodle-actionmenu .toggle-display .userbutton .usertext .role {
-    font-weight: bold;
-}
-/* Hide caret when JS is disabled. */
-.usermenu .moodle-actionmenu .toggle-display .caret {
-    display: none;
-}
-/* A little bit of visual feedback for the action menu when Javascript is disabled. */
-.usermenu .moodle-actionmenu .menu .menu-action.icon img {
-    border-radius: 0;
-    background: transparent;
-    box-shadow: none;
-}
-
-.usermenu .moodle-actionmenu .menu .menu-action.icon:hover img {
-    background: #fff;
-    border-radius: 2px;
-    box-shadow: 0px 0px 16px rgba(0, 0, 0, 0.25);
-}
-
-.usermenu .moodle-actionmenu[data-enhanced] .menu .menu-action.icon img,
-.usermenu .moodle-actionmenu[data-enhanced] .menu .menu-action.icon:hover img {
-    border-radius: 0;
-    background: transparent;
-    box-shadow: none;
-}
-
-.userloggedinas .usermenu .userbutton .avatars .avatar {
-    overflow: hidden;
-}
-
-.userloggedinas .usermenu .userbutton .avatars .avatar img {
-    width: inherit;
-    height: inherit;
-}
-
-.userloggedinas .usermenu .userbutton .avatars .avatar.current {
-    position: relative;
-    top: 4px;
-    left: 4px;
-    width: 20px;
-    height: 20px;
-    margin-top: 11px;
-    margin-bottom: -34px;
-    border: 1px solid #fff;
-    border-radius: 50%;
-    box-shadow: -2px -2px 16px rgba(0, 0, 0, 0.25);
-}
-
-.jsenabled .usermenu .moodle-actionmenu .toggle-display {
-    display: block;
-}
-
-.jsenabled .usermenu .moodle-actionmenu .toggle-display .caret {
-    display: inline-block;
-    position: relative;
-    top: 9px;
-}
-
-.jsenabled .usermenu .moodle-actionmenu > .menubar {
-    display: block;
-    margin: 0px;
-}
-
-.jsenabled .usermenu .moodle-actionmenu > .menu {
-    min-width: 160px;
-    font-size: 14px;
-}
-
-.jsenabled .usermenu .moodle-actionmenu > .menu .filler {
-    display: block;
-    height: 1px;
-    margin: 9px 1px;
-    overflow: hidden;
-    background-color: #e5e5e5;
-    border-bottom: 1px solid #fff;
-}
-
-.jsenabled .usermenu .moodle-actionmenu.show .menu {
-    padding: 5px 0;
-    margin: 2px 0 0;
-    background-clip: padding-box;
-}
-
-.jsenabled .usermenu .moodle-actionmenu.show .menu:before {
-    content: '';
-    display: inline-block;
-    border-left: 7px solid transparent;
-    border-right: 7px solid transparent;
-    border-bottom: 7px solid #ccc;
-    border-bottom-color: rgba(0, 0, 0, .2);
-    position: absolute;
-    top: -7px;
-}
-
-.jsenabled .usermenu .moodle-actionmenu.show .menu:after {
-    content: '';
-    display: inline-block;
-    border-left: 6px solid transparent;
-    border-right: 6px solid transparent;
-    border-bottom: 6px solid #fff;
-    position: absolute;
-    top: -6px;
-}
-
-.jsenabled .usermenu .moodle-actionmenu.show .menu li a {
-    white-space: nowrap;
-    border-radius: 0;
-}
-
-.jsenabled .usermenu .moodle-actionmenu.show .menu a:focus,
-.jsenabled .usermenu .moodle-actionmenu.show .menu a:hover {
-    text-decoration: none;
-}
-
-.dir-ltr .usermenu {
-    float: right;
-}
-
-.dir-ltr .usermenu > .moodle-actionmenu > .menu:before {
-    right: 9px;
-}
-
-.dir-ltr .usermenu > .moodle-actionmenu > .menu:after {
-    right: 10px;
-}
-
-.dir-ltr .usermenu > .moodle-actionmenu > .menubar li a {
-    text-align: right;
-}
-
-.dir-ltr.userloggedinas .usermenu .userbutton .avatars .avatar.current {
-    left: 16px;
-}
-
-.dir-rtl .usermenu {
-    float: left;
-}
-
-.dir-rtl .usermenu > .moodle-actionmenu > .menu {
-    margin-right: 0px;
-}
-
-.dir-rtl .usermenu > .moodle-actionmenu > .menu:before {
-    left: 9px;
-}
-
-.dir-rtl .usermenu > .moodle-actionmenu > .menu:after {
-    left: 10px;
-}
-
-.dir-rtl .usermenu > .moodle-actionmenu > .menubar li a {
-    text-align: left;
-}
-
-.dir-rtl.userloggedinas .usermenu .userbutton .avatars .avatar.current {
-    left: -14px;
-}
-
-/**
- * Navbar
- */
-.navbar {
-    clear: both;
-    overflow: hidden;
-}
-
-.ie6 .navbar {
-    overflow: hidden;
-    height: 100%;
-}
-
-.breadcrumb {
-    float: left;
-}
-
-.navbutton {
-    text-align: right;
-}
-
-.breadcrumb ul {
-    padding: 0;
-    margin: 0;
-    text-indent: 0;
-    list-style: none;
-}
-
-.navbutton {
-    float: right;
-}
-
-.navbutton .singlebutton {
-    margin-left: 4px;
-}
-
-.breadcrumb li,
-.navbutton div,
-.navbutton form {
-    display: inline;
-}
-
-/**
- * Footer
- */
-#page-footer {
-    text-align: center;
-    font-size: 0.9em;
-}
-
-#page-footer .homelink {
-    margin: 1em 0;
-}
-
-#page-footer .homelink a {
-    padding-left: 1em;
-    padding-right: 1em;
-}
-
-#page-footer .logininfo,
-#page-footer .sitelink,
-#page-footer .helplink {
-    margin: 0px 10px;
-}
-
-#page-footer .performanceinfo {
-    text-align: center;
-    margin: 10px 20%;
-}
-
-#page-footer .performanceinfo span {
-    display: block;
-}
-
-#page-footer .validators {
-    margin-top: 40px;
-    padding-top: 5px;
-    border-top: 1px dotted gray;
-}
-
-#page-footer .validators ul {
-    margin: 0px;
-    padding: 0px;
-    list-style-type: none;
-}
-
-#page-footer .validators ul li {
-    display: inline;
-    margin-right: 10px;
-    margin-left: 10px;
-}
-
-#page-footer .performanceinfo .cachesused {
-    margin-top: 1em;
-}
-
-#page-footer .performanceinfo .cachesused .cache-stats-heading {
-    font-weight: bold;
-    display: block;
-}
-
-#page-footer .performanceinfo .cachesused .cache-definition-stats {
-    margin: 0.3em;
-    padding: 0px;
-    border: 1px solid #999;
-    display: inline-block;
-    vertical-align: top;
-    min-height: 4em;
-    color: #000;
-    background-color: #eee;
-}
-
-#page-footer .performanceinfo .cachesused .cache-definition-stats span {
-    padding-left: 0.5em;
-    padding-right: 0.5em;
-    display: block;
-}
-
-#page-footer .performanceinfo .cachesused .cache-definition-stats .cache-definition-stats-heading {
-    background-color: #eee;
-}
-
-#page-footer .performanceinfo .cachesused .cache-store-stats {
-    text-indent: 1em;
-}
-
-#page-footer .performanceinfo .cachesused .cache-store-stats.nohits {
-    background-color: #ffd3d9;
-}
-
-#page-footer .performanceinfo .cachesused .cache-store-stats.lowhits {
-    background-color: #f3f2aa;
-}
-
-#page-footer .performanceinfo .cachesused .cache-store-stats.hihits {
-    background-color: #e7f1c3;
-}
-
-#page-footer .performanceinfo .cachesused .cache-total-stats {
-    display: block;
-    font-weight: bold;
-    margin-top: 0.3em;
-}
-
-#course-footer {
-    clear: both;
-}
-
-/**
- * Tabs
- */
-.tabtree {
-    position: relative;
-    margin-bottom: 3.5em;
-}
-
-.tabtree li {
-    display: inline;
-}
-
-.tabtree ul {
-    margin: 5px;
-}
-
-.tabtree ul li.here ul {
-    position: absolute;
-    top: 100%;
-    width: 100%;
-}
-
-.tabtree ul li.here .empty {
-    display: none;
-}
-
-/**
- * Mforms
- */
-.mform fieldset {
-    border: 1px solid;
-}
-
-.mform fieldset fieldset {
-    border-width: 0;
-}
-
-.mform fieldset legend {
-    font-weight: bold;
-    margin-left: 0.5em;
-    padding: 0 0.35em;
-}
-
-.mform fieldset div {
-    margin: 10px;
-    margin-top: 0;
-}
-
-.mform fieldset div div {
-    margin: 0;
-}
-
-.mform fieldset .advancedbutton {
-    text-align: right;
-}
-
-.mform fieldset.hidden {
-    border-width: 0;
-}
-
-.mform fieldset.group {
-    margin-bottom: 0;
-}
-
-.mform fieldset.error {
-    border: 1px solid #A00;
-}
-
-.collapsible-actions {
-    display: none;
-}
-
-.jsenabled .collapsible-actions {
-    text-align: right;
-    display: block;
-}
-
-.dir-rtl .collapsible-actions {
-    text-align: left;
-}
-
-.collapseexpand {
-    background: url([[pix:t/collapsed]]) left center no-repeat;
-    padding-left: 18px;
-}
-
-.dir-rtl .collapseexpand {
-    background-image: url([[pix:t/collapsed_rtl]]);
-    background-position: right center;
-    padding-left: 0;
-    padding-right: 18px;
-}
-
-.collapse-all,
-.dir-rtl .collapse-all {
-    background-image: url([[pix:t/expanded]]);
-}
-
-.mform fieldset legend {
-    padding: 0 0.35em;
-}
-
-.mform fieldset.collapsible legend a.fheader {
-    padding-left: 18px;
-    background: url([[pix:t/expanded]]) left center no-repeat;
-}
-
-.mform fieldset.collapsed legend a.fheader {
-    background-image: url([[pix:t/collapsed]]);
-}
-
-.jsenabled .mform fieldset.collapsed {
-    border-width: 1px 0 0 1px;
-    padding: 0;
-    border-color: transparent;
-}
-
-.jsenabled .mform fieldset.collapsed div.fcontainer {
-    display: none;
-}
-
-.mform .fitem {
-    width: 100%;
-    overflow: hidden;
-    margin-top: 5px;
-    margin-bottom: 1px;
-    clear: right;
-}
-
-.jsenabled .mform .containsadvancedelements .advanced {
-    display: none;
-}
-
-.mform .containsadvancedelements .advanced.show {
-    display: block;
-}
-
-.mform .fitem .fitemtitle {
-    width: 15%;
-    text-align: right;
-    float: left;
-}
-
-.dir-rtl .mform .fitem .fitemtitle {
-    text-align: left;
-}
-
-.mform .fitem .fitemtitle div {
-    display: inline;
-}
-
-.mform .fitem .felement {
-    border-width: 0;
-    width: 80%;
-    margin-left: 16%;
-}
-
-.mform .fitem fieldset.felement {
-    margin-left: 15%;
-    padding-left: 1%;
-    margin-bottom: 0;
-}
-
-#adminsettings span.error,
-.mform .error,
-.mform .required {
-    color: #A00;
-}
-
-#adminsettings span.error,
-.mform span.error {
-    display: inline-block;
-    padding: 4px;
-    margin-bottom: 4px;
-    background-color: #F2DEDE;
-    border: 1px solid #EED3D7;
-}
-
-.mform .required .fgroup span label {
-    color: #000;
-}
-
-.mform .fdescription.required {
-    color: #A00;
-    text-align: right;
-}
-
-.dir-rtl .mform .fdescription.required {
-    text-align: left;
-}
-
-.mform .fpassword .unmask {
-    display: inline;
-    margin-left: 0.5em;
-}
-
-.mform .ftextarea #id_alltext {
-    width: 100%;
-}
-
-.mform .fstaticlabel {
-    font-weight: bold;
-}
-
-.mform ul.file-list {
-    padding: 0;
-    margin: 0;
-    list-style: none;
-}
-
-.mform label {
-    display: inline-block;
-}
-
-.mform .iconhelp {
-    margin-left: 4px;
-}
-
-.dir-rtl .mform .iconhelp {
-    margin-right: 4px;
-}
-
-.mform label .req,
-.mform label .adv {
-    cursor: help;
-}
-
-.mform .fcheckbox input {
-    margin-left: 0;
-}
-
-.mform .fcheckbox label,
-.mform .fduration label,
-.mform .fitem fieldset.fgroup label,
-.mform .fradio label,
-.mform fieldset.fdate_selector label,
-.mform fieldset.fdate_time_selector label {
-    display: inline;
-    float: none;
-    margin-left: .3em;
-    vertical-align: text-bottom;
-}
-
-.dir-rtl .mform .fcheckbox label,
-.dir-rtl .mform .fduration label,
-.dir-rtl .mform .fitem fieldset.fgroup label,
-.dir-rtl .mform .fradio label,
-.dir-rtl .mform fieldset.fdate_selector label,
-.dir-rtl .mform fieldset.fdate_time_selector label {
-    margin-right: .3em;
-    margin-left: 0;
-}
-
-.mform .ftags label.accesshide {
-    display: block;
-    position: static;
-}
-
-.mform .ftags select {
-    margin-bottom: 0.7em;
-    min-width: 22em;
-}
-
-.mform .moreless-toggler {
-    background: url([[pix:t/more]]) left center no-repeat;
-    padding-left: 16px;
-}
-
-.dir-rtl .moreless-toggler {
-    padding-left: 0;
-    padding-right: 16px;
-    background-position: right center;
-}
-
-.mform .moreless-less {
-    background-image: url([[pix:t/less]]);
-}
-
-.mform .helplink img {
-    margin: 0 0 0 .45em;
-    padding: 0;
-}
-
-.dir-rtl .mform .helplink img {
-    margin: 0 .45em 0 0;
-    padding: 0;
-}
-
-.mform legend .helplink img {
-    margin-right: .2em;
-}
-
-.dir-rtl .mform legend .helplink img {
-    margin: 0 .45em 0 .2em;
-}
-
-.urlselect label,
-.singleselect label {
-    margin-right: .3em;
-}
-
-.dir-rtl .urlselect label,
-.dir-rtl .singleselect label {
-    margin-left: .3em;
-    margin-right: 0;
-}
-
-.dir-rtl .mform fieldset legend {
-    margin-right: 0.5em;
-    margin-left: 0;
-}
-
-.dir-rtl .mform fieldset.collapsible legend a.fheader {
-    background-position: right center;
-    padding-right: 18px;
-    padding-left: 0;
-}
-
-.dir-rtl .mform fieldset.collapsed legend a.fheader {
-    background-image: url([[pix:t/collapsed_rtl]]);
-}
-
-.dir-rtl.jsenabled .mform fieldset.collapsed {
-    border-width: 1px 1px 0 0;
-}
-
-.dir-rtl .mform .fitem fieldset.felement {
-    padding-right: 1%;
-    margin-right: 15%;
-}
-
-.mform .btn-cancel,
-.mform .btn-cancel:active,
-.mform .btn-cancel[disabled] {
-    background-color: transparent;
-    background-image: none;
-    box-shadow: none;
-    -moz-box-shadow: none;
-    -webkit-box-shadow: none;
-    -o-box-shadow: none;
-    -ms-box-shadow: none;
-    margin-left: .5em;
-}
-
-.mform .btn-cancel {
-    border-color: transparent;
-    border-radius: 0 0 0 0;
-    -moz-border-radius: 0 0 0 0;
-    -webkit-border-radius: 0 0 0 0;
-    -o-border-radius: 0 0 0 0;
-    -ms-border-radius: 0 0 0 0;
-    color: #0088CC;
-    cursor: pointer;
-}
-
-.mform .btn-cancel:hover,
-.mform .btn-cancel:focus {
-    background-color: transparent;
-    color: #005580;
-    text-decoration: underline;
-}
-
-.mform .btn-cancel[disabled]:hover,
-.mform .btn-cancel[disabled]:focus {
-    color: #333333;
-    text-decoration: none;
-}
-
-input#id_externalurl {
-    direction: ltr;
-}
-
-#portfolio-add-button {
-    display: inline;
-}
-
-/**
- * Show the labels above text editors and file managers except on wide screens.
- */
-#region-main .mform:not(.unresponsive) .fitem .fitemtitle label {
-    font-weight: bold;
-}
-
-@media (max-width: 1199px) {
-    #region-main .mform:not(.unresponsive) .fitem .fitemtitle {
-        display: block;
-        margin-top: 4px;
-        margin-bottom: 4px;
-        text-align: left;
-        width: 100%;
-    }
-
-    #region-main .mform:not(.unresponsive) .femptylabel .fitemtitle {
-        display: inline-block;
-        width: auto;
-        margin-right: 8px;
-&nb