Index: /pykota/trunk/pykota/storages/mysqlstorage.py
===================================================================
--- /pykota/trunk/pykota/storages/mysqlstorage.py (revision 3288)
+++ /pykota/trunk/pykota/storages/mysqlstorage.py (revision 3294)
@@ -98,5 +98,5 @@
         try :
             before = time.time()
-            self.tool.logdebug("QUERY : %s" % query)
+            self.querydebug("QUERY : %s" % query)
             self.cursor.execute(query)
         except self.database.Error, msg :    
@@ -137,5 +137,5 @@
         try :
             before = time.time()
-            self.tool.logdebug("QUERY : %s" % query)
+            self.querydebug("QUERY : %s" % query)
             self.cursor.execute(query)
         except self.database.Error, msg :    
Index: /pykota/trunk/pykota/storages/pgstorage.py
===================================================================
--- /pykota/trunk/pykota/storages/pgstorage.py (revision 3291)
+++ /pykota/trunk/pykota/storages/pgstorage.py (revision 3294)
@@ -29,4 +29,6 @@
 from pykota.storage import BaseStorage
 from pykota.storages.sql import SQLStorage
+
+from pykota.utils import *                           
 
 try :
@@ -99,5 +101,5 @@
         try :
             before = time.time()
-            self.tool.logdebug("QUERY : %s" % query)
+            self.querydebug("QUERY : %s" % query)
             result = self.database.query(query)
         except PGError, msg :    
@@ -121,5 +123,5 @@
         try :
             before = time.time()
-            self.tool.logdebug("QUERY : %s" % query)
+            self.querydebug("QUERY : %s" % query)
             result = self.database.query(query)
         except PGError, msg :    
@@ -154,5 +156,5 @@
                     field = fields[j]
                     if type(field) == StringType :
-                        fields[j] = self.databaseToUnicode(field) 
+                        fields[j] = databaseToUnicode(field) 
                 entries[i] = tuple(fields)    
             return entries
Index: /pykota/trunk/pykota/storages/sql.py
===================================================================
--- /pykota/trunk/pykota/storages/sql.py (revision 3293)
+++ /pykota/trunk/pykota/storages/sql.py (revision 3294)
@@ -26,4 +26,6 @@
                            StorageJob, StorageLastJob, StorageUserPQuota, \
                            StorageGroupPQuota, StorageBillingCode
+                           
+from pykota.utils import *                           
 
 class SQLStorage :
@@ -36,5 +38,5 @@
         user.LifeTimePaid = record.get("lifetimepaid")
         user.Email = record.get("email")
-        user.Description = self.databaseToUnicode(record.get("description"))
+        user.Description = databaseToUnicode(record.get("description"))
         user.OverCharge = record.get("overcharge", 1.0)
         user.Exists = True
@@ -48,5 +50,5 @@
         group.AccountBalance = record.get("balance")
         group.LifeTimePaid = record.get("lifetimepaid")
-        group.Description = self.databaseToUnicode(record.get("description"))
+        group.Description = databaseToUnicode(record.get("description"))
         group.Exists = True
         return group
@@ -64,5 +66,5 @@
         else :
             printer.PassThrough = False
-        printer.Description = self.databaseToUnicode(record.get("description") or "") # TODO : is 'or ""' still needed ?
+        printer.Description = databaseToUnicode(record.get("description") or "") # TODO : is 'or ""' still needed ?
         printer.Exists = True
         return printer
@@ -76,8 +78,8 @@
         job.JobPrice = record.get("jobprice")
         job.JobAction = record.get("action")
-        job.JobFileName = self.databaseToUnicode(record.get("filename") or "") 
-        job.JobTitle = self.databaseToUnicode(record.get("title") or "") 
+        job.JobFileName = databaseToUnicode(record.get("filename") or "") 
+        job.JobTitle = databaseToUnicode(record.get("title") or "") 
         job.JobCopies = record.get("copies")
-        job.JobOptions = self.databaseToUnicode(record.get("options") or "") 
+        job.JobOptions = databaseToUnicode(record.get("options") or "") 
         job.JobDate = record.get("jobdate")
         job.JobHostName = record.get("hostname")
@@ -85,9 +87,9 @@
         job.JobMD5Sum = record.get("md5sum")
         job.JobPages = record.get("pages")
-        job.JobBillingCode = self.databaseToUnicode(record.get("billingcode") or "")
+        job.JobBillingCode = databaseToUnicode(record.get("billingcode") or "")
         job.PrecomputedJobSize = record.get("precomputedjobsize")
         job.PrecomputedJobPrice = record.get("precomputedjobprice")
-        job.UserName = self.databaseToUnicode(record.get("username"))
-        job.PrinterName = self.databaseToUnicode(record.get("printername"))
+        job.UserName = databaseToUnicode(record.get("username"))
+        job.PrinterName = databaseToUnicode(record.get("printername"))
         if job.JobTitle == job.JobFileName == job.JobOptions == "hidden" :
             (job.JobTitle, job.JobFileName, job.JobOptions) = (_("Hidden because of privacy concerns"),) * 3
@@ -138,5 +140,5 @@
         code = StorageBillingCode(self, billingcode)
         code.ident = record.get("id")
-        code.Description = self.databaseToUnicode(record.get("description") or "") # TODO : is 'or ""' still needed ?
+        code.Description = databaseToUnicode(record.get("description") or "") # TODO : is 'or ""' still needed ?
         code.Balance = record.get("balance") or 0.0
         code.PageCounter = record.get("pagecounter") or 0
@@ -149,5 +151,5 @@
             expressions = []
             for (k, v) in only.items() :
-                expressions.append("%s=%s" % (k, self.doQuote(self.unicodeToDatabase(v))))
+                expressions.append("%s=%s" % (k, self.doQuote(unicodeToDatabase(v))))
             return " AND ".join(expressions)     
         return ""        
@@ -299,5 +301,5 @@
                 self.tool.printInfo("Object %s has no %s attribute !" % (repr(record), attribute), "error")
             else :
-                attrval = self.databaseToUnicode(attrval)
+                attrval = databaseToUnicode(attrval)
                 if patterns :
                     if (not isinstance(patterns, type([]))) and (not isinstance(patterns, type(()))) :
@@ -351,5 +353,5 @@
         """Extracts user information given its name."""
         result = self.doSearch("SELECT * FROM users WHERE username=%s"\
-                      % self.doQuote(self.unicodeToDatabase(username)))
+                      % self.doQuote(unicodeToDatabase(username)))
         if result :
             return self.storageUserFromRecord(username, result[0])
@@ -360,5 +362,5 @@
         """Extracts group information given its name."""
         result = self.doSearch("SELECT groups.*,COALESCE(SUM(balance), 0.0) AS balance, COALESCE(SUM(lifetimepaid), 0.0) AS lifetimepaid FROM groups LEFT OUTER JOIN users ON users.id IN (SELECT userid FROM groupsmembers WHERE groupid=groups.id) WHERE groupname=%s GROUP BY groups.id,groups.groupname,groups.limitby,groups.description" \
-                      % self.doQuote(self.unicodeToDatabase(groupname)))
+                      % self.doQuote(unicodeToDatabase(groupname)))
         if result :
             return self.storageGroupFromRecord(groupname, result[0])
@@ -369,5 +371,5 @@
         """Extracts printer information given its name."""
         result = self.doSearch("SELECT * FROM printers WHERE printername=%s" \
-                      % self.doQuote(self.unicodeToDatabase(printername)))
+                      % self.doQuote(unicodeToDatabase(printername)))
         if result :
             return self.storagePrinterFromRecord(printername, result[0])
@@ -378,5 +380,5 @@
         """Extracts a billing code information given its name."""
         result = self.doSearch("SELECT * FROM billingcodes WHERE billingcode=%s" \
-                      % self.doQuote(self.unicodeToDatabase(label)))
+                      % self.doQuote(unicodeToDatabase(label)))
         if result :
             return self.storageBillingCodeFromRecord(label, result[0])
@@ -416,5 +418,5 @@
         if result :
             for record in result :
-                user = self.storageUserFromRecord(self.databaseToUnicode(record.get("username")), \
+                user = self.storageUserFromRecord(databaseToUnicode(record.get("username")), \
                                                   record)
                 groupmembers.append(user)
@@ -428,5 +430,5 @@
         if result :
             for record in result :
-                groups.append(self.getGroup(self.databaseToUnicode(record.get("groupname"))))
+                groups.append(self.getGroup(databaseToUnicode(record.get("groupname"))))
         return groups        
         
@@ -438,5 +440,5 @@
             for record in result :
                 if record["groupid"] != printer.ident : # in case of integrity violation
-                    parentprinter = self.getPrinter(self.databaseToUnicode(record.get("printername")))
+                    parentprinter = self.getPrinter(databaseToUnicode(record.get("printername")))
                     if parentprinter.Exists :
                         pgroups.append(parentprinter)
@@ -460,5 +462,5 @@
                     patdict[p] = None
             for record in result :
-                pname = self.databaseToUnicode(record["printername"])
+                pname = databaseToUnicode(record["printername"])
                 if patdict.has_key(pname) or self.tool.matchString(pname, patterns) :
                     printer = self.storagePrinterFromRecord(pname, record)
@@ -484,5 +486,5 @@
                     patdict[p] = None
             for record in result :
-                uname = self.databaseToUnicode(record["username"])
+                uname = databaseToUnicode(record["username"])
                 if patdict.has_key(uname) or self.tool.matchString(uname, patterns) :
                     user = self.storageUserFromRecord(uname, record)
@@ -508,5 +510,5 @@
                     patdict[p] = None
             for record in result :
-                gname = self.databaseToUnicode(record["groupname"])
+                gname = databaseToUnicode(record["groupname"])
                 if patdict.has_key(gname) or self.tool.matchString(gname, patterns) :
                     group = self.storageGroupFromRecord(gname, record)
@@ -529,5 +531,5 @@
                     patdict[p] = None
             for record in result :
-                codename = self.databaseToUnicode(record["billingcode"])
+                codename = databaseToUnicode(record["billingcode"])
                 if patdict.has_key(codename) or self.tool.matchString(codename, patterns) :
                     code = self.storageBillingCodeFromRecord(codename, record)
@@ -542,5 +544,5 @@
         if result :
             for record in result :
-                uname = self.databaseToUnicode(record.get("username"))
+                uname = databaseToUnicode(record.get("username"))
                 if self.tool.matchString(uname, names) :
                     user = self.storageUserFromRecord(uname, record)
@@ -557,5 +559,5 @@
         if result :
             for record in result :
-                gname = self.databaseToUnicode(record.get("groupname"))
+                gname = databaseToUnicode(record.get("groupname"))
                 if self.tool.matchString(gname, names) :
                     group = self.getGroup(gname)
@@ -570,8 +572,8 @@
             return oldentry
         self.doModify("INSERT INTO printers (printername, passthrough, maxjobsize, description, priceperpage, priceperjob) VALUES (%s, %s, %s, %s, %s, %s)" \
-                          % (self.doQuote(self.unicodeToDatabase(printer.Name)), \
+                          % (self.doQuote(unicodeToDatabase(printer.Name)), \
                              self.doQuote((printer.PassThrough and "t") or "f"), \
                              self.doQuote(printer.MaxJobSize or 0), \
-                             self.doQuote(self.unicodeToDatabase(printer.Description)), \
+                             self.doQuote(unicodeToDatabase(printer.Description)), \
                              self.doQuote(printer.PricePerPage or 0.0), \
                              self.doQuote(printer.PricePerJob or 0.0)))
@@ -585,8 +587,8 @@
             return oldentry
         self.doModify("INSERT INTO billingcodes (billingcode, balance, pagecounter, description) VALUES (%s, %s, %s, %s)" \
-                           % (self.doQuote(self.unicodeToDatabase(bcode.BillingCode)), 
+                           % (self.doQuote(unicodeToDatabase(bcode.BillingCode)), 
                               self.doQuote(bcode.Balance or 0.0), \
                               self.doQuote(bcode.PageCounter or 0), \
-                              self.doQuote(self.unicodeToDatabase(bcode.Description))))
+                              self.doQuote(unicodeToDatabase(bcode.Description))))
         bcode.isDirty = False
         return None # the entry created doesn't need further modification
@@ -598,5 +600,5 @@
             return oldentry
         self.doModify("INSERT INTO users (username, limitby, balance, lifetimepaid, email, overcharge, description) VALUES (%s, %s, %s, %s, %s, %s, %s)" % \
-                                     (self.doQuote(self.unicodeToDatabase(user.Name)), \
+                                     (self.doQuote(unicodeToDatabase(user.Name)), \
                                       self.doQuote(user.LimitBy or 'quota'), \
                                       self.doQuote(user.AccountBalance or 0.0), \
@@ -604,5 +606,5 @@
                                       self.doQuote(user.Email), \
                                       self.doQuote(user.OverCharge), \
-                                      self.doQuote(self.unicodeToDatabase(user.Description))))
+                                      self.doQuote(unicodeToDatabase(user.Description))))
         if user.PaymentsBacklog :
             for (value, comment) in user.PaymentsBacklog :
@@ -618,7 +620,7 @@
             return oldentry
         self.doModify("INSERT INTO groups (groupname, limitby, description) VALUES (%s, %s, %s)" % \
-                              (self.doQuote(self.unicodeToDatabase(group.Name)), \
+                              (self.doQuote(unicodeToDatabase(group.Name)), \
                                self.doQuote(group.LimitBy or "quota"), \
-                               self.doQuote(self.unicodeToDatabase(group.Description))))
+                               self.doQuote(unicodeToDatabase(group.Description))))
         group.isDirty = False
         return None # the entry created doesn't need further modification
@@ -677,5 +679,5 @@
                               % (self.doQuote((printer.PassThrough and "t") or "f"), \
                                  self.doQuote(printer.MaxJobSize or 0), \
-                                 self.doQuote(self.unicodeToDatabase(printer.Description)), \
+                                 self.doQuote(unicodeToDatabase(printer.Description)), \
                                  self.doQuote(printer.PricePerPage or 0.0), \
                                  self.doQuote(printer.PricePerJob or 0.0), \
@@ -690,5 +692,5 @@
                                   self.doQuote(user.Email), \
                                   self.doQuote(user.OverCharge), \
-                                  self.doQuote(self.unicodeToDatabase(user.Description)), \
+                                  self.doQuote(unicodeToDatabase(user.Description)), \
                                   self.doQuote(user.ident)))
                                   
@@ -697,5 +699,5 @@
         self.doModify("UPDATE groups SET limitby=%s, description=%s WHERE id=%s" \
                                % (self.doQuote(group.LimitBy or 'quota'), \
-                                  self.doQuote(self.unicodeToDatabase(group.Description)), \
+                                  self.doQuote(unicodeToDatabase(group.Description)), \
                                   self.doQuote(group.ident)))
         
@@ -717,5 +719,5 @@
                             % (self.doQuote(bcode.Balance or 0.0), \
                                self.doQuote(bcode.PageCounter or 0), \
-                               self.doQuote(self.unicodeToDatabase(bcode.Description)), \
+                               self.doQuote(unicodeToDatabase(bcode.Description)), \
                                self.doQuote(bcode.ident)))
        
@@ -735,7 +737,7 @@
         """Adds a new payment to the payments history."""
         if user.ident is not None :
-            self.doModify("INSERT INTO payments (userid, amount, description) VALUES (%s, %s, %s)" % (self.doQuote(user.ident), self.doQuote(amount), self.doQuote(self.unicodeToDatabase(comment))))
+            self.doModify("INSERT INTO payments (userid, amount, description) VALUES (%s, %s, %s)" % (self.doQuote(user.ident), self.doQuote(amount), self.doQuote(unicodeToDatabase(comment))))
         else :    
-            self.doModify("INSERT INTO payments (userid, amount, description) VALUES ((SELECT id FROM users WHERE username=%s), %s, %s)" % (self.doQuote(self.unicodeToDatabase(user.Name)), self.doQuote(amount), self.doQuote(self.unicodeToDatabase(comment))))
+            self.doModify("INSERT INTO payments (userid, amount, description) VALUES ((SELECT id FROM users WHERE username=%s), %s, %s)" % (self.doQuote(unicodeToDatabase(user.Name)), self.doQuote(amount), self.doQuote(unicodeToDatabase(comment))))
         
     def writeLastJobSize(self, lastjob, jobsize, jobprice) :        
@@ -748,8 +750,8 @@
             # For legal reasons, we want to hide the title, filename and options
             title = filename = options = "hidden"
-        filename = self.unicodeToDatabase(filename)
-        title = self.unicodeToDatabase(title)
-        options = self.unicodeToDatabase(options)
-        jobbilling = self.unicodeToDatabase(jobbilling)
+        filename = unicodeToDatabase(filename)
+        title = unicodeToDatabase(title)
+        options = unicodeToDatabase(options)
+        jobbilling = unicodeToDatabase(jobbilling)
         if (not self.disablehistory) or (not printer.LastJob.Exists) :
             if jobsize is not None :
@@ -814,7 +816,7 @@
             where.append("hostname=%s" % self.doQuote(hostname))
         if billingcode is not None :    
-            where.append("billingcode=%s" % self.doQuote(self.unicodeToDatabase(billingcode)))
+            where.append("billingcode=%s" % self.doQuote(unicodeToDatabase(billingcode)))
         if jobid is not None :    
-            where.append("jobid=%s" % self.doQuote(jobid)) # TODO : jobid is text, so self.unicodeToDatabase(jobid) but do all of them as well.
+            where.append("jobid=%s" % self.doQuote(jobid)) # TODO : jobid is text, so unicodeToDatabase(jobid) but do all of them as well.
         if start is not None :    
             where.append("jobdate>=%s" % self.doQuote(start))
Index: /pykota/trunk/pykota/storages/ldapstorage.py
===================================================================
--- /pykota/trunk/pykota/storages/ldapstorage.py (revision 3291)
+++ /pykota/trunk/pykota/storages/ldapstorage.py (revision 3294)
@@ -42,4 +42,6 @@
                            StorageJob, StorageLastJob, StorageUserPQuota, \
                            StorageGroupPQuota, StorageBillingCode
+                           
+from pykota.utils import *                           
 
 try :
@@ -160,5 +162,5 @@
                     result = [(base, entry)]
                 else :
-                    self.tool.logdebug("QUERY : Filter : %s, BaseDN : %s, Scope : %s, Attributes : %s" % (key, base, scope, fields))
+                    self.querydebug("QUERY : Filter : %s, BaseDN : %s, Scope : %s, Attributes : %s" % (key, base, scope, fields))
                     result = self.database.search_s(base, scope, key, fields)
             except ldap.NO_SUCH_OBJECT, msg :        
@@ -171,9 +173,9 @@
                 self.secondStageInit()
             else :     
-                self.tool.logdebug("QUERY : Result : %s" % result)
+                self.querydebug("QUERY : Result : %s" % result)
                 result = [ (dn, cidict(attrs)) for (dn, attrs) in result ]
                 if self.useldapcache :
                     for (dn, attributes) in result :
-                        self.tool.logdebug("LDAP cache store %s => %s" % (dn, attributes))
+                        self.querydebug("LDAP cache store %s => %s" % (dn, attributes))
                         self.ldapcache[dn] = attributes
                 return result
@@ -186,7 +188,7 @@
         for tryit in range(3) :
             try :
-                self.tool.logdebug("QUERY : ADD(%s, %s)" % (dn, str(fields)))
+                self.querydebug("QUERY : ADD(%s, %s)" % (dn, fields))
                 entry = ldap.modlist.addModlist(fields)
-                self.tool.logdebug("%s" % entry)
+                self.querydebug("%s" % entry)
                 self.database.add_s(dn, entry)
             except ldap.ALREADY_EXISTS, msg :        
@@ -200,5 +202,5 @@
             else :
                 if self.useldapcache :
-                    self.tool.logdebug("LDAP cache add %s => %s" % (dn, fields))
+                    self.querydebug("LDAP cache add %s => %s" % (dn, fields))
                     self.ldapcache[dn] = fields
                 return dn
@@ -210,5 +212,5 @@
         for tryit in range(3) :
             try :
-                self.tool.logdebug("QUERY : Delete(%s)" % dn)
+                self.querydebug("QUERY : Delete(%s)" % dn)
                 self.database.delete_s(dn)
             except ldap.NO_SUCH_OBJECT :    
@@ -223,5 +225,5 @@
                 if self.useldapcache :
                     try :
-                        self.tool.logdebug("LDAP cache del %s" % dn)
+                        self.querydebug("LDAP cache del %s" % dn)
                         del self.ldapcache[dn]
                     except KeyError :    
@@ -239,5 +241,5 @@
                     if self.ldapcache.has_key(dn) :
                         old = self.ldapcache[dn]
-                        self.tool.logdebug("LDAP cache hit %s => %s" % (dn, old))
+                        self.querydebug("LDAP cache hit %s => %s" % (dn, old))
                         oldentry = {}
                         for (k, v) in old.items() :
@@ -245,5 +247,5 @@
                                 oldentry[k] = v
                     else :    
-                        self.tool.logdebug("LDAP cache miss %s" % dn)
+                        self.querydebug("LDAP cache miss %s" % dn)
                         oldentry = self.doSearch("objectClass=*", base=dn, scope=ldap.SCOPE_BASE)[0][1]
                 else :        
@@ -254,5 +256,5 @@
                             oldvalue = v["convert"](oldentry.get(k, [0])[0])
                         except ValueError :    
-                            self.tool.logdebug("Error converting %s with %s(%s)" % (oldentry.get(k), k, v))
+                            self.querydebug("Error converting %s with %s(%s)" % (oldentry.get(k), k, v))
                             oldvalue = 0
                         if v["operator"] == '+' :
@@ -262,5 +264,5 @@
                         fields[k] = str(newvalue)
                 fields = self.normalizeFields(fields)
-                self.tool.logdebug("QUERY : Modify(%s, %s ==> %s)" % (dn, oldentry, fields))
+                self.querydebug("QUERY : Modify(%s, %s ==> %s)" % (dn, oldentry, fields))
                 entry = ldap.modlist.modifyModlist(oldentry, fields, ignore_oldexistent=ignoreold)
                 modentry = []
@@ -268,5 +270,5 @@
                     if mtyp and (mtyp.lower() != "createtimestamp") :
                         modentry.append((mop, mtyp, mval))
-                self.tool.logdebug("MODIFY : %s ==> %s ==> %s" % (fields, entry, modentry))
+                self.querydebug("MODIFY : %s ==> %s ==> %s" % (fields, entry, modentry))
                 if modentry :
                     self.database.modify_s(dn, modentry)
@@ -288,5 +290,5 @@
                             except KeyError :    
                                 pass
-                    self.tool.logdebug("LDAP cache update %s => %s" % (dn, cachedentry))
+                    self.querydebug("LDAP cache update %s => %s" % (dn, cachedentry))
                 return dn
         raise PyKotaStorageError, message
@@ -303,5 +305,5 @@
                 self.tool.printInfo("Object %s has no %s attribute !" % (dn, attribute), "error")
             else :
-                attrval = self.databaseToUnicode(attrval)
+                attrval = databaseToUnicode(attrval)
                 if patterns :
                     if (not isinstance(patterns, type([]))) and (not isinstance(patterns, type(()))) :
@@ -318,5 +320,5 @@
         result = self.doSearch(ldapfilter, ["pykotaBillingCode"], base=self.info["billingcodebase"])
         if result :
-            return [self.databaseToUnicode(bc) for bc in self.filterNames(result, "pykotaBillingCode", billingcode)]
+            return [databaseToUnicode(bc) for bc in self.filterNames(result, "pykotaBillingCode", billingcode)]
         else :    
             return []
@@ -351,5 +353,5 @@
     def getUserNbJobsFromHistory(self, user) :
         """Returns the number of jobs the user has in history."""
-        result = self.doSearch("(&(pykotaUserName=%s)(objectClass=pykotaJob))" % self.unicodeToDatabase(user.Name), None, base=self.info["jobbase"])
+        result = self.doSearch("(&(pykotaUserName=%s)(objectClass=pykotaJob))" % unicodeToDatabase(user.Name), None, base=self.info["jobbase"])
         return len(result)
         
@@ -357,10 +359,10 @@
         """Extracts user information given its name."""
         user = StorageUser(self, username)
-        username = self.unicodeToDatabase(username)
+        username = unicodeToDatabase(username)
         result = self.doSearch("(&(objectClass=pykotaAccount)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["userrdn"], username), ["pykotaUserName", "pykotaLimitBy", self.info["usermail"], "description"], base=self.info["userbase"])
         if result :
             fields = result[0][1]
             user.ident = result[0][0]
-            user.Description = self.databaseToUnicode(fields.get("description", [None])[0])
+            user.Description = databaseToUnicode(fields.get("description", [None])[0])
             user.Email = fields.get(self.info["usermail"], [None])[0]
             user.LimitBy = fields.get("pykotaLimitBy", ["quota"])[0]
@@ -395,5 +397,5 @@
                         description = ""
                     else :    
-                        description = self.databaseToUnicode(base64.decodestring(description))
+                        description = databaseToUnicode(base64.decodestring(description))
                     if amount.endswith(" #") :    
                         amount = amount[:-2] # TODO : should be catched earlier, the bug is above I think
@@ -405,11 +407,11 @@
         """Extracts group information given its name."""
         group = StorageGroup(self, groupname)
-        groupname = self.unicodeToDatabase(groupname)
+        groupname = unicodeToDatabase(groupname)
         result = self.doSearch("(&(objectClass=pykotaGroup)(|(pykotaGroupName=%s)(%s=%s)))" % (groupname, self.info["grouprdn"], groupname), ["pykotaGroupName", "pykotaLimitBy", "description"], base=self.info["groupbase"])
         if result :
             fields = result[0][1]
             group.ident = result[0][0]
-            group.Name = fields.get("pykotaGroupName", [self.databaseToUnicode(groupname)])[0] 
-            group.Description = self.databaseToUnicode(fields.get("description", [None])[0])
+            group.Name = fields.get("pykotaGroupName", [databaseToUnicode(groupname)])[0] 
+            group.Description = databaseToUnicode(fields.get("description", [None])[0])
             group.LimitBy = fields.get("pykotaLimitBy", ["quota"])[0]
             group.AccountBalance = 0.0
@@ -425,5 +427,5 @@
         """Extracts printer information given its name : returns first matching printer."""
         printer = StoragePrinter(self, printername)
-        printername = self.unicodeToDatabase(printername)
+        printername = unicodeToDatabase(printername)
         result = self.doSearch("(&(objectClass=pykotaPrinter)(|(pykotaPrinterName=%s)(%s=%s)))" \
                       % (printername, self.info["printerrdn"], printername), \
@@ -435,5 +437,5 @@
             fields = result[0][1]       # take only first matching printer, ignore the rest
             printer.ident = result[0][0]
-            printer.Name = fields.get("pykotaPrinterName", [self.databaseToUnicode(printername)])[0] 
+            printer.Name = fields.get("pykotaPrinterName", [databaseToUnicode(printername)])[0] 
             printer.PricePerJob = float(fields.get("pykotaPricePerJob", [0.0])[0])
             printer.PricePerPage = float(fields.get("pykotaPricePerPage", [0.0])[0])
@@ -445,5 +447,5 @@
                 printer.PassThrough = 0
             printer.uniqueMember = fields.get("uniqueMember", [])
-            printer.Description = self.databaseToUnicode(fields.get("description", [""])[0]) 
+            printer.Description = databaseToUnicode(fields.get("description", [""])[0]) 
             printer.Exists = True
         return printer    
@@ -458,5 +460,5 @@
                 base = self.info["userquotabase"]
             result = self.doSearch("(&(objectClass=pykotaUserPQuota)(pykotaUserName=%s)(pykotaPrinterName=%s))" % \
-                                      (self.unicodeToDatabase(user.Name), self.unicodeToDatabase(printer.Name)), \
+                                      (unicodeToDatabase(user.Name), unicodeToDatabase(printer.Name)), \
                                       ["pykotaPageCounter", "pykotaLifePageCounter", "pykotaSoftLimit", "pykotaHardLimit", "pykotaDateLimit", "pykotaWarnCount", "pykotaMaxJobSize"], \
                                       base=base)
@@ -503,5 +505,5 @@
                 base = self.info["groupquotabase"]
             result = self.doSearch("(&(objectClass=pykotaGroupPQuota)(pykotaGroupName=%s)(pykotaPrinterName=%s))" % \
-                                      (self.unicodeToDatabase(group.Name), self.unicodeToDatabase(printer.Name)), \
+                                      (unicodeToDatabase(group.Name), unicodeToDatabase(printer.Name)), \
                                       ["pykotaSoftLimit", "pykotaHardLimit", "pykotaDateLimit", "pykotaMaxJobSize"], \
                                       base=base)
@@ -535,5 +537,5 @@
                 grouppquota.PageCounter = 0
                 grouppquota.LifePageCounter = 0
-                usernamesfilter = "".join(["(pykotaUserName=%s)" % self.unicodeToDatabase(member.Name) for member in self.getGroupMembers(group)])
+                usernamesfilter = "".join(["(pykotaUserName=%s)" % unicodeToDatabase(member.Name) for member in self.getGroupMembers(group)])
                 if usernamesfilter :
                     usernamesfilter = "(|%s)" % usernamesfilter
@@ -543,5 +545,5 @@
                     base = self.info["userquotabase"]
                 result = self.doSearch("(&(objectClass=pykotaUserPQuota)(pykotaPrinterName=%s)%s)" % \
-                                          (self.unicodeToDatabase(printer.Name), usernamesfilter), \
+                                          (unicodeToDatabase(printer.Name), usernamesfilter), \
                                           ["pykotaPageCounter", "pykotaLifePageCounter"], base=base)
                 if result :
@@ -555,5 +557,5 @@
         """Extracts a printer's last job information."""
         lastjob = StorageLastJob(self, printer)
-        pname = self.unicodeToDatabase(printer.Name)
+        pname = unicodeToDatabase(printer.Name)
         result = self.doSearch("(&(objectClass=pykotaLastjob)(|(pykotaPrinterName=%s)(%s=%s)))" % \
                                   (pname, self.info["printerrdn"], pname), \
@@ -591,5 +593,5 @@
                 lastjob.ident = result[0][0]
                 lastjob.JobId = fields.get("pykotaJobId")[0]
-                lastjob.UserName = self.databaseToUnicode(fields.get("pykotaUserName")[0])
+                lastjob.UserName = databaseToUnicode(fields.get("pykotaUserName")[0])
                 lastjob.PrinterPageCounter = int(fields.get("pykotaPrinterPageCounter", [0])[0])
                 try :
@@ -602,11 +604,11 @@
                     lastjob.JobPrice = None
                 lastjob.JobAction = fields.get("pykotaAction", [""])[0]
-                lastjob.JobFileName = self.databaseToUnicode(fields.get("pykotaFileName", [""])[0]) 
-                lastjob.JobTitle = self.databaseToUnicode(fields.get("pykotaTitle", [""])[0]) 
+                lastjob.JobFileName = databaseToUnicode(fields.get("pykotaFileName", [""])[0]) 
+                lastjob.JobTitle = databaseToUnicode(fields.get("pykotaTitle", [""])[0]) 
                 lastjob.JobCopies = int(fields.get("pykotaCopies", [0])[0])
-                lastjob.JobOptions = self.databaseToUnicode(fields.get("pykotaOptions", [""])[0]) 
+                lastjob.JobOptions = databaseToUnicode(fields.get("pykotaOptions", [""])[0]) 
                 lastjob.JobHostName = fields.get("pykotaHostName", [""])[0]
                 lastjob.JobSizeBytes = fields.get("pykotaJobSizeBytes", [0L])[0]
-                lastjob.JobBillingCode = self.databaseToUnicode(fields.get("pykotaBillingCode", [None])[0])
+                lastjob.JobBillingCode = databaseToUnicode(fields.get("pykotaBillingCode", [None])[0])
                 lastjob.JobMD5Sum = fields.get("pykotaMD5Sum", [None])[0]
                 lastjob.JobPages = fields.get("pykotaPages", [""])[0]
@@ -630,5 +632,5 @@
         """Returns the group's members list."""
         groupmembers = []
-        gname = self.unicodeToDatabase(group.Name)
+        gname = unicodeToDatabase(group.Name)
         result = self.doSearch("(&(objectClass=pykotaGroup)(|(pykotaGroupName=%s)(%s=%s)))" % \
                                   (gname, self.info["grouprdn"], gname), \
@@ -637,5 +639,5 @@
         if result :
             for username in result[0][1].get(self.info["groupmembers"], []) :
-                groupmembers.append(self.getUser(self.databaseToUnicode(username)))
+                groupmembers.append(self.getUser(databaseToUnicode(username)))
         return groupmembers        
         
@@ -643,5 +645,5 @@
         """Returns the user's groups list."""
         groups = []
-        uname = self.unicodeToDatabase(user.Name)
+        uname = unicodeToDatabase(user.Name)
         result = self.doSearch("(&(objectClass=pykotaGroup)(%s=%s))" % \
                                   (self.info["groupmembers"], uname), \
@@ -650,5 +652,5 @@
         if result :
             for (groupid, fields) in result :
-                groupname = self.databaseToUnicode((fields.get("pykotaGroupName", [None]) or fields.get(self.info["grouprdn"], [None]))[0])
+                groupname = databaseToUnicode((fields.get("pykotaGroupName", [None]) or fields.get(self.info["grouprdn"], [None]))[0])
                 group = self.getFromCache("GROUPS", groupname)
                 if group is None :
@@ -681,5 +683,5 @@
             for (printerid, fields) in result :
                 if printerid != printer.ident : # In case of integrity violation.
-                    parentprinter = self.getPrinter(self.databaseToUnicode(fields.get("pykotaPrinterName")[0]))
+                    parentprinter = self.getPrinter(databaseToUnicode(fields.get("pykotaPrinterName")[0]))
                     if parentprinter.Exists :
                         pgroups.append(parentprinter)
@@ -703,5 +705,5 @@
                     patdict[p] = None
             for (printerid, fields) in result :
-                printername = self.databaseToUnicode(fields.get("pykotaPrinterName", [""])[0] or fields.get(self.info["printerrdn"], [""])[0])
+                printername = databaseToUnicode(fields.get("pykotaPrinterName", [""])[0] or fields.get(self.info["printerrdn"], [""])[0])
                 if patdict.has_key(printername) or self.tool.matchString(printername, patterns) :
                     printer = StoragePrinter(self, printername)
@@ -716,5 +718,5 @@
                         printer.PassThrough = 0
                     printer.uniqueMember = fields.get("uniqueMember", [])
-                    printer.Description = self.databaseToUnicode(fields.get("description", [""])[0]) 
+                    printer.Description = databaseToUnicode(fields.get("description", [""])[0]) 
                     printer.Exists = True
                     printers.append(printer)
@@ -739,5 +741,5 @@
                     patdict[p] = None
             for (userid, fields) in result :
-                username = self.databaseToUnicode(fields.get("pykotaUserName", [""])[0] or fields.get(self.info["userrdn"], [""])[0])
+                username = databaseToUnicode(fields.get("pykotaUserName", [""])[0] or fields.get(self.info["userrdn"], [""])[0])
                 if patdict.has_key(username) or self.tool.matchString(username, patterns) :
                     user = StorageUser(self, username)
@@ -745,6 +747,6 @@
                     user.Email = fields.get(self.info["usermail"], [None])[0]
                     user.LimitBy = fields.get("pykotaLimitBy", ["quota"])[0]
-                    user.Description = self.databaseToUnicode(fields.get("description", [""])[0]) 
-                    uname = self.unicodeToDatabase(username)
+                    user.Description = databaseToUnicode(fields.get("description", [""])[0]) 
+                    uname = unicodeToDatabase(username)
                     result = self.doSearch("(&(objectClass=pykotaAccountBalance)(|(pykotaUserName=%s)(%s=%s)))" % \
                                               (uname, self.info["balancerdn"], uname), \
@@ -780,5 +782,5 @@
                                 description = ""
                             else :    
-                                description = self.databaseToUnicode(base64.decodestring(description))
+                                description = databaseToUnicode(base64.decodestring(description))
                             if amount.endswith(" #") :    
                                 amount = amount[:-2] # TODO : should be catched earlier, the bug is above I think
@@ -806,11 +808,11 @@
                     patdict[p] = None
             for (groupid, fields) in result :
-                groupname = self.databaseToUnicode(fields.get("pykotaGroupName", [""])[0] or fields.get(self.info["grouprdn"], [""])[0])
+                groupname = databaseToUnicode(fields.get("pykotaGroupName", [""])[0] or fields.get(self.info["grouprdn"], [""])[0])
                 if patdict.has_key(groupname) or self.tool.matchString(groupname, patterns) :
                     group = StorageGroup(self, groupname)
                     group.ident = groupid
-                    group.Name = fields.get("pykotaGroupName", [self.databaseToUnicode(groupname)])[0] 
+                    group.Name = fields.get("pykotaGroupName", [databaseToUnicode(groupname)])[0] 
                     group.LimitBy = fields.get("pykotaLimitBy", ["quota"])[0]
-                    group.Description = self.databaseToUnicode(fields.get("description", [""])[0]) 
+                    group.Description = databaseToUnicode(fields.get("description", [""])[0]) 
                     group.AccountBalance = 0.0
                     group.LifeTimePaid = 0.0
@@ -827,6 +829,6 @@
         """Returns the list of users who uses a given printer, along with their quotas."""
         usersandquotas = []
-        pname = self.unicodeToDatabase(printer.Name)
-        names = [self.unicodeToDatabase(n) for n in names]
+        pname = unicodeToDatabase(printer.Name)
+        names = [unicodeToDatabase(n) for n in names]
         if self.info["userquotabase"].lower() == "user" :
             base = self.info["userbase"]
@@ -839,5 +841,5 @@
         if result :
             for (userquotaid, fields) in result :
-                user = self.getUser(self.databaseToUnicode(fields.get("pykotaUserName")[0]))
+                user = self.getUser(databaseToUnicode(fields.get("pykotaUserName")[0]))
                 userpquota = StorageUserPQuota(self, user, printer)
                 userpquota.ident = userquotaid
@@ -872,6 +874,6 @@
         """Returns the list of groups which uses a given printer, along with their quotas."""
         groupsandquotas = []
-        pname = self.unicodeToDatabase(printer.Name)
-        names = [self.unicodeToDatabase(n) for n in names]
+        pname = unicodeToDatabase(printer.Name)
+        names = [unicodeToDatabase(n) for n in names]
         if self.info["groupquotabase"].lower() == "group" :
             base = self.info["groupbase"]
@@ -884,5 +886,5 @@
         if result :
             for (groupquotaid, fields) in result :
-                group = self.getGroup(self.databaseToUnicode(fields.get("pykotaGroupName")[0]))
+                group = self.getGroup(databaseToUnicode(fields.get("pykotaGroupName")[0]))
                 grouppquota = self.getGroupPQuota(group, printer)
                 groupsandquotas.append((group, grouppquota))
@@ -895,5 +897,5 @@
         if oldentry.Exists :
             return oldentry # we return the existing entry
-        printername = self.unicodeToDatabase(printer.Name)
+        printername = unicodeToDatabase(printer.Name)
         fields = { self.info["printerrdn"] : printername,
                    "objectClass" : ["pykotaObject", "pykotaPrinter"],
@@ -902,5 +904,5 @@
                    "pykotaPassThrough" : (printer.PassThrough and "t") or "f",
                    "pykotaMaxJobSize" : str(printer.MaxJobSize or 0),
-                   "description" : self.unicodeToDatabase(printer.Description or ""),
+                   "description" : unicodeToDatabase(printer.Description or ""),
                    "pykotaPricePerPage" : str(printer.PricePerPage or 0.0),
                    "pykotaPricePerJob" : str(printer.PricePerJob or 0.0),
@@ -916,9 +918,9 @@
         if oldentry.Exists :
             return oldentry # we return the existing entry
-        uname = self.unicodeToDatabase(user.Name)
+        uname = unicodeToDatabase(user.Name)
         newfields = {
                        "pykotaUserName" : uname,
                        "pykotaLimitBy" : (user.LimitBy or "quota"),
-                       "description" : self.unicodeToDatabase(user.Description or ""),
+                       "description" : unicodeToDatabase(user.Description or ""),
                        self.info["usermail"] : user.Email or "",
                     }   
@@ -991,9 +993,9 @@
         if oldentry.Exists :
             return oldentry # we return the existing entry
-        gname = self.unicodeToDatabase(group.Name)
+        gname = unicodeToDatabase(group.Name)
         newfields = { 
                       "pykotaGroupName" : gname,
                       "pykotaLimitBy" : (group.LimitBy or "quota"),
-                      "description" : self.unicodeToDatabase(group.Description or "")
+                      "description" : unicodeToDatabase(group.Description or "")
                     } 
         mustadd = 1
@@ -1040,5 +1042,5 @@
                 if not fields.has_key(self.info["groupmembers"]) :
                     fields[self.info["groupmembers"]] = []
-                fields[self.info["groupmembers"]].append(self.unicodeToDatabase(user.Name))
+                fields[self.info["groupmembers"]].append(unicodeToDatabase(user.Name))
                 self.doModify(group.ident, fields)
                 group.Members.append(user)
@@ -1053,5 +1055,5 @@
                     fields[self.info["groupmembers"]] = []
                 try :    
-                    fields[self.info["groupmembers"]].remove(self.unicodeToDatabase(user.Name))
+                    fields[self.info["groupmembers"]].remove(unicodeToDatabase(user.Name))
                 except ValueError :
                     pass # TODO : Strange, shouldn't it be there ?
@@ -1067,6 +1069,6 @@
             return oldentry # we return the existing entry
         uuid = self.genUUID()
-        uname = self.unicodeToDatabase(upq.User.Name)
-        pname = self.unicodeToDatabase(upq.Printer.Name)
+        uname = unicodeToDatabase(upq.User.Name)
+        pname = unicodeToDatabase(upq.Printer.Name)
         fields = { "cn" : uuid,
                    "objectClass" : ["pykotaObject", "pykotaUserPQuota"],
@@ -1095,6 +1097,6 @@
             return oldentry # we return the existing entry
         uuid = self.genUUID()
-        gname = self.unicodeToDatabase(gpq.Group.Name)
-        pname = self.unicodeToDatabase(gpq.Printer.Name)
+        gname = unicodeToDatabase(gpq.Group.Name)
+        pname = unicodeToDatabase(gpq.Printer.Name)
         fields = { "cn" : uuid,
                    "objectClass" : ["pykotaObject", "pykotaGroupPQuota"],
@@ -1116,5 +1118,5 @@
                    "pykotaPassThrough" : (printer.PassThrough and "t") or "f",
                    "pykotaMaxJobSize" : str(printer.MaxJobSize or 0),
-                   "description" : self.unicodeToDatabase(printer.Description or ""),
+                   "description" : unicodeToDatabase(printer.Description or ""),
                    "pykotaPricePerPage" : str(printer.PricePerPage or 0.0),
                    "pykotaPricePerJob" : str(printer.PricePerJob or 0.0),
@@ -1126,5 +1128,5 @@
         newfields = {
                        "pykotaLimitBy" : (user.LimitBy or "quota"),
-                       "description" : self.unicodeToDatabase(user.Description or ""), 
+                       "description" : unicodeToDatabase(user.Description or ""), 
                        self.info["usermail"] : user.Email or "",
                     }   
@@ -1141,5 +1143,5 @@
         newfields = {
                        "pykotaLimitBy" : (group.LimitBy or "quota"),
-                       "description" : self.unicodeToDatabase(group.Description or ""), 
+                       "description" : unicodeToDatabase(group.Description or ""), 
                     }   
         self.doModify(group.ident, newfields)
@@ -1178,6 +1180,6 @@
         payments = []
         for payment in user.Payments :
-            payments.append("%s # %s # %s" % (payment[0], str(payment[1]), base64.encodestring(self.unicodeToDatabase(payment[2])).strip()))
-        payments.append("%s # %s # %s" % (str(DateTime.now()), str(amount), base64.encodestring(self.unicodeToDatabase(comment)).strip()))
+            payments.append("%s # %s # %s" % (payment[0], str(payment[1]), base64.encodestring(unicodeToDatabase(payment[2])).strip()))
+        payments.append("%s # %s # %s" % (str(DateTime.now()), str(amount), base64.encodestring(unicodeToDatabase(comment)).strip()))
         fields = {
                    "pykotaPayments" : payments,
@@ -1195,6 +1197,6 @@
     def writeJobNew(self, printer, user, jobid, pagecounter, action, jobsize=None, jobprice=None, filename=None, title=None, copies=None, options=None, clienthost=None, jobsizebytes=None, jobmd5sum=None, jobpages=None, jobbilling=None, precomputedsize=None, precomputedprice=None) :
         """Adds a job in a printer's history."""
-        uname = self.unicodeToDatabase(user.Name)
-        pname = self.unicodeToDatabase(printer.Name)
+        uname = unicodeToDatabase(user.Name)
+        pname = unicodeToDatabase(printer.Name)
         if (not self.disablehistory) or (not printer.LastJob.Exists) :
             uuid = self.genUUID()
@@ -1214,13 +1216,13 @@
                    "pykotaPrinterPageCounter" : str(pagecounter),
                    "pykotaAction" : action,
-                   "pykotaFileName" : ((filename is None) and "None") or self.unicodeToDatabase(filename), 
-                   "pykotaTitle" : ((title is None) and "None") or self.unicodeToDatabase(title), 
+                   "pykotaFileName" : ((filename is None) and "None") or unicodeToDatabase(filename), 
+                   "pykotaTitle" : ((title is None) and "None") or unicodeToDatabase(title), 
                    "pykotaCopies" : str(copies), 
-                   "pykotaOptions" : ((options is None) and "None") or self.unicodeToDatabase(options), 
+                   "pykotaOptions" : ((options is None) and "None") or unicodeToDatabase(options), 
                    "pykotaHostName" : str(clienthost), 
                    "pykotaJobSizeBytes" : str(jobsizebytes),
                    "pykotaMD5Sum" : str(jobmd5sum),
                    "pykotaPages" : jobpages,            # don't add this attribute if it is not set, so no string conversion
-                   "pykotaBillingCode" : self.unicodeToDatabase(jobbilling), # don't add this attribute if it is not set, so no string conversion
+                   "pykotaBillingCode" : unicodeToDatabase(jobbilling), # don't add this attribute if it is not set, so no string conversion
                    "pykotaPrecomputedJobSize" : str(precomputedsize),
                    "pykotaPrecomputedJobPrice" : str(precomputedprice),
@@ -1314,13 +1316,13 @@
         where = []
         if user is not None :
-            where.append("(pykotaUserName=%s)" % self.unicodeToDatabase(user.Name))
+            where.append("(pykotaUserName=%s)" % unicodeToDatabase(user.Name))
         if printer is not None :
-            where.append("(pykotaPrinterName=%s)" % self.unicodeToDatabase(printer.Name))
+            where.append("(pykotaPrinterName=%s)" % unicodeToDatabase(printer.Name))
         if hostname is not None :
             where.append("(pykotaHostName=%s)" % hostname)
         if billingcode is not None :
-            where.append("(pykotaBillingCode=%s)" % self.unicodeToDatabase(billingcode))
+            where.append("(pykotaBillingCode=%s)" % unicodeToDatabase(billingcode))
         if jobid is not None :
-            where.append("(pykotaJobId=%s)" % jobid) # TODO : jobid is text, so self.unicodeToDatabase(jobid) but do all of them as well.
+            where.append("(pykotaJobId=%s)" % jobid) # TODO : jobid is text, so unicodeToDatabase(jobid) but do all of them as well.
         if where :    
             where = "(&%s)" % "".join([precond] + where)
@@ -1363,11 +1365,11 @@
                     job.JobPrice = None
                 job.JobAction = fields.get("pykotaAction", [""])[0]
-                job.JobFileName = self.databaseToUnicode(fields.get("pykotaFileName", [""])[0]) 
-                job.JobTitle = self.databaseToUnicode(fields.get("pykotaTitle", [""])[0]) 
+                job.JobFileName = databaseToUnicode(fields.get("pykotaFileName", [""])[0]) 
+                job.JobTitle = databaseToUnicode(fields.get("pykotaTitle", [""])[0]) 
                 job.JobCopies = int(fields.get("pykotaCopies", [0])[0])
-                job.JobOptions = self.databaseToUnicode(fields.get("pykotaOptions", [""])[0]) 
+                job.JobOptions = databaseToUnicode(fields.get("pykotaOptions", [""])[0]) 
                 job.JobHostName = fields.get("pykotaHostName", [""])[0]
                 job.JobSizeBytes = fields.get("pykotaJobSizeBytes", [0L])[0]
-                job.JobBillingCode = self.databaseToUnicode(fields.get("pykotaBillingCode", [None])[0])
+                job.JobBillingCode = databaseToUnicode(fields.get("pykotaBillingCode", [None])[0])
                 job.JobMD5Sum = fields.get("pykotaMD5Sum", [None])[0]
                 job.JobPages = fields.get("pykotaPages", [""])[0]
@@ -1389,6 +1391,6 @@
                    ((end is None) and (job.JobDate >= start)) or \
                    ((job.JobDate >= start) and (job.JobDate <= end)) :
-                    job.UserName = self.databaseToUnicode(fields.get("pykotaUserName")[0])
-                    job.PrinterName = self.databaseToUnicode(fields.get("pykotaPrinterName")[0])
+                    job.UserName = databaseToUnicode(fields.get("pykotaUserName")[0])
+                    job.PrinterName = databaseToUnicode(fields.get("pykotaPrinterName")[0])
                     job.Exists = True
                     jobs.append(job)
@@ -1400,5 +1402,5 @@
     def deleteUser(self, user) :    
         """Completely deletes an user from the Quota Storage."""
-        uname = self.unicodeToDatabase(user.Name)
+        uname = unicodeToDatabase(user.Name)
         todelete = []    
         result = self.doSearch("(&(objectClass=pykotaJob)(pykotaUserName=%s))" % uname, base=self.info["jobbase"])
@@ -1418,5 +1420,5 @@
             # if last job of current printer was printed by the user
             # to delete, we also need to delete the printer's last job entry.
-            printer = self.getPrinter(self.databaseToUnicode(fields["pykotaPrinterName"][0]))
+            printer = self.getPrinter(databaseToUnicode(fields["pykotaPrinterName"][0]))
             if printer.LastJob.UserName == user.Name :
                 todelete.append(printer.LastJob.lastjobident)
@@ -1453,5 +1455,5 @@
     def deleteGroup(self, group) :    
         """Completely deletes a group from the Quota Storage."""
-        gname = self.unicodeToDatabase(group.Name)
+        gname = unicodeToDatabase(group.Name)
         if self.info["groupquotabase"].lower() == "group" :
             base = self.info["groupbase"]
@@ -1524,6 +1526,6 @@
     def deleteUserPQuota(self, upquota) :    
         """Completely deletes an user print quota entry from the database."""
-        uname = self.unicodeToDatabase(upquota.User.Name)
-        pname = self.unicodeToDatabase(upquota.Printer.Name)
+        uname = unicodeToDatabase(upquota.User.Name)
+        pname = unicodeToDatabase(upquota.Printer.Name)
         result = self.doSearch("(&(objectClass=pykotaJob)(pykotaUserName=%s)(pykotaPrinterName=%s))" \
                                    % (uname, pname), \
@@ -1541,5 +1543,5 @@
     def deletePrinter(self, printer) :    
         """Completely deletes a printer from the Quota Storage."""
-        pname = self.unicodeToDatabase(printer.Name)
+        pname = unicodeToDatabase(printer.Name)
         result = self.doSearch("(&(objectClass=pykotaLastJob)(pykotaPrinterName=%s))" % pname, base=self.info["lastjobbase"])
         for (ident, fields) in result :
@@ -1764,5 +1766,5 @@
         """Extracts billing code information given its label : returns first matching billing code."""
         code = StorageBillingCode(self, label)
-        ulabel = self.unicodeToDatabase(label)
+        ulabel = unicodeToDatabase(label)
         result = self.doSearch("(&(objectClass=pykotaBilling)(pykotaBillingCode=%s))" % \
                                   ulabel, \
@@ -1772,8 +1774,8 @@
             fields = result[0][1]       # take only first matching code, ignore the rest
             code.ident = result[0][0]
-            code.BillingCode = self.databaseToUnicode(fields.get("pykotaBillingCode", [ulabel])[0])
+            code.BillingCode = databaseToUnicode(fields.get("pykotaBillingCode", [ulabel])[0])
             code.PageCounter = int(fields.get("pykotaPageCounter", [0])[0])
             code.Balance = float(fields.get("pykotaBalance", [0.0])[0])
-            code.Description = self.databaseToUnicode(fields.get("description", [""])[0]) 
+            code.Description = databaseToUnicode(fields.get("description", [""])[0]) 
             code.Exists = True
         return code    
@@ -1788,8 +1790,8 @@
         fields = { "objectClass" : ["pykotaObject", "pykotaBilling"],
                    "cn" : uuid,
-                   "pykotaBillingCode" : self.unicodeToDatabase(bcode.BillingCode),
+                   "pykotaBillingCode" : unicodeToDatabase(bcode.BillingCode),
                    "pykotaPageCounter" : str(bcode.PageCounter or 0),
                    "pykotaBalance" : str(bcode.Balance or 0.0),
-                   "description" : self.unicodeToDatabase(bcode.Description or ""), 
+                   "description" : unicodeToDatabase(bcode.Description or ""), 
                  } 
         self.doAdd(dn, fields)
@@ -1800,5 +1802,5 @@
         """Sets the new description for a billing code."""
         fields = {
-                   "description" : self.unicodeToDatabase(bcode.Description or ""), 
+                   "description" : unicodeToDatabase(bcode.Description or ""), 
                    "pykotaPageCounter" : str(bcode.PageCounter or 0),
                    "pykotaBalance" : str(bcode.Balance or 0.0),
@@ -1822,5 +1824,5 @@
                     patdict[p] = None
             for (codeid, fields) in result :
-                codename = self.databaseToUnicode(fields.get("pykotaBillingCode", [""])[0])
+                codename = databaseToUnicode(fields.get("pykotaBillingCode", [""])[0])
                 if patdict.has_key(codename) or self.tool.matchString(codename, patterns) :
                     code = StorageBillingCode(self, codename)
@@ -1828,5 +1830,5 @@
                     code.PageCounter = int(fields.get("pykotaPageCounter", [0])[0])
                     code.Balance = float(fields.get("pykotaBalance", [0.0])[0])
-                    code.Description = self.databaseToUnicode(fields.get("description", [""])[0]) 
+                    code.Description = databaseToUnicode(fields.get("description", [""])[0]) 
                     code.Exists = True
                     codes.append(code)
Index: /pykota/trunk/pykota/storages/sqlitestorage.py
===================================================================
--- /pykota/trunk/pykota/storages/sqlitestorage.py (revision 3288)
+++ /pykota/trunk/pykota/storages/sqlitestorage.py (revision 3294)
@@ -35,5 +35,5 @@
     # TODO : to translate or not to translate ?
     raise PyKotaStorageError, "This python version (%s) doesn't seem to have the PySQLite module installed correctly." % sys.version.split()[0]
-
+    
 class Storage(BaseStorage, SQLStorage) :
     def __init__(self, pykotatool, host, dbname, user, passwd) :
@@ -82,5 +82,5 @@
         try :
             before = time.time()
-            self.tool.logdebug("QUERY : %s" % query)
+            self.querydebug("QUERY : %s" % query)
             self.cursor.execute(query)
         except self.database.Error, msg :    
@@ -119,5 +119,5 @@
         try :
             before = time.time()
-            self.tool.logdebug("QUERY : %s" % query)
+            self.querydebug("QUERY : %s" % query)
             self.cursor.execute(query)
         except self.database.Error, msg :    
Index: /pykota/trunk/pykota/utils.py
===================================================================
--- /pykota/trunk/pykota/utils.py (revision 3294)
+++ /pykota/trunk/pykota/utils.py (revision 3294)
@@ -0,0 +1,83 @@
+# -*- coding: UTF-8 -*-
+#
+# PyKota : Print Quotas for CUPS
+#
+# (c) 2003, 2004, 2005, 2006, 2007, 2008 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+# $Id$
+#
+
+"""This module defines some utility functions which make no sense as methods."""
+
+import sys
+import locale
+import gettext
+
+def initlocale(lang="", cset=None) :
+    """Initializes the locale stuff."""
+    try :
+        locale.setlocale(locale.LC_ALL, (lang, cset))
+    except (locale.Error, IOError) :
+        locale.setlocale(locale.LC_ALL, None)
+    (language, charset) = locale.getlocale()
+    language = language or "C"
+    try :
+        charset = charset or locale.getpreferredencoding()
+    except locale.Error :    
+        charset = sys.stdout.encoding or sys.getfilesystemencoding()
+
+    # Dirty hack : if the charset is ASCII, we can safely use UTF-8 instead
+    # This has the advantage of allowing transparent support for recent
+    # versions of CUPS which (en-)force charset to UTF-8 when printing.
+    # This should be needed only when printing, but is probably (?) safe
+    # to do when using interactive commands.
+    if charset.upper() in ('ASCII', 'ANSI_X3.4-1968') :
+        charset = "UTF-8"
+    return (language, charset)
+
+def initgettext(lang, cset) :
+    """Initializes gettext translations for PyKota."""
+    try :
+        try :
+            trans = gettext.translation("pykota", \
+                                        languages=["%s.%s" % (lang, 
+                                                              cset)], 
+                                        codeset=cset)
+        except TypeError : # Python <2.4
+            trans = gettext.translation("pykota", 
+                                        languages=["%s.%s" % (lang, 
+                                                              cset)])
+        trans.install(unicode=True)
+    except :
+        gettext.NullTranslations().install(unicode=True)
+
+def databaseToUnicode(text) :
+    """Converts from database format (UTF-8) to unicode."""
+    if text is not None :
+        return text.decode("UTF-8", "replace")
+    else : 
+        return None
+    
+def unicodeToDatabase(text) :
+    """Converts from unicode to database format (UTF-8)."""
+    if text is not None : 
+        return text.encode("UTF-8", "replace")
+    else :    
+        return None
+            
+def logerr(text) :
+    """Logs an unicode text to stderr."""
+    sys.stderr.write(text.encode(sys.stdout.encoding, "replace"))
+            
Index: /pykota/trunk/pykota/storage.py
===================================================================
--- /pykota/trunk/pykota/storage.py (revision 3291)
+++ /pykota/trunk/pykota/storage.py (revision 3294)
@@ -581,4 +581,8 @@
         self.close()
         
+    def querydebug(self, qmsg) :    
+        """Logs a database query, where all queries are already UTF-8 encoded."""
+        self.tool.logdebug(qmsg.decode("UTF-8", "replace"))
+        
     def getFromCache(self, cachetype, key) :
         """Tries to extract something from the cache."""
@@ -728,18 +732,4 @@
         return gpquotas        
         
-    def databaseToUnicode(self, text) :
-        """Converts from database format (UTF-8) to unicode."""
-        if text is not None :
-            return text.decode("UTF-8", "replace")
-        else : 
-            return None
-        
-    def unicodeToDatabase(self, text) :
-        """Converts from unicode to database format (UTF-8)."""
-        if text is not None : 
-            return text.encode("UTF-8", "replace")
-        else :    
-            return None
-            
     def cleanDates(self, startdate, enddate) :    
         """Clean the dates to create a correct filter."""
Index: /pykota/trunk/pykota/appinit.py
===================================================================
--- /pykota/trunk/pykota/appinit.py (revision 3294)
+++ /pykota/trunk/pykota/appinit.py (revision 3294)
@@ -0,0 +1,33 @@
+# -*- coding: UTF-8 -*-
+#
+# PyKota : Print Quotas for CUPS
+#
+# (c) 2003, 2004, 2005, 2006, 2007, 2008 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+# $Id$
+#
+
+"""This module exectures some application intialization code."""
+
+import sys
+import locale
+import gettext
+
+from pykota.utils import *
+
+(lang, charset) = initlocale()
+initgettext(lang, charset)
+
+sys.argv = [a.decode(charset, "replace") for a in sys.argv]
Index: /pykota/trunk/pykota/tool.py
===================================================================
--- /pykota/trunk/pykota/tool.py (revision 3288)
+++ /pykota/trunk/pykota/tool.py (revision 3294)
@@ -29,5 +29,4 @@
 import getopt
 import smtplib
-import gettext
 import locale
 import socket
@@ -109,34 +108,7 @@
         self.logger = logger.openLogger("stderr")
         
-        # locale stuff
-        try :
-            locale.setlocale(locale.LC_ALL, (lang, charset))
-        except (locale.Error, IOError) :
-            locale.setlocale(locale.LC_ALL, None)
+        # Saves a copy of the locale settings
         (self.language, self.charset) = locale.getlocale()
-        self.language = self.language or "C"
-        try :
-            self.charset = self.charset or locale.getpreferredencoding()
-        except locale.Error :    
-            self.charset = sys.stdout.encoding or sys.getfilesystemencoding()
-        
-        # Dirty hack : if the charset is ASCII, we can safely use UTF-8 instead
-        # This has the advantage of allowing transparent support for recent
-        # versions of CUPS which (en-)force charset to UTF-8 when printing.
-        # This should be needed only when printing, but is probably (?) safe
-        # to do when using interactive commands.
-        if self.charset.upper() in ('ASCII', 'ANSI_X3.4-1968') :
-            self.charset = "UTF-8"
-        
-        # translation stuff
-        try :
-            try :
-                trans = gettext.translation("pykota", languages=["%s.%s" % (self.language, self.charset)], codeset=self.charset)
-            except TypeError : # Python <2.4
-                trans = gettext.translation("pykota", languages=["%s.%s" % (self.language, self.charset)])
-            trans.install(unicode=True)
-        except :
-            gettext.NullTranslations().install(unicode=True)
-    
+        
         # pykota specific stuff
         self.documentation = doc
@@ -362,5 +334,5 @@
                     # and reset the list of arguments to the lines read from
                     # the file.
-                    argsfile = open(parsed["arguments"] or parsed["A"], "r")
+                    argsfile = open(parsed["arguments"] or parsed["A"], "r") # TODO : charset decoding
                     argv = [ l.strip() for l in argsfile.readlines() ]
                     argsfile.close()
Index: /pykota/trunk/bin/edpykota
===================================================================
--- /pykota/trunk/bin/edpykota (revision 3288)
+++ /pykota/trunk/bin/edpykota (revision 3294)
@@ -23,4 +23,7 @@
 
 import sys
+
+import pykota.appinit
+from pykota.utils import *
 
 from pykota.errors import PyKotaCommandLineError
@@ -352,8 +355,8 @@
             retcode = manager.main(args, options)
     except KeyboardInterrupt :        
-        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
+        logerr("\nInterrupted with Ctrl+C !\n")
         retcode = -3
     except PyKotaCommandLineError, msg :     
-        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
+        logerr("%s : %s\n" % (sys.argv[0], msg))
         retcode = -2
     except SystemExit :        
Index: /pykota/trunk/bin/pkinvoice
===================================================================
--- /pykota/trunk/bin/pkinvoice (revision 3288)
+++ /pykota/trunk/bin/pkinvoice (revision 3294)
@@ -43,4 +43,7 @@
 else :    
     hasPIL = True
+
+import pykota.appinit
+from pykota.utils import *
 
 from pykota.errors import PyKotaToolError, PyKotaCommandLineError
@@ -403,8 +406,8 @@
             retcode = invoiceGenerator.main(args, options)
     except KeyboardInterrupt :        
-        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
+        logerr("\nInterrupted with Ctrl+C !\n")
         retcode = -3
     except PyKotaCommandLineError, msg :     
-        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
+        logerr("%s : %s\n" % (sys.argv[0], msg))
         retcode = -2
     except SystemExit :        
Index: /pykota/trunk/bin/pykotme
===================================================================
--- /pykota/trunk/bin/pykotme (revision 3288)
+++ /pykota/trunk/bin/pykotme (revision 3294)
@@ -25,4 +25,7 @@
 import os
 import pwd
+
+import pykota.appinit
+from pykota.utils import *
 
 from pykota.errors import PyKotaCommandLineError
@@ -156,8 +159,8 @@
             retcode = sender.main(args, options)
     except KeyboardInterrupt :        
-        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
+        logerr("\nInterrupted with Ctrl+C !\n")
         retcode = -3
     except PyKotaCommandLineError, msg :    
-        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
+        logerr("%s : %s\n" % (sys.argv[0], msg))
         retcode = -2
     except SystemExit :        
Index: /pykota/trunk/bin/pkbcodes
===================================================================
--- /pykota/trunk/bin/pkbcodes (revision 3288)
+++ /pykota/trunk/bin/pkbcodes (revision 3294)
@@ -25,4 +25,7 @@
 import sys
 import pwd
+
+import pykota.appinit
+from pykota.utils import *
 
 from pykota.errors import PyKotaCommandLineError
@@ -199,8 +202,8 @@
             retcode = manager.main(args, options)
     except KeyboardInterrupt :        
-        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
+        logerr("\nInterrupted with Ctrl+C !\n")
         retcode = -3
     except PyKotaCommandLineError, msg :    
-        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
+        logerr("%s : %s\n" % (sys.argv[0], msg))
         retcode = -2
     except SystemExit :        
Index: /pykota/trunk/bin/pksetup
===================================================================
--- /pykota/trunk/bin/pksetup (revision 3290)
+++ /pykota/trunk/bin/pksetup (revision 3294)
@@ -408,5 +408,5 @@
         homedirectory = self.addPyKotaUser()
         if homedirectory is None :
-            sys.stderr.write("Installation can't proceed. You MUST create a system user named 'pykota'.\n")
+            logerr("Installation can't proceed. You MUST create a system user named 'pykota'.\n")
         else :    
             self.upgradeSystem()
@@ -465,5 +465,5 @@
             installer = globals()[classname]()
         except KeyError :    
-            sys.stderr.write("There's currently no support for the %s distribution, sorry.\n" % sys.argv[1])
+            logerr("There's currently no support for the %s distribution, sorry.\n" % sys.argv[1])
             retcode = -1
         else :    
@@ -471,5 +471,5 @@
                 retcode = installer.setup()
             except KeyboardInterrupt :             
-                sys.stderr.write("\n\n\nWARNING : Setup was aborted at user's request !\n\n")
+                logerr("\n\n\nWARNING : Setup was aborted at user's request !\n\n")
                 retcode = -1
     sys.exit(retcode)
Index: /pykota/trunk/bin/pkturnkey
===================================================================
--- /pykota/trunk/bin/pkturnkey (revision 3288)
+++ /pykota/trunk/bin/pkturnkey (revision 3294)
@@ -29,4 +29,7 @@
 import signal
 
+import pykota.appinit
+from pykota.utils import *
+
 from pykota.errors import PyKotaToolError, PyKotaCommandLineError
 from pykota.tool import Tool, crashed, N_
@@ -226,5 +229,5 @@
                 from pysnmp.proto.api import alpha
             except ImportError :    
-                sys.stderr.write("pysnmp doesn't seem to be installed. SNMP checks will be ignored !\n")
+                logerr("pysnmp doesn't seem to be installed. SNMP checks will be ignored !\n")
                 return 0
         else :        
@@ -528,8 +531,8 @@
             retcode = manager.main(args, options)
     except KeyboardInterrupt :        
-        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
+        logerr("\nInterrupted with Ctrl+C !\n")
         retcode = -3
     except PyKotaCommandLineError, msg :    
-        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
+        logerr("%s : %s\n" % (sys.argv[0], msg))
         retcode = -2
     except SystemExit :        
Index: /pykota/trunk/bin/pkusers
===================================================================
--- /pykota/trunk/bin/pkusers (revision 3288)
+++ /pykota/trunk/bin/pkusers (revision 3294)
@@ -25,4 +25,7 @@
 import pwd
 import grp
+
+import pykota.appinit
+from pykota.utils import *
 
 from pykota.errors import PyKotaCommandLineError
@@ -440,8 +443,8 @@
             retcode = manager.main(args, options)
     except KeyboardInterrupt :        
-        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
+        logerr("\nInterrupted with Ctrl+C !\n")
         retcode = -3
     except PyKotaCommandLineError, msg :    
-        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
+        logerr("%s : %s\n" % (sys.argv[0], msg))
         retcode = -2
     except SystemExit :        
Index: /pykota/trunk/bin/repykota
===================================================================
--- /pykota/trunk/bin/repykota (revision 3288)
+++ /pykota/trunk/bin/repykota (revision 3294)
@@ -27,4 +27,7 @@
 
 from mx import DateTime
+
+import pykota.appinit
+from pykota.utils import *
 
 from pykota.errors import PyKotaToolError, PyKotaCommandLineError
@@ -157,8 +160,8 @@
             retcode = reportTool.main(args, options)
     except KeyboardInterrupt :        
-        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
+        logerr("\nInterrupted with Ctrl+C !\n")
         retcode = -3
     except PyKotaCommandLineError, msg :    
-        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
+        logerr("%s : %s\n" % (sys.argv[0], msg))
         retcode = -2
     except SystemExit :        
Index: /pykota/trunk/bin/warnpykota
===================================================================
--- /pykota/trunk/bin/warnpykota (revision 3288)
+++ /pykota/trunk/bin/warnpykota (revision 3294)
@@ -25,4 +25,7 @@
 import os
 import pwd
+
+import pykota.appinit
+from pykota.utils import *
 
 from pykota.errors import PyKotaCommandLineError
@@ -156,8 +159,8 @@
             retcode = sender.main(args, options)
     except KeyboardInterrupt :        
-        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
+        logerr("\nInterrupted with Ctrl+C !\n")
         retcode = -3
     except PyKotaCommandLineError, msg :    
-        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
+        logerr("%s : %s\n" % (sys.argv[0], msg))
         retcode = -2
     except SystemExit :        
Index: /pykota/trunk/bin/pkbanner
===================================================================
--- /pykota/trunk/bin/pkbanner (revision 3288)
+++ /pykota/trunk/bin/pkbanner (revision 3294)
@@ -44,4 +44,7 @@
     hasPIL = True
     
+import pykota.appinit
+from pykota.utils import *
+
 from pykota.errors import PyKotaToolError, PyKotaCommandLineError
 from pykota.tool import Tool, crashed, N_
@@ -325,8 +328,8 @@
             retcode = banner.main(args, options)
     except KeyboardInterrupt :        
-        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
+        logerr("\nInterrupted with Ctrl+C !\n")
         retcode = -3
     except PyKotaCommandLineError, msg :    
-        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
+        logerr("%s : %s\n" % (sys.argv[0], msg))
         retcode = -2
     except SystemExit :        
Index: /pykota/trunk/bin/autopykota
===================================================================
--- /pykota/trunk/bin/autopykota (revision 3288)
+++ /pykota/trunk/bin/autopykota (revision 3294)
@@ -25,4 +25,7 @@
 import sys
 import os
+
+import pykota.appinit
+from pykota.utils import *
 
 from pykota.errors import PyKotaToolError, PyKotaCommandLineError
@@ -140,8 +143,8 @@
             retcode = automat.main(args, options)
     except KeyboardInterrupt :        
-        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
+        logerr("\nInterrupted with Ctrl+C !\n")
         retcode = -3
     except PyKotaCommandLineError, msg :    
-        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
+        logerr("%s : %s\n" % (sys.argv[0], msg))
         retcode = -2
     except SystemExit :        
Index: /pykota/trunk/bin/pkprinters
===================================================================
--- /pykota/trunk/bin/pkprinters (revision 3288)
+++ /pykota/trunk/bin/pkprinters (revision 3294)
@@ -25,4 +25,7 @@
 import sys
 import pwd
+
+import pykota.appinit
+from pykota.utils import *
 
 from pykota.errors import PyKotaCommandLineError
@@ -372,8 +375,8 @@
             retcode = manager.main(args, options)
     except KeyboardInterrupt :        
-        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
+        logerr("\nInterrupted with Ctrl+C !\n")
         retcode = -3
     except PyKotaCommandLineError, msg :    
-        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
+        logerr("%s : %s\n" % (sys.argv[0], msg))
         retcode = -2
     except SystemExit :        
Index: /pykota/trunk/bin/cupspykota
===================================================================
--- /pykota/trunk/bin/cupspykota (revision 3288)
+++ /pykota/trunk/bin/cupspykota (revision 3294)
@@ -43,4 +43,7 @@
 
 from mx import DateTime
+
+import pykota.appinit
+from pykota.utils import *
 
 from pykota.errors import PyKotaToolError
@@ -1313,5 +1316,5 @@
         sys.exit(0)                
     elif len(sys.argv) not in (6, 7) :    
-        sys.stderr.write("ERROR: %s job-id user title copies options [file]\n"\
+        logerr("ERROR: %s job-id user title copies options [file]\n"\
                               % sys.argv[0])
         sys.exit(1)
Index: /pykota/trunk/bin/pknotify
===================================================================
--- /pykota/trunk/bin/pknotify (revision 3288)
+++ /pykota/trunk/bin/pknotify (revision 3294)
@@ -34,4 +34,7 @@
 else :    
     hasPAM = True
+
+import pykota.appinit
+from pykota.utils import *
 
 from pykota.errors import PyKotaToolError, PyKotaCommandLineError
@@ -354,8 +357,8 @@
             retcode = notifier.main(args, options)
     except KeyboardInterrupt :        
-        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
+        logerr("\nInterrupted with Ctrl+C !\n")
         retcode = -3
     except PyKotaCommandLineError, msg :    
-        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
+        logerr("%s : %s\n" % (sys.argv[0], msg))
         print "CANCEL"  # Forces the cancellation of the print job if a command line switch is incorrect
         retcode = -2
Index: /pykota/trunk/bin/pykosd
===================================================================
--- /pykota/trunk/bin/pykosd (revision 3288)
+++ /pykota/trunk/bin/pykosd (revision 3294)
@@ -30,6 +30,9 @@
     import pyosd
 except ImportError :    
-    sys.stderr.write("Sorry ! You need both xosd and the Python OSD library (pyosd) for this software to work.\n")
+    logerr("Sorry ! You need both xosd and the Python OSD library (pyosd) for this software to work.\n")
     sys.exit(-1)
+
+import pykota.appinit
+from pykota.utils import *
 
 from pykota.errors import PyKotaToolError, PyKotaCommandLineError
@@ -192,8 +195,8 @@
         retcode = 0
     except KeyboardInterrupt :        
-        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
+        logerr("\nInterrupted with Ctrl+C !\n")
         retcode = -3
     except PyKotaCommandLineError, msg :    
-        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
+        logerr("%s : %s\n" % (sys.argv[0], msg))
         retcode = -2
     except SystemExit :        
Index: /pykota/trunk/bin/pkmail
===================================================================
--- /pykota/trunk/bin/pkmail (revision 3288)
+++ /pykota/trunk/bin/pkmail (revision 3294)
@@ -30,4 +30,7 @@
 from email.Header import Header
 import email.Utils
+
+import pykota.appinit
+from pykota.utils import *
 
 from pykota.errors import PyKotaCommandLineError
@@ -164,8 +167,8 @@
             retcode = mailparser.main(args, options)
     except KeyboardInterrupt :        
-        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
+        logerr("\nInterrupted with Ctrl+C !\n")
         retcode = -3
     except PyKotaCommandLineError, msg :    
-        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
+        logerr("%s : %s\n" % (sys.argv[0], msg))
         retcode = -2
     except SystemExit :        
Index: /pykota/trunk/bin/dumpykota
===================================================================
--- /pykota/trunk/bin/dumpykota (revision 3288)
+++ /pykota/trunk/bin/dumpykota (revision 3294)
@@ -23,4 +23,7 @@
 
 import sys
+
+import pykota.appinit
+from pykota.utils import *
 
 from pykota.errors import PyKotaCommandLineError
@@ -183,8 +186,8 @@
             retcode = dumper.main(args, options)
     except KeyboardInterrupt :        
-        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
+        logerr("\nInterrupted with Ctrl+C !\n")
         retcode = -3
     except PyKotaCommandLineError, msg :    
-        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
+        logerr("%s : %s\n" % (sys.argv[0], msg))
         retcode = -2
     except SystemExit :        
Index: /pykota/trunk/bin/pkrefund
===================================================================
--- /pykota/trunk/bin/pkrefund (revision 3288)
+++ /pykota/trunk/bin/pkrefund (revision 3294)
@@ -43,4 +43,7 @@
 else :    
     hasPIL = True
+
+import pykota.appinit
+from pykota.utils import *
 
 from pykota.errors import PyKotaToolError, PyKotaCommandLineError
@@ -440,8 +443,8 @@
             retcode = refundmanager.main(args, options)
     except KeyboardInterrupt :        
-        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
+        logerr("\nInterrupted with Ctrl+C !\n")
         retcode = -3
     except PyKotaCommandLineError, msg :    
-        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
+        logerr("%s : %s\n" % (sys.argv[0], msg))
         retcode = -2
     except SystemExit :        
