def respond(self, body):
		"""Write the response body to the client. Convert it into UMCP format."""

		CORE.info('Writing response...')
		message = self.responseHeaders.getRawHeaders('X-UMC-Message')
		message = json.loads(message and message[0] or '""')

		if not isinstance(body, dict):
			body = dict(result=body)

		data = dict(
			message=message,
			status=self.code,
		)
		data.update(body)

		body = json.dumps(data)
		self.setHeader('Content-Type', 'application/json')
		self.setHeader('Content-Length', '%d' % (len(body),))

		if self.is_iframe_upload:
			# this is a workaround to make iframe uploads work, they need the textarea field
			# TODO: break API: remove
			self.setHeader('Content-Type', 'text/html; charset=UTF-8')
			body = b'<html><body><textarea>%s</textarea></body></html>' % (body,)

		self.write(body)
		self.finish()
	def __check_min_free_space_on_partition(self, filename):
		# check if enough free space is available
		sfs = statvfs(filename)
		free_disk_space = sfs.f_bavail * sfs.f_frsize / 1024  # kilobyte
		if free_disk_space < self.min_free_space:
			CORE.error('There is not enough free space to upload files.')
			self.setResponseCode(400)
			raise ValueError('There is not enough free space on disk.')
	def single_sign_on(self, token):
		"""Authenticate the client by given single sign on token"""
		session = self.single_sign_on.sessions.pop(token, None)
		if not session:
			CORE.warn('Unknown SSO token: %r' % (token,))
			return False

		self.__store_ip_in_session()
		expiration = get_expiration()
		user = self.getSession(User)
		self.addCookie('UMCSessionId', session.uid, path='/', expires=expiration)
		self.addCookie('UMCUsername', user.username, path='/', expires=expiration)
		return True
	def render(self, request):
		request.single_sign_on(request.args.get('loginToken'))

		targeturl = '/univention-management-console/'
		query = dict((arg, value) for arg, value in request.args.iteritems() if arg not in ('loginToken', 'username', 'password'))
		if query:
			# HTTP FIXME: Location header does not allow a querystring in its URI
			# command/lib/sso should be fixed to add e.g. language settings
			targeturl += '?%s' % urlencode(query)

		CORE.info('Redirecting to %s' % (targeturl))
		request.responseHeaders.addRawHeader('Location', targeturl)
		request.setResponseCode(303)
	def render(self, request):
		user = request.getSession(User).user
		if not user:
			request.setResponseCode(BAD_REQUEST_INVALID_OPTS)  # HTTP FIXME
			return

		preferences = dict(self._get_preferences(request))
		new_preferences = dict(user.info.get('umcProperty', []))
		new_preferences.update(preferences)
		user.info['umcProperty'] = new_preferences.items()

		try:
			user.modify()
		except (udm_errors.base) as err:
			CORE.warn('Could not set given option: %s' % err)
			request.setResponseCode(BAD_REQUEST_INVALID_OPTS)  # HTTP FIXME
	def render(self, resource):
		"""Renders identified resource and write response"""

		CORE.info('Rendering resource...')
		try:
			body = resource.render(self)
		except NotAuthenticated:
			body = None
			self.setResponseCode(BAD_REQUEST_UNAUTH)  # HTTP FIXME
		except UnsupportedMethod:
			Request.render(self, resource)  # use twisteds error handling
			return

		if body is NOT_DONE_YET:
			return

		self.respond(body)
	def render(self, request):
		lo, po = get_machine_connection()
		if not lo:
			# unjoined / no LDAP connection
			return []

		try:
			domaincontrollers = lo.search(filter="(objectClass=univentionDomainController)")
		except LDAPError as exc:
			CORE.warn('Could not search for domaincontrollers: %s' % (exc))
			return []

		hosts = [
			'%s.%s' % (computer['cn'][0], computer['associatedDomain'][0])
			for dn, computer in domaincontrollers
			if computer.get('associatedDomain')
		]
		hosts.sort()
		return dict(result=hosts)
	def requestReceived(self, command, path, version):
		"""Processes the self"""
		CORE.info('Receiving request...')
		try:
			# prevent twisted's processing by lowercasing method
			Request.requestReceived(self, command.lower(), path, version)
		finally:
			self.method = command

		# fix twisted's query string processing
		self.__fix_twisted_query_string()
		self.site = self.channel.site

		self._set_default_response_headers()

		try:
			CORE.info('Parse request body...')
			self._parse_request_payload()
		except ValueError as err:
			self.respond(bytes(err))
			return

		self._set_default_request_headers()

		CORE.info('Authenticate? ...')
		self._authenticate_and_process()
	def render(self, request):
		session = request.getSession()
		acls = ACLs(session)
		moduleManager = request.site.moduleManager

		command = '/'.join(request.prepath[1:])

		module_name = acls.get_module_providing(moduleManager, command)
		if not module_name:
			MODULE.warn('No module provides %s' % (command))
			request.setResponseCode(BAD_REQUEST_FORBIDDEN)
			return

		MODULE.info('Checking ACLs for %s (%s)' % (command, module_name))
		if not acls.is_command_allowed(request, command):
			MODULE.warn('Command %s is not allowed' % (command))
			request.setResponseCode(BAD_REQUEST_FORBIDDEN)
			return

		methodname = acls.get_method_name(moduleManager, module_name, command)
		if not methodname:
			MODULE.warn('Command %s does not exists' % (command))
			request.setResponseCode(BAD_REQUEST_NOT_FOUND)
			return

		headers = self.get_request_header(request, methodname)
		body = self.get_request_body(request)

		CORE.info('Passing new request to module %s' % (module_name,))
		process = self.get_process(session, module_name)

		urequest = process.request(request.method, request.uri, headers, body)
		urequest.addCallback(self.respond, request)
		urequest.addErrback(self.failed_request, request)

		return NOT_DONE_YET
	def __check_max_file_size(self, filename):
		st_size = stat(filename).st_size
		if st_size > self.max_upload_size:
			CORE.warn('File of size %d could not be uploaded' % (st_size))
			self.setResponseCode(400)  # HTTP FIXME: 413 entity too large
			raise ValueError('The size of the uploaded file is too large.')
		def _continue_request():
			CORE.info('Dispatch request ...')
			Request.process(self)
	def set_log_level(self, level):
		CORE.process('Set log level to %d' % level)
		set_log_level(level)
	def failed_request(self, failure, request):
		request.setResponseCode(500)
		request.setHeader('X-UMC-Message', json.dumps(failure.getTraceback()))
		request.respond(dict(result=failure.getErrorMessage()))
		CORE.error('failed_request: %s: %s' % (failure.getErrorMessage(), failure.getTraceback()))
	import sys
	import os.path
	from univention.umc.server import ServerDaemon
	from univention.umc.module import ModuleDaemon

	name = os.path.basename(sys.argv[0])
	try:
		Daemon = {
			'umc-server': ServerDaemon,
			'univention-management-console-server': ServerDaemon,
			'umc-module': ModuleDaemon,
			'univention-management-console-module': ModuleDaemon,
		}[name]
	except KeyError:
		import sys
		raise SystemExit('use umc-server or umc-module! not %s' % sys.argv[0])
	else:
		Daemon()


if __name__ == '__main__':
	try:
		main()
	except (SystemExit, KeyboardInterrupt):
		raise
	except:
		import traceback
		from univention.umc.util import CORE
		CORE.error(traceback.format_exc())
		raise