Changeset 1240
- Timestamp:
- 12/27/03 17:49:25 (21 years ago)
- Location:
- pykota/trunk
- Files:
-
- 31 modified
Legend:
- Unmodified
- Added
- Removed
-
pykota/trunk/bin/cupspykota
r1222 r1240 24 24 # 25 25 # $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 # 26 33 # Revision 1.16 2003/11/26 20:43:29 jalet 27 34 # Inadvertantly introduced a bug, which is fixed. … … 84 91 import os 85 92 import popen2 86 import time87 93 import cStringIO 88 94 import shlex … … 187 193 if user.Exists : 188 194 # Is the current user allowed to print at all ? 195 thebackend.logdebug("Checking user %s's quota on printer %s" % (user.Name, printer.Name)) 189 196 action = thebackend.warnUserPQuota(thebackend.storage.getUserPQuota(user, printer)) 190 197 elif policy == "EXTERNAL" : … … 203 210 # pass the job untouched to the underlying layer 204 211 # and starts accounting at the same time 212 thebackend.logdebug("Job accounting begins.") 205 213 thebackend.accounter.beginJob(printer, user) 206 214 … … 222 230 223 231 # And launch it 232 thebackend.logdebug("Starting real backend %s with args %s" % (realbackend, " ".join([os.environ["DEVICE_URI"]] + sys.argv[1:]))) 224 233 subprocess = PyKotaPopen3([realbackend] + sys.argv[1:], capturestderr=1, bufsize=0, arg0=os.environ["DEVICE_URI"]) 225 234 … … 248 257 endinput = 0 249 258 status = -1 259 inputclosed = 0 260 thebackend.logdebug("Entering streams polling loop...") 250 261 while status == -1 : 251 262 # First check if original backend is still alive … … 263 274 availablefds = pollster.poll() 264 275 for (fd, mask) in availablefds : 276 # thebackend.logdebug("file: %i mask: %04x" % (fd, mask)) 265 277 if mask & select.POLLOUT : 266 278 # We can write … … 303 315 # standard output 304 316 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.") 316 323 elif fd == cerrfno : 317 324 # Original CUPS backend has finished … … 319 326 if errdata : 320 327 # 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 = "" 326 330 # 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.") 333 334 334 if endinput :335 if endinput and not inputclosed : 335 336 # We deal with remaining input datas here 336 337 # because EOF can happen in two different … … 338 339 # code, nor making functions. 339 340 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.") 353 348 354 349 # Input file was a real file, we have to close it. 355 350 if mustclose : 356 351 infile.close() 352 353 thebackend.logdebug("Exiting streams polling loop...") 357 354 358 355 # Check exit code of original CUPS backend. … … 365 362 # stops accounting. 366 363 thebackend.accounter.endJob(printer, user) 364 thebackend.logdebug("Job accounting ends.") 367 365 368 366 # retrieve the job size 369 367 jobsize = thebackend.accounter.getJobSize() 368 thebackend.logdebug("Job size : %i" % jobsize) 370 369 371 370 # update the quota for the current user on this printer … … 374 373 userquota = thebackend.storage.getUserPQuota(user, printer) 375 374 if userquota.Exists : 375 thebackend.logdebug("Updating user %s's quota on printer %s" % (user.Name, printer.Name)) 376 376 userquota.increasePagesUsage(jobsize) 377 377 378 378 # adds the current job to history 379 379 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.") 380 381 381 382 return retcode # return (retcode or gotSigTerm) shouldn't be needed -
pykota/trunk/bin/pykota
r1221 r1240 24 24 # 25 25 # $Log$ 26 # Revision 1.48 2003/12/27 16:49:25 uid67467 27 # Should be ok now. 28 # 26 29 # Revision 1.47 2003/11/26 19:17:35 jalet 27 30 # Printing on a printer not present in the Quota Storage now results … … 274 277 if user.Exists : 275 278 # 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)) 276 280 action = thefilter.accounter.doAccounting(printer, user) 277 281 … … 279 283 if action == "DENY" : 280 284 # No, just die cleanly 285 thefilter.logdebug("Printing is denied.") 281 286 return thefilter.removeJob() 282 287 elif policy == "EXTERNAL" : … … 285 290 286 291 # pass the job untouched to the underlying layer 292 thefilter.logdebug("Passing input data to next filter.") 287 293 thefilter.accounter.filterInput(thefilter.inputfile) 288 294 -
pykota/trunk/bin/waitprinter.sh
r1096 r1240 14 14 # $Id$ 15 15 # 16 16 # Fix by Matt Hyclak : 17 sleep 3 18 # 17 19 until snmpget -v1 -c public -Ov $1 HOST-RESOURCES-MIB::hrPrinterStatus.1 | grep -i idle >/dev/null ; do 18 20 sleep 1 ; -
pykota/trunk/cgi-bin/printquota.cgi
r1239 r1240 1 #! /usr/bin/python 2.21 #! /usr/bin/python 2 2 3 3 # PyKota Print Quota Reports generator … … 23 23 # 24 24 # $Log$ 25 # Revision 1.1 7 2003/12/27 15:43:36uid6746726 # S avannah is back online...25 # Revision 1.18 2003/12/27 16:49:25 uid67467 26 # Should be ok now. 27 27 # 28 28 # Revision 1.16 2003/12/02 14:40:20 jalet -
pykota/trunk/conf/pykota.conf.sample
r1233 r1240 129 129 # logs. 130 130 # Actually only database queries are logged. 131 debug : No131 debug : Yes 132 132 133 133 # Mail server to use to warn users … … 236 236 # NB : I use ISO-8859-15, but Windows expects UTF-8, so we pipe the message 237 237 # 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 238 244 # 239 245 # NB : in ANY case, don't forget to redirect your command's standard output … … 344 350 # 345 351 # 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 # 346 358 # WARNING : In any case, when using an external requester, please test the command line outside 347 359 # of PyKota before. This will save you some headaches in case it doesn't work as expected. -
pykota/trunk/CREDITS
r1237 r1240 60 60 - Stephen Markan - Faculty of Environmental Studies, University of Waterloo 61 61 - Jeremy Worth - University of Oxford 62 - Roger Morgan - H�e Technische Bundeslehranstalt Steyr 63 - Pal Monstad 64 - Richard Potter 62 65 63 66 Contributors : … … 67 70 68 71 - Jo�Collet : PyKota's logo 69 - Stefan Wold - Stockholm University : code72 - Stefan Wold - Stockholm University : inital code for external policies 70 73 - John Flynn - University of Belize : LDAP support 71 74 - Wayne Godoy - University of Belize : LDAP support … … 78 81 - Daniel Mikkelsen : Sample configuration file fix 79 82 - Carlos Fernandes : Portugues translation 83 - Ren�und Jensen : Contributed the pagecount.pl script 80 84 81 85 ============================================================== -
pykota/trunk/initscripts/ldap/pykota.schema
r1223 r1240 189 189 DESC 'PyKota Printer' 190 190 MUST ( cn ) 191 MAY ( pykotaPrinterName $ pykotaPricePerPage $ pykotaPricePerJob ) )191 MAY ( pykotaPrinterName $ pykotaPricePerPage $ pykotaPricePerJob $ uniqueMember ) ) 192 192 193 193 # pykotaUserPQuota -
pykota/trunk/initscripts/postgresql/pykota-postgresql.sql
r1203 r1240 20 20 -- 21 21 -- $Log$ 22 -- Revision 1.7 2003/12/27 16:49:25 uid67467 23 -- Should be ok now. 24 -- 22 25 -- Revision 1.6 2003/11/23 19:01:36 jalet 23 26 -- Job price added to history … … 110 113 CREATE TABLE jobhistory(id SERIAL PRIMARY KEY NOT NULL, 111 114 jobid TEXT, 112 userid INT4 REFERENCES users(id),113 printerid INT4 REFERENCES printers(id),115 userid INT4, 116 printerid INT4, 114 117 pagecounter INT4 DEFAULT 0, 115 118 jobsize INT4, … … 120 123 copies INT4, 121 124 options TEXT, 122 jobdate TIMESTAMP DEFAULT now()); 125 jobdate TIMESTAMP DEFAULT now(), 126 CONSTRAINT checkUserPQuota FOREIGN KEY (userid, printerid) REFERENCES userpquota(userid, printerid)); 123 127 CREATE INDEX jobhistory_p_id_ix ON jobhistory (printerid); 124 128 CREATE INDEX jobhistory_pd_id_ix ON jobhistory (printerid, jobdate); … … 141 145 userid INT4 REFERENCES users(id), 142 146 PRIMARY KEY (groupid, userid)); 147 148 -- 149 -- Create the printer groups relationship 150 -- 151 CREATE TABLE printergroupsmembers(groupid INT4 REFERENCES printers(id), 152 printerid INT4 REFERENCES printers(id), 153 PRIMARY KEY (groupid, printerid)); 143 154 144 155 -- 145 156 -- Set some ACLs 146 157 -- 147 REVOKE ALL ON users, groups, printers, userpquota, grouppquota, groupsmembers, jobhistory FROM public;158 REVOKE ALL ON users, groups, printers, userpquota, grouppquota, groupsmembers, printergroupsmembers, jobhistory FROM public; 148 159 REVOKE ALL ON users_id_seq, groups_id_seq, printers_id_seq, userpquota_id_seq, grouppquota_id_seq, jobhistory_id_seq FROM public; 149 160 150 GRANT SELECT, INSERT, UPDATE, DELETE, REFERENCES ON users, groups, printers, userpquota, grouppquota, groupsmembers, jobhistory TO pykotaadmin;161 GRANT SELECT, INSERT, UPDATE, DELETE, REFERENCES ON users, groups, printers, userpquota, grouppquota, groupsmembers, printergroupsmembers, jobhistory TO pykotaadmin; 151 162 GRANT 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;163 GRANT SELECT ON users, groups, printers, userpquota, grouppquota, groupsmembers, printergroupsmembers, jobhistory TO pykotauser; 153 164 -
pykota/trunk/initscripts/postgresql/upgrade-to-1.16.sql
r1203 r1240 20 20 -- 21 21 -- $Log$ 22 -- Revision 1.3 2003/12/27 16:49:25 uid67467 23 -- Should be ok now. 24 -- 22 25 -- Revision 1.2 2003/11/23 19:01:36 jalet 23 26 -- Job price added to history … … 48 51 ALTER TABLE jobhistory ADD COLUMN options TEXT; 49 52 53 -- 54 -- Remove bad integrity rules 55 -- and replace them with a new one 56 -- 57 ALTER TABLE jobhistory DROP CONSTRAINT "$1"; 58 ALTER TABLE jobhistory DROP CONSTRAINT "$2"; 59 ALTER 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 -- 67 CREATE TABLE printergroupsmembers(groupid INT4 REFERENCES printers(id), 68 printerid INT4 REFERENCES printers(id), 69 PRIMARY KEY (groupid, printerid)); 70 50 71 -- 51 72 -- Now add some indexes … … 56 77 CREATE UNIQUE INDEX grouppquota_up_id_ix ON grouppquota (groupid, printerid); 57 78 79 -- 80 -- And now sets some ACLs 81 -- 82 REVOKE ALL ON printergroupsmembers FROM public; 83 GRANT SELECT, INSERT, UPDATE, DELETE, REFERENCES ON printergroupsmembers TO pykotaadmin; 84 GRANT 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/ README1 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/mailandpopup.sh bin/README contributed/pagecount.pl 2 2 recursive-include po README *.po *.mo *.pot 3 3 recursive-include man README *.1 -
pykota/trunk/NEWS
r1239 r1240 22 22 PyKota NEWS : 23 23 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 24 59 - 1.16alpha17 : 25 60 -
pykota/trunk/po/en/pykota.po
r1239 r1240 21 21 # 22 22 # $Log$ 23 # Revision 1.3 7 2003/12/27 15:43:36uid6746724 # S avannah is back online...23 # Revision 1.38 2003/12/27 16:49:25 uid67467 24 # Should be ok now. 25 25 # 26 26 # Revision 1.36 2003/11/18 23:43:11 jalet -
pykota/trunk/po/es/pykota.po
r1239 r1240 21 21 # 22 22 # $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. 28 25 # 29 26 # Revision 1.3 2003/11/24 16:52:53 jalet … … 133 130 "\n" 134 131 "\n" 135 "Please contact your system administrator :\n"136 "\n"137 "\t%s - <%s>\n"138 msgstr ""139 "\n"140 "\n"141 132 "Por favor contacte a su administrador del sistema:\n" 142 133 "\n" 143 134 "\t%s - <%s>\n" 135 msgstr "" 144 136 145 137 msgid "Invalid grace delay %s" -
pykota/trunk/po/fr/pykota.po
r1239 r1240 21 21 # 22 22 # $Log$ 23 # Revision 1.3 6 2003/12/27 15:43:36uid6746724 # S avannah is back online...23 # Revision 1.37 2003/12/27 16:49:25 uid67467 24 # Should be ok now. 25 25 # 26 26 # Revision 1.35 2003/11/18 23:43:12 jalet -
pykota/trunk/po/pt/pykota.po
r1237 r1240 21 21 # 22 22 # $Log$ 23 # Revision 1.2 2003/12/27 16:49:25 uid67467 24 # Should be ok now. 25 # 23 26 # Revision 1.1 2003/12/03 18:49:37 jalet 24 27 # Portugues translation added thanks to Carlos Fernandes … … 83 86 msgstr "Impressora %s n�encontrada" 84 87 85 msgid " ***Report for %s quota on printer %s"86 msgstr " ***Relatorio de quota %s para a impressora %s"88 msgid "Report for %s quota on printer %s" 89 msgstr "Relatorio de quota %s para a impressora %s" 87 90 88 91 msgid "Error in page count value %i for user %s on printer %s" -
pykota/trunk/po/pykota.pot
r1239 r1240 21 21 # 22 22 # $Log$ 23 # Revision 1.3 7 2003/12/27 15:43:36uid6746724 # S avannah is back online...23 # Revision 1.38 2003/12/27 16:49:25 uid67467 24 # Should be ok now. 25 25 # 26 26 # Revision 1.36 2003/11/18 23:43:11 jalet -
pykota/trunk/pykota/accounter.py
r1239 r1240 22 22 # 23 23 # $Log$ 24 # Revision 1. 8 2003/12/27 15:43:36uid6746725 # S avannah is back online...24 # Revision 1.9 2003/12/27 16:49:25 uid67467 25 # Should be ok now. 26 26 # 27 27 # Revision 1.7 2003/11/25 23:46:40 jalet … … 144 144 return action 145 145 146 def computeJobSize(self) : 147 """Must be overriden in children classes.""" 148 raise RuntimeError, "AccounterBase.computeJobSize() must be overriden !" 149 150 146 151 def openAccounter(kotafilter) : 147 152 """Returns a connection handle to the appropriate accounter.""" … … 152 157 raise PyKotaAccounterError, _("Unsupported accounter backend %s") % backend 153 158 else : 154 return getattr(accounterbackend, "Accounter")(kotafilter, args)159 return accounterbackend.Accounter(kotafilter, args) -
pykota/trunk/pykota/accounters/external.py
r1239 r1240 22 22 # 23 23 # $Log$ 24 # Revision 1.1 1 2003/12/27 15:43:36uid6746725 # S avannah is back online...24 # Revision 1.12 2003/12/27 16:49:25 uid67467 25 # Should be ok now. 26 26 # 27 27 # Revision 1.10 2003/11/23 19:01:36 jalet -
pykota/trunk/pykota/accounters/querying.py
r1239 r1240 22 22 # 23 23 # $Log$ 24 # Revision 1. 9 2003/12/27 15:43:36uid6746725 # S avannah is back online...24 # Revision 1.10 2003/12/27 16:49:25 uid67467 25 # Should be ok now. 26 26 # 27 27 # Revision 1.8 2003/11/21 14:28:46 jalet … … 70 70 """Returns the printer's internal page counter.""" 71 71 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) : 73 74 try : 74 75 counter = self.requester.getPrinterPageCounter(self.filter.printerhostname) … … 82 83 break 83 84 time.sleep(TIMETOSLEEP) 85 self.filter.logdebug("Printer's internal page counter value is : %s" % str(counter)) 84 86 return counter 85 87 -
pykota/trunk/pykota/accounters/stupid.py
r1239 r1240 22 22 # 23 23 # $Log$ 24 # Revision 1. 9 2003/12/27 15:43:36uid6746725 # S avannah is back online...24 # Revision 1.10 2003/12/27 16:49:25 uid67467 25 # Should be ok now. 26 26 # 27 27 # Revision 1.8 2003/11/23 19:01:37 jalet -
pykota/trunk/pykota/logger.py
r1218 r1240 22 22 # 23 23 # $Log$ 24 # Revision 1.11 2003/12/27 16:49:25 uid67467 25 # Should be ok now. 26 # 24 27 # Revision 1.10 2003/11/25 22:37:22 jalet 25 28 # Small code move … … 69 72 __str__ = __repr__ 70 73 71 def openLogger( pykotatool,backend) :74 def openLogger(backend) : 72 75 """Returns the appropriate logger subsystem object.""" 73 76 try : … … 76 79 raise PyKotaLoggingError, _("Unsupported logging subsystem %s") % backend 77 80 else : 78 return getattr(loggingbackend, "Logger")()81 return loggingbackend.Logger() -
pykota/trunk/pykota/reporter.py
r1239 r1240 22 22 # 23 23 # $Log$ 24 # Revision 1. 5 2003/12/27 15:43:36uid6746725 # S avannah is back online...24 # Revision 1.6 2003/12/27 16:49:25 uid67467 25 # Should be ok now. 26 26 # 27 27 # Revision 1.4 2003/12/02 14:40:21 jalet … … 41 41 # 42 42 # 43 44 from mx import DateTime 43 45 44 46 class PyKotaReporterError(Exception): … … 96 98 datelimit = "DENY" 97 99 reached = "+B" 100 elif balance <= self.tool.config.getPoorMan() : 101 datelimit = "WARNING" 102 reached = "?B" 98 103 else : 99 104 datelimit = "" 100 105 reached = "-B" 101 106 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 : 103 112 now = DateTime.now() 104 113 datelimit = DateTime.ISO.ParseDateTime(quota.DateLimit) 105 114 if now >= datelimit : 106 115 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"111 116 else : 112 117 datelimit = "" … … 124 129 raise PyKotaReporterError, _("Unsupported reporter backend %s") % reporttype 125 130 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 22 22 # 23 23 # $Log$ 24 # Revision 1. 2 2003/12/27 15:43:36uid6746725 # S avannah is back online...24 # Revision 1.3 2003/12/27 16:49:25 uid67467 25 # Should be ok now. 26 26 # 27 27 # Revision 1.1 2003/12/02 14:41:17 jalet … … 56 56 for (group, grouppquota) in self.tool.storage.getPrinterGroupsAndQuotas(printer, self.ugnames) : 57 57 oddeven += 1 58 if oddeven % 1:58 if oddeven % 2 : 59 59 oddevenclass = "odd" 60 60 else : 61 61 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) 63 63 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 " ", lifepagecounter, lifetimepaid)]))) 64 64 total += pages … … 68 68 for (user, userpquota) in self.tool.storage.getPrinterUsersAndQuotas(printer, self.ugnames) : 69 69 oddeven += 1 70 if oddeven % 1:70 if oddeven % 2 : 71 71 oddevenclass = "odd" 72 72 else : -
pykota/trunk/pykota/reporters/text.py
r1235 r1240 22 22 # 23 23 # $Log$ 24 # Revision 1.7 2003/12/27 16:49:25 uid67467 25 # Should be ok now. 26 # 24 27 # Revision 1.6 2003/12/02 14:40:21 jalet 25 28 # Some code refactoring. … … 45 48 # 46 49 47 from mx import DateTime48 49 50 from pykota.reporter import BaseReporter, PyKotaReporterError 50 51 … … 68 69 self.report.append('-' * len(header)) 69 70 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) 71 72 self.report.append("%-9.9s %s %7i %7s %7s %10s %-10.10s %8i %10s" % (name, reached, pagecounter, soft, hard, balance, datelimit, lifepagecounter, lifetimepaid)) 72 73 total += pages -
pykota/trunk/pykota/requester.py
r1219 r1240 22 22 # 23 23 # $Log$ 24 # Revision 1.11 2003/12/27 16:49:25 uid67467 25 # Should be ok now. 26 # 24 27 # Revision 1.10 2003/11/25 23:46:40 jalet 25 28 # Don't try to verify if module name is valid, Python does this better than us. … … 75 78 raise PyKotaRequesterError, _("Unsupported requester backend %s") % backend 76 79 else : 77 return getattr(requesterbackend, "Requester")(printername, args)80 return requesterbackend.Requester(printername, args) -
pykota/trunk/pykota/storage.py
r1219 r1240 22 22 # 23 23 # $Log$ 24 # Revision 1.29 2003/12/27 16:49:25 uid67467 25 # Should be ok now. 26 # 24 27 # Revision 1.28 2003/11/25 23:46:40 jalet 25 28 # Don't try to verify if module name is valid, Python does this better than us. … … 248 251 self.HardLimit = None 249 252 self.DateLimit = None 253 self.ParentPrintersUserPQuota = (user.Exists and printer.Exists and parent.getParentPrintersUserPQuota(self)) or [] 250 254 251 255 def setDateLimit(self, datelimit) : … … 268 272 def increasePagesUsage(self, nbpages) : 269 273 """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) + nbpages273 newlifepagecounter = int(self.LifePageCounter or 0) + nbpages274 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, msg282 else :283 self.parent.commitTransaction()284 self.PageCounter = newpagecounter285 self.LifePageCounter = newlifepagecounter274 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() 286 290 287 291 class StorageGroupPQuota(StorageObject) : … … 344 348 self.tool.logdebug("Caching enabled.") 345 349 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 !" 346 354 347 355 def __del__(self) : … … 441 449 return user.Groups 442 450 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 443 458 def openConnection(pykotatool) : 444 459 """Returns a connection handle to the appropriate Quota Storage Database.""" … … 454 469 admin = backendinfo["storageadmin"] or backendinfo["storageuser"] 455 470 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) 457 472 -
pykota/trunk/pykota/storages/ldapstorage.py
r1228 r1240 22 22 # 23 23 # $Log$ 24 # Revision 1.41 2003/12/27 16:49:25 uid67467 25 # Should be ok now. 26 # 24 27 # Revision 1.40 2003/11/29 22:02:14 jalet 25 28 # Don't try to retrieve the user print quota information if current printer … … 166 169 # 167 170 171 import types 168 172 import time 169 173 import md5 … … 211 215 return md5.md5("%s" % time.time()).hexdigest() 212 216 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 213 227 def beginTransaction(self) : 214 228 """Starts a transaction.""" … … 237 251 def doAdd(self, dn, fields) : 238 252 """Adds an entry in the LDAP directory.""" 253 fields = self.normalizeFields(fields) 239 254 try : 240 255 self.tool.logdebug("QUERY : ADD(%s, %s)" % (dn, str(fields))) … … 255 270 def doModify(self, dn, fields, ignoreold=1) : 256 271 """Modifies an entry in the LDAP directory.""" 272 fields = self.normalizeFields(fields) 257 273 try : 258 274 oldentry = self.doSearch("objectClass=*", base=dn, scope=ldap.SCOPE_BASE) … … 545 561 return groupsandquotas 546 562 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 547 574 def addPrinter(self, printername) : 548 575 """Adds a printer to the quota storage, returns it.""" … … 679 706 """Sets the date limit permanently for a user print quota.""" 680 707 fields = { 681 "pykotaDateLimit" : "%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second),708 "pykotaDateLimit" : datelimit, 682 709 } 683 710 return self.doModify(userpquota.ident, fields) … … 686 713 """Sets the date limit permanently for a group print quota.""" 687 714 fields = { 688 "pykotaDateLimit" : "%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second),715 "pykotaDateLimit" : datelimit, 689 716 } 690 717 return self.doModify(grouppquota.ident, fields) -
pykota/trunk/pykota/storages/pgstorage.py
r1228 r1240 22 22 # 23 23 # $Log$ 24 # Revision 1.25 2003/12/27 16:49:25 uid67467 25 # Should be ok now. 26 # 24 27 # Revision 1.24 2003/11/29 22:02:14 jalet 25 28 # Don't try to retrieve the user print quota information if current printer … … 392 395 return groupsandquotas 393 396 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 394 408 def addPrinter(self, printername) : 395 409 """Adds a printer to the quota storage, returns it.""" … … 468 482 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))) 469 483 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))) 471 485 else : 472 486 # here we explicitly want to reset jobsize to NULL if needed -
pykota/trunk/pykota/tool.py
r1229 r1240 22 22 # 23 23 # $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 # 24 30 # Revision 1.64 2003/11/29 22:03:17 jalet 25 31 # Some code refactoring work. New code is not used at this time. … … 288 294 self.documentation = doc 289 295 self.config = config.PyKotaConfig("/etc/pykota") 290 self.logger = logger.openLogger(self , self.config.getLoggingBackend())296 self.logger = logger.openLogger(self.config.getLoggingBackend()) 291 297 self.debug = self.config.getDebug() 292 298 self.storage = storage.openConnection(self) … … 574 580 self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage) 575 581 if mailto in [ "BOTH", "USER", "EXTERNAL" ] : 582 message = self.config.getHardWarn(printer.Name) 576 583 for user in self.storage.getGroupMembers(group) : 577 584 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) 579 586 else : 580 587 self.externalMailTo(arguments, action, user, printer, message) … … 599 606 """Checks a user quota and send him a message if quota is exceeded on current printer.""" 600 607 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" 634 654 635 655 class PyKotaFilterOrBackend(PyKotaTool) : … … 651 671 self.username = self.username.lower() 652 672 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 653 683 self.accounter = accounter.openAccounter(self) 654 684 … … 683 713 while destination.startswith("/") : 684 714 destination = destination[1:] 715 checkauth = destination.split("@", 1) 716 if len(checkauth) == 2 : 717 destination = checkauth[1] 685 718 printerhostname = destination.split("/")[0].split(":")[0] 686 719 return ("CUPS", \ … … 737 770 was returned by the external command. 738 771 """ 739 for passnumberin range(1, 3) :772 for dummy in range(1, 3) : 740 773 printer = self.storage.getPrinter(self.printername) 741 774 user = self.storage.getUser(self.username) -
pykota/trunk/pykota/version.py
r1239 r1240 22 22 # 23 23 24 __version__ = "1.16alpha 17_unofficial"24 __version__ = "1.16alpha20_unofficial" 25 25 26 26 __doc__ = """PyKota : a complete Printing Quota Solution for CUPS and LPRng.""" -
pykota/trunk/setup.py
r1226 r1240 24 24 # 25 25 # $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 # 26 33 # Revision 1.27 2003/11/28 08:31:28 jalet 27 34 # Shell script to wait for AppleTalk enabled printers being idle was added. … … 338 345 url = "http://www.librelogiciel.com/software/", 339 346 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" ], 341 348 data_files = data_files) 342 349