Index: /pykota/trunk/conf/pykotadmin.conf.sample
===================================================================
--- /pykota/trunk/conf/pykotadmin.conf.sample (revision 2576)
+++ /pykota/trunk/conf/pykotadmin.conf.sample (revision 2593)
@@ -58,4 +58,6 @@
 [global]
 
+# For SQLite3, you can comment out all the lines in this file.
+
 # PostgreSQL's Quota Storage administrator's name and password
 # Please comment these lines out and see further below if you use LDAP.
Index: /pykota/trunk/conf/pykota.conf.sample
===================================================================
--- /pykota/trunk/conf/pykota.conf.sample (revision 2583)
+++ /pykota/trunk/conf/pykota.conf.sample (revision 2593)
@@ -48,8 +48,19 @@
 [global]
 # Storage backend for quotas
-# only PGStorage (PostgreSQL) and LDAPStorage (OpenLDAP) are supported.
+# only PGStorage (PostgreSQL), LDAPStorage (OpenLDAP or else),
+# and SQLiteStorage (SQLite 3) are supported.
+#
 # MySQL and BerkeleyDB are planned.
 
-# the 'postgresql' value is deprecated, use 'pgstorage' instead.
+####################################################################
+# SQLite3 : comment this section out if you use another backend    #
+####################################################################
+
+#storagebackend : sqlitestorage
+#storagename: /etc/pykota/pykota.db
+
+####################################################################
+# PostgreSQL : comment this section out if you use another backend #
+####################################################################
 storagebackend: pgstorage
 
@@ -74,27 +85,7 @@
 # storageuserpw: Comment out if unused, or set to Quota Storage user password
 
-# Should the database caching mechanism be enabled or not ?
-# If unset, caching is disabled. Possible values Y/N/YES/NO
-# caching mechanism works with both PostgreSQL and OpenLDAP backends
-# but may be really interesting only with OpenLDAP.
-#
-# ACTIVATING CACHE MAY CAUSE PRECISION PROBLEMS IN PRINT ACCOUNTING
-# IF AN USER PRINTS ON SEVERAL PRINTERS AT THE SAME TIME.
-# YOU MAY FIND IT INTERESTING ANYWAY, ESPECIALLY FOR LDAP.
-#
-# FYI, I ALWAYS SET IT TO YES !
-#
-storagecaching: No
-
-# Should full job history be disabled ?
-# If unset or set to No, full job history is kept in the database.
-# This will be useful in the future when the report generator
-# will be written.
-# Disabling the job history can be useful with heavily loaded
-# LDAP servers, to not make the LDAP tree grow out of control.
-# Disabling the job history with the PostgreSQL backend works too
-# but it's probably less useful than with LDAP.
-disablehistory: No
-
+####################################################################
+# LDAP : comment this section out if you use another backend       #
+####################################################################
 # LDAP example, uncomment and adapt it to your own configuration :
 #storagebackend: ldapstorage
@@ -183,4 +174,32 @@
 # BETTER TO LET IT SET TO 'NO'
 # ldapcache: no
+
+#############################################################
+# ALL directives below are common to ALL storage backends   #
+#############################################################
+
+# Should the database caching mechanism be enabled or not ?
+# If unset, caching is disabled. Possible values Y/N/YES/NO
+# caching mechanism works with both PostgreSQL and OpenLDAP backends
+# but may be really interesting only with OpenLDAP.
+#
+# ACTIVATING CACHE MAY CAUSE PRECISION PROBLEMS IN PRINT ACCOUNTING
+# IF AN USER PRINTS ON SEVERAL PRINTERS AT THE SAME TIME.
+# YOU MAY FIND IT INTERESTING ANYWAY, ESPECIALLY FOR LDAP.
+#
+# FYI, I ALWAYS SET IT TO YES !
+#
+storagecaching: No
+
+# Should full job history be disabled ?
+# If unset or set to No, full job history is kept in the database.
+# This will be useful in the future when the report generator
+# will be written.
+# Disabling the job history can be useful with heavily loaded
+# LDAP servers, to not make the LDAP tree grow out of control.
+# Disabling the job history with the PostgreSQL backend works too
+# but it's probably less useful than with LDAP.
+disablehistory: No
+
 
 # Where to log ?
Index: /pykota/trunk/pykota/storages/pgstorage.py
===================================================================
--- /pykota/trunk/pykota/storages/pgstorage.py (revision 2418)
+++ /pykota/trunk/pykota/storages/pgstorage.py (revision 2593)
@@ -118,2 +118,18 @@
             typ = "text"
         return pg._quote(field, typ)
+        
+    def prepareRawResult(self, result) :
+        """Prepares a raw result by including the headers."""
+        if result.ntuples() > 0 :
+            entries = [result.listfields()]
+            entries.extend(result.getresult())
+            nbfields = len(entries[0])
+            for i in range(1, len(entries)) :
+                fields = list(entries[i])
+                for j in range(nbfields) :
+                    field = fields[j]
+                    if type(field) == StringType :
+                        fields[j] = self.databaseToUserCharset(field) 
+                entries[i] = tuple(fields)    
+            return entries
+        
Index: /pykota/trunk/pykota/storages/sql.py
===================================================================
--- /pykota/trunk/pykota/storages/sql.py (revision 2464)
+++ /pykota/trunk/pykota/storages/sql.py (revision 2593)
@@ -30,19 +30,4 @@
 
 class SQLStorage :
-    def prepareRawResult(self, result) :
-        """Prepares a raw result by including the headers."""
-        if result.ntuples() > 0 :
-            entries = [result.listfields()]
-            entries.extend(result.getresult())
-            nbfields = len(entries[0])
-            for i in range(1, len(entries)) :
-                fields = list(entries[i])
-                for j in range(nbfields) :
-                    field = fields[j]
-                    if type(field) == StringType :
-                        fields[j] = self.databaseToUserCharset(field) 
-                entries[i] = tuple(fields)    
-            return entries
-        
     def createFilter(self, only) :    
         """Returns the appropriate SQL filter."""
Index: /pykota/trunk/pykota/storages/sqlitestorage.py
===================================================================
--- /pykota/trunk/pykota/storages/sqlitestorage.py (revision 2591)
+++ /pykota/trunk/pykota/storages/sqlitestorage.py (revision 2593)
@@ -123,2 +123,18 @@
         else :     
             return "NULL"
+            
+    def prepareRawResult(self, result) :
+        """Prepares a raw result by including the headers."""
+        if result :
+            entries = [tuple([f[0] for f in self.cursor.description])]
+            for entry in result :    
+                row = []
+                for value in entry :
+                    try :
+                        value = value.encode("UTF-8")
+                    except :
+                        pass
+                    row.append(value)
+                entries.append(tuple(row))    
+            return entries   
+        
Index: /pykota/trunk/pykota/config.py
===================================================================
--- /pykota/trunk/pykota/config.py (revision 2583)
+++ /pykota/trunk/pykota/config.py (revision 2593)
@@ -95,9 +95,17 @@
         """Returns the storage backend information as a Python mapping."""        
         backendinfo = {}
-        for option in [ "storagebackend", "storageserver", \
-                        "storagename", "storageuser", \
-                      ] :
-            backendinfo[option] = self.getGlobalOption(option)
-        backendinfo["storageuserpw"] = self.getGlobalOption("storageuserpw", ignore=1)  # password is optional
+        backend = self.getGlobalOption("storagebackend").lower()
+        backendinfo["storagebackend"] = backend
+        if backend == "sqlitestorage" :
+            issqlite = 1
+            backendinfo["storagename"] = self.getGlobalOption("storagename")
+            for option in ["storageserver", "storageuser", "storageuserpw"] :
+                backendinfo[option] = None          
+        else :
+            issqlite = 0
+            for option in ["storageserver", "storagename", "storageuser"] :
+                backendinfo[option] = self.getGlobalOption(option)
+            backendinfo["storageuserpw"] = self.getGlobalOption("storageuserpw", ignore=1)  # password is optional
+            
         backendinfo["storageadmin"] = None
         backendinfo["storageadminpw"] = None
@@ -109,5 +117,6 @@
                     backendinfo["storageadmin"] = adminconf.get("global", "storageadmin", raw=1)
                 except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) :    
-                    raise PyKotaConfigError, _("Option %s not found in section global of %s") % ("storageadmin", self.adminfilename)
+                    if not issqlite :
+                        raise PyKotaConfigError, _("Option %s not found in section global of %s") % ("storageadmin", self.adminfilename)
                 try :
                     backendinfo["storageadminpw"] = adminconf.get("global", "storageadminpw", raw=1)
Index: /pykota/trunk/pykota/version.py
===================================================================
--- /pykota/trunk/pykota/version.py (revision 2588)
+++ /pykota/trunk/pykota/version.py (revision 2593)
@@ -22,5 +22,5 @@
 #
 
-__version__ = "1.24alpha3_unofficial"
+__version__ = "1.24alpha4_unofficial"
 
 __doc__ = "PyKota : a complete Printing Quota Solution for CUPS."
Index: /pykota/trunk/initscripts/sqlite/README.sqlite
===================================================================
--- /pykota/trunk/initscripts/sqlite/README.sqlite (revision 2593)
+++ /pykota/trunk/initscripts/sqlite/README.sqlite (revision 2593)
@@ -0,0 +1,84 @@
+# $Id$
+
+PyKota - Print Quotas for CUPS and LPRng
+
+(c) 2003, 2004, 2005 Jerome Alet <alet@librelogiciel.com>
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+============================================================
+
+        NB : FOR NOW SQLITE SUPPORT IS EXPERIMENTAL
+
+        USE AT YOUR OWN RISK !!!
+
+============================================================
+
+Documentation :
+---------------
+
+pykota.sqlite :
+
+    This file can be used to create an empty SQLite3 database
+    for use with PyKota, in the case you don't want to use
+    either LDAP or PostgreSQL.
+    
+    NB : an SQLite3 database can't be shared between several
+    PyKota managed print servers, contrarily to LDAP or 
+    PostgreSQL.
+    
+    HowTo :
+    
+      - Install SQLite v3.2.7 or higher, and its development files,
+        for example on my Debian box :
+        
+                # apt-get install sqlite3 libsqlite3-dev
+
+      - Download and install PySQLite v2.0.5 or higher from :
+      
+                http://initd.org/tracker/pysqlite
+
+        Install it this way :
+
+                # tar -zxf pysqlite-2.0.5.tar.gz
+                # cd pysqlite-2.0.5
+                # python setup.py install
+                
+      - Create an SQLite3 database for PyKota :
+
+                # sqlite3 /etc/pykota/pykota.db <pykota.sqlite
+                # chown pykota.pykota /etc/pykota/pykota.db
+                # chmod 660 /etc/pykota/pykota.db
+                
+        NB : adapt the permissions so that the user your printing
+             system runs as (e.g. user 'lp') can read and write
+             to the /etc/pykota/pykota.db file.
+                
+      - In pykotadmin.conf, just comment out all the lines
+
+      - In pykota.conf, set :
+
+                storagebackend : sqlitestorage
+                storagename : /etc/pykota/pykota.db
+                
+        And comment out all other directives which name begins with 'storage'.
+        NB : feel free to use a different path to store pykota.db, and
+             adapt your configuration files accordingly.
+                
+Your PyKota setup is now ready to be used with an SQLite3 database.             
+
+Please report bugs to : alet@librelogiciel.com
+
+===================================================================
Index: /pykota/trunk/NEWS
===================================================================
--- /pykota/trunk/NEWS (revision 2588)
+++ /pykota/trunk/NEWS (revision 2593)
@@ -22,4 +22,9 @@
 PyKota NEWS :
        
+    - 1.24alpha4 :
+    
+        - Added support for the SQLite3 backend.
+          See pykota/initscripts/sqlite/README.sqlite
+        
     - 1.24alpha3 :
     
