diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..820339f
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "maxmind-db"]
+ path = maxmind-db
+ url = git://github.com/maxmind/MaxMind-DB.git
diff --git a/composer.json b/composer.json
index 3138935..2964e1e 100644
--- a/composer.json
+++ b/composer.json
@@ -14,6 +14,7 @@
],
"require": {
"guzzle/guzzle": "3.*",
+ "maxmind-db/reader": "0.*",
"php": ">=5.3.1"
},
"require-dev": {
diff --git a/maxmind-db b/maxmind-db
new file mode 160000
index 0000000..96559f7
--- /dev/null
+++ b/maxmind-db
@@ -0,0 +1 @@
+Subproject commit 96559f78dabf7733cf4e066bc15f694d1592c16e
diff --git a/src/GeoIp2/Database/Reader.php b/src/GeoIp2/Database/Reader.php
new file mode 100644
index 0000000..8165060
--- /dev/null
+++ b/src/GeoIp2/Database/Reader.php
@@ -0,0 +1,140 @@
+country
+ * and city
methods. We also provide cityIspOrg
+ * and omni
methods to ease compatibility with the web service
+ * client, although we may offer the ability to specify additional databases
+ * to replicate these web services in the future (e.g., the ISP/Org database).
+ *
+ * **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
+{
+ private $dbReader;
+ private $languages;
+
+ /**
+ * Constructor.
+ *
+ * @param string $filename The path to the GeoIP2 database file.
+ * @throws \MaxMind\Db\Reader\InvalidDatabaseException if the database
+ * is corrupt or invalid
+ */
+ public function __construct(
+ $filename,
+ $languages = array('en')
+ ) {
+ $this->dbReader = new MaxMind\Db\Reader($filename);
+ $this->languages = $languages;
+ }
+
+ /**
+ * 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->responseFor('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->responseFor('Country', $ipAddress);
+ }
+
+ /**
+ * This method returns a GeoIP2 City/ISP/Org model.
+ *
+ * @param string $ipAddress IPv4 or IPv6 address as a string.
+ *
+ * @return \GeoIp2\Model\CityIspOrg
+ *
+ * @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 cityIspOrg($ipAddress)
+ {
+ return $this->responseFor('CityIspOrg', $ipAddress);
+ }
+
+ /**
+ * This method returns a GeoIP2 Omni model.
+ *
+ * @param string $ipAddress IPv4 or IPv6 address as a string.
+ *
+ * @return \GeoIp2\Model\Omni
+ *
+ * @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 omni($ipAddress)
+ {
+ return $this->responseFor('Omni', $ipAddress);
+ }
+
+ private function responseFor($class, $ipAddress)
+ {
+ $record = $this->dbReader->get($ipAddress);
+ if ($record === null) {
+ throw new AddressNotFoundException(
+ "$ipAddress was not found in the database."
+ );
+ }
+ $class = "GeoIp2\\Model\\" . $class;
+
+ return new $class($record, $this->languages);
+ }
+}
diff --git a/src/GeoIp2/Exception/AddressNotFoundException.php b/src/GeoIp2/Exception/AddressNotFoundException.php
new file mode 100644
index 0000000..bbdc559
--- /dev/null
+++ b/src/GeoIp2/Exception/AddressNotFoundException.php
@@ -0,0 +1,10 @@
+