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 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, 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 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 _continue_request():
			CORE.info('Dispatch request ...')
			Request.process(self)