author | Sylvain Thénault <sylvain.thenault@logilab.fr> |
Fri, 22 Oct 2010 14:32:59 +0200 | |
changeset 6590 | 37b7f4df46b3 |
parent 6581 | 4a3b264589dc |
child 7070 | 5f8e52d722c5 |
permissions | -rw-r--r-- |
5421
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
1 |
# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
2 |
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
3 |
# |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
4 |
# This file is part of CubicWeb. |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
5 |
# |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
6 |
# CubicWeb is free software: you can redistribute it and/or modify it under the |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
7 |
# terms of the GNU Lesser General Public License as published by the Free |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
8 |
# Software Foundation, either version 2.1 of the License, or (at your option) |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
9 |
# any later version. |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
10 |
# |
5424
8ecbcbff9777
replace logilab-common by CubicWeb in disclaimer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5421
diff
changeset
|
11 |
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT |
5421
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
12 |
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
13 |
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
14 |
# details. |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
15 |
# |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
16 |
# You should have received a copy of the GNU Lesser General Public License along |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
17 |
# with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
5423
e15abfdcce38
backport default into stable: stable is now cw 3.8
Sylvain Thénault <sylvain.thenault@logilab.fr>
diff
changeset
|
18 |
"""abstract class for http request""" |
0 | 19 |
|
20 |
__docformat__ = "restructuredtext en" |
|
21 |
||
22 |
import Cookie |
|
5884
a0eb685dfe7a
[req] hashlib has no hash function, but has an hash1 function even in python 2.5
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5777
diff
changeset
|
23 |
import hashlib |
0 | 24 |
import time |
25 |
import random |
|
26 |
import base64 |
|
3653
ef71abb1e77b
[req] new expires argument to set_cookie
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3293
diff
changeset
|
27 |
from datetime import date |
0 | 28 |
from urlparse import urlsplit |
29 |
from itertools import count |
|
6078
c08e74b0609e
fix missing import in web.request
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
6064
diff
changeset
|
30 |
from warnings import warn |
0 | 31 |
|
32 |
from rql.utils import rqlvar_maker |
|
33 |
||
34 |
from logilab.common.decorators import cached |
|
2613
5e19c2bb370e
R [all] logilab.common 0.44 provides only deprecated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
2559
diff
changeset
|
35 |
from logilab.common.deprecation import deprecated |
2312
af4d8f75c5db
use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2258
diff
changeset
|
36 |
from logilab.mtconverter import xml_escape |
1801
672acc730ce5
ajax_replace_url becomes obsolete, req.build_ajax_replace_url should be used instead
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1718
diff
changeset
|
37 |
|
0 | 38 |
from cubicweb.dbapi import DBAPIRequest |
4023
eae23c40627a
drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4004
diff
changeset
|
39 |
from cubicweb.mail import header |
6063
17a53f6dea42
[request] js is defined in uilib, not utils
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6062
diff
changeset
|
40 |
from cubicweb.uilib import remove_html_tags, js |
17a53f6dea42
[request] js is defined in uilib, not utils
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6062
diff
changeset
|
41 |
from cubicweb.utils import SizeConstrainedList, HTMLHead, make_uid |
3094
978ed8c2c0e4
[googlemap] #344872 set request content-type to text/html
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
2650
diff
changeset
|
42 |
from cubicweb.view import STRICT_DOCTYPE, TRANSITIONAL_DOCTYPE_NOEXT |
1801
672acc730ce5
ajax_replace_url becomes obsolete, req.build_ajax_replace_url should be used instead
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1718
diff
changeset
|
43 |
from cubicweb.web import (INTERNAL_FIELD_VALUE, LOGGER, NothingToEdit, |
5940
0e3ae19b181a
[uilib] refactor json_dumps code organization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5890
diff
changeset
|
44 |
RequestError, StatusResponse) |
5155
1dea6e0fdfc1
Switched from TwistedWeb2 to TwistedWeb
Adrien Chauve <adrien.chauve@logilab.fr>
parents:
4984
diff
changeset
|
45 |
from cubicweb.web.http_headers import Headers |
0 | 46 |
|
662
6f867ab70e3d
move _MARKER from appobject to web.request
sylvain.thenault@logilab.fr
parents:
610
diff
changeset
|
47 |
_MARKER = object() |
6f867ab70e3d
move _MARKER from appobject to web.request
sylvain.thenault@logilab.fr
parents:
610
diff
changeset
|
48 |
|
6564
ff9f7c566464
[request] fix ajax_replace_url which breaks if the url contains some quotes (that will be properly quoted but unquoted by the browser, breaking the js expression) by using a separated js function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6543
diff
changeset
|
49 |
def build_cb_uid(seed): |
ff9f7c566464
[request] fix ajax_replace_url which breaks if the url contains some quotes (that will be properly quoted but unquoted by the browser, breaking the js expression) by using a separated js function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6543
diff
changeset
|
50 |
sha = hashlib.sha1('%s%s%s' % (time.time(), seed, random.random())) |
ff9f7c566464
[request] fix ajax_replace_url which breaks if the url contains some quotes (that will be properly quoted but unquoted by the browser, breaking the js expression) by using a separated js function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6543
diff
changeset
|
51 |
return 'cb_%s' % (sha.hexdigest()) |
ff9f7c566464
[request] fix ajax_replace_url which breaks if the url contains some quotes (that will be properly quoted but unquoted by the browser, breaking the js expression) by using a separated js function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6543
diff
changeset
|
52 |
|
0 | 53 |
|
54 |
def list_form_param(form, param, pop=False): |
|
55 |
"""get param from form parameters and return its value as a list, |
|
56 |
skipping internal markers if any |
|
57 |
||
58 |
* if the parameter isn't defined, return an empty list |
|
59 |
* if the parameter is a single (unicode) value, return a list |
|
60 |
containing that value |
|
61 |
* if the parameter is already a list or tuple, just skip internal |
|
62 |
markers |
|
63 |
||
64 |
if pop is True, the parameter is removed from the form dictionnary |
|
65 |
""" |
|
66 |
if pop: |
|
67 |
try: |
|
68 |
value = form.pop(param) |
|
69 |
except KeyError: |
|
70 |
return [] |
|
71 |
else: |
|
72 |
value = form.get(param, ()) |
|
73 |
if value is None: |
|
74 |
value = () |
|
75 |
elif not isinstance(value, (list, tuple)): |
|
76 |
value = [value] |
|
77 |
return [v for v in value if v != INTERNAL_FIELD_VALUE] |
|
78 |
||
79 |
||
80 |
||
81 |
class CubicWebRequestBase(DBAPIRequest): |
|
1421
77ee26df178f
doc type handling refactoring: do the ext substitution at the module level
sylvain.thenault@logilab.fr
parents:
1173
diff
changeset
|
82 |
"""abstract HTTP request, should be extended according to the HTTP backend""" |
2255
c346af0727ca
more generic way to detect json requests (not yet perfect though)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2245
diff
changeset
|
83 |
json_request = False # to be set to True by json controllers |
1421
77ee26df178f
doc type handling refactoring: do the ext substitution at the module level
sylvain.thenault@logilab.fr
parents:
1173
diff
changeset
|
84 |
|
0 | 85 |
def __init__(self, vreg, https, form=None): |
86 |
super(CubicWebRequestBase, self).__init__(vreg) |
|
87 |
self.https = https |
|
5467
57372dbfd114
[https] fix resource urls in https version of a site: should use the https version as well to avoid warnings from the nrowser
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5444
diff
changeset
|
88 |
if https: |
57372dbfd114
[https] fix resource urls in https version of a site: should use the https version as well to avoid warnings from the nrowser
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5444
diff
changeset
|
89 |
self.uiprops = vreg.config.https_uiprops |
57372dbfd114
[https] fix resource urls in https version of a site: should use the https version as well to avoid warnings from the nrowser
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5444
diff
changeset
|
90 |
self.datadir_url = vreg.config.https_datadir_url |
57372dbfd114
[https] fix resource urls in https version of a site: should use the https version as well to avoid warnings from the nrowser
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5444
diff
changeset
|
91 |
else: |
57372dbfd114
[https] fix resource urls in https version of a site: should use the https version as well to avoid warnings from the nrowser
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5444
diff
changeset
|
92 |
self.uiprops = vreg.config.uiprops |
57372dbfd114
[https] fix resource urls in https version of a site: should use the https version as well to avoid warnings from the nrowser
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5444
diff
changeset
|
93 |
self.datadir_url = vreg.config.datadir_url |
0 | 94 |
# raw html headers that can be added from any view |
95 |
self.html_headers = HTMLHead() |
|
96 |
# form parameters |
|
97 |
self.setup_params(form) |
|
98 |
# dictionnary that may be used to store request data that has to be |
|
99 |
# shared among various components used to publish the request (views, |
|
100 |
# controller, application...) |
|
101 |
self.data = {} |
|
102 |
# search state: 'normal' or 'linksearch' (eg searching for an object |
|
103 |
# to create a relation with another) |
|
1426 | 104 |
self.search_state = ('normal',) |
0 | 105 |
# page id, set by htmlheader template |
106 |
self.pageid = None |
|
3816
37b376bb4088
[web] set pageid at request instanciation rather than in htmlheader template
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3275
diff
changeset
|
107 |
self._set_pageid() |
5155
1dea6e0fdfc1
Switched from TwistedWeb2 to TwistedWeb
Adrien Chauve <adrien.chauve@logilab.fr>
parents:
4984
diff
changeset
|
108 |
# prepare output header |
1dea6e0fdfc1
Switched from TwistedWeb2 to TwistedWeb
Adrien Chauve <adrien.chauve@logilab.fr>
parents:
4984
diff
changeset
|
109 |
self.headers_out = Headers() |
3816
37b376bb4088
[web] set pageid at request instanciation rather than in htmlheader template
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3275
diff
changeset
|
110 |
|
37b376bb4088
[web] set pageid at request instanciation rather than in htmlheader template
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3275
diff
changeset
|
111 |
def _set_pageid(self): |
37b376bb4088
[web] set pageid at request instanciation rather than in htmlheader template
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3275
diff
changeset
|
112 |
"""initialize self.pageid |
37b376bb4088
[web] set pageid at request instanciation rather than in htmlheader template
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3275
diff
changeset
|
113 |
if req.form provides a specific pageid, use it, otherwise build a |
37b376bb4088
[web] set pageid at request instanciation rather than in htmlheader template
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3275
diff
changeset
|
114 |
new one. |
37b376bb4088
[web] set pageid at request instanciation rather than in htmlheader template
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3275
diff
changeset
|
115 |
""" |
37b376bb4088
[web] set pageid at request instanciation rather than in htmlheader template
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3275
diff
changeset
|
116 |
pid = self.form.get('pageid') |
37b376bb4088
[web] set pageid at request instanciation rather than in htmlheader template
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3275
diff
changeset
|
117 |
if pid is None: |
37b376bb4088
[web] set pageid at request instanciation rather than in htmlheader template
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3275
diff
changeset
|
118 |
pid = make_uid(id(self)) |
37b376bb4088
[web] set pageid at request instanciation rather than in htmlheader template
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3275
diff
changeset
|
119 |
self.pageid = pid |
3838
9cc134372bf8
[web] safety belt to avoid overriding pageid with loadxhtml()
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3816
diff
changeset
|
120 |
self.html_headers.define_var('pageid', pid, override=False) |
0 | 121 |
|
2792
135580d15d42
rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
122 |
@property |
6581
4a3b264589dc
[dbapi] enhanced web compatible request when using dbapi
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6564
diff
changeset
|
123 |
def authmode(self): |
4a3b264589dc
[dbapi] enhanced web compatible request when using dbapi
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6564
diff
changeset
|
124 |
return self.vreg.config['auth-mode'] |
4a3b264589dc
[dbapi] enhanced web compatible request when using dbapi
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6564
diff
changeset
|
125 |
|
4a3b264589dc
[dbapi] enhanced web compatible request when using dbapi
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6564
diff
changeset
|
126 |
@property |
2801
7ef4c1c9266b
fix syntax error
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2792
diff
changeset
|
127 |
def varmaker(self): |
4366
d51f28ba9399
fif inlined relation forms pb w/ new ajax forms.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4277
diff
changeset
|
128 |
"""the rql varmaker is exposed both as a property and as the |
d51f28ba9399
fif inlined relation forms pb w/ new ajax forms.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4277
diff
changeset
|
129 |
set_varmaker function since we've two use cases: |
d51f28ba9399
fif inlined relation forms pb w/ new ajax forms.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4277
diff
changeset
|
130 |
|
d51f28ba9399
fif inlined relation forms pb w/ new ajax forms.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4277
diff
changeset
|
131 |
* accessing the req.varmaker property to get a new variable name |
d51f28ba9399
fif inlined relation forms pb w/ new ajax forms.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4277
diff
changeset
|
132 |
|
d51f28ba9399
fif inlined relation forms pb w/ new ajax forms.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4277
diff
changeset
|
133 |
* calling req.set_varmaker() to ensure a varmaker is set for later ajax |
d51f28ba9399
fif inlined relation forms pb w/ new ajax forms.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4277
diff
changeset
|
134 |
calls sharing our .pageid |
d51f28ba9399
fif inlined relation forms pb w/ new ajax forms.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4277
diff
changeset
|
135 |
""" |
d51f28ba9399
fif inlined relation forms pb w/ new ajax forms.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4277
diff
changeset
|
136 |
return self.set_varmaker() |
d51f28ba9399
fif inlined relation forms pb w/ new ajax forms.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4277
diff
changeset
|
137 |
|
6259
c3d98e4bee12
[request] memoize tabindex across ajax calls (on pageid) to avoid ui confusion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
6108
diff
changeset
|
138 |
def _get_tabindex_func(self): |
c3d98e4bee12
[request] memoize tabindex across ajax calls (on pageid) to avoid ui confusion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
6108
diff
changeset
|
139 |
nextfunc = self.get_page_data('nexttabfunc') |
c3d98e4bee12
[request] memoize tabindex across ajax calls (on pageid) to avoid ui confusion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
6108
diff
changeset
|
140 |
if nextfunc is None: |
c3d98e4bee12
[request] memoize tabindex across ajax calls (on pageid) to avoid ui confusion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
6108
diff
changeset
|
141 |
nextfunc = count(1).next |
c3d98e4bee12
[request] memoize tabindex across ajax calls (on pageid) to avoid ui confusion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
6108
diff
changeset
|
142 |
self.set_page_data('nexttabfunc', nextfunc) |
c3d98e4bee12
[request] memoize tabindex across ajax calls (on pageid) to avoid ui confusion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
6108
diff
changeset
|
143 |
return nextfunc |
c3d98e4bee12
[request] memoize tabindex across ajax calls (on pageid) to avoid ui confusion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
6108
diff
changeset
|
144 |
|
4366
d51f28ba9399
fif inlined relation forms pb w/ new ajax forms.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4277
diff
changeset
|
145 |
def set_varmaker(self): |
2792
135580d15d42
rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
146 |
varmaker = self.get_page_data('rql_varmaker') |
135580d15d42
rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
147 |
if varmaker is None: |
135580d15d42
rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
148 |
varmaker = rqlvar_maker() |
135580d15d42
rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
149 |
self.set_page_data('rql_varmaker', varmaker) |
135580d15d42
rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
150 |
return varmaker |
135580d15d42
rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
151 |
|
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
152 |
def set_session(self, session, user=None): |
0 | 153 |
"""method called by the session handler when the user is authenticated |
154 |
or an anonymous connection is open |
|
155 |
""" |
|
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
156 |
super(CubicWebRequestBase, self).set_session(session, user) |
6259
c3d98e4bee12
[request] memoize tabindex across ajax calls (on pageid) to avoid ui confusion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
6108
diff
changeset
|
157 |
# tabindex generator |
c3d98e4bee12
[request] memoize tabindex across ajax calls (on pageid) to avoid ui confusion
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
6108
diff
changeset
|
158 |
self.next_tabindex = self._get_tabindex_func() |
2245
7463e1a748dd
new set_session_props method exposed by the repository, use it to be sure session language is in sync the request language
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2202
diff
changeset
|
159 |
# set request language |
4897
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
160 |
vreg = self.vreg |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
161 |
if self.user: |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
162 |
try: |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
163 |
# 1. user specified language |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
164 |
lang = vreg.typed_value('ui.language', |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
165 |
self.user.properties['ui.language']) |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
166 |
self.set_language(lang) |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
167 |
return |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
168 |
except KeyError: |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
169 |
pass |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
170 |
if vreg.config['language-negociation']: |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
171 |
# 2. http negociated language |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
172 |
for lang in self.header_accept_language(): |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
173 |
if lang in self.translations: |
0 | 174 |
self.set_language(lang) |
175 |
return |
|
4897
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
176 |
# 3. default language |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
177 |
self.set_default_language(vreg) |
1426 | 178 |
|
0 | 179 |
def set_language(self, lang): |
3275
5247789df541
[gettext] provide GNU contexts to avoid translations ambiguities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3094
diff
changeset
|
180 |
gettext, self.pgettext = self.translations[lang] |
5247789df541
[gettext] provide GNU contexts to avoid translations ambiguities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3094
diff
changeset
|
181 |
self._ = self.__ = gettext |
0 | 182 |
self.lang = lang |
183 |
self.debug('request language: %s', lang) |
|
5244
5467674ad101
[web] put a fake object that raise Unauthorized on any attribute access as req.cnx and req._user, so we are properly asked to authenticated on any view that tries to do something with one of those attributes (instead of doing defensive programming everywhere we're doing that)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5223
diff
changeset
|
184 |
if self.cnx: |
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
185 |
self.cnx.set_session_props(lang=lang) |
1426 | 186 |
|
0 | 187 |
# input form parameters management ######################################## |
1426 | 188 |
|
0 | 189 |
# common form parameters which should be protected against html values |
190 |
# XXX can't add 'eid' for instance since it may be multivalued |
|
191 |
# dont put rql as well, if query contains < and > it will be corrupted! |
|
1426 | 192 |
no_script_form_params = set(('vid', |
193 |
'etype', |
|
0 | 194 |
'vtitle', 'title', |
195 |
'__message', |
|
196 |
'__redirectvid', '__redirectrql')) |
|
1426 | 197 |
|
0 | 198 |
def setup_params(self, params): |
199 |
"""WARNING: we're intentionaly leaving INTERNAL_FIELD_VALUE here |
|
200 |
||
1426 | 201 |
subclasses should overrides to |
0 | 202 |
""" |
4897
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
203 |
self.form = {} |
0 | 204 |
if params is None: |
4897
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
205 |
return |
0 | 206 |
encoding = self.encoding |
4897
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
207 |
for param, val in params.iteritems(): |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
208 |
if isinstance(val, (tuple, list)): |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
209 |
val = [unicode(x, encoding) for x in val] |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
210 |
if len(val) == 1: |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
211 |
val = val[0] |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
212 |
elif isinstance(val, str): |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
213 |
val = unicode(val, encoding) |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
214 |
if param in self.no_script_form_params and val: |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
215 |
val = self.no_script_form_param(param, val) |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
216 |
if param == '_cwmsgid': |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
217 |
self.set_message_id(val) |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
218 |
elif param == '__message': |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
219 |
self.set_message(val) |
0 | 220 |
else: |
4897
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
221 |
self.form[param] = val |
1426 | 222 |
|
4897
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
223 |
def no_script_form_param(self, param, value): |
0 | 224 |
"""ensure there is no script in a user form param |
225 |
||
226 |
by default return a cleaned string instead of raising a security |
|
227 |
exception |
|
228 |
||
229 |
this method should be called on every user input (form at least) fields |
|
230 |
that are at some point inserted in a generated html page to protect |
|
231 |
against script kiddies |
|
232 |
""" |
|
4897
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
233 |
# safety belt for strange urls like http://...?vtitle=yo&vtitle=yo |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
234 |
if isinstance(value, (list, tuple)): |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
235 |
self.error('no_script_form_param got a list (%s). Who generated the URL ?', |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
236 |
repr(value)) |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
237 |
value = value[0] |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
238 |
return remove_html_tags(value) |
1426 | 239 |
|
0 | 240 |
def list_form_param(self, param, form=None, pop=False): |
241 |
"""get param from form parameters and return its value as a list, |
|
242 |
skipping internal markers if any |
|
1426 | 243 |
|
0 | 244 |
* if the parameter isn't defined, return an empty list |
245 |
* if the parameter is a single (unicode) value, return a list |
|
246 |
containing that value |
|
247 |
* if the parameter is already a list or tuple, just skip internal |
|
248 |
markers |
|
249 |
||
250 |
if pop is True, the parameter is removed from the form dictionnary |
|
251 |
""" |
|
252 |
if form is None: |
|
253 |
form = self.form |
|
1426 | 254 |
return list_form_param(form, param, pop) |
255 |
||
0 | 256 |
|
257 |
def reset_headers(self): |
|
258 |
"""used by AutomaticWebTest to clear html headers between tests on |
|
259 |
the same resultset |
|
260 |
""" |
|
261 |
self.html_headers = HTMLHead() |
|
262 |
return self |
|
263 |
||
264 |
# web state helpers ####################################################### |
|
1426 | 265 |
|
4897
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
266 |
@property |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
267 |
def message(self): |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
268 |
try: |
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
269 |
return self.session.data.pop(self._msgid, '') |
4897
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
270 |
except AttributeError: |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
271 |
try: |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
272 |
return self._msg |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
273 |
except AttributeError: |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
274 |
return None |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
275 |
|
0 | 276 |
def set_message(self, msg): |
277 |
assert isinstance(msg, unicode) |
|
4897
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
278 |
self._msg = msg |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
279 |
|
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
280 |
def set_message_id(self, msgid): |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
281 |
self._msgid = msgid |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
282 |
|
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
283 |
@cached |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
284 |
def redirect_message_id(self): |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
285 |
return make_uid() |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
286 |
|
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
287 |
def set_redirect_message(self, msg): |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
288 |
assert isinstance(msg, unicode) |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
289 |
msgid = self.redirect_message_id() |
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
290 |
self.session.data[msgid] = msg |
4897
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
291 |
return msgid |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
292 |
|
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
293 |
def append_to_redirect_message(self, msg): |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
294 |
msgid = self.redirect_message_id() |
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
295 |
currentmsg = self.session.data.get(msgid) |
4897
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
296 |
if currentmsg is not None: |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
297 |
currentmsg = '%s %s' % (currentmsg, msg) |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
298 |
else: |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
299 |
currentmsg = msg |
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
300 |
self.session.data[msgid] = currentmsg |
4897
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
301 |
return msgid |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
302 |
|
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
303 |
def reset_message(self): |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
304 |
if hasattr(self, '_msg'): |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
305 |
del self._msg |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
306 |
if hasattr(self, '_msgid'): |
e402e0b32075
[web] start a new message system based on id of message stored in session's data
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4851
diff
changeset
|
307 |
del self._msgid |
1426 | 308 |
|
0 | 309 |
def update_search_state(self): |
310 |
"""update the current search state""" |
|
311 |
searchstate = self.form.get('__mode') |
|
5244
5467674ad101
[web] put a fake object that raise Unauthorized on any attribute access as req.cnx and req._user, so we are properly asked to authenticated on any view that tries to do something with one of those attributes (instead of doing defensive programming everywhere we're doing that)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5223
diff
changeset
|
312 |
if not searchstate and self.cnx: |
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
313 |
searchstate = self.session.data.get('search_state', 'normal') |
0 | 314 |
self.set_search_state(searchstate) |
315 |
||
316 |
def set_search_state(self, searchstate): |
|
317 |
"""set a new search state""" |
|
318 |
if searchstate is None or searchstate == 'normal': |
|
319 |
self.search_state = (searchstate or 'normal',) |
|
320 |
else: |
|
321 |
self.search_state = ('linksearch', searchstate.split(':')) |
|
322 |
assert len(self.search_state[-1]) == 4 |
|
5244
5467674ad101
[web] put a fake object that raise Unauthorized on any attribute access as req.cnx and req._user, so we are properly asked to authenticated on any view that tries to do something with one of those attributes (instead of doing defensive programming everywhere we're doing that)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5223
diff
changeset
|
323 |
if self.cnx: |
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
324 |
self.session.data['search_state'] = searchstate |
0 | 325 |
|
1173
8f123fd081f4
forgot to add that expected method (was a function in view.__init__)
sylvain.thenault@logilab.fr
parents:
1013
diff
changeset
|
326 |
def match_search_state(self, rset): |
8f123fd081f4
forgot to add that expected method (was a function in view.__init__)
sylvain.thenault@logilab.fr
parents:
1013
diff
changeset
|
327 |
"""when searching an entity to create a relation, return True if entities in |
8f123fd081f4
forgot to add that expected method (was a function in view.__init__)
sylvain.thenault@logilab.fr
parents:
1013
diff
changeset
|
328 |
the given rset may be used as relation end |
8f123fd081f4
forgot to add that expected method (was a function in view.__init__)
sylvain.thenault@logilab.fr
parents:
1013
diff
changeset
|
329 |
""" |
8f123fd081f4
forgot to add that expected method (was a function in view.__init__)
sylvain.thenault@logilab.fr
parents:
1013
diff
changeset
|
330 |
try: |
8f123fd081f4
forgot to add that expected method (was a function in view.__init__)
sylvain.thenault@logilab.fr
parents:
1013
diff
changeset
|
331 |
searchedtype = self.search_state[1][-1] |
8f123fd081f4
forgot to add that expected method (was a function in view.__init__)
sylvain.thenault@logilab.fr
parents:
1013
diff
changeset
|
332 |
except IndexError: |
8f123fd081f4
forgot to add that expected method (was a function in view.__init__)
sylvain.thenault@logilab.fr
parents:
1013
diff
changeset
|
333 |
return False # no searching for association |
8f123fd081f4
forgot to add that expected method (was a function in view.__init__)
sylvain.thenault@logilab.fr
parents:
1013
diff
changeset
|
334 |
for etype in rset.column_types(0): |
8f123fd081f4
forgot to add that expected method (was a function in view.__init__)
sylvain.thenault@logilab.fr
parents:
1013
diff
changeset
|
335 |
if etype != searchedtype: |
8f123fd081f4
forgot to add that expected method (was a function in view.__init__)
sylvain.thenault@logilab.fr
parents:
1013
diff
changeset
|
336 |
return False |
8f123fd081f4
forgot to add that expected method (was a function in view.__init__)
sylvain.thenault@logilab.fr
parents:
1013
diff
changeset
|
337 |
return True |
8f123fd081f4
forgot to add that expected method (was a function in view.__init__)
sylvain.thenault@logilab.fr
parents:
1013
diff
changeset
|
338 |
|
0 | 339 |
def update_breadcrumbs(self): |
340 |
"""stores the last visisted page in session data""" |
|
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
341 |
searchstate = self.session.data.get('search_state') |
0 | 342 |
if searchstate == 'normal': |
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
343 |
breadcrumbs = self.session.data.get('breadcrumbs') |
0 | 344 |
if breadcrumbs is None: |
345 |
breadcrumbs = SizeConstrainedList(10) |
|
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
346 |
self.session.data['breadcrumbs'] = breadcrumbs |
4864
e77d3e95872d
[web req] check latest url in breadcrumbs is not the same as the current one to keep more valuable information
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4719
diff
changeset
|
347 |
breadcrumbs.append(self.url()) |
e77d3e95872d
[web req] check latest url in breadcrumbs is not the same as the current one to keep more valuable information
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4719
diff
changeset
|
348 |
else: |
e77d3e95872d
[web req] check latest url in breadcrumbs is not the same as the current one to keep more valuable information
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4719
diff
changeset
|
349 |
url = self.url() |
4974
025a491bad0c
take care to empty breadcrumbs
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4868
diff
changeset
|
350 |
if breadcrumbs and breadcrumbs[-1] != url: |
4864
e77d3e95872d
[web req] check latest url in breadcrumbs is not the same as the current one to keep more valuable information
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4719
diff
changeset
|
351 |
breadcrumbs.append(url) |
0 | 352 |
|
353 |
def last_visited_page(self): |
|
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
354 |
breadcrumbs = self.session.data.get('breadcrumbs') |
0 | 355 |
if breadcrumbs: |
356 |
return breadcrumbs.pop() |
|
357 |
return self.base_url() |
|
358 |
||
6062
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
359 |
def user_rql_callback(self, rqlargs, *args, **kwargs): |
2792
135580d15d42
rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
360 |
"""register a user callback to execute some rql query and return an url |
6062
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
361 |
to call it ready to be inserted in html. |
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
362 |
|
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
363 |
rqlargs should be a tuple containing argument to give to the execute function. |
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
364 |
|
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
365 |
For other allowed arguments, see :meth:`user_callback` method |
2792
135580d15d42
rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
366 |
""" |
135580d15d42
rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
367 |
def rqlexec(req, rql, args=None, key=None): |
135580d15d42
rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
368 |
req.execute(rql, args, key) |
6062
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
369 |
return self.user_callback(rqlexec, rqlargs, *args, **kwargs) |
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
370 |
|
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
371 |
def user_callback(self, cb, cbargs, *args, **kwargs): |
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
372 |
"""register the given user callback and return an url to call it ready |
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
373 |
to be inserted in html. |
2792
135580d15d42
rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
374 |
|
6062
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
375 |
You can specify the underlying js function to call using a 'jsfunc' |
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
376 |
named args, to one of :func:`userCallback`, |
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
377 |
':func:`userCallbackThenUpdateUI`, ':func:`userCallbackThenReloadPage` |
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
378 |
(the default). Take care arguments may vary according to the used |
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
379 |
function. |
2792
135580d15d42
rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
380 |
""" |
135580d15d42
rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
381 |
self.add_js('cubicweb.ajax.js') |
6062
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
382 |
jsfunc = kwargs.pop('jsfunc', 'userCallbackThenReloadPage') |
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
383 |
if 'msg' in kwargs: |
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
384 |
warn('[3.10] msg should be given as positional argument', |
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
385 |
DeprecationWarning, stacklevel=2) |
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
386 |
args = (kwargs.pop('msg'),) + args |
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
387 |
assert not kwargs, 'dunno what to do with remaining kwargs: %s' % kwargs |
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
388 |
cbname = self.register_onetime_callback(cb, *cbargs) |
f1a550102f5c
[request] enhanced user[_rql]_callback method, allowing to call other js variant, eg one of userCallback, userCallbackThenUpdateUI, userCallbackThenReloadPage (the default). Also benefit from the new magic js object.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5940
diff
changeset
|
389 |
return "javascript: %s" % getattr(js, jsfunc)(cbname, *args) |
2792
135580d15d42
rename and move cw.RequestSessionMixIn to cw.req.RequestSessionBase; move some appobjects methods where they actually belong to
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
390 |
|
0 | 391 |
def register_onetime_callback(self, func, *args): |
6564
ff9f7c566464
[request] fix ajax_replace_url which breaks if the url contains some quotes (that will be properly quoted but unquoted by the browser, breaking the js expression) by using a separated js function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6543
diff
changeset
|
392 |
cbname = build_cb_uid(func.__name__) |
0 | 393 |
def _cb(req): |
394 |
try: |
|
395 |
ret = func(req, *args) |
|
396 |
except TypeError: |
|
5505
7f98d22ac6e4
[deprecation] missing version number to old warning message
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
397 |
warn('[3.2] user callback should now take request as argument') |
1426 | 398 |
ret = func(*args) |
0 | 399 |
self.unregister_callback(self.pageid, cbname) |
400 |
return ret |
|
401 |
self.set_page_data(cbname, _cb) |
|
402 |
return cbname |
|
1426 | 403 |
|
0 | 404 |
def unregister_callback(self, pageid, cbname): |
405 |
assert pageid is not None |
|
406 |
assert cbname.startswith('cb_') |
|
407 |
self.info('unregistering callback %s for pageid %s', cbname, pageid) |
|
408 |
self.del_page_data(cbname) |
|
409 |
||
410 |
def clear_user_callbacks(self): |
|
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
411 |
if self.session is not None: # XXX |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
412 |
for key in self.session.data.keys(): |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
413 |
if key.startswith('cb_'): |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
414 |
del self.session.data[key] |
1426 | 415 |
|
0 | 416 |
# web edition helpers ##################################################### |
1426 | 417 |
|
0 | 418 |
@cached # so it's writed only once |
419 |
def fckeditor_config(self): |
|
890
3530baff9120
make fckeditor actually optional, fix its config, avoid needs for a link to fckeditor.js
sylvain.thenault@logilab.fr
parents:
662
diff
changeset
|
420 |
self.add_js('fckeditor/fckeditor.js') |
0 | 421 |
self.html_headers.define_var('fcklang', self.lang) |
422 |
self.html_headers.define_var('fckconfigpath', |
|
890
3530baff9120
make fckeditor actually optional, fix its config, avoid needs for a link to fckeditor.js
sylvain.thenault@logilab.fr
parents:
662
diff
changeset
|
423 |
self.build_url('data/cubicweb.fckcwconfig.js')) |
1013
948a3882c94a
add a use_fckeditor method on http request
sylvain.thenault@logilab.fr
parents:
940
diff
changeset
|
424 |
def use_fckeditor(self): |
948a3882c94a
add a use_fckeditor method on http request
sylvain.thenault@logilab.fr
parents:
940
diff
changeset
|
425 |
return self.vreg.config.fckeditor_installed() and self.property_value('ui.fckeditor') |
0 | 426 |
|
427 |
def edited_eids(self, withtype=False): |
|
428 |
"""return a list of edited eids""" |
|
429 |
yielded = False |
|
430 |
# warning: use .keys since the caller may change `form` |
|
431 |
form = self.form |
|
432 |
try: |
|
433 |
eids = form['eid'] |
|
434 |
except KeyError: |
|
4155
80cc9c6ddcf0
NothingToEdit is not a ValidationError, simplify
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4154
diff
changeset
|
435 |
raise NothingToEdit(self._('no selected entities')) |
0 | 436 |
if isinstance(eids, basestring): |
437 |
eids = (eids,) |
|
438 |
for peid in eids: |
|
439 |
if withtype: |
|
440 |
typekey = '__type:%s' % peid |
|
441 |
assert typekey in form, 'no entity type specified' |
|
442 |
yield peid, form[typekey] |
|
443 |
else: |
|
444 |
yield peid |
|
445 |
yielded = True |
|
446 |
if not yielded: |
|
4155
80cc9c6ddcf0
NothingToEdit is not a ValidationError, simplify
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4154
diff
changeset
|
447 |
raise NothingToEdit(self._('no selected entities')) |
0 | 448 |
|
449 |
# minparams=3 by default: at least eid, __type, and some params to change |
|
450 |
def extract_entity_params(self, eid, minparams=3): |
|
451 |
"""extract form parameters relative to the given eid""" |
|
452 |
params = {} |
|
453 |
eid = str(eid) |
|
454 |
form = self.form |
|
455 |
for param in form: |
|
456 |
try: |
|
457 |
name, peid = param.split(':', 1) |
|
458 |
except ValueError: |
|
459 |
if not param.startswith('__') and param != "eid": |
|
6079 | 460 |
self.warning('param %s mis-formatted', param) |
0 | 461 |
continue |
462 |
if peid == eid: |
|
463 |
value = form[param] |
|
464 |
if value == INTERNAL_FIELD_VALUE: |
|
465 |
value = None |
|
466 |
params[name] = value |
|
467 |
params['eid'] = eid |
|
468 |
if len(params) < minparams: |
|
469 |
raise RequestError(self._('missing parameters for entity %s') % eid) |
|
470 |
return params |
|
1426 | 471 |
|
4277
35cd057339b2
turn all the stuff used to handle 'generic relations' in forms into proper
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
472 |
# XXX this should go to the GenericRelationsField. missing edition cancel protocol. |
0 | 473 |
|
474 |
def remove_pending_operations(self): |
|
475 |
"""shortcut to clear req's pending_{delete,insert} entries |
|
476 |
||
477 |
This is needed when the edition is completed (whether it's validated |
|
478 |
or cancelled) |
|
479 |
""" |
|
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
480 |
self.session.data.pop('pending_insert', None) |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
481 |
self.session.data.pop('pending_delete', None) |
0 | 482 |
|
483 |
def cancel_edition(self, errorurl): |
|
484 |
"""remove pending operations and `errorurl`'s specific stored data |
|
485 |
""" |
|
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
486 |
self.session.data.pop(errorurl, None) |
0 | 487 |
self.remove_pending_operations() |
1426 | 488 |
|
0 | 489 |
# high level methods for HTTP headers management ########################## |
490 |
||
491 |
# must be cached since login/password are popped from the form dictionary |
|
492 |
# and this method may be called multiple times during authentication |
|
493 |
@cached |
|
494 |
def get_authorization(self): |
|
495 |
"""Parse and return the Authorization header""" |
|
496 |
if self.authmode == "cookie": |
|
497 |
try: |
|
498 |
user = self.form.pop("__login") |
|
499 |
passwd = self.form.pop("__password", '') |
|
500 |
return user, passwd.encode('UTF8') |
|
501 |
except KeyError: |
|
502 |
self.debug('no login/password in form params') |
|
503 |
return None, None |
|
504 |
else: |
|
505 |
return self.header_authorization() |
|
1426 | 506 |
|
0 | 507 |
def get_cookie(self): |
508 |
"""retrieve request cookies, returns an empty cookie if not found""" |
|
509 |
try: |
|
510 |
return Cookie.SimpleCookie(self.get_header('Cookie')) |
|
511 |
except KeyError: |
|
512 |
return Cookie.SimpleCookie() |
|
513 |
||
3653
ef71abb1e77b
[req] new expires argument to set_cookie
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3293
diff
changeset
|
514 |
def set_cookie(self, cookie, key, maxage=300, expires=None): |
0 | 515 |
"""set / update a cookie key |
516 |
||
517 |
by default, cookie will be available for the next 5 minutes. |
|
518 |
Give maxage = None to have a "session" cookie expiring when the |
|
519 |
client close its browser |
|
520 |
""" |
|
521 |
morsel = cookie[key] |
|
522 |
if maxage is not None: |
|
523 |
morsel['Max-Age'] = maxage |
|
3653
ef71abb1e77b
[req] new expires argument to set_cookie
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3293
diff
changeset
|
524 |
if expires: |
ef71abb1e77b
[req] new expires argument to set_cookie
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3293
diff
changeset
|
525 |
morsel['expires'] = expires.strftime('%a, %d %b %Y %H:%M:%S %z') |
0 | 526 |
# make sure cookie is set on the correct path |
527 |
morsel['path'] = self.base_url_path() |
|
528 |
self.add_header('Set-Cookie', morsel.OutputString()) |
|
529 |
||
530 |
def remove_cookie(self, cookie, key): |
|
531 |
"""remove a cookie by expiring it""" |
|
3653
ef71abb1e77b
[req] new expires argument to set_cookie
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3293
diff
changeset
|
532 |
self.set_cookie(cookie, key, maxage=0, expires=date(1970, 1, 1)) |
0 | 533 |
|
534 |
def set_content_type(self, content_type, filename=None, encoding=None): |
|
535 |
"""set output content type for this request. An optional filename |
|
536 |
may be given |
|
537 |
""" |
|
6353
b622602f8e9d
don't add another encoding if already present in content-type
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents:
6259
diff
changeset
|
538 |
if content_type.startswith('text/') and ';charset=' not in content_type: |
0 | 539 |
content_type += ';charset=' + (encoding or self.encoding) |
540 |
self.set_header('content-type', content_type) |
|
541 |
if filename: |
|
542 |
if isinstance(filename, unicode): |
|
543 |
filename = header(filename).encode() |
|
544 |
self.set_header('content-disposition', 'inline; filename=%s' |
|
545 |
% filename) |
|
546 |
||
547 |
# high level methods for HTML headers management ########################## |
|
548 |
||
2258
79bc598c6411
when request is a json request, bind on 'ajax-loaded' instead of document.ready()
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2255
diff
changeset
|
549 |
def add_onload(self, jscode): |
4851
e55bdd10421e
remove deprecation warning introduced by add_onload api change
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4719
diff
changeset
|
550 |
self.html_headers.add_onload(jscode) |
2258
79bc598c6411
when request is a json request, bind on 'ajax-loaded' instead of document.ready()
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2255
diff
changeset
|
551 |
|
0 | 552 |
def add_js(self, jsfiles, localfile=True): |
553 |
"""specify a list of JS files to include in the HTML headers |
|
554 |
:param jsfiles: a JS filename or a list of JS filenames |
|
555 |
:param localfile: if True, the default data dir prefix is added to the |
|
556 |
JS filename |
|
557 |
""" |
|
558 |
if isinstance(jsfiles, basestring): |
|
559 |
jsfiles = (jsfiles,) |
|
560 |
for jsfile in jsfiles: |
|
561 |
if localfile: |
|
562 |
jsfile = self.datadir_url + jsfile |
|
563 |
self.html_headers.add_js(jsfile) |
|
564 |
||
4860
cedb6afdb7da
[web] fix #736332: iespec functionality for add_css
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
4719
diff
changeset
|
565 |
def add_css(self, cssfiles, media=u'all', localfile=True, ieonly=False, |
cedb6afdb7da
[web] fix #736332: iespec functionality for add_css
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
4719
diff
changeset
|
566 |
iespec=u'[if lt IE 8]'): |
0 | 567 |
"""specify a CSS file to include in the HTML headers |
5290
15846058378b
[doc/book] fix a bit the request chapter, add autodoc
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4984
diff
changeset
|
568 |
|
0 | 569 |
:param cssfiles: a CSS filename or a list of CSS filenames |
570 |
:param media: the CSS's media if necessary |
|
571 |
:param localfile: if True, the default data dir prefix is added to the |
|
572 |
CSS filename |
|
4860
cedb6afdb7da
[web] fix #736332: iespec functionality for add_css
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
4719
diff
changeset
|
573 |
:param ieonly: True if this css is specific to IE |
cedb6afdb7da
[web] fix #736332: iespec functionality for add_css
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
4719
diff
changeset
|
574 |
:param iespec: conditional expression that will be used around |
cedb6afdb7da
[web] fix #736332: iespec functionality for add_css
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
4719
diff
changeset
|
575 |
the css inclusion. cf: |
cedb6afdb7da
[web] fix #736332: iespec functionality for add_css
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
4719
diff
changeset
|
576 |
http://msdn.microsoft.com/en-us/library/ms537512(VS.85).aspx |
0 | 577 |
""" |
578 |
if isinstance(cssfiles, basestring): |
|
579 |
cssfiles = (cssfiles,) |
|
580 |
if ieonly: |
|
581 |
if self.ie_browser(): |
|
4860
cedb6afdb7da
[web] fix #736332: iespec functionality for add_css
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
4719
diff
changeset
|
582 |
extraargs = [iespec] |
0 | 583 |
add_css = self.html_headers.add_ie_css |
584 |
else: |
|
585 |
return # no need to do anything on non IE browsers |
|
586 |
else: |
|
4860
cedb6afdb7da
[web] fix #736332: iespec functionality for add_css
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
4719
diff
changeset
|
587 |
extraargs = [] |
0 | 588 |
add_css = self.html_headers.add_css |
589 |
for cssfile in cssfiles: |
|
590 |
if localfile: |
|
591 |
cssfile = self.datadir_url + cssfile |
|
4860
cedb6afdb7da
[web] fix #736332: iespec functionality for add_css
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
4719
diff
changeset
|
592 |
add_css(cssfile, media, *extraargs) |
1426 | 593 |
|
5713
605f571198eb
[web] ajax_replace_url superseed build_ajax_replace_url, more generic and relying on the json controller (closes #750090)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5685
diff
changeset
|
594 |
@deprecated('[3.9] use ajax_replace_url() instead, naming rql and vid arguments') |
1801
672acc730ce5
ajax_replace_url becomes obsolete, req.build_ajax_replace_url should be used instead
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1718
diff
changeset
|
595 |
def build_ajax_replace_url(self, nodeid, rql, vid, replacemode='replace', |
672acc730ce5
ajax_replace_url becomes obsolete, req.build_ajax_replace_url should be used instead
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1718
diff
changeset
|
596 |
**extraparams): |
5713
605f571198eb
[web] ajax_replace_url superseed build_ajax_replace_url, more generic and relying on the json controller (closes #750090)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5685
diff
changeset
|
597 |
return self.ajax_replace_url(nodeid, replacemode, rql=rql, vid=vid, |
605f571198eb
[web] ajax_replace_url superseed build_ajax_replace_url, more generic and relying on the json controller (closes #750090)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5685
diff
changeset
|
598 |
**extraparams) |
605f571198eb
[web] ajax_replace_url superseed build_ajax_replace_url, more generic and relying on the json controller (closes #750090)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5685
diff
changeset
|
599 |
|
605f571198eb
[web] ajax_replace_url superseed build_ajax_replace_url, more generic and relying on the json controller (closes #750090)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5685
diff
changeset
|
600 |
def ajax_replace_url(self, nodeid, replacemode='replace', **extraparams): |
5290
15846058378b
[doc/book] fix a bit the request chapter, add autodoc
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4984
diff
changeset
|
601 |
"""builds an ajax url that will replace nodeid's content |
15846058378b
[doc/book] fix a bit the request chapter, add autodoc
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4984
diff
changeset
|
602 |
|
1801
672acc730ce5
ajax_replace_url becomes obsolete, req.build_ajax_replace_url should be used instead
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1718
diff
changeset
|
603 |
:param nodeid: the dom id of the node to replace |
672acc730ce5
ajax_replace_url becomes obsolete, req.build_ajax_replace_url should be used instead
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1718
diff
changeset
|
604 |
:param replacemode: defines how the replacement should be done. |
5290
15846058378b
[doc/book] fix a bit the request chapter, add autodoc
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4984
diff
changeset
|
605 |
|
5713
605f571198eb
[web] ajax_replace_url superseed build_ajax_replace_url, more generic and relying on the json controller (closes #750090)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5685
diff
changeset
|
606 |
Possible values are : |
605f571198eb
[web] ajax_replace_url superseed build_ajax_replace_url, more generic and relying on the json controller (closes #750090)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5685
diff
changeset
|
607 |
- 'replace' to replace the node's content with the generated HTML |
605f571198eb
[web] ajax_replace_url superseed build_ajax_replace_url, more generic and relying on the json controller (closes #750090)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5685
diff
changeset
|
608 |
- 'swap' to replace the node itself with the generated HTML |
605f571198eb
[web] ajax_replace_url superseed build_ajax_replace_url, more generic and relying on the json controller (closes #750090)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5685
diff
changeset
|
609 |
- 'append' to append the generated HTML to the node's content |
605f571198eb
[web] ajax_replace_url superseed build_ajax_replace_url, more generic and relying on the json controller (closes #750090)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5685
diff
changeset
|
610 |
|
605f571198eb
[web] ajax_replace_url superseed build_ajax_replace_url, more generic and relying on the json controller (closes #750090)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5685
diff
changeset
|
611 |
Arbitrary extra named arguments may be given, they will be included as |
605f571198eb
[web] ajax_replace_url superseed build_ajax_replace_url, more generic and relying on the json controller (closes #750090)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5685
diff
changeset
|
612 |
parameters of the generated url. |
1801
672acc730ce5
ajax_replace_url becomes obsolete, req.build_ajax_replace_url should be used instead
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1718
diff
changeset
|
613 |
""" |
6564
ff9f7c566464
[request] fix ajax_replace_url which breaks if the url contains some quotes (that will be properly quoted but unquoted by the browser, breaking the js expression) by using a separated js function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6543
diff
changeset
|
614 |
# define a function in headers and use it in the link to avoid url |
ff9f7c566464
[request] fix ajax_replace_url which breaks if the url contains some quotes (that will be properly quoted but unquoted by the browser, breaking the js expression) by using a separated js function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6543
diff
changeset
|
615 |
# unescaping pb: browsers give the js expression to the interpreter |
ff9f7c566464
[request] fix ajax_replace_url which breaks if the url contains some quotes (that will be properly quoted but unquoted by the browser, breaking the js expression) by using a separated js function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6543
diff
changeset
|
616 |
# after having url unescaping the content. This may make appear some |
ff9f7c566464
[request] fix ajax_replace_url which breaks if the url contains some quotes (that will be properly quoted but unquoted by the browser, breaking the js expression) by using a separated js function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6543
diff
changeset
|
617 |
# quote or other special characters that will break the js expression. |
5713
605f571198eb
[web] ajax_replace_url superseed build_ajax_replace_url, more generic and relying on the json controller (closes #750090)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5685
diff
changeset
|
618 |
extraparams.setdefault('fname', 'view') |
605f571198eb
[web] ajax_replace_url superseed build_ajax_replace_url, more generic and relying on the json controller (closes #750090)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5685
diff
changeset
|
619 |
url = self.build_url('json', **extraparams) |
6564
ff9f7c566464
[request] fix ajax_replace_url which breaks if the url contains some quotes (that will be properly quoted but unquoted by the browser, breaking the js expression) by using a separated js function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6543
diff
changeset
|
620 |
cbname = build_cb_uid(url[:50]) |
ff9f7c566464
[request] fix ajax_replace_url which breaks if the url contains some quotes (that will be properly quoted but unquoted by the browser, breaking the js expression) by using a separated js function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6543
diff
changeset
|
621 |
jscode = 'function %s() { $("#%s").%s; }' % ( |
ff9f7c566464
[request] fix ajax_replace_url which breaks if the url contains some quotes (that will be properly quoted but unquoted by the browser, breaking the js expression) by using a separated js function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6543
diff
changeset
|
622 |
cbname, nodeid, js.loadxhtml(url, None, 'get', replacemode)) |
ff9f7c566464
[request] fix ajax_replace_url which breaks if the url contains some quotes (that will be properly quoted but unquoted by the browser, breaking the js expression) by using a separated js function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6543
diff
changeset
|
623 |
self.html_headers.add_post_inline_script(jscode) |
ff9f7c566464
[request] fix ajax_replace_url which breaks if the url contains some quotes (that will be properly quoted but unquoted by the browser, breaking the js expression) by using a separated js function
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6543
diff
changeset
|
624 |
return "javascript: %s()" % cbname |
1801
672acc730ce5
ajax_replace_url becomes obsolete, req.build_ajax_replace_url should be used instead
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1718
diff
changeset
|
625 |
|
0 | 626 |
# urls/path management #################################################### |
1426 | 627 |
|
0 | 628 |
def url(self, includeparams=True): |
629 |
"""return currently accessed url""" |
|
630 |
return self.base_url() + self.relative_path(includeparams) |
|
631 |
||
632 |
def selected(self, url): |
|
633 |
"""return True if the url is equivalent to currently accessed url""" |
|
634 |
reqpath = self.relative_path().lower() |
|
635 |
baselen = len(self.base_url()) |
|
636 |
return (reqpath == url[baselen:].lower()) |
|
637 |
||
638 |
def base_url_prepend_host(self, hostname): |
|
639 |
protocol, roothost = urlsplit(self.base_url())[:2] |
|
640 |
if roothost.startswith('www.'): |
|
641 |
roothost = roothost[4:] |
|
642 |
return '%s://%s.%s' % (protocol, hostname, roothost) |
|
643 |
||
644 |
def base_url_path(self): |
|
645 |
"""returns the absolute path of the base url""" |
|
646 |
return urlsplit(self.base_url())[2] |
|
1426 | 647 |
|
0 | 648 |
@cached |
649 |
def from_controller(self): |
|
650 |
"""return the id (string) of the controller issuing the request""" |
|
651 |
controller = self.relative_path(False).split('/', 1)[0] |
|
2650
18aec79ec3a3
R [vreg] important refactoring of the vregistry, moving behaviour to end dictionnary (and so leaving room for more flexibility ; keep bw compat ; update api usage in cw
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2613
diff
changeset
|
652 |
registered_controllers = self.vreg['controllers'].keys() |
0 | 653 |
if controller in registered_controllers: |
654 |
return controller |
|
655 |
return 'view' |
|
1426 | 656 |
|
0 | 657 |
def validate_cache(self): |
658 |
"""raise a `DirectResponse` exception if a cached page along the way |
|
659 |
exists and is still usable. |
|
660 |
||
661 |
calls the client-dependant implementation of `_validate_cache` |
|
662 |
""" |
|
663 |
self._validate_cache() |
|
664 |
if self.http_method() == 'HEAD': |
|
665 |
raise StatusResponse(200, '') |
|
1426 | 666 |
|
0 | 667 |
# abstract methods to override according to the web front-end ############# |
1426 | 668 |
|
0 | 669 |
def http_method(self): |
670 |
"""returns 'POST', 'GET', 'HEAD', etc.""" |
|
671 |
raise NotImplementedError() |
|
672 |
||
673 |
def _validate_cache(self): |
|
674 |
"""raise a `DirectResponse` exception if a cached page along the way |
|
675 |
exists and is still usable |
|
676 |
""" |
|
677 |
raise NotImplementedError() |
|
1426 | 678 |
|
0 | 679 |
def relative_path(self, includeparams=True): |
680 |
"""return the normalized path of the request (ie at least relative |
|
2476
1294a6bdf3bf
application -> instance where it makes sense
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2315
diff
changeset
|
681 |
to the instance's root, but some other normalization may be needed |
0 | 682 |
so that the returned path may be used to compare to generated urls |
683 |
||
684 |
:param includeparams: |
|
685 |
boolean indicating if GET form parameters should be kept in the path |
|
686 |
""" |
|
687 |
raise NotImplementedError() |
|
688 |
||
689 |
def get_header(self, header, default=None): |
|
690 |
"""return the value associated with the given input HTTP header, |
|
691 |
raise KeyError if the header is not set |
|
692 |
""" |
|
693 |
raise NotImplementedError() |
|
694 |
||
5155
1dea6e0fdfc1
Switched from TwistedWeb2 to TwistedWeb
Adrien Chauve <adrien.chauve@logilab.fr>
parents:
4984
diff
changeset
|
695 |
def set_header(self, header, value, raw=True): |
0 | 696 |
"""set an output HTTP header""" |
5155
1dea6e0fdfc1
Switched from TwistedWeb2 to TwistedWeb
Adrien Chauve <adrien.chauve@logilab.fr>
parents:
4984
diff
changeset
|
697 |
if raw: |
1dea6e0fdfc1
Switched from TwistedWeb2 to TwistedWeb
Adrien Chauve <adrien.chauve@logilab.fr>
parents:
4984
diff
changeset
|
698 |
# adding encoded header is important, else page content |
1dea6e0fdfc1
Switched from TwistedWeb2 to TwistedWeb
Adrien Chauve <adrien.chauve@logilab.fr>
parents:
4984
diff
changeset
|
699 |
# will be reconverted back to unicode and apart unefficiency, this |
1dea6e0fdfc1
Switched from TwistedWeb2 to TwistedWeb
Adrien Chauve <adrien.chauve@logilab.fr>
parents:
4984
diff
changeset
|
700 |
# may cause decoding problem (e.g. when downloading a file) |
1dea6e0fdfc1
Switched from TwistedWeb2 to TwistedWeb
Adrien Chauve <adrien.chauve@logilab.fr>
parents:
4984
diff
changeset
|
701 |
self.headers_out.setRawHeaders(header, [str(value)]) |
1dea6e0fdfc1
Switched from TwistedWeb2 to TwistedWeb
Adrien Chauve <adrien.chauve@logilab.fr>
parents:
4984
diff
changeset
|
702 |
else: |
1dea6e0fdfc1
Switched from TwistedWeb2 to TwistedWeb
Adrien Chauve <adrien.chauve@logilab.fr>
parents:
4984
diff
changeset
|
703 |
self.headers_out.setHeader(header, value) |
0 | 704 |
|
705 |
def add_header(self, header, value): |
|
706 |
"""add an output HTTP header""" |
|
5155
1dea6e0fdfc1
Switched from TwistedWeb2 to TwistedWeb
Adrien Chauve <adrien.chauve@logilab.fr>
parents:
4984
diff
changeset
|
707 |
# adding encoded header is important, else page content |
1dea6e0fdfc1
Switched from TwistedWeb2 to TwistedWeb
Adrien Chauve <adrien.chauve@logilab.fr>
parents:
4984
diff
changeset
|
708 |
# will be reconverted back to unicode and apart unefficiency, this |
1dea6e0fdfc1
Switched from TwistedWeb2 to TwistedWeb
Adrien Chauve <adrien.chauve@logilab.fr>
parents:
4984
diff
changeset
|
709 |
# may cause decoding problem (e.g. when downloading a file) |
1dea6e0fdfc1
Switched from TwistedWeb2 to TwistedWeb
Adrien Chauve <adrien.chauve@logilab.fr>
parents:
4984
diff
changeset
|
710 |
self.headers_out.addRawHeader(header, str(value)) |
1426 | 711 |
|
0 | 712 |
def remove_header(self, header): |
713 |
"""remove an output HTTP header""" |
|
5155
1dea6e0fdfc1
Switched from TwistedWeb2 to TwistedWeb
Adrien Chauve <adrien.chauve@logilab.fr>
parents:
4984
diff
changeset
|
714 |
self.headers_out.removeHeader(header) |
1426 | 715 |
|
0 | 716 |
def header_authorization(self): |
717 |
"""returns a couple (auth-type, auth-value)""" |
|
718 |
auth = self.get_header("Authorization", None) |
|
719 |
if auth: |
|
720 |
scheme, rest = auth.split(' ', 1) |
|
721 |
scheme = scheme.lower() |
|
722 |
try: |
|
723 |
assert scheme == "basic" |
|
724 |
user, passwd = base64.decodestring(rest).split(":", 1) |
|
725 |
# XXX HTTP header encoding: use email.Header? |
|
726 |
return user.decode('UTF8'), passwd |
|
727 |
except Exception, ex: |
|
728 |
self.debug('bad authorization %s (%s: %s)', |
|
729 |
auth, ex.__class__.__name__, ex) |
|
730 |
return None, None |
|
731 |
||
1716
b12d9e22bac3
basic support for http Accept header (untested)
sylvain.thenault@logilab.fr
parents:
1560
diff
changeset
|
732 |
def parse_accept_header(self, header): |
b12d9e22bac3
basic support for http Accept header (untested)
sylvain.thenault@logilab.fr
parents:
1560
diff
changeset
|
733 |
"""returns an ordered list of preferred languages""" |
b12d9e22bac3
basic support for http Accept header (untested)
sylvain.thenault@logilab.fr
parents:
1560
diff
changeset
|
734 |
accepteds = self.get_header(header, '') |
b12d9e22bac3
basic support for http Accept header (untested)
sylvain.thenault@logilab.fr
parents:
1560
diff
changeset
|
735 |
values = [] |
b12d9e22bac3
basic support for http Accept header (untested)
sylvain.thenault@logilab.fr
parents:
1560
diff
changeset
|
736 |
for info in accepteds.split(','): |
0 | 737 |
try: |
1716
b12d9e22bac3
basic support for http Accept header (untested)
sylvain.thenault@logilab.fr
parents:
1560
diff
changeset
|
738 |
value, scores = info.split(';', 1) |
0 | 739 |
except ValueError: |
1716
b12d9e22bac3
basic support for http Accept header (untested)
sylvain.thenault@logilab.fr
parents:
1560
diff
changeset
|
740 |
value = info |
0 | 741 |
score = 1.0 |
1716
b12d9e22bac3
basic support for http Accept header (untested)
sylvain.thenault@logilab.fr
parents:
1560
diff
changeset
|
742 |
else: |
b12d9e22bac3
basic support for http Accept header (untested)
sylvain.thenault@logilab.fr
parents:
1560
diff
changeset
|
743 |
for score in scores.split(';'): |
b12d9e22bac3
basic support for http Accept header (untested)
sylvain.thenault@logilab.fr
parents:
1560
diff
changeset
|
744 |
try: |
b12d9e22bac3
basic support for http Accept header (untested)
sylvain.thenault@logilab.fr
parents:
1560
diff
changeset
|
745 |
scorekey, scoreval = score.split('=') |
1717
d2c4d3bd0602
correct wrong condition and missing import
Graziella Toutoungis <graziella.toutoungis@logilab.fr>
parents:
1716
diff
changeset
|
746 |
if scorekey == 'q': # XXX 'level' |
4719
aaed3f813ef8
kill dead/useless code as suggested by pylint
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4529
diff
changeset
|
747 |
score = float(scoreval) |
1716
b12d9e22bac3
basic support for http Accept header (untested)
sylvain.thenault@logilab.fr
parents:
1560
diff
changeset
|
748 |
except ValueError: |
b12d9e22bac3
basic support for http Accept header (untested)
sylvain.thenault@logilab.fr
parents:
1560
diff
changeset
|
749 |
continue |
1718
26ff2d292183
correct the values list append
Graziella Toutoungis <graziella.toutoungis@logilab.fr>
parents:
1717
diff
changeset
|
750 |
values.append((score, value)) |
1716
b12d9e22bac3
basic support for http Accept header (untested)
sylvain.thenault@logilab.fr
parents:
1560
diff
changeset
|
751 |
values.sort(reverse=True) |
b12d9e22bac3
basic support for http Accept header (untested)
sylvain.thenault@logilab.fr
parents:
1560
diff
changeset
|
752 |
return (value for (score, value) in values) |
0 | 753 |
|
754 |
def header_if_modified_since(self): |
|
755 |
"""If the HTTP header If-modified-since is set, return the equivalent |
|
756 |
mx date time value (GMT), else return None |
|
757 |
""" |
|
758 |
raise NotImplementedError() |
|
1426 | 759 |
|
3094
978ed8c2c0e4
[googlemap] #344872 set request content-type to text/html
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
2650
diff
changeset
|
760 |
def demote_to_html(self): |
978ed8c2c0e4
[googlemap] #344872 set request content-type to text/html
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
2650
diff
changeset
|
761 |
"""helper method to dynamically set request content type to text/html |
978ed8c2c0e4
[googlemap] #344872 set request content-type to text/html
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
2650
diff
changeset
|
762 |
|
978ed8c2c0e4
[googlemap] #344872 set request content-type to text/html
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
2650
diff
changeset
|
763 |
The global doctype and xmldec must also be changed otherwise the browser |
978ed8c2c0e4
[googlemap] #344872 set request content-type to text/html
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
2650
diff
changeset
|
764 |
will display '<[' at the beginning of the page |
978ed8c2c0e4
[googlemap] #344872 set request content-type to text/html
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
2650
diff
changeset
|
765 |
""" |
978ed8c2c0e4
[googlemap] #344872 set request content-type to text/html
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
2650
diff
changeset
|
766 |
self.set_content_type('text/html') |
978ed8c2c0e4
[googlemap] #344872 set request content-type to text/html
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
2650
diff
changeset
|
767 |
self.main_stream.doctype = TRANSITIONAL_DOCTYPE_NOEXT |
978ed8c2c0e4
[googlemap] #344872 set request content-type to text/html
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
2650
diff
changeset
|
768 |
self.main_stream.xmldecl = u'' |
978ed8c2c0e4
[googlemap] #344872 set request content-type to text/html
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
2650
diff
changeset
|
769 |
|
0 | 770 |
# page data management #################################################### |
771 |
||
772 |
def get_page_data(self, key, default=None): |
|
5683
ca2badf54858
[request] fix typo
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5505
diff
changeset
|
773 |
"""return value associated to `key` in current page data""" |
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
774 |
page_data = self.session.data.get(self.pageid) |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
775 |
if page_data is None: |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
776 |
return default |
0 | 777 |
return page_data.get(key, default) |
1426 | 778 |
|
0 | 779 |
def set_page_data(self, key, value): |
780 |
"""set value associated to `key` in current page data""" |
|
781 |
self.html_headers.add_unload_pagedata() |
|
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
782 |
page_data = self.session.data.setdefault(self.pageid, {}) |
0 | 783 |
page_data[key] = value |
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
784 |
self.session.data[self.pageid] = page_data |
1426 | 785 |
|
0 | 786 |
def del_page_data(self, key=None): |
787 |
"""remove value associated to `key` in current page data |
|
788 |
if `key` is None, all page data will be cleared |
|
789 |
""" |
|
790 |
if key is None: |
|
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
791 |
self.session.data.pop(self.pageid, None) |
0 | 792 |
else: |
5223
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
793 |
try: |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
794 |
del self.session.data[self.pageid][key] |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
795 |
except KeyError: |
6abd6e3599f4
#773448: refactor session and 'no connection' handling, by introducing proper web session. We should now be able to see page even when no anon is configured, and be redirected to the login form as soon as one tries to do a query.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5155
diff
changeset
|
796 |
pass |
0 | 797 |
|
798 |
# user-agent detection #################################################### |
|
799 |
||
800 |
@cached |
|
801 |
def useragent(self): |
|
802 |
return self.get_header('User-Agent', None) |
|
803 |
||
804 |
def ie_browser(self): |
|
805 |
useragent = self.useragent() |
|
806 |
return useragent and 'MSIE' in useragent |
|
1426 | 807 |
|
0 | 808 |
def xhtml_browser(self): |
2558
81c8b5312f9c
move test on force-html-content-type to xhtml_browser method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2556
diff
changeset
|
809 |
"""return True if the browser is considered as xhtml compatible. |
81c8b5312f9c
move test on force-html-content-type to xhtml_browser method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2556
diff
changeset
|
810 |
|
81c8b5312f9c
move test on force-html-content-type to xhtml_browser method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2556
diff
changeset
|
811 |
If the instance is configured to always return text/html and not |
81c8b5312f9c
move test on force-html-content-type to xhtml_browser method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2556
diff
changeset
|
812 |
application/xhtml+xml, this method will always return False, even though |
81c8b5312f9c
move test on force-html-content-type to xhtml_browser method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2556
diff
changeset
|
813 |
this is semantically different |
81c8b5312f9c
move test on force-html-content-type to xhtml_browser method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2556
diff
changeset
|
814 |
""" |
81c8b5312f9c
move test on force-html-content-type to xhtml_browser method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2556
diff
changeset
|
815 |
if self.vreg.config['force-html-content-type']: |
81c8b5312f9c
move test on force-html-content-type to xhtml_browser method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2556
diff
changeset
|
816 |
return False |
0 | 817 |
useragent = self.useragent() |
1421
77ee26df178f
doc type handling refactoring: do the ext substitution at the module level
sylvain.thenault@logilab.fr
parents:
1173
diff
changeset
|
818 |
# * MSIE/Konqueror does not support xml content-type |
77ee26df178f
doc type handling refactoring: do the ext substitution at the module level
sylvain.thenault@logilab.fr
parents:
1173
diff
changeset
|
819 |
# * Opera supports xhtml and handles namespaces properly but it breaks |
77ee26df178f
doc type handling refactoring: do the ext substitution at the module level
sylvain.thenault@logilab.fr
parents:
1173
diff
changeset
|
820 |
# jQuery.attr() |
495
f8b1edfe9621
[#80966] Opera supports xhtml and handles namespaces properly but it breaks jQuery.attr(), so xhtml_browser return False if the webbrowser is opera
Stephanie Marcu <stephanie.marcu@logilab.fr>
parents:
0
diff
changeset
|
821 |
if useragent and ('MSIE' in useragent or 'KHTML' in useragent |
f8b1edfe9621
[#80966] Opera supports xhtml and handles namespaces properly but it breaks jQuery.attr(), so xhtml_browser return False if the webbrowser is opera
Stephanie Marcu <stephanie.marcu@logilab.fr>
parents:
0
diff
changeset
|
822 |
or 'Opera' in useragent): |
0 | 823 |
return False |
824 |
return True |
|
825 |
||
1421
77ee26df178f
doc type handling refactoring: do the ext substitution at the module level
sylvain.thenault@logilab.fr
parents:
1173
diff
changeset
|
826 |
def html_content_type(self): |
2558
81c8b5312f9c
move test on force-html-content-type to xhtml_browser method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2556
diff
changeset
|
827 |
if self.xhtml_browser(): |
1421
77ee26df178f
doc type handling refactoring: do the ext substitution at the module level
sylvain.thenault@logilab.fr
parents:
1173
diff
changeset
|
828 |
return 'application/xhtml+xml' |
77ee26df178f
doc type handling refactoring: do the ext substitution at the module level
sylvain.thenault@logilab.fr
parents:
1173
diff
changeset
|
829 |
return 'text/html' |
77ee26df178f
doc type handling refactoring: do the ext substitution at the module level
sylvain.thenault@logilab.fr
parents:
1173
diff
changeset
|
830 |
|
2559
46859078c866
[R xhtml] remove xhtml_wrap* function, use instead a single req.document_surrounding_div method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2558
diff
changeset
|
831 |
def document_surrounding_div(self): |
46859078c866
[R xhtml] remove xhtml_wrap* function, use instead a single req.document_surrounding_div method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2558
diff
changeset
|
832 |
if self.xhtml_browser(): |
4454
aba1b563705b
[request] add a note about the encoding mgmt (or lack thereof)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4212
diff
changeset
|
833 |
return (u'<?xml version="1.0"?>\n' + STRICT_DOCTYPE + # XXX encoding ? |
2559
46859078c866
[R xhtml] remove xhtml_wrap* function, use instead a single req.document_surrounding_div method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2558
diff
changeset
|
834 |
u'<div xmlns="http://www.w3.org/1999/xhtml" xmlns:cubicweb="http://www.logilab.org/2008/cubicweb">') |
46859078c866
[R xhtml] remove xhtml_wrap* function, use instead a single req.document_surrounding_div method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2558
diff
changeset
|
835 |
return u'<div>' |
46859078c866
[R xhtml] remove xhtml_wrap* function, use instead a single req.document_surrounding_div method
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2558
diff
changeset
|
836 |
|
5467
57372dbfd114
[https] fix resource urls in https version of a site: should use the https version as well to avoid warnings from the nrowser
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5444
diff
changeset
|
837 |
@deprecated('[3.9] use req.uiprops[rid]') |
5444
f7fdb5dd82f6
[webconfig] introduce property sheets. Use them to replace external_resources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
838 |
def external_resource(self, rid, default=_MARKER): |
f7fdb5dd82f6
[webconfig] introduce property sheets. Use them to replace external_resources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
839 |
"""return a path to an external resource, using its identifier |
f7fdb5dd82f6
[webconfig] introduce property sheets. Use them to replace external_resources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
840 |
|
f7fdb5dd82f6
[webconfig] introduce property sheets. Use them to replace external_resources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
841 |
raise `KeyError` if the resource is not defined |
f7fdb5dd82f6
[webconfig] introduce property sheets. Use them to replace external_resources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
842 |
""" |
f7fdb5dd82f6
[webconfig] introduce property sheets. Use them to replace external_resources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
843 |
try: |
5467
57372dbfd114
[https] fix resource urls in https version of a site: should use the https version as well to avoid warnings from the nrowser
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5444
diff
changeset
|
844 |
return self.uiprops[rid] |
5444
f7fdb5dd82f6
[webconfig] introduce property sheets. Use them to replace external_resources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
845 |
except KeyError: |
f7fdb5dd82f6
[webconfig] introduce property sheets. Use them to replace external_resources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
846 |
if default is _MARKER: |
f7fdb5dd82f6
[webconfig] introduce property sheets. Use them to replace external_resources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
847 |
raise |
f7fdb5dd82f6
[webconfig] introduce property sheets. Use them to replace external_resources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
848 |
return default |
f7fdb5dd82f6
[webconfig] introduce property sheets. Use them to replace external_resources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
849 |
|
f7fdb5dd82f6
[webconfig] introduce property sheets. Use them to replace external_resources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
850 |
@deprecated("[3.4] use parse_accept_header('Accept-Language')") |
f7fdb5dd82f6
[webconfig] introduce property sheets. Use them to replace external_resources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
851 |
def header_accept_language(self): |
f7fdb5dd82f6
[webconfig] introduce property sheets. Use them to replace external_resources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
852 |
"""returns an ordered list of preferred languages""" |
f7fdb5dd82f6
[webconfig] introduce property sheets. Use them to replace external_resources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
853 |
return [value.split('-')[0] for value in |
f7fdb5dd82f6
[webconfig] introduce property sheets. Use them to replace external_resources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
854 |
self.parse_accept_header('Accept-Language')] |
f7fdb5dd82f6
[webconfig] introduce property sheets. Use them to replace external_resources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
855 |
|
f7fdb5dd82f6
[webconfig] introduce property sheets. Use them to replace external_resources
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5426
diff
changeset
|
856 |
|
0 | 857 |
from cubicweb import set_log_methods |
858 |
set_log_methods(CubicWebRequestBase, LOGGER) |