commit | author | age
|
d85ba6
|
1 |
from paste.httpheaders import REQUEST_METHOD |
CM |
2 |
from paste.httpheaders import CONTENT_TYPE |
0dd808
|
3 |
from paste.httpheaders import USER_AGENT |
d85ba6
|
4 |
|
1d896c
|
5 |
from zope.interface import directlyProvides |
cb5426
|
6 |
from repoze.who.interfaces import IRequestClassifier |
CM |
7 |
from repoze.who.interfaces import IChallengeDecider |
d85ba6
|
8 |
|
c51195
|
9 |
_DAV_METHODS = ( |
CM |
10 |
'OPTIONS', |
|
11 |
'PROPFIND', |
|
12 |
'PROPPATCH', |
|
13 |
'MKCOL', |
|
14 |
'LOCK', |
|
15 |
'UNLOCK', |
|
16 |
'TRACE', |
|
17 |
'DELETE', |
|
18 |
'COPY', |
|
19 |
'MOVE' |
|
20 |
) |
d85ba6
|
21 |
|
c51195
|
22 |
_DAV_USERAGENTS = ( |
CM |
23 |
'Microsoft Data Access Internet Publishing Provider', |
|
24 |
'WebDrive', |
|
25 |
'Zope External Editor', |
|
26 |
'WebDAVFS', |
|
27 |
'Goliath', |
|
28 |
'neon', |
|
29 |
'davlib', |
|
30 |
'wsAPI', |
|
31 |
'Microsoft-WebDAV' |
|
32 |
) |
d85ba6
|
33 |
|
c51195
|
34 |
def default_request_classifier(environ): |
CM |
35 |
""" Returns one of the classifiers 'dav', 'xmlpost', or 'browser', |
|
36 |
depending on the imperative logic below""" |
|
37 |
request_method = REQUEST_METHOD(environ) |
|
38 |
if request_method in _DAV_METHODS: |
|
39 |
return 'dav' |
|
40 |
useragent = USER_AGENT(environ) |
|
41 |
if useragent: |
|
42 |
for agent in _DAV_USERAGENTS: |
|
43 |
if useragent.find(agent) != -1: |
|
44 |
return 'dav' |
|
45 |
if request_method == 'POST': |
6b7b34
|
46 |
if CONTENT_TYPE(environ).lower().startswith('text/xml'): |
c51195
|
47 |
return 'xmlpost' |
CM |
48 |
return 'browser' |
1d896c
|
49 |
directlyProvides(default_request_classifier, IRequestClassifier) |
d85ba6
|
50 |
|
c51195
|
51 |
def default_challenge_decider(environ, status, headers): |
79a95b
|
52 |
return status.startswith('401 ') |
1d896c
|
53 |
directlyProvides(default_challenge_decider, IChallengeDecider) |
0dd808
|
54 |
|
TS |
55 |
def passthrough_challenge_decider(environ, status, headers): |
|
56 |
""" Don't challenge for pre-challenged responses. |
|
57 |
|
|
58 |
o Assume responsese with 'WWW-Authenticate' or an HTML content type |
|
59 |
are pre-challenged. |
|
60 |
""" |
|
61 |
if not status.startswith('401 '): |
|
62 |
return False |
|
63 |
h_dict = dict(headers) |
|
64 |
if 'WWW-Authenticate' in h_dict: |
|
65 |
return False |
|
66 |
ct = h_dict.get('Content-Type') |
|
67 |
if ct is not None: |
|
68 |
return not ct.startswith('text/html') |
|
69 |
return True |
1d896c
|
70 |
directlyProvides(passthrough_challenge_decider, IChallengeDecider) |