1
|
from quixote import get_publisher
|
2
|
|
3
|
import cPickle
|
4
|
import re
|
5
|
import lasso
|
6
|
import os
|
7
|
import time
|
8
|
|
9
|
global cfg
|
10
|
cfg = {
|
11
|
'sp': {
|
12
|
'metadata': 'metadata.xml',
|
13
|
'privatekey': 'private-key.pem',
|
14
|
},
|
15
|
'idp': {
|
16
|
'idp1' : {
|
17
|
'metadata': 'idp-http-localhost-liberty-metadata-metadata.xml',
|
18
|
'publickey': 'idp-http-localhost-liberty-metadata-publickey.pem',
|
19
|
},
|
20
|
},
|
21
|
}
|
22
|
|
23
|
def get_abs_path(s):
|
24
|
if not s:
|
25
|
return s
|
26
|
if s[0] == '/':
|
27
|
return s
|
28
|
return os.path.join(get_publisher().app_dir, s)
|
29
|
|
30
|
def get_lasso_server(protocol = 'liberty'):
|
31
|
reload_cfg()
|
32
|
if not cfg.has_key('sp'):
|
33
|
return None
|
34
|
if protocol == 'liberty':
|
35
|
server = lasso.Server(
|
36
|
get_abs_path(cfg['sp']['metadata']),
|
37
|
get_abs_path(cfg['sp']['privatekey']),
|
38
|
None, None)
|
39
|
elif protocol == 'saml2' and cfg['sp'].has_key('saml2_metadata'):
|
40
|
server = lasso.Server(
|
41
|
get_abs_path(cfg['sp']['saml2_metadata']),
|
42
|
get_abs_path(cfg['sp']['privatekey']),
|
43
|
None, None)
|
44
|
else:
|
45
|
raise 'XXX: unknown protocol'
|
46
|
for idp in cfg.get('idp', {}).values():
|
47
|
try:
|
48
|
server.addProvider(
|
49
|
lasso.PROVIDER_ROLE_IDP,
|
50
|
get_abs_path(idp['metadata']),
|
51
|
get_abs_path(idp['publickey']),
|
52
|
get_abs_path(idp.get('cacertchain')))
|
53
|
except lasso.Error, error:
|
54
|
if error[0] == -203: # protocol mismatch
|
55
|
continue
|
56
|
if error[0] == -202: # failed to add new provider
|
57
|
continue
|
58
|
raise
|
59
|
|
60
|
return server
|
61
|
|
62
|
def get_provider_label(provider):
|
63
|
if not provider:
|
64
|
return None
|
65
|
if not hasattr(provider, str('getOrganization')):
|
66
|
return provider.providerId
|
67
|
|
68
|
organization = provider.getOrganization()
|
69
|
if not organization:
|
70
|
return provider.providerId
|
71
|
|
72
|
name = re.findall("<OrganizationDisplayName.*>(.*?)</OrganizationDisplayName>", organization)
|
73
|
if not name:
|
74
|
name = re.findall("<OrganizationName.*>(.*?)</OrganizationName>", organization)
|
75
|
if not name:
|
76
|
return provider.providerId
|
77
|
return name[0]
|
78
|
|
79
|
|
80
|
def write_cfg():
|
81
|
s = cPickle.dumps(cfg)
|
82
|
filename = os.path.join(get_publisher().app_dir, 'config.pck')
|
83
|
file(filename, 'w').write(s)
|
84
|
|
85
|
def reload_cfg():
|
86
|
pass
|
87
|
# global cfg
|
88
|
# filename = os.path.join(get_publisher().app_dir, 'config.pck')
|
89
|
# try:
|
90
|
# cfg = cPickle.load(file(filename))
|
91
|
# except:
|
92
|
# cfg = {}
|
93
|
|
94
|
|
95
|
xlate = {
|
96
|
u'\N{ACUTE ACCENT}': "'",
|
97
|
u'\N{BROKEN BAR}': '|',
|
98
|
u'\N{CEDILLA}': '{cedilla}',
|
99
|
u'\N{CENT SIGN}': '{cent}',
|
100
|
u'\N{COPYRIGHT SIGN}': '{C}',
|
101
|
u'\N{CURRENCY SIGN}': '{currency}',
|
102
|
u'\N{DEGREE SIGN}': '{degrees}',
|
103
|
u'\N{DIAERESIS}': '{umlaut}',
|
104
|
u'\N{DIVISION SIGN}': '/',
|
105
|
u'\N{FEMININE ORDINAL INDICATOR}': '{^a}',
|
106
|
u'\N{INVERTED EXCLAMATION MARK}': '!',
|
107
|
u'\N{INVERTED QUESTION MARK}': '?',
|
108
|
u'\N{LATIN CAPITAL LETTER A WITH ACUTE}': 'A',
|
109
|
u'\N{LATIN CAPITAL LETTER A WITH CIRCUMFLEX}': 'A',
|
110
|
u'\N{LATIN CAPITAL LETTER A WITH DIAERESIS}': 'A',
|
111
|
u'\N{LATIN CAPITAL LETTER A WITH GRAVE}': 'A',
|
112
|
u'\N{LATIN CAPITAL LETTER A WITH RING ABOVE}': 'A',
|
113
|
u'\N{LATIN CAPITAL LETTER A WITH TILDE}': 'A',
|
114
|
u'\N{LATIN CAPITAL LETTER AE}': 'Ae',
|
115
|
u'\N{LATIN CAPITAL LETTER C WITH CEDILLA}': 'C',
|
116
|
u'\N{LATIN CAPITAL LETTER E WITH ACUTE}': 'E',
|
117
|
u'\N{LATIN CAPITAL LETTER E WITH CIRCUMFLEX}': 'E',
|
118
|
u'\N{LATIN CAPITAL LETTER E WITH DIAERESIS}': 'E',
|
119
|
u'\N{LATIN CAPITAL LETTER E WITH GRAVE}': 'E',
|
120
|
u'\N{LATIN CAPITAL LETTER ETH}': 'Th',
|
121
|
u'\N{LATIN CAPITAL LETTER I WITH ACUTE}': 'I',
|
122
|
u'\N{LATIN CAPITAL LETTER I WITH CIRCUMFLEX}': 'I',
|
123
|
u'\N{LATIN CAPITAL LETTER I WITH DIAERESIS}': 'I',
|
124
|
u'\N{LATIN CAPITAL LETTER I WITH GRAVE}': 'I',
|
125
|
u'\N{LATIN CAPITAL LETTER N WITH TILDE}': 'N',
|
126
|
u'\N{LATIN CAPITAL LETTER O WITH ACUTE}': 'O',
|
127
|
u'\N{LATIN CAPITAL LETTER O WITH CIRCUMFLEX}': 'O',
|
128
|
u'\N{LATIN CAPITAL LETTER O WITH DIAERESIS}': 'O',
|
129
|
u'\N{LATIN CAPITAL LETTER O WITH GRAVE}': 'O',
|
130
|
u'\N{LATIN CAPITAL LETTER O WITH STROKE}': 'O',
|
131
|
u'\N{LATIN CAPITAL LETTER O WITH TILDE}': 'O',
|
132
|
u'\N{LATIN CAPITAL LETTER THORN}': 'th',
|
133
|
u'\N{LATIN CAPITAL LETTER U WITH ACUTE}': 'U',
|
134
|
u'\N{LATIN CAPITAL LETTER U WITH CIRCUMFLEX}': 'U',
|
135
|
u'\N{LATIN CAPITAL LETTER U WITH DIAERESIS}': 'U',
|
136
|
u'\N{LATIN CAPITAL LETTER U WITH GRAVE}': 'U',
|
137
|
u'\N{LATIN CAPITAL LETTER Y WITH ACUTE}': 'Y',
|
138
|
u'\N{LATIN SMALL LETTER A WITH ACUTE}': 'a',
|
139
|
u'\N{LATIN SMALL LETTER A WITH CIRCUMFLEX}': 'a',
|
140
|
u'\N{LATIN SMALL LETTER A WITH DIAERESIS}': 'a',
|
141
|
u'\N{LATIN SMALL LETTER A WITH GRAVE}': 'a',
|
142
|
u'\N{LATIN SMALL LETTER A WITH RING ABOVE}': 'a',
|
143
|
u'\N{LATIN SMALL LETTER A WITH TILDE}': 'a',
|
144
|
u'\N{LATIN SMALL LETTER AE}': 'ae',
|
145
|
u'\N{LATIN SMALL LETTER C WITH CEDILLA}': 'c',
|
146
|
u'\N{LATIN SMALL LETTER E WITH ACUTE}': 'e',
|
147
|
u'\N{LATIN SMALL LETTER E WITH CIRCUMFLEX}': 'e',
|
148
|
u'\N{LATIN SMALL LETTER E WITH DIAERESIS}': 'e',
|
149
|
u'\N{LATIN SMALL LETTER E WITH GRAVE}': 'e',
|
150
|
u'\N{LATIN SMALL LETTER ETH}': 'th',
|
151
|
u'\N{LATIN SMALL LETTER I WITH ACUTE}': 'i',
|
152
|
u'\N{LATIN SMALL LETTER I WITH CIRCUMFLEX}': 'i',
|
153
|
u'\N{LATIN SMALL LETTER I WITH DIAERESIS}': 'i',
|
154
|
u'\N{LATIN SMALL LETTER I WITH GRAVE}': 'i',
|
155
|
u'\N{LATIN SMALL LETTER N WITH TILDE}': 'n',
|
156
|
u'\N{LATIN SMALL LETTER O WITH ACUTE}': 'o',
|
157
|
u'\N{LATIN SMALL LETTER O WITH CIRCUMFLEX}': 'o',
|
158
|
u'\N{LATIN SMALL LETTER O WITH DIAERESIS}': 'o',
|
159
|
u'\N{LATIN SMALL LETTER O WITH GRAVE}': 'o',
|
160
|
u'\N{LATIN SMALL LETTER O WITH STROKE}': 'o',
|
161
|
u'\N{LATIN SMALL LETTER O WITH TILDE}': 'o',
|
162
|
u'\N{LATIN SMALL LETTER SHARP S}': 'ss',
|
163
|
u'\N{LATIN SMALL LETTER THORN}': 'th',
|
164
|
u'\N{LATIN SMALL LETTER U WITH ACUTE}': 'u',
|
165
|
u'\N{LATIN SMALL LETTER U WITH CIRCUMFLEX}': 'u',
|
166
|
u'\N{LATIN SMALL LETTER U WITH DIAERESIS}': 'u',
|
167
|
u'\N{LATIN SMALL LETTER U WITH GRAVE}': 'u',
|
168
|
u'\N{LATIN SMALL LETTER Y WITH ACUTE}': 'y',
|
169
|
u'\N{LATIN SMALL LETTER Y WITH DIAERESIS}': 'y',
|
170
|
u'\N{LEFT-POINTING DOUBLE ANGLE QUOTATION MARK}': '<<',
|
171
|
u'\N{MACRON}': '_',
|
172
|
u'\N{MASCULINE ORDINAL INDICATOR}': '{^o}',
|
173
|
u'\N{MICRO SIGN}': '{micro}',
|
174
|
u'\N{MIDDLE DOT}': '*',
|
175
|
u'\N{MULTIPLICATION SIGN}': '*',
|
176
|
u'\N{NOT SIGN}': '{not}',
|
177
|
u'\N{PILCROW SIGN}': '{paragraph}',
|
178
|
u'\N{PLUS-MINUS SIGN}': '{+/-}',
|
179
|
u'\N{POUND SIGN}': '{pound}',
|
180
|
u'\N{REGISTERED SIGN}': '{R}',
|
181
|
u'\N{RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK}': '>>',
|
182
|
u'\N{SECTION SIGN}': '{section}',
|
183
|
u'\N{SOFT HYPHEN}': '-',
|
184
|
u'\N{SUPERSCRIPT ONE}': '{^1}',
|
185
|
u'\N{SUPERSCRIPT THREE}': '{^3}',
|
186
|
u'\N{SUPERSCRIPT TWO}': '{^2}',
|
187
|
u'\N{VULGAR FRACTION ONE HALF}': '{1/2}',
|
188
|
u'\N{VULGAR FRACTION ONE QUARTER}': '{1/4}',
|
189
|
u'\N{VULGAR FRACTION THREE QUARTERS}': '{3/4}',
|
190
|
u'\N{YEN SIGN}': '{yen}'
|
191
|
}
|
192
|
|
193
|
def latin1_to_ascii (unicrap):
|
194
|
"""This takes a UNICODE string and replaces Latin-1 characters with
|
195
|
something equivalent in 7-bit ASCII. It returns a plain ASCII string.
|
196
|
This function makes a best effort to convert Latin-1 characters into
|
197
|
ASCII equivalents. It does not just strip out the Latin-1 characters.
|
198
|
All characters in the standard 7-bit ASCII range are preserved.
|
199
|
In the 8th bit range all the Latin-1 accented letters are converted
|
200
|
to unaccented equivalents. Most symbol characters are converted to
|
201
|
something meaningful. Anything not converted is deleted.
|
202
|
|
203
|
<http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/251871>
|
204
|
"""
|
205
|
|
206
|
if not isinstance(unicrap, unicode):
|
207
|
unicrap = unicode(unicrap, 'iso-8859-1')
|
208
|
r = ""
|
209
|
for i in unicrap:
|
210
|
if xlate.has_key(i):
|
211
|
r += xlate[i]
|
212
|
elif ord(i) >= 0x80:
|
213
|
pass
|
214
|
else:
|
215
|
r += str(i)
|
216
|
return r
|
217
|
|
218
|
simplifyRegex = re.compile(r'''([\s()'"/:\.,\&]+)''')
|
219
|
|
220
|
def simplify(s, space = '-'):
|
221
|
if s is None: s = ''
|
222
|
s = latin1_to_ascii(simplifyRegex.sub(' ', s).strip()).replace(' ', space).lower()
|
223
|
return s
|
224
|
|
225
|
|
226
|
def localstrftime(t):
|
227
|
if not t:
|
228
|
return ''
|
229
|
format_string = '%Y-%m-%d %H:%M'
|
230
|
lang = cfg.get('language', {}).get('language', None)
|
231
|
if lang == 'fr' or (lang is None and os.environ.get('LC_ALL', '')[:2] == 'fr'):
|
232
|
format_string = '%d/%m/%Y %H:%M'
|
233
|
return time.strftime(format_string, t)
|
234
|
|
235
|
def date_format():
|
236
|
lang = cfg.get('language', {}).get('language', None)
|
237
|
format_string = '%Y-%m-%d'
|
238
|
return format_string
|
239
|
|
240
|
def ellipsize(s, length = 30):
|
241
|
if not s or len(s) < length:
|
242
|
return s
|
243
|
return s[:length-5] + ' (...)'
|
244
|
|