Index: pykota/trunk/conf/pykota.conf.sample
===================================================================
--- pykota/trunk/conf/pykota.conf.sample (revision 3285)
+++ pykota/trunk/conf/pykota.conf.sample (revision 3296)
@@ -50,5 +50,11 @@
 [global]
 
-
+# This directive configures the charset to use when reading PyKota's 
+# configuration files. All directives values will be decoded and
+# interpreted using the character set defined here.
+# This value can only be present in the [global] section.
+#
+# When not set, the default value 'UTF-8' is used.
+config_charset : UTF-8
 
 ####################################################################
Index: pykota/trunk/pykota/config.py
===================================================================
--- pykota/trunk/pykota/config.py (revision 3288)
+++ pykota/trunk/pykota/config.py (revision 3296)
@@ -45,4 +45,10 @@
         self.config = ConfigParser.ConfigParser()
         self.config.read([self.filename])
+        try :
+            self.config_charset = self.config.get("global", \
+                                                  "config_charset", \
+                                                   raw=1)
+        except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) :
+            self.config_charset = "UTF-8"
             
     def isTrue(self, option) :        
@@ -64,8 +70,8 @@
         return [pname for pname in self.config.sections() if pname != "global"]
         
-    def getGlobalOption(self, option, ignore=0) :    
+    def getGlobalOption(self, option, ignore=False) :    
         """Returns an option from the global section, or raises a PyKotaConfigError if ignore is not set, else returns None."""
         try :
-            return self.config.get("global", option, raw=1)
+            return self.config.get("global", option, raw=1).decode(self.config_charset)
         except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) :    
             if ignore :
@@ -76,7 +82,7 @@
     def getPrinterOption(self, printername, option) :    
         """Returns an option from the printer section, or the global section, or raises a PyKotaConfigError."""
-        globaloption = self.getGlobalOption(option, ignore=1)
-        try :
-            return self.config.get(printername, option, raw=1)
+        globaloption = self.getGlobalOption(option, ignore=True)
+        try :
+            return self.config.get(printername, option, raw=1).decode(self.config_charset)
         except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) :    
             if globaloption is not None :
@@ -99,5 +105,5 @@
             for option in ["storageserver", "storagename", "storageuser"] :
                 backendinfo[option] = self.getGlobalOption(option)
-            backendinfo["storageuserpw"] = self.getGlobalOption("storageuserpw", ignore=1)  # password is optional
+            backendinfo["storageuserpw"] = self.getGlobalOption("storageuserpw", ignore=True)  # password is optional
             
         backendinfo["storageadmin"] = None
@@ -108,10 +114,10 @@
             if adminconf.sections() : # were we able to read the file ?
                 try :
-                    backendinfo["storageadmin"] = adminconf.get("global", "storageadmin", raw=1)
+                    backendinfo["storageadmin"] = adminconf.get("global", "storageadmin", raw=1).decode(self.config_charset)
                 except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) :    
                     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)
+                    backendinfo["storageadminpw"] = adminconf.get("global", "storageadminpw", raw=1).decode(self.config_charset)
                 except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) :    
                     pass # Password is optional
@@ -120,13 +126,13 @@
                 # server directly and users to use the replicas transparently.
                 try :
-                    backendinfo["storagebackend"] = adminconf.get("global", "storagebackend", raw=1)
+                    backendinfo["storagebackend"] = adminconf.get("global", "storagebackend", raw=1).decode(self.config_charset)
                 except ConfigParser.NoOptionError :
                     pass
                 try :
-                    backendinfo["storageserver"] = adminconf.get("global", "storageserver", raw=1)
+                    backendinfo["storageserver"] = adminconf.get("global", "storageserver", raw=1).decode(self.config_charset)
                 except ConfigParser.NoOptionError :
                     pass
                 try :
-                    backendinfo["storagename"] = adminconf.get("global", "storagename", raw=1)
+                    backendinfo["storagename"] = adminconf.get("global", "storagename", raw=1).decode(self.config_charset)
                 except ConfigParser.NoOptionError :
                     pass
@@ -151,6 +157,6 @@
                 
         # should we use TLS, by default (if unset) value is NO        
-        ldapinfo["ldaptls"] = self.isTrue(self.getGlobalOption("ldaptls", ignore=1))
-        ldapinfo["cacert"] = self.getGlobalOption("cacert", ignore=1)
+        ldapinfo["ldaptls"] = self.isTrue(self.getGlobalOption("ldaptls", ignore=True))
+        ldapinfo["cacert"] = self.getGlobalOption("cacert", ignore=True)
         if ldapinfo["cacert"] :
             ldapinfo["cacert"] = ldapinfo["cacert"].strip()
@@ -173,5 +179,5 @@
     def getLogoURL(self) :
         """Returns the URL to use for the logo in the CGI scripts."""
-        url = self.getGlobalOption("logourl", ignore=1) or \
+        url = self.getGlobalOption("logourl", ignore=True) or \
                    "http://www.pykota.com/pykota.png"
         return url.strip()           
@@ -179,5 +185,5 @@
     def getLogoLink(self) :
         """Returns the URL to go to when the user clicks on the logo in the CGI scripts."""
-        url = self.getGlobalOption("logolink", ignore=1) or \
+        url = self.getGlobalOption("logolink", ignore=True) or \
                    "http://www.pykota.com/"
         return url.strip()           
@@ -496,25 +502,25 @@
     def getPrivacy(self) :        
         """Returns True if privacy is activated, else False."""
-        return self.isTrue(self.getGlobalOption("privacy", ignore=1))
+        return self.isTrue(self.getGlobalOption("privacy", ignore=True))
         
     def getDebug(self) :          
         """Returns True if debugging is activated, else False."""
-        return self.isTrue(self.getGlobalOption("debug", ignore=1))
+        return self.isTrue(self.getGlobalOption("debug", ignore=True))
             
     def getCaching(self) :          
         """Returns True if database caching is enabled, else False."""
-        return self.isTrue(self.getGlobalOption("storagecaching", ignore=1))
+        return self.isTrue(self.getGlobalOption("storagecaching", ignore=True))
             
     def getLDAPCache(self) :          
         """Returns True if low-level LDAP caching is enabled, else False."""
-        return self.isTrue(self.getGlobalOption("ldapcache", ignore=1))
+        return self.isTrue(self.getGlobalOption("ldapcache", ignore=True))
             
     def getDisableHistory(self) :          
         """Returns True if we want to disable history, else False."""
-        return self.isTrue(self.getGlobalOption("disablehistory", ignore=1))
+        return self.isTrue(self.getGlobalOption("disablehistory", ignore=True))
             
     def getUserNameToLower(self) :          
         """Deprecated."""
-        return self.getGlobalOption("utolower", ignore=1)
+        return self.getGlobalOption("utolower", ignore=True)
         
     def getUserNameCase(self) :
@@ -522,5 +528,5 @@
         validvalues = [ "upper", "lower", "native" ]
         try :
-            value = self.getGlobalOption("usernamecase", ignore=1).strip().lower()
+            value = self.getGlobalOption("usernamecase", ignore=True).strip().lower()
         except AttributeError :    
             value = "native"
@@ -531,5 +537,5 @@
     def getRejectUnknown(self) :          
         """Returns True if we want to reject the creation of unknown users or groups, else False."""
-        return self.isTrue(self.getGlobalOption("reject_unknown", ignore=1))
+        return self.isTrue(self.getGlobalOption("reject_unknown", ignore=True))
         
     def getPrinterKeepFiles(self, printername) :          
@@ -645,5 +651,5 @@
     def getWinbindSeparator(self) :          
         """Returns the winbind separator's value if it is set, else None."""
-        return self.getGlobalOption("winbind_separator", ignore=1)
+        return self.getGlobalOption("winbind_separator", ignore=True)
 
     def getAccountBanner(self, printername) :
@@ -721,9 +727,9 @@
         branchbasename = "coefficient_"
         try :
-            globalbranches = [ (k, self.config.get("global", k)) for k in self.config.options("global") if k.startswith(branchbasename) ]
+            globalbranches = [ (k, self.config.get("global", k).decode(self.config_charset)) for k in self.config.options("global") if k.startswith(branchbasename) ]
         except ConfigParser.NoSectionError, msg :
             raise PyKotaConfigError, "Invalid configuration file : %s" % msg
         try :
-            sectionbranches = [ (k, self.config.get(printername, k)) for k in self.config.options(printername) if k.startswith(branchbasename) ]
+            sectionbranches = [ (k, self.config.get(printername, k).decode(self.config_charset)) for k in self.config.options(printername) if k.startswith(branchbasename) ]
         except ConfigParser.NoSectionError, msg :
             sectionbranches = []
