This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
larpe/larpe/tags/release-1.1.1/larpe/idwsf2.ptl

200 lines
8.2 KiB
Plaintext

import os
import sys
import re
try:
import lasso
except ImportError:
print >> sys.stderr, 'Missing Lasso module, IdWsf 2.0 support disabled'
else:
if not lasso.WSF_SUPPORT:
print >> sys.stderr, 'Found Lasso module, but IdWsf 2.0 support not enabled'
from quixote import get_publisher, get_session, get_request, get_response, redirect
from quixote.directory import Directory
from qommon.liberty import SOAPException, soap_call
from qommon import template
from qommon.misc import http_get_page
import misc
from form_prefill import FormPrefill
from field_prefill import FieldPrefill
def cleanup_html_value(value):
# Ensure the field value can be properly integrated in HTML code
value = value.replace('"', "'")
# Conversion to iso-8859-1
try:
value = unicode(value, 'utf-8').encode('iso-8859-1')
except UnicodeEncodeError:
return None
class IdWsf2(Directory):
_q_exports = []
def _q_lookup(self, component):
if not hasattr(get_session(), 'prefill_form'):
get_session().prefill_form = component
get_session().after_url = get_request().get_url()
if get_request().get_query():
get_session().after_url += '?' + get_request().get_query()
return redirect('../saml/login')
else:
prefill_form = FormPrefill.get(get_session().prefill_form)
del get_session().prefill_form
if prefill_form:
try:
response, status, page, auth_header = http_get_page(prefill_form.url)
except:
return template.error_page(_('Failed connecting to the original site.'))
try:
fields = self.do_prefill_form(prefill_form)
if not fields:
raise lasso.Error
for key, value in get_request().get_fields().iteritems():
value = cleanup_html_value(value)
if value:
fields[key] = value
except lasso.Error:
return page + '<script type="text/javascript">alert("%s")</script>' % \
_('Failed getting attributes from the attribute provider.')
except:
return page + '<script type="text/javascript">alert("%s")</script>' % \
_('Failed getting attributes for an unknown reason.')
return self.send_prefilled_form(prefill_form, page, fields)
def do_prefill_form(self, prefill_form):
server = misc.get_lasso_server(protocol = 'saml2')
disco = lasso.IdWsf2Discovery(server)
if not get_session().lasso_session_dumps or not get_session().lasso_session_dumps[server.providerId]:
return None
disco.setSessionFromDump(get_session().lasso_session_dumps[server.providerId])
disco.initQuery()
disco.addRequestedServiceType(prefill_form.profile)
disco.buildRequestMsg()
try:
soap_answer = soap_call(disco.msgUrl, disco.msgBody)
except SOAPException:
return None
disco.processQueryResponseMsg(soap_answer)
service = disco.getService()
lasso.registerIdWsf2DstService(prefill_form.prefix, prefill_form.profile)
service.initQuery()
fields = FieldPrefill.select(lambda x: x.form_id == prefill_form.id)
for field in fields:
if field.xpath and field.name:
service.addQueryItem(field.xpath, field.name)
service.buildRequestMsg()
try:
soap_answer = soap_call(service.msgUrl, service.msgBody)
except SOAPException:
return None
service.processQueryResponseMsg(soap_answer)
fields_dict = {}
for field in fields:
if not field.xpath or not field.name:
continue
if field.number > 0:
number = field.number -1
try:
if field.raw_xml:
value = service.getAttributeNodes(field.name)[number]
else:
value = service.getAttributeStrings(field.name)[number]
except (IndexError, TypeError):
value = ''
# Log
if value:
# Regexp transformation
if field.regexp_match:
value = re.sub(field.regexp_match, field.regexp_replacing, value)
value = cleanup_html_value(value)
# Conversion of select field options
if field.select_options:
try:
value = field.select_options[value]
except (IndexError, KeyError):
pass
if not value:
continue
fields_dict[field.name] = value
return fields_dict
def send_prefilled_form(self, prefill_form, page, fields):
for field_name, new_value in fields.iteritems():
# Input
regex = re.compile('(.*)(<input[^>]*? id="%s".*?>)(.*)' % field_name,
re.DOTALL | re.IGNORECASE)
match = regex.match(page)
if not match:
regex = re.compile('(.*)(<input[^>]*? name="%s".*?>)(.*)' % field_name,
re.DOTALL | re.IGNORECASE)
match = regex.match(page)
if match:
before, input_field, after = match.groups()
if 'value="' in input_field.lower():
regex_sub = re.compile('value=".*?"', re.DOTALL | re.IGNORECASE)
input_field = regex_sub.sub('value="%s"' % new_value, input_field)
else:
input_field = input_field.replace('<input', '<input value="%s"' % new_value)
page = ''.join([before, input_field, after])
continue
# Textarea
regex = re.compile('(.*<textarea[^>]*? id="%s".*?>)[^<]*(</textarea>.*)' % field_name,
re.DOTALL | re.IGNORECASE)
match = regex.match(page)
if not match:
regex = re.compile('(.*<textarea[^>]*? name="%s".*?>)[^<]*(</textarea>.*)' % field_name,
re.DOTALL | re.IGNORECASE)
match = regex.match(page)
if match:
before, after = match.groups()
page = ''.join([before, new_value, after])
continue
# Select
regex = re.compile('(.*<select[^>]*? id="%s".*?>)(.*?)(</select>.*)' % field_name,
re.DOTALL | re.IGNORECASE)
match = regex.match(page)
if not match:
regex = re.compile('(.*<select[^>]*? name="%s".*?>)(.*?)(</select>.*)' % field_name,
re.DOTALL | re.IGNORECASE)
match = regex.match(page)
if match:
before, options, after = match.groups()
# If the option to select is found, first unselect the previoulsy selected one
regex2 = re.compile('(.*<option[^>]*? value="%s".*?)(>[^<]*</option>.*)' % new_value,
re.DOTALL | re.IGNORECASE)
match2 = regex2.match(options)
if match2:
before2, after2 = match2.groups()
regex3 = re.compile('(.*<option[^>]*?)( selected(="selected")?)(.*?>[^<]*</option>.*)',
re.DOTALL | re.IGNORECASE)
match3 = regex3.match(options)
if match3:
before3, selected, selected_value, after3 = match3.groups()
options = ''.join([before3, after3])
regex2 = re.compile('(.*<option[^>]*? value="%s".*?)(>[^<]*</option>.*)' % new_value,
re.DOTALL | re.IGNORECASE)
match2 = regex2.match(options)
if match2:
before2, after2 = match2.groups()
options = ''.join([before2, ' selected="selected"', after2])
page = ''.join([before, options, after])
return page