Projet

Général

Profil

Télécharger (8,16 ko) Statistiques
| Branche: | Révision:

root / larpe / tags / release-1.1.1 / larpe / idwsf2.ptl @ d03cb81c

1
import os
2
import sys
3
import re
4

    
5
try:
6
    import lasso
7
except ImportError:
8
    print >> sys.stderr, 'Missing Lasso module, IdWsf 2.0 support disabled'
9
else:
10
    if not lasso.WSF_SUPPORT:
11
        print >> sys.stderr, 'Found Lasso module, but IdWsf 2.0 support not enabled'
12

    
13
from quixote import get_publisher, get_session, get_request, get_response, redirect
14
from quixote.directory import Directory
15

    
16
from qommon.liberty import SOAPException, soap_call
17
from qommon import template
18
from qommon.misc import http_get_page
19

    
20
import misc
21
from form_prefill import FormPrefill
22
from field_prefill import FieldPrefill
23

    
24
def cleanup_html_value(value):
25
    # Ensure the field value can be properly integrated in HTML code
26
    value = value.replace('"', "'")
27
    # Conversion to iso-8859-1
28
    try:
29
        value = unicode(value, 'utf-8').encode('iso-8859-1')
30
    except UnicodeEncodeError:
31
        return None
32

    
33
class IdWsf2(Directory):
34
    _q_exports = []
35

    
36
    def _q_lookup(self, component):
37
        if not hasattr(get_session(), 'prefill_form'):
38
            get_session().prefill_form = component
39
            get_session().after_url = get_request().get_url()
40
            if get_request().get_query():
41
                get_session().after_url += '?' + get_request().get_query()
42
            return redirect('../saml/login')
43
        else:
44
            prefill_form = FormPrefill.get(get_session().prefill_form)
45
            del get_session().prefill_form
46
            if prefill_form:
47
                try:
48
                    response, status, page, auth_header = http_get_page(prefill_form.url)
49
                except:
50
                    return template.error_page(_('Failed connecting to the original site.'))
51
                try:
52
                    fields = self.do_prefill_form(prefill_form)
53
                    if not fields:
54
                        raise lasso.Error
55
                    for key, value in get_request().get_fields().iteritems():
56
                        value = cleanup_html_value(value)
57
                        if value:
58
                            fields[key] = value
59
                except lasso.Error:
60
                    return page + '<script type="text/javascript">alert("%s")</script>' % \
61
                         _('Failed getting attributes from the attribute provider.')
62
                except:
63
                    return page + '<script type="text/javascript">alert("%s")</script>' % \
64
                         _('Failed getting attributes for an unknown reason.')
65

    
66
                return self.send_prefilled_form(prefill_form, page, fields)
67

    
68
    def do_prefill_form(self, prefill_form):
69
        server = misc.get_lasso_server(protocol = 'saml2')
70
        disco = lasso.IdWsf2Discovery(server)
71
        if not get_session().lasso_session_dumps or not get_session().lasso_session_dumps[server.providerId]:
72
            return None
73
        disco.setSessionFromDump(get_session().lasso_session_dumps[server.providerId])
74

    
75
        disco.initQuery()
76
        disco.addRequestedServiceType(prefill_form.profile)
77
        disco.buildRequestMsg()
78

    
79
        try:
80
            soap_answer = soap_call(disco.msgUrl, disco.msgBody)
81
        except SOAPException:
82
            return None
83
        disco.processQueryResponseMsg(soap_answer)
84

    
85
        service = disco.getService()
86
        lasso.registerIdWsf2DstService(prefill_form.prefix, prefill_form.profile)
87

    
88
        service.initQuery()
89

    
90
        fields = FieldPrefill.select(lambda x: x.form_id == prefill_form.id)
91
        for field in fields:
92
            if field.xpath and field.name:
93
                service.addQueryItem(field.xpath, field.name)
94

    
95
        service.buildRequestMsg()
96

    
97
        try:
98
            soap_answer = soap_call(service.msgUrl, service.msgBody)
99
        except SOAPException:
100
            return None
101
        service.processQueryResponseMsg(soap_answer)
102

    
103
        fields_dict = {}
104
        for field in fields:
105
            if not field.xpath or not field.name:
106
                continue
107
            if field.number > 0:
108
                number = field.number -1
109
            try:
110
                if field.raw_xml:
111
                    value = service.getAttributeNodes(field.name)[number]
112
                else:
113
                    value = service.getAttributeStrings(field.name)[number]
114
            except (IndexError, TypeError):
115
                value = ''
116
                # Log
117
            if value:
118
                # Regexp transformation
119
                if field.regexp_match:
120
                    value = re.sub(field.regexp_match, field.regexp_replacing, value)
121
                value = cleanup_html_value(value)
122
                # Conversion of select field options
123
                if field.select_options:
124
                    try:
125
                        value = field.select_options[value]
126
                    except (IndexError, KeyError):
127
                        pass
128
                if not value:
129
                    continue
130
            fields_dict[field.name] = value
131

    
132
        return fields_dict
133

    
134
    def send_prefilled_form(self, prefill_form, page, fields):
135
        for field_name, new_value in fields.iteritems():
136
            # Input
137
            regex = re.compile('(.*)(<input[^>]*? id="%s".*?>)(.*)' % field_name,
138
                               re.DOTALL | re.IGNORECASE)
139
            match = regex.match(page)
140
            if not match:
141
                regex = re.compile('(.*)(<input[^>]*? name="%s".*?>)(.*)' % field_name,
142
                                   re.DOTALL | re.IGNORECASE)
143
                match = regex.match(page)
144
            if match:
145
                before, input_field, after = match.groups()
146
                if 'value="' in input_field.lower():
147
                    regex_sub = re.compile('value=".*?"', re.DOTALL | re.IGNORECASE)
148
                    input_field = regex_sub.sub('value="%s"' % new_value, input_field)
149
                else:
150
                    input_field = input_field.replace('<input', '<input value="%s"' % new_value)
151
                page = ''.join([before, input_field, after])
152
                continue
153

    
154
            # Textarea
155
            regex = re.compile('(.*<textarea[^>]*? id="%s".*?>)[^<]*(</textarea>.*)' % field_name,
156
                               re.DOTALL | re.IGNORECASE)
157
            match = regex.match(page)
158
            if not match:
159
                regex = re.compile('(.*<textarea[^>]*? name="%s".*?>)[^<]*(</textarea>.*)' % field_name,
160
                                   re.DOTALL | re.IGNORECASE)
161
                match = regex.match(page)
162
            if match:
163
                before, after = match.groups()
164
                page = ''.join([before, new_value, after])
165
                continue
166

    
167
            # Select
168
            regex = re.compile('(.*<select[^>]*? id="%s".*?>)(.*?)(</select>.*)' % field_name,
169
                               re.DOTALL | re.IGNORECASE)
170
            match = regex.match(page)
171
            if not match:
172
                regex = re.compile('(.*<select[^>]*? name="%s".*?>)(.*?)(</select>.*)' % field_name,
173
                                   re.DOTALL | re.IGNORECASE)
174
                match = regex.match(page)
175
            if match:
176
                before, options, after = match.groups()
177
                # If the option to select is found, first unselect the previoulsy selected one
178
                regex2 = re.compile('(.*<option[^>]*? value="%s".*?)(>[^<]*</option>.*)' % new_value,
179
                               re.DOTALL | re.IGNORECASE)
180
                match2 = regex2.match(options)
181
                if match2:
182
                    before2, after2 = match2.groups()
183
                    regex3 = re.compile('(.*<option[^>]*?)( selected(="selected")?)(.*?>[^<]*</option>.*)',
184
                               re.DOTALL | re.IGNORECASE)
185
                    match3 = regex3.match(options)
186
                    if match3:
187
                        before3, selected, selected_value, after3 = match3.groups()
188
                        options = ''.join([before3, after3])
189
                regex2 = re.compile('(.*<option[^>]*? value="%s".*?)(>[^<]*</option>.*)' % new_value,
190
                    re.DOTALL | re.IGNORECASE)
191
                match2 = regex2.match(options)
192
                if match2:
193
                    before2, after2 = match2.groups()
194
                    options = ''.join([before2, ' selected="selected"', after2])
195

    
196
                page = ''.join([before, options, after])
197

    
198
        return page
199

    
(8-8/19)