#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
#
# Univention Print Quota
#  helper script: set print quota for a user
#
# Copyright 2004-2014 Univention GmbH
#
# http://www.univention.de/
#
# All rights reserved.
#
# The source code of this program is made available
# under the terms of the GNU Affero General Public License version 3
# (GNU AGPL V3) as published by the Free Software Foundation.
#
# Binary versions of this program provided by Univention to you as
# well as other copyrighted, protected or trademarked materials like
# Logos, graphics, fonts, specific documentations and configurations,
# cryptographic keys etc. are subject to a license agreement between
# you and Univention and not subject to the GNU AGPL V3.
#
# In the case you use this program under the terms of the GNU AGPL V3,
# the program is provided 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License with the Debian GNU/Linux or Univention distribution in file
# /usr/share/common-licenses/AGPL-3; if not, see
# <http://www.gnu.org/licenses/>.

import sys
import syslog
import os
import ldap
from ldap.filter import escape_filter_chars
import univention.uldap
import univention.config_registry
from univention.config_registry.interfaces import Interfaces

bc = univention.config_registry.ConfigRegistry()
bc.load()

syslog.openlog('PyKota/univention-printquota-setuser')

debuglevel = 1
def log(level, message):
	if debuglevel >= level:
		syslog.syslog(message)

def callEdpykota(options):
	log(2, "call edpykota: %s" % options)
	if debuglevel > 2:
		rval = os.system("/usr/bin/edpykota %s 2>&1 | logger -t PyKota/univention-printquota-setuser" % (options))
	else:
		rval = os.system("/usr/bin/edpykota %s > /dev/null 2>&1" % (options))
	if not rval == 0:
		log(1, "WARNING: edpykota returned with %s" % rval)

def set_quota(printer, who, soft, hard, group=0):
	arg=''
	if group == 1:
		arg="-g"
	if s_limit=='0' and h_limit=='0':
		callEdpykota("--add %s --printer %s --noquota %s" % (arg,printer, who))
	else:
		callEdpykota("--add %s --printer %s --softlimit %s --hardlimit %s %s" % (arg,printer, soft, hard, who))

if bc.get('pykota/policy/debug'):
	try:
		debuglevel = int(bc['pykota/policy/debug'])
		log(3, "debug level set to %s" % debuglevel)
	except (LookupError, ValueError):
		log(0, "failed to set debug-level from univention-config-registry")

try:
	usr_filter = sys.argv[1]
	prt_filter = sys.argv[2]
except IndexError:
	log(0, 'exit, too few arguments, need username and printer')
	sys.exit('Too few arguments, need username and printer')

lo = univention.uldap.getMachineConnection(secret_file="/etc/pykota.secret", ldap_master=False)
try:
	user_dn,attrs=lo.search('(&(objectClass=person)(uid=%s))' % usr_filter, required=1, unique=1, attr=['uid'])[0]
except:
	log(1, "WARNING: Exception while searching for user-dn")
	pass

groups={}
try:
	for group_dn in lo.search('(&(objectClass=univentionGroup)(uniquemember=%s))' % user_dn):
		groups[group_dn[1]['cn'][0]]=''
except:
	log(0, "exit, Unknown User")
	sys.exit('Unknown User')

has_groupquota = False
has_userquota = False

##### Printergroups ######
# set quota for user or his groups in all printergroups
try:
	entries = lo.search('(&(objectClass=univentionPrinterGroup)(univentionPrinterGroupMember=%s))' % prt_filter)
except:
	entries = []
for entry in entries:
	prt_grp_dn=entry[0]
	if entry[1]['univentionPrinterQuotaSupport'][0] != '0':
		prt_grp_name=entry[1]['cn'][0]
		policies = lo.getPolicies(prt_grp_dn).get('univentionPolicySharePrintQuota', {})
		if policies.has_key('univentionPrintQuotaGroups'):
			for entry in policies['univentionPrintQuotaGroups']['value']:
				s_limit, h_limit, grp=entry.split(' ',2)
				if groups.has_key(grp):
					grp="\"%s\""%grp
					set_quota(prt_grp_name, grp, s_limit, h_limit, 1)
					callEdpykota("--add --printer %s %s" % (prt_grp_name, usr_filter))
					has_groupquota = True
		if policies.has_key('univentionPrintQuotaUsers'):
			for entry in policies['univentionPrintQuotaUsers']['value']:
				s_limit, h_limit, usr=entry.split(' ',2)
				if usr == usr_filter:
					set_quota(prt_grp_name, usr, s_limit, h_limit)
					has_userquota = True
		if policies.has_key('univentionPrintQuotaGroupsPerUsers'):
			for entry in policies['univentionPrintQuotaGroupsPerUsers']['value']:
				s_limit, h_limit, grp=entry.split(' ',2)
				if groups.has_key(grp):
					set_quota(prt_grp_name, usr_filter, s_limit, h_limit)

###### single Printers ######
prt_policies = {}
try:
	interfaces = Interfaces(bc)
	default_addr = interfaces.get_default_ip_address()
	ldap_filter = '(&%s)' % ''.join((
		'(objectClass=univentionPrinter)',
		'(|%s)' % ''.join((
			'(univentionPrinterSpoolHost=%(hostname)s.%(domainname)s)' % bc,
			'(univentionPrinterSpoolHost=%s)' % (default_addr.ip,),
			)),
		'(cn=%s)' % (escape_filter_chars(prt_filter),),
		))
	dn, attrs = lo.search(ldap_filter, required=1, unique=1)[0]
	prt_policies = lo.getPolicies(dn).get('univentionPolicySharePrintQuota', {})
except ldap.INAPPROPRIATE_MATCHING:
	log(1, "WARNING: poilicy-result failed, maybe more than one printer found")
except:
	log(1, "WARNING: poilicy-result failed")

#if not has_groupquota: # = False
if prt_policies.has_key('univentionPrintQuotaGroups'):
	for entry in prt_policies['univentionPrintQuotaGroups']['value']:
		s_limit, h_limit, grp=entry.split(' ',2)
		if groups.has_key(grp):
			grp="\"%s\""%grp
			set_quota(prt_filter, grp, s_limit, h_limit, 1)
			has_groupquota = True

#if not has_userquota: # = False
if prt_policies.has_key('univentionPrintQuotaUsers'):
	for entry in prt_policies['univentionPrintQuotaUsers']['value']:
		s_limit, h_limit, usr=entry.split(' ',2)
		if usr == usr_filter:
			set_quota(prt_filter, usr, s_limit, h_limit)
			has_userquota = True

if prt_policies.has_key('univentionPrintQuotaGroupsPerUsers'):
	for entry in prt_policies['univentionPrintQuotaGroupsPerUsers']['value']:
		s_limit, h_limit, grp=entry.split(' ',2)
		if groups.has_key(grp):
			set_quota(prt_filter, usr_filter, s_limit, h_limit)
			has_userquota = True


if not has_userquota and has_groupquota:
	callEdpykota("--add --printer %s %s" % (prt_filter, usr_filter))

if not has_userquota and not has_groupquota and bc['cups/quota/inform'] == 'yes':
	message="you are not allowed to use this printer."
	address = lo.get(user_dn).get('mailPrimaryAddress', {})[0]
	os.system("/bin/echo -e \"%s\n\nprinter: %s\" | /usr/bin/mail -s \"printquota message regarding %s\" %s"%(message,prt_filter,prt_filter,address))
	log(3, "user is not allowed to use printer, send warning")
