postgresql support
authorarno <arno@renevier.net>
Fri, 16 Apr 2010 15:42:01 +0000 (17:42 +0200)
committerarno <arno@renevier.net>
Fri, 16 Apr 2010 22:45:55 +0000 (00:45 +0200)
13 files changed:
README.txt
api.php
inc/db/postgresql.php [new file with mode: 0644]
inc/html/admin.php
inc/html/index.php
inc/html/install.php
inc/html/upgrade.php
inc/i10n/de/syp.php
inc/i10n/en/syp.php
inc/i10n/fr/syp.php
inc/settings.php.in
items.php
news.php

index 838116204485a4a268028e698bd736a2995e9d21..bf24c24f5c89e5a291ed4862feb5d6eb69932992 100644 (file)
@@ -6,11 +6,10 @@ image and its description.
 Requirements
 ------------
 - php5
-- mysql extension for php
-- mysql must support spatial extension; mysql version must be >= 4.1 for MyISAM
-  tables or >= 5.0.16 for other tables. I assumed it would not be a problem.
-  If that's a problem for you, send me a mail, and I'll do without spatial
-  support.
+- mysql (or postgresql) extension for php
+- If mysql is used, it must support spatial extension; mysql version must be >=
+  4.1 for MyISAM tables or >= 5.0.16 for other tables.
+- If postgresql is used, version must be at least 7.4
 
 Installation
 ------------
diff --git a/api.php b/api.php
index e74f3b46ff1e0d873f486053ae8f47f0aa157bbb..2dbfac4857a88e258513b114b3dcdb262ad770a3 100644 (file)
--- a/api.php
+++ b/api.php
@@ -385,7 +385,7 @@ function main ($con) {
 if (!@include_once ("./inc/settings.php")) {
     error_server ();
 }
-require_once ("./inc/db/mysql.php");
+require_once ("./inc/db/" . (defined ("DBTYPE")? DBTYPE: "mysql") . ".php");
 require_once ("./inc/utils.php");
 
 try {
diff --git a/inc/db/postgresql.php b/inc/db/postgresql.php
new file mode 100644 (file)
index 0000000..eb8d3bf
--- /dev/null
@@ -0,0 +1,247 @@
+<?php
+/* Copyright (c) 2010 Arnaud Renevier, Inc, published under the modified BSD
+   license. */
+
+require_once ("./inc/db/anydb.php");
+
+class postgresqlConnection implements anydbConnection {
+    var $link = null;
+    var $dbprefix = null;
+
+    public function connect ($host, $user, $pwd, $dbname, $dbprefix) {
+        if (!function_exists ("pg_connect")) {
+            throw new Exception (anydbConnection::err_driver_unavailable);
+        }
+        if ($this->link) { // connection has already been opened
+            return;
+        }
+        $this->link = @pg_connect ("host= " . $host . " user=" . $user . " password=" . $pwd . " dbname=" . $dbname);
+        if (!$this->link) {
+            throw new Exception (anydbConnection::err_connection);
+        }
+        $this->dbprefix = $dbprefix;
+    }
+
+    public function users_table_exists () {
+        return $this->_tblexists ("users");
+    }
+
+    public function create_users_table () {
+        $query = sprintf ("CREATE TABLE " .
+                           "%susers (
+                            name VARCHAR(255) NOT NULL, pwd CHAR(32),
+                            PRIMARY KEY (name));", $this->dbprefix);
+        $this->_execute_query ($query);
+    }
+
+    public function items_table_exists () {
+        return $this->_tblexists ("items");
+    }
+    public function create_items_table () {
+        $query = sprintf ("CREATE TABLE " .
+                            "%sitems (
+                                id SERIAL,
+                                longitude NUMERIC,
+                                latitude NUMERIC,
+                                title VARCHAR(127),
+                                description TEXT,
+                                imgpath VARCHAR(255),
+                                date TIMESTAMP,
+                                owner VARCHAR(255),
+                                PRIMARY KEY (id)
+                            );", $this->dbprefix);
+        $this->_execute_query ($query);
+    }
+
+    public function user_exists ($user_name) {
+        $usrname_escaped = pg_escape_string ($user_name);
+        $query = sprintf ("SELECT COUNT(*) FROM %susers WHERE name LIKE '%s';",
+                        $this->dbprefix, $usrname_escaped);
+        $res = pg_fetch_array ($this->_execute_query ($query));
+        return ($res[0] >= 1);
+    }
+
+    public function setpwd ($user_name, $pwd) {
+        if (strlen ($pwd) == 0) {
+            throw new Exception (anydbConnection::err_query);
+        }
+        $usrname_escaped = pg_escape_string ($user_name);
+        if ($this->user_exists ($user_name)) {
+            $query = sprintf ("UPDATE %susers SET pwd='%s' WHERE name like '%s';", 
+                    $this->dbprefix, md5 ($pwd), $usrname_escaped);
+        } else {
+            $query = sprintf ("INSERT INTO %susers VALUES ('%s', '%s');", 
+                               $this->dbprefix, $usrname_escaped, md5 ($pwd));
+        }
+        $this->_execute_query ($query);
+    }
+
+    public function checkpwdmd5 ($user_name, $pwd_md5) {
+        $query = sprintf ("SELECT COUNT(*) FROM %susers WHERE name LIKE '%s'
+                           AND pwd LIKE '%s';",
+                           $this->dbprefix, 
+                           pg_escape_string ($user_name),
+                           pg_escape_string ($pwd_md5));
+        $res = pg_fetch_array ($this->_execute_query ($query));
+        if ($res[0] >= 1) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public function save_feature ($feature) {
+        try {
+            $id = $feature->id;
+        } catch (Exception $e) {}
+        if (isset ($id)) {
+            $query = sprintf ("UPDATE %sitems SET
+                                    imgpath='%s', 
+                                    title='%s', 
+                                    description='%s', 
+                                    longitude='%s',
+                                    latitude='%s'
+                            WHERE id = '%s';",
+                            $this->dbprefix,
+                            pg_escape_string ($feature->imgpath),
+                            pg_escape_string ($feature->title),
+                            pg_escape_string ($feature->description),
+                            $feature->lon,
+                            $feature->lat,
+                            $id);
+                $this->_execute_query ($query);
+                return $feature;
+        } else {
+              $query = sprintf ("INSERT INTO %sitems
+                              (imgpath, title, description, longitude, latitude, date, owner)
+                                VALUES ('%s', '%s', '%s', %s, %s, NOW(), '%s')", 
+                              $this->dbprefix,
+                              pg_escape_string ($feature->imgpath),
+                              pg_escape_string ($feature->title),
+                              pg_escape_string ($feature->description),
+                              $feature->lon,
+                              $feature->lat,
+                              pg_escape_string ($feature->user)
+                    );
+
+                $this->_execute_query ($query);
+                // mimics mysql_insert_id
+                $res = pg_fetch_array(pg_query($this->link, sprintf( "select currval('%sitems_id_seq')", $this->dbprefix)));
+                $id = $res[0];
+                return new feature ($id, $feature->lon, $feature->lat,
+                                    $feature->imgpath, $feature->title,
+                                    $feature->description, $feature->date,
+                                    $feature->user);
+        }
+    }
+    
+    public function delete_feature ($feature) {
+        $query = sprintf ("DELETE from %sitems WHERE id = '%s'",
+                        $this->dbprefix,
+                        pg_escape_string ($feature->id));
+        $this->_execute_query ($query);
+        return true;
+    }
+
+    public function getfeature ($id) {
+        $query = sprintf ("SELECT id, imgpath, title, description, longitude, latitude,
+                           date_part('epoch', date) AS date, owner
+                           FROM %sitems WHERE id = '%s';", 
+                        $this->dbprefix, pg_escape_string ($id));
+        $row = pg_fetch_assoc ($this->_execute_query ($query));
+        if ($row === false) {
+            return null;
+        }
+        return $this->_feature_frow_row ($row);
+    }
+
+    public function listfeatures ($user) {
+        if ($user && ($user != "admin")) {
+            $from_user_query = sprintf (" WHERE owner = '%s' ",
+                                        pg_escape_string ($user));
+        } else {
+            $from_user_query = "";
+        }
+
+        $query = sprintf ("SELECT id, imgpath, title, description, longitude, latitude,
+                            date_part('epoch', date) AS date, owner
+                            FROM %sitems %s;",
+                          $this->dbprefix, $from_user_query);
+
+        $features = array ();
+        $res = $this->_execute_query ($query);
+        while ($row = pg_fetch_assoc ($res)) {
+            $feature = $this->_feature_frow_row ($row);
+            if (isset ($feature)) {
+                $features[] = $feature;
+            }
+        }
+        return $features;
+    }
+
+    public function mostrecentfeatures ($num_features) {
+        $query = sprintf ("SELECT id, imgpath, title, description, longitude, latitude,
+                           date_part('epoch', date) AS date, owner FROM %sitems ORDER BY date DESC",
+                           $this->dbprefix);
+        if ($num_features) {
+            $query .= sprintf (" LIMIT %d", $num_features);
+        }
+        $features = array ();
+        $res = $this->_execute_query ($query);
+        while ($row = pg_fetch_assoc ($res)) {
+            $feature = $this->_feature_frow_row ($row);
+            if (isset ($feature)) {
+                $features[] = $feature;
+            }
+        }
+        return $features;
+    }
+
+    public function imgpath_exists ($imgpath) {
+        $query = sprintf ("SELECT COUNT(*) FROM %sitems WHERE imgpath LIKE '%s';",
+                           $this->dbprefix, pg_escape_string ($imgpath));
+        $res = pg_fetch_array  ($this->_execute_query ($query));
+        return ($res [0] >= 1);
+    }
+
+    public function getdbname () {
+        return "PostgreSQL";
+    }
+
+    private function _tblexists ($tblname) {
+        $query = sprintf("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='public' and table_name = '%s%s';",
+                            $this->dbprefix, $tblname);
+        $res = pg_fetch_array ($this->_execute_query ($query));
+        return ($res[0] >= 1);
+    }
+
+    private function _feature_frow_row ($row) {
+        // XXX: should I remove invalid features from database ?
+        try {
+            $feature = new feature ($row ["id"], $row["longitude"], $row["latitude"], $row ["imgpath"],
+                                    $row ["title"], $row ["description"],
+                                    $row ["date"], $row ["owner"]);
+        } catch (Exception $e) {
+            return null;
+        }
+        return $feature;
+    }
+
+    private function _execute_query ($query) {
+        if (!function_exists ("pg_query")) {
+            throw new Exception (anydbConnection::err_driver_unavailable);
+        }
+        if (!$this->link) {
+            throw new Exception (anydbConnection::err_query);
+        }
+        $res = pg_query ($this->link, $query);
+        if ($res == false) {
+            throw new Exception (anydbConnection::err_query);
+        }
+        return $res;
+    }
+
+}
+
+$connection = new postgresqlConnection();
+?>
index b0df4b5c6ea866c69d40fbc09ad907ce8facd6d2..ef43708a4b50f03314742deadafb2527c329420a 100644 (file)
@@ -7,7 +7,7 @@ $error = false;
 if (!@include_once ("./inc/settings.php")) {
     $error = true;
 }
-require_once ("./inc/db/mysql.php");
+require_once ("./inc/db/" . (defined ("DBTYPE")? DBTYPE: "mysql") . ".php");
 require_once ("./inc/utils.php");
 
 try {
index 550ee48564cde59b8e2503a3ee14afb9f6557405..f1e3239b8a23accaea7286e1f146aeb86aa96425 100644 (file)
@@ -3,7 +3,7 @@
    license. */
 
 @include_once ("./inc/settings.php");
-require_once ("./inc/db/mysql.php");
+require_once ("./inc/db/" . (defined ("DBTYPE")? DBTYPE: "mysql") . ".php");
 
 try {
     $connection->connect (DBHOST, DBUSER, DBPWD, DBNAME, DBPREFIX);
index 4b2d02cb3673dca4cc1a1a53d096015f807cce6b..7bab8efd67b21eed0fa9c9f52be97d38583ea4b5 100644 (file)
 
     function create_install_form () {
         if (isset ($_POST ["db_form_submit"])) {
+            $type = $_POST ["db_type"];
             $host = $_POST ["db_host"];
             $name = $_POST ["db_name"];
             $user = $_POST ["db_user"];
             $prefix = $_POST ["db_prefix"];
             $title = $_POST ["site_title"];
         } else {
+            $type = "mysql";
             $host = "localhost";
             $user = "syp";
             $name = "syp";
         print '<form method="post" action="' . $_SERVER ["REQUEST_URI"] .  '"><fieldset>' . "\n";
         print '<legend>' . trans ("SYP configuration") . '</legend>' . "\n";
 
+        $drivers = array();
+        $handle = opendir("./inc/db");
+        if (!$handle) {
+            par_error_and_leave (trans ('Could not list <code>inc/db</code> directory'));
+        }
+        while (false !== ($file = readdir($handle))) {
+            if ($file == "." or $file == "..") {
+                continue;
+            }
+            $driver_name = substr($file,0,strrpos($file,'.'));
+            if ($driver_name == "anydb") {
+                continue;
+            }
+            array_push ($drivers, $driver_name);
+        }
+        closedir($handle);
+
+
+        print '<div><label for="db_type" title="' .
+              trans ("You can specify a database backend. Mysql is the most available for standard web hosting services.") .
+              '">' . trans ("database backend:") . '</label>' . "\n" .
+              '<select id="db_type" name="db_type">'. "\n";
+        foreach ($drivers as $driver) {
+            if ($driver == $type) {
+                print '<option name="' . $driver . '" selected="true">' . $driver . '</option>' . "\n";
+            } else {
+                print '<option name="' . $driver . '">' . $driver . '</option>' . "\n";
+            }
+        }
+        print "</select>" . "\n";
+
         print '<div><label for="db_host" title="' .
               trans ("address of the database server (example: localhost, db.myhost.com or 192.168.0.15).") .
               '">' . trans ("database server hostname:") . '</label>' . "\n" .
            }
         }
 
+        define (DBTYPE, _unquote ($_POST ["db_type"]));
         define (DBHOST, _unquote ($_POST ["db_host"]));
         define (DBNAME, _unquote ($_POST ["db_name"]));
         define (DBUSER, _unquote ($_POST ["db_user"]));
         leave ();
     }
 
-    require_once ("./inc/db/mysql.php");
+    if (!include_once ("./inc/db/" . DBTYPE . ".php")) {
+        par_error_and_leave (trans("Unkown backend: ", DBTYPE));
+    }
     require_once ("./inc/utils.php");
 
     try {
         if ($handle) {
             while (!feof ($handle)) {
                 $line = fgets ($handle, 4096);
-                foreach (array ("DBHOST", "DBNAME", "DBUSER", "DBPWD", "DBPREFIX", "SITETITLE") as $value) {
+                foreach (array ("DBTYPE", "DBHOST", "DBNAME", "DBUSER", "DBPWD", "DBPREFIX", "SITETITLE") as $value) {
                     $pattern = "(define\s+\(\s*\"$value\"\s*,\s*\")[^\"]*(\"\s*\)\s*;)";
                     if (preg_match( "/$pattern/", $line, $match )) {
                         $line = $match[1] . addslashes (constant ($value)) . $match[2];
index 580868456ed45dda73ca420316b04b3402329927..38eefe6f4abbaf578aa8caf3f35bf1bbdbd5026f 100644 (file)
@@ -30,7 +30,7 @@
         return true;
     }
 
-    require_once ("./inc/db/mysql.php");
+    require_once ("./inc/db/" . (defined ("DBTYPE")? DBTYPE: "mysql") . ".php");
     require_once ("./inc/install_utils.php");
     require_once ("./inc/utils.php");
 
index 72b264e081994f37b026957a1980a1dc522e7f26..a55c0c701adb04ba0a062acb2e0507f8f3aaeb03 100644 (file)
         "SYP-Konfiguration"
           ,
 
+        "Could not list <code>inc/db</code> directory"
+          =>
+        ""
+          ,
+
+        "You can specify a database backend. Mysql is the most available for standard web hosting services."
+          =>
+        ""
+          ,
+
+        "database backend:"
+          =>
+        ""
+          ,
+
         "address of the database server (example: localhost, db.myhost.com or 192.168.0.15)."
           =>
         "Adresse des Datenbank-Servers (z.B.: localhost, db.myhost.com or 192.168.0.15)."
         "Installation starten"
           ,
 
+        "Unknown backend:"
+          =>
+        ""
+          ,
+
         "not supported"
           =>
         "nicht unterstützt"
           ,
 
     )
-?>
\ No newline at end of file
+?>
index df80f512faa93f57ba22349667f70a717e8dd928..effab76671944d9a446906d27ae031b52ba7cf04 100644 (file)
         "SYP configuration"
           => "",
 
+        "Could not list <code>inc/db</code> directory"
+          => "",
+
+        "You can specify a database backend. Mysql is the most available for standard web hosting services."
+          => "",
+
+        "database backend:"
+          => "",
+
         "address of the database server (example: localhost, db.myhost.com or 192.168.0.15)."
           => "",
 
@@ -80,6 +89,9 @@
         "Start install"
           => "",
 
+        "Unknown backend:"
+          => "",
+
         "not supported"
           => "",
 
index 26b93b15418ac3428f98fb234f963d5c45720e79..96382012a17dcca8716eebdd362aac7cb28da43a 100644 (file)
         "Configuration de SYP"
           ,
 
+        "Could not list <code>inc/db</code> directory"
+          =>
+        "Impossible de lister <code>inc/db</code>"
+          ,
+
+        "You can specify a database backend. Mysql is the most available for standard web hosting services."
+          =>
+        "You pouvez définir un type de base de données. Mysql est disponible chez la plupart des hébergeurs."
+          ,
+
+        "database backend:"
+          =>
+        "type de base de données&nbsp;:"
+          ,
+
         "address of the database server (example: localhost, db.myhost.com or 192.168.0.15)."
           =>
         "adresse du serveur de base de données (exemple: localhost, db.myhost.com ou 192.168.0.15)"
         "Commencer l'installation"
           ,
 
+        "Unknown backend:"
+          =>
+        "Type de base de données inconnu:"
+          ,
+
         "not supported"
           =>
         "support non détecté"
           ,
 
     )
-?>
\ No newline at end of file
+?>
index ed12c5f4d9de94ddae06623ed58d7a2c8fc0cee6..845e6b2502b0715226152ca96c89763f5d4fd28d 100644 (file)
@@ -2,6 +2,9 @@
 /* Copyright (c) 2009 Arnaud Renevier, Inc, published under the modified BSD
    license. */
 
+// database type
+define ("DBTYPE", "mysql");
+
 // database hostname
 define ("DBHOST", "localhost");
 
index e2fe1dbbe272b222d6f12d5df6e03a75ffbd6044..37f089d023bf7b040a07603a9f73c4f80c737f49 100644 (file)
--- a/items.php
+++ b/items.php
@@ -78,7 +78,7 @@ if (!@include_once ("./inc/settings.php")) {
     exit ("server error");
 }
 require_once ("./inc/utils.php");
-require_once ("./inc/db/mysql.php");
+require_once ("./inc/db/" . (defined ("DBTYPE")? DBTYPE: "mysql") . ".php");
 
 try {
     $connection->connect (DBHOST, DBUSER, DBPWD, DBNAME, DBPREFIX);
index cc06521a5b880cf4be43b436605ebfdcb9844200..886b00e5ff2f6cbb2dea20191cf1b7f56bf90b8e 100644 (file)
--- a/news.php
+++ b/news.php
@@ -123,7 +123,7 @@ function main ($features) {
 if (!@include_once ("./inc/settings.php")) {
     exit ("server error");
 }
-require_once ("./inc/db/mysql.php");
+require_once ("./inc/db/" . (defined ("DBTYPE")? DBTYPE: "mysql") . ".php");
 require_once ("./inc/utils.php");
 
 try {