Révision d03cb81c
Ajouté par Jérôme Schneider il y a presque 14 ans
- ID d03cb81c13da6c4c0cd6c418321ca6c7bb7c9ef1
larpe/tags/release-1.1.1/AUTHORS | ||
---|---|---|
1 |
Damien Laniel <dlaniel@entrouvert.com> |
|
2 |
|
|
3 |
Artwork and administrave interface design taken from DotClear, version 1.2 and |
|
4 |
2.0, released under the GNU General Public License; and GTK+, version 2.8, |
|
5 |
released under the GNU Lesser General Public License. |
larpe/tags/release-1.1.1/COPYING | ||
---|---|---|
1 |
GNU GENERAL PUBLIC LICENSE |
|
2 |
Version 2, June 1991 |
|
3 |
|
|
4 |
Copyright (C) 1989, 1991 Free Software Foundation, Inc., |
|
5 |
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
6 |
Everyone is permitted to copy and distribute verbatim copies |
|
7 |
of this license document, but changing it is not allowed. |
|
8 |
|
|
9 |
Preamble |
|
10 |
|
|
11 |
The licenses for most software are designed to take away your |
|
12 |
freedom to share and change it. By contrast, the GNU General Public |
|
13 |
License is intended to guarantee your freedom to share and change free |
|
14 |
software--to make sure the software is free for all its users. This |
|
15 |
General Public License applies to most of the Free Software |
|
16 |
Foundation's software and to any other program whose authors commit to |
|
17 |
using it. (Some other Free Software Foundation software is covered by |
|
18 |
the GNU Lesser General Public License instead.) You can apply it to |
|
19 |
your programs, too. |
|
20 |
|
|
21 |
When we speak of free software, we are referring to freedom, not |
|
22 |
price. Our General Public Licenses are designed to make sure that you |
|
23 |
have the freedom to distribute copies of free software (and charge for |
|
24 |
this service if you wish), that you receive source code or can get it |
|
25 |
if you want it, that you can change the software or use pieces of it |
|
26 |
in new free programs; and that you know you can do these things. |
|
27 |
|
|
28 |
To protect your rights, we need to make restrictions that forbid |
|
29 |
anyone to deny you these rights or to ask you to surrender the rights. |
|
30 |
These restrictions translate to certain responsibilities for you if you |
|
31 |
distribute copies of the software, or if you modify it. |
|
32 |
|
|
33 |
For example, if you distribute copies of such a program, whether |
|
34 |
gratis or for a fee, you must give the recipients all the rights that |
|
35 |
you have. You must make sure that they, too, receive or can get the |
|
36 |
source code. And you must show them these terms so they know their |
|
37 |
rights. |
|
38 |
|
|
39 |
We protect your rights with two steps: (1) copyright the software, and |
|
40 |
(2) offer you this license which gives you legal permission to copy, |
|
41 |
distribute and/or modify the software. |
|
42 |
|
|
43 |
Also, for each author's protection and ours, we want to make certain |
|
44 |
that everyone understands that there is no warranty for this free |
|
45 |
software. If the software is modified by someone else and passed on, we |
|
46 |
want its recipients to know that what they have is not the original, so |
|
47 |
that any problems introduced by others will not reflect on the original |
|
48 |
authors' reputations. |
|
49 |
|
|
50 |
Finally, any free program is threatened constantly by software |
|
51 |
patents. We wish to avoid the danger that redistributors of a free |
|
52 |
program will individually obtain patent licenses, in effect making the |
|
53 |
program proprietary. To prevent this, we have made it clear that any |
|
54 |
patent must be licensed for everyone's free use or not licensed at all. |
|
55 |
|
|
56 |
The precise terms and conditions for copying, distribution and |
|
57 |
modification follow. |
|
58 |
|
|
59 |
GNU GENERAL PUBLIC LICENSE |
|
60 |
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION |
|
61 |
|
|
62 |
0. This License applies to any program or other work which contains |
|
63 |
a notice placed by the copyright holder saying it may be distributed |
|
64 |
under the terms of this General Public License. The "Program", below, |
|
65 |
refers to any such program or work, and a "work based on the Program" |
|
66 |
means either the Program or any derivative work under copyright law: |
|
67 |
that is to say, a work containing the Program or a portion of it, |
|
68 |
either verbatim or with modifications and/or translated into another |
|
69 |
language. (Hereinafter, translation is included without limitation in |
|
70 |
the term "modification".) Each licensee is addressed as "you". |
|
71 |
|
|
72 |
Activities other than copying, distribution and modification are not |
|
73 |
covered by this License; they are outside its scope. The act of |
|
74 |
running the Program is not restricted, and the output from the Program |
|
75 |
is covered only if its contents constitute a work based on the |
|
76 |
Program (independent of having been made by running the Program). |
|
77 |
Whether that is true depends on what the Program does. |
|
78 |
|
|
79 |
1. You may copy and distribute verbatim copies of the Program's |
|
80 |
source code as you receive it, in any medium, provided that you |
|
81 |
conspicuously and appropriately publish on each copy an appropriate |
|
82 |
copyright notice and disclaimer of warranty; keep intact all the |
|
83 |
notices that refer to this License and to the absence of any warranty; |
|
84 |
and give any other recipients of the Program a copy of this License |
|
85 |
along with the Program. |
|
86 |
|
|
87 |
You may charge a fee for the physical act of transferring a copy, and |
|
88 |
you may at your option offer warranty protection in exchange for a fee. |
|
89 |
|
|
90 |
2. You may modify your copy or copies of the Program or any portion |
|
91 |
of it, thus forming a work based on the Program, and copy and |
|
92 |
distribute such modifications or work under the terms of Section 1 |
|
93 |
above, provided that you also meet all of these conditions: |
|
94 |
|
|
95 |
a) You must cause the modified files to carry prominent notices |
|
96 |
stating that you changed the files and the date of any change. |
|
97 |
|
|
98 |
b) You must cause any work that you distribute or publish, that in |
|
99 |
whole or in part contains or is derived from the Program or any |
|
100 |
part thereof, to be licensed as a whole at no charge to all third |
|
101 |
parties under the terms of this License. |
|
102 |
|
|
103 |
c) If the modified program normally reads commands interactively |
|
104 |
when run, you must cause it, when started running for such |
|
105 |
interactive use in the most ordinary way, to print or display an |
|
106 |
announcement including an appropriate copyright notice and a |
|
107 |
notice that there is no warranty (or else, saying that you provide |
|
108 |
a warranty) and that users may redistribute the program under |
|
109 |
these conditions, and telling the user how to view a copy of this |
|
110 |
License. (Exception: if the Program itself is interactive but |
|
111 |
does not normally print such an announcement, your work based on |
|
112 |
the Program is not required to print an announcement.) |
|
113 |
|
|
114 |
These requirements apply to the modified work as a whole. If |
|
115 |
identifiable sections of that work are not derived from the Program, |
|
116 |
and can be reasonably considered independent and separate works in |
|
117 |
themselves, then this License, and its terms, do not apply to those |
|
118 |
sections when you distribute them as separate works. But when you |
|
119 |
distribute the same sections as part of a whole which is a work based |
|
120 |
on the Program, the distribution of the whole must be on the terms of |
|
121 |
this License, whose permissions for other licensees extend to the |
|
122 |
entire whole, and thus to each and every part regardless of who wrote it. |
|
123 |
|
|
124 |
Thus, it is not the intent of this section to claim rights or contest |
|
125 |
your rights to work written entirely by you; rather, the intent is to |
|
126 |
exercise the right to control the distribution of derivative or |
|
127 |
collective works based on the Program. |
|
128 |
|
|
129 |
In addition, mere aggregation of another work not based on the Program |
|
130 |
with the Program (or with a work based on the Program) on a volume of |
|
131 |
a storage or distribution medium does not bring the other work under |
|
132 |
the scope of this License. |
|
133 |
|
|
134 |
3. You may copy and distribute the Program (or a work based on it, |
|
135 |
under Section 2) in object code or executable form under the terms of |
|
136 |
Sections 1 and 2 above provided that you also do one of the following: |
|
137 |
|
|
138 |
a) Accompany it with the complete corresponding machine-readable |
|
139 |
source code, which must be distributed under the terms of Sections |
|
140 |
1 and 2 above on a medium customarily used for software interchange; or, |
|
141 |
|
|
142 |
b) Accompany it with a written offer, valid for at least three |
|
143 |
years, to give any third party, for a charge no more than your |
|
144 |
cost of physically performing source distribution, a complete |
|
145 |
machine-readable copy of the corresponding source code, to be |
|
146 |
distributed under the terms of Sections 1 and 2 above on a medium |
|
147 |
customarily used for software interchange; or, |
|
148 |
|
|
149 |
c) Accompany it with the information you received as to the offer |
|
150 |
to distribute corresponding source code. (This alternative is |
|
151 |
allowed only for noncommercial distribution and only if you |
|
152 |
received the program in object code or executable form with such |
|
153 |
an offer, in accord with Subsection b above.) |
|
154 |
|
|
155 |
The source code for a work means the preferred form of the work for |
|
156 |
making modifications to it. For an executable work, complete source |
|
157 |
code means all the source code for all modules it contains, plus any |
|
158 |
associated interface definition files, plus the scripts used to |
|
159 |
control compilation and installation of the executable. However, as a |
|
160 |
special exception, the source code distributed need not include |
|
161 |
anything that is normally distributed (in either source or binary |
|
162 |
form) with the major components (compiler, kernel, and so on) of the |
|
163 |
operating system on which the executable runs, unless that component |
|
164 |
itself accompanies the executable. |
|
165 |
|
|
166 |
If distribution of executable or object code is made by offering |
|
167 |
access to copy from a designated place, then offering equivalent |
|
168 |
access to copy the source code from the same place counts as |
|
169 |
distribution of the source code, even though third parties are not |
|
170 |
compelled to copy the source along with the object code. |
|
171 |
|
|
172 |
4. You may not copy, modify, sublicense, or distribute the Program |
|
173 |
except as expressly provided under this License. Any attempt |
|
174 |
otherwise to copy, modify, sublicense or distribute the Program is |
|
175 |
void, and will automatically terminate your rights under this License. |
|
176 |
However, parties who have received copies, or rights, from you under |
|
177 |
this License will not have their licenses terminated so long as such |
|
178 |
parties remain in full compliance. |
|
179 |
|
|
180 |
5. You are not required to accept this License, since you have not |
|
181 |
signed it. However, nothing else grants you permission to modify or |
|
182 |
distribute the Program or its derivative works. These actions are |
|
183 |
prohibited by law if you do not accept this License. Therefore, by |
|
184 |
modifying or distributing the Program (or any work based on the |
|
185 |
Program), you indicate your acceptance of this License to do so, and |
|
186 |
all its terms and conditions for copying, distributing or modifying |
|
187 |
the Program or works based on it. |
|
188 |
|
|
189 |
6. Each time you redistribute the Program (or any work based on the |
|
190 |
Program), the recipient automatically receives a license from the |
|
191 |
original licensor to copy, distribute or modify the Program subject to |
|
192 |
these terms and conditions. You may not impose any further |
|
193 |
restrictions on the recipients' exercise of the rights granted herein. |
|
194 |
You are not responsible for enforcing compliance by third parties to |
|
195 |
this License. |
|
196 |
|
|
197 |
7. If, as a consequence of a court judgment or allegation of patent |
|
198 |
infringement or for any other reason (not limited to patent issues), |
|
199 |
conditions are imposed on you (whether by court order, agreement or |
|
200 |
otherwise) that contradict the conditions of this License, they do not |
|
201 |
excuse you from the conditions of this License. If you cannot |
|
202 |
distribute so as to satisfy simultaneously your obligations under this |
|
203 |
License and any other pertinent obligations, then as a consequence you |
|
204 |
may not distribute the Program at all. For example, if a patent |
|
205 |
license would not permit royalty-free redistribution of the Program by |
|
206 |
all those who receive copies directly or indirectly through you, then |
|
207 |
the only way you could satisfy both it and this License would be to |
|
208 |
refrain entirely from distribution of the Program. |
|
209 |
|
|
210 |
If any portion of this section is held invalid or unenforceable under |
|
211 |
any particular circumstance, the balance of the section is intended to |
|
212 |
apply and the section as a whole is intended to apply in other |
|
213 |
circumstances. |
|
214 |
|
|
215 |
It is not the purpose of this section to induce you to infringe any |
|
216 |
patents or other property right claims or to contest validity of any |
|
217 |
such claims; this section has the sole purpose of protecting the |
|
218 |
integrity of the free software distribution system, which is |
|
219 |
implemented by public license practices. Many people have made |
|
220 |
generous contributions to the wide range of software distributed |
|
221 |
through that system in reliance on consistent application of that |
|
222 |
system; it is up to the author/donor to decide if he or she is willing |
|
223 |
to distribute software through any other system and a licensee cannot |
|
224 |
impose that choice. |
|
225 |
|
|
226 |
This section is intended to make thoroughly clear what is believed to |
|
227 |
be a consequence of the rest of this License. |
|
228 |
|
|
229 |
8. If the distribution and/or use of the Program is restricted in |
|
230 |
certain countries either by patents or by copyrighted interfaces, the |
|
231 |
original copyright holder who places the Program under this License |
|
232 |
may add an explicit geographical distribution limitation excluding |
|
233 |
those countries, so that distribution is permitted only in or among |
|
234 |
countries not thus excluded. In such case, this License incorporates |
|
235 |
the limitation as if written in the body of this License. |
|
236 |
|
|
237 |
9. The Free Software Foundation may publish revised and/or new versions |
|
238 |
of the General Public License from time to time. Such new versions will |
|
239 |
be similar in spirit to the present version, but may differ in detail to |
|
240 |
address new problems or concerns. |
|
241 |
|
|
242 |
Each version is given a distinguishing version number. If the Program |
|
243 |
specifies a version number of this License which applies to it and "any |
|
244 |
later version", you have the option of following the terms and conditions |
|
245 |
either of that version or of any later version published by the Free |
|
246 |
Software Foundation. If the Program does not specify a version number of |
|
247 |
this License, you may choose any version ever published by the Free Software |
|
248 |
Foundation. |
|
249 |
|
|
250 |
10. If you wish to incorporate parts of the Program into other free |
|
251 |
programs whose distribution conditions are different, write to the author |
|
252 |
to ask for permission. For software which is copyrighted by the Free |
|
253 |
Software Foundation, write to the Free Software Foundation; we sometimes |
|
254 |
make exceptions for this. Our decision will be guided by the two goals |
|
255 |
of preserving the free status of all derivatives of our free software and |
|
256 |
of promoting the sharing and reuse of software generally. |
|
257 |
|
|
258 |
NO WARRANTY |
|
259 |
|
|
260 |
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY |
|
261 |
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN |
|
262 |
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES |
|
263 |
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED |
|
264 |
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
|
265 |
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS |
|
266 |
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE |
|
267 |
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, |
|
268 |
REPAIR OR CORRECTION. |
|
269 |
|
|
270 |
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING |
|
271 |
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR |
|
272 |
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, |
|
273 |
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING |
|
274 |
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED |
|
275 |
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY |
|
276 |
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER |
|
277 |
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE |
|
278 |
POSSIBILITY OF SUCH DAMAGES. |
|
279 |
|
|
280 |
END OF TERMS AND CONDITIONS |
|
281 |
|
|
282 |
How to Apply These Terms to Your New Programs |
|
283 |
|
|
284 |
If you develop a new program, and you want it to be of the greatest |
|
285 |
possible use to the public, the best way to achieve this is to make it |
|
286 |
free software which everyone can redistribute and change under these terms. |
|
287 |
|
|
288 |
To do so, attach the following notices to the program. It is safest |
|
289 |
to attach them to the start of each source file to most effectively |
|
290 |
convey the exclusion of warranty; and each file should have at least |
|
291 |
the "copyright" line and a pointer to where the full notice is found. |
|
292 |
|
|
293 |
<one line to give the program's name and a brief idea of what it does.> |
|
294 |
Copyright (C) <year> <name of author> |
|
295 |
|
|
296 |
This program is free software; you can redistribute it and/or modify |
|
297 |
it under the terms of the GNU General Public License as published by |
|
298 |
the Free Software Foundation; either version 2 of the License, or |
|
299 |
(at your option) any later version. |
|
300 |
|
|
301 |
This program is distributed in the hope that it will be useful, |
|
302 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
303 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
304 |
GNU General Public License for more details. |
|
305 |
|
|
306 |
You should have received a copy of the GNU General Public License along |
|
307 |
with this program; if not, write to the Free Software Foundation, Inc., |
|
308 |
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
|
309 |
|
|
310 |
Also add information on how to contact you by electronic and paper mail. |
|
311 |
|
|
312 |
If the program is interactive, make it output a short notice like this |
|
313 |
when it starts in an interactive mode: |
|
314 |
|
|
315 |
Gnomovision version 69, Copyright (C) year name of author |
|
316 |
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. |
|
317 |
This is free software, and you are welcome to redistribute it |
|
318 |
under certain conditions; type `show c' for details. |
|
319 |
|
|
320 |
The hypothetical commands `show w' and `show c' should show the appropriate |
|
321 |
parts of the General Public License. Of course, the commands you use may |
|
322 |
be called something other than `show w' and `show c'; they could even be |
|
323 |
mouse-clicks or menu items--whatever suits your program. |
|
324 |
|
|
325 |
You should also get your employer (if you work as a programmer) or your |
|
326 |
school, if any, to sign a "copyright disclaimer" for the program, if |
|
327 |
necessary. Here is a sample; alter the names: |
|
328 |
|
|
329 |
Yoyodyne, Inc., hereby disclaims all copyright interest in the program |
|
330 |
`Gnomovision' (which makes passes at compilers) written by James Hacker. |
|
331 |
|
|
332 |
<signature of Ty Coon>, 1 April 1989 |
|
333 |
Ty Coon, President of Vice |
|
334 |
|
|
335 |
This General Public License does not permit incorporating your program into |
|
336 |
proprietary programs. If your program is a subroutine library, you may |
|
337 |
consider it more useful to permit linking proprietary applications with the |
|
338 |
library. If this is what you want to do, use the GNU Lesser General |
|
339 |
Public License instead of this License. |
larpe/tags/release-1.1.1/MANIFEST.in | ||
---|---|---|
1 |
include Makefile |
|
2 |
include setup.py |
|
3 |
include larpectl |
|
4 |
include apache2-vhost-larpe |
|
5 |
include apache2.conf |
|
6 |
include larpe-reload-apache2-script |
|
7 |
include larpe-reload-apache2.c |
|
8 |
include README COPYING MANIFEST.in MANIFEST NEWS AUTHORS |
|
9 |
recursive-include larpe *.py *.ptl |
|
10 |
recursive-include data * |
|
11 |
recursive-include root * |
|
12 |
recursive-include po *.po *.pot Makefile |
|
13 |
recursive-include doc *.rst Makefile *.png *.sty custom.tex *.py *.sh *.css |
larpe/tags/release-1.1.1/Makefile | ||
---|---|---|
1 |
prefix = /usr |
|
2 |
config_prefix = /var |
|
3 |
config_dir = $(config_prefix)/lib/larpe |
|
4 |
|
|
5 |
INSTALL = /usr/bin/install -c |
|
6 |
PYTHON = /usr/bin/python |
|
7 |
|
|
8 |
LARPE_VERSION = 0.2.9 |
|
9 |
|
|
10 |
larpe-reload-apache2: larpe-reload-apache2.c |
|
11 |
|
|
12 |
install: larpe-reload-apache2 |
|
13 |
rm -rf build |
|
14 |
$(MAKE) -C po install |
|
15 |
$(PYTHON) setup.py install --root "$(DESTDIR)/" --prefix "$(prefix)" --no-compile |
|
16 |
$(INSTALL) -d $(DESTDIR)$(prefix)/sbin/ |
|
17 |
$(INSTALL) larpectl $(DESTDIR)$(prefix)/sbin/ |
|
18 |
$(INSTALL) -m 4550 larpe-reload-apache2 $(DESTDIR)$(prefix)/sbin/ |
|
19 |
$(INSTALL) -d $(DESTDIR)/etc/larpe |
|
20 |
$(INSTALL) -m 644 conf/apache2-vhost-larpe-common $(DESTDIR)/etc/larpe |
|
21 |
$(INSTALL) -d $(DESTDIR)$(config_dir) |
|
22 |
$(INSTALL) -d $(DESTDIR)$(config_dir)/vhosts.d |
|
23 |
$(INSTALL) -d $(DESTDIR)$(config_dir)/vhost-locations.d |
|
24 |
$(INSTALL) -d $(DESTDIR)$(config_dir)/vhosts.d.disabled |
|
25 |
$(INSTALL) -d $(DESTDIR)$(config_dir)/vhost-locations.d.disabled |
|
26 |
|
|
27 |
uninstall: |
|
28 |
$(MAKE) -C po uninstall |
|
29 |
-rm -f $(DESTDIR)$(prefix)/sbin/larpe-reload-apache2 |
|
30 |
-rm -f $(DESTDIR)$(prefix)/sbin/larpe-reload-apache2-script |
|
31 |
-rm -f $(DESTDIR)$(prefix)/sbin/larpectl |
|
32 |
-rm -rf $(DESTDIR)$(prefix)/share/larpe/ |
|
33 |
@echo |
|
34 |
@echo "Depending on your Python version, you will have to remove manually the files in /usr/lib/python(version)/site-packages/larpe/" |
|
35 |
|
|
36 |
clean: |
|
37 |
$(MAKE) -C po clean |
|
38 |
$(MAKE) -C doc clean |
|
39 |
-$(PYTHON) setup.py clean |
|
40 |
-rm -f larpe-reload-apache2 |
|
41 |
|
|
42 |
dist: clean |
|
43 |
tar czf dist/larpe-$(LARPE_VERSION).tar.gz -C .. --transform s/trunk/larpe-$(LARPE_VERSION)/ --exclude-from=exclude_from_dist trunk |
|
44 |
|
|
45 |
.PHONY: clean dist |
larpe/tags/release-1.1.1/NEWS | ||
---|---|---|
1 |
NEWS |
|
2 |
==== |
|
3 |
|
|
4 |
Version 1.0 |
|
5 |
----------- |
|
6 |
|
|
7 |
- Adds Liberty Alliance to some sites without modying sites code |
|
8 |
- SAML 2.0 and ID-FF 1.2 support (authentication and logout) |
|
9 |
- Form prefilling with ID-WSF 2.0 |
|
10 |
- Configuration assistant (wizard-like) for configuring new sites |
|
11 |
- Fully tested for several sites with very different behaviours |
|
12 |
- Plugin system to handle specific behaviour of some sites |
|
13 |
- Automatic Apache 2 configuration |
|
14 |
- Automatic creation of Apache python filters to transform authentication boxes on the sites |
|
15 |
- Support for proxies |
|
16 |
- Logging and debug options |
|
17 |
- Packages for Debian and Fedora (and children of both) distributions |
larpe/tags/release-1.1.1/README | ||
---|---|---|
1 |
Larpe - Liberty Alliance Reverse Proxy |
|
2 |
====================================== |
|
3 |
|
|
4 |
Description |
|
5 |
----------- |
|
6 |
|
|
7 |
Larpe is a Liberty Alliance Reverse Proxy. It allows any service provider (that |
|
8 |
is a website) to use Liberty Alliance features (Identity federation, Single |
|
9 |
Sign On and Single Sign Logout) without changing the code of the service |
|
10 |
provider itself. It uses the Lasso library which is certified by the Liberty |
|
11 |
Alliance consortium. |
|
12 |
|
|
13 |
|
|
14 |
Documentation |
|
15 |
------------- |
|
16 |
|
|
17 |
* README, as you are doing; |
|
18 |
|
|
19 |
* doc/en/ for English documentation, published as HTML on |
|
20 |
http://larpe.labs.libre-entreprise.org/doc/en/larpe-admin.html |
|
21 |
|
|
22 |
|
|
23 |
Copyright |
|
24 |
--------- |
|
25 |
|
|
26 |
Larpe is copyrighted by Entr'ouvert and is licensed under the GNU General |
|
27 |
Public Licence. Artwork and administrative design are from DotClear and |
|
28 |
released under the GNU General Public License by Olivier Meunier and others. |
|
29 |
Some artwork comes from GTK+ (LGPL). |
|
30 |
|
|
31 |
Read the COPYING file for the complete license text. Read the AUTHORS file for |
|
32 |
additional credits. |
larpe/tags/release-1.1.1/TODO | ||
---|---|---|
1 |
- Tests |
|
2 |
- egroupware |
|
3 |
- http://labs.libre-entreprise.org/ |
|
4 |
- logs.entrouvert.org |
|
5 |
|
|
6 |
====== Roadmap de Larpe ====== |
|
7 |
|
|
8 |
===== 0.2 ===== |
|
9 |
|
|
10 |
* Vérifier la compatibilité avec egroupware |
|
11 |
* Mettre le vhosts générés dans /var/lib/larpe/vhosts.d et mettre un include /var/lib/larpe/vhosts.d/* dans la conf générale |
|
12 |
* Supprimer debconf |
|
13 |
* Vérification des formulaires de configuration d'hôtes |
|
14 |
* Tests de valeurs erronés diverses |
|
15 |
* Erreur si on donne un label qui existe deja |
|
16 |
* Ne plus inclure le binaire larpe-reload-apache2 dans les sources |
|
17 |
* Corriger les avertissements debian |
|
18 |
* Ne pas demander la clé publique de l'idp |
|
19 |
* Compléter les traductions |
|
20 |
* Ajouter la possibilité de changer la langue dans l'interface d'administration |
|
21 |
* Mettre à jour la documentation |
|
22 |
* Ajouter un chapitre sur les sites testés et leurs options de configuration particulières |
|
23 |
* Traduire la documentation en français |
|
24 |
|
|
25 |
===== 0.3 ===== |
|
26 |
|
|
27 |
* Implémenter le SLO en SOAP |
|
28 |
* Supprimer un /liberty/ des urls |
|
29 |
* Voir comment activer le SSLProxyEngine quand on utilise un sous répertoire |
|
30 |
* Faire un site web pour présenter Larpe |
|
31 |
* Ajouter la possibilité d'envoyer les exceptions par courriel à l'administrateur |
|
32 |
* Améliorer la journalisation des accès et des erreurs |
|
33 |
|
|
34 |
===== 1.0 ===== |
|
35 |
|
|
36 |
* Support de SAML 2.0 |
|
37 |
* Implémenter l'accès à un site nécessitant une authentification préalable avant tout accès |
|
38 |
* Choix de cette fonctionnalité par une option de configuration par site |
|
39 |
* Lors de la création d'un site, choix d'un moteur de site connu (mediawiki, squirrelmail, ...) qui pré-remplirait un ensemble d'options nécessaire à ce moteur |
|
40 |
* Documentation technique pour les développeurs ? |
|
41 |
|
|
42 |
===== Non classés ===== |
|
43 |
|
|
44 |
* Support des sites qui ont une authentification HTTP (à priori, nécessite de charger toute la configuration de larpe dans le filtre python d'apache) |
|
45 |
* Création de nouveaux comptes pour les sites, avec des jetons (déjà implémenté en partie ; est-ce utile ?) |
|
46 |
|
|
47 |
Fait |
|
48 |
==== |
|
49 |
|
|
50 |
- Serveur python principal |
|
51 |
- Fonctionnalités liberty |
|
52 |
- SSO (depuis le sp et depuis l'idp) |
|
53 |
- Fédération |
|
54 |
- SLO (depuis le sp et depuis l'idp) |
|
55 |
- Défédération (depuis l'idp) en SOAP et redirect |
|
56 |
- Support https |
|
57 |
- Possibilité d'utiliser toutes les combinaisons de sous domaines et de sous répertoires |
|
58 |
- RP par vhost (appli1.example.com, rp de appli1.interne) |
|
59 |
- RP par repertoire (www.example.com/appli1, rp de appl1.interne) |
|
60 |
- Récupère la configuration de l'IP des vhosts |
|
61 |
|
|
62 |
- Administration |
|
63 |
- Authentification liberty sur l'admin |
|
64 |
- Créer de nouveaux sites (+ modifier, supprimer) |
|
65 |
- Écrire les vhosts correspondants |
|
66 |
- Rechargement de la configuration d'apache |
|
67 |
- Script + wrapper en C suid root |
|
68 |
- Gestion d'utilisateurs pour administrer le RP (Authentification http) |
|
69 |
- Gestion des traductions |
|
70 |
|
|
71 |
- Filtre Python branché en sortie sur Apache à la suite du filtre de réécriture html (proxy_html) |
|
72 |
- Générique |
|
73 |
- Personalisable par site pour une meilleure intégration dans les pages |
|
74 |
|
|
75 |
- Sites testés |
|
76 |
- Dotclear |
|
77 |
- Dacode |
|
78 |
- linuxfr.org |
|
79 |
- Sympa |
|
80 |
- listes.entrouvert.com |
|
81 |
- listes.libre-entreprise.org |
|
82 |
- Mediawiki |
|
83 |
- all4dev.libre-entreprise.org |
|
84 |
- www.libre-entreprise.org |
|
85 |
- www.besancon.com |
|
86 |
- Egroupware |
|
87 |
- quintine.entrouvert.org/egroupware/ |
|
88 |
- squirrelmail |
|
89 |
- Concerto Espace-famille |
|
90 |
- Ciril Net RH |
|
91 |
- Agirhe |
|
92 |
|
|
93 |
- Documentation |
|
94 |
|
|
95 |
- Paquets Debian |
|
96 |
- Debconf pour demander le nom de domaine et le courriel de l'admin, ainsi que le compte administrateur |
|
97 |
|
|
98 |
- Installation sur lupin |
|
99 |
|
|
100 |
- Batterie de tests de non-regression |
|
101 |
|
larpe/tags/release-1.1.1/conf/apache2-vhost-larpe | ||
---|---|---|
1 |
<VirtualHost *> |
|
2 |
ServerName localhost |
|
3 |
ServerAdmin root@localhost |
|
4 |
|
|
5 |
include /etc/larpe/apache2-vhost-larpe-common |
|
6 |
include /var/lib/larpe/vhost-locations.d |
|
7 |
|
|
8 |
CustomLog /var/log/apache2/larpe-access.log combined |
|
9 |
ErrorLog /var/log/apache2/larpe-error.log |
|
10 |
</VirtualHost> |
|
11 |
|
|
12 |
include /var/lib/larpe/vhosts.d |
larpe/tags/release-1.1.1/conf/apache2-vhost-larpe-common | ||
---|---|---|
1 |
# Static files |
|
2 |
DocumentRoot /usr/share/larpe/web/ |
|
3 |
|
|
4 |
# Python application |
|
5 |
SCGIMount / 127.0.0.1:3007 |
|
6 |
|
|
7 |
# Static files for larpe |
|
8 |
<Location /larpe/> |
|
9 |
ProxyPass ! |
|
10 |
SCGIHandler off |
|
11 |
</Location> |
|
12 |
|
|
13 |
# Larpe python application |
|
14 |
<Location /liberty/> |
|
15 |
ProxyPass ! |
|
16 |
</Location> |
|
17 |
|
|
18 |
# No gzip compression |
|
19 |
RequestHeader unset Accept-Encoding |
larpe/tags/release-1.1.1/conf/filters/output_ciril_net_rh.py | ||
---|---|---|
1 |
import re |
|
2 |
import os |
|
3 |
import pickle |
|
4 |
|
|
5 |
from larpe import sessions |
|
6 |
from mod_python import Cookie |
|
7 |
|
|
8 |
def is_auth_ok(req): |
|
9 |
""" Test if you are authenticate on the Larpe server """ |
|
10 |
cookies = Cookie.get_cookies(req, Cookie.MarshalCookie, secret='secret007') |
|
11 |
sessions_dir = os.path.join("%(larpe_dir)s", "sessions") |
|
12 |
for name, cookie in cookies.iteritems(): |
|
13 |
value = cookie.value.replace('"', '') |
|
14 |
if "larpe-" in name and value in os.listdir(sessions_dir): |
|
15 |
try: |
|
16 |
file = open(os.path.join(sessions_dir, value), "rb") |
|
17 |
session = pickle.load(file) |
|
18 |
if not session.users or not session.id: |
|
19 |
return False |
|
20 |
return True |
|
21 |
except Exception, err: |
|
22 |
return False |
|
23 |
return False |
|
24 |
|
|
25 |
|
|
26 |
def filter_page(filter, page): |
|
27 |
r = re.compile(r"""(<a.*?href=["']).*?(["'].*?>D.*?connexion</a>)""") |
|
28 |
page = r.sub(r"""\1%(logout_url)s\2""", page) |
|
29 |
return page |
|
30 |
|
|
31 |
def outputfilter(filter): |
|
32 |
""" Apache called this function by default """ |
|
33 |
if not re.search("^/liberty/.*", filter.req.uri) and not is_auth_ok(filter.req): |
|
34 |
filter.write('<meta http-equiv="refresh" content="0; url=%(login_url)s" />') |
|
35 |
filter.close() |
|
36 |
return |
|
37 |
|
|
38 |
if filter.req.content_type is not None: |
|
39 |
is_html = re.search('text/html', filter.req.content_type) |
|
40 |
if filter.req.content_type is None or not is_html: |
|
41 |
filter.pass_on() |
|
42 |
else: |
|
43 |
if not hasattr(filter.req, 'temp_doc'): |
|
44 |
# Create a new attribute to hold the document |
|
45 |
filter.req.temp_doc = [] |
|
46 |
# If content-length ended up wrong, Gecko browsers truncated data |
|
47 |
if 'Content-Length' in filter.req.headers_out: |
|
48 |
del filter.req.headers_out['Content-Length'] |
|
49 |
|
|
50 |
temp_doc = filter.req.temp_doc |
|
51 |
s = filter.read() |
|
52 |
# Could get '' at any point, but only get None at end |
|
53 |
while s: |
|
54 |
temp_doc.append(s) |
|
55 |
s = filter.read() |
|
56 |
|
|
57 |
# The end |
|
58 |
if s is None: |
|
59 |
page = ''.join(temp_doc) |
|
60 |
page = filter_page(filter, page) |
|
61 |
filter.write(page) |
|
62 |
filter.close() |
|
63 |
|
larpe/tags/release-1.1.1/conf/filters/output_replace_form.py | ||
---|---|---|
1 |
import re |
|
2 |
|
|
3 |
def filter_page(filter, page): |
|
4 |
current_form = re.compile('<form [^>]*?action="%(auth_form_action)s".*?>.*?</form>', re.DOTALL) |
|
5 |
page = current_form.sub('<form method="post" action="/liberty/%(name)s/login"><input type="submit" value="Connexion" /></form>', page) |
|
6 |
return page |
|
7 |
|
|
8 |
def outputfilter(filter): |
|
9 |
# Only filter html code |
|
10 |
if filter.req.content_type is not None: |
|
11 |
is_html = re.search('text/html', filter.req.content_type) |
|
12 |
if filter.req.content_type is None or not is_html: |
|
13 |
filter.pass_on() |
|
14 |
else: |
|
15 |
if not hasattr(filter.req, 'temp_doc'): |
|
16 |
# Create a new attribute to hold the document |
|
17 |
filter.req.temp_doc = [] |
|
18 |
# If content-length ended up wrong, Gecko browsers truncated data |
|
19 |
if 'Content-Length' in filter.req.headers_out: |
|
20 |
del filter.req.headers_out['Content-Length'] |
|
21 |
|
|
22 |
temp_doc = filter.req.temp_doc |
|
23 |
s = filter.read() |
|
24 |
# Could get '' at any point, but only get None at end |
|
25 |
while s: |
|
26 |
temp_doc.append(s) |
|
27 |
s = filter.read() |
|
28 |
|
|
29 |
# The end |
|
30 |
if s is None: |
|
31 |
page = ''.join(temp_doc) |
|
32 |
page = filter_page(filter, page) |
|
33 |
filter.write(page) |
|
34 |
filter.close() |
|
35 |
|
larpe/tags/release-1.1.1/debian/changelog | ||
---|---|---|
1 |
larpe (1.1.1-1) unstable; urgency=low |
|
2 |
|
|
3 |
* Removing a useless import |
|
4 |
* Change Debian maintainer |
|
5 |
* Change architecture from any to all |
|
6 |
* Using pysupport instead of pycentral |
|
7 |
* Update Debian package dependencies |
|
8 |
|
|
9 |
-- Jerome Schneider <jschneider@entrouvert.com> Mon, 19 Jul 2010 16:18:28 +0200 |
|
10 |
|
|
11 |
larpe (1.1-1) unstable; urgency=low |
|
12 |
|
|
13 |
* New release |
|
14 |
- Rewrite filter management |
|
15 |
- Filters are now customisable |
|
16 |
- Improve Ciril module |
|
17 |
- Improve plugins management |
|
18 |
- Support multi filters |
|
19 |
- Fix SAML 2 logout |
|
20 |
- Fix site authentification plugins management |
|
21 |
- Fix sessions management |
|
22 |
- Code cleaning |
|
23 |
|
|
24 |
-- Jerome Schneider <jschneider@entrouvert.com> Mon, 19 Jul 2010 11:52:47 +0200 |
|
25 |
|
|
26 |
larpe (1.0-1) unstable; urgency=low |
|
27 |
|
|
28 |
* New release |
|
29 |
- SAML 2.0 and ID-FF 1.2 support (authentication and logout) |
|
30 |
- Form prefilling with ID-WSF 2.0 |
|
31 |
- Configuration assistant (wizard-like) for configuring new sites |
|
32 |
- Fully tested for several sites with very different behaviours |
|
33 |
- Plugin system to handle specific behaviour of some sites |
|
34 |
- Automatic Apache 2 configuration |
|
35 |
- Automatic creation of Apache python filters to transform authentication |
|
36 |
boxes on the sites |
|
37 |
- Support for proxies |
|
38 |
- Logging and debug options |
|
39 |
|
|
40 |
-- Damien Laniel <dlaniel@entrouvert.com> Mon, 09 Mar 2009 11:19:49 +0100 |
|
41 |
|
|
42 |
larpe (0.2.1-1) unstable; urgency=low |
|
43 |
|
|
44 |
* New release |
|
45 |
|
|
46 |
-- Damien Laniel <dlaniel@entrouvert.com> Wed, 20 Jun 2007 15:43:16 +0200 |
|
47 |
|
|
48 |
larpe (0.2.0-1) unstable; urgency=low |
|
49 |
|
|
50 |
* New release |
|
51 |
|
|
52 |
-- Damien Laniel <dlaniel@entrouvert.com> Tue, 30 Jan 2007 18:07:04 +0100 |
|
53 |
|
|
54 |
larpe (0.1.1-2) unstable; urgency=low |
|
55 |
|
|
56 |
* Use python2.4 |
|
57 |
|
|
58 |
-- Damien Laniel <dlaniel@entrouvert.com> Tue, 19 Dec 2006 17:21:05 +0100 |
|
59 |
|
|
60 |
larpe (0.1.1-1) unstable; urgency=low |
|
61 |
|
|
62 |
* New release |
|
63 |
|
|
64 |
-- Damien Laniel <dlaniel@entrouvert.com> Thu, 5 Oct 2006 11:47:53 +0200 |
|
65 |
|
|
66 |
larpe (0.1.0-1) unstable; urgency=low |
|
67 |
|
|
68 |
* New release |
|
69 |
|
|
70 |
-- Damien Laniel <dlaniel@entrouvert.com> Wed, 4 Oct 2006 10:19:26 +0200 |
|
71 |
|
|
72 |
larpe (0.0.4-1) unstable; urgency=low |
|
73 |
|
|
74 |
* New version, many improvements, more compatible sites, some bug fixes |
|
75 |
|
|
76 |
-- Damien Laniel <dlaniel@entrouvert.com> Tue, 3 Oct 2006 20:44:06 +0200 |
|
77 |
|
|
78 |
larpe (0.0.3-1) unstable; urgency=low |
|
79 |
|
|
80 |
* New version, many improvements, more compatible sites, some bug fixes |
|
81 |
|
|
82 |
-- Damien Laniel <dlaniel@entrouvert.com> Mon, 25 Sep 2006 11:11:36 +0200 |
|
83 |
|
|
84 |
larpe (0.0.2-1) unstable; urgency=low |
|
85 |
|
|
86 |
* Initial package. |
|
87 |
|
|
88 |
-- Damien Laniel <dlaniel@entrouvert.com> Fri, 08 Sep 2006 16:00:00 +0200 |
|
89 |
|
larpe/tags/release-1.1.1/debian/compat | ||
---|---|---|
1 |
5 |
larpe/tags/release-1.1.1/debian/config | ||
---|---|---|
1 |
#!/bin/sh -e |
|
2 |
|
|
3 |
# Source debconf library. |
|
4 |
. /usr/share/debconf/confmodule |
|
5 |
|
|
6 |
# Hostname |
|
7 |
#db_input high larpe/hostname || true |
|
8 |
#db_go |
|
9 |
|
|
10 |
# Administrator email address |
|
11 |
#db_input medium larpe/admin_email || true |
|
12 |
#db_go |
|
13 |
|
|
14 |
# Enable this vhost |
|
15 |
#db_input high larpe/enable_vhost || true |
|
16 |
#db_go |
|
17 |
|
|
18 |
# Administrator login |
|
19 |
#db_input high larpe/admin_username || true |
|
20 |
#db_go |
|
21 |
|
|
22 |
# Administrator password |
|
23 |
#db_input high larpe/admin_password || true |
|
24 |
#db_go |
larpe/tags/release-1.1.1/debian/control | ||
---|---|---|
1 |
Source: larpe |
|
2 |
Section: web |
|
3 |
Priority: optional |
|
4 |
Maintainer: Jérôme Schneider <jschneider@entrouvert.com> |
|
5 |
Build-Depends: debhelper (>= 5.0.37.2), python, python-support (>= 0.4), gettext, python-quixote (>= 2.5) |
|
6 |
Standards-Version: 3.8.0 |
|
7 |
|
|
8 |
Package: larpe |
|
9 |
Architecture: all |
|
10 |
Depends: ${shlibs:Depends}, ${python:Depends}, python-quixote (>= 2.5), python-lasso (>= 2.2.1), python-scgi, python-libxml2, apache2, libapache2-mod-scgi, libapache2-mod-python, libapache2-mod-proxy-html |
|
11 |
XB-Python-Version: ${python:Versions} |
|
12 |
Description: Liberty Alliance Reverse Proxy |
|
13 |
Larpe allows any service provider (that is a website) to use Liberty Alliance |
|
14 |
identity management and Single Sign On features without changing the code of |
|
15 |
the service provider itself. |
|
16 |
. |
larpe/tags/release-1.1.1/debian/copyright | ||
---|---|---|
1 |
This package was debianized by Damien Laniel <dlaniel@entrouvert.com> on |
|
2 |
Fri, 08 Sep 2006 16:00:00 +0200. |
|
3 |
|
|
4 |
Upstream Author: Damien Laniel <dlaniel@entrouvert.com> |
|
5 |
|
|
6 |
Copyright (c) 2005 Entr'ouvert; |
|
7 |
copyright (c) 2003-2005 dotclear for some graphics. |
|
8 |
|
|
9 |
License is GNU GPL v2 or later plus OpenSSL exception clause. |
|
10 |
|
|
11 |
This program is free software; you can redistribute it and/or |
|
12 |
modify it under the terms of the GNU General Public License |
|
13 |
as published by the Free Software Foundation; either version 2 |
|
14 |
of the License, or (at your option) any later version. |
|
15 |
|
|
16 |
This program is distributed in the hope that it will be useful, |
|
17 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
18 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
19 |
GNU General Public License for more details. |
|
20 |
|
|
21 |
You should have received a copy of the GNU General Public License |
|
22 |
along with this program; if not, write to the Free Software |
|
23 |
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
24 |
|
|
25 |
On Debian GNU/Linux systems, the complete text of the GNU General Public |
|
26 |
License can be found in `/usr/share/common-licenses/GPL'. |
|
27 |
|
larpe/tags/release-1.1.1/debian/dirs | ||
---|---|---|
1 |
etc/apache2/sites-available |
|
2 |
etc/larpe |
|
3 |
usr/sbin |
|
4 |
var/lib/larpe |
larpe/tags/release-1.1.1/debian/docs | ||
---|---|---|
1 |
README |
|
2 |
AUTHORS |
larpe/tags/release-1.1.1/debian/init | ||
---|---|---|
1 |
#! /bin/sh |
|
2 |
### BEGIN INIT INFO |
|
3 |
# Provides: larpe |
|
4 |
# Required-Start: $local_fs $network |
|
5 |
# Required-Stop: $local_fs $network |
|
6 |
# Default-Start: 2 3 4 5 |
|
7 |
# Default-Stop: 0 1 6 |
|
8 |
# Short-Description: Start Larpe Liberty Alliance reverse proxy |
|
9 |
# Description: Start Larpe Liberty Alliance reverse proxy |
|
10 |
### END INIT INFO |
|
11 |
|
|
12 |
set -e |
|
13 |
|
|
14 |
# Gracefully exit if the package has been removed. |
|
15 |
test -x $DAEMON || exit 0 |
|
16 |
|
|
17 |
# Source function library |
|
18 |
. /lib/lsb/init-functions |
|
19 |
|
|
20 |
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin |
|
21 |
DESC="larpe" |
|
22 |
NAME=larpe |
|
23 |
DAEMON=/usr/sbin/larpectl |
|
24 |
PIDFILE=/var/run/$NAME.pid |
|
25 |
SCRIPTNAME=/etc/init.d/$NAME |
|
26 |
|
|
27 |
|
|
28 |
# Read config file if it is present. |
|
29 |
if [ -r /etc/default/$NAME ] |
|
30 |
then |
|
31 |
. /etc/default/$NAME |
|
32 |
fi |
|
33 |
|
|
34 |
# |
|
35 |
# Function that starts the daemon/service. |
|
36 |
# |
|
37 |
d_start() { |
|
38 |
start-stop-daemon --start --quiet --pidfile $PIDFILE --oknodo \ |
|
39 |
--chuid www-data:www-data --make-pidfile --background --exec $DAEMON -- start $OPTIONS |
|
40 |
} |
|
41 |
|
|
42 |
# |
|
43 |
# Function that stops the daemon/service. |
|
44 |
# |
|
45 |
d_stop() { |
|
46 |
start-stop-daemon --stop --quiet --pidfile $PIDFILE --oknodo |
|
47 |
rm -f $PIDFILE |
|
48 |
} |
|
49 |
|
|
50 |
case "$1" in |
|
51 |
start) |
|
52 |
log_begin_msg "Starting $DESC: $NAME" |
|
53 |
d_start |
|
54 |
log_end_msg $? |
|
55 |
;; |
|
56 |
|
|
57 |
stop) |
|
58 |
log_begin_msg "Stopping $DESC: $NAME" |
|
59 |
d_stop |
|
60 |
log_end_msg $? |
|
61 |
;; |
|
62 |
|
|
63 |
restart|force-reload) |
|
64 |
# |
|
65 |
# If the "reload" option is implemented, move the "force-reload" |
|
66 |
# option to the "reload" entry above. If not, "force-reload" is |
|
67 |
# just the same as "restart". |
|
68 |
# |
|
69 |
log_begin_msg "Restarting $DESC: $NAME" |
|
70 |
d_stop |
|
71 |
sleep 1 |
|
72 |
d_start |
|
73 |
log_end_msg $? |
|
74 |
;; |
|
75 |
|
|
76 |
*) |
|
77 |
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2 |
|
78 |
exit 1 |
|
79 |
;; |
|
80 |
esac |
|
81 |
|
|
82 |
exit 0 |
larpe/tags/release-1.1.1/debian/larpe-reload-apache2-script | ||
---|---|---|
1 |
#!/bin/sh |
|
2 |
|
|
3 |
/etc/init.d/apache2 reload |
larpe/tags/release-1.1.1/debian/postinst | ||
---|---|---|
1 |
#! /bin/sh |
|
2 |
# postinst script for larpe |
|
3 |
# |
|
4 |
# see: dh_installdeb(1) |
|
5 |
|
|
6 |
set -e |
|
7 |
|
|
8 |
# summary of how this script can be called: |
|
9 |
# * <postinst> `configure' <most-recently-configured-version> |
|
10 |
# * <old-postinst> `abort-upgrade' <new version> |
|
11 |
# * <conflictor's-postinst> `abort-remove' `in-favour' <package> |
|
12 |
# <new-version> |
|
13 |
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour' |
|
14 |
# <failed-install-package> <version> `removing' |
|
15 |
# <conflicting-package> <version> |
|
16 |
# for details, see http://www.debian.org/doc/debian-policy/ or |
|
17 |
# the debian-policy package |
|
18 |
# |
|
19 |
# quoting from the policy: |
|
20 |
# Any necessary prompting should almost always be confined to the |
|
21 |
# post-installation script, and should be protected with a conditional |
|
22 |
# so that unnecessary prompting doesn't happen if a package's |
|
23 |
# installation fails and the `postinst' is called with `abort-upgrade', |
|
24 |
# `abort-remove' or `abort-deconfigure'. |
|
25 |
|
|
26 |
PACKAGE=larpe |
|
27 |
VERSION=2.4 |
|
28 |
LIB="/usr/lib/python$VERSION" |
|
29 |
DIRLIST="/usr/share/pycentral/larpe/site-packages/larpe/" |
|
30 |
|
|
31 |
case "$1" in |
|
32 |
configure|abort-upgrade|abort-remove|abort-deconfigure) |
|
33 |
for i in $DIRLIST ; do |
|
34 |
/usr/bin/python$VERSION -O $LIB/compileall.py -q $i |
|
35 |
/usr/bin/python$VERSION $LIB/compileall.py -q $i |
|
36 |
done |
|
37 |
|
|
38 |
# Load Apache 2 modules |
|
39 |
for module in "proxy" "rewrite" "headers" "proxy_http"; do |
|
40 |
a2enmod ${module} > /dev/null || true |
|
41 |
done |
|
42 |
|
|
43 |
# Restart Apache 2 |
|
44 |
set +e |
|
45 |
if [ -x /usr/sbin/invoke-rc.d ]; then |
|
46 |
invoke-rc.d apache2 restart || true |
|
47 |
else |
|
48 |
/etc/init.d/apache2 restart || true |
|
49 |
fi |
|
50 |
set -e |
|
51 |
;; |
|
52 |
|
|
53 |
*) |
|
54 |
echo "postinst called with unknown argument \`$1'" >&2 |
|
55 |
exit 1 |
|
56 |
;; |
|
57 |
esac |
|
58 |
|
|
59 |
|
|
60 |
|
|
61 |
# dh_installdeb will replace this with shell code automatically |
|
62 |
# generated by other debhelper scripts. |
|
63 |
|
|
64 |
#DEBHELPER# |
|
65 |
|
|
66 |
exit 0 |
larpe/tags/release-1.1.1/debian/prerm | ||
---|---|---|
1 |
#! /bin/sh |
|
2 |
# prerm script for larpe |
|
3 |
# |
|
4 |
# see: dh_installdeb(1) |
|
5 |
|
|
6 |
set -e |
|
7 |
|
|
8 |
# summary of how this script can be called: |
|
9 |
# * <prerm> `remove' |
|
10 |
# * <old-prerm> `upgrade' <new-version> |
|
11 |
# * <new-prerm> `failed-upgrade' <old-version> |
|
12 |
# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version> |
|
13 |
# * <deconfigured's-prerm> `deconfigure' `in-favour' |
|
14 |
# <package-being-installed> <version> `removing' |
|
15 |
# <conflicting-package> <version> |
|
16 |
# for details, see http://www.debian.org/doc/debian-policy/ or |
|
17 |
# the debian-policy package |
|
18 |
|
|
19 |
|
|
20 |
PACKAGE=larpe |
|
21 |
|
|
22 |
case "$1" in |
|
23 |
remove|upgrade|deconfigure) |
|
24 |
dpkg --listfiles $PACKAGE | |
|
25 |
awk '$0~/\.py$/ {print $0"c\n" $0"o"}' | |
|
26 |
xargs rm -f >&2 |
|
27 |
;; |
|
28 |
failed-upgrade) |
|
29 |
;; |
|
30 |
*) |
|
31 |
echo "prerm called with unknown argument \`$1'" >&2 |
|
32 |
exit 1 |
|
33 |
;; |
|
34 |
esac |
|
35 |
|
|
36 |
# dh_installdeb will replace this with shell code automatically |
|
37 |
# generated by other debhelper scripts. |
|
38 |
|
|
39 |
#DEBHELPER# |
|
40 |
|
|
41 |
exit 0 |
larpe/tags/release-1.1.1/debian/pycompat | ||
---|---|---|
1 |
2 |
larpe/tags/release-1.1.1/debian/rules | ||
---|---|---|
1 |
#!/usr/bin/make -f |
|
2 |
# GNU copyright 1997 to 1999 by Joey Hess. |
|
3 |
|
|
4 |
# Uncomment this to turn on verbose mode. |
|
5 |
#export DH_VERBOSE=1 |
|
6 |
|
|
7 |
PYTHON=/usr/bin/python |
|
8 |
|
|
9 |
LARPE_USER = www-data |
|
10 |
LARPE_GROUP = www-data |
|
11 |
|
|
12 |
ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS))) |
|
13 |
CFLAGS += -g |
|
14 |
endif |
|
15 |
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) |
|
16 |
INSTALL_PROGRAM += -s |
|
17 |
endif |
|
18 |
|
|
19 |
build: build-stamp |
|
20 |
|
|
21 |
build-stamp: |
|
22 |
dh_testdir |
|
23 |
touch build-stamp |
|
24 |
|
|
25 |
clean: |
|
26 |
dh_testdir |
|
27 |
dh_testroot |
|
28 |
rm -f build-stamp |
|
29 |
|
|
30 |
make clean |
|
31 |
|
|
32 |
dh_clean |
|
33 |
|
|
34 |
install: build |
|
35 |
dh_testdir |
|
36 |
dh_testroot |
|
37 |
dh_clean -k |
|
38 |
dh_installdirs |
|
39 |
|
|
40 |
make install prefix=/usr DESTDIR=$(CURDIR)/debian/larpe |
|
41 |
# Apache Vhost |
|
42 |
dh_install conf/apache2-vhost-larpe etc/apache2/sites-available |
|
43 |
# Apache reload script |
|
44 |
dh_install debian/larpe-reload-apache2-script usr/sbin |
|
45 |
|
|
46 |
# Give files ownership to Larpe user and group |
|
47 |
chown -R $(LARPE_USER):$(LARPE_GROUP) $(CURDIR)/debian/larpe/usr/share/larpe/ |
|
48 |
chown -R $(LARPE_USER):$(LARPE_GROUP) $(CURDIR)/debian/larpe/var/lib/larpe/ |
|
49 |
chgrp $(LARPE_GROUP) $(CURDIR)/debian/larpe/usr/sbin/larpe-reload-apache2 |
|
50 |
|
|
51 |
# Build architecture-independent files here. |
|
52 |
binary-indep: build install |
|
53 |
# We have nothing to do by default. |
|
54 |
|
|
55 |
# Build architecture-dependent files here. |
|
56 |
binary-arch: build install |
|
57 |
dh_testdir |
|
58 |
dh_testroot |
|
59 |
dh_installdocs |
|
60 |
dh_installinit |
|
61 |
dh_installchangelogs |
|
62 |
dh_link |
|
63 |
dh_strip |
|
64 |
dh_compress |
|
65 |
dh_fixperms -X /var/lib/larpe -X /usr/sbin/larpe-reload-apache2 |
|
66 |
dh_pysupport |
|
67 |
dh_installdeb |
|
68 |
dh_shlibdeps |
|
69 |
dh_gencontrol |
|
70 |
dh_md5sums |
|
71 |
dh_builddeb |
|
72 |
|
|
73 |
binary: binary-indep binary-arch |
|
74 |
.PHONY: build clean binary-indep binary-arch binary install |
larpe/tags/release-1.1.1/doc/Makefile | ||
---|---|---|
1 |
all: |
|
2 |
$(MAKE) -C en |
|
3 |
|
|
4 |
clean: |
|
5 |
$(MAKE) -C en clean |
|
6 |
|
|
7 |
.PHONY: clean |
|
8 |
|
larpe/tags/release-1.1.1/doc/en/Makefile | ||
---|---|---|
1 |
RST2HTML = rst2html |
|
2 |
RST2LATEX = ../scripts/rst2latex.py |
|
3 |
PDFLATEX = pdflatex |
|
4 |
RM = rm -f |
|
5 |
|
|
6 |
all: larpe-admin.pdf larpe-admin.html |
|
7 |
|
|
8 |
%.html: %.rst |
|
9 |
$(RST2HTML) --stylesheet=default.css --link-stylesheet --language=en $? > $@ |
|
10 |
|
|
11 |
figures-no-alpha-stamp: |
|
12 |
-$(RM) -r figures-no-alpha/ |
|
13 |
mkdir figures-no-alpha/ |
|
14 |
for F in figures/*.png; do \ |
|
15 |
../scripts/removealpha.sh $$F figures-no-alpha/`basename $$F`; \ |
|
16 |
done |
|
17 |
touch figures-no-alpha-stamp |
|
18 |
|
|
19 |
%.tex: %.rst #figures-no-alpha-stamp |
|
20 |
cat $? | sed -e 's/figures\//figures-no-alpha\//' \ |
|
21 |
-e 's/ ::$$/ : ::/g' \ |
|
22 |
-e 's/.. section-numbering:://' | $(RST2LATEX) --language=en > $@ |
|
23 |
|
|
24 |
%.pdf: %.tex custom.tex |
|
25 |
$(PDFLATEX) $? |
|
26 |
logfile=`echo "$@" |sed -r "s/(.*)....$$/\\1/"`.log; while [ -f "$$logfile" -a -n "`grep "Rerun to get cross-references right" $$logfile`" ]; do $(PDFLATEX) $< ; done |
|
27 |
|
|
28 |
clean: |
|
29 |
-$(RM) *.aux *.toc *.log *.out |
|
30 |
-$(RM) larpe-admin.pdf |
|
31 |
-$(RM) larpe-admin.tex |
|
32 |
-$(RM) larpe-admin.html |
|
33 |
-$(RM) -r figures-no-alpha figures-no-alpha-stamp |
|
34 |
|
|
35 |
.PHONY: all clean |
larpe/tags/release-1.1.1/doc/en/custom.tex | ||
---|---|---|
1 |
\usepackage{float,fancyhdr,lscape,sectsty,colortbl,color,lastpage,setspace} |
|
2 |
\usepackage[perpage,bottom]{footmisc} |
|
3 |
\usepackage[hang]{caption2} |
|
4 |
\usepackage{marvosym} |
|
5 |
|
|
6 |
\usepackage{float,url,listings,tocbibind,fancyhdr,calc,placeins} |
|
7 |
|
|
8 |
\usepackage{palatino} |
|
9 |
\usepackage[Glenn]{fncychap} |
|
10 |
|
|
11 |
\pagestyle{fancy} |
|
12 |
\fancyhead{} |
|
13 |
\fancyfoot{} |
|
14 |
\fancyhead[L]{Authentic} |
|
15 |
\fancyhead[R]{Administrator Guide} |
|
16 |
\fancyfoot[C]{Page \thepage} |
|
17 |
\addtolength{\headheight}{1.6pt} |
|
18 |
|
|
19 |
\setlength\parindent{0pt} |
|
20 |
\setlength{\parskip}{1ex plus 0.5ex minus 0.2ex} |
|
21 |
\setlength\abovecaptionskip{0.1ex} |
|
22 |
|
|
23 |
\makeatletter |
|
24 |
\renewcommand{\maketitle}{\begin{titlepage}% |
|
25 |
\let\footnotesize\small |
|
26 |
\let\footnoterule\relax |
|
27 |
\parindent \z@ |
|
28 |
\reset@font |
|
29 |
\null\vfil |
|
30 |
\begin{flushleft} |
|
31 |
\huge \@title |
|
32 |
\end{flushleft} |
|
33 |
\par |
|
34 |
\hrule height 1pt |
|
35 |
\par |
|
36 |
\begin{flushright} |
|
37 |
\LARGE \@author \par |
|
38 |
\end{flushright} |
|
39 |
\vskip 60\p@ |
|
40 |
\vfil\null |
|
41 |
\end{titlepage}% |
|
42 |
\setcounter{footnote}{0}% |
|
43 |
} |
|
44 |
\makeatother |
|
45 |
|
larpe/tags/release-1.1.1/doc/en/default.css | ||
---|---|---|
1 |
body { |
|
2 |
font-family: sans-serif; |
|
3 |
} |
|
4 |
|
|
5 |
|
|
6 |
h1 a, h2 a, h3 a, h4 a { |
|
7 |
text-decoration: inherit; |
|
8 |
color: inherit; |
|
9 |
} |
|
10 |
|
|
11 |
pre.literal-block { |
|
12 |
background: #eee; |
|
13 |
border: 1px inset black; |
|
14 |
padding: 2px; |
|
15 |
margin: auto 10px; |
|
16 |
overflow: auto; |
|
17 |
} |
|
18 |
|
|
19 |
h1.title { |
|
20 |
text-align: center; |
|
21 |
background: #eef; |
|
22 |
border: 1px solid #aaf; |
|
23 |
letter-spacing: 1px; |
|
24 |
} |
|
25 |
|
|
26 |
div.section { |
|
27 |
margin-bottom: 2em; |
|
28 |
} |
|
29 |
|
|
30 |
div.section h1 { |
|
31 |
padding: 0 15px; |
|
32 |
background: #eef; |
|
33 |
border: 1px solid #aaf; |
|
34 |
} |
|
35 |
|
|
36 |
div.section h2 { |
|
37 |
padding: 0 15px; |
|
38 |
background: #eef; |
|
39 |
border: 1px solid #aaf; |
|
40 |
} |
|
41 |
|
|
42 |
div.document { |
|
43 |
margin-top: 1em; |
|
44 |
border-top: 1px solid #aaf; |
|
45 |
border-bottom: 1px solid #aaf; |
|
46 |
} |
|
47 |
|
|
48 |
div.section p, |
|
49 |
div.section ul { |
|
50 |
text-align: justify; |
|
51 |
} |
|
52 |
|
|
53 |
div.contents { |
|
54 |
float: right; |
|
55 |
border: 1px solid black; |
|
56 |
margin: 1em; |
|
57 |
background: #eef; |
|
58 |
max-width: 33%; |
|
59 |
} |
|
60 |
|
|
61 |
div#building-liberty-services-with-lasso div#table-of-contents { |
|
62 |
max-width: inherit; |
|
63 |
float: none; |
|
64 |
background: white url(lasso.png) bottom right no-repeat; |
|
65 |
} |
|
66 |
|
|
67 |
div.contents ul { |
|
68 |
padding-left: 1em; |
|
69 |
list-style: none; |
|
70 |
} |
|
71 |
|
|
72 |
div.contents li { |
|
73 |
padding-bottom: 2px; |
|
74 |
} |
|
75 |
|
|
76 |
div.contents p { |
|
77 |
background: #ddf; |
|
78 |
text-align: center; |
|
79 |
border-bottom: 1px solid black; |
|
80 |
margin: 0; |
|
81 |
} |
|
82 |
|
|
83 |
th.docinfo-name { |
|
84 |
text-align: right; |
|
85 |
padding-right: 0.5em; |
|
86 |
} |
|
87 |
|
|
88 |
dd { |
|
89 |
margin-bottom: 1ex; |
|
90 |
} |
|
91 |
|
|
92 |
table.table { |
|
93 |
margin: 1ex 0; |
|
94 |
border-spacing: 0px; |
|
95 |
} |
|
96 |
|
|
97 |
|
|
98 |
table.table th { |
|
99 |
padding: 0px 1ex; |
|
100 |
background: #eef; |
|
101 |
font-weight: normal; |
|
102 |
} |
|
103 |
|
|
104 |
|
|
105 |
table.table td { |
|
106 |
padding: 0 0.5ex; |
|
107 |
} |
|
108 |
|
|
109 |
div.note, div.warning { |
|
110 |
padding: 0.3ex; |
|
111 |
padding-left: 60px; |
|
112 |
min-height: 50px; |
|
113 |
margin: 1ex 1em; |
|
114 |
} |
|
115 |
|
|
116 |
div.note { |
|
117 |
background: #ffa url(note.png) top left no-repeat; |
|
118 |
border: 1px solid #fd8; |
|
119 |
} |
|
120 |
|
|
121 |
div.warning { |
|
122 |
background: #ffd url(warning.png) top left no-repeat; |
|
123 |
} |
|
124 |
|
|
125 |
p.admonition-title { |
|
126 |
font-weight: bold; |
|
127 |
display: inline; |
|
128 |
display: none; |
|
129 |
padding-right: 1em; |
|
130 |
} |
|
131 |
|
|
132 |
div.figure { |
|
133 |
margin: 0 auto; |
|
134 |
width: 70%; |
|
135 |
min-width: 800px; |
|
136 |
text-align: center; |
|
137 |
} |
|
138 |
|
|
139 |
div.figure p.caption { |
|
140 |
font-style: italic; |
|
141 |
margin: 1ex 0 2em 0; |
|
142 |
text-align: center; |
|
143 |
} |
larpe/tags/release-1.1.1/doc/en/fncychap.sty | ||
---|---|---|
1 |
%%% Copyright Ulf A. Lindgren |
|
2 |
%%% |
|
3 |
%%% Note Premission is granted to modify this file under |
|
4 |
%%% the condition that it is saved using another |
|
5 |
%%% file and package name. |
|
6 |
%%% |
|
7 |
%%% Revision 1.1 (1997) |
|
8 |
%%% |
|
9 |
%%% Jan. 8th Modified package name base date option |
|
10 |
%%% Jan. 22th Modified FmN and FmTi for error in book.cls |
|
11 |
%%% \MakeUppercase{#}->{\MakeUppercase#} |
|
12 |
%%% Apr. 6th Modified Lenny option to prevent undesired |
|
13 |
%%% skip of line. |
|
14 |
%%% Nov. 8th Fixed \@chapapp for AMS |
|
15 |
%%% |
|
16 |
%%% Revision 1.2 (1998) |
|
17 |
%%% |
|
18 |
%%% Feb. 11th Fixed appendix problem related to Bjarne |
|
19 |
%%% Aug. 11th Fixed problem related to 11pt and 12pt |
|
20 |
%%% suggested by Tomas Lundberg. THANKS! |
|
21 |
%%% |
|
22 |
%%% Revision 1.3 (2004) |
|
23 |
%%% Sep. 20th problem with frontmatter, mainmatter and |
|
24 |
%%% backmatter, pointed out by Lapo Mori |
|
25 |
%%% |
|
26 |
%%% Revision 1.31 (2004) |
|
27 |
%%% Sep. 21th problem with the Rejne definition streched text |
|
28 |
%%% caused ugly gaps in the vrule aligned with the title |
|
29 |
%%% text. Kindly pointed out to me by Hendri Adriaens |
|
30 |
%%% |
|
31 |
%%% Revision 1.32 (2005) |
|
32 |
%%% Jun. 23th compatibility problem with the KOMA class 'scrbook.cls' |
|
33 |
%%% a remedy is a redefinition of '\@schapter' in |
|
34 |
%%% line with that used in KOMA. The problem was pointed |
|
35 |
%%% out to me by Mikkel Holm Olsen |
|
36 |
%%% |
|
37 |
%%% Revision 1.33 (2005) |
|
38 |
%%% Aug. 9th misspelled ``TWELV'' corrected, the error was pointed |
|
39 |
%%% out to me by George Pearson |
|
40 |
%%% |
|
41 |
|
|
42 |
|
|
43 |
%%% Last modified Aug. 9th 2005 |
|
44 |
|
|
45 |
\NeedsTeXFormat{LaTeX2e}[1995/12/01] |
|
46 |
\ProvidesPackage{fncychap} |
|
47 |
[2004/09/21 v1.33 |
|
48 |
LaTeX package (Revised chapters)] |
|
49 |
|
|
50 |
%%%% DEFINITION OF Chapapp variables |
|
51 |
\newcommand{\CNV}{\huge\bfseries} |
|
52 |
\newcommand{\ChNameVar}[1]{\renewcommand{\CNV}{#1}} |
|
53 |
|
|
54 |
|
|
55 |
%%%% DEFINITION OF TheChapter variables |
|
56 |
\newcommand{\CNoV}{\huge\bfseries} |
|
57 |
\newcommand{\ChNumVar}[1]{\renewcommand{\CNoV}{#1}} |
|
58 |
|
|
59 |
\newif\ifUCN |
|
60 |
\UCNfalse |
|
61 |
\newif\ifLCN |
|
62 |
\LCNfalse |
|
63 |
\def\ChNameLowerCase{\LCNtrue\UCNfalse} |
|
64 |
\def\ChNameUpperCase{\UCNtrue\LCNfalse} |
|
65 |
\def\ChNameAsIs{\UCNfalse\LCNfalse} |
|
66 |
|
|
67 |
%%%%% Fix for AMSBook 971008 |
|
68 |
|
|
69 |
\@ifundefined{@chapapp}{\let\@chapapp\chaptername}{} |
|
70 |
|
|
71 |
|
|
72 |
%%%%% Fix for Bjarne and appendix 980211 |
|
73 |
|
|
74 |
\newif\ifinapp |
|
75 |
\inappfalse |
|
76 |
\renewcommand\appendix{\par |
|
77 |
\setcounter{chapter}{0}% |
|
78 |
\setcounter{section}{0}% |
|
79 |
\inapptrue% |
|
80 |
\renewcommand\@chapapp{\appendixname}% |
|
81 |
\renewcommand\thechapter{\@Alph\c@chapter}} |
|
82 |
|
|
83 |
%%%%% Fix for frontmatter, mainmatter, and backmatter 040920 |
|
84 |
|
|
85 |
\@ifundefined{@mainmatter}{\newif\if@mainmatter \@mainmattertrue}{} |
|
86 |
|
|
87 |
%%%%% |
|
88 |
|
|
89 |
|
|
90 |
|
|
91 |
\newcommand{\FmN}[1]{% |
|
92 |
\ifUCN |
|
93 |
{\MakeUppercase#1}\LCNfalse |
|
94 |
\else |
|
95 |
\ifLCN |
|
96 |
{\MakeLowercase#1}\UCNfalse |
|
97 |
\else #1 |
|
98 |
\fi |
|
99 |
\fi} |
|
100 |
|
|
101 |
|
|
102 |
%%%% DEFINITION OF Title variables |
|
103 |
\newcommand{\CTV}{\Huge\bfseries} |
|
104 |
\newcommand{\ChTitleVar}[1]{\renewcommand{\CTV}{#1}} |
|
105 |
|
|
106 |
%%%% DEFINITION OF the basic rule width |
|
107 |
\newlength{\RW} |
|
108 |
\setlength{\RW}{1pt} |
|
109 |
\newcommand{\ChRuleWidth}[1]{\setlength{\RW}{#1}} |
|
110 |
|
|
111 |
\newif\ifUCT |
|
112 |
\UCTfalse |
|
113 |
\newif\ifLCT |
|
114 |
\LCTfalse |
|
115 |
\def\ChTitleLowerCase{\LCTtrue\UCTfalse} |
|
116 |
\def\ChTitleUpperCase{\UCTtrue\LCTfalse} |
|
117 |
\def\ChTitleAsIs{\UCTfalse\LCTfalse} |
|
118 |
\newcommand{\FmTi}[1]{% |
|
119 |
\ifUCT |
|
120 |
{\MakeUppercase#1}\LCTfalse |
|
121 |
\else |
|
122 |
\ifLCT |
|
123 |
{\MakeLowercase#1}\UCTfalse |
|
124 |
\else {#1} |
|
125 |
\fi |
|
126 |
\fi} |
|
127 |
|
|
128 |
|
|
129 |
|
|
130 |
\newlength{\mylen} |
|
131 |
\newlength{\myhi} |
|
132 |
\newlength{\px} |
|
133 |
\newlength{\py} |
|
134 |
\newlength{\pyy} |
|
135 |
\newlength{\pxx} |
|
136 |
|
|
137 |
|
|
138 |
\def\mghrulefill#1{\leavevmode\leaders\hrule\@height #1\hfill\kern\z@} |
|
139 |
|
|
140 |
\newcommand{\DOCH}{% |
|
141 |
\CNV\FmN{\@chapapp}\space \CNoV\thechapter |
|
142 |
\par\nobreak |
|
143 |
\vskip 20\p@ |
|
144 |
} |
|
145 |
\newcommand{\DOTI}[1]{% |
|
146 |
\CTV\FmTi{#1}\par\nobreak |
|
147 |
\vskip 40\p@ |
|
148 |
} |
|
149 |
\newcommand{\DOTIS}[1]{% |
|
150 |
\CTV\FmTi{#1}\par\nobreak |
|
151 |
\vskip 40\p@ |
|
152 |
} |
|
153 |
|
|
154 |
%%%%%% SONNY DEF |
|
155 |
|
|
156 |
\DeclareOption{Sonny}{% |
|
157 |
\ChNameVar{\Large\sf} |
|
158 |
\ChNumVar{\Huge} |
|
159 |
\ChTitleVar{\Large\sf} |
|
160 |
\ChRuleWidth{0.5pt} |
|
161 |
\ChNameUpperCase |
|
162 |
\renewcommand{\DOCH}{% |
|
163 |
\raggedleft |
|
164 |
\CNV\FmN{\@chapapp}\space \CNoV\thechapter |
|
165 |
\par\nobreak |
|
166 |
\vskip 40\p@} |
|
167 |
\renewcommand{\DOTI}[1]{% |
|
168 |
\CTV\raggedleft\mghrulefill{\RW}\par\nobreak |
|
169 |
\vskip 5\p@ |
|
170 |
\CTV\FmTi{#1}\par\nobreak |
|
171 |
\mghrulefill{\RW}\par\nobreak |
|
172 |
\vskip 40\p@} |
|
173 |
\renewcommand{\DOTIS}[1]{% |
|
174 |
\CTV\raggedleft\mghrulefill{\RW}\par\nobreak |
|
175 |
\vskip 5\p@ |
|
176 |
\CTV\FmTi{#1}\par\nobreak |
|
177 |
\mghrulefill{\RW}\par\nobreak |
|
178 |
\vskip 40\p@} |
|
179 |
} |
|
180 |
|
|
181 |
%%%%%% LENNY DEF |
|
182 |
|
|
183 |
\DeclareOption{Lenny}{% |
|
184 |
|
|
185 |
\ChNameVar{\fontsize{14}{16}\usefont{OT1}{phv}{m}{n}\selectfont} |
|
186 |
\ChNumVar{\fontsize{60}{62}\usefont{OT1}{ptm}{m}{n}\selectfont} |
|
187 |
\ChTitleVar{\Huge\bfseries\rm} |
|
188 |
\ChRuleWidth{1pt} |
|
189 |
\renewcommand{\DOCH}{% |
|
190 |
\settowidth{\px}{\CNV\FmN{\@chapapp}} |
|
191 |
\addtolength{\px}{2pt} |
|
192 |
\settoheight{\py}{\CNV\FmN{\@chapapp}} |
|
193 |
\addtolength{\py}{1pt} |
|
194 |
|
|
195 |
\settowidth{\mylen}{\CNV\FmN{\@chapapp}\space\CNoV\thechapter} |
|
196 |
\addtolength{\mylen}{1pt} |
|
197 |
\settowidth{\pxx}{\CNoV\thechapter} |
|
198 |
\addtolength{\pxx}{-1pt} |
|
199 |
|
|
200 |
\settoheight{\pyy}{\CNoV\thechapter} |
|
201 |
\addtolength{\pyy}{-2pt} |
|
202 |
\setlength{\myhi}{\pyy} |
|
203 |
\addtolength{\myhi}{-1\py} |
|
204 |
\par |
|
205 |
\parbox[b]{\textwidth}{% |
|
206 |
\rule[\py]{\RW}{\myhi}% |
|
207 |
\hskip -\RW% |
|
208 |
\rule[\pyy]{\px}{\RW}% |
|
209 |
\hskip -\px% |
|
210 |
\raggedright% |
|
211 |
\CNV\FmN{\@chapapp}\space\CNoV\thechapter% |
|
212 |
\hskip1pt% |
|
213 |
\mghrulefill{\RW}% |
|
214 |
\rule{\RW}{\pyy}\par\nobreak% |
|
215 |
\vskip -\baselineskip% |
|
216 |
\vskip -\pyy% |
|
217 |
\hskip \mylen% |
|
218 |
\mghrulefill{\RW}\par\nobreak% |
|
219 |
\vskip \pyy}% |
|
220 |
\vskip 20\p@} |
|
221 |
|
|
222 |
|
|
223 |
\renewcommand{\DOTI}[1]{% |
|
224 |
\raggedright |
|
225 |
\CTV\FmTi{#1}\par\nobreak |
|
226 |
\vskip 40\p@} |
|
227 |
|
|
228 |
\renewcommand{\DOTIS}[1]{% |
|
229 |
\raggedright |
|
230 |
\CTV\FmTi{#1}\par\nobreak |
|
231 |
\vskip 40\p@} |
|
232 |
} |
|
233 |
|
|
234 |
|
|
235 |
%%%%%%% GLENN DEF |
|
236 |
|
|
237 |
|
|
238 |
\DeclareOption{Glenn}{% |
|
239 |
\ChNameVar{\bfseries\Large\sf} |
|
240 |
\ChNumVar{\Huge} |
|
241 |
\ChTitleVar{\bfseries\Large\rm} |
|
242 |
\ChRuleWidth{1pt} |
|
243 |
\ChNameUpperCase |
|
244 |
\ChTitleUpperCase |
|
245 |
\renewcommand{\DOCH}{% |
|
246 |
\settoheight{\myhi}{\CTV\FmTi{Test}} |
|
247 |
\setlength{\py}{\baselineskip} |
|
248 |
\addtolength{\py}{\RW} |
|
249 |
\addtolength{\py}{\myhi} |
|
250 |
\setlength{\pyy}{\py} |
|
251 |
\addtolength{\pyy}{-1\RW} |
|
252 |
|
|
253 |
\raggedright |
|
254 |
\CNV\FmN{\@chapapp}\space\CNoV\thechapter |
|
255 |
\hskip 3pt\mghrulefill{\RW}\rule[-1\pyy]{2\RW}{\py}\par\nobreak} |
|
256 |
|
|
257 |
\renewcommand{\DOTI}[1]{% |
|
258 |
\addtolength{\pyy}{-4pt} |
|
259 |
\settoheight{\myhi}{\CTV\FmTi{#1}} |
|
260 |
\addtolength{\myhi}{\py} |
|
261 |
\addtolength{\myhi}{-1\RW} |
|
262 |
\vskip -1\pyy |
|
263 |
\rule{2\RW}{\myhi}\mghrulefill{\RW}\hskip 2pt |
|
264 |
\raggedleft\CTV\FmTi{#1}\par\nobreak |
|
265 |
\vskip 80\p@} |
|
266 |
|
|
267 |
\newlength{\backskip} |
|
268 |
\renewcommand{\DOTIS}[1]{% |
|
269 |
% \setlength{\py}{10pt} |
|
270 |
% \setlength{\pyy}{\py} |
|
271 |
% \addtolength{\pyy}{\RW} |
|
272 |
% \setlength{\myhi}{\baselineskip} |
|
273 |
% \addtolength{\myhi}{\pyy} |
|
274 |
% \mghrulefill{\RW}\rule[-1\py]{2\RW}{\pyy}\par\nobreak |
|
275 |
% \addtolength{}{} |
|
276 |
%\vskip -1\baselineskip |
|
277 |
% \rule{2\RW}{\myhi}\mghrulefill{\RW}\hskip 2pt |
|
278 |
% \raggedleft\CTV\FmTi{#1}\par\nobreak |
|
279 |
% \vskip 60\p@} |
|
280 |
%% Fix suggested by Tomas Lundberg |
|
281 |
\setlength{\py}{25pt} % eller vad man vill |
|
282 |
\setlength{\pyy}{\py} |
|
283 |
\setlength{\backskip}{\py} |
|
284 |
\addtolength{\backskip}{2pt} |
|
285 |
\addtolength{\pyy}{\RW} |
|
286 |
\setlength{\myhi}{\baselineskip} |
|
287 |
\addtolength{\myhi}{\pyy} |
|
288 |
\mghrulefill{\RW}\rule[-1\py]{2\RW}{\pyy}\par\nobreak |
|
289 |
\vskip -1\backskip |
|
290 |
\rule{2\RW}{\myhi}\mghrulefill{\RW}\hskip 3pt % |
|
291 |
\raggedleft\CTV\FmTi{#1}\par\nobreak |
|
292 |
\vskip 40\p@} |
|
293 |
} |
|
294 |
|
|
295 |
%%%%%%% CONNY DEF |
|
296 |
|
|
297 |
\DeclareOption{Conny}{% |
|
298 |
\ChNameUpperCase |
|
299 |
\ChTitleUpperCase |
|
300 |
\ChNameVar{\centering\Huge\rm\bfseries} |
|
301 |
\ChNumVar{\Huge} |
|
302 |
\ChTitleVar{\centering\Huge\rm} |
|
303 |
\ChRuleWidth{2pt} |
|
304 |
|
|
305 |
\renewcommand{\DOCH}{% |
|
306 |
\mghrulefill{3\RW}\par\nobreak |
|
307 |
\vskip -0.5\baselineskip |
|
308 |
\mghrulefill{\RW}\par\nobreak |
|
309 |
\CNV\FmN{\@chapapp}\space \CNoV\thechapter |
|
310 |
\par\nobreak |
|
311 |
\vskip -0.5\baselineskip |
|
312 |
} |
|
313 |
\renewcommand{\DOTI}[1]{% |
|
314 |
\mghrulefill{\RW}\par\nobreak |
|
315 |
\CTV\FmTi{#1}\par\nobreak |
|
316 |
\vskip 60\p@ |
|
317 |
} |
|
318 |
\renewcommand{\DOTIS}[1]{% |
|
319 |
\mghrulefill{\RW}\par\nobreak |
|
320 |
\CTV\FmTi{#1}\par\nobreak |
|
321 |
\vskip 60\p@ |
|
322 |
} |
|
323 |
} |
|
324 |
|
|
325 |
%%%%%%% REJNE DEF |
|
326 |
|
|
327 |
\DeclareOption{Rejne}{% |
|
328 |
|
|
329 |
\ChNameUpperCase |
|
330 |
\ChTitleUpperCase |
|
331 |
\ChNameVar{\centering\Large\rm} |
|
332 |
\ChNumVar{\Huge} |
|
333 |
\ChTitleVar{\centering\Huge\rm} |
|
334 |
\ChRuleWidth{1pt} |
|
335 |
\renewcommand{\DOCH}{% |
|
336 |
\settoheight{\py}{\CNoV\thechapter} |
|
337 |
\parskip=0pt plus 1pt % Set parskip to default, just in case v1.31 |
|
338 |
\addtolength{\py}{-1pt} |
|
339 |
\CNV\FmN{\@chapapp}\par\nobreak |
|
340 |
\vskip 20\p@ |
|
341 |
\setlength{\myhi}{2\baselineskip} |
|
342 |
\setlength{\px}{\myhi} |
|
343 |
\addtolength{\px}{-1\RW} |
|
344 |
\rule[-1\px]{\RW}{\myhi}\mghrulefill{\RW}\hskip |
|
345 |
10pt\raisebox{-0.5\py}{\CNoV\thechapter}\hskip 10pt\mghrulefill{\RW}\rule[-1\px]{\RW}{\myhi}\par\nobreak |
|
346 |
\vskip -3\p@% Added -2pt vskip to correct for streched text v1.31 |
|
347 |
} |
|
348 |
\renewcommand{\DOTI}[1]{% |
|
349 |
\setlength{\mylen}{\textwidth} |
|
350 |
\parskip=0pt plus 1pt % Set parskip to default, just in case v1.31 |
|
351 |
\addtolength{\mylen}{-2\RW} |
|
352 |
{\vrule width\RW}\parbox{\mylen}{\CTV\FmTi{#1}}{\vrule width\RW}\par\nobreak% |
|
353 |
\vskip -3pt\rule{\RW}{2\baselineskip}\mghrulefill{\RW}\rule{\RW}{2\baselineskip}% |
|
354 |
\vskip 60\p@% Added -2pt in vskip to correct for streched text v1.31 |
|
355 |
} |
|
356 |
\renewcommand{\DOTIS}[1]{% |
|
357 |
\setlength{\py}{\fboxrule} |
|
358 |
\setlength{\fboxrule}{\RW} |
|
359 |
\setlength{\mylen}{\textwidth} |
|
360 |
\addtolength{\mylen}{-2\RW} |
|
361 |
\fbox{\parbox{\mylen}{\vskip 2\baselineskip\CTV\FmTi{#1}\par\nobreak\vskip \baselineskip}} |
|
362 |
\setlength{\fboxrule}{\py} |
|
363 |
\vskip 60\p@ |
|
364 |
} |
|
365 |
} |
|
366 |
|
|
367 |
|
|
368 |
%%%%%%% BJARNE DEF |
|
369 |
|
|
370 |
\DeclareOption{Bjarne}{% |
|
371 |
\ChNameUpperCase |
|
372 |
\ChTitleUpperCase |
|
373 |
\ChNameVar{\raggedleft\normalsize\rm} |
|
374 |
\ChNumVar{\raggedleft \bfseries\Large} |
|
375 |
\ChTitleVar{\raggedleft \Large\rm} |
|
376 |
\ChRuleWidth{1pt} |
|
377 |
|
|
378 |
|
|
379 |
%% Note thechapter -> c@chapter fix appendix bug |
|
380 |
%% Fixed misspelled 12 |
|
381 |
|
|
382 |
\newcounter{AlphaCnt} |
|
383 |
\newcounter{AlphaDecCnt} |
|
384 |
\newcommand{\AlphaNo}{% |
|
385 |
\ifcase\number\theAlphaCnt |
|
386 |
\ifnum\c@chapter=0 |
|
387 |
ZERO\else{}\fi |
|
388 |
\or ONE\or TWO\or THREE\or FOUR\or FIVE |
|
389 |
\or SIX\or SEVEN\or EIGHT\or NINE\or TEN |
|
390 |
\or ELEVEN\or TWELVE\or THIRTEEN\or FOURTEEN\or FIFTEEN |
|
391 |
\or SIXTEEN\or SEVENTEEN\or EIGHTEEN\or NINETEEN\fi |
|
392 |
} |
|
393 |
|
|
394 |
\newcommand{\AlphaDecNo}{% |
|
395 |
\setcounter{AlphaDecCnt}{0} |
|
396 |
\@whilenum\number\theAlphaCnt>0\do |
|
397 |
{\addtocounter{AlphaCnt}{-10} |
|
398 |
\addtocounter{AlphaDecCnt}{1}} |
|
399 |
\ifnum\number\theAlphaCnt=0 |
|
400 |
\else |
|
401 |
\addtocounter{AlphaDecCnt}{-1} |
|
402 |
\addtocounter{AlphaCnt}{10} |
|
403 |
\fi |
|
404 |
|
|
405 |
|
|
406 |
\ifcase\number\theAlphaDecCnt\or TEN\or TWENTY\or THIRTY\or |
|
407 |
FORTY\or FIFTY\or SIXTY\or SEVENTY\or EIGHTY\or NINETY\fi |
|
408 |
} |
|
409 |
\newcommand{\TheAlphaChapter}{% |
|
410 |
|
|
411 |
\ifinapp |
|
412 |
\thechapter |
|
413 |
\else |
|
414 |
\setcounter{AlphaCnt}{\c@chapter} |
|
415 |
\ifnum\c@chapter<20 |
|
416 |
\AlphaNo |
|
417 |
\else |
|
418 |
\AlphaDecNo\AlphaNo |
|
419 |
\fi |
|
420 |
\fi |
|
421 |
} |
|
422 |
\renewcommand{\DOCH}{% |
|
423 |
\mghrulefill{\RW}\par\nobreak |
|
424 |
\CNV\FmN{\@chapapp}\par\nobreak |
|
425 |
\CNoV\TheAlphaChapter\par\nobreak |
|
426 |
\vskip -1\baselineskip\vskip 5pt\mghrulefill{\RW}\par\nobreak |
|
427 |
\vskip 20\p@ |
|
428 |
} |
|
429 |
\renewcommand{\DOTI}[1]{% |
|
430 |
\CTV\FmTi{#1}\par\nobreak |
|
431 |
\vskip 40\p@ |
|
432 |
} |
|
433 |
\renewcommand{\DOTIS}[1]{% |
|
434 |
\CTV\FmTi{#1}\par\nobreak |
|
435 |
\vskip 40\p@ |
|
436 |
} |
|
437 |
} |
|
438 |
|
|
439 |
\DeclareOption*{% |
|
440 |
\PackageWarning{fancychapter}{unknown style option} |
|
441 |
} |
|
442 |
|
|
443 |
\ProcessOptions* \relax |
|
444 |
|
|
445 |
\def\@makechapterhead#1{% |
|
446 |
\vspace*{50\p@}% |
|
447 |
{\parindent \z@ \raggedright \normalfont |
|
448 |
\ifnum \c@secnumdepth >\m@ne |
|
449 |
\if@mainmatter%%%%% Fix for frontmatter, mainmatter, and backmatter 040920 |
|
450 |
\DOCH |
|
451 |
\fi |
|
452 |
\fi |
|
453 |
\interlinepenalty\@M |
|
454 |
\DOTI{#1} |
|
455 |
}} |
|
456 |
|
|
457 |
|
|
458 |
%%% Begin: To avoid problem with scrbook.cls (fncychap version 1.32) |
|
459 |
|
|
460 |
%%OUT: |
|
461 |
%\def\@schapter#1{\if@twocolumn |
|
462 |
% \@topnewpage[\@makeschapterhead{#1}]% |
|
463 |
% \else |
|
464 |
% \@makeschapterhead{#1}% |
|
465 |
% \@afterheading |
|
466 |
% \fi} |
|
467 |
|
|
468 |
%%IN: |
|
469 |
\def\@schapter#1{% |
|
470 |
\if@twocolumn% |
|
471 |
\@makeschapterhead{#1}% |
|
472 |
\else% |
|
473 |
\@makeschapterhead{#1}% |
|
474 |
\@afterheading% |
|
475 |
\fi} |
|
476 |
|
|
477 |
%%% End: To avoid problem with scrbook.cls (fncychap version 1.32) |
|
478 |
|
|
479 |
\def\@makeschapterhead#1{% |
|
480 |
\vspace*{50\p@}% |
|
481 |
{\parindent \z@ \raggedright |
|
482 |
\normalfont |
|
483 |
\interlinepenalty\@M |
|
484 |
\DOTIS{#1} |
|
485 |
\vskip 40\p@ |
|
486 |
}} |
|
487 |
|
|
488 |
\endinput |
|
489 |
|
|
490 |
|
larpe/tags/release-1.1.1/doc/en/larpe-admin.rst | ||
---|---|---|
1 |
===================================== |
|
2 |
Larpe - Administrator Guide |
|
3 |
===================================== |
|
4 |
|
|
5 |
:author: Damien Laniel |
|
6 |
:contact: dlaniel@entrouvert.com |
|
7 |
:copyright: Copyright © 2006 Entr'ouvert |
|
8 |
|
|
9 |
.. contents:: Table of contents |
|
10 |
|
|
11 |
Overview |
|
12 |
======== |
|
13 |
|
|
14 |
Larpe is a Liberty Alliance Reverse Proxy. It allows any service provider |
|
15 |
(that is a website) to use Liberty Alliance features (Identity federation, |
|
16 |
Single Sign On and Single Logout) without changing the code of |
|
17 |
the service provider itself. It uses the Lasso_ library |
|
18 |
which is certified by the `Liberty Alliance`_ consortium. Lasso_ and Larpe |
|
19 |
are released under the terms of the `GNU GPL license`_. |
|
20 |
|
|
21 |
|
|
22 |
How to get and install Larpe |
|
23 |
============================ |
|
24 |
|
|
25 |
Installation under Debian_ Sarge |
|
26 |
++++++++++++++++++++++++++++++++ |
|
27 |
|
|
28 |
To work correctly Larpe relies on : |
|
29 |
|
|
30 |
* Apache2_ ; |
|
31 |
|
|
32 |
* Lasso_ (0.6.3) ; |
|
33 |
|
|
34 |
* Quixote_ (2.0) ; |
|
35 |
|
|
36 |
* SCGI_ ; |
|
37 |
|
|
38 |
* mod_python_ ; |
|
39 |
|
|
40 |
* libxml2 ; |
|
41 |
|
|
42 |
* mod_proxy_html. |
|
43 |
|
|
44 |
You will also need a Liberty Alliance Identity Provider, be it on the same server or not. |
|
45 |
We recommend Authentic_ for that need. |
|
46 |
|
|
47 |
Package Installation |
|
48 |
-------------------- |
|
49 |
|
|
50 |
You need to add the following line to your /etc/apt/sources.list; this will |
|
51 |
give you access to the repository where Larpe is stored:: |
|
52 |
|
|
53 |
deb http://deb.entrouvert.org/ sarge main |
|
54 |
|
|
55 |
As root type:: |
|
56 |
|
|
57 |
apt-get update |
|
58 |
apt-get install larpe |
|
59 |
|
|
60 |
And follow the debconf wizard to set it up. |
|
61 |
|
|
62 |
All the required packages are now installed and configured. |
|
63 |
|
|
64 |
You might need to change the "<VirtualHost \*>" in your apache2 configuration |
|
65 |
(/etc/apache2/sites-available/apache2-vhost-larpe) depending on how you |
|
66 |
previously configured apache. |
|
67 |
|
|
68 |
Don't forget to modify your /etc/hosts file if necessary. Larpe now works, the |
|
69 |
administration interface is reachable at http://your_domain_name/admin. The username |
|
70 |
and password are the ones you entered during the installation wizard. |
|
71 |
|
|
72 |
If you don't want to modify your sources.list file, you can manually dowload and |
|
73 |
install the required packages with the dpkg -i command : |
|
74 |
|
|
75 |
* Larpe, Authentic and Lasso on http://deb.entrouvert.org/ ; |
|
76 |
|
|
77 |
* Quixote 2.0 on http://authentic.labs.libre-entreprise.org/. |
|
78 |
|
|
79 |
Installation with another Linux distribution |
|
80 |
++++++++++++++++++++++++++++++++++++++++++++ |
|
81 |
|
|
82 |
We suppose Apache2_, SCGI_, mod_python_, libxml2 and mod_proxy_html are already installed. You need then to |
|
83 |
download and install the following sources : |
|
84 |
|
|
85 |
* Lasso http://lasso.entrouvert.org ; |
|
86 |
|
|
87 |
* Quixote http://www.mems-exchange.org/software/Quixote/ ; |
|
88 |
|
|
89 |
* Authentic http://authentic.labs.libre-entreprise.org/ ; |
|
90 |
|
|
91 |
* Larpe http://labs.libre-entreprise.org/frs/?group_id=108. |
|
92 |
|
|
93 |
To install Larpe, uncompress the sources you have downloaded and launch the |
|
94 |
setup.py script :: |
|
95 |
|
|
96 |
tar xzf larpe*.tar.gz |
|
97 |
cd larpe* |
|
98 |
python setup.py install |
|
99 |
|
|
100 |
You need then to configure Apache2_ correctly. You should use the provided apache2-vhost-larpe template and adapt to your configuration. |
|
101 |
|
|
102 |
Don't forget to modify your /etc/hosts file if necessary. Larpe now works, the |
|
103 |
administration interface is reachable at http://your_domain_name/admin. |
|
104 |
|
|
105 |
Basic Larpe configuration |
|
106 |
========================= |
|
107 |
|
|
108 |
Identity Provider configuration |
|
109 |
+++++++++++++++++++++++++++++++ |
|
110 |
|
|
111 |
If you don't have a configured Identity Provider yet, please read Authentic |
|
112 |
manual to set it up. Then you must have the metadata and public key of the Identity |
|
113 |
Provider to begin with Larpe. |
|
114 |
|
|
115 |
Then in Larpe administration interface, click on "Settings", then "Identity Provider". |
|
116 |
Fill in the metadata and public key that you've got from your Identity Provider then |
|
117 |
click Submit. |
|
118 |
Your Identity Provider is now configured in Larpe, you can then configure as many Service |
|
119 |
Providers as you want. |
|
120 |
|
|
121 |
Service Provider Configuration |
|
122 |
++++++++++++++++++++++++++++++ |
|
123 |
|
|
124 |
Service Provider configuration |
|
125 |
------------------------------ |
|
126 |
|
|
127 |
Click on "Hosts" then "New Host". |
|
128 |
|
|
129 |
Fill in the following parameters : |
|
130 |
|
|
131 |
* Label : the name you want to give to your Service Provider ; |
|
132 |
|
|
133 |
* Original Site Address : the root URL of your Service Provider ; |
|
134 |
|
|
135 |
* Authentication Page : if the page which contains the authentication form for |
|
136 |
your Service Provider is on a separate page, fill the url of this page here ; |
|
137 |
|
|
138 |
* Authentication Form Page : if you didn't fill the previous field and if the |
|
139 |
authentication form if not on the first page of your Service Provider either, |
|
140 |
fill the url of the page which contains the authentication form here ; |
|
141 |
|
|
142 |
* Logout Address : when you want Single Sign On and Identity Federation, you probably |
|
143 |
want Single Logout too. If so, fill the logout url of your original site here ; |
|
144 |
|
|
145 |
* Reversed Host Name : the domain name where you want to access your Service Provider |
|
146 |
through the reverse proxy. It can be the domain name of Larpe or not ; |
|
147 |
|
|
148 |
Then click "Submit". Wait a few seconds then go to http://reversed_host_name/reverse_directory/ |
|
149 |
to check if it works. If not, wait a bit more and try again. If it really doesn't work, |
|
150 |
please submit a bug report at http://labs.libre-entreprise.org/tracker/?func=add&group_id=108&atid=512 |
|
151 |
|
|
152 |
Service Provider Example: Linuxfr |
|
153 |
--------------------------------- |
|
154 |
|
|
155 |
To help you setup your own Service Provider, we provide an example of a working Service Provider |
|
156 |
to guide you. |
|
157 |
|
|
158 |
To setup Linuxfr, fill in the following parameters : |
|
159 |
|
|
160 |
* Label : Linuxfr ; |
|
161 |
|
|
162 |
* Original Site Address : http://linuxfr.org/ ; |
|
163 |
|
|
164 |
* Authentication Page : Nothing here ; |
|
165 |
|
|
166 |
* Authentication Form Page : http://linuxfr.org/pub/ ; |
|
167 |
|
|
168 |
* Logout Address : http://linuxfr.org/close_session.html ; |
|
169 |
|
|
170 |
* Reversed Host Name : linuxfr.reverse-proxy.example.com. |
|
171 |
|
|
172 |
With "reverse-proxy.example.com" being the hostname you've set up before for your reverse-proxy |
|
173 |
|
|
174 |
Don't forget to add this new hostname to your /etc/hosts as well. |
|
175 |
|
|
176 |
You can then go to the reversed Linuxfr at http://linuxfr.reverse-proxy.example.com/ |
|
177 |
|
|
178 |
Service Provider Liberty Alliance final setup |
|
179 |
--------------------------------------------- |
|
180 |
|
|
181 |
Now that you can access your Service Provider, you need a final step to use Liberty Alliance |
|
182 |
features. Click on "Hosts", the click on the "Edit" icon of the Service Provider you've |
|
183 |
just configured. Save the Service Provider Metadata (for ID-FF 1.2) and the Public Key |
|
184 |
(right click then "Save as"). Configure this Service Provider on your Identity Provider |
|
185 |
with these two files. |
|
186 |
|
|
187 |
Licenses |
|
188 |
======== |
|
189 |
|
|
190 |
Larpe, Authentic_, Candle_ and Lasso_ are released under the terms of the |
|
191 |
`GNU GPL license`_. |
|
192 |
|
|
193 |
.. _Lasso: http://lasso.entrouvert.org/ |
|
194 |
.. _`Liberty Alliance`: http://projectliberty.org/ |
|
195 |
.. _`GNU GPL License`: http://www.gnu.org/copyleft/gpl.html |
|
196 |
.. _Debian: http://www.debian.org/ |
|
197 |
.. _Apache2: http://httpd.apache.org/ |
|
198 |
.. _Quixote: http://www.mems-exchange.org/software/Quixote |
|
199 |
.. _mod_python: http://www.modpython.org/ |
|
200 |
.. _SCGI: http://www.mems-exchange.org/software/scgi/ |
|
201 |
.. _Candle: http://candle.labs.libre-entreprise.org/ |
|
202 |
.. _Authentic: http://www.entrouvert.com/fr/authentic/ |
larpe/tags/release-1.1.1/doc/scripts/removealpha.sh | ||
---|---|---|
1 |
#! /bin/sh |
|
2 |
|
|
3 |
size=$(identify $1 | cut -d ' ' -f 3) |
|
4 |
composite $1 -size $(identify $1 | cut -d ' ' -f3) xc:white $2 |
|
5 |
|
larpe/tags/release-1.1.1/doc/scripts/rst2latex.py | ||
---|---|---|
1 |
#! /usr/bin/python |
|
2 |
|
|
3 |
"""A minimal reST frontend, to create appropriate LaTeX files.""" |
|
4 |
|
|
5 |
try: |
|
6 |
import locale |
|
7 |
locale.setlocale(locale.LC_ALL, '') |
|
8 |
except: |
|
9 |
pass |
|
10 |
|
|
11 |
from docutils.core import publish_cmdline, Publisher |
|
12 |
|
|
13 |
def set_io(self, source_path=None, destination_path=None): |
|
14 |
Publisher.set_io_orig(self, source_path, destination_path='/dev/null') |
|
15 |
|
|
16 |
Publisher.set_io_orig, Publisher.set_io = Publisher.set_io, set_io |
|
17 |
|
|
18 |
output = publish_cmdline(writer_name='latex', |
|
19 |
settings_overrides = { |
|
20 |
'documentclass': 'report', |
|
21 |
'documentoptions': '11pt,a4paper,titlepage', |
|
22 |
'use_latex_toc': True, |
|
23 |
'use_latex_docinfo': True, |
|
24 |
'stylesheet': 'custom.tex'}) |
|
25 |
|
|
26 |
output = output.replace('\\includegraphics', |
|
27 |
'\\includegraphics[width=.9\\textwidth,height=15cm,clip,keepaspectratio]') |
|
28 |
output = output.replace('\\begin{figure}[htbp]', '\\begin{figure}[H]') |
|
29 |
print output |
larpe/tags/release-1.1.1/exclude_from_dist | ||
---|---|---|
1 |
.svn |
|
2 |
*.pyc |
|
3 |
*.pyo |
|
4 |
*.pye |
|
5 |
*.ptle |
|
6 |
*.swp |
|
7 |
debian.sarge |
|
8 |
make_debian_package.sh |
|
9 |
build |
|
10 |
dist |
|
11 |
tests |
|
12 |
larpe/filter |
larpe/tags/release-1.1.1/fedora/larpe-reload-apache2-script | ||
---|---|---|
1 |
#!/bin/sh |
|
2 |
# |
|
3 |
# The command "/etc/init.d/httpd reload" on Fedora actually _restarts_ Apache |
|
4 |
# We need to _reload_ it without closing existing connections |
|
5 |
|
|
6 |
APACHE2CTL=/usr/sbin/apachectl |
|
7 |
|
|
8 |
echo -n "Testing Apache config... " |
|
9 |
if ! $APACHE2CTL configtest > /dev/null 2>&1; then |
|
10 |
$APACHE2CTL configtest || true |
|
11 |
echo "[FAILED]" |
|
12 |
exit 1 |
|
13 |
else |
|
14 |
echo "[OK]" |
|
15 |
fi |
|
16 |
echo -n "Reloading Apache config... " |
|
17 |
if $APACHE2CTL graceful $2 ; then |
|
18 |
echo "[OK]" |
|
19 |
else |
|
20 |
echo "[FAILED]" |
|
21 |
fi |
|
22 |
|
larpe/tags/release-1.1.1/fedora/larpe.init | ||
---|---|---|
1 |
#! /bin/bash |
|
2 |
# |
|
3 |
# larpe Startup script for the Larpe reverse proxy |
|
4 |
# |
|
5 |
# description: Larpe is Liberty Alliance reverse proxy. It is used to add Liberty Alliance \ |
|
6 |
# features to some sites without modifying the sites themselves. |
|
7 |
# processname: larpe |
|
8 |
# config: /etc/httpd/conf.d/larpe.conf |
|
9 |
# config: /etc/larpe/apache2-vhost-larpe-common |
|
10 |
# config: /etc/sysconfig/larpe |
|
11 |
# pidfile: /var/run/larpe.pid |
|
12 |
# |
|
13 |
|
|
14 |
### BEGIN INIT INFO |
|
15 |
# Provides: larpe |
|
16 |
# Required-Start: $local_fs $network |
|
17 |
# Required-Stop: $local_fs $network |
|
18 |
# Default-Start: |
|
19 |
# Default-Stop: 0 1 2 3 4 5 6 |
|
20 |
# Short-Description: Start Larpe Liberty Alliance reverse proxy |
|
21 |
# Description: Start Larpe Liberty Alliance reverse proxy |
|
22 |
### END INIT INFO |
|
23 |
|
|
24 |
prog=larpe |
|
25 |
LARPECTL=/usr/sbin/larpectl |
|
26 |
PIDFILE=/var/run/larpe.pid |
|
27 |
|
|
28 |
# Source function library. |
|
29 |
. /etc/rc.d/init.d/functions |
|
30 |
|
|
31 |
# Source networking configuration. |
|
32 |
. /etc/sysconfig/network |
|
33 |
|
|
34 |
# Check that networking is up. |
|
35 |
[ ${NETWORKING} = "no" ] && exit 0 |
|
36 |
|
|
37 |
[ -x $LARPECTL ] || exit 5 |
|
38 |
|
|
39 |
# Read config file if it is present. |
|
40 |
if [ -f /etc/sysconfig/larpe ]; then |
|
41 |
. /etc/sysconfig/larpe |
|
42 |
fi |
|
43 |
|
|
44 |
RETVAL=0 |
|
45 |
|
|
46 |
# |
|
47 |
# Function that starts the daemon/service. |
|
48 |
# |
|
49 |
start() { |
|
50 |
echo -n $"Starting $prog: " |
|
51 |
$LARPECTL start & |
|
52 |
RETVAL=$? |
|
53 |
if [ $RETVAL -eq 0 ] |
|
54 |
then |
|
55 |
touch /var/lock/subsys/$prog |
|
56 |
fi |
|
57 |
echo |
|
58 |
return $RETVAL |
|
59 |
} |
|
60 |
|
|
61 |
# |
|
62 |
# Function that stops the daemon/service. |
|
63 |
# |
|
64 |
stop() { |
|
65 |
echo -n $"Stopping $prog: " |
|
66 |
killproc $LARPECTL |
|
67 |
RETVAL=$? |
|
68 |
if [ $RETVAL -eq 0 ] |
|
69 |
then |
|
70 |
rm -rf /var/lock/subsys/$prog |
|
71 |
fi |
|
72 |
echo |
|
73 |
return $RETVAL |
|
74 |
} |
|
75 |
|
|
76 |
# See how we were called. |
|
77 |
case "$1" in |
|
78 |
start) |
|
79 |
start |
|
80 |
;; |
|
81 |
stop) |
|
82 |
stop |
|
83 |
;; |
|
84 |
status) |
|
85 |
status $prog |
|
86 |
RETVAL=$? |
|
87 |
;; |
|
88 |
restart) |
|
89 |
stop |
|
90 |
start |
|
91 |
;; |
|
92 |
condrestart) |
|
93 |
if [ -f ${PIDFILE} ] ; then |
|
94 |
stop |
|
95 |
start |
|
96 |
fi |
|
97 |
;; |
|
98 |
*) |
|
99 |
echo $"Usage: $prog {start|stop|restart|condrestart|status}" |
|
100 |
exit 1 |
|
101 |
esac |
|
102 |
|
|
103 |
exit $RETVAL |
|
104 |
|
larpe/tags/release-1.1.1/fedora/larpe.spec | ||
---|---|---|
1 |
%{!?python_sitearch: %define python_sitearch %(%{__python} -c 'from distutils import sysconfig; print sysconfig.get_python_lib(1)')} |
|
2 |
# eval to 2.3 if python isn't yet present, workaround for no python in fc4 minimal buildroot |
|
3 |
%{!?python_version: %define python_version %(%{__python} -c 'import sys; print sys.version.split(" ")[0]' || echo "2.3")} |
|
4 |
%define apacheconfdir %{_sysconfdir}/httpd/conf.d |
|
5 |
|
|
6 |
Summary: Liberty Alliance Reverse Proxy |
|
7 |
Name: larpe |
|
8 |
Version: 0.2.9 |
|
9 |
Release: 2%{?dist} |
|
10 |
License: GPL |
|
11 |
Group: System Environment/Applications |
|
12 |
Url: http://larpe.labs.libre-entreprise.org/ |
|
13 |
Source0: http://labs.libre-entreprise.org/frs/download.php/591/%{name}-%{version}.tar.gz |
|
14 |
Buildroot: %{_tmppath}/%{name}-%{version}-%(id -u -n) |
|
15 |
BuildRequires: python >= 2.3, python-quixote >= 2.0 |
|
16 |
BuildRequires: gettext |
|
17 |
Requires: httpd >= 2.0, mod_scgi, mod_proxy_html |
|
18 |
Requires: lasso-python >= 0.6.3, python-quixote >= 2.0, python-scgi |
|
19 |
Requires: initscripts |
|
20 |
Requires(post): /sbin/chkconfig |
|
21 |
Requires(preun):/sbin/chkconfig |
|
22 |
Requires(preun): /sbin/service |
|
23 |
|
|
24 |
%description |
|
25 |
Larpe is a Liberty Alliance Reverse Proxy. It allows any service provider (that is a website) |
|
26 |
to use Liberty Alliance features (Identity federation, Single Sign On and Single Logout) without |
|
27 |
changing the code of the service provider itself. |
|
28 |
|
|
29 |
It uses the Lasso library which is certified by the Liberty Alliance consortium. |
|
30 |
|
|
31 |
It is a quixote application and is commonly runned inside Apache web server. |
|
32 |
|
|
33 |
%package doc |
|
34 |
Summary: Documentation files for %{name} development. |
|
35 |
Group: Documentation |
|
36 |
BuildRequires: python-docutils, tetex-latex |
|
37 |
|
|
38 |
%description doc |
|
39 |
This package contains development documentation for %{name}. |
|
40 |
|
|
41 |
%prep |
|
42 |
%setup -q |
|
43 |
|
|
44 |
# Change Apache vhost path in Larpe config |
|
45 |
sed -i s#"/var/log/apache2/larpe-access.log"#"logs/larpe_access_log combined\n TransferLog logs/larpe_access_log"# conf/apache2-vhost-larpe |
|
46 |
sed -i s#"/var/log/apache2/larpe-error.log"#"logs/larpe_error_log"# conf/apache2-vhost-larpe |
|
47 |
sed -i s#"APACHE_MAIN_VHOST.*$"#"APACHE_MAIN_VHOST='/etc/httpd/conf.d/larpe.conf'"# larpe/Defaults.py |
|
48 |
|
|
49 |
%build |
|
50 |
|
|
51 |
%install |
|
52 |
rm -rf %{buildroot} |
|
53 |
|
|
54 |
# install generic files |
|
55 |
make install prefix=%{_prefix} DESTDIR=%{buildroot} |
|
56 |
|
|
57 |
# install init script |
|
58 |
install -d %{buildroot}/%{_initrddir} |
|
59 |
install -p -m 0755 fedora/larpe.init %{buildroot}%{_initrddir}/larpe |
|
60 |
|
|
61 |
# apache configuration |
|
62 |
mkdir -p %{buildroot}%{apacheconfdir} |
|
63 |
install -p -m 644 conf/apache2-vhost-larpe %{buildroot}%{apacheconfdir}/larpe.conf |
|
64 |
|
|
65 |
# apache reload script |
|
66 |
install -p -m 0755 fedora/larpe-reload-apache2-script %{buildroot}%{_sbindir}/ |
|
67 |
|
|
68 |
# install doc files |
|
69 |
install -d -m 0755 %{buildroot}%{_datadir}/gtk-doc/html/larpe |
|
70 |
make -C doc DESTDIR=%{buildroot}%{_datadir}/gtk-doc/html/larpe |
|
71 |
|
|
72 |
%clean |
|
73 |
rm -fr %{buildroot} |
|
74 |
|
|
75 |
%post |
|
76 |
/sbin/chkconfig --add %{name} |
|
77 |
|
|
78 |
# manual post-installation |
|
79 |
cat <<_EOF_ |
|
80 |
You must edit first %{apacheconfdir}/larpe.conf |
|
81 |
|
|
82 |
You must enable Larpe with "chkconfig larpe on ; service larpe start" |
|
83 |
|
|
84 |
You must also restart Apache with "service httpd restart"! |
|
85 |
_EOF_ |
|
86 |
|
|
87 |
%preun |
|
88 |
if [ $1 = 0 ]; then |
|
89 |
/sbin/service %{name} stop > /dev/null 2>&1 |
|
90 |
/sbin/chkconfig --del %{name} |
|
91 |
fi |
|
92 |
|
|
93 |
%files |
|
94 |
%defattr(-,root,root,755) |
|
95 |
%config %{_initrddir}/larpe |
|
96 |
%config(noreplace) %{apacheconfdir}/larpe.conf |
|
97 |
%config(noreplace) %{_sysconfdir}/larpe/apache2-vhost-larpe-common |
|
98 |
%{_sbindir}/larpectl |
|
99 |
%{_sbindir}/larpe-reload-apache2 |
|
100 |
%{_sbindir}/larpe-reload-apache2-script |
|
101 |
%{python_sitearch}/%{name} |
|
102 |
%{_datadir}/%{name} |
|
103 |
%{_datadir}/locale/fr/LC_MESSAGES/larpe.mo |
|
104 |
/var/lib/larpe |
|
105 |
%defattr(644,root,root,755) |
|
106 |
%doc AUTHORS COPYING NEWS README |
|
107 |
|
|
108 |
%files doc |
|
109 |
%defattr(-,root,root) |
|
110 |
%doc %{_datadir}/gtk-doc/html/%{name} |
|
111 |
|
|
112 |
%changelog |
|
113 |
* Tue Mar 05 2009 Jean-Marc Liger <jmliger@siris.sorbonne.fr> 0.2.9-2 |
|
114 |
- Added missing BuildRequires gettext |
|
115 |
- Enabled larpe init script |
|
116 |
|
|
117 |
* Mon Jan 19 2009 Damien Laniel <dlaniel@entrouvert.com> 0.2.9-1 |
|
118 |
- Updated to 0.2.9 |
|
119 |
- Use Larpe Makefile to install generic files |
|
120 |
- Copy fedora specific files |
|
121 |
|
|
122 |
* Sat Jan 17 2009 Jean-Marc Liger <jmliger@siris.sorbonne.fr> 0.2.1-2 |
|
123 |
- Added missing BuildRequires tetex-latex for doc subpackage |
|
124 |
- Rebuilt on CentOS 4,5 |
|
125 |
|
|
126 |
* Wed Jan 14 2009 Jean-Marc Liger <jmliger@siris.sorbonne.fr> 0.2.1-1 |
|
127 |
- Updated to 0.2.1 |
|
128 |
- Added missing Requires lasso-python |
|
129 |
- Added missing Requires python-scgi |
|
130 |
- Rebuilt on CentOS 4,5 |
|
131 |
|
|
132 |
* Fri Mar 02 2007 Jean-Marc Liger <jmliger@siris.sorbonne.fr> 0.2.0-1 |
|
133 |
- Updated to 0.2.0 |
|
134 |
- Added BuildRequires python-quixote |
|
135 |
- Built on Fedora Core 3 / RHEL 4 and Fedora Core 6 / RHEL 5 |
|
136 |
|
|
137 |
* Wed Jan 24 2007 Jean-Marc Liger <jmliger@siris.sorbonne.fr> 0.1.0-1 |
|
138 |
- First 0.1.0 |
|
139 |
- Built on Fedora Core 3 / RHEL 4 and Fedora Core 6 / RHEL 5 |
larpe/tags/release-1.1.1/larpe-reload-apache2.c | ||
---|---|---|
1 |
/* |
|
2 |
Template for a setuid program that calls a script. |
|
3 |
|
|
4 |
The script should be in an unwritable directory and should itself |
|
5 |
be unwritable. In fact all parent directories up to the root |
|
6 |
should be unwritable. The script must not be setuid, that's what |
|
7 |
this program is for. |
|
8 |
|
|
9 |
This is a template program. You need to fill in the name of the |
|
10 |
script that must be executed. This is done by changing the |
|
11 |
definition of FULL_PATH below. |
|
12 |
|
|
13 |
There are also some rules that should be adhered to when writing |
|
14 |
the script itself. |
|
15 |
|
|
16 |
The first and most important rule is to never, ever trust that the |
|
17 |
user of the program will behave properly. Program defensively. |
|
18 |
Check your arguments for reasonableness. If the user is allowed to |
|
19 |
create files, check the names of the files. If the program depends |
|
20 |
on argv[0] for the action it should perform, check it. |
|
21 |
|
|
22 |
Assuming the script is a Bourne shell script, the first line of the |
|
23 |
script should be |
|
24 |
#!/bin/sh - |
|
25 |
The - is important, don't omit it. If you're using esh, the first |
|
26 |
line should be |
|
27 |
#!/usr/local/bin/esh -f |
|
28 |
and for ksh, the first line should be |
|
29 |
#!/usr/local/bin/ksh -p |
|
30 |
The script should then set the variable IFS to the string |
|
31 |
consisting of <space>, <tab>, and <newline>. After this (*not* |
|
32 |
before!), the PATH variable should be set to a reasonable value and |
|
33 |
exported. Do not expect the PATH to have a reasonable value, so do |
|
34 |
not trust the old value of PATH. You should then set the umask of |
|
35 |
the program by calling |
|
36 |
umask 077 # or 022 if you want the files to be readable |
|
37 |
If you plan to change directories, you should either unset CDPATH |
|
38 |
or set it to a good value. Setting CDPATH to just ``.'' (dot) is a |
|
39 |
good idea. |
|
40 |
If, for some reason, you want to use csh, the first line should be |
|
41 |
#!/bin/csh -fb |
|
42 |
You should then set the path variable to something reasonable, |
|
43 |
without trusting the inherited path. Here too, you should set the |
|
44 |
umask using the command |
|
45 |
umask 077 # or 022 if you want the files to be readable |
|
46 |
*/ |
|
47 |
|
|
48 |
#include <unistd.h> |
|
49 |
#include <stdlib.h> |
|
50 |
#include <stdio.h> |
|
51 |
#include <sys/types.h> |
|
52 |
#include <sys/stat.h> |
|
53 |
#include <string.h> |
|
54 |
|
|
55 |
/* CONFIGURATION SECTION */ |
|
56 |
|
|
57 |
#ifndef FULL_PATH/* so that this can be specified from the Makefile */ |
|
58 |
#define FULL_PATH "/usr/sbin/larpe-reload-apache2-script" |
|
59 |
#endif |
|
60 |
#ifndef UMASK |
|
61 |
#define UMASK 077 |
|
62 |
#endif |
|
63 |
|
|
64 |
/* END OF CONFIGURATION SECTION */ |
|
65 |
|
|
66 |
#if defined(__STDC__) && defined(__sgi) |
|
67 |
#define environ _environ |
|
68 |
#endif |
|
69 |
|
|
70 |
/* don't change def_IFS */ |
|
71 |
char def_IFS[] = "IFS= \t\n"; |
|
72 |
/* you may want to change def_PATH, but you should really change it in */ |
|
73 |
/* your script */ |
|
74 |
#ifdef __sgi |
|
75 |
char def_PATH[] = "PATH=/usr/bsd:/usr/bin:/bin:/usr/local/bin:/usr/sbin"; |
|
76 |
#else |
|
77 |
char def_PATH[] = "PATH=/usr/ucb:/usr/bin:/bin:/usr/local/bin"; |
|
78 |
#endif |
|
79 |
/* don't change def_CDPATH */ |
|
80 |
char def_CDPATH[] = "CDPATH=."; |
|
81 |
/* don't change def_ENV */ |
|
82 |
char def_ENV[] = "ENV=:"; |
|
83 |
|
|
84 |
/* |
|
85 |
This function changes all environment variables that start with LD_ |
|
86 |
into variables that start with XD_. This is important since we |
|
87 |
don't want the script that is executed to use any funny shared |
|
88 |
libraries. |
|
89 |
|
|
90 |
The other changes to the environment are, strictly speaking, not |
|
91 |
needed here. They can safely be done in the script. They are done |
|
92 |
here because we don't trust the script writer (just like the script |
|
93 |
writer shouldn't trust the user of the script). |
|
94 |
If IFS is set in the environment, set it to space,tab,newline. |
|
95 |
If CDPATH is set in the environment, set it to ``.''. |
|
96 |
Set PATH to a reasonable default. |
|
97 |
*/ |
|
98 |
void |
|
99 |
clean_environ(void) |
|
100 |
{ |
|
101 |
char **p; |
|
102 |
extern char **environ; |
|
103 |
|
|
104 |
for (p = environ; *p; p++) { |
|
105 |
if (strncmp(*p, "LD_", 3) == 0) |
|
106 |
**p = 'X'; |
|
107 |
else if (strncmp(*p, "_RLD", 4) == 0) |
|
108 |
**p = 'X'; |
|
109 |
else if (strncmp(*p, "PYTHON", 6) == 0) |
|
110 |
**p = 'X'; |
|
111 |
else if (strncmp(*p, "IFS=", 4) == 0) |
|
112 |
*p = def_IFS; |
|
113 |
else if (strncmp(*p, "CDPATH=", 7) == 0) |
|
114 |
*p = def_CDPATH; |
|
115 |
else if (strncmp(*p, "ENV=", 4) == 0) |
|
116 |
*p = def_ENV; |
|
117 |
} |
|
118 |
putenv(def_PATH); |
|
119 |
} |
|
120 |
|
|
121 |
int |
|
122 |
main(int argc, char **argv) |
|
123 |
{ |
|
124 |
struct stat statb; |
|
125 |
gid_t egid = getegid(); |
|
126 |
uid_t euid = geteuid(); |
|
127 |
|
|
128 |
/* |
|
129 |
Sanity check #1. |
|
130 |
This check should be made compile-time, but that's not possible. |
|
131 |
If you're sure that you specified a full path name for FULL_PATH, |
|
132 |
you can omit this check. |
|
133 |
*/ |
|
134 |
if (FULL_PATH[0] != '/') { |
|
135 |
fprintf(stderr, "%s: %s is not a full path name\n", argv[0], |
|
136 |
FULL_PATH); |
|
137 |
fprintf(stderr, "You can only use this wrapper if you\n"); |
|
138 |
fprintf(stderr, "compile it with an absolute path.\n"); |
|
139 |
exit(1); |
|
140 |
} |
|
141 |
|
|
142 |
/* |
|
143 |
Sanity check #2. |
|
144 |
Check that the owner of the script is equal to either the |
|
145 |
effective uid or the super user. |
|
146 |
*/ |
|
147 |
if (stat(FULL_PATH, &statb) < 0) { |
|
148 |
perror("stat"); |
|
149 |
exit(1); |
|
150 |
} |
|
151 |
if (statb.st_uid != 0 && statb.st_uid != euid) { |
|
152 |
fprintf(stderr, "%s: %s has the wrong owner\n", argv[0], |
|
153 |
FULL_PATH); |
|
154 |
fprintf(stderr, "The script should be owned by root,\n"); |
|
155 |
fprintf(stderr, "and shouldn't be writeable by anyone.\n"); |
|
156 |
exit(1); |
|
157 |
} |
|
158 |
|
|
159 |
if (setregid(egid, egid) < 0) |
|
160 |
perror("setregid"); |
|
161 |
if (setreuid(euid, euid) < 0) |
|
162 |
perror("setreuid"); |
|
163 |
|
|
164 |
clean_environ(); |
|
165 |
|
|
166 |
umask(UMASK); |
|
167 |
|
|
168 |
while (**argv == '-')/* don't let argv[0] start with '-' */ |
|
169 |
(*argv)++; |
|
170 |
execv(FULL_PATH, argv); |
|
171 |
fprintf(stderr, "%s: could not execute the script\n", argv[0]); |
|
172 |
exit(1); |
|
173 |
} |
larpe/tags/release-1.1.1/larpe/Defaults.py | ||
---|---|---|
1 |
'''Default global variables''' |
|
2 |
|
|
3 |
APP_DIR = '/var/lib/larpe' |
|
4 |
DATA_DIR = '/usr/share/larpe' |
|
5 |
ERROR_LOG = None #'/var/log/larpe.log' |
|
6 |
WEB_ROOT = 'larpe' |
|
7 |
APACHE_MAIN_VHOST = '/etc/apache2/sites-available/apache2-vhost-larpe' |
|
8 |
APACHE_VHOST_COMMON = '/etc/larpe/apache2-vhost-larpe-common' |
|
9 |
APACHE_RELOAD = '/usr/sbin/larpe-reload-apache2' |
larpe/tags/release-1.1.1/larpe/__init__.py | ||
---|---|---|
1 |
'''Setup path and load Lasso library''' |
|
2 |
try: |
|
3 |
from quixote.ptl import compile_package |
|
4 |
compile_package(__path__) |
|
5 |
except ImportError: |
|
6 |
pass |
|
7 |
|
|
8 |
import sys |
|
9 |
import os |
|
10 |
sys.path.insert(0, os.path.dirname(__file__)) |
|
11 |
|
|
12 |
import qommon |
|
13 |
|
|
14 |
try: |
|
15 |
import lasso |
|
16 |
except ImportError: |
|
17 |
lasso = None |
|
18 |
|
|
19 |
if lasso and not hasattr(lasso, 'SAML2_SUPPORT'): |
|
20 |
lasso.SAML2_SUPPORT = False |
|
21 |
|
larpe/tags/release-1.1.1/larpe/admin/__init__.py | ||
---|---|---|
1 |
try: |
|
2 |
from quixote.ptl import compile_package |
|
3 |
compile_package(__path__) |
|
4 |
except ImportError: |
|
5 |
pass |
|
6 |
from root import RootDirectory |
larpe/tags/release-1.1.1/larpe/admin/apache.py | ||
---|---|---|
1 |
import os |
|
2 |
import re |
|
3 |
import urllib |
|
4 |
import base64 |
|
5 |
|
|
6 |
from quixote import get_publisher, get_request |
|
7 |
|
|
8 |
from qommon import get_cfg |
|
9 |
|
|
10 |
from larpe.hosts import Host |
|
11 |
from larpe.Defaults import APP_DIR, APACHE_MAIN_VHOST, APACHE_VHOST_COMMON, APACHE_RELOAD |
|
12 |
|
|
13 |
def write_apache2_vhosts(): |
|
14 |
hosts = Host.select(lambda x: x.name != 'larpe') |
|
15 |
hosts.sort() |
|
16 |
vhosts_dir = os.path.join(APP_DIR, 'vhosts.d') |
|
17 |
vhost_locations_dir = os.path.join(APP_DIR, 'vhost-locations.d') |
|
18 |
vhosts_dir_disabled = os.path.join(APP_DIR, 'vhosts.d.disabled') |
|
19 |
vhost_locations_dir_disabled = os.path.join(APP_DIR, 'vhost-locations.d.disabled') |
|
20 |
vhost_file_name = get_request().get_server().split(':')[0] |
|
21 |
vhost_file = None |
|
22 |
reversed_hostname = '' |
|
23 |
vhost = None |
|
24 |
|
|
25 |
if get_publisher().cfg.get(str('allow_config_generation'), True): |
|
26 |
vhost_file = open(os.path.join(vhosts_dir, vhost_file_name), 'w') |
|
27 |
locations_file = open(os.path.join(vhost_locations_dir, vhost_file_name), 'w') |
|
28 |
else: |
|
29 |
vhost_file = open(os.path.join(vhosts_dir_disabled, vhost_file_name), 'w') |
|
30 |
locations_file = open(os.path.join(vhost_locations_dir_disabled, vhost_file_name), 'w') |
|
31 |
try: |
|
32 |
main_vhost = open(APACHE_MAIN_VHOST, 'r') |
|
33 |
file_content = main_vhost.read() |
|
34 |
regexp = re.compile('<VirtualHost (.*?)>') |
|
35 |
vhost_ip = regexp.findall(file_content)[0] |
|
36 |
except (IOError, IndexError): |
|
37 |
vhost_ip = '*' |
|
38 |
|
|
39 |
for host in hosts: |
|
40 |
if host.orig_site is None: |
|
41 |
# This site hasn't been fully configured |
|
42 |
continue |
|
43 |
if host.reversed_hostname != reversed_hostname \ |
|
44 |
and host.reversed_hostname != get_cfg('proxy_hostname'): |
|
45 |
if vhost is not None: |
|
46 |
vhost.close() |
|
47 |
vhost = Vhost(host, vhost_ip) |
|
48 |
vhost.write(vhost_file) |
|
49 |
reversed_hostname = host.reversed_hostname |
|
50 |
|
|
51 |
if host.reversed_hostname == get_cfg('proxy_hostname'): |
|
52 |
conf_file = locations_file |
|
53 |
else: |
|
54 |
conf_file = vhost_file |
|
55 |
|
|
56 |
Location(host).write(conf_file) |
|
57 |
|
|
58 |
if vhost_file is not None: |
|
59 |
if vhost is not None: |
|
60 |
vhost.close() |
|
61 |
vhost_file.close() |
|
62 |
if locations_file is not None: |
|
63 |
locations_file.close() |
|
64 |
|
|
65 |
if get_publisher().cfg.get(str('allow_config_generation'), True): |
|
66 |
os.system(APACHE_RELOAD) |
|
67 |
|
|
68 |
|
|
69 |
class Vhost(object): |
|
70 |
def __init__(self, host, main_ip_port): |
|
71 |
self.host = host |
|
72 |
self.main_ip_port = main_ip_port |
|
73 |
self.conf_file = None |
|
74 |
|
|
75 |
def get_ip_port(self): |
|
76 |
if self.host.scheme == 'https': |
|
77 |
return self.main_ip_port.replace(':80', ':443') |
|
78 |
else: |
|
79 |
return self.main_ip_port.replace(':443', ':80') |
|
80 |
ip_port = property(get_ip_port) |
|
81 |
|
|
82 |
def get_proxy_url(self): |
|
83 |
if get_cfg('proxy', {}).get('enabled') and self.host.use_proxy == True: |
|
84 |
return 'http://%(ip)s:%(port)s' % get_cfg('proxy', {}) |
|
85 |
return None |
|
86 |
proxy_url = property(get_proxy_url) |
|
87 |
|
|
88 |
def get_proxy_auth(self): |
|
89 |
if self.get_proxy_url() and get_cfg('proxy', {}).get('user'): |
|
90 |
credentials = base64.encodestring( |
|
91 |
'%(user)s:%(password)s' % get_cfg('proxy', {}))[:-1] |
|
92 |
return '"Basic %s"' % credentials |
|
93 |
return None |
|
94 |
proxy_auth = property(get_proxy_auth) |
|
95 |
|
|
96 |
def get_cfg(self): |
|
97 |
return { 'ip_port': self.ip_port, |
|
98 |
'reversed_hostname': self.host.reversed_hostname, |
|
99 |
'proxy_url': self.proxy_url, |
|
100 |
'proxy_auth': self.proxy_auth } |
|
101 |
cfg = property(get_cfg) |
|
102 |
|
|
103 |
def write(self, conf_file): |
|
104 |
self.conf_file = conf_file |
|
105 |
conf_lines = [] |
|
106 |
# Start Virtual Host |
|
107 |
conf_lines.append('<VirtualHost %(ip_port)s>' % self.cfg) |
|
108 |
# Server name and administrator |
|
109 |
conf_lines.append('ServerName %(reversed_hostname)s' % self.cfg) |
|
110 |
conf_lines.append('# ServerAdmin root@localhost\n') |
|
111 |
# Include common vhost configuration |
|
112 |
conf_lines.append('include %s\n' % APACHE_VHOST_COMMON) |
|
113 |
# SSL |
|
114 |
if self.host.scheme == 'https': |
|
115 |
conf_lines.append('SSLEngine On\n') |
|
116 |
if self.host.orig_site.startswith('https'): |
|
117 |
conf_lines.append('SSLProxyEngine On\n') |
|
118 |
# Remote proxy configuration |
|
119 |
if self.proxy_url is not None: |
|
120 |
conf_lines.append('ProxyRemote * %(proxy_url)s' % self.cfg) |
|
121 |
if self.proxy_auth is not None: |
|
122 |
conf_lines.append( |
|
123 |
'RequestHeader set Proxy-Authorization %(proxy_auth)s\n' % self.cfg) |
|
124 |
# Write it all |
|
125 |
conf_file.write('\n\t'.join(conf_lines)) |
|
126 |
|
|
127 |
def close(self): |
|
128 |
if self.conf_file: |
|
129 |
self.conf_file.write('</VirtualHost>\n\n') |
|
130 |
|
|
131 |
|
|
132 |
def apache_escape_chars(url): |
|
133 |
special_characters = ('\\', '.', '?', '*', '+', '^', '$', '|', '(', ')', '[', ']') |
|
134 |
for char in special_characters: |
|
135 |
url = url.replace(char, '\%s' % char) |
|
136 |
return url |
|
137 |
|
|
138 |
class Location(object): |
|
139 |
def __init__(self, host): |
|
140 |
self.host = host |
|
141 |
|
|
142 |
def get_reversed_directory(self): |
|
143 |
if not self.host.reversed_directory: |
|
144 |
return '%s/' % get_request().environ['SCRIPT_NAME'] |
|
145 |
else: |
|
146 |
return '%s/%s/' % (get_request().environ['SCRIPT_NAME'], self.host.reversed_directory) |
|
147 |
reversed_directory = property(get_reversed_directory) |
|
148 |
|
|
149 |
def get_python_path(self): |
|
150 |
if self.host.apache_output_python_filters and \ |
|
151 |
self.host.apache_python_paths: |
|
152 |
python_path = 'PythonPath "sys.path' |
|
153 |
for path in self.host.apache_python_paths: |
|
154 |
python_path += "+['%s']" % path |
|
155 |
python_path += '"' |
|
156 |
return python_path |
|
157 |
else: |
|
158 |
return None |
|
159 |
python_path = property(get_python_path) |
|
160 |
|
|
161 |
def get_output_filters(self): |
|
162 |
python_filters = '' |
|
163 |
output_filters = [] |
|
164 |
if self.host.apache_output_python_filters: |
|
165 |
i = 0 |
|
166 |
for filter_file in self.host.apache_output_python_filters: |
|
167 |
filter_name = 'filter%d' % i |
|
168 |
python_filters += 'PythonOutputFilter %s %s\n\t\t' % (filter_file, filter_name) |
|
169 |
output_filters.append(filter_name) |
|
170 |
i += 1 |
|
171 |
if self.host.apache_output_filters: |
|
172 |
for output_filter in self.host.apache_output_filters: |
|
173 |
output_filters.append(output_filter) |
|
174 |
if output_filters: |
|
175 |
return python_filters + 'SetOutputFilter ' + ';'.join(output_filters) |
|
176 |
else: |
|
177 |
return None |
|
178 |
output_filters = property(get_output_filters) |
|
179 |
|
|
180 |
def get_old_auth_url(self): |
|
181 |
old_auth_url = None |
|
182 |
if self.host.initiate_sso_url: |
|
183 |
old_auth_url = self.host.initiate_sso_url |
|
184 |
elif self.host.auth_url is not None: |
|
185 |
if self.host.auth_url.startswith('http://'): |
|
186 |
chars_to_skip = 5 |
|
187 |
else: |
|
188 |
chars_to_skip = 6 |
|
189 |
regexp = re.compile(self.host.orig_site[chars_to_skip:]) |
|
190 |
old_auth_url_short = regexp.sub('', self.host.auth_url[chars_to_skip:]) |
|
191 |
if old_auth_url_short.startswith('/'): |
|
192 |
old_auth_url = old_auth_url_short |
|
193 |
else: |
|
194 |
old_auth_url = '/' + old_auth_url_short |
|
195 |
if old_auth_url: |
|
196 |
old_auth_url = apache_escape_chars(old_auth_url) |
|
197 |
return old_auth_url |
|
198 |
old_auth_url = property(get_old_auth_url) |
|
199 |
|
|
200 |
def get_new_auth_url(self): |
|
201 |
if not hasattr(self.host, 'base_url'): |
|
202 |
return None |
|
203 |
base_url_tokens = self.host.base_url.split('/') |
|
204 |
base_url_tokens[-1] = 'login' |
|
205 |
return '/'.join(base_url_tokens) |
|
206 |
new_auth_url = property(get_new_auth_url) |
|
207 |
|
|
208 |
def get_old_logout_url(self): |
|
209 |
old_logout_url = None |
|
210 |
if self.host.logout_url is not None: |
|
211 |
if self.host.logout_url.startswith('http://'): |
|
212 |
chars_to_skip = 5 |
|
213 |
else: |
|
214 |
chars_to_skip = 6 |
|
215 |
regexp = re.compile(self.host.orig_site[chars_to_skip:]) |
|
216 |
old_logout_url_short = regexp.sub('', self.host.logout_url[chars_to_skip:]) |
|
217 |
if old_logout_url_short.startswith('/'): |
|
218 |
old_logout_url = old_logout_url_short |
|
219 |
else: |
|
220 |
old_logout_url = '/' + old_logout_url_short |
|
221 |
old_logout_url = apache_escape_chars(old_logout_url) |
|
222 |
return old_logout_url |
|
223 |
old_logout_url = property(get_old_logout_url) |
|
224 |
|
|
225 |
def get_new_logout_url(self): |
|
226 |
if not hasattr(self.host, 'base_url'): |
|
227 |
return None |
|
228 |
base_url_tokens = self.host.base_url.split('/') |
|
229 |
base_url_tokens[-1] = 'logout' |
|
230 |
return '/'.join(base_url_tokens) |
|
231 |
new_logout_url = property(get_new_logout_url) |
|
232 |
|
|
233 |
def get_orig_site_url_and_dir(self): |
|
234 |
# Split url |
|
235 |
if self.host.orig_site.startswith('http://'): |
|
236 |
orig_host, orig_query = urllib.splithost(self.host.orig_site[5:]) |
|
237 |
else: |
|
238 |
orig_host, orig_query = urllib.splithost(self.host.orig_site[6:]) |
|
239 |
# Add a trailing slash if necessary |
|
240 |
if self.host.orig_site.endswith('/'): |
|
241 |
orig_url = self.host.orig_site |
|
242 |
orig_dir = orig_query |
|
243 |
else: |
|
244 |
orig_url = self.host.orig_site + '/' |
|
245 |
orig_dir = orig_query + '/' |
|
246 |
return orig_url, orig_dir |
|
247 |
|
|
248 |
def get_orig_url(self): |
|
249 |
orig_url, orig_dir = self.get_orig_site_url_and_dir() |
|
250 |
return orig_url |
|
251 |
orig_url = property(get_orig_url) |
|
252 |
|
|
253 |
def get_orig_dir(self): |
|
254 |
orig_url, orig_dir = self.get_orig_site_url_and_dir() |
|
255 |
return orig_dir |
|
256 |
orig_dir = property(get_orig_dir) |
|
257 |
|
|
258 |
def get_cfg(self): |
|
259 |
return { 'reversed_directory': self.reversed_directory, |
|
260 |
'old_auth_url': self.old_auth_url, |
|
261 |
'new_auth_url': self.new_auth_url, |
|
262 |
'old_logout_url': self.old_logout_url, |
|
263 |
'new_logout_url': self.new_logout_url, |
|
264 |
'orig_url': self.orig_url, |
|
265 |
'orig_dir': self.orig_dir } |
|
266 |
cfg = property(get_cfg) |
|
267 |
|
|
268 |
def write(self, conf_file): |
|
269 |
conf_lines = [] |
|
270 |
# Start Location |
|
271 |
conf_lines.append('\n\t<Location %(reversed_directory)s>' % self.cfg) |
|
272 |
# No user restriction |
|
273 |
conf_lines.append('Allow from all') |
|
274 |
# Apache output filters |
|
275 |
if self.python_path: |
|
276 |
conf_lines.append(self.python_path) |
|
277 |
if self.output_filters: |
|
278 |
conf_lines.append(self.output_filters) |
|
279 |
# Redirect rules |
|
280 |
# Redirect old authentication url to the new one |
|
281 |
if self.old_auth_url is not None and self.host.auth_form_places == 'form_once': |
|
282 |
conf_lines.append( |
|
283 |
'RedirectMatch %(old_auth_url)s %(new_auth_url)s' % self.cfg) |
|
284 |
# Redirect old logout url to the new one |
|
285 |
if self.old_logout_url is not None: |
|
286 |
conf_lines.append( |
|
287 |
'RedirectMatch %(old_logout_url)s %(new_logout_url)s' % self.cfg) |
|
288 |
# Redirect the home page to the login page |
|
289 |
if self.host.redirect_root_to_login is True: |
|
290 |
conf_lines.append('RedirectMatch ^/$ %(new_auth_url)s' % self.cfg) |
|
291 |
# Convert urls in http headers to/from the new domain |
|
292 |
conf_lines.append('ProxyPass %(orig_url)s' % self.cfg) |
|
293 |
conf_lines.append('ProxyPassReverse %(orig_url)s' % self.cfg) |
|
294 |
# Convert urls in html pages to/from the new domain |
|
295 |
conf_lines.append('ProxyHTMLURLMap %(orig_dir)s %(reversed_directory)s' % self.cfg) |
|
296 |
conf_lines.append('ProxyHTMLURLMap %(orig_url)s %(reversed_directory)s' % self.cfg) |
|
297 |
# Write it all and close the Location |
|
298 |
conf_file.write('\n\t\t'.join(conf_lines)) |
|
299 |
conf_file.write('\n\t</Location>\n') |
|
300 |
|
larpe/tags/release-1.1.1/larpe/admin/fields_prefill.ptl | ||
---|---|---|
1 |
from quixote import get_response, redirect |
|
2 |
from quixote.directory import Directory |
|
3 |
|
|
4 |
from qommon.form import * |
|
5 |
from qommon.admin.menu import html_top, command_icon |
|
6 |
|
|
7 |
from field_prefill import FieldPrefill |
|
8 |
|
|
9 |
class FieldUI: |
|
10 |
def __init__(self, field_prefill): |
|
11 |
self.field_prefill = field_prefill |
|
12 |
|
|
13 |
def form_edit(self): |
|
14 |
form = Form(enctype='multipart/form-data') |
|
15 |
form.add(StringWidget, 'name', title = _('Field name'), required = True, |
|
16 |
size = 50, value = self.field_prefill.name) |
|
17 |
form.add(StringWidget, 'xpath', title = _('Xpath of the attribute'), required = True, |
|
18 |
size = 50, value = self.field_prefill.xpath, hint=_('Example: /pp:PP/pp:InformalName')) |
|
19 |
form.add(IntWidget, 'number', title = _('Number of the field in the data'), required = True, |
|
20 |
size = 3, value = self.field_prefill.number, |
|
21 |
hint=_('Change it if there are multiple fields corresponding to the same Xpath and you want to get another than the first one')) |
|
22 |
form.add(CheckboxWidget, 'raw_xml', title=_('Get raw XML value'), |
|
23 |
value = self.field_prefill.raw_xml) |
|
24 |
form.add(StringWidget, 'regexp_match', title = _('Python regexp of a string to match'), |
|
25 |
size = 50, value = self.field_prefill.regexp_match) |
|
26 |
form.add(StringWidget, 'regexp_replacing', title = _('Python regexp of the replacing string'), |
|
27 |
size = 50, value = self.field_prefill.regexp_replacing) |
|
28 |
form.add(WidgetDict, 'select_options', title = _('Options mapping for a select field'), |
|
29 |
value = self.field_prefill.select_options, add_element_label = _('Add item')) |
|
30 |
form.add_submit('submit', _('Submit')) |
|
31 |
form.add_submit('cancel', _('Cancel')) |
|
32 |
return form |
|
33 |
|
|
34 |
def submit_edit(self, form): |
|
35 |
for f in ('name', 'xpath', 'number', 'raw_xml', 'regexp_match', 'regexp_replacing', 'select_options'): |
|
36 |
widget = form.get_widget(f) |
|
37 |
setattr(self.field_prefill, f, widget.parse()) |
|
38 |
self.field_prefill.store() |
|
39 |
|
|
40 |
class FieldPage(Directory): |
|
41 |
_q_exports = ['', 'delete'] |
|
42 |
|
|
43 |
def __init__(self, field_id): |
|
44 |
self.field_prefill = FieldPrefill.get(field_id) |
|
45 |
self.field_ui = FieldUI(self.field_prefill) |
|
46 |
get_response().breadcrumb.append((field_id + '/', field_id)) |
|
47 |
|
|
48 |
def _q_index [html] (self): |
|
49 |
form = self.field_ui.form_edit() |
|
50 |
redo = False |
|
51 |
|
|
52 |
if form.get_widget('cancel').parse(): |
|
53 |
return redirect('..') |
|
54 |
|
|
55 |
if form.get_widget('select_options') and form.get_widget('select_options').get_widget('add_element').parse(): |
|
56 |
form.clear_errors() |
|
57 |
redo = True |
|
58 |
|
|
59 |
if redo is False and form.is_submitted() and not form.has_errors(): |
|
60 |
self.field_ui.submit_edit(form) |
|
61 |
return redirect('..') |
|
62 |
|
|
63 |
get_response().breadcrumb.append( ('edit', _('Edit')) ) |
|
64 |
html_top('edit', title = _('Edit')) |
|
65 |
'<h2>%s</h2>' % _('Edit') |
|
66 |
|
|
67 |
form.render() |
|
68 |
|
|
69 |
def delete [html] (self): |
|
70 |
form = Form(enctype='multipart/form-data') |
|
71 |
form.widgets.append(HtmlWidget('<p>%s</p>' % _( |
|
72 |
'You are about to irrevocably delete this field.'))) |
|
73 |
form.add_submit('submit', _('Submit')) |
|
74 |
form.add_submit('cancel', _('Cancel')) |
|
75 |
if form.get_widget('cancel').parse(): |
|
76 |
return redirect('..') |
|
77 |
if not form.is_submitted() or form.has_errors(): |
|
78 |
get_response().breadcrumb.append(('delete', _('Delete'))) |
|
79 |
html_top('delete_form', title = _('Delete Field')) |
|
80 |
'<h2>%s : %s</h2>' % (_('Delete Field'), self.field_prefill.id) |
|
81 |
form.render() |
|
82 |
else: |
|
83 |
self.field_prefill.remove_self() |
|
84 |
return redirect('..') |
|
85 |
|
|
86 |
|
|
87 |
class FieldsDirectory(Directory): |
|
88 |
_q_exports = ['', 'new'] |
|
89 |
|
|
90 |
def __init__(self, form_prefill): |
|
91 |
get_response().breadcrumb.append(('fields/', _('Fields'))) |
|
92 |
self.form_prefill = form_prefill |
|
93 |
|
|
94 |
def _q_lookup(self, component): |
|
95 |
return FieldPage(component) |
|
96 |
|
|
97 |
def _q_index [html] (self): |
|
98 |
html_top('fields', title = _('Fields')) |
|
99 |
"""<ul id="nav-fields-admin"> |
|
100 |
<li><a href="new">%s</a></li> |
|
101 |
</ul>""" % _('New Field') |
|
102 |
|
|
103 |
'<ul class="biglist">' |
|
104 |
|
|
105 |
for field_prefill in FieldPrefill.select(lambda x: x.form_id == self.form_prefill.id): |
|
106 |
if not field_prefill.name: |
|
107 |
continue |
|
108 |
|
|
109 |
# Split too long xpath |
|
110 |
xpath = field_prefill.xpath |
|
111 |
xpath_tokens = xpath.split(str('/')) |
|
112 |
if len(xpath_tokens) > 3: |
|
113 |
xpath = str('.../') + str('/').join(xpath_tokens[-3:]) |
|
114 |
|
|
115 |
'<li>' |
|
116 |
'<strong class="label">%s</strong>' % field_prefill.name |
|
117 |
'<br />%s' % xpath |
|
118 |
'<p class="commands">' |
|
119 |
command_icon('%s/' % field_prefill.id, 'edit') |
|
120 |
command_icon('%s/delete' % field_prefill.id, 'remove') |
|
121 |
'</p></li>' |
|
122 |
'</ul>' |
|
123 |
|
|
124 |
def new [html] (self): |
|
125 |
get_response().breadcrumb.append(('new', _('New')) ) |
|
126 |
field_prefill = FieldPrefill() |
|
127 |
field_prefill.form_id = self.form_prefill.id |
|
128 |
field_prefill.store() |
|
129 |
return redirect('%s/' % field_prefill.id) |
|
130 |
|
larpe/tags/release-1.1.1/larpe/admin/forms_prefill.ptl | ||
---|---|---|
1 |
from quixote import get_response, redirect |
|
2 |
from quixote.directory import Directory |
|
3 |
|
|
4 |
from qommon.form import * |
|
5 |
from qommon.admin.menu import html_top, command_icon |
|
6 |
|
|
7 |
from form_prefill import FormPrefill |
|
8 |
from fields_prefill import FieldsDirectory |
|
9 |
|
|
10 |
class FormUI: |
|
11 |
def __init__(self, form_prefill): |
|
12 |
self.form_prefill = form_prefill |
|
13 |
|
|
14 |
def form_edit(self): |
|
15 |
form = Form(enctype='multipart/form-data') |
|
16 |
form.add(StringWidget, 'name', title = _('Form name'), required = True, |
|
17 |
size = 50, value = self.form_prefill.name, hint=_('Only used for display')) |
|
18 |
form.add(UrlWidget, 'url', title = _('Form address'), required = True, |
|
19 |
size = 50, value = self.form_prefill.url) |
|
20 |
form.add(StringWidget, 'profile', title = _('ID-WSF data profile'), required = True, |
|
21 |
size = 50, value = self.form_prefill.profile, hint=_('Example: urn:liberty:id-sis-pp:2005-05')) |
|
22 |
form.add(StringWidget, 'prefix', title = _('ID-WSF data XML prefix'), required = True, |
|
23 |
size = 50, value = self.form_prefill.prefix, hint=_('Example: pp')) |
|
24 |
form.add_submit('submit', _('Submit')) |
|
25 |
form.add_submit('cancel', _('Cancel')) |
|
26 |
return form |
|
27 |
|
|
28 |
def submit_edit(self, form): |
|
29 |
for f in ('name', 'url', 'profile', 'prefix'): |
|
30 |
widget = form.get_widget(f) |
|
31 |
setattr(self.form_prefill, f, widget.parse()) |
|
32 |
self.form_prefill.store() |
|
33 |
|
|
34 |
class FormPage(Directory): |
|
35 |
_q_exports = ['', 'edit', 'delete'] |
|
36 |
|
|
37 |
def __init__(self, form_id): |
|
38 |
self.form_prefill = FormPrefill.get(form_id) |
|
39 |
self.form_ui = FormUI(self.form_prefill) |
|
40 |
get_response().breadcrumb.append((form_id + '/', form_id)) |
|
41 |
|
|
42 |
def _q_index [html] (self): |
|
43 |
html_top('forms_prefill', title = 'Form prefilling') |
|
44 |
|
|
45 |
'<h2>%s</h2>' % _('Form prefilling configuration') |
|
46 |
'<dl>' |
|
47 |
'<dt><a href="edit">%s</a></dt> <dd>%s</dd>' % ( |
|
48 |
_('Edit'), _('Configure this form')) |
|
49 |
'<dt><a href="fields/">%s</a></dt> <dd>%s</dd>' % ( |
|
50 |
_('Fields'), _('Configure the fields of this form')) |
|
51 |
'</dl>' |
|
52 |
|
|
53 |
def _q_lookup(self, component): |
|
54 |
if component == 'fields': |
|
55 |
return FieldsDirectory(self.form_prefill) |
|
56 |
|
|
57 |
def edit [html] (self): |
|
58 |
form = self.form_ui.form_edit() |
|
59 |
if form.get_widget('cancel').parse(): |
|
60 |
return redirect('.') |
|
61 |
|
|
62 |
if form.is_submitted() and not form.has_errors(): |
|
63 |
self.form_ui.submit_edit(form) |
|
64 |
return redirect('.') |
|
65 |
|
|
66 |
get_response().breadcrumb.append( ('edit', _('Edit')) ) |
|
67 |
html_top('edit', title = _('Edit')) |
|
68 |
'<h2>%s</h2>' % _('Edit') |
|
69 |
|
|
70 |
form.render() |
|
71 |
|
|
72 |
def delete [html] (self): |
|
73 |
form = Form(enctype='multipart/form-data') |
|
74 |
form.widgets.append(HtmlWidget('<p>%s</p>' % _( |
|
75 |
'You are about to irrevocably delete this form.'))) |
|
76 |
form.add_submit('submit', _('Submit')) |
|
77 |
form.add_submit('cancel', _('Cancel')) |
|
78 |
if form.get_widget('cancel').parse(): |
|
79 |
return redirect('..') |
|
80 |
if not form.is_submitted() or form.has_errors(): |
|
81 |
get_response().breadcrumb.append(('delete', _('Delete'))) |
|
82 |
html_top('delete_form', title = _('Delete Form')) |
|
83 |
'<h2>%s : %s</h2>' % (_('Delete Form'), self.form_prefill.id) |
|
84 |
form.render() |
|
85 |
else: |
|
86 |
self.form_prefill.remove_self() |
|
87 |
return redirect('..') |
|
88 |
|
|
89 |
|
|
90 |
class FormsDirectory(Directory): |
|
91 |
_q_exports = ['', 'new'] |
|
92 |
|
|
93 |
def __init__(self, host): |
|
94 |
get_response().breadcrumb.append(('forms_prefill/', _('Forms'))) |
|
95 |
self.host = host |
|
96 |
|
|
97 |
def _q_lookup(self, component): |
|
98 |
return FormPage(component) |
|
99 |
|
|
100 |
def _q_index [html] (self): |
|
101 |
html_top('forms', title = _('Forms')) |
|
102 |
"""<ul id="nav-forms-admin"> |
|
103 |
<li><a href="new">%s</a></li> |
|
104 |
</ul>""" % _('New Form') |
|
105 |
|
|
106 |
'<ul class="biglist">' |
|
107 |
|
|
108 |
for form_prefill in FormPrefill.select(lambda x: x.host_id == self.host.id): |
|
109 |
if not form_prefill.name: |
|
110 |
continue |
|
111 |
'<li>' |
|
112 |
'<strong class="label">%s</strong>' % form_prefill.name |
|
113 |
url = form_prefill.url |
|
114 |
'<br /><a href="%s">%s</a>' % (url, url) |
|
115 |
'<p class="commands">' |
|
116 |
command_icon('%s/' % form_prefill.id, 'edit') |
|
117 |
command_icon('%s/delete' % form_prefill.id, 'remove') |
|
118 |
'</p></li>' |
|
119 |
'</ul>' |
|
120 |
|
|
121 |
def new [html] (self): |
|
122 |
get_response().breadcrumb.append(('new', _('New')) ) |
|
123 |
form_prefill = FormPrefill() |
|
124 |
form_prefill.host_id = self.host.id |
|
125 |
form_prefill.store() |
|
126 |
return redirect('%s/edit' % form_prefill.id) |
|
127 |
|
larpe/tags/release-1.1.1/larpe/admin/hosts.ptl | ||
---|---|---|
1 |
import os |
|
2 |
import urllib |
|
3 |
import urlparse |
|
4 |
|
|
5 |
from quixote import redirect, get_request, get_response, get_publisher |
|
6 |
from quixote.directory import Directory |
|
7 |
|
|
8 |
import lasso |
|
9 |
|
|
10 |
from qommon.admin.menu import html_top, command_icon |
|
11 |
from qommon import get_cfg |
|
12 |
from qommon.form import * |
|
13 |
from qommon.misc import http_get_page, get_abs_path |
|
14 |
|
|
15 |
from larpe import site_authentication |
|
16 |
from larpe import errors |
|
17 |
from larpe import misc |
|
18 |
from larpe.hosts import Host |
|
19 |
from larpe.admin.apache import Location |
|
20 |
from larpe.admin.liberty_utils import * |
|
21 |
from larpe.admin.apache import write_apache2_vhosts |
|
22 |
from larpe.admin.forms_prefill import FormsDirectory |
|
23 |
from larpe.Defaults import DATA_DIR |
|
24 |
from larpe.plugins import site_authentication_plugins |
|
25 |
|
|
26 |
def check_basic_configuration(form): |
|
27 |
get_publisher().reload_cfg() |
|
28 |
# Check reversed_hostname and reversed_directory |
|
29 |
reversed_hostname = form.get_widget('reversed_hostname').parse() |
|
30 |
reversed_directory = form.get_widget('reversed_directory').parse() |
|
31 |
if reversed_hostname == get_publisher().cfg['proxy_hostname'] and not reversed_directory: |
|
32 |
form.set_error('reversed_hostname', |
|
33 |
_('You must either choose a different hostname from Larpe or specify a reversed directory')) |
|
34 |
|
|
35 |
def convert_label_to_name(label): |
|
36 |
'''Build host name from host label''' |
|
37 |
name = label.lower() |
|
38 |
invalid_characters = [' ', "'"] |
|
39 |
for char in invalid_characters: |
|
40 |
name = name.replace(char, '_') |
|
41 |
return name |
|
42 |
|
|
43 |
class DictWidget(Widget): |
|
44 |
def render_content [html] (self): |
|
45 |
self.render_br = False |
|
46 |
if self.value['enabled'] is True: |
|
47 |
htmltag('input', xml_end=True, type='checkbox', name=self.name + '_enabled', checked='checked') |
|
48 |
else: |
|
49 |
htmltag('input', xml_end=True, type='checkbox', name=self.name + '_enabled') |
|
50 |
' ' + self.name + ' ' |
|
51 |
htmltag('input', xml_end=True, type='text', name=self.name, value=self.value['value'], size='35', **self.attrs) |
|
52 |
|
|
53 |
def _parse(self, request): |
|
54 |
enabled = request.form.get(self.name + '_enabled') |
|
55 |
value = request.form.get(self.name) |
|
56 |
self.value = { 'enabled': enabled, 'value': value } |
|
57 |
|
|
58 |
|
|
59 |
class ConfigurationAssistant(Directory): |
|
60 |
_q_exports = ['start', 'check_new_address', 'modify_site_address_and_name', |
|
61 |
'authentication_and_logout_adresses', 'check_auto_detected_configuration', |
|
62 |
'credentials', 'send_authentication_request', 'check_authentication', |
|
63 |
'see_authentication_response', 'see_response_html_page', |
|
64 |
'see_bad_response_html_page', 'authentication_success_criteria', |
|
65 |
'modify_authentication_request', 'auth_request_post_parameters', |
|
66 |
'auth_request_http_headers', 'sso_init_link', 'metadatas', |
|
67 |
'check_full_configuration', 'advanced_options'] |
|
68 |
|
|
69 |
def __init__(self, host): |
|
70 |
self.host = host |
|
71 |
|
|
72 |
def html_top [html] (self, title): |
|
73 |
html_top('hosts', title) |
|
74 |
'<h2>%s</h2>' % title |
|
75 |
|
|
76 |
def start [html] (self): |
|
77 |
# Check the global domain name has been previously set |
|
78 |
get_publisher().reload_cfg() |
|
79 |
if not get_cfg('domain_names') or not get_cfg('domain_names')[0]: |
|
80 |
get_response().breadcrumb.append(('start', _('Basic configuration'))) |
|
81 |
self.html_top(_('Need domain name configuration')) |
|
82 |
return htmltext(_('''Before configuring hosts, you must |
|
83 |
<a href="../../../settings/domain_names">setup a global domain name</a> in |
|
84 |
%(settings)s menu.''') % { 'settings': _('Settings') }) |
|
85 |
|
|
86 |
form = self.form_start() |
|
87 |
|
|
88 |
if form.get_widget('cancel').parse(): |
|
89 |
return redirect('../..') |
|
90 |
|
|
91 |
connection_failure = None |
|
92 |
if form.is_submitted() and not form.has_errors(): |
|
93 |
try: |
|
94 |
self.submit_start_form(form) |
|
95 |
except Exception, e: |
|
96 |
connection_failure = e |
|
97 |
else: |
|
98 |
if form.get_widget('terminate').parse(): |
|
99 |
return redirect('..') |
|
100 |
return redirect('check_new_address') |
|
101 |
|
|
102 |
get_response().breadcrumb.append(('start', _('Basic configuration'))) |
|
103 |
self.html_top(_('Step 1 - Basic configuration')) |
|
104 |
|
|
105 |
if connection_failure: |
|
106 |
'<div class="errornotice">%s</div>' % connection_failure |
|
107 |
|
|
108 |
form.render() |
|
109 |
|
|
110 |
def form_start(self): |
|
111 |
form = Form(enctype='multipart/form-data') |
|
112 |
form.add(UrlWidget, 'orig_site', title = _('Original site root address'), required = True, |
|
113 |
size = 50, value = self.host.orig_site, |
|
114 |
hint = _('If your site address is http://test.org/index.php, put http://test.org/ here')) |
|
115 |
get_publisher().reload_cfg() |
|
116 |
if get_cfg('proxy', {}).get('enabled'): |
|
117 |
form.add(CheckboxWidget, 'use_proxy', title = _('Use a proxy'), |
|
118 |
hint = _("Uncheck it if Larpe doesn't need to use the proxy to connect to this site"), |
|
119 |
value = self.host.use_proxy) |
|
120 |
else: |
|
121 |
form.add(HtmlWidget, htmltext('<p>%s</p>' % \ |
|
122 |
_('''If Larpe needs to use a proxy to connect to this site, you must first configure |
|
123 |
it in <a href="../../../settings/proxy">global proxy parameters</a>.'''))) |
|
124 |
form.add_submit('cancel', _('Cancel')) |
|
125 |
form.add_submit('submit', _('Next')) |
|
126 |
form.add_submit('terminate', _('Terminate')) |
|
127 |
return form |
|
128 |
|
|
129 |
def submit_start_form(self, form): |
|
130 |
fields = ['orig_site'] |
|
131 |
use_proxy = get_cfg('proxy', {}).get('enabled') |
|
132 |
if use_proxy: |
|
133 |
fields += ['use_proxy'] |
|
134 |
for f in fields: |
|
135 |
setattr(self.host, f, form.get_widget(f).parse()) |
|
136 |
|
|
137 |
# If no proxy is setup yet, set use_proxy to False for new hosts in case a proxy is later configured |
|
138 |
if not use_proxy: |
|
139 |
self.host.use_proxy = False |
|
140 |
|
|
141 |
# Remove what is after the last '/' |
|
142 |
#self.host.orig_site = '/'.join(self.host.orig_site.split('/')[:-1]) |
|
143 |
|
|
144 |
html_page = self.get_data_after_redirects(self.host.orig_site) |
|
145 |
|
|
146 |
if not self.host.label: |
|
147 |
# Look for html title in original site index page |
|
148 |
regexp = re.compile("""<title.*?>(.*?)</title>""", re.DOTALL | re.IGNORECASE) |
|
149 |
title = regexp.findall(html_page) |
|
150 |
if title: |
|
151 |
self.host.label = title[0] |
|
152 |
else: |
|
153 |
self.host.label = 'Untitled' |
|
154 |
# If another site already uses this site title, add trailings "_" until we find an available name |
|
155 |
existing_label = True |
|
156 |
while existing_label is True: |
|
157 |
for any_host in Host.select(): |
|
158 |
if any_host.id != self.host.id and self.host.label == any_host.label: |
|
159 |
self.host.label += '_' |
|
160 |
break |
|
161 |
else: |
|
162 |
existing_label = False |
|
163 |
|
|
164 |
# Fill host.name attribute |
|
165 |
self.host.name = convert_label_to_name(self.host.label) |
|
166 |
|
|
167 |
if not self.host.scheme: |
|
168 |
# Get tokens from orig site url |
|
169 |
orig_scheme, rest = urllib.splittype(self.host.orig_site) |
|
170 |
orig_host, rest = urllib.splithost(rest) |
|
171 |
|
|
172 |
get_publisher().reload_cfg() |
|
173 |
# Set url scheme (HTTP or HTTPS) |
|
174 |
# TODO: Handle the option "Both" |
|
175 |
if get_cfg('sites_url_scheme'): |
|
176 |
self.host.scheme = get_cfg('sites_url_scheme') |
|
177 |
else: |
|
178 |
self.host.scheme = orig_scheme |
|
179 |
|
|
180 |
if not self.host.reversed_hostname: |
|
181 |
# Build a new domain name |
|
182 |
short_name = orig_host.split('.')[0] |
|
183 |
if short_name == 'www': |
|
184 |
short_name = orig_host.split('.')[1] |
|
185 |
self.host.reversed_hostname = '%s.%s' % (short_name, get_cfg('domain_names')[0]) |
|
186 |
# If another site already uses this domain name, add some trailing "_" until we find an available name |
|
187 |
existing_domain = True |
|
188 |
while existing_domain is True: |
|
189 |
for any_host in Host.select(): |
|
190 |
if any_host.id != self.host.id and self.host.reversed_hostname == any_host.reversed_hostname: |
|
191 |
self.host.reversed_hostname += '-' |
|
192 |
break |
|
193 |
else: |
|
194 |
existing_domain = False |
|
195 |
self.host.reversed_directory = None |
|
196 |
|
|
197 |
if not self.host.new_url: |
|
198 |
# New url for this host |
|
199 |
self.host.new_url = '%s://%s%s/' % (self.host.scheme, self.host.reversed_hostname, get_request().environ['SCRIPT_NAME']) |
|
200 |
# FIXME: Check if the new domain name already exists |
|
201 |
|
|
202 |
# New url for this host |
|
203 |
# self.host.new_url = '%s://%s%s/' % (self.host.scheme, self.host.reversed_hostname, get_request().environ['SCRIPT_NAME']) |
|
204 |
# if self.host.reversed_directory is not None: |
|
205 |
# self.host.new_url += '%s/' % self.host.reversed_directory |
|
206 |
|
|
207 |
self.host.store() |
|
208 |
write_apache2_vhosts() |
|
209 |
|
|
210 |
# XXX: Should use the FancyURLopener class instead when it supports proxies |
|
211 |
def get_data_after_redirects(self, start_url): |
|
212 |
if not start_url: |
|
213 |
return '' |
|
214 |
status = 302 |
|
215 |
location = None |
|
216 |
while status // 100 == 3: |
|
217 |
if location is None: |
|
218 |
url = start_url |
|
219 |
elif location.startswith('http'): |
|
220 |
# Location is an absolute path |
|
221 |
url = location |
|
222 |
else: |
|
223 |
# Location is a relative path |
|
224 |
url = urlparse.urljoin(start_url, location) |
|
225 |
response, status, data, auth_headers = http_get_page(url, use_proxy=self.host.use_proxy) |
|
226 |
location = response.getheader('Location', None) |
|
227 |
return data |
|
228 |
|
|
229 |
def create_dirs(self): |
|
230 |
# Hack : sites must use the configuration which is stored in main Larpe directory, |
|
231 |
# but they need to have a directory named with their hostname, which will contain the |
|
232 |
# main domain name for Larpe so they know where is the main configuration |
|
233 |
hostname_dir = get_abs_path(os.path.join('..', self.host.reversed_hostname)) |
|
234 |
if not os.path.exists(hostname_dir): |
|
235 |
os.mkdir(hostname_dir) |
|
236 |
# Load the configuration from the main directory |
|
237 |
get_publisher().reload_cfg() |
|
238 |
# Write it in the site directory |
|
239 |
get_publisher().write_cfg(hostname_dir) |
|
240 |
|
|
241 |
# Storage directories |
|
242 |
if not self.host.reversed_directory: |
|
243 |
reversed_dir = 'default' |
|
244 |
else: |
|
245 |
reversed_dir = self.host.reversed_directory |
|
246 |
self.host.site_dir = \ |
|
247 |
os.path.join(get_publisher().app_dir, 'sp', self.host.reversed_hostname, reversed_dir) |
|
248 |
user_dir = os.path.join(self.host.site_dir, 'users') |
|
249 |
token_dir = os.path.join(self.host.site_dir, 'tokens') |
|
250 |
filter_dir = os.path.join(self.host.site_dir, 'filters') |
|
251 |
for dir in (self.host.site_dir, user_dir, token_dir, filter_dir): |
|
252 |
if not os.path.isdir(dir): |
|
253 |
os.makedirs(dir) |
|
254 |
|
|
255 |
def generate_ssl_keys(self): |
|
256 |
# Generate SSL keys |
|
257 |
private_key_path = os.path.join(self.host.site_dir, 'private_key.pem') |
|
258 |
public_key_path = os.path.join(self.host.site_dir, 'public_key.pem') |
|
259 |
if not os.path.isfile(private_key_path) or not os.path.isfile(public_key_path): |
|
260 |
set_provider_keys(private_key_path, public_key_path) |
|
261 |
self.host.private_key = private_key_path |
|
262 |
self.host.public_key = public_key_path |
|
263 |
|
|
264 |
def generate_metadatas(self): |
|
265 |
metadata_cfg = {} |
|
266 |
|
|
267 |
# Organization name |
|
268 |
self.host.organization_name = self.host.label |
|
269 |
metadata_cfg['organization_name'] = self.host.organization_name |
|
270 |
|
|
271 |
# Base URL |
|
272 |
base_url = '%s://%s%s/liberty/%s/liberty' % (self.host.scheme, |
|
273 |
self.host.reversed_hostname, |
|
274 |
get_request().environ['SCRIPT_NAME'], |
|
275 |
self.host.name) |
|
276 |
metadata_cfg['base_url'] = base_url |
|
277 |
self.host.base_url = base_url |
|
278 |
|
|
279 |
if lasso.SAML2_SUPPORT: |
|
280 |
saml2_base_url = '%s://%s%s/liberty/%s/saml' % (self.host.scheme, |
|
281 |
self.host.reversed_hostname, |
|
282 |
get_request().environ['SCRIPT_NAME'], |
|
283 |
self.host.name) |
|
284 |
metadata_cfg['saml2_base_url'] = saml2_base_url |
|
285 |
self.host.saml2_base_url = saml2_base_url |
|
286 |
|
|
287 |
# Provider Id |
|
288 |
provider_id = '%s/metadata' % base_url |
|
289 |
metadata_cfg['provider_id'] = provider_id |
|
290 |
self.host.provider_id = provider_id |
|
291 |
|
|
292 |
if lasso.SAML2_SUPPORT: |
|
293 |
saml2_provider_id = '%s/metadata' % saml2_base_url |
|
294 |
metadata_cfg['saml2_provider_id'] = saml2_provider_id |
|
295 |
self.host.saml2_provider_id = saml2_provider_id |
|
296 |
|
|
297 |
# Read public key |
|
298 |
public_key = '' |
|
299 |
if self.host.public_key is not None and os.path.exists(self.host.public_key): |
|
300 |
metadata_cfg['signing_public_key'] = open(self.host.public_key).read() |
|
301 |
|
|
302 |
# Write metadatas |
|
303 |
metadata_path = os.path.join(self.host.site_dir, 'metadata.xml') |
|
304 |
open(metadata_path, 'w').write(get_metadata(metadata_cfg)) |
|
305 |
self.host.metadata = metadata_path |
|
306 |
|
|
307 |
if lasso.SAML2_SUPPORT: |
|
308 |
saml2_metadata_path = os.path.join(self.host.site_dir, 'saml2_metadata.xml') |
|
309 |
open(saml2_metadata_path, 'w').write(get_saml2_metadata(metadata_cfg)) |
|
310 |
self.host.saml2_metadata = saml2_metadata_path |
|
311 |
|
|
312 |
def check_new_address [html] (self): |
|
313 |
form = Form(enctype='multipart/form-data') |
|
314 |
form.add_submit('cancel', _('Previous')) |
|
315 |
form.add_submit('submit', _('Next')) |
|
316 |
form.add_submit('terminate', _('Terminate')) |
|
317 |
|
|
318 |
if form.get_widget('cancel').parse(): |
|
319 |
return redirect('start') |
|
320 |
|
|
321 |
if form.is_submitted(): |
|
322 |
self.create_dirs() |
|
323 |
if self.host.private_key is None: |
|
324 |
self.generate_ssl_keys() |
|
325 |
self.generate_metadatas() |
|
326 |
self.host.store() |
|
327 |
|
|
328 |
if form.get_widget('terminate').parse(): |
|
329 |
return redirect('..') |
|
330 |
return redirect('authentication_and_logout_adresses') |
|
331 |
|
|
332 |
get_response().breadcrumb.append(('check_new_address', _('Check site address and name'))) |
|
333 |
self.html_top(_('Step 2 - Check the new site address works')) |
|
334 |
|
|
335 |
'<h3>%s</h3>' % _('DNS configuration') |
|
336 |
|
|
337 |
'<p>%s</p>' % _('''Before opening the following link, ensure you have configured your DNS |
|
338 |
for this address. If you don't have a DNS server and you just want to test Larpe, add this |
|
339 |
domain name in the file "/etc/hosts".''') |
|
340 |
|
|
341 |
'<p>%s</p>' % _('''Then you can open this link in a new window or tab and see if your site |
|
342 |
is displayed. If it's ok, you can click the "%(next)s" button. Otherwise, click the "%(previous)s" |
|
343 |
button and check your settings.''') % {'next': _('Next'), 'previous': _('Previous')} |
|
344 |
|
|
345 |
'<h3>%s</h3>' % _('Site adress and name') |
|
346 |
|
|
347 |
'<p>%s' % _('The new address of this site is ') |
|
348 |
'<a href="%s">%s</a><br/>' % (self.host.new_url, self.host.new_url) |
|
349 |
'%s</p>' % _('The name of this site is "%s".') % self.host.label |
|
350 |
'<p>%s</p>' % htmltext(_('''You can also <a href="modify_site_address_and_name"> |
|
351 |
modify the address or the name of this site</a>''')) |
|
352 |
|
|
353 |
form.render() |
|
354 |
|
|
355 |
def modify_site_address_and_name [html] (self): |
|
356 |
form = self.form_modify_site_address_and_name() |
|
357 |
|
|
358 |
if form.get_widget('cancel').parse(): |
|
359 |
return redirect('check_new_address') |
|
360 |
|
|
361 |
if form.is_submitted() and not form.has_errors(): |
|
362 |
label = form.get_widget('label').parse() |
|
363 |
name = convert_label_to_name(label) |
|
364 |
for any_host in Host.select(): |
|
365 |
if any_host.id != self.host.id and name == any_host.name: |
|
366 |
form.set_error('label', _('An host with the same name already exists')) |
|
367 |
break |
|
368 |
|
|
369 |
if form.is_submitted() and not form.has_errors(): |
|
370 |
self.submit_modify_site_address_and_name_form(form) |
|
371 |
return redirect('check_new_address') |
|
372 |
|
|
373 |
get_response().breadcrumb.append(('modify_site_address_and_name', _('Modify site address and name'))) |
|
374 |
self.html_top(_('Modify site address and name')) |
|
375 |
|
|
376 |
form.render() |
|
377 |
|
|
378 |
def form_modify_site_address_and_name(self): |
|
379 |
form = Form(enctype='multipart/form-data') |
|
380 |
form.add(UrlWidget, 'new_url', title = _('Address'), required = True, |
|
381 |
size = 50, value = self.host.new_url) |
|
382 |
form.add(StringWidget, 'label', title = _('Name'), required = True, |
|
383 |
size = 50, value = self.host.label) |
|
384 |
form.add_submit('submit', _('Submit')) |
|
385 |
form.add_submit('cancel', _('Cancel')) |
|
386 |
return form |
|
387 |
|
|
388 |
def submit_modify_site_address_and_name_form(self, form): |
|
389 |
fields = ['new_url', 'label'] |
|
390 |
for f in fields: |
|
391 |
setattr(self.host, f, form.get_widget(f).parse()) |
|
392 |
|
|
393 |
# Split url to retrieve components |
|
394 |
tokens = urlparse.urlparse(self.host.new_url) |
|
395 |
self.host.scheme = tokens[0] |
|
396 |
self.host.reversed_hostname = tokens[1] |
|
397 |
self.host.reversed_directory = tokens[2] |
|
398 |
if self.host.reversed_directory.startswith('/'): |
|
399 |
self.host.reversed_directory = self.host.reversed_directory[1:] |
|
400 |
|
|
401 |
# Fill host.name attribute |
|
402 |
self.host.name = convert_label_to_name(self.host.label) |
|
403 |
|
|
404 |
self.host.store() |
|
405 |
write_apache2_vhosts() |
|
406 |
|
|
407 |
def authentication_and_logout_adresses [html] (self): |
|
408 |
form = self.form_authentication_and_logout_adresses() |
|
409 |
|
|
410 |
if form.get_widget('cancel').parse(): |
|
411 |
return redirect('check_new_address') |
|
412 |
|
|
413 |
if form.is_submitted() and not form.has_errors(): |
|
414 |
self.submit_authentication_and_logout_adresses_form(form) |
|
415 |
if form.get_widget('terminate').parse(): |
|
416 |
return redirect('..') |
|
417 |
return redirect('check_auto_detected_configuration') |
|
418 |
|
|
419 |
get_response().breadcrumb.append(('authentication_and_logout_adresses', _('Authentication and logout'))) |
|
420 |
self.html_top(_('Step 3 - Configure authentication and logout pages')) |
|
421 |
|
|
422 |
form.render() |
|
423 |
|
|
424 |
def form_authentication_and_logout_adresses(self): |
|
425 |
form = Form(enctype='multipart/form-data') |
|
426 |
form.add(ValidUrlWidget, 'auth_url', title = _('Authentication form page address'), |
|
427 |
hint = _('Address of a page on the site which contains the authentication form'), |
|
428 |
required = True, size = 50, value = self.host.auth_url) |
|
429 |
form.add(ValidUrlWidget, 'logout_url', title = _('Logout address'), required = False, |
|
430 |
hint = _('Address of the logout link on the site'), |
|
431 |
size = 50, value = self.host.logout_url) |
|
432 |
form.add_submit('cancel', _('Previous')) |
|
433 |
form.add_submit('submit', _('Next')) |
|
434 |
form.add_submit('terminate', _('Terminate')) |
|
435 |
return form |
|
436 |
|
|
437 |
def submit_authentication_and_logout_adresses_form(self, form): |
|
438 |
fields = ['auth_url', 'logout_url'] |
|
439 |
for f in fields: |
|
440 |
setattr(self.host, f, form.get_widget(f).parse()) |
|
441 |
self.host.auth_form_url = self.host.auth_url |
|
442 |
|
|
443 |
if not self.host.http_headers: |
|
444 |
self.host.http_headers = { |
|
445 |
'Content-Type': { 'enabled': True, 'value': 'application/x-www-form-urlencoded', 'immutable': False }, |
|
446 |
'X-Forwarded-For': { 'enabled': True, 'value': _('(computed automatically)'), 'immutable': True }, |
|
447 |
'X-Forwarded-Host': { 'enabled': True, 'value': self.host.reversed_hostname, 'immutable': False }, |
|
448 |
} |
|
449 |
|
|
450 |
self.auto_detect_configuration() |
|
451 |
self.host.store() |
|
452 |
write_apache2_vhosts() |
|
453 |
|
|
454 |
def check_auto_detected_configuration [html] (self): |
|
455 |
plugins_name = site_authentication_plugins.get_plugins_name() |
|
456 |
plugins_name.append(None) |
|
457 |
plugins_name.sort() |
|
458 |
form = Form(enctype='multipart/form-data') |
|
459 |
form.add(SingleSelectWidget, 'plugin', title = _('Plugin'), required = False, |
|
460 |
hint = _('You can force a plugin'), |
|
461 |
value = self.host.site_authentication_plugin, |
|
462 |
options = plugins_name) |
|
463 |
form.add_submit('cancel', _('Previous')) |
|
464 |
form.add_submit('submit', _('Next')) |
|
465 |
form.add_submit('terminate', _('Terminate')) |
|
466 |
|
|
467 |
if form.get_widget('cancel').parse(): |
|
468 |
return redirect('authentication_and_logout_adresses') |
|
469 |
|
|
470 |
if form.is_submitted(): |
|
471 |
self.host.site_authentication_plugin = form.get_widget('plugin').parse() |
|
472 |
self.host.store() |
|
473 |
if form.get_widget('terminate').parse(): |
|
474 |
write_apache2_vhosts() |
|
475 |
return redirect('..') |
|
476 |
return redirect('credentials') |
|
477 |
|
|
478 |
get_response().breadcrumb.append(('check_auto_detected_configuration', _('Auto detected configuration'))) |
|
479 |
self.html_top(_('Step 4 - Check automatically detected configuration for the authentication form')) |
|
480 |
|
|
481 |
host_attrs = ( |
|
482 |
('auth_check_url', _('Address where the authentication form must be sent')), |
|
483 |
('login_field_name', _('Name of the login field')), |
|
484 |
('password_field_name', _('Name of the password field')), |
|
485 |
) |
|
486 |
|
|
487 |
html_fields = '' |
|
488 |
success = True |
|
489 |
for attr, name in host_attrs: |
|
490 |
color = 'black' |
|
491 |
if attr in ('auth_check_url', 'login_field_name', 'password_field_name') and \ |
|
492 |
not getattr(self.host, str(attr)): |
|
493 |
color = 'red' |
|
494 |
success = False |
|
495 |
html_fields += '<div style="margin-bottom: 0.1em; font-weight: bold; color: %s;">%s</div>' % (color, name) |
|
496 |
html_fields += '<div style="margin-left: 1em; margin-bottom: 0.3em; color: %s;">%s</div>' % \ |
|
497 |
(color, getattr(self.host, str(attr))) |
|
498 |
if getattr(self.host, str(attr)) == '': |
|
499 |
html_fields += '<br />' |
|
500 |
|
|
501 |
'<p>' |
|
502 |
if success: |
|
503 |
htmltext(_('''\ |
|
504 |
The following authentication form parameters have been detected. If they look right, you can go to the next step. |
|
505 |
If you think they are wrong, go back and check your settings then try again. |
|
506 |
''')) |
|
507 |
else: |
|
508 |
htmltext(_('''\ |
|
509 |
The following authentication form parameters in red haven't been correctly detected. Go back and check |
|
510 |
your settings then try again. |
|
511 |
''')) |
|
512 |
'</p>' |
|
513 |
|
|
514 |
html_fields |
|
515 |
form.render() |
|
516 |
|
|
517 |
def credentials [html] (self): |
|
518 |
form = self.form_credentials() |
|
519 |
|
|
520 |
if form.get_widget('cancel').parse(): |
|
521 |
return redirect('check_auto_detected_configuration') |
|
522 |
|
|
523 |
if form.is_submitted() and not form.has_errors(): |
|
524 |
self.submit_credentials_form(form) |
|
525 |
if form.get_widget('terminate').parse(): |
|
526 |
return redirect('..') |
|
527 |
return redirect('send_authentication_request') |
|
528 |
|
|
529 |
get_response().breadcrumb.append(('credentials', _('Credentials'))) |
|
530 |
self.html_top(_('Step 5 - Fill in a valid username/password for this site')) |
|
531 |
form.render() |
|
532 |
|
|
533 |
def form_credentials(self): |
|
534 |
form = Form(enctype='multipart/form-data') |
|
535 |
form.add(StringWidget, 'username', title = _('Username'), required = True, |
|
536 |
size = 30, value = self.host.valid_username) |
|
537 |
form.add(PasswordWidget, 'password', title = _('Password'), required = True, |
|
538 |
size = 30, value = self.host.valid_password) |
|
539 |
for name, values in self.host.select_fields.iteritems(): |
|
540 |
options = [] |
|
541 |
if values: |
|
542 |
for value in values: |
|
543 |
options.append(value) |
|
544 |
form.add(SingleSelectWidget, name, title = name.capitalize(), |
|
545 |
value = values[0], options = options) |
|
546 |
form.add_submit('cancel', _('Previous')) |
|
547 |
form.add_submit('submit', _('Next')) |
|
548 |
form.add_submit('terminate', _('Terminate')) |
|
549 |
return form |
|
550 |
|
|
551 |
def submit_credentials_form(self, form): |
|
552 |
self.host.valid_username = form.get_widget('username').parse() |
|
553 |
self.host.valid_password = form.get_widget('password').parse() |
|
554 |
self.host.valid_select = {} |
|
555 |
for name, values in self.host.select_fields.iteritems(): |
|
556 |
if form.get_widget(name): |
|
557 |
self.host.valid_select[name] = form.get_widget(name).parse() |
|
558 |
|
|
559 |
self.host.store() |
|
560 |
|
|
561 |
def send_authentication_request(self): |
|
562 |
site_auth = site_authentication.get_site_authentication(self.host) |
|
563 |
|
|
564 |
# Request with good credentials |
|
565 |
self.host.auth_request_status, self.host.auth_request_data = site_auth.local_auth_check_dispatch( |
|
566 |
self.host.valid_username, self.host.valid_password, self.host.valid_select) |
|
567 |
self.host.auth_request_success, self.host.auth_request_return_content = \ |
|
568 |
site_auth.check_auth(self.host.auth_request_status, self.host.auth_request_data) |
|
569 |
|
|
570 |
# Request with bad credentials |
|
571 |
self.host.auth_bad_request_status, self.host.auth_bad_request_data = site_auth.local_auth_check_dispatch( |
|
572 |
'this_is_a_bad_login', 'this_is_a_bad_password', {}) |
|
573 |
self.host.auth_bad_request_success, self.host.auth_bad_request_return_content = \ |
|
574 |
site_auth.check_auth(self.host.auth_bad_request_status, self.host.auth_bad_request_data) |
|
575 |
|
|
576 |
self.host.store() |
|
577 |
|
|
578 |
return redirect('check_authentication') |
|
579 |
|
|
580 |
def check_authentication [html] (self): |
|
581 |
form = Form(enctype='multipart/form-data') |
|
582 |
form.add_submit('cancel', _('Previous')) |
|
583 |
form.add_submit('submit', _('Next')) |
|
584 |
form.add_submit('terminate', _('Terminate')) |
|
585 |
|
|
586 |
if form.get_widget('cancel').parse(): |
|
587 |
return redirect('credentials') |
|
588 |
|
|
589 |
if form.is_submitted(): |
|
590 |
if form.get_widget('terminate').parse(): |
|
591 |
return redirect('..') |
|
592 |
return redirect('sso_init_link') |
|
593 |
|
|
594 |
get_response().breadcrumb.append(('check_authentication', _('Check authentication'))) |
|
595 |
self.html_top(_('Step 6 - Check the authentication process')) |
|
596 |
|
|
597 |
if self.host.auth_request_success: |
|
598 |
good_cred_status = 'Success <span style="color: green">[OK]</span>' |
|
599 |
else: |
|
600 |
good_cred_status = 'Failed <span style="color: red">[KO]</span' |
|
601 |
|
|
602 |
if not self.host.auth_bad_request_success: |
|
603 |
bad_cred_status = 'Failed <span style="color: green">[OK]</span>' |
|
604 |
else: |
|
605 |
bad_cred_status = 'Success <span style="color: red">[KO]</span>' |
|
606 |
|
|
607 |
'<p>Results of authentication requests :</p>\n' |
|
608 |
'<ul>\n' |
|
609 |
'\t<li>With good credentials : %s</li>' % good_cred_status |
|
610 |
'\t<li>With bad credentials : %s</li>' % bad_cred_status |
|
611 |
'</ul>\n' |
|
612 |
|
|
613 |
if self.host.auth_request_success and not self.host.auth_bad_request_success : |
|
614 |
'<p>%s</p>\n' % _('Authentication succeeded ! You can go to the next step.') |
|
615 |
else: |
|
616 |
'<p>%s</p>\n' % _('Authentication has failed. To resolve this problem, you can :') |
|
617 |
'<ul>\n' |
|
618 |
'\t<li><a href="send_authentication_request">%s</a></li>\n' % \ |
|
619 |
_('Try authentication again') |
|
620 |
'\t<li><a href="see_authentication_response">%s</a></li>\n' % \ |
|
621 |
_('See the response of the authentication requests') |
|
622 |
'\t<li><a href="modify_authentication_request">%s</a></li>\n' % \ |
|
623 |
_('Modify the parameters of the authentication requests') |
|
624 |
'\t<li><a href="authentication_success_criteria">%s</a></li>\n' % \ |
|
625 |
_('Change the way Larpe detects the authentication is successful or not') |
|
626 |
'\t<li>%s</li>\n' % _('Go back and change your username and/or password') |
|
627 |
'</ul>\n' |
|
628 |
|
|
629 |
form.render() |
|
630 |
|
|
631 |
def see_authentication_response [html] (self): |
|
632 |
get_response().breadcrumb.append(('see_authentication_response', _('Authentication response'))) |
|
633 |
self.html_top(_('Authentication response')) |
|
634 |
|
|
635 |
'<h3>%s</h3>' % _('Response of the request with good credentials') |
|
636 |
|
|
637 |
'<div style="margin-bottom: 0.1em; font-weight: bold; color: black;">%s</div>' % \ |
|
638 |
str(_('HTTP status code')) |
|
639 |
'<div style="margin-left: 1em; margin-bottom: 0.3em; color: black;">%s (%s)</div>' % \ |
|
640 |
(self.host.auth_request_status, status_reasons[self.host.auth_request_status]) |
|
641 |
|
|
642 |
'<dl>' |
|
643 |
'<dt><a href="see_bad_response_html_page">%s</a></dt>' % _('See HTML page') |
|
644 |
'</dl>' |
|
645 |
|
|
646 |
'<h3>%s</h3>' % _('Response of the request with bad credentials') |
|
647 |
|
|
648 |
'<div style="margin-bottom: 0.1em; font-weight: bold; color: black;">%s</div>' % \ |
|
649 |
str(_('HTTP status code')) |
|
650 |
'<div style="margin-left: 1em; margin-bottom: 0.3em; color: black;">%s (%s)</div>' % \ |
|
651 |
(self.host.auth_bad_request_status, status_reasons[self.host.auth_bad_request_status]) |
|
652 |
|
|
653 |
'<dl>' |
|
654 |
'<dt><a href="see_response_html_page">%s</a></dt>' % _('See HTML page') |
|
655 |
'</dl>' |
|
656 |
|
|
657 |
'<div class="buttons"><a href="check_authentication"><input type="button" value="%s" /></a></div><br />' % _('Back') |
|
658 |
|
|
659 |
def see_response_html_page (self): |
|
660 |
return self.host.auth_request_data |
|
661 |
|
|
662 |
def see_bad_response_html_page (self): |
|
663 |
return self.host.auth_bad_request_data |
|
664 |
|
|
665 |
def authentication_success_criteria [html] (self): |
|
666 |
form = self.form_authentication_success_criteria() |
|
667 |
|
|
668 |
if form.get_widget('cancel').parse(): |
|
669 |
return redirect('check_authentication') |
|
670 |
|
|
671 |
if form.is_submitted() and not form.has_errors(): |
|
672 |
self.submit_authentication_success_criteria_form(form) |
|
673 |
return redirect('check_authentication') |
|
674 |
|
|
675 |
get_response().breadcrumb.append(('authentication_success_criteria', _('Authentication success criteria'))) |
|
676 |
self.html_top(_('Authentication success criteria')) |
|
677 |
|
|
678 |
form.render() |
|
679 |
|
|
680 |
def form_authentication_success_criteria(self): |
|
681 |
form = Form(enctype='multipart/form-data') |
|
682 |
form.add(RadiobuttonsWidget, 'auth_system', title = _('Authentication system of the original site'), |
|
683 |
options=[ |
|
684 |
('password', _('Check the existence of a password field'), 'password'), |
|
685 |
('match_text', _('Match some text to detect an authentication failure'), 'match_text'), |
|
686 |
], |
|
687 |
sort=False, |
|
688 |
delim=htmltext('<br />'), |
|
689 |
value = self.host.auth_system) |
|
690 |
form.add(RegexStringWidget, 'auth_match_text', title = _('Text to match in case of authentication failure'), |
|
691 |
required = False, size = 50, value = self.host.auth_match_text) |
|
692 |
form.add_submit('submit', _('Submit')) |
|
693 |
form.add_submit('cancel', _('Cancel')) |
|
694 |
return form |
|
695 |
|
|
696 |
def submit_authentication_success_criteria_form(self, form): |
|
697 |
for f in ('auth_system', 'auth_match_text'): |
|
698 |
value = form.get_widget(f).parse() |
|
699 |
setattr(self.host, f, value) |
|
700 |
|
|
701 |
self.host.store() |
|
702 |
|
|
703 |
def modify_authentication_request [html] (self): |
|
704 |
get_response().breadcrumb.append(('modify_authentication_request', _('Authentication request'))) |
|
705 |
self.html_top(_('Modify the parameters of the authentication requests')) |
|
706 |
|
|
707 |
'<dl>' |
|
708 |
'<dt><a href="auth_request_post_parameters">%s</a></dt> <dd>%s</dd>' % ( |
|
709 |
_('Modify POST parameters'), _('Configure the form attributes that will be sent within the authentication POST requests')) |
|
710 |
'<dt><a href="auth_request_http_headers">%s</a></dt> <dd>%s</dd>' % ( |
|
711 |
_('Modify HTTP headers'), _('Configure the HTTP headers of the authentication requests made by Larpe')) |
|
712 |
'</dl>' |
|
713 |
'<div class="buttons"><a href="check_authentication"><input type="button" value="%s" /></a></div><br />' % _('Back') |
|
714 |
|
|
715 |
def auth_request_post_parameters [html] (self): |
|
716 |
form = self.form_auth_request_post_parameters() |
|
717 |
|
|
718 |
if form.get_widget('cancel').parse(): |
|
719 |
return redirect('modify_authentication_request') |
|
720 |
|
|
721 |
if form.is_submitted() and not form.has_errors(): |
|
722 |
self.submit_auth_request_post_parameters_form(form) |
|
723 |
return redirect('modify_authentication_request') |
|
724 |
|
|
725 |
get_response().breadcrumb.append(('auth_request_post_parameters', _('POST parameters'))) |
|
726 |
self.html_top(_('Configure POST parameters')) |
|
727 |
|
|
728 |
'<p>%s</p>' % _('''Here are the detected form fields that will be sent as parameters of the |
|
729 |
authentication POST request. You can desactivate some or all of them, or change their value.''') |
|
730 |
|
|
731 |
form.render() |
|
732 |
|
|
733 |
def form_auth_request_post_parameters(self): |
|
734 |
form = Form(enctype='multipart/form-data') |
|
735 |
for name, value in self.host.post_parameters.iteritems(): |
|
736 |
if value['immutable']: |
|
737 |
form.add(DictWidget, name, value, disabled = 'disabled') |
|
738 |
else: |
|
739 |
form.add(DictWidget, name, value) |
|
740 |
form.add_submit('submit', _('Submit')) |
|
741 |
form.add_submit('cancel', _('Cancel')) |
|
742 |
return form |
|
743 |
|
|
744 |
def submit_auth_request_post_parameters_form(self, form): |
|
745 |
for name, old_value in self.host.post_parameters.iteritems(): |
|
746 |
value = form.get_widget(name).parse() |
|
747 |
if value['enabled'] == 'on': |
|
748 |
old_value['enabled'] = True |
|
749 |
else: |
|
750 |
old_value['enabled'] = False |
|
751 |
if old_value['immutable'] is False: |
|
752 |
old_value['value'] = value['value'] |
|
753 |
self.host.post_parameters[name] = old_value |
|
754 |
self.host.store() |
|
755 |
|
|
756 |
def auth_request_http_headers [html] (self): |
|
757 |
form = self.form_auth_request_http_headers() |
|
758 |
|
|
759 |
if form.get_widget('cancel').parse(): |
|
760 |
return redirect('modify_authentication_request') |
|
761 |
|
|
762 |
if form.is_submitted() and not form.has_errors(): |
|
763 |
self.submit_auth_request_http_headers_form(form) |
|
764 |
return redirect('modify_authentication_request') |
|
765 |
|
|
766 |
get_response().breadcrumb.append(('auth_request_http_headers', _('HTTP headers'))) |
|
767 |
self.html_top(_('Configure HTTP headers')) |
|
768 |
|
|
769 |
'<p>%s</p>' % _('''Here are the HTTP headers that will be sent within the authentication |
|
770 |
POST request. You can desactivate some or all of them, or change their value.''') |
|
771 |
|
|
772 |
form.render() |
|
773 |
|
|
774 |
def form_auth_request_http_headers(self): |
|
775 |
form = Form(enctype='multipart/form-data') |
|
776 |
for name, value in self.host.http_headers.iteritems(): |
|
777 |
if value['immutable']: |
|
778 |
form.add(DictWidget, name, value, disabled = 'disabled') |
|
779 |
else: |
|
780 |
form.add(DictWidget, name, value) |
|
781 |
form.add(HtmlWidget, htmltext('<p>%s</p>' % \ |
|
782 |
_('The headers "Host", "Accept-Encoding" and "Content-Length" will also automatically be sent.'))) |
|
783 |
if get_cfg('proxy', {}).get('enabled') and self.host.use_proxy: |
|
784 |
form.add(HtmlWidget, htmltext('<p>%s</p>' % \ |
|
785 |
_('''As Larpe uses a proxy for this site, the headers "Proxy-Authorization", |
|
786 |
"Proxy-Connection" and "Keep-Alive" will be sent as well.'''))) |
|
787 |
form.add_submit('submit', _('Submit')) |
|
788 |
form.add_submit('cancel', _('Cancel')) |
|
789 |
return form |
|
790 |
|
|
791 |
def submit_auth_request_http_headers_form(self, form): |
|
792 |
for name, old_value in self.host.http_headers.iteritems(): |
|
793 |
value = form.get_widget(name).parse() |
|
794 |
if value['enabled'] == 'on': |
|
795 |
old_value['enabled'] = True |
|
796 |
else: |
|
797 |
old_value['enabled'] = False |
|
798 |
if old_value['immutable'] is False: |
|
799 |
old_value['value'] = value['value'] |
|
800 |
self.host.http_headers[name] = old_value |
|
801 |
self.host.store() |
|
802 |
|
|
803 |
def generate_apache_filters(self): |
|
804 |
self.host.apache_python_paths = [] |
|
805 |
self.host.apache_output_python_filters = [] |
|
806 |
site_auth = site_authentication.get_site_authentication(self.host) |
|
807 |
output_filters = site_auth.output_filters |
|
808 |
replace_login_form = self.host.auth_form_places == 'form_everywhere' and \ |
|
809 |
self.host.auth_form_action |
|
810 |
if replace_login_form and not 'output_replace_form' in output_filters: |
|
811 |
output_filters.append('output_replace_form') |
|
812 |
if output_filters: |
|
813 |
location = Location(self.host) |
|
814 |
conf = { 'auth_form_action': self.host.auth_form_action, |
|
815 |
'name': self.host.name, |
|
816 |
'larpe_dir': get_publisher().app_dir, |
|
817 |
'logout_url': location.new_logout_url, |
|
818 |
'login_url': location.new_auth_url } |
|
819 |
# Set Python filter path for Apache configuration |
|
820 |
python_path = os.path.join(self.host.site_dir, 'filters') |
|
821 |
if python_path not in self.host.apache_python_paths: |
|
822 |
self.host.apache_python_paths.append(python_path) |
|
823 |
|
|
824 |
for filter in output_filters: |
|
825 |
python_file = open( |
|
826 |
os.path.join(self.host.site_dir, 'filters', filter + ".py"), |
|
827 |
'w') |
|
828 |
python_file.write( |
|
829 |
open(os.path.join(DATA_DIR, "filters", filter + ".py")).read() % conf |
|
830 |
) |
|
831 |
if not filter in self.host.apache_output_python_filters: |
|
832 |
self.host.apache_output_python_filters.append(filter) |
|
833 |
|
|
834 |
def sso_init_link [html] (self): |
|
835 |
form = self.form_sso_init_link() |
|
836 |
|
|
837 |
if form.get_widget('cancel').parse(): |
|
838 |
return redirect('check_authentication') |
|
839 |
|
|
840 |
if form.is_submitted() and not form.has_errors(): |
|
841 |
self.submit_sso_init_link_form(form) |
|
842 |
if form.get_widget('terminate').parse(): |
|
843 |
return redirect('..') |
|
844 |
return redirect('metadatas') |
|
845 |
|
|
846 |
get_response().breadcrumb.append(('sso_init_link', _('SSO initiation'))) |
|
847 |
self.html_top(_('Step 7 - Configure how a Single Sign On can be initiated')) |
|
848 |
|
|
849 |
'<p>%s\n' % _('Most sites use one of the following 2 ways to allow users to initialise an authentication :') |
|
850 |
'\t<ol>\n' |
|
851 |
'\t\t<li>%s</li>\n' % \ |
|
852 |
_('''The site has a single authentication page. It redirects users to this page when |
|
853 |
they click a "Login" button or try to access a page which require users to be authenticated.''') |
|
854 |
'\t\t<li>%s</li>\n' % \ |
|
855 |
_('''The site includes an authentication form in most or all of his pages. Users can |
|
856 |
authenticate on any of these pages, and don't need to be redirected to a separate authentication page.''') |
|
857 |
'\t</ol>\n' |
|
858 |
'</p>\n' |
|
859 |
|
|
860 |
'<p>%s</p>' % _('Select the way your site works :') |
|
861 |
|
|
862 |
form.render() |
|
863 |
|
|
864 |
def form_sso_init_link(self): |
|
865 |
form = Form(enctype='multipart/form-data') |
|
866 |
form.add(RadiobuttonsWidget, 'auth_form_places', |
|
867 |
options=[ |
|
868 |
('form_once', _('The site has a single authentication page'), 'form_once'), |
|
869 |
('form_everywhere', _('The site includes an authentication form in most or all pages'), 'form_everywhere'), |
|
870 |
], |
|
871 |
sort=False, required = True, delim=htmltext('<br />'), value = self.host.auth_form_places) |
|
872 |
form.add_submit('cancel', _('Previous')) |
|
873 |
form.add_submit('submit', _('Next')) |
|
874 |
form.add_submit('terminate', _('Terminate')) |
|
875 |
return form |
|
876 |
|
|
877 |
def submit_sso_init_link_form(self, form): |
|
878 |
fields = [ 'auth_form_places', ] |
|
879 |
for f in fields: |
|
880 |
setattr(self.host, f, form.get_widget(f).parse()) |
|
881 |
self.host.auth_form_url = self.host.auth_url |
|
882 |
self.generate_apache_filters() |
|
883 |
self.host.store() |
|
884 |
write_apache2_vhosts() |
|
885 |
|
|
886 |
def metadatas [html] (self): |
|
887 |
form = Form(enctype='multipart/form-data') |
|
888 |
form.add_submit('cancel', _('Previous')) |
|
889 |
form.add_submit('submit', _('Next')) |
|
890 |
form.add_submit('terminate', _('Terminate')) |
|
891 |
|
|
892 |
if form.get_widget('cancel').parse(): |
|
893 |
return redirect('sso_init_link') |
|
894 |
|
|
895 |
if form.is_submitted(): |
|
896 |
if form.get_widget('terminate').parse(): |
|
897 |
return redirect('..') |
|
898 |
return redirect('advanced_options') |
|
899 |
|
|
900 |
get_response().breadcrumb.append(('metadatas', _('Metadatas'))) |
|
901 |
self.html_top(_('Step 8 - Metadatas of %(site_name)s' % {'site_name': self.host.name})) |
|
902 |
|
|
903 |
'<p>%s</p>' % \ |
|
904 |
_('''Download the metadatas and the public key for this site and |
|
905 |
upload them on your identity provider in order to use Liberty Alliance features.''') |
|
906 |
|
|
907 |
'<dl>' |
|
908 |
if hasattr(self.host, str('base_url')): |
|
909 |
if lasso.SAML2_SUPPORT: |
|
910 |
saml2_metadata_url = '%s/metadata.xml' % self.host.saml2_base_url |
|
911 |
'<dt><a href="%s">%s</a></dt> <dd>%s</dd>' % ( |
|
912 |
saml2_metadata_url, |
|
913 |
_('SAML 2.0 Metadata'), |
|
914 |
_('Download SAML 2.0 metadata file')) |
|
915 |
metadata_url = '%s/metadata.xml' % self.host.base_url |
|
916 |
'<dt><a href="%s">%s</a></dt> <dd>%s</dd>' % ( |
|
917 |
metadata_url, |
|
918 |
_('ID-FF 1.2 Metadata'), |
|
919 |
_('Download ID-FF 1.2 metadata file')) |
|
920 |
else: |
|
921 |
'<p>%s</p>' % _('No metadata has been generated for this host.') |
|
922 |
|
|
923 |
if hasattr(self.host, str('base_url')) and self.host.public_key and os.path.exists(self.host.public_key): |
|
924 |
public_key_url = '%s/public_key' % self.host.base_url |
|
925 |
'<dt><a href="%s">%s</a></dt> <dd>%s</dd>' % ( |
|
926 |
public_key_url, |
|
927 |
_('Public key'), |
|
928 |
_('Download SSL Public Key file')) |
|
929 |
else: |
|
930 |
'<p>%s</p>' % _('No public key has been generated for this host.') |
|
931 |
'</dl>' |
|
932 |
|
|
933 |
form.render() |
|
934 |
|
|
935 |
def advanced_options [html] (self): |
|
936 |
form = self.form_advanced_options() |
|
937 |
|
|
938 |
if form.get_widget('cancel').parse(): |
|
939 |
return redirect('metadatas') |
|
940 |
|
|
941 |
if not form.is_submitted() or form.has_errors(): |
|
942 |
get_response().breadcrumb.append(('advanced_options', _('Advanced options'))) |
|
943 |
self.html_top(_('Step 9 - Advanced options')) |
|
944 |
|
|
945 |
'<p>%s</p>' % _('Configure advanced options to setup the last details of your site.') |
|
946 |
'<p>%s</p>' % _('''If you don't know what to configure here, just click %(next)s and |
|
947 |
come here later if needed.''') % {'next': _('Next')} |
|
948 |
|
|
949 |
form.render() |
|
950 |
else: |
|
951 |
self.submit_advanced_options_form(form) |
|
952 |
if form.get_widget('terminate').parse(): |
|
953 |
return redirect('..') |
|
954 |
return redirect('check_full_configuration') |
|
955 |
|
|
956 |
def form_advanced_options(self): |
|
957 |
form = Form(enctype='multipart/form-data') |
|
958 |
form.add(CheckboxWidget, 'redirect_root_to_login', |
|
959 |
title=_('Redirect the root URL of the site to the login page.'), |
|
960 |
value = self.host.redirect_root_to_login) |
|
961 |
form.add(UrlOrAbsPathWidget, 'return_url', title = _('Return address'), |
|
962 |
hint = _('Where the user will be redirected after a successful authentication'), |
|
963 |
required = False, size = 50, value = self.host.return_url) |
|
964 |
form.add(UrlOrAbsPathWidget, 'root_url', title = _('Error address'), |
|
965 |
hint = _('Where the user will be redirected after a disconnection or an error'), |
|
966 |
required = False, size = 50, value = self.host.root_url) |
|
967 |
form.add(UrlOrAbsPathWidget, 'initiate_sso_url', title = _('URL which must initiate the SSO'), |
|
968 |
hint = _('''Address which must initiate the SSO. If empty, defaults to the previously |
|
969 |
specified "%s"''') % _('Authentication form page address'), |
|
970 |
required = False, size = 50, value = self.host.initiate_sso_url) |
|
971 |
form.add(CheckboxWidget, 'proxy-html', title = _('Apache HTML proxy'), |
|
972 |
hint = _('''Converts urls in the HTML pages according to the host new domain name. |
|
973 |
Disabled by default because it makes some sites not work correctly.'''), |
|
974 |
value = 'proxy-html' in self.host.apache_output_filters) |
|
975 |
|
|
976 |
form.add_submit('cancel', _('Previous')) |
|
977 |
form.add_submit('submit', _('Next')) |
|
978 |
form.add_submit('terminate', _('Terminate')) |
|
979 |
return form |
|
980 |
|
|
981 |
def submit_advanced_options_form(self, form): |
|
982 |
old_redirect_root_to_login = self.host.redirect_root_to_login |
|
983 |
|
|
984 |
for f in ('redirect_root_to_login', 'return_url', 'root_url', 'initiate_sso_url'): |
|
985 |
value = form.get_widget(f).parse() |
|
986 |
setattr(self.host, f, value) |
|
987 |
|
|
988 |
f = 'proxy-html' |
|
989 |
value = form.get_widget(f).parse() |
|
990 |
if value is True and f not in self.host.apache_output_filters: |
|
991 |
self.host.apache_output_filters.append(f) |
|
992 |
if value is False and f in self.host.apache_output_filters: |
|
993 |
self.host.apache_output_filters.remove(f) |
|
994 |
|
|
995 |
self.host.store() |
|
996 |
|
|
997 |
if self.host.initiate_sso_url or self.host.redirect_root_to_login is not old_redirect_root_to_login: |
|
998 |
write_apache2_vhosts() |
|
999 |
|
|
1000 |
def check_full_configuration [html] (self): |
|
1001 |
form = Form(enctype='multipart/form-data') |
|
1002 |
form.add_submit('cancel', _('Previous')) |
|
1003 |
form.add_submit('submit', _('Finish')) |
|
1004 |
|
|
1005 |
if form.get_widget('cancel').parse(): |
|
1006 |
return redirect('advanced_options') |
|
1007 |
|
|
1008 |
if form.is_submitted(): |
|
1009 |
return redirect('../..') |
|
1010 |
|
|
1011 |
get_response().breadcrumb.append(('check_full_configuration', _('Check everything works'))) |
|
1012 |
self.html_top(_('Step 10 - Check everything works')) |
|
1013 |
|
|
1014 |
'<p>%s</p>' % \ |
|
1015 |
_('''Now you can fully test your site, start from the home page, initiate a |
|
1016 |
Single Sign On, federate your identities and do a Single Logout.''') |
|
1017 |
|
|
1018 |
'<p>%s' % _('The address of your site is : ') |
|
1019 |
'<a href="%s">%s</a>' % (self.host.new_url, self.host.new_url) |
|
1020 |
'</p>' |
|
1021 |
|
|
1022 |
'<p>%s</p>' % \ |
|
1023 |
_('''If everything works, click the "%(finish)s" button, otherwise you can go |
|
1024 |
back and check your settings.''') % { 'finish': _('Finish') } |
|
1025 |
|
|
1026 |
form.render() |
|
1027 |
|
|
1028 |
def auto_detect_configuration(self): |
|
1029 |
# Reset previous detected values |
|
1030 |
self.host.auth_form = None |
|
1031 |
self.host.auth_check_url = None |
|
1032 |
self.host.login_field_name = None |
|
1033 |
self.host.password_field_name = None |
|
1034 |
if not self.host.post_parameters: |
|
1035 |
self.host.post_parameters = {} |
|
1036 |
|
|
1037 |
self.parse_page(self.host.auth_form_url) |
|
1038 |
|
|
1039 |
def parse_page(self, page_url): |
|
1040 |
# Get the authentication page |
|
1041 |
try: |
|
1042 |
response, status, page, auth_header = http_get_page(page_url, use_proxy=self.host.use_proxy) |
|
1043 |
except Exception, msg: |
|
1044 |
print msg |
|
1045 |
return |
|
1046 |
|
|
1047 |
if page is None: |
|
1048 |
return |
|
1049 |
#raise FormError, ('auth_check_url', '%s : %s' % (_('Failed to get page'), self.host.auth_form_url)) |
|
1050 |
|
|
1051 |
# Default authentication mode |
|
1052 |
self.host.auth_mode = 'form' |
|
1053 |
|
|
1054 |
if not self.host.site_authentication_plugin: |
|
1055 |
self.host.site_authentication_plugin = site_authentication_plugins.auto_detect(page) |
|
1056 |
self.parse_frames(page) |
|
1057 |
self.parse_forms(page) |
|
1058 |
if self.host.auth_form is not None: |
|
1059 |
self.parse_form_action() |
|
1060 |
input_fields = self.parse_input_fields() |
|
1061 |
self.parse_login_field(input_fields) |
|
1062 |
self.parse_password_field() |
|
1063 |
self.parse_select_fields() |
|
1064 |
self.parse_other_fields() |
|
1065 |
|
|
1066 |
def parse_frames(self, page): |
|
1067 |
'''If there are frames, parse them recursively''' |
|
1068 |
regexp = re.compile("""<frame.*?src=["'](.*?)["'][^>]*?>""", re.DOTALL | re.IGNORECASE) |
|
1069 |
found_frames = regexp.findall(page) |
|
1070 |
if found_frames: |
|
1071 |
for frame_url in found_frames: |
|
1072 |
if frame_url.startswith('http'): |
|
1073 |
frame_full_url = frame_url |
|
1074 |
else: |
|
1075 |
page_url_tokens = frame_url.split('/') |
|
1076 |
page_url_tokens[-1] = frame_url |
|
1077 |
frame_full_url = '/'.join(page_url_tokens) |
|
1078 |
self.parse_page(frame_full_url) |
|
1079 |
|
|
1080 |
def parse_forms(self, page): |
|
1081 |
'''Search for an authentication form''' |
|
1082 |
# Get all forms |
|
1083 |
regexp = re.compile("""<form.*?</form>""", re.DOTALL | re.IGNORECASE) |
|
1084 |
found_forms = regexp.findall(page) |
|
1085 |
if not found_forms: |
|
1086 |
return |
|
1087 |
#raise FormError, ('auth_check_url', '%s : %s' % (_('Failed to find any form'), self.host.auth_form_url)) |
|
1088 |
|
|
1089 |
# Get the first form with a password field |
|
1090 |
for found_form in found_forms: |
|
1091 |
regexp = re.compile("""<input[^>]*?type=["']?password["']?[^>]*?>""", re.DOTALL | re.IGNORECASE) |
|
1092 |
if regexp.search(found_form) is not None: |
|
1093 |
self.host.auth_form = found_form |
|
1094 |
break |
|
1095 |
|
|
1096 |
def parse_form_action(self): |
|
1097 |
'''Get the action url of the form''' |
|
1098 |
regexp = re.compile("""<form.*?action=["']?(.*?)["']?[\s>].*?>""", re.DOTALL | re.IGNORECASE) |
|
1099 |
self.host.auth_form_action = regexp.findall(self.host.auth_form)[0] |
|
1100 |
# FIXME: Find a Python module which unescapes html entities |
|
1101 |
self.host.auth_check_url = self.host.auth_form_action.replace('&', '&') |
|
1102 |
if not self.host.auth_check_url.startswith('http'): |
|
1103 |
if self.host.auth_check_url.startswith('/'): |
|
1104 |
if self.host.orig_site.startswith('https'): |
|
1105 |
orig_site_root = 'https://%s' % urllib.splithost(self.host.orig_site[6:])[0] |
|
1106 |
else: |
|
1107 |
orig_site_root = 'http://%s' % urllib.splithost(self.host.orig_site[5:])[0] |
|
1108 |
self.host.auth_check_url = orig_site_root + self.host.auth_check_url |
|
1109 |
else: |
|
1110 |
auth_form_url_tokens = self.host.auth_form_url.split('/') |
|
1111 |
auth_form_url_tokens[-1] = self.host.auth_check_url |
|
1112 |
self.host.auth_check_url = '/'.join(auth_form_url_tokens) |
|
1113 |
|
|
1114 |
def parse_input_fields(self): |
|
1115 |
'''Get all input fields''' |
|
1116 |
regexp = re.compile("""<input[^>]*?>""", re.DOTALL | re.IGNORECASE) |
|
1117 |
return regexp.findall(self.host.auth_form) |
|
1118 |
|
|
1119 |
def parse_login_field(self, input_fields): |
|
1120 |
'''Get login field name''' |
|
1121 |
try: |
|
1122 |
regexp = re.compile("""<input[^>]*?type=["']?text["']?[^>]*?>""", re.DOTALL | re.IGNORECASE) |
|
1123 |
text_fields = regexp.findall(self.host.auth_form) |
|
1124 |
login_field = '' |
|
1125 |
if text_fields: |
|
1126 |
login_field = text_fields[0] |
|
1127 |
else: |
|
1128 |
for field in input_fields: |
|
1129 |
if re.search("""type=["']?""", field, re.DOTALL | re.IGNORECASE) is None: |
|
1130 |
login_field = field |
|
1131 |
break |
|
1132 |
regexp = re.compile("""name=["']?(.*?)["']?[\s/>]""", re.DOTALL | re.IGNORECASE) |
|
1133 |
self.host.login_field_name = regexp.findall(login_field)[0] |
|
1134 |
if not self.host.post_parameters.has_key(self.host.login_field_name): |
|
1135 |
self.host.post_parameters[self.host.login_field_name] = \ |
|
1136 |
{ 'enabled': True, 'value': _('(filled by users)'), 'immutable': True } |
|
1137 |
self.host.store() |
|
1138 |
except IndexError, e: |
|
1139 |
self.host.login_field_name = None |
|
1140 |
print 'Error handling login field : %s' % e |
|
1141 |
|
|
1142 |
def parse_password_field(self): |
|
1143 |
'''Get password field name''' |
|
1144 |
try: |
|
1145 |
regexp = re.compile("""<input[^>]*?type=["']?password["']?[^>]*?>""", re.DOTALL | re.IGNORECASE) |
|
1146 |
password_field = regexp.findall(self.host.auth_form)[0] |
|
1147 |
regexp = re.compile("""name=["']?(.*?)["']?[\s/>]""", re.DOTALL | re.IGNORECASE) |
|
1148 |
self.host.password_field_name = regexp.findall(password_field)[0] |
|
1149 |
if not self.host.post_parameters.has_key(self.host.password_field_name): |
|
1150 |
self.host.post_parameters[self.host.password_field_name] = \ |
|
1151 |
{ 'enabled': True, 'value': _('(filled by users)'), 'immutable': True } |
|
1152 |
except IndexError, e: |
|
1153 |
self.host.password_field_name = None |
|
1154 |
print 'Error handling password field : %s' % e |
|
1155 |
|
|
1156 |
def parse_select_fields(self): |
|
1157 |
'''Add select fields to host attributes''' |
|
1158 |
# First added for Imuse (Rennes) |
|
1159 |
regexp = re.compile("""<select.*?</select>""", re.DOTALL | re.IGNORECASE) |
|
1160 |
self.host.select_fields = {} |
|
1161 |
for field in regexp.findall(self.host.auth_form): |
|
1162 |
try: |
|
1163 |
regexp = re.compile("""name=["']?(.*?)["']?[\s/>]""", re.DOTALL | re.IGNORECASE) |
|
1164 |
name = regexp.findall(field)[0] |
|
1165 |
regexp = re.compile("""<option[^>]*?>.*?</option>""", re.DOTALL | re.IGNORECASE) |
|
1166 |
options = regexp.findall(field) |
|
1167 |
values = [] |
|
1168 |
for option in options: |
|
1169 |
regexp = re.compile("""<option[^>]*?>(.*?)</option>""", re.DOTALL | re.IGNORECASE) |
|
1170 |
option_label = regexp.findall(option) |
|
1171 |
regexp = re.compile("""value=["']?(.*?)["']?[\s/>]""", re.DOTALL | re.IGNORECASE) |
|
1172 |
option_value = regexp.findall(option) |
|
1173 |
if option_label: |
|
1174 |
if not option_value: |
|
1175 |
option_value = option_label |
|
1176 |
values.append((option_value[0], option_label[0])) |
|
1177 |
else: |
|
1178 |
print >> sys.stderr, 'W: Could not parse select options' |
|
1179 |
self.host.select_fields[name] = values |
|
1180 |
if not self.host.post_parameters.has_key(name): |
|
1181 |
self.host.post_parameters[name] = \ |
|
1182 |
{ 'enabled': True, 'value': _('(filled by users)'), 'immutable': True } |
|
1183 |
except IndexError, e: |
|
1184 |
continue |
|
1185 |
|
|
1186 |
def parse_other_fields(self): |
|
1187 |
'''Get the default value of all other fields''' |
|
1188 |
self.host.other_fields = {} |
|
1189 |
|
|
1190 |
# Get hidden fields |
|
1191 |
regexp = re.compile("""<input[^>]*?type=["']?hidden["']?[^>]*?>""", re.DOTALL | re.IGNORECASE) |
|
1192 |
other_fields = regexp.findall(self.host.auth_form) |
|
1193 |
|
|
1194 |
# Only get first submit field |
|
1195 |
regexp = re.compile("""<input[^>]*?type=["']?submit["']?[^>]*?>""", re.DOTALL | re.IGNORECASE) |
|
1196 |
found = regexp.findall(self.host.auth_form) |
|
1197 |
if found: |
|
1198 |
if other_fields: |
|
1199 |
other_fields.append(found[0]) |
|
1200 |
else: |
|
1201 |
other_fields = found[0] |
|
1202 |
|
|
1203 |
for field in other_fields: |
|
1204 |
try: |
|
1205 |
regexp = re.compile("""name=["']?(.*?)["']?[\s/>]""", re.DOTALL | re.IGNORECASE) |
|
1206 |
name = regexp.findall(field)[0] |
|
1207 |
regexp = re.compile("""value=["'](.*?)["'][\s/>]""", re.DOTALL | re.IGNORECASE) |
|
1208 |
value = regexp.findall(field)[0] |
|
1209 |
self.host.other_fields[name] = value |
|
1210 |
if not self.host.post_parameters.has_key(name): |
|
1211 |
self.host.post_parameters[name] = { 'enabled': True, 'value': value, 'immutable': False } |
|
1212 |
except IndexError, e: |
|
1213 |
continue |
|
1214 |
|
|
1215 |
|
|
1216 |
class HostPage(Directory): |
|
1217 |
_q_exports = ['', 'delete'] |
|
1218 |
|
|
1219 |
def __init__(self, host_id): |
|
1220 |
self.host = Host.get(host_id) |
|
1221 |
get_response().breadcrumb.append((host_id + '/', self.host.label)) |
|
1222 |
|
|
1223 |
def _q_lookup(self, component): |
|
1224 |
if component == 'configuration_assistant': |
|
1225 |
return ConfigurationAssistant(self.host) |
|
1226 |
elif component == 'forms_prefill': |
|
1227 |
return FormsDirectory(self.host) |
|
1228 |
|
|
1229 |
def _q_index [html] (self): |
|
1230 |
get_publisher().reload_cfg() |
|
1231 |
html_top('hosts', title = self.host.label) |
|
1232 |
|
|
1233 |
'<h2>%s</h2>' % _('Configuration assistant') |
|
1234 |
|
|
1235 |
'<dl>' |
|
1236 |
|
|
1237 |
'<dt><a href="configuration_assistant/start">%s</a></dt> <dd>%s</dd>' % ( |
|
1238 |
_('Address of the original site'), _('Configure the root address of the site')) |
|
1239 |
|
|
1240 |
'<dt><a href="configuration_assistant/check_new_address">%s</a></dt> <dd>%s</dd>' % ( |
|
1241 |
_('New address and name'), _('Configure the new address and name of this site')) |
|
1242 |
|
|
1243 |
'<dt><a href="configuration_assistant/authentication_and_logout_adresses">%s</a></dt> <dd>%s</dd>' % ( |
|
1244 |
_('Authentication and logout addresses'), _('Configure the authentication and logout addresses of the original site')) |
|
1245 |
|
|
1246 |
'<dt><a href="configuration_assistant/check_auto_detected_configuration">%s</a></dt> <dd>%s</dd>' % ( |
|
1247 |
_('Check auto detected configuration'), _('Check the automatically detected configuration is right')) |
|
1248 |
|
|
1249 |
'<dt><a href="configuration_assistant/credentials">%s</a></dt> <dd>%s</dd>' % ( |
|
1250 |
_('Credentials'), _('Configure some valid credentials to authenticate on the original site')) |
|
1251 |
|
|
1252 |
'<dt><a href="configuration_assistant/send_authentication_request">%s</a></dt> <dd>%s</dd>' % ( |
|
1253 |
_('Retry authentication'), _('Retry sending an authentication request to the site to check if your new parameters work well')) |
|
1254 |
|
|
1255 |
'<dt><a href="configuration_assistant/see_authentication_response">%s</a></dt> <dd>%s</dd>' % ( |
|
1256 |
_('Check authentication response'), _('Check the response from the latest authentication request')) |
|
1257 |
|
|
1258 |
'<dt><a href="configuration_assistant/authentication_success_criteria">%s</a></dt> <dd>%s</dd>' % ( |
|
1259 |
_('Configure authentication success criteria'), _('Specify how Larpe knows if the authentication has succeeded or not')) |
|
1260 |
|
|
1261 |
'<dt><a href="configuration_assistant/modify_authentication_request">%s</a></dt> <dd>%s</dd>' % ( |
|
1262 |
_('Modify authentication request'), _('Modify POST fields or HTTP headers of the authentication request')) |
|
1263 |
|
|
1264 |
'<dt><a href="configuration_assistant/sso_init_link">%s</a></dt> <dd>%s</dd>' % ( |
|
1265 |
_('Configure how a Single Sign On can be initiated'), _('Configure how a Single Sign On can be initiated')) |
|
1266 |
|
|
1267 |
'<dt><a href="configuration_assistant/metadatas">%s</a></dt> <dd>%s</dd>' % ( |
|
1268 |
_('Metadatas and key'), _('Download SAML 2.0 or ID-FF metadatas and SSL public key')) |
|
1269 |
|
|
1270 |
'<dt><a href="configuration_assistant/advanced_options">%s</a></dt> <dd>%s</dd>' % ( |
|
1271 |
_('Adavanced options'), _('Configure advanced options to setup the last details of your site')) |
|
1272 |
|
|
1273 |
'</dl>' |
|
1274 |
|
|
1275 |
'<h2>%s</h2>' % _('Form prefilling with ID-WSF') |
|
1276 |
|
|
1277 |
'<dl>' |
|
1278 |
'<dt><a href="forms_prefill/">%s</a></dt> <dd>%s</dd>' % ( |
|
1279 |
_('Forms'), _('Configure the forms to prefill')) |
|
1280 |
'</dl>' |
|
1281 |
|
|
1282 |
def delete [html] (self): |
|
1283 |
form = Form(enctype='multipart/form-data') |
|
1284 |
form.widgets.append(HtmlWidget('<p>%s</p>' % _( |
|
1285 |
'You are about to irrevocably delete this host.'))) |
|
1286 |
form.add_submit('submit', _('Submit')) |
|
1287 |
form.add_submit('cancel', _('Cancel')) |
|
1288 |
if form.get_widget('cancel').parse(): |
|
1289 |
return redirect('..') |
|
1290 |
if not form.is_submitted() or form.has_errors(): |
|
1291 |
get_response().breadcrumb.append(('delete', _('Delete'))) |
|
1292 |
html_top('hosts', title = _('Delete Host')) |
|
1293 |
'<h2>%s : %s</h2>' % (_('Delete Host'), self.host.label) |
|
1294 |
form.render() |
|
1295 |
else: |
|
1296 |
self.host.remove_self() |
|
1297 |
write_apache2_vhosts() |
|
1298 |
return redirect('..') |
|
1299 |
|
|
1300 |
|
|
1301 |
class HostsDirectory(Directory): |
|
1302 |
_q_exports = ['', 'new'] |
|
1303 |
|
|
1304 |
def _q_index [html] (self): |
|
1305 |
get_response().breadcrumb.append(('hosts/', _('Hosts'))) |
|
1306 |
html_top('hosts', title = _('Hosts')) |
|
1307 |
"""<ul id="nav-hosts-admin"> |
|
1308 |
<li><a href="new">%s</a></li> |
|
1309 |
</ul>""" % _('New Host') |
|
1310 |
|
|
1311 |
'<ul class="biglist">' |
|
1312 |
|
|
1313 |
for host in Host.select(lambda x: x.name != 'larpe', order_by = 'label'): |
|
1314 |
if not host.name: |
|
1315 |
continue |
|
1316 |
if not hasattr(host, str('scheme')): |
|
1317 |
host.scheme = str('http') |
|
1318 |
'<li>' |
|
1319 |
'<strong class="label">%s</strong>' % host.label |
|
1320 |
if hasattr(host, str('new_url')) and host.new_url: |
|
1321 |
url = host.new_url |
|
1322 |
else: |
|
1323 |
# Compat with older Larpe versions |
|
1324 |
url = '%s://%s%s/' % (host.scheme, host.reversed_hostname, get_request().environ['SCRIPT_NAME']) |
|
1325 |
if host.reversed_directory is not None: |
|
1326 |
url += '%s/' % host.reversed_directory |
|
1327 |
'<br /><a href="%s">%s</a>' % (url, url) |
|
1328 |
'<p class="commands">' |
|
1329 |
command_icon('%s/' % host.id, 'edit') |
|
1330 |
command_icon('%s/delete' % host.id, 'remove') |
|
1331 |
'</p></li>' |
|
1332 |
'</ul>' |
|
1333 |
|
|
1334 |
def new [html] (self): |
|
1335 |
if not os.path.isdir(os.path.join(get_publisher().app_dir, str('idp'))): |
|
1336 |
html_top('hosts', title = _('New Host')) |
|
1337 |
html = '<h2>%s</h2>' % _('New Host') |
|
1338 |
html += 'You must <a href="%s/admin/settings/liberty_idp/">' % misc.get_root_url() |
|
1339 |
html += 'configure an Identity Provider</a> first<br /><br />' |
|
1340 |
html += '<a href="."><input type="button" value="%s" /></a>' % _('Back') |
|
1341 |
return html |
|
1342 |
|
|
1343 |
get_response().breadcrumb.append(('hosts/', _('Hosts'))) |
|
1344 |
get_response().breadcrumb.append(('new', _('New')) ) |
|
1345 |
host = Host() |
|
1346 |
host.store() |
|
1347 |
return redirect('%s/configuration_assistant/start' % host.id) |
|
1348 |
|
|
1349 |
def _q_lookup(self, component): |
|
1350 |
get_response().breadcrumb.append(('hosts/', _('Hosts'))) |
|
1351 |
return HostPage(component) |
|
1352 |
|
larpe/tags/release-1.1.1/larpe/admin/liberty_utils.py | ||
---|---|---|
1 |
import os |
|
2 |
|
|
3 |
def set_provider_keys(private_key_path, public_key_path): |
|
4 |
# use system calls for openssl since PyOpenSSL doesn't expose the |
|
5 |
# necessary functions. |
|
6 |
if os.system('openssl version > /dev/null 2>&1') == 0: |
|
7 |
os.system('openssl genrsa -out %s 2048' % private_key_path) |
|
8 |
os.system('openssl rsa -in %s -pubout -out %s' % (private_key_path, public_key_path)) |
|
9 |
|
|
10 |
|
|
11 |
def get_metadata(cfg): |
|
12 |
prologue = """\ |
|
13 |
<?xml version="1.0"?> |
|
14 |
<EntityDescriptor |
|
15 |
providerID="%(provider_id)s" |
|
16 |
xmlns="urn:liberty:metadata:2003-08">""" % cfg |
|
17 |
|
|
18 |
sp_head = """ |
|
19 |
<SPDescriptor protocolSupportEnumeration="urn:liberty:iff:2003-08">""" |
|
20 |
|
|
21 |
signing_public_key = '' |
|
22 |
if cfg.has_key('signing_public_key') and cfg['signing_public_key']: |
|
23 |
if 'CERTIF' in cfg['signing_public_key']: |
|
24 |
signing_public_key = """ |
|
25 |
<KeyDescriptor use="signing"> |
|
26 |
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> |
|
27 |
<ds:X509Data><ds:X509Certificate>%s</ds:X509Certificate></ds:X509Data> |
|
28 |
</ds:KeyInfo> |
|
29 |
</KeyDescriptor>""" % cfg['signing_public_key'] |
|
30 |
elif 'KEY' in cfg['signing_public_key']: |
|
31 |
signing_public_key = """ |
|
32 |
<KeyDescriptor use="signing"> |
|
33 |
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> |
|
34 |
<ds:KeyValue>%s</ds:KeyValue> |
|
35 |
</ds:KeyInfo> |
|
36 |
</KeyDescriptor>""" % cfg['signing_public_key'] |
|
37 |
|
|
38 |
sp_body = """ |
|
39 |
<AssertionConsumerServiceURL id="AssertionConsumerServiceURL1" isDefault="true">%(base_url)s/assertionConsumer</AssertionConsumerServiceURL> |
|
40 |
|
|
41 |
<SoapEndpoint>%(base_url)s/soapEndpoint</SoapEndpoint> |
|
42 |
|
|
43 |
<SingleLogoutServiceURL>%(base_url)s/singleLogout</SingleLogoutServiceURL> |
|
44 |
<SingleLogoutServiceReturnURL>%(base_url)s/singleLogoutReturn</SingleLogoutServiceReturnURL> |
|
45 |
<SingleLogoutProtocolProfile>http://projectliberty.org/profiles/slo-idp-http</SingleLogoutProtocolProfile> |
|
46 |
<SingleLogoutProtocolProfile>http://projectliberty.org/profiles/slo-sp-soap</SingleLogoutProtocolProfile> |
|
47 |
<SingleLogoutProtocolProfile>http://projectliberty.org/profiles/slo-sp-http</SingleLogoutProtocolProfile> |
|
48 |
|
|
49 |
<FederationTerminationServiceURL>%(base_url)s/federationTermination</FederationTerminationServiceURL> |
|
50 |
<FederationTerminationServiceReturnURL>%(base_url)s/federationTerminationReturn</FederationTerminationServiceReturnURL> |
|
51 |
<FederationTerminationNotificationProtocolProfile>http://projectliberty.org/profiles/fedterm-idp-soap</FederationTerminationNotificationProtocolProfile> |
|
52 |
<FederationTerminationNotificationProtocolProfile>http://projectliberty.org/profiles/fedterm-idp-http</FederationTerminationNotificationProtocolProfile> |
|
53 |
<FederationTerminationNotificationProtocolProfile>http://projectliberty.org/profiles/fedterm-sp-soap</FederationTerminationNotificationProtocolProfile> |
|
54 |
<FederationTerminationNotificationProtocolProfile>http://projectliberty.org/profiles/fedterm-sp-http</FederationTerminationNotificationProtocolProfile> |
|
55 |
|
|
56 |
<AuthnRequestsSigned>true</AuthnRequestsSigned> |
|
57 |
|
|
58 |
</SPDescriptor>""" % cfg |
|
59 |
|
|
60 |
orga = '' |
|
61 |
if cfg.get('organization_name'): |
|
62 |
orga = """ |
|
63 |
<Organization> |
|
64 |
<OrganizationName>%s</OrganizationName> |
|
65 |
</Organization>""" % unicode(cfg['organization_name'], 'iso-8859-1').encode('utf-8') |
|
66 |
|
|
67 |
epilogue = """ |
|
68 |
</EntityDescriptor>""" |
|
69 |
|
|
70 |
return '\n'.join([prologue, sp_head, signing_public_key, sp_body, orga, epilogue]) |
|
71 |
|
|
72 |
|
|
73 |
|
|
74 |
def get_saml2_metadata(cfg): |
|
75 |
prologue = """\ |
|
76 |
<?xml version="1.0"?> |
|
77 |
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" |
|
78 |
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" |
|
79 |
xmlns:ds="http://www.w3.org/2000/09/xmldsig#" |
|
80 |
entityID="%(saml2_provider_id)s">""" % cfg |
|
81 |
|
|
82 |
sp_head = """ |
|
83 |
<SPSSODescriptor |
|
84 |
AuthnRequestsSigned="true" |
|
85 |
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">""" |
|
86 |
|
|
87 |
signing_public_key = '' |
|
88 |
if cfg.has_key('signing_public_key') and cfg['signing_public_key']: |
|
89 |
if 'CERTIF' in cfg['signing_public_key']: |
|
90 |
signing_public_key = """ |
|
91 |
<KeyDescriptor use="signing"> |
|
92 |
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> |
|
93 |
<ds:X509Data><ds:X509Certificate>%s</ds:X509Certificate></ds:X509Data> |
|
94 |
</ds:KeyInfo> |
|
95 |
</KeyDescriptor>""" % cfg['signing_public_key'] |
|
96 |
elif 'KEY' in cfg['signing_public_key']: |
|
97 |
signing_public_key = """ |
|
98 |
<KeyDescriptor use="signing"> |
|
99 |
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> |
|
100 |
<ds:KeyValue>%s</ds:KeyValue> |
|
101 |
</ds:KeyInfo> |
|
102 |
</KeyDescriptor>""" % cfg['signing_public_key'] |
|
103 |
|
|
104 |
sp_body = """ |
|
105 |
<AssertionConsumerService isDefault="true" index="0" |
|
106 |
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" |
|
107 |
Location="%(saml2_base_url)s/singleSignOnArtifact" /> |
|
108 |
<SingleLogoutService |
|
109 |
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" |
|
110 |
Location="%(saml2_base_url)s/singleLogoutSOAP" /> |
|
111 |
<SingleLogoutService |
|
112 |
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" |
|
113 |
Location="%(saml2_base_url)s/singleLogout" |
|
114 |
ResponseLocation="%(saml2_base_url)s/singleLogoutReturn" /> |
|
115 |
|
|
116 |
</SPSSODescriptor>""" % cfg |
|
117 |
|
|
118 |
orga = '' |
|
119 |
if cfg.get('organization_name'): |
|
120 |
orga = """ |
|
121 |
<Organization> |
|
122 |
<OrganizationName>%s</OrganizationName> |
|
123 |
</Organization>""" % unicode(cfg['organization_name'], 'iso-8859-1').encode('utf-8') |
|
124 |
|
|
125 |
epilogue = """ |
|
126 |
</EntityDescriptor>""" |
|
127 |
|
|
128 |
return '\n'.join([prologue, sp_head, signing_public_key, sp_body, orga, epilogue]) |
|
129 |
|
larpe/tags/release-1.1.1/larpe/admin/root.ptl | ||
---|---|---|
1 |
import os |
|
2 |
|
|
3 |
import lasso |
|
4 |
|
|
5 |
from quixote import get_session, get_session_manager, get_publisher, get_request, get_response |
|
6 |
from quixote.directory import Directory, AccessControlled |
|
7 |
|
|
8 |
from qommon.admin.menu import html_top |
|
9 |
from qommon.admin import logger |
|
10 |
|
|
11 |
from larpe import errors |
|
12 |
from larpe import misc |
|
13 |
|
|
14 |
import hosts |
|
15 |
import users |
|
16 |
import settings |
|
17 |
|
|
18 |
def gpl [html] (): |
|
19 |
"""<p>This program is free software; you can redistribute it and/or modify it |
|
20 |
under the terms of the GNU General Public License as published by the Free |
|
21 |
Software Foundation; either version 2 of the License, or (at your option) |
|
22 |
any later version.</p> |
|
23 |
|
|
24 |
<p>This program is distributed in the hope that it will be useful, but |
|
25 |
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
|
26 |
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
27 |
for more details.</p> |
|
28 |
|
|
29 |
<p>You should have received a copy of the GNU General Public License along with |
|
30 |
this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
|
31 |
Place - Suite 330, Boston, MA 02111-1307, USA.</p> |
|
32 |
""" |
|
33 |
|
|
34 |
|
|
35 |
class RootDirectory(AccessControlled, Directory): |
|
36 |
_q_exports = ['', 'hosts', 'users', 'settings', 'logger'] |
|
37 |
|
|
38 |
hosts = hosts.HostsDirectory() |
|
39 |
users = users.UsersDirectory() |
|
40 |
settings = settings.SettingsDirectory() |
|
41 |
logger = logger.LoggerDirectory() |
|
42 |
|
|
43 |
menu_items = [ |
|
44 |
('hosts/', N_('Hosts')), |
|
45 |
('users/', N_('Users')), |
|
46 |
('settings/', N_('Settings')), |
|
47 |
('logger/', N_('Logs')), |
|
48 |
('/', N_('Liberty Alliance Reverse Proxy'))] |
|
49 |
|
|
50 |
def _q_access(self): |
|
51 |
# FIXME : this block should be moved somewhere else |
|
52 |
get_publisher().reload_cfg() |
|
53 |
if not get_publisher().cfg.has_key('proxy_hostname'): |
|
54 |
get_publisher().cfg['proxy_hostname'] = get_request().get_server().split(':')[0] |
|
55 |
get_publisher().write_cfg() |
|
56 |
|
|
57 |
response = get_response() |
|
58 |
if not hasattr(response, 'breadcrumb'): |
|
59 |
response.breadcrumb = [ ('../admin/', _('Administration')) ] |
|
60 |
|
|
61 |
# Cheater |
|
62 |
if os.path.exists(os.path.join(get_publisher().app_dir, 'ADMIN_FOR_ALL')): |
|
63 |
return |
|
64 |
|
|
65 |
# No admin user created yet, free access |
|
66 |
user_list = users.User.select(lambda x: x.is_admin) |
|
67 |
if not user_list: |
|
68 |
return |
|
69 |
|
|
70 |
host_list = hosts.Host.select(lambda x: x.name == 'larpe') |
|
71 |
if host_list: |
|
72 |
host = host_list[0] |
|
73 |
else: |
|
74 |
raise errors.AccessForbiddenError() |
|
75 |
|
|
76 |
if misc.get_current_protocol() == lasso.PROTOCOL_SAML_2_0: |
|
77 |
user = get_session().get_user(host.saml2_provider_id) |
|
78 |
else: |
|
79 |
user = get_session().get_user(host.provider_id) |
|
80 |
if user: |
|
81 |
if not user.name or not user.is_admin: |
|
82 |
raise errors.AccessForbiddenError() |
|
83 |
else: |
|
84 |
raise errors.AccessUnauthorizedError() |
|
85 |
|
|
86 |
|
|
87 |
def _q_index [html] (self): |
|
88 |
html_top('') |
|
89 |
gpl() |
|
90 |
|
larpe/tags/release-1.1.1/larpe/admin/settings.ptl | ||
---|---|---|
1 |
import cStringIO |
|
2 |
import cPickle |
|
3 |
import re |
|
4 |
import os |
|
5 |
import lasso |
|
6 |
import glob |
|
7 |
import zipfile |
|
8 |
|
|
9 |
from quixote import get_publisher, get_request, get_response, redirect |
|
10 |
from quixote.directory import Directory, AccessControlled |
|
11 |
|
|
12 |
from qommon.form import * |
|
13 |
from qommon.misc import get_abs_path |
|
14 |
from qommon.admin.cfg import cfg_submit |
|
15 |
from qommon.admin.menu import html_top, error_page |
|
16 |
from qommon.admin.emails import EmailsDirectory as QommonEmailsDirectory |
|
17 |
from qommon.admin.settings import SettingsDirectory as QommonSettingsDirectory |
|
18 |
|
|
19 |
from larpe import misc |
|
20 |
from larpe.hosts import Host |
|
21 |
from larpe.admin.liberty_utils import * |
|
22 |
|
|
23 |
class LibertyIDPDir(Directory): |
|
24 |
_q_exports = ['', ('metadata.xml', 'metadata')] |
|
25 |
|
|
26 |
def _q_index [html] (self): |
|
27 |
form = Form(enctype="multipart/form-data") |
|
28 |
form.add(FileWidget, "metadata", title = _("Metadata"), required=True) |
|
29 |
form.add(FileWidget, "publickey", title = _("Public Key"), required=False) |
|
30 |
form.add(FileWidget, "cacertchain", title = _("CA Certificate Chain"), required=False) |
|
31 |
form.add_submit("submit", _("Submit")) |
|
32 |
|
|
33 |
if not form.is_submitted() or form.has_errors(): |
|
34 |
html_top('settings', title = _('New Identity Provider')) |
|
35 |
"<h2>%s</h2>" % _('New Identity Provider') |
|
36 |
form.render() |
|
37 |
else: |
|
38 |
self.submit_new(form) |
|
39 |
|
|
40 |
def submit_new(self, form, key_provider_id = None): |
|
41 |
metadata, publickey, cacertchain = None, None, None |
|
42 |
if form.get_widget('metadata').parse(): |
|
43 |
metadata = form.get_widget('metadata').parse().fp.read() |
|
44 |
if form.get_widget('publickey').parse(): |
|
45 |
publickey = form.get_widget('publickey').parse().fp.read() |
|
46 |
if form.get_widget('cacertchain').parse(): |
|
47 |
cacertchain = form.get_widget('cacertchain').parse().fp.read() |
|
48 |
|
|
49 |
if not key_provider_id: |
|
50 |
try: |
|
51 |
provider_id = re.findall(r'(provider|entity)ID="(.*?)"', metadata)[0][1] |
|
52 |
except IndexError: |
|
53 |
return error_page('settings', _('Bad metadata')) |
|
54 |
key_provider_id = provider_id.replace(str('://'), str('-')).replace(str('/'), str('-')) |
|
55 |
|
|
56 |
dir = get_abs_path(os.path.join('idp', key_provider_id)) |
|
57 |
if not os.path.isdir(dir): |
|
58 |
os.makedirs(dir) |
|
59 |
|
|
60 |
if metadata: |
|
61 |
metadata_fn = os.path.join(dir, 'metadata.xml') |
|
62 |
open(metadata_fn, 'w').write(metadata) |
|
63 |
if publickey: |
|
64 |
publickey_fn = os.path.join(dir, 'public_key') |
|
65 |
open(publickey_fn, 'w').write(publickey) |
|
66 |
else: |
|
67 |
publickey_fn = None |
|
68 |
if cacertchain: |
|
69 |
cacertchain_fn = os.path.join(dir, 'ca_cert_chain.pem') |
|
70 |
open(cacertchain_fn, 'w').write(cacertchain) |
|
71 |
else: |
|
72 |
cacertchain_fn = None |
|
73 |
|
|
74 |
p = lasso.Provider(lasso.PROVIDER_ROLE_IDP, metadata_fn, publickey_fn, None) |
|
75 |
|
|
76 |
try: |
|
77 |
misc.get_provider_label(p) |
|
78 |
get_publisher().cfg['idp'] = key_provider_id |
|
79 |
get_publisher().write_cfg() |
|
80 |
except TypeError: |
|
81 |
if metadata: |
|
82 |
os.unlink(metadata_fn) |
|
83 |
if publickey: |
|
84 |
os.unlink(publickey_fn) |
|
85 |
if cacertchain: |
|
86 |
os.unlink(cacertchain_fn) |
|
87 |
return error_page('settings', _('Bad metadata')) |
|
88 |
|
|
89 |
redirect('..') |
|
90 |
|
|
91 |
def metadata(self): |
|
92 |
response = get_response() |
|
93 |
response.set_content_type('text/xml', 'utf-8') |
|
94 |
get_publisher().reload_cfg() |
|
95 |
if get_publisher().cfg['idp']: |
|
96 |
idp_metadata = os.path.join(get_abs_path('idp'), get_publisher().cfg['idp'], 'metadata.xml') |
|
97 |
return unicode(open(idp_metadata).read(), 'utf-8') |
|
98 |
return 'No IDP is configured' |
|
99 |
|
|
100 |
|
|
101 |
class EmailsDirectory(QommonEmailsDirectory): |
|
102 |
def _q_index [html] (self): |
|
103 |
# Don't use custom emails |
|
104 |
html_top('settings', title = _('Emails')) |
|
105 |
'<h2>%s</h2>' % _('Emails') |
|
106 |
|
|
107 |
'<ul>' |
|
108 |
'<li><a href="options">%s</a></li>' % _('General Options') |
|
109 |
'</ul>' |
|
110 |
|
|
111 |
'<p>' |
|
112 |
'<a href="..">%s</a>' % _('Back') |
|
113 |
'</p>' |
|
114 |
|
|
115 |
|
|
116 |
class SettingsDirectory(QommonSettingsDirectory): |
|
117 |
_q_exports = ['', 'liberty_sp', 'liberty_idp', 'domain_names', 'apache2_configuration_generation', |
|
118 |
'proxy', 'language', 'emails', 'debug_options' ] |
|
119 |
|
|
120 |
liberty_idp = LibertyIDPDir() |
|
121 |
emails = EmailsDirectory() |
|
122 |
|
|
123 |
def _q_index [html] (self): |
|
124 |
get_publisher().reload_cfg() |
|
125 |
html_top('settings', title = _('Settings')) |
|
126 |
|
|
127 |
if lasso.SAML2_SUPPORT: |
|
128 |
'<h2>%s</h2>' % _('Liberty Alliance & SAML 2.0 Service Provider') |
|
129 |
else: |
|
130 |
'<h2>%s</h2>' % _('Liberty Alliance Service Provider') |
|
131 |
'<dl> <dt><a href="liberty_sp">%s</a></dt> <dd>%s</dd>' % ( |
|
132 |
_('Service Provider'), _('Configure Larpe as a Service Provider')) |
|
133 |
|
|
134 |
hosts = Host.select(lambda x: x.name == 'larpe') |
|
135 |
if hosts: |
|
136 |
self.host = hosts[0] |
|
137 |
|
|
138 |
if lasso.SAML2_SUPPORT and self.host.saml2_metadata is not None: |
|
139 |
metadata_url = '%s/metadata.xml' % self.host.saml2_base_url |
|
140 |
'<dt><a href="%s">%s</a></dt> <dd>%s</dd>' % ( |
|
141 |
metadata_url, |
|
142 |
_('SAML 2.0 Metadata'), |
|
143 |
_('Download SAML 2.0 metadata file for Larpe')) |
|
144 |
|
|
145 |
if self.host.metadata is not None: |
|
146 |
metadata_url = '%s/metadata.xml' % self.host.base_url |
|
147 |
'<dt><a href="%s">%s</a></dt> <dd>%s</dd>' % ( |
|
148 |
metadata_url, |
|
149 |
_('ID-FF 1.2 Metadata'), |
|
150 |
_('Download ID-FF 1.2 metadata file for Larpe')) |
|
151 |
|
|
152 |
if self.host.public_key is not None: |
|
153 |
public_key_url = '%s/public_key' % self.host.base_url |
|
154 |
'<dt><a href="%s">%s</a></dt> <dd>%s</dd>' % ( |
|
155 |
public_key_url, |
|
156 |
_('Public key'), |
|
157 |
_('Download SSL Public Key file')) |
|
158 |
|
|
159 |
if lasso.SAML2_SUPPORT: |
|
160 |
'<h2>%s</h2>' % _('Liberty Alliance & SAML 2.0 Identity Provider') |
|
161 |
else: |
|
162 |
'<h2>%s</h2>' % _('Liberty Alliance Identity Provider') |
|
163 |
|
|
164 |
'<dl>' |
|
165 |
|
|
166 |
'<dt><a href="liberty_idp/">%s</a></dt> <dd>%s</dd>' % ( |
|
167 |
_('Identity Provider'), _('Configure an identity provider')) |
|
168 |
|
|
169 |
if get_publisher().cfg.has_key('idp'): |
|
170 |
'<dt><a href="liberty_idp/metadata.xml">%s</a></dt> <dd>%s</dd>' % ( |
|
171 |
_('Identity Provider metadatas'), _('See current identity provider metadatas')) |
|
172 |
|
|
173 |
'</dl>' |
|
174 |
|
|
175 |
'<h2>%s</h2>' % _('Global parameters for the sites') |
|
176 |
|
|
177 |
'<dl>' |
|
178 |
'<dt><a href="domain_names">%s</a></dt> <dd>%s</dd>' % ( |
|
179 |
_('Domain name'), _('Configure the base domain name for the sites')) |
|
180 |
'<dt><a href="apache2_configuration_generation">%s</a></dt> <dd>%s</dd>' % ( |
|
181 |
_('Apache 2 configuration generation'), _('Customise Apache 2 configuration generation')) |
|
182 |
'<dt><a href="proxy">%s</a></dt> <dd>%s</dd>' % ( |
|
183 |
_('Proxy'), _('Connect to the sites through a web proxy')) |
|
184 |
'</dl>' |
|
185 |
|
|
186 |
'<h2>%s</h2>' % _('Customisation') |
|
187 |
|
|
188 |
'<dl>' |
|
189 |
'<dt><a href="language">%s</a></dt> <dd>%s</dd>' % ( |
|
190 |
_('Language'), _('Configure site language')) |
|
191 |
'<dt><a href="emails/">%s</a></dt> <dd>%s</dd>' % ( |
|
192 |
_('Emails'), _('Configure email settings')) |
|
193 |
'</dl>' |
|
194 |
|
|
195 |
'<h2>%s</h2>' % _('Misc') |
|
196 |
|
|
197 |
'<dl>' |
|
198 |
'<dt><a href="debug_options">%s</a></dt> <dd>%s</dd>' % ( |
|
199 |
_('Debug Options'), _('Configure options useful for debugging')) |
|
200 |
'</dl>' |
|
201 |
|
|
202 |
|
|
203 |
def liberty_sp [html] (self): |
|
204 |
get_publisher().reload_cfg() |
|
205 |
|
|
206 |
# Get the host object for the reverse proxy |
|
207 |
hosts = Host.select(lambda x: x.name == 'larpe') |
|
208 |
if hosts: |
|
209 |
self.host = hosts[0] |
|
210 |
else: |
|
211 |
self.host = Host() |
|
212 |
self.host.reversed_hostname = get_publisher().cfg[str('proxy_hostname')] |
|
213 |
|
|
214 |
form = Form(enctype='multipart/form-data') |
|
215 |
form.add(StringWidget, 'organization_name', title=_('Organisation Name'), size=50, |
|
216 |
required = True, value = self.host.organization_name) |
|
217 |
form.add_submit('submit', _('Submit')) |
|
218 |
form.add_submit('cancel', _('Cancel')) |
|
219 |
if form.get_widget('cancel').parse(): |
|
220 |
return redirect('.') |
|
221 |
if not form.is_submitted() or form.has_errors(): |
|
222 |
html_top('settings', title = _('Service Provider Configuration')) |
|
223 |
'<h2>%s</h2>' % _('Service Provider Configuration') |
|
224 |
form.render() |
|
225 |
else: |
|
226 |
self.liberty_sp_submit(form) |
|
227 |
redirect('.') |
|
228 |
|
|
229 |
def liberty_sp_submit(self, form): |
|
230 |
get_publisher().reload_cfg() |
|
231 |
metadata_cfg = {} |
|
232 |
|
|
233 |
f = 'organization_name' |
|
234 |
if form.get_widget(f): |
|
235 |
setattr(self.host, f, form.get_widget(f).parse()) |
|
236 |
|
|
237 |
metadata_cfg['organization_name'] = self.host.organization_name |
|
238 |
|
|
239 |
self.host.name = 'larpe' |
|
240 |
|
|
241 |
# Liberty Alliance / SAML parameters |
|
242 |
base_url = '%s/liberty/%s/liberty' % (misc.get_root_url(), self.host.name) |
|
243 |
metadata_cfg['base_url'] = base_url |
|
244 |
self.host.base_url = base_url |
|
245 |
|
|
246 |
if lasso.SAML2_SUPPORT: |
|
247 |
saml2_base_url = '%s/liberty/%s/saml' % (misc.get_root_url(), self.host.name) |
|
248 |
metadata_cfg['saml2_base_url'] = saml2_base_url |
|
249 |
self.host.saml2_base_url = saml2_base_url |
|
250 |
|
|
251 |
provider_id = '%s/metadata' % base_url |
|
252 |
metadata_cfg['provider_id'] = provider_id |
|
253 |
self.host.provider_id = provider_id |
|
254 |
|
|
255 |
if lasso.SAML2_SUPPORT: |
|
256 |
saml2_provider_id = '%s/metadata' % saml2_base_url |
|
257 |
metadata_cfg['saml2_provider_id'] = saml2_provider_id |
|
258 |
self.host.saml2_provider_id = saml2_provider_id |
|
259 |
|
|
260 |
# Storage directories |
|
261 |
site_dir = os.path.join(get_publisher().app_dir, 'sp', |
|
262 |
self.host.reversed_hostname, self.host.name) |
|
263 |
user_dir = os.path.join(site_dir, 'users') |
|
264 |
token_dir = os.path.join(site_dir, 'tokens') |
|
265 |
for dir in (site_dir, user_dir, token_dir): |
|
266 |
if not os.path.isdir(dir): |
|
267 |
os.makedirs(dir) |
|
268 |
metadata_cfg['site_dir'] = site_dir |
|
269 |
self.host.site_dir = site_dir |
|
270 |
|
|
271 |
# Generate SSL keys |
|
272 |
private_key_path = os.path.join(site_dir, 'private_key.pem') |
|
273 |
public_key_path = os.path.join(site_dir, 'public_key') |
|
274 |
if not os.path.isfile(private_key_path) or not os.path.isfile(public_key_path): |
|
275 |
set_provider_keys(private_key_path, public_key_path) |
|
276 |
self.host.private_key = private_key_path |
|
277 |
metadata_cfg['signing_public_key'] = open(public_key_path).read() |
|
278 |
self.host.public_key = public_key_path |
|
279 |
|
|
280 |
# Write metadatas |
|
281 |
metadata_path = os.path.join(site_dir, 'metadata.xml') |
|
282 |
open(metadata_path, 'w').write(get_metadata(metadata_cfg)) |
|
283 |
self.host.metadata = metadata_path |
|
284 |
|
|
285 |
if hasattr(self.host, 'saml2_provider_id'): |
|
286 |
saml2_metadata_path = os.path.join(site_dir, 'saml2_metadata.xml') |
|
287 |
open(saml2_metadata_path, 'w').write(get_saml2_metadata(metadata_cfg)) |
|
288 |
self.host.saml2_metadata = saml2_metadata_path |
|
289 |
|
|
290 |
self.host.root_url = '%s/' % misc.get_root_url() |
|
291 |
self.host.return_url = '%s/admin/' % misc.get_root_url() |
|
292 |
|
|
293 |
self.host.store() |
|
294 |
|
|
295 |
def domain_names [html] (self): |
|
296 |
form = self.form_domain_name() |
|
297 |
|
|
298 |
if form.get_widget('cancel').parse(): |
|
299 |
return redirect('.') |
|
300 |
|
|
301 |
if not form.is_submitted() or form.has_errors(): |
|
302 |
html_top('settings', title = _('Domain name')) |
|
303 |
'<h2>%s</h2>' % _('Domain name') |
|
304 |
form.render() |
|
305 |
else: |
|
306 |
self.submit_domain_name(form) |
|
307 |
redirect('.') |
|
308 |
|
|
309 |
def form_domain_name(self): |
|
310 |
get_publisher().reload_cfg() |
|
311 |
if get_cfg('domain_names'): |
|
312 |
domain_name = get_cfg('domain_names')[0] |
|
313 |
else: |
|
314 |
domain_name = None |
|
315 |
|
|
316 |
form = Form(enctype='multipart/form-data') |
|
317 |
form.add(StringWidget, 'domain_name', |
|
318 |
title=_('Domain name for the sites'), |
|
319 |
value = domain_name) |
|
320 |
# TODO: Add the option "Both" and handle it in hosts configuration |
|
321 |
form.add(SingleSelectWidget, 'sites_url_scheme', title = _('Use HTTP or HTTPS'), |
|
322 |
value = get_cfg('sites_url_scheme'), |
|
323 |
options = [ (None, _('Same as the site')), |
|
324 |
('http', 'HTTP'), |
|
325 |
('https', 'HTTPS') ] ) |
|
326 |
form.add_submit('submit', _('Submit')) |
|
327 |
form.add_submit('cancel', _('Cancel')) |
|
328 |
return form |
|
329 |
|
|
330 |
def submit_domain_name(self, form): |
|
331 |
get_publisher().reload_cfg() |
|
332 |
get_publisher().cfg['domain_names'] = [ form.get_widget('domain_name').parse() ] |
|
333 |
get_publisher().cfg['sites_url_scheme'] = form.get_widget('sites_url_scheme').parse() |
|
334 |
get_publisher().write_cfg() |
|
335 |
|
|
336 |
def apache2_configuration_generation [html] (self): |
|
337 |
get_publisher().reload_cfg() |
|
338 |
|
|
339 |
form = Form(enctype='multipart/form-data') |
|
340 |
form.add(CheckboxWidget, 'allow_config_generation', |
|
341 |
title=_('Automatically generate Apache 2 configuration for new hosts and reload Apache 2 after changes'), |
|
342 |
value = get_publisher().cfg.get(str('allow_config_generation'), True)) |
|
343 |
form.add_submit('submit', _('Submit')) |
|
344 |
form.add_submit('cancel', _('Cancel')) |
|
345 |
if form.get_widget('cancel').parse(): |
|
346 |
return redirect('.') |
|
347 |
if not form.is_submitted() or form.has_errors(): |
|
348 |
html_top('settings', title = _('Apache 2 configuration generation')) |
|
349 |
'<h2>%s</h2>' % _('Apache 2 configuration generation') |
|
350 |
form.render() |
|
351 |
else: |
|
352 |
self.apache2_configuration_generation_submit(form) |
|
353 |
redirect('.') |
|
354 |
|
|
355 |
def apache2_configuration_generation_submit(self, form): |
|
356 |
get_publisher().reload_cfg() |
|
357 |
|
|
358 |
f = 'allow_config_generation' |
|
359 |
get_publisher().cfg[f] = form.get_widget(f).parse() |
|
360 |
|
|
361 |
get_publisher().write_cfg() |
larpe/tags/release-1.1.1/larpe/admin/users.ptl | ||
---|---|---|
1 |
import random |
|
2 |
|
|
3 |
import lasso |
|
4 |
|
|
5 |
from quixote import get_request, get_session, redirect, get_publisher |
|
6 |
from quixote.directory import Directory |
|
7 |
|
|
8 |
from qommon.admin.menu import html_top, error_page, command_icon |
|
9 |
from qommon.errors import EmailError |
|
10 |
from qommon.form import * |
|
11 |
from qommon import emails |
|
12 |
|
|
13 |
from larpe import errors |
|
14 |
from larpe import misc |
|
15 |
from larpe.users import User |
|
16 |
from larpe.hosts import Host |
|
17 |
|
|
18 |
class UserUI: |
|
19 |
def __init__(self, user): |
|
20 |
self.user = user |
|
21 |
|
|
22 |
def form_new(self): |
|
23 |
form = Form(enctype="multipart/form-data") |
|
24 |
form.add(StringWidget, "name", title = _('User Name'), required = True, size=30) |
|
25 |
form.add(StringWidget, "email", title = _('Email'), required = False, size=30) |
|
26 |
form.add_submit("submit", _("Submit")) |
|
27 |
form.add_submit("cancel", _("Cancel")) |
|
28 |
return form |
|
29 |
|
|
30 |
def form_edit(self): |
|
31 |
form = Form(enctype="multipart/form-data") |
|
32 |
form.add(StringWidget, "name", title = _('User Name'), required = True, size=30, |
|
33 |
value = self.user.name) |
|
34 |
form.add(StringWidget, "email", title = _('Email'), required = False, size=30, |
|
35 |
value = self.user.email) |
|
36 |
form.add_submit("submit", _("Submit")) |
|
37 |
form.add_submit("cancel", _("Cancel")) |
|
38 |
return form |
|
39 |
|
|
40 |
def submit_form(self, form): |
|
41 |
if not self.user: |
|
42 |
self.user = User() |
|
43 |
for f in ('name', 'email'): |
|
44 |
widget = form.get_widget(f) |
|
45 |
if widget: |
|
46 |
setattr(self.user, f, widget.parse()) |
|
47 |
self.user.is_admin = True |
|
48 |
self.user.store() |
|
49 |
|
|
50 |
|
|
51 |
class UserPage(Directory): |
|
52 |
_q_exports = ['', 'edit', 'delete', 'token'] |
|
53 |
|
|
54 |
def __init__(self, component): |
|
55 |
self.user = User.get(component) |
|
56 |
self.user_ui = UserUI(self.user) |
|
57 |
get_response().breadcrumb.append((component + '/', self.user.name)) |
|
58 |
|
|
59 |
def _q_index [html] (self): |
|
60 |
html_top('users', '%s - %s' % (_('User'), self.user.name)) |
|
61 |
'<h2>%s - %s</h2>' % (_('User'), self.user.name) |
|
62 |
'<div class="form">' |
|
63 |
'<div class="title">%s</div>' % _('Name') |
|
64 |
'<div class="StringWidget content">%s</div>' % self.user.name |
|
65 |
if self.user.email: |
|
66 |
'<div class="title">%s</div>' % _('Email') |
|
67 |
'<div class="StringWidget content">%s</div>' % self.user.email |
|
68 |
# if self.user.lasso_dump: |
|
69 |
# identity = lasso.Identity.newFromDump(self.user.lasso_dump) |
|
70 |
# server = misc.get_lasso_server() |
|
71 |
# if len(identity.providerIds) and server: |
|
72 |
# '<h3>%s</h3>' % _('Liberty Alliance Details') |
|
73 |
# '<div class="StringWidget content"><ul>' |
|
74 |
# for pid in identity.providerIds: |
|
75 |
# provider = server.getProvider(pid) |
|
76 |
# label = misc.get_provider_label(provider) |
|
77 |
# if label: |
|
78 |
# label = '%s (%s)' % (label, pid) |
|
79 |
# else: |
|
80 |
# label = pid |
|
81 |
# federation = identity.getFederation(pid) |
|
82 |
# '<li>' |
|
83 |
# _('Account federated with %s') % label |
|
84 |
# '<br />' |
|
85 |
# if federation.localNameIdentifier: |
|
86 |
# _("local: ") + federation.localNameIdentifier.content |
|
87 |
# if federation.remoteNameIdentifier: |
|
88 |
# _("remote: ") + federation.remoteNameIdentifier.content |
|
89 |
# '</li>' |
|
90 |
# '</ul></div>' |
|
91 |
|
|
92 |
# # XXX: only display this in debug mode: |
|
93 |
# '<h4>%s</h4>' % _('Lasso Identity Dump') |
|
94 |
# '<pre>%s</pre>' % self.user.lasso_dump |
|
95 |
'</div>' |
|
96 |
|
|
97 |
def debug [html] (self): |
|
98 |
get_response().breadcrumb.append( ('debug', _('Debug')) ) |
|
99 |
html_top('users', 'Debug') |
|
100 |
"<h2>Debug - %s</h2>" % self.user.name |
|
101 |
"<pre>" |
|
102 |
self.user.lasso_dump |
|
103 |
"</pre>" |
|
104 |
|
|
105 |
def edit [html] (self): |
|
106 |
form = self.user_ui.form_edit() |
|
107 |
if form.get_widget('cancel').parse(): |
|
108 |
return redirect('..') |
|
109 |
if not form.is_submitted() or form.has_errors(): |
|
110 |
get_response().breadcrumb.append( ('edit', _('Edit')) ) |
|
111 |
html_top('users', title = _('Edit User')) |
|
112 |
'<h2>%s</h2>' % _('Edit User') |
|
113 |
form.render() |
|
114 |
else: |
|
115 |
self.user_ui.submit_form(form) |
|
116 |
return redirect('..') |
|
117 |
|
|
118 |
def delete [html] (self): |
|
119 |
form = Form(enctype="multipart/form-data") |
|
120 |
form.widgets.append(HtmlWidget('<p>%s</p>' % _( |
|
121 |
"You are about to irrevocably delete this user."))) |
|
122 |
form.add_submit("submit", _("Submit")) |
|
123 |
form.add_submit("cancel", _("Cancel")) |
|
124 |
if form.get_widget('cancel').parse(): |
|
125 |
return redirect('..') |
|
126 |
if not form.is_submitted() or form.has_errors(): |
|
127 |
get_response().breadcrumb.append(('delete', _('Delete'))) |
|
128 |
html_top('users', title = _('Delete User')) |
|
129 |
'<h2>%s %s</h2>' % (_('Deleting User :'), self.user.name) |
|
130 |
form.render() |
|
131 |
else: |
|
132 |
self.user.remove_self() |
|
133 |
return redirect('..') |
|
134 |
|
|
135 |
def token [html] (self): |
|
136 |
form = Form(enctype="multipart/form-data", use_tokens = False) |
|
137 |
form.add_submit("submit", _("Generate")) |
|
138 |
form.add_submit("cancel", _("Cancel")) |
|
139 |
request = get_request() |
|
140 |
if request.form.has_key('cancel') or request.form.has_key('done'): |
|
141 |
return redirect('..') |
|
142 |
|
|
143 |
get_response().breadcrumb.append(('token', _('Identification Token'))) |
|
144 |
|
|
145 |
if not form.is_submitted() or form.has_errors(): |
|
146 |
html_top('users', title = _('Identification Token')) |
|
147 |
'<h2>%s</h2>' % _('Identification Token') |
|
148 |
'<p>%s</p>' % _('You are about to generate a token than can be used to federate the account.') |
|
149 |
'<p>%s</p>' % _('After that, you will have the choice to send it to the user by email so that he can federate his accounts.') |
|
150 |
if self.user.identification_token: |
|
151 |
'<p>%s</p>' % _('Note that user has already been issued an identification token : %s') % self.user.identification_token |
|
152 |
form.render() |
|
153 |
else: |
|
154 |
if request.form.has_key('submit'): |
|
155 |
html_top('users', title = _('Identification Token')) |
|
156 |
token = '-'.join(['%04d' % random.randint(1, 9999) for x in range(4)]) |
|
157 |
self.user.identification_token = str(token) |
|
158 |
self.user.store() |
|
159 |
|
|
160 |
'<p>' |
|
161 |
_('Identification Token for %s') % self.user.name |
|
162 |
' : %s</p>' % self.user.identification_token |
|
163 |
|
|
164 |
form = Form(enctype="multipart/form-data", use_tokens = False) |
|
165 |
form.add_submit('done', _('Done')) |
|
166 |
if self.user.email: |
|
167 |
form.add_submit("submit-email", _("Send by email")) |
|
168 |
form.render() |
|
169 |
else: |
|
170 |
site_url = '%s://%s%s/token?token=%s' \ |
|
171 |
% (request.get_scheme(), request.get_server(), |
|
172 |
get_request().environ['SCRIPT_NAME'], self.user.identification_token) |
|
173 |
body = _("""You have been given an identification token. |
|
174 |
|
|
175 |
Your token is %(token)s |
|
176 |
|
|
177 |
Click on %(url)s to use it. |
|
178 |
""") % {'token': self.user.identification_token, 'url': site_url} |
|
179 |
try: |
|
180 |
emails.email(_('Identification Token'), body, self.user.email) |
|
181 |
except EmailError, e: |
|
182 |
html_top('users', title = _('Identification Token')) |
|
183 |
_('Failed sending email. Check your email configuration.') |
|
184 |
'<div class="buttons"><a href=".."><input type="button" value="%s" /></a></div><br />' % _('Back') |
|
185 |
else: |
|
186 |
return redirect('..') |
|
187 |
|
|
188 |
class UsersDirectory(Directory): |
|
189 |
|
|
190 |
_q_exports = ['', 'new'] |
|
191 |
|
|
192 |
def _q_index [html] (self): |
|
193 |
get_publisher().reload_cfg() |
|
194 |
get_response().breadcrumb.append( ('users/', _('Users')) ) |
|
195 |
html_top('users', title = _('Users')) |
|
196 |
|
|
197 |
|
|
198 |
if not list(Host.select(lambda x: x.name == 'larpe')): |
|
199 |
'<p>%s</p>' % _('Liberty support must be setup before creating users.') |
|
200 |
else: |
|
201 |
"""<ul id="nav-users-admin"> |
|
202 |
<li><a href="new">%s</a></li> |
|
203 |
</ul>""" % _('New User') |
|
204 |
|
|
205 |
debug_cfg = get_publisher().cfg.get('debug', {}) |
|
206 |
|
|
207 |
users = User.select(lambda x: x.name is not None, order_by = 'name') |
|
208 |
|
|
209 |
'<ul class="biglist">' |
|
210 |
for user in users: |
|
211 |
'<li>' |
|
212 |
'<strong class="label">%s</strong>' % user.name |
|
213 |
if user.email: |
|
214 |
'<p class="details">' |
|
215 |
user.email |
|
216 |
'</p>' |
|
217 |
|
|
218 |
'<p class="commands">' |
|
219 |
command_icon('%s/' % user.id, 'view') |
|
220 |
if not user.name_identifiers: |
|
221 |
if not user.identification_token: |
|
222 |
command_icon('%s/token' % user.id, 'token', |
|
223 |
label = _('Identification Token'), icon = 'stock_exec_16.png') |
|
224 |
else: |
|
225 |
command_icon('%s/token' % user.id, 'token', |
|
226 |
label = _('Identification Token (current: %s)') % \ |
|
227 |
user.identification_token, |
|
228 |
icon = 'stock_exec_16.png') |
|
229 |
command_icon('%s/edit' % user.id, 'edit') |
|
230 |
command_icon('%s/delete' % user.id, 'remove') |
|
231 |
if debug_cfg.get('logger', False): |
|
232 |
command_icon('../logger/by_user/%s/' % user.id, 'logs', |
|
233 |
label = _('Logs'), icon = 'stock_harddisk_16.png') |
|
234 |
'</p></li>' |
|
235 |
'</ul>' |
|
236 |
|
|
237 |
def new [html] (self): |
|
238 |
get_response().breadcrumb.append( ('users/', _('Users')) ) |
|
239 |
get_response().breadcrumb.append( ('new', _('New')) ) |
|
240 |
hosts = list(Host.select(lambda x: x.name == 'larpe')) |
|
241 |
if not hosts: |
|
242 |
return error_page('users', _('Liberty support must be setup before creating users.')) |
|
243 |
host = hosts[0] |
|
244 |
# XXX: user must be logged in to get here |
|
245 |
user_ui = UserUI(None) |
|
246 |
# FIXME : should be able to use User.count(). Track fake user creations. |
|
247 |
users = User.select(lambda x: x.name is not None) |
|
248 |
first_user = (len(users) == 0) |
|
249 |
form = user_ui.form_new() |
|
250 |
if form.get_widget('cancel').parse(): |
|
251 |
return redirect('.') |
|
252 |
|
|
253 |
if not form.is_submitted() or form.has_errors(): |
|
254 |
html_top('users', title = _('New User')) |
|
255 |
'<h2>%s</h2>' % _('New User') |
|
256 |
form.render() |
|
257 |
else: |
|
258 |
user_ui.submit_form(form) |
|
259 |
if first_user: |
|
260 |
session = get_session() |
|
261 |
if hasattr(session, str('lasso_dump')): |
|
262 |
user_ui.user.name_identifiers = [ session.name_identifier ] |
|
263 |
user_ui.user.lasso_dumps = [ session.lasso_anonymous_identity_dump ] |
|
264 |
user_ui.user.store() |
|
265 |
if misc.get_current_protocol() == lasso.PROTOCOL_SAML_2_0: |
|
266 |
get_session().set_user(user_ui.user.id, host.saml2_provider_id) |
|
267 |
else: |
|
268 |
get_session().set_user(user_ui.user.id, host.provider_id) |
|
269 |
return redirect('.') |
|
270 |
|
|
271 |
def _q_lookup(self, component): |
|
272 |
get_response().breadcrumb.append( ('users/', _('Users')) ) |
|
273 |
try: |
|
274 |
return UserPage(component) |
|
275 |
except KeyError: |
|
276 |
raise errors.TraversalError() |
larpe/tags/release-1.1.1/larpe/ctl/__init__.py | ||
---|---|---|
1 |
from start import start |
|
2 |
|
larpe/tags/release-1.1.1/larpe/ctl/start.py | ||
---|---|---|
1 |
import socket |
|
2 |
import sys |
|
3 |
import quixote.server.simple_server |
|
4 |
|
|
5 |
from qommon.scgi_server import run |
|
6 |
|
|
7 |
import publisher |
|
8 |
|
|
9 |
def start(args): |
|
10 |
run_function = run |
|
11 |
run_kwargs = { |
|
12 |
'port': 3007, |
|
13 |
'script_name': '' |
|
14 |
} |
|
15 |
http = 0 |
|
16 |
|
|
17 |
i = 0 |
|
18 |
while i < len(args): |
|
19 |
if args[i] == '--port': |
|
20 |
run_kwargs['port'] = int(args[i+1]) |
|
21 |
i += 1 |
|
22 |
elif args[i] == '--silent': |
|
23 |
sys.stdout = open('/dev/null', 'w') |
|
24 |
sys.stderr = open('/dev/null', 'w') |
|
25 |
elif args[i] == '--script-name': |
|
26 |
run_kwargs['script_name'] = args[i+1] |
|
27 |
i += 1 |
|
28 |
elif args[i] == '--app-dir': |
|
29 |
publisher.LarpePublisher.APP_DIR = args[i+1] |
|
30 |
i += 1 |
|
31 |
elif args[i] == '--data-dir': |
|
32 |
publisher.LarpePublisher.DATA_DIR = args[i+1] |
|
33 |
i += 1 |
|
34 |
elif args[i] == '--http': |
|
35 |
http = 1 |
|
36 |
i += 1 |
|
37 |
|
|
38 |
if http == 1: |
|
39 |
run_function = quixote.server.simple_server.run |
|
40 |
if run_kwargs['script_name']: |
|
41 |
print "--http option is incompatible with --script-name" |
|
42 |
del run_kwargs['script_name'] |
|
43 |
try: |
|
44 |
run_function(publisher.LarpePublisher.create_publisher, **run_kwargs) |
|
45 |
except socket.error, err: |
|
46 |
if err[0] == 98: |
|
47 |
print >> sys.stderr, 'address already in use' |
|
48 |
sys.exit(1) |
|
49 |
raise |
|
50 |
except KeyboardInterrupt: |
|
51 |
sys.exit(1) |
|
52 |
|
larpe/tags/release-1.1.1/larpe/errors.ptl | ||
---|---|---|
1 |
from quixote import get_session, get_request, redirect |
|
2 |
|
|
3 |
from qommon.errors import * |
|
4 |
|
|
5 |
class AccessUnauthorizedError(AccessError): |
|
6 |
def render [html] (self): |
|
7 |
session = get_session() |
|
8 |
request = get_request() |
|
9 |
query = request.get_query() |
|
10 |
session.after_url = request.get_url() |
|
11 |
if query: |
|
12 |
session.after_url += '?' + query |
|
13 |
session.after_url = str(session.after_url) |
|
14 |
login_url = '%s/liberty/larpe/login' % request.environ['SCRIPT_NAME'] |
|
15 |
redirect(login_url) |
larpe/tags/release-1.1.1/larpe/federations.py | ||
---|---|---|
1 |
'''Federation object. Configuration variables and utilities''' |
|
2 |
|
|
3 |
from qommon.storage import StorableObject |
|
4 |
|
|
5 |
class Federation(StorableObject): |
|
6 |
_names = 'federations' |
|
7 |
|
|
8 |
username = None |
|
9 |
password = None |
|
10 |
host_id = None |
|
11 |
name_identifiers = None |
|
12 |
cookies = None |
|
13 |
select_fields = {} |
|
14 |
|
|
15 |
def __init__(self, username, password, host_id, name_identifier, cookies=None, select=None): |
|
16 |
select = select or {} |
|
17 |
StorableObject.__init__(self) |
|
18 |
self.username = username |
|
19 |
self.password = password |
|
20 |
self.host_id = host_id |
|
21 |
self.name_identifiers = [ name_identifier ] |
|
22 |
self.cookies = cookies |
|
23 |
self.select_fields = select |
|
24 |
|
|
25 |
def remove_name_identifier(self, name_identifier): |
|
26 |
self.name_identifiers.remove(name_identifier) |
|
27 |
if not self.name_identifiers: |
|
28 |
self.remove_self() |
|
29 |
|
|
30 |
def set_cookies(self, cookies): |
|
31 |
self.cookies = cookies |
|
32 |
|
|
33 |
def __str__(self): |
|
34 |
return 'Federation username : %s, name identifiers : %s, cookies : %s' \ |
|
35 |
% (self.username, self.name_identifiers, self.cookies) |
larpe/tags/release-1.1.1/larpe/field_prefill.py | ||
---|---|---|
1 |
from qommon.storage import StorableObject |
|
2 |
|
|
3 |
class FieldPrefill(StorableObject): |
|
4 |
_names = 'field_prefill' |
|
5 |
|
|
6 |
form_id = 0 |
|
7 |
name = None |
|
8 |
xpath = None |
|
9 |
number = 1 |
|
10 |
raw_xml = False |
|
11 |
regexp_match = None |
|
12 |
regexp_replacing = None |
|
13 |
select_options = {} |
larpe/tags/release-1.1.1/larpe/form_prefill.py | ||
---|---|---|
1 |
from qommon.storage import StorableObject |
|
2 |
|
|
3 |
class FormPrefill(StorableObject): |
|
4 |
_names = 'form_prefill' |
|
5 |
|
|
6 |
host_id = 0 |
|
7 |
name = None |
|
8 |
url = None |
|
9 |
profile = None |
|
10 |
prefix = None |
larpe/tags/release-1.1.1/larpe/hosts.py | ||
---|---|---|
1 |
'''Host object. Configuration variables and utilities''' |
|
2 |
|
|
3 |
import os |
|
4 |
from shutil import rmtree |
|
5 |
|
|
6 |
from quixote import get_request |
|
7 |
|
|
8 |
from qommon.storage import StorableObject |
|
9 |
|
|
10 |
from Defaults import APP_DIR |
|
11 |
|
|
12 |
def get_proxied_site_name(): |
|
13 |
nb_subdirs = get_request().environ['SCRIPT_NAME'].count('/') |
|
14 |
return get_request().get_path().split('/')[nb_subdirs + 2] |
|
15 |
|
|
16 |
class Host(StorableObject): |
|
17 |
'''Host object. Configuration variables and utilities''' |
|
18 |
_names = 'hosts' |
|
19 |
|
|
20 |
# Main settings |
|
21 |
label = None |
|
22 |
name = None |
|
23 |
orig_site = None |
|
24 |
new_url = None |
|
25 |
scheme = None |
|
26 |
auth_url = None |
|
27 |
auth_form_places = 'form_once' |
|
28 |
auth_form_page_url = None |
|
29 |
auth_form = None |
|
30 |
auth_form_url = None |
|
31 |
logout_url = None |
|
32 |
reversed_hostname = None |
|
33 |
reversed_directory = None |
|
34 |
organization_name = None |
|
35 |
use_ssl = False |
|
36 |
private_key = None |
|
37 |
public_key = None |
|
38 |
site_dir = None |
|
39 |
|
|
40 |
# Auto detected settings |
|
41 |
auth_mode = 'form' |
|
42 |
auth_form_action = None |
|
43 |
auth_check_url = None |
|
44 |
login_field_name = None |
|
45 |
password_field_name = None |
|
46 |
select_fields = {} |
|
47 |
post_parameters = {} |
|
48 |
http_headers = {} |
|
49 |
|
|
50 |
# Advanced settings |
|
51 |
return_url = '/' |
|
52 |
root_url = '/' |
|
53 |
auth_system = 'password' |
|
54 |
auth_match_text = '' |
|
55 |
send_hidden_fields = True |
|
56 |
initiate_sso_url = None |
|
57 |
redirect_root_to_login = False |
|
58 |
|
|
59 |
# Other attributes |
|
60 |
provider_id = None |
|
61 |
# Default value that indicates the proxy (if configured) is not disabled for this host yet |
|
62 |
use_proxy = True |
|
63 |
|
|
64 |
valid_username = None |
|
65 |
valid_password = None |
|
66 |
apache_output_filters = [] |
|
67 |
apache_output_python_filters = [] |
|
68 |
apache_python_paths = [] |
|
69 |
|
|
70 |
# Plugins |
|
71 |
# If name is set to None, use the default site authentication class |
|
72 |
site_authentication_plugin = None |
|
73 |
|
|
74 |
def get_host_from_url(cls): |
|
75 |
try: |
|
76 |
host = list(Host.select(lambda x: x.name == get_proxied_site_name()))[0] |
|
77 |
if hasattr(host, 'site_authentication_instance'): |
|
78 |
del host.site_authentication_instance |
|
79 |
return list(Host.select(lambda x: x.name == get_proxied_site_name()))[0] |
|
80 |
except IndexError: |
|
81 |
return None |
|
82 |
get_host_from_url = classmethod(get_host_from_url) |
|
83 |
|
|
84 |
def get_host_with_provider_id(cls, provider_id): |
|
85 |
try: |
|
86 |
return list(Host.select(lambda x: x.provider_id == provider_id))[0] |
|
87 |
except IndexError: |
|
88 |
return None |
|
89 |
get_host_with_provider_id = classmethod(get_host_with_provider_id) |
|
90 |
|
|
91 |
def get_root_url(self): |
|
92 |
if self.root_url.startswith('/'): |
|
93 |
if self.reversed_directory: |
|
94 |
return '%s/%s%s' % (get_request().environ['SCRIPT_NAME'], |
|
95 |
self.reversed_directory, |
|
96 |
self.root_url) |
|
97 |
else: |
|
98 |
return '%s%s' % (get_request().environ['SCRIPT_NAME'], self.root_url) |
|
99 |
# In this case, must be a full url |
|
100 |
return self.root_url |
|
101 |
|
|
102 |
def get_return_url(self): |
|
103 |
if self.return_url.startswith('/'): |
|
104 |
if self.reversed_directory: |
|
105 |
return '%s/%s%s' % (get_request().environ['SCRIPT_NAME'], |
|
106 |
self.reversed_directory, |
|
107 |
self.return_url) |
|
108 |
else: |
|
109 |
return '%s%s' % (get_request().environ['SCRIPT_NAME'], self.return_url) |
|
110 |
# In this case, must be a full url |
|
111 |
return self.return_url |
|
112 |
|
|
113 |
def __cmp__(self, other): |
|
114 |
hostname_cmp = cmp(self.reversed_hostname, other.reversed_hostname) |
|
115 |
if hostname_cmp != 0: |
|
116 |
return hostname_cmp |
|
117 |
return cmp(self.reversed_directory, other.reversed_directory) |
|
118 |
|
|
119 |
def remove_self(self): |
|
120 |
# Main configuration file |
|
121 |
StorableObject.remove_self(self) |
|
122 |
# Other generated files |
|
123 |
if self.site_dir and os.path.exists(self.site_dir): |
|
124 |
rmtree(self.site_dir, ignore_errors=1) |
|
125 |
# Also remove hostname directory if empty (meaning there was no other subdirectory |
|
126 |
# for this hostname) |
|
127 |
try: |
|
128 |
os.rmdir('/'.join(self.site_dir.split('/')[:-1])) |
|
129 |
except OSError: |
|
130 |
pass |
|
131 |
# Virtual host directory |
|
132 |
if self.reversed_hostname: |
|
133 |
path = os.path.join(APP_DIR, self.reversed_hostname) |
|
134 |
if os.path.exists(path): |
|
135 |
rmtree(path, ignore_errors=1) |
|
136 |
|
larpe/tags/release-1.1.1/larpe/idwsf2.ptl | ||
---|---|---|
1 |
import os |
|
2 |
import sys |
|
3 |
import re |
|
4 |
|
|
5 |
try: |
|
6 |
import lasso |
|
7 |
except ImportError: |
|
8 |
print >> sys.stderr, 'Missing Lasso module, IdWsf 2.0 support disabled' |
|
9 |
else: |
|
10 |
if not lasso.WSF_SUPPORT: |
|
11 |
print >> sys.stderr, 'Found Lasso module, but IdWsf 2.0 support not enabled' |
|
12 |
|
|
13 |
from quixote import get_publisher, get_session, get_request, get_response, redirect |
|
14 |
from quixote.directory import Directory |
|
15 |
|
|
16 |
from qommon.liberty import SOAPException, soap_call |
|
17 |
from qommon import template |
|
18 |
from qommon.misc import http_get_page |
|
19 |
|
|
20 |
import misc |
|
21 |
from form_prefill import FormPrefill |
|
22 |
from field_prefill import FieldPrefill |
|
23 |
|
|
24 |
def cleanup_html_value(value): |
|
25 |
# Ensure the field value can be properly integrated in HTML code |
|
26 |
value = value.replace('"', "'") |
|
27 |
# Conversion to iso-8859-1 |
|
28 |
try: |
|
29 |
value = unicode(value, 'utf-8').encode('iso-8859-1') |
|
30 |
except UnicodeEncodeError: |
|
31 |
return None |
|
32 |
|
|
33 |
class IdWsf2(Directory): |
|
34 |
_q_exports = [] |
|
35 |
|
|
36 |
def _q_lookup(self, component): |
|
37 |
if not hasattr(get_session(), 'prefill_form'): |
|
38 |
get_session().prefill_form = component |
|
39 |
get_session().after_url = get_request().get_url() |
|
40 |
if get_request().get_query(): |
|
41 |
get_session().after_url += '?' + get_request().get_query() |
|
42 |
return redirect('../saml/login') |
|
43 |
else: |
|
44 |
prefill_form = FormPrefill.get(get_session().prefill_form) |
|
45 |
del get_session().prefill_form |
|
46 |
if prefill_form: |
|
47 |
try: |
|
48 |
response, status, page, auth_header = http_get_page(prefill_form.url) |
|
49 |
except: |
|
50 |
return template.error_page(_('Failed connecting to the original site.')) |
|
51 |
try: |
|
52 |
fields = self.do_prefill_form(prefill_form) |
|
53 |
if not fields: |
|
54 |
raise lasso.Error |
|
55 |
for key, value in get_request().get_fields().iteritems(): |
|
56 |
value = cleanup_html_value(value) |
|
57 |
if value: |
|
58 |
fields[key] = value |
|
59 |
except lasso.Error: |
|
60 |
return page + '<script type="text/javascript">alert("%s")</script>' % \ |
|
61 |
_('Failed getting attributes from the attribute provider.') |
|
62 |
except: |
|
63 |
return page + '<script type="text/javascript">alert("%s")</script>' % \ |
|
64 |
_('Failed getting attributes for an unknown reason.') |
|
65 |
|
|
66 |
return self.send_prefilled_form(prefill_form, page, fields) |
|
67 |
|
|
68 |
def do_prefill_form(self, prefill_form): |
|
69 |
server = misc.get_lasso_server(protocol = 'saml2') |
|
70 |
disco = lasso.IdWsf2Discovery(server) |
|
71 |
if not get_session().lasso_session_dumps or not get_session().lasso_session_dumps[server.providerId]: |
|
72 |
return None |
|
73 |
disco.setSessionFromDump(get_session().lasso_session_dumps[server.providerId]) |
|
74 |
|
|
75 |
disco.initQuery() |
|
76 |
disco.addRequestedServiceType(prefill_form.profile) |
|
77 |
disco.buildRequestMsg() |
|
78 |
|
|
79 |
try: |
|
80 |
soap_answer = soap_call(disco.msgUrl, disco.msgBody) |
|
81 |
except SOAPException: |
|
82 |
return None |
|
83 |
disco.processQueryResponseMsg(soap_answer) |
|
84 |
|
|
85 |
service = disco.getService() |
|
86 |
lasso.registerIdWsf2DstService(prefill_form.prefix, prefill_form.profile) |
|
87 |
|
|
88 |
service.initQuery() |
|
89 |
|
|
90 |
fields = FieldPrefill.select(lambda x: x.form_id == prefill_form.id) |
|
91 |
for field in fields: |
|
92 |
if field.xpath and field.name: |
|
93 |
service.addQueryItem(field.xpath, field.name) |
|
94 |
|
|
95 |
service.buildRequestMsg() |
|
96 |
|
|
97 |
try: |
|
98 |
soap_answer = soap_call(service.msgUrl, service.msgBody) |
|
99 |
except SOAPException: |
|
100 |
return None |
|
101 |
service.processQueryResponseMsg(soap_answer) |
|
102 |
|
|
103 |
fields_dict = {} |
|
104 |
for field in fields: |
|
105 |
if not field.xpath or not field.name: |
|
106 |
continue |
|
107 |
if field.number > 0: |
|
108 |
number = field.number -1 |
|
109 |
try: |
|
110 |
if field.raw_xml: |
|
111 |
value = service.getAttributeNodes(field.name)[number] |
|
112 |
else: |
|
113 |
value = service.getAttributeStrings(field.name)[number] |
|
114 |
except (IndexError, TypeError): |
|
115 |
value = '' |
|
116 |
# Log |
|
117 |
if value: |
|
118 |
# Regexp transformation |
|
119 |
if field.regexp_match: |
|
120 |
value = re.sub(field.regexp_match, field.regexp_replacing, value) |
|
121 |
value = cleanup_html_value(value) |
|
122 |
# Conversion of select field options |
|
123 |
if field.select_options: |
|
124 |
try: |
|
125 |
value = field.select_options[value] |
|
126 |
except (IndexError, KeyError): |
|
127 |
pass |
|
128 |
if not value: |
|
129 |
continue |
|
130 |
fields_dict[field.name] = value |
|
131 |
|
|
132 |
return fields_dict |
|
133 |
|
|
134 |
def send_prefilled_form(self, prefill_form, page, fields): |
|
135 |
for field_name, new_value in fields.iteritems(): |
|
136 |
# Input |
|
137 |
regex = re.compile('(.*)(<input[^>]*? id="%s".*?>)(.*)' % field_name, |
|
138 |
re.DOTALL | re.IGNORECASE) |
|
139 |
match = regex.match(page) |
|
140 |
if not match: |
|
141 |
regex = re.compile('(.*)(<input[^>]*? name="%s".*?>)(.*)' % field_name, |
|
142 |
re.DOTALL | re.IGNORECASE) |
|
143 |
match = regex.match(page) |
|
144 |
if match: |
|
145 |
before, input_field, after = match.groups() |
|
146 |
if 'value="' in input_field.lower(): |
|
147 |
regex_sub = re.compile('value=".*?"', re.DOTALL | re.IGNORECASE) |
|
148 |
input_field = regex_sub.sub('value="%s"' % new_value, input_field) |
|
149 |
else: |
|
150 |
input_field = input_field.replace('<input', '<input value="%s"' % new_value) |
|
151 |
page = ''.join([before, input_field, after]) |
|
152 |
continue |
|
153 |
|
|
154 |
# Textarea |
|
155 |
regex = re.compile('(.*<textarea[^>]*? id="%s".*?>)[^<]*(</textarea>.*)' % field_name, |
|
156 |
re.DOTALL | re.IGNORECASE) |
|
157 |
match = regex.match(page) |
|
158 |
if not match: |
|
159 |
regex = re.compile('(.*<textarea[^>]*? name="%s".*?>)[^<]*(</textarea>.*)' % field_name, |
|
160 |
re.DOTALL | re.IGNORECASE) |
|
161 |
match = regex.match(page) |
|
162 |
if match: |
|
163 |
before, after = match.groups() |
|
164 |
page = ''.join([before, new_value, after]) |
|
165 |
continue |
|
166 |
|
|
167 |
# Select |
|
168 |
regex = re.compile('(.*<select[^>]*? id="%s".*?>)(.*?)(</select>.*)' % field_name, |
|
169 |
re.DOTALL | re.IGNORECASE) |
|
170 |
match = regex.match(page) |
|
171 |
if not match: |
|
172 |
regex = re.compile('(.*<select[^>]*? name="%s".*?>)(.*?)(</select>.*)' % field_name, |
|
173 |
re.DOTALL | re.IGNORECASE) |
|
174 |
match = regex.match(page) |
|
175 |
if match: |
|
176 |
before, options, after = match.groups() |
|
177 |
# If the option to select is found, first unselect the previoulsy selected one |
|
178 |
regex2 = re.compile('(.*<option[^>]*? value="%s".*?)(>[^<]*</option>.*)' % new_value, |
|
179 |
re.DOTALL | re.IGNORECASE) |
|
180 |
match2 = regex2.match(options) |
|
181 |
if match2: |
|
182 |
before2, after2 = match2.groups() |
|
183 |
regex3 = re.compile('(.*<option[^>]*?)( selected(="selected")?)(.*?>[^<]*</option>.*)', |
|
184 |
re.DOTALL | re.IGNORECASE) |
|
185 |
match3 = regex3.match(options) |
|
186 |
if match3: |
|
187 |
before3, selected, selected_value, after3 = match3.groups() |
|
188 |
options = ''.join([before3, after3]) |
|
189 |
regex2 = re.compile('(.*<option[^>]*? value="%s".*?)(>[^<]*</option>.*)' % new_value, |
|
190 |
re.DOTALL | re.IGNORECASE) |
|
191 |
match2 = regex2.match(options) |
|
192 |
if match2: |
|
193 |
before2, after2 = match2.groups() |
|
194 |
options = ''.join([before2, ' selected="selected"', after2]) |
|
195 |
|
|
196 |
page = ''.join([before, options, after]) |
|
197 |
|
|
198 |
return page |
|
199 |
|
larpe/tags/release-1.1.1/larpe/liberty.ptl | ||
---|---|---|
1 |
import libxml2 |
|
2 |
import urllib |
|
3 |
import urlparse |
|
4 |
import httplib |
|
5 |
import re |
|
6 |
import os |
|
7 |
|
|
8 |
from quixote import get_field, get_request, get_response, get_session, get_session_manager, redirect |
|
9 |
from quixote.directory import Directory |
|
10 |
from quixote.http_request import parse_header |
|
11 |
|
|
12 |
import lasso |
|
13 |
|
|
14 |
from qommon import get_logger |
|
15 |
from qommon.form import * |
|
16 |
from qommon.template import * |
|
17 |
from qommon.liberty import soap_call, SOAPException |
|
18 |
|
|
19 |
import misc |
|
20 |
from users import User |
|
21 |
from hosts import Host |
|
22 |
from federations import Federation |
|
23 |
import site_authentication |
|
24 |
|
|
25 |
class Liberty(Directory): |
|
26 |
_q_exports = ['', 'login', 'assertionConsumer', 'soapEndpoint', |
|
27 |
'singleLogout', 'singleLogoutReturn', |
|
28 |
'federationTermination', 'federationTerminationReturn', |
|
29 |
('metadata.xml', 'metadata'), 'public_key', 'local_auth'] |
|
30 |
|
|
31 |
def perform_login(self, idp = None): |
|
32 |
server = misc.get_lasso_server() |
|
33 |
login = lasso.Login(server) |
|
34 |
login.initAuthnRequest(idp, lasso.HTTP_METHOD_REDIRECT) |
|
35 |
login.request.nameIdPolicy = 'federated' |
|
36 |
login.request.forceAuthn = False |
|
37 |
login.request.isPassive = False |
|
38 |
login.request.consent = 'urn:liberty:consent:obtained' |
|
39 |
login.buildAuthnRequestMsg() |
|
40 |
return redirect(login.msgUrl) |
|
41 |
|
|
42 |
def assertionConsumer(self): |
|
43 |
server = misc.get_lasso_server() |
|
44 |
if not server: |
|
45 |
return error_page(_('Liberty support is not yet configured')) |
|
46 |
login = lasso.Login(server) |
|
47 |
request = get_request() |
|
48 |
if request.get_method() == 'GET' or get_field('LAREQ'): |
|
49 |
if request.get_method() == 'GET': |
|
50 |
login.initRequest(request.get_query(), lasso.HTTP_METHOD_REDIRECT) |
|
51 |
else: |
|
52 |
login.initRequest(get_field('LAREQ'), lasso.HTTP_METHOD_POST) |
|
53 |
|
|
54 |
login.buildRequestMsg() |
|
55 |
try: |
|
56 |
soap_answer = soap_call(login.msgUrl, login.msgBody) |
|
57 |
except SOAPException: |
|
58 |
return error_page(_('Failure to communicate with identity provider')) |
|
59 |
try: |
|
60 |
login.processResponseMsg(soap_answer) |
|
61 |
except lasso.Error, error: |
|
62 |
if error[0] == lasso.LOGIN_ERROR_STATUS_NOT_SUCCESS: |
|
63 |
return error_page(_('Unknown authentication failure')) |
|
64 |
if hasattr(lasso, 'LOGIN_ERROR_UNKNOWN_PRINCIPAL'): |
|
65 |
if error[0] == lasso.LOGIN_ERROR_UNKNOWN_PRINCIPAL: |
|
66 |
return error_page(_('Authentication failure; unknown principal')) |
|
67 |
return error_page(_("Identity Provider didn't accept artifact transaction.")) |
|
68 |
else: |
|
69 |
login.processAuthnResponseMsg(get_field('LARES')) |
|
70 |
login.acceptSso() |
|
71 |
session = get_session() |
|
72 |
if login.isSessionDirty: |
|
73 |
if login.session: |
|
74 |
session.lasso_session_dumps[server.providerId] = login.session.dump() |
|
75 |
else: |
|
76 |
session.lasso_session_dumps[server.providerId] = None |
|
77 |
|
|
78 |
# Look for an existing user |
|
79 |
user = self.lookup_user(session, login) |
|
80 |
|
|
81 |
# Check if it is for Larpe administration or token |
|
82 |
host = Host.get_host_from_url() |
|
83 |
if host is None: |
|
84 |
return redirect('%s/' % get_request().environ['SCRIPT_NAME']) |
|
85 |
if host.name == 'larpe': |
|
86 |
if user: |
|
87 |
session.set_user(user.id, server.providerId) |
|
88 |
else: |
|
89 |
session.name_identifier = login.nameIdentifier.content |
|
90 |
session.lasso_anonymous_identity_dump = login.identity.dump() |
|
91 |
session.provider_id = server.providerId |
|
92 |
|
|
93 |
if session.after_url: |
|
94 |
# Access to an admin page or token url with parameter |
|
95 |
after_url = session.after_url |
|
96 |
session.after_url = None |
|
97 |
return redirect(after_url) |
|
98 |
|
|
99 |
if user and user.is_admin: |
|
100 |
return redirect('%s/admin/' % get_request().environ['SCRIPT_NAME']) |
|
101 |
else: |
|
102 |
return redirect('%s/token' % get_request().environ['SCRIPT_NAME']) |
|
103 |
|
|
104 |
# Set session user |
|
105 |
if not user: |
|
106 |
user = User() |
|
107 |
user.name_identifiers = [ login.nameIdentifier.content ] |
|
108 |
user.lasso_dumps = [ login.identity.dump() ] |
|
109 |
user.store() |
|
110 |
session.set_user(user.id, server.providerId) |
|
111 |
|
|
112 |
federations = Federation.select(lambda x: host.id == x.host_id \ |
|
113 |
and user.name_identifiers[0] in x.name_identifiers) |
|
114 |
|
|
115 |
if federations: |
|
116 |
return site_authentication.get_site_authentication(host).sso_local_login(federations[0]) |
|
117 |
else: |
|
118 |
response = get_response() |
|
119 |
if session.after_url: |
|
120 |
after_url = session.after_url |
|
121 |
session.after_url = None |
|
122 |
return redirect(after_url) |
|
123 |
response.set_status(303) |
|
124 |
response.headers['location'] = urlparse.urljoin(request.get_url(), str('local_auth')) |
|
125 |
response.content_type = 'text/plain' |
|
126 |
return 'Your browser should redirect you' |
|
127 |
|
|
128 |
def lookup_user(self, session, login): |
|
129 |
found_users = list(User.select(lambda x: login.nameIdentifier.content in x.name_identifiers)) |
|
130 |
if found_users: |
|
131 |
return found_users[0] |
|
132 |
return None |
|
133 |
|
|
134 |
def singleLogout(self): |
|
135 |
request = get_request() |
|
136 |
logout = lasso.Logout(misc.get_lasso_server()) |
|
137 |
if lasso.isLibertyQuery(request.get_query()): |
|
138 |
try: |
|
139 |
logout.processRequestMsg(request.get_query()) |
|
140 |
except lasso.Error, error: |
|
141 |
if error[0] == lasso.DS_ERROR_INVALID_SIGNATURE: |
|
142 |
return error_page(_('Failed to check single logout request signature.')) |
|
143 |
raise |
|
144 |
session = get_session() |
|
145 |
if not session.id: |
|
146 |
# session has not been found, this may be because the user has |
|
147 |
# its browser configured so that cookies are not sent for |
|
148 |
# remote queries and IdP is using image-based SLO. |
|
149 |
# so we look up a session with the appropriate name identifier |
|
150 |
for session in get_session_manager().values(): |
|
151 |
# This block differs from qommon |
|
152 |
user = session.get_user(logout.server.providerId) |
|
153 |
if user and logout.nameIdentifier.content in user.name_identifiers: |
|
154 |
break |
|
155 |
else: |
|
156 |
session = get_session() |
|
157 |
return self.slo_idp(logout, session) |
|
158 |
else: |
|
159 |
return self.slo_sp(logout, get_session()) |
|
160 |
|
|
161 |
def singleLogoutReturn(self): |
|
162 |
logout = lasso.Logout(misc.get_lasso_server()) |
|
163 |
host = Host.get_host_from_url() |
|
164 |
if host is None: |
|
165 |
return redirect('%s/' % get_request().environ['SCRIPT_NAME']) |
|
166 |
|
|
167 |
try: |
|
168 |
logout.processResponseMsg(get_request().get_query()) |
|
169 |
except lasso.Error, error: |
|
170 |
if error[0] == lasso.PROFILE_ERROR_INVALID_QUERY: |
|
171 |
raise AccessError() |
|
172 |
if error[0] == lasso.DS_ERROR_INVALID_SIGNATURE: |
|
173 |
return error_page(_('Failed to check single logout request signature.')) |
|
174 |
if hasattr(lasso, 'LOGOUT_ERROR_REQUEST_DENIED') and \ |
|
175 |
error[0] == lasso.LOGOUT_ERROR_REQUEST_DENIED: |
|
176 |
return redirect(host.get_root_url()) # ignore silently |
|
177 |
elif error[0] == lasso.ERROR_UNDEFINED: |
|
178 |
# XXX: unknown status; ignoring for now. |
|
179 |
return redirect(host.get_root_url()) # ignore silently |
|
180 |
raise |
|
181 |
return redirect(host.get_root_url()) |
|
182 |
|
|
183 |
def slo_idp(self, logout, session): |
|
184 |
'''Single Logout initiated by IdP''' |
|
185 |
# This block differs from qommon |
|
186 |
if session.lasso_session_dumps.has_key(logout.server.providerId): |
|
187 |
logout.setSessionFromDump(session.lasso_session_dumps[logout.server.providerId]) |
|
188 |
user = session.get_user(logout.server.providerId) |
|
189 |
if user and user.lasso_dumps: |
|
190 |
logout.setIdentityFromDump(user.lasso_dumps[0]) |
|
191 |
if user and logout.nameIdentifier.content not in user.name_identifiers: |
|
192 |
raise 'No appropriate name identifier in user (%s and %s)' % ( |
|
193 |
logout.nameIdentifier.content, user.name_identifiers) |
|
194 |
|
|
195 |
host = Host.get_host_with_provider_id(logout.server.providerId) |
|
196 |
if host is not None: |
|
197 |
site_authentication.get_site_authentication(host).local_logout(user=user) |
|
198 |
|
|
199 |
try: |
|
200 |
logout.validateRequest() |
|
201 |
except lasso.Error, error: |
|
202 |
if error[0] != lasso.PROFILE_ERROR_SESSION_NOT_FOUND: |
|
203 |
raise |
|
204 |
else: |
|
205 |
get_session_manager().expire_session(logout.server.providerId) |
|
206 |
|
|
207 |
logout.buildResponseMsg() |
|
208 |
if logout.msgBody: # soap answer |
|
209 |
return logout.msgBody |
|
210 |
else: |
|
211 |
return redirect(logout.msgUrl) |
|
212 |
|
|
213 |
def slo_sp(self, logout, session): |
|
214 |
host = Host.get_host_from_url() |
|
215 |
if host is None: |
|
216 |
return redirect('%s/' % get_request().environ['SCRIPT_NAME']) |
|
217 |
|
|
218 |
if not session.id or not session.users.has_key(logout.server.providerId) \ |
|
219 |
or not session.lasso_session_dumps.has_key(logout.server.providerId): |
|
220 |
get_session_manager().expire_session(logout.server.providerId) |
|
221 |
return redirect(host.get_root_url()) |
|
222 |
|
|
223 |
logout.setSessionFromDump(session.lasso_session_dumps[logout.server.providerId]) |
|
224 |
user = session.get_user(logout.server.providerId) |
|
225 |
|
|
226 |
if host.name != 'larpe' and user: |
|
227 |
site_authentication.get_site_authentication(host).local_logout(user=user) |
|
228 |
|
|
229 |
if user and user.lasso_dumps: |
|
230 |
logout.setIdentityFromDump(user.lasso_dumps[0]) |
|
231 |
else: |
|
232 |
get_session_manager().expire_session(logout.server.providerId) |
|
233 |
return redirect(host.get_root_url()) |
|
234 |
|
|
235 |
return self.slo_sp_redirect(logout, host) |
|
236 |
|
|
237 |
def slo_sp_redirect(self, logout, host): |
|
238 |
try: |
|
239 |
logout.initRequest(None, lasso.HTTP_METHOD_REDIRECT) |
|
240 |
except lasso.Error, error: |
|
241 |
if error[0] == lasso.PROFILE_ERROR_NAME_IDENTIFIER_NOT_FOUND: |
|
242 |
get_session_manager().expire_session() |
|
243 |
return redirect(host.get_root_url()) |
|
244 |
raise |
|
245 |
logout.buildRequestMsg() |
|
246 |
get_session_manager().expire_session(logout.server.providerId) |
|
247 |
return redirect(logout.msgUrl) |
|
248 |
|
|
249 |
def soapEndpoint(self): |
|
250 |
request = get_request() |
|
251 |
ctype = request.environ.get('CONTENT_TYPE') |
|
252 |
if not ctype: |
|
253 |
return |
|
254 |
|
|
255 |
ctype, ctype_params = parse_header(ctype) |
|
256 |
if ctype != 'text/xml': |
|
257 |
return |
|
258 |
|
|
259 |
response = get_response() |
|
260 |
response.set_content_type('text/xml') |
|
261 |
|
|
262 |
length = int(request.environ.get('CONTENT_LENGTH')) |
|
263 |
soap_message = request.stdin.read(length) |
|
264 |
|
|
265 |
request_type = lasso.getRequestTypeFromSoapMsg(soap_message) |
|
266 |
|
|
267 |
if request_type == lasso.REQUEST_TYPE_LOGOUT: |
|
268 |
logout = lasso.Logout(misc.get_lasso_server()) |
|
269 |
logout.processRequestMsg(soap_message) |
|
270 |
name_identifier = logout.nameIdentifier.content |
|
271 |
for session in get_session_manager().values(): |
|
272 |
user = session.get_user(logout.server.providerId) |
|
273 |
if user and logout.nameIdentifier.content in user.name_identifiers: |
|
274 |
break |
|
275 |
else: |
|
276 |
session = None |
|
277 |
return self.slo_idp(logout, session) |
|
278 |
|
|
279 |
if request_type == lasso.REQUEST_TYPE_DEFEDERATION: |
|
280 |
defederation = lasso.Defederation(misc.get_lasso_server()) |
|
281 |
defederation.processNotificationMsg(soap_message) |
|
282 |
for session in get_session_manager().values(): |
|
283 |
user = session.get_user(defederation.server.providerId) |
|
284 |
if user and defederation.nameIdentifier.content in user.name_identifiers: |
|
285 |
break |
|
286 |
else: |
|
287 |
session = None |
|
288 |
return self.fedterm(defederation, session) |
|
289 |
|
|
290 |
def federationTermination(self): |
|
291 |
request = get_request() |
|
292 |
if not lasso.isLibertyQuery(request.get_query()): |
|
293 |
return redirect('%s/' % get_request().environ['SCRIPT_NAME']) |
|
294 |
|
|
295 |
defederation = lasso.Defederation(misc.get_lasso_server()) |
|
296 |
defederation.processNotificationMsg(request.get_query()) |
|
297 |
return self.fedterm(defederation, get_session()) |
|
298 |
|
|
299 |
def fedterm(self, defederation, session): |
|
300 |
if session is not None: |
|
301 |
host = Host.get_host_with_provider_id(defederation.server.providerId) |
|
302 |
if host is not None: |
|
303 |
site_authentication.get_site_authentication(host).local_defederate(session, defederation.server.providerId) |
|
304 |
if session.lasso_session_dumps.has_key(defederation.server.providerId): |
|
305 |
defederation.setSessionFromDump(session.lasso_session_dumps[defederation.server.providerId]) |
|
306 |
user = session.get_user(defederation.server.providerId) |
|
307 |
if user and user.lasso_dumps: |
|
308 |
defederation.setIdentityFromDump(user.lasso_dumps[0]) |
|
309 |
else: |
|
310 |
user = None |
|
311 |
|
|
312 |
try: |
|
313 |
defederation.validateNotification() |
|
314 |
except lasso.Error, error: |
|
315 |
pass # ignore failure (?) |
|
316 |
else: |
|
317 |
if user: |
|
318 |
if not defederation.identity: |
|
319 |
# if it was the last federation the whole identity dump collapsed |
|
320 |
del user.lasso_dumps[0] |
|
321 |
else: |
|
322 |
user.lasso_dumps[0] = defederation.identity.dump() |
|
323 |
user.store() |
|
324 |
|
|
325 |
if user and defederation.nameIdentifier.content: |
|
326 |
user.remove_name_identifier(defederation.nameIdentifier.content) |
|
327 |
user.store() |
|
328 |
|
|
329 |
if defederation.isSessionDirty and session is not None: |
|
330 |
if not defederation.session: |
|
331 |
del session.lasso_session_dumps[defederation.server.providerId] |
|
332 |
else: |
|
333 |
session.lasso_session_dumps[defederation.server.providerId] = defederation.session.dump() |
|
334 |
session.store() |
|
335 |
|
|
336 |
get_session_manager().expire_session(defederation.server.providerId) |
|
337 |
|
|
338 |
if defederation.msgUrl: |
|
339 |
return redirect(defederation.msgUrl) |
|
340 |
else: |
|
341 |
response = get_response() |
|
342 |
response.set_status(204) |
|
343 |
return '' |
|
344 |
|
|
345 |
def federationTerminationReturn(self): |
|
346 |
host = Host.get_host_from_url() |
|
347 |
if host is None: |
|
348 |
return redirect('%s/' % get_request().environ['SCRIPT_NAME']) |
|
349 |
return redirect(host.get_return_url()) |
|
350 |
|
|
351 |
def local_auth(self): |
|
352 |
host = Host.get_host_from_url() |
|
353 |
if host is None: |
|
354 |
return redirect('%s/' % get_request().environ['SCRIPT_NAME']) |
|
355 |
return site_authentication.get_site_authentication(host).local_auth |
|
356 |
local_auth = property(local_auth) |
|
357 |
|
|
358 |
def metadata(self): |
|
359 |
host = Host.get_host_from_url() |
|
360 |
if host is None: |
|
361 |
return redirect('%s/' % get_request().environ['SCRIPT_NAME']) |
|
362 |
get_response().set_content_type('text/xml', 'utf-8') |
|
363 |
metadata = unicode(open(host.metadata).read(), 'utf-8') |
|
364 |
return metadata |
|
365 |
|
|
366 |
def public_key(self): |
|
367 |
host = Host.get_host_from_url() |
|
368 |
if host is None: |
|
369 |
return redirect('%s/' % get_request().environ['SCRIPT_NAME']) |
|
370 |
get_response().set_content_type('text/plain') |
|
371 |
public_key = open(host.public_key).read() |
|
372 |
return public_key |
larpe/tags/release-1.1.1/larpe/liberty_root.ptl | ||
---|---|---|
1 |
from quixote.directory import Directory |
|
2 |
from quixote import get_response |
|
3 |
|
|
4 |
from liberty_site import LibertySite |
|
5 |
|
|
6 |
class LibertyRootDirectory(Directory): |
|
7 |
|
|
8 |
def _q_lookup(self, component): |
|
9 |
return LibertySite(component) |
larpe/tags/release-1.1.1/larpe/liberty_site.ptl | ||
---|---|---|
1 |
import sys |
|
2 |
import random |
|
3 |
|
|
4 |
from quixote import get_publisher, get_response, redirect, get_request |
|
5 |
from quixote.directory import Directory |
|
6 |
from quixote.errors import TraversalError |
|
7 |
|
|
8 |
import lasso |
|
9 |
|
|
10 |
import admin |
|
11 |
import liberty |
|
12 |
import saml2 |
|
13 |
import idwsf2 |
|
14 |
import httplib |
|
15 |
import urllib |
|
16 |
|
|
17 |
from qommon.form import * |
|
18 |
from qommon.misc import get_abs_path, get_current_protocol |
|
19 |
from qommon import template, get_logger |
|
20 |
|
|
21 |
import errors |
|
22 |
import misc |
|
23 |
|
|
24 |
from users import User |
|
25 |
from hosts import Host |
|
26 |
|
|
27 |
class LibertySite(Directory): |
|
28 |
|
|
29 |
_q_exports = ['', 'login', 'logout', 'liberty', 'saml', 'idwsf2'] |
|
30 |
|
|
31 |
liberty = liberty.Liberty() |
|
32 |
saml = saml2.Saml2() |
|
33 |
idwsf2 = idwsf2.IdWsf2() |
|
34 |
|
|
35 |
def __init__(self, component): |
|
36 |
self.name = component |
|
37 |
|
|
38 |
def _q_index (self): |
|
39 |
raise errors.TraversalError() |
|
40 |
|
|
41 |
def login [html] (self): |
|
42 |
get_logger().info('login') |
|
43 |
get_publisher().reload_cfg() |
|
44 |
|
|
45 |
if not get_publisher().cfg.has_key('idp'): |
|
46 |
return template.error_page(_('SSO support is not yet configured')) |
|
47 |
else: |
|
48 |
server = misc.get_lasso_server('liberty') |
|
49 |
if server is not None: |
|
50 |
return self.liberty.perform_login() |
|
51 |
|
|
52 |
server = misc.get_lasso_server('saml2') |
|
53 |
if server is not None: |
|
54 |
return self.saml.perform_login() |
|
55 |
|
|
56 |
return template.error_page(_('SSO support is not yet configured')) |
|
57 |
|
|
58 |
def logout(self): |
|
59 |
get_logger().info('logout') |
|
60 |
session = get_session() |
|
61 |
if not session: |
|
62 |
return redirect('%s/' % get_request().environ['SCRIPT_NAME']) |
|
63 |
|
|
64 |
if misc.get_current_protocol() == lasso.PROTOCOL_SAML_2_0: |
|
65 |
return self.saml.slo_sp() |
|
66 |
else: |
|
67 |
return self.liberty.singleLogout() |
|
68 |
|
larpe/tags/release-1.1.1/larpe/logger.py | ||
---|---|---|
1 |
import logging |
|
2 |
|
|
3 |
from quixote import get_request, get_session |
|
4 |
|
|
5 |
from qommon.logger import BotFilter |
|
6 |
|
|
7 |
from hosts import Host |
|
8 |
|
|
9 |
class Formatter(logging.Formatter): |
|
10 |
def format(self, record): |
|
11 |
request = get_request() |
|
12 |
|
|
13 |
record.address = request.get_environ('REMOTE_ADDR', '-') |
|
14 |
record.path = request.get_path() |
|
15 |
record.session_id = get_session().get_session_id() or '[nosession]' |
|
16 |
|
|
17 |
user = None |
|
18 |
host = Host.get_host_from_url() |
|
19 |
if not host: |
|
20 |
host = Host.select(lambda x: x.name == 'larpe')[0] |
|
21 |
if host: |
|
22 |
user = get_session().get_user(host.provider_id) |
|
23 |
if not user: |
|
24 |
user = get_session().get_user(host.saml2_provider_id) |
|
25 |
|
|
26 |
if user: |
|
27 |
user_id = user.id |
|
28 |
else: |
|
29 |
user_id = 'unlogged' |
|
30 |
if BotFilter.is_bot(): |
|
31 |
user_id = 'bot' |
|
32 |
record.user_id = user_id |
|
33 |
|
|
34 |
return logging.Formatter.format(self, record) |
larpe/tags/release-1.1.1/larpe/misc.py | ||
---|---|---|
1 |
import re |
|
2 |
import os |
|
3 |
|
|
4 |
import lasso |
|
5 |
|
|
6 |
from quixote import get_publisher, get_request |
|
7 |
|
|
8 |
from qommon.misc import get_abs_path |
|
9 |
|
|
10 |
from hosts import Host |
|
11 |
|
|
12 |
def get_root_url(): |
|
13 |
req = get_request() |
|
14 |
return '%s://%s%s' % (req.get_scheme(), req.get_server(), req.environ['SCRIPT_NAME']) |
|
15 |
|
|
16 |
def get_proxied_site_path(): |
|
17 |
host = Host.get_host_from_url() |
|
18 |
if host is None: |
|
19 |
return None |
|
20 |
return host.site_dir |
|
21 |
|
|
22 |
def get_proxied_site_domain(): |
|
23 |
return get_request().get_server().split(':')[0] |
|
24 |
|
|
25 |
def get_identity_provider_config(): |
|
26 |
get_publisher().reload_cfg() |
|
27 |
idps_dir = get_abs_path('idp') |
|
28 |
if get_publisher().cfg.has_key('idp'): |
|
29 |
idp_dir = os.path.join(idps_dir, get_publisher().cfg['idp']) |
|
30 |
|
|
31 |
metadata_path = os.path.join(idp_dir, 'metadata.xml') |
|
32 |
|
|
33 |
public_key_path = os.path.join(idp_dir, 'public_key') |
|
34 |
if not os.path.isfile(public_key_path): |
|
35 |
public_key_path = None |
|
36 |
|
|
37 |
ca_cert_chain_path = os.path.join(idp_dir, 'ca_cert_chain.pem') |
|
38 |
if not os.path.isfile(ca_cert_chain_path): |
|
39 |
ca_cert_chain_path = None |
|
40 |
|
|
41 |
return metadata_path, public_key_path, ca_cert_chain_path |
|
42 |
return None, None, None |
|
43 |
|
|
44 |
def get_lasso_server(protocol='liberty'): |
|
45 |
proxied_site_path = get_proxied_site_path() |
|
46 |
if proxied_site_path is None: |
|
47 |
return None |
|
48 |
if protocol == 'liberty': |
|
49 |
server = lasso.Server( |
|
50 |
os.path.join(proxied_site_path, 'metadata.xml'), |
|
51 |
os.path.join(proxied_site_path, 'private_key.pem'), |
|
52 |
None, None) |
|
53 |
elif protocol == 'saml2': |
|
54 |
server = lasso.Server( |
|
55 |
os.path.join(proxied_site_path, 'saml2_metadata.xml'), |
|
56 |
os.path.join(proxied_site_path, 'private_key.pem'), |
|
57 |
None, None) |
|
58 |
else: |
|
59 |
raise 'Unknown protocol' |
|
60 |
|
|
61 |
metadata_path, public_key_path, ca_cert_chain_path = get_identity_provider_config() |
|
62 |
if metadata_path: |
|
63 |
try: |
|
64 |
server.addProvider( |
|
65 |
lasso.PROVIDER_ROLE_IDP, |
|
66 |
metadata_path, |
|
67 |
public_key_path, |
|
68 |
ca_cert_chain_path) |
|
69 |
except lasso.Error, error: |
|
70 |
if error[0] == lasso.SERVER_ERROR_ADD_PROVIDER_PROTOCOL_MISMATCH: |
|
71 |
return None |
|
72 |
if error[0] == lasso.SERVER_ERROR_ADD_PROVIDER_FAILED: |
|
73 |
return None |
|
74 |
raise |
|
75 |
|
|
76 |
return server |
|
77 |
|
|
78 |
def get_provider_label(provider): |
|
79 |
if not provider: |
|
80 |
return None |
|
81 |
if not hasattr(provider, str('getOrganization')): |
|
82 |
return provider.providerId |
|
83 |
|
|
84 |
organization = provider.getOrganization() |
|
85 |
if not organization: |
|
86 |
return provider.providerId |
|
87 |
|
|
88 |
name = re.findall("<OrganizationDisplayName.*>(.*?)</OrganizationDisplayName>", organization) |
|
89 |
if not name: |
|
90 |
name = re.findall("<OrganizationName.*>(.*?)</OrganizationName>", organization) |
|
91 |
if not name: |
|
92 |
return provider.providerId |
|
93 |
return name[0] |
|
94 |
|
|
95 |
def get_current_protocol(): |
|
96 |
metadata_path, public_key_path, ca_cert_chain_path = get_identity_provider_config() |
|
97 |
if not metadata_path: |
|
98 |
return None |
|
99 |
try: |
|
100 |
provider = lasso.Provider(lasso.PROVIDER_ROLE_IDP, metadata_path, public_key_path, None) |
|
101 |
except lasso.Error: |
|
102 |
return None |
|
103 |
else: |
|
104 |
return provider.getProtocolConformance() |
|
105 |
|
larpe/tags/release-1.1.1/larpe/plugins/__init__.py | ||
---|---|---|
1 |
from larpe.plugins.site_authentication_plugins import SiteAuthenticationPlugins |
|
2 |
|
|
3 |
site_authentication_plugins = SiteAuthenticationPlugins() |
larpe/tags/release-1.1.1/larpe/plugins/site_authentication/agirhe.py | ||
---|---|---|
1 |
import re |
|
2 |
import urllib |
|
3 |
|
|
4 |
from quixote import get_request, get_response, get_session |
|
5 |
|
|
6 |
from qommon.misc import http_post_request |
|
7 |
from qommon.errors import ConnectionError |
|
8 |
from qommon import get_logger |
|
9 |
|
|
10 |
from larpe.qommon.misc import http_get_page |
|
11 |
from larpe.plugins import site_authentication_plugins |
|
12 |
from larpe.site_authentication import SiteAuthentication |
|
13 |
|
|
14 |
class AgirheSiteAuthentication(SiteAuthentication): |
|
15 |
plugin_name = 'agirhe' |
|
16 |
|
|
17 |
def auto_detect_site(cls, html_doc): |
|
18 |
if re.search( |
|
19 |
"""<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/""", |
|
20 |
html_doc): |
|
21 |
return True |
|
22 |
return False |
|
23 |
auto_detect_site = classmethod(auto_detect_site) |
|
24 |
|
|
25 |
def local_auth_check_post(self, username, password, select=None): |
|
26 |
select = select or {} |
|
27 |
url = self.host.auth_check_url |
|
28 |
|
|
29 |
# Build request body |
|
30 |
body = '%s=%s&%s=%s' % ( |
|
31 |
self.host.login_field_name, username, self.host.password_field_name, password) |
|
32 |
# Add select fields to the body |
|
33 |
for name, value in select.iteritems(): |
|
34 |
body += '&%s=%s' % (name, value) |
|
35 |
|
|
36 |
# Get the authentication page |
|
37 |
try: |
|
38 |
response, status, page, auth_headers = http_get_page( |
|
39 |
self.host.auth_form_url, use_proxy=self.host.use_proxy) |
|
40 |
except ConnectionError, err: |
|
41 |
get_logger().warn(err) |
|
42 |
return None, None |
|
43 |
|
|
44 |
# Get current hidden fields everytime |
|
45 |
self.parse_forms(page) |
|
46 |
if self.host.auth_form is not None: |
|
47 |
self.parse_other_fields() |
|
48 |
|
|
49 |
# Add hidden fields to the body |
|
50 |
for key, value in self.host.other_fields.iteritems(): |
|
51 |
value = urllib.quote_plus(value) |
|
52 |
body += '&%s=%s' % (key, value) |
|
53 |
|
|
54 |
# Build request HTTP headers |
|
55 |
headers = {'Content-Type': 'application/x-www-form-urlencoded', |
|
56 |
'X-Forwarded-For': get_request().get_environ('REMOTE_ADDR', '-'), |
|
57 |
'X-Forwarded-Host': self.host.reversed_hostname} |
|
58 |
|
|
59 |
# Send request |
|
60 |
response, status, data, auth_headers = http_post_request( |
|
61 |
url, body, headers, self.host.use_proxy) |
|
62 |
|
|
63 |
cookies = response.getheader('Set-Cookie', None) |
|
64 |
self.host.cookies = [] |
|
65 |
if cookies is not None: |
|
66 |
cookies_list = [] |
|
67 |
cookies_set_list = [] |
|
68 |
for cookie in cookies.split(', '): |
|
69 |
# Drop the path and other attributes |
|
70 |
cookie_only = cookie.split('; ')[0] |
|
71 |
regexp = re.compile('=') |
|
72 |
if regexp.search(cookie_only) is None: |
|
73 |
continue |
|
74 |
# Split name and value |
|
75 |
cookie_split = cookie_only.split('=') |
|
76 |
cookie_name = cookie_split[0] |
|
77 |
cookie_value = cookie_split[1] |
|
78 |
cookies_list.append('%s=%s' % (cookie_name, cookie_value)) |
|
79 |
set_cookie = '%s=%s; path=/' % (cookie_name, cookie_value) |
|
80 |
cookies_set_list.append(set_cookie) |
|
81 |
self.host.cookies.append(cookie_name) |
|
82 |
cookies_headers = '\r\nSet-Cookie: '.join(cookies_set_list) |
|
83 |
get_response().set_header('Set-Cookie', cookies_headers) |
|
84 |
self.host.store() |
|
85 |
get_session().cookies = '; '.join(cookies_list) |
|
86 |
else: |
|
87 |
get_logger().warn('No cookie from local authentication') |
|
88 |
|
|
89 |
return response.status, data |
|
90 |
|
|
91 |
# The 3 following functions have been copied from admin/hosts.ptl |
|
92 |
|
|
93 |
def parse_forms(self, page): |
|
94 |
'''Search for an authentication form''' |
|
95 |
# Get all forms |
|
96 |
regexp = re.compile("""<form.*?</form>""", re.DOTALL | re.IGNORECASE) |
|
97 |
found_forms = regexp.findall(page) |
|
98 |
if not found_forms: |
|
99 |
return |
|
100 |
|
|
101 |
# Get the first form with a password field |
|
102 |
for found_form in found_forms: |
|
103 |
regexp = re.compile( |
|
104 |
"""<input[^>]*?type=["']?password["']?[^>]*?>""", re.DOTALL | re.IGNORECASE) |
|
105 |
if regexp.search(found_form) is not None: |
|
106 |
self.host.auth_form = found_form |
|
107 |
break |
|
108 |
|
|
109 |
def parse_other_fields(self): |
|
110 |
'''Get the default value of all other fields''' |
|
111 |
self.host.other_fields = {} |
|
112 |
|
|
113 |
# Get hidden fields |
|
114 |
regexp = re.compile( |
|
115 |
"""<input[^>]*?type=["']?hidden["']?[^>]*?>""", re.DOTALL | re.IGNORECASE) |
|
116 |
other_fields = regexp.findall(self.host.auth_form) |
|
117 |
|
|
118 |
# Only get first submit field |
|
119 |
regexp = re.compile( |
|
120 |
"""<input[^>]*?type=["']?submit["']?[^>]*?>""", re.DOTALL | re.IGNORECASE) |
|
121 |
found = regexp.findall(self.host.auth_form) |
|
122 |
if found: |
|
123 |
if other_fields: |
|
124 |
other_fields.append(found[0]) |
|
125 |
else: |
|
126 |
other_fields = found[0] |
|
127 |
|
|
128 |
for field in other_fields: |
|
129 |
try: |
|
130 |
regexp = re.compile("""name=["']?(.*?)["']?[\s/>]""", re.DOTALL | re.IGNORECASE) |
|
131 |
name = regexp.findall(field)[0] |
|
132 |
regexp = re.compile("""value=["'](.*?)["'][\s/>]""", re.DOTALL | re.IGNORECASE) |
|
133 |
value = regexp.findall(field)[0] |
|
134 |
self.host.other_fields[name] = value |
|
135 |
if not self.host.post_parameters.has_key(name): |
|
136 |
self.host.post_parameters[name] = { 'enabled': True, |
|
137 |
'value': value, |
|
138 |
'immutable': False } |
|
139 |
except IndexError: |
|
140 |
continue |
|
141 |
|
|
142 |
site_authentication_plugins.register(AgirheSiteAuthentication) |
larpe/tags/release-1.1.1/larpe/plugins/site_authentication/ciril_net_rh.py | ||
---|---|---|
1 |
|
|
2 |
import re |
|
3 |
|
|
4 |
from quixote import redirect |
|
5 |
|
|
6 |
from larpe.plugins import site_authentication_plugins |
|
7 |
from larpe.site_authentication import SiteAuthentication |
|
8 |
|
|
9 |
class CirilSiteAuthentication(SiteAuthentication): |
|
10 |
|
|
11 |
plugin_name = 'ciril' |
|
12 |
output_filters = ['output_ciril_net_rh'] |
|
13 |
|
|
14 |
def auto_detect_site(cls, html_doc): |
|
15 |
if re.search( |
|
16 |
"""<form name="myForm" id="myForm" method="post" target="choixAppli" action="/cgi-bin/acces.exe" """, |
|
17 |
html_doc): |
|
18 |
return True |
|
19 |
return False |
|
20 |
auto_detect_site = classmethod(auto_detect_site) |
|
21 |
|
|
22 |
def check_auth(self, status, data): |
|
23 |
success = False |
|
24 |
return_content = '' |
|
25 |
|
|
26 |
# If status is 500, fail without checking other criterias |
|
27 |
if status // 100 == 5: |
|
28 |
success = False |
|
29 |
return_content = redirect(self.host.get_return_url()) |
|
30 |
|
|
31 |
regexp = re.compile( |
|
32 |
"""javascript\:window\.open\('(/net_rh/accueil.php\?.*?)', '_blank'\)""", |
|
33 |
re.DOTALL | re.IGNORECASE) |
|
34 |
match = regexp.findall(data) |
|
35 |
if match: |
|
36 |
success = True |
|
37 |
return_content = redirect(match[0]) |
|
38 |
|
|
39 |
return success, return_content |
|
40 |
|
|
41 |
|
|
42 |
|
|
43 |
site_authentication_plugins.register(CirilSiteAuthentication) |
|
44 |
|
larpe/tags/release-1.1.1/larpe/plugins/site_authentication/concerto.py | ||
---|---|---|
1 |
import re |
|
2 |
|
|
3 |
from quixote import get_request, get_response, get_session |
|
4 |
|
|
5 |
from qommon.misc import http_post_request |
|
6 |
from qommon import get_logger |
|
7 |
|
|
8 |
from larpe.plugins import site_authentication_plugins |
|
9 |
from larpe.site_authentication import SiteAuthentication |
|
10 |
|
|
11 |
class ConcertoSiteAuthentication(SiteAuthentication): |
|
12 |
plugin_name = 'concerto' |
|
13 |
|
|
14 |
def auto_detect_site(cls, html_doc): |
|
15 |
if re.search( |
|
16 |
"""<meta name="description" content="Page d'accueil du site Espace-Famille" />""", |
|
17 |
html_doc): |
|
18 |
return True |
|
19 |
return False |
|
20 |
auto_detect_site = classmethod(auto_detect_site) |
|
21 |
|
|
22 |
def local_auth_check_post(self, username, password, select=None, session_cookies=False): |
|
23 |
select = select or {} |
|
24 |
url = self.host.auth_check_url |
|
25 |
|
|
26 |
# Build request body |
|
27 |
body = '%s=%s&%s=%s' % ( |
|
28 |
self.host.login_field_name, username, self.host.password_field_name, password) |
|
29 |
# Add select fields to the body |
|
30 |
for name, value in select.iteritems(): |
|
31 |
body += '&%s=%s' % (name, value) |
|
32 |
# Add hidden fields to the body |
|
33 |
if self.host.send_hidden_fields: |
|
34 |
for key, value in self.host.other_fields.iteritems(): |
|
35 |
body += '&%s=%s' % (key, value) |
|
36 |
|
|
37 |
# Build request HTTP headers |
|
38 |
headers = {'Content-Type': 'application/x-www-form-urlencoded', |
|
39 |
'X-Forwarded-For': get_request().get_environ('REMOTE_ADDR', '-'), |
|
40 |
'X-Forwarded-Host': self.host.reversed_hostname} |
|
41 |
|
|
42 |
# Add session id cookie |
|
43 |
if session_cookies is True: |
|
44 |
for key, value in self.host.other_fields.iteritems(): |
|
45 |
headers['Cookie'] = 'JSESSIONID=' + value |
|
46 |
|
|
47 |
# Send request |
|
48 |
response, status, data, auth_headers = http_post_request( |
|
49 |
url, body, headers, self.host.use_proxy) |
|
50 |
|
|
51 |
cookies = response.getheader('Set-Cookie', None) |
|
52 |
self.host.cookies = [] |
|
53 |
new_session_id = None |
|
54 |
if cookies is not None: |
|
55 |
cookies_list = [] |
|
56 |
cookies_set_list = [] |
|
57 |
for cookie in cookies.split(', '): |
|
58 |
# Drop the path and other attributes |
|
59 |
cookie_only = cookie.split('; ')[0] |
|
60 |
regexp = re.compile('=') |
|
61 |
if regexp.search(cookie_only) is None: |
|
62 |
continue |
|
63 |
# Split name and value |
|
64 |
cookie_split = cookie_only.split('=') |
|
65 |
cookie_name = cookie_split[0] |
|
66 |
cookie_value = cookie_split[1] |
|
67 |
if cookie_name == 'JSESSIONID': |
|
68 |
new_session_id = cookie_value |
|
69 |
cookies_list.append('%s=%s' % (cookie_name, cookie_value)) |
|
70 |
set_cookie = '%s=%s; path=/demo' % (cookie_name, cookie_value) |
|
71 |
cookies_set_list.append(set_cookie) |
|
72 |
self.host.cookies.append(cookie_name) |
|
73 |
cookies_headers = '\r\nSet-Cookie: '.join(cookies_set_list) |
|
74 |
get_response().set_header('Set-Cookie', cookies_headers) |
|
75 |
self.host.store() |
|
76 |
get_session().cookies = '; '.join(cookies_list) |
|
77 |
else: |
|
78 |
get_logger().warn('No cookie from local authentication') |
|
79 |
|
|
80 |
if session_cookies is False: |
|
81 |
# Change idSession hidden field with new session id |
|
82 |
self.host.other_fields['idSession'] = new_session_id |
|
83 |
# Retry the request with the new session id |
|
84 |
return self.local_auth_check_post(username, password, select, session_cookies=True) |
|
85 |
else: |
|
86 |
return response.status, data |
|
87 |
|
|
88 |
site_authentication_plugins.register(ConcertoSiteAuthentication) |
|
89 |
|
larpe/tags/release-1.1.1/larpe/plugins/site_authentication/egroupware.py | ||
---|---|---|
1 |
import re |
|
2 |
import urlparse |
|
3 |
|
|
4 |
from quixote import get_request, get_response, get_session |
|
5 |
|
|
6 |
from qommon.misc import http_post_request, http_get_page |
|
7 |
from qommon import get_logger |
|
8 |
|
|
9 |
from larpe.plugins import site_authentication_plugins |
|
10 |
from larpe.site_authentication import SiteAuthentication |
|
11 |
|
|
12 |
class EgroupwareSiteAuthentication(SiteAuthentication): |
|
13 |
plugin_name = 'egroupware' |
|
14 |
|
|
15 |
def auto_detect_site(cls, html_doc): |
|
16 |
if re.search("""<meta name="description" content="eGroupWare" />""", html_doc): |
|
17 |
return True |
|
18 |
return False |
|
19 |
auto_detect_site = classmethod(auto_detect_site) |
|
20 |
|
|
21 |
def local_auth_check_post(self, username, password, select=None): |
|
22 |
select = select or {} |
|
23 |
url = self.host.auth_check_url |
|
24 |
|
|
25 |
# Build request body |
|
26 |
body = '%s=%s&%s=%s' % ( |
|
27 |
self.host.login_field_name, username, self.host.password_field_name, password) |
|
28 |
# Add select fields to the body |
|
29 |
for name, value in select.iteritems(): |
|
30 |
body += '&%s=%s' % (name, value) |
|
31 |
# Add hidden fields to the body |
|
32 |
if self.host.send_hidden_fields: |
|
33 |
for key, value in self.host.other_fields.iteritems(): |
|
34 |
body += '&%s=%s' % (key, value) |
|
35 |
|
|
36 |
# Build request HTTP headers |
|
37 |
headers = {'Content-Type': 'application/x-www-form-urlencoded', |
|
38 |
'X-Forwarded-For': get_request().get_environ('REMOTE_ADDR', '-'), |
|
39 |
'X-Forwarded-Host': self.host.reversed_hostname} |
|
40 |
|
|
41 |
# Send request |
|
42 |
response, status, data, auth_headers = http_post_request( |
|
43 |
url, body, headers, self.host.use_proxy) |
|
44 |
|
|
45 |
# The specific code is these 2 lines and the called function |
|
46 |
if self.host.name.startswith('egroupware'): |
|
47 |
data = self.get_data_after_redirects(response, data) |
|
48 |
|
|
49 |
cookies = response.getheader('Set-Cookie', None) |
|
50 |
self.host.cookies = [] |
|
51 |
if cookies is not None: |
|
52 |
cookies_list = [] |
|
53 |
cookies_set_list = [] |
|
54 |
for cookie in cookies.split(', '): |
|
55 |
# Drop the path and other attributes |
|
56 |
cookie_only = cookie.split('; ')[0] |
|
57 |
regexp = re.compile('=') |
|
58 |
if regexp.search(cookie_only) is None: |
|
59 |
continue |
|
60 |
# Split name and value |
|
61 |
cookie_split = cookie_only.split('=') |
|
62 |
cookie_name = cookie_split[0] |
|
63 |
cookie_value = cookie_split[1] |
|
64 |
cookies_list.append('%s=%s' % (cookie_name, cookie_value)) |
|
65 |
set_cookie = '%s=%s; path=/' % (cookie_name, cookie_value) |
|
66 |
cookies_set_list.append(set_cookie) |
|
67 |
self.host.cookies.append(cookie_name) |
|
68 |
cookies_headers = '\r\nSet-Cookie: '.join(cookies_set_list) |
|
69 |
get_response().set_header('Set-Cookie', cookies_headers) |
|
70 |
self.host.store() |
|
71 |
get_session().cookies = '; '.join(cookies_list) |
|
72 |
else: |
|
73 |
get_logger().warn('No cookie from local authentication') |
|
74 |
|
|
75 |
return response.status, data |
|
76 |
|
|
77 |
def get_data_after_redirects(self, response, data): |
|
78 |
status = response.status |
|
79 |
headers = {'X-Forwarded-For': get_request().get_environ('REMOTE_ADDR', '-'), |
|
80 |
'X-Forwarded-Host': self.host.reversed_hostname} |
|
81 |
while status == 302: |
|
82 |
location = response.getheader('Location', None) |
|
83 |
if location is not None: |
|
84 |
url_tokens = urlparse.urlparse(self.host.auth_check_url) |
|
85 |
url = '%s://%s%s'% (url_tokens[0], url_tokens[1], location) |
|
86 |
response, status, data, auth_headers = http_get_page( |
|
87 |
url, headers, self.host.use_proxy) |
|
88 |
return data |
|
89 |
|
|
90 |
site_authentication_plugins.register(EgroupwareSiteAuthentication) |
|
91 |
|
larpe/tags/release-1.1.1/larpe/plugins/site_authentication/sympa.py | ||
---|---|---|
1 |
import re |
|
2 |
|
|
3 |
from quixote import get_response, redirect |
|
4 |
from quixote.html import htmltext |
|
5 |
|
|
6 |
from larpe.plugins import site_authentication_plugins |
|
7 |
from larpe.site_authentication import SiteAuthentication |
|
8 |
|
|
9 |
class SympaSiteAuthentication(SiteAuthentication): |
|
10 |
plugin_name = 'sympa' |
|
11 |
|
|
12 |
def auto_detect_site(cls, html_doc): |
|
13 |
if re.search("""<FORM ACTION="/wwsympa.fcgi" METHOD=POST>""", html_doc): |
|
14 |
return True |
|
15 |
return False |
|
16 |
auto_detect_site = classmethod(auto_detect_site) |
|
17 |
|
|
18 |
def check_auth(self, status, data): |
|
19 |
success = False |
|
20 |
return_content = '' |
|
21 |
|
|
22 |
if self.host.auth_system == 'password': |
|
23 |
# If there is a password field, authentication probably failed |
|
24 |
regexp = re.compile( |
|
25 |
"""<input[^>]*?type=["']?password["']?[^>]*?>""", re.DOTALL | re.IGNORECASE) |
|
26 |
if not regexp.findall(data): |
|
27 |
success = True |
|
28 |
# The specific part is only these 2 lines |
|
29 |
get_response().filter.update({'no_template': True}) |
|
30 |
return_content = htmltext(data) |
|
31 |
elif self.host.auth_system == 'status': |
|
32 |
match_status = int(self.host.auth_match_status) |
|
33 |
if match_status == status: |
|
34 |
success = True |
|
35 |
return_content = redirect(self.host.return_url) |
|
36 |
elif self.host.auth_system == 'match_text': |
|
37 |
# If the auth_match_text is not matched, it means the authentication is successful |
|
38 |
regexp = re.compile(self.host.auth_match_text, re.DOTALL) |
|
39 |
if not regexp.findall(data): |
|
40 |
success = True |
|
41 |
return_content = redirect(self.host.get_return_url()) |
|
42 |
|
|
43 |
return success, return_content |
|
44 |
|
|
45 |
site_authentication_plugins.register(SympaSiteAuthentication) |
larpe/tags/release-1.1.1/larpe/plugins/site_authentication_plugins.py | ||
---|---|---|
1 |
|
|
2 |
class SiteAuthenticationPlugins: |
|
3 |
""" This class manages the plugins for site authentification """ |
|
4 |
|
|
5 |
def __init__(self): |
|
6 |
self.site_authentication_classes = dict() |
|
7 |
|
|
8 |
def register(self, klass): |
|
9 |
""" Register a custom SiteAuthentification instance """ |
|
10 |
self.site_authentication_classes[klass.plugin_name] = klass |
|
11 |
|
|
12 |
def get(self, plugin_name): |
|
13 |
""" Return a custom SiteAuthentification instance """ |
|
14 |
if self.site_authentication_classes.has_key(plugin_name): |
|
15 |
return self.site_authentication_classes[plugin_name] |
|
16 |
else: |
|
17 |
return None |
|
18 |
|
|
19 |
def get_plugins_name(self): |
|
20 |
plugins_name = list() |
|
21 |
for plugin_name in self.site_authentication_classes.iterkeys(): |
|
22 |
plugins_name.append(plugin_name) |
|
23 |
return plugins_name |
|
24 |
|
|
25 |
def auto_detect(self, html_doc): |
|
26 |
""" |
|
27 |
Try to find automatically the right plugin name |
|
28 |
Return the plugin name or None |
|
29 |
""" |
|
30 |
for name, klass in self.site_authentication_classes.iteritems(): |
|
31 |
if klass.auto_detect_site(html_doc): |
|
32 |
return klass.plugin_name |
|
33 |
return None |
|
34 |
|
larpe/tags/release-1.1.1/larpe/publisher.py | ||
---|---|---|
1 |
import os |
|
2 |
import cPickle |
|
3 |
|
|
4 |
from quixote import get_request |
|
5 |
|
|
6 |
from Defaults import * |
|
7 |
|
|
8 |
from qommon.publisher import set_publisher_class, QommonPublisher |
|
9 |
|
|
10 |
from root import RootDirectory |
|
11 |
from admin import RootDirectory as AdminRootDirectory |
|
12 |
|
|
13 |
from sessions import StorageSessionManager |
|
14 |
from users import User |
|
15 |
|
|
16 |
class LarpePublisher(QommonPublisher): |
|
17 |
APP_NAME = 'larpe' |
|
18 |
APP_DIR = APP_DIR |
|
19 |
DATA_DIR = DATA_DIR |
|
20 |
ERROR_LOG = ERROR_LOG |
|
21 |
WEB_ROOT = WEB_ROOT |
|
22 |
|
|
23 |
supported_languages = ['fr'] |
|
24 |
|
|
25 |
root_directory_class = RootDirectory |
|
26 |
admin_directory_class = AdminRootDirectory |
|
27 |
|
|
28 |
session_manager_class = StorageSessionManager |
|
29 |
user_class = User |
|
30 |
|
|
31 |
def get_application_static_files_root_url(self): |
|
32 |
return '%s/%s/' % (get_request().environ['SCRIPT_NAME'], WEB_ROOT) |
|
33 |
|
|
34 |
def set_app_dir(self, request): |
|
35 |
self.app_dir = os.path.join(self.APP_DIR, request.get_server().lower().split(':')[0]) |
|
36 |
self.reload_cfg() |
|
37 |
if self.cfg.has_key('proxy_hostname'): |
|
38 |
self.app_dir = os.path.join(self.APP_DIR, self.cfg['proxy_hostname']) |
|
39 |
if self.app_dir is not None and not os.path.exists(self.app_dir): |
|
40 |
os.mkdir(self.app_dir) |
|
41 |
return True |
|
42 |
|
|
43 |
cfg = None |
|
44 |
def write_cfg(self, directory=None): |
|
45 |
dump = cPickle.dumps(self.cfg) |
|
46 |
if directory is None: |
|
47 |
directory = self.app_dir |
|
48 |
filename = os.path.join(directory, 'config.pck') |
|
49 |
open(filename, 'w').write(dump) |
|
50 |
|
|
51 |
set_publisher_class(LarpePublisher) |
|
52 |
extra_dir = os.path.join(os.path.dirname(__file__), 'plugins','site_authentication') |
|
53 |
LarpePublisher.register_extra_dir(extra_dir) |
larpe/tags/release-1.1.1/larpe/root.ptl | ||
---|---|---|
1 |
import os |
|
2 |
import httplib |
|
3 |
|
|
4 |
import lasso |
|
5 |
|
|
6 |
from quixote import get_request, get_response, get_session, redirect |
|
7 |
from quixote.directory import Directory |
|
8 |
|
|
9 |
from qommon.form import * |
|
10 |
from qommon import template |
|
11 |
|
|
12 |
import admin |
|
13 |
import liberty_root |
|
14 |
import errors |
|
15 |
|
|
16 |
from hosts import Host |
|
17 |
from users import User |
|
18 |
from Defaults import WEB_ROOT |
|
19 |
|
|
20 |
class RootDirectory(Directory): |
|
21 |
_q_exports = ['', 'admin', 'liberty', 'logout', 'token'] |
|
22 |
|
|
23 |
admin = admin.RootDirectory() |
|
24 |
liberty = liberty_root.LibertyRootDirectory() |
|
25 |
|
|
26 |
def _q_index [html] (self): |
|
27 |
template.html_top(_('Welcome to Larpe reverse proxy')) |
|
28 |
'<ul><li><a href="%s/admin/">%s</a></li></ul>' % (get_request().environ['SCRIPT_NAME'], |
|
29 |
_('Configure Larpe')) |
|
30 |
|
|
31 |
def _q_traverse(self, path): |
|
32 |
response = get_response() |
|
33 |
response.filter = {} |
|
34 |
|
|
35 |
return Directory._q_traverse(self, path) |
|
36 |
|
|
37 |
def _q_lookup(self, component): |
|
38 |
return redirect(component + '/') |
|
39 |
|
|
40 |
def logout(self): |
|
41 |
return redirect(get_publisher().get_root_url() + 'liberty/larpe/logout') |
|
42 |
|
|
43 |
def token [html] (self): |
|
44 |
session = get_session() |
|
45 |
|
|
46 |
if not session.name_identifier or not session.lasso_anonymous_identity_dump: |
|
47 |
raise errors.AccessUnauthorizedError() |
|
48 |
|
|
49 |
# If the token is in the query string, use it |
|
50 |
query_string = get_request().get_query() |
|
51 |
if query_string: |
|
52 |
parameters = query_string.split(str('&')) |
|
53 |
for param in parameters: |
|
54 |
values = param.split(str('=')) |
|
55 |
if len(values) < 2: |
|
56 |
continue |
|
57 |
if values[0] == str('token'): |
|
58 |
return self._federate_token(values[1]) |
|
59 |
|
|
60 |
# Otherwise, display a form to ask for the token |
|
61 |
form = Form(enctype='multipart/form-data') |
|
62 |
form.add(StringWidget, 'token', title = _('Identification Token'), |
|
63 |
required = True, size = 30) |
|
64 |
form.add_submit('submit', _('Submit')) |
|
65 |
form.add_submit('cancel', _('Cancel')) |
|
66 |
|
|
67 |
if form.get_widget('cancel').parse(): |
|
68 |
return redirect('.') |
|
69 |
|
|
70 |
if not form.is_submitted() or form.has_errors(): |
|
71 |
template.html_top(_('Identification Token')) |
|
72 |
'<p>' |
|
73 |
_('Please enter your identification token. ') |
|
74 |
_('Your local account will be federated with your Liberty Alliance account.') |
|
75 |
'</p>' |
|
76 |
form.render() |
|
77 |
else: |
|
78 |
token = form.get_widget('token').parse() |
|
79 |
return self._federate_token(token) |
|
80 |
|
|
81 |
def _federate_token(self, token): |
|
82 |
session = get_session() |
|
83 |
|
|
84 |
# Get the user who owns this token |
|
85 |
users_with_token = list(User.select(lambda x: x.identification_token == token)) |
|
86 |
if len(users_with_token) == 0: |
|
87 |
return template.error_page(_('Unknown Token')) |
|
88 |
|
|
89 |
# Fill user attributes |
|
90 |
user = users_with_token[0] |
|
91 |
user.name_identifiers = [ session.name_identifier ] |
|
92 |
user.lasso_dumps = [ session.lasso_anonymous_identity_dump ] |
|
93 |
user.identification_token = None |
|
94 |
user.is_admin = True |
|
95 |
user.store() |
|
96 |
|
|
97 |
# Set this user in the session |
|
98 |
session.set_user(user.id, session.provider_id) |
|
99 |
|
|
100 |
# Delete now useless session attributes |
|
101 |
session.name_identifier = None |
|
102 |
session.lasso_anonymous_identity_dump = None |
|
103 |
session.provider_id = None |
|
104 |
|
|
105 |
return redirect('%s/admin/' % get_request().environ['SCRIPT_NAME']) |
|
106 |
|
larpe/tags/release-1.1.1/larpe/saml2.ptl | ||
---|---|---|
1 |
import os |
|
2 |
import sys |
|
3 |
import urlparse |
|
4 |
|
|
5 |
try: |
|
6 |
import lasso |
|
7 |
except ImportError: |
|
8 |
print >> sys.stderr, 'Missing Lasso module, SAMLv2 support disabled' |
|
9 |
|
|
10 |
from quixote import get_publisher, get_request, get_response, get_session, get_session_manager, redirect |
|
11 |
|
|
12 |
from qommon.liberty import SOAPException, soap_call |
|
13 |
from qommon.saml2 import Saml2Directory |
|
14 |
from qommon import template |
|
15 |
from qommon import get_logger |
|
16 |
|
|
17 |
import misc |
|
18 |
from users import User |
|
19 |
from hosts import Host |
|
20 |
from federations import Federation |
|
21 |
import site_authentication |
|
22 |
|
|
23 |
class Saml2(Saml2Directory): |
|
24 |
_q_exports = Saml2Directory._q_exports + ['local_auth'] |
|
25 |
|
|
26 |
def login(self): |
|
27 |
return self.perform_login() |
|
28 |
|
|
29 |
def perform_login(self, idp = None): |
|
30 |
server = misc.get_lasso_server(protocol = 'saml2') |
|
31 |
if not server: |
|
32 |
return template.error_page(_('SAML 2.0 support not yet configured.')) |
|
33 |
login = lasso.Login(server) |
|
34 |
login.initAuthnRequest(idp, lasso.HTTP_METHOD_REDIRECT) |
|
35 |
login.request.nameIDPolicy.format = lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT |
|
36 |
login.request.nameIDPolicy.allowCreate = True |
|
37 |
login.request.forceAuthn = False |
|
38 |
login.request.isPassive = False |
|
39 |
login.request.consent = 'urn:oasis:names:tc:SAML:2.0:consent:current-implicit' |
|
40 |
login.buildAuthnRequestMsg() |
|
41 |
return redirect(login.msgUrl) |
|
42 |
|
|
43 |
def singleSignOnArtifact(self): |
|
44 |
server = misc.get_lasso_server(protocol = 'saml2') |
|
45 |
if not server: |
|
46 |
return template.error_page(_('SAML 2.0 support not yet configured.')) |
|
47 |
login = lasso.Login(server) |
|
48 |
request = get_request() |
|
49 |
try: |
|
50 |
login.initRequest(request.get_query(), lasso.HTTP_METHOD_ARTIFACT_GET) |
|
51 |
except lasso.Error, error: |
|
52 |
if error[0] == lasso.PROFILE_ERROR_MISSING_ARTIFACT: |
|
53 |
return template.error_page(_('Missing SAML Artifact')) |
|
54 |
else: |
|
55 |
raise |
|
56 |
|
|
57 |
login.buildRequestMsg() |
|
58 |
#remote_provider_cfg = get_cfg('idp', {}).get(misc.get_provider_key(login.remoteProviderId)) |
|
59 |
#client_cert = remote_provider_cfg.get('clientcertificate') |
|
60 |
|
|
61 |
try: |
|
62 |
soap_answer = soap_call(login.msgUrl, login.msgBody) |
|
63 |
except SOAPException: |
|
64 |
return template.error_page(_('Failure to communicate with identity provider')) |
|
65 |
|
|
66 |
try: |
|
67 |
login.processResponseMsg(soap_answer) |
|
68 |
except lasso.Error, error: |
|
69 |
if error[0] == lasso.LOGIN_ERROR_STATUS_NOT_SUCCESS: |
|
70 |
return template.error_page(_('Unknown authentication failure')) |
|
71 |
if error[0] == lasso.LOGIN_ERROR_UNKNOWN_PRINCIPAL: |
|
72 |
return template.error_page(_('Authentication failure; unknown principal')) |
|
73 |
if error[0] == lasso.LOGIN_ERROR_FEDERATION_NOT_FOUND: |
|
74 |
return template.error_page('there was no federation') |
|
75 |
raise |
|
76 |
|
|
77 |
return self.sso_after_response(login) |
|
78 |
|
|
79 |
def sso_after_response(self, login): |
|
80 |
providerId = login.server.providerId |
|
81 |
try: |
|
82 |
assertion = login.response.assertion[0] |
|
83 |
if assertion.subject.subjectConfirmation.subjectConfirmationData.recipient != \ |
|
84 |
get_request().get_url(): |
|
85 |
return template.error_page('SubjectConfirmation Recipient Mismatch') |
|
86 |
except: |
|
87 |
return template.error_page('SubjectConfirmation Recipient Mismatch') |
|
88 |
|
|
89 |
assertions_dir = os.path.join(get_publisher().app_dir, 'assertions') |
|
90 |
if not os.path.exists(assertions_dir): |
|
91 |
os.mkdir(assertions_dir) |
|
92 |
|
|
93 |
assertion_fn = os.path.join(assertions_dir, assertion.iD) |
|
94 |
if os.path.exists(assertion_fn): |
|
95 |
return template.error_page('Assertion replay') |
|
96 |
|
|
97 |
try: |
|
98 |
if assertion.subject.subjectConfirmation.method != \ |
|
99 |
'urn:oasis:names:tc:SAML:2.0:cm:bearer': |
|
100 |
return template.error_page('Unknown SubjectConfirmation Method') |
|
101 |
except: |
|
102 |
return template.error_page('Unknown SubjectConfirmation Method') |
|
103 |
|
|
104 |
try: |
|
105 |
audience_ok = False |
|
106 |
for audience_restriction in assertion.conditions.audienceRestriction: |
|
107 |
if audience_restriction.audience != providerId: |
|
108 |
return template.error_page('Incorrect AudienceRestriction') |
|
109 |
audience_ok = True |
|
110 |
if not audience_ok: |
|
111 |
return template.error_page('Incorrect AudienceRestriction') |
|
112 |
except: |
|
113 |
return template.error_page('Incorrect AudienceRestriction') |
|
114 |
|
|
115 |
# try: |
|
116 |
# current_time = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()) |
|
117 |
# not_before = assertion.subject.subjectConfirmation.subjectConfirmationData.notBefore |
|
118 |
# not_on_or_after = assertion.subject.subjectConfirmation.subjectConfirmationData.notOnOrAfter |
|
119 |
# if not_before and current_time < not_before: |
|
120 |
# return template.error_page('Assertion received too early') |
|
121 |
# if not_on_or_after and current_time > not_on_or_after: |
|
122 |
# return template.error_page('Assertion expired') |
|
123 |
# except: |
|
124 |
# return template.error_page('Error checking Assertion Time') |
|
125 |
|
|
126 |
# TODO: check for unknown conditions |
|
127 |
|
|
128 |
login.acceptSso() |
|
129 |
|
|
130 |
session = get_session() |
|
131 |
if login.isSessionDirty: |
|
132 |
if login.session: |
|
133 |
session.lasso_session_dumps[providerId] = login.session.dump() |
|
134 |
session.lasso_session_indexes[providerId] = assertion.authnStatement[0].sessionIndex |
|
135 |
session.lasso_session_name_identifiers[providerId] = login.nameIdentifier.content |
|
136 |
else: |
|
137 |
session.lasso_session_dumps[login.server.providerId] = None |
|
138 |
|
|
139 |
if assertion.authnStatement[0].sessionIndex: |
|
140 |
session.lasso_session_index = assertion.authnStatement[0].sessionIndex |
|
141 |
|
|
142 |
user = self.lookup_user(session, login) |
|
143 |
|
|
144 |
# Check if it is for Larpe administration or token |
|
145 |
host = Host.get_host_from_url() |
|
146 |
if host is None: |
|
147 |
return redirect('%s/' % get_request().environ['SCRIPT_NAME']) |
|
148 |
if host.name == 'larpe': |
|
149 |
if user: |
|
150 |
session.set_user(user.id, login.server.providerId) |
|
151 |
else: |
|
152 |
session.name_identifier = login.nameIdentifier.content |
|
153 |
session.lasso_anonymous_identity_dump = login.identity.dump() |
|
154 |
session.provider_id = login.server.providerId |
|
155 |
|
|
156 |
if session.after_url: |
|
157 |
# Access to an admin page or token url with parameter |
|
158 |
after_url = session.after_url |
|
159 |
session.after_url = None |
|
160 |
return redirect(after_url) |
|
161 |
|
|
162 |
if user and user.is_admin: |
|
163 |
return redirect('%s/admin/' % get_request().environ['SCRIPT_NAME']) |
|
164 |
else: |
|
165 |
return redirect('%s/token' % get_request().environ['SCRIPT_NAME']) |
|
166 |
|
|
167 |
# Set session user |
|
168 |
if not user: |
|
169 |
user = User() |
|
170 |
user.name_identifiers = [ login.nameIdentifier.content ] |
|
171 |
user.lasso_dumps = [ login.identity.dump() ] |
|
172 |
user.store() |
|
173 |
session.set_user(user.id, login.server.providerId) |
|
174 |
|
|
175 |
# Check if a federation already exist |
|
176 |
federations = Federation.select(lambda x: host.id == x.host_id \ |
|
177 |
and user.name_identifiers[0] in x.name_identifiers) |
|
178 |
|
|
179 |
if federations: |
|
180 |
return site_authentication.get_site_authentication(host).sso_local_login(federations[0]) |
|
181 |
else: |
|
182 |
# Build response redirection |
|
183 |
response = get_response() |
|
184 |
if session.after_url: |
|
185 |
after_url = session.after_url |
|
186 |
session.after_url = None |
|
187 |
return redirect(after_url) |
|
188 |
response.set_status(303) |
|
189 |
response.headers['location'] = urlparse.urljoin(get_request().get_url(), str('local_auth')) |
|
190 |
response.content_type = 'text/plain' |
|
191 |
return 'Your browser should redirect you' |
|
192 |
|
|
193 |
def lookup_user(self, session, login): |
|
194 |
found_users = list(User.select(lambda x: login.nameIdentifier.content in x.name_identifiers, ignore_errors = True)) |
|
195 |
if found_users: |
|
196 |
return found_users[0] |
|
197 |
return None |
|
198 |
|
|
199 |
def slo_sp(self, method = None): |
|
200 |
host = Host.get_host_from_url() |
|
201 |
if host is None: |
|
202 |
return redirect('%s/' % get_request().environ['SCRIPT_NAME']) |
|
203 |
|
|
204 |
if method is None: |
|
205 |
method = lasso.HTTP_METHOD_REDIRECT |
|
206 |
|
|
207 |
logout = lasso.Logout(misc.get_lasso_server(protocol = 'saml2')) |
|
208 |
session = get_session() |
|
209 |
|
|
210 |
if not session.id or not session.users.has_key(logout.server.providerId) \ |
|
211 |
or not session.lasso_session_dumps.has_key(logout.server.providerId): |
|
212 |
get_session_manager().expire_session(logout.server.providerId) |
|
213 |
return redirect(host.get_root_url()) |
|
214 |
logout.setSessionFromDump(session.lasso_session_dumps[logout.server.providerId]) |
|
215 |
user = session.get_user(logout.server.providerId) |
|
216 |
|
|
217 |
if host.name != 'larpe' and user: |
|
218 |
site_authentication.get_site_authentication(host).local_logout(user=user) |
|
219 |
|
|
220 |
if user and user.lasso_dumps: |
|
221 |
logout.setIdentityFromDump(user.lasso_dumps[0]) |
|
222 |
else: |
|
223 |
get_session_manager().expire_session(logout.server.providerId) |
|
224 |
return redirect(host.get_root_url()) |
|
225 |
|
|
226 |
if method == lasso.HTTP_METHOD_REDIRECT: |
|
227 |
return self.slo_sp_redirect(logout) |
|
228 |
|
|
229 |
# Not implemented yet |
|
230 |
if method == lasso.HTTP_METHOD_SOAP: |
|
231 |
return self.slo_sp_soap(logout) |
|
232 |
|
|
233 |
def slo_sp_redirect(self, logout): |
|
234 |
session = get_session() |
|
235 |
try: |
|
236 |
logout.initRequest(None, lasso.HTTP_METHOD_REDIRECT) |
|
237 |
except lasso.Error, error: |
|
238 |
if error[0] == lasso.PROFILE_ERROR_NAME_IDENTIFIER_NOT_FOUND: |
|
239 |
get_session_manager().expire_session(logout.server.providerId) |
|
240 |
return redirect(host.get_root_url()) |
|
241 |
if error[0] == lasso.PROFILE_ERROR_SESSION_NOT_FOUND: |
|
242 |
get_session_manager().expire_session(logout.server.providerId) |
|
243 |
return redirect(host.get_root_url()) |
|
244 |
raise |
|
245 |
|
|
246 |
logout.buildRequestMsg() |
|
247 |
return redirect(logout.msgUrl) |
|
248 |
|
|
249 |
def singleLogoutReturn(self): |
|
250 |
host = Host.get_host_from_url() |
|
251 |
if host is None: |
|
252 |
return redirect('%s/' % get_request().environ['SCRIPT_NAME']) |
|
253 |
|
|
254 |
logout = lasso.Logout(misc.get_lasso_server(protocol = 'saml2')) |
|
255 |
session = get_session() |
|
256 |
|
|
257 |
if not session.id or not session.users.has_key(logout.server.providerId) \ |
|
258 |
or not session.lasso_session_dumps.has_key(logout.server.providerId): |
|
259 |
get_session_manager().expire_session(logout.server.providerId) |
|
260 |
return redirect(host.get_root_url()) |
|
261 |
logout.setSessionFromDump(session.lasso_session_dumps[logout.server.providerId]) |
|
262 |
|
|
263 |
message = get_request().get_query() |
|
264 |
return self.slo_return(logout, message) |
|
265 |
|
|
266 |
def slo_return(self, logout, message): |
|
267 |
host = Host.get_host_from_url() |
|
268 |
|
|
269 |
session = get_session() |
|
270 |
|
|
271 |
try: |
|
272 |
logout.processResponseMsg(message) |
|
273 |
except lasso.Error, error: |
|
274 |
if error[0] == lasso.PROFILE_ERROR_INVALID_QUERY: |
|
275 |
get_logger().warn('Invalid response') |
|
276 |
elif error[0] == lasso.DS_ERROR_INVALID_SIGNATURE: |
|
277 |
get_logger().warn('Failed to check single logout request signature') |
|
278 |
elif error[0] == lasso.LOGOUT_ERROR_REQUEST_DENIED: |
|
279 |
get_logger().warn('Request Denied') |
|
280 |
elif error[0] == lasso.LOGOUT_ERROR_UNKNOWN_PRINCIPAL: |
|
281 |
get_logger().warn('Unknown principal on logout, probably session stopped already on IdP') |
|
282 |
else: |
|
283 |
get_logger().error('Unknown Lasso exception on logout return: ' + repr(error)) |
|
284 |
except Exception, exception: |
|
285 |
get_logger().error('Unknown exception on logout return: ' + repr(exception)) |
|
286 |
|
|
287 |
get_session_manager().expire_session(logout.server.providerId) |
|
288 |
|
|
289 |
return redirect(host.get_root_url()) |
|
290 |
|
|
291 |
def singleLogoutSOAP(self): |
|
292 |
try: |
|
293 |
soap_message = self.get_soap_message() |
|
294 |
except: |
|
295 |
return |
|
296 |
|
|
297 |
response = get_response() |
|
298 |
response.set_content_type('text/xml') |
|
299 |
|
|
300 |
request_type = lasso.getRequestTypeFromSoapMsg(soap_message) |
|
301 |
|
|
302 |
if request_type != lasso.REQUEST_TYPE_LOGOUT: |
|
303 |
get_logger().warn('SOAP message on single logout url not a slo message') |
|
304 |
return |
|
305 |
|
|
306 |
logout = lasso.Logout(misc.get_lasso_server(protocol = 'saml2')) |
|
307 |
providerId = logout.server.providerId |
|
308 |
logout.processRequestMsg(soap_message) |
|
309 |
name_identifier = logout.nameIdentifier.content |
|
310 |
# find one session matching the name identifier, and eventually the request |
|
311 |
for session in get_session_manager().values(): |
|
312 |
session_index = session.lasso_session_indexes.get(providerId) |
|
313 |
name_identifier = session.lasso_session_name_identifiers.get(providerId) |
|
314 |
request_name_identifier = logout.nameIdentifier.content |
|
315 |
request_session_index = logout.request.sessionIndex |
|
316 |
if request_name_identifier == name_identifier and \ |
|
317 |
(not session_index or request_session_index == session_index) \ |
|
318 |
and session.lasso_session_dumps.get(providerId): |
|
319 |
get_logger().info('SLO/SOAP from %s' % logout.remoteProviderId) |
|
320 |
break |
|
321 |
else: |
|
322 |
# no session, build straight failure answer |
|
323 |
logout.buildResponseMsg() |
|
324 |
return logout.msgBody |
|
325 |
|
|
326 |
return self.slo_idp(logout, session) |
|
327 |
|
|
328 |
def singleLogout(self): |
|
329 |
logout = lasso.Logout(misc.get_lasso_server(protocol = 'saml2')) |
|
330 |
try: |
|
331 |
logout.processRequestMsg(get_request().get_query()) |
|
332 |
except lasso.Error, error: |
|
333 |
if error[0] == lasso.DS_ERROR_INVALID_SIGNATURE: |
|
334 |
return template.error_page(_('Failed to check single logout request signature.')) |
|
335 |
raise |
|
336 |
session = get_session() |
|
337 |
if not session.id: |
|
338 |
# session has not been found, this may be because the user has |
|
339 |
# its browser configured so that cookies are not sent for |
|
340 |
# remote queries and IdP is using image-based SLO. |
|
341 |
# so we look up a session with the appropriate name identifier |
|
342 |
# find a matching |
|
343 |
for session in get_session_manager().values(): |
|
344 |
session_index = session.lasso_session_indexes.get(providerId) |
|
345 |
name_identifier = session.lasso_session_name_identifiers.get(providerId) |
|
346 |
request_name_identifier = logout.nameIdentifier.content |
|
347 |
request_session_index = logout.request.sessionIndex |
|
348 |
if request_name_identifier == name_identifier and \ |
|
349 |
(not session_index or request_session_index == session_index) \ |
|
350 |
and session.lasso_session_dump.get(providerId): |
|
351 |
get_logger().info('SLO/SOAP from %s' % logout.remoteProviderId) |
|
352 |
break |
|
353 |
else: |
|
354 |
# no session, build straight failure answer |
|
355 |
logout.buildResponseMsg() |
|
356 |
return logout.msgBody |
|
357 |
|
|
358 |
return self.slo_idp(logout, session) |
|
359 |
|
|
360 |
def slo_idp(self, logout, session): |
|
361 |
# This block differs from qommon |
|
362 |
if session.lasso_session_dumps.has_key(logout.server.providerId): |
|
363 |
logout.setSessionFromDump(session.lasso_session_dumps[logout.server.providerId]) |
|
364 |
user = session.get_user(logout.server.providerId) |
|
365 |
if user and user.lasso_dumps: |
|
366 |
logout.setIdentityFromDump(user.lasso_dumps[0]) |
|
367 |
|
|
368 |
if user and logout.nameIdentifier.content not in user.name_identifiers: |
|
369 |
raise 'no appropriate name identifier in session (%s and %s)' % ( |
|
370 |
logout.nameIdentifier.content, session.name_identifier) |
|
371 |
|
|
372 |
try: |
|
373 |
assertion = logout.session.getAssertions(logout.remoteProviderId)[0] |
|
374 |
if logout.request.sessionIndex and ( |
|
375 |
assertion.authnStatement[0].sessionIndex != logout.request.sessionIndex): |
|
376 |
logout.setSessionFromDump('<Session />') |
|
377 |
except: |
|
378 |
pass |
|
379 |
|
|
380 |
try: |
|
381 |
logout.validateRequest() |
|
382 |
except lasso.Error, error: |
|
383 |
if error[0] == lasso.PROFILE_ERROR_SESSION_NOT_FOUND: |
|
384 |
pass |
|
385 |
elif error[0] == lasso.PROFILE_ERROR_IDENTITY_NOT_FOUND: |
|
386 |
pass |
|
387 |
elif error[0] == lasso.PROFILE_ERROR_MISSING_ASSERTION: |
|
388 |
pass |
|
389 |
elif error[0] == lasso.SERVER_ERROR_PROVIDER_NOT_FOUND: |
|
390 |
pass |
|
391 |
elif error[0] == lasso.NAME_IDENTIFIER_NOT_FOUND: |
|
392 |
pass |
|
393 |
else: |
|
394 |
raise |
|
395 |
else: |
|
396 |
providerId = logout.server.providerId |
|
397 |
session_index = logout.request.sessionIndex |
|
398 |
name_identifier = logout.nameIdentifier.content |
|
399 |
# Remove reference to local authentication on this SP in the session |
|
400 |
# if a user is present, try a local logout |
|
401 |
for session2 in get_session_manager().values(): |
|
402 |
if session2.lasso_session_name_identifiers.get(providerId) == name_identifier \ |
|
403 |
and ( not session_index |
|
404 |
or session2.lasso_session_indexes.get(providerId) == session_index): |
|
405 |
if session2.users.has_key(providerId): |
|
406 |
# local logout |
|
407 |
site_auth = site_authentication.get_site_authentication(Host.get_host_from_url()) |
|
408 |
site_auth.local_logout(user=session2.get_user(providerId), |
|
409 |
cookies=getattr(session2,'cookies', None)) |
|
410 |
del session2.users[providerId] |
|
411 |
if session2.lasso_session_dumps.has_key(providerId): |
|
412 |
del session2.lasso_session_dumps[providerId] |
|
413 |
if session2.lasso_session_indexes.has_key(providerId): |
|
414 |
del session2.lasso_session_indexes[providerId] |
|
415 |
if session2.lasso_session_name_identifiers.has_key(providerId): |
|
416 |
del session2.lasso_session_name_identifiers[providerId] |
|
417 |
session2.store() |
|
418 |
get_session_manager().expire_session(logout.server.providerId) |
|
419 |
|
|
420 |
logout.buildResponseMsg() |
|
421 |
if logout.msgBody: # soap answer |
|
422 |
return logout.msgBody |
|
423 |
else: |
|
424 |
return redirect(logout.msgUrl) |
|
425 |
|
|
426 |
def local_auth(self): |
|
427 |
host = Host.get_host_from_url() |
|
428 |
if host is None: |
|
429 |
return redirect('%s/' % get_request().environ['SCRIPT_NAME']) |
|
430 |
return site_authentication.get_site_authentication(host).local_auth |
|
431 |
local_auth = property(local_auth) |
|
432 |
|
|
433 |
def metadata(self): |
|
434 |
host = Host.get_host_from_url() |
|
435 |
if host is None: |
|
436 |
return redirect('%s/' % get_request().environ['SCRIPT_NAME']) |
|
437 |
get_response().set_content_type('text/xml', 'utf-8') |
|
438 |
metadata = unicode(open(host.saml2_metadata).read(), 'utf-8') |
|
439 |
return metadata |
|
440 |
|
|
441 |
def public_key(self): |
|
442 |
host = Host.get_host_from_url() |
|
443 |
if host is None: |
|
444 |
return redirect('%s/' % get_request().environ['SCRIPT_NAME']) |
|
445 |
get_response().set_content_type('text/plain') |
|
446 |
public_key = open(host.public_key).read() |
|
447 |
return public_key |
|
448 |
|
larpe/tags/release-1.1.1/larpe/sessions.py | ||
---|---|---|
1 |
'''Session and SessionManager objects. Configuration variables and utilities''' |
|
2 |
|
|
3 |
from quixote import get_request |
|
4 |
|
|
5 |
import qommon.sessions |
|
6 |
from qommon.sessions import Session |
|
7 |
from qommon.sessions import StorageSessionManager as SessionManager |
|
8 |
|
|
9 |
from users import User |
|
10 |
from hosts import Host |
|
11 |
|
|
12 |
class BasicSession(Session): |
|
13 |
'''Session object. Configuration variables and utilities''' |
|
14 |
_names = 'sessions' |
|
15 |
|
|
16 |
def __init__(self, id): |
|
17 |
self.users = {} |
|
18 |
self.lasso_session_dumps = {} |
|
19 |
self.lasso_session_indexes = {} |
|
20 |
self.lasso_session_name_identifiers = {} |
|
21 |
self.provider_id = None |
|
22 |
Session.__init__(self, id) |
|
23 |
|
|
24 |
# lasso_session_indexes newly introduced |
|
25 |
def __setstate__(self, dict): |
|
26 |
self.lasso_session_indexes = {} |
|
27 |
self.lasso_session_name_identifiers = {} |
|
28 |
self.__dict__.update(dict) |
|
29 |
|
|
30 |
def has_info(self): |
|
31 |
return self.users or self.lasso_session_dumps or self.provider_id or Session.has_info(self) |
|
32 |
is_dirty = has_info |
|
33 |
|
|
34 |
def get_user(self, provider_id=None): |
|
35 |
# Defaults to getting Larpe user. |
|
36 |
# It allows get_request().user to work in administration interface. |
|
37 |
if not provider_id: |
|
38 |
user_id = None |
|
39 |
host = Host.get_host_from_url() |
|
40 |
if not host: |
|
41 |
host_list = Host.select(lambda x: x.name == 'larpe') |
|
42 |
if host_list: |
|
43 |
host = host_list[0] |
|
44 |
if host: |
|
45 |
user_id = self.users.get(host.provider_id) |
|
46 |
if not user_id: |
|
47 |
user_id = self.users.get(host.saml2_provider_id) |
|
48 |
else: |
|
49 |
user_id = self.users.get(provider_id) |
|
50 |
|
|
51 |
if user_id: |
|
52 |
try: |
|
53 |
user = User.get(user_id) |
|
54 |
except KeyError: |
|
55 |
user = User() |
|
56 |
# if str(user_id).startswith('anonymous-'): |
|
57 |
user.id = user_id |
|
58 |
# user.anonymous = True |
|
59 |
# if self.name_identifiers.has_key(providerId): |
|
60 |
# if not user.name_identifiers.has_key(providerId): |
|
61 |
# user.name_identifiers[providerId] = [ self.name_identifiers[providerId] ] |
|
62 |
|
|
63 |
# if self.name_identifiers.has_key(providerId): |
|
64 |
# user.name_identifiers[providerId] = [ self.name_identifiers[providerId] ] |
|
65 |
# else: |
|
66 |
# user.name_identifiers[providerId] = [] |
|
67 |
# user.lasso_dumps[providerId] = self.lasso_anonymous_identity_dump |
|
68 |
return user |
|
69 |
return None |
|
70 |
|
|
71 |
def set_user(self, user_id, provider_id): |
|
72 |
self.users[provider_id] = user_id |
|
73 |
|
|
74 |
class StorageSessionManager(SessionManager): |
|
75 |
'''SessionManager object. Subclass with multi-hosts specific features.''' |
|
76 |
def expire_session(self, provider_id=None): |
|
77 |
session = get_request().session |
|
78 |
if session.id is not None: |
|
79 |
if provider_id: |
|
80 |
if session.users.has_key(provider_id): |
|
81 |
del session.users[provider_id] |
|
82 |
if session.lasso_session_dumps.has_key(provider_id): |
|
83 |
del session.lasso_session_dumps[provider_id] |
|
84 |
if session.lasso_session_indexes.has_key(provider_id): |
|
85 |
del session.lasso_session_indexes[provider_id] |
|
86 |
if session.lasso_session_name_identifiers.has_key(provider_id): |
|
87 |
del session.lasso_session_name_identifiers[provider_id] |
|
88 |
session.store() |
|
89 |
if not session.users: |
|
90 |
SessionManager.expire_session(self) |
|
91 |
|
|
92 |
qommon.sessions.BasicSession = BasicSession |
larpe/tags/release-1.1.1/larpe/site_authentication.ptl | ||
---|---|---|
1 |
import libxml2 |
|
2 |
import urllib |
|
3 |
import urlparse |
|
4 |
import httplib |
|
5 |
import re |
|
6 |
import os |
|
7 |
import socket |
|
8 |
import base64 |
|
9 |
|
|
10 |
from quixote import get_request, get_response, get_session, redirect, get_publisher |
|
11 |
from quixote.directory import Directory |
|
12 |
from quixote.http_request import parse_header |
|
13 |
|
|
14 |
import lasso |
|
15 |
|
|
16 |
from qommon import get_logger |
|
17 |
from qommon.form import * |
|
18 |
from qommon.errors import ConnectionError, ConfigurationError, LoginError |
|
19 |
from qommon.misc import http_post_request, http_get_page |
|
20 |
from qommon.template import * |
|
21 |
|
|
22 |
from larpe.plugins import site_authentication_plugins |
|
23 |
|
|
24 |
import misc |
|
25 |
from users import User |
|
26 |
from federations import Federation |
|
27 |
|
|
28 |
class SiteAuthentication: |
|
29 |
|
|
30 |
output_filters = [] |
|
31 |
|
|
32 |
def __init__(self, host): |
|
33 |
self.host = host |
|
34 |
|
|
35 |
def federate(self, username, password, provider_id, cookies, select): |
|
36 |
user = get_session().get_user(provider_id) |
|
37 |
if user is not None: |
|
38 |
Federation(username, password, self.host.id, user.name_identifiers[0], cookies, select).store() |
|
39 |
|
|
40 |
def sso_local_login(self, federation): |
|
41 |
status, data = self.local_auth_check_dispatch( |
|
42 |
federation.username, federation.password, federation.select_fields) |
|
43 |
success, return_content = self.check_auth(status, data) |
|
44 |
if success: |
|
45 |
session = get_session() |
|
46 |
if hasattr(session, 'cookies'): |
|
47 |
federation.set_cookies(session.cookies) |
|
48 |
federation.store() |
|
49 |
return return_content |
|
50 |
else: |
|
51 |
return redirect('local_auth') |
|
52 |
|
|
53 |
def local_auth [html] (self, first_time=True): |
|
54 |
response = get_response() |
|
55 |
response.set_content_type('text/html') |
|
56 |
|
|
57 |
if hasattr(get_response(), str('breadcrumb')): |
|
58 |
del get_response().breadcrumb |
|
59 |
|
|
60 |
get_response().filter['default_org'] = '%s - %s' % (self.host.label, _('Local authentication')) |
|
61 |
get_response().filter['body_class'] = 'login' |
|
62 |
|
|
63 |
form = self.form_local_auth() |
|
64 |
form.add_submit('submit', _('Submit')) |
|
65 |
#form.add_submit('cancel', _('Cancel')) |
|
66 |
|
|
67 |
# if form.get_widget('cancel').parse(): |
|
68 |
# return redirect('.') |
|
69 |
authentication_failure = None |
|
70 |
if form.is_submitted() and not form.has_errors(): |
|
71 |
try: |
|
72 |
return self.submit_local_auth_form(form) |
|
73 |
except LoginError: |
|
74 |
authentication_failure = _('Authentication failure') |
|
75 |
get_logger().info('local auth page : %s' % authentication_failure) |
|
76 |
except ConnectionError, err: |
|
77 |
authentication_failure = _('Connection failed : %s') % err |
|
78 |
get_logger().info('local auth page : %s' % authentication_failure) |
|
79 |
except ConfigurationError, err: |
|
80 |
authentication_failure = _('This service provider is not fully configured : %s') % err |
|
81 |
get_logger().info('local auth page : %s' % authentication_failure) |
|
82 |
except Exception, err: |
|
83 |
authentication_failure = _('Unknown error : %s' % err) |
|
84 |
get_logger().info('local auth page : %s' % authentication_failure) |
|
85 |
|
|
86 |
if authentication_failure: |
|
87 |
'<div class="errornotice">%s</div>' % authentication_failure |
|
88 |
'<p>' |
|
89 |
_('Please type your login and password for this Service Provider.') |
|
90 |
_('Your local account will be federated with your Liberty Alliance account.') |
|
91 |
'</p>' |
|
92 |
|
|
93 |
form.render() |
|
94 |
|
|
95 |
# Also used in admin/hosts.ptl |
|
96 |
def form_local_auth(self): |
|
97 |
form = Form(enctype='multipart/form-data') |
|
98 |
form.add(StringWidget, 'username', title = _('Username'), required = True, |
|
99 |
size = 30) |
|
100 |
form.add(PasswordWidget, 'password', title = _('Password'), required = True, |
|
101 |
size = 30) |
|
102 |
for name, values in self.host.select_fields.iteritems(): |
|
103 |
options = [] |
|
104 |
if values: |
|
105 |
for value in values: |
|
106 |
options.append(value) |
|
107 |
form.add(SingleSelectWidget, name, title = name.capitalize(), |
|
108 |
value = values[0], options = options) |
|
109 |
return form |
|
110 |
|
|
111 |
def submit_local_auth_form(self, form): |
|
112 |
username = form.get_widget('username').parse() |
|
113 |
password = form.get_widget('password').parse() |
|
114 |
select = {} |
|
115 |
for name, values in self.host.select_fields.iteritems(): |
|
116 |
if form.get_widget(name): |
|
117 |
select[name] = form.get_widget(name).parse() |
|
118 |
return self.local_auth_check(username, password, select) |
|
119 |
|
|
120 |
def local_auth_check(self, username, password, select=None): |
|
121 |
select = select or {} |
|
122 |
status, data = self.local_auth_check_dispatch(username, password, select) |
|
123 |
if status == 0: |
|
124 |
raise |
|
125 |
success, return_content = self.check_auth(status, data) |
|
126 |
if success: |
|
127 |
if misc.get_current_protocol() == lasso.PROTOCOL_SAML_2_0: |
|
128 |
provider_id = self.host.saml2_provider_id |
|
129 |
else: |
|
130 |
provider_id = self.host.provider_id |
|
131 |
session = get_session() |
|
132 |
|
|
133 |
if hasattr(session, 'cookies'): |
|
134 |
self.federate(username, password, provider_id, session.cookies, select) |
|
135 |
else: |
|
136 |
self.federate(username, password, provider_id, None, select) |
|
137 |
return return_content |
|
138 |
raise LoginError() |
|
139 |
|
|
140 |
def local_auth_check_dispatch(self, username, password, select=None): |
|
141 |
select = select or {} |
|
142 |
if self.host.auth_mode == 'http_basic': |
|
143 |
return self.local_auth_check_http_basic(username, password) |
|
144 |
elif self.host.auth_mode == 'form' and hasattr(self.host, 'auth_check_url') \ |
|
145 |
and self.host.auth_check_url is not None: |
|
146 |
return self.local_auth_check_post(username, password, select) |
|
147 |
else: |
|
148 |
raise ConfigurationError('No authentication form was found') |
|
149 |
|
|
150 |
def local_auth_check_post(self, username, password, select=None): |
|
151 |
select = select or {} |
|
152 |
url = self.host.auth_check_url |
|
153 |
|
|
154 |
# Build request body |
|
155 |
if self.host.post_parameters: |
|
156 |
body_params = {} |
|
157 |
# Login field |
|
158 |
if self.host.post_parameters[self.host.login_field_name]['enabled'] is True: |
|
159 |
body_params[self.host.login_field_name] = username |
|
160 |
# Password field |
|
161 |
if self.host.post_parameters[self.host.password_field_name]['enabled'] is True: |
|
162 |
body_params[self.host.password_field_name] = password |
|
163 |
# Select fields |
|
164 |
for name, value in select.iteritems(): |
|
165 |
if self.host.post_parameters[name]['enabled'] is True: |
|
166 |
body_params[name] = value |
|
167 |
# Other fields (hidden, submit and custom) |
|
168 |
for name, value in self.host.other_fields.iteritems(): |
|
169 |
if self.host.post_parameters[name]['enabled'] is True: |
|
170 |
body_params[name] = self.host.post_parameters[name]['value'] |
|
171 |
body = urllib.urlencode(body_params) |
|
172 |
else: |
|
173 |
# XXX: Legacy (to be removed later) Send all parameters for sites configured with a previous version of Larpe |
|
174 |
body = '%s=%s&%s=%s' % (self.host.login_field_name, username, self.host.password_field_name, password) |
|
175 |
# Add select fields to the body |
|
176 |
for name, value in select.iteritems(): |
|
177 |
body += '&%s=%s' % (name, value) |
|
178 |
# Add hidden fields to the body |
|
179 |
if self.host.send_hidden_fields: |
|
180 |
for name, value in self.host.other_fields.iteritems(): |
|
181 |
body += '&%s=%s' % (name, value) |
|
182 |
|
|
183 |
# Build request HTTP headers |
|
184 |
if self.host.http_headers: |
|
185 |
headers = {} |
|
186 |
if self.host.http_headers['X-Forwarded-For']['enabled'] is True: |
|
187 |
headers['X-Forwarded-For'] = get_request().get_environ('REMOTE_ADDR', '-') |
|
188 |
for name, value in self.host.http_headers.iteritems(): |
|
189 |
if value['enabled'] is True and value['immutable'] is False: |
|
190 |
headers[name] = value['value'] |
|
191 |
else: |
|
192 |
# XXX: (to be removed later) Send default headers for sites configured with a previous version of Larpe |
|
193 |
headers = { 'Content-Type': 'application/x-www-form-urlencoded', |
|
194 |
'X-Forwarded-For': get_request().get_environ('REMOTE_ADDR', '-'), |
|
195 |
'X-Forwarded-Host': self.host.reversed_hostname } |
|
196 |
|
|
197 |
# Send request |
|
198 |
response, status, data, auth_headers = http_post_request(url, body, headers, self.host.use_proxy) |
|
199 |
|
|
200 |
cookies = response.getheader('Set-Cookie', None) |
|
201 |
self.host.cookies = [] |
|
202 |
if cookies is not None: |
|
203 |
cookies_list = [] |
|
204 |
cookies_set_list = [] |
|
205 |
for cookie in cookies.split(', '): |
|
206 |
# Drop the path and other attributes |
|
207 |
cookie_only = cookie.split('; ')[0] |
|
208 |
regexp = re.compile('=') |
|
209 |
if regexp.search(cookie_only) is None: |
|
210 |
continue |
|
211 |
# Split name and value |
|
212 |
cookie_split = cookie_only.split('=') |
|
213 |
cookie_name = cookie_split[0] |
|
214 |
cookie_value = cookie_split[1] |
|
215 |
cookies_list.append('%s=%s' % (cookie_name, cookie_value)) |
|
216 |
set_cookie = '%s=%s; path=/' % (cookie_name, cookie_value) |
|
217 |
cookies_set_list.append(set_cookie) |
|
218 |
self.host.cookies.append(cookie_name) |
|
219 |
cookies_headers = '\r\nSet-Cookie: '.join(cookies_set_list) |
|
220 |
get_response().set_header('Set-Cookie', cookies_headers) |
|
221 |
self.host.store() |
|
222 |
get_session().cookies = '; '.join(cookies_list) |
|
223 |
else: |
|
224 |
get_logger().warn('No cookie from local authentication') |
|
225 |
|
|
226 |
return response.status, data |
|
227 |
|
|
228 |
def local_auth_check_http_basic(self, username, password): |
|
229 |
url = self.host.auth_form_url |
|
230 |
hostname, query = urllib.splithost(url[5:]) |
|
231 |
conn = httplib.HTTPConnection(hostname) |
|
232 |
|
|
233 |
auth_header = 'Basic %s' % base64.encodestring('%s:%s' % (username, password)) |
|
234 |
|
|
235 |
try: |
|
236 |
conn.request('GET', query, headers={'Authorization': auth_header}) |
|
237 |
except socket.gaierror, err: |
|
238 |
print err |
|
239 |
conn.close() |
|
240 |
return 0, None |
|
241 |
else: |
|
242 |
response = conn.getresponse() |
|
243 |
conn.close() |
|
244 |
return response.status, response.read() |
|
245 |
|
|
246 |
def check_auth(self, status, data): |
|
247 |
success = False |
|
248 |
return_content = '' |
|
249 |
|
|
250 |
# If status is 500, fail without checking other criterias |
|
251 |
if status // 100 == 5: |
|
252 |
success = False |
|
253 |
return_content = redirect(self.host.get_return_url()) |
|
254 |
|
|
255 |
|
|
256 |
# For http auth, only check status code |
|
257 |
elif self.host.auth_mode == 'http_basic': |
|
258 |
# If failed, status code should be 401 |
|
259 |
if status // 100 == 2 or status // 100 == 3: |
|
260 |
success = True |
|
261 |
return_content = redirect(self.host.get_return_url()) |
|
262 |
|
|
263 |
else: |
|
264 |
if self.host.auth_system == 'password': |
|
265 |
# If there is a password field, authentication probably failed |
|
266 |
regexp = re.compile("""<input[^>]*?type=["']?password["']?[^>]*?>""", re.DOTALL | re.IGNORECASE) |
|
267 |
if not regexp.findall(data): |
|
268 |
success = True |
|
269 |
return_content = redirect(self.host.get_return_url()) |
|
270 |
elif self.host.auth_system == 'status': |
|
271 |
match_status = int(self.host.auth_match_status) |
|
272 |
if match_status == status: |
|
273 |
success = True |
|
274 |
return_content = redirect(self.host.get_return_url()) |
|
275 |
elif self.host.auth_system == 'match_text': |
|
276 |
# If the auth_match_text is not matched, it means the authentication is successful |
|
277 |
regexp = re.compile(self.host.auth_match_text, re.DOTALL) |
|
278 |
if not regexp.findall(data): |
|
279 |
success = True |
|
280 |
return_content = redirect(self.host.get_return_url()) |
|
281 |
|
|
282 |
return success, return_content |
|
283 |
|
|
284 |
def local_logout(self, federation=None, user=None, cookies=None): |
|
285 |
if cookies is None and federation is None and user is not None: |
|
286 |
federations = Federation.select(lambda x: user.name_identifiers[0] in x.name_identifiers) |
|
287 |
if federations: |
|
288 |
cookies = federations[0].cookies |
|
289 |
|
|
290 |
# Logout request to the site |
|
291 |
url = self.host.logout_url |
|
292 |
if url is not None and cookies is not None: |
|
293 |
try: |
|
294 |
http_get_page(url, {'Cookie': cookies}) |
|
295 |
except ConnectionError, err: |
|
296 |
get_logger().warning(_("%s logout failed") % url) |
|
297 |
get_logger().debug(err) |
|
298 |
|
|
299 |
# Remove cookies from the browser |
|
300 |
# TODO: this should be removed because this only works |
|
301 |
# with a 'direct' logout |
|
302 |
if hasattr(self.host, 'cookies'): |
|
303 |
for cookie in self.host.cookies: |
|
304 |
get_response().expire_cookie(cookie, path='/') |
|
305 |
|
|
306 |
def local_defederate(self, session, provider_id): |
|
307 |
if session is None: |
|
308 |
return |
|
309 |
user = session.get_user(provider_id) |
|
310 |
if user is not None: |
|
311 |
federations = Federation.select(lambda x: user.name_identifiers[0] in x.name_identifiers) |
|
312 |
for federation in federations: |
|
313 |
self.local_logout(provider_id, federation) |
|
314 |
federation.remove_name_identifier(user.name_identifiers[0]) |
|
315 |
federation.store() |
|
316 |
|
|
317 |
def get_site_authentication(host): |
|
318 |
if host.site_authentication_plugin is None: |
|
319 |
return SiteAuthentication(host) |
|
320 |
return site_authentication_plugins.get(host.site_authentication_plugin)(host) |
|
321 |
|
larpe/tags/release-1.1.1/larpe/users.py | ||
---|---|---|
1 |
'''User object. Configuration variables and utilities''' |
|
2 |
|
|
3 |
from qommon.storage import StorableObject |
|
4 |
|
|
5 |
class User(StorableObject): |
|
6 |
'''User object. Configuration variables and utilities''' |
|
7 |
_names = 'users' |
|
8 |
|
|
9 |
name = None |
|
10 |
email = None |
|
11 |
name_identifiers = None |
|
12 |
identification_token = None |
|
13 |
lasso_dumps = None |
|
14 |
is_admin = False |
|
15 |
anonymous = False |
|
16 |
|
|
17 |
def __init__(self, name=None): |
|
18 |
StorableObject.__init__(self) |
|
19 |
self.name = name |
|
20 |
self.name_identifiers = [] |
|
21 |
self.lasso_dumps = [] |
|
22 |
|
|
23 |
def migrate(self): |
|
24 |
pass |
|
25 |
|
|
26 |
def remove_name_identifier(self, name_identifier): |
|
27 |
self.name_identifiers.remove(name_identifier) |
|
28 |
if not self.name_identifiers: |
|
29 |
self.remove_self() |
|
30 |
else: |
|
31 |
self.store() |
|
32 |
|
|
33 |
def get_display_name(self): |
|
34 |
if self.name: |
|
35 |
return self.name |
|
36 |
if self.email: |
|
37 |
return self.email |
|
38 |
return _('Unknown User') |
|
39 |
display_name = property(get_display_name) |
|
40 |
|
|
41 |
def __str__(self): |
|
42 |
return 'User %s, name : %s, name identifiers : %s, lasso_dumps : %s, token : %s' \ |
|
43 |
% (self.id, self.name, self.name_identifiers, self.lasso_dumps, |
|
44 |
self.identification_token) |
larpe/tags/release-1.1.1/larpectl | ||
---|---|---|
1 |
#!/usr/bin/python |
|
2 |
|
|
3 |
import sys |
|
4 |
|
|
5 |
from larpe import ctl |
|
6 |
|
|
7 |
def print_usage(): |
|
8 |
print 'Usage: larpectl command [...]' |
|
9 |
print '' |
|
10 |
print 'Commands:' |
|
11 |
print ' start start server' |
|
12 |
print ' cache_modulesets parse and cache jhbuild module sets' |
|
13 |
|
|
14 |
if len(sys.argv) < 2: |
|
15 |
print_usage() |
|
16 |
sys.exit(1) |
|
17 |
else: |
|
18 |
command = sys.argv[1] |
|
19 |
|
|
20 |
if command == 'start': |
|
21 |
ctl.start(sys.argv[2:]) |
|
22 |
elif command == 'cache_modulesets': |
|
23 |
ctl.cache_modulesets() |
|
24 |
else: |
|
25 |
print_usage() |
larpe/tags/release-1.1.1/po/Makefile | ||
---|---|---|
1 |
prefix = /usr |
|
2 |
|
|
3 |
POFILES=$(wildcard *.po) |
|
4 |
MOFILES=$(POFILES:.po=.mo) |
|
5 |
PYFILES=$(shell find -L ../larpe -name '*.py' -or -name '*.ptl') |
|
6 |
RM=rm -f |
|
7 |
|
|
8 |
all: $(MOFILES) |
|
9 |
|
|
10 |
install: all |
|
11 |
for file in $(MOFILES); do \ |
|
12 |
lang=`echo $$file | sed 's/\.mo//'`; \ |
|
13 |
install -d $(DESTDIR)$(prefix)/share/locale/$$lang/LC_MESSAGES/; \ |
|
14 |
install -m 0644 $$file $(DESTDIR)$(prefix)/share/locale/$$lang/LC_MESSAGES/larpe.mo; \ |
|
15 |
done |
|
16 |
|
|
17 |
uninstall: |
|
18 |
@for file in $(MOFILES); do \ |
|
19 |
lang=`echo $$file | sed 's/\.mo//'`; \ |
|
20 |
$(RM) $(DESTDIR)$(prefix)/share/locale/$$lang/LC_MESSAGES/larpe.mo; \ |
|
21 |
done |
|
22 |
|
|
23 |
clean: |
|
24 |
-$(RM) messages.mo $(MOFILES) |
|
25 |
|
|
26 |
larpe.pot: $(PYFILES) |
|
27 |
@echo "Rebuilding the pot file" |
|
28 |
$(RM) larpe.pot tmp.*.pot |
|
29 |
cnt=0; |
|
30 |
for file in $(PYFILES); do \ |
|
31 |
cnt=$$(expr $$cnt + 1); \ |
|
32 |
bn=$$cnt.`basename $$file`; \ |
|
33 |
xgettext --keyword=N_ -c -L Python -o tmp.$$bn.pot $$file; \ |
|
34 |
done |
|
35 |
msgcat tmp.*.pot > larpe.pot |
|
36 |
$(RM) tmp.*.pot |
|
37 |
|
|
38 |
%.mo: %.po |
|
39 |
msgfmt -o $@ $< |
|
40 |
|
|
41 |
%.po: larpe.pot |
|
42 |
@echo -n "Merging larpe.pot and $@" |
|
43 |
@msgmerge $@ larpe.pot -o $@.new |
|
44 |
@if [ "`diff $@ $@.new | grep '[<>]' | wc -l`" -ne 2 ]; then \ |
|
45 |
mv -f $@.new $@; \ |
|
46 |
else \ |
|
47 |
$(RM) $@.new; \ |
|
48 |
fi |
|
49 |
@msgfmt --statistics $@ |
larpe/tags/release-1.1.1/po/fr.po | ||
---|---|---|
1 |
msgid "" |
|
2 |
msgstr "" |
|
3 |
"Project-Id-Version: Larpe 0.2.0\n" |
|
4 |
"Report-Msgid-Bugs-To: \n" |
|
5 |
"POT-Creation-Date: 2010-07-19 13:53+0200\n" |
|
6 |
"PO-Revision-Date: 2010-07-19 13:51+0100\n" |
|
7 |
"Last-Translator: Jérôme Schneider <jerome.schneider@gmail.com>\n" |
|
8 |
"Language-Team: French\n" |
|
9 |
"Language: \n" |
|
10 |
"MIME-Version: 1.0\n" |
|
11 |
"Content-Type: text/plain; charset=utf-8\n" |
|
12 |
"Content-Transfer-Encoding: 8bit\n" |
|
13 |
|
|
14 |
#: ../larpe/idwsf2.ptl:50 |
|
15 |
msgid "Failed connecting to the original site." |
|
16 |
msgstr "Échec de connexion au site d'origine" |
|
17 |
|
|
18 |
#: ../larpe/idwsf2.ptl:61 |
|
19 |
msgid "Failed getting attributes from the attribute provider." |
|
20 |
msgstr "" |
|
21 |
"Échec lors de la récupération d'attributs depuis le fournisseur d'attributs." |
|
22 |
|
|
23 |
#: ../larpe/idwsf2.ptl:64 |
|
24 |
msgid "Failed getting attributes for an unknown reason." |
|
25 |
msgstr "Échec lors de la récupération d'attributs pour une raison inconnue" |
|
26 |
|
|
27 |
#: ../larpe/liberty_site.ptl:46 ../larpe/liberty_site.ptl:56 |
|
28 |
msgid "SSO support is not yet configured" |
|
29 |
msgstr "Le support SSO n'est pas encore configuré" |
|
30 |
|
|
31 |
#: ../larpe/admin/users.ptl:24 ../larpe/admin/users.ptl:32 |
|
32 |
msgid "User Name" |
|
33 |
msgstr "Nom de l'utilisateur" |
|
34 |
|
|
35 |
#: ../larpe/admin/users.ptl:25 ../larpe/admin/users.ptl:34 |
|
36 |
#: ../larpe/admin/users.ptl:66 |
|
37 |
msgid "Email" |
|
38 |
msgstr "Courriel" |
|
39 |
|
|
40 |
#: ../larpe/admin/users.ptl:26 ../larpe/admin/users.ptl:36 |
|
41 |
#: ../larpe/admin/users.ptl:122 ../larpe/admin/forms_prefill.ptl:24 |
|
42 |
#: ../larpe/admin/forms_prefill.ptl:76 ../larpe/admin/settings.ptl:31 |
|
43 |
#: ../larpe/admin/settings.ptl:217 ../larpe/admin/settings.ptl:326 |
|
44 |
#: ../larpe/admin/settings.ptl:343 ../larpe/admin/fields_prefill.ptl:30 |
|
45 |
#: ../larpe/admin/fields_prefill.ptl:73 ../larpe/admin/hosts.ptl:384 |
|
46 |
#: ../larpe/admin/hosts.ptl:692 ../larpe/admin/hosts.ptl:740 |
|
47 |
#: ../larpe/admin/hosts.ptl:787 ../larpe/admin/hosts.ptl:1286 |
|
48 |
#: ../larpe/site_authentication.ptl:64 ../larpe/root.ptl:64 |
|
49 |
msgid "Submit" |
|
50 |
msgstr "Valider" |
|
51 |
|
|
52 |
#: ../larpe/admin/users.ptl:27 ../larpe/admin/users.ptl:37 |
|
53 |
#: ../larpe/admin/users.ptl:123 ../larpe/admin/users.ptl:138 |
|
54 |
#: ../larpe/admin/forms_prefill.ptl:25 ../larpe/admin/forms_prefill.ptl:77 |
|
55 |
#: ../larpe/admin/settings.ptl:218 ../larpe/admin/settings.ptl:327 |
|
56 |
#: ../larpe/admin/settings.ptl:344 ../larpe/admin/fields_prefill.ptl:31 |
|
57 |
#: ../larpe/admin/fields_prefill.ptl:74 ../larpe/admin/hosts.ptl:124 |
|
58 |
#: ../larpe/admin/hosts.ptl:385 ../larpe/admin/hosts.ptl:693 |
|
59 |
#: ../larpe/admin/hosts.ptl:741 ../larpe/admin/hosts.ptl:788 |
|
60 |
#: ../larpe/admin/hosts.ptl:1287 ../larpe/root.ptl:65 |
|
61 |
msgid "Cancel" |
|
62 |
msgstr "Annuler" |
|
63 |
|
|
64 |
#: ../larpe/admin/users.ptl:60 ../larpe/admin/users.ptl:61 |
|
65 |
msgid "User" |
|
66 |
msgstr "Utilisateur" |
|
67 |
|
|
68 |
#: ../larpe/admin/users.ptl:63 ../larpe/admin/hosts.ptl:382 |
|
69 |
msgid "Name" |
|
70 |
msgstr "Nom" |
|
71 |
|
|
72 |
#: ../larpe/admin/users.ptl:98 |
|
73 |
msgid "Debug" |
|
74 |
msgstr "Debug" |
|
75 |
|
|
76 |
#: ../larpe/admin/users.ptl:110 ../larpe/admin/forms_prefill.ptl:48 |
|
77 |
#: ../larpe/admin/forms_prefill.ptl:66 ../larpe/admin/forms_prefill.ptl:67 |
|
78 |
#: ../larpe/admin/forms_prefill.ptl:68 ../larpe/admin/fields_prefill.ptl:63 |
|
79 |
#: ../larpe/admin/fields_prefill.ptl:64 ../larpe/admin/fields_prefill.ptl:65 |
|
80 |
msgid "Edit" |
|
81 |
msgstr "Modifier" |
|
82 |
|
|
83 |
#: ../larpe/admin/users.ptl:111 ../larpe/admin/users.ptl:112 |
|
84 |
msgid "Edit User" |
|
85 |
msgstr "Modifier l'utilisateur" |
|
86 |
|
|
87 |
#: ../larpe/admin/users.ptl:121 |
|
88 |
msgid "You are about to irrevocably delete this user." |
|
89 |
msgstr "Vous allez définitivement supprimer cet utilisateur." |
|
90 |
|
|
91 |
#: ../larpe/admin/users.ptl:127 ../larpe/admin/forms_prefill.ptl:81 |
|
92 |
#: ../larpe/admin/fields_prefill.ptl:78 ../larpe/admin/hosts.ptl:1291 |
|
93 |
msgid "Delete" |
|
94 |
msgstr "Supprimer" |
|
95 |
|
|
96 |
#: ../larpe/admin/users.ptl:128 |
|
97 |
msgid "Delete User" |
|
98 |
msgstr "Supprimer l'utilisateur" |
|
99 |
|
|
100 |
#: ../larpe/admin/users.ptl:129 |
|
101 |
msgid "Deleting User :" |
|
102 |
msgstr "Suppression de l'utilisateur :" |
|
103 |
|
|
104 |
#: ../larpe/admin/users.ptl:137 |
|
105 |
msgid "Generate" |
|
106 |
msgstr "Générer" |
|
107 |
|
|
108 |
#: ../larpe/admin/users.ptl:143 ../larpe/admin/users.ptl:146 |
|
109 |
#: ../larpe/admin/users.ptl:147 ../larpe/admin/users.ptl:155 |
|
110 |
#: ../larpe/admin/users.ptl:180 ../larpe/admin/users.ptl:182 |
|
111 |
#: ../larpe/admin/users.ptl:223 ../larpe/root.ptl:62 ../larpe/root.ptl:71 |
|
112 |
msgid "Identification Token" |
|
113 |
msgstr "Jeton d'identification" |
|
114 |
|
|
115 |
#: ../larpe/admin/users.ptl:148 |
|
116 |
msgid "" |
|
117 |
"You are about to generate a token than can be used to federate the account." |
|
118 |
msgstr "" |
|
119 |
"Vous allez générer un jeton qui pourra être utilisé pour fédérer le compte." |
|
120 |
|
|
121 |
#: ../larpe/admin/users.ptl:149 |
|
122 |
msgid "" |
|
123 |
"After that, you will have the choice to send it to the user by email so that " |
|
124 |
"he can federate his accounts." |
|
125 |
msgstr "" |
|
126 |
"Ensuite, vous aurez la possibilité de l'envoyer à l'utilisateur par courriel " |
|
127 |
"pour qu'il puisse fédérer ses comptes." |
|
128 |
|
|
129 |
#: ../larpe/admin/users.ptl:151 |
|
130 |
#, python-format |
|
131 |
msgid "Note that user has already been issued an identification token : %s" |
|
132 |
msgstr "À noter que l'utilisateur a déjà un jeton d'identification : %s" |
|
133 |
|
|
134 |
#: ../larpe/admin/users.ptl:161 |
|
135 |
#, python-format |
|
136 |
msgid "Identification Token for %s" |
|
137 |
msgstr "Jeton d'identification pour %s" |
|
138 |
|
|
139 |
#: ../larpe/admin/users.ptl:165 |
|
140 |
msgid "Done" |
|
141 |
msgstr "Fait" |
|
142 |
|
|
143 |
#: ../larpe/admin/users.ptl:167 |
|
144 |
msgid "Send by email" |
|
145 |
msgstr "Envoyer par courriel" |
|
146 |
|
|
147 |
#: ../larpe/admin/users.ptl:173 |
|
148 |
#, python-format |
|
149 |
msgid "" |
|
150 |
"You have been given an identification token.\n" |
|
151 |
"\n" |
|
152 |
"Your token is %(token)s\n" |
|
153 |
"\n" |
|
154 |
"Click on %(url)s to use it.\n" |
|
155 |
msgstr "" |
|
156 |
"Un jeton d'identification vous a été attribué.\n" |
|
157 |
"\n" |
|
158 |
"Votre jeton est %(token)s\n" |
|
159 |
"\n" |
|
160 |
"Cliquez sur %(url)s pour l'utiliser.\n" |
|
161 |
|
|
162 |
#: ../larpe/admin/users.ptl:183 |
|
163 |
msgid "Failed sending email. Check your email configuration." |
|
164 |
msgstr "" |
|
165 |
"Échec de l'envoi du courriel. Vérifiez votre configuration des courriels." |
|
166 |
|
|
167 |
#: ../larpe/admin/users.ptl:184 ../larpe/admin/settings.ptl:112 |
|
168 |
#: ../larpe/admin/hosts.ptl:657 ../larpe/admin/hosts.ptl:713 |
|
169 |
#: ../larpe/admin/hosts.ptl:1340 |
|
170 |
msgid "Back" |
|
171 |
msgstr "Retour" |
|
172 |
|
|
173 |
#: ../larpe/admin/users.ptl:194 ../larpe/admin/users.ptl:195 |
|
174 |
#: ../larpe/admin/users.ptl:238 ../larpe/admin/users.ptl:272 |
|
175 |
#: ../larpe/admin/root.ptl:45 |
|
176 |
msgid "Users" |
|
177 |
msgstr "Utilisateurs" |
|
178 |
|
|
179 |
#: ../larpe/admin/users.ptl:199 ../larpe/admin/users.ptl:242 |
|
180 |
msgid "Liberty support must be setup before creating users." |
|
181 |
msgstr "" |
|
182 |
"Le support Liberty doit être configuré avant de créer des utilisateurs." |
|
183 |
|
|
184 |
#: ../larpe/admin/users.ptl:203 ../larpe/admin/users.ptl:254 |
|
185 |
#: ../larpe/admin/users.ptl:255 |
|
186 |
msgid "New User" |
|
187 |
msgstr "Nouvel utilisateur" |
|
188 |
|
|
189 |
#: ../larpe/admin/users.ptl:226 |
|
190 |
#, python-format |
|
191 |
msgid "Identification Token (current: %s)" |
|
192 |
msgstr "Jeton d'identification (actuellement: %s)" |
|
193 |
|
|
194 |
#: ../larpe/admin/users.ptl:233 ../larpe/admin/root.ptl:47 |
|
195 |
msgid "Logs" |
|
196 |
msgstr "Journaux" |
|
197 |
|
|
198 |
#: ../larpe/admin/users.ptl:239 ../larpe/admin/forms_prefill.ptl:122 |
|
199 |
#: ../larpe/admin/fields_prefill.ptl:125 ../larpe/admin/hosts.ptl:1344 |
|
200 |
msgid "New" |
|
201 |
msgstr "Nouveau" |
|
202 |
|
|
203 |
#: ../larpe/admin/forms_prefill.ptl:16 |
|
204 |
msgid "Form name" |
|
205 |
msgstr "Nom du formulaire" |
|
206 |
|
|
207 |
#: ../larpe/admin/forms_prefill.ptl:17 |
|
208 |
msgid "Only used for display" |
|
209 |
msgstr "Utilisé uniquement pour l'affichage" |
|
210 |
|
|
211 |
#: ../larpe/admin/forms_prefill.ptl:18 |
|
212 |
msgid "Form address" |
|
213 |
msgstr "Addresse du formulaire" |
|
214 |
|
|
215 |
#: ../larpe/admin/forms_prefill.ptl:20 |
|
216 |
msgid "ID-WSF data profile" |
|
217 |
msgstr "Profile des données ID-WSF" |
|
218 |
|
|
219 |
#: ../larpe/admin/forms_prefill.ptl:21 |
|
220 |
msgid "Example: urn:liberty:id-sis-pp:2005-05" |
|
221 |
msgstr "Exemple : urn:liberty:id-sis-pp:2005-05" |
|
222 |
|
|
223 |
#: ../larpe/admin/forms_prefill.ptl:22 |
|
224 |
msgid "ID-WSF data XML prefix" |
|
225 |
msgstr "Préfixe XML des données ID-WSF" |
|
226 |
|
|
227 |
#: ../larpe/admin/forms_prefill.ptl:23 |
|
228 |
msgid "Example: pp" |
|
229 |
msgstr "Exemple : pp" |
|
230 |
|
|
231 |
#: ../larpe/admin/forms_prefill.ptl:45 |
|
232 |
msgid "Form prefilling configuration" |
|
233 |
msgstr "Configuration du pré-remplissage de formulaire" |
|
234 |
|
|
235 |
#: ../larpe/admin/forms_prefill.ptl:48 |
|
236 |
msgid "Configure this form" |
|
237 |
msgstr "Configurer ce formulaire" |
|
238 |
|
|
239 |
#: ../larpe/admin/forms_prefill.ptl:50 ../larpe/admin/fields_prefill.ptl:91 |
|
240 |
#: ../larpe/admin/fields_prefill.ptl:98 |
|
241 |
msgid "Fields" |
|
242 |
msgstr "Champs" |
|
243 |
|
|
244 |
#: ../larpe/admin/forms_prefill.ptl:50 |
|
245 |
msgid "Configure the fields of this form" |
|
246 |
msgstr "Configurer les champs de ce formulaire" |
|
247 |
|
|
248 |
#: ../larpe/admin/forms_prefill.ptl:75 |
|
249 |
msgid "You are about to irrevocably delete this form." |
|
250 |
msgstr "Vous allez définitivement supprimer ce fomulaire." |
|
251 |
|
|
252 |
#: ../larpe/admin/forms_prefill.ptl:82 ../larpe/admin/forms_prefill.ptl:83 |
|
253 |
msgid "Delete Form" |
|
254 |
msgstr "Supprimer le formulaire" |
|
255 |
|
|
256 |
#: ../larpe/admin/forms_prefill.ptl:94 ../larpe/admin/forms_prefill.ptl:101 |
|
257 |
#: ../larpe/admin/hosts.ptl:1279 |
|
258 |
msgid "Forms" |
|
259 |
msgstr "Formulaires" |
|
260 |
|
|
261 |
#: ../larpe/admin/forms_prefill.ptl:104 |
|
262 |
msgid "New Form" |
|
263 |
msgstr "Nouveau formulaire" |
|
264 |
|
|
265 |
#: ../larpe/admin/settings.ptl:28 |
|
266 |
msgid "Metadata" |
|
267 |
msgstr "Méta-données" |
|
268 |
|
|
269 |
#: ../larpe/admin/settings.ptl:29 |
|
270 |
msgid "Public Key" |
|
271 |
msgstr "Clé publique" |
|
272 |
|
|
273 |
#: ../larpe/admin/settings.ptl:30 |
|
274 |
msgid "CA Certificate Chain" |
|
275 |
msgstr "Chaîne de certification" |
|
276 |
|
|
277 |
#: ../larpe/admin/settings.ptl:34 ../larpe/admin/settings.ptl:35 |
|
278 |
msgid "New Identity Provider" |
|
279 |
msgstr "Nouveau fournisseur d'identité" |
|
280 |
|
|
281 |
#: ../larpe/admin/settings.ptl:53 ../larpe/admin/settings.ptl:87 |
|
282 |
msgid "Bad metadata" |
|
283 |
msgstr "Mauvaises méta-données" |
|
284 |
|
|
285 |
#. Don't use custom emails |
|
286 |
#: ../larpe/admin/settings.ptl:104 ../larpe/admin/settings.ptl:105 |
|
287 |
#: ../larpe/admin/settings.ptl:192 |
|
288 |
msgid "Emails" |
|
289 |
msgstr "Courriels" |
|
290 |
|
|
291 |
#: ../larpe/admin/settings.ptl:108 |
|
292 |
msgid "General Options" |
|
293 |
msgstr "Options générales" |
|
294 |
|
|
295 |
#: ../larpe/admin/settings.ptl:125 ../larpe/admin/hosts.ptl:84 |
|
296 |
#: ../larpe/admin/root.ptl:46 |
|
297 |
msgid "Settings" |
|
298 |
msgstr "Paramètres" |
|
299 |
|
|
300 |
#: ../larpe/admin/settings.ptl:128 |
|
301 |
msgid "Liberty Alliance & SAML 2.0 Service Provider" |
|
302 |
msgstr "Fournisseur de service Liberty Alliance et SAML 2.0" |
|
303 |
|
|
304 |
#: ../larpe/admin/settings.ptl:130 |
|
305 |
msgid "Liberty Alliance Service Provider" |
|
306 |
msgstr "Fournisseur de service Liberty Alliance" |
|
307 |
|
|
308 |
#: ../larpe/admin/settings.ptl:132 |
|
309 |
msgid "Service Provider" |
|
310 |
msgstr "Fournisseur de service" |
|
311 |
|
|
312 |
#: ../larpe/admin/settings.ptl:132 |
|
313 |
msgid "Configure Larpe as a Service Provider" |
|
314 |
msgstr "Configurer Larpe en tant que fournisseur de service" |
|
315 |
|
|
316 |
#: ../larpe/admin/settings.ptl:142 ../larpe/admin/hosts.ptl:913 |
|
317 |
msgid "SAML 2.0 Metadata" |
|
318 |
msgstr "Méta-données SAML 2.0" |
|
319 |
|
|
320 |
#: ../larpe/admin/settings.ptl:143 |
|
321 |
msgid "Download SAML 2.0 metadata file for Larpe" |
|
322 |
msgstr "Télécharger le fichier des méta-données SAML 2.0 pour Larpe" |
|
323 |
|
|
324 |
#: ../larpe/admin/settings.ptl:149 ../larpe/admin/hosts.ptl:918 |
|
325 |
msgid "ID-FF 1.2 Metadata" |
|
326 |
msgstr "Méta-données ID-FF 1.2" |
|
327 |
|
|
328 |
#: ../larpe/admin/settings.ptl:150 |
|
329 |
msgid "Download ID-FF 1.2 metadata file for Larpe" |
|
330 |
msgstr "Télécharger le fichier des méta-données ID-FF 1.2 pour Larpe" |
|
331 |
|
|
332 |
#: ../larpe/admin/settings.ptl:156 ../larpe/admin/hosts.ptl:927 |
|
333 |
msgid "Public key" |
|
334 |
msgstr "Clé publique" |
|
335 |
|
|
336 |
#: ../larpe/admin/settings.ptl:157 ../larpe/admin/hosts.ptl:928 |
|
337 |
msgid "Download SSL Public Key file" |
|
338 |
msgstr "Télécharger le fichier de clé SSL publique" |
|
339 |
|
|
340 |
#: ../larpe/admin/settings.ptl:160 |
|
341 |
msgid "Liberty Alliance & SAML 2.0 Identity Provider" |
|
342 |
msgstr "Fournisseur d'identité Liberty Alliance et SAML 2.0" |
|
343 |
|
|
344 |
#: ../larpe/admin/settings.ptl:162 |
|
345 |
msgid "Liberty Alliance Identity Provider" |
|
346 |
msgstr "Fournisseur d'identité Liberty Alliance" |
|
347 |
|
|
348 |
#: ../larpe/admin/settings.ptl:167 |
|
349 |
msgid "Identity Provider" |
|
350 |
msgstr "Fournisseur d'identité" |
|
351 |
|
|
352 |
#: ../larpe/admin/settings.ptl:167 |
|
353 |
msgid "Configure an identity provider" |
|
354 |
msgstr "Configurer un fournisseur d'identité" |
|
355 |
|
|
356 |
#: ../larpe/admin/settings.ptl:171 |
|
357 |
msgid "Identity Provider metadatas" |
|
358 |
msgstr "Méta-données du fournisseur d'identité" |
|
359 |
|
|
360 |
#: ../larpe/admin/settings.ptl:171 |
|
361 |
msgid "See current identity provider metadatas" |
|
362 |
msgstr "Voir les méta-données du fournisseur d'identité actuel" |
|
363 |
|
|
364 |
#: ../larpe/admin/settings.ptl:175 |
|
365 |
msgid "Global parameters for the sites" |
|
366 |
msgstr "Paramètres globaux des sites" |
|
367 |
|
|
368 |
#: ../larpe/admin/settings.ptl:179 ../larpe/admin/settings.ptl:302 |
|
369 |
#: ../larpe/admin/settings.ptl:303 |
|
370 |
msgid "Domain name" |
|
371 |
msgstr "Nom de domaine" |
|
372 |
|
|
373 |
#: ../larpe/admin/settings.ptl:179 |
|
374 |
msgid "Configure the base domain name for the sites" |
|
375 |
msgstr "Configurer le nom de domaine de base pour les sites" |
|
376 |
|
|
377 |
#: ../larpe/admin/settings.ptl:181 ../larpe/admin/settings.ptl:348 |
|
378 |
#: ../larpe/admin/settings.ptl:349 |
|
379 |
msgid "Apache 2 configuration generation" |
|
380 |
msgstr "Génération de la configuration d'Apache 2" |
|
381 |
|
|
382 |
#: ../larpe/admin/settings.ptl:181 |
|
383 |
msgid "Customise Apache 2 configuration generation" |
|
384 |
msgstr "Personnaliser la génération de la configuration d'Apache 2" |
|
385 |
|
|
386 |
#: ../larpe/admin/settings.ptl:183 |
|
387 |
msgid "Proxy" |
|
388 |
msgstr "Mandataire (proxy)" |
|
389 |
|
|
390 |
#: ../larpe/admin/settings.ptl:183 |
|
391 |
msgid "Connect to the sites through a web proxy" |
|
392 |
msgstr "Se connecter aux sites en passant par un mandataire (proxy)" |
|
393 |
|
|
394 |
#: ../larpe/admin/settings.ptl:186 |
|
395 |
msgid "Customisation" |
|
396 |
msgstr "Personnalisation" |
|
397 |
|
|
398 |
#: ../larpe/admin/settings.ptl:190 |
|
399 |
msgid "Language" |
|
400 |
msgstr "Langue" |
|
401 |
|
|
402 |
#: ../larpe/admin/settings.ptl:190 |
|
403 |
msgid "Configure site language" |
|
404 |
msgstr "Configurer la langue du site" |
|
405 |
|
|
406 |
#: ../larpe/admin/settings.ptl:192 |
|
407 |
msgid "Configure email settings" |
|
408 |
msgstr "Configurer les paramètres des courriels" |
|
409 |
|
|
410 |
#: ../larpe/admin/settings.ptl:195 |
|
411 |
msgid "Misc" |
|
412 |
msgstr "Divers" |
|
413 |
|
|
414 |
#: ../larpe/admin/settings.ptl:199 |
|
415 |
msgid "Debug Options" |
|
416 |
msgstr "Options de débogage" |
|
417 |
|
|
418 |
#: ../larpe/admin/settings.ptl:199 |
|
419 |
msgid "Configure options useful for debugging" |
|
420 |
msgstr "Configurer les options utiles au debogage" |
|
421 |
|
|
422 |
#: ../larpe/admin/settings.ptl:215 |
|
423 |
msgid "Organisation Name" |
|
424 |
msgstr "Nom de l'organisation" |
|
425 |
|
|
426 |
#: ../larpe/admin/settings.ptl:222 ../larpe/admin/settings.ptl:223 |
|
427 |
msgid "Service Provider Configuration" |
|
428 |
msgstr "Configuration du fournisseur d'identité" |
|
429 |
|
|
430 |
#: ../larpe/admin/settings.ptl:318 |
|
431 |
msgid "Domain name for the sites" |
|
432 |
msgstr "Noms de domaine pour les sites" |
|
433 |
|
|
434 |
#. TODO: Add the option "Both" and handle it in hosts configuration |
|
435 |
#: ../larpe/admin/settings.ptl:321 |
|
436 |
msgid "Use HTTP or HTTPS" |
|
437 |
msgstr "Utiliser HTTP ou HTTPS" |
|
438 |
|
|
439 |
#: ../larpe/admin/settings.ptl:323 |
|
440 |
msgid "Same as the site" |
|
441 |
msgstr "Identique au site d'origine" |
|
442 |
|
|
443 |
#: ../larpe/admin/settings.ptl:341 |
|
444 |
msgid "" |
|
445 |
"Automatically generate Apache 2 configuration for new hosts and reload " |
|
446 |
"Apache 2 after changes" |
|
447 |
msgstr "" |
|
448 |
"Générer automatiquement la configuration Apache 2 pour les nouveaux hôtes et " |
|
449 |
"recharger Apache 2 après les changements" |
|
450 |
|
|
451 |
#: ../larpe/admin/fields_prefill.ptl:15 |
|
452 |
msgid "Field name" |
|
453 |
msgstr "Nom du champ" |
|
454 |
|
|
455 |
#: ../larpe/admin/fields_prefill.ptl:17 |
|
456 |
msgid "Xpath of the attribute" |
|
457 |
msgstr "Xpath de l'attribut" |
|
458 |
|
|
459 |
#: ../larpe/admin/fields_prefill.ptl:18 |
|
460 |
msgid "Example: /pp:PP/pp:InformalName" |
|
461 |
msgstr "Exemple : /pp:PP/pp:InformalName" |
|
462 |
|
|
463 |
#: ../larpe/admin/fields_prefill.ptl:19 |
|
464 |
msgid "Number of the field in the data" |
|
465 |
msgstr "Numéro du champ dans les données" |
|
466 |
|
|
467 |
#: ../larpe/admin/fields_prefill.ptl:21 |
|
468 |
msgid "" |
|
469 |
"Change it if there are multiple fields corresponding to the same Xpath and " |
|
470 |
"you want to get another than the first one" |
|
471 |
msgstr "" |
|
472 |
"À changer s'il existe plusieurs champs correspondants au même Xpath et que " |
|
473 |
"vous voulez obtenir un autre élément que le premier" |
|
474 |
|
|
475 |
#: ../larpe/admin/fields_prefill.ptl:22 |
|
476 |
msgid "Get raw XML value" |
|
477 |
msgstr "Récupérer la valeur XML brute" |
|
478 |
|
|
479 |
#: ../larpe/admin/fields_prefill.ptl:24 |
|
480 |
msgid "Python regexp of a string to match" |
|
481 |
msgstr "" |
|
482 |
"Expression régulière en Python correspondant à la chaîne de caractères à " |
|
483 |
"chercher" |
|
484 |
|
|
485 |
#: ../larpe/admin/fields_prefill.ptl:26 |
|
486 |
msgid "Python regexp of the replacing string" |
|
487 |
msgstr "" |
|
488 |
"Expression régulière en Python de la chaîne de caractères de remplacement" |
|
489 |
|
|
490 |
#: ../larpe/admin/fields_prefill.ptl:28 |
|
491 |
msgid "Options mapping for a select field" |
|
492 |
msgstr "Correspondance d'options pour un champ select" |
|
493 |
|
|
494 |
#: ../larpe/admin/fields_prefill.ptl:29 |
|
495 |
msgid "Add item" |
|
496 |
msgstr "Ajouter un élément" |
|
497 |
|
|
498 |
#: ../larpe/admin/fields_prefill.ptl:72 |
|
499 |
msgid "You are about to irrevocably delete this field." |
|
500 |
msgstr "Vous allez définitivement supprimer ce champ." |
|
501 |
|
|
502 |
#: ../larpe/admin/fields_prefill.ptl:79 ../larpe/admin/fields_prefill.ptl:80 |
|
503 |
msgid "Delete Field" |
|
504 |
msgstr "Supprimer le champ" |
|
505 |
|
|
506 |
#: ../larpe/admin/fields_prefill.ptl:101 |
|
507 |
msgid "New Field" |
|
508 |
msgstr "Nouveau champ" |
|
509 |
|
|
510 |
#: ../larpe/admin/hosts.ptl:33 |
|
511 |
msgid "" |
|
512 |
"You must either choose a different hostname from Larpe or specify a reversed " |
|
513 |
"directory" |
|
514 |
msgstr "" |
|
515 |
"Vous devez soit choisir un nom d'hôte différent de celui de Larpe, soit " |
|
516 |
"spécifier un répertoire inversé" |
|
517 |
|
|
518 |
#: ../larpe/admin/hosts.ptl:80 ../larpe/admin/hosts.ptl:102 |
|
519 |
msgid "Basic configuration" |
|
520 |
msgstr "Configuration de base" |
|
521 |
|
|
522 |
#: ../larpe/admin/hosts.ptl:81 |
|
523 |
msgid "Need domain name configuration" |
|
524 |
msgstr "Nécessite la configuration du nom de domaine" |
|
525 |
|
|
526 |
#: ../larpe/admin/hosts.ptl:82 |
|
527 |
#, python-format |
|
528 |
msgid "" |
|
529 |
"Before configuring hosts, you must\n" |
|
530 |
"<a href=\"../../../settings/domain_names\">setup a global domain name</a> " |
|
531 |
"in\n" |
|
532 |
"%(settings)s menu." |
|
533 |
msgstr "" |
|
534 |
"Avant des configurer les sites, vous devez <a href=\"../../../settings/" |
|
535 |
"domain_names\">définir un nom de domaine global</a> dans le menu " |
|
536 |
"%(settings)s." |
|
537 |
|
|
538 |
#: ../larpe/admin/hosts.ptl:103 |
|
539 |
msgid "Step 1 - Basic configuration" |
|
540 |
msgstr "Étape 1 - Configuration de base" |
|
541 |
|
|
542 |
#: ../larpe/admin/hosts.ptl:112 |
|
543 |
msgid "Original site root address" |
|
544 |
msgstr "Adresse racine du site d'origine" |
|
545 |
|
|
546 |
#: ../larpe/admin/hosts.ptl:114 |
|
547 |
msgid "" |
|
548 |
"If your site address is http://test.org/index.php, put http://test.org/ here" |
|
549 |
msgstr "" |
|
550 |
"Si l'adresse de votre site est http://test.org/index.php, mettez http://test." |
|
551 |
"org/ ici" |
|
552 |
|
|
553 |
#: ../larpe/admin/hosts.ptl:117 |
|
554 |
msgid "Use a proxy" |
|
555 |
msgstr "Utiliser un mandataire (proxy)" |
|
556 |
|
|
557 |
#: ../larpe/admin/hosts.ptl:118 |
|
558 |
msgid "" |
|
559 |
"Uncheck it if Larpe doesn't need to use the proxy to connect to this site" |
|
560 |
msgstr "" |
|
561 |
"Décocher cette case si Larpe ne doit pas utiliser un mandataire (proxy) pour " |
|
562 |
"se connecter à ce site" |
|
563 |
|
|
564 |
#: ../larpe/admin/hosts.ptl:122 |
|
565 |
msgid "" |
|
566 |
"If Larpe needs to use a proxy to connect to this site, you must first " |
|
567 |
"configure\n" |
|
568 |
" it in <a href=\"../../../settings/proxy\">global proxy parameters</a>." |
|
569 |
msgstr "" |
|
570 |
"Si Larpe doit utiliser un mandataire (proxy) pour se connecter à ce site, " |
|
571 |
"vous devez d'abord le configurer dans les <a href=\"../../../settings/proxy" |
|
572 |
"\">paramètres globaux du mandataire</a>." |
|
573 |
|
|
574 |
#: ../larpe/admin/hosts.ptl:125 ../larpe/admin/hosts.ptl:315 |
|
575 |
#: ../larpe/admin/hosts.ptl:343 ../larpe/admin/hosts.ptl:433 |
|
576 |
#: ../larpe/admin/hosts.ptl:464 ../larpe/admin/hosts.ptl:547 |
|
577 |
#: ../larpe/admin/hosts.ptl:583 ../larpe/admin/hosts.ptl:873 |
|
578 |
#: ../larpe/admin/hosts.ptl:889 ../larpe/admin/hosts.ptl:947 |
|
579 |
#: ../larpe/admin/hosts.ptl:977 |
|
580 |
msgid "Next" |
|
581 |
msgstr "Suivant" |
|
582 |
|
|
583 |
#: ../larpe/admin/hosts.ptl:126 ../larpe/admin/hosts.ptl:316 |
|
584 |
#: ../larpe/admin/hosts.ptl:434 ../larpe/admin/hosts.ptl:465 |
|
585 |
#: ../larpe/admin/hosts.ptl:548 ../larpe/admin/hosts.ptl:584 |
|
586 |
#: ../larpe/admin/hosts.ptl:874 ../larpe/admin/hosts.ptl:890 |
|
587 |
#: ../larpe/admin/hosts.ptl:978 |
|
588 |
msgid "Terminate" |
|
589 |
msgstr "Terminer" |
|
590 |
|
|
591 |
#: ../larpe/admin/hosts.ptl:314 ../larpe/admin/hosts.ptl:343 |
|
592 |
#: ../larpe/admin/hosts.ptl:432 ../larpe/admin/hosts.ptl:463 |
|
593 |
#: ../larpe/admin/hosts.ptl:546 ../larpe/admin/hosts.ptl:582 |
|
594 |
#: ../larpe/admin/hosts.ptl:872 ../larpe/admin/hosts.ptl:888 |
|
595 |
#: ../larpe/admin/hosts.ptl:976 ../larpe/admin/hosts.ptl:1002 |
|
596 |
msgid "Previous" |
|
597 |
msgstr "Précédent" |
|
598 |
|
|
599 |
#: ../larpe/admin/hosts.ptl:332 |
|
600 |
msgid "Check site address and name" |
|
601 |
msgstr "Vérifier l'adresse et le nom du site" |
|
602 |
|
|
603 |
#: ../larpe/admin/hosts.ptl:333 |
|
604 |
msgid "Step 2 - Check the new site address works" |
|
605 |
msgstr "Étape 2 - Vérifier que la nouvelle adresse du site fonctionne" |
|
606 |
|
|
607 |
#: ../larpe/admin/hosts.ptl:335 |
|
608 |
msgid "DNS configuration" |
|
609 |
msgstr "Configuration DNS" |
|
610 |
|
|
611 |
#: ../larpe/admin/hosts.ptl:337 |
|
612 |
msgid "" |
|
613 |
"Before opening the following link, ensure you have configured your DNS\n" |
|
614 |
"for this address. If you don't have a DNS server and you just want to test " |
|
615 |
"Larpe, add this\n" |
|
616 |
"domain name in the file \"/etc/hosts\"." |
|
617 |
msgstr "" |
|
618 |
"Avant d'ouvrir le lien suivant, assurez vous d'avoir configuré votre DNS " |
|
619 |
"pour cette adresse. Si vous n'avez pas de serveur DNS et que vous souhaitez " |
|
620 |
"seulement tester Larpe, ajoutez ce nom de domaine dans le fichier \"/etc/" |
|
621 |
"hosts\"." |
|
622 |
|
|
623 |
#: ../larpe/admin/hosts.ptl:341 |
|
624 |
#, python-format |
|
625 |
msgid "" |
|
626 |
"Then you can open this link in a new window or tab and see if your site\n" |
|
627 |
"is displayed. If it's ok, you can click the \"%(next)s\" button. Otherwise, " |
|
628 |
"click the \"%(previous)s\"\n" |
|
629 |
"button and check your settings." |
|
630 |
msgstr "" |
|
631 |
"Vous pouvez ensuite ouvrir ce lien dans une nouvelle fenêtre ou un nouvel " |
|
632 |
"onglet et voir si votre site est affiché. Si cela fonctionne, vous pouvez " |
|
633 |
"cliquer sur le bouton \"%(next)s\". Sinon, cliquez sur le bouton" |
|
634 |
"\"%(previous)s\" et vérifiez vos paramètres." |
|
635 |
|
|
636 |
#: ../larpe/admin/hosts.ptl:345 |
|
637 |
msgid "Site adress and name" |
|
638 |
msgstr "Adresse et nom du site" |
|
639 |
|
|
640 |
#: ../larpe/admin/hosts.ptl:347 |
|
641 |
msgid "The new address of this site is " |
|
642 |
msgstr "La nouvelle adresse du site est " |
|
643 |
|
|
644 |
#: ../larpe/admin/hosts.ptl:349 |
|
645 |
#, python-format |
|
646 |
msgid "The name of this site is \"%s\"." |
|
647 |
msgstr "Le nom du site est \"%s\"." |
|
648 |
|
|
649 |
#: ../larpe/admin/hosts.ptl:350 |
|
650 |
msgid "" |
|
651 |
"You can also <a href=\"modify_site_address_and_name\">\n" |
|
652 |
"modify the address or the name of this site</a>" |
|
653 |
msgstr "" |
|
654 |
"Vous pouvez aussi <a href=\"modify_site_address_and_name\">modifier " |
|
655 |
"l'adresse ou le nom du site</a>" |
|
656 |
|
|
657 |
#: ../larpe/admin/hosts.ptl:366 |
|
658 |
msgid "An host with the same name already exists" |
|
659 |
msgstr "Un hôte avec le même nom existe déjà" |
|
660 |
|
|
661 |
#: ../larpe/admin/hosts.ptl:373 ../larpe/admin/hosts.ptl:374 |
|
662 |
msgid "Modify site address and name" |
|
663 |
msgstr "Modifier l'adresse et le nom du site" |
|
664 |
|
|
665 |
#: ../larpe/admin/hosts.ptl:380 |
|
666 |
msgid "Address" |
|
667 |
msgstr "Adresse" |
|
668 |
|
|
669 |
#: ../larpe/admin/hosts.ptl:419 |
|
670 |
msgid "Authentication and logout" |
|
671 |
msgstr "Authentification et déconnexion" |
|
672 |
|
|
673 |
#: ../larpe/admin/hosts.ptl:420 |
|
674 |
msgid "Step 3 - Configure authentication and logout pages" |
|
675 |
msgstr "Étape 3 - Configurer les pages d'authentification et de déconnexion" |
|
676 |
|
|
677 |
#: ../larpe/admin/hosts.ptl:426 ../larpe/admin/hosts.ptl:969 |
|
678 |
msgid "Authentication form page address" |
|
679 |
msgstr "Adresse de la page du formulaire d'authentification" |
|
680 |
|
|
681 |
#: ../larpe/admin/hosts.ptl:427 |
|
682 |
msgid "Address of a page on the site which contains the authentication form" |
|
683 |
msgstr "Adresse d'une page du site contenant le formulaire d'authentification" |
|
684 |
|
|
685 |
#: ../larpe/admin/hosts.ptl:429 |
|
686 |
msgid "Logout address" |
|
687 |
msgstr "Adresse de déconnexion" |
|
688 |
|
|
689 |
#: ../larpe/admin/hosts.ptl:430 |
|
690 |
msgid "Address of the logout link on the site" |
|
691 |
msgstr "Adresse du lien de déconnexion du site" |
|
692 |
|
|
693 |
#: ../larpe/admin/hosts.ptl:446 |
|
694 |
msgid "(computed automatically)" |
|
695 |
msgstr "(calculé automatiquement)" |
|
696 |
|
|
697 |
#: ../larpe/admin/hosts.ptl:459 |
|
698 |
msgid "Plugin" |
|
699 |
msgstr "Extension" |
|
700 |
|
|
701 |
#: ../larpe/admin/hosts.ptl:460 |
|
702 |
msgid "You can force a plugin" |
|
703 |
msgstr "Vous pouvez forcer une extension" |
|
704 |
|
|
705 |
#: ../larpe/admin/hosts.ptl:478 |
|
706 |
msgid "Auto detected configuration" |
|
707 |
msgstr "Configuration détectée automatiquement" |
|
708 |
|
|
709 |
#: ../larpe/admin/hosts.ptl:479 |
|
710 |
msgid "" |
|
711 |
"Step 4 - Check automatically detected configuration for the authentication " |
|
712 |
"form" |
|
713 |
msgstr "" |
|
714 |
"Étape 4 - Vérifier la configuration détectée automatiquement pour " |
|
715 |
"l'authentification" |
|
716 |
|
|
717 |
#: ../larpe/admin/hosts.ptl:482 |
|
718 |
msgid "Address where the authentication form must be sent" |
|
719 |
msgstr "Adresse à laquelle le formulaire d'authentification doit être envoyé" |
|
720 |
|
|
721 |
#: ../larpe/admin/hosts.ptl:483 |
|
722 |
msgid "Name of the login field" |
|
723 |
msgstr "Nom du champ identifiant" |
|
724 |
|
|
725 |
#: ../larpe/admin/hosts.ptl:484 |
|
726 |
msgid "Name of the password field" |
|
727 |
msgstr "Nom du champ mot de passe" |
|
728 |
|
|
729 |
#: ../larpe/admin/hosts.ptl:503 |
|
730 |
msgid "" |
|
731 |
"The following authentication form parameters have been detected. If they " |
|
732 |
"look right, you can go to the next step.\n" |
|
733 |
"If you think they are wrong, go back and check your settings then try " |
|
734 |
"again.\n" |
|
735 |
msgstr "" |
|
736 |
"Les paramètres d'authentification suivants ont été détectés. Si ils semblent " |
|
737 |
"corrects, vous pouvez passer à l'étape suivante.\n" |
|
738 |
"Si vous pensez qu'ils sont incorrects, retournez à l'étape précédente et " |
|
739 |
"vérifiez vos paramètres, puis essayez à nouveau.\n" |
|
740 |
|
|
741 |
#: ../larpe/admin/hosts.ptl:508 |
|
742 |
msgid "" |
|
743 |
"The following authentication form parameters in red haven't been correctly " |
|
744 |
"detected. Go back and check\n" |
|
745 |
"your settings then try again.\n" |
|
746 |
msgstr "" |
|
747 |
"Les paramètres d'authentification suivants en rouge n'ont pas été détectés " |
|
748 |
"correctement. Retournez à une étape précédente vérifiez vos paramètres, puis " |
|
749 |
"essayez à nouveau.\n" |
|
750 |
|
|
751 |
#: ../larpe/admin/hosts.ptl:529 ../larpe/admin/hosts.ptl:1250 |
|
752 |
msgid "Credentials" |
|
753 |
msgstr "Identifiant et mot de passe" |
|
754 |
|
|
755 |
#: ../larpe/admin/hosts.ptl:530 |
|
756 |
msgid "Step 5 - Fill in a valid username/password for this site" |
|
757 |
msgstr "Étape 5 - Nom d'utilisateur et mot de passe pour ce site" |
|
758 |
|
|
759 |
#: ../larpe/admin/hosts.ptl:535 ../larpe/site_authentication.ptl:98 |
|
760 |
msgid "Username" |
|
761 |
msgstr "Identifiant" |
|
762 |
|
|
763 |
#: ../larpe/admin/hosts.ptl:537 ../larpe/site_authentication.ptl:100 |
|
764 |
msgid "Password" |
|
765 |
msgstr "Mot de passe" |
|
766 |
|
|
767 |
#: ../larpe/admin/hosts.ptl:594 |
|
768 |
msgid "Check authentication" |
|
769 |
msgstr "Vérifier l'authentification" |
|
770 |
|
|
771 |
#: ../larpe/admin/hosts.ptl:595 |
|
772 |
msgid "Step 6 - Check the authentication process" |
|
773 |
msgstr "Étape 6 - Vérifier la procédure d'authentification" |
|
774 |
|
|
775 |
#: ../larpe/admin/hosts.ptl:614 |
|
776 |
msgid "Authentication succeeded ! You can go to the next step." |
|
777 |
msgstr "" |
|
778 |
"L'authentification a réussi ! Vous pouvez continuer à l'étape suivante." |
|
779 |
|
|
780 |
#: ../larpe/admin/hosts.ptl:616 |
|
781 |
msgid "Authentication has failed. To resolve this problem, you can :" |
|
782 |
msgstr "L'authentification a échoué. Pour résoudre ce problème, vous pouvez :" |
|
783 |
|
|
784 |
#: ../larpe/admin/hosts.ptl:619 |
|
785 |
msgid "Try authentication again" |
|
786 |
msgstr "Retenter une authentification" |
|
787 |
|
|
788 |
#: ../larpe/admin/hosts.ptl:621 |
|
789 |
msgid "See the response of the authentication requests" |
|
790 |
msgstr "Voir la réponse de la requête d'authentification" |
|
791 |
|
|
792 |
#: ../larpe/admin/hosts.ptl:623 ../larpe/admin/hosts.ptl:705 |
|
793 |
msgid "Modify the parameters of the authentication requests" |
|
794 |
msgstr "Modifier les paramètres des requêtes d'authentification" |
|
795 |
|
|
796 |
#: ../larpe/admin/hosts.ptl:625 |
|
797 |
msgid "Change the way Larpe detects the authentication is successful or not" |
|
798 |
msgstr "" |
|
799 |
"Changer la façon donc Larpe détecte que l'authentification a réussi ou pas" |
|
800 |
|
|
801 |
#: ../larpe/admin/hosts.ptl:626 |
|
802 |
msgid "Go back and change your username and/or password" |
|
803 |
msgstr "Revenir en arrière et changer vos nom d'utilisateur et/ou mot de passe" |
|
804 |
|
|
805 |
#: ../larpe/admin/hosts.ptl:632 ../larpe/admin/hosts.ptl:633 |
|
806 |
msgid "Authentication response" |
|
807 |
msgstr "Réponse de l'authentification" |
|
808 |
|
|
809 |
#: ../larpe/admin/hosts.ptl:635 |
|
810 |
msgid "Response of the request with good credentials" |
|
811 |
msgstr "Réponse de la requête avec un bon couple identifiant/mot de passe" |
|
812 |
|
|
813 |
#: ../larpe/admin/hosts.ptl:638 ../larpe/admin/hosts.ptl:649 |
|
814 |
msgid "HTTP status code" |
|
815 |
msgstr "Code de status HTTP" |
|
816 |
|
|
817 |
#: ../larpe/admin/hosts.ptl:643 ../larpe/admin/hosts.ptl:654 |
|
818 |
msgid "See HTML page" |
|
819 |
msgstr "Voir la page HTML" |
|
820 |
|
|
821 |
#: ../larpe/admin/hosts.ptl:646 |
|
822 |
msgid "Response of the request with bad credentials" |
|
823 |
msgstr "Réponse de la requête avec un mauvais couple identifiant/mot de passe" |
|
824 |
|
|
825 |
#: ../larpe/admin/hosts.ptl:675 ../larpe/admin/hosts.ptl:676 |
|
826 |
msgid "Authentication success criteria" |
|
827 |
msgstr "Critères de succès de l'authentification" |
|
828 |
|
|
829 |
#: ../larpe/admin/hosts.ptl:682 |
|
830 |
msgid "Authentication system of the original site" |
|
831 |
msgstr "Système d'authentification du site d'origine" |
|
832 |
|
|
833 |
#: ../larpe/admin/hosts.ptl:684 |
|
834 |
msgid "Check the existence of a password field" |
|
835 |
msgstr "Vérifier l'existence d'un champ mot de passe" |
|
836 |
|
|
837 |
#: ../larpe/admin/hosts.ptl:685 |
|
838 |
msgid "Match some text to detect an authentication failure" |
|
839 |
msgstr "Trouver du texte pour détecter un échec d'authentification" |
|
840 |
|
|
841 |
#: ../larpe/admin/hosts.ptl:690 |
|
842 |
msgid "Text to match in case of authentication failure" |
|
843 |
msgstr "Texte à trouver dans le cas d'un échec d'authentification" |
|
844 |
|
|
845 |
#: ../larpe/admin/hosts.ptl:704 |
|
846 |
msgid "Authentication request" |
|
847 |
msgstr "Requête d'authentification" |
|
848 |
|
|
849 |
#: ../larpe/admin/hosts.ptl:709 |
|
850 |
msgid "Modify POST parameters" |
|
851 |
msgstr "Modifier les parameters du POST" |
|
852 |
|
|
853 |
#: ../larpe/admin/hosts.ptl:709 |
|
854 |
msgid "" |
|
855 |
"Configure the form attributes that will be sent within the authentication " |
|
856 |
"POST requests" |
|
857 |
msgstr "" |
|
858 |
"Configurer les attributes du formulaire qui seront envoyés dans les requêtes " |
|
859 |
"POST d'authentification" |
|
860 |
|
|
861 |
#: ../larpe/admin/hosts.ptl:711 |
|
862 |
msgid "Modify HTTP headers" |
|
863 |
msgstr "Modifier les entêtes HTTP" |
|
864 |
|
|
865 |
#: ../larpe/admin/hosts.ptl:711 |
|
866 |
msgid "Configure the HTTP headers of the authentication requests made by Larpe" |
|
867 |
msgstr "" |
|
868 |
"Configurer les entêtes HTTP des requêtes d'authentification envoyées par " |
|
869 |
"Larpe" |
|
870 |
|
|
871 |
#: ../larpe/admin/hosts.ptl:725 |
|
872 |
msgid "POST parameters" |
|
873 |
msgstr "Paramètres POST" |
|
874 |
|
|
875 |
#: ../larpe/admin/hosts.ptl:726 |
|
876 |
msgid "Configure POST parameters" |
|
877 |
msgstr "Configurer les paramètres POST" |
|
878 |
|
|
879 |
#: ../larpe/admin/hosts.ptl:728 |
|
880 |
msgid "" |
|
881 |
"Here are the detected form fields that will be sent as parameters of the\n" |
|
882 |
"authentication POST request. You can desactivate some or all of them, or " |
|
883 |
"change their value." |
|
884 |
msgstr "" |
|
885 |
"Voici les champs du formulaire détectés et qui seront envoyés en tant que " |
|
886 |
"paramètres de la requête POST\n" |
|
887 |
"d'authentification. Vous pouvez désactiver certains ou tous ces champs, ou " |
|
888 |
"modifier leur valeur." |
|
889 |
|
|
890 |
#: ../larpe/admin/hosts.ptl:766 |
|
891 |
msgid "HTTP headers" |
|
892 |
msgstr "Entêtes HTTP" |
|
893 |
|
|
894 |
#: ../larpe/admin/hosts.ptl:767 |
|
895 |
msgid "Configure HTTP headers" |
|
896 |
msgstr "Configurer les entêtes HTTP" |
|
897 |
|
|
898 |
#: ../larpe/admin/hosts.ptl:769 |
|
899 |
msgid "" |
|
900 |
"Here are the HTTP headers that will be sent within the authentication\n" |
|
901 |
"POST request. You can desactivate some or all of them, or change their value." |
|
902 |
msgstr "" |
|
903 |
"Voici les entêtes HTTP qui seront envoyés dans la requête POST\n" |
|
904 |
"d'authentification. Vous pouvez désactiver certains ou tous ces champs, ou " |
|
905 |
"modifier leur valeur." |
|
906 |
|
|
907 |
#: ../larpe/admin/hosts.ptl:782 |
|
908 |
msgid "" |
|
909 |
"The headers \"Host\", \"Accept-Encoding\" and \"Content-Length\" will also " |
|
910 |
"automatically be sent." |
|
911 |
msgstr "" |
|
912 |
"Les entêtes \"Host\", \"Accept-Encoding\" et \"Content-Length\" seront " |
|
913 |
"également envoyées automatiquement." |
|
914 |
|
|
915 |
#: ../larpe/admin/hosts.ptl:785 |
|
916 |
msgid "" |
|
917 |
"As Larpe uses a proxy for this site, the headers \"Proxy-Authorization\",\n" |
|
918 |
"\"Proxy-Connection\" and \"Keep-Alive\" will be sent as well." |
|
919 |
msgstr "" |
|
920 |
"Comme Larpe utilise un mandataire (proxy) pour ce site, les entêtes\"Proxy-" |
|
921 |
"Authorization\", \"Proxy-Connection\" et \"Keep-Alive\" seront aussienvoyées." |
|
922 |
|
|
923 |
#: ../larpe/admin/hosts.ptl:846 |
|
924 |
msgid "SSO initiation" |
|
925 |
msgstr "Initiation de l'authentification unique" |
|
926 |
|
|
927 |
#: ../larpe/admin/hosts.ptl:847 |
|
928 |
msgid "Step 7 - Configure how a Single Sign On can be initiated" |
|
929 |
msgstr "" |
|
930 |
"Étape 7 - Configurer la façon dont l'authentification unique peut être " |
|
931 |
"initiée" |
|
932 |
|
|
933 |
#: ../larpe/admin/hosts.ptl:849 |
|
934 |
msgid "" |
|
935 |
"Most sites use one of the following 2 ways to allow users to initialise an " |
|
936 |
"authentication :" |
|
937 |
msgstr "" |
|
938 |
"La plupart des sites utilisent une des 2 méthodes suivantes pour permettre " |
|
939 |
"aux utilisateursd'initier une authentification :" |
|
940 |
|
|
941 |
#: ../larpe/admin/hosts.ptl:852 |
|
942 |
msgid "" |
|
943 |
"The site has a single authentication page. It redirects users to this page " |
|
944 |
"when\n" |
|
945 |
"they click a \"Login\" button or try to access a page which require users to " |
|
946 |
"be authenticated." |
|
947 |
msgstr "" |
|
948 |
"Le site a une page unique d'authentification. Il redirige les utilisateurs " |
|
949 |
"vers cettepas lorsqu'ils cliquent sur un bouton \"Connexion\" ou essaient " |
|
950 |
"d'accéder à une pagequi nécessitent que les utilisateurs soient authentifiés" |
|
951 |
|
|
952 |
#: ../larpe/admin/hosts.ptl:855 |
|
953 |
msgid "" |
|
954 |
"The site includes an authentication form in most or all of his pages. Users " |
|
955 |
"can\n" |
|
956 |
"authenticate on any of these pages, and don't need to be redirected to a " |
|
957 |
"separate authentication page." |
|
958 |
msgstr "" |
|
959 |
"Le site inclut un formulaire d'authentification dans toutes ou la plupart de " |
|
960 |
"ses pages.Les utilisateurs peuvent s'authentifier sur n'importe laquelle de " |
|
961 |
"ces pages, et n'ont pasbesoin d'être redirigés vers une page " |
|
962 |
"d'authentification séparée" |
|
963 |
|
|
964 |
#: ../larpe/admin/hosts.ptl:860 |
|
965 |
msgid "Select the way your site works :" |
|
966 |
msgstr "Sélectionner la façon dont votre site fonctionne :" |
|
967 |
|
|
968 |
#: ../larpe/admin/hosts.ptl:868 |
|
969 |
msgid "The site has a single authentication page" |
|
970 |
msgstr "Le site a une page d'authentification séparée" |
|
971 |
|
|
972 |
#: ../larpe/admin/hosts.ptl:869 |
|
973 |
msgid "The site includes an authentication form in most or all pages" |
|
974 |
msgstr "" |
|
975 |
"Le site inclut un formulaire d'authentification imbriqué dans les pages" |
|
976 |
|
|
977 |
#: ../larpe/admin/hosts.ptl:900 |
|
978 |
msgid "Metadatas" |
|
979 |
msgstr "Méta-données" |
|
980 |
|
|
981 |
#: ../larpe/admin/hosts.ptl:901 |
|
982 |
#, python-format |
|
983 |
msgid "Step 8 - Metadatas of %(site_name)s" |
|
984 |
msgstr "Étape 8- Méta-données de %(site_name)s" |
|
985 |
|
|
986 |
#: ../larpe/admin/hosts.ptl:904 |
|
987 |
msgid "" |
|
988 |
"Download the metadatas and the public key for this site and\n" |
|
989 |
"upload them on your identity provider in order to use Liberty Alliance " |
|
990 |
"features." |
|
991 |
msgstr "" |
|
992 |
"Téléchargez les méta-données et la clé publique de ce site et\n" |
|
993 |
"fournissez-les au fournisseur d'identité afin d'utiliser les fonctionnalités " |
|
994 |
"Liberty Alliance" |
|
995 |
|
|
996 |
#: ../larpe/admin/hosts.ptl:914 |
|
997 |
msgid "Download SAML 2.0 metadata file" |
|
998 |
msgstr "Télécharger le fichier des méta-données SAML 2.0" |
|
999 |
|
|
1000 |
#: ../larpe/admin/hosts.ptl:919 |
|
1001 |
msgid "Download ID-FF 1.2 metadata file" |
|
1002 |
msgstr "Télécharger le fichier des méta-données ID-FF 1.2" |
|
1003 |
|
|
1004 |
#: ../larpe/admin/hosts.ptl:921 |
|
1005 |
msgid "No metadata has been generated for this host." |
|
1006 |
msgstr "Les méta-données pour ce site n'ont pas été générées." |
|
1007 |
|
|
1008 |
#: ../larpe/admin/hosts.ptl:930 |
|
1009 |
msgid "No public key has been generated for this host." |
|
1010 |
msgstr "La clé publique pour ce site n'a pas été générée." |
|
1011 |
|
|
1012 |
#: ../larpe/admin/hosts.ptl:942 |
|
1013 |
msgid "Advanced options" |
|
1014 |
msgstr "Options avancées" |
|
1015 |
|
|
1016 |
#: ../larpe/admin/hosts.ptl:943 |
|
1017 |
msgid "Step 9 - Advanced options" |
|
1018 |
msgstr "Étape 9 - Options avancées" |
|
1019 |
|
|
1020 |
#: ../larpe/admin/hosts.ptl:945 |
|
1021 |
msgid "Configure advanced options to setup the last details of your site." |
|
1022 |
msgstr "" |
|
1023 |
"Configurer les options avancées afin de paramétrer les derniers détails de " |
|
1024 |
"votre site" |
|
1025 |
|
|
1026 |
#: ../larpe/admin/hosts.ptl:946 |
|
1027 |
#, python-format |
|
1028 |
msgid "" |
|
1029 |
"If you don't know what to configure here, just click %(next)s and\n" |
|
1030 |
"come here later if needed." |
|
1031 |
msgstr "" |
|
1032 |
"Si vous ne savez pas quoi configurer ici, cliquez simplement sur %(next)s " |
|
1033 |
"etrevenez sur cette page plus tard si besoin" |
|
1034 |
|
|
1035 |
#: ../larpe/admin/hosts.ptl:959 |
|
1036 |
msgid "Redirect the root URL of the site to the login page." |
|
1037 |
msgstr "Rediriger la racine du site vers la page de d'authentification unique" |
|
1038 |
|
|
1039 |
#: ../larpe/admin/hosts.ptl:961 |
|
1040 |
msgid "Return address" |
|
1041 |
msgstr "Adresse de retour" |
|
1042 |
|
|
1043 |
#: ../larpe/admin/hosts.ptl:962 |
|
1044 |
msgid "Where the user will be redirected after a successful authentication" |
|
1045 |
msgstr "" |
|
1046 |
"Adresse vers laquelle l'utilisateur sera redirigé après s'être authentifié" |
|
1047 |
|
|
1048 |
#: ../larpe/admin/hosts.ptl:964 |
|
1049 |
msgid "Error address" |
|
1050 |
msgstr "Addresse en cas d'erreur" |
|
1051 |
|
|
1052 |
#: ../larpe/admin/hosts.ptl:965 |
|
1053 |
msgid "Where the user will be redirected after a disconnection or an error" |
|
1054 |
msgstr "Où l'utilisateur sera redirigé après une déconnexion ou une erreur" |
|
1055 |
|
|
1056 |
#: ../larpe/admin/hosts.ptl:967 |
|
1057 |
msgid "URL which must initiate the SSO" |
|
1058 |
msgstr "URL qui doit initier l'authentification unique" |
|
1059 |
|
|
1060 |
#: ../larpe/admin/hosts.ptl:968 |
|
1061 |
#, python-format |
|
1062 |
msgid "" |
|
1063 |
"Address which must initiate the SSO. If empty, defaults to the previously\n" |
|
1064 |
"specified \"%s\"" |
|
1065 |
msgstr "" |
|
1066 |
"Adresse qui doit initier l'authentification unique. Si ce champ est vide, " |
|
1067 |
"l'adresse utilisée sera celle qui a été précédemment renseignée en tant que " |
|
1068 |
"\"%s\"" |
|
1069 |
|
|
1070 |
#: ../larpe/admin/hosts.ptl:971 |
|
1071 |
msgid "Apache HTML proxy" |
|
1072 |
msgstr "Mandataire (proxy) HTML d'Apache" |
|
1073 |
|
|
1074 |
#: ../larpe/admin/hosts.ptl:972 |
|
1075 |
msgid "" |
|
1076 |
"Converts urls in the HTML pages according to the host new domain name.\n" |
|
1077 |
"Disabled by default because it makes some sites not work correctly." |
|
1078 |
msgstr "" |
|
1079 |
"Convertir les urls des pages HTML en fonction du nouveau nom de domaine du " |
|
1080 |
"site. Cette option est désactivée par défaut car elle empêche certains sites " |
|
1081 |
"de fonctionner correctement." |
|
1082 |
|
|
1083 |
#: ../larpe/admin/hosts.ptl:1003 ../larpe/admin/hosts.ptl:1024 |
|
1084 |
msgid "Finish" |
|
1085 |
msgstr "Terminer" |
|
1086 |
|
|
1087 |
#: ../larpe/admin/hosts.ptl:1011 |
|
1088 |
msgid "Check everything works" |
|
1089 |
msgstr "Vérifier que tout fonctionne" |
|
1090 |
|
|
1091 |
#: ../larpe/admin/hosts.ptl:1012 |
|
1092 |
msgid "Step 10 - Check everything works" |
|
1093 |
msgstr "Étape 10 - Vérifier que tout fonctionne" |
|
1094 |
|
|
1095 |
#: ../larpe/admin/hosts.ptl:1015 |
|
1096 |
msgid "" |
|
1097 |
"Now you can fully test your site, start from the home page, initiate a\n" |
|
1098 |
"Single Sign On, federate your identities and do a Single Logout." |
|
1099 |
msgstr "" |
|
1100 |
"Vous pouvez maintenant tester vote nouveau site complètement.\n" |
|
1101 |
"Commencez par la page d'accueil, initiez une authentification unique,\n" |
|
1102 |
"fédérez vos identités puis faites une déconnexion unique." |
|
1103 |
|
|
1104 |
#: ../larpe/admin/hosts.ptl:1018 |
|
1105 |
msgid "The address of your site is : " |
|
1106 |
msgstr "L'adresse du site est : " |
|
1107 |
|
|
1108 |
#: ../larpe/admin/hosts.ptl:1023 |
|
1109 |
#, python-format |
|
1110 |
msgid "" |
|
1111 |
"If everything works, click the \"%(finish)s\" button, otherwise you can go\n" |
|
1112 |
"back and check your settings." |
|
1113 |
msgstr "" |
|
1114 |
"Si tout fonctionne, cliquez sur le bouton \"%(finish)s\", sinon vous pouvez " |
|
1115 |
"revenir en arrière et vérifier votre configuration" |
|
1116 |
|
|
1117 |
#: ../larpe/admin/hosts.ptl:1136 ../larpe/admin/hosts.ptl:1151 |
|
1118 |
#: ../larpe/admin/hosts.ptl:1182 |
|
1119 |
msgid "(filled by users)" |
|
1120 |
msgstr "(rempli par les utilisateurs)" |
|
1121 |
|
|
1122 |
#: ../larpe/admin/hosts.ptl:1233 |
|
1123 |
msgid "Configuration assistant" |
|
1124 |
msgstr "Assistant de configuration" |
|
1125 |
|
|
1126 |
#: ../larpe/admin/hosts.ptl:1238 |
|
1127 |
msgid "Address of the original site" |
|
1128 |
msgstr "Adresse du site d'origine" |
|
1129 |
|
|
1130 |
#: ../larpe/admin/hosts.ptl:1238 |
|
1131 |
msgid "Configure the root address of the site" |
|
1132 |
msgstr "Configurer l'adresse racine de ce site" |
|
1133 |
|
|
1134 |
#: ../larpe/admin/hosts.ptl:1241 |
|
1135 |
msgid "New address and name" |
|
1136 |
msgstr "Nouvelle adresse et nouveau nom du site" |
|
1137 |
|
|
1138 |
#: ../larpe/admin/hosts.ptl:1241 |
|
1139 |
msgid "Configure the new address and name of this site" |
|
1140 |
msgstr "Configurer la nouvelle adresse et le nouveau nom du site" |
|
1141 |
|
|
1142 |
#: ../larpe/admin/hosts.ptl:1244 |
|
1143 |
msgid "Authentication and logout addresses" |
|
1144 |
msgstr "Adresses des pages d'authentification et de déconnexion" |
|
1145 |
|
|
1146 |
#: ../larpe/admin/hosts.ptl:1244 |
|
1147 |
msgid "Configure the authentication and logout addresses of the original site" |
|
1148 |
msgstr "" |
|
1149 |
"Configurer les adresses des pages d'authentification et de déconnexion du " |
|
1150 |
"site d'origine" |
|
1151 |
|
|
1152 |
#: ../larpe/admin/hosts.ptl:1247 |
|
1153 |
msgid "Check auto detected configuration" |
|
1154 |
msgstr "Vérifier la configuration détectée automatiquement" |
|
1155 |
|
|
1156 |
#: ../larpe/admin/hosts.ptl:1247 |
|
1157 |
msgid "Check the automatically detected configuration is right" |
|
1158 |
msgstr "Vérifier que la configuration détectée automatiquement est correcte" |
|
1159 |
|
|
1160 |
#: ../larpe/admin/hosts.ptl:1250 |
|
1161 |
msgid "Configure some valid credentials to authenticate on the original site" |
|
1162 |
msgstr "" |
|
1163 |
"Configurer un couple identifiant / mot de passe pour s'authentifier sur le " |
|
1164 |
"site d'origine" |
|
1165 |
|
|
1166 |
#: ../larpe/admin/hosts.ptl:1253 |
|
1167 |
msgid "Retry authentication" |
|
1168 |
msgstr "Retenter l'authentification" |
|
1169 |
|
|
1170 |
#: ../larpe/admin/hosts.ptl:1253 |
|
1171 |
msgid "" |
|
1172 |
"Retry sending an authentication request to the site to check if your new " |
|
1173 |
"parameters work well" |
|
1174 |
msgstr "" |
|
1175 |
"Retenter d'envoyer une requête d'authentification au site pour vérifier si " |
|
1176 |
"vos nouveaux paramètres fonctionnent bien" |
|
1177 |
|
|
1178 |
#: ../larpe/admin/hosts.ptl:1256 |
|
1179 |
msgid "Check authentication response" |
|
1180 |
msgstr "Vérifier la réponse de l'authentification" |
|
1181 |
|
|
1182 |
#: ../larpe/admin/hosts.ptl:1256 |
|
1183 |
msgid "Check the response from the latest authentication request" |
|
1184 |
msgstr "Vérifier la réponse de la dernière requête d'authentification" |
|
1185 |
|
|
1186 |
#: ../larpe/admin/hosts.ptl:1259 |
|
1187 |
msgid "Configure authentication success criteria" |
|
1188 |
msgstr "Configurer les critères de succès de l'authentification" |
|
1189 |
|
|
1190 |
#: ../larpe/admin/hosts.ptl:1259 |
|
1191 |
msgid "Specify how Larpe knows if the authentication has succeeded or not" |
|
1192 |
msgstr "" |
|
1193 |
"Spécifier comment Larpe détermine si l'authentification a réussi ou pas" |
|
1194 |
|
|
1195 |
#: ../larpe/admin/hosts.ptl:1262 |
|
1196 |
msgid "Modify authentication request" |
|
1197 |
msgstr "Modifier la requête d'authentification" |
|
1198 |
|
|
1199 |
#: ../larpe/admin/hosts.ptl:1262 |
|
1200 |
msgid "Modify POST fields or HTTP headers of the authentication request" |
|
1201 |
msgstr "" |
|
1202 |
"Modifier les champs POST ou les entêtes HTTP de la requête d'authentification" |
|
1203 |
|
|
1204 |
#: ../larpe/admin/hosts.ptl:1265 |
|
1205 |
msgid "Configure how a Single Sign On can be initiated" |
|
1206 |
msgstr "Configurer la façon dont l'authentification unique peut être initiée" |
|
1207 |
|
|
1208 |
#: ../larpe/admin/hosts.ptl:1268 |
|
1209 |
msgid "Metadatas and key" |
|
1210 |
msgstr "Méta-données et clé" |
|
1211 |
|
|
1212 |
#: ../larpe/admin/hosts.ptl:1268 |
|
1213 |
msgid "Download SAML 2.0 or ID-FF metadatas and SSL public key" |
|
1214 |
msgstr "Télécharger les méta-données SAML 2.0 ou ID-FF et la clé SSL publique" |
|
1215 |
|
|
1216 |
#: ../larpe/admin/hosts.ptl:1271 |
|
1217 |
msgid "Adavanced options" |
|
1218 |
msgstr "Options avancées" |
|
1219 |
|
|
1220 |
#: ../larpe/admin/hosts.ptl:1271 |
|
1221 |
msgid "Configure advanced options to setup the last details of your site" |
|
1222 |
msgstr "" |
|
1223 |
"Configurer les options avancées afin de paramétrer les derniers détails de " |
|
1224 |
"votre site" |
|
1225 |
|
|
1226 |
#: ../larpe/admin/hosts.ptl:1275 |
|
1227 |
msgid "Form prefilling with ID-WSF" |
|
1228 |
msgstr "Pré-remplissage de formulaire avec ID-WSF" |
|
1229 |
|
|
1230 |
#: ../larpe/admin/hosts.ptl:1279 |
|
1231 |
msgid "Configure the forms to prefill" |
|
1232 |
msgstr "Configurer les formulaires à pré-remplir" |
|
1233 |
|
|
1234 |
#: ../larpe/admin/hosts.ptl:1285 |
|
1235 |
msgid "You are about to irrevocably delete this host." |
|
1236 |
msgstr "Vous allez définitivement supprimer cet hôte." |
|
1237 |
|
|
1238 |
#: ../larpe/admin/hosts.ptl:1292 ../larpe/admin/hosts.ptl:1293 |
|
1239 |
msgid "Delete Host" |
|
1240 |
msgstr "Supprimer l'hôte" |
|
1241 |
|
|
1242 |
#: ../larpe/admin/hosts.ptl:1305 ../larpe/admin/hosts.ptl:1306 |
|
1243 |
#: ../larpe/admin/hosts.ptl:1343 ../larpe/admin/hosts.ptl:1350 |
|
1244 |
#: ../larpe/admin/root.ptl:44 |
|
1245 |
msgid "Hosts" |
|
1246 |
msgstr "Hôtes" |
|
1247 |
|
|
1248 |
#: ../larpe/admin/hosts.ptl:1309 ../larpe/admin/hosts.ptl:1336 |
|
1249 |
#: ../larpe/admin/hosts.ptl:1337 |
|
1250 |
msgid "New Host" |
|
1251 |
msgstr "Nouvel hôte" |
|
1252 |
|
|
1253 |
#: ../larpe/admin/root.ptl:48 |
|
1254 |
msgid "Liberty Alliance Reverse Proxy" |
|
1255 |
msgstr "Relais inverse Liberty Alliance" |
|
1256 |
|
|
1257 |
#: ../larpe/admin/root.ptl:59 |
|
1258 |
msgid "Administration" |
|
1259 |
msgstr "Administration" |
|
1260 |
|
|
1261 |
#: ../larpe/saml2.ptl:32 ../larpe/saml2.ptl:46 |
|
1262 |
msgid "SAML 2.0 support not yet configured." |
|
1263 |
msgstr "Le support SAML 2.0 n'est pas encore configuré" |
|
1264 |
|
|
1265 |
#: ../larpe/saml2.ptl:53 |
|
1266 |
msgid "Missing SAML Artifact" |
|
1267 |
msgstr "Artifact SAML manquant" |
|
1268 |
|
|
1269 |
#: ../larpe/saml2.ptl:64 ../larpe/liberty.ptl:58 |
|
1270 |
msgid "Failure to communicate with identity provider" |
|
1271 |
msgstr "Impossible de communiquer avec le fournisseur d'identités." |
|
1272 |
|
|
1273 |
#: ../larpe/saml2.ptl:70 ../larpe/liberty.ptl:63 |
|
1274 |
msgid "Unknown authentication failure" |
|
1275 |
msgstr "Erreur d'authentification inconnue" |
|
1276 |
|
|
1277 |
#: ../larpe/saml2.ptl:72 ../larpe/liberty.ptl:66 |
|
1278 |
msgid "Authentication failure; unknown principal" |
|
1279 |
msgstr "Erreur d'authentification: utilisateur inconnu" |
|
1280 |
|
|
1281 |
#: ../larpe/saml2.ptl:334 ../larpe/liberty.ptl:142 ../larpe/liberty.ptl:173 |
|
1282 |
msgid "Failed to check single logout request signature." |
|
1283 |
msgstr "Erreur à la vérification de la signature de la demande de déconnexion" |
|
1284 |
|
|
1285 |
#: ../larpe/site_authentication.ptl:60 |
|
1286 |
msgid "Local authentication" |
|
1287 |
msgstr "Authentification locale" |
|
1288 |
|
|
1289 |
#: ../larpe/site_authentication.ptl:74 |
|
1290 |
msgid "Authentication failure" |
|
1291 |
msgstr "Erreur d'authentification" |
|
1292 |
|
|
1293 |
#: ../larpe/site_authentication.ptl:77 |
|
1294 |
#, python-format |
|
1295 |
msgid "Connection failed : %s" |
|
1296 |
msgstr "Échec de la connexion : %s" |
|
1297 |
|
|
1298 |
#: ../larpe/site_authentication.ptl:80 |
|
1299 |
#, python-format |
|
1300 |
msgid "This service provider is not fully configured : %s" |
|
1301 |
msgstr "Ce fournisseur de service n'est pas complètement configuré : %s" |
|
1302 |
|
|
1303 |
#: ../larpe/site_authentication.ptl:83 |
|
1304 |
#, python-format |
|
1305 |
msgid "Unknown error : %s" |
|
1306 |
msgstr "Erreur inconnue : %s" |
|
1307 |
|
|
1308 |
#: ../larpe/site_authentication.ptl:89 |
|
1309 |
msgid "Please type your login and password for this Service Provider." |
|
1310 |
msgstr "" |
|
1311 |
"Entrez votre identifiant et votre mot de passe pour ce fournisseur de " |
|
1312 |
"service." |
|
1313 |
|
|
1314 |
#: ../larpe/site_authentication.ptl:90 ../larpe/root.ptl:74 |
|
1315 |
msgid "" |
|
1316 |
"Your local account will be federated with your Liberty Alliance account." |
|
1317 |
msgstr "Votre compte local sera fédéré avec votre compte Liberty Alliance." |
|
1318 |
|
|
1319 |
#: ../larpe/site_authentication.ptl:296 |
|
1320 |
#, python-format |
|
1321 |
msgid "%s logout failed" |
|
1322 |
msgstr "%s échec de la déconnexion" |
|
1323 |
|
|
1324 |
#: ../larpe/root.ptl:27 |
|
1325 |
msgid "Welcome to Larpe reverse proxy" |
|
1326 |
msgstr "Bienvenue sur le reverse proxy Larpe" |
|
1327 |
|
|
1328 |
#: ../larpe/root.ptl:29 |
|
1329 |
msgid "Configure Larpe" |
|
1330 |
msgstr "Configurer Larpe" |
|
1331 |
|
|
1332 |
#: ../larpe/root.ptl:73 |
|
1333 |
msgid "Please enter your identification token. " |
|
1334 |
msgstr "Veuillez saisir votre jeton d'identification. " |
|
1335 |
|
|
1336 |
#: ../larpe/root.ptl:87 |
|
1337 |
msgid "Unknown Token" |
|
1338 |
msgstr "Jeton inconnu" |
|
1339 |
|
|
1340 |
#: ../larpe/liberty.ptl:45 |
|
1341 |
msgid "Liberty support is not yet configured" |
|
1342 |
msgstr "Le support Liberty n'est pas encore configuré" |
|
1343 |
|
|
1344 |
#: ../larpe/liberty.ptl:67 |
|
1345 |
msgid "Identity Provider didn't accept artifact transaction." |
|
1346 |
msgstr "Le fournisseur d'identité n'a pas accepté l'artifact." |
|
1347 |
|
|
1348 |
#: ../larpe/users.py:38 |
|
1349 |
msgid "Unknown User" |
|
1350 |
msgstr "Utilisateur inconnu" |
|
1351 |
|
|
1352 |
#~ msgid "My Space" |
|
1353 |
#~ msgstr "Mon espace" |
|
1354 |
|
|
1355 |
#~ msgid "back office" |
|
1356 |
#~ msgstr "backoffice" |
|
1357 |
|
|
1358 |
#~ msgid "admin" |
|
1359 |
#~ msgstr "admin" |
|
1360 |
|
|
1361 |
#~ msgid "My Profile" |
|
1362 |
#~ msgstr "Mon profil" |
|
1363 |
|
|
1364 |
#~ msgid "Empty profile" |
|
1365 |
#~ msgstr "Profile vide" |
|
1366 |
|
|
1367 |
#~ msgid "Edit My Profile" |
|
1368 |
#~ msgstr "Editer mon profil" |
|
1369 |
|
|
1370 |
#~ msgid "Change My Password" |
|
1371 |
#~ msgstr "Changement de mot de passe" |
|
1372 |
|
|
1373 |
#~ msgid "Remove My Account" |
|
1374 |
#~ msgstr "Supprimer un compte" |
|
1375 |
|
|
1376 |
#~ msgid "Apply Changes" |
|
1377 |
#~ msgstr "Appliquer les changements" |
|
1378 |
|
|
1379 |
#~ msgid "Edit Profile" |
|
1380 |
#~ msgstr "Editer le profile" |
|
1381 |
|
|
1382 |
#~ msgid "New Password" |
|
1383 |
#~ msgstr "Nouveau mot de passe" |
|
1384 |
|
|
1385 |
#~ msgid "New Password (confirm)" |
|
1386 |
#~ msgstr "Nouveau mot de passe (confirmation)" |
|
1387 |
|
|
1388 |
#~ msgid "Change Password" |
|
1389 |
#~ msgstr "Changement de mot de passe" |
|
1390 |
|
|
1391 |
#~ msgid "Passwords do not match" |
|
1392 |
#~ msgstr "Les mots de passe sont différents" |
|
1393 |
|
|
1394 |
#~ msgid "Are you really sure you want to remove your account?" |
|
1395 |
#~ msgstr "Etes vous vraiment sûr de vouloir supprimer votre compte ?" |
|
1396 |
|
|
1397 |
#~ msgid "Remove my account" |
|
1398 |
#~ msgstr "Supprimer mon compte" |
|
1399 |
|
|
1400 |
#~ msgid "Removing Account" |
|
1401 |
#~ msgstr "Supression du compte" |
|
1402 |
|
|
1403 |
#~ msgid "Text on top of the profile page" |
|
1404 |
#~ msgstr "Texte en haut de la page de profil" |
|
1405 |
|
|
1406 |
#~ msgid "day" |
|
1407 |
#~ msgstr "Moi" |
|
1408 |
|
|
1409 |
#, fuzzy |
|
1410 |
#~ msgid "minute" |
|
1411 |
#~ msgstr "moins" |
|
1412 |
|
|
1413 |
#, fuzzy |
|
1414 |
#~ msgid "minutes" |
|
1415 |
#~ msgstr "moins" |
|
1416 |
|
|
1417 |
#, fuzzy |
|
1418 |
#~ msgid "%s minutes" |
|
1419 |
#~ msgstr "moins" |
|
1420 |
|
|
1421 |
#~ msgid "registered" |
|
1422 |
#~ msgstr "enregistré" |
|
1423 |
|
|
1424 |
#~ msgid "running" |
|
1425 |
#~ msgstr "en fonctionnement" |
|
1426 |
|
|
1427 |
#~ msgid "completed" |
|
1428 |
#~ msgstr "terminé" |
|
1429 |
|
|
1430 |
#~ msgid "Access Forbidden" |
|
1431 |
#~ msgstr "Accès interdit" |
|
1432 |
|
|
1433 |
#~ msgid "the homepage" |
|
1434 |
#~ msgstr "la page d'accueil" |
|
1435 |
|
|
1436 |
#~ msgid "Oops, the server borked severely" |
|
1437 |
#~ msgstr "Oups, le serveur s'est méchamment planté" |
|
1438 |
|
|
1439 |
#~ msgid "" |
|
1440 |
#~ "This is bad bad bad; perhaps you will have more luck if you retry in a " |
|
1441 |
#~ "few minutes ? " |
|
1442 |
#~ msgstr "" |
|
1443 |
#~ "C'est mal mal mal; peut-être aurez-vous plus de chance en réessayant dans " |
|
1444 |
#~ "quelques minutes ? " |
|
1445 |
|
|
1446 |
#~ msgid "" |
|
1447 |
#~ "Alternatively you could harass the webmaster (who may have been emailed " |
|
1448 |
#~ "automatically with this incident but you can't be sure about this." |
|
1449 |
#~ msgstr "" |
|
1450 |
#~ "Autrement vous pouvez harceler le webmestre (qui devrait avoir été " |
|
1451 |
#~ "prévenu automatiquement de cet incident par un courriel, mais en êtes " |
|
1452 |
#~ "vous sûr ?)." |
|
1453 |
|
|
1454 |
#~ msgid "Page not found" |
|
1455 |
#~ msgstr "Page non trouvée" |
|
1456 |
|
|
1457 |
#~ msgid "" |
|
1458 |
#~ "The requested link does not exist on this site. If you arrived here by " |
|
1459 |
#~ "following a link from an external page, please inform that page's " |
|
1460 |
#~ "maintainer." |
|
1461 |
#~ msgstr "" |
|
1462 |
#~ "La page demandée n'existe pas sur ce site. Si vous êtes arrivé ici en " |
|
1463 |
#~ "suivant un lien depuis un autre site, veuillez informer le propriétaire " |
|
1464 |
#~ "de cette autre page." |
|
1465 |
|
|
1466 |
#~ msgid "Password is too short. It must be at least %d characters." |
|
1467 |
#~ msgstr "" |
|
1468 |
#~ "Le mot de passe est trop court. Il doit contenir au moins %d caractères." |
|
1469 |
|
|
1470 |
#~ msgid "Password is too long. It must be at most %d characters." |
|
1471 |
#~ msgstr "" |
|
1472 |
#~ "Le mot de passe est trop long. Il doit contenir au plus %d caractères." |
|
1473 |
|
|
1474 |
#, fuzzy |
|
1475 |
#~ msgid "Invalid Token" |
|
1476 |
#~ msgstr "date invalide" |
|
1477 |
|
|
1478 |
#~ msgid "Account Creation Confirmed" |
|
1479 |
#~ msgstr "Création du compte confirmée" |
|
1480 |
|
|
1481 |
#~ msgid "Log in" |
|
1482 |
#~ msgstr "S'identifier" |
|
1483 |
|
|
1484 |
#~ msgid "Login" |
|
1485 |
#~ msgstr "S'identifier" |
|
1486 |
|
|
1487 |
#~ msgid "Invalid credentials" |
|
1488 |
#~ msgstr "Identifiant ou mot de passe invalide" |
|
1489 |
|
|
1490 |
#~ msgid "This account is waiting for moderation" |
|
1491 |
#~ msgstr "Ce compte est en attente de modération" |
|
1492 |
|
|
1493 |
#~ msgid "This account is waiting for confirmation" |
|
1494 |
#~ msgstr "Ce compte est en attente de confirmation" |
|
1495 |
|
|
1496 |
#~ msgid "This account has been disabled" |
|
1497 |
#~ msgstr "Ce compte a été désactivé" |
|
1498 |
|
|
1499 |
#~ msgid "Submit Request" |
|
1500 |
#~ msgstr "Valider la requête" |
|
1501 |
|
|
1502 |
#~ msgid "Forgotten password" |
|
1503 |
#~ msgstr "Mot de passe oublié" |
|
1504 |
|
|
1505 |
#~ msgid "There is no user with that name or it has no email contact." |
|
1506 |
#~ msgstr "" |
|
1507 |
#~ "Il n'y a pas d'utilisateur avec ce nom ou cet utilisateur n'a pas " |
|
1508 |
#~ "d'adresse de courriel de contact" |
|
1509 |
|
|
1510 |
#~ msgid "Failed to send email (server error)" |
|
1511 |
#~ msgstr "Échec lors de l'envoi du courriel (erreur du serveur)" |
|
1512 |
|
|
1513 |
#~ msgid "Forgotten Password" |
|
1514 |
#~ msgstr "Mot de passe oublié" |
|
1515 |
|
|
1516 |
#~ msgid "" |
|
1517 |
#~ "The token you submitted does not exist, has expired, or has been " |
|
1518 |
#~ "cancelled." |
|
1519 |
#~ msgstr "" |
|
1520 |
#~ "Le jeton que vous avez entré n'existe pas, a expiré, ou a été annulé" |
|
1521 |
|
|
1522 |
#~ msgid "home page" |
|
1523 |
#~ msgstr "page d'accueil" |
|
1524 |
|
|
1525 |
#~ msgid "The token you submitted is not appropriate for the requested task." |
|
1526 |
#~ msgstr "" |
|
1527 |
#~ "Le jeton que vous avez entré n'est pas approprié pour la tâche demandée" |
|
1528 |
|
|
1529 |
#~ msgid "Request Cancelled" |
|
1530 |
#~ msgstr "Requête annulée" |
|
1531 |
|
|
1532 |
#~ msgid "Your request has been cancelled" |
|
1533 |
#~ msgstr "Votre requête a été annulée" |
|
1534 |
|
|
1535 |
#~ msgid "Continue to <a href=\"/\">home page</a></p>" |
|
1536 |
#~ msgstr "Continuez vers <a href=\"/\">page d'accueil</a></p>" |
|
1537 |
|
|
1538 |
#~ msgid "New password sent by email" |
|
1539 |
#~ msgstr "Un nouveau mot de passe a été envoyé par courriel" |
|
1540 |
|
|
1541 |
#, fuzzy |
|
1542 |
#~ msgid "Password (confirm)" |
|
1543 |
#~ msgstr "Nouveau mot de passe (confirmation)" |
|
1544 |
|
|
1545 |
#~ msgid "Create Account" |
|
1546 |
#~ msgstr "Création un compte" |
|
1547 |
|
|
1548 |
#~ msgid "New Account" |
|
1549 |
#~ msgstr "Nouveau compte" |
|
1550 |
|
|
1551 |
#~ msgid "There is already a user with that username" |
|
1552 |
#~ msgstr "Il y a déjà un utilisateur avec ce nom" |
|
1553 |
|
|
1554 |
#~ msgid "There is already a user with that email address" |
|
1555 |
#~ msgstr "Il y a déjà un utilisateur avec cette adresse de courriel" |
|
1556 |
|
|
1557 |
#~ msgid "" |
|
1558 |
#~ "Accounts are configured to require confirmation but accounts can be " |
|
1559 |
#~ "created without emails" |
|
1560 |
#~ msgstr "" |
|
1561 |
#~ "Les comptes sont configurés pour nécessiter une confirmation mais les " |
|
1562 |
#~ "comptes peuvent être crées sans courriel" |
|
1563 |
|
|
1564 |
#, fuzzy |
|
1565 |
#~ msgid "" |
|
1566 |
#~ "Accounts are configured to have a generated password but accounts can be " |
|
1567 |
#~ "created without emails" |
|
1568 |
#~ msgstr "" |
|
1569 |
#~ "Les comptes sont configurés pour nécessiter une confirmation mais les " |
|
1570 |
#~ "comptes peuvent être crées sans courriel" |
|
1571 |
|
|
1572 |
#~ msgid "Account created, waiting for moderation" |
|
1573 |
#~ msgstr "Compte créé, en attente de modération" |
|
1574 |
|
|
1575 |
#~ msgid "A site administrator will now review then activate your account." |
|
1576 |
#~ msgstr "" |
|
1577 |
#~ "Un administrateur du site va maintenant vérifier puis activer votre compte" |
|
1578 |
|
|
1579 |
#~ msgid "You will then get your password by email." |
|
1580 |
#~ msgstr "Votre mot de passe vous sera ensuite envoyé par courriel" |
|
1581 |
|
|
1582 |
#~ msgid "Back to home page" |
|
1583 |
#~ msgstr "Retour à la page d'accueil" |
|
1584 |
|
|
1585 |
#~ msgid "Email sent" |
|
1586 |
#~ msgstr "Courriel envoyé" |
|
1587 |
|
|
1588 |
#~ msgid "Username / Password" |
|
1589 |
#~ msgstr "Identifiant / Mot de passe" |
|
1590 |
|
|
1591 |
#~ msgid "Configure username/password identification method" |
|
1592 |
#~ msgstr "Configurer la méthode d'identification par identifiant/mot de passe" |
|
1593 |
|
|
1594 |
#~ msgid "Identities" |
|
1595 |
#~ msgstr "Identités" |
|
1596 |
|
|
1597 |
#~ msgid "Configure identities creation" |
|
1598 |
#~ msgstr "Configurer la création des identités" |
|
1599 |
|
|
1600 |
#~ msgid "Passwords" |
|
1601 |
#~ msgstr "Mots de passe" |
|
1602 |
|
|
1603 |
#~ msgid "Configure all password things" |
|
1604 |
#~ msgstr "Configurer les paramètres relatifs aux mots de passe" |
|
1605 |
|
|
1606 |
#~ msgid "Bulk Import" |
|
1607 |
#~ msgstr "Import de masse" |
|
1608 |
|
|
1609 |
#~ msgid "Import accounts from a CSV file" |
|
1610 |
#~ msgstr "Comptes importer depuis un fichier CSV" |
|
1611 |
|
|
1612 |
#~ msgid "Users can change their password" |
|
1613 |
#~ msgstr "Les utilisateurs peuvent changer leur mot de passe" |
|
1614 |
|
|
1615 |
#~ msgid "Generate initial password" |
|
1616 |
#~ msgstr "Générer le mot de passe initial" |
|
1617 |
|
|
1618 |
#~ msgid "Lost Password Behaviour" |
|
1619 |
#~ msgstr "Comportement en cas de perte de mot de passe" |
|
1620 |
|
|
1621 |
#~ msgid "Nothing (contact admin)" |
|
1622 |
#~ msgstr "Rien (contactez l'administrateur)" |
|
1623 |
|
|
1624 |
#~ msgid "Email reminder" |
|
1625 |
#~ msgstr "Rappel par courriel" |
|
1626 |
|
|
1627 |
#~ msgid "Question selected by user" |
|
1628 |
#~ msgstr "Question selectionnée par l'utilisateur" |
|
1629 |
|
|
1630 |
#~ msgid "Minimum password length" |
|
1631 |
#~ msgstr "Taille minimum des mots de passe" |
|
1632 |
|
|
1633 |
#~ msgid "Maximum password length" |
|
1634 |
#~ msgstr "Taille maximum des mots de passe" |
|
1635 |
|
|
1636 |
#~ msgid "0 for unlimited length" |
|
1637 |
#~ msgstr "0 pour une taille illimitée" |
|
1638 |
|
|
1639 |
#~ msgid "Email address (for questions...)" |
|
1640 |
#~ msgstr "Addresse de courriel (pour des questions ...)" |
|
1641 |
|
|
1642 |
#~ msgid "None" |
|
1643 |
#~ msgstr "Aucun" |
|
1644 |
|
|
1645 |
#~ msgid "Password Hashing Algorithm" |
|
1646 |
#~ msgstr "Algorithm de hachage de mots de passe" |
|
1647 |
|
|
1648 |
#~ msgid "Identity Creation" |
|
1649 |
#~ msgstr "Création d'identité" |
|
1650 |
|
|
1651 |
#~ msgid "Site Administrator" |
|
1652 |
#~ msgstr "Administrateur du site" |
|
1653 |
|
|
1654 |
#~ msgid "Self-registration" |
|
1655 |
#~ msgstr "Inscription par l'utilisateur" |
|
1656 |
|
|
1657 |
#~ msgid "Moderated user registration" |
|
1658 |
#~ msgstr "Inscription par l'utilisateur avec modération" |
|
1659 |
|
|
1660 |
#~ msgid "Require email confirmation for new accounts" |
|
1661 |
#~ msgstr "Demander une confirmation par courriel pour les nouveaux comptes" |
|
1662 |
|
|
1663 |
#~ msgid "Notify Administrators on Registration" |
|
1664 |
#~ msgstr "Notifier les administrateurs lors d'inscriptions" |
|
1665 |
|
|
1666 |
#~ msgid "Use email as username" |
|
1667 |
#~ msgstr "Utiliser le courriel comme identifiant" |
|
1668 |
|
|
1669 |
#~ msgid "Warn about unused account after so many days" |
|
1670 |
#~ msgstr "Avertir lorsque des comptes sont inutilisés depuis plusieurs jours" |
|
1671 |
|
|
1672 |
#~ msgid "0 for no warning" |
|
1673 |
#~ msgstr "0 pour aucun avertissement" |
|
1674 |
|
|
1675 |
#~ msgid "Removed unused account after so many days" |
|
1676 |
#~ msgstr "Compte inutilisés qui ont été supprimés après plusieurs jours" |
|
1677 |
|
|
1678 |
#~ msgid "0 for no automatic removal" |
|
1679 |
#~ msgstr "0 pour désactiver la suppression automatique" |
|
1680 |
|
|
1681 |
#~ msgid "Identities Interface" |
|
1682 |
#~ msgstr "Interface des identités" |
|
1683 |
|
|
1684 |
#~ msgid "File" |
|
1685 |
#~ msgstr "Fichier" |
|
1686 |
|
|
1687 |
#, fuzzy |
|
1688 |
#~ msgid "Send notifications to users" |
|
1689 |
#~ msgstr "Jeton d'identification" |
|
1690 |
|
|
1691 |
#, fuzzy |
|
1692 |
#~ msgid "Add Role" |
|
1693 |
#~ msgstr "Ajouter un élément" |
|
1694 |
|
|
1695 |
#~ msgid "The CSV file must strictly adhere to the following structure:" |
|
1696 |
#~ msgstr "Le fichier CSV doit correspondre à la structure suivante :" |
|
1697 |
|
|
1698 |
#~ msgid "Charset: %s" |
|
1699 |
#~ msgstr "Encodage: %s" |
|
1700 |
|
|
1701 |
#~ msgid "Column Separator: ;" |
|
1702 |
#~ msgstr "Séparateur de colonne: ;" |
|
1703 |
|
|
1704 |
#~ msgid "Columns:" |
|
1705 |
#~ msgstr "Colonnes :" |
|
1706 |
|
|
1707 |
#, fuzzy |
|
1708 |
#~ msgid "(empty to get an automatically generated password)" |
|
1709 |
#~ msgstr "Nouveau mot de passe généré" |
|
1710 |
|
|
1711 |
#~ msgid "Incorrect number of columns (line: %s)" |
|
1712 |
#~ msgstr "Numéro de colonne incorrect (ligne : %s)" |
|
1713 |
|
|
1714 |
#~ msgid "Duplicate username (line: %s)" |
|
1715 |
#~ msgstr "Nom d'utilisateur dupliqué (ligne: %s)" |
|
1716 |
|
|
1717 |
#~ msgid "Number of accounts created: %s" |
|
1718 |
#~ msgstr "Nombre de compte créé : %s" |
|
1719 |
|
|
1720 |
#, fuzzy |
|
1721 |
#~ msgid "Sending subscription emails" |
|
1722 |
#~ msgstr "Configuration de souscription" |
|
1723 |
|
|
1724 |
#, fuzzy |
|
1725 |
#~ msgid "Notifications" |
|
1726 |
#~ msgstr "Jeton d'identification" |
|
1727 |
|
|
1728 |
#~ msgid "Awaiting Confirmation" |
|
1729 |
#~ msgstr "En attente de confirmation" |
|
1730 |
|
|
1731 |
#~ msgid "Awaiting Moderation" |
|
1732 |
#~ msgstr "En attente de modération" |
|
1733 |
|
|
1734 |
#~ msgid "Disabled Account" |
|
1735 |
#~ msgstr "Nouvel hôte" |
|
1736 |
|
|
1737 |
#~ msgid "Username / password" |
|
1738 |
#~ msgstr "Identifiant / mot de passe" |
|
1739 |
|
|
1740 |
#~ msgid "Duplicate user name" |
|
1741 |
#~ msgstr "Nom d'utilisateur en double" |
|
1742 |
|
|
1743 |
#~ msgid "Accounts" |
|
1744 |
#~ msgstr "Comptes" |
|
1745 |
|
|
1746 |
#~ msgid "Account - %s" |
|
1747 |
#~ msgstr "Compte - %s" |
|
1748 |
|
|
1749 |
#~ msgid "Moderation of account" |
|
1750 |
#~ msgstr "Modération de compte" |
|
1751 |
|
|
1752 |
#~ msgid "Reply by email" |
|
1753 |
#~ msgstr "Répondre par courriel" |
|
1754 |
|
|
1755 |
#~ msgid "Accept" |
|
1756 |
#~ msgstr "Accepter" |
|
1757 |
|
|
1758 |
#~ msgid "Reject" |
|
1759 |
#~ msgstr "Rejeter" |
|
1760 |
|
|
1761 |
#~ msgid "To" |
|
1762 |
#~ msgstr "À" |
|
1763 |
|
|
1764 |
#~ msgid "Subject" |
|
1765 |
#~ msgstr "Sujet" |
|
1766 |
|
|
1767 |
#~ msgid "Message" |
|
1768 |
#~ msgstr "Message" |
|
1769 |
|
|
1770 |
#~ msgid "Submit and don't send email" |
|
1771 |
#~ msgstr "Valider et ne pas envoyer de courriel" |
|
1772 |
|
|
1773 |
#~ msgid "Rejection" |
|
1774 |
#~ msgstr "Rejet" |
|
1775 |
|
|
1776 |
#~ msgid "About your account request" |
|
1777 |
#~ msgstr "À propos de votre demande de compte" |
|
1778 |
|
|
1779 |
#~ msgid "You are not allowed to access Accounts Management" |
|
1780 |
#~ msgstr "Vous n'êtes pas autorisé à accéder à la gestion des comptes" |
|
1781 |
|
|
1782 |
#~ msgid "Accounts Management" |
|
1783 |
#~ msgstr "Gestion des comptes" |
|
1784 |
|
|
1785 |
#~ msgid "New accounts waiting for moderation" |
|
1786 |
#~ msgstr "De nouveaux comptes sont en attente de modération" |
|
1787 |
|
|
1788 |
#~ msgid "Username:" |
|
1789 |
#~ msgstr "Identifiant :" |
|
1790 |
|
|
1791 |
#~ msgid "Subscription notification for password account" |
|
1792 |
#~ msgstr "Notification d'inscription pour un compte à mot de passe" |
|
1793 |
|
|
1794 |
#~ msgid "" |
|
1795 |
#~ "Available variables: email, website, token_url, admin_email, username, " |
|
1796 |
#~ "password" |
|
1797 |
#~ msgstr "" |
|
1798 |
#~ "Variables disponibles : email, website, token_url, admin_email, username, " |
|
1799 |
#~ "password" |
|
1800 |
|
|
1801 |
#, fuzzy |
|
1802 |
#~ msgid "Identification" |
|
1803 |
#~ msgstr "Jeton d'identification" |
|
1804 |
|
|
1805 |
#~ msgid "Subscription Confirmation" |
|
1806 |
#~ msgstr "Configuration de souscription" |
|
1807 |
|
|
1808 |
#~ msgid "" |
|
1809 |
#~ "We have received a request for subscription of your email address,\n" |
|
1810 |
#~ "\"[email]\", to the [website] web site.\n" |
|
1811 |
#~ "\n" |
|
1812 |
#~ "To confirm that you want to be subscribed to the web site, simply\n" |
|
1813 |
#~ "visit this web page:\n" |
|
1814 |
#~ "\n" |
|
1815 |
#~ "[token_url]\n" |
|
1816 |
#~ "\n" |
|
1817 |
#~ "If you do not wish to be subscribed to the web site, pleasy simply\n" |
|
1818 |
#~ "disregard this message. If you think you are being maliciously\n" |
|
1819 |
#~ "subscribed to the web site, or have any other questions, send them\n" |
|
1820 |
#~ "to [admin_email].\n" |
|
1821 |
#~ msgstr "" |
|
1822 |
#~ "Nous avons reçu une demande d'inscription provenant de votre adresse\n" |
|
1823 |
#~ "de courriel,\"[email]\", pour le site internet [website].\n" |
|
1824 |
#~ "\n" |
|
1825 |
#~ "Pour confirmer votre inscription à ce site, visitez simplement cette\n" |
|
1826 |
#~ "page :\n" |
|
1827 |
#~ "\n" |
|
1828 |
#~ "[token_url]\n" |
|
1829 |
#~ "\n" |
|
1830 |
#~ "Si vous ne souhaitez pas être inscrit au site internet, ignorez ce\n" |
|
1831 |
#~ "message. Si vous pensez que vous avez été inscrit à votre insu, ou\n" |
|
1832 |
#~ "avez toute autre question à nous poser, envoyer nous un courriel\n" |
|
1833 |
#~ "à [admin_email].\n" |
|
1834 |
|
|
1835 |
#~ msgid "Request for password change" |
|
1836 |
#~ msgstr "Demande de changement de mot de passe" |
|
1837 |
|
|
1838 |
#~ msgid "Available variables: change_url, cancel_url, time" |
|
1839 |
#~ msgstr "Variables disponibles : change_url, cancel_url, time" |
|
1840 |
|
|
1841 |
#~ msgid "Change Password Request" |
|
1842 |
#~ msgstr "Requête de changement de mot de passe" |
|
1843 |
|
|
1844 |
#~ msgid "" |
|
1845 |
#~ "You have (or someone impersonating you has) requested to change your\n" |
|
1846 |
#~ "password. To complete the change, visit the following link:\n" |
|
1847 |
#~ "\n" |
|
1848 |
#~ "[change_url]\n" |
|
1849 |
#~ "\n" |
|
1850 |
#~ "If you are not the person who made this request, or you wish to cancel\n" |
|
1851 |
#~ "this request, visit the following link:\n" |
|
1852 |
#~ "\n" |
|
1853 |
#~ "[cancel_url]\n" |
|
1854 |
#~ "\n" |
|
1855 |
#~ "If you do nothing, the request will lapse after 3 days (precisely on\n" |
|
1856 |
#~ "[time]).\n" |
|
1857 |
#~ msgstr "" |
|
1858 |
#~ "Vous avez (ou quelqu'un se faisant passer pour vous) demandé à changer " |
|
1859 |
#~ "de\n" |
|
1860 |
#~ "mot de passe. Pour accomplir ce changement, visitez cette page :\n" |
|
1861 |
#~ "\n" |
|
1862 |
#~ "[change_url]\n" |
|
1863 |
#~ "\n" |
|
1864 |
#~ "Si vous n'êtes pas la personne qui a fait cette requête, ou si vous " |
|
1865 |
#~ "voulez\n" |
|
1866 |
#~ "l'annuler, allez sur la page suivante :\n" |
|
1867 |
#~ "\n" |
|
1868 |
#~ "[cancel_url]\n" |
|
1869 |
#~ "\n" |
|
1870 |
#~ "Si vous ne faites rien, la demande expirera automatiquement dans 3 " |
|
1871 |
#~ "jours,\n" |
|
1872 |
#~ "précisement le [time]).\n" |
|
1873 |
|
|
1874 |
#~ msgid "New generated password" |
|
1875 |
#~ msgstr "Nouveau mot de passe généré" |
|
1876 |
|
|
1877 |
#~ msgid "Available variable: password" |
|
1878 |
#~ msgstr "Variables disponibles : password" |
|
1879 |
|
|
1880 |
#~ msgid "Your new password" |
|
1881 |
#~ msgstr "Votre nouveau mot de passe" |
|
1882 |
|
|
1883 |
#~ msgid "Your new password: [password]\n" |
|
1884 |
#~ msgstr "Votre nouveau mot de passe : [password]\n" |
|
1885 |
|
|
1886 |
#~ msgid "Approval of new account" |
|
1887 |
#~ msgstr "Acceptation du nouveau compte" |
|
1888 |
|
|
1889 |
#~ msgid "Available variables: username, password" |
|
1890 |
#~ msgstr "Variables disponibles : username, password" |
|
1891 |
|
|
1892 |
#~ msgid "Your account has been approved" |
|
1893 |
#~ msgstr "Votre compte a été validé" |
|
1894 |
|
|
1895 |
#~ msgid "" |
|
1896 |
#~ "Your account has been approved.\n" |
|
1897 |
#~ "\n" |
|
1898 |
#~ "Account details:\n" |
|
1899 |
#~ "\n" |
|
1900 |
#~ "- username: [username]\n" |
|
1901 |
#~ "[if-any password]- password: [password][end]\n" |
|
1902 |
#~ msgstr "" |
|
1903 |
#~ "Votre compte a été validé.\n" |
|
1904 |
#~ "\n" |
|
1905 |
#~ "Détails du compte :\n" |
|
1906 |
#~ "\n" |
|
1907 |
#~ "- identifiant: [username]\n" |
|
1908 |
#~ "[if-any password]- mot de passe: [password][end]\n" |
|
1909 |
|
|
1910 |
#~ msgid "Warning about unusued account" |
|
1911 |
#~ msgstr "Avertissement pour les comptes inutilisés" |
|
1912 |
|
|
1913 |
#~ msgid "Available variables: username" |
|
1914 |
#~ msgstr "Variables disponibles : username" |
|
1915 |
|
|
1916 |
#~ msgid "Your account is unused" |
|
1917 |
#~ msgstr "Votre compte est inutilisé" |
|
1918 |
|
|
1919 |
#~ msgid "Your account ([username]) is not being used.\n" |
|
1920 |
#~ msgstr "Votre compte ([username]) n'est pas utilisé.\n" |
|
1921 |
|
|
1922 |
#~ msgid "Notification of removal of unused account" |
|
1923 |
#~ msgstr "Notification de suppression de compte inutilisé" |
|
1924 |
|
|
1925 |
#~ msgid "Your account has been removed" |
|
1926 |
#~ msgstr "Votre compte a été supprimé" |
|
1927 |
|
|
1928 |
#~ msgid "" |
|
1929 |
#~ "Your account ([username]) was not being used, it has therefore been " |
|
1930 |
#~ "removed.\n" |
|
1931 |
#~ msgstr "" |
|
1932 |
#~ "Votre compte ([username]) n'était plus utilisé et a donc été supprimé.\n" |
|
1933 |
|
|
1934 |
#~ msgid "Notification of new registration to administrators" |
|
1935 |
#~ msgstr "Notification des nouvelles inscriptions aux administrateurs" |
|
1936 |
|
|
1937 |
#~ msgid "Available variables: hostname, email_as_username, username" |
|
1938 |
#~ msgstr "Variables disponibles : hostname, email_as_username, username" |
|
1939 |
|
|
1940 |
#~ msgid "New Registration" |
|
1941 |
#~ msgstr "Nouvelle inscription" |
|
1942 |
|
|
1943 |
#~ msgid "" |
|
1944 |
#~ "Hello,\n" |
|
1945 |
#~ "\n" |
|
1946 |
#~ "A new account has been created on [hostname].\n" |
|
1947 |
#~ "\n" |
|
1948 |
#~ " - name: [name]\n" |
|
1949 |
#~ " - username: [username]\n" |
|
1950 |
#~ msgstr "" |
|
1951 |
#~ "Bonjour,\n" |
|
1952 |
#~ "\n" |
|
1953 |
#~ "Un nouveau compte a été créé sur [hostname].\n" |
|
1954 |
#~ "\n" |
|
1955 |
#~ " - nom : [name]\n" |
|
1956 |
#~ " - identifiant : [username]\n" |
|
1957 |
|
|
1958 |
#, fuzzy |
|
1959 |
#~ msgid "Welcome email, with generated password" |
|
1960 |
#~ msgstr "Nouveau mot de passe généré" |
|
1961 |
|
|
1962 |
#, fuzzy |
|
1963 |
#~ msgid "Available variables: hostname, username, password, email_as_username" |
|
1964 |
#~ msgstr "Variables disponibles : hostname, email_as_username, username" |
|
1965 |
|
|
1966 |
#, fuzzy |
|
1967 |
#~ msgid "" |
|
1968 |
#~ "Welcome to [hostname],\n" |
|
1969 |
#~ "\n" |
|
1970 |
#~ "Your password is: [password]\n" |
|
1971 |
#~ msgstr "Votre nouveau mot de passe : [password]\n" |
|
1972 |
|
|
1973 |
#~ msgid "Text when account confirmed by user but waiting moderator approval" |
|
1974 |
#~ msgstr "" |
|
1975 |
#~ "Texte quand le compte a été confirmé par l'utilisateur mais en attente de " |
|
1976 |
#~ "validation d'un modérateur" |
|
1977 |
|
|
1978 |
#~ msgid "" |
|
1979 |
#~ "<p>\n" |
|
1980 |
#~ "Your account has been created. In order to be effective\n" |
|
1981 |
#~ "it must be activated by a moderator. You will receive an\n" |
|
1982 |
#~ "email when this is done.\n" |
|
1983 |
#~ "</p>" |
|
1984 |
#~ msgstr "" |
|
1985 |
#~ "<p>\n" |
|
1986 |
#~ "Votre compte a été créé. Afin d'être utilisable,\n" |
|
1987 |
#~ "il doit être activé par un modérateur. Vous recevrez un\n" |
|
1988 |
#~ "courriel quand ce sera fait.\n" |
|
1989 |
#~ "</p>" |
|
1990 |
|
|
1991 |
#~ msgid "Text when account confirmed by user" |
|
1992 |
#~ msgstr "Texte quand le compte a été confirmé par l'utilisateur" |
|
1993 |
|
|
1994 |
#~ msgid "" |
|
1995 |
#~ "<p>\n" |
|
1996 |
#~ "Your account has been created.\n" |
|
1997 |
#~ "</p>" |
|
1998 |
#~ msgstr "" |
|
1999 |
#~ "<p>\n" |
|
2000 |
#~ "Votre compte a été créé.\n" |
|
2001 |
#~ "</p>" |
|
2002 |
|
|
2003 |
#~ msgid "Text when an email with a change password token has been sent" |
|
2004 |
#~ msgstr "" |
|
2005 |
#~ "Texte quand un courriel avec un jeton de changement de mot de passe a été " |
|
2006 |
#~ "envoyé" |
|
2007 |
|
|
2008 |
#~ msgid "" |
|
2009 |
#~ "<p>\n" |
|
2010 |
#~ "A token for changing your password has been emailed to you. Follow the " |
|
2011 |
#~ "instructions in that email to change your password.\n" |
|
2012 |
#~ "</p>\n" |
|
2013 |
#~ "<p>\n" |
|
2014 |
#~ " <a href=\"login\">Log In</a>\n" |
|
2015 |
#~ "</p>" |
|
2016 |
#~ msgstr "" |
|
2017 |
#~ "<p>\n" |
|
2018 |
#~ "Un jeton de changement de mot de passe vous a été envoyé par courriel. " |
|
2019 |
#~ "Suivez les instructions dans celui-ci pour changer votre mot de passe.\n" |
|
2020 |
#~ "</p>\n" |
|
2021 |
#~ "<p>\n" |
|
2022 |
#~ " <a href=\"login\">S'identifier</a>\n" |
|
2023 |
#~ "</p>" |
|
2024 |
|
|
2025 |
#~ msgid "Text when new password has been sent" |
|
2026 |
#~ msgstr "Texte quand un nouveau mot de passe a été envoyé" |
|
2027 |
|
|
2028 |
#~ msgid "" |
|
2029 |
#~ "<p>\n" |
|
2030 |
#~ "Your new password has been sent to you by email.\n" |
|
2031 |
#~ "</p>\n" |
|
2032 |
#~ "<p>\n" |
|
2033 |
#~ " <a href=\"login\">Login</a>\n" |
|
2034 |
#~ "</p>" |
|
2035 |
#~ msgstr "" |
|
2036 |
#~ "<p>\n" |
|
2037 |
#~ "Votre nouveau mot de passe vous a été envoyé par courriel.\n" |
|
2038 |
#~ "</p>\n" |
|
2039 |
#~ "<p>\n" |
|
2040 |
#~ " <a href=\"login\">S'identifier</a>\n" |
|
2041 |
#~ "</p>" |
|
2042 |
|
|
2043 |
#~ msgid "Text on top of registration form" |
|
2044 |
#~ msgstr "Texte en haut du formulaire d'enregistrement" |
|
2045 |
|
|
2046 |
#~ msgid "Text on forgotten password request page" |
|
2047 |
#~ msgstr "Texte sur la page de demande de mot de passe oublié" |
|
2048 |
|
|
2049 |
#~ msgid "" |
|
2050 |
#~ "<p>\n" |
|
2051 |
#~ "If you have an account, but have forgotten your password, enter your user " |
|
2052 |
#~ "name\n" |
|
2053 |
#~ "below and submit a request to change your password.\n" |
|
2054 |
#~ "</p>" |
|
2055 |
#~ msgstr "" |
|
2056 |
#~ "<p>\n" |
|
2057 |
#~ "Si vous avez un compte, mais avez oublié votre mot de passe, entrez votre " |
|
2058 |
#~ "nom d'utilisateur\n" |
|
2059 |
#~ "ci-dessous et validez la requête de changement de mot de passe.\n" |
|
2060 |
#~ "</p>" |
|
2061 |
|
|
2062 |
#~ msgid "Text linking the login page to the account creation page" |
|
2063 |
#~ msgstr "Texte liant la page de connexion à la page de création de compte" |
|
2064 |
|
|
2065 |
#~ msgid "Available variable: register_url" |
|
2066 |
#~ msgstr "Variables disponibles: register_url" |
|
2067 |
|
|
2068 |
#~ msgid "" |
|
2069 |
#~ "<p>\n" |
|
2070 |
#~ "If you do not have an account, you should go to the <a href=" |
|
2071 |
#~ "\"[register_url]\">\n" |
|
2072 |
#~ "New Account page</a>.\n" |
|
2073 |
#~ "</p>" |
|
2074 |
#~ msgstr "" |
|
2075 |
#~ "<p>\n" |
|
2076 |
#~ "Si vous n'avez pas de compte, vous devez aller à la page de <a href=" |
|
2077 |
#~ "\"[register_url]\">\n" |
|
2078 |
#~ "Nouveau Compte</a>.\n" |
|
2079 |
#~ "</p>" |
|
2080 |
|
|
2081 |
#, fuzzy |
|
2082 |
#~ msgid "Text when an invalid password token is used" |
|
2083 |
#~ msgstr "" |
|
2084 |
#~ "Texte quand un courriel avec un jeton de changement de mot de passe a été " |
|
2085 |
#~ "envoyé" |
|
2086 |
|
|
2087 |
#, fuzzy |
|
2088 |
#~ msgid "Text on top of the login page" |
|
2089 |
#~ msgstr "Texte en haut de la page de profil" |
|
2090 |
|
|
2091 |
#, fuzzy |
|
2092 |
#~ msgid "" |
|
2093 |
#~ "Text when a mail for confirmation of an account creation has been sent" |
|
2094 |
#~ msgstr "" |
|
2095 |
#~ "Texte quand un courriel avec un jeton de changement de mot de passe a été " |
|
2096 |
#~ "envoyé" |
|
2097 |
|
|
2098 |
#~ msgid "" |
|
2099 |
#~ "An email has been sent to you so you can confirm your account creation." |
|
2100 |
#~ msgstr "" |
|
2101 |
#~ "Un courriel vous a été envoyé afin que vous confirmiez la création de " |
|
2102 |
#~ "votre compte." |
|
2103 |
|
|
2104 |
#~ msgid "Liberty/SAML2" |
|
2105 |
#~ msgstr "Liberty/SAML2" |
|
2106 |
|
|
2107 |
#~ msgid "Select the identity provider you want to use." |
|
2108 |
#~ msgstr "Choisissez le fournisseur d'identités que vous voulez utiliser." |
|
2109 |
|
|
2110 |
#~ msgid "Identity Providers" |
|
2111 |
#~ msgstr "Fournisseurs d'identité" |
|
2112 |
|
|
2113 |
#~ msgid "Create new from remote URL" |
|
2114 |
#~ msgstr "Nouveau créé à partir d'une URL distante" |
|
2115 |
|
|
2116 |
#~ msgid "Broken" |
|
2117 |
#~ msgstr "Cassé" |
|
2118 |
|
|
2119 |
#~ msgid "Client Key and Certificate" |
|
2120 |
#~ msgstr "Clé et certificat du client" |
|
2121 |
|
|
2122 |
#~ msgid "Hide this provider from user lists" |
|
2123 |
#~ msgstr "Cacher ce fournisseur de la liste présentée à l'utilisateur" |
|
2124 |
|
|
2125 |
#~ msgid "URL to metadata" |
|
2126 |
#~ msgstr "URL vers les méta-données" |
|
2127 |
|
|
2128 |
#~ msgid "Resource not found" |
|
2129 |
#~ msgstr "Ressource non trouvée" |
|
2130 |
|
|
2131 |
#~ msgid "HTTP error on retrieval: %s" |
|
2132 |
#~ msgstr "Erreur HTTP à la récupération : %s" |
|
2133 |
|
|
2134 |
#~ msgid "Failed to retrieve file" |
|
2135 |
#~ msgstr "Échec à la récupération du fichier" |
|
2136 |
|
|
2137 |
#~ msgid "URL to public key" |
|
2138 |
#~ msgstr "URL de la clé publique" |
|
2139 |
|
|
2140 |
#~ msgid "Error in this metadata file" |
|
2141 |
#~ msgstr "Fichier de méta-données erroné" |
|
2142 |
|
|
2143 |
#~ msgid "File looks like a bad metadata file" |
|
2144 |
#~ msgstr "Le fichier de méta-données semble invalide" |
|
2145 |
|
|
2146 |
#~ msgid "" |
|
2147 |
#~ "The metadata file does not embed a public key, please provide it here." |
|
2148 |
#~ msgstr "" |
|
2149 |
#~ "Ce fichier de meta-données ne contient pas de clé publique, vous devez " |
|
2150 |
#~ "donc en fournir une ici." |
|
2151 |
|
|
2152 |
#~ msgid "Update from remote URL" |
|
2153 |
#~ msgstr "Mettre à jour à partir de l'URL distante" |
|
2154 |
|
|
2155 |
#~ msgid "Edit Identity Provider" |
|
2156 |
#~ msgstr "Modifier le fournisseur d'identités" |
|
2157 |
|
|
2158 |
#~ msgid "You are about to irrevocably remove this identity provider." |
|
2159 |
#~ msgstr "Vous allez définitivement supprimer ce fournisseur d'identités." |
|
2160 |
|
|
2161 |
#~ msgid "Deleting" |
|
2162 |
#~ msgstr "Suppression" |
|
2163 |
|
|
2164 |
#~ msgid "Deleting Identity Provider" |
|
2165 |
#~ msgstr "Suppression du fournisseur d'identité" |
|
2166 |
|
|
2167 |
#~ msgid "Bad metadata or missing public key" |
|
2168 |
#~ msgstr "Mauvaises méta-données ou clé publique manquante" |
|
2169 |
|
|
2170 |
#~ msgid "Configure Liberty/SAML identification method" |
|
2171 |
#~ msgstr "Configurer la méthode d'identification Liberty/SAML" |
|
2172 |
|
|
2173 |
#~ msgid "Configure Liberty / SAML 2.0 parameters" |
|
2174 |
#~ msgstr "Configurer les paramètres Liberty / SAML 2.0" |
|
2175 |
|
|
2176 |
#~ msgid "Configure Liberty parameters" |
|
2177 |
#~ msgstr "Configurer les paramètres Liberty" |
|
2178 |
|
|
2179 |
#~ msgid "ID-FF 1.2 Service Provider Metadata" |
|
2180 |
#~ msgstr "Méta-données ID-FF 1.2 du fournisseur de service" |
|
2181 |
|
|
2182 |
#~ msgid "Download Service Provider ID-FF 1.2 Metadata file" |
|
2183 |
#~ msgstr "" |
|
2184 |
#~ "Télécharger le fichier des méta-données ID-FF 1.2 du fournisseur de " |
|
2185 |
#~ "service" |
|
2186 |
|
|
2187 |
#~ msgid "SAML 2.0 Service Provider Metadata" |
|
2188 |
#~ msgstr "Méta-données du fournisseur de service SAML 2.0" |
|
2189 |
|
|
2190 |
#~ msgid "Download Service Provider SAML 2.0 Metadata file" |
|
2191 |
#~ msgstr "" |
|
2192 |
#~ "Télécharger le fichier des méta-données SAML 2.0 du fournisseur de service" |
|
2193 |
|
|
2194 |
#~ msgid "Add and remove identity providers" |
|
2195 |
#~ msgstr "Ajouter et supprimer des fournisseurs d'identités" |
|
2196 |
|
|
2197 |
#~ msgid "Liberty Provider ID" |
|
2198 |
#~ msgstr "Identifiant du fournisseur Liberty (Provider ID)" |
|
2199 |
|
|
2200 |
#~ msgid "Liberty Base URL" |
|
2201 |
#~ msgstr "URL de la racine Liberty" |
|
2202 |
|
|
2203 |
#~ msgid "SAML 2.0 Provider ID" |
|
2204 |
#~ msgstr "Identifiant du fournisseur SAML 2.0 (Provider ID)" |
|
2205 |
|
|
2206 |
#~ msgid "SAML 2.0 Base URL" |
|
2207 |
#~ msgstr "URL de la racine SAML 2.0" |
|
2208 |
|
|
2209 |
#~ msgid "Provider ID" |
|
2210 |
#~ msgstr "Identifiant du fournisseur (Provider ID)" |
|
2211 |
|
|
2212 |
#~ msgid "Base URL" |
|
2213 |
#~ msgstr "URL de la racine" |
|
2214 |
|
|
2215 |
#~ msgid "Signing Private Key" |
|
2216 |
#~ msgstr "Clé privée de signature" |
|
2217 |
|
|
2218 |
#~ msgid "Signing Public Key" |
|
2219 |
#~ msgstr "Clé publique de signature" |
|
2220 |
|
|
2221 |
#~ msgid "Encryption Private Key" |
|
2222 |
#~ msgstr "Clé privée de chiffrement" |
|
2223 |
|
|
2224 |
#~ msgid "Encryption Public Key" |
|
2225 |
#~ msgstr "Clé publique de chiffrement" |
|
2226 |
|
|
2227 |
#~ msgid "Identity Provider Introduction, Common Domain" |
|
2228 |
#~ msgstr "Domaine commun, pour 'Identity Provider Introduction'" |
|
2229 |
|
|
2230 |
#~ msgid "Disabled if empty" |
|
2231 |
#~ msgstr "Désactivé si vide" |
|
2232 |
|
|
2233 |
#~ msgid "Identity Provider Introduction, URL of Cookie Getter" |
|
2234 |
#~ msgstr "Identity Provider Introduction, URL de récupération" |
|
2235 |
|
|
2236 |
#, fuzzy |
|
2237 |
#~ msgid "Sign authentication request" |
|
2238 |
#~ msgstr "Modifier la requête d'authentification" |
|
2239 |
|
|
2240 |
#~ msgid "Grab user details with ID-WSF on first logon" |
|
2241 |
#~ msgstr "" |
|
2242 |
#~ "Récupérer les détails de l'utilisateur avec ID-WSF à la première connexion" |
|
2243 |
|
|
2244 |
#~ msgid "Lasso version is too old for this support." |
|
2245 |
#~ msgstr "La version de Lasso est trop vieille pour ce support" |
|
2246 |
|
|
2247 |
#~ msgid "Liberty/SAML2 identity provider" |
|
2248 |
#~ msgstr "Fournisseur d'identité Liberty Alliance/SAML2" |
|
2249 |
|
|
2250 |
#~ msgid "This feature is not yet implemented." |
|
2251 |
#~ msgstr "Cette fonctionnalité n'a pas encore été implémentée." |
|
2252 |
|
|
2253 |
#~ msgid "Sorry" |
|
2254 |
#~ msgstr "Désolé" |
|
2255 |
|
|
2256 |
#~ msgid "" |
|
2257 |
#~ "The server encountered an internal error and was unable to complete your " |
|
2258 |
#~ "request." |
|
2259 |
#~ msgstr "" |
|
2260 |
#~ "Une erreur s'est produite sur le serveur; votre requête n'a ainsi pas pu " |
|
2261 |
#~ "complètement être traîtée." |
|
2262 |
|
|
2263 |
#~ msgid "Internal Server Error" |
|
2264 |
#~ msgstr "Erreur interne du serveur" |
|
2265 |
|
|
2266 |
#~ msgid "Bad log file: %s" |
|
2267 |
#~ msgstr "Mauvais fichier journal : %s" |
|
2268 |
|
|
2269 |
#~ msgid "Nothing to show" |
|
2270 |
#~ msgstr "Rien à afficher" |
|
2271 |
|
|
2272 |
#~ msgid "Download Raw Log File" |
|
2273 |
#~ msgstr "Télécharger le fichier journal" |
|
2274 |
|
|
2275 |
#~ msgid "Time" |
|
2276 |
#~ msgstr "Horodatage" |
|
2277 |
|
|
2278 |
#~ msgid "Anonymous" |
|
2279 |
#~ msgstr "Anonyme" |
|
2280 |
|
|
2281 |
#~ msgid "Unlogged" |
|
2282 |
#~ msgstr "Non authentifié" |
|
2283 |
|
|
2284 |
#~ msgid "Unknown" |
|
2285 |
#~ msgstr "Inconnu" |
|
2286 |
|
|
2287 |
#~ msgid "Select another logfile:" |
|
2288 |
#~ msgstr "Choisir un autre fichier journal :" |
|
2289 |
|
|
2290 |
#~ msgid "Since: %s" |
|
2291 |
#~ msgstr "Depuis: %s" |
|
2292 |
|
|
2293 |
#~ msgid "Texts" |
|
2294 |
#~ msgstr "Textes" |
|
2295 |
|
|
2296 |
#, fuzzy |
|
2297 |
#~ msgid "Custom Texts" |
|
2298 |
#~ msgstr "Texte personnalisé :" |
|
2299 |
|
|
2300 |
#~ msgid "Restore default text" |
|
2301 |
#~ msgstr "Restaurer le texte par défaut" |
|
2302 |
|
|
2303 |
#~ msgid "Invalid template" |
|
2304 |
#~ msgstr "Squelette invalide" |
|
2305 |
|
|
2306 |
#~ msgid "Text" |
|
2307 |
#~ msgstr "Texte" |
|
2308 |
|
|
2309 |
#~ msgid "System Default" |
|
2310 |
#~ msgstr "Valeur du système" |
|
2311 |
|
|
2312 |
#~ msgid "English" |
|
2313 |
#~ msgstr "Anglais" |
|
2314 |
|
|
2315 |
#~ msgid "French" |
|
2316 |
#~ msgstr "Français" |
|
2317 |
|
|
2318 |
#~ msgid "Use a web proxy" |
|
2319 |
#~ msgstr "Utiliser un mandataire (proxy) web" |
|
2320 |
|
|
2321 |
#~ msgid "Proxy IP address or domain name" |
|
2322 |
#~ msgstr "Adresse IP or nom de domaine du mandataire" |
|
2323 |
|
|
2324 |
#~ msgid "Proxy port" |
|
2325 |
#~ msgstr "Port du mandataire (proxy)" |
|
2326 |
|
|
2327 |
#~ msgid "User name" |
|
2328 |
#~ msgstr "Identifiant" |
|
2329 |
|
|
2330 |
#~ msgid "User password" |
|
2331 |
#~ msgstr "Mot de passe" |
|
2332 |
|
|
2333 |
#~ msgid "Email for Tracebacks" |
|
2334 |
#~ msgstr "Courriel pour les exceptions" |
|
2335 |
|
|
2336 |
#~ msgid "Display Exceptions" |
|
2337 |
#~ msgstr "Afficher les exceptions" |
|
2338 |
|
|
2339 |
#~ msgid "No display" |
|
2340 |
#~ msgstr "Aucun affichage" |
|
2341 |
|
|
2342 |
#~ msgid "Display as Text" |
|
2343 |
#~ msgstr "Afficher sous forme de texte" |
|
2344 |
|
|
2345 |
#~ msgid "Display as Text in an HTML error page" |
|
2346 |
#~ msgstr "Afficher sous forme de texte dans une page d'erreur HTML" |
|
2347 |
|
|
2348 |
#~ msgid "Display as HTML" |
|
2349 |
#~ msgstr "Afficher sous de forme de HTML" |
|
2350 |
|
|
2351 |
#~ msgid "Logger" |
|
2352 |
#~ msgstr "Journalisation" |
|
2353 |
|
|
2354 |
#~ msgid "Enable debug mode" |
|
2355 |
#~ msgstr "Activer le mode de débogage" |
|
2356 |
|
|
2357 |
#, fuzzy |
|
2358 |
#~ msgid "Certificate %s" |
|
2359 |
#~ msgstr "Certificats" |
|
2360 |
|
|
2361 |
#~ msgid "You are about to delete this certificate." |
|
2362 |
#~ msgstr "Vous allez définitivement supprimer ce certificat." |
|
2363 |
|
|
2364 |
#~ msgid "certificates" |
|
2365 |
#~ msgstr "certificats" |
|
2366 |
|
|
2367 |
#~ msgid "Certificates" |
|
2368 |
#~ msgstr "Certificats" |
|
2369 |
|
|
2370 |
#~ msgid "Certificate Authorities" |
|
2371 |
#~ msgstr "Autorités de certification" |
|
2372 |
|
|
2373 |
#~ msgid "Add Certificate Authority" |
|
2374 |
#~ msgstr "Ajoutez une autorité de certification" |
|
2375 |
|
|
2376 |
#~ msgid "You need to install M2Crypto to use this feature" |
|
2377 |
#~ msgstr "Vous devez installer M2Crypto pour utiliser cette fonctionnalité" |
|
2378 |
|
|
2379 |
#~ msgid "Add" |
|
2380 |
#~ msgstr "Ajouter" |
|
2381 |
|
|
2382 |
#~ msgid "Certificate" |
|
2383 |
#~ msgstr "Certificat" |
|
2384 |
|
|
2385 |
#~ msgid "Bad certificate" |
|
2386 |
#~ msgstr "Mauvais certificat" |
|
2387 |
|
|
2388 |
#~ msgid "backoffice" |
|
2389 |
#~ msgstr "backoffice" |
|
2390 |
|
|
2391 |
#~ msgid "logout" |
|
2392 |
#~ msgstr "déconnexion" |
|
2393 |
|
|
2394 |
#~ msgid "help" |
|
2395 |
#~ msgstr "aide" |
|
2396 |
|
|
2397 |
#~ msgid "Administration of %s" |
|
2398 |
#~ msgstr "Administration de %s" |
|
2399 |
|
|
2400 |
#~ msgid "Remove" |
|
2401 |
#~ msgstr "Supprimer" |
|
2402 |
|
|
2403 |
#~ msgid "Duplicate" |
|
2404 |
#~ msgstr "Dupliquer" |
|
2405 |
|
|
2406 |
#~ msgid "View" |
|
2407 |
#~ msgstr "Voir" |
|
2408 |
|
|
2409 |
#~ msgid "Export" |
|
2410 |
#~ msgstr "Exporter" |
|
2411 |
|
|
2412 |
#~ msgid "Error" |
|
2413 |
#~ msgstr "Erreur" |
|
2414 |
|
|
2415 |
#~ msgid "SMTP Server" |
|
2416 |
#~ msgstr "Serveur SMTP" |
|
2417 |
|
|
2418 |
#~ msgid "Email Sender" |
|
2419 |
#~ msgstr "Émetteur des courriels" |
|
2420 |
|
|
2421 |
#~ msgid "Reply-To Address" |
|
2422 |
#~ msgstr "Adresse de réponse (Reply-To)" |
|
2423 |
|
|
2424 |
#~ msgid "Handle Bounces" |
|
2425 |
#~ msgstr "Gérer les rebonds" |
|
2426 |
|
|
2427 |
#~ msgid "Check DNS for domain name" |
|
2428 |
#~ msgstr "Vérifier le nom de domaine à l'aide d'une requête DNS" |
|
2429 |
|
|
2430 |
#~ msgid "Use a DNS request to check domain names used in email fields" |
|
2431 |
#~ msgstr "" |
|
2432 |
#~ "Utiliser une requête DNS pour vérifier les noms de domaine utilisés dans " |
|
2433 |
#~ "les champs courriel" |
|
2434 |
|
|
2435 |
#~ msgid "Enabled Email" |
|
2436 |
#~ msgstr "Courriel activé" |
|
2437 |
|
|
2438 |
#~ msgid "Restore default email" |
|
2439 |
#~ msgstr "Restaurer le courriel par défaut" |
|
2440 |
|
|
2441 |
#~ msgid "required field" |
|
2442 |
#~ msgstr "champ obligatoire" |
|
2443 |
|
|
2444 |
#~ msgid "" |
|
2445 |
#~ "The form you have submitted is invalid. Most likely it has been " |
|
2446 |
#~ "successfully submitted once already. Please review the form data and " |
|
2447 |
#~ "submit the form again." |
|
2448 |
#~ msgstr "" |
|
2449 |
#~ "Le formulaire que vous avez transmis n'est pas valide. Une raison " |
|
2450 |
#~ "probable est qu'il ait déjà été transmis une fois. Vérifiez les données " |
|
2451 |
#~ "du formulaire avant de le soumettre à nouveau." |
|
2452 |
|
|
2453 |
#~ msgid "There were errors processing your form. See below for details." |
|
2454 |
#~ msgstr "" |
|
2455 |
#~ "Il y a eu un problème à la soumission du formulaire. Regardez ci-dessous " |
|
2456 |
#~ "pour le détail." |
|
2457 |
|
|
2458 |
#~ msgid "must be a valid email address" |
|
2459 |
#~ msgstr "doit être une adresse électronique valide" |
|
2460 |
|
|
2461 |
#~ msgid "invalid address domain" |
|
2462 |
#~ msgstr "adresse du domaine invalide" |
|
2463 |
|
|
2464 |
#~ msgid "Prefill" |
|
2465 |
#~ msgstr "Préremplir" |
|
2466 |
|
|
2467 |
#~ msgid "wrong format" |
|
2468 |
#~ msgstr "format invalide" |
|
2469 |
|
|
2470 |
#~ msgid "invalid date" |
|
2471 |
#~ msgstr "date invalide" |
|
2472 |
|
|
2473 |
#~ msgid "invalid date: date must be on or after %s" |
|
2474 |
#~ msgstr "date invalide ; la date doit être antérieure à %s" |
|
2475 |
|
|
2476 |
#~ msgid "invalid date; date must be on or before %s" |
|
2477 |
#~ msgstr "date invalide ; la date doit être postérieure à %s" |
|
2478 |
|
|
2479 |
#~ msgid "Previous Year" |
|
2480 |
#~ msgstr "Année précédente" |
|
2481 |
|
|
2482 |
#~ msgid "Previous Month" |
|
2483 |
#~ msgstr "Mois précédent" |
|
2484 |
|
|
2485 |
#~ msgid "Next Year" |
|
2486 |
#~ msgstr "Année Suivante" |
|
2487 |
|
|
2488 |
#~ msgid "Next Month" |
|
2489 |
#~ msgstr "Mois suivant" |
|
2490 |
|
|
2491 |
#~ msgid "Close" |
|
2492 |
#~ msgstr "Fermer" |
|
2493 |
|
|
2494 |
#~ msgid "Choose Date" |
|
2495 |
#~ msgstr "Choisir la date" |
|
2496 |
|
|
2497 |
#~ msgid "invalid regular expression" |
|
2498 |
#~ msgstr "expression rationnelle invalide" |
|
2499 |
|
|
2500 |
#~ msgid "You must select at most %d answers." |
|
2501 |
#~ msgstr "Vous devez sélectionner au maximum %d réponses." |
|
2502 |
|
|
2503 |
#~ msgid "must start with http:// or https:// and have a domain name" |
|
2504 |
#~ msgstr "doit commencer par http:// ou https:// et avoir un nom de domaine" |
|
2505 |
|
|
2506 |
#~ msgid "client error: access forbidden (error 403)" |
|
2507 |
#~ msgstr "erreur du client : accès interdit (erreur 403)" |
|
2508 |
|
|
2509 |
#~ msgid "client error: page not found (error 404)" |
|
2510 |
#~ msgstr "erreur du client : page non trouvée (erreur 404)" |
|
2511 |
|
|
2512 |
#~ msgid "client error: %(reason)s (error %(code)s)" |
|
2513 |
#~ msgstr "erreur du client : %(reason)s (erreur %(code)s)" |
|
2514 |
|
|
2515 |
#~ msgid "server error: %(reason)s (error %(code)s)" |
|
2516 |
#~ msgstr "erreur du serveur : %(reason)s (erreur %(code)s)" |
|
2517 |
|
|
2518 |
#~ msgid "" |
|
2519 |
#~ "must start with http:// or https:// and have a domain name or start with /" |
|
2520 |
#~ msgstr "" |
|
2521 |
#~ "doit commencer par http:// ou https:// et avoir un nom de domaine ou " |
|
2522 |
#~ "commencer par /" |
|
2523 |
|
|
2524 |
#~ msgid "times" |
|
2525 |
#~ msgstr "fois" |
|
2526 |
|
|
2527 |
#~ msgid "plus" |
|
2528 |
#~ msgstr "plus" |
|
2529 |
|
|
2530 |
#~ msgid "minus" |
|
2531 |
#~ msgstr "moins" |
|
2532 |
|
|
2533 |
#~ msgid "What is the result of %(a)d %(op)s %(b)d?" |
|
2534 |
#~ msgstr "Quel est le résultat de %(a)d %(op)s %(b)d ?" |
|
2535 |
|
|
2536 |
#~ msgid "" |
|
2537 |
#~ "Please answer this simple mathematical question as proof you are not a " |
|
2538 |
#~ "bot." |
|
2539 |
#~ msgstr "" |
|
2540 |
#~ "Répondez à cette simple question mathématique comme preuve que vous " |
|
2541 |
#~ "n'êtes pas un robot'" |
|
2542 |
|
|
2543 |
#~ msgid "wrong answer" |
|
2544 |
#~ msgstr "mauvaise réponse" |
|
2545 |
|
|
2546 |
#~ msgid "January" |
|
2547 |
#~ msgstr "Janvier" |
|
2548 |
|
|
2549 |
#~ msgid "February" |
|
2550 |
#~ msgstr "Février" |
|
2551 |
|
|
2552 |
#~ msgid "March" |
|
2553 |
#~ msgstr "Mars" |
|
2554 |
|
|
2555 |
#~ msgid "April" |
|
2556 |
#~ msgstr "Avril" |
|
2557 |
|
|
2558 |
#~ msgid "May" |
|
2559 |
#~ msgstr "Mai" |
|
2560 |
|
|
2561 |
#~ msgid "June" |
|
2562 |
#~ msgstr "Juin" |
|
2563 |
|
|
2564 |
#~ msgid "July" |
|
2565 |
#~ msgstr "Juillet" |
|
2566 |
|
|
2567 |
#~ msgid "August" |
|
2568 |
#~ msgstr "Août" |
|
2569 |
|
|
2570 |
#~ msgid "September" |
|
2571 |
#~ msgstr "Septembre" |
|
2572 |
|
|
2573 |
#~ msgid "October" |
|
2574 |
#~ msgstr "Octobre" |
|
2575 |
|
|
2576 |
#~ msgid "November" |
|
2577 |
#~ msgstr "Novembre" |
|
2578 |
|
|
2579 |
#~ msgid "December" |
|
2580 |
#~ msgstr "Décembre" |
|
2581 |
|
|
2582 |
#~ msgid "Monday" |
|
2583 |
#~ msgstr "Lundi" |
|
2584 |
|
|
2585 |
#~ msgid "Tuesday" |
|
2586 |
#~ msgstr "Mardi" |
|
2587 |
|
|
2588 |
#~ msgid "Wednesday" |
|
2589 |
#~ msgstr "Mercredi" |
|
2590 |
|
|
2591 |
#~ msgid "Thursday" |
|
2592 |
#~ msgstr "Jeudi" |
|
2593 |
|
|
2594 |
#~ msgid "Friday" |
|
2595 |
#~ msgstr "Vendredi" |
|
2596 |
|
|
2597 |
#~ msgid "Saturday" |
|
2598 |
#~ msgstr "Samedi" |
|
2599 |
|
|
2600 |
#~ msgid "Sunday" |
|
2601 |
#~ msgstr "Dimanche" |
|
2602 |
|
|
2603 |
#~ msgid "Back Office of %s" |
|
2604 |
#~ msgstr "Back Office de %s" |
|
2605 |
|
|
2606 |
#, fuzzy |
|
2607 |
#~ msgid "Invalid authentication response" |
|
2608 |
#~ msgstr "Réponse de l'authentification" |
|
2609 |
|
|
2610 |
#~ msgid "Authentication failure; federation not found" |
|
2611 |
#~ msgstr "Erreur d'authentification: pas de fédération" |
|
2612 |
|
|
2613 |
#~ msgid "Authentication failure; failed to get response" |
|
2614 |
#~ msgstr "Erreur d'authentification: pas de réponse reçue" |
|
2615 |
|
|
2616 |
#, fuzzy |
|
2617 |
#~ msgid "Unknown error" |
|
2618 |
#~ msgstr "Erreur inconnue : %s" |
|
2619 |
|
|
2620 |
#~ msgid "No SAML Response" |
|
2621 |
#~ msgstr "Pas de réponse SAML" |
|
2622 |
|
|
2623 |
#~ msgid "No SAML Response in query string" |
|
2624 |
#~ msgstr "Pas de réponse SAML dans la 'query string'" |
|
2625 |
|
|
2626 |
#~ msgid "Request from unknown provider ID" |
|
2627 |
#~ msgstr "Requête d'un fournisseur inconnu" |
|
2628 |
|
|
2629 |
#~ msgid "Error checking signature" |
|
2630 |
#~ msgstr "Erreur à la vérification de signature" |
|
2631 |
|
|
2632 |
#, fuzzy |
|
2633 |
#~ msgid "Could not send logout request to the identity provider" |
|
2634 |
#~ msgstr "Ajouter et supprimer des fournisseurs d'identités" |
|
2635 |
|
|
2636 |
#~ msgid "It has been sent to the site administrator for analyse." |
|
2637 |
#~ msgstr "Elle a été envoyée à l'administrateur du site pour analyse." |
|
2638 |
|
|
2639 |
#~ msgid "Continue to %s" |
|
2640 |
#~ msgstr "Continuer vers %s" |
|
2641 |
|
|
2642 |
#~ msgid "View Error Details" |
|
2643 |
#~ msgstr "Afficher le détail de l'erreur" |
|
2644 |
|
|
2645 |
#~ msgid "Logged in as %s." |
|
2646 |
#~ msgstr "Identifié en tant que %s." |
|
2647 |
|
|
2648 |
#~ msgid "Passwords will be automatically generated." |
|
2649 |
#~ msgstr "Les mots de passe vont être générés automatiquement." |
|
2650 |
|
|
2651 |
#~ msgid "description" |
|
2652 |
#~ msgstr "description" |
|
2653 |
|
|
2654 |
#~ msgid "hint" |
|
2655 |
#~ msgstr "astuce" |
|
2656 |
|
|
2657 |
#~ msgid "Authentication request initiated by an unaffiliated provider." |
|
2658 |
#~ msgstr "Requête d'authentification initié par un fournisseur non-affilié" |
|
2659 |
|
|
2660 |
#~ msgid "Custom Email:" |
|
2661 |
#~ msgstr "Courriel personnalisé :" |
larpe/tags/release-1.1.1/po/larpe.pot | ||
---|---|---|
1 |
# SOME DESCRIPTIVE TITLE. |
|
2 |
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER |
|
3 |
# This file is distributed under the same license as the PACKAGE package. |
|
4 |
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. |
|
5 |
# |
|
6 |
#, fuzzy |
|
7 |
msgid "" |
|
8 |
msgstr "" |
|
9 |
"Project-Id-Version: PACKAGE VERSION\n" |
|
10 |
"Report-Msgid-Bugs-To: \n" |
|
11 |
"POT-Creation-Date: 2010-07-19 13:53+0200\n" |
|
12 |
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
|
13 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
|
14 |
"Language-Team: LANGUAGE <LL@li.org>\n" |
|
15 |
"Language: \n" |
|
16 |
"MIME-Version: 1.0\n" |
|
17 |
"Content-Type: text/plain; charset=CHARSET\n" |
|
18 |
"Content-Transfer-Encoding: 8bit\n" |
|
19 |
|
|
20 |
#: ../larpe/idwsf2.ptl:50 |
|
21 |
msgid "Failed connecting to the original site." |
|
22 |
msgstr "" |
|
23 |
|
|
24 |
#: ../larpe/idwsf2.ptl:61 |
|
25 |
msgid "Failed getting attributes from the attribute provider." |
|
26 |
msgstr "" |
|
27 |
|
|
28 |
#: ../larpe/idwsf2.ptl:64 |
|
29 |
msgid "Failed getting attributes for an unknown reason." |
|
30 |
msgstr "" |
|
31 |
|
|
32 |
#: ../larpe/liberty_site.ptl:46 ../larpe/liberty_site.ptl:56 |
|
33 |
msgid "SSO support is not yet configured" |
|
34 |
msgstr "" |
|
35 |
|
|
36 |
#: ../larpe/admin/users.ptl:24 ../larpe/admin/users.ptl:32 |
|
37 |
msgid "User Name" |
|
38 |
msgstr "" |
|
39 |
|
|
40 |
#: ../larpe/admin/users.ptl:25 ../larpe/admin/users.ptl:34 |
|
41 |
#: ../larpe/admin/users.ptl:66 |
|
42 |
msgid "Email" |
|
43 |
msgstr "" |
|
44 |
|
|
45 |
#: ../larpe/admin/users.ptl:26 ../larpe/admin/users.ptl:36 |
|
46 |
#: ../larpe/admin/users.ptl:122 ../larpe/admin/forms_prefill.ptl:24 |
|
47 |
#: ../larpe/admin/forms_prefill.ptl:76 ../larpe/admin/settings.ptl:31 |
|
48 |
#: ../larpe/admin/settings.ptl:217 ../larpe/admin/settings.ptl:326 |
|
49 |
#: ../larpe/admin/settings.ptl:343 ../larpe/admin/fields_prefill.ptl:30 |
|
50 |
#: ../larpe/admin/fields_prefill.ptl:73 ../larpe/admin/hosts.ptl:384 |
|
51 |
#: ../larpe/admin/hosts.ptl:692 ../larpe/admin/hosts.ptl:740 |
|
52 |
#: ../larpe/admin/hosts.ptl:787 ../larpe/admin/hosts.ptl:1286 |
|
53 |
#: ../larpe/site_authentication.ptl:64 ../larpe/root.ptl:64 |
|
54 |
msgid "Submit" |
|
55 |
msgstr "" |
|
56 |
|
|
57 |
#: ../larpe/admin/users.ptl:27 ../larpe/admin/users.ptl:37 |
|
58 |
#: ../larpe/admin/users.ptl:123 ../larpe/admin/users.ptl:138 |
|
59 |
#: ../larpe/admin/forms_prefill.ptl:25 ../larpe/admin/forms_prefill.ptl:77 |
|
60 |
#: ../larpe/admin/settings.ptl:218 ../larpe/admin/settings.ptl:327 |
|
61 |
#: ../larpe/admin/settings.ptl:344 ../larpe/admin/fields_prefill.ptl:31 |
|
62 |
#: ../larpe/admin/fields_prefill.ptl:74 ../larpe/admin/hosts.ptl:124 |
|
63 |
#: ../larpe/admin/hosts.ptl:385 ../larpe/admin/hosts.ptl:693 |
|
64 |
#: ../larpe/admin/hosts.ptl:741 ../larpe/admin/hosts.ptl:788 |
|
65 |
#: ../larpe/admin/hosts.ptl:1287 ../larpe/root.ptl:65 |
|
66 |
msgid "Cancel" |
|
67 |
msgstr "" |
|
68 |
|
|
69 |
#: ../larpe/admin/users.ptl:60 ../larpe/admin/users.ptl:61 |
|
70 |
msgid "User" |
|
71 |
msgstr "" |
|
72 |
|
|
73 |
#: ../larpe/admin/users.ptl:63 ../larpe/admin/hosts.ptl:382 |
|
74 |
msgid "Name" |
|
75 |
msgstr "" |
|
76 |
|
|
77 |
#: ../larpe/admin/users.ptl:98 |
|
78 |
msgid "Debug" |
|
79 |
msgstr "" |
|
80 |
|
|
81 |
#: ../larpe/admin/users.ptl:110 ../larpe/admin/forms_prefill.ptl:48 |
|
82 |
#: ../larpe/admin/forms_prefill.ptl:66 ../larpe/admin/forms_prefill.ptl:67 |
|
83 |
#: ../larpe/admin/forms_prefill.ptl:68 ../larpe/admin/fields_prefill.ptl:63 |
|
84 |
#: ../larpe/admin/fields_prefill.ptl:64 ../larpe/admin/fields_prefill.ptl:65 |
|
85 |
msgid "Edit" |
|
86 |
msgstr "" |
|
87 |
|
|
88 |
#: ../larpe/admin/users.ptl:111 ../larpe/admin/users.ptl:112 |
|
89 |
msgid "Edit User" |
|
90 |
msgstr "" |
|
91 |
|
|
92 |
#: ../larpe/admin/users.ptl:121 |
|
93 |
msgid "You are about to irrevocably delete this user." |
|
94 |
msgstr "" |
|
95 |
|
|
96 |
#: ../larpe/admin/users.ptl:127 ../larpe/admin/forms_prefill.ptl:81 |
|
97 |
#: ../larpe/admin/fields_prefill.ptl:78 ../larpe/admin/hosts.ptl:1291 |
|
98 |
msgid "Delete" |
|
99 |
msgstr "" |
|
100 |
|
|
101 |
#: ../larpe/admin/users.ptl:128 |
|
102 |
msgid "Delete User" |
|
103 |
msgstr "" |
|
104 |
|
|
105 |
#: ../larpe/admin/users.ptl:129 |
|
106 |
msgid "Deleting User :" |
|
107 |
msgstr "" |
|
108 |
|
|
109 |
#: ../larpe/admin/users.ptl:137 |
|
110 |
msgid "Generate" |
|
111 |
msgstr "" |
|
112 |
|
|
113 |
#: ../larpe/admin/users.ptl:143 ../larpe/admin/users.ptl:146 |
|
114 |
#: ../larpe/admin/users.ptl:147 ../larpe/admin/users.ptl:155 |
|
115 |
#: ../larpe/admin/users.ptl:180 ../larpe/admin/users.ptl:182 |
|
116 |
#: ../larpe/admin/users.ptl:223 ../larpe/root.ptl:62 ../larpe/root.ptl:71 |
|
117 |
msgid "Identification Token" |
|
118 |
msgstr "" |
|
119 |
|
|
120 |
#: ../larpe/admin/users.ptl:148 |
|
121 |
msgid "" |
|
122 |
"You are about to generate a token than can be used to federate the account." |
|
123 |
msgstr "" |
|
124 |
|
|
125 |
#: ../larpe/admin/users.ptl:149 |
|
126 |
msgid "" |
|
127 |
"After that, you will have the choice to send it to the user by email so that " |
|
128 |
"he can federate his accounts." |
|
129 |
msgstr "" |
|
130 |
|
|
131 |
#: ../larpe/admin/users.ptl:151 |
|
132 |
#, python-format |
|
133 |
msgid "Note that user has already been issued an identification token : %s" |
|
134 |
msgstr "" |
|
135 |
|
|
136 |
#: ../larpe/admin/users.ptl:161 |
|
137 |
#, python-format |
|
138 |
msgid "Identification Token for %s" |
|
139 |
msgstr "" |
|
140 |
|
|
141 |
#: ../larpe/admin/users.ptl:165 |
|
142 |
msgid "Done" |
|
143 |
msgstr "" |
|
144 |
|
|
145 |
#: ../larpe/admin/users.ptl:167 |
|
146 |
msgid "Send by email" |
|
147 |
msgstr "" |
|
148 |
|
|
149 |
#: ../larpe/admin/users.ptl:173 |
|
150 |
#, python-format |
|
151 |
msgid "" |
|
152 |
"You have been given an identification token.\n" |
|
153 |
"\n" |
|
154 |
"Your token is %(token)s\n" |
|
155 |
"\n" |
|
156 |
"Click on %(url)s to use it.\n" |
|
157 |
msgstr "" |
|
158 |
|
|
159 |
#: ../larpe/admin/users.ptl:183 |
|
160 |
msgid "Failed sending email. Check your email configuration." |
|
161 |
msgstr "" |
|
162 |
|
|
163 |
#: ../larpe/admin/users.ptl:184 ../larpe/admin/settings.ptl:112 |
|
164 |
#: ../larpe/admin/hosts.ptl:657 ../larpe/admin/hosts.ptl:713 |
|
165 |
#: ../larpe/admin/hosts.ptl:1340 |
|
166 |
msgid "Back" |
|
167 |
msgstr "" |
|
168 |
|
|
169 |
#: ../larpe/admin/users.ptl:194 ../larpe/admin/users.ptl:195 |
|
170 |
#: ../larpe/admin/users.ptl:238 ../larpe/admin/users.ptl:272 |
|
171 |
#: ../larpe/admin/root.ptl:45 |
|
172 |
msgid "Users" |
|
173 |
msgstr "" |
|
174 |
|
|
175 |
#: ../larpe/admin/users.ptl:199 ../larpe/admin/users.ptl:242 |
|
176 |
msgid "Liberty support must be setup before creating users." |
|
177 |
msgstr "" |
|
178 |
|
|
179 |
#: ../larpe/admin/users.ptl:203 ../larpe/admin/users.ptl:254 |
|
180 |
#: ../larpe/admin/users.ptl:255 |
|
181 |
msgid "New User" |
|
182 |
msgstr "" |
|
183 |
|
|
184 |
#: ../larpe/admin/users.ptl:226 |
|
185 |
#, python-format |
|
186 |
msgid "Identification Token (current: %s)" |
|
187 |
msgstr "" |
|
188 |
|
|
189 |
#: ../larpe/admin/users.ptl:233 ../larpe/admin/root.ptl:47 |
|
190 |
msgid "Logs" |
|
191 |
msgstr "" |
|
192 |
|
|
193 |
#: ../larpe/admin/users.ptl:239 ../larpe/admin/forms_prefill.ptl:122 |
|
194 |
#: ../larpe/admin/fields_prefill.ptl:125 ../larpe/admin/hosts.ptl:1344 |
|
195 |
msgid "New" |
|
196 |
msgstr "" |
|
197 |
|
|
198 |
#: ../larpe/admin/forms_prefill.ptl:16 |
|
199 |
msgid "Form name" |
|
200 |
msgstr "" |
|
201 |
|
|
202 |
#: ../larpe/admin/forms_prefill.ptl:17 |
|
203 |
msgid "Only used for display" |
|
204 |
msgstr "" |
|
205 |
|
|
206 |
#: ../larpe/admin/forms_prefill.ptl:18 |
|
207 |
msgid "Form address" |
|
208 |
msgstr "" |
|
209 |
|
|
210 |
#: ../larpe/admin/forms_prefill.ptl:20 |
|
211 |
msgid "ID-WSF data profile" |
|
212 |
msgstr "" |
|
213 |
|
|
214 |
#: ../larpe/admin/forms_prefill.ptl:21 |
|
215 |
msgid "Example: urn:liberty:id-sis-pp:2005-05" |
|
216 |
msgstr "" |
|
217 |
|
|
218 |
#: ../larpe/admin/forms_prefill.ptl:22 |
|
219 |
msgid "ID-WSF data XML prefix" |
|
220 |
msgstr "" |
|
221 |
|
|
222 |
#: ../larpe/admin/forms_prefill.ptl:23 |
|
223 |
msgid "Example: pp" |
|
224 |
msgstr "" |
|
225 |
|
|
226 |
#: ../larpe/admin/forms_prefill.ptl:45 |
|
227 |
msgid "Form prefilling configuration" |
|
228 |
msgstr "" |
|
229 |
|
|
230 |
#: ../larpe/admin/forms_prefill.ptl:48 |
|
231 |
msgid "Configure this form" |
|
232 |
msgstr "" |
|
233 |
|
|
234 |
#: ../larpe/admin/forms_prefill.ptl:50 ../larpe/admin/fields_prefill.ptl:91 |
|
235 |
#: ../larpe/admin/fields_prefill.ptl:98 |
|
236 |
msgid "Fields" |
|
237 |
msgstr "" |
|
238 |
|
|
239 |
#: ../larpe/admin/forms_prefill.ptl:50 |
|
240 |
msgid "Configure the fields of this form" |
|
241 |
msgstr "" |
|
242 |
|
|
243 |
#: ../larpe/admin/forms_prefill.ptl:75 |
|
244 |
msgid "You are about to irrevocably delete this form." |
|
245 |
msgstr "" |
|
246 |
|
|
247 |
#: ../larpe/admin/forms_prefill.ptl:82 ../larpe/admin/forms_prefill.ptl:83 |
|
248 |
msgid "Delete Form" |
|
249 |
msgstr "" |
|
250 |
|
|
251 |
#: ../larpe/admin/forms_prefill.ptl:94 ../larpe/admin/forms_prefill.ptl:101 |
|
252 |
#: ../larpe/admin/hosts.ptl:1279 |
|
253 |
msgid "Forms" |
|
254 |
msgstr "" |
|
255 |
|
|
256 |
#: ../larpe/admin/forms_prefill.ptl:104 |
|
257 |
msgid "New Form" |
|
258 |
msgstr "" |
|
259 |
|
|
260 |
#: ../larpe/admin/settings.ptl:28 |
|
261 |
msgid "Metadata" |
|
262 |
msgstr "" |
|
263 |
|
|
264 |
#: ../larpe/admin/settings.ptl:29 |
|
265 |
msgid "Public Key" |
|
266 |
msgstr "" |
|
267 |
|
|
268 |
#: ../larpe/admin/settings.ptl:30 |
|
269 |
msgid "CA Certificate Chain" |
|
270 |
msgstr "" |
|
271 |
|
|
272 |
#: ../larpe/admin/settings.ptl:34 ../larpe/admin/settings.ptl:35 |
|
273 |
msgid "New Identity Provider" |
|
274 |
msgstr "" |
|
275 |
|
|
276 |
#: ../larpe/admin/settings.ptl:53 ../larpe/admin/settings.ptl:87 |
|
277 |
msgid "Bad metadata" |
|
278 |
msgstr "" |
|
279 |
|
|
280 |
#. Don't use custom emails |
|
281 |
#: ../larpe/admin/settings.ptl:104 ../larpe/admin/settings.ptl:105 |
|
282 |
#: ../larpe/admin/settings.ptl:192 |
|
283 |
msgid "Emails" |
|
284 |
msgstr "" |
|
285 |
|
|
286 |
#: ../larpe/admin/settings.ptl:108 |
|
287 |
msgid "General Options" |
|
288 |
msgstr "" |
|
289 |
|
|
290 |
#: ../larpe/admin/settings.ptl:125 ../larpe/admin/hosts.ptl:84 |
|
291 |
#: ../larpe/admin/root.ptl:46 |
|
292 |
msgid "Settings" |
|
293 |
msgstr "" |
|
294 |
|
|
295 |
#: ../larpe/admin/settings.ptl:128 |
|
296 |
msgid "Liberty Alliance & SAML 2.0 Service Provider" |
|
297 |
msgstr "" |
|
298 |
|
|
299 |
#: ../larpe/admin/settings.ptl:130 |
|
300 |
msgid "Liberty Alliance Service Provider" |
|
301 |
msgstr "" |
|
302 |
|
|
303 |
#: ../larpe/admin/settings.ptl:132 |
|
304 |
msgid "Service Provider" |
|
305 |
msgstr "" |
|
306 |
|
|
307 |
#: ../larpe/admin/settings.ptl:132 |
|
308 |
msgid "Configure Larpe as a Service Provider" |
|
309 |
msgstr "" |
|
310 |
|
|
311 |
#: ../larpe/admin/settings.ptl:142 ../larpe/admin/hosts.ptl:913 |
|
312 |
msgid "SAML 2.0 Metadata" |
|
313 |
msgstr "" |
|
314 |
|
|
315 |
#: ../larpe/admin/settings.ptl:143 |
|
316 |
msgid "Download SAML 2.0 metadata file for Larpe" |
|
317 |
msgstr "" |
|
318 |
|
|
319 |
#: ../larpe/admin/settings.ptl:149 ../larpe/admin/hosts.ptl:918 |
|
320 |
msgid "ID-FF 1.2 Metadata" |
|
321 |
msgstr "" |
|
322 |
|
|
323 |
#: ../larpe/admin/settings.ptl:150 |
|
324 |
msgid "Download ID-FF 1.2 metadata file for Larpe" |
|
325 |
msgstr "" |
|
326 |
|
|
327 |
#: ../larpe/admin/settings.ptl:156 ../larpe/admin/hosts.ptl:927 |
|
328 |
msgid "Public key" |
|
329 |
msgstr "" |
|
330 |
|
|
331 |
#: ../larpe/admin/settings.ptl:157 ../larpe/admin/hosts.ptl:928 |
|
332 |
msgid "Download SSL Public Key file" |
|
333 |
msgstr "" |
|
334 |
|
|
335 |
#: ../larpe/admin/settings.ptl:160 |
|
336 |
msgid "Liberty Alliance & SAML 2.0 Identity Provider" |
|
337 |
msgstr "" |
|
338 |
|
|
339 |
#: ../larpe/admin/settings.ptl:162 |
|
340 |
msgid "Liberty Alliance Identity Provider" |
|
341 |
msgstr "" |
|
342 |
|
|
343 |
#: ../larpe/admin/settings.ptl:167 |
|
344 |
msgid "Identity Provider" |
|
345 |
msgstr "" |
|
346 |
|
|
347 |
#: ../larpe/admin/settings.ptl:167 |
|
348 |
msgid "Configure an identity provider" |
|
349 |
msgstr "" |
|
350 |
|
|
351 |
#: ../larpe/admin/settings.ptl:171 |
|
352 |
msgid "Identity Provider metadatas" |
|
353 |
msgstr "" |
|
354 |
|
|
355 |
#: ../larpe/admin/settings.ptl:171 |
|
356 |
msgid "See current identity provider metadatas" |
|
357 |
msgstr "" |
|
358 |
|
|
359 |
#: ../larpe/admin/settings.ptl:175 |
|
360 |
msgid "Global parameters for the sites" |
|
361 |
msgstr "" |
|
362 |
|
|
363 |
#: ../larpe/admin/settings.ptl:179 ../larpe/admin/settings.ptl:302 |
|
364 |
#: ../larpe/admin/settings.ptl:303 |
|
365 |
msgid "Domain name" |
|
366 |
msgstr "" |
|
367 |
|
|
368 |
#: ../larpe/admin/settings.ptl:179 |
|
369 |
msgid "Configure the base domain name for the sites" |
|
370 |
msgstr "" |
|
371 |
|
|
372 |
#: ../larpe/admin/settings.ptl:181 ../larpe/admin/settings.ptl:348 |
|
373 |
#: ../larpe/admin/settings.ptl:349 |
|
374 |
msgid "Apache 2 configuration generation" |
|
375 |
msgstr "" |
|
376 |
|
|
377 |
#: ../larpe/admin/settings.ptl:181 |
|
378 |
msgid "Customise Apache 2 configuration generation" |
|
379 |
msgstr "" |
|
380 |
|
|
381 |
#: ../larpe/admin/settings.ptl:183 |
|
382 |
msgid "Proxy" |
|
383 |
msgstr "" |
|
384 |
|
|
385 |
#: ../larpe/admin/settings.ptl:183 |
|
386 |
msgid "Connect to the sites through a web proxy" |
|
387 |
msgstr "" |
|
388 |
|
|
389 |
#: ../larpe/admin/settings.ptl:186 |
|
390 |
msgid "Customisation" |
|
391 |
msgstr "" |
|
392 |
|
|
393 |
#: ../larpe/admin/settings.ptl:190 |
|
394 |
msgid "Language" |
|
395 |
msgstr "" |
|
396 |
|
|
397 |
#: ../larpe/admin/settings.ptl:190 |
|
398 |
msgid "Configure site language" |
|
399 |
msgstr "" |
|
400 |
|
|
401 |
#: ../larpe/admin/settings.ptl:192 |
|
402 |
msgid "Configure email settings" |
|
403 |
msgstr "" |
|
404 |
|
|
405 |
#: ../larpe/admin/settings.ptl:195 |
|
406 |
msgid "Misc" |
|
407 |
msgstr "" |
|
408 |
|
|
409 |
#: ../larpe/admin/settings.ptl:199 |
|
410 |
msgid "Debug Options" |
|
411 |
msgstr "" |
|
412 |
|
|
413 |
#: ../larpe/admin/settings.ptl:199 |
|
414 |
msgid "Configure options useful for debugging" |
|
415 |
msgstr "" |
|
416 |
|
|
417 |
#: ../larpe/admin/settings.ptl:215 |
|
418 |
msgid "Organisation Name" |
|
419 |
msgstr "" |
|
420 |
|
|
421 |
#: ../larpe/admin/settings.ptl:222 ../larpe/admin/settings.ptl:223 |
|
422 |
msgid "Service Provider Configuration" |
|
423 |
msgstr "" |
|
424 |
|
|
425 |
#: ../larpe/admin/settings.ptl:318 |
|
426 |
msgid "Domain name for the sites" |
|
427 |
msgstr "" |
|
428 |
|
|
429 |
#. TODO: Add the option "Both" and handle it in hosts configuration |
|
430 |
#: ../larpe/admin/settings.ptl:321 |
|
431 |
msgid "Use HTTP or HTTPS" |
|
432 |
msgstr "" |
|
433 |
|
|
434 |
#: ../larpe/admin/settings.ptl:323 |
|
435 |
msgid "Same as the site" |
|
436 |
msgstr "" |
|
437 |
|
|
438 |
#: ../larpe/admin/settings.ptl:341 |
|
439 |
msgid "" |
|
440 |
"Automatically generate Apache 2 configuration for new hosts and reload " |
|
441 |
"Apache 2 after changes" |
|
442 |
msgstr "" |
|
443 |
|
|
444 |
#: ../larpe/admin/fields_prefill.ptl:15 |
|
445 |
msgid "Field name" |
|
446 |
msgstr "" |
|
447 |
|
|
448 |
#: ../larpe/admin/fields_prefill.ptl:17 |
|
449 |
msgid "Xpath of the attribute" |
|
450 |
msgstr "" |
|
451 |
|
|
452 |
#: ../larpe/admin/fields_prefill.ptl:18 |
|
453 |
msgid "Example: /pp:PP/pp:InformalName" |
|
454 |
msgstr "" |
|
455 |
|
|
456 |
#: ../larpe/admin/fields_prefill.ptl:19 |
|
457 |
msgid "Number of the field in the data" |
|
458 |
msgstr "" |
|
459 |
|
|
460 |
#: ../larpe/admin/fields_prefill.ptl:21 |
|
461 |
msgid "" |
|
462 |
"Change it if there are multiple fields corresponding to the same Xpath and " |
|
463 |
"you want to get another than the first one" |
|
464 |
msgstr "" |
|
465 |
|
|
466 |
#: ../larpe/admin/fields_prefill.ptl:22 |
|
467 |
msgid "Get raw XML value" |
|
468 |
msgstr "" |
|
469 |
|
|
470 |
#: ../larpe/admin/fields_prefill.ptl:24 |
|
471 |
msgid "Python regexp of a string to match" |
|
472 |
msgstr "" |
|
473 |
|
|
474 |
#: ../larpe/admin/fields_prefill.ptl:26 |
|
475 |
msgid "Python regexp of the replacing string" |
|
476 |
msgstr "" |
|
477 |
|
|
478 |
#: ../larpe/admin/fields_prefill.ptl:28 |
|
479 |
msgid "Options mapping for a select field" |
|
480 |
msgstr "" |
|
481 |
|
|
482 |
#: ../larpe/admin/fields_prefill.ptl:29 |
|
483 |
msgid "Add item" |
|
484 |
msgstr "" |
|
485 |
|
|
486 |
#: ../larpe/admin/fields_prefill.ptl:72 |
|
487 |
msgid "You are about to irrevocably delete this field." |
|
488 |
msgstr "" |
|
489 |
|
|
490 |
#: ../larpe/admin/fields_prefill.ptl:79 ../larpe/admin/fields_prefill.ptl:80 |
|
491 |
msgid "Delete Field" |
|
492 |
msgstr "" |
|
493 |
|
|
494 |
#: ../larpe/admin/fields_prefill.ptl:101 |
|
495 |
msgid "New Field" |
|
496 |
msgstr "" |
|
497 |
|
|
498 |
#: ../larpe/admin/hosts.ptl:33 |
|
499 |
msgid "" |
|
500 |
"You must either choose a different hostname from Larpe or specify a reversed " |
|
501 |
"directory" |
|
502 |
msgstr "" |
|
503 |
|
|
504 |
#: ../larpe/admin/hosts.ptl:80 ../larpe/admin/hosts.ptl:102 |
|
505 |
msgid "Basic configuration" |
|
506 |
msgstr "" |
|
507 |
|
|
508 |
#: ../larpe/admin/hosts.ptl:81 |
|
509 |
msgid "Need domain name configuration" |
|
510 |
msgstr "" |
|
511 |
|
|
512 |
#: ../larpe/admin/hosts.ptl:82 |
|
513 |
#, python-format |
|
514 |
msgid "" |
|
515 |
"Before configuring hosts, you must\n" |
|
516 |
"<a href=\"../../../settings/domain_names\">setup a global domain name</a> " |
|
517 |
"in\n" |
|
518 |
"%(settings)s menu." |
|
519 |
msgstr "" |
|
520 |
|
|
521 |
#: ../larpe/admin/hosts.ptl:103 |
|
522 |
msgid "Step 1 - Basic configuration" |
|
523 |
msgstr "" |
|
524 |
|
|
525 |
#: ../larpe/admin/hosts.ptl:112 |
|
526 |
msgid "Original site root address" |
|
527 |
msgstr "" |
|
528 |
|
|
529 |
#: ../larpe/admin/hosts.ptl:114 |
|
530 |
msgid "" |
|
531 |
"If your site address is http://test.org/index.php, put http://test.org/ here" |
|
532 |
msgstr "" |
|
533 |
|
|
534 |
#: ../larpe/admin/hosts.ptl:117 |
|
535 |
msgid "Use a proxy" |
|
536 |
msgstr "" |
|
537 |
|
|
538 |
#: ../larpe/admin/hosts.ptl:118 |
|
539 |
msgid "" |
|
540 |
"Uncheck it if Larpe doesn't need to use the proxy to connect to this site" |
|
541 |
msgstr "" |
|
542 |
|
|
543 |
#: ../larpe/admin/hosts.ptl:122 |
|
544 |
msgid "" |
|
545 |
"If Larpe needs to use a proxy to connect to this site, you must first " |
|
546 |
"configure\n" |
|
547 |
" it in <a href=\"../../../settings/proxy\">global proxy parameters</a>." |
|
548 |
msgstr "" |
|
549 |
|
|
550 |
#: ../larpe/admin/hosts.ptl:125 ../larpe/admin/hosts.ptl:315 |
|
551 |
#: ../larpe/admin/hosts.ptl:343 ../larpe/admin/hosts.ptl:433 |
|
552 |
#: ../larpe/admin/hosts.ptl:464 ../larpe/admin/hosts.ptl:547 |
|
553 |
#: ../larpe/admin/hosts.ptl:583 ../larpe/admin/hosts.ptl:873 |
|
554 |
#: ../larpe/admin/hosts.ptl:889 ../larpe/admin/hosts.ptl:947 |
|
555 |
#: ../larpe/admin/hosts.ptl:977 |
|
556 |
msgid "Next" |
|
557 |
msgstr "" |
|
558 |
|
|
559 |
#: ../larpe/admin/hosts.ptl:126 ../larpe/admin/hosts.ptl:316 |
|
560 |
#: ../larpe/admin/hosts.ptl:434 ../larpe/admin/hosts.ptl:465 |
|
561 |
#: ../larpe/admin/hosts.ptl:548 ../larpe/admin/hosts.ptl:584 |
|
562 |
#: ../larpe/admin/hosts.ptl:874 ../larpe/admin/hosts.ptl:890 |
|
563 |
#: ../larpe/admin/hosts.ptl:978 |
|
564 |
msgid "Terminate" |
|
565 |
msgstr "" |
|
566 |
|
|
567 |
#: ../larpe/admin/hosts.ptl:314 ../larpe/admin/hosts.ptl:343 |
|
568 |
#: ../larpe/admin/hosts.ptl:432 ../larpe/admin/hosts.ptl:463 |
|
569 |
#: ../larpe/admin/hosts.ptl:546 ../larpe/admin/hosts.ptl:582 |
|
570 |
#: ../larpe/admin/hosts.ptl:872 ../larpe/admin/hosts.ptl:888 |
|
571 |
#: ../larpe/admin/hosts.ptl:976 ../larpe/admin/hosts.ptl:1002 |
|
572 |
msgid "Previous" |
|
573 |
msgstr "" |
|
574 |
|
|
575 |
#: ../larpe/admin/hosts.ptl:332 |
|
576 |
msgid "Check site address and name" |
|
577 |
msgstr "" |
|
578 |
|
|
579 |
#: ../larpe/admin/hosts.ptl:333 |
|
580 |
msgid "Step 2 - Check the new site address works" |
|
581 |
msgstr "" |
|
582 |
|
|
583 |
#: ../larpe/admin/hosts.ptl:335 |
|
584 |
msgid "DNS configuration" |
|
585 |
msgstr "" |
|
586 |
|
|
587 |
#: ../larpe/admin/hosts.ptl:337 |
|
588 |
msgid "" |
|
589 |
"Before opening the following link, ensure you have configured your DNS\n" |
|
590 |
"for this address. If you don't have a DNS server and you just want to test " |
|
591 |
"Larpe, add this\n" |
|
592 |
"domain name in the file \"/etc/hosts\"." |
|
593 |
msgstr "" |
|
594 |
|
|
595 |
#: ../larpe/admin/hosts.ptl:341 |
|
596 |
#, python-format |
|
597 |
msgid "" |
|
598 |
"Then you can open this link in a new window or tab and see if your site\n" |
|
599 |
"is displayed. If it's ok, you can click the \"%(next)s\" button. Otherwise, " |
|
600 |
"click the \"%(previous)s\"\n" |
|
601 |
"button and check your settings." |
|
602 |
msgstr "" |
|
603 |
|
|
604 |
#: ../larpe/admin/hosts.ptl:345 |
|
605 |
msgid "Site adress and name" |
|
606 |
msgstr "" |
|
607 |
|
|
608 |
#: ../larpe/admin/hosts.ptl:347 |
|
609 |
msgid "The new address of this site is " |
|
610 |
msgstr "" |
|
611 |
|
|
612 |
#: ../larpe/admin/hosts.ptl:349 |
|
613 |
#, python-format |
|
614 |
msgid "The name of this site is \"%s\"." |
|
615 |
msgstr "" |
|
616 |
|
|
617 |
#: ../larpe/admin/hosts.ptl:350 |
|
618 |
msgid "" |
|
619 |
"You can also <a href=\"modify_site_address_and_name\">\n" |
|
620 |
"modify the address or the name of this site</a>" |
|
621 |
msgstr "" |
|
622 |
|
|
623 |
#: ../larpe/admin/hosts.ptl:366 |
|
624 |
msgid "An host with the same name already exists" |
|
625 |
msgstr "" |
|
626 |
|
|
627 |
#: ../larpe/admin/hosts.ptl:373 ../larpe/admin/hosts.ptl:374 |
|
628 |
msgid "Modify site address and name" |
|
629 |
msgstr "" |
|
630 |
|
|
631 |
#: ../larpe/admin/hosts.ptl:380 |
|
632 |
msgid "Address" |
|
633 |
msgstr "" |
|
634 |
|
|
635 |
#: ../larpe/admin/hosts.ptl:419 |
|
636 |
msgid "Authentication and logout" |
|
637 |
msgstr "" |
|
638 |
|
|
639 |
#: ../larpe/admin/hosts.ptl:420 |
|
640 |
msgid "Step 3 - Configure authentication and logout pages" |
|
641 |
msgstr "" |
|
642 |
|
|
643 |
#: ../larpe/admin/hosts.ptl:426 ../larpe/admin/hosts.ptl:969 |
|
644 |
msgid "Authentication form page address" |
|
645 |
msgstr "" |
|
646 |
|
|
647 |
#: ../larpe/admin/hosts.ptl:427 |
|
648 |
msgid "Address of a page on the site which contains the authentication form" |
|
649 |
msgstr "" |
|
650 |
|
|
651 |
#: ../larpe/admin/hosts.ptl:429 |
|
652 |
msgid "Logout address" |
|
653 |
msgstr "" |
|
654 |
|
|
655 |
#: ../larpe/admin/hosts.ptl:430 |
|
656 |
msgid "Address of the logout link on the site" |
|
657 |
msgstr "" |
|
658 |
|
|
659 |
#: ../larpe/admin/hosts.ptl:446 |
|
660 |
msgid "(computed automatically)" |
|
661 |
msgstr "" |
|
662 |
|
|
663 |
#: ../larpe/admin/hosts.ptl:459 |
|
664 |
msgid "Plugin" |
|
665 |
msgstr "" |
|
666 |
|
|
667 |
#: ../larpe/admin/hosts.ptl:460 |
|
668 |
msgid "You can force a plugin" |
|
669 |
msgstr "" |
|
670 |
|
|
671 |
#: ../larpe/admin/hosts.ptl:478 |
|
672 |
msgid "Auto detected configuration" |
|
673 |
msgstr "" |
|
674 |
|
|
675 |
#: ../larpe/admin/hosts.ptl:479 |
|
676 |
msgid "" |
|
677 |
"Step 4 - Check automatically detected configuration for the authentication " |
|
678 |
"form" |
|
679 |
msgstr "" |
|
680 |
|
|
681 |
#: ../larpe/admin/hosts.ptl:482 |
|
682 |
msgid "Address where the authentication form must be sent" |
|
683 |
msgstr "" |
|
684 |
|
|
685 |
#: ../larpe/admin/hosts.ptl:483 |
|
686 |
msgid "Name of the login field" |
|
687 |
msgstr "" |
|
688 |
|
|
689 |
#: ../larpe/admin/hosts.ptl:484 |
|
690 |
msgid "Name of the password field" |
|
691 |
msgstr "" |
|
692 |
|
|
693 |
#: ../larpe/admin/hosts.ptl:503 |
|
694 |
msgid "" |
|
695 |
"The following authentication form parameters have been detected. If they " |
|
696 |
"look right, you can go to the next step.\n" |
|
697 |
"If you think they are wrong, go back and check your settings then try " |
|
698 |
"again.\n" |
|
699 |
msgstr "" |
|
700 |
|
|
701 |
#: ../larpe/admin/hosts.ptl:508 |
|
702 |
msgid "" |
|
703 |
"The following authentication form parameters in red haven't been correctly " |
|
704 |
"detected. Go back and check\n" |
|
705 |
"your settings then try again.\n" |
|
706 |
msgstr "" |
|
707 |
|
|
708 |
#: ../larpe/admin/hosts.ptl:529 ../larpe/admin/hosts.ptl:1250 |
|
709 |
msgid "Credentials" |
|
710 |
msgstr "" |
|
711 |
|
|
712 |
#: ../larpe/admin/hosts.ptl:530 |
|
713 |
msgid "Step 5 - Fill in a valid username/password for this site" |
|
714 |
msgstr "" |
|
715 |
|
|
716 |
#: ../larpe/admin/hosts.ptl:535 ../larpe/site_authentication.ptl:98 |
|
717 |
msgid "Username" |
|
718 |
msgstr "" |
|
719 |
|
|
720 |
#: ../larpe/admin/hosts.ptl:537 ../larpe/site_authentication.ptl:100 |
|
721 |
msgid "Password" |
|
722 |
msgstr "" |
|
723 |
|
|
724 |
#: ../larpe/admin/hosts.ptl:594 |
|
725 |
msgid "Check authentication" |
|
726 |
msgstr "" |
|
727 |
|
|
728 |
#: ../larpe/admin/hosts.ptl:595 |
|
729 |
msgid "Step 6 - Check the authentication process" |
|
730 |
msgstr "" |
|
731 |
|
|
732 |
#: ../larpe/admin/hosts.ptl:614 |
|
733 |
msgid "Authentication succeeded ! You can go to the next step." |
|
734 |
msgstr "" |
|
735 |
|
|
736 |
#: ../larpe/admin/hosts.ptl:616 |
|
737 |
msgid "Authentication has failed. To resolve this problem, you can :" |
|
738 |
msgstr "" |
|
739 |
|
|
740 |
#: ../larpe/admin/hosts.ptl:619 |
|
741 |
msgid "Try authentication again" |
|
742 |
msgstr "" |
|
743 |
|
|
744 |
#: ../larpe/admin/hosts.ptl:621 |
|
745 |
msgid "See the response of the authentication requests" |
|
746 |
msgstr "" |
|
747 |
|
|
748 |
#: ../larpe/admin/hosts.ptl:623 ../larpe/admin/hosts.ptl:705 |
|
749 |
msgid "Modify the parameters of the authentication requests" |
|
750 |
msgstr "" |
|
751 |
|
|
752 |
#: ../larpe/admin/hosts.ptl:625 |
|
753 |
msgid "Change the way Larpe detects the authentication is successful or not" |
|
754 |
msgstr "" |
|
755 |
|
|
756 |
#: ../larpe/admin/hosts.ptl:626 |
|
757 |
msgid "Go back and change your username and/or password" |
|
758 |
msgstr "" |
|
759 |
|
|
760 |
#: ../larpe/admin/hosts.ptl:632 ../larpe/admin/hosts.ptl:633 |
|
761 |
msgid "Authentication response" |
|
762 |
msgstr "" |
|
763 |
|
|
764 |
#: ../larpe/admin/hosts.ptl:635 |
|
765 |
msgid "Response of the request with good credentials" |
|
766 |
msgstr "" |
|
767 |
|
|
768 |
#: ../larpe/admin/hosts.ptl:638 ../larpe/admin/hosts.ptl:649 |
|
769 |
msgid "HTTP status code" |
|
770 |
msgstr "" |
|
771 |
|
|
772 |
#: ../larpe/admin/hosts.ptl:643 ../larpe/admin/hosts.ptl:654 |
|
773 |
msgid "See HTML page" |
|
774 |
msgstr "" |
|
775 |
|
|
776 |
#: ../larpe/admin/hosts.ptl:646 |
|
777 |
msgid "Response of the request with bad credentials" |
|
778 |
msgstr "" |
|
779 |
|
|
780 |
#: ../larpe/admin/hosts.ptl:675 ../larpe/admin/hosts.ptl:676 |
|
781 |
msgid "Authentication success criteria" |
|
782 |
msgstr "" |
|
783 |
|
|
784 |
#: ../larpe/admin/hosts.ptl:682 |
|
785 |
msgid "Authentication system of the original site" |
|
786 |
msgstr "" |
|
787 |
|
|
788 |
#: ../larpe/admin/hosts.ptl:684 |
|
789 |
msgid "Check the existence of a password field" |
|
790 |
msgstr "" |
|
791 |
|
|
792 |
#: ../larpe/admin/hosts.ptl:685 |
|
793 |
msgid "Match some text to detect an authentication failure" |
|
794 |
msgstr "" |
|
795 |
|
|
796 |
#: ../larpe/admin/hosts.ptl:690 |
|
797 |
msgid "Text to match in case of authentication failure" |
|
798 |
msgstr "" |
|
799 |
|
|
800 |
#: ../larpe/admin/hosts.ptl:704 |
|
801 |
msgid "Authentication request" |
|
802 |
msgstr "" |
|
803 |
|
|
804 |
#: ../larpe/admin/hosts.ptl:709 |
|
805 |
msgid "Modify POST parameters" |
|
806 |
msgstr "" |
|
807 |
|
|
808 |
#: ../larpe/admin/hosts.ptl:709 |
|
809 |
msgid "" |
|
810 |
"Configure the form attributes that will be sent within the authentication " |
|
811 |
"POST requests" |
|
812 |
msgstr "" |
|
813 |
|
|
814 |
#: ../larpe/admin/hosts.ptl:711 |
|
815 |
msgid "Modify HTTP headers" |
|
816 |
msgstr "" |
|
817 |
|
|
818 |
#: ../larpe/admin/hosts.ptl:711 |
|
819 |
msgid "Configure the HTTP headers of the authentication requests made by Larpe" |
|
820 |
msgstr "" |
|
821 |
|
|
822 |
#: ../larpe/admin/hosts.ptl:725 |
|
823 |
msgid "POST parameters" |
|
824 |
msgstr "" |
|
825 |
|
|
826 |
#: ../larpe/admin/hosts.ptl:726 |
|
827 |
msgid "Configure POST parameters" |
|
828 |
msgstr "" |
|
829 |
|
|
830 |
#: ../larpe/admin/hosts.ptl:728 |
|
831 |
msgid "" |
|
832 |
"Here are the detected form fields that will be sent as parameters of the\n" |
|
833 |
"authentication POST request. You can desactivate some or all of them, or " |
|
834 |
"change their value." |
|
835 |
msgstr "" |
|
836 |
|
|
837 |
#: ../larpe/admin/hosts.ptl:766 |
|
838 |
msgid "HTTP headers" |
|
839 |
msgstr "" |
|
840 |
|
|
841 |
#: ../larpe/admin/hosts.ptl:767 |
|
842 |
msgid "Configure HTTP headers" |
|
843 |
msgstr "" |
|
844 |
|
|
845 |
#: ../larpe/admin/hosts.ptl:769 |
|
846 |
msgid "" |
|
847 |
"Here are the HTTP headers that will be sent within the authentication\n" |
|
848 |
"POST request. You can desactivate some or all of them, or change their value." |
|
849 |
msgstr "" |
|
850 |
|
|
851 |
#: ../larpe/admin/hosts.ptl:782 |
|
852 |
msgid "" |
|
853 |
"The headers \"Host\", \"Accept-Encoding\" and \"Content-Length\" will also " |
|
854 |
"automatically be sent." |
|
855 |
msgstr "" |
|
856 |
|
|
857 |
#: ../larpe/admin/hosts.ptl:785 |
|
858 |
msgid "" |
|
859 |
"As Larpe uses a proxy for this site, the headers \"Proxy-Authorization\",\n" |
|
860 |
"\"Proxy-Connection\" and \"Keep-Alive\" will be sent as well." |
|
861 |
msgstr "" |
|
862 |
|
|
863 |
#: ../larpe/admin/hosts.ptl:846 |
|
864 |
msgid "SSO initiation" |
|
865 |
msgstr "" |
|
866 |
|
|
867 |
#: ../larpe/admin/hosts.ptl:847 |
|
868 |
msgid "Step 7 - Configure how a Single Sign On can be initiated" |
|
869 |
msgstr "" |
|
870 |
|
|
871 |
#: ../larpe/admin/hosts.ptl:849 |
|
872 |
msgid "" |
|
873 |
"Most sites use one of the following 2 ways to allow users to initialise an " |
|
874 |
"authentication :" |
|
875 |
msgstr "" |
|
876 |
|
|
877 |
#: ../larpe/admin/hosts.ptl:852 |
|
878 |
msgid "" |
|
879 |
"The site has a single authentication page. It redirects users to this page " |
|
880 |
"when\n" |
|
881 |
"they click a \"Login\" button or try to access a page which require users to " |
|
882 |
"be authenticated." |
|
883 |
msgstr "" |
|
884 |
|
|
885 |
#: ../larpe/admin/hosts.ptl:855 |
|
886 |
msgid "" |
|
887 |
"The site includes an authentication form in most or all of his pages. Users " |
|
888 |
"can\n" |
|
889 |
"authenticate on any of these pages, and don't need to be redirected to a " |
|
890 |
"separate authentication page." |
|
891 |
msgstr "" |
|
892 |
|
|
893 |
#: ../larpe/admin/hosts.ptl:860 |
|
894 |
msgid "Select the way your site works :" |
|
895 |
msgstr "" |
|
896 |
|
|
897 |
#: ../larpe/admin/hosts.ptl:868 |
|
898 |
msgid "The site has a single authentication page" |
|
899 |
msgstr "" |
|
900 |
|
|
901 |
#: ../larpe/admin/hosts.ptl:869 |
|
902 |
msgid "The site includes an authentication form in most or all pages" |
|
903 |
msgstr "" |
|
904 |
|
|
905 |
#: ../larpe/admin/hosts.ptl:900 |
|
906 |
msgid "Metadatas" |
|
907 |
msgstr "" |
|
908 |
|
|
909 |
#: ../larpe/admin/hosts.ptl:901 |
|
910 |
#, python-format |
|
911 |
msgid "Step 8 - Metadatas of %(site_name)s" |
|
912 |
msgstr "" |
|
913 |
|
|
914 |
#: ../larpe/admin/hosts.ptl:904 |
|
915 |
msgid "" |
|
916 |
"Download the metadatas and the public key for this site and\n" |
|
917 |
"upload them on your identity provider in order to use Liberty Alliance " |
|
918 |
"features." |
|
919 |
msgstr "" |
|
920 |
|
|
921 |
#: ../larpe/admin/hosts.ptl:914 |
|
922 |
msgid "Download SAML 2.0 metadata file" |
|
923 |
msgstr "" |
|
924 |
|
|
925 |
#: ../larpe/admin/hosts.ptl:919 |
|
926 |
msgid "Download ID-FF 1.2 metadata file" |
|
927 |
msgstr "" |
|
928 |
|
|
929 |
#: ../larpe/admin/hosts.ptl:921 |
|
930 |
msgid "No metadata has been generated for this host." |
|
931 |
msgstr "" |
|
932 |
|
|
933 |
#: ../larpe/admin/hosts.ptl:930 |
|
934 |
msgid "No public key has been generated for this host." |
|
935 |
msgstr "" |
|
936 |
|
|
937 |
#: ../larpe/admin/hosts.ptl:942 |
|
938 |
msgid "Advanced options" |
|
939 |
msgstr "" |
|
940 |
|
|
941 |
#: ../larpe/admin/hosts.ptl:943 |
|
942 |
msgid "Step 9 - Advanced options" |
|
943 |
msgstr "" |
|
944 |
|
|
945 |
#: ../larpe/admin/hosts.ptl:945 |
|
946 |
msgid "Configure advanced options to setup the last details of your site." |
|
947 |
msgstr "" |
|
948 |
|
|
949 |
#: ../larpe/admin/hosts.ptl:946 |
|
950 |
#, python-format |
|
951 |
msgid "" |
|
952 |
"If you don't know what to configure here, just click %(next)s and\n" |
|
953 |
"come here later if needed." |
|
954 |
msgstr "" |
|
955 |
|
|
956 |
#: ../larpe/admin/hosts.ptl:959 |
|
957 |
msgid "Redirect the root URL of the site to the login page." |
|
958 |
msgstr "" |
|
959 |
|
|
960 |
#: ../larpe/admin/hosts.ptl:961 |
|
961 |
msgid "Return address" |
|
962 |
msgstr "" |
|
963 |
|
|
964 |
#: ../larpe/admin/hosts.ptl:962 |
|
965 |
msgid "Where the user will be redirected after a successful authentication" |
|
966 |
msgstr "" |
|
967 |
|
|
968 |
#: ../larpe/admin/hosts.ptl:964 |
|
969 |
msgid "Error address" |
|
970 |
msgstr "" |
|
971 |
|
|
972 |
#: ../larpe/admin/hosts.ptl:965 |
|
973 |
msgid "Where the user will be redirected after a disconnection or an error" |
|
974 |
msgstr "" |
|
975 |
|
|
976 |
#: ../larpe/admin/hosts.ptl:967 |
|
977 |
msgid "URL which must initiate the SSO" |
|
978 |
msgstr "" |
|
979 |
|
|
980 |
#: ../larpe/admin/hosts.ptl:968 |
|
981 |
#, python-format |
|
982 |
msgid "" |
|
983 |
"Address which must initiate the SSO. If empty, defaults to the previously\n" |
|
984 |
"specified \"%s\"" |
|
985 |
msgstr "" |
|
986 |
|
|
987 |
#: ../larpe/admin/hosts.ptl:971 |
|
988 |
msgid "Apache HTML proxy" |
|
989 |
msgstr "" |
|
990 |
|
|
991 |
#: ../larpe/admin/hosts.ptl:972 |
|
992 |
msgid "" |
|
993 |
"Converts urls in the HTML pages according to the host new domain name.\n" |
|
994 |
"Disabled by default because it makes some sites not work correctly." |
|
995 |
msgstr "" |
|
996 |
|
|
997 |
#: ../larpe/admin/hosts.ptl:1003 ../larpe/admin/hosts.ptl:1024 |
|
998 |
msgid "Finish" |
|
999 |
msgstr "" |
|
1000 |
|
|
1001 |
#: ../larpe/admin/hosts.ptl:1011 |
|
1002 |
msgid "Check everything works" |
|
1003 |
msgstr "" |
|
1004 |
|
|
1005 |
#: ../larpe/admin/hosts.ptl:1012 |
|
1006 |
msgid "Step 10 - Check everything works" |
|
1007 |
msgstr "" |
|
1008 |
|
|
1009 |
#: ../larpe/admin/hosts.ptl:1015 |
|
1010 |
msgid "" |
|
1011 |
"Now you can fully test your site, start from the home page, initiate a\n" |
|
1012 |
"Single Sign On, federate your identities and do a Single Logout." |
|
1013 |
msgstr "" |
|
1014 |
|
|
1015 |
#: ../larpe/admin/hosts.ptl:1018 |
|
1016 |
msgid "The address of your site is : " |
|
1017 |
msgstr "" |
|
1018 |
|
|
1019 |
#: ../larpe/admin/hosts.ptl:1023 |
|
1020 |
#, python-format |
|
1021 |
msgid "" |
|
1022 |
"If everything works, click the \"%(finish)s\" button, otherwise you can go\n" |
|
1023 |
"back and check your settings." |
|
1024 |
msgstr "" |
|
1025 |
|
|
1026 |
#: ../larpe/admin/hosts.ptl:1136 ../larpe/admin/hosts.ptl:1151 |
|
1027 |
#: ../larpe/admin/hosts.ptl:1182 |
|
1028 |
msgid "(filled by users)" |
|
1029 |
msgstr "" |
|
1030 |
|
|
1031 |
#: ../larpe/admin/hosts.ptl:1233 |
|
1032 |
msgid "Configuration assistant" |
|
1033 |
msgstr "" |
|
1034 |
|
|
1035 |
#: ../larpe/admin/hosts.ptl:1238 |
|
1036 |
msgid "Address of the original site" |
|
1037 |
msgstr "" |
|
1038 |
|
|
1039 |
#: ../larpe/admin/hosts.ptl:1238 |
|
1040 |
msgid "Configure the root address of the site" |
|
1041 |
msgstr "" |
|
1042 |
|
|
1043 |
#: ../larpe/admin/hosts.ptl:1241 |
|
1044 |
msgid "New address and name" |
|
1045 |
msgstr "" |
|
1046 |
|
|
1047 |
#: ../larpe/admin/hosts.ptl:1241 |
|
1048 |
msgid "Configure the new address and name of this site" |
|
1049 |
msgstr "" |
|
1050 |
|
|
1051 |
#: ../larpe/admin/hosts.ptl:1244 |
|
1052 |
msgid "Authentication and logout addresses" |
|
1053 |
msgstr "" |
|
1054 |
|
|
1055 |
#: ../larpe/admin/hosts.ptl:1244 |
|
1056 |
msgid "Configure the authentication and logout addresses of the original site" |
|
1057 |
msgstr "" |
|
1058 |
|
|
1059 |
#: ../larpe/admin/hosts.ptl:1247 |
|
1060 |
msgid "Check auto detected configuration" |
|
1061 |
msgstr "" |
|
1062 |
|
|
1063 |
#: ../larpe/admin/hosts.ptl:1247 |
|
1064 |
msgid "Check the automatically detected configuration is right" |
|
1065 |
msgstr "" |
|
1066 |
|
|
1067 |
#: ../larpe/admin/hosts.ptl:1250 |
|
1068 |
msgid "Configure some valid credentials to authenticate on the original site" |
|
1069 |
msgstr "" |
|
1070 |
|
|
1071 |
#: ../larpe/admin/hosts.ptl:1253 |
|
1072 |
msgid "Retry authentication" |
|
1073 |
msgstr "" |
|
1074 |
|
|
1075 |
#: ../larpe/admin/hosts.ptl:1253 |
|
1076 |
msgid "" |
|
1077 |
"Retry sending an authentication request to the site to check if your new " |
|
1078 |
"parameters work well" |
|
1079 |
msgstr "" |
|
1080 |
|
|
1081 |
#: ../larpe/admin/hosts.ptl:1256 |
|
1082 |
msgid "Check authentication response" |
|
1083 |
msgstr "" |
|
1084 |
|
|
1085 |
#: ../larpe/admin/hosts.ptl:1256 |
|
1086 |
msgid "Check the response from the latest authentication request" |
|
1087 |
msgstr "" |
|
1088 |
|
|
1089 |
#: ../larpe/admin/hosts.ptl:1259 |
|
1090 |
msgid "Configure authentication success criteria" |
|
1091 |
msgstr "" |
|
1092 |
|
|
1093 |
#: ../larpe/admin/hosts.ptl:1259 |
|
1094 |
msgid "Specify how Larpe knows if the authentication has succeeded or not" |
|
1095 |
msgstr "" |
|
1096 |
|
|
1097 |
#: ../larpe/admin/hosts.ptl:1262 |
|
1098 |
msgid "Modify authentication request" |
|
1099 |
msgstr "" |
|
1100 |
|
|
1101 |
#: ../larpe/admin/hosts.ptl:1262 |
|
1102 |
msgid "Modify POST fields or HTTP headers of the authentication request" |
|
1103 |
msgstr "" |
|
1104 |
|
|
1105 |
#: ../larpe/admin/hosts.ptl:1265 |
|
1106 |
msgid "Configure how a Single Sign On can be initiated" |
|
1107 |
msgstr "" |
|
1108 |
|
|
1109 |
#: ../larpe/admin/hosts.ptl:1268 |
|
1110 |
msgid "Metadatas and key" |
|
1111 |
msgstr "" |
|
1112 |
|
|
1113 |
#: ../larpe/admin/hosts.ptl:1268 |
|
1114 |
msgid "Download SAML 2.0 or ID-FF metadatas and SSL public key" |
|
1115 |
msgstr "" |
|
1116 |
|
|
1117 |
#: ../larpe/admin/hosts.ptl:1271 |
|
1118 |
msgid "Adavanced options" |
|
1119 |
msgstr "" |
|
1120 |
|
|
1121 |
#: ../larpe/admin/hosts.ptl:1271 |
|
1122 |
msgid "Configure advanced options to setup the last details of your site" |
|
1123 |
msgstr "" |
|
1124 |
|
|
1125 |
#: ../larpe/admin/hosts.ptl:1275 |
|
1126 |
msgid "Form prefilling with ID-WSF" |
|
1127 |
msgstr "" |
|
1128 |
|
|
1129 |
#: ../larpe/admin/hosts.ptl:1279 |
|
1130 |
msgid "Configure the forms to prefill" |
|
1131 |
msgstr "" |
|
1132 |
|
|
1133 |
#: ../larpe/admin/hosts.ptl:1285 |
|
1134 |
msgid "You are about to irrevocably delete this host." |
|
1135 |
msgstr "" |
|
1136 |
|
|
1137 |
#: ../larpe/admin/hosts.ptl:1292 ../larpe/admin/hosts.ptl:1293 |
|
1138 |
msgid "Delete Host" |
|
1139 |
msgstr "" |
|
1140 |
|
|
1141 |
#: ../larpe/admin/hosts.ptl:1305 ../larpe/admin/hosts.ptl:1306 |
|
1142 |
#: ../larpe/admin/hosts.ptl:1343 ../larpe/admin/hosts.ptl:1350 |
|
1143 |
#: ../larpe/admin/root.ptl:44 |
|
1144 |
msgid "Hosts" |
|
1145 |
msgstr "" |
|
1146 |
|
|
1147 |
#: ../larpe/admin/hosts.ptl:1309 ../larpe/admin/hosts.ptl:1336 |
|
1148 |
#: ../larpe/admin/hosts.ptl:1337 |
|
1149 |
msgid "New Host" |
|
1150 |
msgstr "" |
|
1151 |
|
|
1152 |
#: ../larpe/admin/root.ptl:48 |
|
1153 |
msgid "Liberty Alliance Reverse Proxy" |
|
1154 |
msgstr "" |
|
1155 |
|
|
1156 |
#: ../larpe/admin/root.ptl:59 |
|
1157 |
msgid "Administration" |
|
1158 |
msgstr "" |
|
1159 |
|
|
1160 |
#: ../larpe/saml2.ptl:32 ../larpe/saml2.ptl:46 |
|
1161 |
msgid "SAML 2.0 support not yet configured." |
|
1162 |
msgstr "" |
|
1163 |
|
|
1164 |
#: ../larpe/saml2.ptl:53 |
|
1165 |
msgid "Missing SAML Artifact" |
|
1166 |
msgstr "" |
|
1167 |
|
|
1168 |
#: ../larpe/saml2.ptl:64 ../larpe/liberty.ptl:58 |
|
1169 |
msgid "Failure to communicate with identity provider" |
|
1170 |
msgstr "" |
|
1171 |
|
|
1172 |
#: ../larpe/saml2.ptl:70 ../larpe/liberty.ptl:63 |
|
1173 |
msgid "Unknown authentication failure" |
|
1174 |
msgstr "" |
|
1175 |
|
|
1176 |
#: ../larpe/saml2.ptl:72 ../larpe/liberty.ptl:66 |
|
1177 |
msgid "Authentication failure; unknown principal" |
|
1178 |
msgstr "" |
|
1179 |
|
|
1180 |
#: ../larpe/saml2.ptl:334 ../larpe/liberty.ptl:142 ../larpe/liberty.ptl:173 |
|
1181 |
msgid "Failed to check single logout request signature." |
|
1182 |
msgstr "" |
|
1183 |
|
|
1184 |
#: ../larpe/site_authentication.ptl:60 |
|
1185 |
msgid "Local authentication" |
|
1186 |
msgstr "" |
|
1187 |
|
|
1188 |
#: ../larpe/site_authentication.ptl:74 |
|
1189 |
msgid "Authentication failure" |
|
1190 |
msgstr "" |
|
1191 |
|
|
1192 |
#: ../larpe/site_authentication.ptl:77 |
|
1193 |
#, python-format |
|
1194 |
msgid "Connection failed : %s" |
|
1195 |
msgstr "" |
|
1196 |
|
|
1197 |
#: ../larpe/site_authentication.ptl:80 |
|
1198 |
#, python-format |
|
1199 |
msgid "This service provider is not fully configured : %s" |
|
1200 |
msgstr "" |
|
1201 |
|
|
1202 |
#: ../larpe/site_authentication.ptl:83 |
|
1203 |
#, python-format |
|
1204 |
msgid "Unknown error : %s" |
|
1205 |
msgstr "" |
|
1206 |
|
|
1207 |
#: ../larpe/site_authentication.ptl:89 |
|
1208 |
msgid "Please type your login and password for this Service Provider." |
|
1209 |
msgstr "" |
|
1210 |
|
|
1211 |
#: ../larpe/site_authentication.ptl:90 ../larpe/root.ptl:74 |
|
1212 |
msgid "" |
|
1213 |
"Your local account will be federated with your Liberty Alliance account." |
|
1214 |
msgstr "" |
|
1215 |
|
|
1216 |
#: ../larpe/site_authentication.ptl:296 |
|
1217 |
#, python-format |
|
1218 |
msgid "%s logout failed" |
|
1219 |
msgstr "" |
|
1220 |
|
|
1221 |
#: ../larpe/root.ptl:27 |
|
1222 |
msgid "Welcome to Larpe reverse proxy" |
|
1223 |
msgstr "" |
|
1224 |
|
|
1225 |
#: ../larpe/root.ptl:29 |
|
1226 |
msgid "Configure Larpe" |
|
1227 |
msgstr "" |
|
1228 |
|
|
1229 |
#: ../larpe/root.ptl:73 |
|
1230 |
msgid "Please enter your identification token. " |
|
1231 |
msgstr "" |
|
1232 |
|
|
1233 |
#: ../larpe/root.ptl:87 |
|
1234 |
msgid "Unknown Token" |
|
1235 |
msgstr "" |
|
1236 |
|
|
1237 |
#: ../larpe/liberty.ptl:45 |
|
1238 |
msgid "Liberty support is not yet configured" |
|
1239 |
msgstr "" |
|
1240 |
|
|
1241 |
#: ../larpe/liberty.ptl:67 |
|
1242 |
msgid "Identity Provider didn't accept artifact transaction." |
|
1243 |
msgstr "" |
|
1244 |
|
|
1245 |
#: ../larpe/users.py:38 |
|
1246 |
msgid "Unknown User" |
|
1247 |
msgstr "" |
larpe/tags/release-1.1.1/pylintrc | ||
---|---|---|
1 |
# lint Python modules using external checkers. |
|
2 |
# |
|
3 |
# This is the main checker controlling the other ones and the reports |
|
4 |
# generation. It is itself both a raw checker and an astng checker in order |
|
5 |
# to: |
|
6 |
# * handle message activation / deactivation at the module level |
|
7 |
# * handle some basic but necessary stats'data (number of classes, methods...) |
|
8 |
# |
|
9 |
[MASTER] |
|
10 |
|
|
11 |
# Specify a configuration file. |
|
12 |
#rcfile= |
|
13 |
|
|
14 |
# Python code to execute, usually for sys.path manipulation such as |
|
15 |
# pygtk.require(). |
|
16 |
#init-hook= |
|
17 |
|
|
18 |
# Profiled execution. |
|
19 |
profile=no |
|
20 |
|
|
21 |
# Add <file or directory> to the black list. It should be a base name, not a |
|
22 |
# path. You may set this option multiple times. |
|
23 |
ignore=.svn,qommon |
|
24 |
|
|
25 |
# Pickle collected data for later comparisons. |
|
26 |
persistent=yes |
|
27 |
|
|
28 |
# Set the cache size for astng objects. |
|
29 |
cache-size=500 |
|
30 |
|
|
31 |
# List of plugins (as comma separated values of python modules names) to load, |
|
32 |
# usually to register additional checkers. |
|
33 |
load-plugins= |
|
34 |
|
|
35 |
|
|
36 |
[MESSAGES CONTROL] |
|
37 |
|
|
38 |
# Enable only checker(s) with the given id(s). This option conflicts with the |
|
39 |
# disable-checker option |
|
40 |
#enable-checker= |
|
41 |
|
|
42 |
# Enable all checker(s) except those with the given id(s). This option |
|
43 |
# conflicts with the enable-checker option |
|
44 |
#disable-checker= |
|
45 |
|
|
46 |
# Enable all messages in the listed categories. |
|
47 |
#enable-msg-cat= |
|
48 |
|
|
49 |
# Disable all messages in the listed categories. |
|
50 |
#disable-msg-cat= |
|
51 |
|
|
52 |
# Enable the message(s) with the given id(s). |
|
53 |
#enable-msg= |
|
54 |
|
|
55 |
# Disable the message(s) with the given id(s). |
|
56 |
disable-msg=C0111,R0904,W0403 |
|
57 |
|
|
58 |
|
|
59 |
[REPORTS] |
|
60 |
|
|
61 |
# Set the output format. Available formats are text, parseable, colorized, msvs |
|
62 |
# (visual studio) and html |
|
63 |
output-format=text |
|
64 |
|
|
65 |
# Include message's id in output |
|
66 |
include-ids=yes |
|
67 |
|
|
68 |
# Put messages in a separate file for each module / package specified on the |
|
69 |
# command line instead of printing them on stdout. Reports (if any) will be |
|
70 |
# written in a file name "pylint_global.[txt|html]". |
|
71 |
files-output=no |
|
72 |
|
|
73 |
# Tells wether to display a full report or only the messages |
|
74 |
reports=no |
|
75 |
|
|
76 |
# Python expression which should return a note less than 10 (10 is the highest |
|
77 |
# note). You have access to the variables errors warning, statement which |
|
78 |
# respectivly contain the number of errors / warnings messages and the total |
|
79 |
# number of statements analyzed. This is used by the global evaluation report |
|
80 |
# (R0004). |
|
81 |
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) |
|
82 |
|
|
83 |
# Add a comment according to your evaluation note. This is used by the global |
|
84 |
# evaluation report (R0004). |
|
85 |
comment=no |
|
86 |
|
|
87 |
# Enable the report(s) with the given id(s). |
|
88 |
#enable-report= |
|
89 |
|
|
90 |
# Disable the report(s) with the given id(s). |
|
91 |
#disable-report= |
|
92 |
|
|
93 |
|
|
94 |
# try to find bugs in the code using type inference |
|
95 |
# |
|
96 |
[TYPECHECK] |
|
97 |
|
|
98 |
# Tells wether missing members accessed in mixin class should be ignored. A |
|
99 |
# mixin class is detected if its name ends with "mixin" (case insensitive). |
|
100 |
ignore-mixin-members=yes |
|
101 |
|
|
102 |
# List of classes names for which member attributes should not be checked |
|
103 |
# (useful for classes with attributes dynamicaly set). |
|
104 |
ignored-classes=SQLObject |
|
105 |
|
|
106 |
# When zope mode is activated, add a predefined set of Zope acquired attributes |
|
107 |
# to generated-members. |
|
108 |
zope=no |
|
109 |
|
|
110 |
# List of members which are set dynamically and missed by pylint inference |
|
111 |
# system, and so shouldn't trigger E0201 when accessed. |
|
112 |
generated-members=REQUEST,acl_users,aq_parent |
|
113 |
|
|
114 |
|
|
115 |
# checks for |
|
116 |
# * unused variables / imports |
|
117 |
# * undefined variables |
|
118 |
# * redefinition of variable from builtins or from an outer scope |
|
119 |
# * use of variable before assigment |
|
120 |
# |
|
121 |
[VARIABLES] |
|
122 |
|
|
123 |
# Tells wether we should check for unused import in __init__ files. |
|
124 |
init-import=no |
|
125 |
|
|
126 |
# A regular expression matching names used for dummy variables (i.e. not used). |
|
127 |
dummy-variables-rgx=_|dummy |
|
128 |
|
|
129 |
# List of additional names supposed to be defined in builtins. Remember that |
|
130 |
# you should avoid to define new builtins when possible. |
|
131 |
additional-builtins= |
|
132 |
|
|
133 |
|
|
134 |
# checks for : |
|
135 |
# * doc strings |
|
136 |
# * modules / classes / functions / methods / arguments / variables name |
|
137 |
# * number of arguments, local variables, branchs, returns and statements in |
|
138 |
# functions, methods |
|
139 |
# * required module attributes |
|
140 |
# * dangerous default values as arguments |
|
141 |
# * redefinition of function / method / class |
|
142 |
# * uses of the global statement |
|
143 |
# |
|
144 |
[BASIC] |
|
145 |
|
|
146 |
# Required attributes for module, separated by a comma |
|
147 |
required-attributes= |
|
148 |
|
|
149 |
# Regular expression which should only match functions or classes name which do |
|
150 |
# not require a docstring |
|
151 |
no-docstring-rgx=__.*__ |
|
152 |
|
|
153 |
# Regular expression which should only match correct module names |
|
154 |
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ |
|
155 |
|
|
156 |
# Regular expression which should only match correct module level names |
|
157 |
#const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ |
|
158 |
const-rgx=[a-z\_][a-z0-9\_]{2,30}$ |
|
159 |
|
|
160 |
# Regular expression which should only match correct class names |
|
161 |
class-rgx=[A-Z_][a-zA-Z0-9]+$ |
|
162 |
|
|
163 |
# Regular expression which should only match correct function names |
|
164 |
function-rgx=[a-z_][a-z0-9_]{2,30}$ |
|
165 |
|
|
166 |
# Regular expression which should only match correct method names |
|
167 |
method-rgx=[a-z_][a-z0-9_]{2,30}$ |
|
168 |
|
|
169 |
# Regular expression which should only match correct instance attribute names |
|
170 |
attr-rgx=[a-z_][a-z0-9_]{2,30}$ |
|
171 |
|
|
172 |
# Regular expression which should only match correct argument names |
|
173 |
argument-rgx=[a-z_][a-z0-9_]{2,30}$ |
|
174 |
|
|
175 |
# Regular expression which should only match correct variable names |
|
176 |
variable-rgx=[a-z_][a-z0-9_]{2,30}$ |
|
177 |
|
|
178 |
# Regular expression which should only match correct list comprehension / |
|
179 |
# generator expression variable names |
|
180 |
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ |
|
181 |
|
|
182 |
# Good variable names which should always be accepted, separated by a comma |
|
183 |
good-names=i,j,k,ex,Run,_ |
|
184 |
|
|
185 |
# Bad variable names which should always be refused, separated by a comma |
|
186 |
bad-names=foo,bar,baz,toto,tutu,tata |
|
187 |
|
|
188 |
# List of builtins function names that should not be used, separated by a comma |
|
189 |
bad-functions=map,filter,apply,input |
|
190 |
|
|
191 |
|
|
192 |
# checks for sign of poor/misdesign: |
|
193 |
# * number of methods, attributes, local variables... |
|
194 |
# * size, complexity of functions, methods |
|
195 |
# |
|
196 |
[DESIGN] |
|
197 |
|
|
198 |
# Maximum number of arguments for function / method |
|
199 |
max-args=5 |
|
200 |
|
|
201 |
# Maximum number of locals for function / method body |
|
202 |
max-locals=15 |
|
203 |
|
|
204 |
# Maximum number of return / yield for function / method body |
|
205 |
max-returns=6 |
|
206 |
|
|
207 |
# Maximum number of branch for function / method body |
|
208 |
max-branchs=12 |
|
209 |
|
|
210 |
# Maximum number of statements in function / method body |
|
211 |
max-statements=50 |
|
212 |
|
|
213 |
# Maximum number of parents for a class (see R0901). |
|
214 |
max-parents=7 |
|
215 |
|
|
216 |
# Maximum number of attributes for a class (see R0902). |
|
217 |
max-attributes=7 |
|
218 |
|
|
219 |
# Minimum number of public methods for a class (see R0903). |
|
220 |
min-public-methods=2 |
|
221 |
|
|
222 |
# Maximum number of public methods for a class (see R0904). |
|
223 |
max-public-methods=20 |
|
224 |
|
|
225 |
|
|
226 |
# checks for : |
|
227 |
# * methods without self as first argument |
|
228 |
# * overridden methods signature |
|
229 |
# * access only to existant members via self |
|
230 |
# * attributes not defined in the __init__ method |
|
231 |
# * supported interfaces implementation |
|
232 |
# * unreachable code |
|
233 |
# |
|
234 |
[CLASSES] |
|
235 |
|
|
236 |
# List of interface methods to ignore, separated by a comma. This is used for |
|
237 |
# instance to not check methods defines in Zope's Interface base class. |
|
238 |
ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by |
|
239 |
|
|
240 |
# List of method names used to declare (i.e. assign) instance attributes. |
|
241 |
defining-attr-methods=__init__,__new__,setUp |
|
242 |
|
|
243 |
|
|
244 |
# checks for |
|
245 |
# * external modules dependencies |
|
246 |
# * relative / wildcard imports |
|
247 |
# * cyclic imports |
|
248 |
# * uses of deprecated modules |
|
249 |
# |
|
250 |
[IMPORTS] |
|
251 |
|
|
252 |
# Deprecated modules which should not be used, separated by a comma |
|
253 |
deprecated-modules=regsub,string,TERMIOS,Bastion,rexec |
|
254 |
|
|
255 |
# Create a graph of every (i.e. internal and external) dependencies in the |
|
256 |
# given file (report R0402 must not be disabled) |
|
257 |
import-graph= |
|
258 |
|
|
259 |
# Create a graph of external dependencies in the given file (report R0402 must |
|
260 |
# not be disabled) |
|
261 |
ext-import-graph= |
|
262 |
|
|
263 |
# Create a graph of internal dependencies in the given file (report R0402 must |
|
264 |
# not be disabled) |
|
265 |
int-import-graph= |
|
266 |
|
|
267 |
|
|
268 |
# checks for : |
|
269 |
# * unauthorized constructions |
|
270 |
# * strict indentation |
|
271 |
# * line length |
|
272 |
# * use of <> instead of != |
|
273 |
# |
|
274 |
[FORMAT] |
|
275 |
|
|
276 |
# Maximum number of characters on a single line. |
|
277 |
max-line-length=100 |
|
278 |
|
|
279 |
# Maximum number of lines in a module |
|
280 |
max-module-lines=1000 |
|
281 |
|
|
282 |
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 |
|
283 |
# tab). |
|
284 |
indent-string=' ' |
|
285 |
|
|
286 |
|
|
287 |
# checks for similarities and duplicated code. This computation may be |
|
288 |
# memory / CPU intensive, so you should disable it if you experiments some |
|
289 |
# problems. |
|
290 |
# |
|
291 |
[SIMILARITIES] |
|
292 |
|
|
293 |
# Minimum lines number of a similarity. |
|
294 |
min-similarity-lines=4 |
|
295 |
|
|
296 |
# Ignore comments when computing similarities. |
|
297 |
ignore-comments=yes |
|
298 |
|
|
299 |
# Ignore docstrings when computing similarities. |
|
300 |
ignore-docstrings=yes |
|
301 |
|
|
302 |
|
|
303 |
# checks for: |
|
304 |
# * warning notes in the code like FIXME, XXX |
|
305 |
# * PEP 263: source code with non ascii character but no encoding declaration |
|
306 |
# |
|
307 |
[MISCELLANEOUS] |
|
308 |
|
|
309 |
# List of note tags to take in consideration, separated by a comma. |
|
310 |
notes=FIXME,XXX,TODO |
larpe/tags/release-1.1.1/root/index.html | ||
---|---|---|
1 |
<html xmlns="http://www.w3.org/1999/xhtml"> |
|
2 |
<head> |
|
3 |
<title>Larpe</title> |
|
4 |
<link rel="stylesheet" type="text/css" href="/css/larpe.css"/> |
|
5 |
<style type="text/css"> |
|
6 |
p#larpe { |
|
7 |
margin-top: 30%; |
|
8 |
text-align: center; |
|
9 |
font-weight: bold; |
|
10 |
} |
|
11 |
</style> |
|
12 |
</head> |
|
13 |
<body> |
|
14 |
<p id="larpe"> |
|
15 |
Larpe |
|
16 |
</p> |
|
17 |
</body> |
|
18 |
</html> |
larpe/tags/release-1.1.1/root/larpe/css/dc2/admin.css | ||
---|---|---|
1 |
@import url(../larpe-common.css); |
|
2 |
|
|
3 |
html, body { |
|
4 |
margin: 0; |
|
5 |
background: white url(page-bg.png) repeat-y; |
|
6 |
} |
|
7 |
|
|
8 |
div#main-content { |
|
9 |
margin-left: 160px; |
|
10 |
margin-top: -10px; |
|
11 |
margin-right: 20px; |
|
12 |
} |
|
13 |
|
|
14 |
div#main-content h1 { |
|
15 |
color: #006699; |
|
16 |
font-size: 120%; |
|
17 |
} |
|
18 |
|
|
19 |
div#main-content h2 { |
|
20 |
color: #006699; |
|
21 |
font-size: 115%; |
|
22 |
} |
|
23 |
|
|
24 |
div#main-content h3 { |
|
25 |
color: #006699; |
|
26 |
font-size: 108% |
|
27 |
} |
|
28 |
|
|
29 |
|
|
30 |
|
|
31 |
div#header { |
|
32 |
margin: 0; |
|
33 |
background: white url(head-bg.png) repeat-x; |
|
34 |
height: 58px; |
|
35 |
} |
|
36 |
|
|
37 |
ul#menu { |
|
38 |
background: transparent url(head-logo.png) no-repeat; |
|
39 |
width: 177px; |
|
40 |
margin: 0; |
|
41 |
padding: 80px 0 0 5px; |
|
42 |
} |
|
43 |
|
|
44 |
a { |
|
45 |
color: #0066cc; |
|
46 |
text-decoration: none; |
|
47 |
border-bottom: 1px dotted #ff9900; |
|
48 |
} |
|
49 |
|
|
50 |
p.commands a { |
|
51 |
border: 0; |
|
52 |
} |
|
53 |
|
|
54 |
ul#menu a { |
|
55 |
font-weight: bold; |
|
56 |
} |
|
57 |
|
|
58 |
ul#menu li.active a { |
|
59 |
border-bottom: 1px solid #ff9900; |
|
60 |
} |
|
61 |
|
|
62 |
ul#menu li { |
|
63 |
font-size: 90%; |
|
64 |
margin-bottom: 1em; |
|
65 |
max-width: 130px; |
|
66 |
} |
|
67 |
|
|
68 |
div#footer { |
|
69 |
display: none; |
|
70 |
} |
|
71 |
|
|
72 |
ul.user-info { |
|
73 |
position: absolute; |
|
74 |
margin: 0; |
|
75 |
padding: 0; |
|
76 |
right: 25px; |
|
77 |
top: 13px; |
|
78 |
font-size: 70%; |
|
79 |
font-weight: bold; |
|
80 |
} |
|
81 |
|
|
82 |
ul.user-info li { |
|
83 |
display: inline; |
|
84 |
padding-left: 10px; |
|
85 |
} |
|
86 |
|
|
87 |
/** end of dc2 changes **/ |
|
88 |
|
|
89 |
|
|
90 |
|
|
91 |
ul.biglist { |
|
92 |
margin: 0; |
|
93 |
padding: 0; |
|
94 |
} |
|
95 |
|
|
96 |
ul.biglist li { |
|
97 |
list-style-type: none; |
|
98 |
margin: 4px 0; |
|
99 |
padding: 0 2px; |
|
100 |
border: 1px solid #888; |
|
101 |
background: #ffe; |
|
102 |
clear: both; |
|
103 |
} |
|
104 |
|
|
105 |
ul.biglist li p.details { |
|
106 |
display: block; |
|
107 |
margin: 0; |
|
108 |
color: #555; |
|
109 |
font-size: 80%; |
|
110 |
} |
|
111 |
|
|
112 |
|
|
113 |
ul.biglist li p.commands { |
|
114 |
float: right; |
|
115 |
margin-top: -17px; |
|
116 |
} |
|
117 |
|
|
118 |
ul.biglist li p.commands img { |
|
119 |
padding-right: 5px; |
|
120 |
} |
|
121 |
|
|
122 |
a img { |
|
123 |
border: 0; |
|
124 |
} |
|
125 |
|
|
126 |
td.time { |
|
127 |
text-align: right; |
|
128 |
} |
|
129 |
|
|
130 |
ul.biglist li.disabled, ul.biglist li.disabled p.details { |
|
131 |
color: #999; |
|
132 |
background: #ddd; |
|
133 |
} |
|
134 |
|
|
135 |
|
|
136 |
dl dt { |
|
137 |
margin : 0; |
|
138 |
padding : 0 0 0 0; |
|
139 |
} |
|
140 |
|
|
141 |
dl dd { |
|
142 |
margin : 0.3em 0 1.5em 10px; |
|
143 |
} |
|
144 |
|
|
145 |
|
|
146 |
img.theme-icon { |
|
147 |
float: right; |
|
148 |
margin: -16px 4px 0px 3px; |
|
149 |
border: 1px solid #999; |
|
150 |
} |
|
151 |
|
|
152 |
div#new-field table { |
|
153 |
margin: 0; |
|
154 |
padding: 0; |
|
155 |
} |
|
156 |
|
|
157 |
div#new-field div.widget { |
|
158 |
margin: 0; |
|
159 |
padding: 0; |
|
160 |
} |
|
161 |
|
|
162 |
div#new-field div.buttons { |
|
163 |
margin: 0; |
|
164 |
padding: 0; |
|
165 |
} |
|
166 |
|
|
167 |
div#new-field div.buttons input { |
|
168 |
margin: 0; |
|
169 |
padding: 0; |
|
170 |
} |
|
171 |
|
|
172 |
div#new-field { |
|
173 |
border: 1px solid #888; |
|
174 |
background: #ffe; |
|
175 |
margin: 2em 0 4px 0; |
|
176 |
padding: 0 2px; |
|
177 |
} |
|
178 |
|
|
179 |
div#new-field div.widget { |
|
180 |
} |
|
181 |
|
|
182 |
div#new-field h3 { |
|
183 |
margin: 0; |
|
184 |
font-size: 100%; |
|
185 |
} |
|
186 |
|
|
187 |
div#new-field br { |
|
188 |
display: none; |
|
189 |
} |
|
190 |
|
|
191 |
div#new-field p.commands { |
|
192 |
float: right; |
|
193 |
margin-top: -17px; |
|
194 |
margin-right: 3px; |
|
195 |
} |
|
196 |
|
|
197 |
div.WorkflowStatusWidget { |
|
198 |
border-left: 1px solid black; |
|
199 |
} |
|
200 |
|
|
201 |
p#breadcrumb { |
|
202 |
background: #e6e6e6; |
|
203 |
-moz-border-radius: 6px; |
|
204 |
padding: 3px 8px; |
|
205 |
font-size: 80%; |
|
206 |
border: 1px solid #bfbfbf; |
|
207 |
} |
|
208 |
|
|
209 |
/** steps **/ |
|
210 |
#steps { |
|
211 |
height: 32px; |
|
212 |
margin-bottom: 1em; |
|
213 |
background: #f0f0f0; |
|
214 |
color: #aaa; |
|
215 |
} |
|
216 |
|
|
217 |
#steps ol { |
|
218 |
list-style: none; |
|
219 |
padding: 0 20px; |
|
220 |
} |
|
221 |
|
|
222 |
#steps li { |
|
223 |
display: inline; |
|
224 |
padding-right: 1em; |
|
225 |
display: block; |
|
226 |
float: left; |
|
227 |
width: 30%; |
|
228 |
list-style: none; |
|
229 |
} |
|
230 |
|
|
231 |
#steps ol ul { |
|
232 |
display: none; |
|
233 |
} |
|
234 |
|
|
235 |
#steps span.marker { |
|
236 |
font-size: 26px; |
|
237 |
padding: 2px 9px; |
|
238 |
font-weight: bold; |
|
239 |
color: white; |
|
240 |
text-align: center; |
|
241 |
background: #ddd; |
|
242 |
border: 1px solid #ddd; |
|
243 |
-moz-border-radius: 0.7ex; |
|
244 |
} |
|
245 |
|
|
246 |
#steps li.current span.marker { |
|
247 |
background: #ffa500; |
|
248 |
border: 1px solid #ffc400; |
|
249 |
} |
|
250 |
|
|
251 |
#steps span.label { |
|
252 |
font-size: 90%; |
|
253 |
} |
|
254 |
|
|
255 |
#steps li.current span.label { |
|
256 |
color: black; |
|
257 |
} |
|
258 |
|
|
259 |
#steps ol ul { |
|
260 |
display: none; |
|
261 |
} |
|
262 |
|
|
263 |
|
|
264 |
/** logs **/ |
|
265 |
form#other-log-select { |
|
266 |
margin-top: 2em; |
|
267 |
padding-top: 1em; |
|
268 |
border-top: 1px solid #999; |
|
269 |
} |
|
270 |
|
|
271 |
form#other-log-select select { |
|
272 |
margin: 0 1em; |
|
273 |
} |
|
274 |
|
|
275 |
tr.level-error td { |
|
276 |
border: 1px solid #800; |
|
277 |
background: red; |
|
278 |
} |
|
279 |
|
|
280 |
tr.level-error td.message { |
|
281 |
font-weight: bold; |
|
282 |
} |
|
283 |
|
larpe/tags/release-1.1.1/root/larpe/css/jscalendar/aqua/theme.css | ||
---|---|---|
1 |
/* Distributed as part of The Coolest DHTML Calendar |
|
2 |
Author: Mihai Bazon, www.bazon.net/mishoo |
|
3 |
Copyright Dynarch.com 2005, www.dynarch.com |
|
4 |
*/ |
|
5 |
|
|
6 |
/* The main calendar widget. DIV containing a table. */ |
|
7 |
|
|
8 |
div.calendar { position: relative; } |
|
9 |
|
|
10 |
.calendar, .calendar table { |
|
11 |
border: 1px solid #bdb2bf; |
|
12 |
font-size: 11px; |
|
13 |
color: #000; |
|
14 |
cursor: default; |
|
15 |
background: url("/css/jscalendar/aqua/normal-bg.gif"); |
|
16 |
font-family: "trebuchet ms",verdana,tahoma,sans-serif; |
|
17 |
} |
|
18 |
|
|
19 |
.calendar { |
|
20 |
border-color: #797979; |
|
21 |
} |
|
22 |
|
|
23 |
/* Header part -- contains navigation buttons and day names. */ |
|
24 |
|
|
25 |
.calendar .button { /* "<<", "<", ">", ">>" buttons have this class */ |
|
26 |
text-align: center; /* They are the navigation buttons */ |
|
27 |
padding: 2px; /* Make the buttons seem like they're pressing */ |
|
28 |
background: url("/css/jscalendar/aqua/title-bg.gif") repeat-x 0 100%; color: #000; |
|
29 |
font-weight: bold; |
|
30 |
} |
|
31 |
|
|
32 |
.calendar .nav { |
|
33 |
font-family: verdana,tahoma,sans-serif; |
|
34 |
} |
|
35 |
|
|
36 |
.calendar .nav div { |
|
37 |
background: transparent url("/css/jscalendar/aqua/menuarrow.gif") no-repeat 100% 100%; |
|
38 |
} |
|
39 |
|
|
40 |
.calendar thead tr { background: url("/css/jscalendar/aqua/title-bg.gif") repeat-x 0 100%; color: #000; } |
|
41 |
|
|
42 |
.calendar thead .title { /* This holds the current "month, year" */ |
|
43 |
font-weight: bold; /* Pressing it will take you to the current date */ |
|
44 |
text-align: center; |
|
45 |
padding: 2px; |
|
46 |
background: url("/css/jscalendar/aqua/title-bg.gif") repeat-x 0 100%; color: #000; |
|
47 |
} |
|
48 |
|
|
49 |
.calendar thead .headrow { /* Row <TR> containing navigation buttons */ |
|
50 |
} |
|
51 |
|
|
52 |
.calendar thead .name { /* Cells <TD> containing the day names */ |
|
53 |
border-bottom: 1px solid #797979; |
|
54 |
padding: 2px; |
|
55 |
text-align: center; |
|
56 |
color: #000; |
|
57 |
} |
|
58 |
|
|
59 |
.calendar thead .weekend { /* How a weekend day name shows in header */ |
|
60 |
color: #c44; |
|
61 |
} |
|
62 |
|
|
63 |
.calendar thead .hilite { /* How do the buttons in header appear when hover */ |
|
64 |
background: url("/css/jscalendar/aqua/hover-bg.gif"); |
|
65 |
border-bottom: 1px solid #797979; |
|
66 |
padding: 2px 2px 1px 2px; |
|
67 |
} |
|
68 |
|
|
69 |
.calendar thead .active { /* Active (pressed) buttons in header */ |
|
70 |
background: url("/css/jscalendar/aqua/active-bg.gif"); color: #fff; |
|
71 |
padding: 3px 1px 0px 3px; |
|
72 |
border-bottom: 1px solid #797979; |
|
73 |
} |
|
74 |
|
|
75 |
.calendar thead .daynames { /* Row <TR> containing the day names */ |
|
76 |
background: url("/css/jscalendar/aqua/dark-bg.gif"); |
|
77 |
} |
|
78 |
|
|
79 |
/* The body part -- contains all the days in month. */ |
|
80 |
|
|
81 |
.calendar tbody .day { /* Cells <TD> containing month days dates */ |
|
82 |
font-family: verdana,tahoma,sans-serif; |
|
83 |
width: 2em; |
|
84 |
color: #000; |
|
85 |
text-align: right; |
|
86 |
padding: 2px 4px 2px 2px; |
|
87 |
} |
|
88 |
.calendar tbody .day.othermonth { |
|
89 |
font-size: 80%; |
|
90 |
color: #999; |
|
91 |
} |
|
92 |
.calendar tbody .day.othermonth.oweekend { |
|
93 |
color: #f99; |
|
94 |
} |
|
95 |
|
|
96 |
.calendar table .wn { |
|
97 |
padding: 2px 3px 2px 2px; |
|
98 |
border-right: 1px solid #797979; |
|
99 |
background: url("/css/jscalendar/aqua/dark-bg.gif"); |
|
100 |
} |
|
101 |
|
|
102 |
.calendar tbody .rowhilite td, |
|
103 |
.calendar tbody .rowhilite td.wn { |
|
104 |
background: url("/css/jscalendar/aqua/rowhover-bg.gif"); |
|
105 |
} |
|
106 |
|
|
107 |
.calendar tbody td.today { font-weight: bold; /* background: url("/css/jscalendar/aqua/today-bg.gif") no-repeat 70% 50%; */ } |
|
108 |
|
|
109 |
.calendar tbody td.hilite { /* Hovered cells <TD> */ |
|
110 |
background: url("/css/jscalendar/aqua/hover-bg.gif"); |
|
111 |
padding: 1px 3px 1px 1px; |
|
112 |
border: 1px solid #bbb; |
|
113 |
} |
|
114 |
|
|
115 |
.calendar tbody td.active { /* Active (pressed) cells <TD> */ |
|
116 |
padding: 2px 2px 0px 2px; |
|
117 |
} |
|
118 |
|
|
119 |
.calendar tbody td.weekend { /* Cells showing weekend days */ |
|
120 |
color: #c44; |
|
121 |
} |
|
122 |
|
|
123 |
.calendar tbody td.selected { /* Cell showing selected date */ |
|
124 |
font-weight: bold; |
|
125 |
border: 1px solid #797979; |
|
126 |
padding: 1px 3px 1px 1px; |
|
127 |
background: url("/css/jscalendar/aqua/active-bg.gif"); color: #fff; |
|
128 |
} |
|
129 |
|
|
130 |
.calendar tbody .disabled { color: #999; } |
|
131 |
|
|
132 |
.calendar tbody .emptycell { /* Empty cells (the best is to hide them) */ |
|
133 |
visibility: hidden; |
|
134 |
} |
|
135 |
|
|
136 |
.calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */ |
|
137 |
display: none; |
|
138 |
} |
|
139 |
|
|
140 |
/* The footer part -- status bar and "Close" button */ |
|
141 |
|
|
142 |
.calendar tfoot .footrow { /* The <TR> in footer (only one right now) */ |
|
143 |
text-align: center; |
|
144 |
background: #565; |
|
145 |
color: #fff; |
|
146 |
} |
|
147 |
|
|
148 |
.calendar tfoot .ttip { /* Tooltip (status bar) cell <TD> */ |
|
149 |
padding: 2px; |
|
150 |
background: url("/css/jscalendar/aqua/status-bg.gif") repeat-x 0 0; color: #000; |
|
151 |
} |
|
152 |
|
|
153 |
.calendar tfoot .hilite { /* Hover style for buttons in footer */ |
|
154 |
background: #afa; |
|
155 |
border: 1px solid #084; |
|
156 |
color: #000; |
|
157 |
padding: 1px; |
|
158 |
} |
|
159 |
|
|
160 |
.calendar tfoot .active { /* Active (pressed) style for buttons in footer */ |
|
161 |
background: #7c7; |
|
162 |
padding: 2px 0px 0px 2px; |
|
163 |
} |
|
164 |
|
|
165 |
/* Combo boxes (menus that display months/years for direct selection) */ |
|
166 |
|
|
167 |
.calendar .combo { |
|
168 |
position: absolute; |
|
169 |
display: none; |
|
170 |
top: 0px; |
|
171 |
left: 0px; |
|
172 |
width: 4em; |
|
173 |
cursor: default; |
|
174 |
border-width: 0 1px 1px 1px; |
|
175 |
border-style: solid; |
|
176 |
border-color: #797979; |
|
177 |
background: url("/css/jscalendar/aqua/normal-bg.gif"); color: #000; |
|
178 |
z-index: 100; |
|
179 |
font-size: 90%; |
|
180 |
} |
|
181 |
|
|
182 |
.calendar .combo .label, |
|
183 |
.calendar .combo .label-IEfix { |
|
184 |
text-align: center; |
|
185 |
padding: 1px; |
|
186 |
} |
|
187 |
|
|
188 |
.calendar .combo .label-IEfix { |
|
189 |
width: 4em; |
|
190 |
} |
|
191 |
|
|
192 |
.calendar .combo .hilite { |
|
193 |
background: url("/css/jscalendar/aqua/hover-bg.gif"); color: #000; |
|
194 |
} |
|
195 |
|
|
196 |
.calendar .combo .active { |
|
197 |
background: url("/css/jscalendar/aqua/active-bg.gif"); color: #fff; |
|
198 |
font-weight: bold; |
|
199 |
} |
|
200 |
|
|
201 |
.calendar td.time { |
|
202 |
border-top: 1px solid #797979; |
|
203 |
padding: 1px 0px; |
|
204 |
text-align: center; |
|
205 |
background: url("/css/jscalendar/aqua/dark-bg.gif"); |
|
206 |
} |
|
207 |
|
|
208 |
.calendar td.time .hour, |
|
209 |
.calendar td.time .minute, |
|
210 |
.calendar td.time .ampm { |
|
211 |
padding: 0px 5px 0px 6px; |
|
212 |
font-weight: bold; |
|
213 |
background: url("/css/jscalendar/aqua/normal-bg.gif"); color: #000; |
|
214 |
} |
|
215 |
|
|
216 |
.calendar td.time .hour, |
|
217 |
.calendar td.time .minute { |
|
218 |
font-family: monospace; |
|
219 |
} |
|
220 |
|
|
221 |
.calendar td.time .ampm { |
|
222 |
text-align: center; |
|
223 |
} |
|
224 |
|
|
225 |
.calendar td.time .colon { |
|
226 |
padding: 0px 2px 0px 3px; |
|
227 |
font-weight: bold; |
|
228 |
} |
|
229 |
|
|
230 |
.calendar td.time span.hilite { |
|
231 |
background: url("/css/jscalendar/aqua/hover-bg.gif"); color: #000; |
|
232 |
} |
|
233 |
|
|
234 |
.calendar td.time span.active { |
|
235 |
background: url("/css/jscalendar/aqua/active-bg.gif"); color: #fff; |
|
236 |
} |
larpe/tags/release-1.1.1/root/larpe/css/larpe-admin.css | ||
---|---|---|
1 |
@import url(larpe-common.css); |
|
2 |
|
|
3 |
body { |
|
4 |
font-family: sans-serif; |
|
5 |
background : white url(fond.jpg) repeat; |
|
6 |
} |
|
7 |
|
|
8 |
div#main-content { |
|
9 |
clear: both; |
|
10 |
max-width: 800px; |
|
11 |
margin: 0 4em; |
|
12 |
background: white url(deg-top.png) top left repeat-x; |
|
13 |
border: 1px solid #999; |
|
14 |
padding: 1em; |
|
15 |
} |
|
16 |
|
|
17 |
div#main-content h1 { |
|
18 |
margin: 0 140px 1em 0; |
|
19 |
border: 1px solid #666; |
|
20 |
padding: 0 0.5ex; |
|
21 |
background: white url(bg-footer.png) top right repeat-y; |
|
22 |
font-size: 150%; |
|
23 |
} |
|
24 |
|
|
25 |
#header { |
|
26 |
max-width: 800px; |
|
27 |
margin: 0 4em; |
|
28 |
padding: 0 1em; |
|
29 |
background-image : url(dot999.png); |
|
30 |
background-repeat : repeat-x; |
|
31 |
background-position : 0 100%; |
|
32 |
position: relative; |
|
33 |
top: 1px; |
|
34 |
} |
|
35 |
|
|
36 |
#header ul { |
|
37 |
margin : 0; |
|
38 |
padding : 0; |
|
39 |
list-style : none; |
|
40 |
} |
|
41 |
|
|
42 |
#header li { |
|
43 |
float : left; |
|
44 |
margin : 0 -1px 0 0; |
|
45 |
padding : 0 0 0 8px; |
|
46 |
background-repeat : no-repeat; |
|
47 |
background-position : 0 -110px; |
|
48 |
background-image: url(onglet_left.png); |
|
49 |
border-bottom: 1px solid #999; |
|
50 |
} |
|
51 |
#header a { |
|
52 |
float : left; |
|
53 |
display : block; |
|
54 |
background-image : url(onglet_right.png); |
|
55 |
background-repeat : no-repeat; |
|
56 |
background-position : 100% -110px; |
|
57 |
padding : 10px 10px 4px 3px; |
|
58 |
font-weight : bold; |
|
59 |
text-decoration : none; |
|
60 |
color : #000; |
|
61 |
} |
|
62 |
|
|
63 |
/* Commented Backslash Hack |
|
64 |
Cache des règles à IE5-Mac \*/ |
|
65 |
#header a {float:none;} |
|
66 |
/* Fin du hack IE5-Mac */ |
|
67 |
|
|
68 |
#header li.active, #header li.active:hover { |
|
69 |
background-position : 0 0; |
|
70 |
} |
|
71 |
#header li.active a, #header li.active:hover a { |
|
72 |
background-position : 100% 0; |
|
73 |
} |
|
74 |
#header li:hover { |
|
75 |
background-position : 0 -220px; |
|
76 |
} |
|
77 |
#header li:hover a { |
|
78 |
background-position : 100% -220px; |
|
79 |
} |
|
80 |
|
|
81 |
#header li.active { |
|
82 |
border-bottom: 1px solid #eceade; |
|
83 |
} |
|
84 |
|
|
85 |
/* |
|
86 |
#header li.inactive, |
|
87 |
#header li.inactive:hover { |
|
88 |
background-position: 0 0; |
|
89 |
} |
|
90 |
|
|
91 |
#header li.inactive a, |
|
92 |
#header li.inactive:hover a { |
|
93 |
background-position: 100% 0; |
|
94 |
color: gray; |
|
95 |
} |
|
96 |
*/ |
|
97 |
|
|
98 |
div#footer { |
|
99 |
max-width: 800px; |
|
100 |
margin: 0 4em; |
|
101 |
border: 1px solid #999; |
|
102 |
border-top: 0; |
|
103 |
background: #eceade; |
|
104 |
padding: 0 1em; |
|
105 |
} |
|
106 |
|
|
107 |
div#footer p { |
|
108 |
margin: 0; |
|
109 |
text-align: right; |
|
110 |
font-size: 80%; |
|
111 |
font-weight: bold; |
|
112 |
} |
|
113 |
|
|
114 |
|
|
115 |
div#login-top, |
|
116 |
div#logout-top, |
|
117 |
div#identity-top { |
|
118 |
margin: 6em auto 1em auto; |
|
119 |
border: 1px solid #999; |
|
120 |
background: white; |
|
121 |
padding: 0.5ex 1em; |
|
122 |
} |
|
123 |
|
|
124 |
div#login-top, |
|
125 |
div#login-form { |
|
126 |
width: 20em; |
|
127 |
max-width: 200px; |
|
128 |
} |
|
129 |
|
|
130 |
div#logout-top, |
|
131 |
div#logout-sps, |
|
132 |
div#identity-top, |
|
133 |
div#identity-content { |
|
134 |
width: 40em; |
|
135 |
max-width: 400px; |
|
136 |
} |
|
137 |
|
|
138 |
div#login-top h1, |
|
139 |
div#logout-top h1, |
|
140 |
div#identity-top h1 { |
|
141 |
margin: 0; |
|
142 |
text-align: center; |
|
143 |
} |
|
144 |
|
|
145 |
div#login-form, |
|
146 |
div#logout-sps, |
|
147 |
div#identity-content { |
|
148 |
margin: 0 auto; |
|
149 |
background: white url(deg-top.png) top left repeat-x; |
|
150 |
border: 1px solid #999; |
|
151 |
padding: 1em; |
|
152 |
} |
|
153 |
|
|
154 |
div#login-form br { |
|
155 |
display: none; |
|
156 |
} |
|
157 |
|
|
158 |
div#login-form div.StringWidget { |
|
159 |
margin-bottom: 1ex; |
|
160 |
} |
|
161 |
|
|
162 |
p#cookies { |
|
163 |
margin: 0 1em; |
|
164 |
text-align: center; |
|
165 |
font-size: 90%; |
|
166 |
} |
|
167 |
|
|
168 |
form#login span.required { |
|
169 |
display: none |
|
170 |
} |
|
171 |
|
|
172 |
div#logout-sps ul li { |
|
173 |
list-style: circle; |
|
174 |
} |
|
175 |
|
|
176 |
div#logout-sps ul { |
|
177 |
padding-left: 2em; |
|
178 |
} |
|
179 |
|
|
180 |
div#logout-sps ul li img { |
|
181 |
padding-left: 1em; |
|
182 |
} |
|
183 |
|
|
184 |
ul.user-info { |
|
185 |
float : right; |
|
186 |
width : 102px; |
|
187 |
position : relative; |
|
188 |
margin : 0 0 1em 1em; |
|
189 |
padding : 5px 0 0 30px; |
|
190 |
background : transparent url(user_info_top.png) no-repeat top left; |
|
191 |
list-style : none; |
|
192 |
} |
|
193 |
li.ui-name { |
|
194 |
} |
|
195 |
li.ui-logout { |
|
196 |
display : block; |
|
197 |
background : transparent url(user_info_bottom.png) no-repeat bottom left; |
|
198 |
padding : 8px 0 10px 10px; |
|
199 |
margin : 0 0 0 -30px; |
|
200 |
} |
|
201 |
|
|
202 |
li.ui-logout a { |
|
203 |
padding-left: 20px; |
|
204 |
} |
|
205 |
|
|
206 |
table { |
|
207 |
clear: both; |
|
208 |
} |
|
209 |
|
|
210 |
table th { |
|
211 |
text-align: left; |
|
212 |
border-bottom: 1px solid #999; |
|
213 |
} |
|
214 |
|
|
215 |
table td { |
|
216 |
padding-right: 1ex; |
|
217 |
} |
|
218 |
|
|
219 |
dl dt { |
|
220 |
margin : 0; |
|
221 |
padding : 0 0 0 0; |
|
222 |
} |
|
223 |
|
|
224 |
dl dd { |
|
225 |
margin : 0.3em 0 1.5em 10px; |
|
226 |
} |
|
227 |
|
|
228 |
div#identity-content hr { |
|
229 |
margin: 1em 2em; |
|
230 |
height: 1px; |
|
231 |
background: #999; |
|
232 |
border: 0; |
|
233 |
|
|
234 |
} |
|
235 |
|
|
236 |
div.FieldWidget div.StringWidget { |
|
237 |
float: left; |
|
238 |
width: 30%; |
|
239 |
} |
|
240 |
|
|
241 |
br.FieldWidget, |
|
242 |
div.FieldWidget br { |
|
243 |
display: none; |
|
244 |
} |
|
245 |
|
|
246 |
pre { |
|
247 |
overflow: scroll; |
|
248 |
} |
|
249 |
|
|
250 |
div.explanation { |
|
251 |
margin: 0 140px 1em 0; |
|
252 |
background: white url(bg-footer.png) top right repeat-y; |
|
253 |
border: 1px solid #ccc; |
|
254 |
padding: 3px; |
|
255 |
} |
|
256 |
|
|
257 |
div.explanation ol, |
|
258 |
div.explanation p { |
|
259 |
margin: 0; |
|
260 |
} |
|
261 |
|
|
262 |
div#error-page { |
|
263 |
border: 1px solid #a00; |
|
264 |
} |
|
265 |
|
|
266 |
div#error-page h2 { |
|
267 |
margin: 0; |
|
268 |
border-bottom: 1px solid #a00; |
|
269 |
background: #f52; |
|
270 |
padding: 0 3px; |
|
271 |
} |
|
272 |
|
|
273 |
div#error-page p { |
|
274 |
padding: 0 3px; |
|
275 |
} |
|
276 |
|
|
277 |
img.theme-icon { |
|
278 |
float: right; |
|
279 |
margin: -16px 4px 0px 3px; |
|
280 |
border: 1px solid #999; |
|
281 |
} |
|
282 |
|
|
283 |
a.arrow { |
|
284 |
text-decoration: none; |
|
285 |
} |
|
286 |
|
|
287 |
ul.biglist { |
|
288 |
margin: 0; |
|
289 |
padding: 0; |
|
290 |
} |
|
291 |
|
|
292 |
#fields-list li { |
|
293 |
cursor: move; |
|
294 |
} |
|
295 |
|
|
296 |
ul.biglist li { |
|
297 |
list-style-type: none; |
|
298 |
margin: 4px 0; |
|
299 |
padding: 0 2px; |
|
300 |
border: 1px solid #888; |
|
301 |
background: #ffe; |
|
302 |
clear: both; |
|
303 |
} |
|
304 |
|
|
305 |
ul.biglist li p.details { |
|
306 |
display: block; |
|
307 |
margin: 0; |
|
308 |
color: #555; |
|
309 |
font-size: 80%; |
|
310 |
} |
|
311 |
|
|
312 |
|
|
313 |
ul.biglist li p.commands { |
|
314 |
float: right; |
|
315 |
margin-top: -17px; |
|
316 |
} |
|
317 |
|
|
318 |
ul.biglist li p.commands img { |
|
319 |
padding-right: 5px; |
|
320 |
} |
|
321 |
|
|
322 |
a img { |
|
323 |
border: 0; |
|
324 |
} |
|
325 |
|
|
326 |
td.time { |
|
327 |
text-align: right; |
|
328 |
} |
|
329 |
|
|
330 |
ul.biglist li.disabled, ul.biglist li.disabled p.details { |
|
331 |
color: #999; |
|
332 |
background: #ddd; |
|
333 |
} |
|
334 |
|
|
335 |
form#other-log-select { |
|
336 |
margin-top: 2em; |
|
337 |
padding-top: 1em; |
|
338 |
border-top: 1px solid #999; |
|
339 |
} |
|
340 |
|
|
341 |
form#other-log-select select { |
|
342 |
margin: 0 1em; |
|
343 |
} |
|
344 |
|
|
345 |
tr.level-error td { |
|
346 |
border: 1px solid #800; |
|
347 |
background: red; |
|
348 |
} |
|
349 |
|
|
350 |
tr.level-error td.message { |
|
351 |
font-weight: bold; |
|
352 |
} |
|
353 |
|
|
354 |
div#new-field table { |
|
355 |
margin: 0; |
|
356 |
padding: 0; |
|
357 |
} |
|
358 |
|
|
359 |
div#new-field div.widget { |
|
360 |
margin: 0; |
|
361 |
padding: 0; |
|
362 |
} |
|
363 |
|
|
364 |
div#new-field div.buttons { |
|
365 |
margin: 0; |
|
366 |
padding: 0; |
|
367 |
} |
|
368 |
|
|
369 |
div#new-field div.buttons input { |
|
370 |
margin: 0; |
|
371 |
padding: 0; |
|
372 |
} |
|
373 |
|
|
374 |
div#new-field { |
|
375 |
border: 1px solid #888; |
|
376 |
background: #ffe; |
|
377 |
margin: 2em 0 4px 0; |
|
378 |
padding: 0 2px; |
|
379 |
} |
|
380 |
|
|
381 |
div#new-field div.widget { |
|
382 |
} |
|
383 |
|
|
384 |
div#new-field h3 { |
|
385 |
margin: 0; |
|
386 |
font-size: 100%; |
|
387 |
} |
|
388 |
|
|
389 |
div#new-field br { |
|
390 |
display: none; |
|
391 |
} |
|
392 |
|
|
393 |
div#new-field p.commands { |
|
394 |
float: right; |
|
395 |
margin-top: -17px; |
|
396 |
margin-right: 3px; |
|
397 |
} |
|
398 |
|
|
399 |
div.WorkflowStatusWidget { |
|
400 |
border-left: 1px solid black; |
|
401 |
} |
|
402 |
|
|
403 |
hr { |
|
404 |
border: none; |
|
405 |
border-top: 1px solid #666; |
|
406 |
height: 1px; |
|
407 |
width: 80%; |
|
408 |
} |
|
409 |
|
|
410 |
|
larpe/tags/release-1.1.1/root/larpe/css/larpe-common.css | ||
---|---|---|
1 |
a { |
|
2 |
color: #028; |
|
3 |
} |
|
4 |
|
|
5 |
div.content { |
|
6 |
margin-left: 5px; |
|
7 |
} |
|
8 |
|
|
9 |
div.TextWidget textarea, |
|
10 |
div.StringWidget input, |
|
11 |
div.DateWidget input, |
|
12 |
div.WcsExtraStringWidget input, |
|
13 |
div.RegexStringWidget input, |
|
14 |
div.EmailWidget input, |
|
15 |
div.PasswordWidget input, |
|
16 |
div.UrlWidget input, |
|
17 |
div.ValidUrlWidget input { |
|
18 |
border: 1px inset #ccc; |
|
19 |
margin: 1px; |
|
20 |
padding: 2px 3px; |
|
21 |
} |
|
22 |
|
|
23 |
div.SingleSelectWidget select { |
|
24 |
margin: 1px; |
|
25 |
} |
|
26 |
|
|
27 |
div.widget input.prefill-button { |
|
28 |
border: 1px outset #ccc; |
|
29 |
margin: 0 0 0 1em; |
|
30 |
padding: 0px 0px; |
|
31 |
} |
|
32 |
|
|
33 |
div.widget input.prefill-button:focus { |
|
34 |
border: 1px outset #ccc; |
|
35 |
margin: 0 0 0 1em; |
|
36 |
padding: 0; |
|
37 |
} |
|
38 |
|
|
39 |
|
|
40 |
div.widget textarea.readonly, |
|
41 |
div.widget input.readonly { |
|
42 |
border: 1px solid #ccc; |
|
43 |
background: #eee; |
|
44 |
margin: 0 0 0 1em; |
|
45 |
} |
|
46 |
|
|
47 |
div.TextWidget textarea:focus, |
|
48 |
div.DateWidget input:focus, |
|
49 |
div.StringWidget input:focus, |
|
50 |
div.WcsExtraStringWidget input:focus, |
|
51 |
div.RegexStringWidget input:focus, |
|
52 |
div.EmailWidget input:focus, |
|
53 |
div.PasswordWidget input:focus, |
|
54 |
div.UrlWidget input:focus, |
|
55 |
div.ValidUrlWidget input:focus { |
|
56 |
border: 2px solid #ccf; |
|
57 |
/*margin: 0px; */ |
|
58 |
padding: 1px 2px; |
|
59 |
} |
|
60 |
|
|
61 |
div.AccountSettingWidget label { |
|
62 |
padding-right: 2em; |
|
63 |
} |
|
64 |
|
|
65 |
div.SubmitWidget input, input[type=submit] { |
|
66 |
margin-top: 1em; |
|
67 |
border: 1px outset #ccc; |
|
68 |
} |
|
69 |
|
|
70 |
div.form .title, form.quixote .title { |
|
71 |
font-weight: bold; |
|
72 |
} |
|
73 |
|
|
74 |
div.errornotice { |
|
75 |
background: #fd6; |
|
76 |
border: 1px solid #ffae15; |
|
77 |
margin: 0em 1em 1em 1em; |
|
78 |
padding: 5px; |
|
79 |
} |
|
80 |
|
|
81 |
div.infonotice { |
|
82 |
background: #7b95a6; |
|
83 |
border: 1px solid #153eaf; |
|
84 |
margin: 0em 1em 1em 1em; |
|
85 |
padding: 5px; |
|
86 |
} |
|
87 |
|
|
88 |
div.error { |
|
89 |
color: black; |
|
90 |
font-weight: bold; |
|
91 |
background: transparent url(warning.png) top left no-repeat; |
|
92 |
padding-left: 20px; |
|
93 |
} |
|
94 |
|
|
95 |
div.buttons div.SubmitWidget, |
|
96 |
div.buttons div.SubmitWidget div.content { |
|
97 |
display: inline; |
|
98 |
} |
|
99 |
|
|
100 |
div.buttons br { display: none; } |
|
101 |
|
|
102 |
div.widget { |
|
103 |
margin-bottom: 0.5em; |
|
104 |
clear: both; |
|
105 |
} |
|
106 |
|
|
107 |
input[type="submit"][name="submit"] { |
|
108 |
font-weight: bold; |
|
109 |
} |
|
110 |
|
|
111 |
div.form pre { |
|
112 |
overflow: scroll; |
|
113 |
} |
|
114 |
|
|
115 |
|
|
116 |
div#error h1 { |
|
117 |
margin: 0; |
|
118 |
} |
|
119 |
|
|
120 |
div#error { |
|
121 |
width: 40em; |
|
122 |
max-width: 500px; |
|
123 |
margin: 15% auto; |
|
124 |
background: white; |
|
125 |
border: 1px solid #999; |
|
126 |
padding: 1em; |
|
127 |
} |
|
128 |
|
|
129 |
div.hint { |
|
130 |
font-size: 80%; |
|
131 |
} |
|
132 |
|
|
133 |
span.required { |
|
134 |
background: transparent url(required.png) 0px 0.5ex no-repeat; |
|
135 |
padding: 0 0 0 24px; |
|
136 |
margin-left: 1ex; |
|
137 |
overflow: hidden; |
|
138 |
color: white; |
|
139 |
} |
|
140 |
|
|
141 |
div.buttons { |
|
142 |
margin-top: 1em; |
|
143 |
} |
|
144 |
|
|
145 |
div.RadiobuttonsWidget div.content { |
|
146 |
display: block; |
|
147 |
} |
|
148 |
|
|
149 |
div.error-page { |
|
150 |
margin: 1em; |
|
151 |
} |
|
152 |
|
|
153 |
pre#exception { |
|
154 |
overflow: scroll; |
|
155 |
padding: 1em; |
|
156 |
border: 1px solid #bbb; |
|
157 |
background: #f0f0f0; |
|
158 |
font-size: 90%; |
|
159 |
} |
|
160 |
|
|
161 |
div.StringWidget ul { |
|
162 |
margin: 0; |
|
163 |
padding-left: 2em; |
|
164 |
list-style: circle; |
|
165 |
} |
|
166 |
|
|
167 |
div.inline-first div.title, |
|
168 |
div.inline div.title { |
|
169 |
display: inline; |
|
170 |
float: left; |
|
171 |
max-width: 20em; |
|
172 |
text-align: left; |
|
173 |
padding-top: 6px; |
|
174 |
} |
|
175 |
|
|
176 |
div.inline-first div.title span.required, |
|
177 |
div.inline div.title span.required { |
|
178 |
margin-left: 1ex; |
|
179 |
padding-left: 12px; |
|
180 |
} |
|
181 |
|
|
182 |
div.inline-first div.content, |
|
183 |
div.inline div.content { |
|
184 |
margin-left: 1ex; |
|
185 |
} |
|
186 |
|
|
187 |
div.inline-first div.hint, |
|
188 |
div.inline div.hint { |
|
189 |
display: none; |
|
190 |
} |
|
191 |
|
|
192 |
div.inline-first { |
|
193 |
float: left; |
|
194 |
clear: both; |
|
195 |
} |
|
196 |
|
|
197 |
div.inline { |
|
198 |
float: left; |
|
199 |
clear: none; |
|
200 |
} |
|
201 |
|
|
202 |
div.inline-first div.content, |
|
203 |
div.inline div.content { |
|
204 |
margin-right: 1.5em; |
|
205 |
} |
|
206 |
|
|
207 |
|
|
208 |
|
|
209 |
div.inline-first div.content, |
|
210 |
div.inline div.content { |
|
211 |
display: inline; |
|
212 |
} |
|
213 |
|
|
214 |
.clear-both { |
|
215 |
clear: both; |
|
216 |
} |
|
217 |
|
|
218 |
div.CheckboxesWidget div.content ul { |
|
219 |
list-style: none; |
|
220 |
padding: 0; |
|
221 |
margin: 0; |
|
222 |
} |
|
223 |
|
|
224 |
div.CheckboxesWidget div.content ul li { |
|
225 |
display: inline; |
|
226 |
margin-right: 2em; |
|
227 |
} |
|
228 |
|
|
229 |
div#receipt { |
|
230 |
clear: both; |
|
231 |
} |
|
232 |
|
|
233 |
div#receipt span.label { |
|
234 |
font-weight: bold; |
|
235 |
display: block; |
|
236 |
} |
|
237 |
|
|
238 |
div#receipt span.value { |
|
239 |
display: block; |
|
240 |
margin-left: 1em; |
|
241 |
} |
|
242 |
|
|
243 |
form div.page, |
|
244 |
div#receipt div.page { |
|
245 |
border: 1px solid #aaa; |
|
246 |
padding: 1ex; |
|
247 |
margin-bottom: 1em; |
|
248 |
} |
|
249 |
|
|
250 |
form div.page p, |
|
251 |
div#receipt div.page p { |
|
252 |
margin-top: 0; |
|
253 |
} |
|
254 |
|
|
255 |
form div.page h3, |
|
256 |
div#receipt div.page h3 { |
|
257 |
margin: 0; |
|
258 |
margin-bottom: 1ex; |
|
259 |
} |
|
260 |
|
larpe/tags/release-1.1.1/root/larpe/css/larpe.css | ||
---|---|---|
1 |
@import url(larpe-common.css); |
|
2 |
@import url(jscalendar/aqua/theme.css); |
|
3 |
/* derived from soFresh, a DotClear theme by Maurice Svay (GPL) |
|
4 |
* http://www.svay.com/files/soFresh/theme-sofresh-1.2.zip */ |
|
5 |
|
|
6 |
html, body { |
|
7 |
font-family: sans-serif; |
|
8 |
text-align: center; |
|
9 |
background: #eee; |
|
10 |
color: black; |
|
11 |
} |
|
12 |
|
|
13 |
div#page { |
|
14 |
width: 800px; |
|
15 |
margin: 2em auto; |
|
16 |
text-align: justify; |
|
17 |
background: white url(img/page.png) repeat-y; |
|
18 |
color: black; |
|
19 |
} |
|
20 |
|
|
21 |
body.login div#page { |
|
22 |
width: 500px; |
|
23 |
background: white url(img/page-500.png) repeat-y; |
|
24 |
} |
|
25 |
#top { |
|
26 |
color: #09F; |
|
27 |
background: #FFF url(img/top.jpg) no-repeat; |
|
28 |
height: 100px; |
|
29 |
margin: 0; |
|
30 |
} |
|
31 |
|
|
32 |
body.login #top { |
|
33 |
background: white url(img/top-500.png) no-repeat; |
|
34 |
} |
|
35 |
|
|
36 |
#top h1 { |
|
37 |
margin: 0; |
|
38 |
padding-left: 30px; |
|
39 |
padding-right: 30px; |
|
40 |
line-height: 100px; |
|
41 |
height: 100px; |
|
42 |
overflow: hidden; |
|
43 |
} |
|
44 |
|
|
45 |
#footer { |
|
46 |
background: #FFF url(img/footer.jpg) no-repeat; |
|
47 |
color: #999; |
|
48 |
text-align: center; |
|
49 |
min-height: 30px; |
|
50 |
} |
|
51 |
|
|
52 |
body.login #footer { |
|
53 |
background: white url(img/footer-500.png) no-repeat; |
|
54 |
} |
|
55 |
|
|
56 |
div#main-content { |
|
57 |
margin: 0 2em; |
|
58 |
} |
|
59 |
|
|
60 |
div#main-content h1 { |
|
61 |
color: #09F; |
|
62 |
} |
|
63 |
|
|
64 |
#steps { |
|
65 |
height: 32px; |
|
66 |
margin-bottom: 1em; |
|
67 |
} |
|
68 |
|
|
69 |
#steps ol { |
|
70 |
list-style: none; |
|
71 |
padding: 0 20px; |
|
72 |
} |
|
73 |
|
|
74 |
#steps li { |
|
75 |
display: inline; |
|
76 |
padding-right: 1em; |
|
77 |
display: block; |
|
78 |
float: left; |
|
79 |
width: 30%; |
|
80 |
list-style: none; |
|
81 |
} |
|
82 |
|
|
83 |
#steps ol ul { |
|
84 |
border: 1px solid #ffa500; |
|
85 |
margin-left: 2em; |
|
86 |
background: #ffdb94; |
|
87 |
margin-bottom: 1em; |
|
88 |
padding: 0; |
|
89 |
width: auto; |
|
90 |
} |
|
91 |
|
|
92 |
#steps li li { |
|
93 |
display: block; |
|
94 |
width: auto; |
|
95 |
float: none; |
|
96 |
text-align: left; |
|
97 |
margin-left: 1em; |
|
98 |
font-size: 90%; |
|
99 |
} |
|
100 |
|
|
101 |
#steps li li.current { |
|
102 |
color: black; |
|
103 |
} |
|
104 |
|
|
105 |
|
|
106 |
#steps span.marker { |
|
107 |
font-size: 26px; |
|
108 |
padding: 2px 9px; |
|
109 |
font-weight: bold; |
|
110 |
color: white; |
|
111 |
text-align: center; |
|
112 |
background: #ddd; |
|
113 |
border: 1px solid #ddd; |
|
114 |
-moz-border-radius: 0.7ex; |
|
115 |
} |
|
116 |
|
|
117 |
#steps li.current span.marker { |
|
118 |
background: #ffa500; |
|
119 |
border: 1px solid #ffc400; |
|
120 |
} |
|
121 |
|
|
122 |
#steps span.label { |
|
123 |
font-size: 90%; |
|
124 |
} |
|
125 |
|
|
126 |
#steps li.current span.label { |
|
127 |
color: black; |
|
128 |
} |
|
129 |
|
|
130 |
#steps { |
|
131 |
background: #f0f0f0; |
|
132 |
color: #aaa; |
|
133 |
} |
|
134 |
|
|
135 |
#steps ol ul { |
|
136 |
display: none; |
|
137 |
} |
|
138 |
|
|
139 |
#steps ol li.current ul { |
|
140 |
display: block; |
|
141 |
} |
|
142 |
|
|
143 |
form { |
|
144 |
clear: both; |
|
145 |
} |
|
146 |
|
|
147 |
p#receiver { |
|
148 |
margin: 0; |
|
149 |
margin-left: 2em; |
|
150 |
margin-top: -0.7em; |
|
151 |
margin-bottom: 1em; |
|
152 |
padding: 2px 5px; |
|
153 |
border: 1px solid #ccc; |
|
154 |
float: left; |
|
155 |
background: #ffe; |
|
156 |
} |
|
157 |
|
|
158 |
p#login, |
|
159 |
p#logout { |
|
160 |
margin-top: 2em; |
|
161 |
text-align: right; |
|
162 |
} |
|
163 |
|
|
164 |
p#login a, p#logout a { |
|
165 |
text-decoration: underline; |
|
166 |
/* |
|
167 |
text-decoration: none; |
|
168 |
-moz-border-radius: 2em !important; |
|
169 |
padding: 1px 6px !important; |
|
170 |
border: 1px solid #ccc !important; |
|
171 |
border-bottom: 2px solid #999 !important;*/ |
|
172 |
} |
|
173 |
|
|
174 |
p#login a:hover { |
|
175 |
background-color: #ddeeff; |
|
176 |
} |
|
177 |
|
|
178 |
h2#submitted, h2#done { |
|
179 |
margin-top: 2em; |
|
180 |
color: #09F; |
|
181 |
font-size: 130%; |
|
182 |
} |
|
183 |
|
|
184 |
h2#done { |
|
185 |
margin-top: 1em; |
|
186 |
} |
|
187 |
|
|
188 |
ul li { |
|
189 |
list-style-image: url(img/li.png); |
|
190 |
} |
|
191 |
|
|
192 |
h2, h3 { |
|
193 |
color: #09F; |
|
194 |
margin-left: 0.5em; |
|
195 |
margin-bottom: 0; |
|
196 |
} |
|
197 |
|
|
198 |
h3 { |
|
199 |
margin-left: 1em; |
|
200 |
} |
|
201 |
|
|
202 |
table#listing { |
|
203 |
margin: 1em 0; |
|
204 |
} |
|
205 |
|
|
206 |
table#listing th { |
|
207 |
text-align: left; |
|
208 |
border-bottom: 1px solid #999; |
|
209 |
background: #eee; |
|
210 |
} |
|
211 |
|
|
212 |
table#listing td { |
|
213 |
padding-right: 1ex; |
|
214 |
} |
|
215 |
|
|
216 |
table#listing th a { |
|
217 |
text-decoration: none; |
|
218 |
color: #666; |
|
219 |
} |
|
220 |
|
|
221 |
table.sortable span.sortarrow { |
|
222 |
color: black; |
|
223 |
text-decoration: none; |
|
224 |
} |
|
225 |
|
|
226 |
table#listing tr.status-new { |
|
227 |
background: #aea; |
|
228 |
} |
|
229 |
|
|
230 |
table#listing tr.status-finished, |
|
231 |
table#listing tr.status-rejected { |
|
232 |
color: #444; |
|
233 |
} |
|
234 |
|
|
235 |
table#listing tr.status-rejected td { |
|
236 |
text-decoration: line-through; |
|
237 |
} |
|
238 |
|
|
239 |
div.question p.label { |
|
240 |
font-weight: bold; |
|
241 |
} |
|
242 |
|
|
243 |
img.bar { |
|
244 |
border: 1px solid black; |
|
245 |
} |
|
246 |
|
|
247 |
div.question table { |
|
248 |
margin-left: 10px; |
|
249 |
} |
|
250 |
|
|
251 |
div.question table td { |
|
252 |
} |
|
253 |
|
|
254 |
div.question table td.percent { |
|
255 |
text-align: right; |
|
256 |
padding: 0 1em; |
|
257 |
width: 6em; |
|
258 |
} |
|
259 |
|
|
260 |
div.question table td.label { |
|
261 |
width: 6em; |
|
262 |
} |
|
263 |
|
|
264 |
span.user { |
|
265 |
margin-left: 1em; |
|
266 |
font-style: italic; |
|
267 |
} |
|
268 |
|
|
269 |
a.listing { |
|
270 |
font-size: 80%; |
|
271 |
padding-left: 1em; |
|
272 |
} |
|
273 |
|
|
274 |
a { |
|
275 |
text-decoration: none; |
|
276 |
color: #113; |
|
277 |
} |
|
278 |
|
|
279 |
a:hover { |
|
280 |
color: #06C; |
|
281 |
text-decoration: underline; |
|
282 |
} |
|
283 |
|
|
284 |
|
|
285 |
#prelude { |
|
286 |
color: #aaa; |
|
287 |
background: transparent; |
|
288 |
text-align: right; |
|
289 |
position: relative; |
|
290 |
top: -85px; |
|
291 |
margin: 0; |
|
292 |
} |
|
293 |
|
|
294 |
p#breadcrumb { |
|
295 |
margin-top: 0; |
|
296 |
} |
|
297 |
|
|
298 |
div.error-page { |
|
299 |
margin-bottom: 2em; |
|
300 |
} |
|
301 |
|
|
302 |
div.hint { |
|
303 |
display: inline; |
|
304 |
padding-left: 1ex; |
|
305 |
font-style: italic; |
|
306 |
} |
|
307 |
|
|
308 |
a.standalone { |
|
309 |
background: white url(img/h2.png) top left no-repeat; |
|
310 |
padding-left: 20px; |
|
311 |
} |
|
312 |
|
|
313 |
div#welcome-message a { |
|
314 |
text-decoration: underline; |
|
315 |
} |
|
316 |
|
|
317 |
input.cancel { |
|
318 |
margin-left: 5em; |
|
319 |
} |
|
320 |
|
|
321 |
hr { |
|
322 |
border: none; |
|
323 |
border-top: 1px solid #666; |
|
324 |
height: 1px; |
|
325 |
width: 80%; |
|
326 |
} |
|
327 |
|
|
328 |
div.buttons { |
|
329 |
clear: both; |
|
330 |
} |
|
331 |
|
larpe/tags/release-1.1.1/setup.py | ||
---|---|---|
1 |
#!/usr/bin/env python |
|
2 |
|
|
3 |
import os |
|
4 |
import distutils.core |
|
5 |
from quixote.ptl.qx_distutils import qx_build_py |
|
6 |
|
|
7 |
local_cfg = None |
|
8 |
if os.path.exists('larpe/larpe_cfg.py'): |
|
9 |
local_cfg = open('larpe/larpe_cfg.py').read() |
|
10 |
os.unlink('larpe/larpe_cfg.py') |
|
11 |
|
|
12 |
def data_tree(destdir, sourcedir): |
|
13 |
extensions = ['.css', '.png', '.jpeg', '.jpg', '.xml', '.html', '.js', '.py'] |
|
14 |
r = [] |
|
15 |
for root, dirs, files in os.walk(sourcedir): |
|
16 |
l = [os.path.join(root, x) for x in files if os.path.splitext(x)[1] in extensions] |
|
17 |
r.append( (root.replace(sourcedir, destdir, 1), l) ) |
|
18 |
if '.svn' in dirs: |
|
19 |
dirs.remove('.svn') |
|
20 |
return r |
|
21 |
|
|
22 |
distutils.core.setup( |
|
23 |
name = 'larpe', |
|
24 |
version = '1.1.1', |
|
25 |
maintainer = 'Jerome Schneider', |
|
26 |
maintainer_email = 'jschneider@entrouvert.com', |
|
27 |
url = 'http://larpe.labs.libre-entreprise.org', |
|
28 |
package_dir = { 'larpe': 'larpe' }, |
|
29 |
packages = ['larpe', 'larpe.admin', 'larpe.ctl', 'larpe.plugins', 'larpe.plugins.site_authentication', 'larpe.qommon', |
|
30 |
'larpe.qommon.admin', 'larpe.qommon.ident', 'larpe.qommon.backoffice', 'larpe.qommon.vendor'], |
|
31 |
cmdclass = {'build_py': qx_build_py}, |
|
32 |
data_files = data_tree('share/larpe/web/', 'root/') + \ |
|
33 |
data_tree('share/larpe/web/larpe/qo/', 'larpe/qommon/static/') + \ |
|
34 |
data_tree('share/larpe/', 'conf/') |
|
35 |
) |
|
36 |
|
|
37 |
if local_cfg: |
|
38 |
open('larpe/larpe_cfg.py', 'w').write(local_cfg) |
|
39 |
|
larpe/tags/release-1.1.1/tests/all4dev/slo_check | ||
---|---|---|
1 |
url http://all4dev.test.org/index.php/Main_Page |
|
2 |
find "Create an account or log in" |
larpe/tags/release-1.1.1/tests/all4dev/sso_check | ||
---|---|---|
1 |
url http://all4dev.test.org/index.php/Main_Page |
|
2 |
find $find_username |
|
3 |
find logout |
larpe/tags/release-1.1.1/tests/blueprint/slo_check | ||
---|---|---|
1 |
find "<frameset" |
larpe/tags/release-1.1.1/tests/blueprint/sso_check | ||
---|---|---|
1 |
find logout.gif |
larpe/tags/release-1.1.1/tests/check.sh | ||
---|---|---|
1 |
#!/bin/sh |
|
2 |
# |
|
3 |
# Usage : check.sh : Test all sites in current directory |
|
4 |
# check.sh list_of_sites : Test the sites whose name is given on the command line |
|
5 |
|
|
6 |
exclude_sites="linuxfr listes_libre_entreprise egroupware" |
|
7 |
|
|
8 |
if [ $# -eq 0 ]; |
|
9 |
then |
|
10 |
# Test all sites |
|
11 |
for site in *; |
|
12 |
do |
|
13 |
test_site=1 |
|
14 |
for exclude_site in $exclude_sites; |
|
15 |
do |
|
16 |
if [ $site = $exclude_site ]; |
|
17 |
then |
|
18 |
test_site=0 |
|
19 |
fi |
|
20 |
done |
|
21 |
if [ $test_site -eq 1 ]; |
|
22 |
then |
|
23 |
sites="$sites $site" |
|
24 |
fi |
|
25 |
done |
|
26 |
else |
|
27 |
# Test the sites whose name is given on the command line |
|
28 |
while [ $# -ne 0 ]; |
|
29 |
do |
|
30 |
sites="$sites $1" |
|
31 |
shift |
|
32 |
done |
|
33 |
fi |
|
34 |
|
|
35 |
function check() { |
|
36 |
site="$1" |
|
37 |
files="" |
|
38 |
|
|
39 |
# Combine as many functionnalities as given, at the same time |
|
40 |
shift |
|
41 |
echo -n " " |
|
42 |
while [ $# -ne 0 ]; |
|
43 |
do |
|
44 |
functionnality="$1" |
|
45 |
echo -n "$functionnality " |
|
46 |
case "$functionnality" in |
|
47 |
"Federation") |
|
48 |
add_files="sso idp_login federation $site/sso_check";; |
|
49 |
"SSO") |
|
50 |
add_files="sso idp_login $site/sso_check";; |
|
51 |
"SLO") |
|
52 |
add_files="slo $site/slo_check";; |
|
53 |
esac |
|
54 |
files="$files $add_files" |
|
55 |
shift |
|
56 |
done |
|
57 |
echo -n "..." |
|
58 |
|
|
59 |
cat $site/config $files | twill-sh > twill_output |
|
60 |
grep "ERROR" twill_output &> /dev/null |
|
61 |
if [ $? -eq 0 ]; |
|
62 |
then |
|
63 |
echo " [FAILED]" |
|
64 |
cat twill_output |
|
65 |
exit 1 |
|
66 |
else |
|
67 |
echo " [OK]" |
|
68 |
fi |
|
69 |
} |
|
70 |
|
|
71 |
echo |
|
72 |
# Check loop |
|
73 |
for site in $sites; |
|
74 |
do |
|
75 |
if [ ! -d $site ]; |
|
76 |
then |
|
77 |
continue |
|
78 |
fi |
|
79 |
|
|
80 |
echo "Testing $site :" |
|
81 |
|
|
82 |
echo -n " Defederation ..." |
|
83 |
cat $site/config defederation idp_login | twill-sh &> /dev/null |
|
84 |
echo " [OK]" |
|
85 |
check $site "Federation" |
|
86 |
check $site "SSO" |
|
87 |
check $site "SLO" |
|
88 |
check $site "SSO" "SLO" |
|
89 |
check $site "SLO" "SSO" "SLO" "SLO" "SSO" "SLO" |
|
90 |
|
|
91 |
rm -f twill_output |
|
92 |
echo |
|
93 |
done |
larpe/tags/release-1.1.1/tests/defederation | ||
---|---|---|
1 |
go $defederation_url |
larpe/tags/release-1.1.1/tests/dotclear/slo_check | ||
---|---|---|
1 |
#url http://dotclear.test.org/ |
|
2 |
url https://dotclear.test.org/ |
larpe/tags/release-1.1.1/tests/dotclear/sso_check | ||
---|---|---|
1 |
#url http://dotclear.test.org/ecrire/ |
|
2 |
url https://dotclear.test.org/ecrire/ |
|
3 |
find $find_username |
|
4 |
find déconnexion |
larpe/tags/release-1.1.1/tests/dotclear_subdir/slo_check | ||
---|---|---|
1 |
url http://listes.test.org/dotclear/ |
larpe/tags/release-1.1.1/tests/dotclear_subdir/sso_check | ||
---|---|---|
1 |
url http://listes.test.org/dotclear/ecrire/ |
|
2 |
find $find_username |
|
3 |
find déconnexion |
larpe/tags/release-1.1.1/tests/federation | ||
---|---|---|
1 |
formvalue 1 username $sp_username |
|
2 |
formvalue 1 password $sp_password |
|
3 |
submit |
larpe/tags/release-1.1.1/tests/gen_config.sh | ||
---|---|---|
1 |
#!/bin/sh |
|
2 |
|
|
3 |
if [ $# -eq 0 ]; |
|
4 |
then |
|
5 |
echo "Usage : $0 site_name" |
|
6 |
exit 1 |
|
7 |
fi |
|
8 |
|
|
9 |
while [ $# -ne 0 ]; |
|
10 |
do |
|
11 |
if [ -d $1 ]; |
|
12 |
then |
|
13 |
config_file="$1/config" |
|
14 |
echo -n "Generating config template for $1 ... " |
|
15 |
echo "setlocal sp_login_url " >> $config_file |
|
16 |
echo "setlocal sp_logout_url " >> $config_file |
|
17 |
echo "setlocal defederation_url " >> $config_file |
|
18 |
echo "setlocal idp_username " >> $config_file |
|
19 |
echo "setlocal idp_password " >> $config_file |
|
20 |
echo "setlocal sp_username " >> $config_file |
|
21 |
echo "setlocal sp_password " >> $config_file |
|
22 |
echo "setlocal find_username " >> $config_file |
|
23 |
echo "[OK]" |
|
24 |
fi |
|
25 |
shift |
|
26 |
done |
larpe/tags/release-1.1.1/tests/idp_login | ||
---|---|---|
1 |
formvalue 1 username $idp_username |
|
2 |
formvalue 1 password $idp_password |
|
3 |
submit |
larpe/tags/release-1.1.1/tests/libre-entreprise/slo_check | ||
---|---|---|
1 |
#url http://libre-entreprise.reverse-proxy.entrouvert.org/index.php/Accueil |
|
2 |
url http://le.test.org/index.php/Accueil |
|
3 |
find "Créer un compte ou se connecter" |
larpe/tags/release-1.1.1/tests/libre-entreprise/sso_check | ||
---|---|---|
1 |
#url http://libre-entreprise.reverse-proxy.entrouvert.org/index.php/Accueil |
|
2 |
url http://le.test.org/index.php/Accueil |
|
3 |
find $find_username |
|
4 |
find déconnexion |
larpe/tags/release-1.1.1/tests/listes_entrouvert/slo_check | ||
---|---|---|
1 |
find Login |
larpe/tags/release-1.1.1/tests/listes_entrouvert/sso_check | ||
---|---|---|
1 |
find $find_username |
|
2 |
find "You have logged in" |
larpe/tags/release-1.1.1/tests/listes_libre_entreprise/slo_check | ||
---|---|---|
1 |
find Login |
larpe/tags/release-1.1.1/tests/listes_libre_entreprise/sso_check | ||
---|---|---|
1 |
find $find_username |
|
2 |
find "Vous êtes identifié" |
larpe/tags/release-1.1.1/tests/slo | ||
---|---|---|
1 |
go $sp_logout_url |
larpe/tags/release-1.1.1/tests/sso | ||
---|---|---|
1 |
go $sp_login_url |
Formats disponibles : Unified diff
Tagging release 1.1.1
git-svn-id: svn+ssh://labs.libre-entreprise.org/svnroot/larpe@502 3ed937ae-f919-0410-9a43-8e6f19e4ba6e