#!/usr/bin/python
# -*- coding: ISO-8859-15 -*-

# PyKota Print Quota Data Dumper
#
# PyKota - Print Quotas for CUPS and LPRng
#
# (c) 2003-2004 Jerome Alet <alet@librelogiciel.com>
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
#
# $Id: dumpykota,v 1.15 2004/10/12 15:37:00 jalet Exp $
#
# $Log: dumpykota,v $
# Revision 1.15  2004/10/12 15:37:00  jalet
# Now outputs the name of the offending user if a mere mortal tries to use
# one of these commands !!!
#
# Revision 1.14  2004/10/11 22:53:05  jalet
# Postponed string interpolation to help message's output method
#
# Revision 1.13  2004/10/11 12:49:06  jalet
# Renders help translatable
#
# Revision 1.12  2004/10/07 21:14:28  jalet
# Hopefully final fix for data encoding to and from the database
#
# Revision 1.11  2004/10/07 14:35:40  jalet
# Now edpykota refuses to launch if the user is not a PyKota administrator.
# dumpykota : now has the same error message than edpykota in this case.
#
# Revision 1.10  2004/10/06 10:05:47  jalet
# Minor changes to allow any PyKota administrator to launch enhanced versions
# of the commands, and not only the root user.
#
# Revision 1.9  2004/10/05 20:08:46  jalet
# Misleading help message. Thx to Johannes Laemmermann.
#
# Revision 1.8  2004/10/05 09:59:19  jalet
# Restore compatibility with Python 2.1
#
# Revision 1.7  2004/10/04 21:25:29  jalet
# dumpykota can now output datas in the XML format
#
# Revision 1.6  2004/09/15 18:28:41  jalet
# Updated help for dumpykota
#
# Revision 1.5  2004/09/15 07:38:05  jalet
# Fix for uninitialized variable
#
# Revision 1.4  2004/09/15 07:26:19  jalet
# Data dumps are now ordered by entry creation date if applicable.
# Now dumpykota exits with a message when there's a broken pipe like
# in dumpykota --data history | head -3
#
# Revision 1.3  2004/09/15 06:58:25  jalet
# User groups membership and printer groups membership can now be dumped too
#
# Revision 1.2  2004/09/14 22:29:12  jalet
# First version of dumpykota. Works fine but only with PostgreSQL backend
# for now.
#
# Revision 1.1  2004/07/01 19:22:37  jalet
# First draft of dumpykota
#
#
#

import sys
import os
import pwd

try :
    import jaxml
except ImportError :    
    sys.stderr.write("The jaxml Python module is not installed. XML output is disabled.\n")
    sys.stderr.write("Download jaxml from http://www.librelogiciel.com/software/ or from your Debian archive of choice\n")
    hasJAXML = 0
else :    
    hasJAXML = 1

from pykota import version
from pykota.tool import PyKotaTool, PyKotaToolError, crashed, N_
from pykota.config import PyKotaConfigError
from pykota.storage import PyKotaStorageError

__doc__ = N_("""dumpykota v%s (c) 2003-2004 C@LL - Conseil Internet & Logiciels Libres

Dumps PyKota database's content.

command line usage :

  dumpykota [options] 

options :

  -v | --version       Prints dumpykota's version number then exits.
  -h | --help          Prints this message then exits.
  
  -d | --data type     Dumps 'type' datas. Allowed types are :
                       
                         - history : dumps the jobs history.
                         - users : dumps users.
                         - groups : dumps user groups.
                         - printers : dump printers.
                         - upquotas : dump user quotas.
                         - gpquotas : dump user groups quotas.
                         - payments : dumps user payments.
                         - pmembers : dumps printer groups members.
                         - umembers : dumps user groups members.
                         
                       NB : the -d | --data command line option   
                       is MANDATORY.
  
  -f | --format fmt    Dumps datas in the 'fmt' format. When not specified,
                       the format is to dump datas in the csv format (comma
                       separated values). All data dumped is between double
                       quotes. Allowed formats are :
                       
                         - csv : separate datas with commas
                         - ssv : separate datas with semicolons
                         - tsv : separate datas with tabs
                         - xml : dump data as XML
                         
  -o | --output fname  All datas will be dumped to the file instead of
                       to the standard output. The special '-' filename
                       is the default value and means stdout.
                       WARNING : existing files are truncated !
  
Examples :

  $ dumpykota --data history --format csv >myfile.csv
  
  This dumps the history in a comma separated values file, for possible
  use in a spreadsheet.
  
  $ dumpykota --data users --format xml -o users.xml
  
  Dumps all users datas to the users.xml file.
  
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.

Please e-mail bugs to: %s""")
        
class DumPyKota(PyKotaTool) :        
    """A class for dumpykota."""
    def main(self, arguments, options) :
        """Print Quota Data Dumper."""
        if not self.config.isAdmin :
            raise PyKotaToolError, "%s : %s" % (pwd.getpwuid(os.geteuid())[0], _("You're not allowed to use this command."))
            
        datatype = options["data"]
        if datatype not in [ "history",
                             "users",
                             "groups",
                             "printers",
                             "upquotas",
                             "gpquotas",
                             "payments",
                             "pmembers",
                             "umembers",
                           ] :
            raise PyKotaToolError, _("Invalid modifier [%s] for --data command line option, see help.") % datatype
                    
        format = options["format"]
        if format not in [ "csv",
                           "ssv",
                           "tsv",
                           "xml",
                         ] :
            raise PyKotaToolError, _("Invalid modifier [%s] for --format command line option, see help.") % datatype
            
        if (format == "xml") and not hasJAXML :
            raise PyKotaToolError, _("XML output is disabled because the jaxml module is not available.")
            
        entries = getattr(self.storage, "extract%s" % datatype.title())()    
        if entries :
            mustclose = 0    
            if options["output"].strip() == "-" :    
                self.outfile = sys.stdout
            else :    
                self.outfile = open(options["output"], "w")
                mustclose = 1
                
            retcode = getattr(self, "dump%s" % format.title())(entries, datatype)
            
            if mustclose :
                self.outfile.close()
                
            return retcode    
        return 0
        
    def dumpWithSeparator(self, separator, entries) :    
        """Dumps datas with a separator."""
        for entry in entries :
            line = separator.join([ '"%s"' % field for field in entry ])
            try :
                self.outfile.write("%s\n" % line)
            except IOError, msg :    
                sys.stderr.write("%s : %s\n" % (_("PyKota data dumper failed : I/O error"), msg))
                return -1
        return 0        
        
    def dumpCsv(self, entries, dummy) :    
        """Dumps datas with a comma as the separator."""
        return self.dumpWithSeparator(",", entries)
                           
    def dumpSsv(self, entries, dummy) :    
        """Dumps datas with a comma as the separator."""
        return self.dumpWithSeparator(";", entries)
                           
    def dumpTsv(self, entries, dummy) :    
        """Dumps datas with a comma as the separator."""
        return self.dumpWithSeparator("\t", entries)
        
    def dumpXml(self, entries, datatype) :    
        """Dumps datas as XML."""
        x = jaxml.XML_document(encoding="UTF-8")
        x.pykota(version=version.__version__, author=version.__author__)
        x.dump(storage=self.config.getStorageBackend()["storagebackend"], type=datatype)
        headers = entries[0]
        for entry in entries[1:] :
            x._push()
            x.entry()
            for i in range(len(entry)) :
                value = str(entry[i])
                try :
                    value = unicode(value, self.getCharset()).encode("UTF-8")
                except UnicodeError :    
                    pass
                x.attribute(value, type=type(value).__name__, name=headers[i])
            x._pop()    
        x._output(self.outfile)
                           
if __name__ == "__main__" : 
    retcode = 0
    try :
        defaults = { \
                     "format" : "csv", \
                     "output" : "-", \
                   }
        short_options = "vhd:f:o:"
        long_options = ["help", "version", "data=", "format=", "output="]
        
        # Initializes the command line tool
        dumper = DumPyKota(doc=__doc__)
        
        # parse and checks the command line
        (options, args) = dumper.parseCommandline(sys.argv[1:], short_options, long_options, allownothing=1)
        
        # sets long options
        options["help"] = options["h"] or options["help"]
        options["version"] = options["v"] or options["version"]
        options["data"] = options["d"] or options["data"]
        options["format"] = options["f"] or options["format"] or defaults["format"]
        options["output"] = options["o"] or options["output"] or defaults["output"]
        
        if options["help"] :
            dumper.display_usage_and_quit()
        elif options["version"] :
            dumper.display_version_and_quit()
        elif options["data"] is None :    
            raise PyKotaToolError, _("The -d | --data command line option is mandatory, see help.")
        else :
            if args :
                raise PyKotaToolError, _("Too many arguments, see help.")
            retcode = dumper.main(args, options)
    except SystemExit :        
        pass
    except :
        try :
            dumper.crashed("dumpykota failed")
        except :    
            crashed("dumpykota failed")
        retcode = -1

    try :
        dumper.storage.close()
    except (TypeError, NameError, AttributeError) :    
        pass
        
    sys.exit(retcode)    
