Changeset 1240

Show
Ignore:
Timestamp:
12/27/03 17:49:25 (21 years ago)
Author:
uid67467
Message:

Should be ok now.

Location:
pykota/trunk
Files:
31 modified

Legend:

Unmodified
Added
Removed
  • pykota/trunk/bin/cupspykota

    r1222 r1240  
    2424# 
    2525# $Log$ 
     26# Revision 1.17  2003/12/27 16:49:25  uid67467 
     27# Should be ok now. 
     28# 
     29# Revision 1.17  2003/12/06 08:54:29  jalet 
     30# Code simplifications. 
     31# Added many debugging messages. 
     32# 
    2633# Revision 1.16  2003/11/26 20:43:29  jalet 
    2734# Inadvertantly introduced a bug, which is fixed. 
     
    8491import os 
    8592import popen2 
    86 import time 
    8793import cStringIO 
    8894import shlex 
     
    187193        if user.Exists : 
    188194            # Is the current user allowed to print at all ? 
     195            thebackend.logdebug("Checking user %s's quota on printer %s" % (user.Name, printer.Name)) 
    189196            action = thebackend.warnUserPQuota(thebackend.storage.getUserPQuota(user, printer)) 
    190197        elif policy == "EXTERNAL" :                 
     
    203210        # pass the job untouched to the underlying layer 
    204211        # and starts accounting at the same time 
     212        thebackend.logdebug("Job accounting begins.") 
    205213        thebackend.accounter.beginJob(printer, user) 
    206214         
     
    222230         
    223231        # And launch it 
     232        thebackend.logdebug("Starting real backend %s with args %s" % (realbackend, " ".join([os.environ["DEVICE_URI"]] + sys.argv[1:]))) 
    224233        subprocess = PyKotaPopen3([realbackend] + sys.argv[1:], capturestderr=1, bufsize=0, arg0=os.environ["DEVICE_URI"]) 
    225234         
     
    248257        endinput = 0 
    249258        status = -1 
     259        inputclosed = 0 
     260        thebackend.logdebug("Entering streams polling loop...") 
    250261        while status == -1 : 
    251262            # First check if original backend is still alive 
     
    263274            availablefds = pollster.poll() 
    264275            for (fd, mask) in availablefds : 
     276                # thebackend.logdebug("file: %i    mask: %04x" % (fd, mask)) 
    265277                if mask & select.POLLOUT : 
    266278                    # We can write 
     
    303315                        # standard output 
    304316                        if outdata :                 
    305                             try : 
    306                                 os.write(stdoutfno, outdata) 
    307                                 outdata = "" 
    308                             except :     
    309                                 pass 
    310                         try :         
    311                             pollster.unregister(fromcfno)         
    312                         except KeyError :     
    313                             pass 
    314                         else :     
    315                             os.close(fromcfno) 
     317                            os.write(stdoutfno, outdata) 
     318                            outdata = "" 
     319                        # We are no more interested in this file descriptor         
     320                        pollster.unregister(fromcfno)         
     321                        os.close(fromcfno) 
     322                        thebackend.logdebug("Real backend's stdout ends.") 
    316323                    elif fd == cerrfno :     
    317324                        # Original CUPS backend has finished  
     
    319326                        if errdata :                 
    320327                            # Try to write remaining info (normally "Ready to print.") 
    321                             try : 
    322                                 os.write(stderrfno, errdata) 
    323                                 errdata = "" 
    324                             except :     
    325                                 pass 
     328                            os.write(stderrfno, errdata) 
     329                            errdata = "" 
    326330                        # We are no more interested in this file descriptor         
    327                         try :         
    328                             pollster.unregister(cerrfno)         
    329                         except KeyError :     
    330                             pass 
    331                         else :     
    332                             os.close(cerrfno) 
     331                        pollster.unregister(cerrfno)         
     332                        os.close(cerrfno) 
     333                        thebackend.logdebug("Real backend's stderr ends.") 
    333334                         
    334             if endinput :             
     335            if endinput and not inputclosed :             
    335336                # We deal with remaining input datas here 
    336337                # because EOF can happen in two different 
     
    338339                # code, nor making functions. 
    339340                if indata :                 
    340                     try : 
    341                         os.write(tocfno, indata) 
    342                         indata = "" 
    343                     except :     
    344                         pass 
    345                 # Again, we're not interested in this file descriptor         
    346                 # anymore. 
    347                 try :         
    348                     pollster.unregister(tocfno)         
    349                 except KeyError :     
    350                     pass 
    351                 else :     
    352                     os.close(tocfno) 
     341                    os.write(tocfno, indata) 
     342                    indata = "" 
     343                # Again, we're not interested in this file descriptor anymore. 
     344                pollster.unregister(tocfno)         
     345                os.close(tocfno) 
     346                inputclosed = 1 
     347                thebackend.logdebug("Input data ends.") 
    353348                 
    354349        # Input file was a real file, we have to close it.     
    355350        if mustclose : 
    356351            infile.close() 
     352             
     353        thebackend.logdebug("Exiting streams polling loop...") 
    357354             
    358355        # Check exit code of original CUPS backend.     
     
    365362    # stops accounting.  
    366363    thebackend.accounter.endJob(printer, user) 
     364    thebackend.logdebug("Job accounting ends.") 
    367365         
    368366    # retrieve the job size     
    369367    jobsize = thebackend.accounter.getJobSize() 
     368    thebackend.logdebug("Job size : %i" % jobsize) 
    370369     
    371370    # update the quota for the current user on this printer  
     
    374373        userquota = thebackend.storage.getUserPQuota(user, printer) 
    375374        if userquota.Exists : 
     375            thebackend.logdebug("Updating user %s's quota on printer %s" % (user.Name, printer.Name)) 
    376376            userquota.increasePagesUsage(jobsize) 
    377377     
    378378    # adds the current job to history     
    379379    printer.addJobToHistory(thebackend.jobid, user, thebackend.accounter.getLastPageCounter(), action, jobsize, jobprice, thebackend.preserveinputfile, thebackend.title, thebackend.copies, thebackend.options) 
     380    thebackend.logdebug("Job added to history.") 
    380381     
    381382    return retcode # return (retcode or gotSigTerm) shouldn't be needed 
  • pykota/trunk/bin/pykota

    r1221 r1240  
    2424# 
    2525# $Log$ 
     26# Revision 1.48  2003/12/27 16:49:25  uid67467 
     27# Should be ok now. 
     28# 
    2629# Revision 1.47  2003/11/26 19:17:35  jalet 
    2730# Printing on a printer not present in the Quota Storage now results 
     
    274277        if user.Exists : 
    275278            # Now does the accounting and act depending on the result 
     279            thefilter.logdebug("Does accounting for user %s on printer %s." % (user.Name, printer.Name)) 
    276280            action = thefilter.accounter.doAccounting(printer, user) 
    277281         
     
    279283            if action == "DENY" : 
    280284                # No, just die cleanly 
     285                thefilter.logdebug("Printing is denied.") 
    281286                return thefilter.removeJob() 
    282287        elif policy == "EXTERNAL" :                 
     
    285290         
    286291        # pass the job untouched to the underlying layer 
     292        thefilter.logdebug("Passing input data to next filter.") 
    287293        thefilter.accounter.filterInput(thefilter.inputfile)       
    288294     
  • pykota/trunk/bin/waitprinter.sh

    r1096 r1240  
    1414# $Id$ 
    1515# 
    16  
     16# Fix by Matt Hyclak : 
     17sleep 3  
     18# 
    1719until snmpget -v1 -c public -Ov $1 HOST-RESOURCES-MIB::hrPrinterStatus.1 | grep -i idle >/dev/null ; do  
    1820   sleep 1 ;  
  • pykota/trunk/cgi-bin/printquota.cgi

    r1239 r1240  
    1 #! /usr/bin/python2.2 
     1#! /usr/bin/python 
    22 
    33# PyKota Print Quota Reports generator 
     
    2323# 
    2424# $Log$ 
    25 # Revision 1.17  2003/12/27 15:43:36  uid67467 
    26 # Savannah is back online... 
     25# Revision 1.18  2003/12/27 16:49:25  uid67467 
     26# Should be ok now. 
    2727# 
    2828# Revision 1.16  2003/12/02 14:40:20  jalet 
  • pykota/trunk/conf/pykota.conf.sample

    r1233 r1240  
    129129# logs. 
    130130# Actually only database queries are logged. 
    131 debug : No 
     131debug : Yes 
    132132 
    133133# Mail server to use to warn users 
     
    236236#   NB : I use ISO-8859-15, but Windows expects UTF-8, so we pipe the message 
    237237#        into iconv before sending it to the Windows user. 
     238# 
     239# or more simply : 
     240# 
     241#       mailto: external(/usr/bin/mailandpopup.sh %(username)s %(printername)s "%(email)s" "%(message)s" 2>&1 >/dev/null) 
     242# 
     243#   NB : The mailandpopup.sh shell script is now included in PyKota 
    238244# 
    239245#   NB : in ANY case, don't forget to redirect your command's standard output 
     
    344350# 
    345351# 
     352# An example using the contributed pagecount.pl script which does  
     353# the same as above, but should work on more printers :  
     354# 
     355# requester: external(/usr/bin/pagecount.pl %(printer)s 9100) 
     356# 
     357# 
    346358# WARNING : In any case, when using an external requester, please test the command line outside 
    347359#           of PyKota before. This will save you some headaches in case it doesn't work as expected. 
  • pykota/trunk/CREDITS

    r1237 r1240  
    6060    - Stephen Markan - Faculty of Environmental Studies, University of Waterloo 
    6161    - Jeremy Worth - University of Oxford 
     62    - Roger Morgan - H�e Technische Bundeslehranstalt Steyr 
     63    - Pal Monstad 
     64    - Richard Potter 
    6265 
    6366Contributors : 
     
    6770   
    6871    - Jo�Collet : PyKota's logo 
    69     - Stefan Wold - Stockholm University : code 
     72    - Stefan Wold - Stockholm University : inital code for external policies 
    7073    - John Flynn - University of Belize : LDAP support 
    7174    - Wayne Godoy - University of Belize : LDAP support 
     
    7881    - Daniel Mikkelsen : Sample configuration file fix 
    7982    - Carlos Fernandes : Portugues translation 
     83    - Ren�und Jensen : Contributed the pagecount.pl script 
    8084 
    8185============================================================== 
  • pykota/trunk/initscripts/ldap/pykota.schema

    r1223 r1240  
    189189        DESC 'PyKota Printer' 
    190190        MUST ( cn ) 
    191         MAY  ( pykotaPrinterName $ pykotaPricePerPage $ pykotaPricePerJob ) ) 
     191        MAY  ( pykotaPrinterName $ pykotaPricePerPage $ pykotaPricePerJob $ uniqueMember ) ) 
    192192         
    193193# pykotaUserPQuota         
  • pykota/trunk/initscripts/postgresql/pykota-postgresql.sql

    r1203 r1240  
    2020-- 
    2121-- $Log$ 
     22-- Revision 1.7  2003/12/27 16:49:25  uid67467 
     23-- Should be ok now. 
     24-- 
    2225-- Revision 1.6  2003/11/23 19:01:36  jalet 
    2326-- Job price added to history 
     
    110113CREATE TABLE jobhistory(id SERIAL PRIMARY KEY NOT NULL, 
    111114                        jobid TEXT, 
    112                         userid INT4 REFERENCES users(id), 
    113                         printerid INT4 REFERENCES printers(id), 
     115                        userid INT4, 
     116                        printerid INT4, 
    114117                        pagecounter INT4 DEFAULT 0, 
    115118                        jobsize INT4, 
     
    120123                        copies INT4, 
    121124                        options TEXT, 
    122                         jobdate TIMESTAMP DEFAULT now()); 
     125                        jobdate TIMESTAMP DEFAULT now(), 
     126                        CONSTRAINT checkUserPQuota FOREIGN KEY (userid, printerid) REFERENCES userpquota(userid, printerid)); 
    123127CREATE INDEX jobhistory_p_id_ix ON jobhistory (printerid); 
    124128CREATE INDEX jobhistory_pd_id_ix ON jobhistory (printerid, jobdate); 
     
    141145                           userid INT4 REFERENCES users(id), 
    142146                           PRIMARY KEY (groupid, userid)); 
     147                            
     148--                          
     149-- Create the printer groups relationship 
     150-- 
     151CREATE TABLE printergroupsmembers(groupid INT4 REFERENCES printers(id), 
     152                           printerid INT4 REFERENCES printers(id), 
     153                           PRIMARY KEY (groupid, printerid)); 
    143154 
    144155--                         
    145156-- Set some ACLs                         
    146157-- 
    147 REVOKE ALL ON users, groups, printers, userpquota, grouppquota, groupsmembers, jobhistory FROM public;                         
     158REVOKE ALL ON users, groups, printers, userpquota, grouppquota, groupsmembers, printergroupsmembers, jobhistory FROM public;                         
    148159REVOKE ALL ON users_id_seq, groups_id_seq, printers_id_seq, userpquota_id_seq, grouppquota_id_seq, jobhistory_id_seq FROM public; 
    149160 
    150 GRANT SELECT, INSERT, UPDATE, DELETE, REFERENCES ON users, groups, printers, userpquota, grouppquota, groupsmembers, jobhistory TO pykotaadmin; 
     161GRANT SELECT, INSERT, UPDATE, DELETE, REFERENCES ON users, groups, printers, userpquota, grouppquota, groupsmembers, printergroupsmembers, jobhistory TO pykotaadmin; 
    151162GRANT SELECT, UPDATE ON users_id_seq, groups_id_seq, printers_id_seq, userpquota_id_seq, grouppquota_id_seq, jobhistory_id_seq TO pykotaadmin; 
    152 GRANT SELECT ON users, groups, printers, userpquota, grouppquota, groupsmembers, jobhistory TO pykotauser; 
     163GRANT SELECT ON users, groups, printers, userpquota, grouppquota, groupsmembers, printergroupsmembers, jobhistory TO pykotauser; 
    153164 
  • pykota/trunk/initscripts/postgresql/upgrade-to-1.16.sql

    r1203 r1240  
    2020-- 
    2121-- $Log$ 
     22-- Revision 1.3  2003/12/27 16:49:25  uid67467 
     23-- Should be ok now. 
     24-- 
    2225-- Revision 1.2  2003/11/23 19:01:36  jalet 
    2326-- Job price added to history 
     
    4851ALTER TABLE jobhistory ADD COLUMN options TEXT; 
    4952 
     53-- 
     54-- Remove bad integrity rules 
     55-- and replace them with a new one 
     56-- 
     57ALTER TABLE jobhistory DROP CONSTRAINT "$1"; 
     58ALTER TABLE jobhistory DROP CONSTRAINT "$2"; 
     59ALTER TABLE jobhistory ADD CONSTRAINT checkUserPQuota FOREIGN KEY (userid, printerid) REFERENCES userpquota (userid, printerid); 
     60 
     61--  
     62-- Add new tables 
     63-- 
     64--                          
     65-- Create the printer groups relationship 
     66-- 
     67CREATE TABLE printergroupsmembers(groupid INT4 REFERENCES printers(id), 
     68                           printerid INT4 REFERENCES printers(id), 
     69                           PRIMARY KEY (groupid, printerid)); 
     70 
    5071--                          
    5172-- Now add some indexes 
     
    5677CREATE UNIQUE INDEX grouppquota_up_id_ix ON grouppquota (groupid, printerid); 
    5778 
     79--  
     80-- And now sets some ACLs 
     81--  
     82REVOKE ALL ON printergroupsmembers FROM public;                         
     83GRANT SELECT, INSERT, UPDATE, DELETE, REFERENCES ON printergroupsmembers TO pykotaadmin; 
     84GRANT SELECT ON printergroupsmembers TO pykotauser; 
     85 
  • pykota/trunk/MANIFEST.in

    r1226 r1240  
    1 include COPYING TODO NEWS CREDITS SECURITY MANIFEST.in clean.sh bin/cupspykota bin/pykota bin/edpykota bin/warnpykota bin/repykota bin/pykotme bin/waitprinter.sh bin/papwaitprinter.sh bin/README  
     1include COPYING TODO NEWS CREDITS SECURITY MANIFEST.in clean.sh bin/cupspykota bin/pykota bin/edpykota bin/warnpykota bin/repykota bin/pykotme bin/waitprinter.sh bin/papwaitprinter.sh bin/mailandpopup.sh bin/README contributed/pagecount.pl 
    22recursive-include po README *.po *.mo *.pot 
    33recursive-include man README *.1 
  • pykota/trunk/NEWS

    r1239 r1240  
    2222PyKota NEWS : 
    2323 
     24    - 1.16alpha20 : 
     25     
     26        - Fixed several small bugs with the help of PyChecker. 
     27         
     28    - 1.16alpha19 : 
     29      
     30        - Fixed a bug in PostgreSQL backend's code. 
     31         
     32    - 1.16alpha18 : 
     33     
     34        - Initial code for printer groups support. Printer groups have 
     35          to be added with external tools like psql or gq for example. 
     36          Printer groups seems to work fine with users. Untested with user  
     37          groups for now. 
     38 
     39        - Several minor visual problems fixed in reports. 
     40         
     41        - Fixed a bug in LDAP date handling. 
     42         
     43        - Fix for LDAP problem with some combination of OpenLDAP + Python-LDAP 
     44          + some particular settings. 
     45           
     46        - mailandpopup.sh shell script added. See sample configuration file 
     47          for details. 
     48         
     49        - Several environment variables are now exported when executing  
     50          external commands (accounters, requesters, mailers) : 
     51            
     52            PYKOTAUSERNAME => user who is printing 
     53            PYKOTAPRINTERNAME => printer on which the job is being sent 
     54            PYKOTATITLE => Job's title 
     55            PYKOTAFILENAME => Job's filename 
     56            PYKOTACOPIES => number of copies asked 
     57            PYKOTAOPTIONS => print command options (-o with CUPS) 
     58           
    2459    - 1.16alpha17 : 
    2560     
  • pykota/trunk/po/en/pykota.po

    r1239 r1240  
    2121# 
    2222# $Log$ 
    23 # Revision 1.37  2003/12/27 15:43:36  uid67467 
    24 # Savannah is back online... 
     23# Revision 1.38  2003/12/27 16:49:25  uid67467 
     24# Should be ok now. 
    2525# 
    2626# Revision 1.36  2003/11/18 23:43:11  jalet 
  • pykota/trunk/po/es/pykota.po

    r1239 r1240  
    2121# 
    2222# $Log$ 
    23 # Revision 1.5  2003/12/27 15:43:36  uid67467 
    24 # Savannah is back online... 
    25 # 
    26 # Revision 1.4  2003/12/03 18:51:09  jalet 
    27 # Fixed spanish translation 
     23# Revision 1.6  2003/12/27 16:49:25  uid67467 
     24# Should be ok now. 
    2825# 
    2926# Revision 1.3  2003/11/24 16:52:53  jalet 
     
    133130"\n" 
    134131"\n" 
    135 "Please contact your system administrator :\n" 
    136 "\n" 
    137 "\t%s - <%s>\n" 
    138 msgstr "" 
    139 "\n" 
    140 "\n" 
    141132"Por favor contacte a su administrador del sistema:\n" 
    142133"\n" 
    143134"\t%s - <%s>\n" 
     135msgstr "" 
    144136 
    145137msgid "Invalid grace delay %s" 
  • pykota/trunk/po/fr/pykota.po

    r1239 r1240  
    2121# 
    2222# $Log$ 
    23 # Revision 1.36  2003/12/27 15:43:36  uid67467 
    24 # Savannah is back online... 
     23# Revision 1.37  2003/12/27 16:49:25  uid67467 
     24# Should be ok now. 
    2525# 
    2626# Revision 1.35  2003/11/18 23:43:12  jalet 
  • pykota/trunk/po/pt/pykota.po

    r1237 r1240  
    2121# 
    2222# $Log$ 
     23# Revision 1.2  2003/12/27 16:49:25  uid67467 
     24# Should be ok now. 
     25# 
    2326# Revision 1.1  2003/12/03 18:49:37  jalet 
    2427# Portugues translation added thanks to Carlos Fernandes 
     
    8386msgstr "Impressora %s n�encontrada" 
    8487 
    85 msgid "*** Report for %s quota on printer %s" 
    86 msgstr "*** Relatorio de quota %s para a impressora %s" 
     88msgid "Report for %s quota on printer %s" 
     89msgstr "Relatorio de quota %s para a impressora %s" 
    8790 
    8891msgid "Error in page count value %i for user %s on printer %s" 
  • pykota/trunk/po/pykota.pot

    r1239 r1240  
    2121# 
    2222# $Log$ 
    23 # Revision 1.37  2003/12/27 15:43:36  uid67467 
    24 # Savannah is back online... 
     23# Revision 1.38  2003/12/27 16:49:25  uid67467 
     24# Should be ok now. 
    2525# 
    2626# Revision 1.36  2003/11/18 23:43:11  jalet 
  • pykota/trunk/pykota/accounter.py

    r1239 r1240  
    2222# 
    2323# $Log$ 
    24 # Revision 1.8  2003/12/27 15:43:36  uid67467 
    25 # Savannah is back online... 
     24# Revision 1.9  2003/12/27 16:49:25  uid67467 
     25# Should be ok now. 
    2626# 
    2727# Revision 1.7  2003/11/25 23:46:40  jalet 
     
    144144        return action 
    145145         
     146    def computeJobSize(self) :     
     147        """Must be overriden in children classes.""" 
     148        raise RuntimeError, "AccounterBase.computeJobSize() must be overriden !" 
     149         
     150         
    146151def openAccounter(kotafilter) : 
    147152    """Returns a connection handle to the appropriate accounter.""" 
     
    152157        raise PyKotaAccounterError, _("Unsupported accounter backend %s") % backend 
    153158    else :     
    154         return getattr(accounterbackend, "Accounter")(kotafilter, args) 
     159        return accounterbackend.Accounter(kotafilter, args) 
  • pykota/trunk/pykota/accounters/external.py

    r1239 r1240  
    2222# 
    2323# $Log$ 
    24 # Revision 1.11  2003/12/27 15:43:36  uid67467 
    25 # Savannah is back online... 
     24# Revision 1.12  2003/12/27 16:49:25  uid67467 
     25# Should be ok now. 
    2626# 
    2727# Revision 1.10  2003/11/23 19:01:36  jalet 
  • pykota/trunk/pykota/accounters/querying.py

    r1239 r1240  
    2222# 
    2323# $Log$ 
    24 # Revision 1.9  2003/12/27 15:43:36  uid67467 
    25 # Savannah is back online... 
     24# Revision 1.10  2003/12/27 16:49:25  uid67467 
     25# Should be ok now. 
    2626# 
    2727# Revision 1.8  2003/11/21 14:28:46  jalet 
     
    7070        """Returns the printer's internal page counter.""" 
    7171        global MAXTRIES, TIMETOSLEEP 
    72         for i in range(MAXTRIES) : 
     72        self.filter.logdebug("Reading printer's internal page counter...") 
     73        for dummy in range(MAXTRIES) : 
    7374            try : 
    7475                counter = self.requester.getPrinterPageCounter(self.filter.printerhostname) 
     
    8283                break 
    8384            time.sleep(TIMETOSLEEP)     
     85        self.filter.logdebug("Printer's internal page counter value is : %s" % str(counter)) 
    8486        return counter     
    8587         
  • pykota/trunk/pykota/accounters/stupid.py

    r1239 r1240  
    2222# 
    2323# $Log$ 
    24 # Revision 1.9  2003/12/27 15:43:36  uid67467 
    25 # Savannah is back online... 
     24# Revision 1.10  2003/12/27 16:49:25  uid67467 
     25# Should be ok now. 
    2626# 
    2727# Revision 1.8  2003/11/23 19:01:37  jalet 
  • pykota/trunk/pykota/logger.py

    r1218 r1240  
    2222# 
    2323# $Log$ 
     24# Revision 1.11  2003/12/27 16:49:25  uid67467 
     25# Should be ok now. 
     26# 
    2427# Revision 1.10  2003/11/25 22:37:22  jalet 
    2528# Small code move 
     
    6972    __str__ = __repr__ 
    7073 
    71 def openLogger(pykotatool, backend) : 
     74def openLogger(backend) : 
    7275    """Returns the appropriate logger subsystem object.""" 
    7376    try : 
     
    7679        raise PyKotaLoggingError, _("Unsupported logging subsystem %s") % backend 
    7780    else :     
    78         return getattr(loggingbackend, "Logger")() 
     81        return loggingbackend.Logger() 
  • pykota/trunk/pykota/reporter.py

    r1239 r1240  
    2222# 
    2323# $Log$ 
    24 # Revision 1.5  2003/12/27 15:43:36  uid67467 
    25 # Savannah is back online... 
     24# Revision 1.6  2003/12/27 16:49:25  uid67467 
     25# Should be ok now. 
    2626# 
    2727# Revision 1.4  2003/12/02 14:40:21  jalet 
     
    4141# 
    4242# 
     43 
     44from mx import DateTime 
    4345 
    4446class PyKotaReporterError(Exception): 
     
    9698                datelimit = "DENY" 
    9799                reached = "+B" 
     100            elif balance <= self.tool.config.getPoorMan() : 
     101                datelimit = "WARNING" 
     102                reached = "?B" 
    98103            else :     
    99104                datelimit = "" 
    100105                reached = "-B" 
    101106        else : 
    102             if quota.DateLimit is not None : 
     107            if (quota.HardLimit is not None) and (pagecounter >= quota.HardLimit) :     
     108                datelimit = "DENY" 
     109            elif (quota.HardLimit is None) and (quota.SoftLimit is not None) and (pagecounter >= quota.SoftLimit) : 
     110                datelimit = "DENY" 
     111            elif quota.DateLimit is not None : 
    103112                now = DateTime.now() 
    104113                datelimit = DateTime.ISO.ParseDateTime(quota.DateLimit) 
    105114                if now >= datelimit : 
    106115                    datelimit = "DENY" 
    107             elif (quota.HardLimit is not None) and (pagecounter >= quota.HardLimit) :     
    108                 datelimit = "DENY" 
    109             elif (quota.HardLimit is None) and (quota.SoftLimit is not None) and (pagecounter >= quota.SoftLimit) : 
    110                 datelimit = "DENY" 
    111116            else :     
    112117                datelimit = "" 
     
    124129        raise PyKotaReporterError, _("Unsupported reporter backend %s") % reporttype 
    125130    else :     
    126         return getattr(reporterbackend, "Reporter")(tool, printers, ugnames, isgroup) 
     131        return reporterbackend.Reporter(tool, printers, ugnames, isgroup) 
  • pykota/trunk/pykota/reporters/html.py

    r1239 r1240  
    2222# 
    2323# $Log$ 
    24 # Revision 1.2  2003/12/27 15:43:36  uid67467 
    25 # Savannah is back online... 
     24# Revision 1.3  2003/12/27 16:49:25  uid67467 
     25# Should be ok now. 
    2626# 
    2727# Revision 1.1  2003/12/02 14:41:17  jalet 
     
    5656                for (group, grouppquota) in self.tool.storage.getPrinterGroupsAndQuotas(printer, self.ugnames) : 
    5757                    oddeven += 1 
    58                     if oddeven % 1 : 
     58                    if oddeven % 2 : 
    5959                        oddevenclass = "odd" 
    6060                    else :     
    6161                        oddevenclass = "even" 
    62                     (pages, money, name, reached, soft, hard, balance, datelimit, lifepagecounter, lifetimepaid) = self.getQuota(group, grouppquota) 
     62                    (pages, money, name, reached, pagecounter, soft, hard, balance, datelimit, lifepagecounter, lifetimepaid) = self.getQuota(group, grouppquota) 
    6363                    self.report.append('<tr class="%s">%s</tr>' % (oddevenclass, "".join(["<td>%s</td>" % h for h in (name, reached, pagecounter, soft, hard, balance, datelimit or "&nbsp;", lifepagecounter, lifetimepaid)]))) 
    6464                    total += pages 
     
    6868                for (user, userpquota) in self.tool.storage.getPrinterUsersAndQuotas(printer, self.ugnames) : 
    6969                    oddeven += 1 
    70                     if oddeven % 1 : 
     70                    if oddeven % 2 : 
    7171                        oddevenclass = "odd" 
    7272                    else :     
  • pykota/trunk/pykota/reporters/text.py

    r1235 r1240  
    2222# 
    2323# $Log$ 
     24# Revision 1.7  2003/12/27 16:49:25  uid67467 
     25# Should be ok now. 
     26# 
    2427# Revision 1.6  2003/12/02 14:40:21  jalet 
    2528# Some code refactoring. 
     
    4548# 
    4649 
    47 from mx import DateTime 
    48  
    4950from pykota.reporter import BaseReporter, PyKotaReporterError 
    5051     
     
    6869                self.report.append('-' * len(header)) 
    6970                for (group, grouppquota) in self.tool.storage.getPrinterGroupsAndQuotas(printer, self.ugnames) : 
    70                     (pages, money, name, reached, soft, hard, balance, datelimit, lifepagecounter, lifetimepaid) = self.getQuota(group, grouppquota) 
     71                    (pages, money, name, reached, pagecounter, soft, hard, balance, datelimit, lifepagecounter, lifetimepaid) = self.getQuota(group, grouppquota) 
    7172                    self.report.append("%-9.9s %s %7i %7s %7s %10s %-10.10s %8i %10s" % (name, reached, pagecounter, soft, hard, balance, datelimit, lifepagecounter, lifetimepaid)) 
    7273                    total += pages 
  • pykota/trunk/pykota/requester.py

    r1219 r1240  
    2222# 
    2323# $Log$ 
     24# Revision 1.11  2003/12/27 16:49:25  uid67467 
     25# Should be ok now. 
     26# 
    2427# Revision 1.10  2003/11/25 23:46:40  jalet 
    2528# Don't try to verify if module name is valid, Python does this better than us. 
     
    7578        raise PyKotaRequesterError, _("Unsupported requester backend %s") % backend 
    7679    else :     
    77         return getattr(requesterbackend, "Requester")(printername, args) 
     80        return requesterbackend.Requester(printername, args) 
  • pykota/trunk/pykota/storage.py

    r1219 r1240  
    2222# 
    2323# $Log$ 
     24# Revision 1.29  2003/12/27 16:49:25  uid67467 
     25# Should be ok now. 
     26# 
    2427# Revision 1.28  2003/11/25 23:46:40  jalet 
    2528# Don't try to verify if module name is valid, Python does this better than us. 
     
    248251        self.HardLimit = None 
    249252        self.DateLimit = None 
     253        self.ParentPrintersUserPQuota = (user.Exists and printer.Exists and parent.getParentPrintersUserPQuota(self)) or [] 
    250254         
    251255    def setDateLimit(self, datelimit) :     
     
    268272    def increasePagesUsage(self, nbpages) : 
    269273        """Increase the value of used pages and money.""" 
    270         if nbpages : 
    271             jobprice = (float(self.Printer.PricePerPage or 0.0) * nbpages) + float(self.Printer.PricePerJob or 0.0) 
    272             newpagecounter = int(self.PageCounter or 0) + nbpages 
    273             newlifepagecounter = int(self.LifePageCounter or 0) + nbpages 
    274             self.parent.beginTransaction() 
    275             try : 
    276                 if jobprice : # optimization : don't access the database if unneeded. 
    277                     self.User.consumeAccountBalance(jobprice) 
    278                 self.parent.writeUserPQuotaPagesCounters(self, newpagecounter, newlifepagecounter) 
    279             except PyKotaStorageError, msg :     
    280                 self.parent.rollbackTransaction() 
    281                 raise PyKotaStorageError, msg 
    282             else :     
    283                 self.parent.commitTransaction() 
    284                 self.PageCounter = newpagecounter 
    285                 self.LifePageCounter = newlifepagecounter 
     274        jobprice = (float(self.Printer.PricePerPage or 0.0) * nbpages) + float(self.Printer.PricePerJob or 0.0) 
     275        self.parent.beginTransaction() 
     276        try : 
     277            if nbpages : 
     278                self.User.consumeAccountBalance(jobprice) 
     279                for upq in [ self ] + self.ParentPrintersUserPQuota : 
     280                    newpagecounter = int(upq.PageCounter or 0) + nbpages 
     281                    newlifepagecounter = int(upq.LifePageCounter or 0) + nbpages 
     282                    self.parent.writeUserPQuotaPagesCounters(upq, newpagecounter, newlifepagecounter) 
     283                    upq.PageCounter = newpagecounter 
     284                    upq.LifePageCounter = newlifepagecounter 
     285        except PyKotaStorageError, msg :     
     286            self.parent.rollbackTransaction() 
     287            raise PyKotaStorageError, msg 
     288        else :     
     289            self.parent.commitTransaction() 
    286290         
    287291class StorageGroupPQuota(StorageObject) : 
     
    344348            self.tool.logdebug("Caching enabled.") 
    345349            self.caches = { "USERS" : {}, "GROUPS" : {}, "PRINTERS" : {}, "USERPQUOTAS" : {}, "GROUPPQUOTAS" : {}, "JOBS" : {}, "LASTJOBS" : {} } 
     350         
     351    def close(self) :     
     352        """Must be overriden in children classes.""" 
     353        raise RuntimeError, "BaseStorage.close() must be overriden !" 
    346354         
    347355    def __del__(self) :         
     
    441449        return user.Groups    
    442450         
     451    def getParentPrintersUserPQuota(self, userpquota) :      
     452        """Returns all user print quota on the printer and its parents.""" 
     453        upquotas = [ ] 
     454        for printer in self.getParentPrinters(userpquota.Printer) : 
     455            upquotas.append(self.getUserPQuota(userpquota.User, printer)) 
     456        return upquotas         
     457         
    443458def openConnection(pykotatool) : 
    444459    """Returns a connection handle to the appropriate Quota Storage Database.""" 
     
    454469        admin = backendinfo["storageadmin"] or backendinfo["storageuser"] 
    455470        adminpw = backendinfo["storageadminpw"] or backendinfo["storageuserpw"] 
    456         return getattr(storagebackend, "Storage")(pykotatool, host, database, admin, adminpw) 
     471        return storagebackend.Storage(pykotatool, host, database, admin, adminpw) 
    457472 
  • pykota/trunk/pykota/storages/ldapstorage.py

    r1228 r1240  
    2222# 
    2323# $Log$ 
     24# Revision 1.41  2003/12/27 16:49:25  uid67467 
     25# Should be ok now. 
     26# 
    2427# Revision 1.40  2003/11/29 22:02:14  jalet 
    2528# Don't try to retrieve the user print quota information if current printer 
     
    166169# 
    167170 
     171import types 
    168172import time 
    169173import md5 
     
    211215        return md5.md5("%s" % time.time()).hexdigest() 
    212216         
     217    def normalizeFields(self, fields) :     
     218        """Ensure all items are lists.""" 
     219        for (k, v) in fields.items() : 
     220            if type(v) not in (types.TupleType, types.ListType) : 
     221                if not v : 
     222                    del fields[k] 
     223                else :     
     224                    fields[k] = [ v ] 
     225        return fields         
     226         
    213227    def beginTransaction(self) :     
    214228        """Starts a transaction.""" 
     
    237251    def doAdd(self, dn, fields) : 
    238252        """Adds an entry in the LDAP directory.""" 
     253        fields = self.normalizeFields(fields) 
    239254        try : 
    240255            self.tool.logdebug("QUERY : ADD(%s, %s)" % (dn, str(fields))) 
     
    255270    def doModify(self, dn, fields, ignoreold=1) : 
    256271        """Modifies an entry in the LDAP directory.""" 
     272        fields = self.normalizeFields(fields) 
    257273        try : 
    258274            oldentry = self.doSearch("objectClass=*", base=dn, scope=ldap.SCOPE_BASE) 
     
    545561        return groupsandquotas 
    546562         
     563    def getParentPrinters(self, printer) :     
     564        """Get all the printer groups this printer is a member of.""" 
     565        pgroups = [] 
     566        result = self.doSearch("(&(objectClass=pykotaPrinter)(uniqueMember=%s))" % printer.ident, ["pykotaPrinterName"], base=self.info["printerbase"]) 
     567        if result : 
     568            for (printerid, fields) in result : 
     569                parentprinter = self.getPrinter(fields.get("pykotaPrinterName")[0]) 
     570                if parentprinter.Exists : 
     571                    pgroups.append(parentprinter) 
     572        return pgroups 
     573         
    547574    def addPrinter(self, printername) :         
    548575        """Adds a printer to the quota storage, returns it.""" 
     
    679706        """Sets the date limit permanently for a user print quota.""" 
    680707        fields = { 
    681                    "pykotaDateLimit" : "%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second), 
     708                   "pykotaDateLimit" : datelimit, 
    682709                 } 
    683710        return self.doModify(userpquota.ident, fields) 
     
    686713        """Sets the date limit permanently for a group print quota.""" 
    687714        fields = { 
    688                    "pykotaDateLimit" : "%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second), 
     715                   "pykotaDateLimit" : datelimit, 
    689716                 } 
    690717        return self.doModify(grouppquota.ident, fields) 
  • pykota/trunk/pykota/storages/pgstorage.py

    r1228 r1240  
    2222# 
    2323# $Log$ 
     24# Revision 1.25  2003/12/27 16:49:25  uid67467 
     25# Should be ok now. 
     26# 
    2427# Revision 1.24  2003/11/29 22:02:14  jalet 
    2528# Don't try to retrieve the user print quota information if current printer 
     
    392395        return groupsandquotas 
    393396         
     397    def getParentPrinters(self, printer) :     
     398        """Get all the printer groups this printer is a member of.""" 
     399        pgroups = [] 
     400        result = self.doSearch("SELECT printername FROM printergroupsmembers JOIN printers ON groupid=id WHERE printerid=%s;" % self.doQuote(printer.ident)) 
     401        if result : 
     402            for record in result : 
     403                parentprinter = self.getPrinter(record.get("printername")) 
     404                if parentprinter.Exists : 
     405                    pgroups.append(parentprinter) 
     406        return pgroups 
     407         
    394408    def addPrinter(self, printername) :         
    395409        """Adds a printer to the quota storage, returns it.""" 
     
    468482                self.doModify("INSERT INTO jobhistory (userid, printerid, jobid, pagecounter, action, jobsize, jobprice, filename, title, copies, options) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)" % (self.doQuote(user.ident), self.doQuote(printer.ident), self.doQuote(jobid), self.doQuote(pagecounter), self.doQuote(action), self.doQuote(jobsize), self.doQuote(jobprice), self.doQuote(filename), self.doQuote(title), self.doQuote(copies), self.doQuote(options))) 
    469483            else :     
    470                 self.doModify("INSERT INTO jobhistory (userid, printerid, jobid, pagecounter, action, filename, title, copies, options) VALUES (%s, %s, %s, %s, %s)" % (self.doQuote(user.ident), self.doQuote(printer.ident), self.doQuote(jobid), self.doQuote(pagecounter), self.doQuote(action), self.doQuote(filename), self.doQuote(title), self.doQuote(copies), self.doQuote(options))) 
     484                self.doModify("INSERT INTO jobhistory (userid, printerid, jobid, pagecounter, action, filename, title, copies, options) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)" % (self.doQuote(user.ident), self.doQuote(printer.ident), self.doQuote(jobid), self.doQuote(pagecounter), self.doQuote(action), self.doQuote(filename), self.doQuote(title), self.doQuote(copies), self.doQuote(options))) 
    471485        else :         
    472486            # here we explicitly want to reset jobsize to NULL if needed 
  • pykota/trunk/pykota/tool.py

    r1229 r1240  
    2222# 
    2323# $Log$ 
     24# Revision 1.65  2003/12/27 16:49:25  uid67467 
     25# Should be ok now. 
     26# 
     27# Revision 1.65  2003/12/06 08:14:38  jalet 
     28# Added support for CUPS device uris which contain authentication information. 
     29# 
    2430# Revision 1.64  2003/11/29 22:03:17  jalet 
    2531# Some code refactoring work. New code is not used at this time. 
     
    288294        self.documentation = doc 
    289295        self.config = config.PyKotaConfig("/etc/pykota") 
    290         self.logger = logger.openLogger(self, self.config.getLoggingBackend()) 
     296        self.logger = logger.openLogger(self.config.getLoggingBackend()) 
    291297        self.debug = self.config.getDebug() 
    292298        self.storage = storage.openConnection(self) 
     
    574580                self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage) 
    575581            if mailto in [ "BOTH", "USER", "EXTERNAL" ] : 
     582                message = self.config.getHardWarn(printer.Name) 
    576583                for user in self.storage.getGroupMembers(group) : 
    577584                    if mailto != "EXTERNAL" : 
    578                         self.sendMessageToUser(admin, adminmail, user, _("Print Quota Exceeded"), self.config.getHardWarn(printer.Name)) 
     585                        self.sendMessageToUser(admin, adminmail, user, _("Print Quota Exceeded"), message) 
    579586                    else :     
    580587                        self.externalMailTo(arguments, action, user, printer, message) 
     
    599606        """Checks a user quota and send him a message if quota is exceeded on current printer.""" 
    600607        user = userpquota.User 
    601         printer = userpquota.Printer 
    602         admin = self.config.getAdmin(printer.Name) 
    603         adminmail = self.config.getAdminMail(printer.Name) 
    604         (mailto, arguments) = self.config.getMailTo(printer.Name) 
    605         action = self.checkUserPQuota(userpquota) 
    606         if action.startswith("POLICY_") : 
    607             action = action[7:] 
    608         if action == "DENY" : 
    609             adminmessage = _("Print Quota exceeded for user %s on printer %s") % (user.Name, printer.Name) 
    610             self.logger.log_message(adminmessage) 
    611             if mailto in [ "BOTH", "USER", "EXTERNAL" ] : 
    612                 message = self.config.getHardWarn(printer.Name) 
    613                 if mailto != "EXTERNAL" : 
    614                     self.sendMessageToUser(admin, adminmail, user, _("Print Quota Exceeded"), message) 
    615                 else :     
    616                     self.externalMailTo(arguments, action, user, printer, message) 
    617             if mailto in [ "BOTH", "ADMIN" ] : 
    618                 self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage) 
    619         elif action == "WARN" :     
    620             adminmessage = _("Print Quota low for user %s on printer %s") % (user.Name, printer.Name) 
    621             self.logger.log_message(adminmessage) 
    622             if mailto in [ "BOTH", "USER", "EXTERNAL" ] : 
    623                 if user.LimitBy and (user.LimitBy.lower() == "balance") :  
    624                     message = self.config.getPoorWarn() 
    625                 else :      
    626                     message = self.config.getSoftWarn(printer.Name) 
    627                 if mailto != "EXTERNAL" :     
    628                     self.sendMessageToUser(admin, adminmail, user, _("Print Quota Low"), message) 
    629                 else :     
    630                     self.externalMailTo(arguments, action, user, printer, message) 
    631             if mailto in [ "BOTH", "ADMIN" ] : 
    632                 self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage) 
    633         return action         
     608        actions = [] 
     609        for upq in [userpquota] + userpquota.ParentPrintersUserPQuota : 
     610            printer = upq.Printer 
     611            admin = self.config.getAdmin(printer.Name) 
     612            adminmail = self.config.getAdminMail(printer.Name) 
     613            (mailto, arguments) = self.config.getMailTo(printer.Name) 
     614            self.logdebug("Checking quota for user %s on printer %s" % (upq.User.Name, printer.Name)) 
     615            action = self.checkUserPQuota(upq) 
     616            self.logdebug("Result is %s" % action) 
     617            if action.startswith("POLICY_") : 
     618                action = action[7:] 
     619            if action == "DENY" : 
     620                adminmessage = _("Print Quota exceeded for user %s on printer %s") % (user.Name, printer.Name) 
     621                self.logger.log_message(adminmessage) 
     622                if mailto in [ "BOTH", "USER", "EXTERNAL" ] : 
     623                    message = self.config.getHardWarn(printer.Name) 
     624                    if mailto != "EXTERNAL" : 
     625                        self.sendMessageToUser(admin, adminmail, user, _("Print Quota Exceeded"), message) 
     626                    else :     
     627                        self.externalMailTo(arguments, action, user, printer, message) 
     628                if mailto in [ "BOTH", "ADMIN" ] : 
     629                    self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage) 
     630            elif action == "WARN" :     
     631                adminmessage = _("Print Quota low for user %s on printer %s") % (user.Name, printer.Name) 
     632                self.logger.log_message(adminmessage) 
     633                if mailto in [ "BOTH", "USER", "EXTERNAL" ] : 
     634                    if user.LimitBy and (user.LimitBy.lower() == "balance") :  
     635                        message = self.config.getPoorWarn() 
     636                    else :      
     637                        message = self.config.getSoftWarn(printer.Name) 
     638                    if mailto != "EXTERNAL" :     
     639                        self.sendMessageToUser(admin, adminmail, user, _("Print Quota Low"), message) 
     640                    else :     
     641                        self.externalMailTo(arguments, action, user, printer, message) 
     642                if mailto in [ "BOTH", "ADMIN" ] : 
     643                    self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage) 
     644            actions.append(action)         
     645        if "DENY" in actions :     
     646            self.logdebug("Final result is %s" % action) 
     647            return "DENY" 
     648        elif "WARN" in actions :     
     649            self.logdebug("Final result is %s" % action) 
     650            return "WARN" 
     651        else :     
     652            self.logdebug("Final result is %s" % action) 
     653            return "ALLOW" 
    634654         
    635655class PyKotaFilterOrBackend(PyKotaTool) :     
     
    651671            self.username = self.username.lower() 
    652672        self.preserveinputfile = self.inputfile  
     673        # 
     674        # Export internal data to the environment 
     675        os.environ["PYKOTAUSERNAME"] = str(self.username) 
     676        os.environ["PYKOTAPRINTERNAME"] = str(self.printername) 
     677        os.environ["PYKOTACOPIES"] = str(self.copies) 
     678        os.environ["PYKOTATITLE"] = str(self.title) 
     679        os.environ["PYKOTAOPTIONS"] = str(self.options) 
     680        os.environ["PYKOTAFILENAME"] = str(self.inputfile) 
     681        # 
     682        # And opens the correct accounter  
    653683        self.accounter = accounter.openAccounter(self) 
    654684     
     
    683713            while destination.startswith("/") : 
    684714                destination = destination[1:] 
     715            checkauth = destination.split("@", 1)     
     716            if len(checkauth) == 2 : 
     717                destination = checkauth[1] 
    685718            printerhostname = destination.split("/")[0].split(":")[0] 
    686719            return ("CUPS", \ 
     
    737770           was returned by the external command. 
    738771        """ 
    739         for passnumber in range(1, 3) : 
     772        for dummy in range(1, 3) : 
    740773            printer = self.storage.getPrinter(self.printername) 
    741774            user = self.storage.getUser(self.username) 
  • pykota/trunk/pykota/version.py

    r1239 r1240  
    2222# 
    2323 
    24 __version__ = "1.16alpha17_unofficial" 
     24__version__ = "1.16alpha20_unofficial" 
    2525 
    2626__doc__ = """PyKota : a complete Printing Quota Solution for CUPS and LPRng.""" 
  • pykota/trunk/setup.py

    r1226 r1240  
    2424# 
    2525# $Log$ 
     26# Revision 1.28  2003/12/27 16:49:25  uid67467 
     27# Should be ok now. 
     28# 
     29# Revision 1.28  2003/12/06 09:03:43  jalet 
     30# Added Perl script to retrieve printer's internal page counter via PJL, 
     31# contributed by Ren�und Jensen. 
     32# 
    2633# Revision 1.27  2003/11/28 08:31:28  jalet 
    2734# Shell script to wait for AppleTalk enabled printers being idle was added. 
     
    338345      url = "http://www.librelogiciel.com/software/", 
    339346      packages = [ "pykota", "pykota.storages", "pykota.requesters", "pykota.loggers", "pykota.accounters", "pykota.reporters" ], 
    340       scripts = [ "bin/cupspykota", "bin/pykota", "bin/edpykota", "bin/repykota", "bin/warnpykota", "bin/pykotme", "bin/waitprinter.sh", "bin/papwaitprinter.sh" ], 
     347      scripts = [ "bin/cupspykota", "bin/pykota", "bin/edpykota", "bin/repykota", "bin/warnpykota", "bin/pykotme", "bin/waitprinter.sh", "bin/papwaitprinter.sh", "bin/mailandpopup.sh", "contributed/pagecount.pl" ], 
    341348      data_files = data_files) 
    342349